From 17abb37d291e302c033dc8007981c627a59e4f35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Omar=20Gonz=C3=A1les=20D=C3=ADaz?= Date: Thu, 12 Nov 2026 21:26:16 -0500 Subject: [PATCH] Give folder listings their own thread pool and make showItem invokable Listings, folder counts, previews and descriptions all ran on the global thread pool. Counting huge or slow subfolders could occupy every thread and queue the listing of a folder just opened behind them, so clicks seemed to do nothing until a few retries overtook the stuck work. Listings now run on a dedicated pool, and folder counts on a small separate one. Backend::showItem was missing Q_INVOKABLE, so clicking a file in the columns view threw "Property 'showItem' ... is not a function". Co-Authored-By: Claude Sonnet 5.5 --- src/backend.h | 2 +- src/foldermodel.cpp | 25 +++++++++++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/backend.h b/src/backend.h index 7d0f582d..51c3683e 100644 --- a/src/backend.h +++ b/src/backend.h @@ -102,7 +102,7 @@ class Backend : public QObject { // Called for org.freedesktop.FileManager1: open a folder, or open the // folder holding a file and select it. void showFolder(const QString &path); - void showItem(const QString &path); + Q_INVOKABLE void showItem(const QString &path); static QString expandTyped(const QString &text, const QString &home, const QString ¤t); static QString complete(const QString &text, const QString &home, const QString ¤t); diff --git a/src/foldermodel.cpp b/src/foldermodel.cpp index 2cce5a3f..83375e10 100644 --- a/src/foldermodel.cpp +++ b/src/foldermodel.cpp @@ -40,6 +40,27 @@ FolderModel::~FolderModel() { *m_latest = 0; } +// Folder listings run on a pool of their own, apart from the folder counts +// and previews on the global one: slow or huge subfolders being counted can't +// then hold up the listing of the folder just opened. +static QThreadPool &listingPool() { + static QThreadPool *const pool = [] { + auto *p = new QThreadPool; + p->setMaxThreadCount(8); + return p; + }(); + return *pool; +} + +static QThreadPool &countingPool() { + static QThreadPool *const pool = [] { + auto *p = new QThreadPool; + p->setMaxThreadCount(2); + return p; + }(); + return *pool; +} + // Recent listings, shared by every model (the window's folder and each // column), so stepping back and forth or opening a column for a folder just // seen shows it in the same frame instead of an old or empty one. Each is @@ -481,7 +502,7 @@ void FolderModel::reload() { remember(); countFolders(generation); }); - watcher->setFuture(QtConcurrent::run([path, showHidden, sort, query, items, latest, generation, locale] { + watcher->setFuture(QtConcurrent::run(&listingPool(), [path, showHidden, sort, query, items, latest, generation, locale] { QString error; const auto overtaken = [&] { return *latest != generation; }; auto entries = isPluginView(path) ? listItems(items, query) @@ -524,7 +545,7 @@ void FolderModel::countFolders(quint64 generation) { remember(); }); const auto latest = m_latest; - watcher->setFuture(QtConcurrent::run([folders, showHidden, latest, generation]() mutable { + watcher->setFuture(QtConcurrent::run(&countingPool(), [folders, showHidden, latest, generation]() mutable { // Overtaken (another folder, or a re-read), the counts would be // thrown away, so it stops instead of listing every subfolder. for (auto &folder : folders) {