view 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 source

/****************************************************************************
**
** 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;
}