diff --git a/src/plugins/coreplugin/locator/basefilefilter.cpp b/src/plugins/coreplugin/locator/basefilefilter.cpp index ff6afc088d3..f38b61b74e1 100644 --- a/src/plugins/coreplugin/locator/basefilefilter.cpp +++ b/src/plugins/coreplugin/locator/basefilefilter.cpp @@ -46,7 +46,6 @@ BaseFileFilter::BaseFileFilter() QList BaseFileFilter::matchesFor(QFutureInterface &future, const QString &origEntry) { - updateFiles(); QList betterEntries; QList goodEntries; QString needle = trimWildcards(QDir::fromNativeSeparators(origEntry)); @@ -120,7 +119,3 @@ void BaseFileFilter::generateFileNames() } m_forceNewSearchList = true; } - -void BaseFileFilter::updateFiles() -{ -} diff --git a/src/plugins/coreplugin/locator/basefilefilter.h b/src/plugins/coreplugin/locator/basefilefilter.h index b8e95dc06f0..9c8cfad82d6 100644 --- a/src/plugins/coreplugin/locator/basefilefilter.h +++ b/src/plugins/coreplugin/locator/basefilefilter.h @@ -46,10 +46,10 @@ public: void accept(Core::LocatorFilterEntry selection) const; protected: - // runs in non-UI thread - virtual void updateFiles(); + /* Generates the file names from the list of file paths in m_files. */ void generateFileNames(); + /* Subclasses should update the file list latest in their prepareSearch method. */ inline QStringList &files() { return m_files; } inline const QStringList &files() const { return m_files; } diff --git a/src/plugins/coreplugin/locator/filesystemfilter.cpp b/src/plugins/coreplugin/locator/filesystemfilter.cpp index f3c6aa0c824..85ec1f3f84e 100644 --- a/src/plugins/coreplugin/locator/filesystemfilter.cpp +++ b/src/plugins/coreplugin/locator/filesystemfilter.cpp @@ -63,6 +63,18 @@ FileSystemFilter::FileSystemFilter(LocatorWidget *locatorWidget) setIncludedByDefault(false); } +void FileSystemFilter::prepareSearch(const QString &entry) +{ + Q_UNUSED(entry) + IDocument *document= EditorManager::currentDocument(); + if (document && !document->filePath().isEmpty()) { + QFileInfo info(document->filePath()); + m_currentDocumentDirectory = info.absolutePath() + QLatin1Char('/'); + } else { + m_currentDocumentDirectory.clear(); + } +} + QList FileSystemFilter::matchesFor(QFutureInterface &future, const QString &entry) { QList goodEntries; @@ -72,15 +84,10 @@ QList FileSystemFilter::matchesFor(QFutureInterfacefilePath().isEmpty()) { - QFileInfo info(document->filePath()); - directory.prepend(info.absolutePath() + QLatin1Char('/')); - } - } + else if (!m_currentDocumentDirectory.isEmpty()) + directory.prepend(m_currentDocumentDirectory); } QDir dirInfo(directory); QDir::Filters dirFilter = QDir::Dirs|QDir::Drives|QDir::NoDot; diff --git a/src/plugins/coreplugin/locator/filesystemfilter.h b/src/plugins/coreplugin/locator/filesystemfilter.h index a6f0283065c..d4786503324 100644 --- a/src/plugins/coreplugin/locator/filesystemfilter.h +++ b/src/plugins/coreplugin/locator/filesystemfilter.h @@ -49,6 +49,7 @@ class FileSystemFilter : public Core::ILocatorFilter public: explicit FileSystemFilter(LocatorWidget *locatorWidget); + void prepareSearch(const QString &entry); QList matchesFor(QFutureInterface &future, const QString &entry); void accept(Core::LocatorFilterEntry selection) const; QByteArray saveState() const; @@ -59,6 +60,7 @@ public: private: LocatorWidget *m_locatorWidget; bool m_includeHidden; + QString m_currentDocumentDirectory; }; } // namespace Internal diff --git a/src/plugins/coreplugin/locator/ilocatorfilter.cpp b/src/plugins/coreplugin/locator/ilocatorfilter.cpp index ea91197cc66..7a019ed61ab 100644 --- a/src/plugins/coreplugin/locator/ilocatorfilter.cpp +++ b/src/plugins/coreplugin/locator/ilocatorfilter.cpp @@ -53,6 +53,11 @@ QString ILocatorFilter::shortcutString() const return m_shortcut; } +void ILocatorFilter::prepareSearch(const QString &entry) +{ + Q_UNUSED(entry) +} + void ILocatorFilter::setShortcutString(const QString &shortcut) { m_shortcut = shortcut; diff --git a/src/plugins/coreplugin/locator/ilocatorfilter.h b/src/plugins/coreplugin/locator/ilocatorfilter.h index 3c6e213fa02..8887973b1e7 100644 --- a/src/plugins/coreplugin/locator/ilocatorfilter.h +++ b/src/plugins/coreplugin/locator/ilocatorfilter.h @@ -100,7 +100,13 @@ public: /* String to type to use this filter exclusively. */ QString shortcutString() const; - /* List of matches for the given user entry. */ + /* Called on the main thread before matchesFor is called in a separate thread. + Can be used to perform actions that need to be done in the main thread before actually + running the search. */ + virtual void prepareSearch(const QString &entry); + + /* List of matches for the given user entry. This runs in a separate thread, but only + a single thread at a time. */ virtual QList matchesFor(QFutureInterface &future, const QString &entry) = 0; /* User has selected the given entry that belongs to this filter. */ diff --git a/src/plugins/coreplugin/locator/locator_test.cpp b/src/plugins/coreplugin/locator/locator_test.cpp index c9bcdb880ba..cb88d0261b6 100644 --- a/src/plugins/coreplugin/locator/locator_test.cpp +++ b/src/plugins/coreplugin/locator/locator_test.cpp @@ -57,9 +57,6 @@ public: } void refresh(QFutureInterface &) {} - -protected: - void updateFiles() {} }; inline QString _(const QByteArray &ba) { return QString::fromLatin1(ba, ba.size()); } diff --git a/src/plugins/coreplugin/locator/locatorfiltersfilter.cpp b/src/plugins/coreplugin/locator/locatorfiltersfilter.cpp index 7f99d475bc7..dcb9172f83a 100644 --- a/src/plugins/coreplugin/locator/locatorfiltersfilter.cpp +++ b/src/plugins/coreplugin/locator/locatorfiltersfilter.cpp @@ -52,11 +52,12 @@ LocatorFiltersFilter::LocatorFiltersFilter(Locator *plugin, setConfigurable(false); } -QList LocatorFiltersFilter::matchesFor(QFutureInterface &future, const QString &entry) +void LocatorFiltersFilter::prepareSearch(const QString &entry) { - QList entries; + m_filterShortcutStrings.clear(); + m_filterDisplayNames.clear(); if (!entry.isEmpty()) - return entries; + return; QMap uniqueFilters; foreach (ILocatorFilter *filter, m_plugin->filters()) { @@ -65,27 +66,36 @@ QList LocatorFiltersFilter::matchesFor(QFutureInterfaceshortcutString().isEmpty() && !filter->isHidden() && filter->isEnabled()) { - LocatorFilterEntry filterEntry(this, - filter->shortcutString(), - QVariant::fromValue(filter), - m_icon); - filterEntry.extraInfo = filter->displayName(); - entries.append(filterEntry); + m_filterShortcutStrings.append(filter->shortcutString()); + m_filterDisplayNames.append(filter->displayName()); } } +} +QList LocatorFiltersFilter::matchesFor(QFutureInterface &future, const QString &entry) +{ + Q_UNUSED(entry) // search is already done in the GUI thread in prepareSearch + QList entries; + for (int i = 0; i < m_filterShortcutStrings.size(); ++i) { + if (future.isCanceled()) + break; + LocatorFilterEntry filterEntry(this, + m_filterShortcutStrings.at(i), + m_filterShortcutStrings.at(i), + m_icon); + filterEntry.extraInfo = m_filterDisplayNames.at(i); + entries.append(filterEntry); + } return entries; } void LocatorFiltersFilter::accept(LocatorFilterEntry selection) const { - ILocatorFilter *filter = selection.internalData.value(); - if (filter) - m_locatorWidget->show(filter->shortcutString() + QLatin1Char(' '), - filter->shortcutString().length() + 1); + const QString shortcutString = selection.internalData.toString(); + if (!shortcutString.isEmpty()) + m_locatorWidget->show(shortcutString + QLatin1Char(' '), + shortcutString.length() + 1); } void LocatorFiltersFilter::refresh(QFutureInterface &future) diff --git a/src/plugins/coreplugin/locator/locatorfiltersfilter.h b/src/plugins/coreplugin/locator/locatorfiltersfilter.h index bfb7d2655bf..5ea89f44f3d 100644 --- a/src/plugins/coreplugin/locator/locatorfiltersfilter.h +++ b/src/plugins/coreplugin/locator/locatorfiltersfilter.h @@ -53,6 +53,7 @@ public: LocatorWidget *locatorWidget); // ILocatorFilter + void prepareSearch(const QString &entry); QList matchesFor(QFutureInterface &future, const QString &entry); void accept(LocatorFilterEntry selection) const; void refresh(QFutureInterface &future); @@ -60,6 +61,8 @@ public: private: Locator *m_plugin; LocatorWidget *m_locatorWidget; + QStringList m_filterShortcutStrings; + QStringList m_filterDisplayNames; QIcon m_icon; }; diff --git a/src/plugins/coreplugin/locator/locatorwidget.cpp b/src/plugins/coreplugin/locator/locatorwidget.cpp index 348a91da711..91032d07a05 100644 --- a/src/plugins/coreplugin/locator/locatorwidget.cpp +++ b/src/plugins/coreplugin/locator/locatorwidget.cpp @@ -491,6 +491,9 @@ void LocatorWidget::updateCompletionList(const QString &text) QString searchText; const QList filters = filtersFor(text, searchText); + + foreach (ILocatorFilter *filter, filters) + filter->prepareSearch(searchText); QFuture future = QtConcurrent::run(runSearch, filters, searchText); m_entriesWatcher->setFuture(future); } diff --git a/src/plugins/coreplugin/locator/opendocumentsfilter.cpp b/src/plugins/coreplugin/locator/opendocumentsfilter.cpp index 422b9afa202..c7f86276290 100644 --- a/src/plugins/coreplugin/locator/opendocumentsfilter.cpp +++ b/src/plugins/coreplugin/locator/opendocumentsfilter.cpp @@ -34,6 +34,7 @@ #include #include +#include using namespace Core; using namespace Core; @@ -67,7 +68,7 @@ QList OpenDocumentsFilter::matchesFor(QFutureInterface OpenDocumentsFilter::matchesFor(QFutureInterface OpenDocumentsFilter::editors() const +{ + QMutexLocker lock(&m_mutex); Q_UNUSED(lock) + return m_editors; +} + void OpenDocumentsFilter::refresh(QFutureInterface &future) { Q_UNUSED(future) diff --git a/src/plugins/coreplugin/locator/opendocumentsfilter.h b/src/plugins/coreplugin/locator/opendocumentsfilter.h index b16ca7144b9..63c4944a802 100644 --- a/src/plugins/coreplugin/locator/opendocumentsfilter.h +++ b/src/plugins/coreplugin/locator/opendocumentsfilter.h @@ -34,9 +34,10 @@ #include -#include -#include #include +#include +#include +#include namespace Core { namespace Internal { @@ -55,6 +56,9 @@ public slots: void refreshInternally(); private: + QList editors() const; + + mutable QMutex m_mutex; QList m_editors; }; diff --git a/src/plugins/help/helpindexfilter.cpp b/src/plugins/help/helpindexfilter.cpp index ebd04c3954c..f604b8748c9 100644 --- a/src/plugins/help/helpindexfilter.cpp +++ b/src/plugins/help/helpindexfilter.cpp @@ -59,16 +59,19 @@ HelpIndexFilter::~HelpIndexFilter() { } +void HelpIndexFilter::prepareSearch(const QString &entry) +{ + if (entry.length() < 2) + m_keywords = Core::HelpManager::findKeywords(entry, caseSensitivity(entry), 200); + else + m_keywords = Core::HelpManager::findKeywords(entry, caseSensitivity(entry)); +} + QList HelpIndexFilter::matchesFor(QFutureInterface &future, const QString &entry) { - QStringList keywords; - if (entry.length() < 2) - keywords = Core::HelpManager::findKeywords(entry, caseSensitivity(entry), 200); - else - keywords = Core::HelpManager::findKeywords(entry, caseSensitivity(entry)); - + Q_UNUSED(entry) // search is already done in the GUI thread in prepareSearch QList entries; - foreach (const QString &keyword, keywords) { + foreach (const QString &keyword, m_keywords) { if (future.isCanceled()) break; entries.append(LocatorFilterEntry(this, keyword, QVariant(), m_icon)); diff --git a/src/plugins/help/helpindexfilter.h b/src/plugins/help/helpindexfilter.h index ae0e4bf7f4a..89933afe987 100644 --- a/src/plugins/help/helpindexfilter.h +++ b/src/plugins/help/helpindexfilter.h @@ -46,6 +46,7 @@ public: ~HelpIndexFilter(); // ILocatorFilter + void prepareSearch(const QString &entry); QList matchesFor(QFutureInterface &future, const QString &entry); void accept(Core::LocatorFilterEntry selection) const; void refresh(QFutureInterface &future); @@ -55,6 +56,7 @@ signals: private: QIcon m_icon; + QStringList m_keywords; }; } // namespace Internal diff --git a/src/plugins/help/remotehelpfilter.cpp b/src/plugins/help/remotehelpfilter.cpp index 1d57572911d..932b6b5bcb8 100644 --- a/src/plugins/help/remotehelpfilter.cpp +++ b/src/plugins/help/remotehelpfilter.cpp @@ -29,6 +29,7 @@ #include "remotehelpfilter.h" +#include #include namespace Help { @@ -99,7 +100,7 @@ RemoteHelpFilter::~RemoteHelpFilter() QList RemoteHelpFilter::matchesFor(QFutureInterface &future, const QString &pattern) { QList entries; - foreach (const QString &url, m_remoteUrls) { + foreach (const QString &url, remoteUrls()) { if (future.isCanceled()) break; @@ -156,6 +157,7 @@ bool RemoteHelpFilter::openConfigDialog(QWidget *parent, bool &needsRefresh) Q_UNUSED(needsRefresh) RemoteFilterOptions optionsDialog(this, parent); if (optionsDialog.exec() == QDialog::Accepted) { + QMutexLocker lock(&m_mutex); Q_UNUSED(lock) m_remoteUrls.clear(); setIncludedByDefault(!optionsDialog.m_ui.limitCheck->isChecked()); setShortcutString(optionsDialog.m_ui.shortcutEdit->text().trimmed()); @@ -166,5 +168,11 @@ bool RemoteHelpFilter::openConfigDialog(QWidget *parent, bool &needsRefresh) return true; } +QStringList RemoteHelpFilter::remoteUrls() const +{ + QMutexLocker lock(&m_mutex); Q_UNUSED(lock) + return m_remoteUrls; +} + } // namespace Internal } // namespace Help diff --git a/src/plugins/help/remotehelpfilter.h b/src/plugins/help/remotehelpfilter.h index 958deb1cbd2..100e7fc6742 100644 --- a/src/plugins/help/remotehelpfilter.h +++ b/src/plugins/help/remotehelpfilter.h @@ -35,6 +35,7 @@ #include #include +#include namespace Help { namespace Internal { @@ -54,7 +55,7 @@ public: bool restoreState(const QByteArray &state); bool openConfigDialog(QWidget *parent, bool &needsRefresh); - QStringList remoteUrls() const { return m_remoteUrls; } + QStringList remoteUrls() const; signals: void linkActivated(const QUrl &url) const; @@ -62,6 +63,7 @@ signals: private: QIcon m_icon; QStringList m_remoteUrls; + mutable QMutex m_mutex; }; class RemoteFilterOptions : public QDialog diff --git a/src/plugins/projectexplorer/allprojectsfilter.cpp b/src/plugins/projectexplorer/allprojectsfilter.cpp index 6972b25daa7..7c98f2f34fe 100644 --- a/src/plugins/projectexplorer/allprojectsfilter.cpp +++ b/src/plugins/projectexplorer/allprojectsfilter.cpp @@ -34,6 +34,8 @@ #include +#include + using namespace Core; using namespace ProjectExplorer; using namespace ProjectExplorer::Internal; @@ -52,11 +54,14 @@ AllProjectsFilter::AllProjectsFilter() : m_filesUpToDate(false) void AllProjectsFilter::markFilesAsOutOfDate() { + QMutexLocker lock(&m_mutex); Q_UNUSED(lock) m_filesUpToDate = false; } -void AllProjectsFilter::updateFilesImpl() +void AllProjectsFilter::prepareSearch(const QString &entry) { + Q_UNUSED(entry) + QMutexLocker lock(&m_mutex); Q_UNUSED(lock) if (m_filesUpToDate) return; files().clear(); @@ -67,13 +72,8 @@ void AllProjectsFilter::updateFilesImpl() m_filesUpToDate = true; } -void AllProjectsFilter::updateFiles() -{ - QMetaObject::invokeMethod(this, "updateFilesImpl", Qt::BlockingQueuedConnection); -} - void AllProjectsFilter::refresh(QFutureInterface &future) { Q_UNUSED(future) - QMetaObject::invokeMethod(this, "markFilesAsOutOfDate", Qt::BlockingQueuedConnection); + markFilesAsOutOfDate(); } diff --git a/src/plugins/projectexplorer/allprojectsfilter.h b/src/plugins/projectexplorer/allprojectsfilter.h index 1d12e6d54d0..7330c987b58 100644 --- a/src/plugins/projectexplorer/allprojectsfilter.h +++ b/src/plugins/projectexplorer/allprojectsfilter.h @@ -32,6 +32,7 @@ #include +#include #include namespace ProjectExplorer { @@ -44,16 +45,14 @@ class AllProjectsFilter : public Core::BaseFileFilter public: AllProjectsFilter(); void refresh(QFutureInterface &future); - -protected: - void updateFiles(); + void prepareSearch(const QString &entry); private slots: void markFilesAsOutOfDate(); - void updateFilesImpl(); private: bool m_filesUpToDate; + QMutex m_mutex; }; } // namespace Internal diff --git a/src/plugins/projectexplorer/currentprojectfilter.cpp b/src/plugins/projectexplorer/currentprojectfilter.cpp index 2a04772e98b..834b7f5be84 100644 --- a/src/plugins/projectexplorer/currentprojectfilter.cpp +++ b/src/plugins/projectexplorer/currentprojectfilter.cpp @@ -33,7 +33,7 @@ #include -#include +#include using namespace Core; using namespace ProjectExplorer; @@ -54,25 +54,23 @@ CurrentProjectFilter::CurrentProjectFilter() void CurrentProjectFilter::markFilesAsOutOfDate() { + QMutexLocker lock(&m_filesUpToDateMutex); Q_UNUSED(lock) m_filesUpToDate = false; } -void CurrentProjectFilter::updateFilesImpl() +void CurrentProjectFilter::prepareSearch(const QString &entry) { + Q_UNUSED(entry) + QMutexLocker lock(&m_filesUpToDateMutex); Q_UNUSED(lock) if (m_filesUpToDate) return; files().clear(); + m_filesUpToDate = true; if (!m_project) return; files() = m_project->files(Project::AllFiles); Utils::sort(files()); generateFileNames(); - m_filesUpToDate = true; -} - -void CurrentProjectFilter::updateFiles() -{ - QMetaObject::invokeMethod(this, "updateFilesImpl", Qt::BlockingQueuedConnection); } void CurrentProjectFilter::currentProjectChanged(ProjectExplorer::Project *project) @@ -92,5 +90,5 @@ void CurrentProjectFilter::currentProjectChanged(ProjectExplorer::Project *proje void CurrentProjectFilter::refresh(QFutureInterface &future) { Q_UNUSED(future) - QMetaObject::invokeMethod(this, "markFilesAsOutOfDate", Qt::BlockingQueuedConnection); + markFilesAsOutOfDate(); } diff --git a/src/plugins/projectexplorer/currentprojectfilter.h b/src/plugins/projectexplorer/currentprojectfilter.h index f1a9a5f682a..d2b9b7e767c 100644 --- a/src/plugins/projectexplorer/currentprojectfilter.h +++ b/src/plugins/projectexplorer/currentprojectfilter.h @@ -32,6 +32,7 @@ #include +#include #include namespace ProjectExplorer { @@ -47,18 +48,16 @@ class CurrentProjectFilter : public Core::BaseFileFilter public: CurrentProjectFilter(); void refresh(QFutureInterface &future); - -protected: - void updateFiles(); + void prepareSearch(const QString &entry); private slots: void currentProjectChanged(ProjectExplorer::Project *project); void markFilesAsOutOfDate(); - void updateFilesImpl(); private: Project *m_project; bool m_filesUpToDate; + QMutex m_filesUpToDateMutex; }; } // namespace Internal diff --git a/src/plugins/texteditor/linenumberfilter.cpp b/src/plugins/texteditor/linenumberfilter.cpp index 4be1ef5efdd..d62ca628042 100644 --- a/src/plugins/texteditor/linenumberfilter.cpp +++ b/src/plugins/texteditor/linenumberfilter.cpp @@ -56,6 +56,12 @@ LineNumberFilter::LineNumberFilter(QObject *parent) setIncludedByDefault(true); } +void LineNumberFilter::prepareSearch(const QString &entry) +{ + Q_UNUSED(entry) + m_hasCurrentEditor = EditorManager::currentEditor() != 0; +} + QList LineNumberFilter::matchesFor(QFutureInterface &, const QString &entry) { QList value; @@ -70,7 +76,7 @@ QList LineNumberFilter::matchesFor(QFutureInterface 0 || column > 0)) { + if (m_hasCurrentEditor && (line > 0 || column > 0)) { LineColumn data; data.first = line; data.second = column - 1; // column API is 0-based diff --git a/src/plugins/texteditor/linenumberfilter.h b/src/plugins/texteditor/linenumberfilter.h index 3806d18f336..ede35e5433d 100644 --- a/src/plugins/texteditor/linenumberfilter.h +++ b/src/plugins/texteditor/linenumberfilter.h @@ -48,9 +48,13 @@ class LineNumberFilter : public Core::ILocatorFilter public: explicit LineNumberFilter(QObject *parent = 0); + void prepareSearch(const QString &entry); QList matchesFor(QFutureInterface &future, const QString &entry); void accept(Core::LocatorFilterEntry selection) const; void refresh(QFutureInterface &) {} + +private: + bool m_hasCurrentEditor; }; } // namespace Internal