summaryrefslogtreecommitdiffstats
path: root/src/assistant/tools/assistant
diff options
context:
space:
mode:
Diffstat (limited to 'src/assistant/tools/assistant')
-rw-r--r--src/assistant/tools/assistant/Info_mac.plist18
-rw-r--r--src/assistant/tools/assistant/aboutdialog.cpp184
-rw-r--r--src/assistant/tools/assistant/aboutdialog.h91
-rw-r--r--src/assistant/tools/assistant/assistant.icnsbin0 -> 162568 bytes
-rw-r--r--src/assistant/tools/assistant/assistant.icobin0 -> 355574 bytes
-rw-r--r--src/assistant/tools/assistant/assistant.pro118
-rw-r--r--src/assistant/tools/assistant/assistant.qchbin0 -> 364544 bytes
-rw-r--r--src/assistant/tools/assistant/assistant.qrc5
-rw-r--r--src/assistant/tools/assistant/assistant.rc32
-rw-r--r--src/assistant/tools/assistant/assistant_images.qrc37
-rw-r--r--src/assistant/tools/assistant/bookmarkdialog.cpp237
-rw-r--r--src/assistant/tools/assistant/bookmarkdialog.h89
-rw-r--r--src/assistant/tools/assistant/bookmarkdialog.ui156
-rw-r--r--src/assistant/tools/assistant/bookmarkfiltermodel.cpp321
-rw-r--r--src/assistant/tools/assistant/bookmarkfiltermodel.h118
-rw-r--r--src/assistant/tools/assistant/bookmarkitem.cpp184
-rw-r--r--src/assistant/tools/assistant/bookmarkitem.h91
-rw-r--r--src/assistant/tools/assistant/bookmarkmanager.cpp559
-rw-r--r--src/assistant/tools/assistant/bookmarkmanager.h160
-rw-r--r--src/assistant/tools/assistant/bookmarkmanagerwidget.cpp321
-rw-r--r--src/assistant/tools/assistant/bookmarkmanagerwidget.h103
-rw-r--r--src/assistant/tools/assistant/bookmarkmanagerwidget.ui137
-rw-r--r--src/assistant/tools/assistant/bookmarkmodel.cpp461
-rw-r--r--src/assistant/tools/assistant/bookmarkmodel.h117
-rw-r--r--src/assistant/tools/assistant/bookmarkwidget.ui85
-rw-r--r--src/assistant/tools/assistant/centralwidget.cpp636
-rw-r--r--src/assistant/tools/assistant/centralwidget.h172
-rw-r--r--src/assistant/tools/assistant/cmdlineparser.cpp376
-rw-r--r--src/assistant/tools/assistant/cmdlineparser.h117
-rw-r--r--src/assistant/tools/assistant/contentwindow.cpp204
-rw-r--r--src/assistant/tools/assistant/contentwindow.h86
-rw-r--r--src/assistant/tools/assistant/doc/HOWTO16
-rw-r--r--src/assistant/tools/assistant/doc/assistant.qdoc461
-rw-r--r--src/assistant/tools/assistant/doc/assistant.qdocconf16
-rw-r--r--src/assistant/tools/assistant/doc/assistant.qhp22
-rw-r--r--src/assistant/tools/assistant/doc/classic.css92
-rw-r--r--src/assistant/tools/assistant/doc/images/assistant-address-toolbar.pngbin0 -> 2899 bytes
-rw-r--r--src/assistant/tools/assistant/doc/images/assistant-assistant.pngbin0 -> 205326 bytes
-rw-r--r--src/assistant/tools/assistant/doc/images/assistant-dockwidgets.pngbin0 -> 50554 bytes
-rw-r--r--src/assistant/tools/assistant/doc/images/assistant-docwindow.pngbin0 -> 55582 bytes
-rw-r--r--src/assistant/tools/assistant/doc/images/assistant-examples.pngbin0 -> 9799 bytes
-rw-r--r--src/assistant/tools/assistant/doc/images/assistant-filter-toolbar.pngbin0 -> 1767 bytes
-rw-r--r--src/assistant/tools/assistant/doc/images/assistant-preferences-documentation.pngbin0 -> 13417 bytes
-rw-r--r--src/assistant/tools/assistant/doc/images/assistant-preferences-filters.pngbin0 -> 15561 bytes
-rw-r--r--src/assistant/tools/assistant/doc/images/assistant-preferences-fonts.pngbin0 -> 13139 bytes
-rw-r--r--src/assistant/tools/assistant/doc/images/assistant-preferences-options.pngbin0 -> 14255 bytes
-rw-r--r--src/assistant/tools/assistant/doc/images/assistant-search.pngbin0 -> 59254 bytes
-rw-r--r--src/assistant/tools/assistant/doc/images/assistant-toolbar.pngbin0 -> 6532 bytes
-rw-r--r--src/assistant/tools/assistant/filternamedialog.cpp77
-rw-r--r--src/assistant/tools/assistant/filternamedialog.h67
-rw-r--r--src/assistant/tools/assistant/filternamedialog.ui67
-rw-r--r--src/assistant/tools/assistant/findwidget.cpp234
-rw-r--r--src/assistant/tools/assistant/findwidget.h100
-rw-r--r--src/assistant/tools/assistant/globalactions.cpp246
-rw-r--r--src/assistant/tools/assistant/globalactions.h105
-rw-r--r--src/assistant/tools/assistant/helpenginewrapper.cpp844
-rw-r--r--src/assistant/tools/assistant/helpenginewrapper.h218
-rw-r--r--src/assistant/tools/assistant/helpviewer.cpp221
-rw-r--r--src/assistant/tools/assistant/helpviewer.h158
-rw-r--r--src/assistant/tools/assistant/helpviewer_p.h123
-rw-r--r--src/assistant/tools/assistant/helpviewer_qtb.cpp384
-rw-r--r--src/assistant/tools/assistant/helpviewer_qwv.cpp495
-rw-r--r--src/assistant/tools/assistant/images/assistant-128.pngbin0 -> 6448 bytes
-rw-r--r--src/assistant/tools/assistant/images/assistant.pngbin0 -> 2034 bytes
-rw-r--r--src/assistant/tools/assistant/images/bookmark.pngbin0 -> 1266 bytes
-rw-r--r--src/assistant/tools/assistant/images/closebutton.pngbin0 -> 288 bytes
-rw-r--r--src/assistant/tools/assistant/images/darkclosebutton.pngbin0 -> 319 bytes
-rw-r--r--src/assistant/tools/assistant/images/mac/addtab.pngbin0 -> 469 bytes
-rw-r--r--src/assistant/tools/assistant/images/mac/book.pngbin0 -> 1477 bytes
-rw-r--r--src/assistant/tools/assistant/images/mac/closetab.pngbin0 -> 516 bytes
-rw-r--r--src/assistant/tools/assistant/images/mac/editcopy.pngbin0 -> 1468 bytes
-rw-r--r--src/assistant/tools/assistant/images/mac/find.pngbin0 -> 1836 bytes
-rw-r--r--src/assistant/tools/assistant/images/mac/home.pngbin0 -> 1807 bytes
-rw-r--r--src/assistant/tools/assistant/images/mac/next.pngbin0 -> 1310 bytes
-rw-r--r--src/assistant/tools/assistant/images/mac/previous.pngbin0 -> 1080 bytes
-rw-r--r--src/assistant/tools/assistant/images/mac/print.pngbin0 -> 2087 bytes
-rw-r--r--src/assistant/tools/assistant/images/mac/resetzoom.pngbin0 -> 1567 bytes
-rw-r--r--src/assistant/tools/assistant/images/mac/synctoc.pngbin0 -> 1838 bytes
-rw-r--r--src/assistant/tools/assistant/images/mac/zoomin.pngbin0 -> 1696 bytes
-rw-r--r--src/assistant/tools/assistant/images/mac/zoomout.pngbin0 -> 1662 bytes
-rw-r--r--src/assistant/tools/assistant/images/trolltech-logo.pngbin0 -> 10096 bytes
-rw-r--r--src/assistant/tools/assistant/images/win/addtab.pngbin0 -> 314 bytes
-rw-r--r--src/assistant/tools/assistant/images/win/book.pngbin0 -> 1109 bytes
-rw-r--r--src/assistant/tools/assistant/images/win/closetab.pngbin0 -> 375 bytes
-rw-r--r--src/assistant/tools/assistant/images/win/editcopy.pngbin0 -> 1325 bytes
-rw-r--r--src/assistant/tools/assistant/images/win/find.pngbin0 -> 1944 bytes
-rw-r--r--src/assistant/tools/assistant/images/win/home.pngbin0 -> 1414 bytes
-rw-r--r--src/assistant/tools/assistant/images/win/next.pngbin0 -> 1038 bytes
-rw-r--r--src/assistant/tools/assistant/images/win/previous.pngbin0 -> 898 bytes
-rw-r--r--src/assistant/tools/assistant/images/win/print.pngbin0 -> 1456 bytes
-rw-r--r--src/assistant/tools/assistant/images/win/resetzoom.pngbin0 -> 1134 bytes
-rw-r--r--src/assistant/tools/assistant/images/win/synctoc.pngbin0 -> 1235 bytes
-rw-r--r--src/assistant/tools/assistant/images/win/zoomin.pngbin0 -> 1208 bytes
-rw-r--r--src/assistant/tools/assistant/images/win/zoomout.pngbin0 -> 1226 bytes
-rw-r--r--src/assistant/tools/assistant/images/wrap.pngbin0 -> 500 bytes
-rw-r--r--src/assistant/tools/assistant/indexwindow.cpp231
-rw-r--r--src/assistant/tools/assistant/indexwindow.h90
-rw-r--r--src/assistant/tools/assistant/installdialog.cpp355
-rw-r--r--src/assistant/tools/assistant/installdialog.h105
-rw-r--r--src/assistant/tools/assistant/installdialog.ui118
-rw-r--r--src/assistant/tools/assistant/main.cpp440
-rw-r--r--src/assistant/tools/assistant/mainwindow.cpp1099
-rw-r--r--src/assistant/tools/assistant/mainwindow.h172
-rw-r--r--src/assistant/tools/assistant/openpagesmanager.cpp378
-rw-r--r--src/assistant/tools/assistant/openpagesmanager.h115
-rw-r--r--src/assistant/tools/assistant/openpagesmodel.cpp119
-rw-r--r--src/assistant/tools/assistant/openpagesmodel.h76
-rw-r--r--src/assistant/tools/assistant/openpagesswitcher.cpp194
-rw-r--r--src/assistant/tools/assistant/openpagesswitcher.h85
-rw-r--r--src/assistant/tools/assistant/openpageswidget.cpp237
-rw-r--r--src/assistant/tools/assistant/openpageswidget.h92
-rw-r--r--src/assistant/tools/assistant/preferencesdialog.cpp507
-rw-r--r--src/assistant/tools/assistant/preferencesdialog.h110
-rw-r--r--src/assistant/tools/assistant/preferencesdialog.ui400
-rw-r--r--src/assistant/tools/assistant/qtdocinstaller.cpp128
-rw-r--r--src/assistant/tools/assistant/qtdocinstaller.h84
-rw-r--r--src/assistant/tools/assistant/remotecontrol.cpp388
-rw-r--r--src/assistant/tools/assistant/remotecontrol.h96
-rw-r--r--src/assistant/tools/assistant/remotecontrol_win.h68
-rw-r--r--src/assistant/tools/assistant/searchwidget.cpp237
-rw-r--r--src/assistant/tools/assistant/searchwidget.h90
-rw-r--r--src/assistant/tools/assistant/topicchooser.cpp87
-rw-r--r--src/assistant/tools/assistant/topicchooser.h73
-rw-r--r--src/assistant/tools/assistant/topicchooser.ui116
-rw-r--r--src/assistant/tools/assistant/tracer.h75
-rw-r--r--src/assistant/tools/assistant/xbelsupport.cpp233
-rw-r--r--src/assistant/tools/assistant/xbelsupport.h87
127 files changed, 15846 insertions, 0 deletions
diff --git a/src/assistant/tools/assistant/Info_mac.plist b/src/assistant/tools/assistant/Info_mac.plist
new file mode 100644
index 000000000..76369a1c5
--- /dev/null
+++ b/src/assistant/tools/assistant/Info_mac.plist
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+ <key>CFBundleIconFile</key>
+ <string>@ICON@</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Created by Qt/QMake</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.trolltech.assistant</string>
+ <key>CFBundleExecutable</key>
+ <string>@EXECUTABLE@</string>
+</dict>
+</plist>
diff --git a/src/assistant/tools/assistant/aboutdialog.cpp b/src/assistant/tools/assistant/aboutdialog.cpp
new file mode 100644
index 000000000..b4c390e90
--- /dev/null
+++ b/src/assistant/tools/assistant/aboutdialog.cpp
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** 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 "aboutdialog.h"
+
+#include "helpviewer.h"
+#include "tracer.h"
+
+#include <QtCore/QBuffer>
+
+#include <QtGui/QLabel>
+#include <QtGui/QPushButton>
+#include <QtGui/QLayout>
+#include <QtGui/QApplication>
+#include <QtGui/QDesktopWidget>
+#include <QtGui/QMessageBox>
+#include <QtGui/QDesktopServices>
+
+QT_BEGIN_NAMESPACE
+
+AboutLabel::AboutLabel(QWidget *parent)
+ : QTextBrowser(parent)
+{
+ TRACE_OBJ
+ setFrameStyle(QFrame::NoFrame);
+ QPalette p;
+ p.setColor(QPalette::Base, p.color(QPalette::Background));
+ setPalette(p);
+}
+
+void AboutLabel::setText(const QString &text, const QByteArray &resources)
+{
+ TRACE_OBJ
+ QDataStream in(resources);
+ in >> m_resourceMap;
+
+ QTextBrowser::setText(text);
+}
+
+QSize AboutLabel::minimumSizeHint() const
+{
+ TRACE_OBJ
+ QTextDocument *doc = document();
+ doc->adjustSize();
+ return QSize(int(doc->size().width()), int(doc->size().height()));
+}
+
+QVariant AboutLabel::loadResource(int type, const QUrl &name)
+{
+ TRACE_OBJ
+ if (type == 2 || type == 3) {
+ if (m_resourceMap.contains(name.toString())) {
+ return m_resourceMap.value(name.toString());
+ }
+ }
+ return QVariant();
+}
+
+void AboutLabel::setSource(const QUrl &url)
+{
+ TRACE_OBJ
+ if (url.isValid() && (!HelpViewer::isLocalUrl(url)
+ || !HelpViewer::canOpenPage(url.path()))) {
+ if (!QDesktopServices::openUrl(url)) {
+ QMessageBox::warning(this, tr("Warning"),
+ tr("Unable to launch external application.\n"), tr("OK"));
+ }
+ }
+}
+
+AboutDialog::AboutDialog(QWidget *parent)
+ : QDialog(parent, Qt::MSWindowsFixedSizeDialogHint |
+ Qt::WindowTitleHint|Qt::WindowSystemMenuHint)
+{
+ TRACE_OBJ
+ m_pixmapLabel = 0;
+ m_aboutLabel = new AboutLabel();
+
+ m_closeButton = new QPushButton();
+ m_closeButton->setText(tr("&Close"));
+ connect(m_closeButton, SIGNAL(clicked()), this, SLOT(close()));
+
+ m_layout = new QGridLayout(this);
+ m_layout->addWidget(m_aboutLabel, 1, 0, 1, -1);
+ m_layout->addItem(new QSpacerItem(20, 10, QSizePolicy::Minimum,
+ QSizePolicy::Fixed), 2, 1, 1, 1);
+ m_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding), 3, 0, 1, 1);
+ m_layout->addWidget(m_closeButton, 3, 1, 1, 1);
+ m_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding), 3, 2, 1, 1);
+}
+
+void AboutDialog::setText(const QString &text, const QByteArray &resources)
+{
+ TRACE_OBJ
+ m_aboutLabel->setText(text, resources);
+ updateSize();
+}
+
+void AboutDialog::setPixmap(const QPixmap &pixmap)
+{
+ TRACE_OBJ
+ if (!m_pixmapLabel) {
+ m_pixmapLabel = new QLabel();
+ m_layout->addWidget(m_pixmapLabel, 0, 0, 1, -1, Qt::AlignCenter);
+ }
+ m_pixmapLabel->setPixmap(pixmap);
+ updateSize();
+}
+
+QString AboutDialog::documentTitle() const
+{
+ TRACE_OBJ
+ return m_aboutLabel->documentTitle();
+}
+
+void AboutDialog::updateSize()
+{
+ TRACE_OBJ
+ QSize screenSize = QApplication::desktop()->availableGeometry(QCursor::pos())
+ .size();
+ int limit = qMin(screenSize.width()/2, 500);
+
+#ifdef Q_WS_MAC
+ limit = qMin(screenSize.width()/2, 420);
+#endif
+
+ layout()->activate();
+ int width = layout()->totalMinimumSize().width();
+
+ if (width > limit)
+ width = limit;
+
+ QFontMetrics fm(qApp->font("QWorkspaceTitleBar"));
+ int windowTitleWidth = qMin(fm.width(windowTitle()) + 50, limit);
+ if (windowTitleWidth > width)
+ width = windowTitleWidth;
+
+ layout()->activate();
+ int height = (layout()->hasHeightForWidth())
+ ? layout()->totalHeightForWidth(width)
+ : layout()->totalMinimumSize().height();
+ setFixedSize(width, height);
+ QCoreApplication::removePostedEvents(this, QEvent::LayoutRequest);
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/aboutdialog.h b/src/assistant/tools/assistant/aboutdialog.h
new file mode 100644
index 000000000..292312d05
--- /dev/null
+++ b/src/assistant/tools/assistant/aboutdialog.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef ABOUTDIALOG_H
+#define ABOUTDIALOG_H
+
+#include <QtGui/QTextBrowser>
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class QLabel;
+class QPushButton;
+class QGridLayout;
+
+class AboutLabel : public QTextBrowser
+{
+ Q_OBJECT
+
+public:
+ AboutLabel(QWidget *parent = 0);
+ void setText(const QString &text, const QByteArray &resources);
+ QSize minimumSizeHint() const;
+
+private:
+ QVariant loadResource(int type, const QUrl &name);
+ void setSource(const QUrl &url);
+
+ QMap<QString, QByteArray> m_resourceMap;
+};
+
+class AboutDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ AboutDialog(QWidget *parent = 0);
+ void setText(const QString &text, const QByteArray &resources);
+ void setPixmap(const QPixmap &pixmap);
+ QString documentTitle() const;
+
+private:
+ void updateSize();
+
+ QLabel *m_pixmapLabel;
+ AboutLabel *m_aboutLabel;
+ QPushButton *m_closeButton;
+ QGridLayout *m_layout;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/assistant/tools/assistant/assistant.icns b/src/assistant/tools/assistant/assistant.icns
new file mode 100644
index 000000000..6291dd397
--- /dev/null
+++ b/src/assistant/tools/assistant/assistant.icns
Binary files differ
diff --git a/src/assistant/tools/assistant/assistant.ico b/src/assistant/tools/assistant/assistant.ico
new file mode 100644
index 000000000..9e1b83f1b
--- /dev/null
+++ b/src/assistant/tools/assistant/assistant.ico
Binary files differ
diff --git a/src/assistant/tools/assistant/assistant.pro b/src/assistant/tools/assistant/assistant.pro
new file mode 100644
index 000000000..7f0fdd158
--- /dev/null
+++ b/src/assistant/tools/assistant/assistant.pro
@@ -0,0 +1,118 @@
+include(../../../shared/fontpanel/fontpanel.pri)
+TEMPLATE = app
+LANGUAGE = C++
+TARGET = assistant
+contains(QT_CONFIG, webkit):QT += webkit
+CONFIG += qt \
+ warn_on \
+ help
+QT += network
+PROJECTNAME = Assistant
+DESTDIR = ../../../../bin
+target.path = $$[QT_INSTALL_BINS]
+INSTALLS += target
+DEPENDPATH += ../shared
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# ## Work around a qmake issue when statically linking to
+# ## not-yet-installed plugins
+QMAKE_LIBDIR += $$QT_BUILD_TREE/plugins/sqldrivers
+HEADERS += aboutdialog.h \
+ bookmarkdialog.h \
+ bookmarkfiltermodel.h \
+ bookmarkitem.h \
+ bookmarkmanager.h \
+ bookmarkmanagerwidget.h \
+ bookmarkmodel.h \
+ centralwidget.h \
+ cmdlineparser.h \
+ contentwindow.h \
+ findwidget.h \
+ filternamedialog.h \
+ helpenginewrapper.h \
+ helpviewer.h \
+ helpviewer_p.h \
+ indexwindow.h \
+ installdialog.h \
+ mainwindow.h \
+ preferencesdialog.h \
+ qtdocinstaller.h \
+ remotecontrol.h \
+ searchwidget.h \
+ topicchooser.h \
+ tracer.h \
+ xbelsupport.h \
+ ../shared/collectionconfiguration.h \
+ openpagesmodel.h \
+ globalactions.h \
+ openpageswidget.h \
+ openpagesmanager.h \
+ openpagesswitcher.h
+win32:HEADERS += remotecontrol_win.h
+
+SOURCES += aboutdialog.cpp \
+ bookmarkdialog.cpp \
+ bookmarkfiltermodel.cpp \
+ bookmarkitem.cpp \
+ bookmarkmanager.cpp \
+ bookmarkmanagerwidget.cpp \
+ bookmarkmodel.cpp \
+ centralwidget.cpp \
+ cmdlineparser.cpp \
+ contentwindow.cpp \
+ findwidget.cpp \
+ filternamedialog.cpp \
+ helpenginewrapper.cpp \
+ helpviewer.cpp \
+ indexwindow.cpp \
+ installdialog.cpp \
+ main.cpp \
+ mainwindow.cpp \
+ preferencesdialog.cpp \
+ qtdocinstaller.cpp \
+ remotecontrol.cpp \
+ searchwidget.cpp \
+ topicchooser.cpp \
+ xbelsupport.cpp \
+ ../shared/collectionconfiguration.cpp \
+ openpagesmodel.cpp \
+ globalactions.cpp \
+ openpageswidget.cpp \
+ openpagesmanager.cpp \
+ openpagesswitcher.cpp
+contains(QT_CONFIG, webkit) {
+ SOURCES += helpviewer_qwv.cpp
+} else {
+ SOURCES += helpviewer_qtb.cpp
+}
+
+FORMS += bookmarkdialog.ui \
+ bookmarkmanagerwidget.ui \
+ bookmarkwidget.ui \
+ filternamedialog.ui \
+ installdialog.ui \
+ preferencesdialog.ui \
+ topicchooser.ui
+
+RESOURCES += assistant.qrc \
+ assistant_images.qrc
+
+win32 {
+ !wince*:LIBS += -lshell32
+ RC_FILE = assistant.rc
+}
+
+mac {
+ ICON = assistant.icns
+ TARGET = Assistant
+ QMAKE_INFO_PLIST = Info_mac.plist
+}
+
+contains(CONFIG, static): {
+ SQLPLUGINS = $$unique(sql-plugins)
+ contains(SQLPLUGINS, sqlite): {
+ QTPLUGIN += qsqlite
+ DEFINES += USE_STATIC_SQLITE_PLUGIN
+ }
+}
diff --git a/src/assistant/tools/assistant/assistant.qch b/src/assistant/tools/assistant/assistant.qch
new file mode 100644
index 000000000..e6d52997b
--- /dev/null
+++ b/src/assistant/tools/assistant/assistant.qch
Binary files differ
diff --git a/src/assistant/tools/assistant/assistant.qrc b/src/assistant/tools/assistant/assistant.qrc
new file mode 100644
index 000000000..dddf1be75
--- /dev/null
+++ b/src/assistant/tools/assistant/assistant.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/trolltech/assistant" >
+ <file>assistant.qch</file>
+ </qresource>
+</RCC>
diff --git a/src/assistant/tools/assistant/assistant.rc b/src/assistant/tools/assistant/assistant.rc
new file mode 100644
index 000000000..b1bf97b5c
--- /dev/null
+++ b/src/assistant/tools/assistant/assistant.rc
@@ -0,0 +1,32 @@
+#include "winver.h"
+
+IDI_ICON1 ICON DISCARDABLE "assistant.ico"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,0
+ PRODUCTVERSION 1,0,0,0
+ FILEFLAGS 0x0L
+ FILEFLAGSMASK 0x3fL
+ FILEOS 0x00040004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "CompanyName", "Nokia Corporation and/or its subsidiary(-ies)"
+ VALUE "FileDescription", "Qt Assistant"
+ VALUE "FileVersion", "1.0.0.0"
+ VALUE "LegalCopyright", "Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)."
+ VALUE "InternalName", "assistant.exe"
+ VALUE "OriginalFilename", "assistant.exe"
+ VALUE "ProductName", "Qt Assistant"
+ VALUE "ProductVersion", "1.0.0.0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
diff --git a/src/assistant/tools/assistant/assistant_images.qrc b/src/assistant/tools/assistant/assistant_images.qrc
new file mode 100644
index 000000000..b4f25236d
--- /dev/null
+++ b/src/assistant/tools/assistant/assistant_images.qrc
@@ -0,0 +1,37 @@
+<RCC>
+ <qresource prefix="/trolltech/assistant">
+ <file>images/trolltech-logo.png</file>
+ <file>images/assistant-128.png</file>
+ <file>images/assistant.png</file>
+ <file>images/wrap.png</file>
+ <file>images/bookmark.png</file>
+ <file>images/mac/addtab.png</file>
+ <file>images/mac/book.png</file>
+ <file>images/mac/closetab.png</file>
+ <file>images/mac/editcopy.png</file>
+ <file>images/mac/find.png</file>
+ <file>images/mac/home.png</file>
+ <file>images/mac/next.png</file>
+ <file>images/mac/previous.png</file>
+ <file>images/mac/print.png</file>
+ <file>images/mac/synctoc.png</file>
+ <file>images/mac/zoomin.png</file>
+ <file>images/mac/zoomout.png</file>
+ <file>images/mac/resetzoom.png</file>
+ <file>images/win/addtab.png</file>
+ <file>images/win/book.png</file>
+ <file>images/win/closetab.png</file>
+ <file>images/win/editcopy.png</file>
+ <file>images/win/find.png</file>
+ <file>images/win/home.png</file>
+ <file>images/win/next.png</file>
+ <file>images/win/previous.png</file>
+ <file>images/win/print.png</file>
+ <file>images/win/synctoc.png</file>
+ <file>images/win/zoomin.png</file>
+ <file>images/win/zoomout.png</file>
+ <file>images/win/resetzoom.png</file>
+ <file>images/closebutton.png</file>
+ <file>images/darkclosebutton.png</file>
+ </qresource>
+</RCC>
diff --git a/src/assistant/tools/assistant/bookmarkdialog.cpp b/src/assistant/tools/assistant/bookmarkdialog.cpp
new file mode 100644
index 000000000..d2f88f968
--- /dev/null
+++ b/src/assistant/tools/assistant/bookmarkdialog.cpp
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** 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 "bookmarkdialog.h"
+#include "bookmarkfiltermodel.h"
+#include "bookmarkitem.h"
+#include "bookmarkmodel.h"
+#include "helpenginewrapper.h"
+#include "tracer.h"
+
+#include <QtGui/QKeyEvent>
+#include <QtGui/QMenu>
+
+QT_BEGIN_NAMESPACE
+
+BookmarkDialog::BookmarkDialog(BookmarkModel *sourceModel, const QString &title,
+ const QString &url, QWidget *parent)
+ : QDialog(parent)
+ , m_url(url)
+ , m_title(title)
+ , bookmarkModel(sourceModel)
+{
+ TRACE_OBJ
+ ui.setupUi(this);
+
+ ui.bookmarkEdit->setText(m_title);
+ ui.newFolderButton->setVisible(false);
+ ui.buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
+
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(accepted()));
+ connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(rejected()));
+ connect(ui.newFolderButton, SIGNAL(clicked()), this, SLOT(addFolder()));
+ connect(ui.toolButton, SIGNAL(clicked()), this, SLOT(toolButtonClicked()));
+ connect(ui.bookmarkEdit, SIGNAL(textChanged(QString)), this,
+ SLOT(textChanged(QString)));
+
+ bookmarkProxyModel = new BookmarkFilterModel(this);
+ bookmarkProxyModel->setSourceModel(bookmarkModel);
+ ui.bookmarkFolders->setModel(bookmarkProxyModel);
+ connect(ui.bookmarkFolders, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(currentIndexChanged(int)));
+
+ bookmarkTreeModel = new BookmarkTreeModel(this);
+ bookmarkTreeModel->setSourceModel(bookmarkModel);
+ ui.treeView->setModel(bookmarkTreeModel);
+
+ ui.treeView->expandAll();
+ ui.treeView->setVisible(false);
+ ui.treeView->installEventFilter(this);
+ ui.treeView->viewport()->installEventFilter(this);
+ ui.treeView->setContextMenuPolicy(Qt::CustomContextMenu);
+
+ connect(ui.treeView, SIGNAL(customContextMenuRequested(QPoint)), this,
+ SLOT(customContextMenuRequested(QPoint)));
+ connect(ui.treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,
+ QModelIndex)), this, SLOT(currentIndexChanged(QModelIndex)));
+
+ ui.bookmarkFolders->setCurrentIndex(0);
+ ui.treeView->setCurrentIndex(ui.treeView->indexAt(QPoint(2, 2)));
+
+ const HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance();
+ if (helpEngine.usesAppFont())
+ setFont(helpEngine.appFont());
+}
+
+BookmarkDialog::~BookmarkDialog()
+{
+ TRACE_OBJ
+}
+
+bool BookmarkDialog::isRootItem(const QModelIndex &index) const
+{
+ return !bookmarkTreeModel->parent(index).isValid();
+}
+
+bool BookmarkDialog::eventFilter(QObject *object, QEvent *event)
+{
+ TRACE_OBJ
+ if (object != ui.treeView && object != ui.treeView->viewport())
+ return QWidget::eventFilter(object, event);
+
+ if (event->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(event);
+ switch (ke->key()) {
+ case Qt::Key_F2: {
+ const QModelIndex &index = ui.treeView->currentIndex();
+ if (!isRootItem(index)) {
+ bookmarkModel->setItemsEditable(true);
+ ui.treeView->edit(index);
+ bookmarkModel->setItemsEditable(false);
+ }
+ } break;
+ default: break;
+ }
+ }
+
+ return QObject::eventFilter(object, event);
+}
+
+void BookmarkDialog::currentIndexChanged(int row)
+{
+ TRACE_OBJ
+ QModelIndex next = bookmarkProxyModel->index(row, 0, QModelIndex());
+ if (next.isValid()) {
+ next = bookmarkProxyModel->mapToSource(next);
+ ui.treeView->setCurrentIndex(bookmarkTreeModel->mapFromSource(next));
+ }
+}
+
+void BookmarkDialog::currentIndexChanged(const QModelIndex &index)
+{
+ TRACE_OBJ
+ const QModelIndex current = bookmarkTreeModel->mapToSource(index);
+ if (current.isValid()) {
+ const int row = bookmarkProxyModel->mapFromSource(current).row();
+ ui.bookmarkFolders->setCurrentIndex(row);
+ }
+}
+
+void BookmarkDialog::accepted()
+{
+ TRACE_OBJ
+ QModelIndex index = ui.treeView->currentIndex();
+ if (index.isValid()) {
+ index = bookmarkModel->addItem(bookmarkTreeModel->mapToSource(index));
+ bookmarkModel->setData(index, DataVector() << m_title << m_url << false);
+ } else
+ rejected();
+
+ accept();
+}
+
+void BookmarkDialog::rejected()
+{
+ TRACE_OBJ
+ foreach (const QPersistentModelIndex &index, cache)
+ bookmarkModel->removeItem(index);
+ reject();
+}
+
+void BookmarkDialog::addFolder()
+{
+ TRACE_OBJ
+ QModelIndex index = ui.treeView->currentIndex();
+ if (index.isValid()) {
+ index = bookmarkModel->addItem(bookmarkTreeModel->mapToSource(index),
+ true);
+ cache.append(index);
+
+ index = bookmarkTreeModel->mapFromSource(index);
+ if (index.isValid()) {
+ bookmarkModel->setItemsEditable(true);
+ ui.treeView->edit(index);
+ ui.treeView->expand(index);
+ ui.treeView->setCurrentIndex(index);
+ bookmarkModel->setItemsEditable(false);
+ }
+ }
+}
+
+void BookmarkDialog::toolButtonClicked()
+{
+ TRACE_OBJ
+ const bool visible = !ui.treeView->isVisible();
+ ui.treeView->setVisible(visible);
+ ui.newFolderButton->setVisible(visible);
+
+ if (visible) {
+ resize(QSize(width(), 400));
+ ui.toolButton->setText(QLatin1String("-"));
+ } else {
+ resize(width(), minimumHeight());
+ ui.toolButton->setText(QLatin1String("+"));
+ }
+}
+
+void BookmarkDialog::textChanged(const QString& text)
+{
+ m_title = text;
+}
+
+void BookmarkDialog::customContextMenuRequested(const QPoint &point)
+{
+ TRACE_OBJ
+ const QModelIndex &index = ui.treeView->currentIndex();
+ if (isRootItem(index))
+ return; // check if we go to rename the "Bookmarks Menu", bail
+
+ QMenu menu(QLatin1String(""), this);
+ QAction *renameItem = menu.addAction(tr("Rename Folder"));
+
+ QAction *picked = menu.exec(ui.treeView->mapToGlobal(point));
+ if (picked == renameItem) {
+ bookmarkModel->setItemsEditable(true);
+ ui.treeView->edit(index);
+ bookmarkModel->setItemsEditable(false);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/bookmarkdialog.h b/src/assistant/tools/assistant/bookmarkdialog.h
new file mode 100644
index 000000000..dfa65bbf8
--- /dev/null
+++ b/src/assistant/tools/assistant/bookmarkdialog.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+#ifndef BOOKMARKDIALOG_H
+#define BOOKMARKDIALOG_H
+
+#include "ui_bookmarkdialog.h"
+
+QT_BEGIN_NAMESPACE
+
+class BookmarkModel;
+class BookmarkFilterModel;
+class BookmarkTreeModel;
+
+class BookmarkDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ BookmarkDialog(BookmarkModel *bookmarkModel, const QString &title,
+ const QString &url, QWidget *parent = 0);
+ ~BookmarkDialog();
+
+private:
+ bool isRootItem(const QModelIndex &index) const;
+ bool eventFilter(QObject *object, QEvent *event);
+
+private slots:
+ void currentIndexChanged(int index);
+ void currentIndexChanged(const QModelIndex &index);
+
+ void accepted();
+ void rejected();
+
+ void addFolder();
+ void toolButtonClicked();
+ void textChanged(const QString& text);
+ void customContextMenuRequested(const QPoint &point);
+
+private:
+ QString m_url;
+ QString m_title;
+ Ui::BookmarkDialog ui;
+ QList<QPersistentModelIndex> cache;
+
+ BookmarkModel *bookmarkModel;
+ BookmarkTreeModel *bookmarkTreeModel;
+ BookmarkFilterModel *bookmarkProxyModel;
+};
+
+QT_END_NAMESPACE
+
+#endif // BOOKMARKDIALOG_H
diff --git a/src/assistant/tools/assistant/bookmarkdialog.ui b/src/assistant/tools/assistant/bookmarkdialog.ui
new file mode 100644
index 000000000..51315317b
--- /dev/null
+++ b/src/assistant/tools/assistant/bookmarkdialog.ui
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>BookmarkDialog</class>
+ <widget class="QDialog" name="BookmarkDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>450</width>
+ <height>133</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Add Bookmark</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Bookmark:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Add in Folder:</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLineEdit" name="bookmarkEdit"/>
+ </item>
+ <item>
+ <widget class="QComboBox" name="bookmarkFolders"/>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QToolButton" name="toolButton">
+ <property name="minimumSize">
+ <size>
+ <width>25</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>+</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QTreeView" name="treeView">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Ignored">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="uniformRowHeights">
+ <bool>true</bool>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <property name="headerHidden">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="QPushButton" name="newFolderButton">
+ <property name="text">
+ <string>New Folder</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>BookmarkDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>BookmarkDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/assistant/tools/assistant/bookmarkfiltermodel.cpp b/src/assistant/tools/assistant/bookmarkfiltermodel.cpp
new file mode 100644
index 000000000..412e08e5d
--- /dev/null
+++ b/src/assistant/tools/assistant/bookmarkfiltermodel.cpp
@@ -0,0 +1,321 @@
+/****************************************************************************
+**
+** 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 "bookmarkfiltermodel.h"
+
+#include "bookmarkitem.h"
+#include "bookmarkmodel.h"
+
+BookmarkFilterModel::BookmarkFilterModel(QObject *parent)
+ : QAbstractProxyModel(parent)
+ , hideBookmarks(true)
+ , sourceModel(0)
+{
+}
+
+void BookmarkFilterModel::setSourceModel(QAbstractItemModel *_sourceModel)
+{
+ beginResetModel();
+
+ if (sourceModel) {
+ disconnect(sourceModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)),
+ this, SLOT(changed(QModelIndex, QModelIndex)));
+ disconnect(sourceModel, SIGNAL(rowsInserted(QModelIndex, int, int)),
+ this, SLOT(rowsInserted(QModelIndex, int, int)));
+ disconnect(sourceModel,
+ SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)), this,
+ SLOT(rowsAboutToBeRemoved(QModelIndex, int, int)));
+ disconnect(sourceModel, SIGNAL(rowsRemoved(QModelIndex, int, int)),
+ this, SLOT(rowsRemoved(QModelIndex, int, int)));
+ disconnect(sourceModel, SIGNAL(layoutAboutToBeChanged()), this,
+ SLOT(layoutAboutToBeChanged()));
+ disconnect(sourceModel, SIGNAL(layoutChanged()), this,
+ SLOT(layoutChanged()));
+ disconnect(sourceModel, SIGNAL(modelAboutToBeReset()), this,
+ SLOT(modelAboutToBeReset()));
+ disconnect(sourceModel, SIGNAL(modelReset()), this, SLOT(modelReset()));
+ }
+
+ QAbstractProxyModel::setSourceModel(sourceModel);
+ sourceModel = qobject_cast<BookmarkModel*> (_sourceModel);
+
+ connect(sourceModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this,
+ SLOT(changed(QModelIndex, QModelIndex)));
+
+ connect(sourceModel, SIGNAL(rowsInserted(QModelIndex, int, int)),
+ this, SLOT(rowsInserted(QModelIndex, int, int)));
+
+ connect(sourceModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)),
+ this, SLOT(rowsAboutToBeRemoved(QModelIndex, int, int)));
+ connect(sourceModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this,
+ SLOT(rowsRemoved(QModelIndex, int, int)));
+
+ connect(sourceModel, SIGNAL(layoutAboutToBeChanged()), this,
+ SLOT(layoutAboutToBeChanged()));
+ connect(sourceModel, SIGNAL(layoutChanged()), this,
+ SLOT(layoutChanged()));
+
+ connect(sourceModel, SIGNAL(modelAboutToBeReset()), this,
+ SLOT(modelAboutToBeReset()));
+ connect(sourceModel, SIGNAL(modelReset()), this, SLOT(modelReset()));
+
+ if (sourceModel)
+ setupCache(sourceModel->index(0, 0, QModelIndex()).parent());
+
+ endResetModel();
+}
+
+int BookmarkFilterModel::rowCount(const QModelIndex &index) const
+{
+ Q_UNUSED(index)
+ return cache.count();
+}
+
+int BookmarkFilterModel::columnCount(const QModelIndex &index) const
+{
+ Q_UNUSED(index)
+ if (sourceModel)
+ return sourceModel->columnCount();
+ return 0;
+}
+
+QModelIndex BookmarkFilterModel::mapToSource(const QModelIndex &proxyIndex) const
+{
+ const int row = proxyIndex.row();
+ if (proxyIndex.isValid() && row >= 0 && row < cache.count())
+ return cache[row];
+ return QModelIndex();
+}
+
+QModelIndex BookmarkFilterModel::mapFromSource(const QModelIndex &sourceIndex) const
+{
+ return index(cache.indexOf(sourceIndex), 0, QModelIndex());
+}
+
+QModelIndex BookmarkFilterModel::parent(const QModelIndex &child) const
+{
+ Q_UNUSED(child)
+ return QModelIndex();
+}
+
+QModelIndex BookmarkFilterModel::index(int row, int column,
+ const QModelIndex &index) const
+{
+ Q_UNUSED(index)
+ if (row < 0 || column < 0 || cache.count() <= row
+ || !sourceModel || sourceModel->columnCount() <= column) {
+ return QModelIndex();
+ }
+ return createIndex(row, 0);
+}
+
+Qt::DropActions BookmarkFilterModel::supportedDropActions () const
+{
+ if (sourceModel)
+ return sourceModel->supportedDropActions();
+ return Qt::IgnoreAction;
+}
+
+Qt::ItemFlags BookmarkFilterModel::flags(const QModelIndex &index) const
+{
+ if (sourceModel)
+ return sourceModel->flags(index);
+ return Qt::NoItemFlags;
+}
+
+QVariant BookmarkFilterModel::data(const QModelIndex &index, int role) const
+{
+ if (sourceModel)
+ return sourceModel->data(mapToSource(index), role);
+ return QVariant();
+}
+
+bool BookmarkFilterModel::setData(const QModelIndex &index, const QVariant &value,
+ int role)
+{
+ if (sourceModel)
+ return sourceModel->setData(mapToSource(index), value, role);
+ return false;
+}
+
+void BookmarkFilterModel::filterBookmarks()
+{
+ if (sourceModel) {
+ beginResetModel();
+ hideBookmarks = true;
+ setupCache(sourceModel->index(0, 0, QModelIndex()).parent());
+ endResetModel();
+ }
+}
+
+void BookmarkFilterModel::filterBookmarkFolders()
+{
+ if (sourceModel) {
+ beginResetModel();
+ hideBookmarks = false;
+ setupCache(sourceModel->index(0, 0, QModelIndex()).parent());
+ endResetModel();
+ }
+}
+
+void BookmarkFilterModel::changed(const QModelIndex &topLeft,
+ const QModelIndex &bottomRight)
+{
+ emit dataChanged(mapFromSource(topLeft), mapFromSource(bottomRight));
+}
+
+void BookmarkFilterModel::rowsInserted(const QModelIndex &parent, int start,
+ int end)
+{
+ if (!sourceModel)
+ return;
+
+ QModelIndex cachePrevious = parent;
+ if (BookmarkItem *parentItem = sourceModel->itemFromIndex(parent)) {
+ BookmarkItem *newItem = parentItem->child(start);
+
+ // iterate over tree hirarchie to find the previous folder
+ for (int i = 0; i < parentItem->childCount(); ++i) {
+ if (BookmarkItem *child = parentItem->child(i)) {
+ const QModelIndex &tmp = sourceModel->indexFromItem(child);
+ if (tmp.data(UserRoleFolder).toBool() && child != newItem)
+ cachePrevious = tmp;
+ }
+ }
+
+ const QModelIndex &newIndex = sourceModel->indexFromItem(newItem);
+ const bool isFolder = newIndex.data(UserRoleFolder).toBool();
+ if ((isFolder && hideBookmarks) || (!isFolder && !hideBookmarks)) {
+ beginInsertRows(mapFromSource(parent), start, end);
+ const int index = cache.indexOf(cachePrevious) + 1;
+ if (cache.value(index, QPersistentModelIndex()) != newIndex)
+ cache.insert(index, newIndex);
+ endInsertRows();
+ }
+ }
+}
+
+void BookmarkFilterModel::rowsAboutToBeRemoved(const QModelIndex &parent,
+ int start, int end)
+{
+ if (!sourceModel)
+ return;
+
+ if (BookmarkItem *parentItem = sourceModel->itemFromIndex(parent)) {
+ if (BookmarkItem *child = parentItem->child(start)) {
+ indexToRemove = sourceModel->indexFromItem(child);
+ if (cache.contains(indexToRemove))
+ beginRemoveRows(mapFromSource(parent), start, end);
+ }
+ }
+}
+
+void BookmarkFilterModel::rowsRemoved(const QModelIndex &/*parent*/, int, int)
+{
+ if (cache.contains(indexToRemove)) {
+ cache.removeAll(indexToRemove);
+ endRemoveRows();
+ }
+}
+
+void BookmarkFilterModel::layoutAboutToBeChanged()
+{
+ // TODO: ???
+}
+
+void BookmarkFilterModel::layoutChanged()
+{
+ // TODO: ???
+}
+
+void BookmarkFilterModel::modelAboutToBeReset()
+{
+ beginResetModel();
+}
+
+void BookmarkFilterModel::modelReset()
+{
+ if (sourceModel)
+ setupCache(sourceModel->index(0, 0, QModelIndex()).parent());
+ endResetModel();
+}
+
+void BookmarkFilterModel::setupCache(const QModelIndex &parent)
+{
+ cache.clear();
+ for (int i = 0; i < sourceModel->rowCount(parent); ++i)
+ collectItems(sourceModel->index(i, 0, parent));
+}
+
+void BookmarkFilterModel::collectItems(const QModelIndex &parent)
+{
+ if (parent.isValid()) {
+ bool isFolder = sourceModel->data(parent, UserRoleFolder).toBool();
+ if ((isFolder && hideBookmarks) || (!isFolder && !hideBookmarks))
+ cache.append(parent);
+
+ if (sourceModel->hasChildren(parent)) {
+ for (int i = 0; i < sourceModel->rowCount(parent); ++i)
+ collectItems(sourceModel->index(i, 0, parent));
+ }
+ }
+}
+
+// -- BookmarkTreeModel
+
+BookmarkTreeModel::BookmarkTreeModel(QObject *parent)
+ : QSortFilterProxyModel(parent)
+{
+}
+
+int BookmarkTreeModel::columnCount(const QModelIndex &parent) const
+{
+ return qMin(1, QSortFilterProxyModel::columnCount(parent));
+}
+
+bool BookmarkTreeModel::filterAcceptsRow(int row, const QModelIndex &parent) const
+{
+ Q_UNUSED(row)
+ BookmarkModel *model = qobject_cast<BookmarkModel*> (sourceModel());
+ if (model->rowCount(parent) > 0
+ && model->data(model->index(row, 0, parent), UserRoleFolder).toBool())
+ return true;
+ return false;
+}
diff --git a/src/assistant/tools/assistant/bookmarkfiltermodel.h b/src/assistant/tools/assistant/bookmarkfiltermodel.h
new file mode 100644
index 000000000..65ed12f20
--- /dev/null
+++ b/src/assistant/tools/assistant/bookmarkfiltermodel.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+#ifndef BOOKMARKFILTERMODEL_H
+#define BOOKMARKFILTERMODEL_H
+
+#include <QtCore/QPersistentModelIndex>
+
+#include <QtGui/QAbstractProxyModel>
+#include <QtGui/QSortFilterProxyModel>
+
+QT_BEGIN_NAMESPACE
+
+class BookmarkItem;
+class BookmarkModel;
+
+typedef QList<QPersistentModelIndex> PersistentModelIndexCache;
+
+class BookmarkFilterModel : public QAbstractProxyModel
+{
+ Q_OBJECT
+public:
+ explicit BookmarkFilterModel(QObject *parent = 0);
+
+ void setSourceModel(QAbstractItemModel *sourceModel);
+
+ int rowCount(const QModelIndex &index) const;
+ int columnCount(const QModelIndex &index) const;
+
+ QModelIndex mapToSource(const QModelIndex &proxyIndex) const;
+ QModelIndex mapFromSource(const QModelIndex &sourceIndex) const;
+
+ QModelIndex parent(const QModelIndex &child) const;
+ QModelIndex index(int row, int column, const QModelIndex &parent) const;
+
+ Qt::DropActions supportedDropActions () const;
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+
+ QVariant data(const QModelIndex &index, int role) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role);
+
+ void filterBookmarks();
+ void filterBookmarkFolders();
+
+private slots:
+ void changed(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+ void rowsInserted(const QModelIndex &parent, int start, int end);
+ void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
+ void rowsRemoved(const QModelIndex &parent, int start, int end);
+ void layoutAboutToBeChanged();
+ void layoutChanged();
+ void modelAboutToBeReset();
+ void modelReset();
+
+private:
+ void setupCache(const QModelIndex &parent);
+ void collectItems(const QModelIndex &parent);
+
+private:
+ bool hideBookmarks;
+ BookmarkModel *sourceModel;
+ PersistentModelIndexCache cache;
+ QPersistentModelIndex indexToRemove;
+};
+
+// -- BookmarkTreeModel
+
+class BookmarkTreeModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+public:
+ BookmarkTreeModel(QObject *parent = 0);
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+
+protected:
+ bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
+};
+
+QT_END_NAMESPACE
+
+#endif // BOOKMARKFILTERMODEL_H
diff --git a/src/assistant/tools/assistant/bookmarkitem.cpp b/src/assistant/tools/assistant/bookmarkitem.cpp
new file mode 100644
index 000000000..8bcf451c1
--- /dev/null
+++ b/src/assistant/tools/assistant/bookmarkitem.cpp
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** 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 "bookmarkitem.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+BookmarkItem::BookmarkItem(const DataVector &data, BookmarkItem *parent)
+ : m_data(data)
+ , m_parent(parent)
+{
+}
+
+BookmarkItem::~BookmarkItem()
+{
+ qDeleteAll(m_children);
+}
+
+BookmarkItem*
+BookmarkItem::parent() const
+{
+ return m_parent;
+}
+
+void
+BookmarkItem::setParent(BookmarkItem *parent)
+{
+ m_parent = parent;
+}
+
+void
+BookmarkItem::addChild(BookmarkItem *child)
+{
+ child->setParent(this);
+ m_children.append(child);
+}
+
+BookmarkItem*
+BookmarkItem::child(int number) const
+{
+ if (number >= 0 && number < m_children.count())
+ return m_children[number];
+ return 0;
+}
+
+int BookmarkItem::childCount() const
+{
+ return m_children.count();
+}
+
+int BookmarkItem::childNumber() const
+{
+ if (m_parent)
+ return m_parent->m_children.indexOf(const_cast<BookmarkItem*>(this));
+ return 0;
+}
+
+QVariant
+BookmarkItem::data(int column) const
+{
+ if (column == 0)
+ return m_data[0];
+
+ if (column == 1 || column == UserRoleUrl)
+ return m_data[1];
+
+ if (column == UserRoleFolder)
+ return m_data[1].toString() == QLatin1String("Folder");
+
+ if (column == UserRoleExpanded)
+ return m_data[2];
+
+ return QVariant();
+}
+
+void
+BookmarkItem::setData(const DataVector &data)
+{
+ m_data = data;
+}
+
+bool
+BookmarkItem::setData(int column, const QVariant &newValue)
+{
+ int index = -1;
+ if (column == 0 || column == 1)
+ index = column;
+
+ if (column == UserRoleUrl || column == UserRoleFolder)
+ index = 1;
+
+ if (column == UserRoleExpanded)
+ index = 2;
+
+ if (index < 0)
+ return false;
+
+ m_data[index] = newValue;
+ return true;
+}
+
+bool
+BookmarkItem::insertChildren(bool isFolder, int position, int count)
+{
+ if (position < 0 || position > m_children.size())
+ return false;
+
+ for (int row = 0; row < count; ++row) {
+ m_children.insert(position, new BookmarkItem(DataVector()
+ << (isFolder
+ ? QCoreApplication::translate("BookmarkItem", "New Folder")
+ : QCoreApplication::translate("BookmarkItem", "Untitled"))
+ << (isFolder ? "Folder" : "about:blank") << false, this));
+ }
+
+ return true;
+}
+
+bool
+BookmarkItem::removeChildren(int position, int count)
+{
+ if (position < 0 || position > m_children.size())
+ return false;
+
+ for (int row = 0; row < count; ++row)
+ delete m_children.takeAt(position);
+
+ return true;
+}
+
+void
+BookmarkItem::dumpTree(int indent) const
+{
+ const QString tree(indent, ' ');
+ qDebug() << tree + (data(UserRoleFolder).toBool() ? "Folder" : "Bookmark")
+ << "Label:" << data(0).toString() << "parent:" << m_parent << "this:"
+ << this;
+
+ foreach (BookmarkItem *item, m_children)
+ item->dumpTree(indent + 4);
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/bookmarkitem.h b/src/assistant/tools/assistant/bookmarkitem.h
new file mode 100644
index 000000000..96ce786be
--- /dev/null
+++ b/src/assistant/tools/assistant/bookmarkitem.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef BOOKMARKITEM_H
+#define BOOKMARKITEM_H
+
+#include <QtCore/QVariant>
+#include <QtCore/QVector>
+
+QT_BEGIN_NAMESPACE
+
+enum {
+ UserRoleUrl = Qt::UserRole + 50,
+ UserRoleFolder = Qt::UserRole + 100,
+ UserRoleExpanded = Qt::UserRole + 150
+};
+
+typedef QVector<QVariant> DataVector;
+
+class BookmarkItem
+{
+public:
+ explicit BookmarkItem(const DataVector &data, BookmarkItem *parent = 0);
+ ~BookmarkItem();
+
+ BookmarkItem *parent() const;
+ void setParent(BookmarkItem *parent);
+
+ void addChild(BookmarkItem *child);
+ BookmarkItem *child(int number) const;
+
+ int childCount() const;
+ int childNumber() const;
+
+ QVariant data(int column) const;
+ void setData(const DataVector &data);
+ bool setData(int column, const QVariant &value);
+
+ bool insertChildren(bool isFolder, int position, int count);
+ bool removeChildren(int position, int count);
+
+ void dumpTree(int indent) const;
+
+private:
+ DataVector m_data;
+
+ BookmarkItem *m_parent;
+ QList<BookmarkItem*> m_children;
+};
+
+QT_END_NAMESPACE
+
+#endif // BOOKMARKITEM_H
diff --git a/src/assistant/tools/assistant/bookmarkmanager.cpp b/src/assistant/tools/assistant/bookmarkmanager.cpp
new file mode 100644
index 000000000..87331463b
--- /dev/null
+++ b/src/assistant/tools/assistant/bookmarkmanager.cpp
@@ -0,0 +1,559 @@
+/****************************************************************************
+**
+** 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 "tracer.h"
+
+#include "bookmarkmanager.h"
+#include "bookmarkmanagerwidget.h"
+#include "bookmarkdialog.h"
+#include "bookmarkfiltermodel.h"
+#include "bookmarkitem.h"
+#include "bookmarkmodel.h"
+#include "centralwidget.h"
+#include "helpenginewrapper.h"
+
+#include <QtGui/QMenu>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QMessageBox>
+#include <QtGui/QSortFilterProxyModel>
+#include <QtGui/QToolBar>
+
+QT_BEGIN_NAMESPACE
+
+// -- BookmarkManager::BookmarkWidget
+
+void BookmarkManager::BookmarkWidget::focusInEvent(QFocusEvent *event)
+{
+ TRACE_OBJ
+ if (event->reason() != Qt::MouseFocusReason) {
+ ui.lineEdit->selectAll();
+ ui.lineEdit->setFocus();
+
+ // force the focus in event on bookmark manager
+ emit focusInEvent();
+ }
+}
+
+// -- BookmarkManager::BookmarkTreeView
+
+BookmarkManager::BookmarkTreeView::BookmarkTreeView(QWidget *parent)
+ : QTreeView(parent)
+{
+ TRACE_OBJ
+ setAcceptDrops(true);
+ setDragEnabled(true);
+ setAutoExpandDelay(1000);
+ setUniformRowHeights(true);
+ setDropIndicatorShown(true);
+ setExpandsOnDoubleClick(true);
+
+ connect(this, SIGNAL(expanded(QModelIndex)), this,
+ SLOT(setExpandedData(QModelIndex)));
+ connect(this, SIGNAL(collapsed(QModelIndex)), this,
+ SLOT(setExpandedData(QModelIndex)));
+
+}
+
+void BookmarkManager::BookmarkTreeView::subclassKeyPressEvent(QKeyEvent *event)
+{
+ TRACE_OBJ
+ QTreeView::keyPressEvent(event);
+}
+
+void BookmarkManager::BookmarkTreeView::setExpandedData(const QModelIndex &index)
+{
+ TRACE_OBJ
+ if (BookmarkModel *treeModel = qobject_cast<BookmarkModel*> (model()))
+ treeModel->setData(index, isExpanded(index), UserRoleExpanded);
+}
+
+// -- BookmarkManager
+
+QMutex BookmarkManager::mutex;
+BookmarkManager* BookmarkManager::bookmarkManager = 0;
+
+// -- public
+
+BookmarkManager* BookmarkManager::instance()
+{
+ TRACE_OBJ
+ if (!bookmarkManager) {
+ QMutexLocker _(&mutex);
+ if (!bookmarkManager)
+ bookmarkManager = new BookmarkManager();
+ }
+ return bookmarkManager;
+}
+
+void BookmarkManager::destroy()
+{
+ TRACE_OBJ
+ delete bookmarkManager;
+ bookmarkManager = 0;
+}
+
+QWidget* BookmarkManager::bookmarkDockWidget() const
+{
+ TRACE_OBJ
+ if (bookmarkWidget)
+ return bookmarkWidget;
+ return 0;
+}
+
+void BookmarkManager::setBookmarksMenu(QMenu* menu)
+{
+ TRACE_OBJ
+ bookmarkMenu = menu;
+ refreshBookmarkMenu();
+}
+
+void BookmarkManager::setBookmarksToolbar(QToolBar *toolBar)
+{
+ TRACE_OBJ
+ m_toolBar = toolBar;
+ refreshBookmarkToolBar();
+}
+
+// -- public slots
+
+void BookmarkManager::addBookmark(const QString &title, const QString &url)
+{
+ TRACE_OBJ
+ showBookmarkDialog(title.isEmpty() ? tr("Untitled") : title,
+ url.isEmpty() ? QLatin1String("about:blank") : url);
+}
+
+// -- private
+
+BookmarkManager::BookmarkManager()
+ : typeAndSearch(false)
+ , bookmarkMenu(0)
+ , m_toolBar(0)
+ , bookmarkModel(new BookmarkModel)
+ , bookmarkFilterModel(0)
+ , typeAndSearchModel(0)
+ , bookmarkWidget(new BookmarkWidget)
+ , bookmarkTreeView(new BookmarkTreeView)
+ , bookmarkManagerWidget(0)
+{
+ TRACE_OBJ
+ bookmarkWidget->installEventFilter(this);
+ connect(bookmarkWidget->ui.add, SIGNAL(clicked()), this,
+ SLOT(addBookmark()));
+ connect(bookmarkWidget->ui.remove, SIGNAL(clicked()), this,
+ SLOT(removeBookmark()));
+ connect(bookmarkWidget->ui.lineEdit, SIGNAL(textChanged(QString)), this,
+ SLOT(textChanged(QString)));
+ connect(bookmarkWidget, SIGNAL(focusInEvent()), this, SLOT(focusInEvent()));
+
+ bookmarkTreeView->setModel(bookmarkModel);
+ bookmarkTreeView->installEventFilter(this);
+ bookmarkTreeView->viewport()->installEventFilter(this);
+ bookmarkTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
+ bookmarkWidget->ui.stackedWidget->addWidget(bookmarkTreeView);
+
+ connect(bookmarkTreeView, SIGNAL(activated(QModelIndex)), this,
+ SLOT(setSourceFromIndex(QModelIndex)));
+ connect(bookmarkTreeView, SIGNAL(customContextMenuRequested(QPoint)), this,
+ SLOT(customContextMenuRequested(QPoint)));
+
+ connect(&HelpEngineWrapper::instance(), SIGNAL(setupFinished()), this,
+ SLOT(setupFinished()));
+ connect(bookmarkModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this,
+ SLOT(refreshBookmarkMenu()));
+ connect(bookmarkModel, SIGNAL(rowsInserted(QModelIndex, int, int)), this,
+ SLOT(refreshBookmarkMenu()));
+ connect(bookmarkModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this,
+ SLOT(refreshBookmarkMenu()));
+
+ connect(bookmarkModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this,
+ SLOT(refreshBookmarkToolBar()));
+ connect(bookmarkModel, SIGNAL(rowsInserted(QModelIndex, int, int)), this,
+ SLOT(refreshBookmarkToolBar()));
+ connect(bookmarkModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this,
+ SLOT(refreshBookmarkToolBar()));
+}
+
+BookmarkManager::~BookmarkManager()
+{
+ TRACE_OBJ
+ delete bookmarkManagerWidget;
+ HelpEngineWrapper::instance().setBookmarks(bookmarkModel->bookmarks());
+ delete bookmarkModel;
+}
+
+void BookmarkManager::removeItem(const QModelIndex &index)
+{
+ TRACE_OBJ
+ QModelIndex current = index;
+ if (typeAndSearch) { // need to map because of proxy
+ current = typeAndSearchModel->mapToSource(current);
+ current = bookmarkFilterModel->mapToSource(current);
+ } else if (!bookmarkModel->parent(index).isValid()) {
+ return; // check if we should delete the "Bookmarks Menu", bail
+ }
+
+ if (bookmarkModel->hasChildren(current)) {
+ int value = QMessageBox::question(bookmarkTreeView, tr("Remove"),
+ tr("You are going to delete a Folder, this will also<br>"
+ "remove it's content. Are you sure to continue?"),
+ QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel);
+ if (value == QMessageBox::Cancel)
+ return;
+ }
+ bookmarkModel->removeItem(current);
+}
+
+bool BookmarkManager::eventFilter(QObject *object, QEvent *event)
+{
+ if (object != bookmarkTreeView && object != bookmarkTreeView->viewport()
+ && object != bookmarkWidget)
+ return QObject::eventFilter(object, event);
+
+ TRACE_OBJ
+ const bool isWidget = object == bookmarkWidget;
+ if (event->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(event);
+ switch (ke->key()) {
+ case Qt::Key_F2: {
+ renameBookmark(bookmarkTreeView->currentIndex());
+ } break;
+
+ case Qt::Key_Delete: {
+ removeItem(bookmarkTreeView->currentIndex());
+ return true;
+ } break;
+
+ case Qt::Key_Up: { // needs event filter on widget
+ case Qt::Key_Down:
+ if (isWidget)
+ bookmarkTreeView->subclassKeyPressEvent(ke);
+ } break;
+
+ case Qt::Key_Escape: {
+ emit escapePressed();
+ } break;
+
+ default: break;
+ }
+ }
+
+ if (event->type() == QEvent::MouseButtonRelease && !isWidget) {
+ QMouseEvent *me = static_cast<QMouseEvent*>(event);
+ switch (me->button()) {
+ case Qt::LeftButton: {
+ if (me->modifiers() & Qt::ControlModifier)
+ setSourceFromIndex(bookmarkTreeView->currentIndex(), true);
+ } break;
+
+ case Qt::MidButton: {
+ setSourceFromIndex(bookmarkTreeView->currentIndex(), true);
+ } break;
+
+ default: break;
+ }
+ }
+
+ return QObject::eventFilter(object, event);
+}
+
+void BookmarkManager::buildBookmarksMenu(const QModelIndex &index, QMenu* menu)
+{
+ TRACE_OBJ
+ if (!index.isValid())
+ return;
+
+ const QString &text = index.data().toString();
+ const QIcon &icon = qvariant_cast<QIcon>(index.data(Qt::DecorationRole));
+ if (index.data(UserRoleFolder).toBool()) {
+ if (QMenu* subMenu = menu->addMenu(icon, text)) {
+ for (int i = 0; i < bookmarkModel->rowCount(index); ++i)
+ buildBookmarksMenu(bookmarkModel->index(i, 0, index), subMenu);
+ }
+ } else {
+ QAction *action = menu->addAction(icon, text);
+ action->setData(index.data(UserRoleUrl).toString());
+ }
+}
+
+void BookmarkManager::showBookmarkDialog(const QString &name, const QString &url)
+{
+ TRACE_OBJ
+ BookmarkDialog dialog(bookmarkModel, name, url, bookmarkTreeView);
+ dialog.exec();
+}
+
+// -- private slots
+
+void BookmarkManager::setupFinished()
+{
+ TRACE_OBJ
+ bookmarkModel->setBookmarks(HelpEngineWrapper::instance().bookmarks());
+ bookmarkModel->expandFoldersIfNeeeded(bookmarkTreeView);
+
+ refreshBookmarkMenu();
+ refreshBookmarkToolBar();
+
+ bookmarkTreeView->hideColumn(1);
+ bookmarkTreeView->header()->setVisible(false);
+ bookmarkTreeView->header()->setStretchLastSection(true);
+
+ if (!bookmarkFilterModel)
+ bookmarkFilterModel = new BookmarkFilterModel(this);
+ bookmarkFilterModel->setSourceModel(bookmarkModel);
+ bookmarkFilterModel->filterBookmarkFolders();
+
+ if (!typeAndSearchModel)
+ typeAndSearchModel = new QSortFilterProxyModel(this);
+ typeAndSearchModel->setDynamicSortFilter(true);
+ typeAndSearchModel->setSourceModel(bookmarkFilterModel);
+}
+
+void BookmarkManager::addBookmark()
+{
+ TRACE_OBJ
+ if (CentralWidget *widget = CentralWidget::instance())
+ addBookmark(widget->currentTitle(), widget->currentSource().toString());
+}
+
+void BookmarkManager::removeBookmark()
+{
+ TRACE_OBJ
+ removeItem(bookmarkTreeView->currentIndex());
+}
+
+void BookmarkManager::manageBookmarks()
+{
+ TRACE_OBJ
+ if (bookmarkManagerWidget == 0) {
+ bookmarkManagerWidget = new BookmarkManagerWidget(bookmarkModel);
+ connect(bookmarkManagerWidget, SIGNAL(setSource(QUrl)), this,
+ SIGNAL(setSource(QUrl)));
+ connect(bookmarkManagerWidget, SIGNAL(setSourceInNewTab(QUrl))
+ , this, SIGNAL(setSourceInNewTab(QUrl)));
+ connect(bookmarkManagerWidget, SIGNAL(managerWidgetAboutToClose())
+ , this, SLOT(managerWidgetAboutToClose()));
+ }
+ bookmarkManagerWidget->show();
+ bookmarkManagerWidget->raise();
+}
+
+void BookmarkManager::refreshBookmarkMenu()
+{
+ TRACE_OBJ
+ if (!bookmarkMenu)
+ return;
+
+ bookmarkMenu->clear();
+
+ bookmarkMenu->addAction(tr("Manage Bookmarks..."), this,
+ SLOT(manageBookmarks()));
+ bookmarkMenu->addAction(QIcon::fromTheme("bookmark-new"),
+ tr("Add Bookmark..."), this, SLOT(addBookmark()), QKeySequence(tr("Ctrl+D")));
+
+ bookmarkMenu->addSeparator();
+
+ QModelIndex root = bookmarkModel->index(0, 0, QModelIndex()).parent();
+ buildBookmarksMenu(bookmarkModel->index(0, 0, root), bookmarkMenu);
+
+ bookmarkMenu->addSeparator();
+
+ root = bookmarkModel->index(1, 0, QModelIndex());
+ for (int i = 0; i < bookmarkModel->rowCount(root); ++i)
+ buildBookmarksMenu(bookmarkModel->index(i, 0, root), bookmarkMenu);
+
+ connect(bookmarkMenu, SIGNAL(triggered(QAction*)), this,
+ SLOT(setSourceFromAction(QAction*)));
+}
+
+void BookmarkManager::refreshBookmarkToolBar()
+{
+ TRACE_OBJ
+ if (!m_toolBar)
+ return;
+
+ m_toolBar->clear();
+ m_toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+
+ const QModelIndex &root = bookmarkModel->index(0, 0, QModelIndex());
+ for (int i = 0; i < bookmarkModel->rowCount(root); ++i) {
+ const QModelIndex &index = bookmarkModel->index(i, 0, root);
+ if (index.data(UserRoleFolder).toBool()) {
+ QToolButton *button = new QToolButton(m_toolBar);
+ button->setPopupMode(QToolButton::InstantPopup);
+ button->setText(index.data().toString());
+ QMenu *menu = new QMenu(button);
+ for (int j = 0; j < bookmarkModel->rowCount(index); ++j)
+ buildBookmarksMenu(bookmarkModel->index(j, 0, index), menu);
+ connect(menu, SIGNAL(triggered(QAction*)), this,
+ SLOT(setSourceFromAction(QAction*)));
+ button->setMenu(menu);
+ button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ button->setIcon(qvariant_cast<QIcon>(index.data(Qt::DecorationRole)));
+ QAction *a = m_toolBar->addWidget(button);
+ a->setText(index.data().toString());
+ } else {
+ QAction *action = m_toolBar->addAction(
+ qvariant_cast<QIcon>(index.data(Qt::DecorationRole)),
+ index.data().toString(), this, SLOT(setSourceFromAction()));
+ action->setData(index.data(UserRoleUrl).toString());
+ }
+ }
+}
+
+void BookmarkManager::renameBookmark(const QModelIndex &index)
+{
+ // check if we should rename the "Bookmarks Menu", bail
+ if (!typeAndSearch && !bookmarkModel->parent(index).isValid())
+ return;
+
+ bookmarkModel->setItemsEditable(true);
+ bookmarkTreeView->edit(index);
+ bookmarkModel->setItemsEditable(false);
+}
+
+
+void BookmarkManager::setSourceFromAction()
+{
+ TRACE_OBJ
+ setSourceFromAction(qobject_cast<QAction*> (sender()));
+}
+
+void BookmarkManager::setSourceFromAction(QAction *action)
+{
+ TRACE_OBJ
+ if (action) {
+ const QVariant &data = action->data();
+ if (data.canConvert<QUrl>())
+ emit setSource(data.toUrl());
+ }
+}
+
+void BookmarkManager::setSourceFromIndex(const QModelIndex &index, bool newTab)
+{
+ TRACE_OBJ
+ QAbstractItemModel *base = bookmarkModel;
+ if (typeAndSearch)
+ base = typeAndSearchModel;
+
+ if (base->data(index, UserRoleFolder).toBool())
+ return;
+
+ const QVariant &data = base->data(index, UserRoleUrl);
+ if (data.canConvert<QUrl>()) {
+ if (newTab)
+ emit setSourceInNewTab(data.toUrl());
+ else
+ emit setSource(data.toUrl());
+ }
+}
+
+void BookmarkManager::customContextMenuRequested(const QPoint &point)
+{
+ TRACE_OBJ
+ QModelIndex index = bookmarkTreeView->indexAt(point);
+ if (!index.isValid())
+ return;
+
+ // check if we should open the menu on "Bookmarks Menu", bail
+ if (!typeAndSearch && !bookmarkModel->parent(index).isValid())
+ return;
+
+ QAction *remove = 0;
+ QAction *rename = 0;
+ QAction *showItem = 0;
+ QAction *showItemInNewTab = 0;
+
+ QMenu menu(QLatin1String(""));
+ if (!typeAndSearch && bookmarkModel->data(index, UserRoleFolder).toBool()) {
+ remove = menu.addAction(tr("Delete Folder"));
+ rename = menu.addAction(tr("Rename Folder"));
+ } else {
+ showItem = menu.addAction(tr("Show Bookmark"));
+ showItemInNewTab = menu.addAction(tr("Show Bookmark in New Tab"));
+ menu.addSeparator();
+ remove = menu.addAction(tr("Delete Bookmark"));
+ rename = menu.addAction(tr("Rename Bookmark"));
+ }
+
+ QAction *pickedAction = menu.exec(bookmarkTreeView->mapToGlobal(point));
+ if (pickedAction == rename)
+ renameBookmark(index);
+ else if (pickedAction == remove)
+ removeItem(index);
+ else if (pickedAction == showItem || pickedAction == showItemInNewTab)
+ setSourceFromIndex(index, pickedAction == showItemInNewTab);
+}
+
+void BookmarkManager::focusInEvent()
+{
+ TRACE_OBJ
+ const QModelIndex &index = bookmarkTreeView->indexAt(QPoint(2, 2));
+ if (index.isValid())
+ bookmarkTreeView->setCurrentIndex(index);
+}
+
+void BookmarkManager::managerWidgetAboutToClose()
+{
+ delete bookmarkManagerWidget;
+ bookmarkManagerWidget = 0;
+}
+
+void BookmarkManager::textChanged(const QString &text)
+{
+ TRACE_OBJ
+ if (!bookmarkWidget->ui.lineEdit->text().isEmpty()) {
+ if (!typeAndSearch) {
+ typeAndSearch = true;
+ bookmarkTreeView->setItemsExpandable(false);
+ bookmarkTreeView->setRootIsDecorated(false);
+ bookmarkTreeView->setModel(typeAndSearchModel);
+ }
+ typeAndSearchModel->setFilterRegExp(QRegExp(text));
+ } else {
+ typeAndSearch = false;
+ bookmarkTreeView->setModel(bookmarkModel);
+ bookmarkTreeView->setItemsExpandable(true);
+ bookmarkTreeView->setRootIsDecorated(true);
+ bookmarkModel->expandFoldersIfNeeeded(bookmarkTreeView);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/bookmarkmanager.h b/src/assistant/tools/assistant/bookmarkmanager.h
new file mode 100644
index 000000000..f5823a7fa
--- /dev/null
+++ b/src/assistant/tools/assistant/bookmarkmanager.h
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+#ifndef BOOKMARKMANAGER_H
+#define BOOKMARKMANAGER_H
+
+#include <QtCore/QMutex>
+#include <QtGui/QTreeView>
+
+#include "ui_bookmarkwidget.h"
+
+QT_BEGIN_NAMESPACE
+
+class BookmarkManagerWidget;
+class BookmarkModel;
+class BookmarkFilterModel;
+class QKeyEvent;
+class QSortFilterProxyModel;
+class QToolBar;
+
+class BookmarkManager : public QObject
+{
+ Q_OBJECT
+ class BookmarkWidget;
+ class BookmarkTreeView;
+ class BookmarkListView;
+ Q_DISABLE_COPY(BookmarkManager);
+
+public:
+ static BookmarkManager* instance();
+ static void destroy();
+
+ QWidget* bookmarkDockWidget() const;
+ void setBookmarksMenu(QMenu* menu);
+ void setBookmarksToolbar(QToolBar *toolBar);
+
+public slots:
+ void addBookmark(const QString &title, const QString &url);
+
+signals:
+ void escapePressed();
+ void setSource(const QUrl &url);
+ void setSourceInNewTab(const QUrl &url);
+
+private:
+ BookmarkManager();
+ ~BookmarkManager();
+
+ void removeItem(const QModelIndex &index);
+ bool eventFilter(QObject *object, QEvent *event);
+ void buildBookmarksMenu(const QModelIndex &index, QMenu *menu);
+ void showBookmarkDialog(const QString &name, const QString &url);
+
+private slots:
+ void setupFinished();
+
+ void addBookmark();
+ void removeBookmark();
+ void manageBookmarks();
+ void refreshBookmarkMenu();
+ void refreshBookmarkToolBar();
+ void renameBookmark(const QModelIndex &index);
+
+ void setSourceFromAction();
+ void setSourceFromAction(QAction *action);
+ void setSourceFromIndex(const QModelIndex &index, bool newTab = false);
+
+ void focusInEvent();
+ void managerWidgetAboutToClose();
+ void textChanged(const QString &text);
+ void customContextMenuRequested(const QPoint &point);
+
+private:
+ bool typeAndSearch;
+
+ static QMutex mutex;
+ static BookmarkManager *bookmarkManager;
+
+ QMenu *bookmarkMenu;
+ QToolBar *m_toolBar;
+
+ BookmarkModel *bookmarkModel;
+ BookmarkFilterModel *bookmarkFilterModel;
+ QSortFilterProxyModel *typeAndSearchModel;
+
+ BookmarkWidget *bookmarkWidget;
+ BookmarkTreeView *bookmarkTreeView;
+ BookmarkManagerWidget *bookmarkManagerWidget;
+};
+
+class BookmarkManager::BookmarkWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ BookmarkWidget(QWidget *parent = 0)
+ : QWidget(parent) { ui.setupUi(this); }
+ virtual ~BookmarkWidget() {}
+
+ Ui::BookmarkWidget ui;
+
+signals:
+ void focusInEvent();
+
+private:
+ void focusInEvent(QFocusEvent *event);
+};
+
+class BookmarkManager::BookmarkTreeView : public QTreeView
+{
+ Q_OBJECT
+public:
+ BookmarkTreeView(QWidget *parent = 0);
+ ~BookmarkTreeView() {}
+
+ void subclassKeyPressEvent(QKeyEvent *event);
+
+private slots:
+ void setExpandedData(const QModelIndex &index);
+};
+
+QT_END_NAMESPACE
+
+#endif // BOOKMARKMANAGER_H
diff --git a/src/assistant/tools/assistant/bookmarkmanagerwidget.cpp b/src/assistant/tools/assistant/bookmarkmanagerwidget.cpp
new file mode 100644
index 000000000..dd410d3a2
--- /dev/null
+++ b/src/assistant/tools/assistant/bookmarkmanagerwidget.cpp
@@ -0,0 +1,321 @@
+/****************************************************************************
+**
+** 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 "bookmarkmanagerwidget.h"
+#include "bookmarkitem.h"
+#include "bookmarkmodel.h"
+#include "tracer.h"
+#include "xbelsupport.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QFile>
+#include <QtCore/QUrl>
+
+#include <QtGui/QCloseEvent>
+#include <QtGui/QFileDialog>
+#include <QtGui/QKeySequence>
+#include <QtGui/QMessageBox>
+#include <QtGui/QShortcut>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ #define TR(x) QCoreApplication::translate("BookmarkManager", x)
+}
+
+BookmarkManagerWidget::BookmarkManagerWidget(BookmarkModel *sourceModel,
+ QWidget *parent)
+ : QWidget(parent)
+ , bookmarkModel(sourceModel)
+{
+ TRACE_OBJ
+ ui.setupUi(this);
+
+ ui.treeView->setModel(bookmarkModel);
+
+ ui.treeView->expandAll();
+ ui.treeView->installEventFilter(this);
+ ui.treeView->viewport()->installEventFilter(this);
+ ui.treeView->setContextMenuPolicy(Qt::CustomContextMenu);
+
+ connect(ui.treeView, SIGNAL(customContextMenuRequested(QPoint)), this,
+ SLOT(customContextMenuRequested(QPoint)));
+
+ connect(ui.remove, SIGNAL(clicked()), this, SLOT(removeItem()));
+ connect(ui.lineEdit, SIGNAL(textChanged(QString)), this,
+ SLOT(textChanged(QString)));
+ new QShortcut(QKeySequence::Find, ui.lineEdit, SLOT(setFocus()));
+
+ importExportMenu.addAction(tr("Import..."), this, SLOT(importBookmarks()));
+ importExportMenu.addAction(tr("Export..."), this, SLOT(exportBookmarks()));
+ ui.importExport->setMenu(&importExportMenu);
+
+ new QShortcut(QKeySequence::FindNext, this, SLOT(findNext()));
+ new QShortcut(QKeySequence::FindPrevious, this, SLOT(findPrevious()));
+
+ connect(bookmarkModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this,
+ SLOT(refeshBookmarkCache()));
+ connect(bookmarkModel, SIGNAL(rowsInserted(QModelIndex, int, int)), this,
+ SLOT(refeshBookmarkCache()));
+ connect(bookmarkModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this,
+ SLOT(refeshBookmarkCache()));
+
+ ui.treeView->setCurrentIndex(ui.treeView->indexAt(QPoint(2, 2)));
+}
+
+BookmarkManagerWidget::~BookmarkManagerWidget()
+{
+ TRACE_OBJ
+}
+
+void BookmarkManagerWidget::closeEvent(QCloseEvent *event)
+{
+ TRACE_OBJ
+ event->accept();
+ emit managerWidgetAboutToClose();
+}
+
+void BookmarkManagerWidget::renameItem(const QModelIndex &index)
+{
+ TRACE_OBJ
+ // check if we should rename the "Bookmarks Menu", bail
+ if (!bookmarkModel->parent(index).isValid())
+ return;
+
+ bookmarkModel->setItemsEditable(true);
+ ui.treeView->edit(index);
+ bookmarkModel->setItemsEditable(false);
+}
+
+static int nextIndex(int current, int count, bool forward)
+{
+ TRACE_OBJ
+ if (current >= 0)
+ return (forward ? (current + 1) : ((current - 1) + count)) % count;
+ return 0;
+}
+
+void BookmarkManagerWidget::selectNextIndex(bool direction) const
+{
+ QModelIndex current = ui.treeView->currentIndex();
+ if (current.isValid() && !cache.isEmpty()) {
+ current = cache.at(nextIndex(cache.indexOf(current), cache.count(),
+ direction));
+ }
+ ui.treeView->setCurrentIndex(current);
+}
+
+bool BookmarkManagerWidget::eventFilter(QObject *object, QEvent *event)
+{
+ TRACE_OBJ
+ if (object != ui.treeView && object != ui.treeView->viewport())
+ return QWidget::eventFilter(object, event);
+
+ if (event->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(event);
+ switch (ke->key()) {
+ case Qt::Key_F2: {
+ renameItem(ui.treeView->currentIndex());
+ } break;
+
+ case Qt::Key_Delete: {
+ removeItem(ui.treeView->currentIndex());
+ } break;
+
+ default: break;
+ }
+ }
+
+ if (event->type() == QEvent::MouseButtonRelease) {
+ QMouseEvent *me = static_cast<QMouseEvent*>(event);
+ switch (me->button()) {
+ case Qt::LeftButton: {
+ if (me->modifiers() & Qt::ControlModifier)
+ setSourceFromIndex(ui.treeView->currentIndex(), true);
+ } break;
+
+ case Qt::MidButton: {
+ setSourceFromIndex(ui.treeView->currentIndex(), true);
+ } break;
+
+ default: break;
+ }
+ }
+ return QObject::eventFilter(object, event);
+}
+
+void BookmarkManagerWidget::findNext()
+{
+ TRACE_OBJ
+ selectNextIndex(true);
+}
+
+void BookmarkManagerWidget::findPrevious()
+{
+ TRACE_OBJ
+ selectNextIndex(false);
+}
+
+void BookmarkManagerWidget::importBookmarks()
+{
+ TRACE_OBJ
+ const QString &fileName = QFileDialog::getOpenFileName(0, TR("Open File"),
+ QDir::currentPath(), TR("Files (*.xbel)"));
+
+ if (fileName.isEmpty())
+ return;
+
+ QFile file(fileName);
+ if (file.open(QIODevice::ReadOnly)) {
+ XbelReader reader(bookmarkModel);
+ reader.readFromFile(&file);
+ }
+}
+
+void BookmarkManagerWidget::exportBookmarks()
+{
+ TRACE_OBJ
+ QString fileName = QFileDialog::getSaveFileName(0, TR("Save File"),
+ QLatin1String("untitled.xbel"), TR("Files (*.xbel)"));
+
+ const QLatin1String suffix(".xbel");
+ if (!fileName.endsWith(suffix))
+ fileName.append(suffix);
+
+ QFile file(fileName);
+ if (file.open(QIODevice::WriteOnly)) {
+ XbelWriter writer(bookmarkModel);
+ writer.writeToFile(&file);
+ } else {
+ QMessageBox::information(this, TR("Qt Assistant"),
+ TR("Unable to save bookmarks."), TR("OK"));
+ }
+}
+
+void BookmarkManagerWidget::refeshBookmarkCache()
+{
+ TRACE_OBJ
+ cache.clear();
+
+ const QString &text = ui.lineEdit->text();
+ if (!text.isEmpty())
+ cache = bookmarkModel->indexListFor(text);
+}
+
+void BookmarkManagerWidget::textChanged(const QString &/*text*/)
+{
+ TRACE_OBJ
+ refeshBookmarkCache();
+ if (!cache.isEmpty())
+ ui.treeView->setCurrentIndex(cache.at(0));
+}
+
+void BookmarkManagerWidget::removeItem(const QModelIndex &index)
+{
+ TRACE_OBJ
+ QModelIndex current = index.isValid() ? index : ui.treeView->currentIndex();
+ if (!bookmarkModel->parent(current).isValid())
+ return; // check if we should delete the "Bookmarks Menu", bail
+
+ if (bookmarkModel->hasChildren(current)) {
+ int value = QMessageBox::question(this, TR("Remove"), TR("You are going"
+ "to delete a Folder, this will also<br> remove it's content. Are "
+ "you sure to continue?"),
+ QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel);
+ if (value == QMessageBox::Cancel)
+ return;
+ }
+ bookmarkModel->removeItem(current);
+}
+
+void BookmarkManagerWidget::customContextMenuRequested(const QPoint &point)
+{
+ TRACE_OBJ
+ const QModelIndex &index = ui.treeView->indexAt(point);
+ if (!index.isValid())
+ return;
+
+ // check if we should open the menu on "Bookmarks Menu", bail
+ if (!bookmarkModel->parent(index).isValid())
+ return;
+
+ QAction *remove = 0;
+ QAction *rename = 0;
+ QAction *showItem = 0;
+ QAction *showItemInNewTab = 0;
+
+ QMenu menu(QLatin1String(""));
+ if (bookmarkModel->data(index, UserRoleFolder).toBool()) {
+ remove = menu.addAction(TR("Delete Folder"));
+ rename = menu.addAction(TR("Rename Folder"));
+ } else {
+ showItem = menu.addAction(TR("Show Bookmark"));
+ showItemInNewTab = menu.addAction(TR("Show Bookmark in New Tab"));
+ menu.addSeparator();
+ remove = menu.addAction(TR("Delete Bookmark"));
+ rename = menu.addAction(TR("Rename Bookmark"));
+ }
+
+ QAction *pickedAction = menu.exec(ui.treeView->mapToGlobal(point));
+ if (pickedAction == rename)
+ renameItem(index);
+ else if (pickedAction == remove)
+ removeItem(index);
+ else if (pickedAction == showItem || pickedAction == showItemInNewTab)
+ setSourceFromIndex(index, pickedAction == showItemInNewTab);
+}
+
+void
+BookmarkManagerWidget::setSourceFromIndex(const QModelIndex &index, bool newTab)
+{
+ TRACE_OBJ
+ if (bookmarkModel->data(index, UserRoleFolder).toBool())
+ return;
+
+ const QVariant &data = bookmarkModel->data(index, UserRoleUrl);
+ if (data.canConvert<QUrl>()) {
+ if (newTab)
+ emit setSourceInNewTab(data.toUrl());
+ else
+ emit setSource(data.toUrl());
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/bookmarkmanagerwidget.h b/src/assistant/tools/assistant/bookmarkmanagerwidget.h
new file mode 100644
index 000000000..a0dec72a6
--- /dev/null
+++ b/src/assistant/tools/assistant/bookmarkmanagerwidget.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+#ifndef BOOKMARKMANAGERWIDGET_H
+#define BOOKMARKMANAGERWIDGET_H
+
+#include "ui_bookmarkmanagerwidget.h"
+
+#include <QtCore/QPersistentModelIndex>
+
+#include <QtGui/QMenu>
+
+QT_BEGIN_NAMESPACE
+
+class BookmarkModel;
+class QCloseEvent;
+class QString;
+
+class BookmarkManagerWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit BookmarkManagerWidget(BookmarkModel *bookmarkModel,
+ QWidget *parent = 0);
+ ~BookmarkManagerWidget();
+
+protected:
+ void closeEvent(QCloseEvent *event);
+
+signals:
+ void setSource(const QUrl &url);
+ void setSourceInNewTab(const QUrl &url);
+
+ void managerWidgetAboutToClose();
+
+private:
+ void renameItem(const QModelIndex &index);
+ void selectNextIndex(bool direction) const;
+ bool eventFilter(QObject *object, QEvent *event);
+
+private slots:
+ void findNext();
+ void findPrevious();
+
+ void importBookmarks();
+ void exportBookmarks();
+
+ void refeshBookmarkCache();
+ void textChanged(const QString &text);
+
+ void removeItem(const QModelIndex &index = QModelIndex());
+
+ void customContextMenuRequested(const QPoint &point);
+ void setSourceFromIndex(const QModelIndex &index, bool newTab = false);
+
+private:
+ QMenu importExportMenu;
+ Ui::BookmarkManagerWidget ui;
+ QList<QPersistentModelIndex> cache;
+
+ BookmarkModel *bookmarkModel;
+};
+
+QT_END_NAMESPACE
+
+#endif // BOOKMARKMANAGERWIDGET_H
diff --git a/src/assistant/tools/assistant/bookmarkmanagerwidget.ui b/src/assistant/tools/assistant/bookmarkmanagerwidget.ui
new file mode 100644
index 000000000..dc965d94e
--- /dev/null
+++ b/src/assistant/tools/assistant/bookmarkmanagerwidget.ui
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>BookmarkManagerWidget</class>
+ <widget class="QWidget" name="BookmarkManagerWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>517</width>
+ <height>348</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Manage Bookmarks</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Search:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="lineEdit"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QTreeView" name="treeView">
+ <property name="acceptDrops">
+ <bool>true</bool>
+ </property>
+ <property name="showDropIndicator" stdset="0">
+ <bool>true</bool>
+ </property>
+ <property name="dragEnabled">
+ <bool>true</bool>
+ </property>
+ <property name="autoExpandDelay">
+ <number>1000</number>
+ </property>
+ <property name="uniformRowHeights">
+ <bool>true</bool>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <attribute name="headerDefaultSectionSize">
+ <number>225</number>
+ </attribute>
+ <attribute name="headerMinimumSectionSize">
+ <number>50</number>
+ </attribute>
+ <attribute name="headerDefaultSectionSize">
+ <number>225</number>
+ </attribute>
+ <attribute name="headerMinimumSectionSize">
+ <number>50</number>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QPushButton" name="remove">
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="importExport">
+ <property name="text">
+ <string>Import and Backup</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButton_5">
+ <property name="text">
+ <string>OK</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>pushButton_5</sender>
+ <signal>clicked()</signal>
+ <receiver>BookmarkManagerWidget</receiver>
+ <slot>close()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>445</x>
+ <y>328</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>340</x>
+ <y>313</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/assistant/tools/assistant/bookmarkmodel.cpp b/src/assistant/tools/assistant/bookmarkmodel.cpp
new file mode 100644
index 000000000..49b89c38f
--- /dev/null
+++ b/src/assistant/tools/assistant/bookmarkmodel.cpp
@@ -0,0 +1,461 @@
+/****************************************************************************
+**
+** 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 "bookmarkmodel.h"
+#include "bookmarkitem.h"
+
+#include <QtCore/QMimeData>
+#include <QtCore/QStack>
+
+#include <QtGui/QApplication>
+#include <QtGui/QStyle>
+#include <QtGui/QTreeView>
+
+const quint32 VERSION = 0xe53798;
+const QLatin1String MIMETYPE("application/bookmarks.assistant");
+
+BookmarkModel::BookmarkModel()
+ : QAbstractItemModel()
+ , m_folder(false)
+ , m_editable(false)
+ , rootItem(0)
+{
+}
+
+BookmarkModel::~BookmarkModel()
+{
+ delete rootItem;
+}
+
+QByteArray
+BookmarkModel::bookmarks() const
+{
+ QByteArray ba;
+ QDataStream stream(&ba, QIODevice::WriteOnly);
+ stream << qint32(VERSION);
+
+ const QModelIndex &root = index(0,0, QModelIndex()).parent();
+ for (int i = 0; i < rowCount(root); ++i)
+ collectItems(index(i, 0, root), 0, &stream);
+
+ return ba;
+}
+
+void
+BookmarkModel::setBookmarks(const QByteArray &bookmarks)
+{
+ beginResetModel();
+
+ delete rootItem;
+ folderIcon = QApplication::style()->standardIcon(QStyle::SP_DirClosedIcon);
+ bookmarkIcon = QIcon(QLatin1String(":/trolltech/assistant/images/bookmark.png"));
+
+ rootItem = new BookmarkItem(DataVector() << tr("Name") << tr("Address")
+ << true);
+
+ QStack<BookmarkItem*> parents;
+ QDataStream stream(bookmarks);
+
+ qint32 version;
+ stream >> version;
+ if (version < VERSION) {
+ stream.device()->seek(0);
+ BookmarkItem* toolbar = new BookmarkItem(DataVector() << tr("Toolbar Menu")
+ << QLatin1String("Folder") << true);
+ rootItem->addChild(toolbar);
+
+ BookmarkItem* menu = new BookmarkItem(DataVector() << tr("Bookmarks Menu")
+ << QLatin1String("Folder") << true);
+ rootItem->addChild(menu);
+ parents.push(menu);
+ } else {
+ parents.push(rootItem);
+ }
+
+ qint32 depth;
+ bool expanded;
+ QString name, url;
+ while (!stream.atEnd()) {
+ stream >> depth >> name >> url >> expanded;
+ while ((parents.count() - 1) != depth)
+ parents.pop();
+
+ BookmarkItem *item = new BookmarkItem(DataVector() << name << url << expanded);
+ if (url == QLatin1String("Folder")) {
+ parents.top()->addChild(item);
+ parents.push(item);
+ } else {
+ parents.top()->addChild(item);
+ }
+ }
+
+ cache.clear();
+ setupCache(index(0,0, QModelIndex().parent()));
+ endResetModel();
+}
+
+void
+BookmarkModel::setItemsEditable(bool editable)
+{
+ m_editable = editable;
+}
+
+void
+BookmarkModel::expandFoldersIfNeeeded(QTreeView *treeView)
+{
+ foreach (const QModelIndex &index, cache)
+ treeView->setExpanded(index, index.data(UserRoleExpanded).toBool());
+}
+
+QModelIndex
+BookmarkModel::addItem(const QModelIndex &parent, bool isFolder)
+{
+ m_folder = isFolder;
+ QModelIndex next;
+ if (insertRow(rowCount(parent), parent))
+ next = index(rowCount(parent) - 1, 0, parent);
+ m_folder = false;
+
+ return next;
+}
+
+bool
+BookmarkModel::removeItem(const QModelIndex &index)
+{
+ if (!index.isValid())
+ return false;
+
+ QModelIndexList indexes;
+ if (rowCount(index) > 0)
+ indexes = collectItems(index);
+ indexes.append(index);
+
+ foreach (const QModelIndex &itemToRemove, indexes) {
+ if (!removeRow(itemToRemove.row(), itemToRemove.parent()))
+ return false;
+ cache.remove(itemFromIndex(itemToRemove));
+ }
+ return true;
+}
+
+int
+BookmarkModel::rowCount(const QModelIndex &index) const
+{
+ if (BookmarkItem *item = itemFromIndex(index))
+ return item->childCount();
+ return 0;
+}
+
+int
+BookmarkModel::columnCount(const QModelIndex &/*index*/) const
+{
+ return 2;
+}
+
+QModelIndex
+BookmarkModel::parent(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return QModelIndex();
+
+ if (BookmarkItem *childItem = itemFromIndex(index)) {
+ if (BookmarkItem *parent = childItem->parent()) {
+ if (parent != rootItem)
+ return createIndex(parent->childNumber(), 0, parent);
+ }
+ }
+ return QModelIndex();
+}
+
+QModelIndex
+BookmarkModel::index(int row, int column, const QModelIndex &index) const
+{
+ if (index.isValid() && (index.column() != 0 && index.column() != 1))
+ return QModelIndex();
+
+ if (BookmarkItem *parent = itemFromIndex(index)) {
+ if (BookmarkItem *childItem = parent->child(row))
+ return createIndex(row, column, childItem);
+ }
+ return QModelIndex();
+}
+
+Qt::DropActions
+BookmarkModel::supportedDropActions () const
+{
+ return /* Qt::CopyAction | */Qt::MoveAction;
+}
+
+Qt::ItemFlags
+BookmarkModel::flags(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return Qt::NoItemFlags;
+
+ Qt::ItemFlags defaultFlags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+
+ if (m_editable)
+ defaultFlags |= Qt::ItemIsEditable;
+
+ if (itemFromIndex(index) && index.data(UserRoleFolder).toBool()) {
+ if (index.column() > 0)
+ return defaultFlags &~ Qt::ItemIsEditable;
+ return defaultFlags | Qt::ItemIsDropEnabled;
+ }
+
+ return defaultFlags | Qt::ItemIsDragEnabled;
+}
+
+QVariant
+BookmarkModel::data(const QModelIndex &index, int role) const
+{
+ if (index.isValid()) {
+ if (BookmarkItem *item = itemFromIndex(index)) {
+ switch (role) {
+ case Qt::EditRole: {
+ case Qt::DisplayRole:
+ if (index.data(UserRoleFolder).toBool() && index.column() == 1)
+ return QLatin1String("");
+ return item->data(index.column());
+ } break;
+
+ case Qt::DecorationRole: {
+ if (index.column() == 0)
+ return index.data(UserRoleFolder).toBool()
+ ? folderIcon : bookmarkIcon;
+ } break;
+
+ default:;
+ return item->data(role);
+ }
+ }
+ }
+ return QVariant();
+}
+
+void BookmarkModel::setData(const QModelIndex &index, const DataVector &data)
+{
+ if (BookmarkItem *item = itemFromIndex(index)) {
+ item->setData(data);
+ emit dataChanged(index, index);
+ }
+}
+
+bool
+BookmarkModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ bool result = false;
+ if (role != Qt::EditRole && role != UserRoleExpanded)
+ return result;
+
+ if (BookmarkItem *item = itemFromIndex(index)) {
+ if (role == Qt::EditRole) {
+ const bool isFolder = index.data(UserRoleFolder).toBool();
+ if (!isFolder || (isFolder && index.column() == 0))
+ result = item->setData(index.column(), value);
+ } else if (role == UserRoleExpanded) {
+ result = item->setData(UserRoleExpanded, value);
+ }
+ }
+
+ if (result)
+ emit dataChanged(index, index);
+ return result;
+}
+
+QVariant
+BookmarkModel::headerData(int section, Qt::Orientation orientation,
+ int role) const
+{
+ if (rootItem && orientation == Qt::Horizontal && role == Qt::DisplayRole)
+ return rootItem->data(section);
+ return QVariant();
+}
+
+QModelIndex
+BookmarkModel::indexFromItem(BookmarkItem *item) const
+{
+ return cache.value(item, QModelIndex());
+}
+
+BookmarkItem*
+BookmarkModel::itemFromIndex(const QModelIndex &index) const
+{
+ if (index.isValid())
+ return static_cast<BookmarkItem*>(index.internalPointer());
+ return rootItem;
+}
+
+QList<QPersistentModelIndex>
+BookmarkModel::indexListFor(const QString &label) const
+{
+ QList<QPersistentModelIndex> hits;
+ const QModelIndexList &list = collectItems(QModelIndex());
+ foreach(const QModelIndex &index, list) {
+ if (index.data().toString().contains(label, Qt::CaseInsensitive))
+ hits.prepend(index); // list is reverse sorted
+ }
+ return hits;
+}
+
+bool
+BookmarkModel::insertRows(int position, int rows, const QModelIndex &parent)
+{
+ if (!parent.data(UserRoleFolder).toBool())
+ return false;
+
+ bool success = false;
+ if (BookmarkItem *parentItem = itemFromIndex(parent)) {
+ beginInsertRows(parent, position, position + rows - 1);
+ success = parentItem->insertChildren(m_folder, position, rows);
+ if (success) {
+ const QModelIndex &current = index(position, 0, parent);
+ cache.insert(itemFromIndex(current), current);
+ }
+ endInsertRows();
+ }
+ return success;
+}
+
+bool
+BookmarkModel::removeRows(int position, int rows, const QModelIndex &index)
+{
+ bool success = false;
+ if (BookmarkItem *parent = itemFromIndex(index)) {
+ beginRemoveRows(index, position, position + rows - 1);
+ success = parent->removeChildren(position, rows);
+ endRemoveRows();
+ }
+ return success;
+}
+
+QStringList
+BookmarkModel::mimeTypes() const
+{
+ return QStringList() << MIMETYPE;
+}
+
+QMimeData*
+BookmarkModel::mimeData(const QModelIndexList &indexes) const
+{
+ if (indexes.isEmpty())
+ return 0;
+
+ QByteArray data;
+ QDataStream stream(&data, QIODevice::WriteOnly);
+
+ foreach (const QModelIndex &index, indexes) {
+ if (index.column() == 0)
+ collectItems(index, 0, &stream);
+ }
+
+ QMimeData *mimeData = new QMimeData();
+ mimeData->setData(MIMETYPE, data);
+ return mimeData;
+}
+
+bool
+BookmarkModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent)
+{
+ if (action == Qt::IgnoreAction)
+ return true;
+
+ if (!data->hasFormat(MIMETYPE) || column > 0)
+ return false;
+
+ QByteArray ba = data->data(MIMETYPE);
+ QDataStream stream(&ba, QIODevice::ReadOnly);
+ while (stream.atEnd())
+ return false;
+
+ qint32 depth;
+ bool expanded;
+ QString name, url;
+ while (!stream.atEnd()) {
+ stream >> depth >> name >> url >> expanded;
+ if (insertRow(qMax(0, row), parent)) {
+ const QModelIndex &current = index(qMax(0, row), 0, parent);
+ if (current.isValid()) {
+ BookmarkItem* item = itemFromIndex(current);
+ item->setData(DataVector() << name << url << expanded);
+ }
+ }
+ }
+ return true;
+}
+
+void
+BookmarkModel::setupCache(const QModelIndex &parent)
+{
+ const QModelIndexList &list = collectItems(parent);
+ foreach (const QModelIndex &index, list)
+ cache.insert(itemFromIndex(index), index);
+}
+
+QModelIndexList
+BookmarkModel::collectItems(const QModelIndex &parent) const
+{
+ QModelIndexList list;
+ for (int i = rowCount(parent) - 1; i >= 0 ; --i) {
+ const QModelIndex &next = index(i, 0, parent);
+ if (data(next, UserRoleFolder).toBool())
+ list += collectItems(next);
+ list.append(next);
+ }
+ return list;
+}
+
+void
+BookmarkModel::collectItems(const QModelIndex &parent, qint32 depth,
+ QDataStream *stream) const
+{
+ if (parent.isValid()) {
+ *stream << depth;
+ *stream << parent.data().toString();
+ *stream << parent.data(UserRoleUrl).toString();
+ *stream << parent.data(UserRoleExpanded).toBool();
+
+ for (int i = 0; i < rowCount(parent); ++i) {
+ if (parent.data(UserRoleFolder).toBool())
+ collectItems(index(i, 0 , parent), depth + 1, stream);
+ }
+ }
+}
diff --git a/src/assistant/tools/assistant/bookmarkmodel.h b/src/assistant/tools/assistant/bookmarkmodel.h
new file mode 100644
index 000000000..33c9e981d
--- /dev/null
+++ b/src/assistant/tools/assistant/bookmarkmodel.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+#ifndef BOOKMARKMODEL_H
+#define BOOKMARKMODEL_H
+
+#include <QtCore/QAbstractItemModel>
+
+#include <QtGui/QIcon>
+
+QT_BEGIN_NAMESPACE
+
+class BookmarkItem;
+class QMimeData;
+class QTreeView;
+
+typedef QMap<BookmarkItem*, QPersistentModelIndex> ItemModelIndexCache;
+
+class BookmarkModel : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+ BookmarkModel();
+ ~BookmarkModel();
+
+ QByteArray bookmarks() const;
+ void setBookmarks(const QByteArray &bookmarks);
+
+ void setItemsEditable(bool editable);
+ void expandFoldersIfNeeeded(QTreeView *treeView);
+
+ QModelIndex addItem(const QModelIndex &parent, bool isFolder = false);
+ bool removeItem(const QModelIndex &index);
+
+ int rowCount(const QModelIndex &index = QModelIndex()) const;
+ int columnCount(const QModelIndex &index = QModelIndex()) const;
+
+ QModelIndex parent(const QModelIndex &index) const;
+ QModelIndex index(int row, int column, const QModelIndex &index) const;
+
+ Qt::DropActions supportedDropActions () const;
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+
+ QVariant data(const QModelIndex &index, int role) const;
+ void setData(const QModelIndex &index, const QVector<QVariant> &data);
+ bool setData(const QModelIndex &index, const QVariant &value, int role);
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+
+ QModelIndex indexFromItem(BookmarkItem *item) const;
+ BookmarkItem *itemFromIndex(const QModelIndex &index) const;
+ QList<QPersistentModelIndex> indexListFor(const QString &label) const;
+
+ bool insertRows(int position, int rows, const QModelIndex &parent);
+ bool removeRows(int position, int rows, const QModelIndex &parent);
+
+ QStringList mimeTypes() const;
+ QMimeData* mimeData(const QModelIndexList &indexes) const;
+ bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row,
+ int column, const QModelIndex &parent);
+
+private:
+ void setupCache(const QModelIndex &parent);
+ QModelIndexList collectItems(const QModelIndex &parent) const;
+ void collectItems(const QModelIndex &parent, qint32 depth,
+ QDataStream *stream) const;
+
+private:
+ int columns;
+ bool m_folder;
+ bool m_editable;
+ QIcon folderIcon;
+ QIcon bookmarkIcon;
+ QTreeView *treeView;
+ BookmarkItem *rootItem;
+ ItemModelIndexCache cache;
+};
+
+QT_END_NAMESPACE
+
+#endif // BOOKMARKMODEL_H
diff --git a/src/assistant/tools/assistant/bookmarkwidget.ui b/src/assistant/tools/assistant/bookmarkwidget.ui
new file mode 100644
index 000000000..a31a2779c
--- /dev/null
+++ b/src/assistant/tools/assistant/bookmarkwidget.ui
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>BookmarkWidget</class>
+ <widget class="QWidget" name="BookmarkWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>235</width>
+ <height>606</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Bookmarks</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="margin">
+ <number>4</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Filter:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="lineEdit"/>
+ </item>
+ <item>
+ <widget class="QStackedWidget" name="stackedWidget"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="add">
+ <property name="text">
+ <string>Add</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="remove">
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/assistant/tools/assistant/centralwidget.cpp b/src/assistant/tools/assistant/centralwidget.cpp
new file mode 100644
index 000000000..c8c454f60
--- /dev/null
+++ b/src/assistant/tools/assistant/centralwidget.cpp
@@ -0,0 +1,636 @@
+/****************************************************************************
+**
+** 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 "centralwidget.h"
+
+#include "findwidget.h"
+#include "helpenginewrapper.h"
+#include "helpviewer.h"
+#include "openpagesmanager.h"
+#include "tracer.h"
+#include "../shared/collectionconfiguration.h"
+
+#include <QtCore/QTimer>
+
+#include <QtGui/QKeyEvent>
+#include <QtGui/QMenu>
+#include <QtGui/QPageSetupDialog>
+#include <QtGui/QPrintDialog>
+#include <QtGui/QPrintPreviewDialog>
+#include <QtGui/QPrinter>
+#include <QtGui/QStackedWidget>
+#include <QtGui/QTextBrowser>
+#include <QtGui/QVBoxLayout>
+
+#include <QtHelp/QHelpSearchEngine>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ CentralWidget *staticCentralWidget = 0;
+}
+
+// -- TabBar
+
+TabBar::TabBar(QWidget *parent)
+ : QTabBar(parent)
+{
+ TRACE_OBJ
+#ifdef Q_OS_MAC
+ setDocumentMode(true);
+#endif
+ setMovable(true);
+ setShape(QTabBar::RoundedNorth);
+ setContextMenuPolicy(Qt::CustomContextMenu);
+ setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred,
+ QSizePolicy::TabWidget));
+ connect(this, SIGNAL(currentChanged(int)), this, SLOT(slotCurrentChanged(int)));
+ connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(slotTabCloseRequested(int)));
+ connect(this, SIGNAL(customContextMenuRequested(QPoint)), this,
+ SLOT(slotCustomContextMenuRequested(QPoint)));
+}
+
+TabBar::~TabBar()
+{
+ TRACE_OBJ
+}
+
+int TabBar::addNewTab(const QString &title)
+{
+ TRACE_OBJ
+ const int index = addTab(title);
+ setTabsClosable(count() > 1);
+ return index;
+}
+
+void TabBar::setCurrent(HelpViewer *viewer)
+{
+ TRACE_OBJ
+ for (int i = 0; i < count(); ++i) {
+ HelpViewer *data = tabData(i).value<HelpViewer*>();
+ if (data == viewer) {
+ setCurrentIndex(i);
+ break;
+ }
+ }
+}
+
+void TabBar::removeTabAt(HelpViewer *viewer)
+{
+ TRACE_OBJ
+ for (int i = 0; i < count(); ++i) {
+ HelpViewer *data = tabData(i).value<HelpViewer*>();
+ if (data == viewer) {
+ removeTab(i);
+ break;
+ }
+ }
+ setTabsClosable(count() > 1);
+}
+
+void TabBar::titleChanged()
+{
+ TRACE_OBJ
+ for (int i = 0; i < count(); ++i) {
+ HelpViewer *data = tabData(i).value<HelpViewer*>();
+ QString title = data->title();
+ title.replace(QLatin1Char('&'), QLatin1String("&&"));
+ setTabText(i, title.isEmpty() ? tr("(Untitled)") : title);
+ }
+}
+
+void TabBar::slotCurrentChanged(int index)
+{
+ TRACE_OBJ
+ emit currentTabChanged(tabData(index).value<HelpViewer*>());
+}
+
+void TabBar::slotTabCloseRequested(int index)
+{
+ TRACE_OBJ
+ OpenPagesManager::instance()->closePage(tabData(index).value<HelpViewer*>());
+}
+
+void TabBar::slotCustomContextMenuRequested(const QPoint &pos)
+{
+ TRACE_OBJ
+ const int tab = tabAt(pos);
+ if (tab < 0)
+ return;
+
+ QMenu menu(QLatin1String(""), this);
+ menu.addAction(tr("New &Tab"), OpenPagesManager::instance(), SLOT(createPage()));
+
+ const bool enableAction = count() > 1;
+ QAction *closePage = menu.addAction(tr("&Close Tab"));
+ closePage->setEnabled(enableAction);
+
+ QAction *closePages = menu.addAction(tr("Close Other Tabs"));
+ closePages->setEnabled(enableAction);
+
+ menu.addSeparator();
+
+ HelpViewer *viewer = tabData(tab).value<HelpViewer*>();
+ QAction *newBookmark = menu.addAction(tr("Add Bookmark for this Page..."));
+ const QString &url = viewer->source().toString();
+ if (url.isEmpty() || url == QLatin1String("about:blank"))
+ newBookmark->setEnabled(false);
+
+ QAction *pickedAction = menu.exec(mapToGlobal(pos));
+ if (pickedAction == closePage)
+ slotTabCloseRequested(tab);
+ else if (pickedAction == closePages) {
+ for (int i = count() - 1; i >= 0; --i) {
+ if (i != tab)
+ slotTabCloseRequested(i);
+ }
+ } else if (pickedAction == newBookmark)
+ emit addBookmark(viewer->title(), url);
+}
+
+// -- CentralWidget
+
+CentralWidget::CentralWidget(QWidget *parent)
+ : QWidget(parent)
+#ifndef QT_NO_PRINTER
+ , m_printer(0)
+#endif
+ , m_findWidget(new FindWidget(this))
+ , m_stackedWidget(new QStackedWidget(this))
+ , m_tabBar(new TabBar(this))
+{
+ TRACE_OBJ
+ staticCentralWidget = this;
+ QVBoxLayout *vboxLayout = new QVBoxLayout(this);
+
+ vboxLayout->setMargin(0);
+ vboxLayout->setSpacing(0);
+ vboxLayout->addWidget(m_tabBar);
+ m_tabBar->setVisible(HelpEngineWrapper::instance().showTabs());
+ vboxLayout->addWidget(m_stackedWidget);
+ vboxLayout->addWidget(m_findWidget);
+ m_findWidget->hide();
+
+ connect(m_findWidget, SIGNAL(findNext()), this, SLOT(findNext()));
+ connect(m_findWidget, SIGNAL(findPrevious()), this, SLOT(findPrevious()));
+ connect(m_findWidget, SIGNAL(find(QString, bool, bool)), this,
+ SLOT(find(QString, bool, bool)));
+ connect(m_findWidget, SIGNAL(escapePressed()), this, SLOT(activateTab()));
+ connect(m_tabBar, SIGNAL(addBookmark(QString, QString)), this,
+ SIGNAL(addBookmark(QString, QString)));
+}
+
+CentralWidget::~CentralWidget()
+{
+ TRACE_OBJ
+ QStringList zoomFactors;
+ QStringList currentPages;
+ for (int i = 0; i < m_stackedWidget->count(); ++i) {
+ const HelpViewer * const viewer = viewerAt(i);
+ const QUrl &source = viewer->source();
+ if (source.isValid()) {
+ currentPages << source.toString();
+ zoomFactors << QString::number(viewer->scale());
+ }
+ }
+
+ HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance();
+ helpEngine.setLastShownPages(currentPages);
+ helpEngine.setLastZoomFactors(zoomFactors);
+ helpEngine.setLastTabPage(m_stackedWidget->currentIndex());
+
+#ifndef QT_NO_PRINTER
+ delete m_printer;
+#endif
+}
+
+CentralWidget *CentralWidget::instance()
+{
+ TRACE_OBJ
+ return staticCentralWidget;
+}
+
+QUrl CentralWidget::currentSource() const
+{
+ TRACE_OBJ
+ return currentHelpViewer()->source();
+}
+
+QString CentralWidget::currentTitle() const
+{
+ TRACE_OBJ
+ return currentHelpViewer()->title();
+}
+
+bool CentralWidget::hasSelection() const
+{
+ TRACE_OBJ
+ return !currentHelpViewer()->selectedText().isEmpty();
+}
+
+bool CentralWidget::isForwardAvailable() const
+{
+ TRACE_OBJ
+ return currentHelpViewer()->isForwardAvailable();
+}
+
+bool CentralWidget::isBackwardAvailable() const
+{
+ TRACE_OBJ
+ return currentHelpViewer()->isBackwardAvailable();
+}
+
+HelpViewer* CentralWidget::viewerAt(int index) const
+{
+ TRACE_OBJ
+ return static_cast<HelpViewer*>(m_stackedWidget->widget(index));
+}
+
+HelpViewer* CentralWidget::currentHelpViewer() const
+{
+ TRACE_OBJ
+ return static_cast<HelpViewer *>(m_stackedWidget->currentWidget());
+}
+
+void CentralWidget::addPage(HelpViewer *page, bool fromSearch)
+{
+ TRACE_OBJ
+ page->installEventFilter(this);
+ page->setFocus(Qt::OtherFocusReason);
+ connectSignals(page);
+ const int index = m_stackedWidget->addWidget(page);
+ m_tabBar->setTabData(m_tabBar->addNewTab(page->title()),
+ QVariant::fromValue(viewerAt(index)));
+ connect (page, SIGNAL(titleChanged()), m_tabBar, SLOT(titleChanged()));
+
+ if (fromSearch) {
+ connect(currentHelpViewer(), SIGNAL(loadFinished(bool)), this,
+ SLOT(highlightSearchTerms()));
+ }
+}
+
+void CentralWidget::removePage(int index)
+{
+ TRACE_OBJ
+ const bool currentChanged = index == currentIndex();
+ m_tabBar->removeTabAt(viewerAt(index));
+ m_stackedWidget->removeWidget(m_stackedWidget->widget(index));
+ if (currentChanged)
+ emit currentViewerChanged();
+}
+
+int CentralWidget::currentIndex() const
+{
+ TRACE_OBJ
+ return m_stackedWidget->currentIndex();
+}
+
+void CentralWidget::setCurrentPage(HelpViewer *page)
+{
+ TRACE_OBJ
+ m_tabBar->setCurrent(page);
+ m_stackedWidget->setCurrentWidget(page);
+ emit currentViewerChanged();
+}
+
+void CentralWidget::connectTabBar()
+{
+ TRACE_OBJ
+ connect(m_tabBar, SIGNAL(currentTabChanged(HelpViewer*)),
+ OpenPagesManager::instance(), SLOT(setCurrentPage(HelpViewer*)));
+}
+
+// -- public slots
+
+void CentralWidget::copy()
+{
+ TRACE_OBJ
+ currentHelpViewer()->copy();
+}
+
+void CentralWidget::home()
+{
+ TRACE_OBJ
+ currentHelpViewer()->home();
+}
+
+void CentralWidget::zoomIn()
+{
+ TRACE_OBJ
+ currentHelpViewer()->scaleUp();
+}
+
+void CentralWidget::zoomOut()
+{
+ TRACE_OBJ
+ currentHelpViewer()->scaleDown();
+}
+
+void CentralWidget::resetZoom()
+{
+ TRACE_OBJ
+ currentHelpViewer()->resetScale();
+}
+
+void CentralWidget::forward()
+{
+ TRACE_OBJ
+ currentHelpViewer()->forward();
+}
+
+void CentralWidget::nextPage()
+{
+ TRACE_OBJ
+ m_stackedWidget->setCurrentIndex((m_stackedWidget->currentIndex() + 1)
+ % m_stackedWidget->count());
+}
+
+void CentralWidget::backward()
+{
+ TRACE_OBJ
+ currentHelpViewer()->backward();
+}
+
+void CentralWidget::previousPage()
+{
+ TRACE_OBJ
+ m_stackedWidget->setCurrentIndex((m_stackedWidget->currentIndex() - 1)
+ % m_stackedWidget->count());
+}
+
+void CentralWidget::print()
+{
+ TRACE_OBJ
+#ifndef QT_NO_PRINTER
+ initPrinter();
+ QPrintDialog dlg(m_printer, this);
+
+ if (!currentHelpViewer()->selectedText().isEmpty())
+ dlg.addEnabledOption(QAbstractPrintDialog::PrintSelection);
+ dlg.addEnabledOption(QAbstractPrintDialog::PrintPageRange);
+ dlg.addEnabledOption(QAbstractPrintDialog::PrintCollateCopies);
+ dlg.setWindowTitle(tr("Print Document"));
+ if (dlg.exec() == QDialog::Accepted)
+ currentHelpViewer()->print(m_printer);
+#endif
+}
+
+void CentralWidget::pageSetup()
+{
+ TRACE_OBJ
+#ifndef QT_NO_PRINTER
+ initPrinter();
+ QPageSetupDialog dlg(m_printer);
+ dlg.exec();
+#endif
+}
+
+void CentralWidget::printPreview()
+{
+ TRACE_OBJ
+#ifndef QT_NO_PRINTER
+ initPrinter();
+ QPrintPreviewDialog preview(m_printer, this);
+ connect(&preview, SIGNAL(paintRequested(QPrinter*)),
+ SLOT(printPreview(QPrinter*)));
+ preview.exec();
+#endif
+}
+
+void CentralWidget::setSource(const QUrl &url)
+{
+ TRACE_OBJ
+ HelpViewer *viewer = currentHelpViewer();
+ viewer->setSource(url);
+ viewer->setFocus(Qt::OtherFocusReason);
+}
+
+void CentralWidget::setSourceFromSearch(const QUrl &url)
+{
+ TRACE_OBJ
+ connect(currentHelpViewer(), SIGNAL(loadFinished(bool)), this,
+ SLOT(highlightSearchTerms()));
+ currentHelpViewer()->setSource(url);
+ currentHelpViewer()->setFocus(Qt::OtherFocusReason);
+}
+
+void CentralWidget::findNext()
+{
+ TRACE_OBJ
+ find(m_findWidget->text(), true, false);
+}
+
+void CentralWidget::findPrevious()
+{
+ TRACE_OBJ
+ find(m_findWidget->text(), false, false);
+}
+
+void CentralWidget::find(const QString &ttf, bool forward, bool incremental)
+{
+ TRACE_OBJ
+ bool found = false;
+ if (HelpViewer *viewer = currentHelpViewer()) {
+ HelpViewer::FindFlags flags = 0;
+ if (!forward)
+ flags |= HelpViewer::FindBackward;
+ if (m_findWidget->caseSensitive())
+ flags |= HelpViewer::FindCaseSensitively;
+ found = viewer->findText(ttf, flags, incremental, false);
+ }
+
+ if (!found && ttf.isEmpty())
+ found = true; // the line edit is empty, no need to mark it red...
+
+ if (!m_findWidget->isVisible())
+ m_findWidget->show();
+ m_findWidget->setPalette(found);
+}
+
+void CentralWidget::activateTab()
+{
+ TRACE_OBJ
+ currentHelpViewer()->setFocus();
+}
+
+void CentralWidget::showTextSearch()
+{
+ TRACE_OBJ
+ m_findWidget->show();
+}
+
+void CentralWidget::updateBrowserFont()
+{
+ TRACE_OBJ
+ const int count = m_stackedWidget->count();
+ const QFont &font = viewerAt(count - 1)->viewerFont();
+ for (int i = 0; i < count; ++i)
+ viewerAt(i)->setViewerFont(font);
+}
+
+void CentralWidget::updateUserInterface()
+{
+ m_tabBar->setVisible(HelpEngineWrapper::instance().showTabs());
+}
+
+// -- protected
+
+void CentralWidget::keyPressEvent(QKeyEvent *e)
+{
+ TRACE_OBJ
+ const QString &text = e->text();
+ if (text.startsWith(QLatin1Char('/'))) {
+ if (!m_findWidget->isVisible()) {
+ m_findWidget->showAndClear();
+ } else {
+ m_findWidget->show();
+ }
+ } else {
+ QWidget::keyPressEvent(e);
+ }
+}
+
+void CentralWidget::focusInEvent(QFocusEvent * /* event */)
+{
+ TRACE_OBJ
+ // If we have a current help viewer then this is the 'focus proxy',
+ // otherwise it's the central widget. This is needed, so an embedding
+ // program can just set the focus to the central widget and it does
+ // The Right Thing(TM)
+ QObject *receiver = m_stackedWidget;
+ if (HelpViewer *viewer = currentHelpViewer())
+ receiver = viewer;
+ QTimer::singleShot(1, receiver, SLOT(setFocus()));
+}
+
+// -- private slots
+
+void CentralWidget::highlightSearchTerms()
+{
+ TRACE_OBJ
+ QHelpSearchEngine *searchEngine =
+ HelpEngineWrapper::instance().searchEngine();
+ QList<QHelpSearchQuery> queryList = searchEngine->query();
+
+ QStringList terms;
+ foreach (const QHelpSearchQuery &query, queryList) {
+ switch (query.fieldName) {
+ default: break;
+ case QHelpSearchQuery::ALL: {
+ case QHelpSearchQuery::PHRASE:
+ case QHelpSearchQuery::DEFAULT:
+ case QHelpSearchQuery::ATLEAST:
+ foreach (QString term, query.wordList)
+ terms.append(term.remove(QLatin1Char('"')));
+ }
+ }
+ }
+
+ HelpViewer *viewer = currentHelpViewer();
+ foreach (const QString& term, terms)
+ viewer->findText(term, 0, false, true);
+ disconnect(viewer, SIGNAL(loadFinished(bool)), this,
+ SLOT(highlightSearchTerms()));
+}
+
+void CentralWidget::printPreview(QPrinter *p)
+{
+ TRACE_OBJ
+#ifndef QT_NO_PRINTER
+ currentHelpViewer()->print(p);
+#endif
+}
+
+void CentralWidget::handleSourceChanged(const QUrl &url)
+{
+ TRACE_OBJ
+ if (sender() == currentHelpViewer())
+ emit sourceChanged(url);
+}
+
+// -- private
+
+void CentralWidget::initPrinter()
+{
+ TRACE_OBJ
+#ifndef QT_NO_PRINTER
+ if (!m_printer)
+ m_printer = new QPrinter(QPrinter::HighResolution);
+#endif
+}
+
+void CentralWidget::connectSignals(HelpViewer *page)
+{
+ TRACE_OBJ
+ connect(page, SIGNAL(copyAvailable(bool)), this,
+ SIGNAL(copyAvailable(bool)));
+ connect(page, SIGNAL(forwardAvailable(bool)), this,
+ SIGNAL(forwardAvailable(bool)));
+ connect(page, SIGNAL(backwardAvailable(bool)), this,
+ SIGNAL(backwardAvailable(bool)));
+ connect(page, SIGNAL(sourceChanged(QUrl)), this,
+ SLOT(handleSourceChanged(QUrl)));
+ connect(page, SIGNAL(highlighted(QString)), this,
+ SIGNAL(highlighted(QString)));
+ connect(page, SIGNAL(printRequested()), this, SLOT(print()));
+}
+
+bool CentralWidget::eventFilter(QObject *object, QEvent *e)
+{
+ TRACE_OBJ
+ if (e->type() != QEvent::KeyPress)
+ return QWidget::eventFilter(object, e);
+
+ HelpViewer *viewer = currentHelpViewer();
+ QKeyEvent *keyEvent = static_cast<QKeyEvent*> (e);
+ if (viewer == object && keyEvent->key() == Qt::Key_Backspace) {
+ if (viewer->isBackwardAvailable()) {
+#if !defined(QT_NO_WEBKIT)
+ // this helps in case there is an html <input> field
+ if (!viewer->hasFocus())
+#endif
+ viewer->backward();
+ }
+ }
+ return QWidget::eventFilter(object, e);
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/centralwidget.h b/src/assistant/tools/assistant/centralwidget.h
new file mode 100644
index 000000000..2645fa8df
--- /dev/null
+++ b/src/assistant/tools/assistant/centralwidget.h
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef CENTRALWIDGET_H
+#define CENTRALWIDGET_H
+
+#include <QtCore/QUrl>
+
+#include <QtGui/QTabBar>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class FindWidget;
+class HelpViewer;
+class QStackedWidget;
+
+class TabBar : public QTabBar
+{
+ Q_OBJECT
+public:
+ TabBar(QWidget *parent = 0);
+ ~TabBar();
+
+ int addNewTab(const QString &title);
+ void setCurrent(HelpViewer *viewer);
+ void removeTabAt(HelpViewer *viewer);
+
+public slots:
+ void titleChanged();
+
+signals:
+ void currentTabChanged(HelpViewer *viewer);
+ void addBookmark(const QString &title, const QString &url);
+
+private slots:
+ void slotCurrentChanged(int index);
+ void slotTabCloseRequested(int index);
+ void slotCustomContextMenuRequested(const QPoint &pos);
+};
+
+class CentralWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ CentralWidget(QWidget *parent = 0);
+ ~CentralWidget();
+
+ static CentralWidget *instance();
+
+ QUrl currentSource() const;
+ QString currentTitle() const;
+
+ bool hasSelection() const;
+ bool isForwardAvailable() const;
+ bool isBackwardAvailable() const;
+
+ HelpViewer *viewerAt(int index) const;
+ HelpViewer *currentHelpViewer() const;
+
+ void addPage(HelpViewer *page, bool fromSearch = false);
+ void removePage(int index);
+
+ int currentIndex() const;
+ void setCurrentPage(HelpViewer *page);
+
+ void connectTabBar();
+
+public slots:
+ void copy();
+ void home();
+
+ void zoomIn();
+ void zoomOut();
+ void resetZoom();
+
+ void forward();
+ void nextPage();
+
+ void backward();
+ void previousPage();
+
+ void print();
+ void pageSetup();
+ void printPreview();
+
+ void setSource(const QUrl &url);
+ void setSourceFromSearch(const QUrl &url);
+
+ void findNext();
+ void findPrevious();
+ void find(const QString &text, bool forward, bool incremental);
+
+ void activateTab();
+ void showTextSearch();
+ void updateBrowserFont();
+ void updateUserInterface();
+
+signals:
+ void currentViewerChanged();
+ void copyAvailable(bool yes);
+ void sourceChanged(const QUrl &url);
+ void highlighted(const QString &link);
+ void forwardAvailable(bool available);
+ void backwardAvailable(bool available);
+ void addBookmark(const QString &title, const QString &url);
+
+protected:
+ void keyPressEvent(QKeyEvent *);
+ void focusInEvent(QFocusEvent *event);
+
+private slots:
+ void highlightSearchTerms();
+ void printPreview(QPrinter *printer);
+ void handleSourceChanged(const QUrl &url);
+
+private:
+ void initPrinter();
+ void connectSignals(HelpViewer *page);
+ bool eventFilter(QObject *object, QEvent *e);
+
+private:
+#ifndef QT_NO_PRINTER
+ QPrinter *m_printer;
+#endif
+ FindWidget *m_findWidget;
+ QStackedWidget *m_stackedWidget;
+ TabBar *m_tabBar;
+};
+
+QT_END_NAMESPACE
+
+#endif // CENTRALWIDGET_H
diff --git a/src/assistant/tools/assistant/cmdlineparser.cpp b/src/assistant/tools/assistant/cmdlineparser.cpp
new file mode 100644
index 000000000..6a239d305
--- /dev/null
+++ b/src/assistant/tools/assistant/cmdlineparser.cpp
@@ -0,0 +1,376 @@
+/****************************************************************************
+**
+** 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 "tracer.h"
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QStringBuilder>
+#include <QtGui/QMessageBox>
+
+#include "cmdlineparser.h"
+
+QT_BEGIN_NAMESPACE
+
+static const char helpMessage[] = QT_TRANSLATE_NOOP("CmdLineParser",
+ "Usage: assistant [Options]\n\n"
+ "-collectionFile file Uses the specified collection\n"
+ " file instead of the default one\n"
+ "-showUrl url Shows the document with the\n"
+ " url.\n"
+ "-enableRemoteControl Enables Assistant to be\n"
+ " remotely controlled.\n"
+ "-show widget Shows the specified dockwidget\n"
+ " which can be \"contents\", \"index\",\n"
+ " \"bookmarks\" or \"search\".\n"
+ "-activate widget Activates the specified dockwidget\n"
+ " which can be \"contents\", \"index\",\n"
+ " \"bookmarks\" or \"search\".\n"
+ "-hide widget Hides the specified dockwidget\n"
+ " which can be \"contents\", \"index\"\n"
+ " \"bookmarks\" or \"search\".\n"
+ "-register helpFile Registers the specified help file\n"
+ " (.qch) in the given collection\n"
+ " file.\n"
+ "-unregister helpFile Unregisters the specified help file\n"
+ " (.qch) from the give collection\n"
+ " file.\n"
+ "-setCurrentFilter filter Set the filter as the active filter.\n"
+ "-remove-search-index Removes the full text search index.\n"
+ "-rebuild-search-index Re-builds the full text search index (potentially slow).\n"
+ "-quiet Does not display any error or\n"
+ " status message.\n"
+ "-help Displays this help.\n"
+ );
+
+
+CmdLineParser::CmdLineParser(const QStringList &arguments)
+ : m_pos(0),
+ m_enableRemoteControl(false),
+ m_contents(Untouched),
+ m_index(Untouched),
+ m_bookmarks(Untouched),
+ m_search(Untouched),
+ m_register(None),
+ m_removeSearchIndex(false),
+ m_rebuildSearchIndex(false),
+ m_quiet(false)
+{
+ TRACE_OBJ
+ for (int i = 1; i < arguments.count(); ++i) {
+ const QString &arg = arguments.at(i);
+ if (arg.toLower() == "-quiet")
+ m_quiet = true;
+ else
+ m_arguments.append(arg);
+ }
+}
+
+CmdLineParser::Result CmdLineParser::parse()
+{
+ TRACE_OBJ
+ bool showHelp = false;
+
+ while (m_error.isEmpty() && hasMoreArgs()) {
+ const QString &arg = nextArg().toLower();
+ if (arg == QLatin1String("-collectionfile"))
+ handleCollectionFileOption();
+ else if (arg == QLatin1String("-showurl"))
+ handleShowUrlOption();
+ else if (arg == QLatin1String("-enableremotecontrol"))
+ m_enableRemoteControl = true;
+ else if (arg == QLatin1String("-show"))
+ handleShowOption();
+ else if (arg == QLatin1String("-hide"))
+ handleHideOption();
+ else if (arg == QLatin1String("-activate"))
+ handleActivateOption();
+ else if (arg == QLatin1String("-register"))
+ handleRegisterOption();
+ else if (arg == QLatin1String("-unregister"))
+ handleUnregisterOption();
+ else if (arg == QLatin1String("-setcurrentfilter"))
+ handleSetCurrentFilterOption();
+ else if (arg == QLatin1String("-remove-search-index"))
+ m_removeSearchIndex = true;
+ else if (arg == QLatin1String("-rebuild-search-index"))
+ m_rebuildSearchIndex = true;
+ else if (arg == QLatin1String("-help"))
+ showHelp = true;
+ else
+ m_error = tr("Unknown option: %1").arg(arg);
+ }
+
+ if (!m_error.isEmpty()) {
+ showMessage(m_error + QLatin1String("\n\n\n") + tr(helpMessage), true);
+ return Error;
+ } else if (showHelp) {
+ showMessage(tr(helpMessage), false);
+ return Help;
+ }
+ return Ok;
+}
+
+bool CmdLineParser::hasMoreArgs() const
+{
+ TRACE_OBJ
+ return m_pos < m_arguments.count();
+}
+
+const QString &CmdLineParser::nextArg()
+{
+ TRACE_OBJ
+ Q_ASSERT(hasMoreArgs());
+ return m_arguments.at(m_pos++);
+}
+
+void CmdLineParser::handleCollectionFileOption()
+{
+ TRACE_OBJ
+ if (hasMoreArgs()) {
+ const QString &fileName = nextArg();
+ m_collectionFile = getFileName(fileName);
+ if (m_collectionFile.isEmpty())
+ m_error = tr("The collection file '%1' does not exist.").
+ arg(fileName);
+ } else {
+ m_error = tr("Missing collection file.");
+ }
+}
+
+void CmdLineParser::handleShowUrlOption()
+{
+ TRACE_OBJ
+ if (hasMoreArgs()) {
+ const QString &urlString = nextArg();
+ QUrl url(urlString);
+ if (url.isValid()) {
+ m_url = url;
+ } else
+ m_error = tr("Invalid URL '%1'.").arg(urlString);
+ } else {
+ m_error = tr("Missing URL.");
+ }
+}
+
+void CmdLineParser::handleShowOption()
+{
+ TRACE_OBJ
+ handleShowOrHideOrActivateOption(Show);
+}
+
+void CmdLineParser::handleHideOption()
+{
+ TRACE_OBJ
+ handleShowOrHideOrActivateOption(Hide);
+}
+
+void CmdLineParser::handleActivateOption()
+{
+ TRACE_OBJ
+ handleShowOrHideOrActivateOption(Activate);
+}
+
+void CmdLineParser::handleShowOrHideOrActivateOption(ShowState state)
+{
+ TRACE_OBJ
+ if (hasMoreArgs()) {
+ const QString &widget = nextArg().toLower();
+ if (widget == QLatin1String("contents"))
+ m_contents = state;
+ else if (widget == QLatin1String("index"))
+ m_index = state;
+ else if (widget == QLatin1String("bookmarks"))
+ m_bookmarks = state;
+ else if (widget == QLatin1String("search"))
+ m_search = state;
+ else
+ m_error = tr("Unknown widget: %1").arg(widget);
+ } else {
+ m_error = tr("Missing widget.");
+ }
+}
+
+void CmdLineParser::handleRegisterOption()
+{
+ TRACE_OBJ
+ handleRegisterOrUnregisterOption(Register);
+}
+
+void CmdLineParser::handleUnregisterOption()
+{
+ TRACE_OBJ
+ handleRegisterOrUnregisterOption(Unregister);
+}
+
+void CmdLineParser::handleRegisterOrUnregisterOption(RegisterState state)
+{
+ TRACE_OBJ
+ if (hasMoreArgs()) {
+ const QString &fileName = nextArg();
+ m_helpFile = getFileName(fileName);
+ if (m_helpFile.isEmpty())
+ m_error = tr("The Qt help file '%1' does not exist.").arg(fileName);
+ else
+ m_register = state;
+ } else {
+ m_error = tr("Missing help file.");
+ }
+}
+
+void CmdLineParser::handleSetCurrentFilterOption()
+{
+ TRACE_OBJ
+ if (hasMoreArgs())
+ m_currentFilter = nextArg();
+ else
+ m_error = tr("Missing filter argument.");
+}
+
+QString CmdLineParser::getFileName(const QString &fileName)
+{
+ TRACE_OBJ
+ QFileInfo fi(fileName);
+ if (!fi.exists())
+ return QString();
+ return fi.absoluteFilePath();
+}
+
+void CmdLineParser::showMessage(const QString &msg, bool error)
+{
+ TRACE_OBJ
+ if (m_quiet)
+ return;
+#ifdef Q_OS_WIN
+ QString message = QLatin1String("<pre>") % msg % QLatin1String("</pre>");
+ if (error)
+ QMessageBox::critical(0, tr("Error"), message);
+ else
+ QMessageBox::information(0, tr("Notice"), message);
+#else
+ fprintf(error ? stderr : stdout, "%s\n", qPrintable(msg));
+#endif
+}
+
+void CmdLineParser::setCollectionFile(const QString &file)
+{
+ TRACE_OBJ
+ m_collectionFile = file;
+}
+
+QString CmdLineParser::collectionFile() const
+{
+ TRACE_OBJ
+ return m_collectionFile;
+}
+
+bool CmdLineParser::collectionFileGiven() const
+{
+ TRACE_OBJ
+ return m_arguments.contains(QLatin1String("-collectionfile"),
+ Qt::CaseInsensitive);
+}
+
+QUrl CmdLineParser::url() const
+{
+ TRACE_OBJ
+ return m_url;
+}
+
+bool CmdLineParser::enableRemoteControl() const
+{
+ TRACE_OBJ
+ return m_enableRemoteControl;
+}
+
+CmdLineParser::ShowState CmdLineParser::contents() const
+{
+ TRACE_OBJ
+ return m_contents;
+}
+
+CmdLineParser::ShowState CmdLineParser::index() const
+{
+ TRACE_OBJ
+ return m_index;
+}
+
+CmdLineParser::ShowState CmdLineParser::bookmarks() const
+{
+ TRACE_OBJ
+ return m_bookmarks;
+}
+
+CmdLineParser::ShowState CmdLineParser::search() const
+{
+ TRACE_OBJ
+ return m_search;
+}
+
+QString CmdLineParser::currentFilter() const
+{
+ TRACE_OBJ
+ return m_currentFilter;
+}
+
+bool CmdLineParser::removeSearchIndex() const
+{
+ TRACE_OBJ
+ return m_removeSearchIndex;
+}
+
+bool CmdLineParser::rebuildSearchIndex() const
+{
+ TRACE_OBJ
+ return m_rebuildSearchIndex;
+}
+
+CmdLineParser::RegisterState CmdLineParser::registerRequest() const
+{
+ TRACE_OBJ
+ return m_register;
+}
+
+QString CmdLineParser::helpFile() const
+{
+ TRACE_OBJ
+ return m_helpFile;
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/cmdlineparser.h b/src/assistant/tools/assistant/cmdlineparser.h
new file mode 100644
index 000000000..f45679f66
--- /dev/null
+++ b/src/assistant/tools/assistant/cmdlineparser.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef CMDLINEPARSER_H
+#define CMDLINEPARSER_H
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QStringList>
+#include <QtCore/QUrl>
+
+QT_BEGIN_NAMESPACE
+
+class CmdLineParser
+{
+ Q_DECLARE_TR_FUNCTIONS(CmdLineParser)
+public:
+ enum Result {Ok, Help, Error};
+ enum ShowState {Untouched, Show, Hide, Activate};
+ enum RegisterState {None, Register, Unregister};
+
+ CmdLineParser(const QStringList &arguments);
+ Result parse();
+
+ void setCollectionFile(const QString &file);
+ QString collectionFile() const;
+ bool collectionFileGiven() const;
+ QString cloneFile() const;
+ QUrl url() const;
+ bool enableRemoteControl() const;
+ ShowState contents() const;
+ ShowState index() const;
+ ShowState bookmarks() const;
+ ShowState search() const;
+ QString currentFilter() const;
+ bool removeSearchIndex() const;
+ bool rebuildSearchIndex() const;
+ RegisterState registerRequest() const;
+ QString helpFile() const;
+
+ void showMessage(const QString &msg, bool error);
+
+private:
+ QString getFileName(const QString &fileName);
+ bool hasMoreArgs() const;
+ const QString &nextArg();
+ void handleCollectionFileOption();
+ void handleShowUrlOption();
+ void handleShowOption();
+ void handleHideOption();
+ void handleActivateOption();
+ void handleShowOrHideOrActivateOption(ShowState state);
+ void handleRegisterOption();
+ void handleUnregisterOption();
+ void handleRegisterOrUnregisterOption(RegisterState state);
+ void handleSetCurrentFilterOption();
+
+ QStringList m_arguments;
+ int m_pos;
+ QString m_collectionFile;
+ QString m_cloneFile;
+ QString m_helpFile;
+ QUrl m_url;
+ bool m_enableRemoteControl;
+
+ ShowState m_contents;
+ ShowState m_index;
+ ShowState m_bookmarks;
+ ShowState m_search;
+ RegisterState m_register;
+ QString m_currentFilter;
+ bool m_removeSearchIndex;
+ bool m_rebuildSearchIndex;
+ bool m_quiet;
+ QString m_error;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/assistant/tools/assistant/contentwindow.cpp b/src/assistant/tools/assistant/contentwindow.cpp
new file mode 100644
index 000000000..fbf70aa1f
--- /dev/null
+++ b/src/assistant/tools/assistant/contentwindow.cpp
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** 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 "contentwindow.h"
+
+#include "centralwidget.h"
+#include "helpenginewrapper.h"
+#include "helpviewer.h"
+#include "openpagesmanager.h"
+#include "tracer.h"
+
+#include <QtGui/QLayout>
+#include <QtGui/QFocusEvent>
+#include <QtGui/QMenu>
+
+#include <QtHelp/QHelpContentWidget>
+
+QT_BEGIN_NAMESPACE
+
+ContentWindow::ContentWindow()
+ : m_contentWidget(HelpEngineWrapper::instance().contentWidget())
+ , m_expandDepth(-2)
+{
+ TRACE_OBJ
+ m_contentWidget->viewport()->installEventFilter(this);
+ m_contentWidget->setContextMenuPolicy(Qt::CustomContextMenu);
+
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->setMargin(4);
+ layout->addWidget(m_contentWidget);
+
+ connect(m_contentWidget, SIGNAL(customContextMenuRequested(QPoint)), this,
+ SLOT(showContextMenu(QPoint)));
+ connect(m_contentWidget, SIGNAL(linkActivated(QUrl)), this,
+ SIGNAL(linkActivated(QUrl)));
+
+ QHelpContentModel *contentModel =
+ qobject_cast<QHelpContentModel*>(m_contentWidget->model());
+ connect(contentModel, SIGNAL(contentsCreated()), this, SLOT(expandTOC()));
+}
+
+ContentWindow::~ContentWindow()
+{
+ TRACE_OBJ
+}
+
+bool ContentWindow::syncToContent(const QUrl& url)
+{
+ TRACE_OBJ
+ QModelIndex idx = m_contentWidget->indexOf(url);
+ if (!idx.isValid())
+ return false;
+ m_contentWidget->setCurrentIndex(idx);
+ return true;
+}
+
+void ContentWindow::expandTOC()
+{
+ TRACE_OBJ
+ Q_ASSERT(m_expandDepth >= -2);
+ if (m_expandDepth > -2) {
+ expandToDepth(m_expandDepth);
+ m_expandDepth = -2;
+ }
+}
+
+void ContentWindow::expandToDepth(int depth)
+{
+ TRACE_OBJ
+ Q_ASSERT(depth >= -2);
+ m_expandDepth = depth;
+ if (depth == -1)
+ m_contentWidget->expandAll();
+ else if (depth == 0)
+ m_contentWidget->collapseAll();
+ else
+ m_contentWidget->expandToDepth(depth - 1);
+}
+
+void ContentWindow::focusInEvent(QFocusEvent *e)
+{
+ TRACE_OBJ
+ if (e->reason() != Qt::MouseFocusReason)
+ m_contentWidget->setFocus();
+}
+
+void ContentWindow::keyPressEvent(QKeyEvent *e)
+{
+ TRACE_OBJ
+ if (e->key() == Qt::Key_Escape)
+ emit escapePressed();
+}
+
+bool ContentWindow::eventFilter(QObject *o, QEvent *e)
+{
+ TRACE_OBJ
+ if (m_contentWidget && o == m_contentWidget->viewport()
+ && e->type() == QEvent::MouseButtonRelease) {
+ QMouseEvent *me = static_cast<QMouseEvent*>(e);
+ const QModelIndex &index = m_contentWidget->indexAt(me->pos());
+ if (!index.isValid())
+ return QWidget::eventFilter(o, e);
+
+ const Qt::MouseButtons button = me->button();
+ QItemSelectionModel *sm = m_contentWidget->selectionModel();
+ if (sm->isSelected(index)) {
+ if ((button == Qt::LeftButton && (me->modifiers() & Qt::ControlModifier))
+ || (button == Qt::MidButton)) {
+ QHelpContentModel *contentModel =
+ qobject_cast<QHelpContentModel*>(m_contentWidget->model());
+ if (contentModel) {
+ QHelpContentItem *itm = contentModel->contentItemAt(index);
+ if (itm && HelpViewer::canOpenPage(itm->url().path()))
+ OpenPagesManager::instance()->createPage(itm->url());
+ }
+ } else if (button == Qt::LeftButton) {
+ itemClicked(index);
+ }
+ }
+ }
+ return QWidget::eventFilter(o, e);
+}
+
+
+void ContentWindow::showContextMenu(const QPoint &pos)
+{
+ TRACE_OBJ
+ if (!m_contentWidget->indexAt(pos).isValid())
+ return;
+
+ QHelpContentModel *contentModel =
+ qobject_cast<QHelpContentModel*>(m_contentWidget->model());
+ QHelpContentItem *itm =
+ contentModel->contentItemAt(m_contentWidget->currentIndex());
+
+ QMenu menu;
+ QAction *curTab = menu.addAction(tr("Open Link"));
+ QAction *newTab = menu.addAction(tr("Open Link in New Tab"));
+ if (!HelpViewer::canOpenPage(itm->url().path()))
+ newTab->setEnabled(false);
+
+ menu.move(m_contentWidget->mapToGlobal(pos));
+
+ QAction *action = menu.exec();
+ if (curTab == action)
+ emit linkActivated(itm->url());
+ else if (newTab == action)
+ OpenPagesManager::instance()->createPage(itm->url());
+}
+
+void ContentWindow::itemClicked(const QModelIndex &index)
+{
+ TRACE_OBJ
+ QHelpContentModel *contentModel =
+ qobject_cast<QHelpContentModel*>(m_contentWidget->model());
+
+ if (contentModel) {
+ if (QHelpContentItem *itm = contentModel->contentItemAt(index)) {
+ const QUrl &url = itm->url();
+ if (url != CentralWidget::instance()->currentSource())
+ emit linkActivated(url);
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/contentwindow.h b/src/assistant/tools/assistant/contentwindow.h
new file mode 100644
index 000000000..b8bdc8fee
--- /dev/null
+++ b/src/assistant/tools/assistant/contentwindow.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef CONTENTWINDOW_H
+#define CONTENTWINDOW_H
+
+#include <QtCore/QUrl>
+#include <QtCore/QModelIndex>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QHelpEngine;
+class QHelpContentItem;
+class QHelpContentWidget;
+
+class ContentWindow : public QWidget
+{
+ Q_OBJECT
+
+public:
+ ContentWindow();
+ ~ContentWindow();
+
+ bool syncToContent(const QUrl &url);
+ void expandToDepth(int depth);
+
+signals:
+ void linkActivated(const QUrl &link);
+ void escapePressed();
+
+private slots:
+ void showContextMenu(const QPoint &pos);
+ void expandTOC();
+ void itemClicked(const QModelIndex &index);
+
+private:
+ void focusInEvent(QFocusEvent *e);
+ void keyPressEvent(QKeyEvent *e);
+ bool eventFilter(QObject *o, QEvent *e);
+
+ QHelpContentWidget * const m_contentWidget;
+ int m_expandDepth;
+};
+
+QT_END_NAMESPACE
+
+#endif // CONTENTWINDOW_H
diff --git a/src/assistant/tools/assistant/doc/HOWTO b/src/assistant/tools/assistant/doc/HOWTO
new file mode 100644
index 000000000..a0143479e
--- /dev/null
+++ b/src/assistant/tools/assistant/doc/HOWTO
@@ -0,0 +1,16 @@
+How to build/ update a new assistant.qch for Assistant internal help
+
+- update:
+ - open assistant.qdocconf, update year and qt version
+
+ - ..\..\..\..\qdoc3\debug\qdoc3.exe assistant.qdocconf
+ will generate an folder html containing all required stuff
+
+ - cp assistant.qhp to generated html folder
+ - run qhelpgenerator html\assistant.qhp -o ..\assistant.qch
+
+ - rebuild assistant
+
+- to test your changes:
+ - remove assistant.qch in your cache directory
+ - restart assistant
diff --git a/src/assistant/tools/assistant/doc/assistant.qdoc b/src/assistant/tools/assistant/doc/assistant.qdoc
new file mode 100644
index 000000000..8bd7432ec
--- /dev/null
+++ b/src/assistant/tools/assistant/doc/assistant.qdoc
@@ -0,0 +1,461 @@
+/****************************************************************************
+**
+** 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 documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page assistant.html
+ \title Qt Assistant
+
+ \chapter Introduction
+
+ This document introduces \e{Qt Assistant}, a tool for presenting on-line
+ documentation. It also introduces the Qt Reference Documentation which
+ is accessible using \e{Qt Assistant}, or with a web browser. The document is
+ divided into the following sections:
+
+ Table of contents:
+
+ \list
+ \o \l{Introduction}
+ \o \l{The One-Minute Guide to Using Qt Assistant}
+ \o \l{Introduction to the Qt Reference Documentation}
+ \o \l{Qt Assistant in More Detail}
+ \o \l{Full Text Searching}
+ \endlist
+
+ \chapter The One-Minute Guide to Using Qt Assistant
+
+ Once you have installed Qt, \QA should be ready to run:
+
+ \list
+ \o On Windows, \QA is available as a menu option on the Qt menu.
+ \o On Mac OS X, \QA is installed in the /Developer/Applications/Qt directory.
+ \o On Unix/Linux, open a terminal, type \c{assistant} and press \key{Enter}.
+ \endlist
+
+ When you start up \QA, you will be presented with a standard main window
+ application, with a menu bar and toolbar. Below these, on the left hand
+ side are navigation windows called \e{Contents}, \e{Index} and \e{Bookmarks}.
+ On the right, taking up most of the space, is the \e{Documentation} window.
+ By default, \QA loads the Qt reference documentation along with the manuals
+ of other Qt tools, like \QD or \QL.
+
+ \QA works in a similar way to a Web browser. If you click hyperlinks
+ (cross-references), the \e{Documentation} window will present the relevant
+ page. You can bookmark pages of particular interest and you can click the
+ \gui{Previous} and \gui{Next} toolbar buttons to navigate within the pages
+ you have visited.
+
+ Although \QA can be used just like a Web browser to navigate through
+ the documentation, \QA offers a powerful means of navigation that Web
+ browsers do not provide. \QA uses an advanced full text search engine
+ to index all the pages in each compressed help file so that you can
+ search for particular words and phrases.
+
+ To perform an index search, click the \gui{Index} tab on the Sidebar
+ (or press \key{Alt+I}). In the \gui{'Look For'} line edit enter a word;
+ e.g., 'homedirpath'. As you type, words are found and highlighted in a list
+ beneath the line edit. If the highlighted text matches what you're
+ looking for, double click it, (or press \key{Enter}) and the
+ \e{Documentation} window will display the relevant page. You rarely have
+ to type in the whole word before \QA finds a match. Note that for some
+ words there may be more than one possible page that is relevant.
+
+ \QA also provides full text searching for finding specific words in
+ the documentation. To activate the full text search, either press \key(Alt+S)
+ or click on the \gui{Search} tab in the \e{Documentation} window. Then
+ enter the term you're looking for and hit the \gui{Search} button. All
+ documents containing the specified term will then be listed in the list box
+ below.
+
+ \chapter Introduction to the Qt Reference Documentation
+
+ The documentation for the Qt library is written in-line in the \c
+ .cpp files by the developers themselves. The documentation team
+ revises the documentation to ensure that it is accurate and usable,
+ and to provide quality control. The documentation team also writes the
+ larger texts, such as the class descriptions that introduce a class
+ along with the concepts the class uses, as well as introducing the
+ functions and properties that the class provides.
+
+ The documentation focuses on the API rather than the internals, since
+ we make great efforts to keep our API consistent and compatible with
+ each new version, but we may change the internals considerably to improve
+ performance and enhance functionality.
+
+ The Qt Reference Documentation consists of almost 1,500 HTML pages
+ (over 2,500 printed pages). The overwhelming majority of pages
+ document Qt classes. Since developers differ in the way they
+ think and work we provide a variety of approaches to navigating the
+ documentation set:
+
+ \list
+ \i The \menu{Qt's Classes} page lists every class
+ in Qt's public API, and consists of several hundred classes.
+ \i The \menu{Qt's Main Classes} page lists the
+ classes you're most likely to use most often, and provides a much
+ shorter and more managable list than the All Classes list.
+ \i The \menu{Grouped Classes} page presents a list
+ of groups, each of which leads to a list of related classes, for
+ example, the \menu{Advanced Widgets} list.
+ \i The \menu{Class Inheritance Hierarchy} page
+ presents a list of classes in terms of the hierarchy of Qt classes.
+ \i The \menu{Member Function Index} page lists all the
+ functions provided by Qt classes, each one with links to the class(es)
+ in which it appears.
+ \endlist
+
+ No matter where you find yourself in the Qt documentation, you will
+ find extensive cross-referencing. Even snippets of example code
+ contain clickable links, so that for example, if you come across a
+ class declaration in a code example, the class name will be a
+ clickable link to the class's documentation.
+
+ In addition to the class documentation some of Qt's modules have
+ extensive descriptions, and there are many overview documents which
+ describe various aspects of the Qt library; all these are linked from
+ the reference documentation home page. There are also two tutorials
+ and numerous example programs in the examples subdirectory of the Qt
+ distribution.
+
+ \chapter Qt Assistant in More Detail
+
+ \img assistant-assistant.png
+
+ \section1 Command Line Options
+
+ \QA handles the following command line options:
+
+ \table
+ \header
+ \o Command Line Option
+ \o Brief Description
+ \row
+ \o -collectionFile <file.qhc>
+ \o Uses the specified collection file instead of the default one.
+ \row
+ \o -showUrl URL
+ \o Shows the document referenced by URL.
+ \row
+ \o -enableRemoteControl
+ \o Enables \QA to be remotly controlled.
+ \row
+ \o -show <widget>
+ \o Shows the specified dockwidget which can be "contents", "index",
+ "bookmarks" or "search".
+ \row
+ \o -hide <widget>
+ \o Hides the specified dockwidget which can be "contents", "index",
+ "bookmarks" or "search.
+ \row
+ \o -activate <widget>
+ \o Activates the specified dockwidget which can be "contents",
+ "index", "bookmarks" or "search.
+ \row
+ \o -register <doc.qch>
+ \o Registers the specified compressed help file in the given help
+ collection.
+ \row
+ \o -unregister <doc.qch>
+ \o Unregisters the specified compressed help file from the given
+ collection file.
+ \row
+ \o -quiet
+ \o Doesn't show any error, warning or success messages.
+ \endtable
+
+ \section1 Tool Windows
+
+ \img assistant-dockwidgets.png
+
+ The tool windows provide four ways to navigate the documentation:
+
+ \list
+ \o The \gui{Contents} window presents a table of contents implemented as a
+ tree view for the documentation that is available. If you click an item,
+ its documentation will appear in the \e{Documentation} window. If you double
+ click an item or click on the control to the left of it, the item's sub-items
+ will appear. Click a sub-item to make its page appear in the \e{Documentation}
+ window. Click on the control next to an open item to hide its sub-items.
+ \o The \gui{Index} window is used to look up key words or phrases.
+ See \l{The One-Minute Guide to Using Qt Assistant} for how to use this
+ window.
+ \o The \gui{Bookmarks} window lists any bookmarks you have made. Double
+ click a bookmark to make its page appear in the \e{Documentation} window.
+ The \gui{Bookmarks} window provides a context menu with \gui{Show Item},
+ \gui{Delete Item} as well as \gui{Rename Item}. Click in the main menu
+ \menu{Bookmark|Add Bookmark...} (or press \key{Ctrl+B}) to bookmark the
+ page that is currently showing in the \e{Documentation} window. Right click
+ a bookmark in the list to rename or delete the highlighted bookmark.
+ \endlist
+
+ If you want the \gui{Documentation} window to use as much space as possible,
+ you can easily group, move or hide the tool windows. To group the windows,
+ drag one on top of the other and release the mouse. If one or all tool
+ windows are not shown, press \key{Alt+C}, \key{Alt+I} or \key{Alt+O} to show
+ the required window.
+
+ The tool windows can be docked into the main window, so you can drag them
+ to the top, left, right or bottom of \e{Qt Assistant's} window, or you can
+ drag them outside \QA to float them as independent windows.
+
+ \section1 Documentation Window
+
+ \img assistant-docwindow.png
+
+ The \gui{Documentation} window lets you create a tab for each
+ documentation page that you view. Click the \gui{Add Tab} button and a new
+ tab will appear with the page name as the tab's caption. This makes it
+ convenient to switch between pages when you are working with different
+ documentation. You can delete a tab by clicking the \gui{Close Tab} button
+ located on the right side of the \gui{Documentation} window.
+
+ \section1 Toolbars
+
+ \img assistant-toolbar.png
+
+ The main toolbar provides fast access to the most common actions.
+
+ \table
+ \header \o Action \o Description \o Menu Item \o Shortcut
+ \row \o \gui{Previous} \o Takes you to the previous page in the history.
+ \o \menu{Go|Previous} \o \key{Alt+Left Arrow}
+ \row \o \gui{Next} \o Takes you to the next page in the history.
+ \o \menu{Go|Next} \o \key{Alt+Right Arrow}
+ \row \o \gui{Home}
+ \o Takes you to the home page as specified in the Preferences Dialog.
+ \o \menu{Go|Home} \o \key{Ctrl+Home}.
+ \row \o \gui{Sync with Table of Contents}
+ \o Synchronizes the \gui{Contents} tool window with the page currently
+ shown in the \gui{Documentation} window.
+ \o \menu{Go|Sync with Table of Contents} \o
+ \row \o \gui{Copy} \o Copies any selected text to the clipboard.
+ \o \menu{Edit|Copy} \o \key{Ctrl+C}
+ \row \o \gui{Print} \o Opens the \gui{Print} dialog.
+ \o \menu{File|Print} \o \key{Ctrl+P}
+ \row \o \gui{Find in Text} \o Opens the \gui{Find Text} dialog.
+ \o \menu{Edit|Find in Text} \o \key{Ctrl+F}
+ \row \o \gui{Zoom in}
+ \o Increases the font size used to display text in the current tab.
+ \o \menu{View|Zoom in} \o \key{Ctrl++}
+ \row \o \gui{Zoom out}
+ \o Decreases the font size used to display text in the current tab.
+ \o \menu{View|Zoom out} \o \key{Ctrl+-}
+ \row \o \gui{Normal Size}
+ \o Resets the font size to its normal size in the current tab.
+ \o \menu{View|Normal Size} \o \key{Ctrl+0}
+ \endtable
+
+ \img assistant-address-toolbar.png
+
+ The address toolbar provides a fast way to enter a specific URL for a
+ documentation file. By default, the address toolbar is not shown, so it
+ has to be activated via \menu{View|Toolbars|Address Toolbar}.
+
+ \img assistant-filter-toolbar.png
+
+ The filter toolbar allows you to apply a filter to the currently installed
+ documentation. As with the address toolbar, the filter toolbar is not visible
+ by default and has to be activated via \menu{View|Toolbars|Filter Toolbar}.
+
+ \section1 Menus
+
+ \section2 File Menu
+
+ \list
+ \o \menu{File|Page Setup...} invokes a dialog allowing you to define
+ page layout properties, such as margin sizes, page orientation and paper size.
+ \o \menu{File|Print Preview...} provides a preview of the printed pages.
+ \o \menu{File|Print...} opens the \l{#Print Dialog}{\gui{Print} dialog}.
+ \o \menu{File|New Tab} opens a new empty tab in the \gui{Documentation}
+ window.
+ \o \menu{File|Close Tab} closes the current tab of the
+ \gui{Documentation} window.
+ \o \menu{File|Exit} closes the \QA application.
+ \endlist
+
+ \section2 Edit Menu
+
+ \list
+ \o \menu{Edit|Copy} copies any selected text to the clipboard.
+ \o \menu{Edit|Find in Text} invokes the \l{#Find Text Control}{\gui{Find Text}
+ control} at the lower end of the \gui{Documentation} window.
+ \o \menu{Edit|Find Next} looks for the next occurance of the specified
+ text in the \gui{Find Text} control.
+ \o \menu{Edit|Find Previous} looks for the previous occurance of
+ the specified text in the \l{#Find Text Control}{\gui{Find Text} control}.
+ \o \menu{Edit|Preferences} invokes the \l{#Preferences Dialog}{\gui{Preferences} dialog}.
+ \endlist
+
+ \section2 View Menu
+
+ \list
+ \o \menu{View|Zoom in} increases the font size in the current tab.
+ \o \menu{View|Zoom out} decreases the font size in the current tab.
+ \o \menu{View|Normal Size} resets the font size in the current tab.
+ \o \menu{View|Contents} toggles the display of the \gui{Contents} tool window.
+ \o \menu{View|Index} toggles the display of the \gui{Index} tool window.
+ \o \menu{View|Bookmarks} toggles the display of the \gui{Bookmarks} tool window.
+ \o \menu{View|Search} toggles the display of the Search in the \gui{Documentation} window.
+ \endlist
+
+ \section2 Go Menu
+
+ \list
+ \o \menu{Go|Home} goes to the home page.
+ \o \menu{Go|Back} displays the previous page in the history.
+ \o \menu{Go|Forward} displays the next page in the history.
+ \o \menu{Go|Sync with Table of Contents} syncs the \gui{Contents} tool window to the currently shown page.
+ \o \menu{Go|Next Page} selects the next tab in the \gui{Documentation} window.
+ \o \menu{Go|Previous Page} selects the previous tab in the \gui{Documentation} window.
+ \endlist
+
+ \section2 Bookmarks Menu
+
+ \list
+ \o \menu{Bookmarks|Add} adds the current page to the list of bookmarks.
+ \endlist
+
+ \section1 Dialogs
+
+ \section2 Print Dialog
+
+ This dialog is platform-specific. It gives access to various printer
+ options and can be used to print the document shown in the current tab.
+
+ \section2 Preferences Dialog
+
+ \img assistant-preferences-fonts.png
+
+ The \menu{Fonts} page allows you to change the font family and font sizes of the
+ browser window displaying the documentation or the application itself.
+
+ \img assistant-preferences-filters.png
+
+ The \menu{Filters} page lets you create and remove documentation
+ filters. To add a new filter, click the \gui{Add} button, specify a
+ filter name in the pop-up dialog and click \gui{OK}, then select
+ the filter attributes in the list box on the right hand side.
+ You can delete a filter by selecting it and clicking the \gui{Remove}
+ button.
+
+ \img assistant-preferences-documentation.png
+
+ The \menu{Documentation} page lets you install and remove compressed help
+ files. Click the \gui{Install} button and choose the path of the compressed
+ help file (*.qch) you would like to install.
+ To delete a help file, select a documentation set in the list and click
+ \gui{Remove}.
+
+ \img assistant-preferences-options.png
+
+ The \menu{Options} page lets you specify the homepage \QA will display when
+ you click the \gui{Home} button in \QA's main user interface. You can specify
+ the hompage by typing it here or clicking on one of the buttons below the
+ textbox. \gui{Current Page} sets the currently displayed page as your home
+ page while \gui{Restore to default} will reset your home page to the default
+ home page.
+
+ \section1 Find Text Control
+
+ This control is used to find text in the current page. Enter the text you want
+ to find in the line edit. The search is incremental, meaning that the most
+ relevant result is shown as you enter characters into the line edit.
+
+ If you check the \gui{Whole words only} checkbox, the search will only consider
+ whole words; for example, if you search for "spin" with this checkbox checked it will
+ not match "spinbox", but will match "spin". If you check the \gui{Case sensitive}
+ checkbox then, for example, "spin" will match "spin" but not "Spin". You can
+ search forwards or backwards from your current position in the page by clicking
+ the \gui{Previous} or \gui{Next} buttons. To hide the find control, either click the
+ \gui{Close} button or hit the \key{Esc} key.
+
+ \section1 Filtering Help Contents
+
+ \QA allows you to install any kind of documentation as long as it is organized
+ in Qt compressed help files (*.qch). For example, it is possible to install the
+ Qt reference documentation for Qt 4.4.0 and Qt 4.4.1 at the same time. In many
+ respects, this is very convenient since only one version of \QA is needed.
+ However, at the same time it becomes more complicated when performing tasks like
+ searching the index because nearly every keyword is defined in Qt 4.4.0 as well
+ as in Qt 4.4.1. This means that \QA will always ask the user to choose which one
+ should be displayed.
+
+ We use documentation filters to solve this issue. A filter is identified by its
+ name, and contains a list of filter attributes. An attribute is just a string and
+ can be freely chosen. Attributes are defined by the documentation itself, this
+ means that every documentation set usually has one or more attributes.
+
+ For example, the Qt 4.4.0 \QA documentation defines the attributes \c {assistant},
+ \c{tools} and \c{4.4.0}, \QD defines \c{designer}, \c{tools} and \c{4.4.0}.
+ The filter to display all tools would then define only the attribute
+ \c{tools} since this attribute is part of both documentation sets.
+ Adding the attribute \c{assistant} to the filter would then only show \QA
+ documentation since the \QD documentation does not contain this
+ attribute. Having an empty list of attributes in a filter will match all
+ documentation; i.e., it is equivalent to requesting unfiltered documentation.
+
+ \section1 Full Text Searching
+
+ \img assistant-search.png
+
+ \QA provides a powerful full text search engine. To search
+ for certain words or text, click the \gui{Search} tab in the \gui{Documentation}
+ window. Then enter the text you want to look for and press \key{Enter}
+ or click the \gui{Search} button. The search is not case sensitive, so,
+ for example, Foo, fOo and FOO are all treated as the same. The following are
+ examples of common search patterns:
+
+ \list
+ \o \c deep -- lists all the documents that contain the word 'deep'
+ \o \c{deep*} -- lists all the documents that contain a word beginning
+ with 'deep'
+ \o \c{deep copy} -- lists all documents that contain both 'deep' \e
+ and 'copy'
+ \o \c{"deep copy"} -- list all documents that contain the phrase 'deep copy'
+ \endlist
+
+ It is also possible to use the \gui{Advanced search} to get more flexibility.
+ You can specify some words so that hits containing these are excluded from the
+ result, or you can search for an exact phrase. Searching for similar words will
+ give results like these:
+
+ \list
+ \o \c{QStin} -- lists all the documents with titles that are similar, such as \c{QString}
+ \o \c{QSting} -- lists all the documents with titles that are similar, such as \c{QString}
+ \o \c{QStrin} -- lists all the documents with titles that are similar, such as \c{QString}
+ \endlist
+
+ Options can be combined to improve the search results.
+
+ The list of documents found is ordered according to the number of
+ occurrences of the search text which they contain, with those containing
+ the highest number of occurrences appearing first. Simply click any
+ document in the list to display it in the \gui{Documentation} window.
+
+ If the documentation has changed \mdash for example, if documents have been added
+ or removed \mdash \QA will index them again.
+*/
diff --git a/src/assistant/tools/assistant/doc/assistant.qdocconf b/src/assistant/tools/assistant/doc/assistant.qdocconf
new file mode 100644
index 000000000..4bd3842d6
--- /dev/null
+++ b/src/assistant/tools/assistant/doc/assistant.qdocconf
@@ -0,0 +1,16 @@
+include(../../../../qdoc3/test/qt.qdocconf)
+
+version =
+
+sourcedirs = $QTDIR/tools/assistant/tools/assistant/doc
+imagedirs = $QTDIR/tools/assistant/tools/assistant/doc/images
+outputdir = $QTDIR/tools/assistant/tools/assistant/doc/html
+project = assistant
+description = "Qt Assistant"
+HTML.{postheader,address} = ""
+HTML.footer = "<p /><address><hr /><div align=\"center\">\n" \
+ "<table width=\"100%\" cellspacing=\"0\" border=\"0\"><tr class=\"address\">\n" \
+ "<td width=\"30%\" align=\"left\">Copyright &copy; 2011 Nokia Corporation and/or its subsidiary(-ies)</td>\n" \
+ "<td width=\"40%\" align=\"center\">Trademarks</td>\n" \
+ "<td width=\"30%\" align=\"right\"><div align=\"right\">Qt 4.8.0</div></td>\n" \
+ "</tr></table></div></address>"
diff --git a/src/assistant/tools/assistant/doc/assistant.qhp b/src/assistant/tools/assistant/doc/assistant.qhp
new file mode 100644
index 000000000..7ea4cdd46
--- /dev/null
+++ b/src/assistant/tools/assistant/doc/assistant.qhp
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<QtHelpProject version="1.0">
+ <virtualFolder>assistant</virtualFolder>
+ <namespace>com.trolltech.com.assistantinternal-1.0.0</namespace>
+ <filterSection>
+ <files>
+ <file>assistant.html</file>
+ <file>classic.css</file>
+ <file>images/assistant-address-toolbar.png</file>
+ <file>images/assistant-assistant.png</file>
+ <file>images/assistant-dockwidgets.png</file>
+ <file>images/assistant-docwindow.png</file>
+ <file>images/assistant-filter-toolbar.png</file>
+ <file>images/assistant-preferences-documentation.png</file>
+ <file>images/assistant-preferences-filters.png</file>
+ <file>images/assistant-preferences-fonts.png</file>
+ <file>images/assistant-preferences-options.png</file>
+ <file>images/assistant-search.png</file>
+ <file>images/assistant-toolbar.png</file>
+ </files>
+ </filterSection>
+</QtHelpProject>
diff --git a/src/assistant/tools/assistant/doc/classic.css b/src/assistant/tools/assistant/doc/classic.css
new file mode 100644
index 000000000..911354035
--- /dev/null
+++ b/src/assistant/tools/assistant/doc/classic.css
@@ -0,0 +1,92 @@
+h3.fn,span.fn
+{
+ margin-left: 1cm;
+ text-indent: -1cm;
+}
+
+a:link
+{
+ color: #004faf;
+ text-decoration: none
+}
+
+a:visited
+{
+ color: #672967;
+ text-decoration: none
+}
+
+td.postheader
+{
+ font-family: sans-serif
+}
+
+tr.address
+{
+ font-family: sans-serif
+}
+
+body
+{
+ background: #ffffff;
+ color: black
+}
+
+table tr.odd {
+ background: #f0f0f0;
+ color: black;
+}
+
+table tr.even {
+ background: #e4e4e4;
+ color: black;
+}
+
+table.annotated th {
+ padding: 3px;
+ text-align: left
+}
+
+table.annotated td {
+ padding: 3px;
+}
+
+table tr pre
+{
+ padding-top: none;
+ padding-bottom: none;
+ padding-left: none;
+ padding-right: none;
+ border: none;
+ background: none
+}
+
+tr.qt-style
+{
+ background: #a2c511;
+ color: black
+}
+
+body pre
+{
+ padding: 0.2em;
+ border: #e7e7e7 1px solid;
+ background: #f1f1f1;
+ color: black
+}
+
+span.preprocessor, span.preprocessor a
+{
+ color: darkblue;
+}
+
+span.comment
+{
+ color: darkred;
+ font-style: italic
+}
+
+span.string,span.char
+{
+ color: darkgreen;
+}
diff --git a/src/assistant/tools/assistant/doc/images/assistant-address-toolbar.png b/src/assistant/tools/assistant/doc/images/assistant-address-toolbar.png
new file mode 100644
index 000000000..847b7debb
--- /dev/null
+++ b/src/assistant/tools/assistant/doc/images/assistant-address-toolbar.png
Binary files differ
diff --git a/src/assistant/tools/assistant/doc/images/assistant-assistant.png b/src/assistant/tools/assistant/doc/images/assistant-assistant.png
new file mode 100644
index 000000000..1ff5cc976
--- /dev/null
+++ b/src/assistant/tools/assistant/doc/images/assistant-assistant.png
Binary files differ
diff --git a/src/assistant/tools/assistant/doc/images/assistant-dockwidgets.png b/src/assistant/tools/assistant/doc/images/assistant-dockwidgets.png
new file mode 100644
index 000000000..17bc064c5
--- /dev/null
+++ b/src/assistant/tools/assistant/doc/images/assistant-dockwidgets.png
Binary files differ
diff --git a/src/assistant/tools/assistant/doc/images/assistant-docwindow.png b/src/assistant/tools/assistant/doc/images/assistant-docwindow.png
new file mode 100644
index 000000000..c5bac581f
--- /dev/null
+++ b/src/assistant/tools/assistant/doc/images/assistant-docwindow.png
Binary files differ
diff --git a/src/assistant/tools/assistant/doc/images/assistant-examples.png b/src/assistant/tools/assistant/doc/images/assistant-examples.png
new file mode 100644
index 000000000..47c01bcda
--- /dev/null
+++ b/src/assistant/tools/assistant/doc/images/assistant-examples.png
Binary files differ
diff --git a/src/assistant/tools/assistant/doc/images/assistant-filter-toolbar.png b/src/assistant/tools/assistant/doc/images/assistant-filter-toolbar.png
new file mode 100644
index 000000000..4e89a79b9
--- /dev/null
+++ b/src/assistant/tools/assistant/doc/images/assistant-filter-toolbar.png
Binary files differ
diff --git a/src/assistant/tools/assistant/doc/images/assistant-preferences-documentation.png b/src/assistant/tools/assistant/doc/images/assistant-preferences-documentation.png
new file mode 100644
index 000000000..790fd9a1a
--- /dev/null
+++ b/src/assistant/tools/assistant/doc/images/assistant-preferences-documentation.png
Binary files differ
diff --git a/src/assistant/tools/assistant/doc/images/assistant-preferences-filters.png b/src/assistant/tools/assistant/doc/images/assistant-preferences-filters.png
new file mode 100644
index 000000000..7453dd66d
--- /dev/null
+++ b/src/assistant/tools/assistant/doc/images/assistant-preferences-filters.png
Binary files differ
diff --git a/src/assistant/tools/assistant/doc/images/assistant-preferences-fonts.png b/src/assistant/tools/assistant/doc/images/assistant-preferences-fonts.png
new file mode 100644
index 000000000..d42d190d0
--- /dev/null
+++ b/src/assistant/tools/assistant/doc/images/assistant-preferences-fonts.png
Binary files differ
diff --git a/src/assistant/tools/assistant/doc/images/assistant-preferences-options.png b/src/assistant/tools/assistant/doc/images/assistant-preferences-options.png
new file mode 100644
index 000000000..d6624151a
--- /dev/null
+++ b/src/assistant/tools/assistant/doc/images/assistant-preferences-options.png
Binary files differ
diff --git a/src/assistant/tools/assistant/doc/images/assistant-search.png b/src/assistant/tools/assistant/doc/images/assistant-search.png
new file mode 100644
index 000000000..ef75c3329
--- /dev/null
+++ b/src/assistant/tools/assistant/doc/images/assistant-search.png
Binary files differ
diff --git a/src/assistant/tools/assistant/doc/images/assistant-toolbar.png b/src/assistant/tools/assistant/doc/images/assistant-toolbar.png
new file mode 100644
index 000000000..1b41825c6
--- /dev/null
+++ b/src/assistant/tools/assistant/doc/images/assistant-toolbar.png
Binary files differ
diff --git a/src/assistant/tools/assistant/filternamedialog.cpp b/src/assistant/tools/assistant/filternamedialog.cpp
new file mode 100644
index 000000000..1d9563d2f
--- /dev/null
+++ b/src/assistant/tools/assistant/filternamedialog.cpp
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** 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 "tracer.h"
+
+#include <QtGui/QPushButton>
+
+#include "filternamedialog.h"
+
+QT_BEGIN_NAMESPACE
+
+FilterNameDialog::FilterNameDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ TRACE_OBJ
+ m_ui.setupUi(this);
+ connect(m_ui.buttonBox->button(QDialogButtonBox::Ok),
+ SIGNAL(clicked()), this, SLOT(accept()));
+ connect(m_ui.buttonBox->button(QDialogButtonBox::Cancel),
+ SIGNAL(clicked()), this, SLOT(reject()));
+ connect(m_ui.lineEdit, SIGNAL(textChanged(QString)),
+ this, SLOT(updateOkButton()));
+ m_ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(true);
+
+}
+
+QString FilterNameDialog::filterName() const
+{
+ TRACE_OBJ
+ return m_ui.lineEdit->text();
+}
+
+void FilterNameDialog::updateOkButton()
+{
+ TRACE_OBJ
+ m_ui.buttonBox->button(QDialogButtonBox::Ok)
+ ->setDisabled(m_ui.lineEdit->text().isEmpty());
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/filternamedialog.h b/src/assistant/tools/assistant/filternamedialog.h
new file mode 100644
index 000000000..35575421e
--- /dev/null
+++ b/src/assistant/tools/assistant/filternamedialog.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef FILTERNAMEDIALOG_H
+#define FILTERNAMEDIALOG_H
+
+#include <QtGui/QDialog>
+#include "ui_filternamedialog.h"
+
+QT_BEGIN_NAMESPACE
+
+class FilterNameDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ FilterNameDialog(QWidget *parent = 0);
+ QString filterName() const;
+
+private slots:
+ void updateOkButton();
+
+private:
+ Ui::FilterNameDialogClass m_ui;
+};
+
+QT_END_NAMESPACE
+
+#endif // FILTERNAMEDIALOG_H
diff --git a/src/assistant/tools/assistant/filternamedialog.ui b/src/assistant/tools/assistant/filternamedialog.ui
new file mode 100644
index 000000000..755a93479
--- /dev/null
+++ b/src/assistant/tools/assistant/filternamedialog.ui
@@ -0,0 +1,67 @@
+<ui version="4.0" >
+ <class>FilterNameDialogClass</class>
+ <widget class="QDialog" name="FilterNameDialogClass" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>312</width>
+ <height>95</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Add Filter Name</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Filter Name:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" colspan="2" >
+ <widget class="QLineEdit" name="lineEdit" />
+ </item>
+ <item row="1" column="0" colspan="3" >
+ <widget class="Line" name="line" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="2" >
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/assistant/tools/assistant/findwidget.cpp b/src/assistant/tools/assistant/findwidget.cpp
new file mode 100644
index 000000000..d45ed30b0
--- /dev/null
+++ b/src/assistant/tools/assistant/findwidget.cpp
@@ -0,0 +1,234 @@
+/****************************************************************************
+**
+** 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 "tracer.h"
+#include "findwidget.h"
+
+#include <QtGui/QApplication>
+#include <QtGui/QCheckBox>
+#include <QtGui/QHideEvent>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QLabel>
+#include <QtGui/QLayout>
+#include <QtGui/QLineEdit>
+#include <QtGui/QToolButton>
+
+QT_BEGIN_NAMESPACE
+
+FindWidget::FindWidget(QWidget *parent)
+ : QWidget(parent)
+ , appPalette(qApp->palette())
+{
+ TRACE_OBJ
+ installEventFilter(this);
+ QHBoxLayout *hboxLayout = new QHBoxLayout(this);
+ QString resourcePath = QLatin1String(":/trolltech/assistant/images/");
+
+#ifndef Q_OS_MAC
+ hboxLayout->setMargin(0);
+ hboxLayout->setSpacing(6);
+ resourcePath.append(QLatin1String("win"));
+#else
+ resourcePath.append(QLatin1String("mac"));
+#endif
+
+ toolClose = setupToolButton(QLatin1String(""),
+ resourcePath + QLatin1String("/closetab.png"));
+ hboxLayout->addWidget(toolClose);
+ connect(toolClose, SIGNAL(clicked()), SLOT(hide()));
+
+ editFind = new QLineEdit(this);
+ hboxLayout->addWidget(editFind);
+ editFind->setMinimumSize(QSize(150, 0));
+ connect(editFind, SIGNAL(textChanged(QString)), this,
+ SLOT(textChanged(QString)));
+ connect(editFind, SIGNAL(returnPressed()), this, SIGNAL(findNext()));
+ connect(editFind, SIGNAL(textChanged(QString)), this, SLOT(updateButtons()));
+
+ toolPrevious = setupToolButton(tr("Previous"),
+ resourcePath + QLatin1String("/previous.png"));
+ connect(toolPrevious, SIGNAL(clicked()), this, SIGNAL(findPrevious()));
+
+ hboxLayout->addWidget(toolPrevious);
+
+ toolNext = setupToolButton(tr("Next"),
+ resourcePath + QLatin1String("/next.png"));
+ hboxLayout->addWidget(toolNext);
+ connect(toolNext, SIGNAL(clicked()), this, SIGNAL(findNext()));
+
+ checkCase = new QCheckBox(tr("Case Sensitive"), this);
+ hboxLayout->addWidget(checkCase);
+
+ labelWrapped = new QLabel(this);
+ labelWrapped->setScaledContents(true);
+ labelWrapped->setTextFormat(Qt::RichText);
+ labelWrapped->setMinimumSize(QSize(0, 20));
+ labelWrapped->setMaximumSize(QSize(105, 20));
+ labelWrapped->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignVCenter);
+ labelWrapped->setText(tr("<img src=\":/trolltech/assistant/images/wrap.png\""
+ ">&nbsp;Search wrapped"));
+ hboxLayout->addWidget(labelWrapped);
+
+ QSpacerItem *spacerItem = new QSpacerItem(20, 20, QSizePolicy::Expanding,
+ QSizePolicy::Minimum);
+ hboxLayout->addItem(spacerItem);
+ setMinimumWidth(minimumSizeHint().width());
+ labelWrapped->hide();
+
+ updateButtons();
+}
+
+FindWidget::~FindWidget()
+{
+ TRACE_OBJ
+}
+
+void FindWidget::show()
+{
+ TRACE_OBJ
+ QWidget::show();
+ editFind->selectAll();
+ editFind->setFocus(Qt::ShortcutFocusReason);
+}
+
+void FindWidget::showAndClear()
+{
+ TRACE_OBJ
+ show();
+ editFind->clear();
+}
+
+QString FindWidget::text() const
+{
+ TRACE_OBJ
+ return editFind->text();
+}
+
+bool FindWidget::caseSensitive() const
+{
+ TRACE_OBJ
+ return checkCase->isChecked();
+}
+
+void FindWidget::setPalette(bool found)
+{
+ TRACE_OBJ
+ QPalette palette = editFind->palette();
+ palette.setColor(QPalette::Active, QPalette::Base, found ? Qt::white
+ : QColor(255, 102, 102));
+ editFind->setPalette(palette);
+}
+
+void FindWidget::setTextWrappedVisible(bool visible)
+{
+ TRACE_OBJ
+ labelWrapped->setVisible(visible);
+}
+
+void FindWidget::hideEvent(QHideEvent* event)
+{
+ TRACE_OBJ
+#if !defined(QT_NO_WEBKIT)
+ // TODO: remove this once webkit supports setting the palette
+ if (!event->spontaneous())
+ qApp->setPalette(appPalette);
+#else
+ Q_UNUSED(event);
+#endif
+}
+
+void FindWidget::showEvent(QShowEvent* event)
+{
+ TRACE_OBJ
+#if !defined(QT_NO_WEBKIT)
+ // TODO: remove this once webkit supports setting the palette
+ if (!event->spontaneous()) {
+ QPalette p = appPalette;
+ p.setColor(QPalette::Inactive, QPalette::Highlight,
+ p.color(QPalette::Active, QPalette::Highlight));
+ p.setColor(QPalette::Inactive, QPalette::HighlightedText,
+ p.color(QPalette::Active, QPalette::HighlightedText));
+ qApp->setPalette(p);
+ }
+#else
+ Q_UNUSED(event);
+#endif
+}
+
+void FindWidget::updateButtons()
+{
+ TRACE_OBJ
+ const bool enable = !editFind->text().isEmpty();
+ toolNext->setEnabled(enable);
+ toolPrevious->setEnabled(enable);
+}
+
+void FindWidget::textChanged(const QString &text)
+{
+ TRACE_OBJ
+ emit find(text, true, true);
+}
+
+bool FindWidget::eventFilter(QObject *object, QEvent *e)
+{
+ TRACE_OBJ
+ if (e->type() == QEvent::KeyPress) {
+ if ((static_cast<QKeyEvent*>(e))->key() == Qt::Key_Escape) {
+ hide();
+ emit escapePressed();
+ }
+ }
+ return QWidget::eventFilter(object, e);
+}
+
+QToolButton* FindWidget::setupToolButton(const QString &text, const QString &icon)
+{
+ TRACE_OBJ
+ QToolButton *toolButton = new QToolButton(this);
+
+ toolButton->setText(text);
+ toolButton->setAutoRaise(true);
+ toolButton->setIcon(QIcon(icon));
+ toolButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+
+ return toolButton;
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/findwidget.h b/src/assistant/tools/assistant/findwidget.h
new file mode 100644
index 000000000..d3be0f587
--- /dev/null
+++ b/src/assistant/tools/assistant/findwidget.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+#ifndef FINDWIDGET_H
+#define FINDWIDGET_H
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QCheckBox;
+class QLabel;
+class QLineEdit;
+class QToolButton;
+
+class FindWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ FindWidget(QWidget *parent = 0);
+ ~FindWidget();
+
+ void show();
+ void showAndClear();
+
+ QString text() const;
+ bool caseSensitive() const;
+
+ void setPalette(bool found);
+ void setTextWrappedVisible(bool visible);
+
+signals:
+ void findNext();
+ void findPrevious();
+ void escapePressed();
+ void find(const QString &text, bool forward, bool incremental);
+
+protected:
+ void hideEvent(QHideEvent* event);
+ void showEvent(QShowEvent * event);
+
+private slots:
+ void updateButtons();
+ void textChanged(const QString &text);
+
+private:
+ bool eventFilter(QObject *object, QEvent *e);
+ QToolButton* setupToolButton(const QString &text, const QString &icon);
+
+private:
+ QPalette appPalette;
+
+ QLineEdit *editFind;
+ QCheckBox *checkCase;
+ QLabel *labelWrapped;
+ QToolButton *toolNext;
+ QToolButton *toolClose;
+ QToolButton *toolPrevious;
+};
+
+QT_END_NAMESPACE
+
+#endif // FINDWIDGET_H
diff --git a/src/assistant/tools/assistant/globalactions.cpp b/src/assistant/tools/assistant/globalactions.cpp
new file mode 100644
index 000000000..7fc59ebcd
--- /dev/null
+++ b/src/assistant/tools/assistant/globalactions.cpp
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** 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 Assistant module 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 "globalactions.h"
+
+#include "centralwidget.h"
+#include "helpviewer.h"
+#include "tracer.h"
+
+#include <QtGui/QAction>
+#include <QtGui/QMenu>
+
+#if !defined(QT_NO_WEBKIT)
+#include <QtWebKit/QWebHistory>
+#endif
+
+GlobalActions *GlobalActions::instance(QObject *parent)
+{
+ Q_ASSERT(!m_instance != !parent);
+ if (!m_instance)
+ m_instance = new GlobalActions(parent);
+ return m_instance;
+}
+
+GlobalActions::GlobalActions(QObject *parent) : QObject(parent)
+{
+ TRACE_OBJ
+
+ // TODO: Put resource path in misc class
+ QString resourcePath = QLatin1String(":/trolltech/assistant/images/");
+#ifdef Q_OS_MAC
+ resourcePath.append(QLatin1String("mac"));
+#else
+ resourcePath.append(QLatin1String("win"));
+#endif
+ CentralWidget *centralWidget = CentralWidget::instance();
+
+ m_backAction = new QAction(tr("&Back"), parent);
+ m_backAction->setEnabled(false);
+ m_backAction->setShortcuts(QKeySequence::Back);
+ m_backAction->setIcon(QIcon(resourcePath + QLatin1String("/previous.png")));
+ connect(m_backAction, SIGNAL(triggered()), centralWidget, SLOT(backward()));
+ m_actionList << m_backAction;
+
+ m_nextAction = new QAction(tr("&Forward"), parent);
+ m_nextAction->setPriority(QAction::LowPriority);
+ m_nextAction->setEnabled(false);
+ m_nextAction->setShortcuts(QKeySequence::Forward);
+ m_nextAction->setIcon(QIcon(resourcePath + QLatin1String("/next.png")));
+ connect(m_nextAction, SIGNAL(triggered()), centralWidget, SLOT(forward()));
+ m_actionList << m_nextAction;
+
+ setupNavigationMenus(m_backAction, m_nextAction, centralWidget);
+
+ m_homeAction = new QAction(tr("&Home"), parent);
+ m_homeAction->setShortcut(tr("ALT+Home"));
+ m_homeAction->setIcon(QIcon(resourcePath + QLatin1String("/home.png")));
+ connect(m_homeAction, SIGNAL(triggered()), centralWidget, SLOT(home()));
+ m_actionList << m_homeAction;
+
+ QAction *separator = new QAction(parent);
+ separator->setSeparator(true);
+ m_actionList << separator;
+
+ m_zoomInAction = new QAction(tr("Zoom &in"), parent);
+ m_zoomInAction->setPriority(QAction::LowPriority);
+ m_zoomInAction->setIcon(QIcon(resourcePath + QLatin1String("/zoomin.png")));
+ m_zoomInAction->setShortcut(QKeySequence::ZoomIn);
+ connect(m_zoomInAction, SIGNAL(triggered()), centralWidget, SLOT(zoomIn()));
+ m_actionList << m_zoomInAction;
+
+ m_zoomOutAction = new QAction(tr("Zoom &out"), parent);
+ m_zoomOutAction->setPriority(QAction::LowPriority);
+ m_zoomOutAction->setIcon(QIcon(resourcePath + QLatin1String("/zoomout.png")));
+ m_zoomOutAction->setShortcut(QKeySequence::ZoomOut);
+ connect(m_zoomOutAction, SIGNAL(triggered()), centralWidget, SLOT(zoomOut()));
+ m_actionList << m_zoomOutAction;
+
+ separator = new QAction(parent);
+ separator->setSeparator(true);
+ m_actionList << separator;
+
+ m_copyAction = new QAction(tr("&Copy selected Text"), parent);
+ m_copyAction->setPriority(QAction::LowPriority);
+ m_copyAction->setIconText("&Copy");
+ m_copyAction->setIcon(QIcon(resourcePath + QLatin1String("/editcopy.png")));
+ m_copyAction->setShortcuts(QKeySequence::Copy);
+ m_copyAction->setEnabled(false);
+ connect(m_copyAction, SIGNAL(triggered()), centralWidget, SLOT(copy()));
+ m_actionList << m_copyAction;
+
+ m_printAction = new QAction(tr("&Print..."), parent);
+ m_printAction->setPriority(QAction::LowPriority);
+ m_printAction->setIcon(QIcon(resourcePath + QLatin1String("/print.png")));
+ m_printAction->setShortcut(QKeySequence::Print);
+ connect(m_printAction, SIGNAL(triggered()), centralWidget, SLOT(print()));
+ m_actionList << m_printAction;
+
+ m_findAction = new QAction(tr("&Find in Text..."), parent);
+ m_findAction->setIconText(tr("&Find"));
+ m_findAction->setIcon(QIcon(resourcePath + QLatin1String("/find.png")));
+ m_findAction->setShortcuts(QKeySequence::Find);
+ connect(m_findAction, SIGNAL(triggered()), centralWidget, SLOT(showTextSearch()));
+ m_actionList << m_findAction;
+
+#ifdef Q_WS_X11
+ m_backAction->setIcon(QIcon::fromTheme("go-previous" , m_backAction->icon()));
+ m_nextAction->setIcon(QIcon::fromTheme("go-next" , m_nextAction->icon()));
+ m_zoomInAction->setIcon(QIcon::fromTheme("zoom-in" , m_zoomInAction->icon()));
+ m_zoomOutAction->setIcon(QIcon::fromTheme("zoom-out" , m_zoomOutAction->icon()));
+ m_copyAction->setIcon(QIcon::fromTheme("edit-copy" , m_copyAction->icon()));
+ m_findAction->setIcon(QIcon::fromTheme("edit-find" , m_findAction->icon()));
+ m_homeAction->setIcon(QIcon::fromTheme("go-home" , m_homeAction->icon()));
+ m_printAction->setIcon(QIcon::fromTheme("document-print" , m_printAction->icon()));
+#endif
+}
+
+void GlobalActions::updateActions()
+{
+ TRACE_OBJ
+ CentralWidget *centralWidget = CentralWidget::instance();
+ m_copyAction->setEnabled(centralWidget->hasSelection());
+ m_nextAction->setEnabled(centralWidget->isForwardAvailable());
+ m_backAction->setEnabled(centralWidget->isBackwardAvailable());
+}
+
+void GlobalActions::setCopyAvailable(bool available)
+{
+ TRACE_OBJ
+ m_copyAction->setEnabled(available);
+}
+
+#if !defined(QT_NO_WEBKIT)
+
+void GlobalActions::slotAboutToShowBackMenu()
+{
+ TRACE_OBJ
+ m_backMenu->clear();
+ if (QWebHistory *history = CentralWidget::instance()->currentHelpViewer()->history()) {
+ const int currentItemIndex = history->currentItemIndex();
+ QList<QWebHistoryItem> items = history->backItems(history->count());
+ for (int i = items.count() - 1; i >= 0; --i) {
+ QAction *action = new QAction(this);
+ action->setText(items.at(i).title());
+ action->setData(-1 * (currentItemIndex - i));
+ m_backMenu->addAction(action);
+ }
+ }
+}
+
+void GlobalActions::slotAboutToShowNextMenu()
+{
+ TRACE_OBJ
+ m_nextMenu->clear();
+ if (QWebHistory *history = CentralWidget::instance()->currentHelpViewer()->history()) {
+ const int count = history->count();
+ QList<QWebHistoryItem> items = history->forwardItems(count);
+ for (int i = 0; i < items.count(); ++i) {
+ QAction *action = new QAction(this);
+ action->setData(count - i);
+ action->setText(items.at(i).title());
+ m_nextMenu->addAction(action);
+ }
+ }
+}
+
+void GlobalActions::slotOpenActionUrl(QAction *action)
+{
+ TRACE_OBJ
+ if (HelpViewer* viewer = CentralWidget::instance()->currentHelpViewer()) {
+ const int offset = action->data().toInt();
+ QWebHistory *history = viewer->history();
+ if (offset > 0) {
+ history->goToItem(history->forwardItems(history->count()
+ - offset + 1).back()); // forward
+ } else if (offset < 0) {
+ history->goToItem(history->backItems(-1 * offset).first()); // back
+ }
+ }
+}
+
+#endif
+
+void GlobalActions::setupNavigationMenus(QAction *back, QAction *next,
+ QWidget *parent)
+{
+#if !defined(QT_NO_WEBKIT)
+ m_backMenu = new QMenu(parent);
+ connect(m_backMenu, SIGNAL(aboutToShow()), this,
+ SLOT(slotAboutToShowBackMenu()));
+ connect(m_backMenu, SIGNAL(triggered(QAction*)), this,
+ SLOT(slotOpenActionUrl(QAction*)));
+ back->setMenu(m_backMenu);
+
+ m_nextMenu = new QMenu(parent);
+ connect(m_nextMenu, SIGNAL(aboutToShow()), this,
+ SLOT(slotAboutToShowNextMenu()));
+ connect(m_nextMenu, SIGNAL(triggered(QAction*)), this,
+ SLOT(slotOpenActionUrl(QAction*)));
+ next->setMenu(m_nextMenu);
+#else
+ Q_UNUSED(back)
+ Q_UNUSED(next)
+ Q_UNUSED(parent)
+#endif
+}
+
+GlobalActions *GlobalActions::m_instance = 0;
diff --git a/src/assistant/tools/assistant/globalactions.h b/src/assistant/tools/assistant/globalactions.h
new file mode 100644
index 000000000..a9059a9a4
--- /dev/null
+++ b/src/assistant/tools/assistant/globalactions.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** 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 Assistant module 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$
+**
+****************************************************************************/
+
+#ifndef GLOBALACTION_H
+#define GLOBALACTION_H
+
+#include <QtCore/QList>
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QAction;
+class QMenu;
+
+class GlobalActions : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(GlobalActions)
+public:
+ static GlobalActions *instance(QObject *parent = 0);
+
+ QList<QAction *> actionList() const { return m_actionList; }
+ QAction *backAction() const { return m_backAction; }
+ QAction *nextAction() const { return m_nextAction; }
+ QAction *homeAction() const { return m_homeAction; }
+ QAction *zoomInAction() const { return m_zoomInAction; }
+ QAction *zoomOutAction() const { return m_zoomOutAction; }
+ QAction *copyAction() const { return m_copyAction; }
+ QAction *printAction() const { return m_printAction; }
+ QAction *findAction() const { return m_findAction; }
+
+ Q_SLOT void updateActions();
+ Q_SLOT void setCopyAvailable(bool available);
+
+#if !defined(QT_NO_WEBKIT)
+private slots:
+ void slotAboutToShowBackMenu();
+ void slotAboutToShowNextMenu();
+ void slotOpenActionUrl(QAction *action);
+#endif
+
+private:
+ void setupNavigationMenus(QAction *back, QAction *next, QWidget *parent);
+
+private:
+ GlobalActions(QObject *parent);
+
+ static GlobalActions *m_instance;
+
+ QAction *m_backAction;
+ QAction *m_nextAction;
+ QAction *m_homeAction;
+ QAction *m_zoomInAction;
+ QAction *m_zoomOutAction;
+ QAction *m_copyAction;
+ QAction *m_printAction;
+ QAction *m_findAction;
+
+ QList<QAction *> m_actionList;
+
+ QMenu *m_backMenu;
+ QMenu *m_nextMenu;
+};
+
+QT_END_NAMESPACE
+
+#endif // GLOBALACTION_H
diff --git a/src/assistant/tools/assistant/helpenginewrapper.cpp b/src/assistant/tools/assistant/helpenginewrapper.cpp
new file mode 100644
index 000000000..4c7ff5b30
--- /dev/null
+++ b/src/assistant/tools/assistant/helpenginewrapper.cpp
@@ -0,0 +1,844 @@
+/****************************************************************************
+**
+** 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 "tracer.h"
+
+#include "helpenginewrapper.h"
+#include "../shared/collectionconfiguration.h"
+
+#include <QtCore/QDateTime>
+#include <QtCore/QFileInfo>
+#include <QtCore/QFileSystemWatcher>
+#include <QtCore/QPair>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QTimer>
+#include <QtHelp/QHelpContentModel>
+#include <QtHelp/QHelpEngine>
+#include <QtHelp/QHelpIndexModel>
+#include <QtHelp/QHelpSearchEngine>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ const QString Unfiltered;
+ const QString AppFontKey(QLatin1String("appFont"));
+ const QString AppWritingSystemKey(QLatin1String("appWritingSystem"));
+ const QString BookmarksKey(QLatin1String("Bookmarks"));
+ const QString BrowserFontKey(QLatin1String("browserFont"));
+ const QString BrowserWritingSystemKey(QLatin1String("browserWritingSystem"));
+ const QString HomePageKey(QLatin1String("homepage"));
+ const QString MainWindowKey(QLatin1String("MainWindow"));
+ const QString MainWindowGeometryKey(QLatin1String("MainWindowGeometry"));
+ const QString SearchWasAttachedKey(QLatin1String("SearchWasAttached"));
+ const QString StartOptionKey(QLatin1String("StartOption"));
+ const QString UseAppFontKey(QLatin1String("useAppFont"));
+ const QString UseBrowserFontKey(QLatin1String("useBrowserFont"));
+ const QString VersionKey(QString(QLatin1String("qtVersion%1$$$%2")).
+ arg(QLatin1String(QT_VERSION_STR)));
+ const QString ShowTabsKey(QLatin1String("showTabs"));
+} // anonymous namespace
+
+class TimeoutForwarder : public QObject
+{
+ Q_OBJECT
+public:
+ TimeoutForwarder(const QString &fileName);
+private slots:
+ void forward();
+private:
+ friend class HelpEngineWrapperPrivate;
+
+ const QString m_fileName;
+};
+
+class HelpEngineWrapperPrivate : public QObject
+{
+ Q_OBJECT
+ friend class HelpEngineWrapper;
+ friend class TimeoutForwarder;
+private slots:
+ void qchFileChanged(const QString &fileName);
+
+signals:
+ void documentationRemoved(const QString &namespaceName);
+ void documentationUpdated(const QString &namespaceName);
+
+private:
+ HelpEngineWrapperPrivate(const QString &collectionFile);
+
+ void initFileSystemWatchers();
+ void checkDocFilesWatched();
+ void qchFileChanged(const QString &fileName, bool fromTimeout);
+
+ static const int UpdateGracePeriod = 2000;
+
+ QHelpEngine * const m_helpEngine;
+ QFileSystemWatcher * const m_qchWatcher;
+ typedef QPair<QDateTime, QSharedPointer<TimeoutForwarder> > RecentSignal;
+ QMap<QString, RecentSignal> m_recentQchUpdates;
+};
+
+const QString HelpEngineWrapper::TrUnfiltered = HelpEngineWrapper::tr("Unfiltered");
+
+HelpEngineWrapper *HelpEngineWrapper::helpEngineWrapper = 0;
+
+HelpEngineWrapper &HelpEngineWrapper::instance(const QString &collectionFile)
+{
+ TRACE_OBJ
+ /*
+ * Note that this Singleton cannot be static, because it has to be
+ * deleted before the QApplication.
+ */
+ if (helpEngineWrapper == 0)
+ helpEngineWrapper = new HelpEngineWrapper(collectionFile);
+ return *helpEngineWrapper;
+}
+
+void HelpEngineWrapper::removeInstance()
+{
+ TRACE_OBJ
+ delete helpEngineWrapper;
+ helpEngineWrapper = 0;
+}
+
+HelpEngineWrapper::HelpEngineWrapper(const QString &collectionFile)
+ : d(new HelpEngineWrapperPrivate(collectionFile))
+{
+ TRACE_OBJ
+
+ /*
+ * Otherwise we will waste time if several new docs are found,
+ * because we will start to index them, only to be interrupted
+ * by the next request. Also, there is a nasty SQLITE bug that will
+ * cause the application to hang for minutes in that case.
+ * This call is reverted by initialDocSetupDone(), which must be
+ * called after the new docs have been installed.
+ */
+ disconnect(d->m_helpEngine, SIGNAL(setupFinished()),
+ searchEngine(), SLOT(indexDocumentation()));
+
+ connect(d, SIGNAL(documentationRemoved(QString)),
+ this, SIGNAL(documentationRemoved(QString)));
+ connect(d, SIGNAL(documentationUpdated(QString)),
+ this, SIGNAL(documentationUpdated(QString)));
+ connect(d->m_helpEngine, SIGNAL(currentFilterChanged(QString)),
+ this, SLOT(handleCurrentFilterChanged(QString)));
+ connect(d->m_helpEngine, SIGNAL(setupFinished()),
+ this, SIGNAL(setupFinished()));
+}
+
+HelpEngineWrapper::~HelpEngineWrapper()
+{
+ TRACE_OBJ
+ const QStringList &namespaces = d->m_helpEngine->registeredDocumentations();
+ foreach (const QString &nameSpace, namespaces) {
+ const QString &docFile
+ = d->m_helpEngine->documentationFileName(nameSpace);
+ d->m_qchWatcher->removePath(docFile);
+ }
+
+ delete d;
+}
+
+void HelpEngineWrapper::initialDocSetupDone()
+{
+ TRACE_OBJ
+ connect(d->m_helpEngine, SIGNAL(setupFinished()),
+ searchEngine(), SLOT(indexDocumentation()));
+ setupData();
+}
+
+QHelpSearchEngine *HelpEngineWrapper::searchEngine() const
+{
+ TRACE_OBJ
+ return d->m_helpEngine->searchEngine();
+}
+
+QHelpContentModel *HelpEngineWrapper::contentModel() const
+{
+ TRACE_OBJ
+ return d->m_helpEngine->contentModel();
+}
+
+QHelpIndexModel *HelpEngineWrapper::indexModel() const
+{
+ TRACE_OBJ
+ return d->m_helpEngine->indexModel();
+}
+
+QHelpContentWidget *HelpEngineWrapper::contentWidget()
+{
+ TRACE_OBJ
+ return d->m_helpEngine->contentWidget();
+}
+
+QHelpIndexWidget *HelpEngineWrapper::indexWidget()
+{
+ TRACE_OBJ
+ return d->m_helpEngine->indexWidget();
+}
+
+const QStringList HelpEngineWrapper::registeredDocumentations() const
+{
+ TRACE_OBJ
+ return d->m_helpEngine->registeredDocumentations();
+}
+
+const QString HelpEngineWrapper::collectionFile() const
+{
+ TRACE_OBJ
+ return d->m_helpEngine->collectionFile();
+}
+
+bool HelpEngineWrapper::registerDocumentation(const QString &docFile)
+{
+ TRACE_OBJ
+ d->checkDocFilesWatched();
+ if (!d->m_helpEngine->registerDocumentation(docFile))
+ return false;
+ d->m_qchWatcher->addPath(docFile);
+ d->checkDocFilesWatched();
+ return true;
+}
+
+bool HelpEngineWrapper::unregisterDocumentation(const QString &namespaceName)
+{
+ TRACE_OBJ
+ d->checkDocFilesWatched();
+ const QString &file = d->m_helpEngine->documentationFileName(namespaceName);
+ if (!d->m_helpEngine->unregisterDocumentation(namespaceName))
+ return false;
+ d->m_qchWatcher->removePath(file);
+ d->checkDocFilesWatched();
+ return true;
+}
+
+bool HelpEngineWrapper::setupData()
+{
+ TRACE_OBJ
+ return d->m_helpEngine->setupData();
+}
+
+bool HelpEngineWrapper::addCustomFilter(const QString &filterName,
+ const QStringList &attributes)
+{
+ TRACE_OBJ
+ return d->m_helpEngine->addCustomFilter(filterName, attributes);
+}
+
+bool HelpEngineWrapper::removeCustomFilter(const QString &filterName)
+{
+ TRACE_OBJ
+ return d->m_helpEngine->removeCustomFilter(filterName);
+}
+
+void HelpEngineWrapper::setCurrentFilter(const QString &currentFilter)
+{
+ TRACE_OBJ
+ const QString &filter
+ = currentFilter == TrUnfiltered ? Unfiltered : currentFilter;
+ d->m_helpEngine->setCurrentFilter(filter);
+}
+
+const QString HelpEngineWrapper::currentFilter() const
+{
+ TRACE_OBJ
+ const QString &filter = d->m_helpEngine->currentFilter();
+ return filter == Unfiltered ? TrUnfiltered : filter;
+}
+
+const QStringList HelpEngineWrapper::customFilters() const
+{
+ TRACE_OBJ
+ QStringList filters = d->m_helpEngine->customFilters();
+ filters.removeOne(Unfiltered);
+ filters.prepend(TrUnfiltered);
+ return filters;
+}
+
+QUrl HelpEngineWrapper::findFile(const QUrl &url) const
+{
+ TRACE_OBJ
+ return d->m_helpEngine->findFile(url);
+}
+
+QByteArray HelpEngineWrapper::fileData(const QUrl &url) const
+{
+ TRACE_OBJ
+ return d->m_helpEngine->fileData(url);
+}
+
+QMap<QString, QUrl> HelpEngineWrapper::linksForIdentifier(const QString &id) const
+{
+ TRACE_OBJ
+ return d->m_helpEngine->linksForIdentifier(id);
+}
+
+const QStringList HelpEngineWrapper::filterAttributes() const
+{
+ TRACE_OBJ
+ return d->m_helpEngine->filterAttributes();
+}
+
+const QStringList HelpEngineWrapper::filterAttributes(const QString &filterName) const
+{
+ TRACE_OBJ
+ return d->m_helpEngine->filterAttributes(filterName);
+}
+
+QString HelpEngineWrapper::error() const
+{
+ TRACE_OBJ
+ return d->m_helpEngine->error();
+}
+
+const QStringList HelpEngineWrapper::qtDocInfo(const QString &component) const
+{
+ TRACE_OBJ
+ return d->m_helpEngine->customValue(VersionKey.arg(component)).toString().
+ split(CollectionConfiguration::ListSeparator);
+}
+
+void HelpEngineWrapper::setQtDocInfo(const QString &component,
+ const QStringList &doc)
+{
+ TRACE_OBJ
+ d->m_helpEngine->setCustomValue(VersionKey.arg(component),
+ doc.join(CollectionConfiguration::ListSeparator));
+}
+
+const QStringList HelpEngineWrapper::lastShownPages() const
+{
+ TRACE_OBJ
+ return CollectionConfiguration::lastShownPages(*d->m_helpEngine);
+}
+
+void HelpEngineWrapper::setLastShownPages(const QStringList &lastShownPages)
+{
+ TRACE_OBJ
+ CollectionConfiguration::setLastShownPages(*d->m_helpEngine, lastShownPages);
+}
+
+const QStringList HelpEngineWrapper::lastZoomFactors() const
+{
+ TRACE_OBJ
+ return CollectionConfiguration::lastZoomFactors(*d->m_helpEngine);
+}
+
+void HelpEngineWrapper::setLastZoomFactors(const QStringList &lastZoomFactors)
+{
+ TRACE_OBJ
+ CollectionConfiguration::setLastZoomFactors(*d->m_helpEngine, lastZoomFactors);
+}
+
+const QString HelpEngineWrapper::cacheDir() const
+{
+ TRACE_OBJ
+ return CollectionConfiguration::cacheDir(*d->m_helpEngine);
+}
+
+bool HelpEngineWrapper::cacheDirIsRelativeToCollection() const
+{
+ TRACE_OBJ
+ return CollectionConfiguration::cacheDirIsRelativeToCollection(*d->m_helpEngine);
+}
+
+void HelpEngineWrapper::setCacheDir(const QString &cacheDir,
+ bool relativeToCollection)
+{
+ TRACE_OBJ
+ CollectionConfiguration::setCacheDir(*d->m_helpEngine, cacheDir,
+ relativeToCollection);
+}
+
+bool HelpEngineWrapper::filterFunctionalityEnabled() const
+{
+ TRACE_OBJ
+ return CollectionConfiguration::filterFunctionalityEnabled(*d->m_helpEngine);
+}
+
+void HelpEngineWrapper::setFilterFunctionalityEnabled(bool enabled)
+{
+ TRACE_OBJ
+ CollectionConfiguration::setFilterFunctionalityEnabled(*d->m_helpEngine,
+ enabled);
+}
+
+bool HelpEngineWrapper::filterToolbarVisible() const
+{
+ TRACE_OBJ
+ return CollectionConfiguration::filterToolbarVisible(*d->m_helpEngine);
+}
+
+void HelpEngineWrapper::setFilterToolbarVisible(bool visible)
+{
+ TRACE_OBJ
+ CollectionConfiguration::setFilterToolbarVisible(*d->m_helpEngine, visible);
+}
+
+bool HelpEngineWrapper::addressBarEnabled() const
+{
+ TRACE_OBJ
+ return CollectionConfiguration::addressBarEnabled(*d->m_helpEngine);
+}
+
+void HelpEngineWrapper::setAddressBarEnabled(bool enabled)
+{
+ TRACE_OBJ
+ CollectionConfiguration::setAddressBarEnabled(*d->m_helpEngine, enabled);
+}
+
+bool HelpEngineWrapper::addressBarVisible() const
+{
+ TRACE_OBJ
+ return CollectionConfiguration::addressBarVisible(*d->m_helpEngine);
+}
+
+void HelpEngineWrapper::setAddressBarVisible(bool visible)
+{
+ TRACE_OBJ
+ CollectionConfiguration::setAddressBarVisible(*d->m_helpEngine, visible);
+}
+
+bool HelpEngineWrapper::documentationManagerEnabled() const
+{
+ TRACE_OBJ
+ return CollectionConfiguration::documentationManagerEnabled(*d->m_helpEngine);
+}
+
+void HelpEngineWrapper::setDocumentationManagerEnabled(bool enabled)
+{
+ TRACE_OBJ
+ CollectionConfiguration::setDocumentationManagerEnabled(*d->m_helpEngine,
+ enabled);
+}
+
+const QByteArray HelpEngineWrapper::aboutMenuTexts() const
+{
+ TRACE_OBJ
+ return CollectionConfiguration::aboutMenuTexts(*d->m_helpEngine);
+}
+
+void HelpEngineWrapper::setAboutMenuTexts(const QByteArray &texts)
+{
+ TRACE_OBJ
+ CollectionConfiguration::setAboutMenuTexts(*d->m_helpEngine, texts);
+}
+
+const QByteArray HelpEngineWrapper::aboutIcon() const
+{
+ TRACE_OBJ
+ return CollectionConfiguration::aboutIcon(*d->m_helpEngine);
+}
+
+void HelpEngineWrapper::setAboutIcon(const QByteArray &icon)
+{
+ TRACE_OBJ
+ CollectionConfiguration::setAboutIcon(*d->m_helpEngine, icon);
+}
+
+const QByteArray HelpEngineWrapper::aboutImages() const
+{
+ TRACE_OBJ
+ return CollectionConfiguration::aboutImages(*d->m_helpEngine);
+}
+
+void HelpEngineWrapper::setAboutImages(const QByteArray &images)
+{
+ TRACE_OBJ
+ CollectionConfiguration::setAboutImages(*d->m_helpEngine, images);
+}
+
+const QByteArray HelpEngineWrapper::aboutTexts() const
+{
+ TRACE_OBJ
+ return CollectionConfiguration::aboutTexts(*d->m_helpEngine);
+}
+
+void HelpEngineWrapper::setAboutTexts(const QByteArray &texts)
+{
+ TRACE_OBJ
+ CollectionConfiguration::setAboutTexts(*d->m_helpEngine, texts);
+}
+
+const QString HelpEngineWrapper::windowTitle() const
+{
+ TRACE_OBJ
+ return CollectionConfiguration::windowTitle(*d->m_helpEngine);
+}
+
+void HelpEngineWrapper::setWindowTitle(const QString &windowTitle)
+{
+ TRACE_OBJ
+ CollectionConfiguration::setWindowTitle(*d->m_helpEngine, windowTitle);
+}
+
+const QByteArray HelpEngineWrapper::applicationIcon() const
+{
+ TRACE_OBJ
+ return CollectionConfiguration::applicationIcon(*d->m_helpEngine);
+}
+
+void HelpEngineWrapper::setApplicationIcon(const QByteArray &icon)
+{
+ TRACE_OBJ
+ CollectionConfiguration::setApplicationIcon(*d->m_helpEngine, icon);
+}
+
+const QByteArray HelpEngineWrapper::mainWindow() const
+{
+ TRACE_OBJ
+ return d->m_helpEngine->customValue(MainWindowKey).toByteArray();
+}
+
+void HelpEngineWrapper::setMainWindow(const QByteArray &mainWindow)
+{
+ TRACE_OBJ
+ d->m_helpEngine->setCustomValue(MainWindowKey, mainWindow);
+}
+
+const QByteArray HelpEngineWrapper::mainWindowGeometry() const
+{
+ TRACE_OBJ
+ return d->m_helpEngine->customValue(MainWindowGeometryKey).toByteArray();
+}
+
+void HelpEngineWrapper::setMainWindowGeometry(const QByteArray &geometry)
+{
+ TRACE_OBJ
+ d->m_helpEngine->setCustomValue(MainWindowGeometryKey, geometry);
+}
+
+const QByteArray HelpEngineWrapper::bookmarks() const
+{
+ TRACE_OBJ
+ return d->m_helpEngine->customValue(BookmarksKey).toByteArray();
+}
+
+void HelpEngineWrapper::setBookmarks(const QByteArray &bookmarks)
+{
+ TRACE_OBJ
+ d->m_helpEngine->setCustomValue(BookmarksKey, bookmarks);
+}
+
+int HelpEngineWrapper::lastTabPage() const
+{
+ TRACE_OBJ
+ return CollectionConfiguration::lastTabPage(*d->m_helpEngine);
+}
+
+void HelpEngineWrapper::setLastTabPage(int lastPage)
+{
+ TRACE_OBJ
+ CollectionConfiguration::setLastTabPage(*d->m_helpEngine, lastPage);
+}
+
+int HelpEngineWrapper::startOption() const
+{
+ TRACE_OBJ
+ return d->m_helpEngine->customValue(StartOptionKey, ShowLastPages).toInt();
+}
+
+void HelpEngineWrapper::setStartOption(int option)
+{
+ TRACE_OBJ
+ d->m_helpEngine->setCustomValue(StartOptionKey, option);
+}
+
+const QString HelpEngineWrapper::homePage() const
+{
+ TRACE_OBJ
+ const QString &homePage
+ = d->m_helpEngine->customValue(HomePageKey).toString();
+ if (!homePage.isEmpty())
+ return homePage;
+ return defaultHomePage();
+}
+
+void HelpEngineWrapper::setHomePage(const QString &page)
+{
+ TRACE_OBJ
+ d->m_helpEngine->setCustomValue(HomePageKey, page);
+
+}
+
+const QString HelpEngineWrapper::defaultHomePage() const
+{
+ TRACE_OBJ
+ return CollectionConfiguration::defaultHomePage(*d->m_helpEngine);
+}
+
+void HelpEngineWrapper::setDefaultHomePage(const QString &page)
+{
+ TRACE_OBJ
+ CollectionConfiguration::setDefaultHomePage(*d->m_helpEngine, page);
+}
+
+bool HelpEngineWrapper::hasFontSettings() const
+{
+ TRACE_OBJ
+ return d->m_helpEngine->customValue(UseAppFontKey).isValid();
+}
+
+bool HelpEngineWrapper::usesAppFont() const
+{
+ TRACE_OBJ
+ return d->m_helpEngine->customValue(UseAppFontKey).toBool();
+}
+
+void HelpEngineWrapper::setUseAppFont(bool useAppFont)
+{
+ TRACE_OBJ
+ d->m_helpEngine->setCustomValue(UseAppFontKey, useAppFont);
+}
+
+bool HelpEngineWrapper::usesBrowserFont() const
+{
+ TRACE_OBJ
+ return d->m_helpEngine->customValue(UseBrowserFontKey, false).toBool();
+}
+
+void HelpEngineWrapper::setUseBrowserFont(bool useBrowserFont)
+{
+ TRACE_OBJ
+ d->m_helpEngine->setCustomValue(UseBrowserFontKey, useBrowserFont);
+}
+
+const QFont HelpEngineWrapper::appFont() const
+{
+ TRACE_OBJ
+ return qvariant_cast<QFont>(d->m_helpEngine->customValue(AppFontKey));
+}
+
+void HelpEngineWrapper::setAppFont(const QFont &font)
+{
+ TRACE_OBJ
+ d->m_helpEngine->setCustomValue(AppFontKey, font);
+}
+
+QFontDatabase::WritingSystem HelpEngineWrapper::appWritingSystem() const
+{
+ TRACE_OBJ
+ return static_cast<QFontDatabase::WritingSystem>(
+ d->m_helpEngine->customValue(AppWritingSystemKey).toInt());
+}
+
+void HelpEngineWrapper::setAppWritingSystem(QFontDatabase::WritingSystem system)
+{
+ TRACE_OBJ
+ d->m_helpEngine->setCustomValue(AppWritingSystemKey, system);
+}
+
+const QFont HelpEngineWrapper::browserFont() const
+{
+ TRACE_OBJ
+ return qvariant_cast<QFont>(d->m_helpEngine->customValue(BrowserFontKey));
+}
+
+void HelpEngineWrapper::setBrowserFont(const QFont &font)
+{
+ TRACE_OBJ
+ d->m_helpEngine->setCustomValue(BrowserFontKey, font);
+}
+
+QFontDatabase::WritingSystem HelpEngineWrapper::browserWritingSystem() const
+{
+ TRACE_OBJ
+ return static_cast<QFontDatabase::WritingSystem>(
+ d->m_helpEngine->customValue(BrowserWritingSystemKey).toInt());
+}
+
+void HelpEngineWrapper::setBrowserWritingSystem(QFontDatabase::WritingSystem system)
+{
+ TRACE_OBJ
+ d->m_helpEngine->setCustomValue(BrowserWritingSystemKey, system);
+}
+
+void HelpEngineWrapper::handleCurrentFilterChanged(const QString &filter)
+{
+ TRACE_OBJ
+ const QString &filterToReport
+ = filter == Unfiltered ? TrUnfiltered : filter;
+ emit currentFilterChanged(filterToReport);
+}
+
+bool HelpEngineWrapper::showTabs() const
+{
+ TRACE_OBJ
+ return d->m_helpEngine->customValue(ShowTabsKey, false).toBool();
+}
+
+void HelpEngineWrapper::setShowTabs(bool show)
+{
+ TRACE_OBJ
+ d->m_helpEngine->setCustomValue(ShowTabsKey, show);
+}
+
+bool HelpEngineWrapper::fullTextSearchFallbackEnabled() const
+{
+ TRACE_OBJ
+ return CollectionConfiguration::fullTextSearchFallbackEnabled(*d->m_helpEngine);
+}
+
+// -- TimeoutForwarder
+
+TimeoutForwarder::TimeoutForwarder(const QString &fileName)
+ : m_fileName(fileName)
+{
+ TRACE_OBJ
+}
+
+void TimeoutForwarder::forward()
+{
+ TRACE_OBJ
+ HelpEngineWrapper::instance().d->qchFileChanged(m_fileName, true);
+}
+
+// -- HelpEngineWrapperPrivate
+
+HelpEngineWrapperPrivate::HelpEngineWrapperPrivate(const QString &collectionFile)
+ : m_helpEngine(new QHelpEngine(collectionFile, this)),
+ m_qchWatcher(new QFileSystemWatcher(this))
+{
+ TRACE_OBJ
+ if (!m_helpEngine->customFilters().contains(Unfiltered))
+ m_helpEngine->addCustomFilter(Unfiltered, QStringList());
+ initFileSystemWatchers();
+}
+
+void HelpEngineWrapperPrivate::initFileSystemWatchers()
+{
+ TRACE_OBJ
+ foreach(const QString &ns, m_helpEngine->registeredDocumentations()) {
+ const QString &docFile = m_helpEngine->documentationFileName(ns);
+ m_qchWatcher->addPath(docFile);
+ connect(m_qchWatcher, SIGNAL(fileChanged(QString)),
+ this, SLOT(qchFileChanged(QString)));
+ }
+ checkDocFilesWatched();
+}
+
+void HelpEngineWrapperPrivate::qchFileChanged(const QString &fileName)
+{
+ TRACE_OBJ
+ qchFileChanged(fileName, false);
+}
+
+void HelpEngineWrapperPrivate::checkDocFilesWatched()
+{
+ TRACE_OBJ
+ const int watchedFilesCount = m_qchWatcher->files().count();
+ const int docFilesCount = m_helpEngine->registeredDocumentations().count();
+ if (watchedFilesCount != docFilesCount) {
+ qWarning("Strange: Have %d docs, but %d are being watched",
+ watchedFilesCount, docFilesCount);
+ }
+}
+
+void HelpEngineWrapperPrivate::qchFileChanged(const QString &fileName,
+ bool fromTimeout)
+{
+ TRACE_OBJ
+
+ /*
+ * We don't use QHelpEngineCore::namespaceName(fileName), because the file
+ * may not exist anymore or contain a different namespace.
+ */
+ QString ns;
+ foreach (const QString &curNs, m_helpEngine->registeredDocumentations()) {
+ if (m_helpEngine->documentationFileName(curNs) == fileName) {
+ ns = curNs;
+ break;
+ }
+ }
+
+ /*
+ * We can't do an assertion here, because QFileSystemWatcher may send the
+ * signal more than once.
+ */
+ if (ns.isEmpty()) {
+ m_recentQchUpdates.remove(fileName);
+ return;
+ }
+
+ /*
+ * Since the QFileSystemWatcher typically sends the signal more than once,
+ * we repeatedly delay our reaction a bit until we think the last signal
+ * was sent.
+ */
+
+ QMap<QString, RecentSignal>::Iterator it = m_recentQchUpdates.find(fileName);
+ const QDateTime &now = QDateTime::currentDateTime();
+
+ // Case 1: This is the first recent signal for the file.
+ if (it == m_recentQchUpdates.end()) {
+ QSharedPointer<TimeoutForwarder> forwarder(new TimeoutForwarder(fileName));
+ m_recentQchUpdates.insert(fileName, RecentSignal(now, forwarder));
+ QTimer::singleShot(UpdateGracePeriod, forwarder.data(), SLOT(forward()));
+ return;
+ }
+
+ // Case 2: The last signal for this file has not expired yet.
+ if (it.value().first > now.addMSecs(-UpdateGracePeriod)) {
+ if (!fromTimeout)
+ it.value().first = now;
+ else
+ QTimer::singleShot(UpdateGracePeriod, it.value().second.data(),
+ SLOT(forward()));
+ return;
+ }
+
+ // Case 3: The last signal for this file has expired.
+ if (m_helpEngine->unregisterDocumentation(ns)) {
+ if (!QFileInfo(fileName).exists()
+ || !m_helpEngine->registerDocumentation(fileName)) {
+ m_qchWatcher->removePath(fileName);
+ emit documentationRemoved(ns);
+ } else {
+ emit documentationUpdated(ns);
+ }
+ m_helpEngine->setupData();
+ }
+ m_recentQchUpdates.erase(it);
+}
+
+QT_END_NAMESPACE
+
+#include "helpenginewrapper.moc"
diff --git a/src/assistant/tools/assistant/helpenginewrapper.h b/src/assistant/tools/assistant/helpenginewrapper.h
new file mode 100644
index 000000000..ff825b04a
--- /dev/null
+++ b/src/assistant/tools/assistant/helpenginewrapper.h
@@ -0,0 +1,218 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef HELPENGINEWRAPPER_H
+#define HELPENGINEWRAPPER_H
+
+#include <QtCore/QMap>
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QUrl>
+#include <QtGui/QFont>
+#include <QtGui/QFontDatabase>
+
+QT_BEGIN_NAMESPACE
+
+class QFileSystemWatcher;
+class QHelpContentModel;
+class QHelpContentWidget;
+class QHelpIndexModel;
+class QHelpIndexWidget;
+class QHelpSearchEngine;
+
+enum {
+ ShowHomePage = 0,
+ ShowBlankPage = 1,
+ ShowLastPages = 2
+};
+
+class HelpEngineWrapperPrivate;
+class TimeoutForwarder;
+
+class HelpEngineWrapper : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(HelpEngineWrapper)
+ friend class TimeoutForwarder;
+public:
+ static HelpEngineWrapper &instance(const QString &collectionFile = QString());
+ static void removeInstance();
+
+ // Forwarded help engine member functions, possibly enriched.
+ QHelpSearchEngine *searchEngine() const;
+ QHelpContentModel *contentModel() const;
+ QHelpIndexModel *indexModel() const;
+ QHelpContentWidget *contentWidget();
+ QHelpIndexWidget *indexWidget();
+ bool setupData();
+ const QStringList registeredDocumentations() const;
+ const QString collectionFile() const;
+ bool registerDocumentation(const QString &docFile);
+ bool unregisterDocumentation(const QString &namespaceName);
+ bool addCustomFilter(const QString &filterName,
+ const QStringList &attributes);
+ bool removeCustomFilter(const QString &filterName);
+ void setCurrentFilter(const QString &filterName);
+ const QString currentFilter() const;
+ const QStringList customFilters() const;
+ QUrl findFile(const QUrl &url) const;
+ QByteArray fileData(const QUrl &url) const;
+ QMap<QString, QUrl> linksForIdentifier(const QString &id) const;
+ const QStringList filterAttributes() const;
+ const QStringList filterAttributes(const QString &filterName) const;
+ QString error() const;
+
+ /*
+ * To be called after assistant has finished looking for new documentation.
+ * This will mainly cause the search index to be updated, if necessary.
+ */
+ void initialDocSetupDone();
+
+ const QStringList qtDocInfo(const QString &component) const;
+ void setQtDocInfo(const QString &component, const QStringList &doc);
+
+ const QString homePage() const;
+ void setHomePage(const QString &page);
+ const QString defaultHomePage() const;
+ void setDefaultHomePage(const QString &page);
+
+ int lastTabPage() const;
+ void setLastTabPage(int lastPage);
+
+ // TODO: Don't allow last pages and zoom factors to be set in isolation
+ // Perhaps also fill up missing elements automatically or assert.
+ const QStringList lastShownPages() const;
+ void setLastShownPages(const QStringList &lastShownPages);
+ const QStringList lastZoomFactors() const;
+ void setLastZoomFactors(const QStringList &lastZoomFactors);
+
+ const QString cacheDir() const;
+ bool cacheDirIsRelativeToCollection() const;
+ void setCacheDir(const QString &cacheDir, bool relativeToCollection);
+
+ bool filterFunctionalityEnabled() const;
+ void setFilterFunctionalityEnabled(bool enabled);
+
+ bool filterToolbarVisible() const;
+ void setFilterToolbarVisible(bool visible);
+
+ bool addressBarEnabled() const;
+ void setAddressBarEnabled(bool enabled);
+
+ bool addressBarVisible() const;
+ void setAddressBarVisible(bool visible);
+
+ bool documentationManagerEnabled() const;
+ void setDocumentationManagerEnabled(bool enabled);
+
+ const QByteArray aboutMenuTexts() const;
+ void setAboutMenuTexts(const QByteArray &texts);
+ const QByteArray aboutTexts() const;
+ void setAboutTexts(const QByteArray &texts);
+ const QByteArray aboutIcon() const;
+ void setAboutIcon(const QByteArray &icon);
+ const QByteArray aboutImages() const;
+ void setAboutImages(const QByteArray &images);
+
+ const QString windowTitle() const;
+ void setWindowTitle(const QString &windowTitle);
+
+ const QByteArray applicationIcon() const;
+ void setApplicationIcon(const QByteArray &icon);
+
+ const QByteArray mainWindow() const;
+ void setMainWindow(const QByteArray &mainWindow);
+ const QByteArray mainWindowGeometry() const;
+ void setMainWindowGeometry(const QByteArray &geometry);
+
+ const QByteArray bookmarks() const;
+ void setBookmarks(const QByteArray &bookmarks);
+
+ int startOption() const;
+ void setStartOption(int option);
+
+ bool hasFontSettings() const;
+ bool usesAppFont() const;
+ void setUseAppFont(bool useAppFont);
+ bool usesBrowserFont() const;
+ void setUseBrowserFont(bool useBrowserFont);
+ const QFont appFont() const;
+ void setAppFont(const QFont &font);
+ QFontDatabase::WritingSystem appWritingSystem() const;
+ void setAppWritingSystem(QFontDatabase::WritingSystem system);
+ const QFont browserFont() const;
+ void setBrowserFont(const QFont &font);
+ QFontDatabase::WritingSystem browserWritingSystem() const;
+ void setBrowserWritingSystem(QFontDatabase::WritingSystem system);
+
+ bool showTabs() const;
+ void setShowTabs(bool show);
+
+ static const QString TrUnfiltered;
+
+ bool fullTextSearchFallbackEnabled() const;
+
+signals:
+
+ // For asynchronous doc updates triggered by external actions.
+ void documentationRemoved(const QString &namespaceName);
+ void documentationUpdated(const QString &namespaceName);
+
+ // Forwarded from QHelpEngineCore.
+ void currentFilterChanged(const QString &currentFilter);
+ void setupFinished();
+
+private slots:
+ void handleCurrentFilterChanged(const QString &filter);
+
+private:
+ HelpEngineWrapper(const QString &collectionFile);
+ ~HelpEngineWrapper();
+
+ static HelpEngineWrapper *helpEngineWrapper;
+
+ HelpEngineWrapperPrivate *d;
+};
+
+QT_END_NAMESPACE
+
+#endif // HELPENGINEWRAPPER_H
diff --git a/src/assistant/tools/assistant/helpviewer.cpp b/src/assistant/tools/assistant/helpviewer.cpp
new file mode 100644
index 000000000..7bed4965a
--- /dev/null
+++ b/src/assistant/tools/assistant/helpviewer.cpp
@@ -0,0 +1,221 @@
+/****************************************************************************
+**
+** 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 "helpviewer.h"
+#include "helpviewer_p.h"
+
+#include "helpenginewrapper.h"
+#include "tracer.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QFileInfo>
+#include <QtCore/QStringBuilder>
+#include <QtCore/QTemporaryFile>
+#include <QtCore/QUrl>
+
+#include <QtGui/QDesktopServices>
+#include <QtGui/QMouseEvent>
+
+#include <QtHelp/QHelpEngineCore>
+
+QT_BEGIN_NAMESPACE
+
+const QString HelpViewer::DocPath = QLatin1String("qthelp://com.trolltech.");
+
+const QString HelpViewer::AboutBlank =
+ QCoreApplication::translate("HelpViewer", "<title>about:blank</title>");
+
+const QString HelpViewer::LocalHelpFile = QLatin1String("qthelp://"
+ "com.trolltech.com.assistantinternal-1.0.0/assistant/assistant.html");
+
+const QString HelpViewer::PageNotFoundMessage =
+ QCoreApplication::translate("HelpViewer", "<title>Error 404...</title><div "
+ "align=\"center\"><br><br><h1>The page could not be found</h1><br><h3>'%1'"
+ "</h3></div>");
+
+struct ExtensionMap {
+ const char *extension;
+ const char *mimeType;
+} extensionMap[] = {
+ { ".bmp", "image/bmp" },
+ { ".css", "text/css" },
+ { ".gif", "image/gif" },
+ { ".html", "text/html" },
+ { ".htm", "text/html" },
+ { ".ico", "image/x-icon" },
+ { ".jpeg", "image/jpeg" },
+ { ".jpg", "image/jpeg" },
+ { ".js", "application/x-javascript" },
+ { ".mng", "video/x-mng" },
+ { ".pbm", "image/x-portable-bitmap" },
+ { ".pgm", "image/x-portable-graymap" },
+ { ".pdf", "application/pdf" },
+ { ".png", "image/png" },
+ { ".ppm", "image/x-portable-pixmap" },
+ { ".rss", "application/rss+xml" },
+ { ".svg", "image/svg+xml" },
+ { ".svgz", "image/svg+xml" },
+ { ".text", "text/plain" },
+ { ".tif", "image/tiff" },
+ { ".tiff", "image/tiff" },
+ { ".txt", "text/plain" },
+ { ".xbm", "image/x-xbitmap" },
+ { ".xml", "text/xml" },
+ { ".xpm", "image/x-xpm" },
+ { ".xsl", "text/xsl" },
+ { ".xhtml", "application/xhtml+xml" },
+ { ".wml", "text/vnd.wap.wml" },
+ { ".wmlc", "application/vnd.wap.wmlc" },
+ { "about:blank", 0 },
+ { 0, 0 }
+};
+
+HelpViewer::~HelpViewer()
+{
+ TRACE_OBJ
+ delete d;
+}
+
+bool HelpViewer::isLocalUrl(const QUrl &url)
+{
+ TRACE_OBJ
+ const QString &scheme = url.scheme();
+ return scheme.isEmpty()
+ || scheme == QLatin1String("file")
+ || scheme == QLatin1String("qrc")
+ || scheme == QLatin1String("data")
+ || scheme == QLatin1String("qthelp")
+ || scheme == QLatin1String("about");
+}
+
+bool HelpViewer::canOpenPage(const QString &url)
+{
+ TRACE_OBJ
+ return !mimeFromUrl(url).isEmpty();
+}
+
+QString HelpViewer::mimeFromUrl(const QUrl &url)
+{
+ TRACE_OBJ
+ const QString &path = url.path();
+ const int index = path.lastIndexOf(QLatin1Char('.'));
+ const QByteArray &ext = path.mid(index).toUtf8().toLower();
+
+ const ExtensionMap *e = extensionMap;
+ while (e->extension) {
+ if (ext == e->extension)
+ return QLatin1String(e->mimeType);
+ ++e;
+ }
+ return QLatin1String("");
+}
+
+bool HelpViewer::launchWithExternalApp(const QUrl &url)
+{
+ TRACE_OBJ
+ if (isLocalUrl(url)) {
+ const HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance();
+ const QUrl &resolvedUrl = helpEngine.findFile(url);
+ if (!resolvedUrl.isValid())
+ return false;
+
+ const QString& path = resolvedUrl.path();
+ if (!canOpenPage(path)) {
+ QTemporaryFile tmpTmpFile;
+ if (!tmpTmpFile.open())
+ return false;
+
+ const QString &extension = QFileInfo(path).completeSuffix();
+ QFile actualTmpFile(tmpTmpFile.fileName() % QLatin1String(".")
+ % extension);
+ if (!actualTmpFile.open(QIODevice::ReadWrite | QIODevice::Truncate))
+ return false;
+
+ actualTmpFile.write(helpEngine.fileData(resolvedUrl));
+ actualTmpFile.close();
+ return QDesktopServices::openUrl(QUrl(actualTmpFile.fileName()));
+ }
+ } else if (url.scheme() == QLatin1String("http")) {
+ return QDesktopServices::openUrl(url);
+ }
+ return false;
+}
+
+// -- public slots
+
+void HelpViewer::home()
+{
+ TRACE_OBJ
+ setSource(HelpEngineWrapper::instance().homePage());
+}
+
+// -- private slots
+
+void HelpViewer::setLoadStarted()
+{
+ d->m_loadFinished = false;
+}
+
+void HelpViewer::setLoadFinished(bool ok)
+{
+ d->m_loadFinished = ok;
+ emit sourceChanged(source());
+}
+
+// -- private
+
+bool HelpViewer::handleForwardBackwardMouseButtons(QMouseEvent *event)
+{
+ TRACE_OBJ
+ if (event->button() == Qt::XButton1) {
+ backward();
+ return true;
+ }
+
+ if (event->button() == Qt::XButton2) {
+ forward();
+ return true;
+ }
+
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/helpviewer.h b/src/assistant/tools/assistant/helpviewer.h
new file mode 100644
index 000000000..bba01d0e6
--- /dev/null
+++ b/src/assistant/tools/assistant/helpviewer.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef HELPVIEWER_H
+#define HELPVIEWER_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/QString>
+#include <QtCore/QUrl>
+#include <QtCore/QVariant>
+
+#include <QtGui/QAction>
+#include <QtGui/QFont>
+
+#if defined(QT_NO_WEBKIT)
+#include <QtGui/QTextBrowser>
+#else
+#include <QtWebKit/QWebView>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_NO_WEBKIT)
+class HelpViewer : public QWebView
+#else
+class HelpViewer : public QTextBrowser
+#endif
+{
+ Q_OBJECT
+ class HelpViewerPrivate;
+ Q_DISABLE_COPY(HelpViewer)
+
+public:
+ enum FindFlag {
+ FindBackward = 0x01,
+ FindCaseSensitively = 0x02
+ };
+ Q_DECLARE_FLAGS(FindFlags, FindFlag)
+
+ HelpViewer(qreal zoom, QWidget *parent = 0);
+ ~HelpViewer();
+
+ QFont viewerFont() const;
+ void setViewerFont(const QFont &font);
+
+ void scaleUp();
+ void scaleDown();
+
+ void resetScale();
+ qreal scale() const;
+
+ QString title() const;
+ void setTitle(const QString &title);
+
+ QUrl source() const;
+ void setSource(const QUrl &url);
+
+ QString selectedText() const;
+ bool isForwardAvailable() const;
+ bool isBackwardAvailable() const;
+
+ bool findText(const QString &text, FindFlags flags, bool incremental,
+ bool fromSearch);
+
+ static const QString DocPath;
+ static const QString AboutBlank;
+ static const QString LocalHelpFile;
+ static const QString PageNotFoundMessage;
+
+ static bool isLocalUrl(const QUrl &url);
+ static bool canOpenPage(const QString &url);
+ static QString mimeFromUrl(const QUrl &url);
+ static bool launchWithExternalApp(const QUrl &url);
+
+public slots:
+ void copy();
+ void home();
+
+ void forward();
+ void backward();
+
+signals:
+ void titleChanged();
+#if !defined(QT_NO_WEBKIT)
+ void copyAvailable(bool yes);
+ void sourceChanged(const QUrl &url);
+ void forwardAvailable(bool enabled);
+ void backwardAvailable(bool enabled);
+ void highlighted(const QString &link);
+ void printRequested();
+#else
+ void loadStarted();
+ void loadFinished(bool finished);
+#endif
+
+protected:
+ void keyPressEvent(QKeyEvent *e);
+ void wheelEvent(QWheelEvent *event);
+ void mousePressEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+
+private slots:
+ void actionChanged();
+ void setLoadStarted();
+ void setLoadFinished(bool ok);
+
+private:
+ bool eventFilter(QObject *obj, QEvent *event);
+ void contextMenuEvent(QContextMenuEvent *event);
+ QVariant loadResource(int type, const QUrl &name);
+ bool handleForwardBackwardMouseButtons(QMouseEvent *e);
+
+private:
+ HelpViewerPrivate *d;
+};
+
+QT_END_NAMESPACE
+Q_DECLARE_METATYPE(HelpViewer*)
+
+#endif // HELPVIEWER_H
diff --git a/src/assistant/tools/assistant/helpviewer_p.h b/src/assistant/tools/assistant/helpviewer_p.h
new file mode 100644
index 000000000..378871197
--- /dev/null
+++ b/src/assistant/tools/assistant/helpviewer_p.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef HELPVIEWERPRIVATE_H
+#define HELPVIEWERPRIVATE_H
+
+#include "centralwidget.h"
+#include "helpviewer.h"
+#include "openpagesmanager.h"
+
+#include <QtCore/QObject>
+#ifdef QT_NO_WEBKIT
+#include <QtGui/QTextBrowser>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class HelpViewer::HelpViewerPrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+#ifdef QT_NO_WEBKIT
+ HelpViewerPrivate(int zoom)
+ : zoomCount(zoom)
+ , forceFont(false)
+ , lastAnchor(QString())
+#else
+ HelpViewerPrivate()
+#endif
+ {
+ m_loadFinished = false;
+ }
+
+#ifdef QT_NO_WEBKIT
+ bool hasAnchorAt(QTextBrowser *browser, const QPoint& pos)
+ {
+ lastAnchor = browser->anchorAt(pos);
+ if (lastAnchor.isEmpty())
+ return false;
+
+ lastAnchor = browser->source().resolved(lastAnchor).toString();
+ if (lastAnchor.at(0) == QLatin1Char('#')) {
+ QString src = browser->source().toString();
+ int hsh = src.indexOf(QLatin1Char('#'));
+ lastAnchor = (hsh >= 0 ? src.left(hsh) : src) + lastAnchor;
+ }
+ return true;
+ }
+
+ void openLink(bool newPage)
+ {
+ if(lastAnchor.isEmpty())
+ return;
+ if (newPage)
+ OpenPagesManager::instance()->createPage(lastAnchor);
+ else
+ CentralWidget::instance()->setSource(lastAnchor);
+ lastAnchor.clear();
+ }
+
+public slots:
+ void openLink()
+ {
+ openLink(false);
+ }
+
+ void openLinkInNewPage()
+ {
+ openLink(true);
+ }
+
+public:
+ int zoomCount;
+ bool forceFont;
+ QString lastAnchor;
+#endif // QT_NO_WEBKIT
+
+public:
+ bool m_loadFinished;
+};
+
+QT_END_NAMESPACE
+
+#endif // HELPVIEWERPRIVATE_H
diff --git a/src/assistant/tools/assistant/helpviewer_qtb.cpp b/src/assistant/tools/assistant/helpviewer_qtb.cpp
new file mode 100644
index 000000000..0a6325cb5
--- /dev/null
+++ b/src/assistant/tools/assistant/helpviewer_qtb.cpp
@@ -0,0 +1,384 @@
+/****************************************************************************
+**
+** 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 "helpviewer.h"
+
+#include "globalactions.h"
+#include "helpenginewrapper.h"
+#include "helpviewer_p.h"
+#include "openpagesmanager.h"
+#include "tracer.h"
+
+#include <QtCore/QStringBuilder>
+
+#include <QtGui/QContextMenuEvent>
+#include <QtGui/QMenu>
+#include <QtGui/QClipboard>
+#include <QtGui/QApplication>
+
+QT_BEGIN_NAMESPACE
+
+HelpViewer::HelpViewer(qreal zoom, QWidget *parent)
+ : QTextBrowser(parent)
+ , d(new HelpViewerPrivate(zoom))
+{
+ TRACE_OBJ
+ QPalette p = palette();
+ p.setColor(QPalette::Inactive, QPalette::Highlight,
+ p.color(QPalette::Active, QPalette::Highlight));
+ p.setColor(QPalette::Inactive, QPalette::HighlightedText,
+ p.color(QPalette::Active, QPalette::HighlightedText));
+ setPalette(p);
+
+ installEventFilter(this);
+ document()->setDocumentMargin(8);
+
+ QFont font = viewerFont();
+ font.setPointSize(int(font.pointSize() + zoom));
+ setViewerFont(font);
+
+ connect(this, SIGNAL(sourceChanged(QUrl)), this, SIGNAL(titleChanged()));
+ connect(this, SIGNAL(loadFinished(bool)), this, SLOT(setLoadFinished(bool)));
+}
+
+QFont HelpViewer::viewerFont() const
+{
+ TRACE_OBJ
+ if (HelpEngineWrapper::instance().usesBrowserFont())
+ return HelpEngineWrapper::instance().browserFont();
+ return qApp->font();
+}
+
+void HelpViewer::setViewerFont(const QFont &newFont)
+{
+ TRACE_OBJ
+ if (font() != newFont) {
+ d->forceFont = true;
+ setFont(newFont);
+ d->forceFont = false;
+ }
+}
+
+void HelpViewer::scaleUp()
+{
+ TRACE_OBJ
+ if (d->zoomCount < 10) {
+ d->zoomCount++;
+ d->forceFont = true;
+ zoomIn();
+ d->forceFont = false;
+ }
+}
+
+void HelpViewer::scaleDown()
+{
+ TRACE_OBJ
+ if (d->zoomCount > -5) {
+ d->zoomCount--;
+ d->forceFont = true;
+ zoomOut();
+ d->forceFont = false;
+ }
+}
+
+void HelpViewer::resetScale()
+{
+ TRACE_OBJ
+ if (d->zoomCount != 0) {
+ d->forceFont = true;
+ zoomOut(d->zoomCount);
+ d->forceFont = false;
+ }
+ d->zoomCount = 0;
+}
+
+qreal HelpViewer::scale() const
+{
+ TRACE_OBJ
+ return d->zoomCount;
+}
+
+QString HelpViewer::title() const
+{
+ TRACE_OBJ
+ return documentTitle();
+}
+
+void HelpViewer::setTitle(const QString &title)
+{
+ TRACE_OBJ
+ setDocumentTitle(title);
+}
+
+QUrl HelpViewer::source() const
+{
+ TRACE_OBJ
+ return QTextBrowser::source();
+}
+
+void HelpViewer::setSource(const QUrl &url)
+{
+ TRACE_OBJ
+ if (launchWithExternalApp(url))
+ return;
+
+ emit loadStarted();
+ QString string = url.toString();
+ const HelpEngineWrapper &engine = HelpEngineWrapper::instance();
+ const QUrl &resolvedUrl = (string == QLatin1String("help") ? LocalHelpFile :
+ engine.findFile(string));
+ QTextBrowser::setSource(resolvedUrl);
+ if (!url.isValid()) {
+ setHtml(string == QLatin1String("about:blank") ? AboutBlank
+ : PageNotFoundMessage.arg(url.toString()));
+ }
+ emit loadFinished(true);
+}
+
+QString HelpViewer::selectedText() const
+{
+ TRACE_OBJ
+ return textCursor().selectedText();
+}
+
+bool HelpViewer::isForwardAvailable() const
+{
+ TRACE_OBJ
+ return QTextBrowser::isForwardAvailable();
+}
+
+bool HelpViewer::isBackwardAvailable() const
+{
+ TRACE_OBJ
+ return QTextBrowser::isBackwardAvailable();
+}
+
+bool HelpViewer::findText(const QString &text, FindFlags flags, bool incremental,
+ bool fromSearch)
+{
+ TRACE_OBJ
+ QTextDocument *doc = document();
+ QTextCursor cursor = textCursor();
+ if (!doc || cursor.isNull())
+ return false;
+
+ const int position = cursor.selectionStart();
+ if (incremental)
+ cursor.setPosition(position);
+
+ QTextDocument::FindFlags textDocFlags;
+ if (flags & HelpViewer::FindBackward)
+ textDocFlags |= QTextDocument::FindBackward;
+ if (flags & HelpViewer::FindCaseSensitively)
+ textDocFlags |= QTextDocument::FindCaseSensitively;
+
+ QTextCursor found = doc->find(text, cursor, textDocFlags);
+ if (found.isNull()) {
+ if ((flags & HelpViewer::FindBackward) == 0)
+ cursor.movePosition(QTextCursor::Start);
+ else
+ cursor.movePosition(QTextCursor::End);
+ found = doc->find(text, cursor, textDocFlags);
+ }
+
+ if (fromSearch) {
+ cursor.beginEditBlock();
+ viewport()->setUpdatesEnabled(false);
+
+ QTextCharFormat marker;
+ marker.setForeground(Qt::red);
+ cursor.movePosition(QTextCursor::Start);
+ setTextCursor(cursor);
+
+ while (find(text)) {
+ QTextCursor hit = textCursor();
+ hit.mergeCharFormat(marker);
+ }
+
+ viewport()->setUpdatesEnabled(true);
+ cursor.endEditBlock();
+ }
+
+ bool cursorIsNull = found.isNull();
+ if (cursorIsNull) {
+ found = textCursor();
+ found.setPosition(position);
+ }
+ setTextCursor(found);
+ return !cursorIsNull;
+}
+
+// -- public slots
+
+void HelpViewer::copy()
+{
+ TRACE_OBJ
+ QTextBrowser::copy();
+}
+
+void HelpViewer::forward()
+{
+ TRACE_OBJ
+ QTextBrowser::forward();
+}
+
+void HelpViewer::backward()
+{
+ TRACE_OBJ
+ QTextBrowser::backward();
+}
+
+// -- protected
+
+void HelpViewer::keyPressEvent(QKeyEvent *e)
+{
+ TRACE_OBJ
+ if ((e->key() == Qt::Key_Home && e->modifiers() != Qt::NoModifier)
+ || (e->key() == Qt::Key_End && e->modifiers() != Qt::NoModifier)) {
+ QKeyEvent* event = new QKeyEvent(e->type(), e->key(), Qt::NoModifier,
+ e->text(), e->isAutoRepeat(), e->count());
+ e = event;
+ }
+ QTextBrowser::keyPressEvent(e);
+}
+
+
+void HelpViewer::wheelEvent(QWheelEvent *e)
+{
+ TRACE_OBJ
+ if (e->modifiers() == Qt::ControlModifier) {
+ e->accept();
+ e->delta() > 0 ? scaleUp() : scaleDown();
+ } else {
+ QTextBrowser::wheelEvent(e);
+ }
+}
+
+void HelpViewer::mousePressEvent(QMouseEvent *e)
+{
+ TRACE_OBJ
+#ifdef Q_OS_LINUX
+ if (handleForwardBackwardMouseButtons(e))
+ return;
+#endif
+
+ QTextBrowser::mousePressEvent(e);
+}
+
+void HelpViewer::mouseReleaseEvent(QMouseEvent *e)
+{
+ TRACE_OBJ
+#ifndef Q_OS_LINUX
+ if (handleForwardBackwardMouseButtons(e))
+ return;
+#endif
+
+ bool controlPressed = e->modifiers() & Qt::ControlModifier;
+ if ((controlPressed && d->hasAnchorAt(this, e->pos())) ||
+ (e->button() == Qt::MidButton && d->hasAnchorAt(this, e->pos()))) {
+ d->openLinkInNewPage();
+ return;
+ }
+
+ QTextBrowser::mouseReleaseEvent(e);
+}
+
+// -- private slots
+
+void HelpViewer::actionChanged()
+{
+ // stub
+ TRACE_OBJ
+}
+
+// -- private
+
+bool HelpViewer::eventFilter(QObject *obj, QEvent *event)
+{
+ TRACE_OBJ
+ if (event->type() == QEvent::FontChange && !d->forceFont)
+ return true;
+ return QTextBrowser::eventFilter(obj, event);
+}
+
+void HelpViewer::contextMenuEvent(QContextMenuEvent *event)
+{
+ TRACE_OBJ
+
+ QMenu menu(QString(), 0);
+ QUrl link;
+ QAction *copyAnchorAction = 0;
+ if (d->hasAnchorAt(this, event->pos())) {
+ link = anchorAt(event->pos());
+ if (link.isRelative())
+ link = source().resolved(link);
+ menu.addAction(tr("Open Link"), d, SLOT(openLink()));
+ menu.addAction(tr("Open Link in New Tab\tCtrl+LMB"), d, SLOT(openLinkInNewPage()));
+
+ if (!link.isEmpty() && link.isValid())
+ copyAnchorAction = menu.addAction(tr("Copy &Link Location"));
+ } else if (!selectedText().isEmpty()) {
+ menu.addAction(tr("Copy"), this, SLOT(copy()));
+ } else {
+ menu.addAction(tr("Reload"), this, SLOT(reload()));
+ }
+
+ if (copyAnchorAction == menu.exec(event->globalPos()))
+ QApplication::clipboard()->setText(link.toString());
+}
+
+QVariant HelpViewer::loadResource(int type, const QUrl &name)
+{
+ TRACE_OBJ
+ QByteArray ba;
+ if (type < 4) {
+ ba = HelpEngineWrapper::instance().fileData(name);
+ if (name.toString().endsWith(QLatin1String(".svg"), Qt::CaseInsensitive)) {
+ QImage image;
+ image.loadFromData(ba, "svg");
+ if (!image.isNull())
+ return image;
+ }
+ }
+ return ba;
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/helpviewer_qwv.cpp b/src/assistant/tools/assistant/helpviewer_qwv.cpp
new file mode 100644
index 000000000..efb9b5900
--- /dev/null
+++ b/src/assistant/tools/assistant/helpviewer_qwv.cpp
@@ -0,0 +1,495 @@
+/****************************************************************************
+**
+** 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 "helpviewer.h"
+#include "helpviewer_p.h"
+
+#include "centralwidget.h"
+#include "helpenginewrapper.h"
+#include "openpagesmanager.h"
+#include "tracer.h"
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QString>
+#include <QtCore/QTimer>
+
+#include <QtGui/QApplication>
+#include <QtGui/QWheelEvent>
+
+#include <QtHelp/QHelpEngineCore>
+
+#include <QtNetwork/QNetworkAccessManager>
+#include <QtNetwork/QNetworkReply>
+#include <QtNetwork/QNetworkRequest>
+
+QT_BEGIN_NAMESPACE
+
+// -- HelpNetworkReply
+
+class HelpNetworkReply : public QNetworkReply
+{
+public:
+ HelpNetworkReply(const QNetworkRequest &request, const QByteArray &fileData,
+ const QString &mimeType);
+
+ virtual void abort();
+
+ virtual qint64 bytesAvailable() const
+ { return data.length() + QNetworkReply::bytesAvailable(); }
+
+protected:
+ virtual qint64 readData(char *data, qint64 maxlen);
+
+private:
+ QByteArray data;
+ qint64 origLen;
+};
+
+HelpNetworkReply::HelpNetworkReply(const QNetworkRequest &request,
+ const QByteArray &fileData, const QString& mimeType)
+ : data(fileData), origLen(fileData.length())
+{
+ TRACE_OBJ
+ setRequest(request);
+ setOpenMode(QIODevice::ReadOnly);
+
+ setHeader(QNetworkRequest::ContentTypeHeader, mimeType);
+ setHeader(QNetworkRequest::ContentLengthHeader, QByteArray::number(origLen));
+ QTimer::singleShot(0, this, SIGNAL(metaDataChanged()));
+ QTimer::singleShot(0, this, SIGNAL(readyRead()));
+}
+
+void HelpNetworkReply::abort()
+{
+ TRACE_OBJ
+}
+
+qint64 HelpNetworkReply::readData(char *buffer, qint64 maxlen)
+{
+ TRACE_OBJ
+ qint64 len = qMin(qint64(data.length()), maxlen);
+ if (len) {
+ memcpy(buffer, data.constData(), len);
+ data.remove(0, len);
+ }
+ if (!data.length())
+ QTimer::singleShot(0, this, SIGNAL(finished()));
+ return len;
+}
+
+// -- HelpNetworkAccessManager
+
+class HelpNetworkAccessManager : public QNetworkAccessManager
+{
+public:
+ HelpNetworkAccessManager(QObject *parent);
+
+protected:
+ virtual QNetworkReply *createRequest(Operation op,
+ const QNetworkRequest &request, QIODevice *outgoingData = 0);
+};
+
+HelpNetworkAccessManager::HelpNetworkAccessManager(QObject *parent)
+ : QNetworkAccessManager(parent)
+{
+ TRACE_OBJ
+}
+
+QNetworkReply *HelpNetworkAccessManager::createRequest(Operation /*op*/,
+ const QNetworkRequest &request, QIODevice* /*outgoingData*/)
+{
+ TRACE_OBJ
+ QString url = request.url().toString();
+ const HelpEngineWrapper &engine = HelpEngineWrapper::instance();
+ // TODO: For some reason the url to load is already wrong (passed from webkit)
+ // though the css file and the references inside should work that way. One
+ // possible problem might be that the css is loaded at the same level as the
+ // html, thus a path inside the css like (../images/foo.png) might cd out of
+ // the virtual folder
+ if (!engine.findFile(url).isValid()) {
+ if (url.startsWith(HelpViewer::DocPath)) {
+ QUrl newUrl = request.url();
+ if (!newUrl.path().startsWith(QLatin1String("/qdoc/"))) {
+ newUrl.setPath(QLatin1String("qdoc") + newUrl.path());
+ url = newUrl.toString();
+ }
+ }
+ }
+
+ const QString &mimeType = HelpViewer::mimeFromUrl(url);
+ const QByteArray &data = engine.findFile(url).isValid() ? engine.fileData(url)
+ : HelpViewer::PageNotFoundMessage.arg(url).toUtf8();
+
+ return new HelpNetworkReply(request, data, mimeType.isEmpty()
+ ? QLatin1String("application/octet-stream") : mimeType);
+}
+
+// -- HelpPage
+
+class HelpPage : public QWebPage
+{
+public:
+ HelpPage(QObject *parent);
+
+protected:
+ virtual QWebPage *createWindow(QWebPage::WebWindowType);
+ virtual void triggerAction(WebAction action, bool checked = false);
+
+ virtual bool acceptNavigationRequest(QWebFrame *frame,
+ const QNetworkRequest &request, NavigationType type);
+
+private:
+ bool closeNewTabIfNeeded;
+
+ friend class HelpViewer;
+ QUrl m_loadingUrl;
+ Qt::MouseButtons m_pressedButtons;
+ Qt::KeyboardModifiers m_keyboardModifiers;
+};
+
+HelpPage::HelpPage(QObject *parent)
+ : QWebPage(parent)
+ , closeNewTabIfNeeded(false)
+ , m_pressedButtons(Qt::NoButton)
+ , m_keyboardModifiers(Qt::NoModifier)
+{
+ TRACE_OBJ
+}
+
+QWebPage *HelpPage::createWindow(QWebPage::WebWindowType)
+{
+ TRACE_OBJ
+ HelpPage* newPage = static_cast<HelpPage*>(OpenPagesManager::instance()
+ ->createPage()->page());
+ newPage->closeNewTabIfNeeded = closeNewTabIfNeeded;
+ closeNewTabIfNeeded = false;
+ return newPage;
+}
+
+void HelpPage::triggerAction(WebAction action, bool checked)
+{
+ TRACE_OBJ
+ switch (action) {
+ case OpenLinkInNewWindow:
+ closeNewTabIfNeeded = true;
+ default: // fall through
+ QWebPage::triggerAction(action, checked);
+ break;
+ }
+}
+
+bool HelpPage::acceptNavigationRequest(QWebFrame *,
+ const QNetworkRequest &request, QWebPage::NavigationType type)
+{
+ TRACE_OBJ
+ const bool closeNewTab = closeNewTabIfNeeded;
+ closeNewTabIfNeeded = false;
+
+ const QUrl &url = request.url();
+ if (HelpViewer::launchWithExternalApp(url)) {
+ if (closeNewTab)
+ QMetaObject::invokeMethod(OpenPagesManager::instance(), "closeCurrentPage");
+ return false;
+ }
+
+ if (type == QWebPage::NavigationTypeLinkClicked
+ && (m_keyboardModifiers & Qt::ControlModifier || m_pressedButtons == Qt::MidButton)) {
+ m_pressedButtons = Qt::NoButton;
+ m_keyboardModifiers = Qt::NoModifier;
+ OpenPagesManager::instance()->createPage(url);
+ return false;
+ }
+
+ m_loadingUrl = url; // because of async page loading, we will hit some kind
+ // of race condition while using a remote command, like a combination of
+ // SetSource; SyncContent. SetSource would be called and SyncContents shortly
+ // afterwards, but the page might not have finished loading and the old url
+ // would be returned.
+ return true;
+}
+
+// -- HelpViewer
+
+HelpViewer::HelpViewer(qreal zoom, QWidget *parent)
+ : QWebView(parent)
+ , d(new HelpViewerPrivate)
+{
+ TRACE_OBJ
+ setAcceptDrops(false);
+ settings()->setAttribute(QWebSettings::JavaEnabled, false);
+ settings()->setAttribute(QWebSettings::PluginsEnabled, false);
+
+ setPage(new HelpPage(this));
+ page()->setNetworkAccessManager(new HelpNetworkAccessManager(this));
+
+ QAction* action = pageAction(QWebPage::OpenLinkInNewWindow);
+ action->setText(tr("Open Link in New Page"));
+
+ pageAction(QWebPage::DownloadLinkToDisk)->setVisible(false);
+ pageAction(QWebPage::DownloadImageToDisk)->setVisible(false);
+ pageAction(QWebPage::OpenImageInNewWindow)->setVisible(false);
+
+ connect(pageAction(QWebPage::Copy), SIGNAL(changed()), this,
+ SLOT(actionChanged()));
+ connect(pageAction(QWebPage::Back), SIGNAL(changed()), this,
+ SLOT(actionChanged()));
+ connect(pageAction(QWebPage::Forward), SIGNAL(changed()), this,
+ SLOT(actionChanged()));
+ connect(page(), SIGNAL(linkHovered(QString, QString, QString)), this,
+ SIGNAL(highlighted(QString)));
+ connect(this, SIGNAL(urlChanged(QUrl)), this, SIGNAL(sourceChanged(QUrl)));
+ connect(this, SIGNAL(loadStarted()), this, SLOT(setLoadStarted()));
+ connect(this, SIGNAL(loadFinished(bool)), this, SLOT(setLoadFinished(bool)));
+ connect(this, SIGNAL(titleChanged(QString)), this, SIGNAL(titleChanged()));
+ connect(page(), SIGNAL(printRequested(QWebFrame*)), this, SIGNAL(printRequested()));
+
+ setFont(viewerFont());
+ setTextSizeMultiplier(zoom == 0.0 ? 1.0 : zoom);
+}
+
+QFont HelpViewer::viewerFont() const
+{
+ TRACE_OBJ
+ if (HelpEngineWrapper::instance().usesBrowserFont())
+ return HelpEngineWrapper::instance().browserFont();
+
+ QWebSettings *webSettings = QWebSettings::globalSettings();
+ return QFont(webSettings->fontFamily(QWebSettings::StandardFont),
+ webSettings->fontSize(QWebSettings::DefaultFontSize));
+}
+
+void HelpViewer::setViewerFont(const QFont &font)
+{
+ TRACE_OBJ
+ QWebSettings *webSettings = settings();
+ webSettings->setFontFamily(QWebSettings::StandardFont, font.family());
+ webSettings->setFontSize(QWebSettings::DefaultFontSize, font.pointSize());
+}
+
+void HelpViewer::scaleUp()
+{
+ TRACE_OBJ
+ setTextSizeMultiplier(textSizeMultiplier() + 0.1);
+}
+
+void HelpViewer::scaleDown()
+{
+ TRACE_OBJ
+ setTextSizeMultiplier(qMax(0.0, textSizeMultiplier() - 0.1));
+}
+
+void HelpViewer::resetScale()
+{
+ TRACE_OBJ
+ setTextSizeMultiplier(1.0);
+}
+
+qreal HelpViewer::scale() const
+{
+ TRACE_OBJ
+ return textSizeMultiplier();
+}
+
+QString HelpViewer::title() const
+{
+ TRACE_OBJ
+ return QWebView::title();
+}
+
+void HelpViewer::setTitle(const QString &title)
+{
+ TRACE_OBJ
+ Q_UNUSED(title)
+}
+
+QUrl HelpViewer::source() const
+{
+ TRACE_OBJ
+ HelpPage *currentPage = static_cast<HelpPage*> (page());
+ if (currentPage && !d->m_loadFinished) {
+ // see HelpPage::acceptNavigationRequest(...)
+ return currentPage->m_loadingUrl;
+ }
+ return url();
+}
+
+void HelpViewer::setSource(const QUrl &url)
+{
+ TRACE_OBJ
+ load(url.toString() == QLatin1String("help") ? LocalHelpFile : url);
+}
+
+QString HelpViewer::selectedText() const
+{
+ TRACE_OBJ
+ return QWebView::selectedText();
+}
+
+bool HelpViewer::isForwardAvailable() const
+{
+ TRACE_OBJ
+ return pageAction(QWebPage::Forward)->isEnabled();
+}
+
+bool HelpViewer::isBackwardAvailable() const
+{
+ TRACE_OBJ
+ return pageAction(QWebPage::Back)->isEnabled();
+}
+
+bool HelpViewer::findText(const QString &text, FindFlags flags, bool incremental,
+ bool fromSearch)
+{
+ TRACE_OBJ
+ Q_UNUSED(incremental); Q_UNUSED(fromSearch);
+ QWebPage::FindFlags options = QWebPage::FindWrapsAroundDocument;
+ if (flags & FindBackward)
+ options |= QWebPage::FindBackward;
+ if (flags & FindCaseSensitively)
+ options |= QWebPage::FindCaseSensitively;
+
+ bool found = QWebView::findText(text, options);
+ options = QWebPage::HighlightAllOccurrences;
+ QWebView::findText(QLatin1String(""), options); // clear first
+ QWebView::findText(text, options); // force highlighting of all other matches
+ return found;
+}
+
+// -- public slots
+
+void HelpViewer::copy()
+{
+ TRACE_OBJ
+ triggerPageAction(QWebPage::Copy);
+}
+
+void HelpViewer::forward()
+{
+ TRACE_OBJ
+ QWebView::forward();
+}
+
+void HelpViewer::backward()
+{
+ TRACE_OBJ
+ back();
+}
+
+// -- protected
+
+void HelpViewer::keyPressEvent(QKeyEvent *e)
+{
+ TRACE_OBJ
+ // TODO: remove this once we support multiple keysequences per command
+ if (e->key() == Qt::Key_Insert && e->modifiers() == Qt::CTRL) {
+ if (!selectedText().isEmpty())
+ copy();
+ }
+ QWebView::keyPressEvent(e);
+}
+
+void HelpViewer::wheelEvent(QWheelEvent *event)
+{
+ TRACE_OBJ
+ if (event->modifiers()& Qt::ControlModifier) {
+ event->accept();
+ event->delta() > 0 ? scaleUp() : scaleDown();
+ } else {
+ QWebView::wheelEvent(event);
+ }
+}
+
+void HelpViewer::mousePressEvent(QMouseEvent *event)
+{
+ TRACE_OBJ
+#ifdef Q_OS_LINUX
+ if (handleForwardBackwardMouseButtons(event))
+ return;
+#endif
+
+ if (HelpPage *currentPage = static_cast<HelpPage*> (page())) {
+ currentPage->m_pressedButtons = event->buttons();
+ currentPage->m_keyboardModifiers = event->modifiers();
+ }
+
+ QWebView::mousePressEvent(event);
+}
+
+void HelpViewer::mouseReleaseEvent(QMouseEvent *event)
+{
+ TRACE_OBJ
+#ifndef Q_OS_LINUX
+ if (handleForwardBackwardMouseButtons(event))
+ return;
+#endif
+
+ QWebView::mouseReleaseEvent(event);
+}
+
+// -- private slots
+
+void HelpViewer::actionChanged()
+{
+ TRACE_OBJ
+ QAction *a = qobject_cast<QAction *>(sender());
+ if (a == pageAction(QWebPage::Copy))
+ emit copyAvailable(a->isEnabled());
+ else if (a == pageAction(QWebPage::Back))
+ emit backwardAvailable(a->isEnabled());
+ else if (a == pageAction(QWebPage::Forward))
+ emit forwardAvailable(a->isEnabled());
+}
+
+// -- private
+
+bool HelpViewer::eventFilter(QObject *obj, QEvent *event)
+{
+ TRACE_OBJ
+ return QWebView::eventFilter(obj, event);
+}
+
+void HelpViewer::contextMenuEvent(QContextMenuEvent *event)
+{
+ TRACE_OBJ
+ QWebView::contextMenuEvent(event);
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/images/assistant-128.png b/src/assistant/tools/assistant/images/assistant-128.png
new file mode 100644
index 000000000..f05949f6d
--- /dev/null
+++ b/src/assistant/tools/assistant/images/assistant-128.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/assistant.png b/src/assistant/tools/assistant/images/assistant.png
new file mode 100644
index 000000000..ea4d1e70c
--- /dev/null
+++ b/src/assistant/tools/assistant/images/assistant.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/bookmark.png b/src/assistant/tools/assistant/images/bookmark.png
new file mode 100644
index 000000000..57e57e343
--- /dev/null
+++ b/src/assistant/tools/assistant/images/bookmark.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/closebutton.png b/src/assistant/tools/assistant/images/closebutton.png
new file mode 100644
index 000000000..c978cf51a
--- /dev/null
+++ b/src/assistant/tools/assistant/images/closebutton.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/darkclosebutton.png b/src/assistant/tools/assistant/images/darkclosebutton.png
new file mode 100644
index 000000000..1077663b2
--- /dev/null
+++ b/src/assistant/tools/assistant/images/darkclosebutton.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/mac/addtab.png b/src/assistant/tools/assistant/images/mac/addtab.png
new file mode 100644
index 000000000..20928fb40
--- /dev/null
+++ b/src/assistant/tools/assistant/images/mac/addtab.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/mac/book.png b/src/assistant/tools/assistant/images/mac/book.png
new file mode 100644
index 000000000..7a3204c87
--- /dev/null
+++ b/src/assistant/tools/assistant/images/mac/book.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/mac/closetab.png b/src/assistant/tools/assistant/images/mac/closetab.png
new file mode 100644
index 000000000..ab9d669ee
--- /dev/null
+++ b/src/assistant/tools/assistant/images/mac/closetab.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/mac/editcopy.png b/src/assistant/tools/assistant/images/mac/editcopy.png
new file mode 100644
index 000000000..f55136446
--- /dev/null
+++ b/src/assistant/tools/assistant/images/mac/editcopy.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/mac/find.png b/src/assistant/tools/assistant/images/mac/find.png
new file mode 100644
index 000000000..3561745f0
--- /dev/null
+++ b/src/assistant/tools/assistant/images/mac/find.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/mac/home.png b/src/assistant/tools/assistant/images/mac/home.png
new file mode 100644
index 000000000..78d94da18
--- /dev/null
+++ b/src/assistant/tools/assistant/images/mac/home.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/mac/next.png b/src/assistant/tools/assistant/images/mac/next.png
new file mode 100644
index 000000000..a585cab80
--- /dev/null
+++ b/src/assistant/tools/assistant/images/mac/next.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/mac/previous.png b/src/assistant/tools/assistant/images/mac/previous.png
new file mode 100644
index 000000000..612fb34dc
--- /dev/null
+++ b/src/assistant/tools/assistant/images/mac/previous.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/mac/print.png b/src/assistant/tools/assistant/images/mac/print.png
new file mode 100644
index 000000000..10ca56c82
--- /dev/null
+++ b/src/assistant/tools/assistant/images/mac/print.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/mac/resetzoom.png b/src/assistant/tools/assistant/images/mac/resetzoom.png
new file mode 100644
index 000000000..759b38296
--- /dev/null
+++ b/src/assistant/tools/assistant/images/mac/resetzoom.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/mac/synctoc.png b/src/assistant/tools/assistant/images/mac/synctoc.png
new file mode 100644
index 000000000..067fa941b
--- /dev/null
+++ b/src/assistant/tools/assistant/images/mac/synctoc.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/mac/zoomin.png b/src/assistant/tools/assistant/images/mac/zoomin.png
new file mode 100644
index 000000000..d46f5aff0
--- /dev/null
+++ b/src/assistant/tools/assistant/images/mac/zoomin.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/mac/zoomout.png b/src/assistant/tools/assistant/images/mac/zoomout.png
new file mode 100644
index 000000000..46326566d
--- /dev/null
+++ b/src/assistant/tools/assistant/images/mac/zoomout.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/trolltech-logo.png b/src/assistant/tools/assistant/images/trolltech-logo.png
new file mode 100644
index 000000000..c53e744ca
--- /dev/null
+++ b/src/assistant/tools/assistant/images/trolltech-logo.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/win/addtab.png b/src/assistant/tools/assistant/images/win/addtab.png
new file mode 100644
index 000000000..4bb0feb92
--- /dev/null
+++ b/src/assistant/tools/assistant/images/win/addtab.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/win/book.png b/src/assistant/tools/assistant/images/win/book.png
new file mode 100644
index 000000000..09ec4d33f
--- /dev/null
+++ b/src/assistant/tools/assistant/images/win/book.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/win/closetab.png b/src/assistant/tools/assistant/images/win/closetab.png
new file mode 100644
index 000000000..ef9e02086
--- /dev/null
+++ b/src/assistant/tools/assistant/images/win/closetab.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/win/editcopy.png b/src/assistant/tools/assistant/images/win/editcopy.png
new file mode 100644
index 000000000..1121b47d8
--- /dev/null
+++ b/src/assistant/tools/assistant/images/win/editcopy.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/win/find.png b/src/assistant/tools/assistant/images/win/find.png
new file mode 100644
index 000000000..6ea35e930
--- /dev/null
+++ b/src/assistant/tools/assistant/images/win/find.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/win/home.png b/src/assistant/tools/assistant/images/win/home.png
new file mode 100644
index 000000000..b1c6ae191
--- /dev/null
+++ b/src/assistant/tools/assistant/images/win/home.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/win/next.png b/src/assistant/tools/assistant/images/win/next.png
new file mode 100644
index 000000000..8df4127a0
--- /dev/null
+++ b/src/assistant/tools/assistant/images/win/next.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/win/previous.png b/src/assistant/tools/assistant/images/win/previous.png
new file mode 100644
index 000000000..0780bc23d
--- /dev/null
+++ b/src/assistant/tools/assistant/images/win/previous.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/win/print.png b/src/assistant/tools/assistant/images/win/print.png
new file mode 100644
index 000000000..ba7c02dc1
--- /dev/null
+++ b/src/assistant/tools/assistant/images/win/print.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/win/resetzoom.png b/src/assistant/tools/assistant/images/win/resetzoom.png
new file mode 100644
index 000000000..b69ae4e7f
--- /dev/null
+++ b/src/assistant/tools/assistant/images/win/resetzoom.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/win/synctoc.png b/src/assistant/tools/assistant/images/win/synctoc.png
new file mode 100644
index 000000000..da301bc59
--- /dev/null
+++ b/src/assistant/tools/assistant/images/win/synctoc.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/win/zoomin.png b/src/assistant/tools/assistant/images/win/zoomin.png
new file mode 100644
index 000000000..2e586fc7b
--- /dev/null
+++ b/src/assistant/tools/assistant/images/win/zoomin.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/win/zoomout.png b/src/assistant/tools/assistant/images/win/zoomout.png
new file mode 100644
index 000000000..a736d3934
--- /dev/null
+++ b/src/assistant/tools/assistant/images/win/zoomout.png
Binary files differ
diff --git a/src/assistant/tools/assistant/images/wrap.png b/src/assistant/tools/assistant/images/wrap.png
new file mode 100644
index 000000000..90f18d9f7
--- /dev/null
+++ b/src/assistant/tools/assistant/images/wrap.png
Binary files differ
diff --git a/src/assistant/tools/assistant/indexwindow.cpp b/src/assistant/tools/assistant/indexwindow.cpp
new file mode 100644
index 000000000..38bc8b96a
--- /dev/null
+++ b/src/assistant/tools/assistant/indexwindow.cpp
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** 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 "indexwindow.h"
+
+#include "centralwidget.h"
+#include "helpenginewrapper.h"
+#include "helpviewer.h"
+#include "openpagesmanager.h"
+#include "topicchooser.h"
+#include "tracer.h"
+
+#include <QtGui/QLayout>
+#include <QtGui/QLabel>
+#include <QtGui/QLineEdit>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QMenu>
+#include <QtGui/QContextMenuEvent>
+#include <QtGui/QListWidgetItem>
+
+#include <QtHelp/QHelpIndexWidget>
+
+QT_BEGIN_NAMESPACE
+
+IndexWindow::IndexWindow(QWidget *parent)
+ : QWidget(parent)
+ , m_searchLineEdit(new QLineEdit)
+ , m_indexWidget(HelpEngineWrapper::instance().indexWidget())
+{
+ TRACE_OBJ
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ QLabel *l = new QLabel(tr("&Look for:"));
+ layout->addWidget(l);
+
+ l->setBuddy(m_searchLineEdit);
+ connect(m_searchLineEdit, SIGNAL(textChanged(QString)), this,
+ SLOT(filterIndices(QString)));
+ m_searchLineEdit->installEventFilter(this);
+ layout->setMargin(4);
+ layout->addWidget(m_searchLineEdit);
+
+ HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance();
+ m_indexWidget->installEventFilter(this);
+ connect(helpEngine.indexModel(), SIGNAL(indexCreationStarted()), this,
+ SLOT(disableSearchLineEdit()));
+ connect(helpEngine.indexModel(), SIGNAL(indexCreated()), this,
+ SLOT(enableSearchLineEdit()));
+ connect(m_indexWidget, SIGNAL(linkActivated(QUrl,QString)), this,
+ SIGNAL(linkActivated(QUrl)));
+ connect(m_indexWidget, SIGNAL(linksActivated(QMap<QString,QUrl>,QString)),
+ this, SIGNAL(linksActivated(QMap<QString,QUrl>,QString)));
+ connect(m_searchLineEdit, SIGNAL(returnPressed()), m_indexWidget,
+ SLOT(activateCurrentItem()));
+ layout->addWidget(m_indexWidget);
+
+ m_indexWidget->viewport()->installEventFilter(this);
+}
+
+IndexWindow::~IndexWindow()
+{
+ TRACE_OBJ
+}
+
+void IndexWindow::filterIndices(const QString &filter)
+{
+ TRACE_OBJ
+ if (filter.contains(QLatin1Char('*')))
+ m_indexWidget->filterIndices(filter, filter);
+ else
+ m_indexWidget->filterIndices(filter, QString());
+}
+
+bool IndexWindow::eventFilter(QObject *obj, QEvent *e)
+{
+ TRACE_OBJ
+ if (obj == m_searchLineEdit && e->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(e);
+ QModelIndex idx = m_indexWidget->currentIndex();
+ switch (ke->key()) {
+ case Qt::Key_Up:
+ idx = m_indexWidget->model()->index(idx.row()-1,
+ idx.column(), idx.parent());
+ if (idx.isValid()) {
+ m_indexWidget->setCurrentIndex(idx);
+ return true;
+ }
+ break;
+ case Qt::Key_Down:
+ idx = m_indexWidget->model()->index(idx.row()+1,
+ idx.column(), idx.parent());
+ if (idx.isValid()) {
+ m_indexWidget->setCurrentIndex(idx);
+ return true;
+ }
+ break;
+ case Qt::Key_Escape:
+ emit escapePressed();
+ return true;
+ default: ; // stop complaining
+ }
+ } else if (obj == m_indexWidget && e->type() == QEvent::ContextMenu) {
+ QContextMenuEvent *ctxtEvent = static_cast<QContextMenuEvent*>(e);
+ QModelIndex idx = m_indexWidget->indexAt(ctxtEvent->pos());
+ if (idx.isValid()) {
+ QMenu menu;
+ QAction *curTab = menu.addAction(tr("Open Link"));
+ QAction *newTab = menu.addAction(tr("Open Link in New Tab"));
+ menu.move(m_indexWidget->mapToGlobal(ctxtEvent->pos()));
+
+ QAction *action = menu.exec();
+ if (curTab == action)
+ m_indexWidget->activateCurrentItem();
+ else if (newTab == action) {
+ open(m_indexWidget, idx);
+ }
+ }
+ } else if (m_indexWidget && obj == m_indexWidget->viewport()
+ && e->type() == QEvent::MouseButtonRelease) {
+ QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(e);
+ QModelIndex idx = m_indexWidget->indexAt(mouseEvent->pos());
+ if (idx.isValid()) {
+ Qt::MouseButtons button = mouseEvent->button();
+ if (((button == Qt::LeftButton) && (mouseEvent->modifiers() & Qt::ControlModifier))
+ || (button == Qt::MidButton)) {
+ open(m_indexWidget, idx);
+ }
+ }
+ }
+#ifdef Q_OS_MAC
+ else if (obj == m_indexWidget && e->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(e);
+ if (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter)
+ m_indexWidget->activateCurrentItem();
+ }
+#endif
+ return QWidget::eventFilter(obj, e);
+}
+
+void IndexWindow::enableSearchLineEdit()
+{
+ TRACE_OBJ
+ m_searchLineEdit->setDisabled(false);
+ filterIndices(m_searchLineEdit->text());
+}
+
+void IndexWindow::disableSearchLineEdit()
+{
+ TRACE_OBJ
+ m_searchLineEdit->setDisabled(true);
+}
+
+void IndexWindow::setSearchLineEditText(const QString &text)
+{
+ TRACE_OBJ
+ m_searchLineEdit->setText(text);
+}
+
+void IndexWindow::focusInEvent(QFocusEvent *e)
+{
+ TRACE_OBJ
+ if (e->reason() != Qt::MouseFocusReason) {
+ m_searchLineEdit->selectAll();
+ m_searchLineEdit->setFocus();
+ }
+}
+
+void IndexWindow::open(QHelpIndexWidget* indexWidget, const QModelIndex &index)
+{
+ TRACE_OBJ
+ QHelpIndexModel *model = qobject_cast<QHelpIndexModel*>(indexWidget->model());
+ if (model) {
+ QString keyword = model->data(index, Qt::DisplayRole).toString();
+ QMap<QString, QUrl> links = model->linksForKeyword(keyword);
+
+ QUrl url;
+ if (links.count() > 1) {
+ TopicChooser tc(this, keyword, links);
+ if (tc.exec() == QDialog::Accepted)
+ url = tc.link();
+ } else if (links.count() == 1) {
+ url = links.constBegin().value();
+ } else {
+ return;
+ }
+
+ if (!HelpViewer::canOpenPage(url.path()))
+ CentralWidget::instance()->setSource(url);
+ else
+ OpenPagesManager::instance()->createPage(url);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/indexwindow.h b/src/assistant/tools/assistant/indexwindow.h
new file mode 100644
index 000000000..6c1c4e14e
--- /dev/null
+++ b/src/assistant/tools/assistant/indexwindow.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef INDEXWINDOW_H
+#define INDEXWINDOW_H
+
+#include <QtCore/QUrl>
+#include <QtGui/QWidget>
+#include <QtGui/QLineEdit>
+
+QT_BEGIN_NAMESPACE
+
+class QHelpIndexWidget;
+class QModelIndex;
+
+class IndexWindow : public QWidget
+{
+ Q_OBJECT
+
+public:
+ IndexWindow(QWidget *parent = 0);
+ ~IndexWindow();
+
+ void setSearchLineEditText(const QString &text);
+ QString searchLineEditText() const
+ {
+ return m_searchLineEdit->text();
+ }
+
+signals:
+ void linkActivated(const QUrl &link);
+ void linksActivated(const QMap<QString, QUrl> &links,
+ const QString &keyword);
+ void escapePressed();
+
+private slots:
+ void filterIndices(const QString &filter);
+ void enableSearchLineEdit();
+ void disableSearchLineEdit();
+
+private:
+ bool eventFilter(QObject *obj, QEvent *e);
+ void focusInEvent(QFocusEvent *e);
+ void open(QHelpIndexWidget *indexWidget, const QModelIndex &index);
+
+ QLineEdit *m_searchLineEdit;
+ QHelpIndexWidget *m_indexWidget;
+};
+
+QT_END_NAMESPACE
+
+#endif // INDEXWINDOW_H
diff --git a/src/assistant/tools/assistant/installdialog.cpp b/src/assistant/tools/assistant/installdialog.cpp
new file mode 100644
index 000000000..29473a2f9
--- /dev/null
+++ b/src/assistant/tools/assistant/installdialog.cpp
@@ -0,0 +1,355 @@
+/****************************************************************************
+**
+** 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 "tracer.h"
+
+#include "installdialog.h"
+
+#include <QtCore/QTimer>
+#include <QtCore/QUrl>
+#include <QtCore/QBuffer>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QCryptographicHash>
+
+#include <QtGui/QMessageBox>
+#include <QtGui/QFileDialog>
+
+#include <QtHelp/QHelpEngineCore>
+
+#include <QtNetwork/QHttp>
+
+QT_BEGIN_NAMESPACE
+#ifndef QT_NO_HTTP
+
+#define QCH_FILENAME 92943
+#define QCH_NAMESPACE 92944
+#define QCH_CHECKSUM 92945
+
+InstallDialog::InstallDialog(QHelpEngineCore *helpEngine, QWidget *parent,
+ const QString &host, int port)
+ : QDialog(parent), m_helpEngine(helpEngine), m_host(host), m_port(port)
+{
+ TRACE_OBJ
+ m_ui.setupUi(this);
+
+ m_ui.installButton->setEnabled(false);
+ m_ui.cancelButton->setEnabled(false);
+ m_ui.pathLineEdit->setText(QFileInfo(m_helpEngine->collectionFile()).absolutePath());
+ m_ui.progressBar->hide();
+
+ m_windowTitle = tr("Install Documentation");
+
+ m_http = new QHttp(this);
+ connect(m_http, SIGNAL(requestFinished(int,bool)),
+ this, SLOT(httpRequestFinished(int,bool)));
+ connect(m_http, SIGNAL(dataReadProgress(int,int)),
+ this, SLOT(updateDataReadProgress(int,int)));
+ connect(m_http, SIGNAL(responseHeaderReceived(QHttpResponseHeader)),
+ this, SLOT(readResponseHeader(QHttpResponseHeader)));
+ connect(m_ui.installButton, SIGNAL(clicked()), this, SLOT(install()));
+ connect(m_ui.cancelButton, SIGNAL(clicked()), this, SLOT(cancelDownload()));
+ connect(m_ui.browseButton, SIGNAL(clicked()), this, SLOT(browseDirectories()));
+
+ connect(m_ui.listWidget, SIGNAL(itemChanged(QListWidgetItem*)),
+ this, SLOT(updateInstallButton()));
+
+ QTimer::singleShot(0, this, SLOT(init()));
+}
+
+InstallDialog::~InstallDialog()
+{
+ TRACE_OBJ
+}
+
+QStringList InstallDialog::installedDocumentations() const
+{
+ TRACE_OBJ
+ return m_installedDocumentations;
+}
+
+void InstallDialog::init()
+{
+ TRACE_OBJ
+ m_ui.statusLabel->setText(tr("Downloading documentation info..."));
+ m_ui.progressBar->show();
+
+ QUrl url(QLatin1String("http://qt.nokia.com/doc/assistantdocs/docs.txt"));
+ m_buffer = new QBuffer();
+ m_buffer->open(QBuffer::ReadWrite);
+
+ if (m_port > -1)
+ m_http->setProxy(m_host, m_port);
+ m_http->setHost(url.host());
+ m_httpAborted = false;
+ m_docInfoId = m_http->get(url.path(), m_buffer);
+
+ m_ui.cancelButton->setEnabled(true);
+ m_ui.closeButton->setEnabled(false);
+}
+
+void InstallDialog::updateInstallButton()
+{
+ TRACE_OBJ
+ QListWidgetItem *item = 0;
+ for (int i=0; i<m_ui.listWidget->count(); ++i) {
+ item = m_ui.listWidget->item(i);
+ if (item->checkState() == Qt::Checked
+ && item->flags() & Qt::ItemIsEnabled) {
+ m_ui.installButton->setEnabled(true);
+ return;
+ }
+ }
+ m_ui.installButton->setEnabled(false);
+}
+
+void InstallDialog::updateDocItemList()
+{
+ TRACE_OBJ
+ QStringList registeredDocs = m_helpEngine->registeredDocumentations();
+ QListWidgetItem *item = 0;
+ for (int i=0; i<m_ui.listWidget->count(); ++i) {
+ item = m_ui.listWidget->item(i);
+ QString ns = item->data(QCH_NAMESPACE).toString();
+ if (!ns.isEmpty() && registeredDocs.contains(ns)) {
+ item->setFlags(Qt::ItemIsUserCheckable);
+ item->setCheckState(Qt::Checked);
+ }
+ item->setCheckState(Qt::Unchecked);
+ }
+}
+
+void InstallDialog::cancelDownload()
+{
+ TRACE_OBJ
+ m_ui.statusLabel->setText(tr("Download canceled."));
+ m_httpAborted = true;
+ m_itemsToInstall.clear();
+ m_http->abort();
+ m_ui.cancelButton->setEnabled(false);
+ m_ui.closeButton->setEnabled(true);
+ updateInstallButton();
+}
+
+void InstallDialog::install()
+{
+ TRACE_OBJ
+ QListWidgetItem *item = 0;
+ for (int i=0; i<m_ui.listWidget->count(); ++i) {
+ item = m_ui.listWidget->item(i);
+ if (item->checkState() == Qt::Checked)
+ m_itemsToInstall.append(item);
+ }
+ m_ui.installButton->setEnabled(false);
+ downloadNextFile();
+}
+
+void InstallDialog::downloadNextFile()
+{
+ TRACE_OBJ
+ if (!m_itemsToInstall.count()) {
+ m_ui.cancelButton->setEnabled(false);
+ m_ui.closeButton->setEnabled(true);
+ m_ui.statusLabel->setText(tr("Done."));
+ m_ui.progressBar->hide();
+ updateDocItemList();
+ updateInstallButton();
+ return;
+ }
+
+ QListWidgetItem *item = m_itemsToInstall.dequeue();
+ m_currentCheckSum = item->data(QCH_CHECKSUM).toString();
+ QString fileName = item->data(QCH_FILENAME).toString();
+ QString saveFileName = m_ui.pathLineEdit->text() + QDir::separator()
+ + fileName;
+
+ if (QFile::exists(saveFileName)
+ && QMessageBox::information(this, m_windowTitle,
+ tr("The file %1 already exists. Do you want to overwrite it?")
+ .arg(saveFileName), QMessageBox::Yes | QMessageBox::No,
+ QMessageBox::Yes) == QMessageBox::No) {
+ installFile(saveFileName);
+ downloadNextFile();
+ return;
+ }
+
+ m_file = new QFile(saveFileName);
+ if (!m_file->open(QIODevice::WriteOnly|QIODevice::Truncate)) {
+ QMessageBox::information(this, m_windowTitle,
+ tr("Unable to save the file %1: %2.")
+ .arg(saveFileName).arg(m_file->errorString()));
+ delete m_file;
+ m_file = 0;
+ downloadNextFile();
+ return;
+ }
+
+ m_ui.statusLabel->setText(tr("Downloading %1...").arg(fileName));
+ m_ui.progressBar->show();
+
+ QLatin1String urlStr("http://qt.nokia.com/doc/assistantdocs/%1");
+ QUrl url(QString(urlStr).arg(fileName));
+
+ m_httpAborted = false;
+ m_docId = m_http->get(url.path(), m_file);
+
+ m_ui.cancelButton->setEnabled(true);
+ m_ui.closeButton->setEnabled(false);
+}
+
+void InstallDialog::httpRequestFinished(int requestId, bool error)
+{
+ TRACE_OBJ
+ if (requestId == m_docInfoId && m_buffer) {
+ m_ui.progressBar->hide();
+ if (error) {
+ QMessageBox::information(this, m_windowTitle,
+ tr("Download failed: %1.")
+ .arg(m_http->errorString()));
+ } else if (!m_httpAborted) {
+ QStringList registeredDocs = m_helpEngine->registeredDocumentations();
+ m_buffer->seek(0);
+ while (m_buffer->canReadLine()) {
+ QByteArray ba = m_buffer->readLine();
+ QStringList lst = QString::fromAscii(ba.constData()).split(QLatin1Char('|'));
+ if (lst.count() != 4) {
+ QMessageBox::information(this, m_windowTitle,
+ tr("Documentation info file is corrupt!"));
+ } else {
+ QListWidgetItem *item = new QListWidgetItem(m_ui.listWidget);
+ item->setText(lst.at(2).trimmed());
+ item->setData(QCH_FILENAME, lst.first());
+ item->setData(QCH_NAMESPACE, lst.at(1));
+ item->setData(QCH_CHECKSUM, lst.last().trimmed());
+ }
+ }
+ updateDocItemList();
+ }
+ if (m_buffer)
+ m_buffer->close();
+ delete m_buffer;
+ m_buffer = 0;
+ m_ui.statusLabel->setText(tr("Done."));
+ m_ui.cancelButton->setEnabled(false);
+ m_ui.closeButton->setEnabled(true);
+ updateInstallButton();
+ } else if (requestId == m_docId) {
+ m_file->close();
+ if (!m_httpAborted) {
+ QString checkSum;
+ if (m_file->open(QIODevice::ReadOnly)) {
+ QByteArray digest = QCryptographicHash::hash(m_file->readAll(),
+ QCryptographicHash::Md5);
+ m_file->close();
+ checkSum = QString::fromLatin1(digest.toHex());
+ }
+ if (error) {
+ m_file->remove();
+ QMessageBox::warning(this, m_windowTitle,
+ tr("Download failed: %1.")
+ .arg(m_http->errorString()));
+ } else if (checkSum.isEmpty() || m_currentCheckSum != checkSum) {
+ m_file->remove();
+ QMessageBox::warning(this, m_windowTitle,
+ tr("Download failed: Downloaded file is corrupted."));
+ } else {
+ m_ui.statusLabel->setText(tr("Installing documentation %1...")
+ .arg(QFileInfo(m_file->fileName()).fileName()));
+ m_ui.progressBar->setMaximum(0);
+ m_ui.statusLabel->setText(tr("Done."));
+ installFile(m_file->fileName());
+ }
+ } else {
+ m_file->remove();
+ }
+ delete m_file;
+ m_file = 0;
+ downloadNextFile();
+ }
+}
+
+void InstallDialog::installFile(const QString &fileName)
+{
+ TRACE_OBJ
+ if (m_helpEngine->registerDocumentation(fileName)) {
+ m_installedDocumentations
+ .append(QHelpEngineCore::namespaceName(fileName));
+ } else {
+ QMessageBox::information(this, m_windowTitle,
+ tr("Error while installing documentation:\n%1")
+ .arg(m_helpEngine->error()));
+ }
+}
+
+void InstallDialog::readResponseHeader(const QHttpResponseHeader &responseHeader)
+{
+ TRACE_OBJ
+ if (responseHeader.statusCode() != 200) {
+ QMessageBox::information(this, m_windowTitle,
+ tr("Download failed: %1.")
+ .arg(responseHeader.reasonPhrase()));
+ m_httpAborted = true;
+ m_ui.progressBar->hide();
+ m_http->abort();
+ return;
+ }
+}
+
+void InstallDialog::updateDataReadProgress(int bytesRead, int totalBytes)
+{
+ TRACE_OBJ
+ if (m_httpAborted)
+ return;
+
+ m_ui.progressBar->setMaximum(totalBytes);
+ m_ui.progressBar->setValue(bytesRead);
+}
+
+void InstallDialog::browseDirectories()
+{
+ TRACE_OBJ
+ QString dir = QFileDialog::getExistingDirectory(this, m_windowTitle,
+ m_ui.pathLineEdit->text());
+ if (!dir.isEmpty())
+ m_ui.pathLineEdit->setText(dir);
+}
+
+#endif
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/installdialog.h b/src/assistant/tools/assistant/installdialog.h
new file mode 100644
index 000000000..0fb45a130
--- /dev/null
+++ b/src/assistant/tools/assistant/installdialog.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef INSTALLDIALOG_H
+#define INSTALLDIALOG_H
+
+#include <QtCore/QQueue>
+#include <QtGui/QDialog>
+#include <QtNetwork/QHttpResponseHeader>
+#include "ui_installdialog.h"
+
+#ifndef QT_NO_HTTP
+
+QT_BEGIN_NAMESPACE
+
+class QHttp;
+class QBuffer;
+class QFile;
+class QHelpEngineCore;
+
+class InstallDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit InstallDialog(QHelpEngineCore *helpEngine, QWidget *parent = 0,
+ const QString &host = QString(), int port = -1);
+ ~InstallDialog();
+
+ QStringList installedDocumentations() const;
+
+private slots:
+ void init();
+ void cancelDownload();
+ void install();
+ void httpRequestFinished(int requestId, bool error);
+ void readResponseHeader(const QHttpResponseHeader &responseHeader);
+ void updateDataReadProgress(int bytesRead, int totalBytes);
+ void updateInstallButton();
+ void browseDirectories();
+
+private:
+ void downloadNextFile();
+ void updateDocItemList();
+ void installFile(const QString &fileName);
+
+ Ui::InstallDialog m_ui;
+ QHelpEngineCore *m_helpEngine;
+ QHttp *m_http;
+ QBuffer *m_buffer;
+ QFile *m_file;
+ bool m_httpAborted;
+ int m_docInfoId;
+ int m_docId;
+ QQueue<QListWidgetItem*> m_itemsToInstall;
+ QString m_currentCheckSum;
+ QString m_windowTitle;
+ QStringList m_installedDocumentations;
+ QString m_host;
+ int m_port;
+};
+
+QT_END_NAMESPACE
+
+#endif
+
+#endif // INSTALLDIALOG_H
diff --git a/src/assistant/tools/assistant/installdialog.ui b/src/assistant/tools/assistant/installdialog.ui
new file mode 100644
index 000000000..21a05da77
--- /dev/null
+++ b/src/assistant/tools/assistant/installdialog.ui
@@ -0,0 +1,118 @@
+<ui version="4.0" >
+ <class>InstallDialog</class>
+ <widget class="QDialog" name="InstallDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>436</width>
+ <height>245</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Install Documentation</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" colspan="4" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Available Documentation:</string>
+ </property>
+ </widget>
+ </item>
+ <item rowspan="4" row="1" column="0" colspan="4" >
+ <widget class="QListWidget" name="listWidget" />
+ </item>
+ <item row="1" column="4" >
+ <widget class="QPushButton" name="installButton" >
+ <property name="text" >
+ <string>Install</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="4" >
+ <widget class="QPushButton" name="cancelButton" >
+ <property name="text" >
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="4" >
+ <widget class="QPushButton" name="closeButton" >
+ <property name="text" >
+ <string>Close</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="4" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>56</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="5" column="0" >
+ <widget class="QLabel" name="label_4" >
+ <property name="text" >
+ <string>Installation Path:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1" colspan="2" >
+ <widget class="QLineEdit" name="pathLineEdit" />
+ </item>
+ <item row="5" column="3" >
+ <widget class="QToolButton" name="browseButton" >
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0" colspan="5" >
+ <widget class="Line" name="line" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0" colspan="2" >
+ <widget class="QLabel" name="statusLabel" />
+ </item>
+ <item row="7" column="2" colspan="3" >
+ <widget class="QProgressBar" name="progressBar" >
+ <property name="value" >
+ <number>0</number>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>closeButton</sender>
+ <signal>clicked()</signal>
+ <receiver>InstallDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>330</x>
+ <y>107</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>332</x>
+ <y>158</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/assistant/tools/assistant/main.cpp b/src/assistant/tools/assistant/main.cpp
new file mode 100644
index 000000000..84972c546
--- /dev/null
+++ b/src/assistant/tools/assistant/main.cpp
@@ -0,0 +1,440 @@
+/****************************************************************************
+**
+** 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 "tracer.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QLocale>
+#include <QtCore/QScopedPointer>
+#include <QtCore/QStringList>
+#include <QtCore/QTranslator>
+#include <QtCore/QUrl>
+
+#include <QtGui/QApplication>
+#include <QtGui/QDesktopServices>
+
+#include <QtHelp/QHelpEngine>
+#include <QtHelp/QHelpSearchEngine>
+
+#include <QtNetwork/QLocalSocket>
+
+#include <QtSql/QSqlDatabase>
+
+#include "../shared/collectionconfiguration.h"
+#include "helpenginewrapper.h"
+#include "mainwindow.h"
+#include "cmdlineparser.h"
+
+// #define TRACING_REQUESTED
+
+QT_USE_NAMESPACE
+
+#if defined(USE_STATIC_SQLITE_PLUGIN)
+ #include <QtPlugin>
+ Q_IMPORT_PLUGIN(qsqlite)
+#endif
+
+namespace {
+
+void
+updateLastPagesOnUnregister(QHelpEngineCore& helpEngine, const QString& nsName)
+{
+ TRACE_OBJ
+ int lastPage = CollectionConfiguration::lastTabPage(helpEngine);
+ QStringList currentPages = CollectionConfiguration::lastShownPages(helpEngine);
+ if (!currentPages.isEmpty()) {
+ QStringList zoomList = CollectionConfiguration::lastZoomFactors(helpEngine);
+ while (zoomList.count() < currentPages.count())
+ zoomList.append(CollectionConfiguration::DefaultZoomFactor);
+
+ for (int i = currentPages.count(); --i >= 0;) {
+ if (QUrl(currentPages.at(i)).host() == nsName) {
+ zoomList.removeAt(i);
+ currentPages.removeAt(i);
+ lastPage = (lastPage == (i + 1)) ? 1 : lastPage;
+ }
+ }
+
+ CollectionConfiguration::setLastShownPages(helpEngine, currentPages);
+ CollectionConfiguration::setLastTabPage(helpEngine, lastPage);
+ CollectionConfiguration::setLastZoomFactors(helpEngine, zoomList);
+ }
+}
+
+bool
+updateUserCollection(QHelpEngineCore& user, const QHelpEngineCore& caller)
+{
+ TRACE_OBJ
+ if (!CollectionConfiguration::isNewer(caller, user))
+ return false;
+ CollectionConfiguration::copyConfiguration(caller, user);
+ return true;
+}
+
+void stripNonexistingDocs(QHelpEngineCore& collection)
+{
+ TRACE_OBJ
+ const QStringList &namespaces = collection.registeredDocumentations();
+ foreach (const QString &ns, namespaces) {
+ QFileInfo fi(collection.documentationFileName(ns));
+ if (!fi.exists() || !fi.isFile())
+ collection.unregisterDocumentation(ns);
+ }
+}
+
+QString indexFilesFolder(const QString &collectionFile)
+{
+ TRACE_OBJ
+ QString indexFilesFolder = QLatin1String(".fulltextsearch");
+ if (!collectionFile.isEmpty()) {
+ QFileInfo fi(collectionFile);
+ indexFilesFolder = QLatin1Char('.') +
+ fi.fileName().left(fi.fileName().lastIndexOf(QLatin1String(".qhc")));
+ }
+ return indexFilesFolder;
+}
+
+/*
+ * Returns the expected absolute file path of the cached collection file
+ * correspondinging to the given collection's file.
+ * It may or may not exist yet.
+ */
+QString constructCachedCollectionFilePath(const QHelpEngineCore &collection)
+{
+ TRACE_OBJ
+ const QString &filePath = collection.collectionFile();
+ const QString &fileName = QFileInfo(filePath).fileName();
+ const QString &cacheDir = CollectionConfiguration::cacheDir(collection);
+ const QString &dir = !cacheDir.isEmpty()
+ && CollectionConfiguration::cacheDirIsRelativeToCollection(collection)
+ ? QFileInfo(filePath).dir().absolutePath()
+ + QDir::separator() + cacheDir
+ : MainWindow::collectionFileDirectory(false, cacheDir);
+ return dir + QDir::separator() + fileName;
+}
+
+bool synchronizeDocs(QHelpEngineCore &collection,
+ QHelpEngineCore &cachedCollection,
+ CmdLineParser &cmd)
+{
+ TRACE_OBJ
+ const QDateTime &lastCollectionRegisterTime =
+ CollectionConfiguration::lastRegisterTime(collection);
+ if (!lastCollectionRegisterTime.isValid() || lastCollectionRegisterTime
+ < CollectionConfiguration::lastRegisterTime(cachedCollection))
+ return true;
+
+ const QStringList &docs = collection.registeredDocumentations();
+ const QStringList &cachedDocs = cachedCollection.registeredDocumentations();
+
+ /*
+ * Ensure that the cached collection contains all docs that
+ * the collection contains.
+ */
+ foreach (const QString &doc, docs) {
+ if (!cachedDocs.contains(doc)) {
+ const QString &docFile = collection.documentationFileName(doc);
+ if (!cachedCollection.registerDocumentation(docFile)) {
+ cmd.showMessage(QCoreApplication::translate("Assistant",
+ "Error registering documentation file '%1': %2").
+ arg(docFile).arg(cachedCollection.error()), true);
+ return false;
+ }
+ }
+ }
+
+ CollectionConfiguration::updateLastRegisterTime(cachedCollection);
+
+ return true;
+}
+
+bool removeSearchIndex(const QString &collectionFile)
+{
+ TRACE_OBJ
+ QString path = QFileInfo(collectionFile).path();
+ path += QLatin1Char('/') + indexFilesFolder(collectionFile);
+
+ QLocalSocket localSocket;
+ localSocket.connectToServer(QString(QLatin1String("QtAssistant%1"))
+ .arg(QLatin1String(QT_VERSION_STR)));
+
+ QDir dir(path); // check if there is no other instance ruinning
+ if (!dir.exists() || localSocket.waitForConnected())
+ return false;
+
+ QStringList lst = dir.entryList(QDir::Files | QDir::Hidden);
+ foreach (const QString &item, lst)
+ dir.remove(item);
+ return true;
+}
+
+bool rebuildSearchIndex(QCoreApplication &app, const QString &collectionFile,
+ CmdLineParser &cmd)
+{
+ TRACE_OBJ
+ QHelpEngine engine(collectionFile);
+ if (!engine.setupData()) {
+ cmd.showMessage(QCoreApplication::translate("Assistant", "Error: %1")
+ .arg(engine.error()), true);
+ return false;
+ }
+
+ QHelpSearchEngine * const searchEngine = engine.searchEngine();
+ QObject::connect(searchEngine, SIGNAL(indexingFinished()), &app,
+ SLOT(quit()));
+ searchEngine->reindexDocumentation();
+ return app.exec() == 0;
+}
+
+bool useGui(int argc, char *argv[])
+{
+ TRACE_OBJ
+ bool gui = true;
+#ifndef Q_OS_WIN
+ // Look for arguments that imply command-line mode.
+ const char * cmdModeArgs[] = {
+ "-help", "-register", "-unregister", "-remove-search-index",
+ "-rebuild-search-index"
+ };
+ for (int i = 1; i < argc; ++i) {
+ for (size_t j = 0; j < sizeof cmdModeArgs/sizeof *cmdModeArgs; ++j) {
+ if(strcmp(argv[i], cmdModeArgs[j]) == 0) {
+ gui = false;
+ break;
+ }
+ }
+ }
+#else
+ Q_UNUSED(argc)
+ Q_UNUSED(argv)
+#endif
+ return gui;
+}
+
+bool registerDocumentation(QHelpEngineCore &collection, CmdLineParser &cmd,
+ bool printSuccess)
+{
+ TRACE_OBJ
+ if (!collection.registerDocumentation(cmd.helpFile())) {
+ cmd.showMessage(QCoreApplication::translate("Assistant",
+ "Could not register documentation file\n%1\n\nReason:\n%2")
+ .arg(cmd.helpFile()).arg(collection.error()), true);
+ return false;
+ }
+ if (printSuccess)
+ cmd.showMessage(QCoreApplication::translate("Assistant",
+ "Documentation successfully registered."),
+ false);
+ CollectionConfiguration::updateLastRegisterTime(collection);
+ return true;
+}
+
+bool unregisterDocumentation(QHelpEngineCore &collection,
+ const QString &namespaceName, CmdLineParser &cmd, bool printSuccess)
+{
+ TRACE_OBJ
+ if (!collection.unregisterDocumentation(namespaceName)) {
+ cmd.showMessage(QCoreApplication::translate("Assistant",
+ "Could not unregister documentation"
+ " file\n%1\n\nReason:\n%2").
+ arg(cmd.helpFile()).arg(collection.error()), true);
+ return false;
+ }
+ updateLastPagesOnUnregister(collection, namespaceName);
+ if (printSuccess)
+ cmd.showMessage(QCoreApplication::translate("Assistant",
+ "Documentation successfully unregistered."),
+ false);
+ return true;
+}
+
+void setupTranslation(const QString &fileName, const QString &dir)
+{
+ QTranslator *translator = new QTranslator(QCoreApplication::instance());
+ if (translator->load(fileName, dir)) {
+ QCoreApplication::installTranslator(translator);
+ } else if (!fileName.endsWith(QLatin1String("en_US"))
+ && !fileName.endsWith(QLatin1String("_C"))) {
+ qWarning("Could not load translation file %s in directory %s.",
+ qPrintable(fileName), qPrintable(dir));
+ }
+}
+
+void setupTranslations()
+{
+ TRACE_OBJ
+ const QString& locale = QLocale::system().name();
+ const QString &resourceDir
+ = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
+ setupTranslation(QLatin1String("assistant_") + locale, resourceDir);
+ setupTranslation(QLatin1String("qt_") + locale, resourceDir);
+ setupTranslation(QLatin1String("qt_help_") + locale, resourceDir);
+}
+
+} // Anonymous namespace.
+
+int main(int argc, char *argv[])
+{
+ TRACE_OBJ
+ QApplication a(argc, argv, useGui(argc, argv));
+ a.addLibraryPath(a.applicationDirPath() + QLatin1String("/plugins"));
+ setupTranslations();
+
+ // Parse arguments.
+ CmdLineParser cmd(a.arguments());
+ CmdLineParser::Result res = cmd.parse();
+ if (res == CmdLineParser::Help)
+ return 0;
+ else if (res == CmdLineParser::Error)
+ return -1;
+
+ /*
+ * Create the collection objects that we need. We always have the
+ * cached collection file. Depending on whether the user specified
+ * one, we also may have an input collection file.
+ */
+ const QString collectionFile = cmd.collectionFile();
+ const bool collectionFileGiven = !collectionFile.isEmpty();
+ QScopedPointer<QHelpEngineCore> collection;
+ if (collectionFileGiven) {
+ collection.reset(new QHelpEngineCore(collectionFile));
+ if (!collection->setupData()) {
+ cmd.showMessage(QCoreApplication::translate("Assistant",
+ "Error reading collection file '%1': %2.").
+ arg(collectionFile).arg(collection->error()), true);
+ return EXIT_FAILURE;
+ }
+ }
+ const QString &cachedCollectionFile = collectionFileGiven
+ ? constructCachedCollectionFilePath(*collection)
+ : MainWindow::defaultHelpCollectionFileName();
+ if (collectionFileGiven && !QFileInfo(cachedCollectionFile).exists()
+ && !collection->copyCollectionFile(cachedCollectionFile)) {
+ cmd.showMessage(QCoreApplication::translate("Assistant",
+ "Error creating collection file '%1': %2.").
+ arg(cachedCollectionFile).arg(collection->error()), true);
+ return EXIT_FAILURE;
+ }
+ QHelpEngineCore cachedCollection(cachedCollectionFile);
+ if (!cachedCollection.setupData()) {
+ cmd.showMessage(QCoreApplication::translate("Assistant",
+ "Error reading collection file '%1': %2.").
+ arg(cachedCollectionFile).
+ arg(cachedCollection.error()), true);
+ return EXIT_FAILURE;
+ }
+
+ stripNonexistingDocs(cachedCollection);
+ if (collectionFileGiven) {
+ if (CollectionConfiguration::isNewer(*collection, cachedCollection))
+ CollectionConfiguration::copyConfiguration(*collection,
+ cachedCollection);
+ if (!synchronizeDocs(*collection, cachedCollection, cmd))
+ return EXIT_FAILURE;
+ }
+
+ if (cmd.registerRequest() != CmdLineParser::None) {
+ const QStringList &cachedDocs =
+ cachedCollection.registeredDocumentations();
+ const QString &namespaceName =
+ QHelpEngineCore::namespaceName(cmd.helpFile());
+ if (cmd.registerRequest() == CmdLineParser::Register) {
+ if (collectionFileGiven
+ && !registerDocumentation(*collection, cmd, true))
+ return EXIT_FAILURE;
+ if (!cachedDocs.contains(namespaceName)
+ && !registerDocumentation(cachedCollection, cmd, !collectionFileGiven))
+ return EXIT_FAILURE;
+ return EXIT_SUCCESS;
+ }
+ if (cmd.registerRequest() == CmdLineParser::Unregister) {
+ if (collectionFileGiven
+ && !unregisterDocumentation(*collection, namespaceName, cmd, true))
+ return EXIT_FAILURE;
+ if (cachedDocs.contains(namespaceName)
+ && !unregisterDocumentation(cachedCollection, namespaceName,
+ cmd, !collectionFileGiven))
+ return EXIT_FAILURE;
+ return EXIT_SUCCESS;
+ }
+ }
+
+ if (cmd.removeSearchIndex()) {
+ return removeSearchIndex(cachedCollectionFile)
+ ? EXIT_SUCCESS : EXIT_FAILURE;
+ }
+
+ if (cmd.rebuildSearchIndex()) {
+ return rebuildSearchIndex(a, cachedCollectionFile, cmd)
+ ? EXIT_SUCCESS : EXIT_FAILURE;
+ }
+
+ if (!QSqlDatabase::isDriverAvailable(QLatin1String("QSQLITE"))) {
+ cmd.showMessage(QCoreApplication::translate("Assistant",
+ "Cannot load sqlite database driver!"),
+ true);
+ return EXIT_FAILURE;
+ }
+
+ if (!cmd.currentFilter().isEmpty()) {
+ if (collectionFileGiven)
+ collection->setCurrentFilter(cmd.currentFilter());
+ cachedCollection.setCurrentFilter(cmd.currentFilter());
+ }
+
+ if (collectionFileGiven)
+ cmd.setCollectionFile(cachedCollectionFile);
+
+ MainWindow *w = new MainWindow(&cmd);
+ w->show();
+ a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
+
+ /*
+ * We need to be careful here: The main window has to be deleted before
+ * the help engine wrapper, which has to be deleted before the
+ * QApplication.
+ */
+ const int retval = a.exec();
+ delete w;
+ HelpEngineWrapper::removeInstance();
+ return retval;
+}
diff --git a/src/assistant/tools/assistant/mainwindow.cpp b/src/assistant/tools/assistant/mainwindow.cpp
new file mode 100644
index 000000000..342fc76da
--- /dev/null
+++ b/src/assistant/tools/assistant/mainwindow.cpp
@@ -0,0 +1,1099 @@
+/****************************************************************************
+**
+** 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 "mainwindow.h"
+
+#include "aboutdialog.h"
+#include "bookmarkmanager.h"
+#include "centralwidget.h"
+#include "cmdlineparser.h"
+#include "contentwindow.h"
+#include "globalactions.h"
+#include "helpenginewrapper.h"
+#include "indexwindow.h"
+#include "openpagesmanager.h"
+#include "preferencesdialog.h"
+#include "qtdocinstaller.h"
+#include "remotecontrol.h"
+#include "searchwidget.h"
+#include "topicchooser.h"
+#include "tracer.h"
+
+#include <QtCore/QByteArray>
+#include <QtCore/QDateTime>
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QPair>
+#include <QtCore/QResource>
+#include <QtCore/QTextStream>
+#include <QtCore/QTimer>
+
+#include <QtGui/QAction>
+#include <QtGui/QComboBox>
+#include <QtGui/QDesktopServices>
+#include <QtGui/QDesktopWidget>
+#include <QtGui/QDockWidget>
+#include <QtGui/QFontDatabase>
+#include <QtGui/QFileDialog>
+#include <QtGui/QLabel>
+#include <QtGui/QLayout>
+#include <QtGui/QLineEdit>
+#include <QtGui/QMenuBar>
+#include <QtGui/QMessageBox>
+#include <QtGui/QProgressBar>
+#include <QtGui/QShortcut>
+#include <QtGui/QStatusBar>
+#include <QtGui/QToolBar>
+#include <QtGui/QToolButton>
+
+#include <QtHelp/QHelpContentModel>
+#include <QtHelp/QHelpEngineCore>
+#include <QtHelp/QHelpIndexModel>
+#include <QtHelp/QHelpSearchEngine>
+
+#include <cstdlib>
+
+QT_BEGIN_NAMESPACE
+
+MainWindow::MainWindow(CmdLineParser *cmdLine, QWidget *parent)
+ : QMainWindow(parent)
+ , m_bookmarkWidget(0)
+ , m_filterCombo(0)
+ , m_toolBarMenu(0)
+ , m_cmdLine(cmdLine)
+ , m_progressWidget(0)
+ , m_qtDocInstaller(0)
+ , m_connectedInitSignals(false)
+{
+ TRACE_OBJ
+
+ setToolButtonStyle(Qt::ToolButtonFollowStyle);
+ setDockOptions(dockOptions() | AllowNestedDocks);
+
+ QString collectionFile;
+ if (usesDefaultCollection()) {
+ MainWindow::collectionFileDirectory(true);
+ collectionFile = MainWindow::defaultHelpCollectionFileName();
+ } else {
+ collectionFile = cmdLine->collectionFile();
+ }
+ HelpEngineWrapper &helpEngineWrapper =
+ HelpEngineWrapper::instance(collectionFile);
+ BookmarkManager *bookMarkManager = BookmarkManager::instance();
+
+ if (!initHelpDB(!cmdLine->collectionFileGiven())) {
+ qDebug("Fatal error: Help engine initialization failed. "
+ "Error message was: %s\nAssistant will now exit.",
+ qPrintable(HelpEngineWrapper::instance().error()));
+ std::exit(1);
+ }
+
+ m_centralWidget = new CentralWidget(this);
+ setCentralWidget(m_centralWidget);
+
+ m_indexWindow = new IndexWindow(this);
+ QDockWidget *indexDock = new QDockWidget(tr("Index"), this);
+ indexDock->setObjectName(QLatin1String("IndexWindow"));
+ indexDock->setWidget(m_indexWindow);
+ addDockWidget(Qt::LeftDockWidgetArea, indexDock);
+
+ m_contentWindow = new ContentWindow;
+ QDockWidget *contentDock = new QDockWidget(tr("Contents"), this);
+ contentDock->setObjectName(QLatin1String("ContentWindow"));
+ contentDock->setWidget(m_contentWindow);
+ addDockWidget(Qt::LeftDockWidgetArea, contentDock);
+
+ m_searchWindow = new SearchWidget(helpEngineWrapper.searchEngine());
+ m_searchWindow->setFont(!helpEngineWrapper.usesBrowserFont() ? qApp->font()
+ : helpEngineWrapper.browserFont());
+ QDockWidget *searchDock = new QDockWidget(tr("Search"), this);
+ searchDock->setObjectName(QLatin1String("SearchWindow"));
+ searchDock->setWidget(m_searchWindow);
+ addDockWidget(Qt::LeftDockWidgetArea, searchDock);
+
+ QDockWidget *bookmarkDock = new QDockWidget(tr("Bookmarks"), this);
+ bookmarkDock->setObjectName(QLatin1String("BookmarkWindow"));
+ bookmarkDock->setWidget(m_bookmarkWidget
+ = bookMarkManager->bookmarkDockWidget());
+ addDockWidget(Qt::LeftDockWidgetArea, bookmarkDock);
+
+ QDockWidget *openPagesDock = new QDockWidget(tr("Open Pages"), this);
+ openPagesDock->setObjectName(QLatin1String("Open Pages"));
+ OpenPagesManager *openPagesManager
+ = OpenPagesManager::createInstance(this, usesDefaultCollection(), m_cmdLine->url());
+ openPagesDock->setWidget(openPagesManager->openPagesWidget());
+ addDockWidget(Qt::LeftDockWidgetArea, openPagesDock);
+
+ connect(m_centralWidget, SIGNAL(addBookmark(QString, QString)),
+ bookMarkManager, SLOT(addBookmark(QString, QString)));
+ connect(bookMarkManager, SIGNAL(escapePressed()), this,
+ SLOT(activateCurrentCentralWidgetTab()));
+ connect(bookMarkManager, SIGNAL(setSource(QUrl)), m_centralWidget,
+ SLOT(setSource(QUrl)));
+ connect(bookMarkManager, SIGNAL(setSourceInNewTab(QUrl)),
+ openPagesManager, SLOT(createPage(QUrl)));
+
+ QHelpSearchEngine *searchEngine = helpEngineWrapper.searchEngine();
+ connect(searchEngine, SIGNAL(indexingStarted()), this, SLOT(indexingStarted()));
+ connect(searchEngine, SIGNAL(indexingFinished()), this, SLOT(indexingFinished()));
+
+ QString defWindowTitle = tr("Qt Assistant");
+ setWindowTitle(defWindowTitle);
+
+ setupActions();
+ statusBar()->show();
+ m_centralWidget->connectTabBar();
+
+ setupFilterToolbar();
+ setupAddressToolbar();
+
+ const QString windowTitle = helpEngineWrapper.windowTitle();
+ setWindowTitle(windowTitle.isEmpty() ? defWindowTitle : windowTitle);
+ QByteArray iconArray = helpEngineWrapper.applicationIcon();
+ if (iconArray.size() > 0) {
+ QPixmap pix;
+ pix.loadFromData(iconArray);
+ QIcon appIcon(pix);
+ qApp->setWindowIcon(appIcon);
+ } else {
+ QIcon appIcon(QLatin1String(":/trolltech/assistant/images/assistant-128.png"));
+ qApp->setWindowIcon(appIcon);
+ }
+
+ QToolBar *toolBar = addToolBar(tr("Bookmark Toolbar"));
+ toolBar->setObjectName(QLatin1String("Bookmark Toolbar"));
+ bookMarkManager->setBookmarksToolbar(toolBar);
+
+ // Show the widget here, otherwise the restore geometry and state won't work
+ // on x11.
+ show();
+
+ toolBar->hide();
+ toolBarMenu()->addAction(toolBar->toggleViewAction());
+
+ QByteArray ba(helpEngineWrapper.mainWindow());
+ if (!ba.isEmpty())
+ restoreState(ba);
+
+ ba = helpEngineWrapper.mainWindowGeometry();
+ if (!ba.isEmpty()) {
+ restoreGeometry(ba);
+ } else {
+ tabifyDockWidget(contentDock, indexDock);
+ tabifyDockWidget(indexDock, bookmarkDock);
+ tabifyDockWidget(bookmarkDock, searchDock);
+ contentDock->raise();
+ const QRect screen = QApplication::desktop()->screenGeometry();
+ resize(4*screen.width()/5, 4*screen.height()/5);
+ }
+
+ if (!helpEngineWrapper.hasFontSettings()) {
+ helpEngineWrapper.setUseAppFont(false);
+ helpEngineWrapper.setUseBrowserFont(false);
+ helpEngineWrapper.setAppFont(qApp->font());
+ helpEngineWrapper.setAppWritingSystem(QFontDatabase::Latin);
+ helpEngineWrapper.setBrowserFont(qApp->font());
+ helpEngineWrapper.setBrowserWritingSystem(QFontDatabase::Latin);
+ } else {
+ updateApplicationFont();
+ }
+
+ updateAboutMenuText();
+
+ QTimer::singleShot(0, this, SLOT(insertLastPages()));
+ if (m_cmdLine->enableRemoteControl())
+ (void)new RemoteControl(this);
+
+ if (m_cmdLine->contents() == CmdLineParser::Show)
+ showContents();
+ else if (m_cmdLine->contents() == CmdLineParser::Hide)
+ hideContents();
+
+ if (m_cmdLine->index() == CmdLineParser::Show)
+ showIndex();
+ else if (m_cmdLine->index() == CmdLineParser::Hide)
+ hideIndex();
+
+ if (m_cmdLine->bookmarks() == CmdLineParser::Show)
+ showBookmarksDockWidget();
+ else if (m_cmdLine->bookmarks() == CmdLineParser::Hide)
+ hideBookmarksDockWidget();
+
+ if (m_cmdLine->search() == CmdLineParser::Show)
+ showSearch();
+ else if (m_cmdLine->search() == CmdLineParser::Hide)
+ hideSearch();
+
+ if (m_cmdLine->contents() == CmdLineParser::Activate)
+ showContents();
+ else if (m_cmdLine->index() == CmdLineParser::Activate)
+ showIndex();
+ else if (m_cmdLine->bookmarks() == CmdLineParser::Activate)
+ showBookmarksDockWidget();
+
+ if (!m_cmdLine->currentFilter().isEmpty()) {
+ const QString &curFilter = m_cmdLine->currentFilter();
+ if (helpEngineWrapper.customFilters().contains(curFilter))
+ helpEngineWrapper.setCurrentFilter(curFilter);
+ }
+
+ if (usesDefaultCollection())
+ QTimer::singleShot(0, this, SLOT(lookForNewQtDocumentation()));
+ else
+ checkInitState();
+
+ connect(&helpEngineWrapper, SIGNAL(documentationRemoved(QString)),
+ this, SLOT(documentationRemoved(QString)));
+ connect(&helpEngineWrapper, SIGNAL(documentationUpdated(QString)),
+ this, SLOT(documentationUpdated(QString)));
+
+ setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North);
+ GlobalActions::instance()->updateActions();
+ if (helpEngineWrapper.addressBarEnabled())
+ showNewAddress();
+}
+
+MainWindow::~MainWindow()
+{
+ TRACE_OBJ
+ if (m_qtDocInstaller)
+ delete m_qtDocInstaller;
+}
+
+bool MainWindow::usesDefaultCollection() const
+{
+ TRACE_OBJ
+ return m_cmdLine->collectionFile().isEmpty();
+}
+
+void MainWindow::closeEvent(QCloseEvent *e)
+{
+ TRACE_OBJ
+ BookmarkManager::destroy();
+ HelpEngineWrapper::instance().setMainWindow(saveState());
+ HelpEngineWrapper::instance().setMainWindowGeometry(saveGeometry());
+ QMainWindow::closeEvent(e);
+}
+
+bool MainWindow::initHelpDB(bool registerInternalDoc)
+{
+ TRACE_OBJ
+ HelpEngineWrapper &helpEngineWrapper = HelpEngineWrapper::instance();
+ if (!helpEngineWrapper.setupData())
+ return false;
+
+ if (!registerInternalDoc) {
+ if (helpEngineWrapper.defaultHomePage() == QLatin1String("help"))
+ helpEngineWrapper.setDefaultHomePage(QLatin1String("about:blank"));
+ return true;
+ }
+ bool assistantInternalDocRegistered = false;
+ QString intern(QLatin1String("com.trolltech.com.assistantinternal-"));
+ foreach (const QString &ns, helpEngineWrapper.registeredDocumentations()) {
+ if (ns.startsWith(intern)) {
+ intern = ns;
+ assistantInternalDocRegistered = true;
+ break;
+ }
+ }
+
+ const QString &collectionFile = helpEngineWrapper.collectionFile();
+ QFileInfo fi(collectionFile);
+ QString helpFile;
+ QTextStream(&helpFile) << fi.absolutePath() << QDir::separator()
+ << QLatin1String("assistant.qch.") << (QT_VERSION >> 16)
+ << QLatin1Char('.') << ((QT_VERSION >> 8) & 0xFF);
+
+ bool needsSetup = false;
+ if (!assistantInternalDocRegistered || !QFile::exists(helpFile)) {
+ QFile file(helpFile);
+ if (file.open(QIODevice::WriteOnly)) {
+ QResource res(QLatin1String(":/trolltech/assistant/assistant.qch"));
+ if (file.write((const char*)res.data(), res.size()) != res.size())
+ qDebug() << QLatin1String("could not write assistant.qch...");
+
+ file.close();
+ }
+ helpEngineWrapper.unregisterDocumentation(intern);
+ helpEngineWrapper.registerDocumentation(helpFile);
+ needsSetup = true;
+ }
+
+ if (needsSetup)
+ helpEngineWrapper.setupData();
+ return true;
+}
+
+void MainWindow::lookForNewQtDocumentation()
+{
+ TRACE_OBJ
+ HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance();
+ QStringList docs;
+ docs << QLatin1String("assistant")
+ << QLatin1String("designer")
+ << QLatin1String("linguist")
+ << QLatin1String("qmake")
+ << QLatin1String("qt");
+ QList<QtDocInstaller::DocInfo> qtDocInfos;
+ foreach (const QString &doc, docs)
+ qtDocInfos.append(QtDocInstaller::DocInfo(doc, helpEngine.qtDocInfo(doc)));
+
+ m_qtDocInstaller = new QtDocInstaller(qtDocInfos);
+ connect(m_qtDocInstaller, SIGNAL(docsInstalled(bool)), this,
+ SLOT(qtDocumentationInstalled()));
+ connect(m_qtDocInstaller, SIGNAL(qchFileNotFound(QString)), this,
+ SLOT(resetQtDocInfo(QString)));
+ connect(m_qtDocInstaller, SIGNAL(registerDocumentation(QString, QString)),
+ this, SLOT(registerDocumentation(QString, QString)));
+ if (helpEngine.qtDocInfo(QLatin1String("qt")).count() != 2)
+ statusBar()->showMessage(tr("Looking for Qt Documentation..."));
+ m_qtDocInstaller->installDocs();
+}
+
+void MainWindow::qtDocumentationInstalled()
+{
+ TRACE_OBJ
+ statusBar()->clearMessage();
+ checkInitState();
+}
+
+void MainWindow::checkInitState()
+{
+ TRACE_OBJ
+ HelpEngineWrapper::instance().initialDocSetupDone();
+ if (!m_cmdLine->enableRemoteControl())
+ return;
+
+ HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance();
+ if (helpEngine.contentModel()->isCreatingContents()
+ || helpEngine.indexModel()->isCreatingIndex()) {
+ if (!m_connectedInitSignals) {
+ connect(helpEngine.contentModel(), SIGNAL(contentsCreated()),
+ this, SLOT(checkInitState()));
+ connect(helpEngine.indexModel(), SIGNAL(indexCreated()), this,
+ SLOT(checkInitState()));
+ m_connectedInitSignals = true;
+ }
+ } else {
+ if (m_connectedInitSignals) {
+ disconnect(helpEngine.contentModel(), 0, this, 0);
+ disconnect(helpEngine.indexModel(), 0, this, 0);
+ }
+ emit initDone();
+ }
+}
+
+void MainWindow::insertLastPages()
+{
+ TRACE_OBJ
+ if (m_cmdLine->search() == CmdLineParser::Activate)
+ showSearch();
+}
+
+void MainWindow::setupActions()
+{
+ TRACE_OBJ
+ QString resourcePath = QLatin1String(":/trolltech/assistant/images/");
+#ifdef Q_OS_MAC
+ setUnifiedTitleAndToolBarOnMac(true);
+ resourcePath.append(QLatin1String("mac"));
+#else
+ resourcePath.append(QLatin1String("win"));
+#endif
+
+ QMenu *menu = menuBar()->addMenu(tr("&File"));
+
+ OpenPagesManager * const openPages = OpenPagesManager::instance();
+ m_newTabAction
+ = menu->addAction(tr("New &Tab"), openPages, SLOT(createPage()));
+ m_newTabAction->setShortcut(QKeySequence::AddTab);
+ m_closeTabAction = menu->addAction(tr("&Close Tab"),
+ openPages, SLOT(closeCurrentPage()));
+ m_closeTabAction->setShortcuts(QKeySequence::Close);
+
+ menu->addSeparator();
+
+ m_pageSetupAction = menu->addAction(tr("Page Set&up..."), m_centralWidget,
+ SLOT(pageSetup()));
+ m_printPreviewAction = menu->addAction(tr("Print Preview..."), m_centralWidget,
+ SLOT(printPreview()));
+
+ GlobalActions *globalActions = GlobalActions::instance(this);
+ menu->addAction(globalActions->printAction());
+ menu->addSeparator();
+
+ QIcon appExitIcon = QIcon::fromTheme("application-exit");
+ QAction *tmp;
+#ifdef Q_OS_WIN
+ tmp = menu->addAction(appExitIcon, tr("E&xit"), this, SLOT(close()));
+ tmp->setShortcut(QKeySequence(tr("CTRL+Q")));
+#else
+ tmp = menu->addAction(appExitIcon, tr("&Quit"), this, SLOT(close()));
+ tmp->setShortcut(QKeySequence::Quit);
+#endif
+ tmp->setMenuRole(QAction::QuitRole);
+
+ menu = menuBar()->addMenu(tr("&Edit"));
+ menu->addAction(globalActions->copyAction());
+ menu->addAction(globalActions->findAction());
+
+ QAction *findNextAction = menu->addAction(tr("Find &Next"), m_centralWidget,
+ SLOT(findNext()));
+ findNextAction->setShortcuts(QKeySequence::FindNext);
+
+ QAction *findPreviousAction = menu->addAction(tr("Find &Previous"),
+ m_centralWidget, SLOT(findPrevious()));
+ findPreviousAction->setShortcuts(QKeySequence::FindPrevious);
+
+ menu->addSeparator();
+ tmp = menu->addAction(tr("Preferences..."), this, SLOT(showPreferences()));
+ tmp->setMenuRole(QAction::PreferencesRole);
+
+ m_viewMenu = menuBar()->addMenu(tr("&View"));
+ m_viewMenu->addAction(globalActions->zoomInAction());
+ m_viewMenu->addAction(globalActions->zoomOutAction());
+
+ m_resetZoomAction = m_viewMenu->addAction(tr("Normal &Size"), m_centralWidget,
+ SLOT(resetZoom()));
+ m_resetZoomAction->setPriority(QAction::LowPriority);
+ m_resetZoomAction->setIcon(QIcon(resourcePath + QLatin1String("/resetzoom.png")));
+ m_resetZoomAction->setShortcut(tr("Ctrl+0"));
+
+ m_viewMenu->addSeparator();
+
+ m_viewMenu->addAction(tr("Contents"), this, SLOT(showContents()),
+ QKeySequence(tr("ALT+C")));
+ m_viewMenu->addAction(tr("Index"), this, SLOT(showIndex()),
+ QKeySequence(tr("ALT+I")));
+ m_viewMenu->addAction(tr("Bookmarks"), this, SLOT(showBookmarksDockWidget()),
+ QKeySequence(tr("ALT+O")));
+ m_viewMenu->addAction(tr("Search"), this, SLOT(showSearch()),
+ QKeySequence(tr("ALT+S")));
+ m_viewMenu->addAction(tr("Open Pages"), this, SLOT(showOpenPages()),
+ QKeySequence(tr("ALT+P")));
+
+ menu = menuBar()->addMenu(tr("&Go"));
+ menu->addAction(globalActions->homeAction());
+ menu->addAction(globalActions->backAction());
+ menu->addAction(globalActions->nextAction());
+
+ m_syncAction = menu->addAction(tr("Sync with Table of Contents"), this,
+ SLOT(syncContents()));
+ m_syncAction->setIconText(tr("Sync"));
+ m_syncAction->setIcon(QIcon(resourcePath + QLatin1String("/synctoc.png")));
+
+ menu->addSeparator();
+
+ tmp = menu->addAction(tr("Next Page"), openPages, SLOT(nextPage()));
+ tmp->setShortcuts(QList<QKeySequence>() << QKeySequence(tr("Ctrl+Alt+Right"))
+ << QKeySequence(Qt::CTRL + Qt::Key_PageDown));
+
+ tmp = menu->addAction(tr("Previous Page"), openPages, SLOT(previousPage()));
+ tmp->setShortcuts(QList<QKeySequence>() << QKeySequence(tr("Ctrl+Alt+Left"))
+ << QKeySequence(Qt::CTRL + Qt::Key_PageUp));
+
+#ifdef Q_WS_MAC
+ QShortcut *sct = new QShortcut(QKeySequence(Qt::ALT + Qt::Key_Tab), this);
+ connect(sct, SIGNAL(activated()), openPages, SLOT(nextPageWithSwitcher()));
+ sct = new QShortcut(QKeySequence(Qt::ALT + Qt::SHIFT + Qt::Key_Tab), this);
+ connect(sct, SIGNAL(activated()), openPages, SLOT(previousPageWithSwitcher()));
+#else
+ QShortcut *sct = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Tab), this);
+ connect(sct, SIGNAL(activated()), openPages, SLOT(nextPageWithSwitcher()));
+ sct = new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Tab), this);
+ connect(sct, SIGNAL(activated()), openPages, SLOT(previousPageWithSwitcher()));
+#endif
+
+ BookmarkManager::instance()->setBookmarksMenu(menuBar()->addMenu(tr("&Bookmarks")));
+
+ menu = menuBar()->addMenu(tr("&Help"));
+ m_aboutAction = menu->addAction(tr("About..."), this, SLOT(showAboutDialog()));
+ m_aboutAction->setMenuRole(QAction::AboutRole);
+
+#ifdef Q_WS_X11
+ m_resetZoomAction->setIcon(QIcon::fromTheme("zoom-original" , m_resetZoomAction->icon()));
+ m_syncAction->setIcon(QIcon::fromTheme("view-refresh" , m_syncAction->icon()));
+#endif
+
+ QToolBar *navigationBar = addToolBar(tr("Navigation Toolbar"));
+ navigationBar->setObjectName(QLatin1String("NavigationToolBar"));
+ navigationBar->addAction(globalActions->backAction());
+ navigationBar->addAction(globalActions->nextAction());
+ navigationBar->addAction(globalActions->homeAction());
+ navigationBar->addAction(m_syncAction);
+ navigationBar->addSeparator();
+ navigationBar->addAction(globalActions->copyAction());
+ navigationBar->addAction(globalActions->printAction());
+ navigationBar->addAction(globalActions->findAction());
+ navigationBar->addSeparator();
+ navigationBar->addAction(globalActions->zoomInAction());
+ navigationBar->addAction(globalActions->zoomOutAction());
+ navigationBar->addAction(m_resetZoomAction);
+
+#if defined(Q_WS_MAC)
+ QMenu *windowMenu = new QMenu(tr("&Window"), this);
+ menuBar()->insertMenu(menu->menuAction(), windowMenu);
+ windowMenu->addAction(tr("Zoom"), this, SLOT(showMaximized()));
+ windowMenu->addAction(tr("Minimize"), this, SLOT(showMinimized()),
+ QKeySequence(tr("Ctrl+M")));
+#endif
+
+ // content viewer connections
+ connect(m_centralWidget, SIGNAL(copyAvailable(bool)), globalActions,
+ SLOT(setCopyAvailable(bool)));
+ connect(m_centralWidget, SIGNAL(currentViewerChanged()), globalActions,
+ SLOT(updateActions()));
+ connect(m_centralWidget, SIGNAL(forwardAvailable(bool)), globalActions,
+ SLOT(updateActions()));
+ connect(m_centralWidget, SIGNAL(backwardAvailable(bool)), globalActions,
+ SLOT(updateActions()));
+ connect(m_centralWidget, SIGNAL(highlighted(QString)), statusBar(),
+ SLOT(showMessage(QString)));
+
+ // index window
+ connect(m_indexWindow, SIGNAL(linkActivated(QUrl)), m_centralWidget,
+ SLOT(setSource(QUrl)));
+ connect(m_indexWindow, SIGNAL(linksActivated(QMap<QString,QUrl>,QString)),
+ this, SLOT(showTopicChooser(QMap<QString,QUrl>,QString)));
+ connect(m_indexWindow, SIGNAL(escapePressed()), this,
+ SLOT(activateCurrentCentralWidgetTab()));
+
+ // content window
+ connect(m_contentWindow, SIGNAL(linkActivated(QUrl)), m_centralWidget,
+ SLOT(setSource(QUrl)));
+ connect(m_contentWindow, SIGNAL(escapePressed()), this,
+ SLOT(activateCurrentCentralWidgetTab()));
+
+ // search window
+ connect(m_searchWindow, SIGNAL(requestShowLink(QUrl)),
+ CentralWidget::instance(), SLOT(setSourceFromSearch(QUrl)));
+ connect(m_searchWindow, SIGNAL(requestShowLinkInNewTab(QUrl)),
+ OpenPagesManager::instance(), SLOT(createNewPageFromSearch(QUrl)));
+
+#if defined(QT_NO_PRINTER)
+ m_pageSetupAction->setVisible(false);
+ m_printPreviewAction->setVisible(false);
+ m_printAction->setVisible(false);
+#endif
+}
+
+QMenu *MainWindow::toolBarMenu()
+{
+ TRACE_OBJ
+ if (!m_toolBarMenu) {
+ m_viewMenu->addSeparator();
+ m_toolBarMenu = m_viewMenu->addMenu(tr("Toolbars"));
+ }
+ return m_toolBarMenu;
+}
+
+void MainWindow::setupFilterToolbar()
+{
+ TRACE_OBJ
+ HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance();
+ if (!helpEngine.filterFunctionalityEnabled())
+ return;
+
+ m_filterCombo = new QComboBox(this);
+ m_filterCombo->setMinimumWidth(QFontMetrics(QFont()).
+ width(QLatin1String("MakeTheComboBoxWidthEnough")));
+
+ QToolBar *filterToolBar = addToolBar(tr("Filter Toolbar"));
+ filterToolBar->setObjectName(QLatin1String("FilterToolBar"));
+ filterToolBar->addWidget(new QLabel(tr("Filtered by:").append(QLatin1Char(' ')),
+ this));
+ filterToolBar->addWidget(m_filterCombo);
+
+ if (!helpEngine.filterToolbarVisible())
+ filterToolBar->hide();
+ toolBarMenu()->addAction(filterToolBar->toggleViewAction());
+
+ connect(&helpEngine, SIGNAL(setupFinished()), this,
+ SLOT(setupFilterCombo()), Qt::QueuedConnection);
+ connect(m_filterCombo, SIGNAL(activated(QString)), this,
+ SLOT(filterDocumentation(QString)));
+ connect(&helpEngine, SIGNAL(currentFilterChanged(QString)), this,
+ SLOT(currentFilterChanged(QString)));
+
+ setupFilterCombo();
+}
+
+void MainWindow::setupAddressToolbar()
+{
+ TRACE_OBJ
+ HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance();
+ if (!helpEngine.addressBarEnabled())
+ return;
+
+ m_addressLineEdit = new QLineEdit(this);
+ QToolBar *addressToolBar = addToolBar(tr("Address Toolbar"));
+ addressToolBar->setObjectName(QLatin1String("AddressToolBar"));
+ insertToolBarBreak(addressToolBar);
+
+ addressToolBar->addWidget(new QLabel(tr("Address:").append(QLatin1String(" ")),
+ this));
+ addressToolBar->addWidget(m_addressLineEdit);
+
+ if (!helpEngine.addressBarVisible())
+ addressToolBar->hide();
+ toolBarMenu()->addAction(addressToolBar->toggleViewAction());
+
+ // address lineedit
+ connect(m_addressLineEdit, SIGNAL(returnPressed()), this,
+ SLOT(gotoAddress()));
+ connect(m_centralWidget, SIGNAL(currentViewerChanged()), this,
+ SLOT(showNewAddress()));
+ connect(m_centralWidget, SIGNAL(sourceChanged(QUrl)), this,
+ SLOT(showNewAddress(QUrl)));
+}
+
+void MainWindow::updateAboutMenuText()
+{
+ TRACE_OBJ
+ QByteArray ba = HelpEngineWrapper::instance().aboutMenuTexts();
+ if (ba.size() > 0) {
+ QString lang;
+ QString str;
+ QString trStr;
+ QString currentLang = QLocale::system().name();
+ int i = currentLang.indexOf(QLatin1Char('_'));
+ if (i > -1)
+ currentLang = currentLang.left(i);
+ QDataStream s(&ba, QIODevice::ReadOnly);
+ while (!s.atEnd()) {
+ s >> lang;
+ s >> str;
+ if (lang == QLatin1String("default") && trStr.isEmpty()) {
+ trStr = str;
+ } else if (lang == currentLang) {
+ trStr = str;
+ break;
+ }
+ }
+ if (!trStr.isEmpty())
+ m_aboutAction->setText(trStr);
+ }
+}
+
+void MainWindow::showNewAddress()
+{
+ TRACE_OBJ
+ showNewAddress(m_centralWidget->currentSource());
+}
+
+void MainWindow::showNewAddress(const QUrl &url)
+{
+ TRACE_OBJ
+ m_addressLineEdit->setText(url.toString());
+}
+
+void MainWindow::gotoAddress()
+{
+ TRACE_OBJ
+ m_centralWidget->setSource(m_addressLineEdit->text());
+}
+
+void MainWindow::showTopicChooser(const QMap<QString, QUrl> &links,
+ const QString &keyword)
+{
+ TRACE_OBJ
+ TopicChooser tc(this, keyword, links);
+ if (tc.exec() == QDialog::Accepted) {
+ m_centralWidget->setSource(tc.link());
+ }
+}
+
+void MainWindow::showPreferences()
+{
+ TRACE_OBJ
+ PreferencesDialog dia(this);
+ connect(&dia, SIGNAL(updateApplicationFont()), this,
+ SLOT(updateApplicationFont()));
+ connect(&dia, SIGNAL(updateBrowserFont()), m_centralWidget,
+ SLOT(updateBrowserFont()));
+ connect(&dia, SIGNAL(updateUserInterface()), m_centralWidget,
+ SLOT(updateUserInterface()));
+ dia.showDialog();
+}
+
+void MainWindow::syncContents()
+{
+ TRACE_OBJ
+ qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
+ const QUrl url = m_centralWidget->currentSource();
+ showContents();
+ if (!m_contentWindow->syncToContent(url))
+ statusBar()->showMessage(
+ tr("Could not find the associated content item."), 3000);
+ qApp->restoreOverrideCursor();
+}
+
+void MainWindow::showAboutDialog()
+{
+ TRACE_OBJ
+ HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance();
+ QByteArray contents;
+ QByteArray ba = helpEngine.aboutTexts();
+ if (!ba.isEmpty()) {
+ QString lang;
+ QByteArray cba;
+ QString currentLang = QLocale::system().name();
+ int i = currentLang.indexOf(QLatin1Char('_'));
+ if (i > -1)
+ currentLang = currentLang.left(i);
+ QDataStream s(&ba, QIODevice::ReadOnly);
+ while (!s.atEnd()) {
+ s >> lang;
+ s >> cba;
+ if (lang == QLatin1String("default") && contents.isEmpty()) {
+ contents = cba;
+ } else if (lang == currentLang) {
+ contents = cba;
+ break;
+ }
+ }
+ }
+
+ AboutDialog aboutDia(this);
+
+ QByteArray iconArray;
+ if (!contents.isEmpty()) {
+ iconArray = helpEngine.aboutIcon();
+ QByteArray resources = helpEngine.aboutImages();
+ QPixmap pix;
+ pix.loadFromData(iconArray);
+ aboutDia.setText(QString::fromUtf8(contents), resources);
+ if (!pix.isNull())
+ aboutDia.setPixmap(pix);
+ aboutDia.setWindowTitle(aboutDia.documentTitle());
+ } else {
+ QByteArray resources;
+ aboutDia.setText(tr("<center>"
+ "<h3>%1</h3>"
+ "<p>Version %2</p></center>"
+ "<p>Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).</p>")
+ .arg(tr("Qt Assistant")).arg(QLatin1String(QT_VERSION_STR)),
+ resources);
+ QLatin1String path(":/trolltech/assistant/images/assistant-128.png");
+ aboutDia.setPixmap(QString(path));
+ }
+ if (aboutDia.windowTitle().isEmpty())
+ aboutDia.setWindowTitle(tr("About %1").arg(windowTitle()));
+ aboutDia.exec();
+}
+
+void MainWindow::setContentsVisible(bool visible)
+{
+ TRACE_OBJ
+ if (visible)
+ showContents();
+ else
+ hideContents();
+}
+
+void MainWindow::showContents()
+{
+ TRACE_OBJ
+ activateDockWidget(m_contentWindow);
+}
+
+void MainWindow::hideContents()
+{
+ TRACE_OBJ
+ m_contentWindow->parentWidget()->hide();
+}
+
+void MainWindow::setIndexVisible(bool visible)
+{
+ TRACE_OBJ
+ if (visible)
+ showIndex();
+ else
+ hideIndex();
+}
+
+void MainWindow::showIndex()
+{
+ TRACE_OBJ
+ activateDockWidget(m_indexWindow);
+}
+
+void MainWindow::hideIndex()
+{
+ TRACE_OBJ
+ m_indexWindow->parentWidget()->hide();
+}
+
+void MainWindow::setBookmarksVisible(bool visible)
+{
+ TRACE_OBJ
+ if (visible)
+ showBookmarksDockWidget();
+ else
+ hideBookmarksDockWidget();
+}
+
+void MainWindow::showBookmarksDockWidget()
+{
+ TRACE_OBJ
+ activateDockWidget(m_bookmarkWidget);
+}
+
+void MainWindow::hideBookmarksDockWidget()
+{
+ TRACE_OBJ
+ m_bookmarkWidget->parentWidget()->hide();
+}
+
+void MainWindow::setSearchVisible(bool visible)
+{
+ TRACE_OBJ
+ if (visible)
+ showSearch();
+ else
+ hideSearch();
+}
+
+void MainWindow::showSearch()
+{
+ TRACE_OBJ
+ activateDockWidget(m_searchWindow);
+}
+
+void MainWindow::showOpenPages()
+{
+ TRACE_OBJ
+ activateDockWidget(OpenPagesManager::instance()->openPagesWidget());
+}
+
+void MainWindow::hideSearch()
+{
+ TRACE_OBJ
+ m_searchWindow->parentWidget()->hide();
+}
+
+void MainWindow::activateDockWidget(QWidget *w)
+{
+ TRACE_OBJ
+ w->parentWidget()->show();
+ w->parentWidget()->raise();
+ w->setFocus();
+}
+
+void MainWindow::setIndexString(const QString &str)
+{
+ TRACE_OBJ
+ m_indexWindow->setSearchLineEditText(str);
+}
+
+void MainWindow::activateCurrentBrowser()
+{
+ TRACE_OBJ
+ CentralWidget::instance()->activateTab();
+}
+
+void MainWindow::activateCurrentCentralWidgetTab()
+{
+ TRACE_OBJ
+ m_centralWidget->activateTab();
+}
+
+void MainWindow::updateApplicationFont()
+{
+ TRACE_OBJ
+ HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance();
+ QFont font = qApp->font();
+ if (helpEngine.usesAppFont())
+ font = helpEngine.appFont();
+
+ const QWidgetList &widgets = qApp->allWidgets();
+ foreach (QWidget* widget, widgets)
+ widget->setFont(font);
+}
+
+void MainWindow::setupFilterCombo()
+{
+ TRACE_OBJ
+ HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance();
+ QString curFilter = m_filterCombo->currentText();
+ if (curFilter.isEmpty())
+ curFilter = helpEngine.currentFilter();
+ m_filterCombo->clear();
+ m_filterCombo->addItems(helpEngine.customFilters());
+ int idx = m_filterCombo->findText(curFilter);
+ if (idx < 0)
+ idx = 0;
+ m_filterCombo->setCurrentIndex(idx);
+}
+
+void MainWindow::filterDocumentation(const QString &customFilter)
+{
+ TRACE_OBJ
+ HelpEngineWrapper::instance().setCurrentFilter(customFilter);
+}
+
+void MainWindow::expandTOC(int depth)
+{
+ TRACE_OBJ
+ Q_ASSERT(depth >= -1);
+ m_contentWindow->expandToDepth(depth);
+}
+
+void MainWindow::indexingStarted()
+{
+ TRACE_OBJ
+ if (!m_progressWidget) {
+ m_progressWidget = new QWidget();
+ QLayout* hlayout = new QHBoxLayout(m_progressWidget);
+
+ QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
+
+ QLabel *label = new QLabel(tr("Updating search index"));
+ label->setSizePolicy(sizePolicy);
+ hlayout->addWidget(label);
+
+ QProgressBar *progressBar = new QProgressBar();
+ progressBar->setRange(0, 0);
+ progressBar->setTextVisible(false);
+ progressBar->setSizePolicy(sizePolicy);
+
+ hlayout->setSpacing(6);
+ hlayout->setMargin(0);
+ hlayout->addWidget(progressBar);
+
+ statusBar()->addPermanentWidget(m_progressWidget);
+ }
+}
+
+void MainWindow::indexingFinished()
+{
+ TRACE_OBJ
+ statusBar()->removeWidget(m_progressWidget);
+ delete m_progressWidget;
+ m_progressWidget = 0;
+}
+
+QString MainWindow::collectionFileDirectory(bool createDir, const QString &cacheDir)
+{
+ TRACE_OBJ
+ QString collectionPath =
+ QDesktopServices::storageLocation(QDesktopServices::DataLocation);
+ if (collectionPath.isEmpty()) {
+ if (cacheDir.isEmpty())
+ collectionPath = QDir::homePath() + QDir::separator()
+ + QLatin1String(".assistant");
+ else
+ collectionPath = QDir::homePath() + QLatin1String("/.") + cacheDir;
+ } else {
+ if (cacheDir.isEmpty())
+ collectionPath = collectionPath + QLatin1String("/Trolltech/Assistant");
+ else
+ collectionPath = collectionPath + QDir::separator() + cacheDir;
+ }
+ collectionPath = QDir::cleanPath(collectionPath);
+ if (createDir) {
+ QDir dir;
+ if (!dir.exists(collectionPath))
+ dir.mkpath(collectionPath);
+ }
+ return collectionPath;
+}
+
+QString MainWindow::defaultHelpCollectionFileName()
+{
+ TRACE_OBJ
+ // forces creation of the default collection file path
+ return collectionFileDirectory(true) + QDir::separator() +
+ QString(QLatin1String("qthelpcollection_%1.qhc")).
+ arg(QLatin1String(QT_VERSION_STR));
+}
+
+void MainWindow::currentFilterChanged(const QString &filter)
+{
+ TRACE_OBJ
+ const int index = m_filterCombo->findText(filter);
+ Q_ASSERT(index != -1);
+ m_filterCombo->setCurrentIndex(index);
+}
+
+void MainWindow::documentationRemoved(const QString &namespaceName)
+{
+ TRACE_OBJ
+ OpenPagesManager::instance()->closePages(namespaceName);
+}
+
+void MainWindow::documentationUpdated(const QString &namespaceName)
+{
+ TRACE_OBJ
+ OpenPagesManager::instance()->reloadPages(namespaceName);
+}
+
+void MainWindow::resetQtDocInfo(const QString &component)
+{
+ TRACE_OBJ
+ HelpEngineWrapper::instance().setQtDocInfo(component,
+ QStringList(QDateTime().toString(Qt::ISODate)));
+}
+
+void MainWindow::registerDocumentation(const QString &component,
+ const QString &absFileName)
+{
+ TRACE_OBJ
+ QString ns = QHelpEngineCore::namespaceName(absFileName);
+ if (ns.isEmpty())
+ return;
+
+ HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance();
+ if (helpEngine.registeredDocumentations().contains(ns))
+ helpEngine.unregisterDocumentation(ns);
+ if (!helpEngine.registerDocumentation(absFileName)) {
+ QMessageBox::warning(this, tr("Qt Assistant"),
+ tr("Could not register file '%1': %2").
+ arg(absFileName).arg(helpEngine.error()));
+ } else {
+ QStringList docInfo;
+ docInfo << QFileInfo(absFileName).lastModified().toString(Qt::ISODate)
+ << absFileName;
+ helpEngine.setQtDocInfo(component, docInfo);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/mainwindow.h b/src/assistant/tools/assistant/mainwindow.h
new file mode 100644
index 000000000..6fe10ec45
--- /dev/null
+++ b/src/assistant/tools/assistant/mainwindow.h
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QtCore/QList>
+#include <QtCore/QUrl>
+#include <QtGui/QMainWindow>
+
+QT_BEGIN_NAMESPACE
+
+class QAction;
+class QComboBox;
+class QFileSystemWatcher;
+class QLineEdit;
+class QMenu;
+
+class CentralWidget;
+class CmdLineParser;
+class ContentWindow;
+class IndexWindow;
+class OpenPagesWindow;
+class QtDocInstaller;
+class QHelpEngineCore;
+class QHelpEngine;
+class SearchWidget;
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindow(CmdLineParser *cmdLine, QWidget *parent = 0);
+ ~MainWindow();
+
+ static void activateCurrentBrowser();
+ static QString collectionFileDirectory(bool createDir = false,
+ const QString &cacheDir = QString());
+ static QString defaultHelpCollectionFileName();
+
+public:
+ void setIndexString(const QString &str);
+ void expandTOC(int depth);
+ bool usesDefaultCollection() const;
+
+signals:
+ void initDone();
+
+public slots:
+ void setContentsVisible(bool visible);
+ void setIndexVisible(bool visible);
+ void setBookmarksVisible(bool visible);
+ void setSearchVisible(bool visible);
+ void syncContents();
+ void activateCurrentCentralWidgetTab();
+ void currentFilterChanged(const QString &filter);
+
+private slots:
+ void showContents();
+ void showIndex();
+ void showSearch();
+ void showOpenPages();
+ void insertLastPages();
+ void gotoAddress();
+ void showPreferences();
+ void showNewAddress();
+ void showAboutDialog();
+ void showNewAddress(const QUrl &url);
+ void showTopicChooser(const QMap<QString, QUrl> &links, const QString &keyword);
+ void updateApplicationFont();
+ void filterDocumentation(const QString &customFilter);
+ void setupFilterCombo();
+ void lookForNewQtDocumentation();
+ void indexingStarted();
+ void indexingFinished();
+ void qtDocumentationInstalled();
+ void registerDocumentation(const QString &component,
+ const QString &absFileName);
+ void resetQtDocInfo(const QString &component);
+ void checkInitState();
+ void documentationRemoved(const QString &namespaceName);
+ void documentationUpdated(const QString &namespaceName);
+
+private:
+ bool initHelpDB(bool registerInternalDoc);
+ void setupActions();
+ void closeEvent(QCloseEvent *e);
+ void activateDockWidget(QWidget *w);
+ void updateAboutMenuText();
+ void setupFilterToolbar();
+ void setupAddressToolbar();
+ QMenu *toolBarMenu();
+ void hideContents();
+ void hideIndex();
+ void hideSearch();
+
+private slots:
+ void showBookmarksDockWidget();
+ void hideBookmarksDockWidget();
+
+private:
+ QWidget *m_bookmarkWidget;
+
+private:
+ CentralWidget *m_centralWidget;
+ IndexWindow *m_indexWindow;
+ ContentWindow *m_contentWindow;
+ SearchWidget *m_searchWindow;
+ QLineEdit *m_addressLineEdit;
+ QComboBox *m_filterCombo;
+
+ QAction *m_syncAction;
+ QAction *m_printPreviewAction;
+ QAction *m_pageSetupAction;
+ QAction *m_resetZoomAction;
+ QAction *m_aboutAction;
+ QAction *m_closeTabAction;
+ QAction *m_newTabAction;
+
+ QMenu *m_viewMenu;
+ QMenu *m_toolBarMenu;
+
+ CmdLineParser *m_cmdLine;
+
+ QWidget *m_progressWidget;
+ QtDocInstaller *m_qtDocInstaller;
+
+ bool m_connectedInitSignals;
+};
+
+QT_END_NAMESPACE
+
+#endif // MAINWINDOW_H
diff --git a/src/assistant/tools/assistant/openpagesmanager.cpp b/src/assistant/tools/assistant/openpagesmanager.cpp
new file mode 100644
index 000000000..272d9e242
--- /dev/null
+++ b/src/assistant/tools/assistant/openpagesmanager.cpp
@@ -0,0 +1,378 @@
+/****************************************************************************
+**
+** 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 Assistant module 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 "openpagesmanager.h"
+
+#include "centralwidget.h"
+#include "helpenginewrapper.h"
+#include "helpviewer.h"
+#include "openpagesmodel.h"
+#include "openpagesswitcher.h"
+#include "openpageswidget.h"
+#include "tracer.h"
+#include "../shared/collectionconfiguration.h"
+
+#include <QtGui/QApplication>
+#include <QtGui/QTreeView>
+
+QT_BEGIN_NAMESPACE
+
+OpenPagesManager *OpenPagesManager::m_instance = 0;
+
+OpenPagesManager *OpenPagesManager::createInstance(QObject *parent,
+ bool defaultCollection, const QUrl &cmdLineUrl)
+{
+ TRACE_OBJ
+ Q_ASSERT(!m_instance);
+ m_instance = new OpenPagesManager(parent, defaultCollection, cmdLineUrl);
+ return m_instance;
+}
+
+OpenPagesManager *OpenPagesManager::instance()
+{
+ TRACE_OBJ
+ Q_ASSERT(m_instance);
+ return m_instance;
+}
+
+OpenPagesManager::OpenPagesManager(QObject *parent, bool defaultCollection,
+ const QUrl &cmdLineUrl)
+ : QObject(parent)
+ , m_model(new OpenPagesModel(this))
+ , m_openPagesWidget(0)
+ , m_openPagesSwitcher(0)
+{
+ TRACE_OBJ
+ m_openPagesWidget = new OpenPagesWidget(m_model);
+ m_openPagesWidget->setFrameStyle(QFrame::NoFrame);
+ connect(m_openPagesWidget, SIGNAL(setCurrentPage(QModelIndex)), this,
+ SLOT(setCurrentPage(QModelIndex)));
+ connect(m_openPagesWidget, SIGNAL(closePage(QModelIndex)), this,
+ SLOT(closePage(QModelIndex)));
+ connect(m_openPagesWidget, SIGNAL(closePagesExcept(QModelIndex)), this,
+ SLOT(closePagesExcept(QModelIndex)));
+
+ m_openPagesSwitcher = new OpenPagesSwitcher(m_model);
+ connect(m_openPagesSwitcher, SIGNAL(closePage(QModelIndex)), this,
+ SLOT(closePage(QModelIndex)));
+ connect(m_openPagesSwitcher, SIGNAL(setCurrentPage(QModelIndex)), this,
+ SLOT(setCurrentPage(QModelIndex)));
+
+ setupInitialPages(defaultCollection, cmdLineUrl);
+}
+
+OpenPagesManager ::~OpenPagesManager()
+{
+ TRACE_OBJ
+ m_instance = 0;
+ delete m_openPagesSwitcher;
+}
+
+int OpenPagesManager::pageCount() const
+{
+ TRACE_OBJ
+ return m_model->rowCount();
+}
+
+void OpenPagesManager::setupInitialPages(bool defaultCollection,
+ const QUrl &cmdLineUrl)
+{
+ TRACE_OBJ
+ if (cmdLineUrl.isValid()) {
+ createPage(cmdLineUrl);
+ return;
+ }
+
+ HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance();
+ int initialPage = 0;
+ switch (helpEngine.startOption()) {
+ case ShowHomePage:
+ m_model->addPage(helpEngine.homePage());
+ break;
+ case ShowBlankPage:
+ m_model->addPage(QUrl(QLatin1String("about:blank")));
+ break;
+ case ShowLastPages: {
+ const QStringList &lastShownPageList = helpEngine.lastShownPages();
+ const int pageCount = lastShownPageList.count();
+ if (pageCount == 0) {
+ if (defaultCollection)
+ m_model->addPage(QUrl(QLatin1String("help")));
+ else
+ m_model->addPage(QUrl(QLatin1String("about:blank")));
+ } else {
+ QStringList zoomFactors = helpEngine.lastZoomFactors();
+ while (zoomFactors.count() < pageCount)
+ zoomFactors.append(CollectionConfiguration::DefaultZoomFactor);
+ initialPage = helpEngine.lastTabPage();
+ if (initialPage >= pageCount) {
+ qWarning("Initial page set to %d, maximum possible value is %d",
+ initialPage, pageCount - 1);
+ initialPage = 0;
+ }
+ for (int curPage = 0; curPage < pageCount; ++curPage) {
+ const QString &curFile = lastShownPageList.at(curPage);
+ if (helpEngine.findFile(curFile).isValid()
+ || curFile == QLatin1String("about:blank")) {
+ m_model->addPage(curFile, zoomFactors.at(curPage).toFloat());
+ } else if (curPage <= initialPage && initialPage > 0)
+ --initialPage;
+ }
+ }
+ break;
+ }
+ default:
+ Q_ASSERT(!"Unhandled option");
+ }
+
+ if (m_model->rowCount() == 0)
+ m_model->addPage(helpEngine.homePage());
+ for (int i = 0; i < m_model->rowCount(); ++i)
+ CentralWidget::instance()->addPage(m_model->pageAt(i));
+ setCurrentPage((initialPage >= m_model->rowCount())
+ ? m_model->rowCount() - 1 : initialPage);
+ m_openPagesSwitcher->selectCurrentPage();
+}
+
+HelpViewer *OpenPagesManager::createPage()
+{
+ TRACE_OBJ
+ return createPage(QUrl(QLatin1String("about:blank")));
+}
+
+void OpenPagesManager::closeCurrentPage()
+{
+ TRACE_OBJ
+ Q_ASSERT(m_model->rowCount() > 1);
+ const QModelIndexList selectedIndexes
+ = m_openPagesWidget->selectionModel()->selectedRows();
+ if (selectedIndexes.isEmpty())
+ return;
+ Q_ASSERT(selectedIndexes.count() == 1);
+ removePage(selectedIndexes.first().row());
+}
+
+HelpViewer *OpenPagesManager::createPage(const QUrl &url, bool fromSearch)
+{
+ TRACE_OBJ
+ if (HelpViewer::launchWithExternalApp(url))
+ return 0;
+
+ m_model->addPage(url);
+ const int index = m_model->rowCount() - 1;
+ HelpViewer * const page = m_model->pageAt(index);
+ CentralWidget::instance()->addPage(page, fromSearch);
+ setCurrentPage(index);
+ return page;
+}
+
+HelpViewer *OpenPagesManager::createNewPageFromSearch(const QUrl &url)
+{
+ TRACE_OBJ
+ return createPage(url, true);
+}
+
+void OpenPagesManager::closePage(HelpViewer *viewer)
+{
+ TRACE_OBJ
+ for (int i = 0; i < m_model->rowCount(); ++i) {
+ if (m_model->pageAt(i) == viewer) {
+ removePage(i);
+ break;
+ }
+ }
+}
+
+void OpenPagesManager::closePage(const QModelIndex &index)
+{
+ TRACE_OBJ
+ if (index.isValid())
+ removePage(index.row());
+}
+
+void OpenPagesManager::closePages(const QString &nameSpace)
+{
+ TRACE_OBJ
+ closeOrReloadPages(nameSpace, false);
+}
+
+void OpenPagesManager::reloadPages(const QString &nameSpace)
+{
+ TRACE_OBJ
+ closeOrReloadPages(nameSpace, true);
+ m_openPagesWidget->selectCurrentPage();
+}
+
+void OpenPagesManager::closeOrReloadPages(const QString &nameSpace, bool tryReload)
+{
+ TRACE_OBJ
+ for (int i = m_model->rowCount() - 1; i >= 0; --i) {
+ HelpViewer *page = m_model->pageAt(i);
+ if (page->source().host() != nameSpace)
+ continue;
+ if (tryReload && HelpEngineWrapper::instance().findFile(page->source()).isValid())
+ page->reload();
+ else if (m_model->rowCount() == 1)
+ page->setSource(QUrl(QLatin1String("about:blank")));
+ else
+ removePage(i);
+ }
+}
+
+bool OpenPagesManager::pagesOpenForNamespace(const QString &nameSpace) const
+{
+ TRACE_OBJ
+ for (int i = 0; i < m_model->rowCount(); ++i)
+ if (m_model->pageAt(i)->source().host() == nameSpace)
+ return true;
+ return false;
+}
+
+void OpenPagesManager::setCurrentPage(const QModelIndex &index)
+{
+ TRACE_OBJ
+ if (index.isValid())
+ setCurrentPage(index.row());
+}
+
+void OpenPagesManager::setCurrentPage(int index)
+{
+ TRACE_OBJ
+ setCurrentPage(m_model->pageAt(index));
+}
+
+void OpenPagesManager::setCurrentPage(HelpViewer *page)
+{
+ TRACE_OBJ
+ CentralWidget::instance()->setCurrentPage(page);
+ m_openPagesWidget->selectCurrentPage();
+}
+
+void OpenPagesManager::removePage(int index)
+{
+ TRACE_OBJ
+ CentralWidget::instance()->removePage(index);
+ m_model->removePage(index);
+ m_openPagesWidget->selectCurrentPage();
+}
+
+
+void OpenPagesManager::closePagesExcept(const QModelIndex &index)
+{
+ TRACE_OBJ
+ if (!index.isValid())
+ return;
+
+ int i = 0;
+ HelpViewer *viewer = m_model->pageAt(index.row());
+ while (m_model->rowCount() > 1) {
+ if (m_model->pageAt(i) != viewer)
+ removePage(i);
+ else
+ ++i;
+ }
+}
+
+QAbstractItemView *OpenPagesManager::openPagesWidget() const
+{
+ TRACE_OBJ
+ return m_openPagesWidget;
+}
+
+void OpenPagesManager::nextPage()
+{
+ TRACE_OBJ
+ nextOrPreviousPage(1);
+}
+
+void OpenPagesManager::nextPageWithSwitcher()
+{
+ TRACE_OBJ
+ if (!m_openPagesSwitcher->isVisible()) {
+ m_openPagesSwitcher->selectCurrentPage();
+ m_openPagesSwitcher->gotoNextPage();
+ showSwitcherOrSelectPage();
+ } else {
+ m_openPagesSwitcher->gotoNextPage();
+ }
+}
+
+void OpenPagesManager::previousPage()
+{
+ TRACE_OBJ
+ nextOrPreviousPage(-1);
+}
+
+void OpenPagesManager::previousPageWithSwitcher()
+{
+ TRACE_OBJ
+ if (!m_openPagesSwitcher->isVisible()) {
+ m_openPagesSwitcher->selectCurrentPage();
+ m_openPagesSwitcher->gotoPreviousPage();
+ showSwitcherOrSelectPage();
+ } else {
+ m_openPagesSwitcher->gotoPreviousPage();
+ }
+}
+
+void OpenPagesManager::nextOrPreviousPage(int offset)
+{
+ TRACE_OBJ
+ setCurrentPage((CentralWidget::instance()->currentIndex() + offset
+ + m_model->rowCount()) % m_model->rowCount());
+}
+
+void OpenPagesManager::showSwitcherOrSelectPage() const
+{
+ TRACE_OBJ
+ if (QApplication::keyboardModifiers() != Qt::NoModifier) {
+ const int width = CentralWidget::instance()->width();
+ const int height = CentralWidget::instance()->height();
+ const QPoint p(CentralWidget::instance()->mapToGlobal(QPoint(0, 0)));
+ m_openPagesSwitcher->move((width - m_openPagesSwitcher->width()) / 2 + p.x(),
+ (height - m_openPagesSwitcher->height()) / 2 + p.y());
+ m_openPagesSwitcher->setVisible(true);
+ } else {
+ m_openPagesSwitcher->selectAndHide();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/openpagesmanager.h b/src/assistant/tools/assistant/openpagesmanager.h
new file mode 100644
index 000000000..c34686c8c
--- /dev/null
+++ b/src/assistant/tools/assistant/openpagesmanager.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** 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 Assistant module 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$
+**
+****************************************************************************/
+
+#ifndef OPENPAGESMANAGER_H
+#define OPENPAGESMANAGER_H
+
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractItemView;
+class QModelIndex;
+class QUrl;
+
+class HelpViewer;
+class OpenPagesModel;
+class OpenPagesSwitcher;
+class OpenPagesWidget;
+
+class OpenPagesManager : public QObject
+{
+ Q_OBJECT
+public:
+ static OpenPagesManager *createInstance(QObject *parent,
+ bool defaultCollection, const QUrl &cmdLineUrl);
+ static OpenPagesManager *instance();
+
+ bool pagesOpenForNamespace(const QString &nameSpace) const;
+ void closePages(const QString &nameSpace);
+ void reloadPages(const QString &nameSpace);
+
+ QAbstractItemView* openPagesWidget() const;
+
+ int pageCount() const;
+ void setCurrentPage(int index);
+
+public slots:
+ HelpViewer *createPage(const QUrl &url, bool fromSearch = false);
+ HelpViewer *createNewPageFromSearch(const QUrl &url);
+ HelpViewer *createPage();
+ void closeCurrentPage();
+
+ void nextPage();
+ void nextPageWithSwitcher();
+ void previousPage();
+ void previousPageWithSwitcher();
+
+ void closePage(HelpViewer *page);
+ void setCurrentPage(HelpViewer *page);
+
+private slots:
+ void setCurrentPage(const QModelIndex &index);
+ void closePage(const QModelIndex &index);
+ void closePagesExcept(const QModelIndex &index);
+
+private:
+ OpenPagesManager(QObject *parent, bool defaultCollection,
+ const QUrl &cmdLineUrl);
+ ~OpenPagesManager();
+
+ void setupInitialPages(bool defaultCollection, const QUrl &cmdLineUrl);
+ void closeOrReloadPages(const QString &nameSpace, bool tryReload);
+ void removePage(int index);
+
+ void nextOrPreviousPage(int offset);
+ void showSwitcherOrSelectPage() const;
+
+ OpenPagesModel *m_model;
+ OpenPagesWidget *m_openPagesWidget;
+ OpenPagesSwitcher *m_openPagesSwitcher;
+
+ static OpenPagesManager *m_instance;
+};
+
+QT_END_NAMESPACE
+
+#endif // OPENPAGESMANAGER_H
diff --git a/src/assistant/tools/assistant/openpagesmodel.cpp b/src/assistant/tools/assistant/openpagesmodel.cpp
new file mode 100644
index 000000000..3517693f9
--- /dev/null
+++ b/src/assistant/tools/assistant/openpagesmodel.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** 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 Assistant module 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 "openpagesmodel.h"
+
+#include "helpenginewrapper.h"
+#include "helpviewer.h"
+#include "tracer.h"
+
+#include <QtCore/QStringList>
+#include <QtCore/QUrl>
+
+QT_BEGIN_NAMESPACE
+
+OpenPagesModel::OpenPagesModel(QObject *parent) : QAbstractTableModel(parent)
+{
+ TRACE_OBJ
+}
+
+int OpenPagesModel::rowCount(const QModelIndex &parent) const
+{
+ TRACE_OBJ
+ return parent.isValid() ? 0 : m_pages.count();
+}
+
+int OpenPagesModel::columnCount(const QModelIndex &/*parent*/) const
+{
+ TRACE_OBJ
+ return 2;
+}
+
+QVariant OpenPagesModel::data(const QModelIndex &index, int role) const
+{
+ TRACE_OBJ
+ if (!index.isValid() || index.row() >= rowCount() || index.column() > 0
+ || role != Qt::DisplayRole)
+ return QVariant();
+ QString title = m_pages.at(index.row())->title();
+ title.replace(QLatin1Char('&'), QLatin1String("&&"));
+ return title.isEmpty() ? QLatin1String("(Untitled)") : title;
+}
+
+void OpenPagesModel::addPage(const QUrl &url, qreal zoom)
+{
+ TRACE_OBJ
+ beginInsertRows(QModelIndex(), rowCount(), rowCount());
+ HelpViewer *page = new HelpViewer(zoom);
+ connect(page, SIGNAL(titleChanged()), this, SLOT(handleTitleChanged()));
+ m_pages << page;
+ endInsertRows();
+ page->setSource(url);
+}
+
+void OpenPagesModel::removePage(int index)
+{
+ TRACE_OBJ
+ Q_ASSERT(index >= 0 && index < rowCount());
+ beginRemoveRows(QModelIndex(), index, index);
+ HelpViewer *page = m_pages.at(index);
+ m_pages.removeAt(index);
+ endRemoveRows();
+ page->deleteLater();
+}
+
+HelpViewer *OpenPagesModel::pageAt(int index) const
+{
+ TRACE_OBJ
+ Q_ASSERT(index >= 0 && index < rowCount());
+ return m_pages.at(index);
+}
+
+void OpenPagesModel::handleTitleChanged()
+{
+ TRACE_OBJ
+ HelpViewer *page = static_cast<HelpViewer *>(sender());
+ const int row = m_pages.indexOf(page);
+ Q_ASSERT(row != -1 );
+ const QModelIndex &item = index(row, 0);
+ emit dataChanged(item, item);
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/openpagesmodel.h b/src/assistant/tools/assistant/openpagesmodel.h
new file mode 100644
index 000000000..dd28a7c5f
--- /dev/null
+++ b/src/assistant/tools/assistant/openpagesmodel.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** 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 Assistant module 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$
+**
+****************************************************************************/
+
+#ifndef OPENPAGESMODEL_H
+#define OPENPAGESMODEL_H
+
+#include <QtCore/QAbstractTableModel>
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+
+class HelpViewer;
+class QUrl;
+
+class OpenPagesModel : public QAbstractTableModel
+{
+ Q_OBJECT
+public:
+ OpenPagesModel(QObject *parent);
+
+ virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+ void addPage(const QUrl &url, qreal zoom = 0);
+ void removePage(int index);
+ HelpViewer *pageAt(int index) const;
+
+private slots:
+ void handleTitleChanged();
+
+private:
+ QList<HelpViewer *> m_pages;
+};
+
+QT_END_NAMESPACE
+
+#endif // OPENPAGESMODEL_H
diff --git a/src/assistant/tools/assistant/openpagesswitcher.cpp b/src/assistant/tools/assistant/openpagesswitcher.cpp
new file mode 100644
index 000000000..8e7f29bf0
--- /dev/null
+++ b/src/assistant/tools/assistant/openpagesswitcher.cpp
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** 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 Assistant module 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 "openpagesswitcher.h"
+
+#include "centralwidget.h"
+#include "openpagesmodel.h"
+#include "openpageswidget.h"
+#include "tracer.h"
+
+#include <QtCore/QEvent>
+
+#include <QtGui/QKeyEvent>
+#include <QtGui/QVBoxLayout>
+
+QT_BEGIN_NAMESPACE
+
+const int gWidth = 300;
+const int gHeight = 200;
+
+OpenPagesSwitcher::OpenPagesSwitcher(OpenPagesModel *model)
+ : QFrame(0, Qt::Popup)
+ , m_openPagesModel(model)
+{
+ TRACE_OBJ
+ resize(gWidth, gHeight);
+
+ m_openPagesWidget = new OpenPagesWidget(m_openPagesModel);
+
+ // We disable the frame on this list view and use a QFrame around it instead.
+ // This improves the look with QGTKStyle.
+#ifndef Q_WS_MAC
+ setFrameStyle(m_openPagesWidget->frameStyle());
+#endif
+ m_openPagesWidget->setFrameStyle(QFrame::NoFrame);
+
+ m_openPagesWidget->allowContextMenu(false);
+ m_openPagesWidget->installEventFilter(this);
+
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->setMargin(0);
+ layout->addWidget(m_openPagesWidget);
+
+ connect(m_openPagesWidget, SIGNAL(closePage(QModelIndex)), this,
+ SIGNAL(closePage(QModelIndex)));
+ connect(m_openPagesWidget, SIGNAL(setCurrentPage(QModelIndex)), this,
+ SIGNAL(setCurrentPage(QModelIndex)));
+}
+
+OpenPagesSwitcher::~OpenPagesSwitcher()
+{
+ TRACE_OBJ
+}
+
+void OpenPagesSwitcher::gotoNextPage()
+{
+ TRACE_OBJ
+ selectPageUpDown(1);
+}
+
+void OpenPagesSwitcher::gotoPreviousPage()
+{
+ TRACE_OBJ
+ selectPageUpDown(-1);
+}
+
+void OpenPagesSwitcher::selectAndHide()
+{
+ TRACE_OBJ
+ setVisible(false);
+ emit setCurrentPage(m_openPagesWidget->currentIndex());
+}
+
+void OpenPagesSwitcher::selectCurrentPage()
+{
+ TRACE_OBJ
+ m_openPagesWidget->selectCurrentPage();
+}
+
+void OpenPagesSwitcher::setVisible(bool visible)
+{
+ TRACE_OBJ
+ QWidget::setVisible(visible);
+ if (visible)
+ setFocus();
+}
+
+void OpenPagesSwitcher::focusInEvent(QFocusEvent *event)
+{
+ TRACE_OBJ
+ Q_UNUSED(event)
+ m_openPagesWidget->setFocus();
+}
+
+bool OpenPagesSwitcher::eventFilter(QObject *object, QEvent *event)
+{
+ TRACE_OBJ
+ if (object == m_openPagesWidget) {
+ if (event->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(event);
+ if (ke->key() == Qt::Key_Escape) {
+ setVisible(false);
+ return true;
+ }
+
+ const int key = ke->key();
+ if (key == Qt::Key_Return || key == Qt::Key_Enter || key == Qt::Key_Space) {
+ emit setCurrentPage(m_openPagesWidget->currentIndex());
+ return true;
+ }
+
+ Qt::KeyboardModifier modifier = Qt::ControlModifier;
+#ifdef Q_WS_MAC
+ modifier = Qt::AltModifier;
+#endif
+ if (key == Qt::Key_Backtab
+ && (ke->modifiers() == (modifier | Qt::ShiftModifier)))
+ gotoPreviousPage();
+ else if (key == Qt::Key_Tab && (ke->modifiers() == modifier))
+ gotoNextPage();
+ } else if (event->type() == QEvent::KeyRelease) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(event);
+ if (ke->modifiers() == 0
+ /*HACK this is to overcome some event inconsistencies between platforms*/
+ || (ke->modifiers() == Qt::AltModifier
+ && (ke->key() == Qt::Key_Alt || ke->key() == -1))) {
+ selectAndHide();
+ }
+ }
+ }
+ return QWidget::eventFilter(object, event);
+}
+
+void OpenPagesSwitcher::selectPageUpDown(int summand)
+{
+ TRACE_OBJ
+ const int pageCount = m_openPagesModel->rowCount();
+ if (pageCount < 2)
+ return;
+
+ const QModelIndexList &list = m_openPagesWidget->selectionModel()->selectedIndexes();
+ if (list.isEmpty())
+ return;
+
+ QModelIndex index = list.first();
+ if (!index.isValid())
+ return;
+
+ index = m_openPagesModel->index((index.row() + summand + pageCount) % pageCount, 0);
+ if (index.isValid()) {
+ m_openPagesWidget->setCurrentIndex(index);
+ m_openPagesWidget->scrollTo(index, QAbstractItemView::PositionAtCenter);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/openpagesswitcher.h b/src/assistant/tools/assistant/openpagesswitcher.h
new file mode 100644
index 000000000..80c7e965d
--- /dev/null
+++ b/src/assistant/tools/assistant/openpagesswitcher.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** 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 Assistant module 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$
+**
+****************************************************************************/
+
+#ifndef OPENPAGESSWITCHER_H
+#define OPENPAGESSWITCHER_H
+
+#include <QtGui/QFrame>
+
+QT_BEGIN_NAMESPACE
+
+class OpenPagesModel;
+class OpenPagesWidget;
+class QModelIndex;
+
+class OpenPagesSwitcher : public QFrame
+{
+ Q_OBJECT
+
+public:
+ OpenPagesSwitcher(OpenPagesModel *model);
+ ~OpenPagesSwitcher();
+
+ void gotoNextPage();
+ void gotoPreviousPage();
+
+ void selectAndHide();
+ void selectCurrentPage();
+
+ void setVisible(bool visible);
+ void focusInEvent(QFocusEvent *event);
+ bool eventFilter(QObject *object, QEvent *event);
+
+signals:
+ void closePage(const QModelIndex &index);
+ void setCurrentPage(const QModelIndex &index);
+
+private:
+ void selectPageUpDown(int summand);
+
+private:
+ OpenPagesModel *m_openPagesModel;
+ OpenPagesWidget *m_openPagesWidget;
+};
+
+QT_END_NAMESPACE
+
+#endif // OPENPAGESSWITCHER_H
diff --git a/src/assistant/tools/assistant/openpageswidget.cpp b/src/assistant/tools/assistant/openpageswidget.cpp
new file mode 100644
index 000000000..db037125b
--- /dev/null
+++ b/src/assistant/tools/assistant/openpageswidget.cpp
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** 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 Assistant module 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 "openpageswidget.h"
+
+#include "centralwidget.h"
+#include "openpagesmodel.h"
+#include "tracer.h"
+
+#include <QtGui/QApplication>
+#include <QtGui/QHeaderView>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QMenu>
+#include <QtGui/QPainter>
+
+#ifdef Q_WS_MAC
+#include <qmacstyle_mac.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+OpenPagesDelegate::OpenPagesDelegate(QObject *parent)
+ : QStyledItemDelegate(parent)
+{
+ TRACE_OBJ
+}
+
+void OpenPagesDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ TRACE_OBJ
+ if (option.state & QStyle::State_MouseOver) {
+ if ((QApplication::mouseButtons() & Qt::LeftButton) == 0)
+ pressedIndex = QModelIndex();
+ QBrush brush = option.palette.alternateBase();
+ if (index == pressedIndex)
+ brush = option.palette.dark();
+ painter->fillRect(option.rect, brush);
+ }
+
+ QStyledItemDelegate::paint(painter, option, index);
+
+ if (index.column() == 1 && index.model()->rowCount() > 1
+ && option.state & QStyle::State_MouseOver) {
+ QIcon icon((option.state & QStyle::State_Selected)
+ ? ":/trolltech/assistant/images/closebutton.png"
+ : ":/trolltech/assistant/images/darkclosebutton.png");
+
+ const QRect iconRect(option.rect.right() - option.rect.height(),
+ option.rect.top(), option.rect.height(), option.rect.height());
+ icon.paint(painter, iconRect, Qt::AlignRight | Qt::AlignVCenter);
+ }
+}
+
+// -- OpenPagesWidget
+
+OpenPagesWidget::OpenPagesWidget(OpenPagesModel *model)
+ : m_allowContextMenu(true)
+{
+ TRACE_OBJ
+ setModel(model);
+ setIndentation(0);
+ setItemDelegate((m_delegate = new OpenPagesDelegate(this)));
+
+ setTextElideMode(Qt::ElideMiddle);
+ setAttribute(Qt::WA_MacShowFocusRect, false);
+
+ viewport()->setAttribute(Qt::WA_Hover);
+ setSelectionBehavior(QAbstractItemView::SelectRows);
+ setSelectionMode(QAbstractItemView::SingleSelection);
+
+ header()->hide();
+ header()->setStretchLastSection(false);
+ header()->setResizeMode(0, QHeaderView::Stretch);
+ header()->setResizeMode(1, QHeaderView::Fixed);
+ header()->resizeSection(1, 18);
+
+ installEventFilter(this);
+ setUniformRowHeights(true);
+ setContextMenuPolicy(Qt::CustomContextMenu);
+
+ connect(this, SIGNAL(clicked(QModelIndex)), this,
+ SLOT(handleClicked(QModelIndex)));
+ connect(this, SIGNAL(pressed(QModelIndex)), this,
+ SLOT(handlePressed(QModelIndex)));
+ connect(this, SIGNAL(customContextMenuRequested(QPoint)), this,
+ SLOT(contextMenuRequested(QPoint)));
+}
+
+OpenPagesWidget::~OpenPagesWidget()
+{
+ TRACE_OBJ
+}
+
+void OpenPagesWidget::selectCurrentPage()
+{
+ TRACE_OBJ
+ const QModelIndex &current =
+ model()->index(CentralWidget::instance()->currentIndex(), 0);
+
+ QItemSelectionModel * const selModel = selectionModel();
+ selModel->select(current,
+ QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
+ selModel->clearSelection();
+
+ setCurrentIndex(current);
+ scrollTo(currentIndex());
+}
+
+void OpenPagesWidget::allowContextMenu(bool ok)
+{
+ TRACE_OBJ
+ m_allowContextMenu = ok;
+}
+
+void OpenPagesWidget::contextMenuRequested(QPoint pos)
+{
+ TRACE_OBJ
+ QModelIndex index = indexAt(pos);
+ if (!index.isValid() || !m_allowContextMenu)
+ return;
+
+ if (index.column() == 1)
+ index = index.sibling(index.row(), 0);
+ QMenu contextMenu;
+ QAction *closeEditor = contextMenu.addAction(tr("Close %1").arg(index.data()
+ .toString()));
+ QAction *closeOtherEditors = contextMenu.addAction(tr("Close All Except %1")
+ .arg(index.data().toString()));
+
+ if (model()->rowCount() == 1) {
+ closeEditor->setEnabled(false);
+ closeOtherEditors->setEnabled(false);
+ }
+
+ QAction *action = contextMenu.exec(mapToGlobal(pos));
+ if (action == closeEditor)
+ emit closePage(index);
+ else if (action == closeOtherEditors)
+ emit closePagesExcept(index);
+}
+
+void OpenPagesWidget::handlePressed(const QModelIndex &index)
+{
+ TRACE_OBJ
+ if (index.column() == 0)
+ emit setCurrentPage(index);
+
+ if (index.column() == 1)
+ m_delegate->pressedIndex = index;
+}
+
+void OpenPagesWidget::handleClicked(const QModelIndex &index)
+{
+ TRACE_OBJ
+ // implemented here to handle the funky close button and to work around a
+ // bug in item views where the delegate wouldn't get the QStyle::State_MouseOver
+ if (index.column() == 1) {
+ if (model()->rowCount() > 1)
+ emit closePage(index);
+
+ QWidget *vp = viewport();
+ const QPoint &cursorPos = QCursor::pos();
+ QMouseEvent e(QEvent::MouseMove, vp->mapFromGlobal(cursorPos), cursorPos,
+ Qt::NoButton, 0, 0);
+ QCoreApplication::sendEvent(vp, &e);
+ }
+}
+
+bool OpenPagesWidget::eventFilter(QObject *obj, QEvent *event)
+{
+ TRACE_OBJ
+ if (obj != this)
+ return QWidget::eventFilter(obj, event);
+
+ if (event->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(event);
+ if (currentIndex().isValid() && ke->modifiers() == 0) {
+ const int key = ke->key();
+ if (key == Qt::Key_Return || key == Qt::Key_Enter
+ || key == Qt::Key_Space) {
+ emit setCurrentPage(currentIndex());
+ } else if ((key == Qt::Key_Delete || key == Qt::Key_Backspace)
+ && model()->rowCount() > 1) {
+ emit closePage(currentIndex());
+ }
+ }
+ } else if (event->type() == QEvent::KeyRelease) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(event);
+ if (ke->modifiers() == 0
+ && (ke->key() == Qt::Key_Up || ke->key() == Qt::Key_Down)) {
+ emit setCurrentPage(currentIndex());
+ }
+ }
+ return QWidget::eventFilter(obj, event);
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/openpageswidget.h b/src/assistant/tools/assistant/openpageswidget.h
new file mode 100644
index 000000000..6041fe22d
--- /dev/null
+++ b/src/assistant/tools/assistant/openpageswidget.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** 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 Assistant module 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$
+**
+****************************************************************************/
+
+#ifndef OPENPAGESWIDGET_H
+#define OPENPAGESWIDGET_H
+
+#include <QtGui/QStyledItemDelegate>
+#include <QtGui/QTreeView>
+
+QT_BEGIN_NAMESPACE
+
+class OpenPagesModel;
+
+class OpenPagesDelegate : public QStyledItemDelegate
+{
+ Q_OBJECT
+public:
+ explicit OpenPagesDelegate(QObject *parent = 0);
+ void paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+
+ mutable QModelIndex pressedIndex;
+};
+
+class OpenPagesWidget : public QTreeView
+{
+ Q_OBJECT
+public:
+ OpenPagesWidget(OpenPagesModel *model);
+ ~OpenPagesWidget();
+
+ void selectCurrentPage();
+ void allowContextMenu(bool ok);
+
+signals:
+ void setCurrentPage(const QModelIndex &index);
+ void closePage(const QModelIndex &index);
+ void closePagesExcept(const QModelIndex &index);
+
+private slots:
+ void contextMenuRequested(QPoint pos);
+ void handlePressed(const QModelIndex &index);
+ void handleClicked(const QModelIndex &index);
+
+private:
+ bool eventFilter(QObject *obj, QEvent *event);
+
+ bool m_allowContextMenu;
+ OpenPagesDelegate *m_delegate;
+};
+
+QT_END_NAMESPACE
+
+#endif // OPENPAGESWIDGET_H
diff --git a/src/assistant/tools/assistant/preferencesdialog.cpp b/src/assistant/tools/assistant/preferencesdialog.cpp
new file mode 100644
index 000000000..9bfd35c00
--- /dev/null
+++ b/src/assistant/tools/assistant/preferencesdialog.cpp
@@ -0,0 +1,507 @@
+/****************************************************************************
+**
+** 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 "preferencesdialog.h"
+
+#include "centralwidget.h"
+#include "filternamedialog.h"
+#include "fontpanel.h"
+#include "helpenginewrapper.h"
+#include "installdialog.h"
+#include "openpagesmanager.h"
+#include "tracer.h"
+
+#include <QtCore/QtAlgorithms>
+#include <QtCore/QFileSystemWatcher>
+
+#include <QtGui/QDesktopWidget>
+#include <QtGui/QFileDialog>
+#include <QtGui/QFontDatabase>
+#include <QtGui/QHeaderView>
+#include <QtGui/QMenu>
+#include <QtGui/QMessageBox>
+
+#include <QtHelp/QHelpEngineCore>
+
+QT_BEGIN_NAMESPACE
+
+PreferencesDialog::PreferencesDialog(QWidget *parent)
+ : QDialog(parent)
+ , m_appFontChanged(false)
+ , m_browserFontChanged(false)
+ , helpEngine(HelpEngineWrapper::instance())
+{
+ TRACE_OBJ
+ m_ui.setupUi(this);
+
+ connect(m_ui.buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()),
+ this, SLOT(applyChanges()));
+ connect(m_ui.buttonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()),
+ this, SLOT(reject()));
+
+ m_hideFiltersTab = !helpEngine.filterFunctionalityEnabled();
+ m_hideDocsTab = !helpEngine.documentationManagerEnabled();
+
+ if (!m_hideFiltersTab) {
+ m_ui.attributeWidget->header()->hide();
+ m_ui.attributeWidget->setRootIsDecorated(false);
+
+ connect(m_ui.attributeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
+ this, SLOT(updateFilterMap()));
+
+ connect(m_ui.filterWidget,
+ SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), this,
+ SLOT(updateAttributes(QListWidgetItem*)));
+
+ connect(m_ui.filterAddButton, SIGNAL(clicked()), this,
+ SLOT(addFilter()));
+ connect(m_ui.filterRemoveButton, SIGNAL(clicked()), this,
+ SLOT(removeFilter()));
+
+ updateFilterPage();
+ } else {
+ m_ui.tabWidget->removeTab(m_ui.tabWidget->indexOf(m_ui.filtersTab));
+ }
+
+ if (!m_hideDocsTab) {
+ connect(m_ui.docAddButton, SIGNAL(clicked()), this,
+ SLOT(addDocumentationLocal()));
+ connect(m_ui.docRemoveButton, SIGNAL(clicked()), this,
+ SLOT(removeDocumentation()));
+
+ m_docsBackup = helpEngine.registeredDocumentations();
+ m_ui.registeredDocsListWidget->addItems(m_docsBackup);
+ } else {
+ m_ui.tabWidget->removeTab(m_ui.tabWidget->indexOf(m_ui.docsTab));
+ }
+
+ updateFontSettingsPage();
+ updateOptionsPage();
+
+ if (helpEngine.usesAppFont())
+ setFont(helpEngine.appFont());
+}
+
+PreferencesDialog::~PreferencesDialog()
+{
+ TRACE_OBJ
+ if (m_appFontChanged) {
+ helpEngine.setAppFont(m_appFontPanel->selectedFont());
+ helpEngine.setUseAppFont(m_appFontPanel->isChecked());
+ helpEngine.setAppWritingSystem(m_appFontPanel->writingSystem());
+ emit updateApplicationFont();
+ }
+
+ if (m_browserFontChanged) {
+ helpEngine.setBrowserFont(m_browserFontPanel->selectedFont());
+ helpEngine.setUseBrowserFont(m_browserFontPanel->isChecked());
+ helpEngine.setBrowserWritingSystem(m_browserFontPanel->writingSystem());
+ emit updateBrowserFont();
+ }
+
+ QString homePage = m_ui.homePageLineEdit->text();
+ if (homePage.isEmpty())
+ homePage = QLatin1String("help");
+ helpEngine.setHomePage(homePage);
+
+ int option = m_ui.helpStartComboBox->currentIndex();
+ helpEngine.setStartOption(option);
+}
+
+void PreferencesDialog::showDialog()
+{
+ TRACE_OBJ
+ if (exec() != Accepted)
+ m_appFontChanged = m_browserFontChanged = false;
+}
+
+void PreferencesDialog::updateFilterPage()
+{
+ TRACE_OBJ
+ m_ui.filterWidget->clear();
+ m_ui.attributeWidget->clear();
+
+ m_filterMapBackup.clear();
+ const QStringList &filters = helpEngine.customFilters();
+ foreach (const QString &filter, filters) {
+ if (filter == HelpEngineWrapper::TrUnfiltered)
+ continue;
+ QStringList atts = helpEngine.filterAttributes(filter);
+ m_filterMapBackup.insert(filter, atts);
+ if (!m_filterMap.contains(filter))
+ m_filterMap.insert(filter, atts);
+ }
+
+ m_ui.filterWidget->addItems(m_filterMap.keys());
+
+ foreach (const QString &a, helpEngine.filterAttributes())
+ new QTreeWidgetItem(m_ui.attributeWidget, QStringList() << a);
+
+ if (!m_filterMap.keys().isEmpty())
+ m_ui.filterWidget->setCurrentRow(0);
+}
+
+void PreferencesDialog::updateAttributes(QListWidgetItem *item)
+{
+ TRACE_OBJ
+ QStringList checkedList;
+ if (item)
+ checkedList = m_filterMap.value(item->text());
+ QTreeWidgetItem *itm;
+ for (int i = 0; i < m_ui.attributeWidget->topLevelItemCount(); ++i) {
+ itm = m_ui.attributeWidget->topLevelItem(i);
+ if (checkedList.contains(itm->text(0)))
+ itm->setCheckState(0, Qt::Checked);
+ else
+ itm->setCheckState(0, Qt::Unchecked);
+ }
+}
+
+void PreferencesDialog::updateFilterMap()
+{
+ TRACE_OBJ
+ if (!m_ui.filterWidget->currentItem())
+ return;
+ QString filter = m_ui.filterWidget->currentItem()->text();
+ if (!m_filterMap.contains(filter))
+ return;
+
+ QStringList newAtts;
+ QTreeWidgetItem *itm = 0;
+ for (int i = 0; i < m_ui.attributeWidget->topLevelItemCount(); ++i) {
+ itm = m_ui.attributeWidget->topLevelItem(i);
+ if (itm->checkState(0) == Qt::Checked)
+ newAtts.append(itm->text(0));
+ }
+ m_filterMap[filter] = newAtts;
+}
+
+void PreferencesDialog::addFilter()
+{
+ TRACE_OBJ
+ FilterNameDialog dia(this);
+ if (dia.exec() == QDialog::Rejected)
+ return;
+
+ QString filterName = dia.filterName();
+ if (!m_filterMap.contains(filterName)) {
+ m_filterMap.insert(filterName, QStringList());
+ m_ui.filterWidget->addItem(filterName);
+ }
+
+ QList<QListWidgetItem*> lst = m_ui.filterWidget
+ ->findItems(filterName, Qt::MatchCaseSensitive);
+ m_ui.filterWidget->setCurrentItem(lst.first());
+}
+
+void PreferencesDialog::removeFilter()
+{
+ TRACE_OBJ
+ QListWidgetItem *item =
+ m_ui.filterWidget ->takeItem(m_ui.filterWidget->currentRow());
+ if (!item)
+ return;
+
+ m_filterMap.remove(item->text());
+ m_removedFilters.append(item->text());
+ delete item;
+ if (m_ui.filterWidget->count())
+ m_ui.filterWidget->setCurrentRow(0);
+}
+
+void PreferencesDialog::addDocumentationLocal()
+{
+ TRACE_OBJ
+ const QStringList fileNames = QFileDialog::getOpenFileNames(this,
+ tr("Add Documentation"), QString(), tr("Qt Compressed Help Files (*.qch)"));
+ if (fileNames.isEmpty())
+ return;
+
+ QStringList invalidFiles;
+ QStringList alreadyRegistered;
+ foreach (const QString &fileName, fileNames) {
+ const QString nameSpace = QHelpEngineCore::namespaceName(fileName);
+ if (nameSpace.isEmpty()) {
+ invalidFiles.append(fileName);
+ continue;
+ }
+
+ if (m_ui.registeredDocsListWidget->findItems(nameSpace,
+ Qt::MatchFixedString).count()) {
+ alreadyRegistered.append(nameSpace);
+ continue;
+ }
+
+ if (helpEngine.registerDocumentation(fileName)) {
+ m_ui.registeredDocsListWidget->addItem(nameSpace);
+ m_regDocs.append(nameSpace);
+ m_unregDocs.removeAll(nameSpace);
+ }
+ }
+
+ if (!invalidFiles.isEmpty() || !alreadyRegistered.isEmpty()) {
+ QString message;
+ if (!alreadyRegistered.isEmpty()) {
+ foreach (const QString &ns, alreadyRegistered) {
+ message += tr("The namespace %1 is already registered!")
+ .arg(QString("<b>%1</b>").arg(ns)) + QLatin1String("<br>");
+ }
+ if (!invalidFiles.isEmpty())
+ message.append(QLatin1String("<br>"));
+ }
+
+ if (!invalidFiles.isEmpty()) {
+ message += tr("The specified file is not a valid Qt Help File!");
+ message.append(QLatin1String("<ul>"));
+ foreach (const QString &file, invalidFiles)
+ message += QLatin1String("<li>") + file + QLatin1String("</li>");
+ message.append(QLatin1String("</ul>"));
+ }
+ QMessageBox::warning(this, tr("Add Documentation"), message);
+ }
+
+ updateFilterPage();
+}
+
+void PreferencesDialog::removeDocumentation()
+{
+ TRACE_OBJ
+
+ bool foundBefore = false;
+ QList<QListWidgetItem*> l = m_ui.registeredDocsListWidget->selectedItems();
+ foreach (QListWidgetItem* item, l) {
+ const QString& ns = item->text();
+ if (!foundBefore && OpenPagesManager::instance()->pagesOpenForNamespace(ns)) {
+ if (0 == QMessageBox::information(this, tr("Remove Documentation"),
+ tr("Some documents currently opened in Assistant reference the "
+ "documentation you are attempting to remove. Removing the "
+ "documentation will close those documents."), tr("Cancel"),
+ tr("OK"))) return;
+ foundBefore = true;
+ }
+
+ m_unregDocs.append(ns);
+ delete m_ui.registeredDocsListWidget->takeItem(
+ m_ui.registeredDocsListWidget->row(item));
+ }
+
+ if (m_ui.registeredDocsListWidget->count()) {
+ m_ui.registeredDocsListWidget->setCurrentRow(0,
+ QItemSelectionModel::ClearAndSelect);
+ }
+}
+
+void PreferencesDialog::applyChanges()
+{
+ TRACE_OBJ
+ bool filtersWereChanged = false;
+ if (!m_hideFiltersTab) {
+ if (m_filterMap.count() != m_filterMapBackup.count()) {
+ filtersWereChanged = true;
+ } else {
+ QMapIterator<QString, QStringList> it(m_filterMapBackup);
+ while (it.hasNext() && !filtersWereChanged) {
+ it.next();
+ if (!m_filterMap.contains(it.key())) {
+ filtersWereChanged = true;
+ } else {
+ QStringList a = it.value();
+ QStringList b = m_filterMap.value(it.key());
+ if (a.count() != b.count()) {
+ filtersWereChanged = true;
+ } else {
+ QStringList::const_iterator i(a.constBegin());
+ while (i != a.constEnd()) {
+ if (!b.contains(*i)) {
+ filtersWereChanged = true;
+ break;
+ }
+ ++i;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (filtersWereChanged) {
+ foreach (const QString &filter, m_removedFilters)
+ helpEngine.removeCustomFilter(filter);
+ QMapIterator<QString, QStringList> it(m_filterMap);
+ while (it.hasNext()) {
+ it.next();
+ helpEngine.addCustomFilter(it.key(), it.value());
+ }
+ }
+
+ foreach (const QString &doc, m_unregDocs) {
+ OpenPagesManager::instance()->closePages(doc);
+ helpEngine.unregisterDocumentation(doc);
+ }
+
+ if (filtersWereChanged || !m_regDocs.isEmpty() || !m_unregDocs.isEmpty())
+ helpEngine.setupData();
+
+ helpEngine.setShowTabs(m_ui.showTabs->isChecked());
+ if (m_showTabs != m_ui.showTabs->isChecked())
+ emit updateUserInterface();
+
+ accept();
+}
+
+void PreferencesDialog::updateFontSettingsPage()
+{
+ TRACE_OBJ
+ m_browserFontPanel = new FontPanel(this);
+ m_browserFontPanel->setCheckable(true);
+ m_ui.stackedWidget_2->insertWidget(0, m_browserFontPanel);
+
+ m_appFontPanel = new FontPanel(this);
+ m_appFontPanel->setCheckable(true);
+ m_ui.stackedWidget_2->insertWidget(1, m_appFontPanel);
+
+ m_ui.stackedWidget_2->setCurrentIndex(0);
+
+ const QString customSettings(tr("Use custom settings"));
+ m_appFontPanel->setTitle(customSettings);
+
+ QFont font = helpEngine.appFont();
+ m_appFontPanel->setSelectedFont(font);
+
+ QFontDatabase::WritingSystem system = helpEngine.appWritingSystem();
+ m_appFontPanel->setWritingSystem(system);
+
+ m_appFontPanel->setChecked(helpEngine.usesAppFont());
+
+ m_browserFontPanel->setTitle(customSettings);
+
+ font = helpEngine.browserFont();
+ m_browserFontPanel->setSelectedFont(font);
+
+ system = helpEngine.browserWritingSystem();
+ m_browserFontPanel->setWritingSystem(system);
+
+ m_browserFontPanel->setChecked(helpEngine.usesBrowserFont());
+
+ connect(m_appFontPanel, SIGNAL(toggled(bool)), this,
+ SLOT(appFontSettingToggled(bool)));
+ connect(m_browserFontPanel, SIGNAL(toggled(bool)), this,
+ SLOT(browserFontSettingToggled(bool)));
+
+ QList<QComboBox*> allCombos = m_appFontPanel->findChildren<QComboBox*>();
+ foreach (QComboBox* box, allCombos) {
+ connect(box, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(appFontSettingChanged(int)));
+ }
+
+ allCombos = m_browserFontPanel->findChildren<QComboBox*>();
+ foreach (QComboBox* box, allCombos) {
+ connect(box, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(browserFontSettingChanged(int)));
+ }
+}
+
+void PreferencesDialog::appFontSettingToggled(bool on)
+{
+ TRACE_OBJ
+ Q_UNUSED(on)
+ m_appFontChanged = true;
+}
+
+void PreferencesDialog::appFontSettingChanged(int index)
+{
+ TRACE_OBJ
+ Q_UNUSED(index)
+ m_appFontChanged = true;
+}
+
+void PreferencesDialog::browserFontSettingToggled(bool on)
+{
+ TRACE_OBJ
+ Q_UNUSED(on)
+ m_browserFontChanged = true;
+}
+
+void PreferencesDialog::browserFontSettingChanged(int index)
+{
+ TRACE_OBJ
+ Q_UNUSED(index)
+ m_browserFontChanged = true;
+}
+
+void PreferencesDialog::updateOptionsPage()
+{
+ TRACE_OBJ
+ m_ui.homePageLineEdit->setText(helpEngine.homePage());
+
+ int option = helpEngine.startOption();
+ m_ui.helpStartComboBox->setCurrentIndex(option);
+
+ m_showTabs = helpEngine.showTabs();
+ m_ui.showTabs->setChecked(m_showTabs);
+
+ connect(m_ui.blankPageButton, SIGNAL(clicked()), this, SLOT(setBlankPage()));
+ connect(m_ui.currentPageButton, SIGNAL(clicked()), this, SLOT(setCurrentPage()));
+ connect(m_ui.defaultPageButton, SIGNAL(clicked()), this, SLOT(setDefaultPage()));
+}
+
+void PreferencesDialog::setBlankPage()
+{
+ TRACE_OBJ
+ m_ui.homePageLineEdit->setText(QLatin1String("about:blank"));
+}
+
+void PreferencesDialog::setCurrentPage()
+{
+ TRACE_OBJ
+ QString homepage = CentralWidget::instance()->currentSource().toString();
+ if (homepage.isEmpty())
+ homepage = QLatin1String("help");
+
+ m_ui.homePageLineEdit->setText(homepage);
+}
+
+void PreferencesDialog::setDefaultPage()
+{
+ TRACE_OBJ
+ m_ui.homePageLineEdit->setText(helpEngine.defaultHomePage());
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/preferencesdialog.h b/src/assistant/tools/assistant/preferencesdialog.h
new file mode 100644
index 000000000..f9b445e72
--- /dev/null
+++ b/src/assistant/tools/assistant/preferencesdialog.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef PREFERENCESDIALOG_H
+#define PREFERENCESDIALOG_H
+
+#include <QtGui/QDialog>
+#include "ui_preferencesdialog.h"
+
+QT_BEGIN_NAMESPACE
+
+class FontPanel;
+class HelpEngineWrapper;
+class QFileSystemWatcher;
+
+class PreferencesDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ PreferencesDialog(QWidget *parent = 0);
+ ~PreferencesDialog();
+
+ void showDialog();
+
+private slots:
+ void updateAttributes(QListWidgetItem *item);
+ void updateFilterMap();
+ void addFilter();
+ void removeFilter();
+ void addDocumentationLocal();
+ void removeDocumentation();
+ void applyChanges();
+ void appFontSettingToggled(bool on);
+ void appFontSettingChanged(int index);
+ void browserFontSettingToggled(bool on);
+ void browserFontSettingChanged(int index);
+
+ void setBlankPage();
+ void setCurrentPage();
+ void setDefaultPage();
+
+signals:
+ void updateBrowserFont();
+ void updateApplicationFont();
+ void updateUserInterface();
+
+private:
+ void updateFilterPage();
+ void updateFontSettingsPage();
+ void updateOptionsPage();
+
+ Ui::PreferencesDialogClass m_ui;
+ bool m_hideFiltersTab;
+ bool m_hideDocsTab;
+ QMap<QString, QStringList> m_filterMapBackup;
+ QMap<QString, QStringList> m_filterMap;
+ QStringList m_removedFilters;
+ QStringList m_docsBackup;
+ QStringList m_regDocs;
+ QStringList m_unregDocs;
+ FontPanel *m_appFontPanel;
+ FontPanel *m_browserFontPanel;
+ bool m_appFontChanged;
+ bool m_browserFontChanged;
+ HelpEngineWrapper &helpEngine;
+ bool m_showTabs;
+};
+
+QT_END_NAMESPACE
+
+#endif // SETTINGSDIALOG_H
diff --git a/src/assistant/tools/assistant/preferencesdialog.ui b/src/assistant/tools/assistant/preferencesdialog.ui
new file mode 100644
index 000000000..1c6833ad9
--- /dev/null
+++ b/src/assistant/tools/assistant/preferencesdialog.ui
@@ -0,0 +1,400 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PreferencesDialogClass</class>
+ <widget class="QDialog" name="PreferencesDialogClass">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>375</width>
+ <height>275</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Preferences</string>
+ </property>
+ <layout class="QVBoxLayout">
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="fontsTab">
+ <attribute name="title">
+ <string>Fonts</string>
+ </attribute>
+ <layout class="QGridLayout">
+ <item row="0" column="0">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLabel" name="fontLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Font settings:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="comboBox">
+ <item>
+ <property name="text">
+ <string>Browser</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Application</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0">
+ <widget class="QStackedWidget" name="stackedWidget_2">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="page_4"/>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="filtersTab">
+ <attribute name="title">
+ <string>Filters</string>
+ </attribute>
+ <layout class="QGridLayout">
+ <item row="0" column="0" colspan="2">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Filter:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="label_2">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="text">
+ <string>Attributes:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="QListWidget" name="filterWidget"/>
+ </item>
+ <item row="1" column="2" rowspan="2">
+ <widget class="QTreeWidget" name="attributeWidget">
+ <column>
+ <property name="text">
+ <string>1</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QPushButton" name="filterAddButton">
+ <property name="text">
+ <string>Add</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QPushButton" name="filterRemoveButton">
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="docsTab">
+ <attribute name="title">
+ <string>Documentation</string>
+ </attribute>
+ <layout class="QVBoxLayout">
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Registered Documentation:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QListWidget" name="registeredDocsListWidget">
+ <property name="selectionMode">
+ <enum>QAbstractItemView::ExtendedSelection</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="docAddButton">
+ <property name="text">
+ <string>Add...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="docRemoveButton">
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="optionsTab">
+ <attribute name="title">
+ <string>Options</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string/>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLabel" name="label_5">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>On help start:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="helpStartComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <item>
+ <property name="text">
+ <string>Show my home page</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Show a blank page</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Show my tabs from last session</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>54</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string/>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Homepage</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="homePageLineEdit"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="currentPageButton">
+ <property name="text">
+ <string>Current Page</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="blankPageButton">
+ <property name="text">
+ <string>Blank Page</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="defaultPageButton">
+ <property name="text">
+ <string>Restore to default</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_3">
+ <property name="title">
+ <string>Appearance</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QCheckBox" name="showTabs">
+ <property name="text">
+ <string>Show tabs for each individual page</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>72</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>comboBox</sender>
+ <signal>currentIndexChanged(int)</signal>
+ <receiver>stackedWidget_2</receiver>
+ <slot>setCurrentIndex(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>375</x>
+ <y>32</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>347</x>
+ <y>125</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/assistant/tools/assistant/qtdocinstaller.cpp b/src/assistant/tools/assistant/qtdocinstaller.cpp
new file mode 100644
index 000000000..ffe352c87
--- /dev/null
+++ b/src/assistant/tools/assistant/qtdocinstaller.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** 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 "tracer.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QDateTime>
+#include <QtCore/QFileSystemWatcher>
+#include <QtHelp/QHelpEngineCore>
+#include "helpenginewrapper.h"
+#include "qtdocinstaller.h"
+
+QT_BEGIN_NAMESPACE
+
+QtDocInstaller::QtDocInstaller(const QList<DocInfo> &docInfos)
+ : m_abort(false), m_docInfos(docInfos)
+{
+ TRACE_OBJ
+}
+
+QtDocInstaller::~QtDocInstaller()
+{
+ TRACE_OBJ
+ if (!isRunning())
+ return;
+ m_mutex.lock();
+ m_abort = true;
+ m_mutex.unlock();
+ wait();
+}
+
+void QtDocInstaller::installDocs()
+{
+ TRACE_OBJ
+ start(LowPriority);
+}
+
+void QtDocInstaller::run()
+{
+ TRACE_OBJ
+ m_qchDir = QLibraryInfo::location(QLibraryInfo::DocumentationPath)
+ + QDir::separator() + QLatin1String("qch");
+ m_qchFiles = m_qchDir.entryList(QStringList() << QLatin1String("*.qch"));
+
+ bool changes = false;
+ foreach (const DocInfo &docInfo, m_docInfos) {
+ changes |= installDoc(docInfo);
+ m_mutex.lock();
+ if (m_abort) {
+ m_mutex.unlock();
+ return;
+ }
+ m_mutex.unlock();
+ }
+ emit docsInstalled(changes);
+}
+
+bool QtDocInstaller::installDoc(const DocInfo &docInfo)
+{
+ TRACE_OBJ
+ const QString &component = docInfo.first;
+ const QStringList &info = docInfo.second;
+ QDateTime dt;
+ if (!info.isEmpty() && !info.first().isEmpty())
+ dt = QDateTime::fromString(info.first(), Qt::ISODate);
+
+ QString qchFile;
+ if (info.count() == 2)
+ qchFile = info.last();
+
+ if (m_qchFiles.isEmpty()) {
+ emit qchFileNotFound(component);
+ return false;
+ }
+ foreach (const QString &f, m_qchFiles) {
+ if (f.startsWith(component)) {
+ QFileInfo fi(m_qchDir.absolutePath() + QDir::separator() + f);
+ if (dt.isValid() && fi.lastModified().toTime_t() == dt.toTime_t()
+ && qchFile == fi.absoluteFilePath())
+ return false;
+ emit registerDocumentation(component, fi.absoluteFilePath());
+ return true;
+ }
+ }
+
+ emit qchFileNotFound(component);
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/qtdocinstaller.h b/src/assistant/tools/assistant/qtdocinstaller.h
new file mode 100644
index 000000000..909df10ce
--- /dev/null
+++ b/src/assistant/tools/assistant/qtdocinstaller.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QTDOCINSTALLER
+#define QTDOCINSTALLER
+
+#include <QtCore/QDir>
+#include <QtCore/QMutex>
+#include <QtCore/QPair>
+#include <QtCore/QStringList>
+#include <QtCore/QThread>
+
+QT_BEGIN_NAMESPACE
+
+class HelpEngineWrapper;
+
+class QtDocInstaller : public QThread
+{
+ Q_OBJECT
+
+public:
+ typedef QPair<QString, QStringList> DocInfo;
+ QtDocInstaller(const QList<DocInfo> &docInfos);
+ ~QtDocInstaller();
+ void installDocs();
+
+signals:
+ void qchFileNotFound(const QString &component);
+ void registerDocumentation(const QString &component,
+ const QString &absFileName);
+ void docsInstalled(bool newDocsInstalled);
+
+private:
+ void run();
+ bool installDoc(const DocInfo &docInfo);
+
+ bool m_abort;
+ QMutex m_mutex;
+ QStringList m_qchFiles;
+ QDir m_qchDir;
+ QList<DocInfo> m_docInfos;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/assistant/tools/assistant/remotecontrol.cpp b/src/assistant/tools/assistant/remotecontrol.cpp
new file mode 100644
index 000000000..5d93fbc2e
--- /dev/null
+++ b/src/assistant/tools/assistant/remotecontrol.cpp
@@ -0,0 +1,388 @@
+/****************************************************************************
+**
+** 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 "remotecontrol.h"
+
+#include "centralwidget.h"
+#include "helpenginewrapper.h"
+#include "mainwindow.h"
+#include "openpagesmanager.h"
+#include "tracer.h"
+
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QFileSystemWatcher>
+#include <QtCore/QThread>
+#include <QtCore/QTextStream>
+#include <QtCore/QSocketNotifier>
+
+#include <QtGui/QMessageBox>
+#include <QtGui/QApplication>
+
+#include <QtHelp/QHelpEngine>
+#include <QtHelp/QHelpIndexWidget>
+#include <QtHelp/QHelpSearchQueryWidget>
+
+#ifdef Q_OS_WIN
+# include "remotecontrol_win.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_OS_WIN
+
+StdInListenerWin::StdInListenerWin(QObject *parent)
+ : QThread(parent)
+{
+ TRACE_OBJ
+}
+
+StdInListenerWin::~StdInListenerWin()
+{
+ TRACE_OBJ
+ terminate();
+ wait();
+}
+
+void StdInListenerWin::run()
+{
+ TRACE_OBJ
+ bool ok = true;
+ char chBuf[4096];
+ DWORD dwRead;
+
+#ifndef Q_WS_WINCE
+ HANDLE hStdin, hStdinDup;
+
+ hStdin = GetStdHandle(STD_INPUT_HANDLE);
+ if (hStdin == INVALID_HANDLE_VALUE)
+ return;
+
+ DuplicateHandle(GetCurrentProcess(), hStdin,
+ GetCurrentProcess(), &hStdinDup,
+ 0, false, DUPLICATE_SAME_ACCESS);
+
+ CloseHandle(hStdin);
+#else
+ HANDLE hStdinDup;
+ hStdinDup = stdin;
+#endif
+
+ while (ok) {
+ ok = ReadFile(hStdinDup, chBuf, sizeof(chBuf), &dwRead, NULL);
+ if (ok && dwRead != 0)
+ emit receivedCommand(QString::fromLocal8Bit(chBuf, dwRead));
+ }
+}
+#endif
+
+RemoteControl::RemoteControl(MainWindow *mainWindow)
+ : QObject(mainWindow)
+ , m_mainWindow(mainWindow)
+ , m_debug(false)
+ , m_caching(true)
+ , m_syncContents(false)
+ , m_expandTOC(-2)
+ , helpEngine(HelpEngineWrapper::instance())
+
+{
+ TRACE_OBJ
+ connect(m_mainWindow, SIGNAL(initDone()), this, SLOT(applyCache()));
+#ifdef Q_OS_WIN
+ StdInListenerWin *l = new StdInListenerWin(this);
+ connect(l, SIGNAL(receivedCommand(QString)),
+ this, SLOT(handleCommandString(QString)));
+ l->start();
+#else
+ QSocketNotifier *notifier = new QSocketNotifier(fileno(stdin),
+ QSocketNotifier::Read, this);
+ connect(notifier, SIGNAL(activated(int)), this, SLOT(receivedData()));
+ notifier->setEnabled(true);
+#endif
+}
+
+void RemoteControl::receivedData()
+{
+ TRACE_OBJ
+ QByteArray ba;
+ while (true) {
+ char c = getc(stdin);
+ if (c == EOF || c == '\0')
+ break;
+ if (c)
+ ba.append(c);
+ if (c == '\n')
+ break;
+ }
+ handleCommandString(QString::fromLocal8Bit(ba));
+}
+
+void RemoteControl::handleCommandString(const QString &cmdString)
+{
+ TRACE_OBJ
+ QStringList cmds = cmdString.split(QLatin1Char(';'));
+ QStringList::const_iterator it = cmds.constBegin();
+ while (it != cmds.constEnd()) {
+ QString cmd, arg;
+ splitInputString(*it, cmd, arg);
+
+ if (m_debug)
+ QMessageBox::information(0, tr("Debugging Remote Control"),
+ tr("Received Command: %1 %2").arg(cmd).arg(arg));
+
+ if (cmd == QLatin1String("debug"))
+ handleDebugCommand(arg);
+ else if (cmd == QLatin1String("show"))
+ handleShowOrHideCommand(arg, true);
+ else if (cmd == QLatin1String("hide"))
+ handleShowOrHideCommand(arg, false);
+ else if (cmd == QLatin1String("setsource"))
+ handleSetSourceCommand(arg);
+ else if (cmd == QLatin1String("synccontents"))
+ handleSyncContentsCommand();
+ else if (cmd == QLatin1String("activatekeyword"))
+ handleActivateKeywordCommand(arg);
+ else if (cmd == QLatin1String("activateidentifier"))
+ handleActivateIdentifierCommand(arg);
+ else if (cmd == QLatin1String("expandtoc"))
+ handleExpandTocCommand(arg);
+ else if (cmd == QLatin1String("setcurrentfilter"))
+ handleSetCurrentFilterCommand(arg);
+ else if (cmd == QLatin1String("register"))
+ handleRegisterCommand(arg);
+ else if (cmd == QLatin1String("unregister"))
+ handleUnregisterCommand(arg);
+ else
+ return;
+
+ ++it;
+ }
+ m_mainWindow->raise();
+ m_mainWindow->activateWindow();
+}
+
+void RemoteControl::splitInputString(const QString &input, QString &cmd,
+ QString &arg)
+{
+ TRACE_OBJ
+ QString cmdLine = input.trimmed();
+ int i = cmdLine.indexOf(QLatin1Char(' '));
+ cmd = cmdLine.left(i);
+ arg = cmdLine.mid(i+1);
+ cmd = cmd.toLower();
+}
+
+void RemoteControl::handleDebugCommand(const QString &arg)
+{
+ TRACE_OBJ
+ m_debug = arg == QLatin1String("on");
+}
+
+void RemoteControl::handleShowOrHideCommand(const QString &arg, bool show)
+{
+ TRACE_OBJ
+ if (arg.toLower() == QLatin1String("contents"))
+ m_mainWindow->setContentsVisible(show);
+ else if (arg.toLower() == QLatin1String("index"))
+ m_mainWindow->setIndexVisible(show);
+ else if (arg.toLower() == QLatin1String("bookmarks"))
+ m_mainWindow->setBookmarksVisible(show);
+ else if (arg.toLower() == QLatin1String("search"))
+ m_mainWindow->setSearchVisible(show);
+}
+
+void RemoteControl::handleSetSourceCommand(const QString &arg)
+{
+ TRACE_OBJ
+ QUrl url(arg);
+ if (url.isValid()) {
+ if (url.isRelative())
+ url = CentralWidget::instance()->currentSource().resolved(url);
+ if (m_caching) {
+ clearCache();
+ m_setSource = url;
+ } else {
+ CentralWidget::instance()->setSource(url);
+ }
+ }
+}
+
+void RemoteControl::handleSyncContentsCommand()
+{
+ TRACE_OBJ
+ if (m_caching)
+ m_syncContents = true;
+ else
+ m_mainWindow->syncContents();
+}
+
+void RemoteControl::handleActivateKeywordCommand(const QString &arg)
+{
+ TRACE_OBJ
+ if (m_caching) {
+ clearCache();
+ m_activateKeyword = arg;
+ } else {
+ m_mainWindow->setIndexString(arg);
+ if (!arg.isEmpty()) {
+ if (!helpEngine.indexWidget()->currentIndex().isValid()
+ && helpEngine.fullTextSearchFallbackEnabled()) {
+ if (QHelpSearchEngine *se = helpEngine.searchEngine()) {
+ m_mainWindow->setSearchVisible(true);
+ if (QHelpSearchQueryWidget *w = se->queryWidget()) {
+ w->collapseExtendedSearch();
+ QList<QHelpSearchQuery> queryList;
+ queryList << QHelpSearchQuery(QHelpSearchQuery::DEFAULT,
+ QStringList(arg));
+ w->setQuery(queryList);
+ se->search(queryList);
+ }
+ }
+ } else {
+ m_mainWindow->setIndexVisible(true);
+ helpEngine.indexWidget()->activateCurrentItem();
+ }
+ }
+ }
+}
+
+void RemoteControl::handleActivateIdentifierCommand(const QString &arg)
+{
+ TRACE_OBJ
+ if (m_caching) {
+ clearCache();
+ m_activateIdentifier = arg;
+ } else {
+ const QMap<QString, QUrl> &links = helpEngine.linksForIdentifier(arg);
+ if (!links.isEmpty())
+ CentralWidget::instance()->setSource(links.constBegin().value());
+ }
+}
+
+void RemoteControl::handleExpandTocCommand(const QString &arg)
+{
+ TRACE_OBJ
+ bool ok = false;
+ int depth = -2;
+ if (!arg.isEmpty())
+ depth = arg.toInt(&ok);
+ if (!ok || depth < -2)
+ depth = -2;
+
+ if (m_caching)
+ m_expandTOC = depth;
+ else if (depth != -2)
+ m_mainWindow->expandTOC(depth);
+}
+
+void RemoteControl::handleSetCurrentFilterCommand(const QString &arg)
+{
+ TRACE_OBJ
+ if (helpEngine.customFilters().contains(arg)) {
+ if (m_caching) {
+ clearCache();
+ m_currentFilter = arg;
+ } else {
+ helpEngine.setCurrentFilter(arg);
+ }
+ }
+}
+
+void RemoteControl::handleRegisterCommand(const QString &arg)
+{
+ TRACE_OBJ
+ const QString &absFileName = QFileInfo(arg).absoluteFilePath();
+ if (helpEngine.registeredDocumentations().
+ contains(QHelpEngineCore::namespaceName(absFileName)))
+ return;
+ if (helpEngine.registerDocumentation(absFileName))
+ helpEngine.setupData();
+}
+
+void RemoteControl::handleUnregisterCommand(const QString &arg)
+{
+ TRACE_OBJ
+ const QString &absFileName = QFileInfo(arg).absoluteFilePath();
+ const QString &ns = QHelpEngineCore::namespaceName(absFileName);
+ if (helpEngine.registeredDocumentations().contains(ns)) {
+ OpenPagesManager::instance()->closePages(ns);
+ if (helpEngine.unregisterDocumentation(ns))
+ helpEngine.setupData();
+ }
+}
+
+void RemoteControl::applyCache()
+{
+ TRACE_OBJ
+ if (m_setSource.isValid()) {
+ CentralWidget::instance()->setSource(m_setSource);
+ } else if (!m_activateKeyword.isEmpty()) {
+ m_mainWindow->setIndexString(m_activateKeyword);
+ helpEngine.indexWidget()->activateCurrentItem();
+ } else if (!m_activateIdentifier.isEmpty()) {
+ QMap<QString, QUrl> links =
+ helpEngine.linksForIdentifier(m_activateIdentifier);
+ if (!links.isEmpty())
+ CentralWidget::instance()->setSource(links.constBegin().value());
+ } else if (!m_currentFilter.isEmpty()) {
+ helpEngine.setCurrentFilter(m_currentFilter);
+ }
+
+ if (m_syncContents)
+ m_mainWindow->syncContents();
+
+ Q_ASSERT(m_expandTOC >= -2);
+ if (m_expandTOC != -2)
+ m_mainWindow->expandTOC(m_expandTOC);
+
+ m_caching = false;
+}
+
+void RemoteControl::clearCache()
+{
+ TRACE_OBJ
+ m_currentFilter.clear();
+ m_setSource.clear();
+ m_syncContents = false;
+ m_activateKeyword.clear();
+ m_activateIdentifier.clear();
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/remotecontrol.h b/src/assistant/tools/assistant/remotecontrol.h
new file mode 100644
index 000000000..4a185f050
--- /dev/null
+++ b/src/assistant/tools/assistant/remotecontrol.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef REMOTECONTROL_H
+#define REMOTECONTROL_H
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QUrl>
+
+QT_BEGIN_NAMESPACE
+
+class HelpEngineWrapper;
+class MainWindow;
+
+class RemoteControl : public QObject
+{
+ Q_OBJECT
+
+public:
+ RemoteControl(MainWindow *mainWindow);
+
+private slots:
+ void receivedData();
+ void handleCommandString(const QString &cmdString);
+ void applyCache();
+
+private:
+ void clearCache();
+ void splitInputString(const QString &input, QString &cmd, QString &arg);
+ void handleDebugCommand(const QString &arg);
+ void handleShowOrHideCommand(const QString &arg, bool show);
+ void handleSetSourceCommand(const QString &arg);
+ void handleSyncContentsCommand();
+ void handleActivateKeywordCommand(const QString &arg);
+ void handleActivateIdentifierCommand(const QString &arg);
+ void handleExpandTocCommand(const QString &arg);
+ void handleSetCurrentFilterCommand(const QString &arg);
+ void handleRegisterCommand(const QString &arg);
+ void handleUnregisterCommand(const QString &arg);
+
+private:
+ MainWindow *m_mainWindow;
+ bool m_debug;
+
+ bool m_caching;
+ QUrl m_setSource;
+ bool m_syncContents;
+ QString m_activateKeyword;
+ QString m_activateIdentifier;
+ int m_expandTOC;
+ QString m_currentFilter;
+ HelpEngineWrapper &helpEngine;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/assistant/tools/assistant/remotecontrol_win.h b/src/assistant/tools/assistant/remotecontrol_win.h
new file mode 100644
index 000000000..807815df1
--- /dev/null
+++ b/src/assistant/tools/assistant/remotecontrol_win.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef REMOTECONTROL_WIN_H
+#define REMOTECONTROL_WIN_H
+
+#include <windows.h>
+#include <QtCore/QThread>
+
+QT_BEGIN_NAMESPACE
+
+class StdInListenerWin : public QThread
+{
+ Q_OBJECT
+
+public:
+ StdInListenerWin(QObject *parent);
+ ~StdInListenerWin();
+
+signals:
+ void receivedCommand(const QString &cmd);
+
+private:
+ void run();
+ bool ok;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/assistant/tools/assistant/searchwidget.cpp b/src/assistant/tools/assistant/searchwidget.cpp
new file mode 100644
index 000000000..627d9e745
--- /dev/null
+++ b/src/assistant/tools/assistant/searchwidget.cpp
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** 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 "tracer.h"
+
+#include "mainwindow.h"
+#include "searchwidget.h"
+
+#include <QtCore/QMap>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+
+#include <QtGui/QMenu>
+#include <QtGui/QLayout>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QClipboard>
+#include <QtGui/QApplication>
+#include <QtGui/QTextBrowser>
+
+#include <QtHelp/QHelpSearchEngine>
+#include <QtHelp/QHelpSearchQueryWidget>
+#include <QtHelp/QHelpSearchResultWidget>
+
+QT_BEGIN_NAMESPACE
+
+SearchWidget::SearchWidget(QHelpSearchEngine *engine, QWidget *parent)
+ : QWidget(parent)
+ , zoomCount(0)
+ , searchEngine(engine)
+{
+ TRACE_OBJ
+ QVBoxLayout *vLayout = new QVBoxLayout(this);
+
+ resultWidget = searchEngine->resultWidget();
+ QHelpSearchQueryWidget *queryWidget = searchEngine->queryWidget();
+
+ vLayout->addWidget(queryWidget);
+ vLayout->addWidget(resultWidget);
+
+ setFocusProxy(queryWidget);
+
+ connect(queryWidget, SIGNAL(search()), this, SLOT(search()));
+ connect(resultWidget, SIGNAL(requestShowLink(QUrl)), this,
+ SIGNAL(requestShowLink(QUrl)));
+
+ connect(searchEngine, SIGNAL(searchingStarted()), this,
+ SLOT(searchingStarted()));
+ connect(searchEngine, SIGNAL(searchingFinished(int)), this,
+ SLOT(searchingFinished(int)));
+
+ QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>();
+ if (browser) // Will be null if lib was configured not to use CLucene.
+ browser->viewport()->installEventFilter(this);
+}
+
+SearchWidget::~SearchWidget()
+{
+ TRACE_OBJ
+ // nothing todo
+}
+
+void SearchWidget::zoomIn()
+{
+ TRACE_OBJ
+ QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>();
+ if (browser && zoomCount != 10) {
+ zoomCount++;
+ browser->zoomIn();
+ }
+}
+
+void SearchWidget::zoomOut()
+{
+ TRACE_OBJ
+ QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>();
+ if (browser && zoomCount != -5) {
+ zoomCount--;
+ browser->zoomOut();
+ }
+}
+
+void SearchWidget::resetZoom()
+{
+ TRACE_OBJ
+ if (zoomCount == 0)
+ return;
+
+ QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>();
+ if (browser) {
+ browser->zoomOut(zoomCount);
+ zoomCount = 0;
+ }
+}
+
+void SearchWidget::search() const
+{
+ TRACE_OBJ
+ QList<QHelpSearchQuery> query = searchEngine->queryWidget()->query();
+ searchEngine->search(query);
+}
+
+void SearchWidget::searchingStarted()
+{
+ TRACE_OBJ
+ qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
+}
+
+void SearchWidget::searchingFinished(int hits)
+{
+ TRACE_OBJ
+ Q_UNUSED(hits)
+ qApp->restoreOverrideCursor();
+}
+
+bool SearchWidget::eventFilter(QObject* o, QEvent *e)
+{
+ TRACE_OBJ
+ QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>();
+ if (browser && o == browser->viewport()
+ && e->type() == QEvent::MouseButtonRelease){
+ QMouseEvent *me = static_cast<QMouseEvent*>(e);
+ QUrl link = resultWidget->linkAt(me->pos());
+ if (!link.isEmpty() || link.isValid()) {
+ bool controlPressed = me->modifiers() & Qt::ControlModifier;
+ if((me->button() == Qt::LeftButton && controlPressed)
+ || (me->button() == Qt::MidButton)) {
+ emit requestShowLinkInNewTab(link);
+ }
+ }
+ }
+ return QWidget::eventFilter(o,e);
+}
+
+void SearchWidget::keyPressEvent(QKeyEvent *keyEvent)
+{
+ TRACE_OBJ
+ if (keyEvent->key() == Qt::Key_Escape)
+ MainWindow::activateCurrentBrowser();
+ else
+ keyEvent->ignore();
+}
+
+void SearchWidget::contextMenuEvent(QContextMenuEvent *contextMenuEvent)
+{
+ TRACE_OBJ
+ QMenu menu;
+ QPoint point = contextMenuEvent->globalPos();
+
+ QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>();
+ if (!browser)
+ return;
+
+ point = browser->mapFromGlobal(point);
+ if (!browser->rect().contains(point, true))
+ return;
+
+ QUrl link = browser->anchorAt(point);
+
+ QKeySequence keySeq(QKeySequence::Copy);
+ QAction *copyAction = menu.addAction(tr("&Copy") + QLatin1String("\t") +
+ keySeq.toString(QKeySequence::NativeText));
+ copyAction->setEnabled(QTextCursor(browser->textCursor()).hasSelection());
+
+ QAction *copyAnchorAction = menu.addAction(tr("Copy &Link Location"));
+ copyAnchorAction->setEnabled(!link.isEmpty() && link.isValid());
+
+ keySeq = QKeySequence(Qt::CTRL);
+ QAction *newTabAction = menu.addAction(tr("Open Link in New Tab") +
+ QLatin1String("\t") + keySeq.toString(QKeySequence::NativeText) +
+ QLatin1String("LMB"));
+ newTabAction->setEnabled(!link.isEmpty() && link.isValid());
+
+ menu.addSeparator();
+
+ keySeq = QKeySequence::SelectAll;
+ QAction *selectAllAction = menu.addAction(tr("Select All") +
+ QLatin1String("\t") + keySeq.toString(QKeySequence::NativeText));
+
+ QAction *usedAction = menu.exec(mapToGlobal(contextMenuEvent->pos()));
+ if (usedAction == copyAction) {
+ QTextCursor cursor = browser->textCursor();
+ if (!cursor.isNull() && cursor.hasSelection()) {
+ QString selectedText = cursor.selectedText();
+ QMimeData *data = new QMimeData();
+ data->setText(selectedText);
+ QApplication::clipboard()->setMimeData(data);
+ }
+ }
+ else if (usedAction == copyAnchorAction) {
+ QApplication::clipboard()->setText(link.toString());
+ }
+ else if (usedAction == newTabAction) {
+ emit requestShowLinkInNewTab(link);
+ }
+ else if (usedAction == selectAllAction) {
+ browser->selectAll();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/searchwidget.h b/src/assistant/tools/assistant/searchwidget.h
new file mode 100644
index 000000000..077c78771
--- /dev/null
+++ b/src/assistant/tools/assistant/searchwidget.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef SEARCHWIDGET_H
+#define SEARCHWIDGET_H
+
+#include <QtCore/QUrl>
+#include <QtCore/QPoint>
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QMouseEvent;
+class QHelpSearchEngine;
+class QHelpSearchResultWidget;
+
+class SearchWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit SearchWidget(QHelpSearchEngine *engine, QWidget *parent = 0);
+ ~SearchWidget();
+
+ void zoomIn();
+ void zoomOut();
+ void resetZoom();
+
+signals:
+ void requestShowLink(const QUrl &url);
+ void requestShowLinkInNewTab(const QUrl &url);
+
+private slots:
+ void search() const;
+ void searchingStarted();
+ void searchingFinished(int hits);
+
+private:
+ bool eventFilter(QObject* o, QEvent *e);
+ void keyPressEvent(QKeyEvent *keyEvent);
+ void contextMenuEvent(QContextMenuEvent *contextMenuEvent);
+
+private:
+ int zoomCount;
+ QHelpSearchEngine *searchEngine;
+ QHelpSearchResultWidget *resultWidget;
+};
+
+QT_END_NAMESPACE
+
+#endif // SEARCHWIDGET_H
diff --git a/src/assistant/tools/assistant/topicchooser.cpp b/src/assistant/tools/assistant/topicchooser.cpp
new file mode 100644
index 000000000..6f2810bf4
--- /dev/null
+++ b/src/assistant/tools/assistant/topicchooser.cpp
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** 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 "tracer.h"
+
+#include "topicchooser.h"
+
+QT_BEGIN_NAMESPACE
+
+TopicChooser::TopicChooser(QWidget *parent, const QString &keyword,
+ const QMap<QString, QUrl> &links)
+ : QDialog(parent)
+{
+ TRACE_OBJ
+ ui.setupUi(this);
+ ui.label->setText(tr("Choose a topic for <b>%1</b>:").arg(keyword));
+
+ QMap<QString, QUrl>::const_iterator it = links.constBegin();
+ for (; it != links.constEnd(); ++it) {
+ ui.listWidget->addItem(it.key());
+ m_links.append(it.value());
+ }
+
+ if (ui.listWidget->count() != 0)
+ ui.listWidget->setCurrentRow(0);
+ ui.listWidget->setFocus();
+
+ connect(ui.buttonDisplay, SIGNAL(clicked()), this, SLOT(accept()));
+ connect(ui.buttonCancel, SIGNAL(clicked()), this, SLOT(reject()));
+ connect(ui.listWidget, SIGNAL(itemActivated(QListWidgetItem*)), this,
+ SLOT(accept()));
+}
+
+QUrl TopicChooser::link() const
+{
+ TRACE_OBJ
+ QListWidgetItem *item = ui.listWidget->currentItem();
+ if (!item)
+ return QUrl();
+
+ QString title = item->text();
+ if (title.isEmpty())
+ return QUrl();
+
+ const int row = ui.listWidget->row(item);
+ Q_ASSERT(row < m_links.count());
+ return m_links.at(row);
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/topicchooser.h b/src/assistant/tools/assistant/topicchooser.h
new file mode 100644
index 000000000..a80f1963d
--- /dev/null
+++ b/src/assistant/tools/assistant/topicchooser.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef TOPICCHOOSER_H
+#define TOPICCHOOSER_H
+
+#include "ui_topicchooser.h"
+
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QString>
+#include <QtCore/QUrl>
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class TopicChooser : public QDialog
+{
+ Q_OBJECT
+
+public:
+ TopicChooser(QWidget *parent, const QString &keyword,
+ const QMap<QString, QUrl> &links);
+
+ QUrl link() const;
+
+private:
+ Ui::TopicChooser ui;
+ QList<QUrl> m_links;
+};
+
+QT_END_NAMESPACE
+
+#endif // TOPICCHOOSER_H
diff --git a/src/assistant/tools/assistant/topicchooser.ui b/src/assistant/tools/assistant/topicchooser.ui
new file mode 100644
index 000000000..d4c90bb4b
--- /dev/null
+++ b/src/assistant/tools/assistant/topicchooser.ui
@@ -0,0 +1,116 @@
+<UI version="4.0" stdsetdef="1" >
+ <class>TopicChooser</class>
+ <widget class="QDialog" name="TopicChooser" >
+ <property name="objectName" >
+ <string notr="true">TopicChooser</string>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>391</width>
+ <height>223</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Choose Topic</string>
+ </property>
+ <property name="sizeGripEnabled" >
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="objectName" >
+ <string notr="true">unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label" >
+ <property name="objectName" >
+ <string notr="true">label</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Topics</string>
+ </property>
+ <property name="buddy" stdset="0" >
+ <cstring>listWidget</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QListWidget" name="listWidget" >
+ <property name="objectName" >
+ <string notr="true">listWidget</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QWidget" name="Layout16" >
+ <property name="objectName" >
+ <string notr="true">Layout16</string>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true">unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <spacer name="Horizontal Spacing2" >
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="sizeType" >
+ <enum>Expanding</enum>
+ </property>
+ <property name="orientation" >
+ <enum>Horizontal</enum>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonDisplay" >
+ <property name="objectName" >
+ <string notr="true">buttonDisplay</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Display</string>
+ </property>
+ <property name="autoDefault" >
+ <bool>true</bool>
+ </property>
+ <property name="default" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonCancel" >
+ <property name="objectName" >
+ <string notr="true">buttonCancel</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Close</string>
+ </property>
+ <property name="autoDefault" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+</UI>
diff --git a/src/assistant/tools/assistant/tracer.h b/src/assistant/tools/assistant/tracer.h
new file mode 100644
index 000000000..1ed609acb
--- /dev/null
+++ b/src/assistant/tools/assistant/tracer.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef TRACER_H
+#define TRACER_H
+
+#include <QtCore/QtGlobal>
+
+QT_BEGIN_NAMESPACE
+
+class Tracer
+{
+public:
+ Tracer(const char *func) : m_func(func)
+ {
+ qDebug("Entering function %s.", m_func);
+ }
+
+ ~Tracer()
+ {
+ qDebug("Leaving function %s.", m_func);
+ }
+
+private:
+ const char * const m_func;
+};
+
+QT_END_NAMESPACE
+
+// #define TRACING_REQUESTED
+#ifdef TRACING_REQUESTED
+#define TRACE_OBJ Tracer traceObj__(Q_FUNC_INFO);
+#else
+#define TRACE_OBJ
+#endif
+
+#endif // TRACER_H
diff --git a/src/assistant/tools/assistant/xbelsupport.cpp b/src/assistant/tools/assistant/xbelsupport.cpp
new file mode 100644
index 000000000..2979d10c1
--- /dev/null
+++ b/src/assistant/tools/assistant/xbelsupport.cpp
@@ -0,0 +1,233 @@
+/****************************************************************************
+**
+** 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 "tracer.h"
+
+#include "xbelsupport.h"
+
+#include "bookmarkitem.h"
+#include "bookmarkmodel.h"
+
+#include <QtCore/QDate>
+#include <QtCore/QModelIndex>
+
+QT_BEGIN_NAMESPACE
+
+struct Bookmark {
+ QString title;
+ QString url;
+ bool folded;
+};
+
+XbelWriter::XbelWriter(BookmarkModel *model)
+ : QXmlStreamWriter()
+ , bookmarkModel(model)
+{
+ TRACE_OBJ
+ setAutoFormatting(true);
+}
+
+void XbelWriter::writeToFile(QIODevice *device)
+{
+ TRACE_OBJ
+ setDevice(device);
+
+ writeStartDocument();
+ writeDTD(QLatin1String("<!DOCTYPE xbel>"));
+ writeStartElement(QLatin1String("xbel"));
+ writeAttribute(QLatin1String("version"), QLatin1String("1.0"));
+
+ const QModelIndex &root = bookmarkModel->index(0,0, QModelIndex());
+ for (int i = 0; i < bookmarkModel->rowCount(root); ++i)
+ writeData(bookmarkModel->index(i, 0, root));
+ writeEndDocument();
+}
+
+void XbelWriter::writeData(const QModelIndex &index)
+{
+ TRACE_OBJ
+ if (index.isValid()) {
+ Bookmark entry;
+ entry.title = index.data().toString();
+ entry.url = index.data(UserRoleUrl).toString();
+
+ if (index.data(UserRoleFolder).toBool()) {
+ writeStartElement(QLatin1String("folder"));
+ entry.folded = !index.data(UserRoleExpanded).toBool();
+ writeAttribute(QLatin1String("folded"), entry.folded
+ ? QLatin1String("yes") : QLatin1String("no"));
+ writeTextElement(QLatin1String("title"), entry.title);
+
+ for (int i = 0; i < bookmarkModel->rowCount(index); ++i)
+ writeData(bookmarkModel->index(i, 0 , index));
+ writeEndElement();
+ } else {
+ writeStartElement(QLatin1String("bookmark"));
+ writeAttribute(QLatin1String("href"), entry.url);
+ writeTextElement(QLatin1String("title"), entry.title);
+ writeEndElement();
+ }
+ }
+}
+
+// -- XbelReader
+
+XbelReader::XbelReader(BookmarkModel *model)
+ : QXmlStreamReader()
+ , bookmarkModel(model)
+{
+ TRACE_OBJ
+}
+
+bool XbelReader::readFromFile(QIODevice *device)
+{
+ TRACE_OBJ
+ setDevice(device);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isStartElement()) {
+ if (name() == QLatin1String("xbel")
+ && attributes().value(QLatin1String("version"))
+ == QLatin1String("1.0")) {
+ const QModelIndex &root = bookmarkModel->index(0,0, QModelIndex());
+ parents.append(bookmarkModel->addItem(root, true));
+ readXBEL();
+ bookmarkModel->setData(parents.first(),
+ QDate::currentDate().toString(Qt::ISODate), Qt::EditRole);
+ } else {
+ raiseError(QLatin1String("The file is not an XBEL version 1.0 file."));
+ }
+ }
+ }
+
+ return !error();
+}
+
+void XbelReader::readXBEL()
+{
+ TRACE_OBJ
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ if (name() == QLatin1String("folder"))
+ readFolder();
+ else if (name() == QLatin1String("bookmark"))
+ readBookmark();
+ else
+ readUnknownElement();
+ }
+ }
+}
+
+void XbelReader::readFolder()
+{
+ TRACE_OBJ
+ parents.append(bookmarkModel->addItem(parents.last(), true));
+ bookmarkModel->setData(parents.last(),
+ attributes().value(QLatin1String("folded")) == QLatin1String("no"),
+ UserRoleExpanded);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ if (name() == QLatin1String("title")) {
+ bookmarkModel->setData(parents.last(), readElementText(),
+ Qt::EditRole);
+ } else if (name() == QLatin1String("folder"))
+ readFolder();
+ else if (name() == QLatin1String("bookmark"))
+ readBookmark();
+ else
+ readUnknownElement();
+ }
+ }
+
+ parents.removeLast();
+}
+
+void XbelReader::readBookmark()
+{
+ TRACE_OBJ
+ const QModelIndex &index = bookmarkModel->addItem(parents.last(), false);
+ if (BookmarkItem* item = bookmarkModel->itemFromIndex(index)) {
+ item->setData(UserRoleUrl, attributes().value(QLatin1String("href"))
+ .toString());
+ }
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ if (name() == QLatin1String("title"))
+ bookmarkModel->setData(index, readElementText(), Qt::EditRole);
+ else
+ readUnknownElement();
+ }
+ }
+}
+
+void XbelReader::readUnknownElement()
+{
+ TRACE_OBJ
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement())
+ readUnknownElement();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/assistant/tools/assistant/xbelsupport.h b/src/assistant/tools/assistant/xbelsupport.h
new file mode 100644
index 000000000..4c2a211ad
--- /dev/null
+++ b/src/assistant/tools/assistant/xbelsupport.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef XBELSUPPORT_H
+#define XBELSUPPORT_H
+
+#include <QtXml/QXmlStreamReader>
+#include <QtCore/QPersistentModelIndex>
+
+QT_FORWARD_DECLARE_CLASS(QIODevice)
+QT_FORWARD_DECLARE_CLASS(QModelIndex)
+
+QT_BEGIN_NAMESPACE
+
+class BookmarkModel;
+
+class XbelWriter : public QXmlStreamWriter
+{
+public:
+ XbelWriter(BookmarkModel *model);
+ void writeToFile(QIODevice *device);
+
+private:
+ void writeData(const QModelIndex &index);
+
+private:
+ BookmarkModel *bookmarkModel;
+};
+
+class XbelReader : public QXmlStreamReader
+{
+public:
+ XbelReader(BookmarkModel *model);
+ bool readFromFile(QIODevice *device);
+
+private:
+ void readXBEL();
+ void readFolder();
+ void readBookmark();
+ void readUnknownElement();
+
+private:
+ BookmarkModel *bookmarkModel;
+ QList<QPersistentModelIndex> parents;
+};
+
+QT_END_NAMESPACE
+
+#endif // XBELSUPPORT_H