Don't reset the whole merged model when one of the submodels changes

This commit is contained in:
David Sansome 2010-05-09 21:16:54 +00:00
parent e2355d855d
commit bef59ffd22
4 changed files with 67 additions and 11 deletions

View File

@ -17,13 +17,17 @@
#include "mergedproxymodel.h"
#include <QStringList>
#include <QtDebug>
#include <limits>
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<const QAbstractItemModel*>(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<int>::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<int>::max() - 1);
endRemoveRows();
resetting_model_ = NULL;
// Delete all the mappings that reference the submodel
MappingContainer::index<tag_by_pointer>::type::iterator it =
mappings_.get<tag_by_pointer>().begin();
MappingContainer::index<tag_by_pointer>::type::iterator end =
mappings_.get<tag_by_pointer>().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<Mapping*>(proxy_index.internalPointer());
if (mappings_.get<tag_by_pointer>().find(mapping) ==
mappings_.get<tag_by_pointer>().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<tag_by_source>::type::iterator it =

View File

@ -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<const QAbstractItemModel*, QModelIndex> merge_points_;
const QAbstractItemModel* resetting_model_;
};
#endif // MERGEDPROXYMODEL_H

View File

@ -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) {

View File

@ -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: