# # # patch "src/model/InventoryProxyModel.cpp" # from [41d21933f657f8770ad2bdb9326713a5fb87e304] # to [0b7f2d44195acd246cdd292415a345a67fb1e83f] # # patch "src/model/InventoryProxyModel.h" # from [31ef55bd31c2a7d42b78e2075d55ec0790d878d5] # to [0472a2751889e3209e24b149fafc783d33459546] # # patch "src/view/widgets/InventoryView.cpp" # from [dbae5d250156d43175d81fcccf0beabb70ee5cbc] # to [cd313bd52774526e90d5e661775fd4cd162abf96] # # patch "src/view/widgets/InventoryView.h" # from [7ccc453cf7ac4036ad6f9ec23b7e9f5bda23690f] # to [a04f4968a3d59a53595de7a71e588b2c2174e8f6] # ============================================================ --- src/model/InventoryProxyModel.cpp 41d21933f657f8770ad2bdb9326713a5fb87e304 +++ src/model/InventoryProxyModel.cpp 0b7f2d44195acd246cdd292415a345a67fb1e83f @@ -25,7 +25,9 @@ InventoryProxyModel::InventoryProxyModel sortColumn(0), hideIgnored(false), viewOption(All), sortOrder(Qt::AscendingOrder) { - filter.setCaseSensitivity(Qt::CaseInsensitive); + // FIXME: maybe this should be configurable? + filter.setCaseSensitivity(Qt::CaseSensitive); + filter.setPatternSyntax(QRegExp::Wildcard); } InventoryProxyModel::~InventoryProxyModel() {} @@ -150,64 +152,50 @@ void InventoryProxyModel::setHideIgnored void InventoryProxyModel::setHideIgnoredFiles(bool hide) { - if (hide == hideIgnored) return; + if (hide == hideIgnored) + return; + hideIgnored = hide; - invalidateFilter(); + invalidate(); } void InventoryProxyModel::setViewOption(int opt) { ViewOption newOpt = static_cast(opt); - if (viewOption == newOpt) return; + if (viewOption == newOpt) + return; + viewOption = newOpt; - invalidateFilter(); + invalidate(); } void InventoryProxyModel::filterItemsByName(const QString & pattern) { - if (pattern.isEmpty()) - { - filter.setPattern(QString()); - filterCache.clear(); - invalidateFilter(); - return; - } - - QString escapedPattern = QRegExp::escape(pattern); - if (filter.pattern() == escapedPattern) - return; - - filter.setPattern(escapedPattern); - filterCache.clear(); - invalidateFilter(); + filter.setPattern(pattern); + invalidate(); } +// FIXME: we're basically doing this twice for each proxy model, while +// a single proxy model which does the filtering for both (sub) proxy +// models should be enough. Tweak that some time. bool InventoryProxyModel::itemMatchesFilter(const InventoryItem * item) { - QString path = item->getPath(); - if (filterCache.contains(path)) - { - return filterCache[path]; - } - if (filter.indexIn(item->getLabel()) >= 0) { - filterCache.insert(path, true); return true; } - if (folderTree) + // we always have to filter _all_ items of the view even if we only + // display a subset of them in a list-alike way, since the parents + // of a specific matched node must match as well in order to keep + // the node in + foreach (const ModelItem * child, item->getChildren()) { - foreach (const ModelItem * child, item->getChildren()) - { - const InventoryItem * invitem = - qobject_cast(child); + const InventoryItem * invitem = + qobject_cast(child); - if (invitem && itemMatchesFilter(invitem)) - { - return true; - } - } + if (invitem && itemMatchesFilter(invitem)) + return true; } return false; ============================================================ --- src/model/InventoryProxyModel.h 31ef55bd31c2a7d42b78e2075d55ec0790d878d5 +++ src/model/InventoryProxyModel.h 0472a2751889e3209e24b149fafc783d33459546 @@ -52,7 +52,6 @@ private: ViewOption viewOption; Qt::SortOrder sortOrder; QRegExp filter; - QMap filterCache; }; #endif ============================================================ --- src/view/widgets/InventoryView.cpp dbae5d250156d43175d81fcccf0beabb70ee5cbc +++ src/view/widgets/InventoryView.cpp cd313bd52774526e90d5e661775fd4cd162abf96 @@ -45,6 +45,21 @@ InventoryView::InventoryView(QWidget * p this, SIGNAL(contextMenuRequested(const QModelIndexList &, const QPoint &)), this, SLOT(slotContextMenuRequested(const QModelIndexList &, const QPoint &)) ); + + // this is a hack: if we connect the model's layoutChanged() signal + // directly with a slot in the view, actions like setting the root + // index of an item or expanding it won't be processed, probably + // because QAbstractItemView also listens to the event and processes + // it after our slot is done. So we're doing our work within the next + // event loop round + timer = new QTimer(); + timer->setSingleShot(true); + timer->setInterval(0); + + connect( + timer, SIGNAL(timeout()), + this, SLOT(delayedLayoutChanged()) + ); } QModelIndex InventoryView::sourceIndex(const QModelIndex & proxy, bool useIndexModel) const @@ -240,75 +255,29 @@ void InventoryView::setModel(QSortFilter if (oldModel) { disconnect( - oldModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), - this, SLOT(expandRootNode(const QModelIndex &, const QModelIndex &)) - ); - - disconnect( oldModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(rowsInserted(QModelIndex &, int, int)) ); disconnect( - oldModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), - this, SLOT(rowsRemoved(const QModelIndex &, int, int)) + oldModel, SIGNAL(layoutChanged()), + timer, SLOT(start()) ); - - disconnect( - oldModel, SIGNAL(modelReset()), - this, SLOT(modelReset()) - ); } TreeView::setModel(newModel); connect( - newModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), - this, SLOT(expandRootNode(const QModelIndex &, const QModelIndex &)) - ); - - connect( newModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(rowsInserted(const QModelIndex &, int, int)) ); connect( - newModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), - this, SLOT(rowsRemoved(const QModelIndex &, int, int)) + newModel, SIGNAL(layoutChanged()), + timer, SLOT(start()) ); - - connect( - newModel, SIGNAL(modelReset()), - this, SLOT(modelReset()) - ); } -/*! - this is merely a generic which uses the dataChanged signal to get notified - if the root node can be expanded or not - unfortunately there is no other - way to trigger such things from the model -*/ -void InventoryView::expandRootNode(const QModelIndex & index, const QModelIndex & dummy) -{ - Q_UNUSED(dummy); - - if (!index.isValid()) - return; - - // this is not the root workspace node... - if (index.parent().isValid()) - return; - - if (type == FileList) - { - setRootIndex(index); - } - else - { - expand(index); - } -} - // adds elements to the popup menu based on the selected items // since not all actions may apply on all items void InventoryView::slotContextMenuRequested(const QModelIndexList & indexList, const QPoint & pos) @@ -577,6 +546,9 @@ void InventoryView::changeDirectory(cons QModelIndex source = sourceIndex(proxy, true); QModelIndex ourProxyIndex = proxyIndex(source); + if (source.isValid()) + lastActiveIndex = source; + if (type == FileList) { // if we don't do this, right-clicking in the empty space will @@ -588,6 +560,7 @@ void InventoryView::changeDirectory(cons if (psitem && psitem->isCdUp()) { + lastActiveIndex = source.parent().parent(); // list the contents of the parent of the parent directory setRootIndex(ourProxyIndex.parent().parent()); return; @@ -816,7 +789,6 @@ void InventoryView::slotRefresh() if (!item) return; const InventoryItem * invItem = dynamic_cast(item); - D(QString("path: %1").arg(item->getLabel())); if (!invItem) return; @@ -971,7 +943,7 @@ void InventoryView::slotFileDiff() if (!invitem->hasStatus(InventoryItem::ContentsChanged)) { - D("File has no content changes"); + L("File has no content changes"); return; } @@ -1194,28 +1166,6 @@ InventoryView::DefaultAction InventoryVi return None; } -/*! - If the model contains no data, display a "no matches" background image - This usually happens when the proxy model has filtered out everything - and maybe in some weird error case which should not happen at all... -*/ -void InventoryView::setBackgroundImage() -{ - if (model()->hasChildren()) - { - setStyleSheet(QString()); - } - else - { - setStyleSheet("InventoryView { " - "background-color: white;" - "background-image: url(:/images/no_matches.png);" - "background-attachment: fixed;" - "background-position: center;" - "background-repeat: no-repeat;}"); - } -} - void InventoryView::rowsInserted(const QModelIndex & parent, int start, int end) { Q_UNUSED(start); @@ -1242,21 +1192,41 @@ void InventoryView::rowsInserted(const Q newPath = QString(); } } - - setBackgroundImage(); } -void InventoryView::rowsRemoved(const QModelIndex & parent, int start, int end) +void InventoryView::delayedLayoutChanged() { - Q_UNUSED(parent); - Q_UNUSED(start); - Q_UNUSED(end); + QModelIndex index = model()->index(0, 0, QModelIndex()); + // if we have a previous, still valid active source index, use + // that to restore the state somewhat which existed before the layout + // of the view changed completely + if (lastActiveIndex.isValid()) + { + index = proxyIndex(lastActiveIndex); + } - setBackgroundImage(); -} + if (index.isValid()) + { + setStyleSheet(QString()); -void InventoryView::modelReset() -{ - setBackgroundImage(); + QVariant dat = index.data(); + + if (type == FileList) + { + setRootIndex(index); + return; + } + + expand(index); + return; + } + + setStyleSheet("InventoryView { " + "background-color: white;" + "background-image: url(:/images/no_matches.png);" + "background-attachment: fixed;" + "background-position: center;" + "background-repeat: no-repeat;}" + ); } ============================================================ --- src/view/widgets/InventoryView.h 7ccc453cf7ac4036ad6f9ec23b7e9f5bda23690f +++ src/view/widgets/InventoryView.h a04f4968a3d59a53595de7a71e588b2c2174e8f6 @@ -24,6 +24,7 @@ #include "InventoryItem.h" #include +#include #include class InventoryItem; @@ -67,7 +68,6 @@ private: DefaultAction getDefaultAction(const QModelIndex &) const; void createAndConnectContextActions(); void closeEvent(); - void setBackgroundImage(); inline QModelIndex sourceIndex(const QModelIndex &, bool useIndexModel = false) const; inline QModelIndex proxyIndex(const QModelIndex &) const; @@ -103,16 +103,16 @@ private: InventoryViewDelegate invViewDelegate; QString newPath; + QPersistentModelIndex lastActiveIndex; + QTimer * timer; private slots: - void expandRootNode(const QModelIndex &, const QModelIndex &); void changeDirectory(const QModelIndex &); void slotContextMenuRequested(const QModelIndexList &, const QPoint &); void itemClicked(const QModelIndex & index); void itemDoubleClicked(const QModelIndex & index); void rowsInserted(const QModelIndex &, int, int); - void rowsRemoved(const QModelIndex &, int, int); - void modelReset(); + void delayedLayoutChanged(); void slotChdir(); void slotOpen();