Example #1
0
QList<ZealSearchResult> ZealDocsetsRegistry::getRelatedLinks(QString name, QString path)
{
    QList<ZealSearchResult> results;
    // Get the url without the #anchor.
    QUrl mainUrl(path);
    mainUrl.setFragment(NULL);
    QString pageUrl(mainUrl.toString());
    docsetEntry entry = docs[name];

    // Prepare the query to look up all pages with the same url.
    QString query;
    if (entry.type == DASH) {
        query = QString("SELECT name, type, path FROM searchIndex WHERE path LIKE \"%1%%\"").arg(pageUrl);
    } else if (entry.type == ZDASH) {
        query = QString("SELECT ztoken.ztokenname, ztokentype.ztypename, zfilepath.zpath, ztokenmetainformation.zanchor "
                        "FROM ztoken "
                        "JOIN ztokenmetainformation ON ztoken.zmetainformation = ztokenmetainformation.z_pk "
                        "JOIN zfilepath ON ztokenmetainformation.zfile = zfilepath.z_pk "
                        "JOIN ztokentype ON ztoken.ztokentype = ztokentype.z_pk "
                        "WHERE zfilepath.zpath = \"%1\"").arg(pageUrl);
    } else if (entry.type == ZEAL) {
        query = QString("SELECT name type, path FROM things WHERE path LIKE \"%1%%\"").arg(pageUrl);
    }

    QSqlQuery result = entry.db.exec(query);
    while (result.next()) {
        QString sectionName = result.value(0).toString();
        QString sectionPath = result.value(2).toString();
        QString parentName;
        if (entry.type == ZDASH) {
            sectionPath.append("#");
            sectionPath.append(result.value(3).toString());
        }

        normalizeName(sectionName, parentName, "");

        results.append(ZealSearchResult(sectionName, "", sectionPath, name, QString()));
    }

    return results;
}
Example #2
0
void ZealDocsetsRegistry::_runQuery(const QString& rawQuery, int queryNum)
{
    if(queryNum != lastQuery) return; // some other queries pending - ignore this one

    QList<ZealSearchResult> results;
    ZealSearchQuery query(rawQuery);

    QString preparedQuery = query.getSanitizedQuery();
    bool hasDocsetFilter = query.hasDocsetFilter();

    for (const ZealDocsetsRegistry::docsetEntry docset : docsets()) {
        if(hasDocsetFilter && !query.docsetPrefixMatch(docset.prefix)) {
            // Filter out this docset as the names don't match the docset prefix
            continue;
        }

        QString qstr;
        QSqlQuery q;
        QList<QList<QVariant> > found;
        bool withSubStrings = false;
        // %.%1% for long Django docset values like django.utils.http
        // %::%1% for long C++ docset values like std::set
        // %/%1% for long Go docset values like archive/tar
        QString subNames = QString(" or %1 like '%.%2%' escape '\\'");
        subNames += QString(" or %1 like '%::%2%' escape '\\'");
        subNames += QString(" or %1 like '%/%2%' escape '\\'");
        while(found.size() < 100) {
            auto curQuery = preparedQuery;
            QString notQuery; // don't return the same result twice
            QString parentQuery;
            if(withSubStrings) {
                // if less than 100 found starting with query, search all substrings
                curQuery = "%"+preparedQuery;
                // don't return 'starting with' results twice
                if(docset.type == ZDASH) {
                    notQuery = QString(" and not (ztokenname like '%1%' escape '\\' %2) ").arg(preparedQuery, subNames.arg("ztokenname", preparedQuery));
                } else {
                    if(docset.type == ZEAL) {
                        notQuery = QString(" and not (t.name like '%1%' escape '\\') ").arg(preparedQuery);
                        parentQuery = QString(" or t2.name like '%1%' escape '\\' ").arg(preparedQuery);
                    } else { // DASH
                        notQuery = QString(" and not (t.name like '%1%' escape '\\' %2) ").arg(preparedQuery, subNames.arg("t.name", preparedQuery));
                    }
                }
            }
            int cols = 3;
            if(docset.type == ZEAL) {
                qstr = QString("select t.name, t2.name, t.path from things t left join things t2 on t2.id=t.parent where "
                               "(t.name like '%1%' escape '\\'  %3) %2 order by length(t.name), lower(t.name) asc, t.path asc limit 100").arg(curQuery, notQuery, parentQuery);

            } else if(docset.type == DASH) {
                qstr = QString("select t.name, null, t.path from searchIndex t where (t.name "
                               "like '%1%' escape '\\' %3)  %2 order by length(t.name), lower(t.name) asc, t.path asc limit 100").arg(curQuery, notQuery, subNames.arg("t.name", curQuery));
            } else if(docset.type == ZDASH) {
                cols = 4;
                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 "

                               "like '%1%' escape '\\' %3) %2 order by length(ztokenname), lower(ztokenname) asc, zpath asc, "
                               "zanchor asc limit 100").arg(curQuery, notQuery, subNames.arg("ztokenname", curQuery));
            }
            q = db(docset.name).exec(qstr);
            while(q.next()) {
                QList<QVariant> values;
                for(int i = 0; i < cols; ++i) {
                    values.append(q.value(i));
                }
                found.append(values);
            }

            if(withSubStrings) break;
            withSubStrings = true;  // try again searching for substrings
        }
        for(auto &row : found) {
            QString parentName;
            if(!row[1].isNull()) {
                parentName = row[1].toString();
            }
            auto path = row[2].toString();
            // FIXME: refactoring to use common code in ZealListModel and ZealDocsetsRegistry
            if(docset.type == ZDASH) {
                path += "#" + row[3].toString();
            }
            auto itemName = row[0].toString();
            normalizeName(itemName, parentName, row[1].toString());
            results.append(ZealSearchResult(itemName, parentName, path, docset.name, preparedQuery));
        }
    }
    qSort(results);
    if(queryNum != lastQuery) return; // some other queries pending - ignore this one

    queryResults = results;
    emit queryCompleted();
}
void ZealDocsetsRegistry::_runQuery(const QString& rawQuery, int queryNum)
{
    if(queryNum != lastQuery) return; // some other queries pending - ignore this one

    QList<ZealSearchResult> results;
    ZealSearchQuery query(rawQuery);

    QString docsetPrefix = query.getDocsetFilter();
    QString preparedQuery = query.getSanitizedQuery();
    bool hasPrefixFilter = !docsetPrefix.isEmpty();

    for (const QString &name : names()) {
        if (hasPrefixFilter && !name.contains(docsetPrefix, Qt::CaseInsensitive)) {
            // Filter out this docset as the names don't match the docset prefix
            continue;
        }

        QString qstr;
        QSqlQuery q;
        QList<QList<QVariant> > found;
        bool withSubStrings = false;
        // %.%1% for long Django docset values like django.utils.http
        // %::%1% for long C++ docset values like std::set
        // %/%1% for long Go docset values like archive/tar
        QString subNames = QString(" or %1 like '%.%2%' escape '\\'");
        subNames += QString(" or %1 like '%::%2%' escape '\\'");
        subNames += QString(" or %1 like '%/%2%' escape '\\'");
        while(found.size() < 100) {
            auto curQuery = preparedQuery;
            QString notQuery; // don't return the same result twice
            QString parentQuery;
            if(withSubStrings) {
                // if less than 100 found starting with query, search all substrings
                curQuery = "%"+preparedQuery;
                // don't return 'starting with' results twice
                if(types[name] == ZDASH) {
                    notQuery = QString(" and not (ztokenname like '%1%' escape '\\' %2) ").arg(preparedQuery, subNames.arg("ztokenname", preparedQuery));
                } else {
                    if(types[name] == ZEAL) {
                        notQuery = QString(" and not (t.name like '%1%' escape '\\') ").arg(preparedQuery);
                        parentQuery = QString(" or t2.name like '%1%' escape '\\' ").arg(preparedQuery);
                    } else { // DASH
                        notQuery = QString(" and not (t.name like '%1%' escape '\\' %2) ").arg(preparedQuery, subNames.arg("t.name", preparedQuery));
                    }
                }
            }
            int cols = 3;
            if(types[name] == ZEAL) {
                qstr = QString("select t.name, t2.name, t.path from things t left join things t2 on t2.id=t.parent where "
                               "(t.name like '%1%' escape '\\'  %3) %2 order by lower(t.name) asc, t.path asc limit 100").arg(curQuery, notQuery, parentQuery);

            } else if(types[name] == DASH) {
                qstr = QString("select t.name, null, t.path from searchIndex t where (t.name "
                               "like '%1%' escape '\\' %3)  %2 order by lower(t.name) asc, t.path asc limit 100").arg(curQuery, notQuery, subNames.arg("t.name", curQuery));
            } else if(types[name] == ZDASH) {
                cols = 4;
                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 "

                               "like '%1%' escape '\\' %3) %2 order by lower(ztokenname) asc, zpath asc, "
                               "zanchor asc limit 100").arg(curQuery, notQuery, subNames.arg("ztokenname", curQuery));
            }
            q = db(name).exec(qstr);
            while(q.next()) {
                QList<QVariant> values;
                for(int i = 0; i < cols; ++i) {
                    values.append(q.value(i));
                }
                found.append(values);
            }

            if(withSubStrings) break;
            withSubStrings = true;  // try again searching for substrings
        }
        for(auto &row : found) {
            QString parentName;
            if(!row[1].isNull()) {
                parentName = row[1].toString();
            }
            auto path = row[2].toString();
            // FIXME: refactoring to use common code in ZealListModel and ZealDocsetsRegistry
            if(types[name] == DASH || types[name] == ZDASH) {
                path = QDir(QDir(QDir("Contents").filePath("Resources")).filePath("Documents")).filePath(path);
            }
            if(types[name] == ZDASH) {
                path += "#" + row[3].toString();
            }
            auto itemName = row[0].toString();
            QString separators[] = {".", "::", "/"};
            for(unsigned i = 0; i < sizeof separators / sizeof *separators; ++i) {
                QString sep = separators[i];
                if(itemName.indexOf(sep) != -1 && itemName.indexOf(sep) != 0 && row[1].isNull()) {
                    auto splitted = itemName.split(sep);
                    itemName = splitted.at(splitted.size()-1);
                    parentName = splitted.at(splitted.size()-2);
                }
            }
            results.append(ZealSearchResult(itemName, parentName, path, name, preparedQuery));
        }
    }
    qSort(results);
    if(queryNum != lastQuery) return; // some other queries pending - ignore this one

    queryResults = results;
    emit queryCompleted();
}