From bef59ffd2288eda230af391ae6b34caa92a04d14 Mon Sep 17 00:00:00 2001 From: David Sansome Date: Sun, 9 May 2010 21:16:54 +0000 Subject: [PATCH] Don't reset the whole merged model when one of the submodels changes --- src/mergedproxymodel.cpp | 37 +++++++++++++++++++++++++++++++++---- src/mergedproxymodel.h | 5 ++++- src/radioviewcontainer.cpp | 33 +++++++++++++++++++++++++++------ src/radioviewcontainer.h | 3 +++ 4 files changed, 67 insertions(+), 11 deletions(-) diff --git a/src/mergedproxymodel.cpp b/src/mergedproxymodel.cpp index 8a9327cd8..19cf3463f 100644 --- a/src/mergedproxymodel.cpp +++ b/src/mergedproxymodel.cpp @@ -17,13 +17,17 @@ #include "mergedproxymodel.h" #include +#include + +#include std::size_t hash_value(const QModelIndex& index) { return qHash(index); } MergedProxyModel::MergedProxyModel(QObject* parent) - : QAbstractProxyModel(parent) + : QAbstractProxyModel(parent), + resetting_model_(NULL) { } @@ -95,12 +99,25 @@ void MergedProxyModel::SourceModelReset() { void MergedProxyModel::SubModelReset() { const QAbstractItemModel* submodel = static_cast(sender()); + // TODO: When we require Qt 4.6, use beginResetModel() and endResetModel() + // in LibraryModel and catch those here - that will let us do away with this + // std::numeric_limits::max() hack. + + // Remove all the children of the item that got deleted + QModelIndex source_parent = merge_points_.value(submodel); + QModelIndex proxy_parent = mapFromSource(source_parent); + + // We can't know how many children it had, since it's already disappeared... + resetting_model_ = submodel; + beginRemoveRows(proxy_parent, 0, std::numeric_limits::max() - 1); + endRemoveRows(); + resetting_model_ = NULL; + // Delete all the mappings that reference the submodel MappingContainer::index::type::iterator it = mappings_.get().begin(); MappingContainer::index::type::iterator end = mappings_.get().end(); - while (it != end) { if ((*it)->source_index.model() == submodel) { delete *it; @@ -110,8 +127,12 @@ void MergedProxyModel::SubModelReset() { } } - // Reset the proxy - reset(); + // "Insert" items from the newly reset submodel + int count = submodel->rowCount(); + if (count) { + beginInsertRows(proxy_parent, 0, count-1); + endInsertRows(); + } } QModelIndex MergedProxyModel::GetActualSourceParent(const QModelIndex& source_parent, @@ -148,12 +169,20 @@ QModelIndex MergedProxyModel::mapToSource(const QModelIndex& proxy_index) const return QModelIndex(); Mapping* mapping = static_cast(proxy_index.internalPointer()); + if (mappings_.get().find(mapping) == + mappings_.get().end()) + return QModelIndex(); + if (mapping->source_index.model() == resetting_model_) + return QModelIndex(); + return mapping->source_index; } QModelIndex MergedProxyModel::mapFromSource(const QModelIndex& source_index) const { if (!source_index.isValid()) return QModelIndex(); + if (source_index.model() == resetting_model_) + return QModelIndex(); // Add a mapping if we don't have one already MappingContainer::index::type::iterator it = diff --git a/src/mergedproxymodel.h b/src/mergedproxymodel.h index d6e697e2d..7230446b9 100644 --- a/src/mergedproxymodel.h +++ b/src/mergedproxymodel.h @@ -85,7 +85,9 @@ class MergedProxyModel : public QAbstractProxyModel { void DeleteAllMappings(); struct Mapping { - Mapping(const QModelIndex& _source_index) : source_index(_source_index) {} + Mapping(const QModelIndex& _source_index) + : source_index(_source_index) {} + QModelIndex source_index; }; @@ -103,6 +105,7 @@ class MergedProxyModel : public QAbstractProxyModel { MappingContainer mappings_; QMap merge_points_; + const QAbstractItemModel* resetting_model_; }; #endif // MERGEDPROXYMODEL_H diff --git a/src/radioviewcontainer.cpp b/src/radioviewcontainer.cpp index ff68b0d81..822193f04 100644 --- a/src/radioviewcontainer.cpp +++ b/src/radioviewcontainer.cpp @@ -31,6 +31,9 @@ RadioViewContainer::RadioViewContainer(QWidget *parent) { ui_.setupUi(this); + connect(ui_.tree, SIGNAL(collapsed(QModelIndex)), SLOT(Collapsed(QModelIndex))); + connect(ui_.tree, SIGNAL(expanded(QModelIndex)), SLOT(Expanded(QModelIndex))); + filter_animation_->setFrameRange(0, ui_.filter->sizeHint().height()); connect(filter_animation_, SIGNAL(frameChanged(int)), SLOT(SetFilterHeight(int))); @@ -47,19 +50,37 @@ void RadioViewContainer::SetModel(RadioModel* model) { SLOT(CurrentIndexChanged(QModelIndex))); } -void RadioViewContainer::CurrentIndexChanged(const QModelIndex& index) { +void RadioViewContainer::ServiceChanged(const QModelIndex& index, bool changed_away) { RadioItem* item = model_->IndexToItem( model_->merged_model()->FindSourceParent(index)); if (!item) return; - RadioService* service = item->service; - if (!service || service == current_service_) - return; + if (changed_away) { + SetFilterVisible(false); + } else { + RadioService* service = item->service; + if (!service || service == current_service_) + return; + current_service_ = service; - qDebug() << service->name(); + SetFilterVisible(service->SetupLibraryFilter(ui_.filter)); + } +} - SetFilterVisible(service->SetupLibraryFilter(ui_.filter)); +void RadioViewContainer::CurrentIndexChanged(const QModelIndex& index) { + ServiceChanged(index); +} + +void RadioViewContainer::Collapsed(const QModelIndex& index) { + if (model_->merged_model()->mapToSource(index).model() == model_) { + SetFilterVisible(false); + current_service_ = NULL; + } +} + +void RadioViewContainer::Expanded(const QModelIndex& index) { + ServiceChanged(index); } void RadioViewContainer::SetFilterVisible(bool visible) { diff --git a/src/radioviewcontainer.h b/src/radioviewcontainer.h index 383ae2b5b..2f20c4f9c 100644 --- a/src/radioviewcontainer.h +++ b/src/radioviewcontainer.h @@ -38,10 +38,13 @@ class RadioViewContainer : public QWidget { RadioView* tree() const { return ui_.tree; } private slots: + void Collapsed(const QModelIndex& index); + void Expanded(const QModelIndex& index); void CurrentIndexChanged(const QModelIndex& index); void SetFilterHeight(int height); private: + void ServiceChanged(const QModelIndex& index, bool changed_away = false); void SetFilterVisible(bool visible); private: