mirror of
https://github.com/zealdocs/zeal.git
synced 2024-11-22 21:53:03 +03:00
Separate thread for queries
This commit is contained in:
parent
57d0dfc166
commit
93cf5a8c0a
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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())
|
||||
|
6
zeal/zealsearchresult.cpp
Normal file
6
zeal/zealsearchresult.cpp
Normal 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
21
zeal/zealsearchresult.h
Normal 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
|
Loading…
Reference in New Issue
Block a user