From 96e8f0bb7b4e289af45c17bf66026fca47b1e626 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Fri, 2 May 2014 16:54:28 +0200 Subject: [PATCH] Help: Cleanly separate different viewer backends Removes the conditional compilation of the text browser vs web kit, cleans up the code, and enables us to provide and test other backends (WebEngine? Native?) Adds runtime switch for testing the text browser variant by setting environment variable QTC_FORCE_TEXTBROWSER (for now) Change-Id: I8cc9bb373438d37c8194e433224314caa0b617bd Reviewed-by: Eike Ziller --- src/plugins/help/centralwidget.cpp | 9 +- src/plugins/help/centralwidget.h | 1 - src/plugins/help/generalsettingspage.cpp | 1 + src/plugins/help/help.pro | 11 +- src/plugins/help/help.qbs | 6 +- src/plugins/help/helpplugin.cpp | 132 +----- src/plugins/help/helpplugin.h | 6 +- src/plugins/help/helpviewer.cpp | 11 +- src/plugins/help/helpviewer.h | 140 ++---- src/plugins/help/helpviewer_p.h | 101 ---- src/plugins/help/helpviewer_qtb.cpp | 379 --------------- src/plugins/help/openpagesmodel.cpp | 3 +- ...pviewer_qwv.cpp => qtwebkithelpviewer.cpp} | 377 ++++++++++----- src/plugins/help/qtwebkithelpviewer.h | 165 +++++++ src/plugins/help/textbrowserhelpviewer.cpp | 440 ++++++++++++++++++ src/plugins/help/textbrowserhelpviewer.h | 129 +++++ 16 files changed, 1083 insertions(+), 828 deletions(-) delete mode 100644 src/plugins/help/helpviewer_p.h delete mode 100644 src/plugins/help/helpviewer_qtb.cpp rename src/plugins/help/{helpviewer_qwv.cpp => qtwebkithelpviewer.cpp} (68%) create mode 100644 src/plugins/help/qtwebkithelpviewer.h create mode 100644 src/plugins/help/textbrowserhelpviewer.cpp create mode 100644 src/plugins/help/textbrowserhelpviewer.h diff --git a/src/plugins/help/centralwidget.cpp b/src/plugins/help/centralwidget.cpp index 7480831ed98..94deeb15a5e 100644 --- a/src/plugins/help/centralwidget.cpp +++ b/src/plugins/help/centralwidget.cpp @@ -132,7 +132,7 @@ void CentralWidget::addPage(HelpViewer *page, bool fromSearch) connectSignals(page); m_stackedWidget->addWidget(page); if (fromSearch) { - connect(currentHelpViewer(), SIGNAL(loadFinished(bool)), this, + connect(currentHelpViewer(), SIGNAL(loadFinished()), this, SLOT(highlightSearchTerms())); } } @@ -255,7 +255,7 @@ void CentralWidget::setSource(const QUrl &url) void CentralWidget::setSourceFromSearch(const QUrl &url) { if (HelpViewer* viewer = currentHelpViewer()) { - connect(viewer, SIGNAL(loadFinished(bool)), this, + connect(viewer, SIGNAL(loadFinished()), this, SLOT(highlightSearchTerms())); viewer->setSource(url); viewer->setFocus(Qt::OtherFocusReason); @@ -309,7 +309,7 @@ void CentralWidget::highlightSearchTerms() foreach (const QString& term, terms) viewer->findText(term, 0, false, true); - disconnect(viewer, SIGNAL(loadFinished(bool)), this, + disconnect(viewer, SIGNAL(loadFinished()), this, SLOT(highlightSearchTerms())); } } @@ -347,7 +347,6 @@ void CentralWidget::connectSignals(HelpViewer *page) connect(page, SIGNAL(forwardAvailable(bool)), this, SIGNAL(forwardAvailable(bool))); connect(page, SIGNAL(backwardAvailable(bool)), this, SIGNAL(backwardAvailable(bool))); connect(page, SIGNAL(printRequested()), this, SLOT(print())); - connect(page, SIGNAL(openFindToolBar()), this, SIGNAL(openFindToolBar())); } bool CentralWidget::eventFilter(QObject *object, QEvent *e) @@ -359,10 +358,8 @@ bool CentralWidget::eventFilter(QObject *object, QEvent *e) QKeyEvent *keyEvent = static_cast (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 field if (!viewer->hasFocus()) -#endif viewer->backward(); } } diff --git a/src/plugins/help/centralwidget.h b/src/plugins/help/centralwidget.h index be8d5abf011..8fa96d0e19f 100644 --- a/src/plugins/help/centralwidget.h +++ b/src/plugins/help/centralwidget.h @@ -94,7 +94,6 @@ protected: void focusInEvent(QFocusEvent *event); signals: - void openFindToolBar(); void sourceChanged(const QUrl &url); void forwardAvailable(bool available); void backwardAvailable(bool available); diff --git a/src/plugins/help/generalsettingspage.cpp b/src/plugins/help/generalsettingspage.cpp index f6b80c757f6..46a30e4bf3e 100644 --- a/src/plugins/help/generalsettingspage.cpp +++ b/src/plugins/help/generalsettingspage.cpp @@ -61,6 +61,7 @@ GeneralSettingsPage::GeneralSettingsPage() : m_ui(0) { m_font = qApp->font(); + // TODO remove QT_NO_WEBKIT #if !defined(QT_NO_WEBKIT) QWebSettings* webSettings = QWebSettings::globalSettings(); m_font.setPointSize(webSettings->fontSize(QWebSettings::DefaultFontSize)); diff --git a/src/plugins/help/help.pro b/src/plugins/help/help.pro index 18d38698fe7..4fb13c424e7 100644 --- a/src/plugins/help/help.pro +++ b/src/plugins/help/help.pro @@ -28,7 +28,6 @@ HEADERS += \ helpmode.h \ helpplugin.h \ helpviewer.h \ - helpviewer_p.h \ openpagesmanager.h \ openpagesmodel.h \ openpagesswitcher.h \ @@ -37,7 +36,9 @@ HEADERS += \ searchwidget.h \ xbelsupport.h \ externalhelpwindow.h \ - searchtaskhandler.h + searchtaskhandler.h \ + qtwebkithelpviewer.h \ + textbrowserhelpviewer.h SOURCES += \ centralwidget.cpp \ @@ -50,8 +51,6 @@ SOURCES += \ helpmode.cpp \ helpplugin.cpp \ helpviewer.cpp \ - helpviewer_qtb.cpp \ - helpviewer_qwv.cpp \ openpagesmanager.cpp \ openpagesmodel.cpp \ openpagesswitcher.cpp \ @@ -60,7 +59,9 @@ SOURCES += \ searchwidget.cpp \ xbelsupport.cpp \ externalhelpwindow.cpp \ - searchtaskhandler.cpp + searchtaskhandler.cpp \ + qtwebkithelpviewer.cpp \ + textbrowserhelpviewer.cpp FORMS += docsettingspage.ui \ filtersettingspage.ui \ diff --git a/src/plugins/help/help.qbs b/src/plugins/help/help.qbs index a8214723200..6ef72e5676a 100644 --- a/src/plugins/help/help.qbs +++ b/src/plugins/help/help.qbs @@ -51,17 +51,17 @@ QtcPlugin { "helpindexfilter.cpp", "helpindexfilter.h", "helpmode.cpp", "helpmode.h", "helpplugin.cpp", "helpplugin.h", - "helpviewer.cpp", "helpviewer.h", "helpviewer_p.h", - "helpviewer_qtb.cpp", - "helpviewer_qwv.cpp", + "helpviewer.cpp", "helpviewer.h", "localhelpmanager.cpp", "localhelpmanager.h", "openpagesmanager.cpp", "openpagesmanager.h", "openpagesmodel.cpp", "openpagesmodel.h", "openpagesswitcher.cpp", "openpagesswitcher.h", "openpageswidget.cpp", "openpageswidget.h", + "qtwebkithelpviewer.cpp", "qtwebkithelpviewer.h", "remotehelpfilter.cpp", "remotehelpfilter.h", "remotehelpfilter.ui", "searchtaskhandler.cpp", "searchtaskhandler.h", "searchwidget.cpp", "searchwidget.h", + "textbrowserhelpviewer.cpp", "textbrowserhelpviewer.h", "xbelsupport.cpp", "xbelsupport.h", ] } diff --git a/src/plugins/help/helpplugin.cpp b/src/plugins/help/helpplugin.cpp index ef86fe8305a..1f3d0cb6dae 100644 --- a/src/plugins/help/helpplugin.cpp +++ b/src/plugins/help/helpplugin.cpp @@ -42,9 +42,11 @@ #include "localhelpmanager.h" #include "openpagesmanager.h" #include "openpagesmodel.h" +#include "qtwebkithelpviewer.h" #include "remotehelpfilter.h" #include "searchwidget.h" #include "searchtaskhandler.h" +#include "textbrowserhelpviewer.h" #include #include @@ -88,13 +90,6 @@ #include -#if !defined(QT_NO_WEBKIT) -#include -#include -#include -#include -#endif - using namespace Help::Internal; const char SB_INDEX[] = QT_TRANSLATE_NOOP("Help::Internal::HelpPlugin", "Index"); @@ -200,9 +195,6 @@ bool HelpPlugin::initialize(const QStringList &arguments, QString *error) m_centralWidget = new Help::Internal::CentralWidget(); connect(m_centralWidget, SIGNAL(sourceChanged(QUrl)), this, SLOT(updateSideBarSource(QUrl))); - connect(m_centralWidget, SIGNAL(openFindToolBar()), this, - SLOT(openFindToolBar())); - // Add Home, Previous and Next actions (used in the toolbar) QAction *action = new QAction(QIcon(QLatin1String(IMAGEPATH "home.png")), tr("Home"), this); @@ -564,12 +556,8 @@ void HelpPlugin::createRightPaneContextViewer() layout->addWidget(toolButton(close)); m_rightPaneSideBarWidget = new QWidget; - m_helpViewerForSideBar = new HelpViewer(qreal(0.0)); - connect(m_helpViewerForSideBar, SIGNAL(openFindToolBar()), this, - SLOT(openFindToolBar())); -#if !defined(QT_NO_WEBKIT) - m_helpViewerForSideBar->pageAction(QWebPage::OpenLinkInNewWindow)->setVisible(false); -#endif + m_helpViewerForSideBar = createHelpViewer(qreal(0.0)); + m_helpViewerForSideBar->setOpenInNewWindowActionVisible(false); QVBoxLayout *rightPaneLayout = new QVBoxLayout(m_rightPaneSideBarWidget); rightPaneLayout->setMargin(0); @@ -648,6 +636,18 @@ void HelpPlugin::resetRightPaneScale() m_helpViewerForSideBar->resetScale(); } +HelpViewer *HelpPlugin::createHelpViewer(qreal zoom) +{ +#ifndef QT_NO_WEBKIT + if (qgetenv("QTC_FORCE_TEXTBROWSER").isEmpty()) + return new QtWebKitHelpViewer(zoom); + else + return new TextBrowserHelpViewer(zoom); +#else + return new TextBrowserHelpViewer(zoom); +#endif +} + void HelpPlugin::activateHelpMode() { if (contextHelpOption() != Help::Constants::ExternalHelpAlways) @@ -910,9 +910,7 @@ void HelpPlugin::activateContext() const QUrl &oldSource = viewer->source(); if (source != oldSource) { -#if !defined(QT_NO_WEBKIT) viewer->stop(); -#endif const QString &fragment = source.fragment(); const bool isQtRefDoc = source.authority().startsWith(qtRefDoc); if (isQtRefDoc) { @@ -920,7 +918,7 @@ void HelpPlugin::activateContext() m_idFromContext = fragment; if (!m_idFromContext.isEmpty()) { - connect(viewer, SIGNAL(loadFinished(bool)), this, + connect(viewer, SIGNAL(loadFinished()), this, SLOT(highlightSearchTerms())); } } @@ -934,9 +932,7 @@ void HelpPlugin::activateContext() } } } else { -#if !defined(QT_NO_WEBKIT) - viewer->page()->mainFrame()->scrollToAnchor(source.fragment()); -#endif + viewer->scrollToAnchor(source.fragment()); } viewer->setFocus(); } @@ -1089,35 +1085,9 @@ void HelpPlugin::addBookmark() void HelpPlugin::highlightSearchTerms() { if (HelpViewer* viewer = viewerForContextMode()) { - disconnect(viewer, SIGNAL(loadFinished(bool)), this, + disconnect(viewer, SIGNAL(loadFinished()), this, SLOT(highlightSearchTerms())); - -#if !defined(QT_NO_WEBKIT) - const QWebElement &document = viewer->page()->mainFrame()->documentElement(); - const QWebElementCollection &collection = document.findAll(QLatin1String("h3.fn a")); - - const QLatin1String property("background-color"); - foreach (const QWebElement &element, collection) { - const QString &name = element.attribute(QLatin1String("name")); - if (name.isEmpty()) - continue; - - if (m_oldAttrValue == name - || name.startsWith(m_oldAttrValue + QLatin1Char('-'))) { - QWebElement parent = element.parent(); - parent.setStyleProperty(property, m_styleProperty); - } - - if (m_idFromContext == name - || name.startsWith(m_idFromContext + QLatin1Char('-'))) { - QWebElement parent = element.parent(); - m_styleProperty = parent.styleProperty(property, - QWebElement::ComputedStyle); - parent.setStyleProperty(property, QLatin1String("yellow")); - } - } - m_oldAttrValue = m_idFromContext; -#endif + viewer->highlightId(m_idFromContext); } } @@ -1152,54 +1122,16 @@ void HelpPlugin::handleHelpRequest(const QUrl &url) void HelpPlugin::slotAboutToShowBackMenu() { -#if !defined(QT_NO_WEBKIT) m_backMenu->clear(); - if (QWebHistory *history = viewerForContextMode()->history()) { - const int currentItemIndex = history->currentItemIndex(); - QList 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); - } - } -#endif + if (HelpViewer *viewer = m_centralWidget->currentHelpViewer()) + viewer->addBackHistoryItems(m_backMenu); } void HelpPlugin::slotAboutToShowNextMenu() { -#if !defined(QT_NO_WEBKIT) m_nextMenu->clear(); - if (QWebHistory *history = viewerForContextMode()->history()) { - const int count = history->count(); - QList 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); - } - } -#endif -} - -void HelpPlugin::slotOpenActionUrl(QAction *action) -{ -#if !defined(QT_NO_WEBKIT) - if (HelpViewer* viewer = viewerForContextMode()) { - 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 - } - } -#else - Q_UNUSED(action) -#endif + if (HelpViewer *viewer = m_centralWidget->currentHelpViewer()) + viewer->addForwardHistoryItems(m_nextMenu); } void HelpPlugin::slotOpenSupportPage() @@ -1212,12 +1144,6 @@ void HelpPlugin::slotReportBug() QDesktopServices::openUrl(QUrl(QLatin1String("https://bugreports.qt-project.org"))); } -void HelpPlugin::openFindToolBar() -{ - if (FindPlugin::instance()) - FindPlugin::instance()->openFindToolBar(FindPlugin::FindForwardDirection); -} - void HelpPlugin::onSideBarVisibilityChanged() { m_isSidebarVisible = m_sideBar->isVisible(); @@ -1273,30 +1199,20 @@ void HelpPlugin::connectExternalHelpWindow() void HelpPlugin::setupNavigationMenus(QAction *back, QAction *next, QWidget *parent) { -#if !defined(QT_NO_WEBKIT) if (!m_backMenu) { m_backMenu = new QMenu(parent); connect(m_backMenu, SIGNAL(aboutToShow()), this, SLOT(slotAboutToShowBackMenu())); - connect(m_backMenu, SIGNAL(triggered(QAction*)), this, - SLOT(slotOpenActionUrl(QAction*))); } if (!m_nextMenu) { m_nextMenu = new QMenu(parent); connect(m_nextMenu, SIGNAL(aboutToShow()), this, SLOT(slotAboutToShowNextMenu())); - connect(m_nextMenu, SIGNAL(triggered(QAction*)), this, - SLOT(slotOpenActionUrl(QAction*))); } back->setMenu(m_backMenu); next->setMenu(m_nextMenu); -#else - Q_UNUSED(back) - Q_UNUSED(next) - Q_UNUSED(parent) -#endif } Q_EXPORT_PLUGIN(HelpPlugin) diff --git a/src/plugins/help/helpplugin.h b/src/plugins/help/helpplugin.h index 76c5e4844f7..eb2dd506bea 100644 --- a/src/plugins/help/helpplugin.h +++ b/src/plugins/help/helpplugin.h @@ -78,6 +78,8 @@ public: void extensionsInitialized(); ShutdownFlag aboutToShutdown(); + static HelpViewer *createHelpViewer(qreal zoom); + private slots: void unregisterOldQtCreatorDocumentation(); @@ -114,11 +116,9 @@ private slots: void slotAboutToShowBackMenu(); void slotAboutToShowNextMenu(); - void slotOpenActionUrl(QAction *action); void slotOpenSupportPage(); void slotReportBug(); - void openFindToolBar(); void onSideBarVisibilityChanged(); void scaleRightPaneUp(); @@ -166,8 +166,6 @@ private: QToolButton *m_closeButton; - QString m_oldAttrValue; - QString m_styleProperty; QString m_idFromContext; Core::IMode* m_oldMode; diff --git a/src/plugins/help/helpviewer.cpp b/src/plugins/help/helpviewer.cpp index 50435be481d..4fbe7488ee7 100644 --- a/src/plugins/help/helpviewer.cpp +++ b/src/plugins/help/helpviewer.cpp @@ -85,6 +85,11 @@ struct ExtensionMap { { 0, 0 } }; +HelpViewer::HelpViewer(QWidget *parent) + : QWidget(parent) +{ +} + bool HelpViewer::isLocalUrl(const QUrl &url) { return url.scheme() == QLatin1String("about") // "No documenation available" @@ -155,11 +160,11 @@ void HelpViewer::slotLoadStarted() qApp->setOverrideCursor(QCursor(Qt::WaitCursor)); } -void HelpViewer::slotLoadFinished(bool ok) +void HelpViewer::slotLoadFinished() { - Q_UNUSED(ok) - emit sourceChanged(source()); qApp->restoreOverrideCursor(); + emit sourceChanged(source()); + emit loadFinished(); } bool HelpViewer::handleForwardBackwardMouseButtons(QMouseEvent *event) diff --git a/src/plugins/help/helpviewer.h b/src/plugins/help/helpviewer.h index 8a877c317b0..a50ed91cc3a 100644 --- a/src/plugins/help/helpviewer.h +++ b/src/plugins/help/helpviewer.h @@ -30,60 +30,56 @@ #ifndef HELPVIEWER_H #define HELPVIEWER_H -#include +#include -#include +#include +#include +#include #include #include -#include - -#include -#include - -#if defined(QT_NO_WEBKIT) -#include -#else -#include -#include -#endif +#include namespace Help { namespace Internal { -#if !defined(QT_NO_WEBKIT) -class HelpViewer : public QWebView -#else -class HelpViewer : public QTextBrowser -#endif +class HelpViewer : public QWidget { Q_OBJECT - class HelpViewerPrivate; public: - explicit HelpViewer(qreal zoom, QWidget *parent = 0); - ~HelpViewer(); + explicit HelpViewer(QWidget *parent = 0); + ~HelpViewer() { } - QFont viewerFont() const; - void setViewerFont(const QFont &font); + virtual QFont viewerFont() const = 0; + virtual void setViewerFont(const QFont &font) = 0; - void scaleUp(); - void scaleDown(); + virtual void scaleUp() = 0; + virtual void scaleDown() = 0; + virtual void resetScale() = 0; - void resetScale(); - qreal scale() const; + virtual qreal scale() const = 0; - QString title() const; - void setTitle(const QString &title); + virtual QString title() const = 0; + virtual void setTitle(const QString &title) = 0; - QUrl source() const; - void setSource(const QUrl &url); + virtual QUrl source() const = 0; + virtual void setSource(const QUrl &url) = 0; + virtual void scrollToAnchor(const QString &anchor) = 0; + virtual void highlightId(const QString &id) { Q_UNUSED(id) } - QString selectedText() const; - bool isForwardAvailable() const; - bool isBackwardAvailable() const; + virtual void setHtml(const QString &html) = 0; - bool findText(const QString &text, Core::FindFlags flags, - bool incremental, bool fromSearch, bool *wrapped = 0); + virtual QString selectedText() const = 0; + virtual bool isForwardAvailable() const = 0; + virtual bool isBackwardAvailable() const = 0; + virtual void addBackHistoryItems(QMenu *backMenu) = 0; + virtual void addForwardHistoryItems(QMenu *forwardMenu) = 0; + virtual void setOpenInNewWindowActionVisible(bool visible) = 0; + + virtual bool findText(const QString &text, Core::FindFlags flags, + bool incremental, bool fromSearch, bool *wrapped = 0) = 0; + + bool handleForwardBackwardMouseButtons(QMouseEvent *e); static bool isLocalUrl(const QUrl &url); static bool canOpenPage(const QString &url); @@ -91,77 +87,27 @@ public: static bool launchWithExternalApp(const QUrl &url); public slots: - void copy(); void home(); - void stop(); - void forward(); - void backward(); + virtual void copy() = 0; + virtual void stop() = 0; + virtual void forward() = 0; + virtual void backward() = 0; + virtual void print(QPrinter *printer) = 0; signals: + void sourceChanged(const QUrl &); void titleChanged(); void printRequested(); - void openFindToolBar(); + void forwardAvailable(bool); + void backwardAvailable(bool); + void loadFinished(); -#if !defined(QT_NO_WEBKIT) - void sourceChanged(const QUrl &); - void forwardAvailable(bool enabled); - void backwardAvailable(bool enabled); -#else - 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(); +protected slots: void slotLoadStarted(); - void slotLoadFinished(bool ok); -#if !defined(QT_NO_WEBKIT) - void slotNetworkReplyFinished(QNetworkReply *reply); -#endif - -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; + void slotLoadFinished(); }; -#ifndef QT_NO_WEBKIT -class HelpPage : public QWebPage -{ - Q_OBJECT -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 slots: - void onHandleUnsupportedContent(QNetworkReply *reply); - -private: - QUrl m_loadingUrl; - bool closeNewTabIfNeeded; - - friend class Help::Internal::HelpViewer; - Qt::MouseButtons m_pressedButtons; - Qt::KeyboardModifiers m_keyboardModifiers; -}; -#endif // QT_NO_WEBKIT - } // namespace Internal } // namespace Help diff --git a/src/plugins/help/helpviewer_p.h b/src/plugins/help/helpviewer_p.h deleted file mode 100644 index 647b8a944b8..00000000000 --- a/src/plugins/help/helpviewer_p.h +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** 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, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef HELPVIEWERPRIVATE_H -#define HELPVIEWERPRIVATE_H - -#include "centralwidget.h" -#include "helpviewer.h" -#include "openpagesmanager.h" - -#include -#include - -namespace Help { - namespace Internal { - -class HelpViewer::HelpViewerPrivate : public QObject -{ - Q_OBJECT - -public: - HelpViewerPrivate(int zoom) - : zoomCount(zoom) - , forceFont(false) - , lastAnchor(QString()) - - {} - - 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; -}; - - } // namespace Help -} // namespace Internal - -#endif // HELPVIEWERPRIVATE_H diff --git a/src/plugins/help/helpviewer_qtb.cpp b/src/plugins/help/helpviewer_qtb.cpp deleted file mode 100644 index 5d32394f490..00000000000 --- a/src/plugins/help/helpviewer_qtb.cpp +++ /dev/null @@ -1,379 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** 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, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "helpviewer.h" - -#if defined(QT_NO_WEBKIT) - -#include "helpconstants.h" -#include "helpviewer_p.h" -#include "localhelpmanager.h" - -#include - -#include -#include -#include -#include -#include - -#include - -using namespace Help; -using namespace Help::Internal; - -// -- HelpViewer - -HelpViewer::HelpViewer(qreal zoom, QWidget *parent) - : QTextBrowser(parent) - , d(new HelpViewerPrivate(zoom)) -{ - 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(slotLoadFinished(bool))); -} - -HelpViewer::~HelpViewer() -{ - delete d; -} - -QFont HelpViewer::viewerFont() const -{ - const QHelpEngineCore &engine = LocalHelpManager::helpEngine(); - return qvariant_cast(engine.customValue(QLatin1String("font"), - qApp->font())); -} - -void HelpViewer::setViewerFont(const QFont &newFont) -{ - if (font() != newFont) { - d->forceFont = true; - setFont(newFont); - d->forceFont = false; - } -} - -void HelpViewer::scaleUp() -{ - if (d->zoomCount < 10) { - d->zoomCount++; - d->forceFont = true; - zoomIn(); - d->forceFont = false; - } -} - -void HelpViewer::scaleDown() -{ - if (d->zoomCount > -5) { - d->zoomCount--; - d->forceFont = true; - zoomOut(); - d->forceFont = false; - } -} - -void HelpViewer::resetScale() -{ - if (d->zoomCount != 0) { - d->forceFont = true; - zoomOut(d->zoomCount); - d->forceFont = false; - } - d->zoomCount = 0; -} - -qreal HelpViewer::scale() const -{ - return d->zoomCount; -} - -QString HelpViewer::title() const -{ - return documentTitle(); -} - -void HelpViewer::setTitle(const QString &title) -{ - setDocumentTitle(title); -} - -QUrl HelpViewer::source() const -{ - return QTextBrowser::source(); -} - -void HelpViewer::setSource(const QUrl &url) -{ - const QString &string = url.toString(); - if (url.isValid() && string != QLatin1String("help")) { - if (launchWithExternalApp(url)) - return; - - QUrl resolvedUrl; - if (url.scheme() == QLatin1String("http")) - resolvedUrl = url; - - if (!resolvedUrl.isValid()) { - const QHelpEngineCore &engine = LocalHelpManager::helpEngine(); - resolvedUrl = engine.findFile(url); - } - - if (resolvedUrl.isValid()) { - QTextBrowser::setSource(resolvedUrl); - emit loadFinished(true); - return; - } - } - - QTextBrowser::setSource(url); - setHtml(string == Help::Constants::AboutBlank - ? HelpViewer::tr("about:blank") - : HelpViewer::tr("Error 404..." - "


The page could not be found

" - "

\"%1\"

") - .arg(url.toString())); - - emit loadFinished(true); -} - -QString HelpViewer::selectedText() const -{ - return textCursor().selectedText(); -} - -bool HelpViewer::isForwardAvailable() const -{ - return QTextBrowser::isForwardAvailable(); -} - -bool HelpViewer::isBackwardAvailable() const -{ - return QTextBrowser::isBackwardAvailable(); -} - -bool HelpViewer::findText(const QString &text, Core::FindFlags flags, - bool incremental, bool fromSearch, bool *wrapped) -{ - if (wrapped) - *wrapped = false; - QTextDocument *doc = document(); - QTextCursor cursor = textCursor(); - if (!doc || cursor.isNull()) - return false; - - const int position = cursor.selectionStart(); - if (incremental) - cursor.setPosition(position); - - QTextDocument::FindFlags f = Core::textDocumentFlagsForFindFlags(flags); - QTextCursor found = doc->find(text, cursor, f); - if (found.isNull()) { - if ((flags & Core::FindBackward) == 0) - cursor.movePosition(QTextCursor::Start); - else - cursor.movePosition(QTextCursor::End); - found = doc->find(text, cursor, f); - if (!found.isNull() && wrapped) - *wrapped = true; - } - - 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() -{ - QTextBrowser::copy(); -} - -void HelpViewer::stop() -{ -} - -void HelpViewer::forward() -{ - QTextBrowser::forward(); -} - -void HelpViewer::backward() -{ - QTextBrowser::backward(); -} - -// -- protected - -void HelpViewer::keyPressEvent(QKeyEvent *e) -{ - 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) -{ - if (e->modifiers() == Qt::ControlModifier) { - e->accept(); - e->delta() > 0 ? scaleUp() : scaleDown(); - } else { - QTextBrowser::wheelEvent(e); - } -} - -void HelpViewer::mousePressEvent(QMouseEvent *e) -{ - if (Utils::HostOsInfo::isLinuxHost() && handleForwardBackwardMouseButtons(e)) - return; - QTextBrowser::mousePressEvent(e); -} - -void HelpViewer::mouseReleaseEvent(QMouseEvent *e) -{ - if (!Utils::HostOsInfo::isLinuxHost() && handleForwardBackwardMouseButtons(e)) - return; - - 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 -} - -// -- private - -bool HelpViewer::eventFilter(QObject *obj, QEvent *event) -{ - if (event->type() == QEvent::FontChange && !d->forceFont) - return true; - - if (event->type() == QEvent::KeyPress) { - if (QKeyEvent *keyEvent = static_cast (event)) { - if (keyEvent->key() == Qt::Key_Slash) - emit openFindToolBar(); - } - } - return QTextBrowser::eventFilter(obj, event); -} - -void HelpViewer::contextMenuEvent(QContextMenuEvent *event) -{ - QMenu menu(QLatin1String(""), 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 as New Page"), d, SLOT(openLinkInNewPage())); - - if (!link.isEmpty() && link.isValid()) - copyAnchorAction = menu.addAction(tr("Copy Link")); - } 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) -{ - QByteArray ba; - if (type < 4) { - const QHelpEngineCore &engine = LocalHelpManager::helpEngine(); - ba = engine.fileData(name); - if (name.toString().endsWith(QLatin1String(".svg"), Qt::CaseInsensitive)) { - QImage image; - image.loadFromData(ba, "svg"); - if (!image.isNull()) - return image; - } - } - return ba; -} - -#endif // QT_NO_WEBKIT diff --git a/src/plugins/help/openpagesmodel.cpp b/src/plugins/help/openpagesmodel.cpp index f6aeaa3ceb1..a834769f3b6 100644 --- a/src/plugins/help/openpagesmodel.cpp +++ b/src/plugins/help/openpagesmodel.cpp @@ -28,6 +28,7 @@ ****************************************************************************/ #include "openpagesmodel.h" +#include "helpplugin.h" #include "helpviewer.h" #include @@ -72,7 +73,7 @@ QVariant OpenPagesModel::data(const QModelIndex &index, int role) const void OpenPagesModel::addPage(const QUrl &url, qreal zoom) { beginInsertRows(QModelIndex(), rowCount(), rowCount()); - HelpViewer *page = new HelpViewer(zoom); + HelpViewer *page = HelpPlugin::createHelpViewer(zoom); connect(page, SIGNAL(titleChanged()), this, SLOT(handleTitleChanged())); m_pages << page; endInsertRows(); diff --git a/src/plugins/help/helpviewer_qwv.cpp b/src/plugins/help/qtwebkithelpviewer.cpp similarity index 68% rename from src/plugins/help/helpviewer_qwv.cpp rename to src/plugins/help/qtwebkithelpviewer.cpp index d8301084a8c..0d1c0164610 100644 --- a/src/plugins/help/helpviewer_qwv.cpp +++ b/src/plugins/help/qtwebkithelpviewer.cpp @@ -27,23 +27,27 @@ ** ****************************************************************************/ -#include "helpviewer.h" +#include "qtwebkithelpviewer.h" #if !defined(QT_NO_WEBKIT) -#include "centralwidget.h" #include "helpconstants.h" #include "localhelpmanager.h" #include "openpagesmanager.h" +#include #include +#include +#include #include -#include #include #include #include +#include +#include #include +#include #include #include @@ -205,8 +209,10 @@ HelpPage::HelpPage(QObject *parent) QWebPage *HelpPage::createWindow(QWebPage::WebWindowType) { - HelpPage* newPage = static_cast(OpenPagesManager::instance() - .createPage()->page()); + // TODO: ensure that we'll get a QtWebKitHelpViewer here + QtWebKitHelpViewer* viewer = static_cast(OpenPagesManager::instance() + .createPage()); + HelpPage *newPage = viewer->page(); newPage->closeNewTabIfNeeded = closeNewTabIfNeeded; closeNewTabIfNeeded = false; return newPage; @@ -299,8 +305,9 @@ void HelpPage::onHandleUnsupportedContent(QNetworkReply *reply) // -- HelpViewer -HelpViewer::HelpViewer(qreal zoom, QWidget *parent) - : QWebView(parent) +QtWebKitHelpWidget::QtWebKitHelpWidget(qreal zoom, QtWebKitHelpViewer *parent) + : QWebView(parent), + m_parent(parent) { setAcceptDrops(false); installEventFilter(this); @@ -326,21 +333,129 @@ HelpViewer::HelpViewer(qreal zoom, QWidget *parent) SLOT(actionChanged())); connect(pageAction(QWebPage::Forward), SIGNAL(changed()), this, SLOT(actionChanged())); - connect(this, SIGNAL(urlChanged(QUrl)), this, SIGNAL(sourceChanged(QUrl))); - connect(this, SIGNAL(loadStarted()), this, SLOT(slotLoadStarted())); - connect(this, SIGNAL(loadFinished(bool)), this, SLOT(slotLoadFinished(bool))); - connect(this, SIGNAL(titleChanged(QString)), this, SIGNAL(titleChanged())); - connect(page(), SIGNAL(printRequested(QWebFrame*)), this, SIGNAL(printRequested())); - setViewerFont(viewerFont()); setZoomFactor(zoom == 0.0 ? 1.0 : zoom); } -HelpViewer::~HelpViewer() +QtWebKitHelpWidget::~QtWebKitHelpWidget() { } -QFont HelpViewer::viewerFont() const +void QtWebKitHelpWidget::scaleUp() +{ + setZoomFactor(zoomFactor() + 0.1); +} + +void QtWebKitHelpWidget::scaleDown() +{ + setZoomFactor(qMax(qreal(0.0), zoomFactor() - qreal(0.1))); +} + +// -- public slots + +void QtWebKitHelpWidget::copy() +{ + triggerPageAction(QWebPage::Copy); +} + +// -- protected + +void QtWebKitHelpWidget::keyPressEvent(QKeyEvent *e) +{ + // 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 QtWebKitHelpWidget::wheelEvent(QWheelEvent *event) +{ + if (event->modifiers()& Qt::ControlModifier) { + event->accept(); + event->delta() > 0 ? scaleUp() : scaleDown(); + } else { + QWebView::wheelEvent(event); + } +} + +void QtWebKitHelpWidget::mousePressEvent(QMouseEvent *event) +{ + if (Utils::HostOsInfo::isLinuxHost() && m_parent->handleForwardBackwardMouseButtons(event)) + return; + + if (HelpPage *currentPage = static_cast(page())) { + currentPage->m_pressedButtons = event->buttons(); + currentPage->m_keyboardModifiers = event->modifiers(); + } + + QWebView::mousePressEvent(event); +} + +void QtWebKitHelpWidget::mouseReleaseEvent(QMouseEvent *event) +{ + if (!Utils::HostOsInfo::isLinuxHost() && m_parent->handleForwardBackwardMouseButtons(event)) + return; + + QWebView::mouseReleaseEvent(event); +} + +// -- private slots + +void QtWebKitHelpWidget::actionChanged() +{ + QAction *a = qobject_cast(sender()); + if (a == pageAction(QWebPage::Back)) + emit backwardAvailable(a->isEnabled()); + else if (a == pageAction(QWebPage::Forward)) + emit forwardAvailable(a->isEnabled()); +} + +void QtWebKitHelpWidget::slotNetworkReplyFinished(QNetworkReply *reply) +{ + if (reply && reply->error() != QNetworkReply::NoError) { + load(QUrl(Help::Constants::AboutBlank)); + setHtml(QString::fromLatin1(g_htmlPage).arg(g_percent1, reply->errorString(), + HelpViewer::tr("Error loading: %1").arg(reply->url().toString()), g_percent4, g_percent6, g_percent7, + QString())); + } +} + +// -- private + +bool QtWebKitHelpWidget::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::KeyPress) { + if (QKeyEvent *keyEvent = static_cast (event)) { + if (keyEvent->key() == Qt::Key_Slash) + Core::FindPlugin::instance()->openFindToolBar(Core::FindPlugin::FindForwardDirection); + } + } + return QWebView::eventFilter(obj, event); +} + +QtWebKitHelpViewer::QtWebKitHelpViewer(qreal zoom, QWidget *parent) + : HelpViewer(parent), + m_webView(new QtWebKitHelpWidget(zoom, this)) +{ + QVBoxLayout *layout = new QVBoxLayout; + setLayout(layout); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(m_webView, 10); + + connect(m_webView, SIGNAL(urlChanged(QUrl)), this, SIGNAL(sourceChanged(QUrl))); + connect(m_webView, SIGNAL(loadStarted()), this, SLOT(slotLoadStarted())); + connect(m_webView, SIGNAL(loadFinished(bool)), this, SLOT(slotLoadFinished())); + connect(m_webView, SIGNAL(titleChanged(QString)), this, SIGNAL(titleChanged())); + connect(m_webView->page(), SIGNAL(printRequested(QWebFrame*)), this, SIGNAL(printRequested())); + connect(m_webView, SIGNAL(backwardAvailable(bool)), this, SIGNAL(backwardAvailable(bool))); + connect(m_webView, SIGNAL(forwardAvailable(bool)), this, SIGNAL(forwardAvailable(bool))); + + setViewerFont(viewerFont()); +} + +QFont QtWebKitHelpViewer::viewerFont() const { QWebSettings* webSettings = QWebSettings::globalSettings(); QFont font(QApplication::font().family(), @@ -350,69 +465,140 @@ QFont HelpViewer::viewerFont() const font)); } -void HelpViewer::setViewerFont(const QFont &font) +void QtWebKitHelpViewer::setViewerFont(const QFont &font) { - QWebSettings *webSettings = settings(); + QWebSettings *webSettings = m_webView->settings(); webSettings->setFontFamily(QWebSettings::StandardFont, font.family()); webSettings->setFontSize(QWebSettings::DefaultFontSize, font.pointSize()); } -void HelpViewer::scaleUp() +void QtWebKitHelpViewer::scaleUp() { - setZoomFactor(zoomFactor() + 0.1); + m_webView->scaleUp(); } -void HelpViewer::scaleDown() +void QtWebKitHelpViewer::scaleDown() { - setZoomFactor(qMax(qreal(0.0), zoomFactor() - qreal(0.1))); + m_webView->scaleDown(); } -void HelpViewer::resetScale() +void QtWebKitHelpViewer::resetScale() { - setZoomFactor(1.0); + m_webView->setZoomFactor(1.0); } -qreal HelpViewer::scale() const +qreal QtWebKitHelpViewer::scale() const { - return zoomFactor(); + return m_webView->zoomFactor(); } -QString HelpViewer::title() const +QString QtWebKitHelpViewer::title() const { - return QWebView::title(); + return m_webView->title(); } -void HelpViewer::setTitle(const QString &title) +void QtWebKitHelpViewer::setTitle(const QString &title) { Q_UNUSED(title) } -QUrl HelpViewer::source() const +QUrl QtWebKitHelpViewer::source() const { - return url(); + return m_webView->url(); } -void HelpViewer::setSource(const QUrl &url) +void QtWebKitHelpViewer::setSource(const QUrl &url) { - load(url); + m_webView->load(url); } -QString HelpViewer::selectedText() const +void QtWebKitHelpViewer::scrollToAnchor(const QString &anchor) { - return QWebView::selectedText(); + m_webView->page()->mainFrame()->scrollToAnchor(anchor); } -bool HelpViewer::isForwardAvailable() const +void QtWebKitHelpViewer::highlightId(const QString &id) { - return pageAction(QWebPage::Forward)->isEnabled(); + const QWebElement &document = m_webView->page()->mainFrame()->documentElement(); + const QWebElementCollection &collection = document.findAll(QLatin1String("h3.fn a")); + + const QLatin1String property("background-color"); + foreach (const QWebElement &element, collection) { + const QString &name = element.attribute(QLatin1String("name")); + if (name.isEmpty()) + continue; + + if (m_oldHighlightId == name + || name.startsWith(m_oldHighlightId + QLatin1Char('-'))) { + QWebElement parent = element.parent(); + parent.setStyleProperty(property, m_oldHighlightStyle); + } + + if (id == name + || name.startsWith(id + QLatin1Char('-'))) { + QWebElement parent = element.parent(); + m_oldHighlightStyle = parent.styleProperty(property, + QWebElement::ComputedStyle); + parent.setStyleProperty(property, QLatin1String("yellow")); + } + } + m_oldHighlightId = id; } -bool HelpViewer::isBackwardAvailable() const +void QtWebKitHelpViewer::setHtml(const QString &html) { - return pageAction(QWebPage::Back)->isEnabled(); + m_webView->setHtml(html); } -bool HelpViewer::findText(const QString &text, Core::FindFlags flags, +QString QtWebKitHelpViewer::selectedText() const +{ + return m_webView->selectedText(); +} + +bool QtWebKitHelpViewer::isForwardAvailable() const +{ + return m_webView->pageAction(QWebPage::Forward)->isEnabled(); +} + +bool QtWebKitHelpViewer::isBackwardAvailable() const +{ + return m_webView->pageAction(QWebPage::Back)->isEnabled(); +} + +void QtWebKitHelpViewer::addBackHistoryItems(QMenu *backMenu) +{ + if (QWebHistory *history = m_webView->history()) { + QList items = history->backItems(history->count()); + for (int i = items.count() - 1; i >= 0; --i) { + QAction *action = new QAction(backMenu); + action->setText(items.at(i).title()); + action->setData(i); + connect(action, SIGNAL(triggered()), this, SLOT(goToBackHistoryItem())); + backMenu->addAction(action); + } + } +} + +void QtWebKitHelpViewer::addForwardHistoryItems(QMenu *forwardMenu) +{ + if (QWebHistory *history = m_webView->history()) { + QList items = history->forwardItems(history->count()); + for (int i = 0; i < items.count(); ++i) { + QAction *action = new QAction(forwardMenu); + action->setText(items.at(i).title()); + action->setData(i); + connect(action, SIGNAL(triggered()), this, SLOT(goToForwardHistoryItem())); + forwardMenu->addAction(action); + } + } +} + +void QtWebKitHelpViewer::setOpenInNewWindowActionVisible(bool visible) +{ + m_webView->pageAction(QWebPage::OpenLinkInNewWindow)->setVisible(visible); +} + +bool QtWebKitHelpViewer::findText(const QString &text, Core::FindFlags flags, bool incremental, bool fromSearch, bool *wrapped) { Q_UNUSED(incremental); @@ -425,121 +611,72 @@ bool HelpViewer::findText(const QString &text, Core::FindFlags flags, if (flags & Core::FindCaseSensitively) options |= QWebPage::FindCaseSensitively; - bool found = QWebView::findText(text, options); + bool found = m_webView->findText(text, options); if (!found) { options |= QWebPage::FindWrapsAroundDocument; - found = QWebView::findText(text, options); + found = m_webView->findText(text, options); if (found && wrapped) *wrapped = true; } options = QWebPage::HighlightAllOccurrences; - QWebView::findText(QLatin1String(""), options); // clear first - QWebView::findText(text, options); // force highlighting of all other matches + m_webView->findText(QLatin1String(""), options); // clear first + m_webView->findText(text, options); // force highlighting of all other matches return found; } -// -- public slots - -void HelpViewer::copy() +HelpPage *QtWebKitHelpViewer::page() const { - triggerPageAction(QWebPage::Copy); + return static_cast(m_webView->page()); } -void HelpViewer::stop() +void QtWebKitHelpViewer::copy() { - triggerPageAction(QWebPage::Stop); + m_webView->copy(); } -void HelpViewer::forward() +void QtWebKitHelpViewer::stop() { - QWebView::forward(); + m_webView->triggerPageAction(QWebPage::Stop); } -void HelpViewer::backward() +void QtWebKitHelpViewer::forward() { - back(); + m_webView->forward(); } -// -- protected - -void HelpViewer::keyPressEvent(QKeyEvent *e) +void QtWebKitHelpViewer::backward() { - // 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); + m_webView->back(); } -void HelpViewer::wheelEvent(QWheelEvent *event) +void QtWebKitHelpViewer::print(QPrinter *printer) { - if (event->modifiers()& Qt::ControlModifier) { - event->accept(); - event->delta() > 0 ? scaleUp() : scaleDown(); - } else { - QWebView::wheelEvent(event); - } + m_webView->print(printer); } -void HelpViewer::mousePressEvent(QMouseEvent *event) +void QtWebKitHelpViewer::goToBackHistoryItem() { - if (Utils::HostOsInfo::isLinuxHost() && handleForwardBackwardMouseButtons(event)) - return; - - if (HelpPage *currentPage = static_cast (page())) { - currentPage->m_pressedButtons = event->buttons(); - currentPage->m_keyboardModifiers = event->modifiers(); - } - - QWebView::mousePressEvent(event); + goToHistoryItem(/*forward=*/false); } -void HelpViewer::mouseReleaseEvent(QMouseEvent *event) +void QtWebKitHelpViewer::goToForwardHistoryItem() { - if (!Utils::HostOsInfo::isLinuxHost() && handleForwardBackwardMouseButtons(event)) - return; - - QWebView::mouseReleaseEvent(event); + goToHistoryItem(/*forward=*/true); } -// -- private slots - -void HelpViewer::actionChanged() +void QtWebKitHelpViewer::goToHistoryItem(bool forward) { - QAction *a = qobject_cast(sender()); - if (a == pageAction(QWebPage::Back)) - emit backwardAvailable(a->isEnabled()); - else if (a == pageAction(QWebPage::Forward)) - emit forwardAvailable(a->isEnabled()); -} - -void HelpViewer::slotNetworkReplyFinished(QNetworkReply *reply) -{ - if (reply && reply->error() != QNetworkReply::NoError) { - setSource(QUrl(Help::Constants::AboutBlank)); - setHtml(QString::fromLatin1(g_htmlPage).arg(g_percent1, reply->errorString(), - HelpViewer::tr("Error loading: %1").arg(reply->url().toString()), g_percent4, g_percent6, g_percent7, - QString())); - } -} - -// -- private - -bool HelpViewer::eventFilter(QObject *obj, QEvent *event) -{ - if (event->type() == QEvent::KeyPress) { - if (QKeyEvent *keyEvent = static_cast (event)) { - if (keyEvent->key() == Qt::Key_Slash) - emit openFindToolBar(); - } - } - return QWebView::eventFilter(obj, event); -} - -void HelpViewer::contextMenuEvent(QContextMenuEvent *event) -{ - QWebView::contextMenuEvent(event); + QAction *action = qobject_cast(sender()); + QTC_ASSERT(action, return); + QWebHistory *history = m_webView->history(); + QTC_ASSERT(history, return); + bool ok = false; + int index = action->data().toInt(&ok); + QTC_ASSERT(ok, return); + if (forward) + history->goToItem(history->forwardItems(history->count()).at(index)); + else + history->goToItem(history->backItems(history->count()).at(index)); } #endif // !QT_NO_WEBKIT diff --git a/src/plugins/help/qtwebkithelpviewer.h b/src/plugins/help/qtwebkithelpviewer.h new file mode 100644 index 00000000000..b6e9437545d --- /dev/null +++ b/src/plugins/help/qtwebkithelpviewer.h @@ -0,0 +1,165 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QTWEBKITHELPVIEWER_H +#define QTWEBKITHELPVIEWER_H + +#include "helpviewer.h" + +#ifndef QT_NO_WEBKIT + +#include +#include + +namespace Help { +namespace Internal { + +class HelpPage; +class QtWebKitHelpWidget; + +class QtWebKitHelpViewer : public HelpViewer +{ + Q_OBJECT +public: + explicit QtWebKitHelpViewer(qreal zoom, QWidget *parent = 0); + ~QtWebKitHelpViewer() { } + + 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); + void scrollToAnchor(const QString &anchor); + void highlightId(const QString &id); + + void setHtml(const QString &html); + + QString selectedText() const; + bool isForwardAvailable() const; + bool isBackwardAvailable() const; + void addBackHistoryItems(QMenu *backMenu); + void addForwardHistoryItems(QMenu *forwardMenu); + void setOpenInNewWindowActionVisible(bool visible); + + bool findText(const QString &text, Core::FindFlags flags, + bool incremental, bool fromSearch, bool *wrapped = 0); + + HelpPage *page() const; + +public slots: + void copy(); + void stop(); + void forward(); + void backward(); + void print(QPrinter *printer); + +private slots: + void goToBackHistoryItem(); + void goToForwardHistoryItem(); + void goToHistoryItem(bool forward); + +private: + QString m_oldHighlightId; + QString m_oldHighlightStyle; + QtWebKitHelpWidget *m_webView; +}; + +class QtWebKitHelpWidget : public QWebView +{ + Q_OBJECT + +public: + explicit QtWebKitHelpWidget(qreal zoom, QtWebKitHelpViewer *parent = 0); + ~QtWebKitHelpWidget(); + + void scaleUp(); + void scaleDown(); + +public slots: + void copy(); + +signals: + void forwardAvailable(bool enabled); + void backwardAvailable(bool enabled); + +protected: + void keyPressEvent(QKeyEvent *e); + void wheelEvent(QWheelEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + +private slots: + void actionChanged(); + void slotNetworkReplyFinished(QNetworkReply *reply); + +private: + bool eventFilter(QObject *obj, QEvent *event); + + QtWebKitHelpViewer *m_parent; +}; + +class HelpPage : public QWebPage +{ + Q_OBJECT +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 slots: + void onHandleUnsupportedContent(QNetworkReply *reply); + +private: + QUrl m_loadingUrl; + bool closeNewTabIfNeeded; + + friend class Help::Internal::QtWebKitHelpWidget; + Qt::MouseButtons m_pressedButtons; + Qt::KeyboardModifiers m_keyboardModifiers; +}; + +} // namespace Internal +} // namespace Help + +#endif // !QT_NO_WEBKIT + +#endif // QTWEBKITHELPVIEWER_H diff --git a/src/plugins/help/textbrowserhelpviewer.cpp b/src/plugins/help/textbrowserhelpviewer.cpp new file mode 100644 index 00000000000..746f556c011 --- /dev/null +++ b/src/plugins/help/textbrowserhelpviewer.cpp @@ -0,0 +1,440 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "textbrowserhelpviewer.h" + +#include "helpconstants.h" +#include "localhelpmanager.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace Help; +using namespace Help::Internal; + +// -- HelpViewer + +TextBrowserHelpViewer::TextBrowserHelpViewer(qreal zoom, QWidget *parent) + : HelpViewer(parent) + , m_textBrowser(new TextBrowserHelpWidget(zoom, this)) +{ + QVBoxLayout *layout = new QVBoxLayout; + setLayout(layout); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(m_textBrowser, 10); + 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); + + // ??? + QFont font = viewerFont(); + font.setPointSize(int(font.pointSize() + zoom)); + setViewerFont(font); + + connect(m_textBrowser, SIGNAL(sourceChanged(QUrl)), this, SIGNAL(titleChanged())); + connect(m_textBrowser, SIGNAL(forwardAvailable(bool)), this, SIGNAL(forwardAvailable(bool))); + connect(m_textBrowser, SIGNAL(backwardAvailable(bool)), this, SIGNAL(backwardAvailable(bool))); +} + +TextBrowserHelpViewer::~TextBrowserHelpViewer() +{ +} + +QFont TextBrowserHelpViewer::viewerFont() const +{ + const QHelpEngineCore &engine = LocalHelpManager::helpEngine(); + return qvariant_cast(engine.customValue(QLatin1String("font"), + qApp->font())); +} + +void TextBrowserHelpViewer::setViewerFont(const QFont &newFont) +{ + if (font() != newFont) { + m_textBrowser->forceFont = true; + m_textBrowser->setFont(newFont); + m_textBrowser->forceFont = false; + } +} + +void TextBrowserHelpViewer::scaleUp() +{ + m_textBrowser->scaleUp(); +} + +void TextBrowserHelpViewer::scaleDown() +{ + m_textBrowser->scaleDown(); +} + +void TextBrowserHelpViewer::resetScale() +{ + if (m_textBrowser->zoomCount != 0) { + m_textBrowser->forceFont = true; + m_textBrowser->zoomOut(m_textBrowser->zoomCount); + m_textBrowser->forceFont = false; + } + m_textBrowser->zoomCount = 0; +} + +qreal TextBrowserHelpViewer::scale() const +{ + return m_textBrowser->zoomCount; +} + +QString TextBrowserHelpViewer::title() const +{ + return m_textBrowser->documentTitle(); +} + +void TextBrowserHelpViewer::setTitle(const QString &title) +{ + m_textBrowser->setDocumentTitle(title); +} + +QUrl TextBrowserHelpViewer::source() const +{ + return m_textBrowser->source(); +} + +void TextBrowserHelpViewer::setSource(const QUrl &url) +{ + const QString &string = url.toString(); + if (url.isValid() && string != QLatin1String("help")) { + if (launchWithExternalApp(url)) + return; + + QUrl resolvedUrl; + if (url.scheme() == QLatin1String("http")) + resolvedUrl = url; + + if (!resolvedUrl.isValid()) { + const QHelpEngineCore &engine = LocalHelpManager::helpEngine(); + resolvedUrl = engine.findFile(url); + } + + if (resolvedUrl.isValid()) { + m_textBrowser->setSource(resolvedUrl); + slotLoadFinished(); + return; + } + } + + m_textBrowser->setSource(url); + m_textBrowser->setHtml(string == Help::Constants::AboutBlank + ? HelpViewer::tr("about:blank") + : HelpViewer::tr("Error 404..." + "


The page could not be found

" + "

\"%1\"

") + .arg(url.toString())); + + slotLoadFinished(); +} + +void TextBrowserHelpViewer::scrollToAnchor(const QString &anchor) +{ + m_textBrowser->scrollToAnchor(anchor); +} + +void TextBrowserHelpViewer::setHtml(const QString &html) +{ + m_textBrowser->setHtml(html); +} + +QString TextBrowserHelpViewer::selectedText() const +{ + return m_textBrowser->textCursor().selectedText(); +} + +bool TextBrowserHelpViewer::isForwardAvailable() const +{ + return m_textBrowser->isForwardAvailable(); +} + +bool TextBrowserHelpViewer::isBackwardAvailable() const +{ + return m_textBrowser->isBackwardAvailable(); +} + +void TextBrowserHelpViewer::setOpenInNewWindowActionVisible(bool visible) +{ + m_textBrowser->showOpenInNewWindowAction = visible; +} + +bool TextBrowserHelpViewer::findText(const QString &text, Core::FindFlags flags, + bool incremental, bool fromSearch, bool *wrapped) +{ + if (wrapped) + *wrapped = false; + QTextDocument *doc = m_textBrowser->document(); + QTextCursor cursor = m_textBrowser->textCursor(); + if (!doc || cursor.isNull()) + return false; + + const int position = cursor.selectionStart(); + if (incremental) + cursor.setPosition(position); + + QTextDocument::FindFlags f = Core::textDocumentFlagsForFindFlags(flags); + QTextCursor found = doc->find(text, cursor, f); + if (found.isNull()) { + if ((flags & Core::FindBackward) == 0) + cursor.movePosition(QTextCursor::Start); + else + cursor.movePosition(QTextCursor::End); + found = doc->find(text, cursor, f); + if (!found.isNull() && wrapped) + *wrapped = true; + } + + if (fromSearch) { + cursor.beginEditBlock(); + m_textBrowser->viewport()->setUpdatesEnabled(false); + + QTextCharFormat marker; + marker.setForeground(Qt::red); + cursor.movePosition(QTextCursor::Start); + m_textBrowser->setTextCursor(cursor); + + while (m_textBrowser->find(text)) { + QTextCursor hit = m_textBrowser->textCursor(); + hit.mergeCharFormat(marker); + } + + m_textBrowser->viewport()->setUpdatesEnabled(true); + cursor.endEditBlock(); + } + + bool cursorIsNull = found.isNull(); + if (cursorIsNull) { + found = m_textBrowser->textCursor(); + found.setPosition(position); + } + m_textBrowser->setTextCursor(found); + return !cursorIsNull; +} + +// -- public slots + +void TextBrowserHelpViewer::copy() +{ + m_textBrowser->copy(); +} + +void TextBrowserHelpViewer::stop() +{ +} + +void TextBrowserHelpViewer::forward() +{ + m_textBrowser->forward(); +} + +void TextBrowserHelpViewer::backward() +{ + m_textBrowser->backward(); +} + +void TextBrowserHelpViewer::print(QPrinter *printer) +{ + m_textBrowser->print(printer); +} + +// -- private + +TextBrowserHelpWidget::TextBrowserHelpWidget(int zoom, TextBrowserHelpViewer *parent) + : QTextBrowser(parent) + , zoomCount(zoom) + , forceFont(false) + , lastAnchor(QString()) + , showOpenInNewWindowAction(true) + , m_parent(parent) +{ + installEventFilter(this); + document()->setDocumentMargin(8); +} + +QVariant TextBrowserHelpWidget::loadResource(int type, const QUrl &name) +{ + QByteArray ba; + if (type < 4) { + const QHelpEngineCore &engine = LocalHelpManager::helpEngine(); + ba = engine.fileData(name); + if (name.toString().endsWith(QLatin1String(".svg"), Qt::CaseInsensitive)) { + QImage image; + image.loadFromData(ba, "svg"); + if (!image.isNull()) + return image; + } + } + return ba; +} + +bool TextBrowserHelpWidget::hasAnchorAt(const QPoint &pos) +{ + lastAnchor = anchorAt(pos); + if (lastAnchor.isEmpty()) + return false; + + lastAnchor = source().resolved(lastAnchor).toString(); + if (lastAnchor.at(0) == QLatin1Char('#')) { + QString src = source().toString(); + int hsh = src.indexOf(QLatin1Char('#')); + lastAnchor = (hsh >= 0 ? src.left(hsh) : src) + lastAnchor; + } + return true; +} + +void TextBrowserHelpWidget::openLink(bool newPage) +{ + if (lastAnchor.isEmpty()) + return; + if (newPage) + OpenPagesManager::instance().createPage(lastAnchor); + else + CentralWidget::instance()->setSource(lastAnchor); + lastAnchor.clear(); +} + +void TextBrowserHelpWidget::scaleUp() +{ + if (zoomCount < 10) { + zoomCount++; + forceFont = true; + zoomIn(); + forceFont = false; + } +} + +void TextBrowserHelpWidget::scaleDown() +{ + if (zoomCount > -5) { + zoomCount--; + forceFont = true; + zoomOut(); + forceFont = false; + } +} + +void TextBrowserHelpWidget::openLink() +{ + openLink(false); +} + +void TextBrowserHelpWidget::openLinkInNewPage() +{ + openLink(true); +} + +void TextBrowserHelpWidget::contextMenuEvent(QContextMenuEvent *event) +{ + QMenu menu(QLatin1String(""), 0); + + QUrl link; + QAction *copyAnchorAction = 0; + if (hasAnchorAt(event->pos())) { + link = anchorAt(event->pos()); + if (link.isRelative()) + link = source().resolved(link); + menu.addAction(tr("Open Link"), this, SLOT(openLink())); + if (showOpenInNewWindowAction) + menu.addAction(tr("Open Link as New Page"), this, SLOT(openLinkInNewPage())); + + if (!link.isEmpty() && link.isValid()) + copyAnchorAction = menu.addAction(tr("Copy Link")); + } else if (!textCursor().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()); +} + +bool TextBrowserHelpWidget::eventFilter(QObject *obj, QEvent *event) +{ + if (obj == this) { + if (event->type() == QEvent::FontChange) { + if (!forceFont) + return true; + } else if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + if (keyEvent->key() == Qt::Key_Slash) { + keyEvent->accept(); + Core::FindPlugin::instance()->openFindToolBar(Core::FindPlugin::FindForwardDirection); + return true; + } + } + } + return QTextBrowser::eventFilter(obj, event); +} + +void TextBrowserHelpWidget::wheelEvent(QWheelEvent *e) +{ + if (e->modifiers() == Qt::ControlModifier) { + e->accept(); + e->delta() > 0 ? scaleUp() : scaleDown(); + } else { + QTextBrowser::wheelEvent(e); + } +} + +void TextBrowserHelpWidget::mousePressEvent(QMouseEvent *e) +{ + if (Utils::HostOsInfo::isLinuxHost() && m_parent->handleForwardBackwardMouseButtons(e)) + return; + QTextBrowser::mousePressEvent(e); +} + +void TextBrowserHelpWidget::mouseReleaseEvent(QMouseEvent *e) +{ + if (!Utils::HostOsInfo::isLinuxHost() && m_parent->handleForwardBackwardMouseButtons(e)) + return; + + bool controlPressed = e->modifiers() & Qt::ControlModifier; + if ((controlPressed && hasAnchorAt(e->pos())) || + (e->button() == Qt::MidButton && hasAnchorAt(e->pos()))) { + openLinkInNewPage(); + return; + } + + QTextBrowser::mouseReleaseEvent(e); +} diff --git a/src/plugins/help/textbrowserhelpviewer.h b/src/plugins/help/textbrowserhelpviewer.h new file mode 100644 index 00000000000..f8ec7d36cce --- /dev/null +++ b/src/plugins/help/textbrowserhelpviewer.h @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef TEXTBROWSERHELPVIEWER_H +#define TEXTBROWSERHELPVIEWER_H + +#include "centralwidget.h" +#include "helpviewer.h" +#include "openpagesmanager.h" + +#include + +namespace Help { +namespace Internal { + +class TextBrowserHelpWidget; + +class TextBrowserHelpViewer : public HelpViewer +{ + Q_OBJECT + +public: + explicit TextBrowserHelpViewer(qreal zoom, QWidget *parent = 0); + ~TextBrowserHelpViewer(); + + 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); + void scrollToAnchor(const QString &anchor); + + void setHtml(const QString &html); + + QString selectedText() const; + bool isForwardAvailable() const; + bool isBackwardAvailable() const; + void addBackHistoryItems(QMenu *backMenu) { Q_UNUSED(backMenu) } + void addForwardHistoryItems(QMenu *forwardMenu) { Q_UNUSED(forwardMenu) } + void setOpenInNewWindowActionVisible(bool visible); + + bool findText(const QString &text, Core::FindFlags flags, + bool incremental, bool fromSearch, bool *wrapped = 0); + +public slots: + void copy(); + void stop(); + void forward(); + void backward(); + void print(QPrinter *printer); + +private: + QVariant loadResource(int type, const QUrl &name); + + TextBrowserHelpWidget *m_textBrowser; +}; + +class TextBrowserHelpWidget : public QTextBrowser +{ + Q_OBJECT + +public: + TextBrowserHelpWidget(int zoom, TextBrowserHelpViewer *parent); + + QVariant loadResource(int type, const QUrl &name); + + bool hasAnchorAt(const QPoint& pos); + void openLink(bool newPage); + void scaleUp(); + void scaleDown(); + +public slots: + void openLink(); + void openLinkInNewPage(); + +protected: + void contextMenuEvent(QContextMenuEvent *event); + bool eventFilter(QObject *obj, QEvent *event); + void wheelEvent(QWheelEvent *e); + void mousePressEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + +public: + int zoomCount; + bool forceFont; + QString lastAnchor; + bool showOpenInNewWindowAction; + TextBrowserHelpViewer *m_parent; +}; + +} // namespace Internal +} // namespace Help + +#endif // TEXTBROWSERHELPVIEWER_H