summaryrefslogtreecommitdiffstats
path: root/src/assistant/lib/qhelpcollectionhandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/assistant/lib/qhelpcollectionhandler.cpp')
-rw-r--r--src/assistant/lib/qhelpcollectionhandler.cpp603
1 files changed, 603 insertions, 0 deletions
diff --git a/src/assistant/lib/qhelpcollectionhandler.cpp b/src/assistant/lib/qhelpcollectionhandler.cpp
new file mode 100644
index 000000000..169d37e05
--- /dev/null
+++ b/src/assistant/lib/qhelpcollectionhandler.cpp
@@ -0,0 +1,603 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhelpcollectionhandler_p.h"
+#include "qhelp_global.h"
+#include "qhelpdbreader_p.h"
+
+#include <QtCore/QFile>
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDebug>
+
+#include <QtSql/QSqlError>
+#include <QtSql/QSqlDriver>
+
+QT_BEGIN_NAMESPACE
+
+QHelpCollectionHandler::QHelpCollectionHandler(const QString &collectionFile, QObject *parent)
+ : QObject(parent)
+ , m_dbOpened(false)
+ , m_collectionFile(collectionFile)
+ , m_connectionName(QString())
+{
+ QFileInfo fi(m_collectionFile);
+ if (!fi.isAbsolute())
+ m_collectionFile = fi.absoluteFilePath();
+ m_query.clear();
+}
+
+QHelpCollectionHandler::~QHelpCollectionHandler()
+{
+ m_query.clear();
+ if (m_dbOpened)
+ QSqlDatabase::removeDatabase(m_connectionName);
+}
+
+bool QHelpCollectionHandler::isDBOpened()
+{
+ if (m_dbOpened)
+ return true;
+ emit error(tr("The collection file '%1' is not set up yet!").
+ arg(m_collectionFile));
+ return false;
+}
+
+QString QHelpCollectionHandler::collectionFile() const
+{
+ return m_collectionFile;
+}
+
+bool QHelpCollectionHandler::openCollectionFile()
+{
+ if (m_dbOpened)
+ return m_dbOpened;
+
+ m_connectionName = QHelpGlobal::uniquifyConnectionName(
+ QLatin1String("QHelpCollectionHandler"), this);
+ bool openingOk = true;
+ {
+ QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"),
+ m_connectionName);
+ if (db.driver()
+ && db.driver()->lastError().type() == QSqlError::ConnectionError) {
+ emit error(tr("Cannot load sqlite database driver!"));
+ return false;
+ }
+
+ db.setDatabaseName(collectionFile());
+ openingOk = db.open();
+ if (openingOk)
+ m_query = QSqlQuery(db);
+ }
+ if (!openingOk) {
+ QSqlDatabase::removeDatabase(m_connectionName);
+ emit error(tr("Cannot open collection file: %1").arg(collectionFile()));
+ return false;
+ }
+
+ m_query.exec(QLatin1String("PRAGMA synchronous=OFF"));
+ m_query.exec(QLatin1String("PRAGMA cache_size=3000"));
+
+ m_query.exec(QLatin1String("SELECT COUNT(*) FROM sqlite_master WHERE TYPE=\'table\'"
+ "AND Name=\'NamespaceTable\'"));
+ m_query.next();
+ if (m_query.value(0).toInt() < 1) {
+ if (!createTables(&m_query)) {
+ emit error(tr("Cannot create tables in file %1!").arg(collectionFile()));
+ return false;
+ }
+ }
+
+ m_dbOpened = true;
+ return m_dbOpened;
+}
+
+bool QHelpCollectionHandler::copyCollectionFile(const QString &fileName)
+{
+ if (!m_dbOpened)
+ return false;
+
+ QFileInfo fi(fileName);
+ if (fi.exists()) {
+ emit error(tr("The collection file '%1' already exists!").
+ arg(fileName));
+ return false;
+ }
+
+ if (!fi.absoluteDir().exists() && !QDir().mkpath(fi.absolutePath())) {
+ emit error(tr("Cannot create directory: %1").arg(fi.absolutePath()));
+ return false;
+ }
+
+ QString colFile = fi.absoluteFilePath();
+ QString connectionName = QHelpGlobal::uniquifyConnectionName(
+ QLatin1String("QHelpCollectionHandlerCopy"), this);
+ QSqlQuery *copyQuery = 0;
+ bool openingOk = true;
+ {
+ QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), connectionName);
+ db.setDatabaseName(colFile);
+ openingOk = db.open();
+ if (openingOk)
+ copyQuery = new QSqlQuery(db);
+ }
+
+ if (!openingOk) {
+ emit error(tr("Cannot open collection file: %1").arg(colFile));
+ return false;
+ }
+
+ copyQuery->exec(QLatin1String("PRAGMA synchronous=OFF"));
+ copyQuery->exec(QLatin1String("PRAGMA cache_size=3000"));
+
+ if (!createTables(copyQuery)) {
+ emit error(tr("Cannot copy collection file: %1").arg(colFile));
+ return false;
+ }
+
+ QString oldBaseDir = QFileInfo(collectionFile()).absolutePath();
+ QString oldFilePath;
+ QFileInfo newColFi(colFile);
+ m_query.exec(QLatin1String("SELECT Name, FilePath FROM NamespaceTable"));
+ while (m_query.next()) {
+ copyQuery->prepare(QLatin1String("INSERT INTO NamespaceTable VALUES(NULL, ?, ?)"));
+ copyQuery->bindValue(0, m_query.value(0).toString());
+ oldFilePath = m_query.value(1).toString();
+ if (!QDir::isAbsolutePath(oldFilePath))
+ oldFilePath = oldBaseDir + QDir::separator() + oldFilePath;
+ copyQuery->bindValue(1, newColFi.absoluteDir().relativeFilePath(oldFilePath));
+ copyQuery->exec();
+ }
+
+ m_query.exec(QLatin1String("SELECT NamespaceId, Name FROM FolderTable"));
+ while (m_query.next()) {
+ copyQuery->prepare(QLatin1String("INSERT INTO FolderTable VALUES(NULL, ?, ?)"));
+ copyQuery->bindValue(0, m_query.value(0).toString());
+ copyQuery->bindValue(1, m_query.value(1).toString());
+ copyQuery->exec();
+ }
+
+ m_query.exec(QLatin1String("SELECT Name FROM FilterAttributeTable"));
+ while (m_query.next()) {
+ copyQuery->prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)"));
+ copyQuery->bindValue(0, m_query.value(0).toString());
+ copyQuery->exec();
+ }
+
+ m_query.exec(QLatin1String("SELECT Name FROM FilterNameTable"));
+ while (m_query.next()) {
+ copyQuery->prepare(QLatin1String("INSERT INTO FilterNameTable VALUES(NULL, ?)"));
+ copyQuery->bindValue(0, m_query.value(0).toString());
+ copyQuery->exec();
+ }
+
+ m_query.exec(QLatin1String("SELECT NameId, FilterAttributeId FROM FilterTable"));
+ while (m_query.next()) {
+ copyQuery->prepare(QLatin1String("INSERT INTO FilterTable VALUES(?, ?)"));
+ copyQuery->bindValue(0, m_query.value(0).toInt());
+ copyQuery->bindValue(1, m_query.value(1).toInt());
+ copyQuery->exec();
+ }
+
+ m_query.exec(QLatin1String("SELECT Key, Value FROM SettingsTable"));
+ while (m_query.next()) {
+ if (m_query.value(0).toString() == QLatin1String("CluceneSearchNamespaces"))
+ continue;
+ copyQuery->prepare(QLatin1String("INSERT INTO SettingsTable VALUES(?, ?)"));
+ copyQuery->bindValue(0, m_query.value(0).toString());
+ copyQuery->bindValue(1, m_query.value(1));
+ copyQuery->exec();
+ }
+
+ copyQuery->clear();
+ delete copyQuery;
+ QSqlDatabase::removeDatabase(connectionName);
+ return true;
+}
+
+bool QHelpCollectionHandler::createTables(QSqlQuery *query)
+{
+ QStringList tables;
+ tables << QLatin1String("CREATE TABLE NamespaceTable ("
+ "Id INTEGER PRIMARY KEY, "
+ "Name TEXT, "
+ "FilePath TEXT )")
+ << QLatin1String("CREATE TABLE FolderTable ("
+ "Id INTEGER PRIMARY KEY, "
+ "NamespaceId INTEGER, "
+ "Name TEXT )")
+ << QLatin1String("CREATE TABLE FilterAttributeTable ("
+ "Id INTEGER PRIMARY KEY, "
+ "Name TEXT )")
+ << QLatin1String("CREATE TABLE FilterNameTable ("
+ "Id INTEGER PRIMARY KEY, "
+ "Name TEXT )")
+ << QLatin1String("CREATE TABLE FilterTable ("
+ "NameId INTEGER, "
+ "FilterAttributeId INTEGER )")
+ << QLatin1String("CREATE TABLE SettingsTable ("
+ "Key TEXT PRIMARY KEY, "
+ "Value BLOB )");
+
+ foreach (const QString &q, tables) {
+ if (!query->exec(q))
+ return false;
+ }
+ return true;
+}
+
+QStringList QHelpCollectionHandler::customFilters() const
+{
+ QStringList list;
+ if (m_dbOpened) {
+ m_query.exec(QLatin1String("SELECT Name FROM FilterNameTable"));
+ while (m_query.next())
+ list.append(m_query.value(0).toString());
+ }
+ return list;
+}
+
+bool QHelpCollectionHandler::removeCustomFilter(const QString &filterName)
+{
+ if (!isDBOpened() || filterName.isEmpty())
+ return false;
+
+ int filterNameId = -1;
+ m_query.prepare(QLatin1String("SELECT Id FROM FilterNameTable WHERE Name=?"));
+ m_query.bindValue(0, filterName);
+ m_query.exec();
+ if (m_query.next())
+ filterNameId = m_query.value(0).toInt();
+
+ if (filterNameId < 0) {
+ emit error(tr("Unknown filter '%1'!").arg(filterName));
+ return false;
+ }
+
+ m_query.prepare(QLatin1String("DELETE FROM FilterTable WHERE NameId=?"));
+ m_query.bindValue(0, filterNameId);
+ m_query.exec();
+
+ m_query.prepare(QLatin1String("DELETE FROM FilterNameTable WHERE Id=?"));
+ m_query.bindValue(0, filterNameId);
+ m_query.exec();
+
+ return true;
+}
+
+bool QHelpCollectionHandler::addCustomFilter(const QString &filterName,
+ const QStringList &attributes)
+{
+ if (!isDBOpened() || filterName.isEmpty())
+ return false;
+
+ int nameId = -1;
+ m_query.prepare(QLatin1String("SELECT Id FROM FilterNameTable WHERE Name=?"));
+ m_query.bindValue(0, filterName);
+ m_query.exec();
+ if (m_query.next())
+ nameId = m_query.value(0).toInt();
+
+ m_query.exec(QLatin1String("SELECT Id, Name FROM FilterAttributeTable"));
+ QStringList idsToInsert = attributes;
+ QMap<QString, int> attributeMap;
+ while (m_query.next()) {
+ attributeMap.insert(m_query.value(1).toString(),
+ m_query.value(0).toInt());
+ if (idsToInsert.contains(m_query.value(1).toString()))
+ idsToInsert.removeAll(m_query.value(1).toString());
+ }
+
+ foreach (const QString &id, idsToInsert) {
+ m_query.prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)"));
+ m_query.bindValue(0, id);
+ m_query.exec();
+ attributeMap.insert(id, m_query.lastInsertId().toInt());
+ }
+
+ if (nameId < 0) {
+ m_query.prepare(QLatin1String("INSERT INTO FilterNameTable VALUES(NULL, ?)"));
+ m_query.bindValue(0, filterName);
+ if (m_query.exec())
+ nameId = m_query.lastInsertId().toInt();
+ }
+
+ if (nameId < 0) {
+ emit error(tr("Cannot register filter %1!").arg(filterName));
+ return false;
+ }
+
+ m_query.prepare(QLatin1String("DELETE FROM FilterTable WHERE NameId=?"));
+ m_query.bindValue(0, nameId);
+ m_query.exec();
+
+ foreach (const QString &att, attributes) {
+ m_query.prepare(QLatin1String("INSERT INTO FilterTable VALUES(?, ?)"));
+ m_query.bindValue(0, nameId);
+ m_query.bindValue(1, attributeMap[att]);
+ if (!m_query.exec())
+ return false;
+ }
+ return true;
+}
+
+QHelpCollectionHandler::DocInfoList QHelpCollectionHandler::registeredDocumentations() const
+{
+ DocInfoList list;
+ if (m_dbOpened) {
+ m_query.exec(QLatin1String("SELECT a.Name, a.FilePath, b.Name "
+ "FROM NamespaceTable a, FolderTable b WHERE a.Id=b.NamespaceId"));
+
+ while (m_query.next()) {
+ DocInfo info;
+ info.fileName = m_query.value(1).toString();
+ info.folderName = m_query.value(2).toString();
+ info.namespaceName = m_query.value(0).toString();
+ list.append(info);
+ }
+ }
+ return list;
+}
+
+bool QHelpCollectionHandler::registerDocumentation(const QString &fileName)
+{
+ if (!isDBOpened())
+ return false;
+
+ QHelpDBReader reader(fileName, QHelpGlobal::uniquifyConnectionName(
+ QLatin1String("QHelpCollectionHandler"), this), 0);
+ if (!reader.init()) {
+ emit error(tr("Cannot open documentation file %1!").arg(fileName));
+ return false;
+ }
+
+ QString ns = reader.namespaceName();
+ if (ns.isEmpty()) {
+ emit error(tr("Invalid documentation file '%1'!").arg(fileName));
+ return false;
+ }
+
+ int nsId = registerNamespace(ns, fileName);
+ if (nsId < 1)
+ return false;
+
+ if (!registerVirtualFolder(reader.virtualFolder(), nsId))
+ return false;
+
+ addFilterAttributes(reader.filterAttributes());
+ foreach (const QString &filterName, reader.customFilters())
+ addCustomFilter(filterName, reader.filterAttributes(filterName));
+
+ optimizeDatabase(fileName);
+
+ return true;
+}
+
+bool QHelpCollectionHandler::unregisterDocumentation(const QString &namespaceName)
+{
+ if (!isDBOpened())
+ return false;
+
+ m_query.prepare(QLatin1String("SELECT Id FROM NamespaceTable WHERE Name=?"));
+ m_query.bindValue(0, namespaceName);
+ m_query.exec();
+
+ int nsId = -1;
+ if (m_query.next())
+ nsId = m_query.value(0).toInt();
+
+ if (nsId < 0) {
+ emit error(tr("The namespace %1 was not registered!").arg(namespaceName));
+ return false;
+ }
+
+ m_query.prepare(QLatin1String("DELETE FROM NamespaceTable WHERE Id=?"));
+ m_query.bindValue(0, nsId);
+ m_query.exec();
+
+ m_query.prepare(QLatin1String("DELETE FROM FolderTable WHERE NamespaceId=?"));
+ m_query.bindValue(0, nsId);
+ return m_query.exec();
+}
+
+bool QHelpCollectionHandler::removeCustomValue(const QString &key)
+{
+ if (!isDBOpened())
+ return false;
+
+ m_query.prepare(QLatin1String("DELETE FROM SettingsTable WHERE Key=?"));
+ m_query.bindValue(0, key);
+ return m_query.exec();
+}
+
+QVariant QHelpCollectionHandler::customValue(const QString &key,
+ const QVariant &defaultValue) const
+{
+ QVariant value = defaultValue;
+ if (m_dbOpened) {
+ m_query.prepare(QLatin1String("SELECT COUNT(Key) FROM SettingsTable WHERE Key=?"));
+ m_query.bindValue(0, key);
+ if (!m_query.exec() || !m_query.next() || !m_query.value(0).toInt()) {
+ m_query.clear();
+ return defaultValue;
+ }
+
+ m_query.clear();
+ m_query.prepare(QLatin1String("SELECT Value FROM SettingsTable WHERE Key=?"));
+ m_query.bindValue(0, key);
+ if (m_query.exec() && m_query.next())
+ value = m_query.value(0);
+ m_query.clear();
+ }
+ return value;
+}
+
+bool QHelpCollectionHandler::setCustomValue(const QString &key,
+ const QVariant &value)
+{
+ if (!isDBOpened())
+ return false;
+
+ m_query.prepare(QLatin1String("SELECT Value FROM SettingsTable WHERE Key=?"));
+ m_query.bindValue(0, key);
+ m_query.exec();
+ if (m_query.next()) {
+ m_query.prepare(QLatin1String("UPDATE SettingsTable SET Value=? where Key=?"));
+ m_query.bindValue(0, value);
+ m_query.bindValue(1, key);
+ }
+ else {
+ m_query.prepare(QLatin1String("INSERT INTO SettingsTable VALUES(?, ?)"));
+ m_query.bindValue(0, key);
+ m_query.bindValue(1, value);
+ }
+ return m_query.exec();
+}
+
+bool QHelpCollectionHandler::addFilterAttributes(const QStringList &attributes)
+{
+ if (!isDBOpened())
+ return false;
+
+ m_query.exec(QLatin1String("SELECT Name FROM FilterAttributeTable"));
+ QSet<QString> atts;
+ while (m_query.next())
+ atts.insert(m_query.value(0).toString());
+
+ foreach (const QString &s, attributes) {
+ if (!atts.contains(s)) {
+ m_query.prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)"));
+ m_query.bindValue(0, s);
+ m_query.exec();
+ }
+ }
+ return true;
+}
+
+QStringList QHelpCollectionHandler::filterAttributes() const
+{
+ QStringList list;
+ if (m_dbOpened) {
+ m_query.exec(QLatin1String("SELECT Name FROM FilterAttributeTable"));
+ while (m_query.next())
+ list.append(m_query.value(0).toString());
+ }
+ return list;
+}
+
+QStringList QHelpCollectionHandler::filterAttributes(const QString &filterName) const
+{
+ QStringList list;
+ if (m_dbOpened) {
+ m_query.prepare(QLatin1String("SELECT a.Name FROM FilterAttributeTable a, "
+ "FilterTable b, FilterNameTable c WHERE a.Id=b.FilterAttributeId "
+ "AND b.NameId=c.Id AND c.Name=?"));
+ m_query.bindValue(0, filterName);
+ m_query.exec();
+ while (m_query.next())
+ list.append(m_query.value(0).toString());
+ }
+ return list;
+}
+
+int QHelpCollectionHandler::registerNamespace(const QString &nspace, const QString &fileName)
+{
+ m_query.prepare(QLatin1String("SELECT COUNT(Id) FROM NamespaceTable WHERE Name=?"));
+ m_query.bindValue(0, nspace);
+ m_query.exec();
+ while (m_query.next()) {
+ if (m_query.value(0).toInt() > 0) {
+ emit error(tr("Namespace %1 already exists!").arg(nspace));
+ return -1;
+ }
+ }
+
+ QFileInfo fi(m_collectionFile);
+ m_query.prepare(QLatin1String("INSERT INTO NamespaceTable VALUES(NULL, ?, ?)"));
+ m_query.bindValue(0, nspace);
+ m_query.bindValue(1, fi.absoluteDir().relativeFilePath(fileName));
+ int namespaceId = -1;
+ if (m_query.exec())
+ namespaceId = m_query.lastInsertId().toInt();
+ if (namespaceId < 1) {
+ emit error(tr("Cannot register namespace '%1'!").arg(nspace));
+ return -1;
+ }
+ return namespaceId;
+}
+
+bool QHelpCollectionHandler::registerVirtualFolder(const QString &folderName, int namespaceId)
+{
+ m_query.prepare(QLatin1String("INSERT INTO FolderTable VALUES(NULL, ?, ?)"));
+ m_query.bindValue(0, namespaceId);
+ m_query.bindValue(1, folderName);
+ return m_query.exec();
+}
+
+void QHelpCollectionHandler::optimizeDatabase(const QString &fileName)
+{
+ if (!QFile::exists(fileName))
+ return;
+
+ { // according to removeDatabase() documentation
+ QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), QLatin1String("optimize"));
+ db.setDatabaseName(fileName);
+ if (!db.open()) {
+ QSqlDatabase::removeDatabase(QLatin1String("optimize"));
+ emit error(tr("Cannot open database '%1' to optimize!").arg(fileName));
+ return;
+ }
+
+ QSqlQuery query(db);
+ db.exec(QLatin1String("PRAGMA synchronous=OFF"));
+ db.exec(QLatin1String("PRAGMA cache_size=3000"));
+ db.exec(QLatin1String("CREATE INDEX IF NOT EXISTS NameIndex ON IndexTable(Name)"));
+ db.exec(QLatin1String("CREATE INDEX IF NOT EXISTS FileNameIndex ON FileNameTable(Name)"));
+ db.exec(QLatin1String("CREATE INDEX IF NOT EXISTS FileIdIndex ON FileNameTable(FileId)"));
+
+ db.close();
+ }
+
+ QSqlDatabase::removeDatabase(QLatin1String("optimize"));
+}
+
+QT_END_NAMESPACE