summaryrefslogtreecommitdiffstats
path: root/src/assistant/lib/qhelpcontentwidget.cpp
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit50123887ba0f33cf47520bee7c419d68742af2d1 (patch)
tree0eb8679b9e4e4370e59b44bfdcae616816e39aca /src/assistant/lib/qhelpcontentwidget.cpp
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'src/assistant/lib/qhelpcontentwidget.cpp')
-rw-r--r--src/assistant/lib/qhelpcontentwidget.cpp586
1 files changed, 586 insertions, 0 deletions
diff --git a/src/assistant/lib/qhelpcontentwidget.cpp b/src/assistant/lib/qhelpcontentwidget.cpp
new file mode 100644
index 000000000..988a909e0
--- /dev/null
+++ b/src/assistant/lib/qhelpcontentwidget.cpp
@@ -0,0 +1,586 @@
+/****************************************************************************
+**
+** 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 "qhelpcontentwidget.h"
+#include "qhelpenginecore.h"
+#include "qhelpengine_p.h"
+#include "qhelpdbreader_p.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QStack>
+#include <QtCore/QThread>
+#include <QtCore/QMutex>
+#include <QtGui/QHeaderView>
+
+QT_BEGIN_NAMESPACE
+
+class QHelpContentItemPrivate
+{
+public:
+ QHelpContentItemPrivate(const QString &t, const QString &l,
+ QHelpDBReader *r, QHelpContentItem *p)
+ {
+ parent = p;
+ title = t;
+ link = l;
+ helpDBReader = r;
+ }
+
+ QList<QHelpContentItem*> childItems;
+ QHelpContentItem *parent;
+ QString title;
+ QString link;
+ QHelpDBReader *helpDBReader;
+};
+
+class QHelpContentProvider : public QThread
+{
+public:
+ QHelpContentProvider(QHelpEnginePrivate *helpEngine);
+ ~QHelpContentProvider();
+ void collectContents(const QString &customFilterName);
+ void stopCollecting();
+ QHelpContentItem *rootItem();
+ int nextChildCount() const;
+
+private:
+ void run();
+
+ QHelpEnginePrivate *m_helpEngine;
+ QHelpContentItem *m_rootItem;
+ QStringList m_filterAttributes;
+ QQueue<QHelpContentItem*> m_rootItems;
+ QMutex m_mutex;
+ bool m_abort;
+};
+
+class QHelpContentModelPrivate
+{
+public:
+ QHelpContentItem *rootItem;
+ QHelpContentProvider *qhelpContentProvider;
+};
+
+
+
+/*!
+ \class QHelpContentItem
+ \inmodule QtHelp
+ \brief The QHelpContentItem class provides an item for use with QHelpContentModel.
+ \since 4.4
+*/
+
+QHelpContentItem::QHelpContentItem(const QString &name, const QString &link,
+ QHelpDBReader *reader, QHelpContentItem *parent)
+{
+ d = new QHelpContentItemPrivate(name, link, reader, parent);
+}
+
+/*!
+ Destroys the help content item.
+*/
+QHelpContentItem::~QHelpContentItem()
+{
+ qDeleteAll(d->childItems);
+ delete d;
+}
+
+void QHelpContentItem::appendChild(QHelpContentItem *item)
+{
+ d->childItems.append(item);
+}
+
+/*!
+ Returns the child of the content item in the give \a row.
+
+ \sa parent()
+*/
+QHelpContentItem *QHelpContentItem::child(int row) const
+{
+ if (row >= childCount())
+ return 0;
+ return d->childItems.value(row);
+}
+
+/*!
+ Returns the number of child items.
+*/
+int QHelpContentItem::childCount() const
+{
+ return d->childItems.count();
+}
+
+/*!
+ Returns the row of this item from its parents view.
+*/
+int QHelpContentItem::row() const
+{
+ if (d->parent)
+ return d->parent->d->childItems.indexOf(const_cast<QHelpContentItem*>(this));
+ return 0;
+}
+
+/*!
+ Returns the title of the content item.
+*/
+QString QHelpContentItem::title() const
+{
+ return d->title;
+}
+
+/*!
+ Returns the URL of this content item.
+*/
+QUrl QHelpContentItem::url() const
+{
+ return d->helpDBReader->urlOfPath(d->link);
+}
+
+/*!
+ Returns the parent content item.
+*/
+QHelpContentItem *QHelpContentItem::parent() const
+{
+ return d->parent;
+}
+
+/*!
+ Returns the position of a given \a child.
+*/
+int QHelpContentItem::childPosition(QHelpContentItem *child) const
+{
+ return d->childItems.indexOf(child);
+}
+
+
+
+QHelpContentProvider::QHelpContentProvider(QHelpEnginePrivate *helpEngine)
+ : QThread(helpEngine)
+{
+ m_helpEngine = helpEngine;
+ m_rootItem = 0;
+ m_abort = false;
+}
+
+QHelpContentProvider::~QHelpContentProvider()
+{
+ stopCollecting();
+}
+
+void QHelpContentProvider::collectContents(const QString &customFilterName)
+{
+ m_mutex.lock();
+ m_filterAttributes = m_helpEngine->q->filterAttributes(customFilterName);
+ m_mutex.unlock();
+ if (!isRunning()) {
+ start(LowPriority);
+ } else {
+ stopCollecting();
+ start(LowPriority);
+ }
+}
+
+void QHelpContentProvider::stopCollecting()
+{
+ if (!isRunning())
+ return;
+ m_mutex.lock();
+ m_abort = true;
+ m_mutex.unlock();
+ wait();
+}
+
+QHelpContentItem *QHelpContentProvider::rootItem()
+{
+ QMutexLocker locker(&m_mutex);
+ return m_rootItems.dequeue();
+}
+
+int QHelpContentProvider::nextChildCount() const
+{
+ return m_rootItems.head()->childCount();
+}
+
+void QHelpContentProvider::run()
+{
+ QString title;
+ QString link;
+ int depth = 0;
+ QHelpContentItem *item = 0;
+
+ m_mutex.lock();
+ m_rootItem = new QHelpContentItem(QString(), QString(), 0);
+ m_rootItems.enqueue(m_rootItem);
+ QStringList atts = m_filterAttributes;
+ const QStringList fileNames = m_helpEngine->orderedFileNameList;
+ m_mutex.unlock();
+
+ foreach (const QString &dbFileName, fileNames) {
+ m_mutex.lock();
+ if (m_abort) {
+ m_abort = false;
+ m_mutex.unlock();
+ break;
+ }
+ m_mutex.unlock();
+ QHelpDBReader reader(dbFileName,
+ QHelpGlobal::uniquifyConnectionName(dbFileName +
+ QLatin1String("FromQHelpContentProvider"),
+ QThread::currentThread()), 0);
+ if (!reader.init())
+ continue;
+ foreach (const QByteArray& ba, reader.contentsForFilter(atts)) {
+ if (ba.size() < 1)
+ continue;
+
+ int _depth = 0;
+ bool _root = false;
+ QStack<QHelpContentItem*> stack;
+
+ QDataStream s(ba);
+ for (;;) {
+ s >> depth;
+ s >> link;
+ s >> title;
+ if (title.isEmpty())
+ break;
+CHECK_DEPTH:
+ if (depth == 0) {
+ m_mutex.lock();
+ item = new QHelpContentItem(title, link,
+ m_helpEngine->fileNameReaderMap.value(dbFileName), m_rootItem);
+ m_rootItem->appendChild(item);
+ m_mutex.unlock();
+ stack.push(item);
+ _depth = 1;
+ _root = true;
+ } else {
+ if (depth > _depth && _root) {
+ _depth = depth;
+ stack.push(item);
+ }
+ if (depth == _depth) {
+ item = new QHelpContentItem(title, link,
+ m_helpEngine->fileNameReaderMap.value(dbFileName), stack.top());
+ stack.top()->appendChild(item);
+ } else if (depth < _depth) {
+ stack.pop();
+ --_depth;
+ goto CHECK_DEPTH;
+ }
+ }
+ }
+ }
+ }
+ m_mutex.lock();
+ m_abort = false;
+ m_mutex.unlock();
+}
+
+
+
+/*!
+ \class QHelpContentModel
+ \inmodule QtHelp
+ \brief The QHelpContentModel class provides a model that supplies content to views.
+ \since 4.4
+*/
+
+/*!
+ \fn void QHelpContentModel::contentsCreationStarted()
+
+ This signal is emitted when the creation of the contents has
+ started. The current contents are invalid from this point on
+ until the signal contentsCreated() is emitted.
+
+ \sa isCreatingContents()
+*/
+
+/*!
+ \fn void QHelpContentModel::contentsCreated()
+
+ This signal is emitted when the contents have been created.
+*/
+
+QHelpContentModel::QHelpContentModel(QHelpEnginePrivate *helpEngine)
+ : QAbstractItemModel(helpEngine)
+{
+ d = new QHelpContentModelPrivate();
+ d->rootItem = 0;
+ d->qhelpContentProvider = new QHelpContentProvider(helpEngine);
+
+ connect(d->qhelpContentProvider, SIGNAL(finished()),
+ this, SLOT(insertContents()), Qt::QueuedConnection);
+ connect(helpEngine->q, SIGNAL(setupStarted()), this, SLOT(invalidateContents()));
+}
+
+/*!
+ Destroys the help content model.
+*/
+QHelpContentModel::~QHelpContentModel()
+{
+ delete d->rootItem;
+ delete d;
+}
+
+void QHelpContentModel::invalidateContents(bool onShutDown)
+{
+ if (onShutDown)
+ disconnect(this, SLOT(insertContents()));
+ d->qhelpContentProvider->stopCollecting();
+ if (d->rootItem) {
+ delete d->rootItem;
+ d->rootItem = 0;
+ }
+ if (!onShutDown)
+ reset();
+}
+
+/*!
+ Creates new contents by querying the help system
+ for contents specified for the \a customFilterName.
+*/
+void QHelpContentModel::createContents(const QString &customFilterName)
+{
+ d->qhelpContentProvider->collectContents(customFilterName);
+ emit contentsCreationStarted();
+}
+
+void QHelpContentModel::insertContents()
+{
+ int count;
+ if (d->rootItem) {
+ count = d->rootItem->childCount() - 1;
+ beginRemoveRows(QModelIndex(), 0, count > 0 ? count : 0);
+ delete d->rootItem;
+ d->rootItem = 0;
+ endRemoveRows();
+ }
+
+ count = d->qhelpContentProvider->nextChildCount() - 1;
+ beginInsertRows(QModelIndex(), 0, count > 0 ? count : 0);
+ d->rootItem = d->qhelpContentProvider->rootItem();
+ endInsertRows();
+ reset();
+ emit contentsCreated();
+}
+
+/*!
+ Returns true if the contents are currently rebuilt, otherwise
+ false.
+*/
+bool QHelpContentModel::isCreatingContents() const
+{
+ return d->qhelpContentProvider->isRunning();
+}
+
+/*!
+ Returns the help content item at the model index position
+ \a index.
+*/
+QHelpContentItem *QHelpContentModel::contentItemAt(const QModelIndex &index) const
+{
+ if (index.isValid())
+ return static_cast<QHelpContentItem*>(index.internalPointer());
+ else
+ return d->rootItem;
+}
+
+/*!
+ Returns the index of the item in the model specified by
+ the given \a row, \a column and \a parent index.
+*/
+QModelIndex QHelpContentModel::index(int row, int column, const QModelIndex &parent) const
+{
+ if (!d->rootItem)
+ return QModelIndex();
+
+ QHelpContentItem *parentItem = contentItemAt(parent);
+ QHelpContentItem *item = parentItem->child(row);
+ if (!item)
+ return QModelIndex();
+ return createIndex(row, column, item);
+}
+
+/*!
+ Returns the parent of the model item with the given
+ \a index, or QModelIndex() if it has no parent.
+*/
+QModelIndex QHelpContentModel::parent(const QModelIndex &index) const
+{
+ QHelpContentItem *item = contentItemAt(index);
+ if (!item)
+ return QModelIndex();
+
+ QHelpContentItem *parentItem = static_cast<QHelpContentItem*>(item->parent());
+ if (!parentItem)
+ return QModelIndex();
+
+ QHelpContentItem *grandparentItem = static_cast<QHelpContentItem*>(parentItem->parent());
+ if (!grandparentItem)
+ return QModelIndex();
+
+ int row = grandparentItem->childPosition(parentItem);
+ return createIndex(row, index.column(), parentItem);
+}
+
+/*!
+ Returns the number of rows under the given \a parent.
+*/
+int QHelpContentModel::rowCount(const QModelIndex &parent) const
+{
+ QHelpContentItem *parentItem = contentItemAt(parent);
+ if (!parentItem)
+ return 0;
+ return parentItem->childCount();
+}
+
+/*!
+ Returns the number of columns under the given \a parent. Currently returns always 1.
+*/
+int QHelpContentModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent)
+
+ return 1;
+}
+
+/*!
+ Returns the data stored under the given \a role for
+ the item referred to by the \a index.
+*/
+QVariant QHelpContentModel::data(const QModelIndex &index, int role) const
+{
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ QHelpContentItem *item = contentItemAt(index);
+ if (!item)
+ return QVariant();
+ return item->title();
+}
+
+
+
+/*!
+ \class QHelpContentWidget
+ \inmodule QtHelp
+ \brief The QHelpContentWidget class provides a tree view for displaying help content model items.
+ \since 4.4
+*/
+
+/*!
+ \fn void QHelpContentWidget::linkActivated(const QUrl &link)
+
+ This signal is emitted when a content item is activated and
+ its associated \a link should be shown.
+*/
+
+QHelpContentWidget::QHelpContentWidget()
+ : QTreeView(0)
+{
+ header()->hide();
+ setUniformRowHeights(true);
+ connect(this, SIGNAL(activated(QModelIndex)),
+ this, SLOT(showLink(QModelIndex)));
+}
+
+/*!
+ Returns the index of the content item with the \a link.
+ An invalid index is returned if no such an item exists.
+*/
+QModelIndex QHelpContentWidget::indexOf(const QUrl &link)
+{
+ QHelpContentModel *contentModel =
+ qobject_cast<QHelpContentModel*>(model());
+ if (!contentModel || link.scheme() != QLatin1String("qthelp"))
+ return QModelIndex();
+
+ m_syncIndex = QModelIndex();
+ for (int i=0; i<contentModel->rowCount(); ++i) {
+ QHelpContentItem *itm =
+ contentModel->contentItemAt(contentModel->index(i, 0));
+ if (itm && itm->url().host() == link.host()) {
+ QString path = link.path();
+ if (path.startsWith(QLatin1Char('/')))
+ path = path.mid(1);
+ if (searchContentItem(contentModel, contentModel->index(i, 0), path)) {
+ return m_syncIndex;
+ }
+ }
+ }
+ return QModelIndex();
+}
+
+bool QHelpContentWidget::searchContentItem(QHelpContentModel *model,
+ const QModelIndex &parent, const QString &path)
+{
+ QHelpContentItem *parentItem = model->contentItemAt(parent);
+ if (!parentItem)
+ return false;
+
+ if (QDir::cleanPath(parentItem->url().path()) == path) {
+ m_syncIndex = parent;
+ return true;
+ }
+
+ for (int i=0; i<parentItem->childCount(); ++i) {
+ if (searchContentItem(model, model->index(i, 0, parent), path))
+ return true;
+ }
+ return false;
+}
+
+void QHelpContentWidget::showLink(const QModelIndex &index)
+{
+ QHelpContentModel *contentModel = qobject_cast<QHelpContentModel*>(model());
+ if (!contentModel)
+ return;
+
+ QHelpContentItem *item = contentModel->contentItemAt(index);
+ if (!item)
+ return;
+ QUrl url = item->url();
+ if (url.isValid())
+ emit linkActivated(url);
+}
+
+QT_END_NAMESPACE