Skip to content

Commit d49ccc1

Browse files
committed
Qt: cache root index in FileSystemProxyModel::filterAcceptsRow
The proxy model's filterAcceptsRow is called once per (row, parent) pair the source QFileSystemModel surfaces, which can run into the tens of thousands during a directory load, sort, or filter pass on a populous tree. The original implementation resolved the source model's root path to a QModelIndex via sm->index(sm->rootPath()) on every single call - cheap individually, but it adds up. The root path itself only changes when the user navigates, so cache both the path and its resolved index on the proxy. On each call, compare the cached path against the current one (a QString equality check, much cheaper than re-walking the model); refresh on mismatch. No behaviour change.
1 parent 146ac2e commit d49ccc1

2 files changed

Lines changed: 28 additions & 4 deletions

File tree

ui/drivers/ui_qt.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1386,12 +1386,26 @@ void LogTextEdit::appendMessage(const QString& text)
13861386
}
13871387

13881388
/* Only accept indexes from current path.
1389-
* https://www.qtcentre.org/threads/50700-QFileSystemModel-and-QSortFilterProxyModel-don-t-work-well-together */
1389+
* https://www.qtcentre.org/threads/50700-QFileSystemModel-and-QSortFilterProxyModel-don-t-work-well-together
1390+
*
1391+
* The root index is cached because this method is invoked once per
1392+
* (row, parent) pair the proxy considers - which can be tens of
1393+
* thousands per directory load on a populous tree - while the
1394+
* QFileSystemModel root path changes only when the user navigates.
1395+
* Resolving the root path to an index via sm->index(...) walks the
1396+
* model on every call without the cache. */
13901397
bool FileSystemProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
13911398
{
1392-
QFileSystemModel *sm = qobject_cast<QFileSystemModel*>(sourceModel());
1393-
QModelIndex rootIndex = sm->index(sm->rootPath());
1394-
if (sourceParent == rootIndex)
1399+
QFileSystemModel *sm = qobject_cast<QFileSystemModel*>(sourceModel());
1400+
const QString currentRoot = sm->rootPath();
1401+
1402+
if (currentRoot != m_cachedRootPath)
1403+
{
1404+
m_cachedRootPath = currentRoot;
1405+
m_cachedRootIndex = sm->index(currentRoot);
1406+
}
1407+
1408+
if (sourceParent == m_cachedRootIndex)
13951409
return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
13961410
return true;
13971411
}

ui/drivers/ui_qt.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,16 @@ class FileSystemProxyModel : public QSortFilterProxyModel
386386
protected:
387387
virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
388388
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
389+
private:
390+
/* Cache for filterAcceptsRow's "is this row a child of the
391+
* source model's current root?" check. The QFileSystemModel
392+
* root path rarely changes, but filterAcceptsRow can fire
393+
* thousands of times per directory load / sort / filter, and
394+
* resolving rootPath() to a QModelIndex via sm->index(...)
395+
* is not free. Compare the cached path string against the
396+
* current one on each call; refresh both members on mismatch. */
397+
mutable QString m_cachedRootPath;
398+
mutable QModelIndex m_cachedRootIndex;
389399
};
390400

391401
class LoadCoreTableWidget : public QTableWidget

0 commit comments

Comments
 (0)