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