Skip to content

Commit

Permalink
Initial support for Dash docsets
Browse files Browse the repository at this point in the history
  • Loading branch information
jkozera committed Jan 31, 2013
1 parent 7c0e73c commit 3bf61b0
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 21 deletions.
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

(from WordNet 3.0)

Zeal is a simple documentation browser inspired by [Dash](http://kapeli.com/dash/), but designed from scratch to avoid copyright issues.
Zeal is a simple documentation browser inspired by [Dash](http://kapeli.com/dash/).

[Screenshots (imgur)](http://imgur.com/a/VrYQx)

Expand All @@ -22,23 +22,24 @@ After compiling/unzipping it you need to download docsets and put them in `$HOME

Do `tar -jxvf file.tar.bz2` in docsets directory to enable given docset.

You can also use Dash's docsets by putting `.docset` directories in the same directory as above.

## How to compile

Currently Zeal requires Qt 5.0. To compile it, run `qmake` and `make` in the `zeal` directory.

## Windows binary

A 64-bit Windows binary with all dependencies is available to download from Dropbox - [zeal.zip](https://www.dropbox.com/s/2kyb3p4ox271a0d/zeal.zip) (24M).
A 64-bit Windows binary with all dependencies is available to download from Dropbox - [zeal.zip](https://www.dropbox.com/s/g4rtvs17b2zyeea/zeal.zip) (24M).

## TODO

* Configuration (customisable hotkey instead of hardcoded Alt+Space, remember window size, etc.)
* Support for global hotkeys under platforms other than Linux/X11 and Windows (OSX)
* Search enhancements - some ideas:
1. Allow selecting subset of docsets to search in.
2. Substring match in case current startswith matching doesn't return anything.
3. Grouping of similar results (like overloaded functions)
4. Better docsets formatting (without headers, sidebars etc.)
2. Grouping of similar results (like overloaded functions)
3. Better docsets formatting (without headers, sidebars etc.)
* More docsets


Expand Down
83 changes: 71 additions & 12 deletions zeal/zealdocsetsregistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,29 @@ ZealDocsetsRegistry* docsets = ZealDocsetsRegistry::instance();

void ZealDocsetsRegistry::addDocset(const QString& path) {
auto dir = QDir(path);
auto db = QSqlDatabase::addDatabase("QSQLITE", dir.dirName());
db.setDatabaseName(dir.filePath("index.sqlite"));
db.open();
dbs.insert(dir.dirName(), db);
dirs.insert(dir.dirName(), dir);
auto name = dir.dirName().replace(".docset", "");
auto db = QSqlDatabase::addDatabase("QSQLITE", name);
if(QFile::exists(dir.filePath("index.sqlite"))) {
db.setDatabaseName(dir.filePath("index.sqlite"));
db.open();
types.insert(name, ZEAL);
} else {
auto dashFile = QDir(QDir(dir.filePath("Contents")).filePath("Resources")).filePath("docSet.dsidx");
db.setDatabaseName(dashFile);
db.open();
auto q = db.exec("select name from sqlite_master where type='table'");
QStringList tables;
while(q.next()) {
tables.append(q.value(0).toString());
}
if(tables.contains("searchIndex")) {
types.insert(name, DASH);
} else {
types.insert(name, ZDASH);
}
}
dbs.insert(name, db);
dirs.insert(name, dir);
}

ZealDocsetsRegistry::ZealDocsetsRegistry() {
Expand All @@ -36,19 +54,60 @@ void ZealDocsetsRegistry::_runQuery(const QString& query, int queryNum)

QList<ZealSearchResult> results;
for(auto name : names()) {
auto qstr = QString("select name, parent, path from things where name "
"like '%1%' order by lower(name) asc, path asc limit 40").arg(query);
auto q = db(name).exec(qstr);

while(q.next()) {
QString qstr;
QSqlQuery q;
bool found = false;
bool withSubStrings = false;
while(!found) {
auto curQuery = query;
if(withSubStrings) {
// if nothing found starting with query, search all substrings
curQuery = "%"+query;
}
if(types[name] == ZEAL) {
qstr = QString("select name, parent, path from things where name "
"like '%1%' order by lower(name) asc, path asc limit 40").arg(curQuery);
} else if(types[name] == DASH) {
qstr = QString("select name, null, path from searchIndex where name "
"like '%1%' order by lower(name) asc, path asc limit 40").arg(curQuery);
} else if(types[name] == ZDASH) {
qstr = QString("select ztokenname, null, zpath, zanchor from ztoken "
"join ztokenmetainformation on ztoken.zmetainformation = ztokenmetainformation.z_pk "
"join zfilepath on ztokenmetainformation.zfile = zfilepath.z_pk where ztokenname "
// %.%1% for long Django docset values like django.utils.http
// (Might be not appropriate for other docsets, but I don't have any on hand to test)
"like '%1%' or ztokenname like '%.%1%' order by lower(ztokenname) asc, zpath asc, zanchor asc limit 40").arg(curQuery);
}
q = db(name).exec(qstr);
if(q.next()) { found = true; }
else {
if(withSubStrings) break;
withSubStrings = true; // try again searching for substrings
}
}
if(!found) continue;
do {
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));
}
auto path = q.value(2).toString();
if(types[name] == DASH || types[name] == ZDASH) {
path = QDir(QDir(QDir("Contents").filePath("Resources")).filePath("Documents")).filePath(path);
}
if(types[name] == ZDASH) {
path += "#" + q.value(3).toString();
}
auto itemName = q.value(0).toString();
if(itemName.indexOf('.') != -1 && itemName.indexOf('.') != 0 && q.value(1).isNull()) {
auto splitted = itemName.split(".");
itemName = splitted.at(splitted.size()-1);
parentName = splitted.at(splitted.size()-2);
}
results.append(ZealSearchResult(itemName, parentName, path, name, query));
} while (q.next());
}
qSort(results);
if(queryNum != lastQuery) return; // some other queries pending - ignore this one
Expand Down
4 changes: 4 additions & 0 deletions zeal/zealdocsetsregistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

#include "zealsearchresult.h"

typedef enum {ZEAL, DASH, ZDASH} DocSetType;

class ZealDocsetsRegistry : public QObject
{
Q_OBJECT
Expand Down Expand Up @@ -64,8 +66,10 @@ private slots:
// if we try to use those two functions by accident

static ZealDocsetsRegistry* m_Instance;
// FIXME: DocSet class could be better instead of 3 maps
QMap<QString, QSqlDatabase> dbs;
QMap<QString, QDir> dirs;
QMap<QString, DocSetType> types;
QList<ZealSearchResult> queryResults;
int lastQuery = -1;
};
Expand Down
4 changes: 2 additions & 2 deletions zeal/zealsearchresult.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +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_)
ZealSearchResult::ZealSearchResult(const QString& name_, const QString& parentName_, const QString& path_, const QString& docset_, const QString& query_)
: name(name_), parentName(parentName_), path(path_), docset(docset_), query(query_)
{
}
12 changes: 10 additions & 2 deletions zeal/zealsearchresult.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,29 @@
class ZealSearchResult
{
public:
ZealSearchResult(const QString& name_, const QString& parentName_, const QString& path_, const QString& docset_);
ZealSearchResult(const QString& name_, const QString& parentName_, const QString& path_, const QString& docset_, const QString& query_);
const QString& getName() const { return name; };
const QString& getParentName() const { return parentName; };
const QString& getPath() const { return path; };
const QString& getDocsetName() const { return docset; };
bool operator<(const ZealSearchResult& r) const {
return name.toLower() < r.name.toLower() ||
if (name.toLower().startsWith(query.toLower()) > r.name.toLower().startsWith(r.query.toLower())) {
// return results that are prefixed with query first
return true;
} else if (name.toLower().startsWith(query.toLower()) < r.name.toLower().startsWith(r.query.toLower())) {
return false;
} else {
return name.toLower() < r.name.toLower() ||
(name.toLower() == r.name.toLower()
&& parentName.toLower() < r.parentName.toLower());
}
}
private:
QString name;
QString parentName;
QString path;
QString docset;
QString query;
};

#endif // ZEALSEARCHRESULT_H

0 comments on commit 3bf61b0

Please sign in to comment.