demos/browser/webview.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/browser/webview.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,308 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "browserapplication.h"
+#include "browsermainwindow.h"
+#include "cookiejar.h"
+#include "downloadmanager.h"
+#include "networkaccessmanager.h"
+#include "tabwidget.h"
+#include "webview.h"
+
+#include <QtGui/QClipboard>
+#include <QtGui/QMenu>
+#include <QtGui/QMessageBox>
+#include <QtGui/QMouseEvent>
+
+#include <QtWebKit/QWebHitTestResult>
+
+#ifndef QT_NO_UITOOLS
+#include <QtUiTools/QUiLoader>
+#endif  //QT_NO_UITOOLS
+
+#include <QtCore/QDebug>
+#include <QtCore/QBuffer>
+
+WebPage::WebPage(QObject *parent)
+    : QWebPage(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 *WebPage::mainWindow()
+{
+    QObject *w = this->parent();
+    while (w) {
+        if (BrowserMainWindow *mw = qobject_cast<BrowserMainWindow*>(w))
+            return mw;
+        w = w->parent();
+    }
+    return BrowserApplication::instance()->mainWindow();
+}
+
+bool WebPage::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 *WebPage::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();
+}
+
+#if !defined(QT_NO_UITOOLS)
+QObject *WebPage::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());
+}
+#endif // !defined(QT_NO_UITOOLS)
+
+void WebPage::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);
+    Q_UNUSED(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());
+    }
+}
+
+
+WebView::WebView(QWidget* parent)
+    : 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);
+
+}
+
+void WebView::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 WebView::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);
+}
+
+void WebView::openLinkInNewTab()
+{
+    m_page->m_openInNewTab = true;
+    pageAction(QWebPage::OpenLinkInNewWindow)->trigger();
+}
+
+void WebView::setProgress(int progress)
+{
+    m_progress = progress;
+}
+
+void WebView::loadFinished()
+{
+    if (100 != m_progress) {
+        qWarning() << "Recieved finished signal while progress is still:" << progress()
+                   << "Url:" << url();
+    }
+    m_progress = 0;
+}
+
+void WebView::loadUrl(const QUrl &url)
+{
+    m_initialUrl = url;
+    load(url);
+}
+
+QString WebView::lastStatusBarText() const
+{
+    return m_statusBarText;
+}
+
+QUrl WebView::url() const
+{
+    QUrl url = QWebView::url();
+    if (!url.isEmpty())
+        return url;
+
+    return m_initialUrl;
+}
+
+void WebView::mousePressEvent(QMouseEvent *event)
+{
+    m_page->m_pressedButtons = event->buttons();
+    m_page->m_keyboardModifiers = event->modifiers();
+    QWebView::mousePressEvent(event);
+}
+
+void WebView::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 WebView::setStatusBarText(const QString &string)
+{
+    m_statusBarText = string;
+}
+
+void WebView::downloadRequested(const QNetworkRequest &request)
+{
+    BrowserApplication::downloadManager()->download(request);
+}
+