tools/assistant/lib/qhelpdbreader.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Assistant of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qhelpdbreader_p.h"
       
    43 #include "qhelp_global.h"
       
    44 
       
    45 #include <QtCore/QVariant>
       
    46 #include <QtCore/QFile>
       
    47 #include <QtSql/QSqlError>
       
    48 #include <QtSql/QSqlQuery>
       
    49 
       
    50 QT_BEGIN_NAMESPACE
       
    51 
       
    52 QHelpDBReader::QHelpDBReader(const QString &dbName)
       
    53     : QObject(0)
       
    54 {
       
    55     initObject(dbName,
       
    56         QHelpGlobal::uniquifyConnectionName(QLatin1String("QHelpDBReader"),
       
    57         this));
       
    58 }
       
    59 
       
    60 QHelpDBReader::QHelpDBReader(const QString &dbName, const QString &uniqueId,
       
    61                            QObject *parent)
       
    62     : QObject(parent)
       
    63 {
       
    64     initObject(dbName, uniqueId);
       
    65 }
       
    66 
       
    67 void QHelpDBReader::initObject(const QString &dbName, const QString &uniqueId)
       
    68 {
       
    69     m_dbName = dbName;
       
    70     m_uniqueId = uniqueId;
       
    71     m_initDone = false;
       
    72     m_query = 0;
       
    73     m_useAttributesCache = false;
       
    74 }
       
    75 
       
    76 QHelpDBReader::~QHelpDBReader()
       
    77 {
       
    78     if (m_initDone) {
       
    79         delete m_query;
       
    80         QSqlDatabase::removeDatabase(m_uniqueId);
       
    81     }
       
    82 }
       
    83 
       
    84 bool QHelpDBReader::init()
       
    85 {
       
    86     if (m_initDone)
       
    87         return true;
       
    88 
       
    89     if (!QFile::exists(m_dbName))
       
    90         return false;
       
    91 
       
    92     QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), m_uniqueId);
       
    93     db.setDatabaseName(m_dbName);
       
    94     if (!db.open()) {
       
    95         /*: The placeholders are: %1 - The name of the database which cannot be opened
       
    96                                   %2 - The unique id for the connection
       
    97                                   %3 - The actual error string */
       
    98         m_error = tr("Cannot open database '%1' '%2': %3").arg(m_dbName, m_uniqueId, db.lastError().text());
       
    99         QSqlDatabase::removeDatabase(m_uniqueId);
       
   100         return false;
       
   101     }
       
   102 
       
   103     m_initDone = true;
       
   104     m_query = new QSqlQuery(db);
       
   105 
       
   106     return true;
       
   107 }
       
   108 
       
   109 QString QHelpDBReader::databaseName() const
       
   110 {
       
   111     return m_dbName;
       
   112 }
       
   113 
       
   114 QString QHelpDBReader::errorMessage() const
       
   115 {
       
   116     return m_error;
       
   117 }
       
   118 
       
   119 QString QHelpDBReader::namespaceName() const
       
   120 {
       
   121     if (!m_namespace.isEmpty())
       
   122         return m_namespace;
       
   123     if (m_query) {
       
   124         m_query->exec(QLatin1String("SELECT Name FROM NamespaceTable"));
       
   125         if (m_query->next())
       
   126             m_namespace = m_query->value(0).toString();
       
   127     }
       
   128     return m_namespace;
       
   129 }
       
   130 
       
   131 QString QHelpDBReader::virtualFolder() const
       
   132 {
       
   133     if (m_query) {
       
   134         m_query->exec(QLatin1String("SELECT Name FROM FolderTable WHERE Id=1"));
       
   135         if (m_query->next())
       
   136             return m_query->value(0).toString();
       
   137     }
       
   138     return QString();
       
   139 }
       
   140 
       
   141 QList<QStringList> QHelpDBReader::filterAttributeSets() const
       
   142 {
       
   143     QList<QStringList> result;
       
   144     if (m_query) {
       
   145         m_query->exec(QLatin1String("SELECT a.Id, b.Name FROM FileAttributeSetTable a, "
       
   146             "FilterAttributeTable b WHERE a.FilterAttributeId=b.Id ORDER BY a.Id"));
       
   147         int oldId = -1;
       
   148         while (m_query->next()) {
       
   149             int id = m_query->value(0).toInt();
       
   150             if (id != oldId) {
       
   151                 result.append(QStringList());
       
   152                 oldId = id;
       
   153             }
       
   154             result.last().append(m_query->value(1).toString());
       
   155         }
       
   156     }
       
   157     return result;
       
   158 }
       
   159 
       
   160 bool QHelpDBReader::fileExists(const QString &virtualFolder,
       
   161                                const QString &filePath,
       
   162                                const QStringList &filterAttributes) const
       
   163 {
       
   164     if (virtualFolder.isEmpty() || filePath.isEmpty() || !m_query)
       
   165         return false;
       
   166 
       
   167 //SELECT COUNT(a.Name) FROM FileNameTable a, FolderTable b, FileFilterTable c, FilterAttributeTable d WHERE a.FolderId=b.Id AND b.Name='qtdoc' AND a.Name='qstring.html' AND a.FileId=c.FileId AND c.FilterAttributeId=d.Id AND d.Name='qtrefdoc'
       
   168 
       
   169     QString query;
       
   170     namespaceName();
       
   171     if (filterAttributes.isEmpty()) {
       
   172         query = QString(QLatin1String("SELECT COUNT(a.Name) FROM FileNameTable a, FolderTable b "
       
   173             "WHERE a.FolderId=b.Id AND b.Name=\'%1\' AND a.Name=\'%2\'")).arg(quote(virtualFolder)).arg(quote(filePath));
       
   174     } else {
       
   175         query = QString(QLatin1String("SELECT COUNT(a.Name) FROM FileNameTable a, FolderTable b, "
       
   176             "FileFilterTable c, FilterAttributeTable d WHERE a.FolderId=b.Id "
       
   177             "AND b.Name=\'%1\' AND a.Name=\'%2\' AND a.FileId=c.FileId AND "
       
   178             "c.FilterAttributeId=d.Id AND d.Name=\'%3\'"))
       
   179             .arg(quote(virtualFolder)).arg(quote(filePath))
       
   180             .arg(quote(filterAttributes.first()));
       
   181         for (int i=1; i<filterAttributes.count(); ++i) {
       
   182             query.append(QString(QLatin1String(" INTERSECT SELECT COUNT(a.Name) FROM FileNameTable a, "
       
   183                 "FolderTable b, FileFilterTable c, FilterAttributeTable d WHERE a.FolderId=b.Id "
       
   184                 "AND b.Name=\'%1\' AND a.Name=\'%2\' AND a.FileId=c.FileId AND "
       
   185                 "c.FilterAttributeId=d.Id AND d.Name=\'%3\'"))
       
   186                 .arg(quote(virtualFolder)).arg(quote(filePath))
       
   187                 .arg(quote(filterAttributes.at(i))));
       
   188         }
       
   189     }
       
   190     m_query->exec(query);
       
   191     if (m_query->next() && m_query->isValid() && m_query->value(0).toInt())
       
   192         return true;
       
   193     return false;
       
   194 }
       
   195 
       
   196 QByteArray QHelpDBReader::fileData(const QString &virtualFolder,
       
   197                                    const QString &filePath) const
       
   198 {
       
   199     QByteArray ba;
       
   200     if (virtualFolder.isEmpty() || filePath.isEmpty() || !m_query)
       
   201         return ba;
       
   202 
       
   203     namespaceName();
       
   204     m_query->prepare(QLatin1String("SELECT a.Data FROM FileDataTable a, FileNameTable b, FolderTable c, "
       
   205         "NamespaceTable d WHERE a.Id=b.FileId AND (b.Name=? OR b.Name=?) AND b.FolderId=c.Id "
       
   206         "AND c.Name=? AND c.NamespaceId=d.Id AND d.Name=?"));
       
   207     m_query->bindValue(0, filePath);
       
   208     m_query->bindValue(1, QLatin1String("./") + filePath);
       
   209     m_query->bindValue(2, virtualFolder);
       
   210     m_query->bindValue(3, m_namespace);
       
   211     m_query->exec();
       
   212     if (m_query->next() && m_query->isValid())
       
   213         ba = qUncompress(m_query->value(0).toByteArray());
       
   214     return ba;
       
   215 }
       
   216 
       
   217 QStringList QHelpDBReader::customFilters() const
       
   218 {
       
   219     QStringList lst;
       
   220     if (m_query) {
       
   221         m_query->exec(QLatin1String("SELECT Name FROM FilterNameTable"));
       
   222         while (m_query->next())
       
   223             lst.append(m_query->value(0).toString());
       
   224     }
       
   225     return lst;
       
   226 }
       
   227 
       
   228 QStringList QHelpDBReader::filterAttributes(const QString &filterName) const
       
   229 {
       
   230     QStringList lst;
       
   231     if (m_query) {
       
   232         if (filterName.isEmpty()) {
       
   233             m_query->prepare(QLatin1String("SELECT Name FROM FilterAttributeTable"));
       
   234         } else {
       
   235             m_query->prepare(QLatin1String("SELECT a.Name FROM FilterAttributeTable a, "
       
   236                 "FilterTable b, FilterNameTable c WHERE c.Name=? "
       
   237                 "AND c.Id=b.NameId AND b.FilterAttributeId=a.Id"));
       
   238             m_query->bindValue(0, filterName);
       
   239         }
       
   240         m_query->exec();
       
   241         while (m_query->next())
       
   242             lst.append(m_query->value(0).toString());
       
   243     }
       
   244     return lst;
       
   245 }
       
   246 
       
   247 QStringList QHelpDBReader::indicesForFilter(const QStringList &filterAttributes) const
       
   248 {
       
   249     QStringList indices;
       
   250     if (!m_query)
       
   251         return indices;
       
   252 
       
   253     //SELECT DISTINCT a.Name FROM IndexTable a, IndexFilterTable b, FilterAttributeTable c WHERE a.Id=b.IndexId AND b.FilterAttributeId=c.Id AND c.Name in ('4.2.3', 'qt')
       
   254 
       
   255     QString query;
       
   256     if (filterAttributes.isEmpty()) {
       
   257         query = QLatin1String("SELECT DISTINCT Name FROM IndexTable");
       
   258     } else {
       
   259         query = QString(QLatin1String("SELECT DISTINCT a.Name FROM IndexTable a, "
       
   260         "IndexFilterTable b, FilterAttributeTable c WHERE a.Id=b.IndexId "
       
   261         "AND b.FilterAttributeId=c.Id AND c.Name='%1'")).arg(quote(filterAttributes.first()));
       
   262         for (int i=1; i<filterAttributes.count(); ++i) {
       
   263             query.append(QString(QLatin1String(" INTERSECT SELECT DISTINCT a.Name FROM IndexTable a, "
       
   264                 "IndexFilterTable b, FilterAttributeTable c WHERE a.Id=b.IndexId "
       
   265                 "AND b.FilterAttributeId=c.Id AND c.Name='%1'"))
       
   266                 .arg(quote(filterAttributes.at(i))));
       
   267         }
       
   268     }
       
   269 
       
   270     m_query->exec(query);
       
   271     while (m_query->next()) {
       
   272         if (!m_query->value(0).toString().isEmpty())
       
   273             indices.append(m_query->value(0).toString());
       
   274     }
       
   275     return indices;
       
   276 }
       
   277 
       
   278 void QHelpDBReader::linksForKeyword(const QString &keyword, const QStringList &filterAttributes,
       
   279                                     QMap<QString, QUrl> &linkMap) const
       
   280 {
       
   281     if (!m_query)
       
   282         return;
       
   283 
       
   284     QString query;
       
   285     if (filterAttributes.isEmpty()) {
       
   286         query = QString(QLatin1String("SELECT d.Title, f.Name, e.Name, d.Name, a.Anchor "
       
   287             "FROM IndexTable a, FileNameTable d, "
       
   288             "FolderTable e, NamespaceTable f WHERE "
       
   289             "a.FileId=d.FileId AND d.FolderId=e.Id AND a.NamespaceId=f.Id "
       
   290             "AND a.Name='%1'")).arg(quote(keyword));
       
   291     } else if (m_useAttributesCache) {
       
   292         query = QString(QLatin1String("SELECT d.Title, f.Name, e.Name, d.Name, a.Anchor, a.Id "
       
   293             "FROM IndexTable a, "
       
   294             "FileNameTable d, FolderTable e, NamespaceTable f WHERE "
       
   295             "a.FileId=d.FileId AND d.FolderId=e.Id "
       
   296             "AND a.NamespaceId=f.Id AND a.Name='%1'"))
       
   297             .arg(quote(keyword));
       
   298         m_query->exec(query);
       
   299         while (m_query->next()) {
       
   300             if (m_indicesCache.contains(m_query->value(5).toInt())) {
       
   301                 linkMap.insertMulti(m_query->value(0).toString(), buildQUrl(m_query->value(1).toString(),
       
   302                     m_query->value(2).toString(), m_query->value(3).toString(),
       
   303                     m_query->value(4).toString()));
       
   304             }
       
   305         }
       
   306         return;
       
   307     } else {
       
   308         query = QString(QLatin1String("SELECT d.Title, f.Name, e.Name, d.Name, a.Anchor "
       
   309             "FROM IndexTable a, IndexFilterTable b, FilterAttributeTable c, "
       
   310             "FileNameTable d, FolderTable e, NamespaceTable f "
       
   311             "WHERE a.FileId=d.FileId AND d.FolderId=e.Id "
       
   312             "AND a.NamespaceId=f.Id AND b.IndexId=a.Id AND b.FilterAttributeId=c.Id "
       
   313             "AND a.Name='%1' AND c.Name='%2'")).arg(quote(keyword))
       
   314             .arg(quote(filterAttributes.first()));
       
   315         for (int i=1; i<filterAttributes.count(); ++i) {
       
   316             query.append(QString(QLatin1String(" INTERSECT SELECT d.Title, f.Name, e.Name, d.Name, a.Anchor "
       
   317                 "FROM IndexTable a, IndexFilterTable b, FilterAttributeTable c, "
       
   318                 "FileNameTable d, FolderTable e, NamespaceTable f "
       
   319                 "WHERE a.FileId=d.FileId AND d.FolderId=e.Id "
       
   320                 "AND a.NamespaceId=f.Id AND b.IndexId=a.Id AND b.FilterAttributeId=c.Id "
       
   321                 "AND a.Name='%1' AND c.Name='%2'")).arg(quote(keyword))
       
   322                 .arg(quote(filterAttributes.at(i))));
       
   323         }
       
   324     }
       
   325 
       
   326     QString title;
       
   327     m_query->exec(query);
       
   328     while (m_query->next()) {
       
   329         title = m_query->value(0).toString();
       
   330         if (title.isEmpty()) // generate a title + corresponding path
       
   331             title = keyword + QLatin1String(" : ") + m_query->value(3).toString();
       
   332         linkMap.insertMulti(title, buildQUrl(m_query->value(1).toString(),
       
   333             m_query->value(2).toString(), m_query->value(3).toString(),
       
   334             m_query->value(4).toString()));
       
   335     }
       
   336 }
       
   337 
       
   338 void QHelpDBReader::linksForIdentifier(const QString &id,
       
   339                                        const QStringList &filterAttributes,
       
   340                                        QMap<QString, QUrl> &linkMap) const
       
   341 {
       
   342     if (!m_query)
       
   343         return;
       
   344 
       
   345     QString query;
       
   346     if (filterAttributes.isEmpty()) {
       
   347         query = QString(QLatin1String("SELECT d.Title, f.Name, e.Name, d.Name, a.Anchor "
       
   348         "FROM IndexTable a, FileNameTable d, FolderTable e, "
       
   349         "NamespaceTable f WHERE a.FileId=d.FileId AND "
       
   350         "d.FolderId=e.Id AND a.NamespaceId=f.Id AND a.Identifier='%1'"))
       
   351         .arg(quote(id));
       
   352     } else if (m_useAttributesCache) {
       
   353         query = QString(QLatin1String("SELECT d.Title, f.Name, e.Name, d.Name, a.Anchor, a.Id "
       
   354             "FROM IndexTable a,"
       
   355             "FileNameTable d, FolderTable e, NamespaceTable f WHERE "
       
   356             "a.FileId=d.FileId AND d.FolderId=e.Id "
       
   357             "AND a.NamespaceId=f.Id AND a.Identifier='%1'"))
       
   358             .arg(quote(id));
       
   359         m_query->exec(query);
       
   360         while (m_query->next()) {
       
   361             if (m_indicesCache.contains(m_query->value(5).toInt())) {
       
   362                 linkMap.insertMulti(m_query->value(0).toString(), buildQUrl(m_query->value(1).toString(),
       
   363                     m_query->value(2).toString(), m_query->value(3).toString(),
       
   364                     m_query->value(4).toString()));
       
   365             }
       
   366         }
       
   367         return;
       
   368     } else {
       
   369         query = QString(QLatin1String("SELECT d.Title, f.Name, e.Name, d.Name, a.Anchor "
       
   370             "FROM IndexTable a, IndexFilterTable b, FilterAttributeTable c, "
       
   371             "FileNameTable d, FolderTable e, NamespaceTable f "
       
   372             "WHERE a.FileId=d.FileId AND d.FolderId=e.Id "
       
   373             "AND a.NamespaceId=f.Id AND b.IndexId=a.Id AND b.FilterAttributeId=c.Id "
       
   374             "AND a.Identifier='%1' AND c.Name='%2'")).arg(quote(id))
       
   375             .arg(quote(filterAttributes.first()));
       
   376         for (int i=0; i<filterAttributes.count(); ++i) {
       
   377             query.append(QString(QLatin1String(" INTERSECT SELECT d.Title, f.Name, e.Name, "
       
   378                 "d.Name, a.Anchor FROM IndexTable a, IndexFilterTable b, "
       
   379                 "FilterAttributeTable c, FileNameTable d, "
       
   380                 "FolderTable e, NamespaceTable f WHERE "
       
   381                 "a.FileId=d.FileId AND d.FolderId=e.Id AND a.NamespaceId=f.Id "
       
   382                 "AND b.IndexId=a.Id AND b.FilterAttributeId=c.Id AND "
       
   383                 "a.Identifier='%1' AND c.Name='%2'")).arg(quote(id))
       
   384                 .arg(quote(filterAttributes.at(i))));
       
   385         }
       
   386     }
       
   387 
       
   388     m_query->exec(query);
       
   389     while (m_query->next()) {
       
   390         linkMap.insertMulti(m_query->value(0).toString(), buildQUrl(m_query->value(1).toString(),
       
   391             m_query->value(2).toString(), m_query->value(3).toString(),
       
   392             m_query->value(4).toString()));
       
   393     }
       
   394 }
       
   395 
       
   396 QUrl QHelpDBReader::buildQUrl(const QString &ns, const QString &folder,
       
   397                               const QString &relFileName, const QString &anchor) const
       
   398 {
       
   399     QUrl url;
       
   400     url.setScheme(QLatin1String("qthelp"));
       
   401     url.setAuthority(ns);
       
   402     url.setPath(folder + QLatin1Char('/') + relFileName);
       
   403     url.setFragment(anchor);
       
   404     return url;
       
   405 }
       
   406 
       
   407 QList<QByteArray> QHelpDBReader::contentsForFilter(const QStringList &filterAttributes) const
       
   408 {
       
   409     QList<QByteArray> contents;
       
   410     if (!m_query)
       
   411         return contents;
       
   412 
       
   413     //SELECT DISTINCT a.Data FROM ContentsTable a, ContentsFilterTable b, FilterAttributeTable c WHERE a.Id=b.ContentsId AND b.FilterAttributeId=c.Id AND c.Name='qt' INTERSECT SELECT DISTINCT a.Data FROM ContentsTable a, ContentsFilterTable b, FilterAttributeTable c WHERE a.Id=b.ContentsId AND b.FilterAttributeId=c.Id AND c.Name='3.3.8';
       
   414 
       
   415     QString query;
       
   416     if (filterAttributes.isEmpty()) {
       
   417         query = QLatin1String("SELECT Data from ContentsTable");
       
   418     } else {
       
   419         query = QString(QLatin1String("SELECT a.Data FROM ContentsTable a, "
       
   420             "ContentsFilterTable b, FilterAttributeTable c "
       
   421             "WHERE a.Id=b.ContentsId AND b.FilterAttributeId=c.Id "
       
   422             "AND c.Name='%1'")).arg(quote(filterAttributes.first()));
       
   423         for (int i=1; i<filterAttributes.count(); ++i) {
       
   424             query.append(QString(QLatin1String(" INTERSECT SELECT a.Data FROM ContentsTable a, "
       
   425             "ContentsFilterTable b, FilterAttributeTable c "
       
   426             "WHERE a.Id=b.ContentsId AND b.FilterAttributeId=c.Id "
       
   427             "AND c.Name='%1'")).arg(quote(filterAttributes.at(i))));
       
   428         }
       
   429     }
       
   430 
       
   431     m_query->exec(query);
       
   432     while (m_query->next()) {
       
   433         contents.append(m_query->value(0).toByteArray());
       
   434     }
       
   435     return contents;
       
   436 }
       
   437 
       
   438 QUrl QHelpDBReader::urlOfPath(const QString &relativePath) const
       
   439 {
       
   440     QUrl url;
       
   441     if (!m_query)
       
   442         return url;
       
   443 
       
   444     m_query->exec(QLatin1String("SELECT a.Name, b.Name FROM NamespaceTable a, "
       
   445         "FolderTable b WHERE a.id=b.NamespaceId and a.Id=1"));
       
   446     if (m_query->next()) {
       
   447         QString rp = relativePath;
       
   448         QString anchor;
       
   449         int i = rp.indexOf(QLatin1Char('#'));
       
   450         if (i > -1) {
       
   451             rp = relativePath.left(i);
       
   452             anchor = relativePath.mid(i+1);
       
   453         }
       
   454         url = buildQUrl(m_query->value(0).toString(),
       
   455             m_query->value(1).toString(), rp, anchor);
       
   456     }
       
   457     return url;
       
   458 }
       
   459 
       
   460 QStringList QHelpDBReader::files(const QStringList &filterAttributes,
       
   461                                  const QString &extensionFilter) const
       
   462 {
       
   463     QStringList lst;
       
   464     if (!m_query)
       
   465         return lst;
       
   466 
       
   467     QString query;
       
   468     QString extension;
       
   469     if (!extensionFilter.isEmpty())
       
   470         extension = QString(QLatin1String("AND b.Name like \'%.%1\'")).arg(extensionFilter);
       
   471 
       
   472     if (filterAttributes.isEmpty()) {
       
   473         query = QString(QLatin1String("SELECT a.Name, b.Name FROM FolderTable a, "
       
   474             "FileNameTable b WHERE b.FolderId=a.Id %1"))
       
   475             .arg(extension);
       
   476     } else {
       
   477         query = QString(QLatin1String("SELECT a.Name, b.Name FROM FolderTable a, "
       
   478             "FileNameTable b, FileFilterTable c, FilterAttributeTable d "
       
   479             "WHERE b.FolderId=a.Id AND b.FileId=c.FileId "
       
   480             "AND c.FilterAttributeId=d.Id AND d.Name=\'%1\' %2"))
       
   481             .arg(quote(filterAttributes.first())).arg(extension);
       
   482         for (int i=1; i<filterAttributes.count(); ++i) {
       
   483             query.append(QString(QLatin1String(" INTERSECT SELECT a.Name, b.Name FROM "
       
   484                 "FolderTable a, FileNameTable b, FileFilterTable c, "
       
   485                 "FilterAttributeTable d WHERE b.FolderId=a.Id AND "
       
   486                 "b.FileId=c.FileId AND c.FilterAttributeId=d.Id AND "
       
   487                 "d.Name=\'%1\' %2")).arg(quote(filterAttributes.at(i)))
       
   488                 .arg(extension));
       
   489         }
       
   490     }
       
   491     m_query->exec(query);
       
   492     while (m_query->next()) {
       
   493         lst.append(m_query->value(0).toString() + QLatin1Char('/')
       
   494             + m_query->value(1).toString());
       
   495     }
       
   496 
       
   497     return lst;
       
   498 }
       
   499 
       
   500 QVariant QHelpDBReader::metaData(const QString &name) const
       
   501 {
       
   502     QVariant v;
       
   503     if (!m_query)
       
   504         return v;
       
   505 
       
   506     m_query->prepare(QLatin1String("SELECT COUNT(Value), Value FROM MetaDataTable "
       
   507         "WHERE Name=?"));
       
   508     m_query->bindValue(0, name);
       
   509     if (m_query->exec() && m_query->next()
       
   510         && m_query->value(0).toInt() == 1)
       
   511         v = m_query->value(1);
       
   512     return v;
       
   513 }
       
   514 
       
   515 QString QHelpDBReader::mergeList(const QStringList &list) const
       
   516 {
       
   517     QString str;
       
   518     foreach (QString s, list)
       
   519         str.append(QLatin1Char('\'') + quote(s) + QLatin1String("\', "));
       
   520     if (str.endsWith(QLatin1String(", ")))
       
   521         str = str.left(str.length()-2);
       
   522     return str;
       
   523 }
       
   524 
       
   525 QString QHelpDBReader::quote(const QString &string) const
       
   526 {
       
   527     QString s = string;
       
   528     s.replace(QLatin1Char('\''), QLatin1String("\'\'"));
       
   529     return s;
       
   530 }
       
   531 
       
   532 QSet<int> QHelpDBReader::indexIds(const QStringList &attributes) const
       
   533 {
       
   534     QSet<int> ids;
       
   535 
       
   536     if (attributes.isEmpty())
       
   537         return ids;
       
   538 
       
   539     QString query = QString(QLatin1String("SELECT a.IndexId FROM IndexFilterTable a, "
       
   540         "FilterAttributeTable b WHERE a.FilterAttributeId=b.Id "
       
   541         "AND b.Name='%1'")).arg(attributes.first());
       
   542     for (int i=0; i<attributes.count(); ++i) {
       
   543         query.append(QString(QLatin1String(" INTERSECT SELECT a.IndexId FROM "
       
   544             "IndexFilterTable a, FilterAttributeTable b WHERE "
       
   545             "a.FilterAttributeId=b.Id AND b.Name='%1'"))
       
   546             .arg(attributes.at(i)));
       
   547     }
       
   548     
       
   549     if (!m_query->exec(query))
       
   550             return ids;
       
   551 
       
   552     while (m_query->next())
       
   553         ids.insert(m_query->value(0).toInt());
       
   554     
       
   555     return ids;
       
   556 }
       
   557 
       
   558 bool QHelpDBReader::createAttributesCache(const QStringList &attributes,
       
   559                                           const QSet<int> &indexIds)
       
   560 {
       
   561     m_useAttributesCache = false;
       
   562 
       
   563     if (attributes.count() < 2) {
       
   564         m_viewAttributes.clear();
       
   565         return true;
       
   566     }
       
   567 
       
   568     bool needUpdate = !m_viewAttributes.count();
       
   569 
       
   570     foreach (QString s, attributes)
       
   571         m_viewAttributes.remove(s);
       
   572 
       
   573     if (m_viewAttributes.count() || needUpdate) {
       
   574         m_viewAttributes.clear();
       
   575         m_indicesCache = indexIds;        
       
   576     }
       
   577     foreach (QString s, attributes)
       
   578         m_viewAttributes.insert(s);
       
   579     m_useAttributesCache = true;
       
   580     return true;
       
   581 }
       
   582 
       
   583 QT_END_NAMESPACE