diff demos/browser/webview.d @ 45:71b382c10ef6

add coarse and incomplete QT browser port
author mandel
date Sun, 17 May 2009 18:49:59 +0000
parents
children 7bfd46c330dc
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/browser/webview.d	Sun May 17 18:49:59 2009 +0000
@@ -0,0 +1,354 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtWebKit.QWebView;
+
+import browserapplication;
+import browsermainwindow;
+import cookiejar;
+import downloadmanager;
+import networkaccessmanager;
+import tabwidget;
+import webview;
+
+import QtGui.QClipboard;
+import QtGui.QMenu;
+import QtGui.QMessageBox;
+import QtGui.QMouseEvent;
+
+import QtWebKit.QWebHitTestResult;
+
+import QtUiTools.QUiLoader;
+
+import QtCore.QDebug;
+import QtCore.QBuffer;
+
+/*
+QT_BEGIN_NAMESPACE
+class QAuthenticator;
+class QMouseEvent;
+class QNetworkProxy;
+class QNetworkReply;
+class QSslError;
+QT_END_NAMESPACE
+
+class BrowserMainWindow;
+*/
+
+class WebPage : public QWebPage {
+    Q_OBJECT
+
+signals:
+    void loadingUrl(const QUrl &url);
+
+public:
+    this(QObject *parent = null)
+{
+	super(parent);
+	m_keyboardModifiers = Qt.NoModifier;
+     m_pressedButtons = Qt.NoButton;
+     m_openInNewTab = false;
+    setNetworkAccessManager(BrowserApplication::networkAccessManager());
+    connect(this, SIGNAL(unsupportedContent(QNetworkReply *)),
+            this, SLOT(handleUnsupportedContent(QNetworkReply *)));
+}
+    BrowserMainWindow *mainWindow()
+{
+    QObject *w = this.parent();
+    while (w) {
+        if (BrowserMainWindow *mw = qobject_cast<BrowserMainWindow*>(w))
+            return mw;
+        w = w.parent();
+    }
+    return BrowserApplication::instance().mainWindow();
+}
+
+protected:
+    bool acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type);
+{
+    // ctrl open in new tab
+    // ctrl-shift open in new tab and select
+    // ctrl-alt open in new window
+    if (type == QWebPage::NavigationTypeLinkClicked
+        && (m_keyboardModifiers & Qt.ControlModifier
+            || m_pressedButtons == Qt.MidButton)) {
+        bool newWindow = (m_keyboardModifiers & Qt.AltModifier);
+        WebView *webView;
+        if (newWindow) {
+            BrowserApplication::instance().newMainWindow();
+            BrowserMainWindow *newMainWindow = BrowserApplication::instance().mainWindow();
+            webView = newMainWindow.currentTab();
+            newMainWindow.raise();
+            newMainWindow.activateWindow();
+            webView.setFocus();
+        } else {
+            bool selectNewTab = (m_keyboardModifiers & Qt.ShiftModifier);
+            webView = mainWindow().tabWidget().newTab(selectNewTab);
+        }
+        webView.load(request);
+        m_keyboardModifiers = Qt.NoModifier;
+        m_pressedButtons = Qt.NoButton;
+        return false;
+    }
+    if (frame == mainFrame()) {
+        m_loadingUrl = request.url();
+        emit loadingUrl(m_loadingUrl);
+    }
+    return QWebPage::acceptNavigationRequest(frame, request, type);
+}
+
+QWebPage *createWindow(QWebPage::WebWindowType type)
+{
+    Q_UNUSED(type);
+    if (m_keyboardModifiers & Qt.ControlModifier || m_pressedButtons == Qt.MidButton)
+        m_openInNewTab = true;
+    if (m_openInNewTab) {
+        m_openInNewTab = false;
+        return mainWindow().tabWidget().newTab().page();
+    }
+    BrowserApplication::instance().newMainWindow();
+    BrowserMainWindow *mainWindow = BrowserApplication::instance().mainWindow();
+    return mainWindow.currentTab().page();
+}
+
+version(QT_NO_UITOOLS) {} else
+{
+	QObject *createPlugin(const QString &classId, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues);
+	{
+	    Q_UNUSED(url);
+	    Q_UNUSED(paramNames);
+	    Q_UNUSED(paramValues);
+	    QUiLoader loader;
+	    return loader.createWidget(classId, view());
+	}
+}
+
+
+
+private slots:
+    void handleUnsupportedContent(QNetworkReply *reply)
+{
+    if (reply.error() == QNetworkReply::NoError) {
+        BrowserApplication::downloadManager().handleUnsupportedContent(reply);
+        return;
+    }
+
+    QFile file(QLatin1String(":/notfound.html"));
+    bool isOpened = file.open(QIODevice::ReadOnly);
+    Q_ASSERT(isOpened);
+    QString title = tr("Error loading page: %1").arg(reply.url().toString());
+    QString html = QString(QLatin1String(file.readAll()))
+                        .arg(title)
+                        .arg(reply.errorString())
+                        .arg(reply.url().toString());
+
+    QBuffer imageBuffer;
+    imageBuffer.open(QBuffer::ReadWrite);
+    QIcon icon = view().style().standardIcon(QStyle::SP_MessageBoxWarning, 0, view());
+    QPixmap pixmap = icon.pixmap(QSize(32,32));
+    if (pixmap.save(&imageBuffer, "PNG")) {
+        html.replace(QLatin1String("IMAGE_BINARY_DATA_HERE"),
+                     QString(QLatin1String(imageBuffer.buffer().toBase64())));
+    }
+
+    QList<QWebFrame*> frames;
+    frames.append(mainFrame());
+    while (!frames.isEmpty()) {
+        QWebFrame *frame = frames.takeFirst();
+        if (frame.url() == reply.url()) {
+            frame.setHtml(html, reply.url());
+            return;
+        }
+        QList<QWebFrame *> children = frame.childFrames();
+        foreach(QWebFrame *frame, children)
+            frames.append(frame);
+    }
+    if (m_loadingUrl == reply.url()) {
+        mainFrame().setHtml(html, reply.url());
+    }
+}
+
+private:
+    friend class WebView;
+
+    // set the webview mousepressedevent
+    Qt.KeyboardModifiers m_keyboardModifiers;
+    Qt.MouseButtons m_pressedButtons;
+    bool m_openInNewTab;
+    QUrl m_loadingUrl;
+};
+
+class WebView : public QWebView {
+    Q_OBJECT
+
+public:
+    WebView(QWidget *parent = null)
+    : QWebView(parent)
+    , m_progress(0)
+    , m_page(new WebPage(this))
+{
+    setPage(m_page);
+    connect(page(), SIGNAL(statusBarMessage(const QString&)),
+            SLOT(setStatusBarText(const QString&)));
+    connect(this, SIGNAL(loadProgress(int)),
+            this, SLOT(setProgress(int)));
+    connect(this, SIGNAL(loadFinished(bool)),
+            this, SLOT(loadFinished()));
+    connect(page(), SIGNAL(loadingUrl(const QUrl&)),
+            this, SIGNAL(urlChanged(const QUrl &)));
+    connect(page(), SIGNAL(downloadRequested(const QNetworkRequest &)),
+            this, SLOT(downloadRequested(const QNetworkRequest &)));
+    page().setForwardUnsupportedContent(true);
+
+}
+
+    WebPage *webPage() const { return m_page; }
+
+    void loadUrl(const QUrl &url)
+{
+    m_initialUrl = url;
+    load(url);
+}
+    
+    QUrl url() const
+{
+    QUrl url = QWebView::url();
+    if (!url.isEmpty())
+        return url;
+
+    return m_initialUrl;
+}
+
+    QString lastStatusBarText() const
+{
+    return m_statusBarText;
+}
+
+    inline int progress() const { return m_progress; }
+
+protected:
+    void mousePressEvent(QMouseEvent *event);
+{
+    m_page.m_pressedButtons = event.buttons();
+    m_page.m_keyboardModifiers = event.modifiers();
+    QWebView::mousePressEvent(event);
+}
+
+    void mouseReleaseEvent(QMouseEvent *event)
+{
+    QWebView::mouseReleaseEvent(event);
+    if (!event.isAccepted() && (m_page.m_pressedButtons & Qt.MidButton)) {
+        QUrl url(QApplication::clipboard().text(QClipboard::Selection));
+        if (!url.isEmpty() && url.isValid() && !url.scheme().isEmpty()) {
+            setUrl(url);
+        }
+    }
+}
+
+    void contextMenuEvent(QContextMenuEvent *event)
+{
+    QWebHitTestResult r = page().mainFrame().hitTestContent(event.pos());
+    if (!r.linkUrl().isEmpty()) {
+        QMenu menu(this);
+        menu.addAction(pageAction(QWebPage::OpenLinkInNewWindow));
+        menu.addAction(tr("Open in New Tab"), this, SLOT(openLinkInNewTab()));
+        menu.addSeparator();
+        menu.addAction(pageAction(QWebPage::DownloadLinkToDisk));
+        // Add link to bookmarks...
+        menu.addSeparator();
+        menu.addAction(pageAction(QWebPage::CopyLinkToClipboard));
+        if (page().settings().testAttribute(QWebSettings::DeveloperExtrasEnabled))
+            menu.addAction(pageAction(QWebPage::InspectElement));
+        menu.exec(mapToGlobal(event.pos()));
+        return;
+    }
+    QWebView::contextMenuEvent(event);
+}
+
+    void wheelEvent(QWheelEvent *event)
+{
+    if (QApplication::keyboardModifiers() & Qt.ControlModifier) {
+        int numDegrees = event.delta() / 8;
+        int numSteps = numDegrees / 15;
+        setTextSizeMultiplier(textSizeMultiplier() + numSteps * 0.1);
+        event.accept();
+        return;
+    }
+    QWebView::wheelEvent(event);
+}
+
+
+private slots:
+    void setProgress(int progress)
+{
+    m_progress = progress;
+}
+
+    void loadFinished()
+{
+    if (100 != m_progress) {
+        qWarning() << "Recieved finished signal while progress is still:" << progress()
+                   << "Url:" << url();
+    }
+    m_progress = 0;
+}
+
+    void setStatusBarText(const QString &string)
+{
+    m_statusBarText = string;
+}
+
+    void downloadRequested(const QNetworkRequest &request)
+{
+    BrowserApplication::downloadManager().download(request);
+}
+
+    void openLinkInNewTab()
+{
+    m_page.m_openInNewTab = true;
+    pageAction(QWebPage::OpenLinkInNewWindow).trigger();
+}
+private:
+    QString m_statusBarText;
+    QUrl m_initialUrl;
+    int m_progress;
+    WebPage *m_page;
+}