Separate thread for queries

This commit is contained in:
Jerzy Kozera 2013-01-19 23:55:28 +00:00
parent 57d0dfc166
commit 93cf5a8c0a
8 changed files with 130 additions and 55 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -1,4 +1,9 @@
#include <QThread>
#include <QVariant>
#include <QtSql/QSqlQuery>
#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<ZealSearchResult> 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<ZealSearchResult>& ZealDocsetsRegistry::getQueryResults()
{
return queryResults;
}

View File

@ -5,11 +5,12 @@
#include <QtSql/QSqlDatabase>
#include <QDir>
#include <QMap>
#include <iostream>
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<ZealSearchResult>& 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<QString, QSqlDatabase> dbs;
QMap<QString, QDir> dirs;
QList<ZealSearchResult> queryResults;
int lastQuery = -1;
};
extern ZealDocsetsRegistry* docsets;

View File

@ -11,8 +11,8 @@ using namespace std;
ZealSearchModel::ZealSearchModel(QObject *parent) :
QAbstractItemModel(parent)
{
counts = new QHash<QString, int>;
strings = new QSet<QString>;
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<QString, int> 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();
}

View File

@ -4,6 +4,7 @@
#include <QHash>
#include <QSet>
#include <QAbstractItemModel>
#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<QString, int> *counts;
const QHash<QString, int> getCounts() const;
QList<ZealSearchResult> dataList;
void populateData();
QSet<QString> *strings;
const QString* getString(const QString& str) const {
if(strings->find(str) == strings->end())

View File

@ -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_)
{
}

21
zeal/zealsearchresult.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef ZEALSEARCHRESULT_H
#define ZEALSEARCHRESULT_H
#include <QString>
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