source: branches/vendor/trolltech/qt/current/tools/assistant/lib/qhelpcollectionhandler.cpp @ 2

Last change on this file since 2 was 2, checked in by Dmitry A. Kuminov, 13 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 19.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information (qt-info@nokia.com)
5**
6** This file is part of the Qt Assistant of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file.  Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file.  Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at qt-sales@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qhelpcollectionhandler_p.h"
43#include "qhelp_global.h"
44#include "qhelpdbreader_p.h"
45
46#include <QtCore/QFile>
47#include <QtCore/QDir>
48#include <QtCore/QFileInfo>
49#include <QtCore/QDebug>
50
51#include <QtSql/QSqlError>
52#include <QtSql/QSqlDriver>
53
54QT_BEGIN_NAMESPACE
55
56QHelpCollectionHandler::QHelpCollectionHandler(const QString &collectionFile, QObject *parent)
57    : QObject(parent)
58    , m_dbOpened(false)
59    , m_collectionFile(collectionFile)
60    , m_connectionName(QString())
61{
62    QFileInfo fi(m_collectionFile);
63    if (!fi.isAbsolute())
64        m_collectionFile = fi.absoluteFilePath();
65    m_query.clear();
66}
67
68QHelpCollectionHandler::~QHelpCollectionHandler()
69{
70    m_query.clear();
71    if (m_dbOpened)
72        QSqlDatabase::removeDatabase(m_connectionName);
73}
74
75bool QHelpCollectionHandler::isDBOpened()
76{
77    if (m_dbOpened)
78        return true;
79    emit error(tr("The collection file is not set up yet!"));
80    return false;
81}
82
83QString QHelpCollectionHandler::collectionFile() const
84{
85    return m_collectionFile;
86}
87
88bool QHelpCollectionHandler::openCollectionFile()
89{
90    if (m_dbOpened)
91        return m_dbOpened;
92
93    m_connectionName = QHelpGlobal::uniquifyConnectionName(
94        QLatin1String("QHelpCollectionHandler"), this);
95    bool openingOk = true;
96    {
97        QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"),
98            m_connectionName);
99        if (db.driver()
100            && db.driver()->lastError().type() == QSqlError::ConnectionError) {
101            emit error(tr("Cannot load sqlite database driver!"));
102            return false;
103        }
104
105        db.setDatabaseName(collectionFile());
106        openingOk = db.open();
107        if (openingOk)
108            m_query = QSqlQuery(db);
109    }
110    if (!openingOk) {
111        QSqlDatabase::removeDatabase(m_connectionName);
112        emit error(tr("Cannot open collection file: %1").arg(collectionFile()));
113        return false;
114    }
115
116    m_query.exec(QLatin1String("SELECT COUNT(*) FROM sqlite_master WHERE TYPE=\'table\'"
117                               "AND Name=\'NamespaceTable\'"));
118    m_query.next();
119    if (m_query.value(0).toInt() < 1) {
120        if (!createTables(&m_query)) {
121            emit error(tr("Cannot create tables in file %1!").arg(collectionFile()));
122            return false;
123        }
124    }
125
126    m_dbOpened = true;
127    return m_dbOpened;
128}
129
130bool QHelpCollectionHandler::copyCollectionFile(const QString &fileName)
131{
132    if (!m_dbOpened)
133        return false;
134
135    QFileInfo fi(fileName);
136    if (fi.exists()) {
137        emit error(tr("The specified collection file already exists!"));
138        return false;
139    }
140
141    if (!fi.absoluteDir().exists() && !QDir().mkpath(fi.absolutePath())) {
142        emit error(tr("Cannot create directory: %1").arg(fi.absolutePath()));
143        return false;
144    }
145
146    QString colFile = fi.absoluteFilePath();
147    QString connectionName = QHelpGlobal::uniquifyConnectionName(
148        QLatin1String("QHelpCollectionHandlerCopy"), this);
149    QSqlQuery *copyQuery = 0;
150    bool openingOk = true;
151    {
152        QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), connectionName);
153        db.setDatabaseName(colFile);
154        openingOk = db.open();
155        if (openingOk)
156            copyQuery = new QSqlQuery(db);
157    }
158
159    if (!openingOk) {
160        emit error(tr("Cannot open collection file: %1").arg(colFile));
161        return false;
162    }
163
164    if (!createTables(copyQuery)) {
165        emit error(tr("Cannot copy collection file: %1").arg(colFile));
166        return false;
167    }
168
169    QString oldBaseDir = QFileInfo(collectionFile()).absolutePath();
170    QString oldFilePath;
171    QFileInfo newColFi(colFile);
172    m_query.exec(QLatin1String("SELECT Name, FilePath FROM NamespaceTable"));
173    while (m_query.next()) {
174        copyQuery->prepare(QLatin1String("INSERT INTO NamespaceTable VALUES(NULL, ?, ?)"));
175        copyQuery->bindValue(0, m_query.value(0).toString());
176        oldFilePath = m_query.value(1).toString();
177        if (!QDir::isAbsolutePath(oldFilePath))
178            oldFilePath = oldBaseDir + QDir::separator() + oldFilePath;
179        copyQuery->bindValue(1, newColFi.absoluteDir().relativeFilePath(oldFilePath));
180        copyQuery->exec();
181    }
182
183    m_query.exec(QLatin1String("SELECT NamespaceId, Name FROM FolderTable"));
184    while (m_query.next()) {
185        copyQuery->prepare(QLatin1String("INSERT INTO FolderTable VALUES(NULL, ?, ?)"));
186        copyQuery->bindValue(0, m_query.value(0).toString());
187        copyQuery->bindValue(1, m_query.value(1).toString());
188        copyQuery->exec();
189    }
190
191    m_query.exec(QLatin1String("SELECT Name FROM FilterAttributeTable"));
192    while (m_query.next()) {
193        copyQuery->prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)"));
194        copyQuery->bindValue(0, m_query.value(0).toString());
195        copyQuery->exec();
196    }
197
198    m_query.exec(QLatin1String("SELECT Name FROM FilterNameTable"));
199    while (m_query.next()) {
200        copyQuery->prepare(QLatin1String("INSERT INTO FilterNameTable VALUES(NULL, ?)"));
201        copyQuery->bindValue(0, m_query.value(0).toString());
202        copyQuery->exec();
203    }
204
205    m_query.exec(QLatin1String("SELECT NameId, FilterAttributeId FROM FilterTable"));
206    while (m_query.next()) {
207        copyQuery->prepare(QLatin1String("INSERT INTO FilterTable VALUES(?, ?)"));
208        copyQuery->bindValue(0, m_query.value(0).toInt());
209        copyQuery->bindValue(1, m_query.value(1).toInt());
210        copyQuery->exec();
211    }
212
213    m_query.exec(QLatin1String("SELECT Key, Value FROM SettingsTable"));
214    while (m_query.next()) {
215        if (m_query.value(0).toString() == QLatin1String("CluceneSearchNamespaces"))
216            continue;
217        copyQuery->prepare(QLatin1String("INSERT INTO SettingsTable VALUES(?, ?)"));
218        copyQuery->bindValue(0, m_query.value(0).toString());
219        copyQuery->bindValue(1, m_query.value(1));
220        copyQuery->exec();
221    }
222
223    copyQuery->clear();
224    delete copyQuery;
225    QSqlDatabase::removeDatabase(connectionName);
226    return true;
227}
228
229bool QHelpCollectionHandler::createTables(QSqlQuery *query)
230{
231    QStringList tables;
232    tables << QLatin1String("CREATE TABLE NamespaceTable ("
233        "Id INTEGER PRIMARY KEY, "
234        "Name TEXT, "
235        "FilePath TEXT )")
236        << QLatin1String("CREATE TABLE FolderTable ("
237        "Id INTEGER PRIMARY KEY, "
238        "NamespaceId INTEGER, "
239        "Name TEXT )")
240        << QLatin1String("CREATE TABLE FilterAttributeTable ("
241        "Id INTEGER PRIMARY KEY, "
242        "Name TEXT )")
243        << QLatin1String("CREATE TABLE FilterNameTable ("
244        "Id INTEGER PRIMARY KEY, "
245        "Name TEXT )")
246        << QLatin1String("CREATE TABLE FilterTable ("
247        "NameId INTEGER, "
248        "FilterAttributeId INTEGER )")
249        << QLatin1String("CREATE TABLE SettingsTable ("
250        "Key TEXT PRIMARY KEY, "
251        "Value BLOB )");
252
253    foreach (QString q, tables) {
254        if (!query->exec(q))
255            return false;
256    }
257    return true;
258}
259
260QStringList QHelpCollectionHandler::customFilters() const
261{
262    QStringList list;
263    if (m_dbOpened) {
264        m_query.exec(QLatin1String("SELECT Name FROM FilterNameTable"));
265        while (m_query.next())
266            list.append(m_query.value(0).toString());
267    }
268    return list;
269}
270
271bool QHelpCollectionHandler::removeCustomFilter(const QString &filterName)
272{
273    if (!isDBOpened() || filterName.isEmpty())
274        return false;
275
276    int filterNameId = -1;
277    m_query.prepare(QLatin1String("SELECT Id FROM FilterNameTable WHERE Name=?"));
278    m_query.bindValue(0, filterName);
279    m_query.exec();
280    if (m_query.next())
281        filterNameId = m_query.value(0).toInt();
282
283    if (filterNameId < 0) {
284        emit error(tr("Unknown filter!"));
285        return false;
286    }
287
288    m_query.prepare(QLatin1String("DELETE FROM FilterTable WHERE NameId=?"));
289    m_query.bindValue(0, filterNameId);
290    m_query.exec();
291
292    m_query.prepare(QLatin1String("DELETE FROM FilterNameTable WHERE Id=?"));
293    m_query.bindValue(0, filterNameId);
294    m_query.exec();
295
296    return true;
297}
298
299bool QHelpCollectionHandler::addCustomFilter(const QString &filterName,
300                                             const QStringList &attributes)
301{
302    if (!isDBOpened() || filterName.isEmpty())
303        return false;
304
305    int nameId = -1;
306    m_query.prepare(QLatin1String("SELECT Id FROM FilterNameTable WHERE Name=?"));
307    m_query.bindValue(0, filterName);
308    m_query.exec();
309    while (m_query.next()) {
310        nameId = m_query.value(0).toInt();
311        break;
312    }
313
314    m_query.exec(QLatin1String("SELECT Id, Name FROM FilterAttributeTable"));
315    QStringList idsToInsert = attributes;
316    QMap<QString, int> attributeMap;
317    while (m_query.next()) {
318        attributeMap.insert(m_query.value(1).toString(),
319            m_query.value(0).toInt());
320        if (idsToInsert.contains(m_query.value(1).toString()))
321            idsToInsert.removeAll(m_query.value(1).toString());
322    }
323
324    foreach (QString id, idsToInsert) {
325        m_query.prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)"));
326        m_query.bindValue(0, id);
327        m_query.exec();
328        attributeMap.insert(id, m_query.lastInsertId().toInt());
329    }
330
331    if (nameId < 0) {
332        m_query.prepare(QLatin1String("INSERT INTO FilterNameTable VALUES(NULL, ?)"));
333        m_query.bindValue(0, filterName);
334        if (m_query.exec())
335            nameId = m_query.lastInsertId().toInt();
336    }
337
338    if (nameId < 0) {
339        emit error(tr("Cannot register filter %1!").arg(filterName));
340        return false;
341    }
342
343    m_query.prepare(QLatin1String("DELETE FROM FilterTable WHERE NameId=?"));
344    m_query.bindValue(0, nameId);
345    m_query.exec();
346
347    foreach (QString att, attributes) {
348        m_query.prepare(QLatin1String("INSERT INTO FilterTable VALUES(?, ?)"));
349        m_query.bindValue(0, nameId);
350        m_query.bindValue(1, attributeMap[att]);
351        if (!m_query.exec())
352            return false;
353    }
354    return true;
355}
356
357QHelpCollectionHandler::DocInfoList QHelpCollectionHandler::registeredDocumentations() const
358{
359    DocInfoList list;
360    if (m_dbOpened) {
361        m_query.exec(QLatin1String("SELECT a.Name, a.FilePath, b.Name "
362            "FROM NamespaceTable a, FolderTable b WHERE a.Id=b.NamespaceId"));
363
364        while (m_query.next()) {
365            DocInfo info;
366            info.fileName = m_query.value(1).toString();
367            info.folderName = m_query.value(2).toString();
368            info.namespaceName = m_query.value(0).toString();
369            list.append(info);
370        }
371    }
372    return list;
373}
374
375bool QHelpCollectionHandler::registerDocumentation(const QString &fileName)
376{
377    if (!isDBOpened())
378        return false;
379
380    QHelpDBReader reader(fileName, QHelpGlobal::uniquifyConnectionName(
381        QLatin1String("QHelpCollectionHandler"), this), 0);
382    if (!reader.init()) {
383        emit error(tr("Cannot open documentation file %1!").arg(fileName));
384        return false;
385    }
386
387    QString ns = reader.namespaceName();
388    if (ns.isEmpty()) {
389        emit error(tr("Invalid documentation file!"));
390        return false;
391    }
392
393    int nsId = registerNamespace(ns, fileName);
394    if (nsId < 1)
395        return false;
396
397    if (!registerVirtualFolder(reader.virtualFolder(), nsId))
398        return false;
399
400    addFilterAttributes(reader.filterAttributes());
401    foreach (QString filterName, reader.customFilters())
402        addCustomFilter(filterName, reader.filterAttributes(filterName));
403
404    optimizeDatabase(fileName);
405
406    return true;
407}
408
409bool QHelpCollectionHandler::unregisterDocumentation(const QString &namespaceName)
410{
411    if (!isDBOpened())
412        return false;
413
414    m_query.prepare(QLatin1String("SELECT Id FROM NamespaceTable WHERE Name=?"));
415    m_query.bindValue(0, namespaceName);
416    m_query.exec();
417
418    int nsId = -1;
419    if (m_query.next())
420        nsId = m_query.value(0).toInt();
421
422    if (nsId < 0) {
423        emit error(tr("The namespace %1 was not registered!").arg(namespaceName));
424        return false;
425    }
426
427    m_query.prepare(QLatin1String("DELETE FROM NamespaceTable WHERE Id=?"));
428    m_query.bindValue(0, nsId);
429    m_query.exec();
430
431    m_query.prepare(QLatin1String("DELETE FROM FolderTable WHERE NamespaceId=?"));
432    m_query.bindValue(0, nsId);
433    return m_query.exec();
434}
435
436bool QHelpCollectionHandler::removeCustomValue(const QString &key)
437{
438    if (!isDBOpened())
439        return false;
440
441    m_query.prepare(QLatin1String("DELETE FROM SettingsTable WHERE Key=?"));
442    m_query.bindValue(0, key);
443    return m_query.exec();
444}
445
446QVariant QHelpCollectionHandler::customValue(const QString &key,
447                                             const QVariant &defaultValue) const
448{
449    QVariant value = defaultValue;
450    if (m_dbOpened) {
451        m_query.prepare(QLatin1String("SELECT COUNT(Key) FROM SettingsTable WHERE Key=?"));
452        m_query.bindValue(0, key);
453        if (!m_query.exec() || !m_query.next() || !m_query.value(0).toInt()) {
454            m_query.clear();
455            return defaultValue;
456        }
457
458        m_query.clear();
459        m_query.prepare(QLatin1String("SELECT Value FROM SettingsTable WHERE Key=?"));
460        m_query.bindValue(0, key);
461        if (m_query.exec() && m_query.next())
462            value = m_query.value(0);
463        m_query.clear();
464    }
465    return value;
466}
467
468bool QHelpCollectionHandler::setCustomValue(const QString &key,
469                                            const QVariant &value)
470{
471    if (!isDBOpened())
472        return false;
473
474    m_query.prepare(QLatin1String("SELECT Value FROM SettingsTable WHERE Key=?"));
475    m_query.bindValue(0, key);
476    m_query.exec();
477    if (m_query.next()) {
478        m_query.prepare(QLatin1String("UPDATE SettingsTable SET Value=? where Key=?"));
479        m_query.bindValue(0, value);
480        m_query.bindValue(1, key);
481    }
482    else {
483        m_query.prepare(QLatin1String("INSERT INTO SettingsTable VALUES(?, ?)"));
484        m_query.bindValue(0, key);
485        m_query.bindValue(1, value);
486    }
487    return m_query.exec();
488}
489
490bool QHelpCollectionHandler::addFilterAttributes(const QStringList &attributes)
491{
492    if (!isDBOpened())
493        return false;
494
495    m_query.exec(QLatin1String("SELECT Name FROM FilterAttributeTable"));
496    QSet<QString> atts;
497    while (m_query.next())
498        atts.insert(m_query.value(0).toString());
499
500    foreach (QString s, attributes) {
501        if (!atts.contains(s)) {
502            m_query.prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)"));
503            m_query.bindValue(0, s);
504            m_query.exec();
505        }
506    }
507    return true;
508}
509
510QStringList QHelpCollectionHandler::filterAttributes() const
511{
512    QStringList list;
513    if (m_dbOpened) {
514        m_query.exec(QLatin1String("SELECT Name FROM FilterAttributeTable"));
515        while (m_query.next())
516            list.append(m_query.value(0).toString());
517    }
518    return list;
519}
520
521QStringList QHelpCollectionHandler::filterAttributes(const QString &filterName) const
522{
523    QStringList list;
524    if (m_dbOpened) {
525        m_query.prepare(QLatin1String("SELECT a.Name FROM FilterAttributeTable a, "
526            "FilterTable b, FilterNameTable c WHERE a.Id=b.FilterAttributeId "
527            "AND b.NameId=c.Id AND c.Name=?"));
528        m_query.bindValue(0, filterName);
529        m_query.exec();
530        while (m_query.next())
531            list.append(m_query.value(0).toString());
532    }
533    return list;
534}
535
536int QHelpCollectionHandler::registerNamespace(const QString &nspace, const QString &fileName)
537{
538    m_query.prepare(QLatin1String("SELECT COUNT(Id) FROM NamespaceTable WHERE Name=?"));
539    m_query.bindValue(0, nspace);
540    m_query.exec();
541    while (m_query.next()) {
542        if (m_query.value(0).toInt() > 0) {
543            emit error(tr("Namespace %1 already exists!").arg(nspace));
544            return -1;
545        }
546    }
547
548    QFileInfo fi(m_collectionFile);
549    m_query.prepare(QLatin1String("INSERT INTO NamespaceTable VALUES(NULL, ?, ?)"));
550    m_query.bindValue(0, nspace);
551    m_query.bindValue(1, fi.absoluteDir().relativeFilePath(fileName));
552    int namespaceId = -1;
553    if (m_query.exec())
554        namespaceId = m_query.lastInsertId().toInt();
555    if (namespaceId < 1) {
556        emit error(tr("Cannot register namespace!"));
557        return -1;
558    }
559    return namespaceId;
560}
561
562bool QHelpCollectionHandler::registerVirtualFolder(const QString &folderName, int namespaceId)
563{
564    m_query.prepare(QLatin1String("INSERT INTO FolderTable VALUES(NULL, ?, ?)"));
565    m_query.bindValue(0, namespaceId);
566    m_query.bindValue(1, folderName);
567    return m_query.exec();
568}
569
570void QHelpCollectionHandler::optimizeDatabase(const QString &fileName)
571{
572    if (!QFile::exists(fileName))
573        return;
574
575    {   // according to removeDatabase() documentation
576        QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), QLatin1String("optimize"));
577        db.setDatabaseName(fileName);
578        if (!db.open()) {
579            QSqlDatabase::removeDatabase(QLatin1String("optimize"));
580            emit error(tr("Cannot open database to optimize!"));
581            return;
582        }
583
584        QSqlQuery query(db);
585        db.exec(QLatin1String("CREATE INDEX IF NOT EXISTS NameIndex ON IndexTable(Name)"));
586        db.exec(QLatin1String("CREATE INDEX IF NOT EXISTS FileNameIndex ON FileNameTable(Name)"));
587        db.exec(QLatin1String("CREATE INDEX IF NOT EXISTS FileIdIndex ON FileNameTable(FileId)"));
588
589        db.close();
590    }
591
592    QSqlDatabase::removeDatabase(QLatin1String("optimize"));
593}
594
595QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.