summaryrefslogtreecommitdiff
path: root/Tools/QtTestBrowser
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-01-06 14:44:00 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2012-01-06 14:44:00 +0100
commit40736c5763bf61337c8c14e16d8587db021a87d4 (patch)
treeb17a9c00042ad89cb1308e2484491799aa14e9f8 /Tools/QtTestBrowser
downloadqtwebkit-40736c5763bf61337c8c14e16d8587db021a87d4.tar.gz
Imported WebKit commit 2ea9d364d0f6efa8fa64acf19f451504c59be0e4 (http://svn.webkit.org/repository/webkit/trunk@104285)
Diffstat (limited to 'Tools/QtTestBrowser')
-rw-r--r--Tools/QtTestBrowser/QtTestBrowser.pro56
-rw-r--r--Tools/QtTestBrowser/QtTestBrowser.qrc6
-rw-r--r--Tools/QtTestBrowser/cookiejar.cpp145
-rw-r--r--Tools/QtTestBrowser/cookiejar.h63
-rw-r--r--Tools/QtTestBrowser/favicon.pngbin0 -> 891 bytes
-rw-r--r--Tools/QtTestBrowser/fpstimer.cpp80
-rw-r--r--Tools/QtTestBrowser/fpstimer.h54
-rw-r--r--Tools/QtTestBrowser/launcherwindow.cpp1141
-rw-r--r--Tools/QtTestBrowser/launcherwindow.h245
-rw-r--r--Tools/QtTestBrowser/locationedit.cpp124
-rw-r--r--Tools/QtTestBrowser/locationedit.h68
-rw-r--r--Tools/QtTestBrowser/main.cpp377
-rw-r--r--Tools/QtTestBrowser/mainwindow.cpp241
-rw-r--r--Tools/QtTestBrowser/mainwindow.h81
-rw-r--r--Tools/QtTestBrowser/urlloader.cpp130
-rw-r--r--Tools/QtTestBrowser/urlloader.h71
-rw-r--r--Tools/QtTestBrowser/useragentlist.txt13
-rw-r--r--Tools/QtTestBrowser/utils.cpp88
-rw-r--r--Tools/QtTestBrowser/utils.h52
-rw-r--r--Tools/QtTestBrowser/webinspector.h55
-rw-r--r--Tools/QtTestBrowser/webpage.cpp220
-rw-r--r--Tools/QtTestBrowser/webpage.h69
-rw-r--r--Tools/QtTestBrowser/webview.cpp291
-rw-r--r--Tools/QtTestBrowser/webview.h131
24 files changed, 3801 insertions, 0 deletions
diff --git a/Tools/QtTestBrowser/QtTestBrowser.pro b/Tools/QtTestBrowser/QtTestBrowser.pro
new file mode 100644
index 000000000..8825b2152
--- /dev/null
+++ b/Tools/QtTestBrowser/QtTestBrowser.pro
@@ -0,0 +1,56 @@
+# -------------------------------------------------------------------
+# Project file for the QtTestBrowser binary
+#
+# See 'Tools/qmake/README' for an overview of the build system
+# -------------------------------------------------------------------
+
+TEMPLATE = app
+
+INCLUDEPATH += $${ROOT_WEBKIT_DIR}/Source/WebKit/qt/WebCoreSupport
+
+load(features)
+
+SOURCES += \
+ locationedit.cpp \
+ launcherwindow.cpp \
+ main.cpp \
+ mainwindow.cpp \
+ urlloader.cpp \
+ utils.cpp \
+ webpage.cpp \
+ webview.cpp \
+ fpstimer.cpp \
+ cookiejar.cpp
+
+HEADERS += \
+ locationedit.h \
+ launcherwindow.h \
+ mainwindow.h \
+ urlloader.h \
+ utils.h \
+ webinspector.h \
+ webpage.h \
+ webview.h \
+ fpstimer.h \
+ cookiejar.h
+
+
+CONFIG += uitools
+
+WEBKIT += webcore
+
+CONFIG += qtwebkit
+
+DESTDIR = $$ROOT_BUILD_DIR/bin
+
+QT += network
+
+macx:QT += xml
+haveQt(5): QT += printsupport widgets
+
+contains(DEFINES, HAVE_FONTCONFIG=1): PKGCONFIG += fontconfig
+
+contains(QT_CONFIG, opengl): QT += opengl
+
+RESOURCES += \
+ QtTestBrowser.qrc
diff --git a/Tools/QtTestBrowser/QtTestBrowser.qrc b/Tools/QtTestBrowser/QtTestBrowser.qrc
new file mode 100644
index 000000000..b6036e89d
--- /dev/null
+++ b/Tools/QtTestBrowser/QtTestBrowser.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/">
+ <file>useragentlist.txt</file>
+ <file>favicon.png</file>
+ </qresource>
+</RCC>
diff --git a/Tools/QtTestBrowser/cookiejar.cpp b/Tools/QtTestBrowser/cookiejar.cpp
new file mode 100644
index 000000000..22a8d17a2
--- /dev/null
+++ b/Tools/QtTestBrowser/cookiejar.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "cookiejar.h"
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
+#include <QStandardPaths>
+#else
+#include <QDesktopServices>
+#endif
+#include <QDir>
+#include <QTextStream>
+
+TestBrowserCookieJar::TestBrowserCookieJar(QObject* parent)
+ : QNetworkCookieJar(parent)
+ , m_storageEnabled(false)
+{
+ // We use a timer for the real disk write to avoid multiple IO
+ // syscalls in sequence (when loading pages which set multiple cookies).
+ m_timer.setInterval(10000);
+ m_timer.setSingleShot(true);
+ connect(&m_timer, SIGNAL(timeout()), this, SLOT(saveToDisk()));
+
+#ifndef QT_NO_DESKTOPSERVICES
+#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
+ QString path = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
+#else
+ QString path = QDesktopServices::storageLocation(QDesktopServices::CacheLocation);
+#endif
+#else
+ QString path = QDir::homePath() + "/.QtTestBrowser";
+#endif
+
+ QDir().mkpath(path);
+ m_file.setFileName(path + "/cookieJar");
+}
+
+TestBrowserCookieJar::~TestBrowserCookieJar()
+{
+ if (m_storageEnabled) {
+ extractRawCookies();
+ saveToDisk();
+ }
+}
+
+bool TestBrowserCookieJar::setCookiesFromUrl(const QList<QNetworkCookie>& cookieList, const QUrl& url)
+{
+ bool status = QNetworkCookieJar::setCookiesFromUrl(cookieList, url);
+ if (status && m_storageEnabled)
+ scheduleSaveToDisk();
+ return status;
+}
+
+void TestBrowserCookieJar::setDiskStorageEnabled(bool enabled)
+{
+ m_storageEnabled = enabled;
+
+ if (enabled && allCookies().isEmpty())
+ loadFromDisk();
+
+ // When disabling, save current cookies.
+ if (!enabled && !allCookies().isEmpty())
+ scheduleSaveToDisk();
+}
+
+void TestBrowserCookieJar::scheduleSaveToDisk()
+{
+ // We extract the raw cookies here because the user may
+ // enable/disable/clear cookies while the timer is running.
+ extractRawCookies();
+ m_timer.start();
+}
+
+void TestBrowserCookieJar::extractRawCookies()
+{
+ QList<QNetworkCookie> cookies = allCookies();
+ m_rawCookies.clear();
+
+ foreach (const QNetworkCookie &cookie, cookies) {
+ if (!cookie.isSessionCookie())
+ m_rawCookies.append(cookie.toRawForm());
+ }
+}
+
+void TestBrowserCookieJar::saveToDisk()
+{
+ m_timer.stop();
+
+ if (m_file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ QTextStream out(&m_file);
+ foreach (const QByteArray &cookie, m_rawCookies)
+ out << cookie + "\n";
+ m_file.close();
+ } else
+ qWarning("IO error handling cookiejar file");
+}
+
+void TestBrowserCookieJar::loadFromDisk()
+{
+ if (!m_file.exists())
+ return;
+
+ QList<QNetworkCookie> cookies;
+
+ if (m_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ QTextStream in(&m_file);
+ while (!in.atEnd())
+ cookies.append(QNetworkCookie::parseCookies(in.readLine().toUtf8()));
+ m_file.close();
+ } else
+ qWarning("IO error handling cookiejar file");
+
+ setAllCookies(cookies);
+}
+
+void TestBrowserCookieJar::reset()
+{
+ setAllCookies(QList<QNetworkCookie>());
+ if (m_storageEnabled)
+ scheduleSaveToDisk();
+}
diff --git a/Tools/QtTestBrowser/cookiejar.h b/Tools/QtTestBrowser/cookiejar.h
new file mode 100644
index 000000000..ad6bd3cb9
--- /dev/null
+++ b/Tools/QtTestBrowser/cookiejar.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef cookiejar_h
+#define cookiejar_h
+
+#include <QFile>
+#include <QNetworkCookieJar>
+#include <QTimer>
+
+class TestBrowserCookieJar : public QNetworkCookieJar {
+ Q_OBJECT
+
+public:
+ TestBrowserCookieJar(QObject* parent = 0);
+ virtual ~TestBrowserCookieJar();
+
+ virtual bool setCookiesFromUrl(const QList<QNetworkCookie>&, const QUrl&);
+
+ void setDiskStorageEnabled(bool);
+
+public slots:
+ void scheduleSaveToDisk();
+ void loadFromDisk();
+ void reset();
+
+private slots:
+ void saveToDisk();
+
+private:
+ void extractRawCookies();
+
+ QList<QByteArray> m_rawCookies;
+ bool m_storageEnabled;
+ QFile m_file;
+ QTimer m_timer;
+};
+
+#endif
diff --git a/Tools/QtTestBrowser/favicon.png b/Tools/QtTestBrowser/favicon.png
new file mode 100644
index 000000000..4462752a5
--- /dev/null
+++ b/Tools/QtTestBrowser/favicon.png
Binary files differ
diff --git a/Tools/QtTestBrowser/fpstimer.cpp b/Tools/QtTestBrowser/fpstimer.cpp
new file mode 100644
index 000000000..eae3d9c00
--- /dev/null
+++ b/Tools/QtTestBrowser/fpstimer.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "fpstimer.h"
+
+#include <QDateTime>
+#include <QTimerEvent>
+
+// We save a maximum of 10000 frames, and purge 2000 at a time
+#define MAX_FRAMES_SAVED 10000
+#define FRAMES_TO_PURGE_WHEN_FULL 2000
+// 60 FPS
+#define FPS_MEASURE_INTERVAL 1000 / 60
+
+FpsTimer::FpsTimer(QObject* parent)
+ : QObject(parent)
+ , m_timer(0)
+{
+}
+
+int FpsTimer::numFrames(int spanMillis) const
+{
+ const QTime now = QTime::currentTime();
+
+ int count = 0;
+ for (int i = m_frames.length() - 1; i >= 0; --i, ++count) {
+ int msecs = m_frames[i].msecsTo(now);
+ if (msecs < 0)
+ msecs += 24 * 60 * 60 * 1000;
+ if (msecs > spanMillis)
+ break;
+ }
+ return count;
+}
+
+void FpsTimer::start()
+{
+ m_timer = startTimer(FPS_MEASURE_INTERVAL);
+}
+
+void FpsTimer::stop()
+{
+ if (!m_timer)
+ return;
+ killTimer(m_timer);
+ m_frames.clear();
+}
+
+void FpsTimer::timerEvent(QTimerEvent* event)
+{
+ if (event->timerId() != m_timer)
+ return;
+ m_frames.append(QTime::currentTime());
+ if (m_frames.length() > MAX_FRAMES_SAVED)
+ m_frames.erase(m_frames.begin(), m_frames.begin() + FRAMES_TO_PURGE_WHEN_FULL);
+}
diff --git a/Tools/QtTestBrowser/fpstimer.h b/Tools/QtTestBrowser/fpstimer.h
new file mode 100644
index 000000000..eed1198af
--- /dev/null
+++ b/Tools/QtTestBrowser/fpstimer.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef fpstimer_h
+#define fpstimer_h
+
+#include <QObject>
+#include <QSet>
+#include <QTime>
+
+class FpsTimer : public QObject {
+ Q_OBJECT
+
+public:
+ FpsTimer(QObject* parent = 0);
+ int numFrames(int spanMillis = 1000) const;
+
+public Q_SLOTS:
+ void start();
+ void stop();
+
+protected slots:
+ virtual void timerEvent(QTimerEvent*);
+
+private:
+ int m_timer;
+ QList<QTime> m_frames;
+};
+
+#endif // FPSMEASURE_H
diff --git a/Tools/QtTestBrowser/launcherwindow.cpp b/Tools/QtTestBrowser/launcherwindow.cpp
new file mode 100644
index 000000000..623a7efa1
--- /dev/null
+++ b/Tools/QtTestBrowser/launcherwindow.cpp
@@ -0,0 +1,1141 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 Kristof Kosztyo <Kosztyo.Kristof@stud.u-szeged.hu>
+ * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
+ * Copyright (C) 2006 George Staikos <staikos@kde.org>
+ * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "launcherwindow.h"
+#include "cookiejar.h"
+#include "urlloader.h"
+
+#include <QApplication>
+#include <QCheckBox>
+#include <QComboBox>
+#include <QCoreApplication>
+#include <QDialogButtonBox>
+#include <QInputDialog>
+#include <QLabel>
+#ifndef QT_NO_LINEEDIT
+#include <QLineEdit>
+#endif
+#ifndef QT_NO_SHORTCUT
+#include <QMenuBar>
+#endif
+#include <QSlider>
+#include <QSplitter>
+#include <QStatusBar>
+#include <QToolButton>
+#include <QToolTip>
+#include <QVBoxLayout>
+
+#if !defined(QT_NO_FILEDIALOG) && !defined(QT_NO_MESSAGEBOX)
+#include <QFileDialog>
+#include <QFileInfo>
+#include <QMessageBox>
+#include <QNetworkReply>
+#endif
+
+#if !defined(QT_NO_NETWORKDISKCACHE) && !defined(QT_NO_DESKTOPSERVICES)
+#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
+#include <QStandardPaths>
+#else
+#include <QDesktopServices>
+#endif
+#include <QtNetwork/QNetworkDiskCache>
+#endif
+
+const int gExitClickArea = 80;
+QVector<int> LauncherWindow::m_zoomLevels;
+
+static TestBrowserCookieJar* testBrowserCookieJarInstance()
+{
+ static TestBrowserCookieJar* cookieJar = new TestBrowserCookieJar(qApp);
+ return cookieJar;
+}
+
+LauncherWindow::LauncherWindow(WindowOptions* data, QGraphicsScene* sharedScene)
+ : MainWindow()
+ , m_currentZoom(100)
+ , m_urlLoader(0)
+ , m_view(0)
+ , m_inspector(0)
+ , m_formatMenuAction(0)
+ , m_zoomAnimation(0)
+#if !defined(QT_NO_FILEDIALOG) && !defined(QT_NO_MESSAGEBOX)
+ , m_reply(0)
+#endif
+#ifndef QT_NO_LINEEDIT
+ , m_findFlag(0)
+#endif
+{
+ if (data)
+ m_windowOptions = *data;
+
+ init();
+ if (sharedScene && data->useGraphicsView)
+ static_cast<QGraphicsView*>(m_view)->setScene(sharedScene);
+
+ createChrome();
+#if !defined(QT_NO_FILEDIALOG) && !defined(QT_NO_MESSAGEBOX)
+ connect(page(), SIGNAL(downloadRequested(const QNetworkRequest&)), this, SLOT(downloadRequest(const QNetworkRequest&)));
+#endif
+}
+
+LauncherWindow::~LauncherWindow()
+{
+ delete m_urlLoader;
+}
+
+void LauncherWindow::init()
+{
+ QSplitter* splitter = new QSplitter(Qt::Vertical, this);
+ setCentralWidget(splitter);
+
+ if (m_windowOptions.startMaximized)
+ setWindowState(windowState() | Qt::WindowMaximized);
+ else
+ resize(800, 600);
+
+ m_inspector = new WebInspector;
+#ifndef QT_NO_PROPERTIES
+ if (!m_windowOptions.inspectorUrl.isEmpty())
+ m_inspector->setProperty("_q_inspectorUrl", m_windowOptions.inspectorUrl);
+#endif
+ connect(this, SIGNAL(destroyed()), m_inspector, SLOT(deleteLater()));
+
+ // the zoom values are chosen to be like in Mozilla Firefox 3
+ if (!m_zoomLevels.count()) {
+ m_zoomLevels << 30 << 50 << 67 << 80 << 90;
+ m_zoomLevels << 100;
+ m_zoomLevels << 110 << 120 << 133 << 150 << 170 << 200 << 240 << 300;
+ }
+
+ initializeView();
+}
+
+void LauncherWindow::initializeView()
+{
+ delete m_view;
+
+ m_inputUrl = addressUrl();
+ QUrl url = page()->mainFrame()->url();
+ setPage(new WebPage(this));
+ setDiskCache(m_windowOptions.useDiskCache);
+ setUseDiskCookies(m_windowOptions.useDiskCookies);
+
+ // We reuse the same cookieJar on multiple QNAMs, which is OK.
+ QObject* cookieJarParent = testBrowserCookieJarInstance()->parent();
+ page()->networkAccessManager()->setCookieJar(testBrowserCookieJarInstance());
+ testBrowserCookieJarInstance()->setParent(cookieJarParent);
+
+ QSplitter* splitter = static_cast<QSplitter*>(centralWidget());
+
+ if (!m_windowOptions.useGraphicsView) {
+ WebViewTraditional* view = new WebViewTraditional(splitter);
+ view->setPage(page());
+
+ view->installEventFilter(this);
+
+ m_view = view;
+ } else {
+ WebViewGraphicsBased* view = new WebViewGraphicsBased(splitter);
+ m_view = view;
+#ifndef QT_NO_OPENGL
+ toggleQGLWidgetViewport(m_windowOptions.useQGLWidgetViewport);
+#endif
+ view->setPage(page());
+
+ connect(view, SIGNAL(currentFPSUpdated(int)), this, SLOT(updateFPS(int)));
+
+ view->installEventFilter(this);
+ // The implementation of QAbstractScrollArea::eventFilter makes us need
+ // to install the event filter also on the viewport of a QGraphicsView.
+ view->viewport()->installEventFilter(this);
+ }
+
+ m_touchMocking = false;
+
+ connect(page(), SIGNAL(loadStarted()), this, SLOT(loadStarted()));
+ connect(page(), SIGNAL(loadFinished(bool)), this, SLOT(loadFinished()));
+ connect(page(), SIGNAL(linkHovered(const QString&, const QString&, const QString&)),
+ this, SLOT(showLinkHover(const QString&, const QString&)));
+ connect(this, SIGNAL(enteredFullScreenMode(bool)), this, SLOT(toggleFullScreenMode(bool)));
+
+ if (m_windowOptions.printLoadedUrls)
+ connect(page()->mainFrame(), SIGNAL(urlChanged(QUrl)), this, SLOT(printURL(QUrl)));
+
+ applyPrefs();
+
+ splitter->addWidget(m_inspector);
+ m_inspector->setPage(page());
+ m_inspector->hide();
+
+ if (m_windowOptions.remoteInspectorPort)
+ page()->setProperty("_q_webInspectorServerPort", m_windowOptions.remoteInspectorPort);
+
+ if (url.isValid())
+ page()->mainFrame()->load(url);
+ else {
+ setAddressUrl(m_inputUrl);
+ m_inputUrl = QString();
+ }
+}
+
+void LauncherWindow::applyPrefs()
+{
+ QWebSettings* settings = page()->settings();
+ settings->setAttribute(QWebSettings::AcceleratedCompositingEnabled, m_windowOptions.useCompositing);
+ settings->setAttribute(QWebSettings::TiledBackingStoreEnabled, m_windowOptions.useTiledBackingStore);
+ settings->setAttribute(QWebSettings::FrameFlatteningEnabled, m_windowOptions.useFrameFlattening);
+ settings->setAttribute(QWebSettings::WebGLEnabled, m_windowOptions.useWebGL);
+
+ if (!isGraphicsBased())
+ return;
+
+ WebViewGraphicsBased* view = static_cast<WebViewGraphicsBased*>(m_view);
+ view->setViewportUpdateMode(m_windowOptions.viewportUpdateMode);
+ view->setFrameRateMeasurementEnabled(m_windowOptions.showFrameRate);
+ view->setItemCacheMode(m_windowOptions.cacheWebView ? QGraphicsItem::DeviceCoordinateCache : QGraphicsItem::NoCache);
+
+ if (m_windowOptions.resizesToContents)
+ toggleResizesToContents(m_windowOptions.resizesToContents);
+}
+
+void LauncherWindow::createChrome()
+{
+#ifndef QT_NO_SHORTCUT
+ QMenu* fileMenu = menuBar()->addMenu("&File");
+ fileMenu->addAction("New Window", this, SLOT(newWindow()), QKeySequence::New);
+ fileMenu->addAction(tr("Open File..."), this, SLOT(openFile()), QKeySequence::Open);
+ fileMenu->addAction(tr("Open Location..."), this, SLOT(openLocation()), QKeySequence(Qt::CTRL | Qt::Key_L));
+ fileMenu->addAction("Close Window", this, SLOT(close()), QKeySequence::Close);
+ fileMenu->addSeparator();
+ fileMenu->addAction("Take Screen Shot...", this, SLOT(screenshot()));
+#ifndef QT_NO_PRINTER
+ fileMenu->addAction(tr("Print..."), this, SLOT(print()), QKeySequence::Print);
+#endif
+ fileMenu->addSeparator();
+ fileMenu->addAction("Quit", QApplication::instance(), SLOT(closeAllWindows()), QKeySequence(Qt::CTRL | Qt::Key_Q));
+
+ QMenu* editMenu = menuBar()->addMenu("&Edit");
+ editMenu->addAction(page()->action(QWebPage::Undo));
+ editMenu->addAction(page()->action(QWebPage::Redo));
+ editMenu->addSeparator();
+ editMenu->addAction(page()->action(QWebPage::Cut));
+ editMenu->addAction(page()->action(QWebPage::Copy));
+ editMenu->addAction(page()->action(QWebPage::Paste));
+ editMenu->addSeparator();
+#ifndef QT_NO_LINEEDIT
+ editMenu->addAction("&Find", this, SLOT(showFindBar()), QKeySequence(Qt::CTRL | Qt::Key_F));
+ editMenu->addSeparator();
+#endif
+ QAction* setEditable = editMenu->addAction("Set Editable", this, SLOT(setEditable(bool)));
+ setEditable->setCheckable(true);
+
+ editMenu->addAction("Clear Cookies", this, SLOT(clearCookies()));
+
+ QMenu* viewMenu = menuBar()->addMenu("&View");
+ viewMenu->addAction(page()->action(QWebPage::Stop));
+ viewMenu->addAction(page()->action(QWebPage::Reload));
+ viewMenu->addSeparator();
+ QAction* zoomIn = viewMenu->addAction("Zoom &In", this, SLOT(zoomIn()));
+ QAction* zoomOut = viewMenu->addAction("Zoom &Out", this, SLOT(zoomOut()));
+ QAction* resetZoom = viewMenu->addAction("Reset Zoom", this, SLOT(resetZoom()));
+ QAction* zoomTextOnly = viewMenu->addAction("Zoom Text Only", this, SLOT(toggleZoomTextOnly(bool)));
+ zoomTextOnly->setCheckable(true);
+ zoomTextOnly->setChecked(false);
+ viewMenu->addSeparator();
+ viewMenu->addAction("Dump HTML", this, SLOT(dumpHtml()));
+ // viewMenu->addAction("Dump plugins", this, SLOT(dumpPlugins()));
+
+ zoomIn->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Plus));
+ zoomOut->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Minus));
+ resetZoom->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_0));
+
+ QMenu* formatMenu = new QMenu("F&ormat", this);
+ m_formatMenuAction = menuBar()->addMenu(formatMenu);
+ m_formatMenuAction->setVisible(false);
+ formatMenu->addAction(page()->action(QWebPage::ToggleBold));
+ formatMenu->addAction(page()->action(QWebPage::ToggleItalic));
+ formatMenu->addAction(page()->action(QWebPage::ToggleUnderline));
+ QMenu* writingMenu = formatMenu->addMenu(tr("Writing Direction"));
+ writingMenu->addAction(page()->action(QWebPage::SetTextDirectionDefault));
+ writingMenu->addAction(page()->action(QWebPage::SetTextDirectionLeftToRight));
+ writingMenu->addAction(page()->action(QWebPage::SetTextDirectionRightToLeft));
+
+ QMenu* windowMenu = menuBar()->addMenu("&Window");
+ QAction* toggleFullScreen = windowMenu->addAction("Toggle FullScreen", this, SIGNAL(enteredFullScreenMode(bool)));
+ toggleFullScreen->setShortcut(Qt::Key_F11);
+ toggleFullScreen->setCheckable(true);
+ toggleFullScreen->setChecked(false);
+ // When exit fullscreen mode by clicking on the exit area (bottom right corner) we must
+ // uncheck the Toggle FullScreen action.
+ toggleFullScreen->connect(this, SIGNAL(enteredFullScreenMode(bool)), SLOT(setChecked(bool)));
+
+ QWebSettings* settings = page()->settings();
+
+ QMenu* toolsMenu = menuBar()->addMenu("&Develop");
+ QMenu* graphicsViewMenu = toolsMenu->addMenu("QGraphicsView");
+ QAction* toggleGraphicsView = graphicsViewMenu->addAction("Toggle use of QGraphicsView", this, SLOT(toggleWebView(bool)));
+ toggleGraphicsView->setCheckable(true);
+ toggleGraphicsView->setChecked(isGraphicsBased());
+
+ QAction* toggleWebGL = toolsMenu->addAction("Toggle WebGL", this, SLOT(toggleWebGL(bool)));
+ toggleWebGL->setCheckable(true);
+ toggleWebGL->setChecked(settings->testAttribute(QWebSettings::WebGLEnabled));
+
+ QAction* spatialNavigationAction = toolsMenu->addAction("Toggle Spatial Navigation", this, SLOT(toggleSpatialNavigation(bool)));
+ spatialNavigationAction->setCheckable(true);
+ spatialNavigationAction->setShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_S));
+
+ QAction* toggleFrameFlattening = toolsMenu->addAction("Toggle Frame Flattening", this, SLOT(toggleFrameFlattening(bool)));
+ toggleFrameFlattening->setCheckable(true);
+ toggleFrameFlattening->setChecked(settings->testAttribute(QWebSettings::FrameFlatteningEnabled));
+
+ QAction* touchMockAction = toolsMenu->addAction("Toggle touch mocking", this, SLOT(setTouchMocking(bool)));
+ touchMockAction->setCheckable(true);
+ touchMockAction->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_T));
+
+ toolsMenu->addSeparator();
+
+ QAction* toggleLocalStorage = toolsMenu->addAction("Enable Local Storage", this, SLOT(toggleLocalStorage(bool)));
+ toggleLocalStorage->setCheckable(true);
+ toggleLocalStorage->setChecked(m_windowOptions.useLocalStorage);
+
+ QAction* toggleOfflineStorageDatabase = toolsMenu->addAction("Enable Offline Storage Database", this, SLOT(toggleOfflineStorageDatabase(bool)));
+ toggleOfflineStorageDatabase->setCheckable(true);
+ toggleOfflineStorageDatabase->setChecked(m_windowOptions.useOfflineStorageDatabase);
+
+ QAction* toggleOfflineWebApplicationCache = toolsMenu->addAction("Enable Offline Web Application Cache", this, SLOT(toggleOfflineWebApplicationCache(bool)));
+ toggleOfflineWebApplicationCache->setCheckable(true);
+ toggleOfflineWebApplicationCache->setChecked(m_windowOptions.useOfflineWebApplicationCache);
+
+ QAction* offlineStorageDefaultQuotaAction = toolsMenu->addAction("Set Offline Storage Default Quota Size", this, SLOT(setOfflineStorageDefaultQuota()));
+ offlineStorageDefaultQuotaAction->setCheckable(true);
+ offlineStorageDefaultQuotaAction->setChecked(m_windowOptions.offlineStorageDefaultQuotaSize);
+
+ toolsMenu->addSeparator();
+
+ QAction* userAgentAction = toolsMenu->addAction("Change User Agent", this, SLOT(showUserAgentDialog()));
+ userAgentAction->setShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_U));
+
+ toolsMenu->addAction("Select Elements...", this, SLOT(selectElements()));
+
+ QAction* showInspectorAction = toolsMenu->addAction("Show Web Inspector", m_inspector, SLOT(setVisible(bool)), QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_I));
+ showInspectorAction->setCheckable(true);
+ showInspectorAction->connect(m_inspector, SIGNAL(visibleChanged(bool)), SLOT(setChecked(bool)));
+ toolsMenu->addSeparator();
+ toolsMenu->addAction("Load URLs from file", this, SLOT(loadURLListFromFile()));
+
+ // GraphicsView sub menu.
+ QAction* toggleAcceleratedCompositing = graphicsViewMenu->addAction("Toggle Accelerated Compositing", this, SLOT(toggleAcceleratedCompositing(bool)));
+ toggleAcceleratedCompositing->setCheckable(true);
+ toggleAcceleratedCompositing->setChecked(settings->testAttribute(QWebSettings::AcceleratedCompositingEnabled));
+ toggleAcceleratedCompositing->setEnabled(isGraphicsBased());
+ toggleAcceleratedCompositing->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
+
+ QAction* toggleResizesToContents = graphicsViewMenu->addAction("Toggle Resizes To Contents Mode", this, SLOT(toggleResizesToContents(bool)));
+ toggleResizesToContents->setCheckable(true);
+ toggleResizesToContents->setChecked(m_windowOptions.resizesToContents);
+ toggleResizesToContents->setEnabled(isGraphicsBased());
+ toggleResizesToContents->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
+
+ QAction* toggleTiledBackingStore = graphicsViewMenu->addAction("Toggle Tiled Backing Store", this, SLOT(toggleTiledBackingStore(bool)));
+ toggleTiledBackingStore->setCheckable(true);
+ toggleTiledBackingStore->setChecked(m_windowOptions.useTiledBackingStore);
+ toggleTiledBackingStore->setEnabled(isGraphicsBased());
+ toggleTiledBackingStore->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
+
+#ifndef QT_NO_OPENGL
+ QAction* toggleQGLWidgetViewport = graphicsViewMenu->addAction("Toggle use of QGLWidget Viewport", this, SLOT(toggleQGLWidgetViewport(bool)));
+ toggleQGLWidgetViewport->setCheckable(true);
+ toggleQGLWidgetViewport->setChecked(m_windowOptions.useQGLWidgetViewport);
+ toggleQGLWidgetViewport->setEnabled(isGraphicsBased());
+ toggleQGLWidgetViewport->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
+#endif
+
+ QMenu* viewportUpdateMenu = graphicsViewMenu->addMenu("Change Viewport Update Mode");
+ viewportUpdateMenu->setEnabled(isGraphicsBased());
+ viewportUpdateMenu->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
+
+ QAction* fullUpdate = viewportUpdateMenu->addAction("FullViewportUpdate");
+ fullUpdate->setCheckable(true);
+ fullUpdate->setChecked((m_windowOptions.viewportUpdateMode == QGraphicsView::FullViewportUpdate) ? true : false);
+
+ QAction* minimalUpdate = viewportUpdateMenu->addAction("MinimalViewportUpdate");
+ minimalUpdate->setCheckable(true);
+ minimalUpdate->setChecked((m_windowOptions.viewportUpdateMode == QGraphicsView::MinimalViewportUpdate) ? true : false);
+
+ QAction* smartUpdate = viewportUpdateMenu->addAction("SmartViewportUpdate");
+ smartUpdate->setCheckable(true);
+ smartUpdate->setChecked((m_windowOptions.viewportUpdateMode == QGraphicsView::SmartViewportUpdate) ? true : false);
+
+ QAction* boundingRectUpdate = viewportUpdateMenu->addAction("BoundingRectViewportUpdate");
+ boundingRectUpdate->setCheckable(true);
+ boundingRectUpdate->setChecked((m_windowOptions.viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) ? true : false);
+
+ QAction* noUpdate = viewportUpdateMenu->addAction("NoViewportUpdate");
+ noUpdate->setCheckable(true);
+ noUpdate->setChecked((m_windowOptions.viewportUpdateMode == QGraphicsView::NoViewportUpdate) ? true : false);
+
+ QSignalMapper* signalMapper = new QSignalMapper(viewportUpdateMenu);
+ signalMapper->setMapping(fullUpdate, QGraphicsView::FullViewportUpdate);
+ signalMapper->setMapping(minimalUpdate, QGraphicsView::MinimalViewportUpdate);
+ signalMapper->setMapping(smartUpdate, QGraphicsView::SmartViewportUpdate);
+ signalMapper->setMapping(boundingRectUpdate, QGraphicsView::BoundingRectViewportUpdate);
+ signalMapper->setMapping(noUpdate, QGraphicsView::NoViewportUpdate);
+
+ connect(fullUpdate, SIGNAL(triggered()), signalMapper, SLOT(map()));
+ connect(minimalUpdate, SIGNAL(triggered()), signalMapper, SLOT(map()));
+ connect(smartUpdate, SIGNAL(triggered()), signalMapper, SLOT(map()));
+ connect(boundingRectUpdate, SIGNAL(triggered()), signalMapper, SLOT(map()));
+ connect(noUpdate, SIGNAL(triggered()), signalMapper, SLOT(map()));
+
+ connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(changeViewportUpdateMode(int)));
+
+ QActionGroup* viewportUpdateModeActions = new QActionGroup(viewportUpdateMenu);
+ viewportUpdateModeActions->addAction(fullUpdate);
+ viewportUpdateModeActions->addAction(minimalUpdate);
+ viewportUpdateModeActions->addAction(smartUpdate);
+ viewportUpdateModeActions->addAction(boundingRectUpdate);
+ viewportUpdateModeActions->addAction(noUpdate);
+
+ graphicsViewMenu->addSeparator();
+
+ QAction* flipAnimated = graphicsViewMenu->addAction("Animated Flip");
+ flipAnimated->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
+ flipAnimated->setEnabled(isGraphicsBased());
+ connect(flipAnimated, SIGNAL(triggered()), SLOT(animatedFlip()));
+
+ QAction* flipYAnimated = graphicsViewMenu->addAction("Animated Y-Flip");
+ flipYAnimated->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
+ flipYAnimated->setEnabled(isGraphicsBased());
+ connect(flipYAnimated, SIGNAL(triggered()), SLOT(animatedYFlip()));
+
+ QAction* cloneWindow = graphicsViewMenu->addAction("Clone Window", this, SLOT(cloneWindow()));
+ cloneWindow->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
+ cloneWindow->setEnabled(isGraphicsBased());
+
+ graphicsViewMenu->addSeparator();
+
+ QAction* showFPS = graphicsViewMenu->addAction("Show FPS", this, SLOT(showFPS(bool)));
+ showFPS->setCheckable(true);
+ showFPS->setEnabled(isGraphicsBased());
+ showFPS->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
+ showFPS->setChecked(m_windowOptions.showFrameRate);
+
+ QMenu* settingsMenu = menuBar()->addMenu("&Settings");
+
+#if !defined(QT_NO_NETWORKDISKCACHE) && !defined(QT_NO_DESKTOPSERVICES)
+ QAction* toggleDiskCache = settingsMenu->addAction("Use Disk Cache", this, SLOT(setDiskCache(bool)));
+ toggleDiskCache->setCheckable(true);
+ toggleDiskCache->setChecked(m_windowOptions.useDiskCache);
+#endif
+
+ QAction* toggleAutoLoadImages = settingsMenu->addAction("Disable Auto Load Images", this, SLOT(toggleAutoLoadImages(bool)));
+ toggleAutoLoadImages->setCheckable(true);
+ toggleAutoLoadImages->setChecked(false);
+
+ QAction* togglePlugins = settingsMenu->addAction("Disable Plugins", this, SLOT(togglePlugins(bool)));
+ togglePlugins->setCheckable(true);
+ togglePlugins->setChecked(false);
+
+ QAction* toggleInterruptingJavaScripteEnabled = settingsMenu->addAction("Enable interrupting js scripts", this, SLOT(toggleInterruptingJavaScriptEnabled(bool)));
+ toggleInterruptingJavaScripteEnabled->setCheckable(true);
+ toggleInterruptingJavaScripteEnabled->setChecked(false);
+
+ QAction* toggleJavascriptCanOpenWindows = settingsMenu->addAction("Enable js popup windows", this, SLOT(toggleJavascriptCanOpenWindows(bool)));
+ toggleJavascriptCanOpenWindows->setCheckable(true);
+ toggleJavascriptCanOpenWindows->setChecked(false);
+
+ QAction* toggleUseDiskCookies = settingsMenu->addAction("Save Cookies on Disk", this, SLOT(setUseDiskCookies(bool)));
+ toggleUseDiskCookies->setCheckable(true);
+ toggleUseDiskCookies->setChecked(m_windowOptions.useDiskCookies);
+
+#ifndef QT_NO_LINEEDIT
+ m_findBar = new QToolBar("Find", this);
+ addToolBar(Qt::BottomToolBarArea, m_findBar);
+
+ QToolButton* findClose = new QToolButton(m_findBar);
+ findClose->setText("X");
+ m_lineEdit = new QLineEdit(m_findBar);
+ m_lineEdit->setMaximumWidth(200);
+ QToolButton* findPrevious = new QToolButton(m_findBar);
+ findPrevious->setArrowType(Qt::LeftArrow);
+ QToolButton* findNext = new QToolButton(m_findBar);
+ findNext->setArrowType(Qt::RightArrow);
+ QCheckBox* findCaseSensitive = new QCheckBox("Case Sensitive", m_findBar);
+ QCheckBox* findWrapAround = new QCheckBox("Wrap Around", m_findBar);
+ QCheckBox* findHighLightAll = new QCheckBox("HighLight All", m_findBar);
+
+ QSignalMapper* findSignalMapper = new QSignalMapper(m_findBar);
+ findSignalMapper->setMapping(m_lineEdit, s_findNormalFlag);
+ findSignalMapper->setMapping(findPrevious, QWebPage::FindBackward);
+ findSignalMapper->setMapping(findNext, s_findNormalFlag);
+ findSignalMapper->setMapping(findCaseSensitive, QWebPage::FindCaseSensitively);
+ findSignalMapper->setMapping(findWrapAround, QWebPage::FindWrapsAroundDocument);
+ findSignalMapper->setMapping(findHighLightAll, QWebPage::HighlightAllOccurrences);
+
+ connect(findClose, SIGNAL(clicked()), this, SLOT(showFindBar()));
+ connect(m_lineEdit, SIGNAL(textChanged(const QString &)), findSignalMapper, SLOT(map()));
+ connect(findPrevious, SIGNAL(pressed()), findSignalMapper, SLOT(map()));
+ connect(findNext, SIGNAL(pressed()), findSignalMapper, SLOT(map()));
+ connect(findCaseSensitive, SIGNAL(stateChanged(int)), findSignalMapper, SLOT(map()));
+ connect(findWrapAround, SIGNAL(stateChanged(int)), findSignalMapper, SLOT(map()));
+ connect(findHighLightAll, SIGNAL(stateChanged(int)), findSignalMapper, SLOT(map()));
+
+ connect(findSignalMapper, SIGNAL(mapped(int)), this, SLOT(find(int)));
+
+ m_findBar->addWidget(findClose);
+ m_findBar->addWidget(m_lineEdit);
+ m_findBar->addWidget(findPrevious);
+ m_findBar->addWidget(findNext);
+ m_findBar->addWidget(findCaseSensitive);
+ m_findBar->addWidget(findWrapAround);
+ m_findBar->addWidget(findHighLightAll);
+ m_findBar->setMovable(false);
+ m_findBar->setVisible(false);
+#endif
+#endif
+}
+
+bool LauncherWindow::isGraphicsBased() const
+{
+ return bool(qobject_cast<QGraphicsView*>(m_view));
+}
+
+void LauncherWindow::sendTouchEvent()
+{
+ if (m_touchPoints.isEmpty())
+ return;
+
+ QEvent::Type type = QEvent::TouchUpdate;
+ if (m_touchPoints.size() == 1) {
+ if (m_touchPoints[0].state() == Qt::TouchPointReleased)
+ type = QEvent::TouchEnd;
+ else if (m_touchPoints[0].state() == Qt::TouchPointPressed)
+ type = QEvent::TouchBegin;
+ }
+
+ QTouchEvent touchEv(type);
+ touchEv.setTouchPoints(m_touchPoints);
+ QCoreApplication::sendEvent(page(), &touchEv);
+
+ // After sending the event, remove all touchpoints that were released
+ if (m_touchPoints[0].state() == Qt::TouchPointReleased)
+ m_touchPoints.removeAt(0);
+ if (m_touchPoints.size() > 1 && m_touchPoints[1].state() == Qt::TouchPointReleased)
+ m_touchPoints.removeAt(1);
+}
+
+bool LauncherWindow::eventFilter(QObject* obj, QEvent* event)
+{
+ // If click pos is the bottom right corner (square with size defined by gExitClickArea)
+ // and the window is on FullScreen, the window must return to its original state.
+ if (event->type() == QEvent::MouseButtonRelease) {
+ QMouseEvent* ev = static_cast<QMouseEvent*>(event);
+ if (windowState() == Qt::WindowFullScreen
+ && ev->pos().x() > (width() - gExitClickArea)
+ && ev->pos().y() > (height() - gExitClickArea)) {
+
+ emit enteredFullScreenMode(false);
+ }
+ }
+
+ if (!m_touchMocking)
+ return QObject::eventFilter(obj, event);
+
+ if (event->type() == QEvent::MouseButtonPress
+ || event->type() == QEvent::MouseButtonRelease
+ || event->type() == QEvent::MouseButtonDblClick
+ || event->type() == QEvent::MouseMove) {
+
+ QMouseEvent* ev = static_cast<QMouseEvent*>(event);
+ if (ev->type() == QEvent::MouseMove
+ && !(ev->buttons() & Qt::LeftButton))
+ return false;
+
+ QTouchEvent::TouchPoint touchPoint;
+ touchPoint.setState(Qt::TouchPointMoved);
+ if ((ev->type() == QEvent::MouseButtonPress
+ || ev->type() == QEvent::MouseButtonDblClick))
+ touchPoint.setState(Qt::TouchPointPressed);
+ else if (ev->type() == QEvent::MouseButtonRelease)
+ touchPoint.setState(Qt::TouchPointReleased);
+
+ touchPoint.setId(0);
+ touchPoint.setScreenPos(ev->globalPos());
+ touchPoint.setPos(ev->pos());
+ touchPoint.setPressure(1);
+
+ // If the point already exists, update it. Otherwise create it.
+ if (m_touchPoints.size() > 0 && !m_touchPoints[0].id())
+ m_touchPoints[0] = touchPoint;
+ else if (m_touchPoints.size() > 1 && !m_touchPoints[1].id())
+ m_touchPoints[1] = touchPoint;
+ else
+ m_touchPoints.append(touchPoint);
+
+ sendTouchEvent();
+ } else if (event->type() == QEvent::KeyPress
+ && static_cast<QKeyEvent*>(event)->key() == Qt::Key_F
+ && static_cast<QKeyEvent*>(event)->modifiers() == Qt::ControlModifier) {
+
+ // If the keyboard point is already pressed, release it.
+ // Otherwise create it and append to m_touchPoints.
+ if (m_touchPoints.size() > 0 && m_touchPoints[0].id() == 1) {
+ m_touchPoints[0].setState(Qt::TouchPointReleased);
+ sendTouchEvent();
+ } else if (m_touchPoints.size() > 1 && m_touchPoints[1].id() == 1) {
+ m_touchPoints[1].setState(Qt::TouchPointReleased);
+ sendTouchEvent();
+ } else {
+ QTouchEvent::TouchPoint touchPoint;
+ touchPoint.setState(Qt::TouchPointPressed);
+ touchPoint.setId(1);
+ touchPoint.setScreenPos(QCursor::pos());
+ touchPoint.setPos(m_view->mapFromGlobal(QCursor::pos()));
+ touchPoint.setPressure(1);
+ m_touchPoints.append(touchPoint);
+ sendTouchEvent();
+
+ // After sending the event, change the touchpoint state to stationary
+ m_touchPoints.last().setState(Qt::TouchPointStationary);
+ }
+ }
+
+ return false;
+}
+
+void LauncherWindow::loadStarted()
+{
+ m_view->setFocus(Qt::OtherFocusReason);
+}
+
+void LauncherWindow::loadFinished()
+{
+ QUrl url = page()->mainFrame()->url();
+ addCompleterEntry(url);
+ if (m_inputUrl.isEmpty())
+ setAddressUrl(url.toString(QUrl::RemoveUserInfo));
+ else {
+ setAddressUrl(m_inputUrl);
+ m_inputUrl = QString();
+ }
+}
+
+void LauncherWindow::showLinkHover(const QString &link, const QString &toolTip)
+{
+ statusBar()->showMessage(link);
+#ifndef QT_NO_TOOLTIP
+ if (!toolTip.isEmpty())
+ QToolTip::showText(QCursor::pos(), toolTip);
+#endif
+}
+
+void LauncherWindow::zoomAnimationFinished()
+{
+ if (!isGraphicsBased())
+ return;
+ QGraphicsWebView* view = static_cast<WebViewGraphicsBased*>(m_view)->graphicsWebView();
+ view->setTiledBackingStoreFrozen(false);
+}
+
+void LauncherWindow::applyZoom()
+{
+#ifndef QT_NO_ANIMATION
+ if (isGraphicsBased() && page()->settings()->testAttribute(QWebSettings::TiledBackingStoreEnabled)) {
+ QGraphicsWebView* view = static_cast<WebViewGraphicsBased*>(m_view)->graphicsWebView();
+ view->setTiledBackingStoreFrozen(true);
+ if (!m_zoomAnimation) {
+ m_zoomAnimation = new QPropertyAnimation(view, "scale");
+ m_zoomAnimation->setStartValue(view->scale());
+ connect(m_zoomAnimation, SIGNAL(finished()), this, SLOT(zoomAnimationFinished()));
+ } else {
+ m_zoomAnimation->stop();
+ m_zoomAnimation->setStartValue(m_zoomAnimation->currentValue());
+ }
+
+ m_zoomAnimation->setDuration(300);
+ m_zoomAnimation->setEndValue(qreal(m_currentZoom) / 100.);
+ m_zoomAnimation->start();
+ return;
+ }
+#endif
+ page()->mainFrame()->setZoomFactor(qreal(m_currentZoom) / 100.0);
+}
+
+void LauncherWindow::zoomIn()
+{
+ int i = m_zoomLevels.indexOf(m_currentZoom);
+ Q_ASSERT(i >= 0);
+ if (i < m_zoomLevels.count() - 1)
+ m_currentZoom = m_zoomLevels[i + 1];
+
+ applyZoom();
+}
+
+void LauncherWindow::zoomOut()
+{
+ int i = m_zoomLevels.indexOf(m_currentZoom);
+ Q_ASSERT(i >= 0);
+ if (i > 0)
+ m_currentZoom = m_zoomLevels[i - 1];
+
+ applyZoom();
+}
+
+void LauncherWindow::resetZoom()
+{
+ m_currentZoom = 100;
+ applyZoom();
+}
+
+void LauncherWindow::toggleZoomTextOnly(bool b)
+{
+ page()->settings()->setAttribute(QWebSettings::ZoomTextOnly, b);
+}
+
+void LauncherWindow::print()
+{
+#if !defined(QT_NO_PRINTER)
+ QPrintPreviewDialog dlg(this);
+ connect(&dlg, SIGNAL(paintRequested(QPrinter*)),
+ page()->mainFrame(), SLOT(print(QPrinter*)));
+ dlg.exec();
+#endif
+}
+
+void LauncherWindow::screenshot()
+{
+ QPixmap pixmap = QPixmap::grabWidget(m_view);
+ QLabel* label = 0;
+ label = new QLabel;
+ label->setAttribute(Qt::WA_DeleteOnClose);
+ label->setWindowTitle("Screenshot - Preview");
+ label->setPixmap(pixmap);
+ label->show();
+
+#ifndef QT_NO_FILEDIALOG
+ QString fileName = QFileDialog::getSaveFileName(label, "Screenshot");
+ if (!fileName.isEmpty()) {
+ pixmap.save(fileName, "png");
+ if (label)
+ label->setWindowTitle(QString("Screenshot - Saved at %1").arg(fileName));
+ }
+#endif
+
+#ifndef QT_NO_OPENGL
+ toggleQGLWidgetViewport(m_windowOptions.useQGLWidgetViewport);
+#endif
+}
+
+void LauncherWindow::setEditable(bool on)
+{
+ page()->setContentEditable(on);
+#ifndef QT_NO_SHORTCUT
+ m_formatMenuAction->setVisible(on);
+#endif
+}
+
+/*
+void LauncherWindow::dumpPlugins() {
+ QList<QWebPluginInfo> plugins = QWebSettings::pluginDatabase()->plugins();
+ foreach (const QWebPluginInfo plugin, plugins) {
+ qDebug() << "Plugin:" << plugin.name();
+ foreach (const QWebPluginInfo::MimeType mime, plugin.mimeTypes()) {
+ qDebug() << " " << mime.name;
+ }
+ }
+}
+*/
+
+void LauncherWindow::dumpHtml()
+{
+ qDebug() << "HTML: " << page()->mainFrame()->toHtml();
+}
+
+void LauncherWindow::selectElements()
+{
+#ifndef QT_NO_INPUTDIALOG
+ bool ok;
+ QString str = QInputDialog::getText(this, "Select elements", "Choose elements",
+ QLineEdit::Normal, "a", &ok);
+
+ if (ok && !str.isEmpty()) {
+ QWebElementCollection result = page()->mainFrame()->findAllElements(str);
+ foreach (QWebElement e, result)
+ e.setStyleProperty("background-color", "yellow");
+ statusBar()->showMessage(QString("%1 element(s) selected").arg(result.count()), 5000);
+ }
+#endif
+}
+
+void LauncherWindow::setDiskCache(bool enable)
+{
+#if !defined(QT_NO_NETWORKDISKCACHE) && !defined(QT_NO_DESKTOPSERVICES)
+ m_windowOptions.useDiskCache = enable;
+ QNetworkDiskCache* cache = 0;
+ if (enable) {
+ cache = new QNetworkDiskCache();
+#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
+ QString cacheLocation = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
+#else
+ QString cacheLocation = QDesktopServices::storageLocation(QDesktopServices::CacheLocation);
+#endif
+ cache->setCacheDirectory(cacheLocation);
+ }
+ page()->networkAccessManager()->setCache(cache);
+#endif
+}
+
+void LauncherWindow::setTouchMocking(bool on)
+{
+ m_touchMocking = on;
+}
+
+void LauncherWindow::toggleWebView(bool graphicsBased)
+{
+ m_windowOptions.useGraphicsView = graphicsBased;
+ initializeView();
+#ifndef QT_NO_SHORTCUT
+ menuBar()->clear();
+#endif
+ createChrome();
+}
+
+void LauncherWindow::toggleAcceleratedCompositing(bool toggle)
+{
+ m_windowOptions.useCompositing = toggle;
+ page()->settings()->setAttribute(QWebSettings::AcceleratedCompositingEnabled, toggle);
+}
+
+void LauncherWindow::toggleTiledBackingStore(bool toggle)
+{
+ page()->settings()->setAttribute(QWebSettings::TiledBackingStoreEnabled, toggle);
+}
+
+void LauncherWindow::toggleResizesToContents(bool toggle)
+{
+ m_windowOptions.resizesToContents = toggle;
+ static_cast<WebViewGraphicsBased*>(m_view)->setResizesToContents(toggle);
+}
+
+void LauncherWindow::toggleWebGL(bool toggle)
+{
+ m_windowOptions.useWebGL = toggle;
+ page()->settings()->setAttribute(QWebSettings::WebGLEnabled, toggle);
+}
+
+void LauncherWindow::animatedFlip()
+{
+ qobject_cast<WebViewGraphicsBased*>(m_view)->animatedFlip();
+}
+
+void LauncherWindow::animatedYFlip()
+{
+ qobject_cast<WebViewGraphicsBased*>(m_view)->animatedYFlip();
+}
+void LauncherWindow::toggleSpatialNavigation(bool b)
+{
+ page()->settings()->setAttribute(QWebSettings::SpatialNavigationEnabled, b);
+}
+
+void LauncherWindow::toggleFullScreenMode(bool enable)
+{
+ bool alreadyEnabled = windowState() & Qt::WindowFullScreen;
+ if (enable ^ alreadyEnabled)
+ setWindowState(windowState() ^ Qt::WindowFullScreen);
+}
+
+void LauncherWindow::toggleFrameFlattening(bool toggle)
+{
+ m_windowOptions.useFrameFlattening = toggle;
+ page()->settings()->setAttribute(QWebSettings::FrameFlatteningEnabled, toggle);
+}
+
+void LauncherWindow::toggleInterruptingJavaScriptEnabled(bool enable)
+{
+ page()->setInterruptingJavaScriptEnabled(enable);
+}
+
+void LauncherWindow::toggleJavascriptCanOpenWindows(bool enable)
+{
+ page()->settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, enable);
+}
+
+void LauncherWindow::setUseDiskCookies(bool enable)
+{
+ testBrowserCookieJarInstance()->setDiskStorageEnabled(enable);
+}
+
+void LauncherWindow::clearCookies()
+{
+ testBrowserCookieJarInstance()->reset();
+}
+
+void LauncherWindow::toggleAutoLoadImages(bool enable)
+{
+ page()->settings()->setAttribute(QWebSettings::AutoLoadImages, !enable);
+}
+
+void LauncherWindow::togglePlugins(bool enable)
+{
+ page()->settings()->setAttribute(QWebSettings::PluginsEnabled, !enable);
+}
+
+#ifndef QT_NO_OPENGL
+void LauncherWindow::toggleQGLWidgetViewport(bool enable)
+{
+ if (!isGraphicsBased())
+ return;
+
+ m_windowOptions.useQGLWidgetViewport = enable;
+ WebViewGraphicsBased* view = static_cast<WebViewGraphicsBased*>(m_view);
+
+ view->setViewport(enable ? new QGLWidget() : 0);
+}
+#endif
+
+void LauncherWindow::changeViewportUpdateMode(int mode)
+{
+ m_windowOptions.viewportUpdateMode = QGraphicsView::ViewportUpdateMode(mode);
+
+ if (!isGraphicsBased())
+ return;
+
+ WebViewGraphicsBased* view = static_cast<WebViewGraphicsBased*>(m_view);
+ view->setViewportUpdateMode(m_windowOptions.viewportUpdateMode);
+}
+
+void LauncherWindow::showFPS(bool enable)
+{
+ if (!isGraphicsBased())
+ return;
+
+ m_windowOptions.showFrameRate = enable;
+ WebViewGraphicsBased* view = static_cast<WebViewGraphicsBased*>(m_view);
+ view->setFrameRateMeasurementEnabled(enable);
+
+ if (!enable)
+ statusBar()->clearMessage();
+}
+
+void LauncherWindow::showUserAgentDialog()
+{
+ QStringList items;
+ QFile file(":/useragentlist.txt");
+ if (file.open(QIODevice::ReadOnly)) {
+ while (!file.atEnd())
+ items << file.readLine().trimmed();
+ file.close();
+ }
+
+ QSettings settings;
+ QString customUserAgent = settings.value("CustomUserAgent").toString();
+ if (!items.contains(customUserAgent) && !customUserAgent.isEmpty())
+ items << customUserAgent;
+
+ QDialog* dialog = new QDialog(this);
+ dialog->resize(size().width() * 0.7, dialog->size().height());
+ dialog->setWindowTitle("Change User Agent");
+
+ QVBoxLayout* layout = new QVBoxLayout(dialog);
+ dialog->setLayout(layout);
+
+#ifndef QT_NO_COMBOBOX
+ QComboBox* combo = new QComboBox(dialog);
+ combo->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
+ combo->setEditable(true);
+ combo->insertItems(0, items);
+ layout->addWidget(combo);
+
+ int index = combo->findText(page()->userAgentForUrl(QUrl()));
+ combo->setCurrentIndex(index);
+#endif
+
+ QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok
+ | QDialogButtonBox::Cancel, Qt::Horizontal, dialog);
+ connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept()));
+ connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject()));
+ layout->addWidget(buttonBox);
+
+#ifndef QT_NO_COMBOBOX
+ if (dialog->exec() && !combo->currentText().isEmpty()) {
+ page()->setUserAgent(combo->currentText());
+ if (!items.contains(combo->currentText()))
+ settings.setValue("CustomUserAgent", combo->currentText());
+ }
+#endif
+
+ delete dialog;
+}
+
+void LauncherWindow::loadURLListFromFile()
+{
+ QString selectedFile;
+#ifndef QT_NO_FILEDIALOG
+ selectedFile = QFileDialog::getOpenFileName(this, tr("Load URL list from file")
+ , QString(), tr("Text Files (*.txt);;All Files (*)"));
+#endif
+ if (selectedFile.isEmpty())
+ return;
+
+ m_urlLoader = new UrlLoader(this->page()->mainFrame(), selectedFile, 0, 0);
+ m_urlLoader->loadNext();
+}
+
+void LauncherWindow::printURL(const QUrl& url)
+{
+ QTextStream output(stdout);
+ output << "Loaded: " << url.toString() << endl;
+}
+
+#if !defined(QT_NO_FILEDIALOG) && !defined(QT_NO_MESSAGEBOX)
+void LauncherWindow::downloadRequest(const QNetworkRequest &request)
+{
+ QNetworkAccessManager* manager = new QNetworkAccessManager(this);
+ m_reply = manager->get(request);
+ connect(m_reply, SIGNAL(finished()), this, SLOT(fileDownloadFinished()));
+}
+
+void LauncherWindow::fileDownloadFinished()
+{
+ QFileInfo fileInf(m_reply->request().url().toString());
+ QString requestFileName = QDir::homePath() + "/" + fileInf.fileName();
+ QString fileName = QFileDialog::getSaveFileName(this, "Save as...", requestFileName, "All Files (*)");
+
+ if (fileName.isEmpty())
+ return;
+ if (m_reply->error() != QNetworkReply::NoError)
+ QMessageBox::critical(this, QString("Download"), QString("Download failed."));
+ else {
+ QFile file(fileName);
+ file.open(QIODevice::WriteOnly);
+ file.write(m_reply->readAll());
+ file.close();
+ QMessageBox::information(this, QString("Download"), fileName + QString(" downloaded successfully."));
+ }
+}
+#endif
+
+void LauncherWindow::updateFPS(int fps)
+{
+ QString fpsStatusText = QString("Current FPS: %1").arg(fps);
+
+ statusBar()->showMessage(fpsStatusText);
+}
+
+void LauncherWindow::toggleLocalStorage(bool toggle)
+{
+ m_windowOptions.useLocalStorage = toggle;
+ page()->settings()->setAttribute(QWebSettings::LocalStorageEnabled, toggle);
+}
+
+void LauncherWindow::toggleOfflineStorageDatabase(bool toggle)
+{
+ m_windowOptions.useOfflineStorageDatabase = toggle;
+ page()->settings()->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, toggle);
+}
+
+void LauncherWindow::toggleOfflineWebApplicationCache(bool toggle)
+{
+ m_windowOptions.useOfflineWebApplicationCache = toggle;
+ page()->settings()->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, toggle);
+}
+
+void LauncherWindow::setOfflineStorageDefaultQuota()
+{
+ // For command line execution, quota size is taken from command line.
+ if (m_windowOptions.offlineStorageDefaultQuotaSize)
+ page()->settings()->setOfflineStorageDefaultQuota(m_windowOptions.offlineStorageDefaultQuotaSize);
+ else {
+#ifndef QT_NO_INPUTDIALOG
+ bool ok;
+ // Maximum size is set to 25 * 1024 * 1024.
+ int quotaSize = QInputDialog::getInt(this, "Offline Storage Default Quota Size" , "Quota Size", 0, 0, 26214400, 1, &ok);
+ if (ok)
+ page()->settings()->setOfflineStorageDefaultQuota(quotaSize);
+#endif
+ }
+}
+
+LauncherWindow* LauncherWindow::newWindow()
+{
+ LauncherWindow* mw = new LauncherWindow(&m_windowOptions);
+ mw->show();
+ return mw;
+}
+
+LauncherWindow* LauncherWindow::cloneWindow()
+{
+ LauncherWindow* mw = new LauncherWindow(&m_windowOptions, qobject_cast<QGraphicsView*>(m_view)->scene());
+ mw->show();
+ return mw;
+}
+
+#ifndef QT_NO_LINEEDIT
+void LauncherWindow::showFindBar()
+{
+ if (!m_findBar->isVisible()) {
+ m_findBar->setVisible(true);
+ m_lineEdit->setText(page()->selectedText());
+ m_lineEdit->setFocus(Qt::PopupFocusReason);
+ } else {
+ m_findBar->setVisible(false);
+ page()->findText("", QWebPage::HighlightAllOccurrences);
+ }
+}
+
+void LauncherWindow::find(int mode = s_findNormalFlag)
+{
+ QPalette palette;
+ bool found;
+ palette.setColor(m_lineEdit->backgroundRole(), Qt::white);
+ page()->findText("", QFlag(QWebPage::HighlightAllOccurrences));
+
+ m_findFlag = m_findFlag ^ mode;
+ if (mode == s_findNormalFlag || mode == QWebPage::FindBackward) {
+ found = page()->findText(m_lineEdit->text(), QFlag(m_findFlag & ~QWebPage::HighlightAllOccurrences));
+ m_findFlag = m_findFlag ^ mode;
+
+ if (found || m_lineEdit->text().isEmpty())
+ m_lineEdit->setPalette(palette);
+ else {
+ palette.setColor(m_lineEdit->backgroundRole(), QColor(255, 0, 0, 127));
+ m_lineEdit->setPalette(palette);
+ }
+ }
+
+ if (m_findFlag & QWebPage::HighlightAllOccurrences)
+ page()->findText(m_lineEdit->text(), QFlag(m_findFlag));
+}
+#endif
diff --git a/Tools/QtTestBrowser/launcherwindow.h b/Tools/QtTestBrowser/launcherwindow.h
new file mode 100644
index 000000000..94452605a
--- /dev/null
+++ b/Tools/QtTestBrowser/launcherwindow.h
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
+ * Copyright (C) 2006 George Staikos <staikos@kde.org>
+ * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef launcherwindow_h
+#define launcherwindow_h
+
+#include <QtNetwork/QNetworkRequest>
+
+#ifndef QT_NO_OPENGL
+#include <QtOpenGL/QGLWidget>
+#endif
+
+#if !defined(QT_NO_PRINTER)
+#include <QPrintPreviewDialog>
+#endif
+
+#ifndef QT_NO_UITOOLS
+#include <QtUiTools/QUiLoader>
+#endif
+
+#include <QDebug>
+
+#include <cstdio>
+#include <qevent.h>
+#include <qwebelement.h>
+#include <qwebframe.h>
+#include <qwebinspector.h>
+#include <qwebsettings.h>
+
+#include "mainwindow.h"
+#include "urlloader.h"
+#include "utils.h"
+#include "webinspector.h"
+#include "webpage.h"
+#include "webview.h"
+
+class QPropertyAnimation;
+class QLineEdit;
+
+class WindowOptions {
+public:
+ WindowOptions()
+ : useGraphicsView(false)
+ , useDiskCache(false)
+ , useCompositing(true)
+ , useTiledBackingStore(false)
+ , useWebGL(false)
+ , useFrameFlattening(false)
+ , cacheWebView(false)
+ , showFrameRate(false)
+ , resizesToContents(false)
+ , viewportUpdateMode(QGraphicsView::MinimalViewportUpdate)
+ , useLocalStorage(false)
+ , useOfflineStorageDatabase(false)
+ , useOfflineWebApplicationCache(false)
+ , useDiskCookies(true)
+ , offlineStorageDefaultQuotaSize(0)
+#ifndef QT_NO_OPENGL
+ , useQGLWidgetViewport(false)
+#endif
+#if defined(Q_WS_X11)
+ , useTestFonts(false)
+#endif
+ , printLoadedUrls(false)
+ , startMaximized(false)
+ {
+ }
+
+ bool useGraphicsView;
+ bool useDiskCache;
+ bool useCompositing;
+ bool useTiledBackingStore;
+ bool useWebGL;
+ bool useFrameFlattening;
+ bool cacheWebView;
+ bool showFrameRate;
+ bool resizesToContents;
+ QGraphicsView::ViewportUpdateMode viewportUpdateMode;
+ bool useLocalStorage;
+ bool useOfflineStorageDatabase;
+ bool useOfflineWebApplicationCache;
+ bool useDiskCookies;
+ quint64 offlineStorageDefaultQuotaSize;
+#ifndef QT_NO_OPENGL
+ bool useQGLWidgetViewport;
+#endif
+#if defined(Q_WS_X11)
+ bool useTestFonts;
+#endif
+ bool printLoadedUrls;
+ QUrl inspectorUrl;
+ quint16 remoteInspectorPort;
+ bool startMaximized;
+};
+
+class LauncherWindow : public MainWindow {
+ Q_OBJECT
+
+public:
+ LauncherWindow(WindowOptions* data = 0, QGraphicsScene* sharedScene = 0);
+ virtual ~LauncherWindow();
+
+ void sendTouchEvent();
+
+ bool eventFilter(QObject* obj, QEvent* event);
+
+protected slots:
+ void loadStarted();
+ void loadFinished();
+
+ void showLinkHover(const QString &link, const QString &toolTip);
+
+ void zoomIn();
+ void zoomOut();
+ void resetZoom();
+ void toggleZoomTextOnly(bool on);
+ void zoomAnimationFinished();
+
+ void print();
+ void screenshot();
+
+ void setEditable(bool on);
+
+ /* void dumpPlugins() */
+ void dumpHtml();
+
+ void loadURLListFromFile();
+
+ void setDiskCache(bool enable);
+ void setTouchMocking(bool on);
+ void toggleWebView(bool graphicsBased);
+ void toggleAcceleratedCompositing(bool toggle);
+ void toggleTiledBackingStore(bool toggle);
+ void toggleResizesToContents(bool toggle);
+ void toggleWebGL(bool toggle);
+ void toggleSpatialNavigation(bool b);
+ void toggleFullScreenMode(bool enable);
+ void toggleFrameFlattening(bool toggle);
+ void toggleInterruptingJavaScriptEnabled(bool enable);
+ void toggleJavascriptCanOpenWindows(bool enable);
+ void toggleAutoLoadImages(bool enable);
+ void setUseDiskCookies(bool enable);
+ void clearCookies();
+ void togglePlugins(bool enable);
+ void toggleLocalStorage(bool toggle);
+ void toggleOfflineStorageDatabase(bool toggle);
+ void toggleOfflineWebApplicationCache(bool toggle);
+ void setOfflineStorageDefaultQuota();
+#ifndef QT_NO_LINEEDIT
+ void showFindBar();
+ void find(int mode);
+#endif
+#ifndef QT_NO_OPENGL
+ void toggleQGLWidgetViewport(bool enable);
+#endif
+
+ void changeViewportUpdateMode(int mode);
+ void animatedFlip();
+ void animatedYFlip();
+ void selectElements();
+ void showFPS(bool enable);
+ void showUserAgentDialog();
+
+ void printURL(const QUrl&);
+#if !defined(QT_NO_FILEDIALOG) && !defined(QT_NO_MESSAGEBOX)
+ void downloadRequest(const QNetworkRequest&);
+ void fileDownloadFinished();
+#endif
+
+public slots:
+ LauncherWindow* newWindow();
+ LauncherWindow* cloneWindow();
+ void updateFPS(int fps);
+
+signals:
+ void enteredFullScreenMode(bool on);
+
+private:
+ void init();
+ void initializeView();
+ void createChrome();
+ void applyPrefs();
+ void applyZoom();
+
+ bool isGraphicsBased() const;
+
+private:
+ static QVector<int> m_zoomLevels;
+ int m_currentZoom;
+
+ UrlLoader* m_urlLoader;
+
+ QWidget* m_view;
+ WebInspector* m_inspector;
+
+ WindowOptions m_windowOptions;
+
+ QAction* m_formatMenuAction;
+
+ QPropertyAnimation* m_zoomAnimation;
+#if !defined(QT_NO_FILEDIALOG) && !defined(QT_NO_MESSAGEBOX)
+ QNetworkReply* m_reply;
+#endif
+ QList<QTouchEvent::TouchPoint> m_touchPoints;
+ bool m_touchMocking;
+
+ QString m_inputUrl;
+#ifndef QT_NO_LINEEDIT
+ QToolBar* m_findBar;
+ QLineEdit* m_lineEdit;
+ int m_findFlag;
+ static const int s_findNormalFlag = 0;
+#endif
+};
+
+#endif
diff --git a/Tools/QtTestBrowser/locationedit.cpp b/Tools/QtTestBrowser/locationedit.cpp
new file mode 100644
index 000000000..6489b2b2e
--- /dev/null
+++ b/Tools/QtTestBrowser/locationedit.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2011 Andreas Kling <kling@webkit.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "locationedit.h"
+
+#ifndef QT_NO_INPUTDIALOG
+
+static const QSize gPageIconSize(16, 16);
+
+static QPixmap defaultPageIcon()
+{
+ static QPixmap icon;
+ if (icon.isNull())
+ icon.load(":/favicon.png");
+
+ return icon;
+}
+
+LocationEdit::LocationEdit(QWidget* parent)
+ : QLineEdit(parent)
+ , m_progress(0)
+{
+ m_clearTimer.setSingleShot(true);
+ connect(&m_clearTimer, SIGNAL(timeout()), this, SLOT(reset()));
+
+ m_pageIconLabel = new QLabel(this);
+ m_pageIconLabel->setFixedSize(gPageIconSize);
+ m_pageIconLabel->setPixmap(defaultPageIcon());
+}
+
+void LocationEdit::setPageIcon(const QIcon& icon)
+{
+ if (icon.isNull())
+ m_pageIconLabel->setPixmap(defaultPageIcon());
+ else
+ m_pageIconLabel->setPixmap(icon.pixmap(gPageIconSize));
+}
+
+void LocationEdit::setProgress(int progress)
+{
+ m_clearTimer.stop();
+ m_progress = progress;
+ update();
+}
+
+void LocationEdit::reset()
+{
+ setProgress(0);
+}
+
+void LocationEdit::resizeEvent(QResizeEvent*)
+{
+ updateInternalGeometry();
+}
+
+void LocationEdit::updateInternalGeometry()
+{
+ QStyleOptionFrameV3 styleOption;
+ initStyleOption(&styleOption);
+
+ QRect textRect = style()->subElementRect(QStyle::SE_LineEditContents, &styleOption, this);
+
+ const int spacing = 2;
+
+ int x = textRect.x() + spacing;
+ int y = (textRect.center().y() + 1) - gPageIconSize.height() / 2;
+
+ m_pageIconLabel->move(x, y);
+
+ QMargins margins = textMargins();
+ margins.setLeft(m_pageIconLabel->sizeHint().width() + spacing);
+ setTextMargins(margins);
+}
+
+void LocationEdit::paintEvent(QPaintEvent* ev)
+{
+ QColor backgroundColor = QApplication::palette().color(QPalette::Base);
+ QColor progressColor = QColor(120, 180, 240);
+ QPalette p = palette();
+
+ if (!m_progress)
+ p.setBrush(QPalette::Base, backgroundColor);
+ else {
+ QLinearGradient gradient(0, 0, width(), 0);
+ gradient.setColorAt(0, progressColor);
+ gradient.setColorAt(((double) m_progress) / 100, progressColor);
+ if (m_progress != 100)
+ gradient.setColorAt((double) m_progress / 100 + 0.001, backgroundColor);
+ p.setBrush(QPalette::Base, gradient);
+ }
+ setPalette(p);
+
+ QLineEdit::paintEvent(ev);
+
+ if (m_progress == 100)
+ m_clearTimer.start(100);
+}
+
+#endif
diff --git a/Tools/QtTestBrowser/locationedit.h b/Tools/QtTestBrowser/locationedit.h
new file mode 100644
index 000000000..b64474de7
--- /dev/null
+++ b/Tools/QtTestBrowser/locationedit.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef locationedit_h
+#define locationedit_h
+
+#include <qconfig.h>
+
+#ifndef QT_NO_INPUTDIALOG
+#include <QApplication>
+#include <QIcon>
+#include <QLabel>
+#include <QLineEdit>
+#include <QStyleOptionFrameV3>
+#include <QTimer>
+
+class LocationEdit : public QLineEdit {
+ Q_OBJECT
+
+public:
+ LocationEdit(QWidget* parent = 0);
+
+ void setPageIcon(const QIcon&);
+
+public slots:
+ void setProgress(int progress);
+
+private slots:
+ void reset();
+
+protected:
+ virtual void paintEvent(QPaintEvent*);
+ virtual void resizeEvent(QResizeEvent*);
+
+private:
+ void updateInternalGeometry();
+
+ int m_progress;
+ QTimer m_clearTimer;
+ QLabel* m_pageIconLabel;
+};
+
+#endif
+#endif
diff --git a/Tools/QtTestBrowser/main.cpp b/Tools/QtTestBrowser/main.cpp
new file mode 100644
index 000000000..603ad6160
--- /dev/null
+++ b/Tools/QtTestBrowser/main.cpp
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
+ * Copyright (C) 2006 George Staikos <staikos@kde.org>
+ * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "DumpRenderTreeSupportQt.h"
+#include "launcherwindow.h"
+#include "urlloader.h"
+
+WindowOptions windowOptions;
+
+#include <QApplication>
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+#include <QFontDatabase>
+
+#if defined(Q_WS_X11)
+#include <fontconfig/fontconfig.h>
+#endif
+
+
+#if defined(Q_WS_X11)
+// Very similar to WebCore::DumpRenderTree::initializeFonts();
+// Duplicated here so that QtTestBrowser would display contents
+// with the same fonts as run-webkit-tests/DumpRenderTree.
+static void initTestFonts()
+{
+ static int numFonts = -1;
+
+ // Some test cases may add or remove application fonts (via @font-face).
+ // Make sure to re-initialize the font set if necessary.
+ FcFontSet* appFontSet = FcConfigGetFonts(0, FcSetApplication);
+ if (appFontSet && numFonts >= 0 && appFontSet->nfont == numFonts)
+ return;
+
+ QByteArray fontDir = getenv("WEBKIT_TESTFONTS");
+ if (fontDir.isEmpty() || !QDir(fontDir).exists()) {
+ fprintf(stderr,
+ "\n\n"
+ "----------------------------------------------------------------------\n"
+ "WEBKIT_TESTFONTS environment variable is not set correctly.\n"
+ "This variable has to point to the directory containing the fonts\n"
+ "you can clone from git://gitorious.org/qtwebkit/testfonts.git\n"
+ "----------------------------------------------------------------------\n"
+ );
+ exit(1);
+ }
+ // Looks for qt/fonts.conf relative to the directory of the QtTestBrowser
+ // executable.
+ QString configFileString = QCoreApplication::applicationDirPath();
+ configFileString += "/../../../Tools/DumpRenderTree/qt/fonts.conf";
+ QByteArray configFileArray = configFileString.toUtf8();
+ FcConfig* config = FcConfigCreate();
+ if (!FcConfigParseAndLoad (config, (FcChar8*) configFileArray.data(), true))
+ qFatal("Couldn't load font configuration file");
+ if (!FcConfigAppFontAddDir (config, (FcChar8*) fontDir.data()))
+ qFatal("Couldn't add font dir!");
+ FcConfigSetCurrent(config);
+
+ appFontSet = FcConfigGetFonts(config, FcSetApplication);
+ numFonts = appFontSet->nfont;
+}
+#endif
+
+int launcherMain(const QApplication& app)
+{
+#ifdef Q_WS_X11
+ if (windowOptions.useTestFonts)
+ initTestFonts();
+#endif
+
+#ifndef NDEBUG
+ int retVal = app.exec();
+ DumpRenderTreeSupportQt::garbageCollectorCollect();
+ QWebSettings::clearMemoryCaches();
+ return retVal;
+#else
+ return app.exec();
+#endif
+}
+
+class LauncherApplication : public QApplication {
+ Q_OBJECT
+
+public:
+ LauncherApplication(int& argc, char** argv);
+ QStringList urls() const { return m_urls; }
+ bool isRobotized() const { return m_isRobotized; }
+ int robotTimeout() const { return m_robotTimeoutSeconds; }
+ int robotExtraTime() const { return m_robotExtraTimeSeconds; }
+
+private:
+ void handleUserOptions();
+ void applyDefaultSettings();
+
+private:
+ bool m_isRobotized;
+ int m_robotTimeoutSeconds;
+ int m_robotExtraTimeSeconds;
+ QStringList m_urls;
+};
+
+void LauncherApplication::applyDefaultSettings()
+{
+ QWebSettings::setMaximumPagesInCache(4);
+
+ QWebSettings::setObjectCacheCapacities((16*1024*1024) / 8, (16*1024*1024) / 8, 16*1024*1024);
+
+ QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled, true);
+ QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
+ QWebSettings::enablePersistentStorage();
+}
+
+LauncherApplication::LauncherApplication(int& argc, char** argv)
+ : QApplication(argc, argv, QApplication::GuiServer)
+ , m_isRobotized(false)
+ , m_robotTimeoutSeconds(0)
+ , m_robotExtraTimeSeconds(0)
+{
+ // To allow QWebInspector's configuration persistence
+ setOrganizationName("Nokia");
+ setApplicationName("QtTestBrowser");
+ setApplicationVersion("0.1");
+
+ applyDefaultSettings();
+
+ handleUserOptions();
+}
+
+static void requiresGraphicsView(const QString& option)
+{
+ if (windowOptions.useGraphicsView)
+ return;
+ appQuit(1, QString("%1 only works in combination with the -graphicsbased option").arg(option));
+}
+
+void LauncherApplication::handleUserOptions()
+{
+ QStringList args = arguments();
+ QFileInfo program(args.at(0));
+ QString programName("QtTestBrowser");
+ if (program.exists())
+ programName = program.baseName();
+
+ QList<QString> updateModes(enumToKeys(QGraphicsView::staticMetaObject,
+ "ViewportUpdateMode", "ViewportUpdate"));
+
+ if (args.contains("-help")) {
+ qDebug() << "Usage:" << programName.toLatin1().data()
+ << "[-graphicsbased]"
+ << "[-no-compositing]"
+#if defined(QT_CONFIGURED_WITH_OPENGL)
+ << "[-gl-viewport]"
+ << "[-webgl]"
+#endif
+ << QString("[-viewport-update-mode %1]").arg(formatKeys(updateModes)).toLatin1().data()
+#if !defined(QT_NO_NETWORKDISKCACHE) && !defined(QT_NO_DESKTOPSERVICES)
+ << "[-disk-cache]"
+#endif
+ << "[-cache-webview]"
+ << "[-maximize]"
+ << "[-show-fps]"
+ << "[-r list]"
+ << "[-robot-timeout seconds]"
+ << "[-robot-extra-time seconds]"
+ << "[-inspector-url location]"
+ << "[-tiled-backing-store]"
+ << "[-resizes-to-contents]"
+ << "[-local-storage-enabled]"
+ << "[-no-disk-cookies]"
+ << "[-offline-storage-database-enabled]"
+ << "[-offline-web-application-cache-enabled]"
+ << "[-set-offline-storage-default-quota maxSize]"
+#if defined(Q_WS_X11)
+ << "[-use-test-fonts]"
+#endif
+ << "[-print-loaded-urls]"
+ << "URLs";
+ appQuit(0);
+ }
+
+ const bool defaultForAnimations = args.contains("-default-animations");
+ if (args.contains("-graphicsbased") || defaultForAnimations)
+ windowOptions.useGraphicsView = true;
+
+ if (args.contains("-no-compositing")) {
+ requiresGraphicsView("-no-compositing");
+ windowOptions.useCompositing = false;
+ }
+
+ if (args.contains("-show-fps")) {
+ requiresGraphicsView("-show-fps");
+ windowOptions.showFrameRate = true;
+ }
+
+ if (args.contains("-disk-cache")) {
+#if !defined(QT_NO_NETWORKDISKCACHE) && !defined(QT_NO_DESKTOPSERVICES)
+ windowOptions.useDiskCache = true;
+#else
+ appQuit(1, "-disk-cache only works if QNetworkDiskCache and QDesktopServices is enabled in your Qt build.");
+#endif
+ }
+
+ if (args.contains("-cache-webview") || defaultForAnimations) {
+ requiresGraphicsView("-cache-webview");
+ windowOptions.cacheWebView = true;
+ }
+
+ if (args.contains("-tiled-backing-store")) {
+ requiresGraphicsView("-tiled-backing-store");
+ windowOptions.useTiledBackingStore = true;
+ }
+
+ if (args.contains("-resizes-to-contents")) {
+ requiresGraphicsView("-resizes-to-contents");
+ windowOptions.resizesToContents = true;
+ }
+
+ if (args.contains("-local-storage-enabled"))
+ windowOptions.useLocalStorage = true;
+
+ if (args.contains("-no-disk-cookies"))
+ windowOptions.useDiskCookies = false;
+
+ if (args.contains("-maximize"))
+ windowOptions.startMaximized = true;
+
+ if (args.contains("-offline-storage-database-enabled"))
+ windowOptions.useOfflineStorageDatabase = true;
+
+ if (args.contains("-offline-web-application-cache-enabled"))
+ windowOptions.useOfflineWebApplicationCache = true;
+
+ int setOfflineStorageDefaultQuotaIndex = args.indexOf("-set-offline-storage-default-quota");
+ if (setOfflineStorageDefaultQuotaIndex != -1) {
+ unsigned int maxSize = takeOptionValue(&args, setOfflineStorageDefaultQuotaIndex).toUInt();
+ windowOptions.offlineStorageDefaultQuotaSize = maxSize;
+ }
+
+ if (defaultForAnimations)
+ windowOptions.viewportUpdateMode = QGraphicsView::BoundingRectViewportUpdate;
+
+ QString arg1("-viewport-update-mode");
+ int modeIndex = args.indexOf(arg1);
+ if (modeIndex != -1) {
+ requiresGraphicsView(arg1);
+
+ QString mode = takeOptionValue(&args, modeIndex);
+ if (mode.isEmpty())
+ appQuit(1, QString("%1 needs a value of one of [%2]").arg(arg1).arg(formatKeys(updateModes)));
+ int idx = updateModes.indexOf(mode);
+ if (idx == -1)
+ appQuit(1, QString("%1 value has to be one of [%2]").arg(arg1).arg(formatKeys(updateModes)));
+
+ windowOptions.viewportUpdateMode = static_cast<QGraphicsView::ViewportUpdateMode>(idx);
+ }
+#ifdef QT_CONFIGURED_WITH_OPENGL
+ if (args.contains("-gl-viewport") || defaultForAnimations) {
+ requiresGraphicsView("-gl-viewport");
+ windowOptions.useQGLWidgetViewport = true;
+ }
+
+ if (args.contains("-webgl")) {
+ requiresGraphicsView("-webgl");
+ windowOptions.useWebGL = true;
+ }
+#endif
+
+#if defined(Q_WS_X11)
+ if (args.contains("-use-test-fonts"))
+ windowOptions.useTestFonts = true;
+#endif
+
+ if (args.contains("-print-loaded-urls"))
+ windowOptions.printLoadedUrls = true;
+
+ QString inspectorUrlArg("-inspector-url");
+ int inspectorUrlIndex = args.indexOf(inspectorUrlArg);
+ if (inspectorUrlIndex != -1)
+ windowOptions.inspectorUrl = takeOptionValue(&args, inspectorUrlIndex);
+
+ QString remoteInspectorPortArg("-remote-inspector-port");
+ int remoteInspectorPortIndex = args.indexOf(remoteInspectorPortArg);
+ if (remoteInspectorPortIndex != -1)
+ windowOptions.remoteInspectorPort = takeOptionValue(&args, remoteInspectorPortIndex).toInt();
+
+ int robotIndex = args.indexOf("-r");
+ if (robotIndex != -1) {
+ QString listFile = takeOptionValue(&args, robotIndex);
+ if (listFile.isEmpty())
+ appQuit(1, "-r needs a list file to start in robotized mode");
+ if (!QFile::exists(listFile))
+ appQuit(1, "The list file supplied to -r does not exist.");
+
+ m_isRobotized = true;
+ m_urls = QStringList(listFile);
+ } else {
+ int lastArg = args.lastIndexOf(QRegExp("^-.*"));
+ m_urls = (lastArg != -1) ? args.mid(++lastArg) : args.mid(1);
+ }
+
+ int robotTimeoutIndex = args.indexOf("-robot-timeout");
+ if (robotTimeoutIndex != -1)
+ m_robotTimeoutSeconds = takeOptionValue(&args, robotTimeoutIndex).toInt();
+
+ int robotExtraTimeIndex = args.indexOf("-robot-extra-time");
+ if (robotExtraTimeIndex != -1)
+ m_robotExtraTimeSeconds = takeOptionValue(&args, robotExtraTimeIndex).toInt();
+}
+
+
+int main(int argc, char **argv)
+{
+ LauncherApplication app(argc, argv);
+
+ if (app.isRobotized()) {
+ LauncherWindow* window = new LauncherWindow();
+ UrlLoader loader(window->page()->mainFrame(), app.urls().at(0), app.robotTimeout(), app.robotExtraTime());
+ loader.loadNext();
+ window->show();
+ return launcherMain(app);
+ }
+
+ QStringList urls = app.urls();
+
+ if (urls.isEmpty()) {
+ QString defaultIndexFile = QString("%1/%2").arg(QDir::homePath()).arg(QLatin1String("index.html"));
+ if (QFile(defaultIndexFile).exists())
+ urls.append(QString("file://") + defaultIndexFile);
+ else
+ urls.append("");
+ }
+
+ LauncherWindow* window = 0;
+ foreach (QString url, urls) {
+ LauncherWindow* newWindow;
+ if (!window)
+ newWindow = window = new LauncherWindow(&windowOptions);
+ else
+ newWindow = window->newWindow();
+
+ newWindow->load(url);
+ }
+
+ window->show();
+ return launcherMain(app);
+}
+
+#include "main.moc"
diff --git a/Tools/QtTestBrowser/mainwindow.cpp b/Tools/QtTestBrowser/mainwindow.cpp
new file mode 100644
index 000000000..68217696b
--- /dev/null
+++ b/Tools/QtTestBrowser/mainwindow.cpp
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
+ * Copyright (C) 2006 George Staikos <staikos@kde.org>
+ * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "mainwindow.h"
+
+#include "locationedit.h"
+#include "utils.h"
+
+#include <QAction>
+#ifndef QT_NO_INPUTDIALOG
+#include <QCompleter>
+#endif
+#ifndef QT_NO_FILEDIALOG
+#include <QFileDialog>
+#endif
+
+MainWindow::MainWindow()
+ : m_page(new WebPage(this))
+ , m_toolBar(0)
+ , urlEdit(0)
+{
+ setAttribute(Qt::WA_DeleteOnClose);
+ if (qgetenv("QTTESTBROWSER_USE_ARGB_VISUALS").toInt() == 1)
+ setAttribute(Qt::WA_TranslucentBackground);
+
+ buildUI();
+}
+
+void MainWindow::buildUI()
+{
+ delete m_toolBar;
+
+ m_toolBar = addToolBar("Navigation");
+ QAction* reloadAction = page()->action(QWebPage::Reload);
+ connect(reloadAction, SIGNAL(triggered()), this, SLOT(changeLocation()));
+
+ m_toolBar->addAction(page()->action(QWebPage::Back));
+ m_toolBar->addAction(page()->action(QWebPage::Forward));
+ m_toolBar->addAction(reloadAction);
+ m_toolBar->addAction(page()->action(QWebPage::Stop));
+
+#ifndef QT_NO_INPUTDIALOG
+ urlEdit = new LocationEdit(m_toolBar);
+ urlEdit->setSizePolicy(QSizePolicy::Expanding, urlEdit->sizePolicy().verticalPolicy());
+ connect(urlEdit, SIGNAL(returnPressed()), SLOT(changeLocation()));
+ QCompleter* completer = new QCompleter(m_toolBar);
+ urlEdit->setCompleter(completer);
+ completer->setModel(&urlModel);
+ m_toolBar->addWidget(urlEdit);
+
+ connect(page()->mainFrame(), SIGNAL(urlChanged(QUrl)), this, SLOT(setAddressUrl(QUrl)));
+ connect(page(), SIGNAL(loadProgress(int)), urlEdit, SLOT(setProgress(int)));
+#endif
+
+ connect(page()->mainFrame(), SIGNAL(loadStarted()), this, SLOT(onLoadStarted()));
+ connect(page()->mainFrame(), SIGNAL(iconChanged()), this, SLOT(onIconChanged()));
+ connect(page()->mainFrame(), SIGNAL(titleChanged(QString)), this, SLOT(onTitleChanged(QString)));
+ connect(page(), SIGNAL(windowCloseRequested()), this, SLOT(close()));
+
+#ifndef QT_NO_SHORTCUT
+ // short-cuts
+ page()->action(QWebPage::Back)->setShortcut(QKeySequence::Back);
+ page()->action(QWebPage::Stop)->setShortcut(Qt::Key_Escape);
+ page()->action(QWebPage::Forward)->setShortcut(QKeySequence::Forward);
+ page()->action(QWebPage::Reload)->setShortcut(QKeySequence::Refresh);
+#ifndef QT_NO_UNDOSTACK
+ page()->action(QWebPage::Undo)->setShortcut(QKeySequence::Undo);
+ page()->action(QWebPage::Redo)->setShortcut(QKeySequence::Redo);
+#endif
+ page()->action(QWebPage::Cut)->setShortcut(QKeySequence::Cut);
+ page()->action(QWebPage::Copy)->setShortcut(QKeySequence::Copy);
+ page()->action(QWebPage::Paste)->setShortcut(QKeySequence::Paste);
+ page()->action(QWebPage::SelectAll)->setShortcut(QKeySequence::SelectAll);
+
+ page()->action(QWebPage::ToggleBold)->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_B));
+ page()->action(QWebPage::ToggleItalic)->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_I));
+ page()->action(QWebPage::ToggleUnderline)->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_U));
+#endif
+}
+
+void MainWindow::setPage(WebPage* page)
+{
+ if (page && m_page)
+ page->setUserAgent(m_page->userAgentForUrl(QUrl()));
+
+ delete m_page;
+ m_page = page;
+
+ buildUI();
+}
+
+WebPage* MainWindow::page() const
+{
+ return m_page;
+}
+
+void MainWindow::setAddressUrl(const QUrl& url)
+{
+ setAddressUrl(url.toString(QUrl::RemoveUserInfo));
+}
+
+void MainWindow::setAddressUrl(const QString& url)
+{
+#ifndef QT_NO_INPUTDIALOG
+ if (!url.contains("about:"))
+ urlEdit->setText(url);
+#endif
+}
+
+void MainWindow::addCompleterEntry(const QUrl& url)
+{
+ QUrl::FormattingOptions opts;
+ opts |= QUrl::RemoveScheme;
+ opts |= QUrl::RemoveUserInfo;
+ opts |= QUrl::StripTrailingSlash;
+ QString s = url.toString(opts);
+ s = s.mid(2);
+ if (s.isEmpty())
+ return;
+
+ if (!urlList.contains(s))
+ urlList += s;
+ urlModel.setStringList(urlList);
+}
+
+void MainWindow::load(const QString& url)
+{
+ QUrl qurl = urlFromUserInput(url);
+ if (qurl.scheme().isEmpty())
+ qurl = QUrl("http://" + url + "/");
+ load(qurl);
+}
+
+void MainWindow::load(const QUrl& url)
+{
+ if (!url.isValid())
+ return;
+
+ setAddressUrl(url.toString());
+ page()->mainFrame()->load(url);
+}
+
+QString MainWindow::addressUrl() const
+{
+#ifndef QT_NO_INPUTDIALOG
+ return urlEdit->text();
+#endif
+ return QString();
+}
+
+void MainWindow::changeLocation()
+{
+#ifndef QT_NO_INPUTDIALOG
+ QString string = urlEdit->text();
+ QUrl mainFrameURL = page()->mainFrame()->url();
+
+ if (mainFrameURL.isValid() && string == mainFrameURL.toString()) {
+ page()->triggerAction(QWebPage::Reload);
+ return;
+ }
+
+ load(string);
+#endif
+}
+
+void MainWindow::openFile()
+{
+#ifndef QT_NO_FILEDIALOG
+ static const QString filter("HTML Files (*.htm *.html);;Text Files (*.txt);;Image Files (*.gif *.jpg *.png);;All Files (*)");
+
+ QFileDialog fileDialog(this, tr("Open"), QString(), filter);
+ fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
+ fileDialog.setFileMode(QFileDialog::ExistingFile);
+ fileDialog.setOptions(QFileDialog::ReadOnly);
+
+ if (fileDialog.exec()) {
+ QString selectedFile = fileDialog.selectedFiles()[0];
+ if (!selectedFile.isEmpty())
+ load(QUrl::fromLocalFile(selectedFile));
+ }
+#endif
+}
+
+void MainWindow::openLocation()
+{
+#ifndef QT_NO_INPUTDIALOG
+ urlEdit->selectAll();
+ urlEdit->setFocus();
+#endif
+}
+
+void MainWindow::onIconChanged()
+{
+#ifndef QT_NO_INPUTDIALOG
+ urlEdit->setPageIcon(page()->mainFrame()->icon());
+#endif
+}
+
+void MainWindow::onLoadStarted()
+{
+#ifndef QT_NO_INPUTDIALOG
+ urlEdit->setPageIcon(QIcon());
+#endif
+}
+
+void MainWindow::onTitleChanged(const QString& title)
+{
+ if (title.isEmpty())
+ setWindowTitle(QCoreApplication::applicationName());
+ else
+ setWindowTitle(QString::fromLatin1("%1 - %2").arg(title).arg(QCoreApplication::applicationName()));
+}
diff --git a/Tools/QtTestBrowser/mainwindow.h b/Tools/QtTestBrowser/mainwindow.h
new file mode 100644
index 000000000..a6a1bd29d
--- /dev/null
+++ b/Tools/QtTestBrowser/mainwindow.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
+ * Copyright (C) 2006 George Staikos <staikos@kde.org>
+ * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef mainwindow_h
+#define mainwindow_h
+
+#include "webpage.h"
+
+#include <QMainWindow>
+#include <QStringListModel>
+#include <QToolBar>
+
+class LocationEdit;
+
+class MainWindow : public QMainWindow {
+ Q_OBJECT
+
+public:
+ MainWindow();
+
+ void addCompleterEntry(const QUrl& url);
+
+ void load(const QString& url);
+ void load(const QUrl& url);
+
+ WebPage* page() const;
+ void setPage(WebPage*);
+
+protected slots:
+ void setAddressUrl(const QString& url);
+ void setAddressUrl(const QUrl& url);
+ void openFile();
+ void openLocation();
+ void changeLocation();
+ void onIconChanged();
+ void onLoadStarted();
+ void onTitleChanged(const QString&);
+
+protected:
+ QString addressUrl() const;
+
+private:
+ void buildUI();
+
+ WebPage* m_page;
+ QToolBar* m_toolBar;
+ QStringListModel urlModel;
+ QStringList urlList;
+ LocationEdit* urlEdit;
+};
+
+#endif
diff --git a/Tools/QtTestBrowser/urlloader.cpp b/Tools/QtTestBrowser/urlloader.cpp
new file mode 100644
index 000000000..2ae722bd9
--- /dev/null
+++ b/Tools/QtTestBrowser/urlloader.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 University of Szeged
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "urlloader.h"
+
+#include <QFile>
+#include <QDebug>
+#include <QWebPage>
+
+UrlLoader::UrlLoader(QWebFrame* frame, const QString& inputFileName, int timeoutSeconds, int extraTimeSeconds)
+ : m_frame(frame)
+ , m_stdOut(stdout)
+ , m_loaded(0)
+ , m_numFramesLoading(0)
+{
+ m_checkIfFinishedTimer.setInterval(200);
+ m_checkIfFinishedTimer.setSingleShot(true);
+ connect(&m_checkIfFinishedTimer, SIGNAL(timeout()), this, SLOT(checkIfFinished()));
+ // loadStarted and loadFinished on QWebPage is emitted for each frame/sub-frame
+ connect(m_frame->page(), SIGNAL(loadStarted()), this, SLOT(frameLoadStarted()));
+ connect(m_frame->page(), SIGNAL(loadFinished(bool)), this, SLOT(frameLoadFinished()));
+
+ if (timeoutSeconds) {
+ m_timeoutTimer.setInterval(timeoutSeconds * 1000);
+ m_timeoutTimer.setSingleShot(true);
+ connect(frame, SIGNAL(loadStarted()), &m_timeoutTimer, SLOT(start()));
+ connect(&m_timeoutTimer, SIGNAL(timeout()), this, SLOT(loadNext()));
+ }
+ if (extraTimeSeconds) {
+ m_extraTimeTimer.setInterval(extraTimeSeconds * 1000);
+ m_extraTimeTimer.setSingleShot(true);
+ connect(this, SIGNAL(pageLoadFinished()), &m_extraTimeTimer, SLOT(start()));
+ connect(&m_extraTimeTimer, SIGNAL(timeout()), this, SLOT(loadNext()));
+ } else
+ connect(this, SIGNAL(pageLoadFinished()), this, SLOT(loadNext()));
+ loadUrlList(inputFileName);
+}
+
+void UrlLoader::loadNext()
+{
+ m_timeoutTimer.stop();
+ m_extraTimeTimer.stop();
+ m_checkIfFinishedTimer.stop();
+ m_numFramesLoading = 0;
+ QString qstr;
+ if (getUrl(qstr)) {
+ QUrl url(qstr, QUrl::StrictMode);
+ if (url.isValid()) {
+ m_stdOut << "Loading " << qstr << " ......" << ++m_loaded << endl;
+ m_frame->load(url);
+ } else
+ loadNext();
+ } else
+ disconnect(m_frame, 0, this, 0);
+}
+
+void UrlLoader::checkIfFinished()
+{
+ if (!m_numFramesLoading)
+ emit pageLoadFinished();
+}
+
+void UrlLoader::frameLoadStarted()
+{
+ ++m_numFramesLoading;
+ m_checkIfFinishedTimer.stop();
+}
+
+void UrlLoader::frameLoadFinished()
+{
+ Q_ASSERT(m_numFramesLoading > 0);
+ --m_numFramesLoading;
+ // Once our frame has finished loading, wait a moment to call loadNext for cases
+ // where a sub-frame starts loading or another frame is loaded through JavaScript.
+ m_checkIfFinishedTimer.start();
+}
+
+void UrlLoader::loadUrlList(const QString& inputFileName)
+{
+ QFile inputFile(inputFileName);
+ if (inputFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ QTextStream stream(&inputFile);
+ QString line;
+ while (true) {
+ line = stream.readLine();
+ if (line.isNull())
+ break;
+ m_urls.append(line);
+ }
+ } else {
+ qDebug() << "Can't open list file";
+ exit(0);
+ }
+ m_index = 0;
+ inputFile.close();
+}
+
+bool UrlLoader::getUrl(QString& qstr)
+{
+ if (m_index == m_urls.size())
+ return false;
+
+ qstr = m_urls[m_index++];
+ return true;
+}
diff --git a/Tools/QtTestBrowser/urlloader.h b/Tools/QtTestBrowser/urlloader.h
new file mode 100644
index 000000000..8ce24c0d0
--- /dev/null
+++ b/Tools/QtTestBrowser/urlloader.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 University of Szeged
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef urlloader_h
+#define urlloader_h
+
+#include "qwebframe.h"
+
+#include <QTextStream>
+#include <QTimer>
+#include <QVector>
+
+class UrlLoader : public QObject {
+ Q_OBJECT
+
+public:
+ UrlLoader(QWebFrame* frame, const QString& inputFileName, int timeoutSeconds, int extraTimeSeconds);
+
+public slots:
+ void loadNext();
+
+private slots:
+ void checkIfFinished();
+ void frameLoadStarted();
+ void frameLoadFinished();
+
+signals:
+ void pageLoadFinished();
+
+private:
+ void loadUrlList(const QString& inputFileName);
+ bool getUrl(QString& qstr);
+
+private:
+ QVector<QString> m_urls;
+ int m_index;
+ QWebFrame* m_frame;
+ QTextStream m_stdOut;
+ int m_loaded;
+ QTimer m_timeoutTimer;
+ QTimer m_extraTimeTimer;
+ QTimer m_checkIfFinishedTimer;
+ int m_numFramesLoading;
+};
+
+#endif
diff --git a/Tools/QtTestBrowser/useragentlist.txt b/Tools/QtTestBrowser/useragentlist.txt
new file mode 100644
index 000000000..decf1043e
--- /dev/null
+++ b/Tools/QtTestBrowser/useragentlist.txt
@@ -0,0 +1,13 @@
+Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.1 (KHTML, like Gecko) QtTestBrowser/0.1 Safari/535.1
+Mozilla/5.0 (SymbianOS/9.4; U; Series60/5.0) AppleWebKit/535.1 (KHTML, like Gecko) QtTestBrowser/0.1 Mobile Safari/535.1
+Mozilla/5.0 (Macintosh; PPC Mac OS X) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8
+Mozilla/5.0 (Unknown; like Android 2.2; Intel Mac OS X 10_6) AppleWebKit/533.3 (KHTML, like Gecko) Version/4.0.3 Mobile Safari/533.3
+Mozilla/5.0 (iPhone; CPU OS 3_2 like Mac OS X) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10
+Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7
+Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10
+Opera/9.80 (Windows NT 6.0; U; en) Presto/2.8.99 Version/11.10
+Mozilla/5.0 (SymbianOS/9.4; U; Series60/5.0 Nokia5800d-1b/20.2.014; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413
+Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.2; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)
+Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
+Mozilla/5.0 (Windows; Windows NT 5.1) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.68 Safari/534.24
+Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
diff --git a/Tools/QtTestBrowser/utils.cpp b/Tools/QtTestBrowser/utils.cpp
new file mode 100644
index 000000000..567c989f7
--- /dev/null
+++ b/Tools/QtTestBrowser/utils.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "utils.h"
+
+
+QString takeOptionValue(QStringList* arguments, int index)
+{
+ QString result;
+
+ if (++index < arguments->count() && !arguments->at(index).startsWith("-"))
+ result = arguments->takeAt(index);
+
+ return result;
+}
+
+QString formatKeys(QList<QString> keys)
+{
+ QString result;
+ for (int i = 0; i < keys.count() - 1; i++)
+ result.append(keys.at(i) + "|");
+ result.append(keys.last());
+ return result;
+}
+
+QList<QString> enumToKeys(const QMetaObject o, const QString& name, const QString& strip)
+{
+ QList<QString> list;
+
+ int enumIndex = o.indexOfEnumerator(name.toLatin1().data());
+ QMetaEnum enumerator = o.enumerator(enumIndex);
+
+ if (enumerator.isValid()) {
+ for (int i = 0; i < enumerator.keyCount(); i++) {
+ QString key(enumerator.valueToKey(i));
+ list.append(key.remove(strip));
+ }
+ }
+
+ return list;
+}
+
+void appQuit(int exitCode, const QString& msg)
+{
+ if (!msg.isEmpty()) {
+ if (exitCode > 0)
+ qDebug("ERROR: %s", msg.toLatin1().data());
+ else
+ qDebug() << msg;
+ }
+ exit(exitCode);
+}
+
+QUrl urlFromUserInput(const QString& string)
+{
+ QString input(string);
+ QFileInfo fi(input);
+ if (fi.exists() && fi.isRelative())
+ input = fi.absoluteFilePath();
+
+ return QUrl::fromUserInput(input);
+}
+
+
diff --git a/Tools/QtTestBrowser/utils.h b/Tools/QtTestBrowser/utils.h
new file mode 100644
index 000000000..b67351e3d
--- /dev/null
+++ b/Tools/QtTestBrowser/utils.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef utils_h
+#define utils_h
+
+#include <QtCore>
+
+#ifndef NO_RETURN
+#if defined(__CC_ARM) || defined(__ARMCC__)
+#define NO_RETURN __declspec(noreturn)
+#elif defined(__GNUC__)
+#define NO_RETURN __attribute((__noreturn__))
+#else
+#define NO_RETURN
+#endif
+#endif
+
+// options handling
+QString takeOptionValue(QStringList* arguments, int index);
+QString formatKeys(QList<QString> keys);
+QList<QString> enumToKeys(const QMetaObject o, const QString& name, const QString& strip);
+
+NO_RETURN void appQuit(int status, const QString& msg = QString());
+
+QUrl urlFromUserInput(const QString& input);
+
+#endif
diff --git a/Tools/QtTestBrowser/webinspector.h b/Tools/QtTestBrowser/webinspector.h
new file mode 100644
index 000000000..c24ecbf9c
--- /dev/null
+++ b/Tools/QtTestBrowser/webinspector.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef webinspector_h
+#define webinspector_h
+
+#include "qwebinspector.h"
+
+class WebInspector : public QWebInspector {
+ Q_OBJECT
+
+public:
+ WebInspector(QWidget* parent = 0) : QWebInspector(parent) {}
+
+signals:
+ void visibleChanged(bool nowVisible);
+
+protected:
+ void showEvent(QShowEvent* event)
+ {
+ QWebInspector::showEvent(event);
+ emit visibleChanged(true);
+ }
+ void hideEvent(QHideEvent* event)
+ {
+ QWebInspector::hideEvent(event);
+ emit visibleChanged(false);
+ }
+};
+
+#endif
diff --git a/Tools/QtTestBrowser/webpage.cpp b/Tools/QtTestBrowser/webpage.cpp
new file mode 100644
index 000000000..98b7d0a74
--- /dev/null
+++ b/Tools/QtTestBrowser/webpage.cpp
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
+ * Copyright (C) 2006 George Staikos <staikos@kde.org>
+ * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "webpage.h"
+
+#include "launcherwindow.h"
+
+#include <QAction>
+#include <QApplication>
+#include <QAuthenticator>
+#ifndef QT_NO_DESKTOPSERVICES
+#include <QDesktopServices>
+#endif
+#include <QDialog>
+#include <QDialogButtonBox>
+#include <QLabel>
+#include <QLayout>
+#ifndef QT_NO_LINEEDIT
+#include <QLineEdit>
+#endif
+#include <QtNetwork/QNetworkReply>
+#include <QtNetwork/QNetworkRequest>
+#include <QtNetwork/QNetworkProxy>
+
+WebPage::WebPage(QObject* parent)
+ : QWebPage(parent)
+ , m_userAgent()
+ , m_interruptingJavaScriptEnabled(false)
+{
+ applyProxy();
+
+ connect(networkAccessManager(), SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)),
+ this, SLOT(authenticationRequired(QNetworkReply*, QAuthenticator*)));
+ connect(this, SIGNAL(featurePermissionRequested(QWebFrame*, QWebPage::Feature)), this, SLOT(requestPermission(QWebFrame*, QWebPage::Feature)));
+ connect(this, SIGNAL(featurePermissionRequestCanceled(QWebFrame*, QWebPage::Feature)), this, SLOT(featurePermissionRequestCanceled(QWebFrame*, QWebPage::Feature)));
+}
+
+void WebPage::applyProxy()
+{
+ QUrl proxyUrl(qgetenv("http_proxy"));
+
+ if (proxyUrl.isValid() && !proxyUrl.host().isEmpty()) {
+ int proxyPort = (proxyUrl.port() > 0) ? proxyUrl.port() : 8080;
+ networkAccessManager()->setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, proxyUrl.host(), proxyPort));
+ }
+}
+
+bool WebPage::supportsExtension(QWebPage::Extension extension) const
+{
+ if (extension == QWebPage::ErrorPageExtension)
+ return true;
+ return false;
+}
+
+bool WebPage::extension(Extension extension, const ExtensionOption* option, ExtensionReturn* output)
+{
+ const QWebPage::ErrorPageExtensionOption* info = static_cast<const QWebPage::ErrorPageExtensionOption*>(option);
+ QWebPage::ErrorPageExtensionReturn* errorPage = static_cast<QWebPage::ErrorPageExtensionReturn*>(output);
+
+ errorPage->content = QString("<html><head><title>Failed loading page</title></head><body>%1</body></html>")
+ .arg(info->errorString).toUtf8();
+
+ return true;
+}
+
+bool WebPage::acceptNavigationRequest(QWebFrame* frame, const QNetworkRequest& request, NavigationType type)
+{
+ QObject* view = parent();
+
+ QVariant value = view->property("keyboardModifiers");
+
+ if (!value.isNull()) {
+ Qt::KeyboardModifiers modifiers = Qt::KeyboardModifiers(value.toInt());
+
+ if (modifiers & Qt::ShiftModifier) {
+ QWebPage* page = createWindow(QWebPage::WebBrowserWindow);
+ page->mainFrame()->load(request);
+ return false;
+ }
+
+ if (modifiers & Qt::AltModifier) {
+ openUrlInDefaultBrowser(request.url());
+ return false;
+ }
+ }
+
+ return QWebPage::acceptNavigationRequest(frame, request, type);
+}
+
+void WebPage::openUrlInDefaultBrowser(const QUrl& url)
+{
+#ifndef QT_NO_DESKTOPSERVICES
+ if (QAction* action = qobject_cast<QAction*>(sender()))
+ QDesktopServices::openUrl(action->data().toUrl());
+ else
+ QDesktopServices::openUrl(url);
+#endif
+}
+
+QString WebPage::userAgentForUrl(const QUrl& url) const
+{
+ if (!m_userAgent.isEmpty())
+ return m_userAgent;
+ return QWebPage::userAgentForUrl(url);
+}
+
+bool WebPage::shouldInterruptJavaScript()
+{
+ if (!m_interruptingJavaScriptEnabled)
+ return false;
+ return QWebPage::shouldInterruptJavaScript();
+}
+
+void WebPage::authenticationRequired(QNetworkReply* reply, QAuthenticator* authenticator)
+{
+ QDialog* dialog = new QDialog(QApplication::activeWindow());
+ dialog->setWindowTitle("HTTP Authentication");
+
+ QGridLayout* layout = new QGridLayout(dialog);
+ dialog->setLayout(layout);
+
+ QLabel* messageLabel = new QLabel(dialog);
+ messageLabel->setWordWrap(true);
+ QString messageStr = QString("Enter with username and password for: %1");
+ messageLabel->setText(messageStr.arg(reply->url().toString()));
+ layout->addWidget(messageLabel, 0, 1);
+
+#ifndef QT_NO_LINEEDIT
+ QLabel* userLabel = new QLabel("Username:", dialog);
+ layout->addWidget(userLabel, 1, 0);
+ QLineEdit* userInput = new QLineEdit(dialog);
+ layout->addWidget(userInput, 1, 1);
+
+ QLabel* passLabel = new QLabel("Password:", dialog);
+ layout->addWidget(passLabel, 2, 0);
+ QLineEdit* passInput = new QLineEdit(dialog);
+ passInput->setEchoMode(QLineEdit::Password);
+ layout->addWidget(passInput, 2, 1);
+#endif
+
+ QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok
+ | QDialogButtonBox::Cancel, Qt::Horizontal, dialog);
+ connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept()));
+ connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject()));
+ layout->addWidget(buttonBox, 3, 1);
+
+ if (dialog->exec() == QDialog::Accepted) {
+#ifndef QT_NO_LINEEDIT
+ authenticator->setUser(userInput->text());
+ authenticator->setPassword(passInput->text());
+#endif
+ }
+
+ delete dialog;
+}
+
+void WebPage::requestPermission(QWebFrame* frame, QWebPage::Feature feature)
+{
+ setFeaturePermission(frame, feature, PermissionGrantedByUser);
+}
+
+void WebPage::featurePermissionRequestCanceled(QWebFrame*, QWebPage::Feature)
+{
+}
+
+QWebPage* WebPage::createWindow(QWebPage::WebWindowType type)
+{
+ LauncherWindow* mw = new LauncherWindow;
+ if (type == WebModalDialog)
+ mw->setWindowModality(Qt::ApplicationModal);
+ mw->show();
+ return mw->page();
+}
+
+QObject* WebPage::createPlugin(const QString &classId, const QUrl&, const QStringList&, const QStringList&)
+{
+ if (classId == "alien_QLabel") {
+ QLabel* l = new QLabel;
+ l->winId();
+ return l;
+ }
+
+#ifndef QT_NO_UITOOLS
+ QUiLoader loader;
+ return loader.createWidget(classId, view());
+#else
+ Q_UNUSED(classId);
+ return 0;
+#endif
+}
+
diff --git a/Tools/QtTestBrowser/webpage.h b/Tools/QtTestBrowser/webpage.h
new file mode 100644
index 000000000..01f3f6a86
--- /dev/null
+++ b/Tools/QtTestBrowser/webpage.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
+ * Copyright (C) 2006 George Staikos <staikos@kde.org>
+ * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef webpage_h
+#define webpage_h
+
+#include <qwebframe.h>
+#include <qwebpage.h>
+
+class WebPage : public QWebPage {
+ Q_OBJECT
+
+public:
+ WebPage(QObject* parent = 0);
+
+ virtual QWebPage* createWindow(QWebPage::WebWindowType);
+ virtual QObject* createPlugin(const QString&, const QUrl&, const QStringList&, const QStringList&);
+ virtual bool supportsExtension(QWebPage::Extension extension) const;
+ virtual bool extension(Extension extension, const ExtensionOption* option, ExtensionReturn* output);
+
+ virtual bool acceptNavigationRequest(QWebFrame* frame, const QNetworkRequest& request, NavigationType type);
+
+ QString userAgentForUrl(const QUrl& url) const;
+ void setInterruptingJavaScriptEnabled(bool enabled) { m_interruptingJavaScriptEnabled = enabled; }
+
+public slots:
+ void openUrlInDefaultBrowser(const QUrl& url = QUrl());
+ void setUserAgent(const QString& ua) { m_userAgent = ua; }
+ bool shouldInterruptJavaScript();
+ void authenticationRequired(QNetworkReply*, QAuthenticator*);
+ void requestPermission(QWebFrame* frame, QWebPage::Feature feature);
+ void featurePermissionRequestCanceled(QWebFrame* frame, QWebPage::Feature feature);
+
+private:
+ void applyProxy();
+ QString m_userAgent;
+ bool m_interruptingJavaScriptEnabled;
+};
+
+#endif
diff --git a/Tools/QtTestBrowser/webview.cpp b/Tools/QtTestBrowser/webview.cpp
new file mode 100644
index 000000000..3ea98f90b
--- /dev/null
+++ b/Tools/QtTestBrowser/webview.cpp
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
+ * Copyright (C) 2006 George Staikos <staikos@kde.org>
+ * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "webview.h"
+
+#include <QAction>
+#include <QGraphicsScene>
+#include <QGraphicsSceneContextMenuEvent>
+#include <QGraphicsSceneMouseEvent>
+#include <QMenu>
+#include <QScrollBar>
+#include <QTimer>
+
+#ifndef QT_NO_ANIMATION
+#include <QAbstractAnimation>
+#include <QAbstractTransition>
+#include <QFinalState>
+#include <QPropertyAnimation>
+#include <QState>
+#include <QStateMachine>
+#endif
+
+WebViewGraphicsBased::WebViewGraphicsBased(QWidget* parent)
+ : QGraphicsView(parent)
+ , m_item(new GraphicsWebView)
+ , m_numPaintsTotal(0)
+ , m_numPaintsSinceLastMeasure(0)
+ , m_measureFps(false)
+ , m_resizesToContents(false)
+ , m_machine(0)
+{
+ setScene(new QGraphicsScene(this));
+ scene()->addItem(m_item);
+ scene()->setFocusItem(m_item);
+
+ setFrameShape(QFrame::NoFrame);
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+
+ m_updateTimer = new QTimer(this);
+ m_updateTimer->setInterval(1000);
+ connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(updateFrameRate()));
+}
+
+void WebViewGraphicsBased::setPage(QWebPage* page)
+{
+ connect(page->mainFrame(), SIGNAL(contentsSizeChanged(const QSize&)), SLOT(contentsSizeChanged(const QSize&)));
+ connect(page, SIGNAL(scrollRequested(int, int, const QRect&)), SLOT(scrollRequested(int, int)));
+ graphicsWebView()->setPage(page);
+}
+
+void WebViewGraphicsBased::scrollRequested(int x, int y)
+{
+ if (!m_resizesToContents)
+ return;
+
+ // Turn off interactive mode while scrolling, or QGraphicsView will replay the
+ // last mouse event which may cause WebKit to initiate a drag operation.
+ bool interactive = isInteractive();
+ setInteractive(false);
+
+ verticalScrollBar()->setValue(-y);
+ horizontalScrollBar()->setValue(-x);
+
+ setInteractive(interactive);
+}
+
+void WebViewGraphicsBased::contentsSizeChanged(const QSize& size)
+{
+ if (m_resizesToContents)
+ scene()->setSceneRect(0, 0, size.width(), size.height());
+}
+
+void WebViewGraphicsBased::setResizesToContents(bool b)
+{
+ if (b == m_resizesToContents)
+ return;
+
+ m_resizesToContents = b;
+ graphicsWebView()->setResizesToContents(m_resizesToContents);
+
+ // When setting resizesToContents ON, our web view widget will always size as big as the
+ // web content being displayed, and so will the QWebPage's viewport. It implies that internally
+ // WebCore will work as if there was no content rendered offscreen, and then no scrollbars need
+ // drawing. In order to keep scrolling working, we:
+ //
+ // 1) Set QGraphicsView's scrollbars policy back to 'auto'.
+ // 2) Set scene's boundaries rect to an invalid size, which automatically makes it to be as big
+ // as it needs to enclose all items onto it. We do that because QGraphicsView also calculates
+ // the size of its scrollable area according to the amount of content in scene that is rendered
+ // offscreen.
+ // 3) Set QWebPage's preferredContentsSize according to the size of QGraphicsView's viewport,
+ // so WebCore properly lays pages out.
+ //
+ // On the other hand, when toggling resizesToContents OFF, we set back the default values, as
+ // opposite as described above.
+ if (m_resizesToContents) {
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ graphicsWebView()->page()->setPreferredContentsSize(size());
+ QRectF itemRect(graphicsWebView()->geometry().topLeft(), graphicsWebView()->page()->mainFrame()->contentsSize());
+ graphicsWebView()->setGeometry(itemRect);
+ scene()->setSceneRect(itemRect);
+ } else {
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ graphicsWebView()->page()->setPreferredContentsSize(QSize());
+ QRect viewportRect(QPoint(0, 0), size());
+ graphicsWebView()->setGeometry(viewportRect);
+ scene()->setSceneRect(viewportRect);
+ }
+}
+
+void WebViewGraphicsBased::resizeEvent(QResizeEvent* event)
+{
+ QGraphicsView::resizeEvent(event);
+
+ QSize size(event->size());
+
+ if (m_resizesToContents) {
+ graphicsWebView()->page()->setPreferredContentsSize(size);
+ return;
+ }
+
+ QRectF rect(QPoint(0, 0), size);
+ graphicsWebView()->setGeometry(rect);
+ scene()->setSceneRect(rect);
+}
+
+void WebViewGraphicsBased::setFrameRateMeasurementEnabled(bool enabled)
+{
+ m_measureFps = enabled;
+ if (m_measureFps) {
+ m_lastConsultTime = m_startTime = QTime::currentTime();
+ m_fpsTimer.start();
+ m_updateTimer->start();
+ } else {
+ m_fpsTimer.stop();
+ m_updateTimer->stop();
+ }
+}
+
+void WebViewGraphicsBased::updateFrameRate()
+{
+ const QTime now = QTime::currentTime();
+ int interval = m_lastConsultTime.msecsTo(now);
+ int frames = m_fpsTimer.numFrames(interval);
+ int current = interval ? frames * 1000 / interval : 0;
+
+ emit currentFPSUpdated(current);
+
+ m_lastConsultTime = now;
+}
+
+void WebViewGraphicsBased::animatedFlip()
+{
+#ifndef QT_NO_ANIMATION
+ QSizeF center = graphicsWebView()->boundingRect().size() / 2;
+ QPointF centerPoint = QPointF(center.width(), center.height());
+ graphicsWebView()->setTransformOriginPoint(centerPoint);
+
+ QPropertyAnimation* animation = new QPropertyAnimation(graphicsWebView(), "rotation", this);
+ animation->setDuration(1000);
+
+ int rotation = int(graphicsWebView()->rotation());
+
+ animation->setStartValue(rotation);
+ animation->setEndValue(rotation + 180 - (rotation % 180));
+
+ animation->start(QAbstractAnimation::DeleteWhenStopped);
+#endif
+}
+
+void WebViewGraphicsBased::animatedYFlip()
+{
+#ifndef QT_NO_ANIMATION
+ if (!m_machine) {
+ m_machine = new QStateMachine(this);
+
+ QState* s0 = new QState(m_machine);
+ s0->assignProperty(this, "yRotation", 0);
+
+ QState* s1 = new QState(m_machine);
+ s1->assignProperty(this, "yRotation", 90);
+
+ QAbstractTransition* t1 = s0->addTransition(s1);
+ QPropertyAnimation* yRotationAnim = new QPropertyAnimation(this, "yRotation", this);
+ t1->addAnimation(yRotationAnim);
+
+ QState* s2 = new QState(m_machine);
+ s2->assignProperty(this, "yRotation", -90);
+ s1->addTransition(s1, SIGNAL(propertiesAssigned()), s2);
+
+ QState* s3 = new QState(m_machine);
+ s3->assignProperty(this, "yRotation", 0);
+
+ QAbstractTransition* t2 = s2->addTransition(s3);
+ t2->addAnimation(yRotationAnim);
+
+ QFinalState* final = new QFinalState(m_machine);
+ s3->addTransition(s3, SIGNAL(propertiesAssigned()), final);
+
+ m_machine->setInitialState(s0);
+ yRotationAnim->setDuration(1000);
+ }
+
+ m_machine->start();
+#endif
+}
+
+void WebViewGraphicsBased::paintEvent(QPaintEvent* event)
+{
+ QGraphicsView::paintEvent(event);
+ if (!m_measureFps)
+ return;
+}
+
+static QMenu* createContextMenu(QWebPage* page, QPoint position)
+{
+ QMenu* menu = page->createStandardContextMenu();
+
+ QWebHitTestResult r = page->mainFrame()->hitTestContent(position);
+
+ if (!r.linkUrl().isEmpty()) {
+ WebPage* webPage = qobject_cast<WebPage*>(page);
+ QAction* newTabAction = menu->addAction("Open in Default &Browser", webPage, SLOT(openUrlInDefaultBrowser()));
+ newTabAction->setData(r.linkUrl());
+ menu->insertAction(menu->actions().at(2), newTabAction);
+ }
+ return menu;
+}
+
+void GraphicsWebView::mousePressEvent(QGraphicsSceneMouseEvent* event)
+{
+ setProperty("mouseButtons", QVariant::fromValue(int(event->buttons())));
+ setProperty("keyboardModifiers", QVariant::fromValue(int(event->modifiers())));
+
+ QGraphicsWebView::mousePressEvent(event);
+}
+
+void WebViewTraditional::mousePressEvent(QMouseEvent* event)
+{
+ setProperty("mouseButtons", QVariant::fromValue(int(event->buttons())));
+ setProperty("keyboardModifiers", QVariant::fromValue(int(event->modifiers())));
+
+ QWebView::mousePressEvent(event);
+}
+
+void GraphicsWebView::contextMenuEvent(QGraphicsSceneContextMenuEvent* event)
+{
+ QMenu* menu = createContextMenu(page(), event->pos().toPoint());
+ menu->exec(event->screenPos());
+ delete menu;
+}
+
+void WebViewTraditional::contextMenuEvent(QContextMenuEvent* event)
+{
+ QMenu* menu = createContextMenu(page(), event->pos());
+ menu->exec(event->globalPos());
+ delete menu;
+}
+
diff --git a/Tools/QtTestBrowser/webview.h b/Tools/QtTestBrowser/webview.h
new file mode 100644
index 000000000..b50b764e6
--- /dev/null
+++ b/Tools/QtTestBrowser/webview.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
+ * Copyright (C) 2006 George Staikos <staikos@kde.org>
+ * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef webview_h
+#define webview_h
+
+#include "fpstimer.h"
+#include "webpage.h"
+#include <qwebview.h>
+#include <qgraphicswebview.h>
+#include <QGraphicsView>
+#include <QGraphicsWidget>
+#include <QTime>
+
+QT_BEGIN_NAMESPACE
+class QStateMachine;
+QT_END_NAMESPACE
+
+class WebViewTraditional : public QWebView {
+ Q_OBJECT
+
+public:
+ WebViewTraditional(QWidget* parent) : QWebView(parent) {}
+
+protected:
+ virtual void contextMenuEvent(QContextMenuEvent*);
+ virtual void mousePressEvent(QMouseEvent*);
+};
+
+
+class GraphicsWebView : public QGraphicsWebView {
+ Q_OBJECT
+
+public:
+ GraphicsWebView(QGraphicsItem* parent = 0) : QGraphicsWebView(parent) {};
+
+protected:
+ virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent*);
+ virtual void mousePressEvent(QGraphicsSceneMouseEvent*);
+};
+
+
+class WebViewGraphicsBased : public QGraphicsView {
+ Q_OBJECT
+ Q_PROPERTY(qreal yRotation READ yRotation WRITE setYRotation)
+
+public:
+ WebViewGraphicsBased(QWidget* parent);
+ void setPage(QWebPage* page);
+
+ void setItemCacheMode(QGraphicsItem::CacheMode mode) { graphicsWebView()->setCacheMode(mode); }
+ QGraphicsItem::CacheMode itemCacheMode() { return graphicsWebView()->cacheMode(); }
+
+ void setFrameRateMeasurementEnabled(bool enabled);
+ bool frameRateMeasurementEnabled() const { return m_measureFps; }
+
+ virtual void resizeEvent(QResizeEvent*);
+ virtual void paintEvent(QPaintEvent* event);
+
+ void setResizesToContents(bool b);
+ bool resizesToContents() const { return m_resizesToContents; }
+
+ void setYRotation(qreal angle);
+ qreal yRotation() const { return m_yRotation; }
+
+ GraphicsWebView* graphicsWebView() const { return m_item; }
+
+public slots:
+ void updateFrameRate();
+ void animatedFlip();
+ void animatedYFlip();
+ void contentsSizeChanged(const QSize&);
+ void scrollRequested(int, int);
+
+signals:
+ void currentFPSUpdated(int fps);
+
+private:
+ GraphicsWebView* m_item;
+ int m_numPaintsTotal;
+ int m_numPaintsSinceLastMeasure;
+ QTime m_startTime;
+ QTime m_lastConsultTime;
+ QTimer* m_updateTimer;
+ bool m_measureFps;
+ qreal m_yRotation;
+ bool m_resizesToContents;
+ QStateMachine* m_machine;
+ FpsTimer m_fpsTimer;
+};
+
+inline void WebViewGraphicsBased::setYRotation(qreal angle)
+{
+ QRectF r = graphicsWebView()->boundingRect();
+ graphicsWebView()->setTransform(QTransform()
+ .translate(r.width() / 2, r.height() / 2)
+ .rotate(angle, Qt::YAxis)
+ .translate(-r.width() / 2, -r.height() / 2));
+ m_yRotation = angle;
+}
+
+#endif