X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fclient%2Fselectionmodelsynchronizer.cpp;h=d533ea4aa6e099660eadbe990f1405d7ad9e7f26;hp=2975f7975feb621034d4e879b49c5747b991528d;hb=5159e200a1c4c0998f302ae7c57325ed322c1e85;hpb=974b7adc16b798eda66e1fff1442b73b748f12f9 diff --git a/src/client/selectionmodelsynchronizer.cpp b/src/client/selectionmodelsynchronizer.cpp index 2975f797..d533ea4a 100644 --- a/src/client/selectionmodelsynchronizer.cpp +++ b/src/client/selectionmodelsynchronizer.cpp @@ -1,11 +1,11 @@ /*************************************************************************** - * Copyright (C) 2005-07 by The Quassel Team * + * Copyright (C) 2005-08 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * + * (at your option) version 3. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * @@ -23,45 +23,129 @@ #include #include "mappedselectionmodel.h" +#include #include SelectionModelSynchronizer::SelectionModelSynchronizer(QAbstractItemModel *parent) : QObject(parent), - _model(parent) + _model(parent), + _selectionModel(parent) { + connect(&_selectionModel, SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), + this, SLOT(currentChanged(const QModelIndex &, const QModelIndex &))); + connect(&_selectionModel, SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), + this, SLOT(selectionChanged(const QItemSelection &, const QItemSelection &))); } -SelectionModelSynchronizer::~SelectionModelSynchronizer() { +bool SelectionModelSynchronizer::checkBaseModel(QItemSelectionModel *selectionModel) { + if(!selectionModel) + return false; + + const QAbstractItemModel *baseModel = selectionModel->model(); + const QAbstractProxyModel *proxyModel = 0; + while((proxyModel = qobject_cast(baseModel)) != 0) { + baseModel = proxyModel->sourceModel(); + if(baseModel == model()) + break; + } + return baseModel == model(); } -void SelectionModelSynchronizer::addSelectionModel(MappedSelectionModel *selectionmodel) { - if(selectionmodel->baseModel() != model()) { - qWarning() << "cannot Syncronize SelectionModel" << selectionmodel << "which has a different baseModel()"; +void SelectionModelSynchronizer::addSelectionModel(QItemSelectionModel *selectionModel) { + if(!checkBaseModel(selectionModel)) { + qWarning() << "cannot Syncronize SelectionModel" << selectionModel << "which has a different baseModel()"; return; } - connect(selectionmodel, SIGNAL(mappedCurrentChanged(QModelIndex)), - this, SLOT(_mappedCurrentChanged(QModelIndex))); - connect(selectionmodel, SIGNAL(mappedSelectionChanged(QItemSelection)), - this, SLOT(_mappedSelectionChanged(QItemSelection))); - - connect(this, SIGNAL(setCurrentIndex(QModelIndex, QItemSelectionModel::SelectionFlags)), - selectionmodel, SLOT(mappedSetCurrentIndex(QModelIndex, QItemSelectionModel::SelectionFlags))); - connect(this, SIGNAL(select(QItemSelection, QItemSelectionModel::SelectionFlags)), - selectionmodel, SLOT(mappedSelect(QItemSelection, QItemSelectionModel::SelectionFlags))); - + connect(selectionModel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), + this, SLOT(mappedCurrentChanged(QModelIndex, QModelIndex))); + connect(selectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + this, SLOT(mappedSelectionChanged(QItemSelection, QItemSelection))); + + if(qobject_cast(selectionModel)) { + connect(this, SIGNAL(setCurrentIndex(QModelIndex, QItemSelectionModel::SelectionFlags)), + selectionModel, SLOT(mappedSetCurrentIndex(QModelIndex, QItemSelectionModel::SelectionFlags))); + connect(this, SIGNAL(select(QItemSelection, QItemSelectionModel::SelectionFlags)), + selectionModel, SLOT(mappedSelect(QItemSelection, QItemSelectionModel::SelectionFlags))); + } else { + connect(this, SIGNAL(setCurrentIndex(QModelIndex, QItemSelectionModel::SelectionFlags)), + selectionModel, SLOT(setCurrentIndex(QModelIndex, QItemSelectionModel::SelectionFlags))); + connect(this, SIGNAL(select(QItemSelection, QItemSelectionModel::SelectionFlags)), + selectionModel, SLOT(select(QItemSelection, QItemSelectionModel::SelectionFlags))); + } } -void SelectionModelSynchronizer::removeSelectionModel(MappedSelectionModel *model) { +void SelectionModelSynchronizer::removeSelectionModel(QItemSelectionModel *model) { disconnect(model, 0, this, 0); disconnect(this, 0, model, 0); } -void SelectionModelSynchronizer::_mappedCurrentChanged(const QModelIndex ¤t) { - emit setCurrentIndex(current, QItemSelectionModel::ClearAndSelect); +void SelectionModelSynchronizer::mappedCurrentChanged(const QModelIndex ¤t, const QModelIndex &previous) { + Q_UNUSED(previous); + QItemSelectionModel *selectionModel = qobject_cast(sender()); + Q_ASSERT(selectionModel); + QModelIndex newSourceCurrent = mapToSource(current, selectionModel); + if(newSourceCurrent.isValid() && newSourceCurrent != currentIndex()) + setCurrentIndex(newSourceCurrent); +} + +void SelectionModelSynchronizer::mappedSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected) { + Q_UNUSED(selected); + Q_UNUSED(deselected); + QItemSelectionModel *selectionModel = qobject_cast(sender()); + Q_ASSERT(selectionModel); + QItemSelection newSourceSelection = mapSelectionToSource(selectionModel->selection(), selectionModel); + QItemSelection currentContainsSelection = newSourceSelection; + currentContainsSelection.merge(currentSelection(), QItemSelectionModel::Deselect); + if(!currentContainsSelection.isEmpty()) + setCurrentSelection(newSourceSelection); +} + +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(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(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::Rows | QItemSelectionModel::ClearAndSelect); +} + +void SelectionModelSynchronizer::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { + Q_UNUSED(previous); + emit setCurrentIndex(current, QItemSelectionModel::Current); } -void SelectionModelSynchronizer::_mappedSelectionChanged(const QItemSelection &selected) { - emit select(selected, QItemSelectionModel::ClearAndSelect); +void SelectionModelSynchronizer::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) { + Q_UNUSED(selected); + Q_UNUSED(deselected); + emit select(_selectionModel.selection(), QItemSelectionModel::ClearAndSelect); }