source: trunk/tools/assistant/lib/qhelpcollectionhandler.cpp@ 477

Last change on this file since 477 was 2, checked in by Dmitry A. Kuminov, 16 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 ([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 "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.