source: branches/vendor/trolltech/qt/current/tools/assistant/lib/qhelpgenerator.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: 26.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 "qhelpgenerator_p.h"
43#include "qhelpdatainterface_p.h"
44
45#include <math.h>
46#include <QtCore/QFile>
47#include <QtCore/QFileInfo>
48#include <QtCore/QDir>
49#include <QtCore/QDebug>
50#include <QtCore/QVariant>
51#include <QtCore/QDateTime>
52#include <QtCore/QTextCodec>
53#include <QtSql/QSqlQuery>
54
55QT_BEGIN_NAMESPACE
56
57class QHelpGeneratorPrivate
58{
59public:
60    QHelpGeneratorPrivate();
61    ~QHelpGeneratorPrivate();
62
63    QString error;
64    QSqlQuery *query;
65
66    int namespaceId;
67    int virtualFolderId;
68
69    QMap<QString, int> fileMap;
70    QMap<int, QSet<int> > fileFilterMap;
71
72    double progress;
73    double oldProgress;
74    double contentStep;
75    double fileStep;
76    double indexStep;
77};
78
79QHelpGeneratorPrivate::QHelpGeneratorPrivate()
80{
81    query = 0;
82    namespaceId = -1;
83    virtualFolderId = -1;
84}
85
86QHelpGeneratorPrivate::~QHelpGeneratorPrivate()
87{
88}
89
90
91
92/*!
93    \internal
94    \class QHelpGenerator
95    \since 4.4
96    \brief The QHelpGenerator class generates a new
97    Qt compressed help file (.qch).
98
99    The help generator takes a help data structure as
100    input for generating a new Qt compressed help files. Since
101    the generation may takes some time, the generator emits
102    various signals to inform about its current state.
103*/
104
105/*!
106    \fn void QHelpGenerator::statusChanged(const QString &msg)
107
108    This signal is emitted when the generation status changes.
109    The status is basically a specific task like inserting
110    files or building up the keyword index. The parameter
111    \a msg contains the detailed status description.
112*/
113
114/*!
115    \fn void QHelpGenerator::progressChanged(double progress)
116
117    This signal is emitted when the progress changes. The
118    \a progress ranges from 0 to 100.
119*/
120
121/*!
122    \fn void QHelpGenerator::warning(const QString &msg)
123
124    This signal is emitted when a non critical error occurs,
125    e.g. when a referenced file cannot be found. \a msg
126    contains the exact warning message.
127*/
128
129/*!
130    Constructs a new help generator with the give \a parent.
131*/
132QHelpGenerator::QHelpGenerator(QObject *parent)
133    : QObject(parent)
134{
135    d = new QHelpGeneratorPrivate;
136}
137
138/*!
139    Destructs the help generator.
140*/
141QHelpGenerator::~QHelpGenerator()
142{
143    delete d;
144}
145
146/*!
147    Takes the \a helpData and generates a new documentation
148    set from it. The Qt compressed help file is written to \a
149    outputFileName. Returns true on success, otherwise false.
150*/
151bool QHelpGenerator::generate(QHelpDataInterface *helpData,
152                              const QString &outputFileName)
153{
154    emit progressChanged(0);
155    d->error.clear();
156    if (!helpData || helpData->namespaceName().isEmpty()) {
157        d->error = tr("Invalid help data!");
158        return false;
159    }
160
161    QString outFileName = outputFileName;
162    if (outFileName.isEmpty()) {
163        d->error = tr("No output file name specified!");
164        return false;
165    }
166
167    QFileInfo fi(outFileName);
168    if (fi.exists()) {
169        if (!fi.dir().remove(fi.fileName())) {
170            d->error = tr("The file %1 cannot be overwritten!").arg(outFileName);
171            return false;
172        }
173    }
174
175    setupProgress(helpData);
176
177    emit statusChanged(tr("Building up file structure..."));
178    bool openingOk = true;
179    {
180        QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), QLatin1String("builder"));
181        db.setDatabaseName(outFileName);
182        openingOk = db.open();
183        if (openingOk)
184            d->query = new QSqlQuery(db);
185    }
186
187    if (!openingOk) {
188        d->error = tr("Cannot open data base file %1!").arg(outFileName);
189        cleanupDB();
190        return false;
191    }
192
193    addProgress(1.0);
194    createTables();
195    insertFileNotFoundFile();
196    insertMetaData(helpData->metaData());
197
198    if (!registerVirtualFolder(helpData->virtualFolder(), helpData->namespaceName())) {
199        d->error = tr("Cannot register namespace %1!").arg(helpData->namespaceName());
200        cleanupDB();
201        return false;
202    }
203    addProgress(1.0);
204
205    emit statusChanged(tr("Insert custom filters..."));
206    foreach (QHelpDataCustomFilter f, helpData->customFilters()) {
207        if (!registerCustomFilter(f.name, f.filterAttributes, true)) {
208            cleanupDB();
209            return false;
210        }
211    }
212    addProgress(1.0);
213
214    int i = 1;
215    QList<QHelpDataFilterSection>::const_iterator it = helpData->filterSections().constBegin();
216    while (it != helpData->filterSections().constEnd()) {
217        emit statusChanged(tr("Insert help data for filter section (%1 of %2)...")
218            .arg(i++).arg(helpData->filterSections().count()));
219        insertFilterAttributes((*it).filterAttributes());
220        QByteArray ba;
221        QDataStream s(&ba, QIODevice::WriteOnly);
222        foreach (QHelpDataContentItem *itm, (*it).contents())
223            writeTree(s, itm, 0);
224        if (!insertFiles((*it).files(), helpData->rootPath(), (*it).filterAttributes())
225            || !insertContents(ba, (*it).filterAttributes())
226            || !insertKeywords((*it).indices(), (*it).filterAttributes())) {
227            cleanupDB();
228            return false;
229        }
230        ++it;
231    }
232
233    cleanupDB();
234    emit progressChanged(100);
235    emit statusChanged(tr("Documentation successfully generated."));
236    return true;
237}
238
239void QHelpGenerator::setupProgress(QHelpDataInterface *helpData)
240{
241    d->progress = 0;
242    d->oldProgress = 0;
243
244    int numberOfFiles = 0;
245    int numberOfIndices = 0;
246    QList<QHelpDataFilterSection>::const_iterator it = helpData->filterSections().constBegin();
247    while (it != helpData->filterSections().constEnd()) {
248        numberOfFiles += (*it).files().count();
249        numberOfIndices += (*it).indices().count();
250        ++it;
251    }
252    // init      2%
253    // filters   1%
254    // contents 10%
255    // files    60%
256    // indices  27%
257    d->contentStep = 10.0/(double)helpData->customFilters().count();
258    d->fileStep = 60.0/(double)numberOfFiles;
259    d->indexStep = 27.0/(double)numberOfIndices;
260}
261
262void QHelpGenerator::addProgress(double step)
263{
264    d->progress += step;
265    if ((d->progress-d->oldProgress) >= 1.0 && d->progress <= 100.0) {
266        d->oldProgress = d->progress;
267        emit progressChanged(ceil(d->progress));
268    }
269}
270
271void QHelpGenerator::cleanupDB()
272{
273    if (d->query) {
274        d->query->clear();
275        delete d->query;
276        d->query = 0;
277    }
278    QSqlDatabase::removeDatabase(QLatin1String("builder"));
279}
280
281void QHelpGenerator::writeTree(QDataStream &s, QHelpDataContentItem *item, int depth)
282{
283    QString fReference = QDir::cleanPath(item->reference());
284    if (fReference.startsWith(QLatin1String("./")))
285        fReference = fReference.mid(2);
286
287    s << depth;
288    s << fReference;
289    s << item->title();
290    foreach (QHelpDataContentItem *i, item->children())
291        writeTree(s, i, depth+1);
292}
293
294/*!
295    Returns the last error message.
296*/
297QString QHelpGenerator::error() const
298{
299    return d->error;
300}
301
302bool QHelpGenerator::createTables()
303{
304    if (!d->query)
305        return false;
306
307    d->query->exec(QLatin1String("SELECT COUNT(*) FROM sqlite_master WHERE TYPE=\'table\'"
308        "AND Name=\'NamespaceTable\'"));
309    d->query->next();
310    if (d->query->value(0).toInt() > 0) {
311        d->error = tr("Some tables already exist!");
312        return false;
313    }
314
315    QStringList tables;
316    tables << QLatin1String("CREATE TABLE NamespaceTable ("
317            "Id INTEGER PRIMARY KEY,"
318            "Name TEXT )")
319        << QLatin1String("CREATE TABLE FilterAttributeTable ("
320            "Id INTEGER PRIMARY KEY, "
321            "Name TEXT )")
322        << QLatin1String("CREATE TABLE FilterNameTable ("
323            "Id INTEGER PRIMARY KEY, "
324            "Name TEXT )")
325        << QLatin1String("CREATE TABLE FilterTable ("
326            "NameId INTEGER, "
327            "FilterAttributeId INTEGER )")
328        << QLatin1String("CREATE TABLE IndexTable ("
329            "Id INTEGER PRIMARY KEY, "
330            "Name TEXT, "
331            "Identifier TEXT, "
332            "NamespaceId INTEGER, "
333            "FileId INTEGER, "
334            "Anchor TEXT )")
335        << QLatin1String("CREATE TABLE IndexItemTable ("
336            "Id INTEGER, "
337            "IndexId INTEGER )")
338        << QLatin1String("CREATE TABLE IndexFilterTable ("
339            "FilterAttributeId INTEGER, "
340            "IndexId INTEGER )")
341        << QLatin1String("CREATE TABLE ContentsTable ("
342            "Id INTEGER PRIMARY KEY, "
343            "NamespaceId INTEGER, "
344            "Data BLOB )")
345        << QLatin1String("CREATE TABLE ContentsFilterTable ("
346            "FilterAttributeId INTEGER, "
347            "ContentsId INTEGER )")
348        << QLatin1String("CREATE TABLE FileAttributeSetTable ("
349            "Id INTEGER, "
350            "FilterAttributeId INTEGER )")
351        << QLatin1String("CREATE TABLE FileDataTable ("
352            "Id INTEGER PRIMARY KEY, "
353            "Data BLOB )")
354        << QLatin1String("CREATE TABLE FileFilterTable ("
355            "FilterAttributeId INTEGER, "
356            "FileId INTEGER )")
357        << QLatin1String("CREATE TABLE FileNameTable ("
358            "FolderId INTEGER, "
359            "Name TEXT, "
360            "FileId INTEGER, "
361            "Title TEXT )")
362        << QLatin1String("CREATE TABLE FolderTable("
363            "Id INTEGER PRIMARY KEY, "
364            "Name Text, "
365            "NamespaceID INTEGER )")
366        << QLatin1String("CREATE TABLE MetaDataTable("
367            "Name Text, "
368            "Value BLOB )");
369
370    foreach (QString q, tables) {
371        if (!d->query->exec(q)) {
372            d->error = tr("Cannot create tables!");
373            return false;
374        }
375    }
376
377    d->query->exec(QLatin1String("INSERT INTO MetaDataTable VALUES('qchVersion', '1.0')"));
378
379    d->query->prepare(QLatin1String("INSERT INTO MetaDataTable VALUES('CreationDate', ?)"));
380    d->query->bindValue(0, QDateTime::currentDateTime().toString(Qt::ISODate));
381    d->query->exec();
382
383    return true;
384}
385
386bool QHelpGenerator::insertFileNotFoundFile()
387{
388    if (!d->query)
389        return false;
390
391    d->query->exec(QLatin1String("SELECT id FROM FileNameTable WHERE Name=\'\'"));
392    if (d->query->next() && d->query->isValid())
393        return true;
394
395    d->query->prepare(QLatin1String("INSERT INTO FileDataTable VALUES (Null, ?)"));
396    d->query->bindValue(0, QByteArray());
397    if (!d->query->exec())
398        return false;
399
400    int fileId = d->query->lastInsertId().toInt();
401    d->query->prepare(QLatin1String("INSERT INTO FileNameTable (FolderId, Name, FileId, Title) "
402        " VALUES (0, '', ?, '')"));
403    d->query->bindValue(0, fileId);
404    if (fileId > -1 && d->query->exec()) {
405        d->fileMap.insert(QString(), fileId);
406        return true;
407    }
408    return false;
409}
410
411bool QHelpGenerator::registerVirtualFolder(const QString &folderName, const QString &ns)
412{
413    if (!d->query || folderName.isEmpty() || ns.isEmpty())
414        return false;
415
416    d->query->prepare(QLatin1String("SELECT Id FROM FolderTable WHERE Name=?"));
417    d->query->bindValue(0, folderName);
418    d->query->exec();
419    d->query->next();
420    if (d->query->isValid() && d->query->value(0).toInt() > 0)
421        return true;
422
423    d->namespaceId = -1;
424    d->query->prepare(QLatin1String("SELECT Id FROM NamespaceTable WHERE Name=?"));
425    d->query->bindValue(0, ns);
426    d->query->exec();
427    while (d->query->next()) {
428        d->namespaceId = d->query->value(0).toInt();
429        break;
430    }
431
432    if (d->namespaceId < 0) {
433        d->query->prepare(QLatin1String("INSERT INTO NamespaceTable VALUES(NULL, ?)"));
434        d->query->bindValue(0, ns);
435        if (d->query->exec())
436            d->namespaceId = d->query->lastInsertId().toInt();
437    }
438
439    if (d->namespaceId > 0) {
440        d->query->prepare(QLatin1String("SELECT Id FROM FolderTable WHERE Name=?"));
441        d->query->bindValue(0, folderName);
442        d->query->exec();
443        while (d->query->next())
444            d->virtualFolderId = d->query->value(0).toInt();
445
446        if (d->virtualFolderId > 0)
447            return true;
448
449        d->query->prepare(QLatin1String("INSERT INTO FolderTable (NamespaceId, Name) "
450            "VALUES (?, ?)"));
451        d->query->bindValue(0, d->namespaceId);
452        d->query->bindValue(1, folderName);
453        if (d->query->exec()) {
454            d->virtualFolderId = d->query->lastInsertId().toInt();
455            return d->virtualFolderId > 0;
456        }
457    }
458    d->error = tr("Cannot register virtual folder!");
459    return false;
460}
461
462bool QHelpGenerator::insertFiles(const QStringList &files, const QString &rootPath,
463                                 const QStringList &filterAttributes)
464{
465    if (!d->query)
466        return false;
467
468    emit statusChanged(tr("Insert files..."));
469    QList<int> filterAtts;
470    foreach (QString filterAtt, filterAttributes) {
471        d->query->prepare(QLatin1String("SELECT Id FROM FilterAttributeTable WHERE Name=?"));
472        d->query->bindValue(0, filterAtt);
473        d->query->exec();
474        if (d->query->next())
475            filterAtts.append(d->query->value(0).toInt());
476    }
477
478    int filterSetId = -1;
479    d->query->exec(QLatin1String("SELECT MAX(Id) FROM FileAttributeSetTable"));
480    if (d->query->next())
481        filterSetId = d->query->value(0).toInt();
482    if (filterSetId < 0)
483        return false;
484    ++filterSetId;
485    foreach (int attId, filterAtts) {
486        d->query->prepare(QLatin1String("INSERT INTO FileAttributeSetTable VALUES(?, ?)"));
487        d->query->bindValue(0, filterSetId);
488        d->query->bindValue(1, attId);
489        d->query->exec();
490    }
491
492    QString title;
493    QString charSet;
494    QMap<int, QSet<int> > tmpFileFilterMap;
495    QList<FileNameTableData> fileNameDataList;
496    QList<QByteArray> fileDataList;
497
498    int tableFileId = 1;
499    d->query->exec(QLatin1String("SELECT MAX(Id) FROM FileDataTable"));
500    if (d->query->next())
501        tableFileId = d->query->value(0).toInt() + 1;
502
503    FileNameTableData fileNameData;
504
505    int i = 0;
506    foreach (QString file, files) {
507        QFileInfo fi(rootPath + QDir::separator() + file);
508        if (!fi.exists()) {
509            emit warning(tr("The file %1 does not exist! Skipping it.")
510                .arg(fi.absoluteFilePath()));
511            continue;
512        }
513
514        QFile f(fi.absoluteFilePath());
515        if (!f.open(QIODevice::ReadOnly)) {
516            emit warning(tr("Cannot open file %1! Skipping it.")
517                .arg(fi.absoluteFilePath()));
518            continue;
519        }
520
521        title.clear();
522        QByteArray data;
523        data = f.readAll();
524
525        if (fi.suffix() == QLatin1String("html") || fi.suffix() == QLatin1String("htm")) {
526            charSet = QHelpGlobal::charsetFromData(data);
527            QTextStream stream(&data);
528            stream.setCodec(QTextCodec::codecForName(charSet.toLatin1().constData()));
529            title = QHelpGlobal::documentTitle(stream.readAll());
530        } else {
531            title = fi.fileName();
532        }
533
534        QString fName = QDir::cleanPath(file);
535        if (fName.startsWith(QLatin1String("./")))
536            fName = fName.mid(2);
537
538        int fileId = -1;
539        if (!d->fileMap.contains(fName)) {
540            fileDataList.append(qCompress(data));
541
542            fileNameData.name = fName;
543            fileNameData.fileId = tableFileId;
544            fileNameData.title = title;
545            fileNameDataList.append(fileNameData);
546
547            d->fileMap.insert(fName, tableFileId);
548            d->fileFilterMap.insert(tableFileId, filterAtts.toSet());
549            tmpFileFilterMap.insert(tableFileId, filterAtts.toSet());
550
551            ++tableFileId;
552        } else {
553            fileId = d->fileMap.value(fName);
554            foreach (int filter, filterAtts) {
555                if (!d->fileFilterMap.value(fileId).contains(filter)
556                    && !tmpFileFilterMap.value(fileId).contains(filter)) {
557                        d->fileFilterMap[fileId].insert(filter);
558                        tmpFileFilterMap[fileId].insert(filter);
559                }
560            }
561        }
562    }
563
564    if (tmpFileFilterMap.count()) {
565        d->query->exec(QLatin1String("BEGIN"));
566        QMap<int, QSet<int> >::const_iterator it = tmpFileFilterMap.constBegin();
567        while (it != tmpFileFilterMap.constEnd()) {
568            QSet<int>::const_iterator i = it.value().constBegin();
569            while (i != it.value().constEnd()) {
570                d->query->prepare(QLatin1String("INSERT INTO FileFilterTable VALUES(?, ?)"));
571                d->query->bindValue(0, *i);
572                d->query->bindValue(1, it.key());
573                d->query->exec();
574                ++i;
575            }
576            ++it;
577        }
578
579        QList<QByteArray>::const_iterator fileIt = fileDataList.constBegin();
580        while (fileIt != fileDataList.constEnd()) {
581            d->query->prepare(QLatin1String("INSERT INTO FileDataTable VALUES (Null, ?)"));
582            d->query->bindValue(0, *fileIt);
583            d->query->exec();
584            ++fileIt;
585            if (++i%20 == 0)
586                addProgress(d->fileStep*20.0);
587        }
588
589        QList<FileNameTableData>::const_iterator fileNameIt = fileNameDataList.constBegin();
590        while (fileNameIt != fileNameDataList.constEnd()) {
591            d->query->prepare(QLatin1String("INSERT INTO FileNameTable (FolderId, Name, FileId, Title) "
592                " VALUES (?, ?, ?, ?)"));
593            d->query->bindValue(0, 1);
594            d->query->bindValue(1, (*fileNameIt).name);
595            d->query->bindValue(2, (*fileNameIt).fileId);
596            d->query->bindValue(3, (*fileNameIt).title);
597            d->query->exec();
598            ++fileNameIt;
599        }
600        d->query->exec(QLatin1String("COMMIT"));
601    }
602
603    d->query->exec(QLatin1String("SELECT MAX(Id) FROM FileDataTable"));
604    if (d->query->next()
605        && d->query->value(0).toInt() == tableFileId-1) {
606        addProgress(d->fileStep*(i%20));
607        return true;
608    }
609    return false;
610}
611
612bool QHelpGenerator::registerCustomFilter(const QString &filterName, const QStringList &filterAttribs,
613                                          bool forceUpdate)
614{
615    if (!d->query)
616        return false;
617
618    d->query->exec(QLatin1String("SELECT Id, Name FROM FilterAttributeTable"));
619    QStringList idsToInsert = filterAttribs;
620    QMap<QString, int> attributeMap;
621    while (d->query->next()) {
622        attributeMap.insert(d->query->value(1).toString(),
623            d->query->value(0).toInt());
624        if (idsToInsert.contains(d->query->value(1).toString()))
625            idsToInsert.removeAll(d->query->value(1).toString());
626    }
627
628    foreach (QString id, idsToInsert) {
629        d->query->prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)"));
630        d->query->bindValue(0, id);
631        d->query->exec();
632        attributeMap.insert(id, d->query->lastInsertId().toInt());
633    }
634
635    int nameId = -1;
636    d->query->prepare(QLatin1String("SELECT Id FROM FilterNameTable WHERE Name=?"));
637    d->query->bindValue(0, filterName);
638    d->query->exec();
639    while (d->query->next()) {
640        nameId = d->query->value(0).toInt();
641        break;
642    }
643
644    if (nameId < 0) {
645        d->query->prepare(QLatin1String("INSERT INTO FilterNameTable VALUES(NULL, ?)"));
646        d->query->bindValue(0, filterName);
647        if (d->query->exec())
648            nameId = d->query->lastInsertId().toInt();
649    } else if (!forceUpdate) {
650        d->error = tr("The filter %1 is already registered!").arg(filterName);
651        return false;
652    }
653
654    if (nameId < 0) {
655        d->error = tr("Cannot register filter %1!").arg(filterName);
656        return false;
657    }
658
659    d->query->prepare(QLatin1String("DELETE FROM FilterTable WHERE NameId=?"));
660    d->query->bindValue(0, nameId);
661    d->query->exec();
662
663    foreach (QString att, filterAttribs) {
664        d->query->prepare(QLatin1String("INSERT INTO FilterTable VALUES(?, ?)"));
665        d->query->bindValue(0, nameId);
666        d->query->bindValue(1, attributeMap[att]);
667        if (!d->query->exec())
668            return false;
669    }
670    return true;
671}
672
673bool QHelpGenerator::insertKeywords(const QList<QHelpDataIndexItem> keywords,
674                                    const QStringList &filterAttributes)
675{
676    if (!d->query)
677        return false;
678
679    emit statusChanged(tr("Insert indices..."));
680    int indexId = 1;
681    d->query->exec(QLatin1String("SELECT MAX(Id) FROM IndexTable"));
682    if (d->query->next())
683        indexId = d->query->value(0).toInt() + 1;
684
685    QList<int> filterAtts;
686    foreach (QString filterAtt, filterAttributes) {
687        d->query->prepare(QLatin1String("SELECT Id FROM FilterAttributeTable WHERE Name=?"));
688        d->query->bindValue(0, filterAtt);
689        d->query->exec();
690        if (d->query->next())
691            filterAtts.append(d->query->value(0).toInt());
692    }
693
694    int pos = -1;
695    QString fileName;
696    QString anchor;
697    QString fName;
698    int fileId = 1;
699    QList<int> indexFilterTable;
700
701    int i = 0;
702    d->query->exec(QLatin1String("BEGIN"));
703    foreach (QHelpDataIndexItem itm, keywords) {
704        pos = itm.reference.indexOf(QLatin1Char('#'));
705        fileName = itm.reference.left(pos);
706        if (pos > -1)
707            anchor = itm.reference.mid(pos+1);
708        else
709            anchor.clear();
710
711        fName = QDir::cleanPath(fileName);
712        if (fName.startsWith(QLatin1String("./")))
713            fName = fName.mid(2);
714
715        if (d->fileMap.contains(fName))
716            fileId = d->fileMap.value(fName);
717        else
718            fileId = 1;
719
720        d->query->prepare(QLatin1String("INSERT INTO IndexTable (Name, Identifier, NamespaceId, FileId, Anchor) "
721            "VALUES(?, ?, ?, ?, ?)"));
722        d->query->bindValue(0, itm.name);
723        d->query->bindValue(1, itm.identifier);
724        d->query->bindValue(2, d->namespaceId);
725        d->query->bindValue(3, fileId);
726        d->query->bindValue(4, anchor);
727        d->query->exec();
728
729        indexFilterTable.append(indexId++);
730        if (++i%100 == 0)
731            addProgress(d->indexStep*100.0);
732    }
733    d->query->exec(QLatin1String("COMMIT"));
734
735    d->query->exec(QLatin1String("BEGIN"));
736    foreach (int idx, indexFilterTable) {
737        foreach (int a, filterAtts) {
738            d->query->prepare(QLatin1String("INSERT INTO IndexFilterTable (FilterAttributeId, IndexId) "
739                "VALUES(?, ?)"));
740            d->query->bindValue(0, a);
741            d->query->bindValue(1, idx);
742            d->query->exec();
743        }
744    }
745    d->query->exec(QLatin1String("COMMIT"));
746
747    d->query->exec(QLatin1String("SELECT COUNT(Id) FROM IndexTable"));
748    if (d->query->next() && d->query->value(0).toInt() >= keywords.count())
749        return true;
750    return false;
751}
752
753bool QHelpGenerator::insertContents(const QByteArray &ba,
754                                    const QStringList &filterAttributes)
755{
756    if (!d->query)
757        return false;
758
759    emit statusChanged(tr("Insert contents..."));
760    d->query->prepare(QLatin1String("INSERT INTO ContentsTable (NamespaceId, Data) "
761        "VALUES(?, ?)"));
762    d->query->bindValue(0, d->namespaceId);
763    d->query->bindValue(1, ba);
764    d->query->exec();
765    int contentId = d->query->lastInsertId().toInt();
766    if (contentId < 1) {
767        d->error = tr("Cannot insert contents!");
768        return false;
769    }
770
771    // associate the filter attributes
772    foreach (QString filterAtt, filterAttributes) {
773        d->query->prepare(QLatin1String("INSERT INTO ContentsFilterTable (FilterAttributeId, ContentsId) "
774            "SELECT Id, ? FROM FilterAttributeTable WHERE Name=?"));
775        d->query->bindValue(0, contentId);
776        d->query->bindValue(1, filterAtt);
777        d->query->exec();
778        if (!d->query->isActive()) {
779            d->error = tr("Cannot register contents!");
780            return false;
781        }
782    }
783    addProgress(d->contentStep);
784    return true;
785}
786
787bool QHelpGenerator::insertFilterAttributes(const QStringList &attributes)
788{
789    if (!d->query)
790        return false;
791
792    d->query->exec(QLatin1String("SELECT Name FROM FilterAttributeTable"));
793    QSet<QString> atts;
794    while (d->query->next())
795        atts.insert(d->query->value(0).toString());
796
797    foreach (QString s, attributes) {
798        if (!atts.contains(s)) {
799            d->query->prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)"));
800            d->query->bindValue(0, s);
801            d->query->exec();
802        }
803    }
804    return true;
805}
806
807bool QHelpGenerator::insertMetaData(const QMap<QString, QVariant> &metaData)
808{
809    if (!d->query)
810        return false;
811
812    QMap<QString, QVariant>::const_iterator it = metaData.constBegin();
813    while (it != metaData.constEnd()) {
814        d->query->prepare(QLatin1String("INSERT INTO MetaDataTable VALUES(?, ?)"));
815        d->query->bindValue(0, it.key());
816        d->query->bindValue(1, it.value());
817        d->query->exec();
818        ++it;
819    }
820    return true;
821}
822
823QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.