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

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

trunk: Merged in qt 4.6.1 sources.

File size: 26.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the Qt Assistant of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** 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 have questions regarding the use of this file, please contact
37** Nokia 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 (const QString &filterAtt, filterAttributes) {
471 d->query->prepare(QLatin1String("SELECT Id FROM FilterAttributeTable "
472 "WHERE Name=?"));
473 d->query->bindValue(0, filterAtt);
474 d->query->exec();
475 if (d->query->next())
476 filterAtts.append(d->query->value(0).toInt());
477 }
478
479 int filterSetId = -1;
480 d->query->exec(QLatin1String("SELECT MAX(Id) FROM FileAttributeSetTable"));
481 if (d->query->next())
482 filterSetId = d->query->value(0).toInt();
483 if (filterSetId < 0)
484 return false;
485 ++filterSetId;
486 foreach (const int &attId, filterAtts) {
487 d->query->prepare(QLatin1String("INSERT INTO FileAttributeSetTable "
488 "VALUES(?, ?)"));
489 d->query->bindValue(0, filterSetId);
490 d->query->bindValue(1, attId);
491 d->query->exec();
492 }
493
494 int tableFileId = 1;
495 d->query->exec(QLatin1String("SELECT MAX(Id) FROM FileDataTable"));
496 if (d->query->next())
497 tableFileId = d->query->value(0).toInt() + 1;
498
499 QString title;
500 QString charSet;
501 FileNameTableData fileNameData;
502 QList<QByteArray> fileDataList;
503 QMap<int, QSet<int> > tmpFileFilterMap;
504 QList<FileNameTableData> fileNameDataList;
505
506 int i = 0;
507 foreach (const QString &file, files) {
508 const QString fileName = QDir::cleanPath(file);
509 if (fileName.startsWith(QLatin1String("../"))) {
510 emit warning(tr("The referenced file %1 must be inside or within a "
511 "subdirectory of (%2). Skipping it.").arg(fileName).arg(rootPath));
512 continue;
513 }
514
515 QFile fi(rootPath + QDir::separator() + fileName);
516 if (!fi.exists()) {
517 emit warning(tr("The file %1 does not exist! Skipping it.")
518 .arg(QDir::cleanPath(rootPath + QDir::separator() + fileName)));
519 continue;
520 }
521
522 if (!fi.open(QIODevice::ReadOnly)) {
523 emit warning(tr("Cannot open file %1! Skipping it.")
524 .arg(QDir::cleanPath(rootPath + QDir::separator() + fileName)));
525 continue;
526 }
527
528 QByteArray data = fi.readAll();
529 if (fileName.endsWith(QLatin1String(".html"))
530 || fileName.endsWith(QLatin1String(".htm"))) {
531 charSet = QHelpGlobal::codecFromData(data);
532 QTextStream stream(&data);
533 stream.setCodec(QTextCodec::codecForName(charSet.toLatin1().constData()));
534 title = QHelpGlobal::documentTitle(stream.readAll());
535 } else {
536 title = fileName.mid(fileName.lastIndexOf(QLatin1Char('/')) + 1);
537 }
538
539 int fileId = -1;
540 if (!d->fileMap.contains(fileName)) {
541 fileDataList.append(qCompress(data));
542
543 fileNameData.name = fileName;
544 fileNameData.fileId = tableFileId;
545 fileNameData.title = title;
546 fileNameDataList.append(fileNameData);
547
548 d->fileMap.insert(fileName, tableFileId);
549 d->fileFilterMap.insert(tableFileId, filterAtts.toSet());
550 tmpFileFilterMap.insert(tableFileId, filterAtts.toSet());
551
552 ++tableFileId;
553 } else {
554 fileId = d->fileMap.value(fileName);
555 foreach (const int &filter, filterAtts) {
556 if (!d->fileFilterMap.value(fileId).contains(filter)
557 && !tmpFileFilterMap.value(fileId).contains(filter)) {
558 d->fileFilterMap[fileId].insert(filter);
559 tmpFileFilterMap[fileId].insert(filter);
560 }
561 }
562 }
563 }
564
565 if (tmpFileFilterMap.count()) {
566 d->query->exec(QLatin1String("BEGIN"));
567 QMap<int, QSet<int> >::const_iterator it = tmpFileFilterMap.constBegin();
568 while (it != tmpFileFilterMap.constEnd()) {
569 QSet<int>::const_iterator si = it.value().constBegin();
570 while (si != it.value().constEnd()) {
571 d->query->prepare(QLatin1String("INSERT INTO FileFilterTable "
572 "VALUES(?, ?)"));
573 d->query->bindValue(0, *si);
574 d->query->bindValue(1, it.key());
575 d->query->exec();
576 ++si;
577 }
578 ++it;
579 }
580
581 QList<QByteArray>::const_iterator fileIt = fileDataList.constBegin();
582 while (fileIt != fileDataList.constEnd()) {
583 d->query->prepare(QLatin1String("INSERT INTO FileDataTable VALUES "
584 "(Null, ?)"));
585 d->query->bindValue(0, *fileIt);
586 d->query->exec();
587 ++fileIt;
588 if (++i%20 == 0)
589 addProgress(d->fileStep*20.0);
590 }
591
592 QList<FileNameTableData>::const_iterator fileNameIt =
593 fileNameDataList.constBegin();
594 while (fileNameIt != fileNameDataList.constEnd()) {
595 d->query->prepare(QLatin1String("INSERT INTO FileNameTable "
596 "(FolderId, Name, FileId, Title) VALUES (?, ?, ?, ?)"));
597 d->query->bindValue(0, 1);
598 d->query->bindValue(1, (*fileNameIt).name);
599 d->query->bindValue(2, (*fileNameIt).fileId);
600 d->query->bindValue(3, (*fileNameIt).title);
601 d->query->exec();
602 ++fileNameIt;
603 }
604 d->query->exec(QLatin1String("COMMIT"));
605 }
606
607 d->query->exec(QLatin1String("SELECT MAX(Id) FROM FileDataTable"));
608 if (d->query->next()
609 && d->query->value(0).toInt() == tableFileId-1) {
610 addProgress(d->fileStep*(i%20));
611 return true;
612 }
613 return false;
614}
615
616bool QHelpGenerator::registerCustomFilter(const QString &filterName,
617 const QStringList &filterAttribs, bool forceUpdate)
618{
619 if (!d->query)
620 return false;
621
622 d->query->exec(QLatin1String("SELECT Id, Name FROM FilterAttributeTable"));
623 QStringList idsToInsert = filterAttribs;
624 QMap<QString, int> attributeMap;
625 while (d->query->next()) {
626 attributeMap.insert(d->query->value(1).toString(),
627 d->query->value(0).toInt());
628 if (idsToInsert.contains(d->query->value(1).toString()))
629 idsToInsert.removeAll(d->query->value(1).toString());
630 }
631
632 foreach (QString id, idsToInsert) {
633 d->query->prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)"));
634 d->query->bindValue(0, id);
635 d->query->exec();
636 attributeMap.insert(id, d->query->lastInsertId().toInt());
637 }
638
639 int nameId = -1;
640 d->query->prepare(QLatin1String("SELECT Id FROM FilterNameTable WHERE Name=?"));
641 d->query->bindValue(0, filterName);
642 d->query->exec();
643 while (d->query->next()) {
644 nameId = d->query->value(0).toInt();
645 break;
646 }
647
648 if (nameId < 0) {
649 d->query->prepare(QLatin1String("INSERT INTO FilterNameTable VALUES(NULL, ?)"));
650 d->query->bindValue(0, filterName);
651 if (d->query->exec())
652 nameId = d->query->lastInsertId().toInt();
653 } else if (!forceUpdate) {
654 d->error = tr("The filter %1 is already registered!").arg(filterName);
655 return false;
656 }
657
658 if (nameId < 0) {
659 d->error = tr("Cannot register filter %1!").arg(filterName);
660 return false;
661 }
662
663 d->query->prepare(QLatin1String("DELETE FROM FilterTable WHERE NameId=?"));
664 d->query->bindValue(0, nameId);
665 d->query->exec();
666
667 foreach (QString att, filterAttribs) {
668 d->query->prepare(QLatin1String("INSERT INTO FilterTable VALUES(?, ?)"));
669 d->query->bindValue(0, nameId);
670 d->query->bindValue(1, attributeMap[att]);
671 if (!d->query->exec())
672 return false;
673 }
674 return true;
675}
676
677bool QHelpGenerator::insertKeywords(const QList<QHelpDataIndexItem> keywords,
678 const QStringList &filterAttributes)
679{
680 if (!d->query)
681 return false;
682
683 emit statusChanged(tr("Insert indices..."));
684 int indexId = 1;
685 d->query->exec(QLatin1String("SELECT MAX(Id) FROM IndexTable"));
686 if (d->query->next())
687 indexId = d->query->value(0).toInt() + 1;
688
689 QList<int> filterAtts;
690 foreach (QString filterAtt, filterAttributes) {
691 d->query->prepare(QLatin1String("SELECT Id FROM FilterAttributeTable WHERE Name=?"));
692 d->query->bindValue(0, filterAtt);
693 d->query->exec();
694 if (d->query->next())
695 filterAtts.append(d->query->value(0).toInt());
696 }
697
698 int pos = -1;
699 QString fileName;
700 QString anchor;
701 QString fName;
702 int fileId = 1;
703 QList<int> indexFilterTable;
704
705 int i = 0;
706 d->query->exec(QLatin1String("BEGIN"));
707 foreach (QHelpDataIndexItem itm, keywords) {
708 pos = itm.reference.indexOf(QLatin1Char('#'));
709 fileName = itm.reference.left(pos);
710 if (pos > -1)
711 anchor = itm.reference.mid(pos+1);
712 else
713 anchor.clear();
714
715 fName = QDir::cleanPath(fileName);
716 if (fName.startsWith(QLatin1String("./")))
717 fName = fName.mid(2);
718
719 if (d->fileMap.contains(fName))
720 fileId = d->fileMap.value(fName);
721 else
722 fileId = 1;
723
724 d->query->prepare(QLatin1String("INSERT INTO IndexTable (Name, Identifier, NamespaceId, FileId, Anchor) "
725 "VALUES(?, ?, ?, ?, ?)"));
726 d->query->bindValue(0, itm.name);
727 d->query->bindValue(1, itm.identifier);
728 d->query->bindValue(2, d->namespaceId);
729 d->query->bindValue(3, fileId);
730 d->query->bindValue(4, anchor);
731 d->query->exec();
732
733 indexFilterTable.append(indexId++);
734 if (++i%100 == 0)
735 addProgress(d->indexStep*100.0);
736 }
737 d->query->exec(QLatin1String("COMMIT"));
738
739 d->query->exec(QLatin1String("BEGIN"));
740 foreach (int idx, indexFilterTable) {
741 foreach (int a, filterAtts) {
742 d->query->prepare(QLatin1String("INSERT INTO IndexFilterTable (FilterAttributeId, IndexId) "
743 "VALUES(?, ?)"));
744 d->query->bindValue(0, a);
745 d->query->bindValue(1, idx);
746 d->query->exec();
747 }
748 }
749 d->query->exec(QLatin1String("COMMIT"));
750
751 d->query->exec(QLatin1String("SELECT COUNT(Id) FROM IndexTable"));
752 if (d->query->next() && d->query->value(0).toInt() >= keywords.count())
753 return true;
754 return false;
755}
756
757bool QHelpGenerator::insertContents(const QByteArray &ba,
758 const QStringList &filterAttributes)
759{
760 if (!d->query)
761 return false;
762
763 emit statusChanged(tr("Insert contents..."));
764 d->query->prepare(QLatin1String("INSERT INTO ContentsTable (NamespaceId, Data) "
765 "VALUES(?, ?)"));
766 d->query->bindValue(0, d->namespaceId);
767 d->query->bindValue(1, ba);
768 d->query->exec();
769 int contentId = d->query->lastInsertId().toInt();
770 if (contentId < 1) {
771 d->error = tr("Cannot insert contents!");
772 return false;
773 }
774
775 // associate the filter attributes
776 foreach (QString filterAtt, filterAttributes) {
777 d->query->prepare(QLatin1String("INSERT INTO ContentsFilterTable (FilterAttributeId, ContentsId) "
778 "SELECT Id, ? FROM FilterAttributeTable WHERE Name=?"));
779 d->query->bindValue(0, contentId);
780 d->query->bindValue(1, filterAtt);
781 d->query->exec();
782 if (!d->query->isActive()) {
783 d->error = tr("Cannot register contents!");
784 return false;
785 }
786 }
787 addProgress(d->contentStep);
788 return true;
789}
790
791bool QHelpGenerator::insertFilterAttributes(const QStringList &attributes)
792{
793 if (!d->query)
794 return false;
795
796 d->query->exec(QLatin1String("SELECT Name FROM FilterAttributeTable"));
797 QSet<QString> atts;
798 while (d->query->next())
799 atts.insert(d->query->value(0).toString());
800
801 foreach (QString s, attributes) {
802 if (!atts.contains(s)) {
803 d->query->prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)"));
804 d->query->bindValue(0, s);
805 d->query->exec();
806 }
807 }
808 return true;
809}
810
811bool QHelpGenerator::insertMetaData(const QMap<QString, QVariant> &metaData)
812{
813 if (!d->query)
814 return false;
815
816 QMap<QString, QVariant>::const_iterator it = metaData.constBegin();
817 while (it != metaData.constEnd()) {
818 d->query->prepare(QLatin1String("INSERT INTO MetaDataTable VALUES(?, ?)"));
819 d->query->bindValue(0, it.key());
820 d->query->bindValue(1, it.value());
821 d->query->exec();
822 ++it;
823 }
824 return true;
825}
826
827QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.