From c8464b6928ce27413dec7db8c2745b77af91f47d Mon Sep 17 00:00:00 2001 From: Artur Spychaj Date: Fri, 4 Dec 2015 21:30:08 -0800 Subject: [PATCH] registry: Allow to cancel current searches When user types into the search box the previous search is canceled. This improves the speed with which the results can be obtained. Based on #460 plus cosmetic changes. Related to #265, #523. --- src/registry/cancellationtoken.cpp | 40 +++++++++++++++++++++++++ src/registry/cancellationtoken.h | 47 ++++++++++++++++++++++++++++++ src/registry/docsetregistry.cpp | 18 +++++++----- src/registry/docsetregistry.h | 6 ++-- src/ui/mainwindow.cpp | 4 ++- src/ui/mainwindow.h | 3 ++ 6 files changed, 107 insertions(+), 11 deletions(-) create mode 100644 src/registry/cancellationtoken.cpp create mode 100644 src/registry/cancellationtoken.h diff --git a/src/registry/cancellationtoken.cpp b/src/registry/cancellationtoken.cpp new file mode 100644 index 000000000..e8e2b8785 --- /dev/null +++ b/src/registry/cancellationtoken.cpp @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Artur Spychaj +** Contact: http://zealdocs.org/contact.html +** +** This file is part of Zeal. +** +** Zeal is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** Zeal is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with Zeal. If not, see . +** +****************************************************************************/ + +#include "cancellationtoken.h" + +using namespace Zeal; + +CancellationToken::CancellationToken() +{ + m_cancelled = QSharedPointer(new bool(false)); +} + +void CancellationToken::cancel() +{ + *m_cancelled = true; +} + +bool CancellationToken::isCanceled() const +{ + return *m_cancelled; +} diff --git a/src/registry/cancellationtoken.h b/src/registry/cancellationtoken.h new file mode 100644 index 000000000..75222d554 --- /dev/null +++ b/src/registry/cancellationtoken.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Artur Spychaj +** Contact: http://zealdocs.org/contact.html +** +** This file is part of Zeal. +** +** Zeal is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** Zeal is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with Zeal. If not, see . +** +****************************************************************************/ + +#ifndef CANCELLATIONTOKEN_H +#define CANCELLATIONTOKEN_H + +#include + +namespace Zeal { + +/// Token that stores whether cancel was called on it. +/// In async code can be used to check if another thread called cancel. +struct CancellationToken +{ +public: + CancellationToken(); + bool isCanceled() const; + void cancel(); + +private: + QSharedPointer m_cancelled; +}; + +} + +Q_DECLARE_METATYPE(Zeal::CancellationToken) + +#endif // CANCELLATIONTOKEN_H diff --git a/src/registry/docsetregistry.cpp b/src/registry/docsetregistry.cpp index ef0ea5d55..81ccb6c08 100644 --- a/src/registry/docsetregistry.cpp +++ b/src/registry/docsetregistry.cpp @@ -23,6 +23,7 @@ #include "docsetregistry.h" +#include "cancellationtoken.h" #include "searchresult.h" #include @@ -35,6 +36,7 @@ DocsetRegistry::DocsetRegistry(QObject *parent) : m_thread(new QThread(this)) { // Register for use in signal connections. + qRegisterMetaType("CancellationToken"); qRegisterMetaType>("QList"); // FIXME: Only search should be performed in a separate thread @@ -122,21 +124,21 @@ void DocsetRegistry::_addDocset(const QString &path) emit docsetAdded(name); } -void DocsetRegistry::search(const QString &query) +void DocsetRegistry::search(const QString &query, const CancellationToken &token) { - // Only invalidate queries - if (query.isEmpty()) - return; - - QMetaObject::invokeMethod(this, "_runQuery", Qt::QueuedConnection, Q_ARG(QString, query)); + QMetaObject::invokeMethod(this, "_runQuery", Qt::QueuedConnection, + Q_ARG(QString, query), Q_ARG(CancellationToken, token)); } -void DocsetRegistry::_runQuery(const QString &query) +void DocsetRegistry::_runQuery(const QString &query, const CancellationToken &token) { QList results; - for (Docset *docset : docsets()) + for (Docset *docset : docsets()) { + if (token.isCanceled()) + return; results << docset->search(query); + } std::sort(results.begin(), results.end()); diff --git a/src/registry/docsetregistry.h b/src/registry/docsetregistry.h index bac4c3cc6..936b89a47 100644 --- a/src/registry/docsetregistry.h +++ b/src/registry/docsetregistry.h @@ -32,6 +32,7 @@ class QThread; namespace Zeal { +struct CancellationToken; struct SearchResult; class DocsetRegistry : public QObject @@ -52,7 +53,8 @@ class DocsetRegistry : public QObject Docset *docset(int index) const; QList docsets() const; - void search(const QString &query); + void search(const QString &query, const CancellationToken &token); + const QList &queryResults(); public slots: void addDocset(const QString &path); @@ -65,7 +67,7 @@ public slots: private slots: void _addDocset(const QString &path); - void _runQuery(const QString &query); + void _runQuery(const QString &query, const CancellationToken &token); private: void addDocsetsFromFolder(const QString &path); diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index b4eba7c2f..fe92ad5ec 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -392,7 +392,9 @@ MainWindow::MainWindow(Core::Application *app, QWidget *parent) : return; currentTabState()->searchQuery = text; - m_application->docsetRegistry()->search(text); + m_cancelSearch.cancel(); + m_cancelSearch = CancellationToken(); + m_application->docsetRegistry()->search(text, m_cancelSearch); if (text.isEmpty()) { currentTabState()->tocModel->setResults(); syncTreeView(); diff --git a/src/ui/mainwindow.h b/src/ui/mainwindow.h index f4ee21365..1ded8e4ce 100644 --- a/src/ui/mainwindow.h +++ b/src/ui/mainwindow.h @@ -25,6 +25,7 @@ #define MAINWINDOW_H #include "registry/searchquery.h" +#include "registry/cancellationtoken.h" #include @@ -123,6 +124,8 @@ private slots: QMenu *m_backMenu = nullptr; QMenu *m_forwardMenu = nullptr; + Zeal::CancellationToken m_cancelSearch; + QxtGlobalShortcut *m_globalShortcut = nullptr; QTabBar *m_tabBar = nullptr;