+
+void SelectionModelSynchronizer::syncedCurrentChanged(const QModelIndex ¤t, const QModelIndex &previous)
+{
+ Q_UNUSED(previous);
+
+ if (!_changeCurrentEnabled)
+ return;
+
+ QItemSelectionModel *selectionModel = qobject_cast<QItemSelectionModel *>(sender());
+ Q_ASSERT(selectionModel);
+ QModelIndex newSourceCurrent = mapToSource(current, selectionModel);
+ if (newSourceCurrent.isValid() && newSourceCurrent != currentIndex())
+ setCurrentIndex(newSourceCurrent);
+}
+
+
+void SelectionModelSynchronizer::syncedSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
+{
+ Q_UNUSED(selected);
+ Q_UNUSED(deselected);
+
+ if (!_changeSelectionEnabled)
+ return;
+
+ QItemSelectionModel *selectionModel = qobject_cast<QItemSelectionModel *>(sender());
+ Q_ASSERT(selectionModel);
+
+ QItemSelection mappedSelection = selectionModel->selection();
+ QItemSelection currentSelectionMapped = mapSelectionFromSource(currentSelection(), selectionModel);
+
+ QItemSelection checkSelection = currentSelectionMapped;
+ checkSelection.merge(mappedSelection, QItemSelectionModel::Deselect);
+ if (checkSelection.isEmpty()) {
+ // that means the new selection contains the current selection (currentSel - newSel = {})
+ checkSelection = mappedSelection;
+ checkSelection.merge(currentSelectionMapped, QItemSelectionModel::Deselect);
+ if (checkSelection.isEmpty()) {
+ // that means the current selection contains the new selection (newSel - currentSel = {})
+ // -> currentSel == newSel
+ return;
+ }
+ }
+ setCurrentSelection(mapSelectionToSource(mappedSelection, selectionModel));
+}
+
+
+QModelIndex SelectionModelSynchronizer::mapFromSource(const QModelIndex &sourceIndex, const QItemSelectionModel *selectionModel)
+{
+ Q_ASSERT(selectionModel);
+
+ QModelIndex mappedIndex = sourceIndex;
+
+ // make a list of all involved proxies, wie have to traverse backwards
+ QList<const QAbstractProxyModel *> proxyModels;
+ const QAbstractItemModel *baseModel = selectionModel->model();
+ const QAbstractProxyModel *proxyModel = 0;
+ while ((proxyModel = qobject_cast<const QAbstractProxyModel *>(baseModel)) != 0) {
+ if (baseModel == model())
+ break;
+ proxyModels << proxyModel;
+ baseModel = proxyModel->sourceModel();
+ }
+
+ // now traverse it;
+ for (int i = proxyModels.count() - 1; i >= 0; i--) {
+ mappedIndex = proxyModels[i]->mapFromSource(mappedIndex);
+ }
+
+ return mappedIndex;
+}
+
+
+QItemSelection SelectionModelSynchronizer::mapSelectionFromSource(const QItemSelection &sourceSelection, const QItemSelectionModel *selectionModel)
+{
+ Q_ASSERT(selectionModel);
+
+ QItemSelection mappedSelection = sourceSelection;
+
+ // make a list of all involved proxies, wie have to traverse backwards
+ QList<const QAbstractProxyModel *> proxyModels;
+ const QAbstractItemModel *baseModel = selectionModel->model();
+ const QAbstractProxyModel *proxyModel = 0;
+ while ((proxyModel = qobject_cast<const QAbstractProxyModel *>(baseModel)) != 0) {
+ if (baseModel == model())
+ break;
+ proxyModels << proxyModel;
+ baseModel = proxyModel->sourceModel();
+ }
+
+ // now traverse it;
+ for (int i = proxyModels.count() - 1; i >= 0; i--) {
+ mappedSelection = proxyModels[i]->mapSelectionFromSource(mappedSelection);
+ }
+ return mappedSelection;
+}
+
+
+QModelIndex SelectionModelSynchronizer::mapToSource(const QModelIndex &index, QItemSelectionModel *selectionModel)
+{
+ Q_ASSERT(selectionModel);
+
+ QModelIndex sourceIndex = index;
+ const QAbstractItemModel *baseModel = selectionModel->model();
+ const QAbstractProxyModel *proxyModel = 0;
+ while ((proxyModel = qobject_cast<const QAbstractProxyModel *>(baseModel)) != 0) {
+ sourceIndex = proxyModel->mapToSource(sourceIndex);
+ baseModel = proxyModel->sourceModel();
+ if (baseModel == model())
+ break;
+ }
+ return sourceIndex;
+}
+
+
+QItemSelection SelectionModelSynchronizer::mapSelectionToSource(const QItemSelection &selection, QItemSelectionModel *selectionModel)
+{
+ Q_ASSERT(selectionModel);
+
+ QItemSelection sourceSelection = selection;
+ const QAbstractItemModel *baseModel = selectionModel->model();
+ const QAbstractProxyModel *proxyModel = 0;
+ while ((proxyModel = qobject_cast<const QAbstractProxyModel *>(baseModel)) != 0) {
+ sourceSelection = proxyModel->mapSelectionToSource(sourceSelection);
+ baseModel = proxyModel->sourceModel();
+ if (baseModel == model())
+ break;
+ }
+ return sourceSelection;
+}
+
+
+void SelectionModelSynchronizer::setCurrentIndex(const QModelIndex &index)
+{
+ _selectionModel.setCurrentIndex(index, QItemSelectionModel::Current);
+}
+
+
+void SelectionModelSynchronizer::setCurrentSelection(const QItemSelection &selection)
+{
+ _selectionModel.select(selection, QItemSelectionModel::ClearAndSelect);
+}
+
+
+void SelectionModelSynchronizer::currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
+{
+ Q_UNUSED(previous);
+
+ _changeCurrentEnabled = false;
+ QSet<QItemSelectionModel *>::iterator iter = _selectionModels.begin();
+ while (iter != _selectionModels.end()) {
+ (*iter)->setCurrentIndex(mapFromSource(current, (*iter)), QItemSelectionModel::Current);
+ iter++;
+ }
+ _changeCurrentEnabled = true;
+}
+
+
+void SelectionModelSynchronizer::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
+{
+ Q_UNUSED(selected);
+ Q_UNUSED(deselected);
+
+ _changeSelectionEnabled = false;
+ QSet<QItemSelectionModel *>::iterator iter = _selectionModels.begin();
+ while (iter != _selectionModels.end()) {
+ (*iter)->select(mapSelectionFromSource(currentSelection(), (*iter)), QItemSelectionModel::ClearAndSelect);
+ iter++;
+ }
+ _changeSelectionEnabled = true;