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 <eike.ziller@digia.com>
This commit is contained in:
Eike Ziller
2014-05-02 16:54:28 +02:00
parent 0ae6905525
commit 96e8f0bb7b
16 changed files with 1083 additions and 828 deletions

View File

@@ -0,0 +1,682 @@
/****************************************************************************
**
** 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 "qtwebkithelpviewer.h"
#if !defined(QT_NO_WEBKIT)
#include "helpconstants.h"
#include "localhelpmanager.h"
#include "openpagesmanager.h"
#include <coreplugin/find/findplugin.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <QAction>
#include <QDebug>
#include <QString>
#include <QStringBuilder>
#include <QTimer>
#include <QVBoxLayout>
#include <QWebElement>
#include <QWebFrame>
#include <QWebHistory>
#include <QApplication>
#include <QDesktopServices>
#include <QWheelEvent>
#include <QHelpEngine>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <utils/networkaccessmanager.h>
#include <cstring>
using namespace Core;
using namespace Help;
using namespace Help::Internal;
static const char g_htmlPage[] = "<html><head><meta http-equiv=\"content-type\" content=\"text/html; "
"charset=UTF-8\"><title>%1</title><style>body{padding: 3em 0em;background: #eeeeee;}"
"hr{color: lightgray;width: 100%;}img{float: left;opacity: .8;}#box{background: white;border: 1px solid "
"lightgray;width: 600px;padding: 60px;margin: auto;}h1{font-size: 130%;font-weight: bold;border-bottom: "
"1px solid lightgray;margin-left: 48px;}h2{font-size: 100%;font-weight: normal;border-bottom: 1px solid "
"lightgray;margin-left: 48px;}ul{font-size: 80%;padding-left: 48px;margin: 0;}#reloadButton{padding-left:"
"48px;}</style></head><body><div id=\"box\"><img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACA"
"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\" width=\"32\"height=\"32\" /><h1>%2</h1><h2>%3</h2>"
"<ul>%4%5%6%7</ul></div></body></html>";
// some of the values we will replace %1...6 inside the former html
const QString g_percent1 = QCoreApplication::translate("HelpViewer", "Error 404...");
const QString g_percent2 = QCoreApplication::translate("HelpViewer", "The page could not be found!");
// percent3 will be the url of the page we got the error from
const QString g_percent4 = QCoreApplication::translate("HelpViewer", "<li>Check that you have one or more "
"documentation sets installed.</li>");
const QString g_percent5 = QCoreApplication::translate("HelpViewer", "<li>Check that you have installed the "
"appropriate browser plug-in to support the file your loading.</li>");
const QString g_percent6 = QCoreApplication::translate("HelpViewer", "<li>If you try to access a public "
"URL, make sure to have a network connection.</li>");
const QString g_percent7 = QCoreApplication::translate("HelpViewer", "<li>If your computer or network is "
"protected by a firewall or proxy, make sure the application is permitted to access the network.</li>");
// -- 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 dataLength;
};
HelpNetworkReply::HelpNetworkReply(const QNetworkRequest &request,
const QByteArray &fileData, const QString& mimeType)
: data(fileData)
, dataLength(fileData.length())
{
setRequest(request);
setUrl(request.url());
setOpenMode(QIODevice::ReadOnly);
setHeader(QNetworkRequest::ContentTypeHeader, mimeType);
setHeader(QNetworkRequest::ContentLengthHeader, QByteArray::number(dataLength));
QTimer::singleShot(0, this, SIGNAL(metaDataChanged()));
QTimer::singleShot(0, this, SIGNAL(readyRead()));
QTimer::singleShot(0, this, SIGNAL(finished()));
}
qint64 HelpNetworkReply::readData(char *buffer, qint64 maxlen)
{
qint64 len = qMin(qint64(data.length()), maxlen);
if (len) {
std::memcpy(buffer, data.constData(), len);
data.remove(0, len);
}
return len;
}
// -- HelpNetworkAccessManager
class HelpNetworkAccessManager : public Utils::NetworkAccessManager
{
public:
HelpNetworkAccessManager(QObject *parent);
protected:
virtual QNetworkReply *createRequest(Operation op,
const QNetworkRequest &request, QIODevice *outgoingData = 0);
};
HelpNetworkAccessManager::HelpNetworkAccessManager(QObject *parent)
: Utils::NetworkAccessManager(parent)
{
}
QNetworkReply *HelpNetworkAccessManager::createRequest(Operation op,
const QNetworkRequest &request, QIODevice* outgoingData)
{
if (!HelpViewer::isLocalUrl(request.url()))
return Utils::NetworkAccessManager::createRequest(op, request, outgoingData);
QString url = request.url().toString();
const QHelpEngineCore &engine = LocalHelpManager::helpEngine();
const QString &mimeType = HelpViewer::mimeFromUrl(url);
const QByteArray &data = engine.findFile(url).isValid() ? engine.fileData(url)
: QString::fromLatin1(g_htmlPage).arg(g_percent1, g_percent2, HelpViewer::tr("Error loading: %1")
.arg(url), g_percent4, g_percent6, g_percent7, QString()).toUtf8();
return new HelpNetworkReply(request, data, mimeType.isEmpty()
? QLatin1String("application/octet-stream") : mimeType);
}
// - HelpPage
HelpPage::HelpPage(QObject *parent)
: QWebPage(parent)
, closeNewTabIfNeeded(false)
, m_pressedButtons(Qt::NoButton)
, m_keyboardModifiers(Qt::NoModifier)
{
setForwardUnsupportedContent(true);
connect(this, SIGNAL(unsupportedContent(QNetworkReply*)), this,
SLOT(onHandleUnsupportedContent(QNetworkReply*)));
}
QWebPage *HelpPage::createWindow(QWebPage::WebWindowType)
{
// TODO: ensure that we'll get a QtWebKitHelpViewer here
QtWebKitHelpViewer* viewer = static_cast<QtWebKitHelpViewer *>(OpenPagesManager::instance()
.createPage());
HelpPage *newPage = viewer->page();
newPage->closeNewTabIfNeeded = closeNewTabIfNeeded;
closeNewTabIfNeeded = false;
return newPage;
}
void HelpPage::triggerAction(WebAction action, bool checked)
{
switch (action) {
case OpenLinkInNewWindow:
closeNewTabIfNeeded = true;
default: // fall through
QWebPage::triggerAction(action, checked);
break;
}
}
bool HelpPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request,
QWebPage::NavigationType type)
{
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;
}
if (frame == mainFrame())
m_loadingUrl = request.url();
return true;
}
void HelpPage::onHandleUnsupportedContent(QNetworkReply *reply)
{
// sub resource of this page
if (m_loadingUrl != reply->url()) {
qWarning() << "Resource" << reply->url().toEncoded() << "has unknown Content-Type, will be ignored.";
reply->deleteLater();
return;
}
// set a default error string we are going to display
QString errorString = HelpViewer::tr("Unknown or unsupported Content!");
if (reply->error() == QNetworkReply::NoError) {
// try to open the url using using the desktop service
if (QDesktopServices::openUrl(reply->url())) {
reply->deleteLater();
return;
}
// seems we failed, now we show the error page inside creator
} else {
errorString = reply->errorString();
}
// setup html
const QString html = QString::fromLatin1(g_htmlPage).arg(g_percent1, errorString,
HelpViewer::tr("Error loading: %1").arg(reply->url().toString()), g_percent4, g_percent5, g_percent6,
g_percent7);
// update the current layout
QList<QWebFrame*> frames;
frames.append(mainFrame());
while (!frames.isEmpty()) {
QWebFrame *frame = frames.takeFirst();
if (frame->url() == reply->url()) {
frame->setHtml(html, reply->url());
return;
}
QList<QWebFrame *> children = frame->childFrames();
foreach (QWebFrame *frame, children)
frames.append(frame);
}
if (m_loadingUrl == reply->url())
mainFrame()->setHtml(html, reply->url());
}
// -- HelpViewer
QtWebKitHelpWidget::QtWebKitHelpWidget(qreal zoom, QtWebKitHelpViewer *parent)
: QWebView(parent),
m_parent(parent)
{
setAcceptDrops(false);
installEventFilter(this);
QWebSettings::globalSettings()->setAttribute(QWebSettings::DnsPrefetchEnabled, true);
setPage(new HelpPage(this));
HelpNetworkAccessManager *manager = new HelpNetworkAccessManager(this);
page()->setNetworkAccessManager(manager);
connect(manager, SIGNAL(finished(QNetworkReply*)), this,
SLOT(slotNetworkReplyFinished(QNetworkReply*)));
QAction* action = pageAction(QWebPage::OpenLinkInNewWindow);
action->setText(tr("Open Link as 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()));
setZoomFactor(zoom == 0.0 ? 1.0 : zoom);
}
QtWebKitHelpWidget::~QtWebKitHelpWidget()
{
}
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<HelpPage*>(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<QAction *>(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<QKeyEvent*> (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(),
webSettings->fontSize(QWebSettings::DefaultFontSize));
const QHelpEngineCore &engine = LocalHelpManager::helpEngine();
return qvariant_cast<QFont>(engine.customValue(QLatin1String("font"),
font));
}
void QtWebKitHelpViewer::setViewerFont(const QFont &font)
{
QWebSettings *webSettings = m_webView->settings();
webSettings->setFontFamily(QWebSettings::StandardFont, font.family());
webSettings->setFontSize(QWebSettings::DefaultFontSize, font.pointSize());
}
void QtWebKitHelpViewer::scaleUp()
{
m_webView->scaleUp();
}
void QtWebKitHelpViewer::scaleDown()
{
m_webView->scaleDown();
}
void QtWebKitHelpViewer::resetScale()
{
m_webView->setZoomFactor(1.0);
}
qreal QtWebKitHelpViewer::scale() const
{
return m_webView->zoomFactor();
}
QString QtWebKitHelpViewer::title() const
{
return m_webView->title();
}
void QtWebKitHelpViewer::setTitle(const QString &title)
{
Q_UNUSED(title)
}
QUrl QtWebKitHelpViewer::source() const
{
return m_webView->url();
}
void QtWebKitHelpViewer::setSource(const QUrl &url)
{
m_webView->load(url);
}
void QtWebKitHelpViewer::scrollToAnchor(const QString &anchor)
{
m_webView->page()->mainFrame()->scrollToAnchor(anchor);
}
void QtWebKitHelpViewer::highlightId(const QString &id)
{
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;
}
void QtWebKitHelpViewer::setHtml(const QString &html)
{
m_webView->setHtml(html);
}
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<QWebHistoryItem> 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<QWebHistoryItem> 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);
Q_UNUSED(fromSearch);
if (wrapped)
*wrapped = false;
QWebPage::FindFlags options;
if (flags & Core::FindBackward)
options |= QWebPage::FindBackward;
if (flags & Core::FindCaseSensitively)
options |= QWebPage::FindCaseSensitively;
bool found = m_webView->findText(text, options);
if (!found) {
options |= QWebPage::FindWrapsAroundDocument;
found = m_webView->findText(text, options);
if (found && wrapped)
*wrapped = true;
}
options = QWebPage::HighlightAllOccurrences;
m_webView->findText(QLatin1String(""), options); // clear first
m_webView->findText(text, options); // force highlighting of all other matches
return found;
}
HelpPage *QtWebKitHelpViewer::page() const
{
return static_cast<HelpPage *>(m_webView->page());
}
void QtWebKitHelpViewer::copy()
{
m_webView->copy();
}
void QtWebKitHelpViewer::stop()
{
m_webView->triggerPageAction(QWebPage::Stop);
}
void QtWebKitHelpViewer::forward()
{
m_webView->forward();
}
void QtWebKitHelpViewer::backward()
{
m_webView->back();
}
void QtWebKitHelpViewer::print(QPrinter *printer)
{
m_webView->print(printer);
}
void QtWebKitHelpViewer::goToBackHistoryItem()
{
goToHistoryItem(/*forward=*/false);
}
void QtWebKitHelpViewer::goToForwardHistoryItem()
{
goToHistoryItem(/*forward=*/true);
}
void QtWebKitHelpViewer::goToHistoryItem(bool forward)
{
QAction *action = qobject_cast<QAction *>(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