From 93cf5a8c0a384a70a0adf9e2ce24381e47d2a599 Mon Sep 17 00:00:00 2001 From: Jerzy Kozera Date: Sat, 19 Jan 2013 23:55:28 +0000 Subject: [PATCH] Separate thread for queries --- zeal/mainwindow.cpp | 11 ++++--- zeal/zeal.pro | 6 ++-- zeal/zealdocsetsregistry.cpp | 48 ++++++++++++++++++++++++++++++ zeal/zealdocsetsregistry.h | 27 ++++++++++++----- zeal/zealsearchmodel.cpp | 57 ++++++++++++------------------------ zeal/zealsearchmodel.h | 9 ++++-- zeal/zealsearchresult.cpp | 6 ++++ zeal/zealsearchresult.h | 21 +++++++++++++ 8 files changed, 130 insertions(+), 55 deletions(-) create mode 100644 zeal/zealsearchresult.cpp create mode 100644 zeal/zealsearchresult.h diff --git a/zeal/mainwindow.cpp b/zeal/mainwindow.cpp index 8aa13a1..7bc91e5 100644 --- a/zeal/mainwindow.cpp +++ b/zeal/mainwindow.cpp @@ -23,7 +23,8 @@ MainWindow::MainWindow(QWidget *parent) : } else { for(auto subdir : dataDir.entryInfoList()) { if(subdir.isDir() && !subdir.isHidden()) { - docsets->addDocset(subdir.absoluteFilePath()); + QMetaObject::invokeMethod(docsets, "addDocset", Qt::BlockingQueuedConnection, + Q_ARG(QString, subdir.absoluteFilePath())); } } } @@ -33,12 +34,14 @@ MainWindow::MainWindow(QWidget *parent) : connect(ui->treeView, &QTreeView::activated, [&](const QModelIndex& index) { ui->webView->setUrl("file://" + index.sibling(index.row(), 1).data().toString()); }); + connect(&zealSearch, &ZealSearchModel::queryCompleted, [&]() { + ui->treeView->setModel(&zealSearch); + ui->treeView->reset(); + ui->treeView->setColumnHidden(1, true); + }); connect(ui->lineEdit, &QLineEdit::textChanged, [&](const QString& text) { if(!text.isEmpty()) { zealSearch.setQuery(text); - ui->treeView->setModel(&zealSearch); - ui->treeView->reset(); - ui->treeView->setColumnHidden(1, true); } else { ui->treeView->setModel(&zealList); } diff --git a/zeal/zeal.pro b/zeal/zeal.pro index c8ce502..59ea4ff 100644 --- a/zeal/zeal.pro +++ b/zeal/zeal.pro @@ -15,12 +15,14 @@ SOURCES += main.cpp\ mainwindow.cpp \ zeallistmodel.cpp \ zealsearchmodel.cpp \ - zealdocsetsregistry.cpp + zealdocsetsregistry.cpp \ + zealsearchresult.cpp HEADERS += mainwindow.h \ zeallistmodel.h \ zealsearchmodel.h \ - zealdocsetsregistry.h + zealdocsetsregistry.h \ + zealsearchresult.h FORMS += mainwindow.ui diff --git a/zeal/zealdocsetsregistry.cpp b/zeal/zealdocsetsregistry.cpp index af912ae..2f6960f 100644 --- a/zeal/zealdocsetsregistry.cpp +++ b/zeal/zealdocsetsregistry.cpp @@ -1,4 +1,9 @@ +#include +#include +#include + #include "zealdocsetsregistry.h" +#include "zealsearchresult.h" ZealDocsetsRegistry* ZealDocsetsRegistry::m_Instance; @@ -12,3 +17,46 @@ void ZealDocsetsRegistry::addDocset(const QString& path) { dbs.insert(dir.dirName(), db); dirs.insert(dir.dirName(), dir); } + +ZealDocsetsRegistry::ZealDocsetsRegistry() { + auto thread = new QThread(this); + moveToThread(thread); + thread->start(); +} + +void ZealDocsetsRegistry::runQuery(const QString& query) +{ + lastQuery += 1; + QMetaObject::invokeMethod(this, "_runQuery", Qt::QueuedConnection, Q_ARG(QString, query), Q_ARG(int, lastQuery)); +} + +void ZealDocsetsRegistry::_runQuery(const QString& query, int queryNum) +{ + if(queryNum != lastQuery) return; // some other queries pending - ignore this one + + QList results; + for(auto name : names()) { + auto qstr = QString("select name, parent, path from things where name " + "like '%1%' order by name asc, path asc limit 40").arg(query); + auto q = db(name).exec(qstr); + + while(q.next()) { + QString parentName; + if(!q.value(1).isNull()) { + auto qp = db(name).exec(QString("select name from things where id = %1").arg(q.value(1).toInt())); + qp.next(); + parentName = qp.value(0).toString(); + } + results.append(ZealSearchResult(q.value(0).toString(), parentName, q.value(2).toString(), name)); + } + } + if(queryNum != lastQuery) return; // some other queries pending - ignore this one + + queryResults = results; + emit queryCompleted(); +} + +const QList& ZealDocsetsRegistry::getQueryResults() +{ + return queryResults; +} diff --git a/zeal/zealdocsetsregistry.h b/zeal/zealdocsetsregistry.h index 63121e4..c3370ab 100644 --- a/zeal/zealdocsetsregistry.h +++ b/zeal/zealdocsetsregistry.h @@ -5,11 +5,12 @@ #include #include #include -#include -using namespace std; -class ZealDocsetsRegistry +#include "zealsearchresult.h" + +class ZealDocsetsRegistry : public QObject { + Q_OBJECT public: static ZealDocsetsRegistry* instance() { @@ -27,8 +28,6 @@ public: return m_Instance; } - void addDocset(const QString& path); - int count() const { return dbs.count(); } @@ -45,10 +44,20 @@ public: return dbs.keys(); } -private: - ZealDocsetsRegistry() { - } + void runQuery(const QString& query); + const QList& getQueryResults(); +signals: + void queryCompleted(); + +public slots: + void addDocset(const QString& path); + +private slots: + void _runQuery(const QString& query, int queryNum); + +private: + ZealDocsetsRegistry(); ZealDocsetsRegistry(const ZealDocsetsRegistry&); // hide copy constructor ZealDocsetsRegistry& operator=(const ZealDocsetsRegistry&); // hide assign op // we leave just the declarations, so the compiler will warn us @@ -57,6 +66,8 @@ private: static ZealDocsetsRegistry* m_Instance; QMap dbs; QMap dirs; + QList queryResults; + int lastQuery = -1; }; extern ZealDocsetsRegistry* docsets; diff --git a/zeal/zealsearchmodel.cpp b/zeal/zealsearchmodel.cpp index 281b931..bf0e55e 100644 --- a/zeal/zealsearchmodel.cpp +++ b/zeal/zealsearchmodel.cpp @@ -11,8 +11,8 @@ using namespace std; ZealSearchModel::ZealSearchModel(QObject *parent) : QAbstractItemModel(parent) { - counts = new QHash; strings = new QSet; + connect(docsets, &ZealDocsetsRegistry::queryCompleted, this, &ZealSearchModel::onQueryCompleted); } Qt::ItemFlags ZealSearchModel::flags(const QModelIndex &index) const @@ -37,36 +37,19 @@ QVariant ZealSearchModel::headerData(int section, Qt::Orientation orientation, i QModelIndex ZealSearchModel::index(int row, int column, const QModelIndex &parent) const { if(!parent.isValid()) { - QSqlDatabase db; - int found = 0, drow = 0; - QString name; - for(QString name_ : docsets->names()) { - db = docsets->db(name_); - found += getCounts()[name_]; - if(found > row) { - name = name_; - break; - } - // not enough rows - decrement row - drow -= getCounts()[name_]; - } - if(found <= row) return QModelIndex(); + if(dataList.count() <= row) return QModelIndex(); + auto item = dataList.at(row); + if(column == 0) { - auto q = db.exec(QString("select name, parent from things where name like '%1%' order by name asc, path asc limit 1 offset ").arg(query)+QString().setNum(row+drow)); - q.next(); - if(!q.value(1).isNull()) { - auto qp = db.exec(QString("select name from things where id = %1").arg(q.value(1).toInt())); - qp.next(); + if(!item.getParentName().isEmpty()) { return createIndex(row, column, (void*)getString( - QString("%1 (%2)").arg(q.value(0).toString(), qp.value(0).toString()))); + QString("%1 (%2)").arg(item.getName(), item.getParentName()))); } else { - return createIndex(row, column, (void*)getString(q.value(0).toString())); + return createIndex(row, column, (void*)getString(item.getName())); } } else if (column == 1) { - auto q = db.exec(QString("select path from things where name like '%1%' order by name asc, path asc limit 1 offset ").arg(query)+QString().setNum(row+drow)); - q.next(); - return createIndex(row, column, (void*)getString(docsets->dir(name).absoluteFilePath(q.value(0).toString()))); + return createIndex(row, column, (void*)getString(docsets->dir(item.getDocsetName()).absoluteFilePath(item.getPath()))); } } return QModelIndex(); @@ -80,7 +63,7 @@ QModelIndex ZealSearchModel::parent(const QModelIndex &child) const int ZealSearchModel::rowCount(const QModelIndex &parent) const { if(!parent.isValid()) { - return accumulate(getCounts().begin(), getCounts().end(), 0); + return dataList.count(); } return 0; } @@ -92,19 +75,17 @@ int ZealSearchModel::columnCount(const QModelIndex &parent) const void ZealSearchModel::setQuery(const QString &q) { query = q; - counts->clear(); - strings->clear(); + populateData(); } -const QHash ZealSearchModel::getCounts() const +void ZealSearchModel::populateData() { - if(counts->empty()) { - for(auto name : docsets->names()) { - auto db = docsets->db(name); - auto q = db.exec(QString("select count(name) from things where name like '%1%'").arg(query)); - q.next(); - (*counts)[name] = min(40, q.value(0).toInt()); - } - } - return *counts; + docsets->runQuery(query); +} + +void ZealSearchModel::onQueryCompleted() +{ + strings->clear(); + dataList = docsets->getQueryResults(); + emit queryCompleted(); } diff --git a/zeal/zealsearchmodel.h b/zeal/zealsearchmodel.h index 150304e..bf4895f 100644 --- a/zeal/zealsearchmodel.h +++ b/zeal/zealsearchmodel.h @@ -4,6 +4,7 @@ #include #include #include +#include "zealsearchresult.h" class ZealSearchModel : public QAbstractItemModel { @@ -20,13 +21,15 @@ public: void setQuery(const QString& q); signals: - + void queryCompleted(); + public slots: + void onQueryCompleted(); private: QString query; - QHash *counts; - const QHash getCounts() const; + QList dataList; + void populateData(); QSet *strings; const QString* getString(const QString& str) const { if(strings->find(str) == strings->end()) diff --git a/zeal/zealsearchresult.cpp b/zeal/zealsearchresult.cpp new file mode 100644 index 0000000..14f12f6 --- /dev/null +++ b/zeal/zealsearchresult.cpp @@ -0,0 +1,6 @@ +#include "zealsearchresult.h" + +ZealSearchResult::ZealSearchResult(const QString& name_, const QString& parentName_, const QString& path_, const QString& docset_) + : name(name_), parentName(parentName_), path(path_), docset(docset_) +{ +} diff --git a/zeal/zealsearchresult.h b/zeal/zealsearchresult.h new file mode 100644 index 0000000..08f5b4c --- /dev/null +++ b/zeal/zealsearchresult.h @@ -0,0 +1,21 @@ +#ifndef ZEALSEARCHRESULT_H +#define ZEALSEARCHRESULT_H + +#include + +class ZealSearchResult +{ +public: + ZealSearchResult(const QString& name_, const QString& parentName_, const QString& path_, const QString& docset_); + const QString& getName() const { return name; }; + const QString& getParentName() const { return parentName; }; + const QString& getPath() const { return path; }; + const QString& getDocsetName() const { return docset; }; +private: + QString name; + QString parentName; + QString path; + QString docset; +}; + +#endif // ZEALSEARCHRESULT_H