view demos/browser/webview.d @ 73:7bfd46c330dc

more porting
author mandel
date Fri, 22 May 2009 10:59:00 +0000
parents 71b382c10ef6
children 37caa90ce503
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$
**
****************************************************************************/
module webview;

import qt.gui.QClipboard;
import qt.gui.QMenu;
import qt.gui.QMessageBox;
import qt.gui.QMouseEvent;

import qt.core.QDebug;
import qt.core.QBuffer;

import QtWebKit.QWebView;
import QtWebKit.QWebHitTestResult;
import QtUiTools.QUiLoader;

import browserapplication;
import browsermainwindow;
import cookiejar;
import downloadmanager;
import networkaccessmanager;
import tabwidget;


class WebPage : public QWebPage
{
	mixin Signal!("loadingUrl", QUrl url);

public:

	this(QObject parent = null)
	{
		super(parent);
		m_keyboardModifiers = Qt.NoModifier;
		m_pressedButtons = Qt.NoButton;
		m_openInNewTab = false;
		setNetworkAccessManager(BrowserApplication.networkAccessManager());
		this.unsupportedContent.connect(&this.handleUnsupportedContent);
	}
	
	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, 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:

	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:

	// set the webview mousepressedevent
	Qt.KeyboardModifiers m_keyboardModifiers;
	Qt.MouseButtons m_pressedButtons;
	bool m_openInNewTab;
	QUrl m_loadingUrl;
};

class WebView : public QWebView
{
public:
	
	WebView(QWidget parent = null)
	{
		super(parent);
		m_progress = 0;
		m_page = new WebPage(this);
		setPage(m_page);
		page().statusBarMessage.connect(&setStatusBarText);
		this.loadProgress.connect(&this.setProgress);
		this.loadFinished.connect(&this.loadFinished);
		page().loadingUrl.connect(&this.urlChanged);
		page().downloadRequested.connect(&this.downloadRequested);
		page().setForwardUnsupportedContent(true);
	}

	WebPage webPage() { return m_page; }

	void loadUrl(QUrl url)
	{
		m_initialUrl = url;
		load(url);
	}

	QUrl url() const
	{
		QUrl url = QWebView.url();
		if (!url.isEmpty())
			return url;
		return m_initialUrl;
	}

	QString lastStatusBarText()
	{
		return m_statusBarText;
	}

	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:

	void setProgress(int progress)
	{
		m_progress = progress;
	}

	void loadFinished()
	{
		if (100 != m_progress) {
			qWarning() << "Received finished signal while progress is still:" << progress() << "Url:" << url();
		}
		m_progress = 0;
	}

	void setStatusBarText(QString string)
	{
		m_statusBarText = string;
	}

	void downloadRequested(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;
}