#include "FileFrecencyProvider.h" #include #include #include "FrecencyStore.h" #include "RepoFileIndex.h" #include "RepoFileRows.h" FileFrecencyProvider::FileFrecencyProvider(QObject* parent) : FuzzyRowProvider(parent) { } void FileFrecencyProvider::setRoot(const QString& root) { if (m_root == root) { return; } { const QMutexLocker locker(&inputLock()); m_root = root; } emit rootChanged(); invalidate(); } void FileFrecencyProvider::setBackend(const QString& backend) { if (m_backend == backend) { return; } { const QMutexLocker locker(&inputLock()); m_backend = backend; } emit backendChanged(); invalidate(); } void FileFrecencyProvider::setIncludeTerminalRow(bool include) { if (m_includeTerminalRow == include) { return; } { const QMutexLocker locker(&inputLock()); m_includeTerminalRow = include; } emit includeTerminalRowChanged(); invalidate(); } QVariantList FileFrecencyProvider::rowsForQuery(const QString& query) { // Reached under inputLock(), so every input member is stable. const QString root = m_root; const bool includeTerminal = m_includeTerminalRow; const RepoBackend backend = repoBackendFromWord(m_backend); // A non-repo workspace has no version control list, so the chooser falls back // to the directory picker. An empty listing here stays silent. if (root.isEmpty() || backend == RepoBackend::None) { return {}; } const RepoFileList listing = RepoFileIndex::cachedFiles(root, backend); // One lock and one copy for the whole query, never one lock per candidate. const QHash scores = FrecencyStore::instance().snapshot(); const RepoRows ranked = rankRepoRows(listing.paths, root, query, includeTerminal, [&scores](const QString& path) { return scores.value(path, 0); }); // A listing that failed names its reason instead of the ranker's note. setNote(listing.error.isEmpty() ? ranked.note : listing.error); return ranked.rows; }