source: trunk/tools/assistant/lib/qhelpgenerator.cpp@ 500

Last change on this file since 500 was 2, checked in by Dmitry A. Kuminov, 16 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 ([email protected])
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 [email protected].
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.