diff options
author | Ben Murdoch <benm@google.com> | 2011-05-13 16:23:25 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-05-16 11:35:02 +0100 |
commit | 65f03d4f644ce73618e5f4f50dd694b26f55ae12 (patch) | |
tree | f478babb801e720de7bfaee23443ffe029f58731 /Source/WebKit/qt/Api | |
parent | 47de4a2fb7262c7ebdb9cd133ad2c54c187454d0 (diff) | |
download | external_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.zip external_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.tar.gz external_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.tar.bz2 |
Merge WebKit at r75993: Initial merge by git.
Change-Id: I602bbdc3974787a3b0450456a30a7868286921c3
Diffstat (limited to 'Source/WebKit/qt/Api')
41 files changed, 16981 insertions, 0 deletions
diff --git a/Source/WebKit/qt/Api/DerivedSources.pro b/Source/WebKit/qt/Api/DerivedSources.pro new file mode 100644 index 0000000..3109ffe --- /dev/null +++ b/Source/WebKit/qt/Api/DerivedSources.pro @@ -0,0 +1,108 @@ +TEMPLATE = lib +TARGET = dummy + +include(headers.pri) + +CONFIG -= debug_and_release + +DESTDIR = ../../../include/QtWebKit + +QUOTE = "" +DOUBLE_ESCAPED_QUOTE = "" +ESCAPE = "" +win32-msvc* | wince* { + ESCAPE = "^" +} else:contains(QMAKE_HOST.os, "Windows"):isEmpty(QMAKE_SH) { + # MinGW's make will run makefile commands using sh, even if make + # was run from the Windows shell, if it finds sh in the path. + ESCAPE = "^" +} else { + QUOTE = "\'" + DOUBLE_ESCAPED_QUOTE = "\\\'" + ESCAPE = "\\" +} + +qtheader_module.target = $${DESTDIR}/QtWebKit +qtheader_module.depends = $${_PRO_FILE_} +qtheader_module.commands = echo $${QUOTE}$${LITERAL_HASH}ifndef QT_QTWEBKIT_MODULE_H$${QUOTE} > $${qtheader_module.target} && +qtheader_module.commands += echo $${QUOTE}$${LITERAL_HASH}define QT_QTWEBKIT_MODULE_H$${QUOTE} >> $${qtheader_module.target} && +qtheader_module.commands += echo $${QUOTE}$${LITERAL_HASH}include $${ESCAPE}<QtNetwork/QtNetwork$${ESCAPE}>$${QUOTE} >> $${qtheader_module.target} && +WEBKIT_CLASS_HEADERS = $${LITERAL_DOLLAR}$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}PWD/QtWebKit + +regex = ".*\\sclass\\sQWEBKIT_EXPORT\\s(\\w+)\\s(.*)" + +for(HEADER, WEBKIT_API_HEADERS) { + # 1. Append to QtWebKit header that includes all other header files + # Quotes need to be escaped once more when placed in eval() + eval(qtheader_module.commands += echo $${DOUBLE_ESCAPED_QUOTE}\$${LITERAL_HASH}include \\\"$$basename(HEADER)\\\"$${DOUBLE_ESCAPED_QUOTE} >> $${qtheader_module.target} &&) + + HEADER_NAME = $$basename(HEADER) + HEADER_TARGET = $$replace(HEADER_NAME, [^a-zA-Z0-9_], -) + HEADER_TARGET = "qtheader-$${HEADER_TARGET}" + + # 2. Create forwarding header files for qwebframe.h, etc. + # Normally they contain absolute paths, for package builds we make the path relative so that + # the package sources are relocatable. + + PATH_TO_HEADER = $$HEADER + CONFIG(standalone_package): PATH_TO_HEADER = ../../../Source/WebKit/qt/Api/$$basename(HEADER) + + eval($${HEADER_TARGET}.target = $${DESTDIR}/$${HEADER_NAME}) + eval($${HEADER_TARGET}.depends = $$HEADER) + eval($${HEADER_TARGET}.commands = echo $${DOUBLE_ESCAPED_QUOTE}\$${LITERAL_HASH}include \\\"$$PATH_TO_HEADER\\\"$${DOUBLE_ESCAPED_QUOTE} > $$eval($${HEADER_TARGET}.target)) + + QMAKE_EXTRA_TARGETS += $$HEADER_TARGET + qtheader_module.depends += $$eval($${HEADER_TARGET}.target) + + # 3. Extract class names of exported classes from the headers and generate + # the class name header files + + src_words = $$cat($$HEADER) + # Really make sure we're dealing with words + src_words = $$split(src_words, " ") + + src = $$join(src_words, $${LITERAL_WHITESPACE}) + for(ever) { + # Looking up by line is faster, so we try that first + res = $$find(src_words, "QWEBKIT_EXPORT") + isEmpty(res):break() + + # Then do a slow lookup to ensure we're dealing with an exported class + res = $$find(src, $$regex) + isEmpty(res):break() + + exp = $$replace(src, $$regex, "EXPORTED_CLASS = \\1") + eval($$exp) + + CLASS_TARGET = "qtheader_$${EXPORTED_CLASS}" + + eval($${CLASS_TARGET}.target = $${DESTDIR}/$${EXPORTED_CLASS}) + eval($${CLASS_TARGET}.depends = $$eval($${HEADER_TARGET}.target)) + eval($${CLASS_TARGET}.commands = echo $${DOUBLE_ESCAPED_QUOTE}\$${LITERAL_HASH}include \\\"$$basename(HEADER)\\\"$${DOUBLE_ESCAPED_QUOTE} > $$eval($${CLASS_TARGET}.target)) + + QMAKE_EXTRA_TARGETS += $$CLASS_TARGET + WEBKIT_CLASS_HEADERS += $${LITERAL_DOLLAR}$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}PWD/$${EXPORTED_CLASS} + + generated_files.depends += $$eval($${CLASS_TARGET}.target) + qtheader_pri.depends += $$eval($${CLASS_TARGET}.target) + + # Qt's QRegExp does not support inline non-greedy matching, + # so we'll have to work around it by updating the haystack + src = $$replace(src, $$regex, "\\2") + src_words = $$join(src, $${LITERAL_WHITESPACE}) + } +} + +qtheader_module.commands += echo $${QUOTE}$${LITERAL_HASH}endif // QT_QTWEBKIT_MODULE_H$${QUOTE} >> $${qtheader_module.target} +QMAKE_EXTRA_TARGETS += qtheader_module + +qtheader_pri.target = $${DESTDIR}/classheaders.pri +qtheader_pri.depends += $${_PRO_FILE_} +qtheader_pri.commands = echo $${QUOTE}WEBKIT_CLASS_HEADERS = $${WEBKIT_CLASS_HEADERS}$${QUOTE} > $${qtheader_pri.target} +QMAKE_EXTRA_TARGETS += qtheader_pri + +generated_files.depends += $${qtheader_module.target} $${qtheader_pri.target} +QMAKE_EXTRA_TARGETS += generated_files + + + diff --git a/Source/WebKit/qt/Api/headers.pri b/Source/WebKit/qt/Api/headers.pri new file mode 100644 index 0000000..29bb125 --- /dev/null +++ b/Source/WebKit/qt/Api/headers.pri @@ -0,0 +1,15 @@ +WEBKIT_API_HEADERS = $$PWD/qwebframe.h \ + $$PWD/qgraphicswebview.h \ + $$PWD/qwebkitglobal.h \ + $$PWD/qwebkitplatformplugin.h \ + $$PWD/qwebpage.h \ + $$PWD/qwebview.h \ + $$PWD/qwebsettings.h \ + $$PWD/qwebhistoryinterface.h \ + $$PWD/qwebdatabase.h \ + $$PWD/qwebsecurityorigin.h \ + $$PWD/qwebelement.h \ + $$PWD/qwebpluginfactory.h \ + $$PWD/qwebhistory.h \ + $$PWD/qwebinspector.h \ + $$PWD/qwebkitversion.h diff --git a/Source/WebKit/qt/Api/qgraphicswebview.cpp b/Source/WebKit/qt/Api/qgraphicswebview.cpp new file mode 100644 index 0000000..b6ac31b --- /dev/null +++ b/Source/WebKit/qt/Api/qgraphicswebview.cpp @@ -0,0 +1,1150 @@ +/* + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qgraphicswebview.h" + +#if !defined(QT_NO_GRAPHICSVIEW) + +#include "qwebframe.h" +#include "qwebframe_p.h" +#include "qwebpage.h" +#include "qwebpage_p.h" +#include "PageClientQt.h" +#include "FrameView.h" +#include "GraphicsContext.h" +#include "IntRect.h" +#include "TiledBackingStore.h" +#include <QtCore/qmetaobject.h> +#include <QtCore/qsharedpointer.h> +#include <QtCore/qtimer.h> +#include <QtGui/qapplication.h> +#include <QtGui/qgraphicsscene.h> +#include <QtGui/qgraphicssceneevent.h> +#include <QtGui/qgraphicsview.h> +#include <QtGui/qpixmapcache.h> +#include <QtGui/qscrollbar.h> +#include <QtGui/qstyleoption.h> +#include <QtGui/qinputcontext.h> +#if defined(Q_WS_X11) +#include <QX11Info> +#endif +#include <Settings.h> + +using namespace WebCore; + +class QGraphicsWebViewPrivate { +public: + QGraphicsWebViewPrivate(QGraphicsWebView* parent) + : q(parent) + , page(0) + , resizesToContents(false) {} + + virtual ~QGraphicsWebViewPrivate(); + + void syncLayers(); + + void updateResizesToContentsForPage(); + + void detachCurrentPage(); + + void _q_doLoadFinished(bool success); + void _q_contentsSizeChanged(const QSize&); + void _q_scaleChanged(); + +#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) + void _q_updateMicroFocus(); +#endif + void _q_pageDestroyed(); + + QGraphicsWebView* q; + QWebPage* page; + bool resizesToContents; + + QGraphicsItemOverlay* overlay() const + { + if (!page || !page->d->client) + return 0; + return pageClient()->overlay; + } + + PageClientQGraphicsWidget* pageClient() const + { + return static_cast<WebCore::PageClientQGraphicsWidget*> (page->d->client.get()); + } +}; + +QGraphicsWebViewPrivate::~QGraphicsWebViewPrivate() +{ + detachCurrentPage(); +} + +void QGraphicsWebViewPrivate::syncLayers() +{ +#if USE(ACCELERATED_COMPOSITING) + pageClient()->syncLayers(); +#endif +} + +void QGraphicsWebViewPrivate::_q_doLoadFinished(bool success) +{ + // If the page had no title, still make sure it gets the signal + if (q->title().isEmpty()) + emit q->urlChanged(q->url()); + + emit q->loadFinished(success); +} + +#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) +void QGraphicsWebViewPrivate::_q_updateMicroFocus() +{ + // Ideally, this should be handled by a common call to an updateMicroFocus function + // in QGraphicsItem. See http://bugreports.qt.nokia.com/browse/QTBUG-7578. + QList<QGraphicsView*> views = q->scene()->views(); + for (int c = 0; c < views.size(); ++c) { + QInputContext* ic = views.at(c)->inputContext(); + if (ic) + ic->update(); + } +} +#endif + +void QGraphicsWebViewPrivate::_q_pageDestroyed() +{ + page = 0; + q->setPage(0); +} + +void QGraphicsWebViewPrivate::updateResizesToContentsForPage() +{ + ASSERT(page); + pageClient()->viewResizesToContents = resizesToContents; + if (resizesToContents) { + // resizes to contents mode requires preferred contents size to be set + if (!page->preferredContentsSize().isValid()) + page->setPreferredContentsSize(QSize(960, 800)); + + QObject::connect(page->mainFrame(), SIGNAL(contentsSizeChanged(QSize)), + q, SLOT(_q_contentsSizeChanged(const QSize&)), Qt::UniqueConnection); + } else { + QObject::disconnect(page->mainFrame(), SIGNAL(contentsSizeChanged(QSize)), + q, SLOT(_q_contentsSizeChanged(const QSize&))); + } + page->d->page->mainFrame()->view()->setPaintsEntireContents(resizesToContents); + page->d->page->mainFrame()->view()->setDelegatesScrolling(resizesToContents); +} + +void QGraphicsWebViewPrivate::_q_contentsSizeChanged(const QSize& size) +{ + if (!resizesToContents) + return; + q->setGeometry(QRectF(q->geometry().topLeft(), size)); +} + +void QGraphicsWebViewPrivate::_q_scaleChanged() +{ +#if ENABLE(TILED_BACKING_STORE) + if (!page) + return; + pageClient()->updateTiledBackingStoreScale(); +#endif +} + +/*! + \class QGraphicsWebView + \brief The QGraphicsWebView class allows Web content to be added to a GraphicsView. + \since 4.6 + + An instance of this class renders Web content from a URL or supplied as data, using + features of the QtWebKit module. + + If the width and height of the item are not set, they will default to 800 and 600, + respectively. If the Web page contents is larger than that, scrollbars will be shown + if not disabled explicitly. + + \section1 Browser Features + + Many of the functions, signals and properties provided by QWebView are also available + for this item, making it simple to adapt existing code to use QGraphicsWebView instead + of QWebView. + + The item uses a QWebPage object to perform the rendering of Web content, and this can + be obtained with the page() function, enabling the document itself to be accessed and + modified. + + As with QWebView, the item records the browsing history using a QWebHistory object, + accessible using the history() function. The QWebSettings object that defines the + configuration of the browser can be obtained with the settings() function, enabling + features like plugin support to be customized for each item. + + \sa QWebView, QGraphicsTextItem +*/ + +/*! + \fn void QGraphicsWebView::titleChanged(const QString &title) + + This signal is emitted whenever the \a title of the main frame changes. + + \sa title() +*/ + +/*! + \fn void QGraphicsWebView::urlChanged(const QUrl &url) + + This signal is emitted when the \a url of the view changes. + + \sa url(), load() +*/ + +/*! + \fn void QGraphicsWebView::iconChanged() + + This signal is emitted whenever the icon of the page is loaded or changes. + + In order for icons to be loaded, you will need to set an icon database path + using QWebSettings::setIconDatabasePath(). + + \sa icon(), QWebSettings::setIconDatabasePath() +*/ + +/*! + \fn void QGraphicsWebView::loadStarted() + + This signal is emitted when a new load of the page is started. + + \sa loadProgress(), loadFinished() +*/ + +/*! + \fn void QGraphicsWebView::loadFinished(bool ok) + + This signal is emitted when a load of the page is finished. + \a ok will indicate whether the load was successful or any error occurred. + + \sa loadStarted() +*/ + +/*! + Constructs an empty QGraphicsWebView with parent \a parent. + + \sa load() +*/ +QGraphicsWebView::QGraphicsWebView(QGraphicsItem* parent) + : QGraphicsWidget(parent) + , d(new QGraphicsWebViewPrivate(this)) +{ + setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true); + setAcceptDrops(true); + setAcceptHoverEvents(true); + setAcceptTouchEvents(true); + setFocusPolicy(Qt::StrongFocus); + setFlag(QGraphicsItem::ItemClipsChildrenToShape, true); +#if ENABLE(TILED_BACKING_STORE) + QObject::connect(this, SIGNAL(scaleChanged()), this, SLOT(_q_scaleChanged())); +#endif +} + +/*! + Destroys the item. +*/ +QGraphicsWebView::~QGraphicsWebView() +{ + delete d; +} + +/*! + Returns a pointer to the underlying web page. + + \sa setPage() +*/ +QWebPage* QGraphicsWebView::page() const +{ + if (!d->page) { + QGraphicsWebView* that = const_cast<QGraphicsWebView*>(this); + QWebPage* page = new QWebPage(that); + + // Default to not having a background, in the case + // the page doesn't provide one. + QPalette palette = QApplication::palette(); + palette.setBrush(QPalette::Base, QColor::fromRgbF(0, 0, 0, 0)); + page->setPalette(palette); + + that->setPage(page); + } + + return d->page; +} + +/*! \reimp +*/ +void QGraphicsWebView::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget*) +{ +#if ENABLE(TILED_BACKING_STORE) + if (WebCore::TiledBackingStore* backingStore = QWebFramePrivate::core(page()->mainFrame())->tiledBackingStore()) { + // FIXME: We should set the backing store viewport earlier than in paint + backingStore->adjustVisibleRect(); + // QWebFrame::render is a public API, bypass it for tiled rendering so behavior does not need to change. + WebCore::GraphicsContext context(painter); + page()->mainFrame()->d->renderFromTiledBackingStore(&context, option->exposedRect.toAlignedRect()); + return; + } +#endif +#if USE(ACCELERATED_COMPOSITING) && !USE(TEXTURE_MAPPER) + page()->mainFrame()->render(painter, d->overlay() ? QWebFrame::ContentsLayer : QWebFrame::AllLayers, option->exposedRect.toAlignedRect()); +#else + page()->mainFrame()->render(painter, QWebFrame::AllLayers, option->exposedRect.toRect()); +#endif +} + +/*! \reimp +*/ +bool QGraphicsWebView::sceneEvent(QEvent* event) +{ + // Re-implemented in order to allows fixing event-related bugs in patch releases. + + if (d->page && (event->type() == QEvent::TouchBegin + || event->type() == QEvent::TouchEnd + || event->type() == QEvent::TouchUpdate)) { + d->page->event(event); + + // Always return true so that we'll receive also TouchUpdate and TouchEnd events + return true; + } + + return QGraphicsWidget::sceneEvent(event); +} + +/*! \reimp +*/ +QVariant QGraphicsWebView::itemChange(GraphicsItemChange change, const QVariant& value) +{ + switch (change) { + // Differently from QWebView, it is interesting to QGraphicsWebView to handle + // post mouse cursor change notifications. Reason: 'ItemCursorChange' is sent + // as the first action in QGraphicsItem::setCursor implementation, and at that + // item widget's cursor has not been effectively changed yet. + // After cursor is properly set (at 'ItemCursorHasChanged' emission time), we + // fire 'CursorChange'. + case ItemCursorChange: + return value; + case ItemCursorHasChanged: { + QEvent event(QEvent::CursorChange); + QApplication::sendEvent(this, &event); + return value; + } + default: + break; + } + + return QGraphicsWidget::itemChange(change, value); +} + +/*! \reimp +*/ +QSizeF QGraphicsWebView::sizeHint(Qt::SizeHint which, const QSizeF& constraint) const +{ + if (which == Qt::PreferredSize) + return QSizeF(800, 600); // ### + return QGraphicsWidget::sizeHint(which, constraint); +} + +/*! \reimp +*/ +QVariant QGraphicsWebView::inputMethodQuery(Qt::InputMethodQuery query) const +{ + if (d->page) + return d->page->inputMethodQuery(query); + return QVariant(); +} + +/*! \reimp +*/ +bool QGraphicsWebView::event(QEvent* event) +{ + // Re-implemented in order to allows fixing event-related bugs in patch releases. + + if (d->page) { +#ifndef QT_NO_CONTEXTMENU + if (event->type() == QEvent::GraphicsSceneContextMenu) { + if (!isEnabled()) + return false; + + QGraphicsSceneContextMenuEvent* ev = static_cast<QGraphicsSceneContextMenuEvent*>(event); + QContextMenuEvent fakeEvent(QContextMenuEvent::Reason(ev->reason()), ev->pos().toPoint()); + if (d->page->swallowContextMenuEvent(&fakeEvent)) { + event->accept(); + return true; + } + d->page->updatePositionDependentActions(fakeEvent.pos()); + } else +#endif // QT_NO_CONTEXTMENU + { +#ifndef QT_NO_CURSOR + if (event->type() == QEvent::CursorChange) { + // An unsetCursor will set the cursor to Qt::ArrowCursor. + // Thus this cursor change might be a QWidget::unsetCursor() + // If this is not the case and it came from WebCore, the + // QWebPageClient already has set its cursor internally + // to Qt::ArrowCursor, so updating the cursor is always + // right, as it falls back to the last cursor set by + // WebCore. + // FIXME: Add a QEvent::CursorUnset or similar to Qt. + if (cursor().shape() == Qt::ArrowCursor) + d->page->d->client->resetCursor(); + } +#endif + } + } + return QGraphicsWidget::event(event); +} + +void QGraphicsWebViewPrivate::detachCurrentPage() +{ + if (!page) + return; + + page->d->view.clear(); + page->d->client = 0; + + // if the page was created by us, we own it and need to + // destroy it as well. + + if (page->parent() == q) + delete page; + else + page->disconnect(q); + + page = 0; +} + +/*! + Makes \a page the new web page of the web graphicsitem. + + The parent QObject of the provided page remains the owner + of the object. If the current document is a child of the web + view, it will be deleted. + + \sa page() +*/ +void QGraphicsWebView::setPage(QWebPage* page) +{ + if (d->page == page) + return; + + d->detachCurrentPage(); + d->page = page; + + if (!d->page) + return; + + d->page->d->client = new PageClientQGraphicsWidget(this, page); // set the page client + + if (d->overlay()) + d->overlay()->prepareGraphicsItemGeometryChange(); + + QSize size = geometry().size().toSize(); + page->setViewportSize(size); + + if (d->resizesToContents) + d->updateResizesToContentsForPage(); + + QWebFrame* mainFrame = d->page->mainFrame(); + + connect(mainFrame, SIGNAL(titleChanged(QString)), + this, SIGNAL(titleChanged(QString))); + connect(mainFrame, SIGNAL(iconChanged()), + this, SIGNAL(iconChanged())); + connect(mainFrame, SIGNAL(urlChanged(QUrl)), + this, SIGNAL(urlChanged(QUrl))); + connect(d->page, SIGNAL(loadStarted()), + this, SIGNAL(loadStarted())); + connect(d->page, SIGNAL(loadProgress(int)), + this, SIGNAL(loadProgress(int))); + connect(d->page, SIGNAL(loadFinished(bool)), + this, SLOT(_q_doLoadFinished(bool))); + connect(d->page, SIGNAL(statusBarMessage(QString)), + this, SIGNAL(statusBarMessage(QString))); + connect(d->page, SIGNAL(linkClicked(QUrl)), + this, SIGNAL(linkClicked(QUrl))); + connect(d->page, SIGNAL(destroyed()), + this, SLOT(_q_pageDestroyed())); +#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) + connect(d->page, SIGNAL(microFocusChanged()), + this, SLOT(_q_updateMicroFocus())); +#endif +} + +/*! + \property QGraphicsWebView::url + \brief the url of the web page currently viewed + + Setting this property clears the view and loads the URL. + + By default, this property contains an empty, invalid URL. + + \sa load(), urlChanged() +*/ + +void QGraphicsWebView::setUrl(const QUrl &url) +{ + page()->mainFrame()->setUrl(url); +} + +QUrl QGraphicsWebView::url() const +{ + if (d->page) + return d->page->mainFrame()->url(); + + return QUrl(); +} + +/*! + \property QGraphicsWebView::title + \brief the title of the web page currently viewed + + By default, this property contains an empty string. + + \sa titleChanged() +*/ +QString QGraphicsWebView::title() const +{ + if (d->page) + return d->page->mainFrame()->title(); + + return QString(); +} + +/*! + \property QGraphicsWebView::icon + \brief the icon associated with the web page currently viewed + + By default, this property contains a null icon. + + \sa iconChanged(), QWebSettings::iconForUrl() +*/ +QIcon QGraphicsWebView::icon() const +{ + if (d->page) + return d->page->mainFrame()->icon(); + + return QIcon(); +} + +/*! + \property QGraphicsWebView::zoomFactor + \brief the zoom factor for the view +*/ + +void QGraphicsWebView::setZoomFactor(qreal factor) +{ + if (factor == page()->mainFrame()->zoomFactor()) + return; + + page()->mainFrame()->setZoomFactor(factor); +} + +qreal QGraphicsWebView::zoomFactor() const +{ + return page()->mainFrame()->zoomFactor(); +} + +/*! \reimp +*/ +void QGraphicsWebView::updateGeometry() +{ + if (d->overlay()) + d->overlay()->prepareGraphicsItemGeometryChange(); + + QGraphicsWidget::updateGeometry(); + + if (!d->page) + return; + + QSize size = geometry().size().toSize(); + d->page->setViewportSize(size); +} + +/*! \reimp +*/ +void QGraphicsWebView::setGeometry(const QRectF& rect) +{ + QGraphicsWidget::setGeometry(rect); + + if (d->overlay()) + d->overlay()->prepareGraphicsItemGeometryChange(); + + if (!d->page) + return; + + // NOTE: call geometry() as setGeometry ensures that + // the geometry is within legal bounds (minimumSize, maximumSize) + QSize size = geometry().size().toSize(); + d->page->setViewportSize(size); +} + +/*! + Convenience slot that stops loading the document. + + \sa reload(), loadFinished() +*/ +void QGraphicsWebView::stop() +{ + if (d->page) + d->page->triggerAction(QWebPage::Stop); +} + +/*! + Convenience slot that loads the previous document in the list of documents + built by navigating links. Does nothing if there is no previous document. + + \sa forward() +*/ +void QGraphicsWebView::back() +{ + if (d->page) + d->page->triggerAction(QWebPage::Back); +} + +/*! + Convenience slot that loads the next document in the list of documents + built by navigating links. Does nothing if there is no next document. + + \sa back() +*/ +void QGraphicsWebView::forward() +{ + if (d->page) + d->page->triggerAction(QWebPage::Forward); +} + +/*! + Reloads the current document. + + \sa stop(), loadStarted() +*/ +void QGraphicsWebView::reload() +{ + if (d->page) + d->page->triggerAction(QWebPage::Reload); +} + +/*! + Loads the specified \a url and displays it. + + \note The view remains the same until enough data has arrived to display the new \a url. + + \sa setUrl(), url(), urlChanged() +*/ +void QGraphicsWebView::load(const QUrl& url) +{ + page()->mainFrame()->load(url); +} + +/*! + \fn void QGraphicsWebView::load(const QNetworkRequest &request, QNetworkAccessManager::Operation operation, const QByteArray &body) + + Loads a network request, \a request, using the method specified in \a operation. + + \a body is optional and is only used for POST operations. + + \note The view remains the same until enough data has arrived to display the new url. + + \sa url(), urlChanged() +*/ + +void QGraphicsWebView::load(const QNetworkRequest& request, + QNetworkAccessManager::Operation operation, + const QByteArray& body) +{ + page()->mainFrame()->load(request, operation, body); +} + +/*! + Sets the content of the web view to the specified \a html. + + External objects such as stylesheets or images referenced in the HTML + document are located relative to \a baseUrl. + + The \a html is loaded immediately; external objects are loaded asynchronously. + + When using this method, WebKit assumes that external resources such as + JavaScript programs or style sheets are encoded in UTF-8 unless otherwise + specified. For example, the encoding of an external script can be specified + through the charset attribute of the HTML script tag. Alternatively, the + encoding can also be specified by the web server. + + This is a convenience function equivalent to setContent(html, "text/html", baseUrl). + + \warning This function works only for HTML, for other mime types (i.e. XHTML, SVG) + setContent() should be used instead. + + \sa load(), setContent(), QWebFrame::toHtml(), QWebFrame::setContent() +*/ +void QGraphicsWebView::setHtml(const QString& html, const QUrl& baseUrl) +{ + page()->mainFrame()->setHtml(html, baseUrl); +} + +/*! + Sets the content of the web graphicsitem to the specified content \a data. If the \a mimeType argument + is empty it is currently assumed that the content is HTML but in future versions we may introduce + auto-detection. + + External objects referenced in the content are located relative to \a baseUrl. + + The \a data is loaded immediately; external objects are loaded asynchronously. + + \sa load(), setHtml(), QWebFrame::toHtml() +*/ +void QGraphicsWebView::setContent(const QByteArray& data, const QString& mimeType, const QUrl& baseUrl) +{ + page()->mainFrame()->setContent(data, mimeType, baseUrl); +} + +/*! + Returns a pointer to the view's history of navigated web pages. + + It is equivalent to + + \snippet webkitsnippets/qtwebkit_qwebview_snippet.cpp 0 +*/ +QWebHistory* QGraphicsWebView::history() const +{ + return page()->history(); +} + +/*! + \property QGraphicsWebView::modified + \brief whether the document was modified by the user + + Parts of HTML documents can be editable for example through the + \c{contenteditable} attribute on HTML elements. + + By default, this property is false. +*/ +bool QGraphicsWebView::isModified() const +{ + if (d->page) + return d->page->isModified(); + return false; +} + +/*! + Returns a pointer to the view/page specific settings object. + + It is equivalent to + + \snippet webkitsnippets/qtwebkit_qwebview_snippet.cpp 1 + + \sa QWebSettings::globalSettings() +*/ +QWebSettings* QGraphicsWebView::settings() const +{ + return page()->settings(); +} + +/*! + Returns a pointer to a QAction that encapsulates the specified web action \a action. +*/ +QAction *QGraphicsWebView::pageAction(QWebPage::WebAction action) const +{ +#ifdef QT_NO_ACTION + Q_UNUSED(action) + return 0; +#else + return page()->action(action); +#endif +} + +/*! + Triggers the specified \a action. If it is a checkable action the specified + \a checked state is assumed. + + \sa pageAction() +*/ +void QGraphicsWebView::triggerPageAction(QWebPage::WebAction action, bool checked) +{ + page()->triggerAction(action, checked); +} + +/*! + Finds the specified string, \a subString, in the page, using the given \a options. + + If the HighlightAllOccurrences flag is passed, the function will highlight all occurrences + that exist in the page. All subsequent calls will extend the highlight, rather than + replace it, with occurrences of the new string. + + If the HighlightAllOccurrences flag is not passed, the function will select an occurrence + and all subsequent calls will replace the current occurrence with the next one. + + To clear the selection, just pass an empty string. + + Returns true if \a subString was found; otherwise returns false. + + \sa QWebPage::selectedText(), QWebPage::selectionChanged() +*/ +bool QGraphicsWebView::findText(const QString &subString, QWebPage::FindFlags options) +{ + if (d->page) + return d->page->findText(subString, options); + return false; +} + +/*! + \property QGraphicsWebView::resizesToContents + \brief whether the size of the QGraphicsWebView and its viewport changes to match the contents size + \since 4.7 + + If this property is set, the QGraphicsWebView will automatically change its + size to match the size of the main frame contents. As a result the top level frame + will never have scrollbars. It will also make CSS fixed positioning to behave like absolute positioning + with elements positioned relative to the document instead of the viewport. + + This property should be used in conjunction with the QWebPage::preferredContentsSize property. + If not explicitly set, the preferredContentsSize is automatically set to a reasonable value. + + \sa QWebPage::setPreferredContentsSize() +*/ +void QGraphicsWebView::setResizesToContents(bool enabled) +{ + if (d->resizesToContents == enabled) + return; + d->resizesToContents = enabled; + if (d->page) + d->updateResizesToContentsForPage(); +} + +bool QGraphicsWebView::resizesToContents() const +{ + return d->resizesToContents; +} + +/*! + \property QGraphicsWebView::tiledBackingStoreFrozen + \brief whether the tiled backing store updates its contents + \since 4.7 + + If the tiled backing store is enabled using QWebSettings::TiledBackingStoreEnabled attribute, this property + can be used to disable backing store updates temporarily. This can be useful for example for running + a smooth animation that changes the scale of the QGraphicsWebView. + + When the backing store is unfrozen, its contents will be automatically updated to match the current + state of the document. If the QGraphicsWebView scale was changed, the backing store is also + re-rendered using the new scale. + + If the tiled backing store is not enabled, this property does nothing. + + \sa QWebSettings::TiledBackingStoreEnabled + \sa QGraphicsObject::scale +*/ +bool QGraphicsWebView::isTiledBackingStoreFrozen() const +{ +#if ENABLE(TILED_BACKING_STORE) + WebCore::TiledBackingStore* backingStore = QWebFramePrivate::core(page()->mainFrame())->tiledBackingStore(); + if (!backingStore) + return false; + return backingStore->contentsFrozen(); +#else + return false; +#endif +} + +void QGraphicsWebView::setTiledBackingStoreFrozen(bool frozen) +{ +#if ENABLE(TILED_BACKING_STORE) + WebCore::TiledBackingStore* backingStore = QWebFramePrivate::core(page()->mainFrame())->tiledBackingStore(); + if (!backingStore) + return; + backingStore->setContentsFrozen(frozen); +#else + UNUSED_PARAM(frozen); +#endif +} + +/*! \reimp +*/ +void QGraphicsWebView::hoverMoveEvent(QGraphicsSceneHoverEvent* ev) +{ + if (d->page) { + const bool accepted = ev->isAccepted(); + QMouseEvent me = QMouseEvent(QEvent::MouseMove, + ev->pos().toPoint(), Qt::NoButton, + Qt::NoButton, Qt::NoModifier); + d->page->event(&me); + ev->setAccepted(accepted); + } + + if (!ev->isAccepted()) + QGraphicsItem::hoverMoveEvent(ev); +} + +/*! \reimp +*/ +void QGraphicsWebView::hoverLeaveEvent(QGraphicsSceneHoverEvent* ev) +{ + Q_UNUSED(ev); +} + +/*! \reimp +*/ +void QGraphicsWebView::mouseMoveEvent(QGraphicsSceneMouseEvent* ev) +{ + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } + + if (!ev->isAccepted()) + QGraphicsItem::mouseMoveEvent(ev); +} + +/*! \reimp +*/ +void QGraphicsWebView::mousePressEvent(QGraphicsSceneMouseEvent* ev) +{ + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } + + if (!ev->isAccepted()) + QGraphicsItem::mousePressEvent(ev); +} + +/*! \reimp +*/ +void QGraphicsWebView::mouseReleaseEvent(QGraphicsSceneMouseEvent* ev) +{ + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } + + if (!ev->isAccepted()) + QGraphicsItem::mouseReleaseEvent(ev); +} + +/*! \reimp +*/ +void QGraphicsWebView::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* ev) +{ + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } + + if (!ev->isAccepted()) + QGraphicsItem::mouseDoubleClickEvent(ev); +} + +/*! \reimp +*/ +void QGraphicsWebView::keyPressEvent(QKeyEvent* ev) +{ + if (d->page) + d->page->event(ev); + + if (!ev->isAccepted()) + QGraphicsItem::keyPressEvent(ev); +} + +/*! \reimp +*/ +void QGraphicsWebView::keyReleaseEvent(QKeyEvent* ev) +{ + if (d->page) + d->page->event(ev); + + if (!ev->isAccepted()) + QGraphicsItem::keyReleaseEvent(ev); +} + +/*! \reimp +*/ +void QGraphicsWebView::focusInEvent(QFocusEvent* ev) +{ + if (d->page) + d->page->event(ev); + else + QGraphicsItem::focusInEvent(ev); +} + +/*! \reimp +*/ +void QGraphicsWebView::focusOutEvent(QFocusEvent* ev) +{ + if (d->page) + d->page->event(ev); + else + QGraphicsItem::focusOutEvent(ev); +} + +/*! \reimp +*/ +bool QGraphicsWebView::focusNextPrevChild(bool next) +{ + if (d->page) + return d->page->focusNextPrevChild(next); + + return QGraphicsWidget::focusNextPrevChild(next); +} + +/*! \reimp +*/ +void QGraphicsWebView::dragEnterEvent(QGraphicsSceneDragDropEvent* ev) +{ +#ifndef QT_NO_DRAGANDDROP + if (d->page) + d->page->event(ev); +#else + Q_UNUSED(ev); +#endif +} + +/*! \reimp +*/ +void QGraphicsWebView::dragLeaveEvent(QGraphicsSceneDragDropEvent* ev) +{ +#ifndef QT_NO_DRAGANDDROP + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } + + if (!ev->isAccepted()) + QGraphicsWidget::dragLeaveEvent(ev); +#else + Q_UNUSED(ev); +#endif +} + +/*! \reimp +*/ +void QGraphicsWebView::dragMoveEvent(QGraphicsSceneDragDropEvent* ev) +{ +#ifndef QT_NO_DRAGANDDROP + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } + + if (!ev->isAccepted()) + QGraphicsWidget::dragMoveEvent(ev); +#else + Q_UNUSED(ev); +#endif +} + +/*! \reimp +*/ +void QGraphicsWebView::dropEvent(QGraphicsSceneDragDropEvent* ev) +{ +#ifndef QT_NO_DRAGANDDROP + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } + + if (!ev->isAccepted()) + QGraphicsWidget::dropEvent(ev); +#else + Q_UNUSED(ev); +#endif +} + +#ifndef QT_NO_CONTEXTMENU +/*! \reimp +*/ +void QGraphicsWebView::contextMenuEvent(QGraphicsSceneContextMenuEvent* ev) +{ + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } +} +#endif // QT_NO_CONTEXTMENU + +#ifndef QT_NO_WHEELEVENT +/*! \reimp +*/ +void QGraphicsWebView::wheelEvent(QGraphicsSceneWheelEvent* ev) +{ + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } + + if (!ev->isAccepted()) + QGraphicsItem::wheelEvent(ev); +} +#endif // QT_NO_WHEELEVENT + +/*! \reimp +*/ +void QGraphicsWebView::inputMethodEvent(QInputMethodEvent* ev) +{ + if (d->page) + d->page->event(ev); + + if (!ev->isAccepted()) + QGraphicsItem::inputMethodEvent(ev); +} + +/*! + \fn void QGraphicsWebView::statusBarMessage(const QString& text) + + This signal is emitted when the statusbar \a text is changed by the page. +*/ + +/*! + \fn void QGraphicsWebView::loadProgress(int progress) + + This signal is emitted every time an element in the web page + completes loading and the overall loading progress advances. + + This signal tracks the progress of all child frames. + + The current value is provided by \a progress and scales from 0 to 100, + which is the default range of QProgressBar. + + \sa loadStarted(), loadFinished() +*/ + +/*! + \fn void QGraphicsWebView::linkClicked(const QUrl &url) + + This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy + property is set to delegate the link handling for the specified \a url. + + \sa QWebPage::linkDelegationPolicy() +*/ + +#endif // QT_NO_GRAPHICSVIEW + +#include "moc_qgraphicswebview.cpp" diff --git a/Source/WebKit/qt/Api/qgraphicswebview.h b/Source/WebKit/qt/Api/qgraphicswebview.h new file mode 100644 index 0000000..e08e895 --- /dev/null +++ b/Source/WebKit/qt/Api/qgraphicswebview.h @@ -0,0 +1,163 @@ +/* + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QGraphicsWebView_h +#define QGraphicsWebView_h + +#include "qwebkitglobal.h" +#include "qwebpage.h" +#include <QtCore/qurl.h> +#include <QtGui/qevent.h> +#include <QtGui/qgraphicswidget.h> +#include <QtGui/qicon.h> +#include <QtGui/qpainter.h> +#include <QtNetwork/qnetworkaccessmanager.h> + +#if !defined(QT_NO_GRAPHICSVIEW) + +class QWebPage; +class QWebHistory; +class QWebSettings; + +class QGraphicsWebViewPrivate; + +class QWEBKIT_EXPORT QGraphicsWebView : public QGraphicsWidget { + Q_OBJECT + + Q_PROPERTY(QString title READ title NOTIFY titleChanged) + Q_PROPERTY(QIcon icon READ icon NOTIFY iconChanged) + Q_PROPERTY(qreal zoomFactor READ zoomFactor WRITE setZoomFactor) + + Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged) + + Q_PROPERTY(bool modified READ isModified) + Q_PROPERTY(bool resizesToContents READ resizesToContents WRITE setResizesToContents) + Q_PROPERTY(bool tiledBackingStoreFrozen READ isTiledBackingStoreFrozen WRITE setTiledBackingStoreFrozen) + +public: + explicit QGraphicsWebView(QGraphicsItem* parent = 0); + ~QGraphicsWebView(); + + QWebPage* page() const; + void setPage(QWebPage*); + + QUrl url() const; + void setUrl(const QUrl&); + + QString title() const; + QIcon icon() const; + + qreal zoomFactor() const; + void setZoomFactor(qreal); + + bool isModified() const; + + void load(const QUrl& url); + void load(const QNetworkRequest& request, QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation, const QByteArray& body = QByteArray()); + + void setHtml(const QString& html, const QUrl& baseUrl = QUrl()); + // FIXME: Consider rename to setHtml? + void setContent(const QByteArray& data, const QString& mimeType = QString(), const QUrl& baseUrl = QUrl()); + + QWebHistory* history() const; + QWebSettings* settings() const; + + QAction* pageAction(QWebPage::WebAction action) const; + void triggerPageAction(QWebPage::WebAction action, bool checked = false); + + bool findText(const QString& subString, QWebPage::FindFlags options = 0); + + bool resizesToContents() const; + void setResizesToContents(bool enabled); + + bool isTiledBackingStoreFrozen() const; + void setTiledBackingStoreFrozen(bool frozen); + + virtual void setGeometry(const QRectF& rect); + virtual void updateGeometry(); + virtual void paint(QPainter*, const QStyleOptionGraphicsItem* options, QWidget* widget = 0); + virtual QVariant itemChange(GraphicsItemChange change, const QVariant& value); + virtual bool event(QEvent*); + + virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF& constraint) const; + + virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const; + +public Q_SLOTS: + void stop(); + void back(); + void forward(); + void reload(); + +Q_SIGNALS: + void loadStarted(); + void loadFinished(bool); + + void loadProgress(int progress); + void urlChanged(const QUrl&); + void titleChanged(const QString&); + void iconChanged(); + void statusBarMessage(const QString& message); + void linkClicked(const QUrl&); + +protected: + virtual void mousePressEvent(QGraphicsSceneMouseEvent*); + virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*); + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent*); + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent*); + virtual void hoverMoveEvent(QGraphicsSceneHoverEvent*); + virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent*); +#ifndef QT_NO_WHEELEVENT + virtual void wheelEvent(QGraphicsSceneWheelEvent*); +#endif + virtual void keyPressEvent(QKeyEvent*); + virtual void keyReleaseEvent(QKeyEvent*); +#ifndef QT_NO_CONTEXTMENU + virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent*); +#endif + virtual void dragEnterEvent(QGraphicsSceneDragDropEvent*); + virtual void dragLeaveEvent(QGraphicsSceneDragDropEvent*); + virtual void dragMoveEvent(QGraphicsSceneDragDropEvent*); + virtual void dropEvent(QGraphicsSceneDragDropEvent*); + virtual void focusInEvent(QFocusEvent*); + virtual void focusOutEvent(QFocusEvent*); + virtual void inputMethodEvent(QInputMethodEvent*); + virtual bool focusNextPrevChild(bool next); + + virtual bool sceneEvent(QEvent*); + +private: + Q_PRIVATE_SLOT(d, void _q_doLoadFinished(bool success)) +#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) + Q_PRIVATE_SLOT(d, void _q_updateMicroFocus()) +#endif + Q_PRIVATE_SLOT(d, void _q_pageDestroyed()) + // we don't want to change the moc based on USE() macro, so this function is here + // but will be empty if ACCLERATED_COMPOSITING is disabled + Q_PRIVATE_SLOT(d, void syncLayers()) + Q_PRIVATE_SLOT(d, void _q_contentsSizeChanged(const QSize&)) + Q_PRIVATE_SLOT(d, void _q_scaleChanged()) + + QGraphicsWebViewPrivate* const d; + friend class QGraphicsWebViewPrivate; +}; + +#endif // QT_NO_GRAPHICSVIEW + +#endif // QGraphicsWebView_h diff --git a/Source/WebKit/qt/Api/qwebdatabase.cpp b/Source/WebKit/qt/Api/qwebdatabase.cpp new file mode 100644 index 0000000..ba039c7 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebdatabase.cpp @@ -0,0 +1,198 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qwebdatabase.h" + +#include "qwebdatabase_p.h" +#include "qwebsecurityorigin.h" +#include "qwebsecurityorigin_p.h" +#include "DatabaseDetails.h" +#include "DatabaseTracker.h" + +using namespace WebCore; + +/*! + \class QWebDatabase + \since 4.5 + \brief The QWebDatabase class provides access to HTML 5 databases created with JavaScript. + + \inmodule QtWebKit + + The upcoming HTML 5 standard includes support for SQL databases that web sites can create and + access on a local computer through JavaScript. QWebDatabase is the C++ interface to these + databases. + + Databases are grouped together in security origins. To get access to all databases defined by + a security origin, use QWebSecurityOrigin::databases(). Each database has an internal name(), + as well as a user-friendly name, provided by displayName(). These names are specified when + creating the database in the JavaScript code. + + WebKit uses SQLite to create and access the local SQL databases. The location of the database + file in the local file system is returned by fileName(). You can access the database directly + through the QtSql database module. + + For each database the web site can define an expectedSize(). The current size of the database + in bytes is returned by size(). + + For more information refer to the \l{http://dev.w3.org/html5/webdatabase/}{HTML5 Web SQL Database Draft Standard}. + + \sa QWebSecurityOrigin +*/ + +/*! + Constructs a web database from \a other. +*/ +QWebDatabase::QWebDatabase(const QWebDatabase& other) + : d(other.d) +{ +} + +/*! + Assigns the \a other web database to this. +*/ +QWebDatabase& QWebDatabase::operator=(const QWebDatabase& other) +{ + d = other.d; + return *this; +} + +/*! + Returns the name of the database. +*/ +QString QWebDatabase::name() const +{ + return d->name; +} + +/*! + Returns the name of the database in a format that is suitable for display to the user. +*/ +QString QWebDatabase::displayName() const +{ +#if ENABLE(DATABASE) + DatabaseDetails details = DatabaseTracker::tracker().detailsForNameAndOrigin(d->name, d->origin.get()); + return details.displayName(); +#else + return QString(); +#endif +} + +/*! + Returns the expected size of the database in bytes as defined by the web author. +*/ +qint64 QWebDatabase::expectedSize() const +{ +#if ENABLE(DATABASE) + DatabaseDetails details = DatabaseTracker::tracker().detailsForNameAndOrigin(d->name, d->origin.get()); + return details.expectedUsage(); +#else + return 0; +#endif +} + +/*! + Returns the current size of the database in bytes. +*/ +qint64 QWebDatabase::size() const +{ +#if ENABLE(DATABASE) + DatabaseDetails details = DatabaseTracker::tracker().detailsForNameAndOrigin(d->name, d->origin.get()); + return details.currentUsage(); +#else + return 0; +#endif +} + +/*! + \internal +*/ +QWebDatabase::QWebDatabase(QWebDatabasePrivate* priv) +{ + d = priv; +} + +/*! + Returns the file name of the web database. + + The name can be used to access the database through the QtSql database module, for example: + \code + QWebDatabase webdb = ... + QSqlDatabase sqldb = QSqlDatabase::addDatabase("QSQLITE", "myconnection"); + sqldb.setDatabaseName(webdb.fileName()); + if (sqldb.open()) { + QStringList tables = sqldb.tables(); + ... + } + \endcode + + \note Concurrent access to a database from multiple threads or processes + is not very efficient because SQLite is used as WebKit's database backend. +*/ +QString QWebDatabase::fileName() const +{ +#if ENABLE(DATABASE) + return DatabaseTracker::tracker().fullPathForDatabase(d->origin.get(), d->name, false); +#else + return QString(); +#endif +} + +/*! + Returns the databases's security origin. +*/ +QWebSecurityOrigin QWebDatabase::origin() const +{ + QWebSecurityOriginPrivate* priv = new QWebSecurityOriginPrivate(d->origin.get()); + QWebSecurityOrigin origin(priv); + return origin; +} + +/*! + Removes the database \a db from its security origin. All data stored in the + database \a db will be destroyed. +*/ +void QWebDatabase::removeDatabase(const QWebDatabase& db) +{ +#if ENABLE(DATABASE) + DatabaseTracker::tracker().deleteDatabase(db.d->origin.get(), db.d->name); +#endif +} + +/*! + \since 4.6 + + Deletes all web databases in the configured offline storage path. + + \sa QWebSettings::setOfflineStoragePath() +*/ +void QWebDatabase::removeAllDatabases() +{ +#if ENABLE(DATABASE) + DatabaseTracker::tracker().deleteAllDatabases(); +#endif +} + +/*! + Destroys the web database object. The data within this database is \b not destroyed. +*/ +QWebDatabase::~QWebDatabase() +{ +} + diff --git a/Source/WebKit/qt/Api/qwebdatabase.h b/Source/WebKit/qt/Api/qwebdatabase.h new file mode 100644 index 0000000..875b2eb --- /dev/null +++ b/Source/WebKit/qt/Api/qwebdatabase.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef _WEBDATABASE_H_ +#define _WEBDATABASE_H_ + +#include <QtCore/qstring.h> +#include <QtCore/qshareddata.h> + +#include "qwebkitglobal.h" + +namespace WebCore { + class DatabaseDetails; +} + +class QWebDatabasePrivate; +class QWebSecurityOrigin; + +class QWEBKIT_EXPORT QWebDatabase { +public: + QWebDatabase(const QWebDatabase& other); + QWebDatabase &operator=(const QWebDatabase& other); + ~QWebDatabase(); + + QString name() const; + QString displayName() const; + qint64 expectedSize() const; + qint64 size() const; + QString fileName() const; + QWebSecurityOrigin origin() const; + + static void removeDatabase(const QWebDatabase&); + static void removeAllDatabases(); + +private: + QWebDatabase(QWebDatabasePrivate* priv); + friend class QWebSecurityOrigin; + +private: + QExplicitlySharedDataPointer<QWebDatabasePrivate> d; +}; + +#endif + diff --git a/Source/WebKit/qt/Api/qwebdatabase_p.h b/Source/WebKit/qt/Api/qwebdatabase_p.h new file mode 100644 index 0000000..ec03ea5 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebdatabase_p.h @@ -0,0 +1,37 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef _WEBDATABASE_P_H_ +#define _WEBDATABASE_P_H_ + +#include <QString> +#include <QtCore/qshareddata.h> + +#include "PlatformString.h" +#include "SecurityOrigin.h" +#include "RefPtr.h" + + +class QWebDatabasePrivate : public QSharedData { +public: + WTF::String name; + WTF::RefPtr<WebCore::SecurityOrigin> origin; +}; + +#endif + diff --git a/Source/WebKit/qt/Api/qwebelement.cpp b/Source/WebKit/qt/Api/qwebelement.cpp new file mode 100644 index 0000000..60ae3a0 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebelement.cpp @@ -0,0 +1,2077 @@ +/* + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qwebelement.h" + +#include "CSSComputedStyleDeclaration.h" +#include "CSSMutableStyleDeclaration.h" +#include "CSSParser.h" +#include "CSSRule.h" +#include "CSSRuleList.h" +#include "CSSStyleRule.h" +#include "CSSStyleSelector.h" +#include "Document.h" +#include "DocumentFragment.h" +#include "FrameView.h" +#include "GraphicsContext.h" +#include "HTMLElement.h" +#if USE(JSC) +#include "JSGlobalObject.h" +#include "JSHTMLElement.h" +#include "JSObject.h" +#include "PropertyNameArray.h" +#include <parser/SourceCode.h> +#include "qt_runtime.h" +#elif USE(V8) +#include "V8DOMWindow.h" +#include "V8Binding.h" +#include "NotImplemented.h" +#endif +#include "NodeList.h" +#include "RenderImage.h" +#include "StaticNodeList.h" +#include "qwebframe.h" +#include "qwebframe_p.h" +#include "runtime_root.h" +#include <wtf/Vector.h> +#include <wtf/text/CString.h> + +#include <QPainter> + +#if USE(V8) +using namespace V8::Bindings; +#endif + +using namespace WebCore; + +class QWebElementPrivate { +public: +}; + +/*! + \class QWebElement + \since 4.6 + \brief The QWebElement class provides convenient access to DOM elements in + a QWebFrame. + \inmodule QtWebKit + + A QWebElement object allows easy access to the document model, represented + by a tree-like structure of DOM elements. The root of the tree is called + the document element and can be accessed using + QWebFrame::documentElement(). + + Specific elements can be accessed using findAll() and findFirst(). These + elements are identified using CSS selectors. The code snippet below + demonstrates the use of findAll(). + + \snippet webkitsnippets/webelement/main.cpp FindAll + + The first list contains all \c span elements in the document. The second + list contains \c span elements that are children of \c p, classified with + \c intro. + + Using findFirst() is more efficient than calling findAll(), and extracting + the first element only in the list returned. + + Alternatively you can traverse the document manually using firstChild() and + nextSibling(): + + \snippet webkitsnippets/webelement/main.cpp Traversing with QWebElement + + Individual elements can be inspected or changed using methods such as attribute() + or setAttribute(). For examle, to capture the user's input in a text field for later + use (auto-completion), a browser could do something like this: + + \snippet webkitsnippets/webelement/main.cpp autocomplete1 + + When the same page is later revisited, the browser can fill in the text field automatically + by modifying the value attribute of the input element: + + \snippet webkitsnippets/webelement/main.cpp autocomplete2 + + Another use case is to emulate a click event on an element. The following + code snippet demonstrates how to call the JavaScript DOM method click() of + a submit button: + + \snippet webkitsnippets/webelement/main.cpp Calling a DOM element method + + The underlying content of QWebElement is explicitly shared. Creating a copy + of a QWebElement does not create a copy of the content. Instead, both + instances point to the same element. + + The contents of child elements can be converted to plain text with + toPlainText(); to XHTML using toInnerXml(). To include the element's tag in + the output, use toOuterXml(). + + It is possible to replace the contents of child elements using + setPlainText() and setInnerXml(). To replace the element itself and its + contents, use setOuterXml(). + + \section1 Examples + + The \l{DOM Traversal Example} shows one way to traverse documents in a running + example. + + The \l{Simple Selector Example} can be used to experiment with the searching + features of this class and provides sample code you can start working with. +*/ + +/*! + Constructs a null web element. +*/ +QWebElement::QWebElement() + : d(0) + , m_element(0) +{ +} + +/*! + \internal +*/ +QWebElement::QWebElement(WebCore::Element* domElement) + : d(0) + , m_element(domElement) +{ + if (m_element) + m_element->ref(); +} + +/*! + \internal +*/ +QWebElement::QWebElement(WebCore::Node* node) + : d(0) + , m_element(0) +{ + if (node && node->isHTMLElement()) { + m_element = static_cast<HTMLElement*>(node); + m_element->ref(); + } +} + +/*! + Constructs a copy of \a other. +*/ +QWebElement::QWebElement(const QWebElement &other) + : d(0) + , m_element(other.m_element) +{ + if (m_element) + m_element->ref(); +} + +/*! + Assigns \a other to this element and returns a reference to this element. +*/ +QWebElement &QWebElement::operator=(const QWebElement &other) +{ + // ### handle "d" assignment + if (this != &other) { + Element *otherElement = other.m_element; + if (otherElement) + otherElement->ref(); + if (m_element) + m_element->deref(); + m_element = otherElement; + } + return *this; +} + +/*! + Destroys the element. However, the underlying DOM element is not destroyed. +*/ +QWebElement::~QWebElement() +{ + delete d; + if (m_element) + m_element->deref(); +} + +bool QWebElement::operator==(const QWebElement& o) const +{ + return m_element == o.m_element; +} + +bool QWebElement::operator!=(const QWebElement& o) const +{ + return m_element != o.m_element; +} + +/*! + Returns true if the element is a null element; otherwise returns false. +*/ +bool QWebElement::isNull() const +{ + return !m_element; +} + +/*! + Returns a new list of child elements matching the given CSS selector + \a selectorQuery. If there are no matching elements, an empty list is + returned. + + \l{Standard CSS2 selector} syntax is used for the query. + + \note This search is performed recursively. + + \sa findFirst() +*/ +QWebElementCollection QWebElement::findAll(const QString &selectorQuery) const +{ + return QWebElementCollection(*this, selectorQuery); +} + +/*! + Returns the first child element that matches the given CSS selector + \a selectorQuery. + + \l{Standard CSS2 selector} syntax is used for the query. + + \note This search is performed recursively. + + \sa findAll() +*/ +QWebElement QWebElement::findFirst(const QString &selectorQuery) const +{ + if (!m_element) + return QWebElement(); + ExceptionCode exception = 0; // ### + return QWebElement(m_element->querySelector(selectorQuery, exception).get()); +} + +/*! + Replaces the existing content of this element with \a text. + + This is equivalent to setting the HTML innerText property. + + \sa toPlainText() +*/ +void QWebElement::setPlainText(const QString &text) +{ + if (!m_element || !m_element->isHTMLElement()) + return; + ExceptionCode exception = 0; + static_cast<HTMLElement*>(m_element)->setInnerText(text, exception); +} + +/*! + Returns the text between the start and the end tag of this + element. + + This is equivalent to reading the HTML innerText property. + + \sa setPlainText() +*/ +QString QWebElement::toPlainText() const +{ + if (!m_element || !m_element->isHTMLElement()) + return QString(); + return static_cast<HTMLElement*>(m_element)->innerText(); +} + +/*! + Replaces the contents of this element as well as its own tag with + \a markup. The string may contain HTML or XML tags, which is parsed and + formatted before insertion into the document. + + \note This is currently only implemented for (X)HTML elements. + + \sa toOuterXml(), toInnerXml(), setInnerXml() +*/ +void QWebElement::setOuterXml(const QString &markup) +{ + if (!m_element || !m_element->isHTMLElement()) + return; + + ExceptionCode exception = 0; + + static_cast<HTMLElement*>(m_element)->setOuterHTML(markup, exception); +} + +/*! + Returns this element converted to XML, including the start and the end + tags as well as its attributes. + + \note This is currently implemented for (X)HTML elements only. + + \note The format of the markup returned will obey the namespace of the + document containing the element. This means the return value will obey XML + formatting rules, such as self-closing tags, only if the document is + 'text/xhtml+xml'. + + \sa setOuterXml(), setInnerXml(), toInnerXml() +*/ +QString QWebElement::toOuterXml() const +{ + if (!m_element || !m_element->isHTMLElement()) + return QString(); + + return static_cast<HTMLElement*>(m_element)->outerHTML(); +} + +/*! + Replaces the contents of this element with \a markup. The string may + contain HTML or XML tags, which is parsed and formatted before insertion + into the document. + + \note This is currently implemented for (X)HTML elements only. + + \sa toInnerXml(), toOuterXml(), setOuterXml() +*/ +void QWebElement::setInnerXml(const QString &markup) +{ + if (!m_element || !m_element->isHTMLElement()) + return; + + ExceptionCode exception = 0; + + static_cast<HTMLElement*>(m_element)->setInnerHTML(markup, exception); +} + +/*! + Returns the XML content between the element's start and end tags. + + \note This is currently implemented for (X)HTML elements only. + + \note The format of the markup returned will obey the namespace of the + document containing the element. This means the return value will obey XML + formatting rules, such as self-closing tags, only if the document is + 'text/xhtml+xml'. + + \sa setInnerXml(), setOuterXml(), toOuterXml() +*/ +QString QWebElement::toInnerXml() const +{ + if (!m_element || !m_element->isHTMLElement()) + return QString(); + + return static_cast<HTMLElement*>(m_element)->innerHTML(); +} + +/*! + Adds an attribute with the given \a name and \a value. If an attribute with + the same name exists, its value is replaced by \a value. + + \sa attribute(), attributeNS(), setAttributeNS() +*/ +void QWebElement::setAttribute(const QString &name, const QString &value) +{ + if (!m_element) + return; + ExceptionCode exception = 0; + m_element->setAttribute(name, value, exception); +} + +/*! + Adds an attribute with the given \a name in \a namespaceUri with \a value. + If an attribute with the same name exists, its value is replaced by + \a value. + + \sa attributeNS(), attribute(), setAttribute() +*/ +void QWebElement::setAttributeNS(const QString &namespaceUri, const QString &name, const QString &value) +{ + if (!m_element) + return; + WebCore::ExceptionCode exception = 0; + m_element->setAttributeNS(namespaceUri, name, value, exception); +} + +/*! + Returns the attribute with the given \a name. If the attribute does not + exist, \a defaultValue is returned. + + \sa setAttribute(), setAttributeNS(), attributeNS() +*/ +QString QWebElement::attribute(const QString &name, const QString &defaultValue) const +{ + if (!m_element) + return QString(); + if (m_element->hasAttribute(name)) + return m_element->getAttribute(name); + else + return defaultValue; +} + +/*! + Returns the attribute with the given \a name in \a namespaceUri. If the + attribute does not exist, \a defaultValue is returned. + + \sa setAttributeNS(), setAttribute(), attribute() +*/ +QString QWebElement::attributeNS(const QString &namespaceUri, const QString &name, const QString &defaultValue) const +{ + if (!m_element) + return QString(); + if (m_element->hasAttributeNS(namespaceUri, name)) + return m_element->getAttributeNS(namespaceUri, name); + else + return defaultValue; +} + +/*! + Returns true if this element has an attribute with the given \a name; + otherwise returns false. + + \sa attribute(), setAttribute() +*/ +bool QWebElement::hasAttribute(const QString &name) const +{ + if (!m_element) + return false; + return m_element->hasAttribute(name); +} + +/*! + Returns true if this element has an attribute with the given \a name, in + \a namespaceUri; otherwise returns false. + + \sa attributeNS(), setAttributeNS() +*/ +bool QWebElement::hasAttributeNS(const QString &namespaceUri, const QString &name) const +{ + if (!m_element) + return false; + return m_element->hasAttributeNS(namespaceUri, name); +} + +/*! + Removes the attribute with the given \a name from this element. + + \sa attribute(), setAttribute(), hasAttribute() +*/ +void QWebElement::removeAttribute(const QString &name) +{ + if (!m_element) + return; + ExceptionCode exception = 0; + m_element->removeAttribute(name, exception); +} + +/*! + Removes the attribute with the given \a name, in \a namespaceUri, from this + element. + + \sa attributeNS(), setAttributeNS(), hasAttributeNS() +*/ +void QWebElement::removeAttributeNS(const QString &namespaceUri, const QString &name) +{ + if (!m_element) + return; + WebCore::ExceptionCode exception = 0; + m_element->removeAttributeNS(namespaceUri, name, exception); +} + +/*! + Returns true if the element has any attributes defined; otherwise returns + false; + + \sa attribute(), setAttribute() +*/ +bool QWebElement::hasAttributes() const +{ + if (!m_element) + return false; + return m_element->hasAttributes(); +} + +/*! + Return the list of attributes for the namespace given as \a namespaceUri. + + \sa attribute(), setAttribute() +*/ +QStringList QWebElement::attributeNames(const QString& namespaceUri) const +{ + if (!m_element) + return QStringList(); + + QStringList attributeNameList; + const NamedNodeMap* const attrs = m_element->attributes(/* read only = */ true); + if (attrs) { + const String namespaceUriString(namespaceUri); // convert QString -> String once + const unsigned attrsCount = attrs->length(); + for (unsigned i = 0; i < attrsCount; ++i) { + const Attribute* const attribute = attrs->attributeItem(i); + if (namespaceUriString == attribute->namespaceURI()) + attributeNameList.append(attribute->localName()); + } + } + return attributeNameList; +} + +/*! + Returns true if the element has keyboard input focus; otherwise, returns false + + \sa setFocus() +*/ +bool QWebElement::hasFocus() const +{ + if (!m_element) + return false; + if (m_element->document()) + return m_element == m_element->document()->focusedNode(); + return false; +} + +/*! + Gives keyboard input focus to this element + + \sa hasFocus() +*/ +void QWebElement::setFocus() +{ + if (!m_element) + return; + if (m_element->document() && m_element->isFocusable()) + m_element->document()->setFocusedNode(m_element); +} + +/*! + Returns the geometry of this element, relative to its containing frame. + + \sa tagName() +*/ +QRect QWebElement::geometry() const +{ + if (!m_element) + return QRect(); + return m_element->getRect(); +} + +/*! + Returns the tag name of this element. + + \sa geometry() +*/ +QString QWebElement::tagName() const +{ + if (!m_element) + return QString(); + return m_element->tagName(); +} + +/*! + Returns the namespace prefix of the element. If the element has no\ + namespace prefix, empty string is returned. +*/ +QString QWebElement::prefix() const +{ + if (!m_element) + return QString(); + return m_element->prefix(); +} + +/*! + Returns the local name of the element. If the element does not use + namespaces, an empty string is returned. +*/ +QString QWebElement::localName() const +{ + if (!m_element) + return QString(); + return m_element->localName(); +} + +/*! + Returns the namespace URI of this element. If the element has no namespace + URI, an empty string is returned. +*/ +QString QWebElement::namespaceUri() const +{ + if (!m_element) + return QString(); + return m_element->namespaceURI(); +} + +/*! + Returns the parent element of this elemen. If this element is the root + document element, a null element is returned. +*/ +QWebElement QWebElement::parent() const +{ + if (m_element) + return QWebElement(m_element->parentElement()); + return QWebElement(); +} + +/*! + Returns the element's first child. + + \sa lastChild(), previousSibling(), nextSibling() +*/ +QWebElement QWebElement::firstChild() const +{ + if (!m_element) + return QWebElement(); + for (Node* child = m_element->firstChild(); child; child = child->nextSibling()) { + if (!child->isElementNode()) + continue; + Element* e = static_cast<Element*>(child); + return QWebElement(e); + } + return QWebElement(); +} + +/*! + Returns the element's last child. + + \sa firstChild(), previousSibling(), nextSibling() +*/ +QWebElement QWebElement::lastChild() const +{ + if (!m_element) + return QWebElement(); + for (Node* child = m_element->lastChild(); child; child = child->previousSibling()) { + if (!child->isElementNode()) + continue; + Element* e = static_cast<Element*>(child); + return QWebElement(e); + } + return QWebElement(); +} + +/*! + Returns the element's next sibling. + + \sa firstChild(), previousSibling(), lastChild() +*/ +QWebElement QWebElement::nextSibling() const +{ + if (!m_element) + return QWebElement(); + for (Node* sib = m_element->nextSibling(); sib; sib = sib->nextSibling()) { + if (!sib->isElementNode()) + continue; + Element* e = static_cast<Element*>(sib); + return QWebElement(e); + } + return QWebElement(); +} + +/*! + Returns the element's previous sibling. + + \sa firstChild(), nextSibling(), lastChild() +*/ +QWebElement QWebElement::previousSibling() const +{ + if (!m_element) + return QWebElement(); + for (Node* sib = m_element->previousSibling(); sib; sib = sib->previousSibling()) { + if (!sib->isElementNode()) + continue; + Element* e = static_cast<Element*>(sib); + return QWebElement(e); + } + return QWebElement(); +} + +/*! + Returns the document which this element belongs to. +*/ +QWebElement QWebElement::document() const +{ + if (!m_element) + return QWebElement(); + Document* document = m_element->document(); + if (!document) + return QWebElement(); + return QWebElement(document->documentElement()); +} + +/*! + Returns the web frame which this element is a part of. If the element is a + null element, null is returned. +*/ +QWebFrame *QWebElement::webFrame() const +{ + if (!m_element) + return 0; + + Document* document = m_element->document(); + if (!document) + return 0; + + Frame* frame = document->frame(); + if (!frame) + return 0; + return QWebFramePrivate::kit(frame); +} + +#if USE(JSC) +static bool setupScriptContext(WebCore::Element* element, JSC::JSValue& thisValue, ScriptState*& state, ScriptController*& scriptController) +{ + if (!element) + return false; + + Document* document = element->document(); + if (!document) + return false; + + Frame* frame = document->frame(); + if (!frame) + return false; + + scriptController = frame->script(); + if (!scriptController) + return false; + + state = scriptController->globalObject(mainThreadNormalWorld())->globalExec(); + if (!state) + return false; + + thisValue = toJS(state, element); + if (!thisValue) + return false; + + return true; +} +#elif USE(V8) +static bool setupScriptContext(WebCore::Element* element, v8::Handle<v8::Value>& thisValue, ScriptState*& state, ScriptController*& scriptController) +{ + if (!element) + return false; + + Document* document = element->document(); + if (!document) + return false; + + Frame* frame = document->frame(); + if (!frame) + return false; + + state = mainWorldScriptState(frame); + // Get V8 wrapper for DOM element + thisValue = toV8(frame->domWindow()); + return true; +} +#endif + + +/*! + Executes \a scriptSource with this element as \c this object. +*/ +QVariant QWebElement::evaluateJavaScript(const QString& scriptSource) +{ + if (scriptSource.isEmpty()) + return QVariant(); + + ScriptState* state = 0; +#if USE(JSC) + JSC::JSValue thisValue; +#elif USE(V8) + v8::Handle<v8::Value> thisValue; +#endif + ScriptController* scriptController = 0; + + if (!setupScriptContext(m_element, thisValue, state, scriptController)) + return QVariant(); +#if USE(JSC) + JSC::ScopeChain& scopeChain = state->dynamicGlobalObject()->globalScopeChain(); + JSC::UString script(reinterpret_cast_ptr<const UChar*>(scriptSource.data()), scriptSource.length()); + JSC::Completion completion = JSC::evaluate(state, scopeChain, JSC::makeSource(script), thisValue); + if ((completion.complType() != JSC::ReturnValue) && (completion.complType() != JSC::Normal)) + return QVariant(); + + JSC::JSValue result = completion.value(); + if (!result) + return QVariant(); + + int distance = 0; + return JSC::Bindings::convertValueToQVariant(state, result, QMetaType::Void, &distance); +#elif USE(V8) + notImplemented(); + return QVariant(); +#endif +} + +/*! + \enum QWebElement::StyleResolveStrategy + + This enum describes how QWebElement's styleProperty resolves the given + property name. + + \value InlineStyle Return the property value as it is defined in + the element, without respecting style inheritance and other CSS + rules. + \value CascadedStyle The property's value is determined using the + inheritance and importance rules defined in the document's + stylesheet. + \value ComputedStyle The property's value is the absolute value + of the style property resolved from the environment. +*/ + +/*! + Returns the value of the style with the given \a name using the specified + \a strategy. If a style with \a name does not exist, an empty string is + returned. + + In CSS, the cascading part depends on which CSS rule has priority and is + thus applied. Generally, the last defined rule has priority. Thus, an + inline style rule has priority over an embedded block style rule, which + in return has priority over an external style rule. + + If the "!important" declaration is set on one of those, the declaration + receives highest priority, unless other declarations also use the + "!important" declaration. Then, the last "!important" declaration takes + predecence. + + \sa setStyleProperty() +*/ + +QString QWebElement::styleProperty(const QString &name, StyleResolveStrategy strategy) const +{ + if (!m_element || !m_element->isStyledElement()) + return QString(); + + int propID = cssPropertyID(name); + + if (!propID) + return QString(); + + CSSStyleDeclaration* style = static_cast<StyledElement*>(m_element)->style(); + + if (strategy == InlineStyle) + return style->getPropertyValue(propID); + + if (strategy == CascadedStyle) { + if (style->getPropertyPriority(propID)) + return style->getPropertyValue(propID); + + // We are going to resolve the style property by walking through the + // list of non-inline matched CSS rules for the element, looking for + // the highest priority definition. + + // Get an array of matched CSS rules for the given element sorted + // by importance and inheritance order. This include external CSS + // declarations, as well as embedded and inline style declarations. + + Document* doc = m_element->document(); + if (RefPtr<CSSRuleList> rules = doc->styleSelector()->styleRulesForElement(m_element, /*authorOnly*/ true)) { + for (int i = rules->length(); i > 0; --i) { + CSSStyleRule* rule = static_cast<CSSStyleRule*>(rules->item(i - 1)); + + if (rule->style()->getPropertyPriority(propID)) + return rule->style()->getPropertyValue(propID); + + if (style->getPropertyValue(propID).isEmpty()) + style = rule->style(); + } + } + + return style->getPropertyValue(propID); + } + + if (strategy == ComputedStyle) { + if (!m_element || !m_element->isStyledElement()) + return QString(); + + int propID = cssPropertyID(name); + + RefPtr<CSSComputedStyleDeclaration> style = computedStyle(m_element, true); + if (!propID || !style) + return QString(); + + return style->getPropertyValue(propID); + } + + return QString(); +} + +/*! + Sets the value of the inline style with the given \a name to \a value. + + Setting a value, does not necessarily mean that it will become the applied + value, due to the fact that the style property's value might have been set + earlier with a higher priority in external or embedded style declarations. + + In order to ensure that the value will be applied, you may have to append + "!important" to the value. +*/ +void QWebElement::setStyleProperty(const QString &name, const QString &value) +{ + if (!m_element || !m_element->isStyledElement()) + return; + + int propID = cssPropertyID(name); + CSSStyleDeclaration* style = static_cast<StyledElement*>(m_element)->style(); + if (!propID || !style) + return; + + ExceptionCode exception = 0; + style->setProperty(name, value, exception); +} + +/*! + Returns the list of classes of this element. +*/ +QStringList QWebElement::classes() const +{ + if (!hasAttribute(QLatin1String("class"))) + return QStringList(); + + QStringList classes = attribute(QLatin1String("class")).simplified().split(QLatin1Char(' '), QString::SkipEmptyParts); + classes.removeDuplicates(); + return classes; +} + +/*! + Returns true if this element has a class with the given \a name; otherwise + returns false. +*/ +bool QWebElement::hasClass(const QString &name) const +{ + QStringList list = classes(); + return list.contains(name); +} + +/*! + Adds the specified class with the given \a name to the element. +*/ +void QWebElement::addClass(const QString &name) +{ + QStringList list = classes(); + if (!list.contains(name)) { + list.append(name); + QString value = list.join(QLatin1String(" ")); + setAttribute(QLatin1String("class"), value); + } +} + +/*! + Removes the specified class with the given \a name from the element. +*/ +void QWebElement::removeClass(const QString &name) +{ + QStringList list = classes(); + if (list.contains(name)) { + list.removeAll(name); + QString value = list.join(QLatin1String(" ")); + setAttribute(QLatin1String("class"), value); + } +} + +/*! + Adds the specified class with the given \a name if it is not present. If + the class is already present, it will be removed. +*/ +void QWebElement::toggleClass(const QString &name) +{ + QStringList list = classes(); + if (list.contains(name)) + list.removeAll(name); + else + list.append(name); + + QString value = list.join(QLatin1String(" ")); + setAttribute(QLatin1String("class"), value); +} + +/*! + Appends the given \a element as the element's last child. + + If \a element is the child of another element, it is re-parented to this + element. If \a element is a child of this element, then its position in + the list of children is changed. + + Calling this function on a null element does nothing. + + \sa prependInside(), prependOutside(), appendOutside() +*/ +void QWebElement::appendInside(const QWebElement &element) +{ + if (!m_element || element.isNull()) + return; + + ExceptionCode exception = 0; + m_element->appendChild(element.m_element, exception); +} + +/*! + Appends the result of parsing \a markup as the element's last child. + + Calling this function on a null element does nothing. + + \sa prependInside(), prependOutside(), appendOutside() +*/ +void QWebElement::appendInside(const QString &markup) +{ + if (!m_element) + return; + + if (!m_element->isHTMLElement()) + return; + + HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element); + RefPtr<DocumentFragment> fragment = htmlElement->Element::deprecatedCreateContextualFragment(markup); + + ExceptionCode exception = 0; + m_element->appendChild(fragment, exception); +} + +/*! + Prepends \a element as the element's first child. + + If \a element is the child of another element, it is re-parented to this + element. If \a element is a child of this element, then its position in + the list of children is changed. + + Calling this function on a null element does nothing. + + \sa appendInside(), prependOutside(), appendOutside() +*/ +void QWebElement::prependInside(const QWebElement &element) +{ + if (!m_element || element.isNull()) + return; + + ExceptionCode exception = 0; + + if (m_element->hasChildNodes()) + m_element->insertBefore(element.m_element, m_element->firstChild(), exception); + else + m_element->appendChild(element.m_element, exception); +} + +/*! + Prepends the result of parsing \a markup as the element's first child. + + Calling this function on a null element does nothing. + + \sa appendInside(), prependOutside(), appendOutside() +*/ +void QWebElement::prependInside(const QString &markup) +{ + if (!m_element) + return; + + if (!m_element->isHTMLElement()) + return; + + HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element); + RefPtr<DocumentFragment> fragment = htmlElement->deprecatedCreateContextualFragment(markup); + + ExceptionCode exception = 0; + + if (m_element->hasChildNodes()) + m_element->insertBefore(fragment, m_element->firstChild(), exception); + else + m_element->appendChild(fragment, exception); +} + + +/*! + Inserts the given \a element before this element. + + If \a element is the child of another element, it is re-parented to the + parent of this element. + + Calling this function on a null element does nothing. + + \sa appendInside(), prependInside(), appendOutside() +*/ +void QWebElement::prependOutside(const QWebElement &element) +{ + if (!m_element || element.isNull()) + return; + + if (!m_element->parentNode()) + return; + + ExceptionCode exception = 0; + m_element->parentNode()->insertBefore(element.m_element, m_element, exception); +} + +/*! + Inserts the result of parsing \a markup before this element. + + Calling this function on a null element does nothing. + + \sa appendInside(), prependInside(), appendOutside() +*/ +void QWebElement::prependOutside(const QString &markup) +{ + if (!m_element) + return; + + if (!m_element->parentNode()) + return; + + if (!m_element->isHTMLElement()) + return; + + HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element); + RefPtr<DocumentFragment> fragment = htmlElement->deprecatedCreateContextualFragment(markup); + + ExceptionCode exception = 0; + m_element->parentNode()->insertBefore(fragment, m_element, exception); +} + +/*! + Inserts the given \a element after this element. + + If \a element is the child of another element, it is re-parented to the + parent of this element. + + Calling this function on a null element does nothing. + + \sa appendInside(), prependInside(), prependOutside() +*/ +void QWebElement::appendOutside(const QWebElement &element) +{ + if (!m_element || element.isNull()) + return; + + if (!m_element->parentNode()) + return; + + ExceptionCode exception = 0; + if (!m_element->nextSibling()) + m_element->parentNode()->appendChild(element.m_element, exception); + else + m_element->parentNode()->insertBefore(element.m_element, m_element->nextSibling(), exception); +} + +/*! + Inserts the result of parsing \a markup after this element. + + Calling this function on a null element does nothing. + + \sa appendInside(), prependInside(), prependOutside() +*/ +void QWebElement::appendOutside(const QString &markup) +{ + if (!m_element) + return; + + if (!m_element->parentNode()) + return; + + if (!m_element->isHTMLElement()) + return; + + HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element); + RefPtr<DocumentFragment> fragment = htmlElement->deprecatedCreateContextualFragment(markup); + + ExceptionCode exception = 0; + if (!m_element->nextSibling()) + m_element->parentNode()->appendChild(fragment, exception); + else + m_element->parentNode()->insertBefore(fragment, m_element->nextSibling(), exception); +} + +/*! + Returns a clone of this element. + + The clone may be inserted at any point in the document. + + \sa appendInside(), prependInside(), prependOutside(), appendOutside() +*/ +QWebElement QWebElement::clone() const +{ + if (!m_element) + return QWebElement(); + + return QWebElement(m_element->cloneElementWithChildren().get()); +} + +/*! + Removes this element from the document and returns a reference to it. + + The element is still valid after removal, and can be inserted into other + parts of the document. + + \sa removeAllChildren(), removeFromDocument() +*/ +QWebElement &QWebElement::takeFromDocument() +{ + if (!m_element) + return *this; + + ExceptionCode exception = 0; + m_element->remove(exception); + + return *this; +} + +/*! + Removes this element from the document and makes it a null element. + + \sa removeAllChildren(), takeFromDocument() +*/ +void QWebElement::removeFromDocument() +{ + if (!m_element) + return; + + ExceptionCode exception = 0; + m_element->remove(exception); + m_element->deref(); + m_element = 0; +} + +/*! + Removes all children from this element. + + \sa removeFromDocument(), takeFromDocument() +*/ +void QWebElement::removeAllChildren() +{ + if (!m_element) + return; + + m_element->removeAllChildren(); +} + +// FIXME: This code, and all callers are wrong, and have no place in a +// WebKit implementation. These should be replaced with WebCore implementations. +static RefPtr<Node> findInsertionPoint(PassRefPtr<Node> root) +{ + RefPtr<Node> node = root; + + // Go as far down the tree as possible. + while (node->hasChildNodes() && node->firstChild()->isElementNode()) + node = node->firstChild(); + + // TODO: Implement SVG support + if (node->isHTMLElement()) { + HTMLElement* element = static_cast<HTMLElement*>(node.get()); + + // The insert point could be a non-enclosable tag and it can thus + // never have children, so go one up. Get the parent element, and not + // note as a root note will always exist. + if (element->ieForbidsInsertHTML()) + node = node->parentElement(); + } + + return node; +} + +/*! + Encloses the contents of this element with \a element. This element becomes + the child of the deepest descendant within \a element. + + ### illustration + + \sa encloseWith() +*/ +void QWebElement::encloseContentsWith(const QWebElement &element) +{ + if (!m_element || element.isNull()) + return; + + RefPtr<Node> insertionPoint = findInsertionPoint(element.m_element); + + if (!insertionPoint) + return; + + ExceptionCode exception = 0; + + // reparent children + for (RefPtr<Node> child = m_element->firstChild(); child;) { + RefPtr<Node> next = child->nextSibling(); + insertionPoint->appendChild(child, exception); + child = next; + } + + if (m_element->hasChildNodes()) + m_element->insertBefore(element.m_element, m_element->firstChild(), exception); + else + m_element->appendChild(element.m_element, exception); +} + +/*! + Encloses the contents of this element with the result of parsing \a markup. + This element becomes the child of the deepest descendant within \a markup. + + \sa encloseWith() +*/ +void QWebElement::encloseContentsWith(const QString &markup) +{ + if (!m_element) + return; + + if (!m_element->parentNode()) + return; + + if (!m_element->isHTMLElement()) + return; + + HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element); + RefPtr<DocumentFragment> fragment = htmlElement->deprecatedCreateContextualFragment(markup); + + if (!fragment || !fragment->firstChild()) + return; + + RefPtr<Node> insertionPoint = findInsertionPoint(fragment->firstChild()); + + if (!insertionPoint) + return; + + ExceptionCode exception = 0; + + // reparent children + for (RefPtr<Node> child = m_element->firstChild(); child;) { + RefPtr<Node> next = child->nextSibling(); + insertionPoint->appendChild(child, exception); + child = next; + } + + if (m_element->hasChildNodes()) + m_element->insertBefore(fragment, m_element->firstChild(), exception); + else + m_element->appendChild(fragment, exception); +} + +/*! + Encloses this element with \a element. This element becomes the child of + the deepest descendant within \a element. + + \sa replace() +*/ +void QWebElement::encloseWith(const QWebElement &element) +{ + if (!m_element || element.isNull()) + return; + + RefPtr<Node> insertionPoint = findInsertionPoint(element.m_element); + + if (!insertionPoint) + return; + + // Keep reference to these two nodes before pulling out this element and + // wrapping it in the fragment. The reason for doing it in this order is + // that once the fragment has been added to the document it is empty, so + // we no longer have access to the nodes it contained. + Node* parent = m_element->parentNode(); + Node* siblingNode = m_element->nextSibling(); + + ExceptionCode exception = 0; + insertionPoint->appendChild(m_element, exception); + + if (!siblingNode) + parent->appendChild(element.m_element, exception); + else + parent->insertBefore(element.m_element, siblingNode, exception); +} + +/*! + Encloses this element with the result of parsing \a markup. This element + becomes the child of the deepest descendant within \a markup. + + \sa replace() +*/ +void QWebElement::encloseWith(const QString &markup) +{ + if (!m_element) + return; + + if (!m_element->parentNode()) + return; + + if (!m_element->isHTMLElement()) + return; + + HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element); + RefPtr<DocumentFragment> fragment = htmlElement->deprecatedCreateContextualFragment(markup); + + if (!fragment || !fragment->firstChild()) + return; + + RefPtr<Node> insertionPoint = findInsertionPoint(fragment->firstChild()); + + if (!insertionPoint) + return; + + // Keep reference to these two nodes before pulling out this element and + // wrapping it in the fragment. The reason for doing it in this order is + // that once the fragment has been added to the document it is empty, so + // we no longer have access to the nodes it contained. + Node* parent = m_element->parentNode(); + Node* siblingNode = m_element->nextSibling(); + + ExceptionCode exception = 0; + insertionPoint->appendChild(m_element, exception); + + if (!siblingNode) + parent->appendChild(fragment, exception); + else + parent->insertBefore(fragment, siblingNode, exception); +} + +/*! + Replaces this element with \a element. + + This method will not replace the <html>, <head> or <body> elements. + + \sa encloseWith() +*/ +void QWebElement::replace(const QWebElement &element) +{ + if (!m_element || element.isNull()) + return; + + appendOutside(element); + takeFromDocument(); +} + +/*! + Replaces this element with the result of parsing \a markup. + + This method will not replace the <html>, <head> or <body> elements. + + \sa encloseWith() +*/ +void QWebElement::replace(const QString &markup) +{ + if (!m_element) + return; + + appendOutside(markup); + takeFromDocument(); +} + +/*! + \internal + Walk \a node's parents until a valid QWebElement is found. + For example, a WebCore::Text node is not a valid Html QWebElement, but its + enclosing p tag is. +*/ +QWebElement QWebElement::enclosingElement(WebCore::Node* node) +{ + QWebElement element(node); + + while (element.isNull() && node) { + node = node->parentNode(); + element = QWebElement(node); + } + return element; +} + +/*! + \fn inline bool QWebElement::operator==(const QWebElement& o) const; + + Returns true if this element points to the same underlying DOM object as + \a o; otherwise returns false. +*/ + +/*! + \fn inline bool QWebElement::operator!=(const QWebElement& o) const; + + Returns true if this element points to a different underlying DOM object + than \a o; otherwise returns false. +*/ + + +/*! + Render the element into \a painter . +*/ +void QWebElement::render(QPainter* painter) +{ + WebCore::Element* e = m_element; + Document* doc = e ? e->document() : 0; + if (!doc) + return; + + Frame* frame = doc->frame(); + if (!frame || !frame->view() || !frame->contentRenderer()) + return; + + FrameView* view = frame->view(); + + view->updateLayoutAndStyleIfNeededRecursive(); + + IntRect rect = e->getRect(); + + if (rect.size().isEmpty()) + return; + + GraphicsContext context(painter); + + context.save(); + context.translate(-rect.x(), -rect.y()); + view->setNodeToDraw(e); + view->paintContents(&context, rect); + view->setNodeToDraw(0); + context.restore(); +} + +class QWebElementCollectionPrivate : public QSharedData +{ +public: + static QWebElementCollectionPrivate* create(const PassRefPtr<Node> &context, const QString &query); + + RefPtr<NodeList> m_result; + +private: + inline QWebElementCollectionPrivate() {} +}; + +QWebElementCollectionPrivate* QWebElementCollectionPrivate::create(const PassRefPtr<Node> &context, const QString &query) +{ + if (!context) + return 0; + + // Let WebKit do the hard work hehehe + ExceptionCode exception = 0; // ### + RefPtr<NodeList> nodes = context->querySelectorAll(query, exception); + if (!nodes) + return 0; + + QWebElementCollectionPrivate* priv = new QWebElementCollectionPrivate; + priv->m_result = nodes; + return priv; +} + +/*! + \class QWebElementCollection + \since 4.6 + \brief The QWebElementCollection class represents a collection of web elements. + \preliminary + + Elements in a document can be selected using QWebElement::findAll() or using the + QWebElement constructor. The collection is composed by choosing all elements in the + document that match a specified CSS selector expression. + + The number of selected elements is provided through the count() property. Individual + elements can be retrieved by index using at(). + + It is also possible to iterate through all elements in the collection using Qt's foreach + macro: + + \code + QWebElementCollection collection = document.findAll("p"); + foreach (QWebElement paraElement, collection) { + ... + } + \endcode +*/ + +/*! + Constructs an empty collection. +*/ +QWebElementCollection::QWebElementCollection() +{ +} + +/*! + Constructs a copy of \a other. +*/ +QWebElementCollection::QWebElementCollection(const QWebElementCollection &other) + : d(other.d) +{ +} + +/*! + Constructs a collection of elements from the list of child elements of \a contextElement that + match the specified CSS selector \a query. +*/ +QWebElementCollection::QWebElementCollection(const QWebElement &contextElement, const QString &query) +{ + d = QExplicitlySharedDataPointer<QWebElementCollectionPrivate>(QWebElementCollectionPrivate::create(contextElement.m_element, query)); +} + +/*! + Assigns \a other to this collection and returns a reference to this collection. +*/ +QWebElementCollection &QWebElementCollection::operator=(const QWebElementCollection &other) +{ + d = other.d; + return *this; +} + +/*! + Destroys the collection. +*/ +QWebElementCollection::~QWebElementCollection() +{ +} + +/*! \fn QWebElementCollection &QWebElementCollection::operator+=(const QWebElementCollection &other) + + Appends the items of the \a other list to this list and returns a + reference to this list. + + \sa operator+(), append() +*/ + +/*! + Returns a collection that contains all the elements of this collection followed + by all the elements in the \a other collection. Duplicates may occur in the result. + + \sa operator+=() +*/ +QWebElementCollection QWebElementCollection::operator+(const QWebElementCollection &other) const +{ + QWebElementCollection n = *this; n.d.detach(); n += other; return n; +} + +/*! + Extends the collection by appending all items of \a other. + + The resulting collection may include duplicate elements. + + \sa operator+=() +*/ +void QWebElementCollection::append(const QWebElementCollection &other) +{ + if (!d) { + *this = other; + return; + } + if (!other.d) + return; + Vector<RefPtr<Node> > nodes; + RefPtr<NodeList> results[] = { d->m_result, other.d->m_result }; + nodes.reserveInitialCapacity(results[0]->length() + results[1]->length()); + + for (int i = 0; i < 2; ++i) { + int j = 0; + Node* n = results[i]->item(j); + while (n) { + nodes.append(n); + n = results[i]->item(++j); + } + } + + d->m_result = StaticNodeList::adopt(nodes); +} + +/*! + Returns the number of elements in the collection. +*/ +int QWebElementCollection::count() const +{ + if (!d) + return 0; + return d->m_result->length(); +} + +/*! + Returns the element at index position \a i in the collection. +*/ +QWebElement QWebElementCollection::at(int i) const +{ + if (!d) + return QWebElement(); + Node* n = d->m_result->item(i); + return QWebElement(static_cast<Element*>(n)); +} + +/*! + \fn const QWebElement QWebElementCollection::operator[](int position) const + + Returns the element at the specified \a position in the collection. +*/ + +/*! \fn QWebElement QWebElementCollection::first() const + + Returns the first element in the collection. + + \sa last(), operator[](), at(), count() +*/ + +/*! \fn QWebElement QWebElementCollection::last() const + + Returns the last element in the collection. + + \sa first(), operator[](), at(), count() +*/ + +/*! + Returns a QList object with the elements contained in this collection. +*/ +QList<QWebElement> QWebElementCollection::toList() const +{ + if (!d) + return QList<QWebElement>(); + QList<QWebElement> elements; + int i = 0; + Node* n = d->m_result->item(i); + while (n) { + if (n->isElementNode()) + elements.append(QWebElement(static_cast<Element*>(n))); + n = d->m_result->item(++i); + } + return elements; +} + +/*! + \fn QWebElementCollection::const_iterator QWebElementCollection::begin() const + + Returns an STL-style iterator pointing to the first element in the collection. + + \sa end() +*/ + +/*! + \fn QWebElementCollection::const_iterator QWebElementCollection::end() const + + Returns an STL-style iterator pointing to the imaginary element after the + last element in the list. + + \sa begin() +*/ + +/*! + \class QWebElementCollection::const_iterator + \since 4.6 + \brief The QWebElementCollection::const_iterator class provides an STL-style const iterator for QWebElementCollection. + + QWebElementCollection provides STL style const iterators for fast low-level access to the elements. + + QWebElementCollection::const_iterator allows you to iterate over a QWebElementCollection. +*/ + +/*! + \fn QWebElementCollection::const_iterator::const_iterator(const const_iterator &other) + + Constructs a copy of \a other. +*/ + +/*! + \fn QWebElementCollection::const_iterator::const_iterator(const QWebElementCollection *collection, int index) + \internal +*/ + +/*! + \fn const QWebElement QWebElementCollection::const_iterator::operator*() const + + Returns the current element. +*/ + +/*! + \fn bool QWebElementCollection::const_iterator::operator==(const const_iterator &other) const + + Returns true if \a other points to the same item as this iterator; + otherwise returns false. + + \sa operator!=() +*/ + +/*! + \fn bool QWebElementCollection::const_iterator::operator!=(const const_iterator &other) const + + Returns true if \a other points to a different element than this; + iterator; otherwise returns false. + + \sa operator==() +*/ + +/*! + \fn QWebElementCollection::const_iterator &QWebElementCollection::const_iterator::operator++() + + The prefix ++ operator (\c{++it}) advances the iterator to the next element in the collection + and returns an iterator to the new current element. + + Calling this function on QWebElementCollection::end() leads to undefined results. + + \sa operator--() +*/ + +/*! + \fn QWebElementCollection::const_iterator QWebElementCollection::const_iterator::operator++(int) + + \overload + + The postfix ++ operator (\c{it++}) advances the iterator to the next element in the collection + and returns an iterator to the previously current element. + + Calling this function on QWebElementCollection::end() leads to undefined results. +*/ + +/*! + \fn QWebElementCollection::const_iterator &QWebElementCollection::const_iterator::operator--() + + The prefix -- operator (\c{--it}) makes the preceding element current and returns an + iterator to the new current element. + + Calling this function on QWebElementCollection::begin() leads to undefined results. + + \sa operator++() +*/ + +/*! + \fn QWebElementCollection::const_iterator QWebElementCollection::const_iterator::operator--(int) + + \overload + + The postfix -- operator (\c{it--}) makes the preceding element current and returns + an iterator to the previously current element. +*/ + +/*! + \fn QWebElementCollection::const_iterator &QWebElementCollection::const_iterator::operator+=(int j) + + Advances the iterator by \a j elements. If \a j is negative, the iterator goes backward. + + \sa operator-=(), operator+() +*/ + +/*! + \fn QWebElementCollection::const_iterator &QWebElementCollection::const_iterator::operator-=(int j) + + Makes the iterator go back by \a j elements. If \a j is negative, the iterator goes forward. + + \sa operator+=(), operator-() +*/ + +/*! + \fn QWebElementCollection::const_iterator QWebElementCollection::const_iterator::operator+(int j) const + + Returns an iterator to the element at \a j positions forward from this iterator. If \a j + is negative, the iterator goes backward. + + \sa operator-(), operator+=() +*/ + +/*! + \fn QWebElementCollection::const_iterator QWebElementCollection::const_iterator::operator-(int j) const + + Returns an iterator to the element at \a j positiosn backward from this iterator. + If \a j is negative, the iterator goes forward. + + \sa operator+(), operator-=() +*/ + +/*! + \fn int QWebElementCollection::const_iterator::operator-(const_iterator other) const + + Returns the number of elements between the item point to by \a other + and the element pointed to by this iterator. +*/ + +/*! + \fn bool QWebElementCollection::const_iterator::operator<(const const_iterator &other) const + + Returns true if the element pointed to by this iterator is less than the element pointed to + by the \a other iterator. +*/ + +/*! + \fn bool QWebElementCollection::const_iterator::operator<=(const const_iterator &other) const + + Returns true if the element pointed to by this iterator is less than or equal to the + element pointed to by the \a other iterator. +*/ + +/*! + \fn bool QWebElementCollection::const_iterator::operator>(const const_iterator &other) const + + Returns true if the element pointed to by this iterator is greater than the element pointed to + by the \a other iterator. +*/ + +/*! + \fn bool QWebElementCollection::const_iterator::operator>=(const const_iterator &other) const + + Returns true if the element pointed to by this iterator is greater than or equal to the + element pointed to by the \a other iterator. +*/ + +/*! + \fn QWebElementCollection::iterator QWebElementCollection::begin() + + Returns an STL-style iterator pointing to the first element in the collection. + + \sa end() +*/ + +/*! + \fn QWebElementCollection::iterator QWebElementCollection::end() + + Returns an STL-style iterator pointing to the imaginary element after the + last element in the list. + + \sa begin() +*/ + +/*! + \fn QWebElementCollection::const_iterator QWebElementCollection::constBegin() const + + Returns an STL-style iterator pointing to the first element in the collection. + + \sa end() +*/ + +/*! + \fn QWebElementCollection::const_iterator QWebElementCollection::constEnd() const + + Returns an STL-style iterator pointing to the imaginary element after the + last element in the list. + + \sa begin() +*/ + +/*! + \class QWebElementCollection::iterator + \since 4.6 + \brief The QWebElementCollection::iterator class provides an STL-style iterator for QWebElementCollection. + + QWebElementCollection provides STL style iterators for fast low-level access to the elements. + + QWebElementCollection::iterator allows you to iterate over a QWebElementCollection. +*/ + +/*! + \fn QWebElementCollection::iterator::iterator(const iterator &other) + + Constructs a copy of \a other. +*/ + +/*! + \fn QWebElementCollection::iterator::iterator(const QWebElementCollection *collection, int index) + \internal +*/ + +/*! + \fn const QWebElement QWebElementCollection::iterator::operator*() const + + Returns the current element. +*/ + +/*! + \fn bool QWebElementCollection::iterator::operator==(const iterator &other) const + + Returns true if \a other points to the same item as this iterator; + otherwise returns false. + + \sa operator!=() +*/ + +/*! + \fn bool QWebElementCollection::iterator::operator!=(const iterator &other) const + + Returns true if \a other points to a different element than this; + iterator; otherwise returns false. + + \sa operator==() +*/ + +/*! + \fn QWebElementCollection::iterator &QWebElementCollection::iterator::operator++() + + The prefix ++ operator (\c{++it}) advances the iterator to the next element in the collection + and returns an iterator to the new current element. + + Calling this function on QWebElementCollection::end() leads to undefined results. + + \sa operator--() +*/ + +/*! + \fn QWebElementCollection::iterator QWebElementCollection::iterator::operator++(int) + + \overload + + The postfix ++ operator (\c{it++}) advances the iterator to the next element in the collection + and returns an iterator to the previously current element. + + Calling this function on QWebElementCollection::end() leads to undefined results. +*/ + +/*! + \fn QWebElementCollection::iterator &QWebElementCollection::iterator::operator--() + + The prefix -- operator (\c{--it}) makes the preceding element current and returns an + iterator to the new current element. + + Calling this function on QWebElementCollection::begin() leads to undefined results. + + \sa operator++() +*/ + +/*! + \fn QWebElementCollection::iterator QWebElementCollection::iterator::operator--(int) + + \overload + + The postfix -- operator (\c{it--}) makes the preceding element current and returns + an iterator to the previously current element. +*/ + +/*! + \fn QWebElementCollection::iterator &QWebElementCollection::iterator::operator+=(int j) + + Advances the iterator by \a j elements. If \a j is negative, the iterator goes backward. + + \sa operator-=(), operator+() +*/ + +/*! + \fn QWebElementCollection::iterator &QWebElementCollection::iterator::operator-=(int j) + + Makes the iterator go back by \a j elements. If \a j is negative, the iterator goes forward. + + \sa operator+=(), operator-() +*/ + +/*! + \fn QWebElementCollection::iterator QWebElementCollection::iterator::operator+(int j) const + + Returns an iterator to the element at \a j positions forward from this iterator. If \a j + is negative, the iterator goes backward. + + \sa operator-(), operator+=() +*/ + +/*! + \fn QWebElementCollection::iterator QWebElementCollection::iterator::operator-(int j) const + + Returns an iterator to the element at \a j positiosn backward from this iterator. + If \a j is negative, the iterator goes forward. + + \sa operator+(), operator-=() +*/ + +/*! + \fn int QWebElementCollection::iterator::operator-(iterator other) const + + Returns the number of elements between the item point to by \a other + and the element pointed to by this iterator. +*/ + +/*! + \fn bool QWebElementCollection::iterator::operator<(const iterator &other) const + + Returns true if the element pointed to by this iterator is less than the element pointed to + by the \a other iterator. +*/ + +/*! + \fn bool QWebElementCollection::iterator::operator<=(const iterator &other) const + + Returns true if the element pointed to by this iterator is less than or equal to the + element pointed to by the \a other iterator. +*/ + +/*! + \fn bool QWebElementCollection::iterator::operator>(const iterator &other) const + + Returns true if the element pointed to by this iterator is greater than the element pointed to + by the \a other iterator. +*/ + +/*! + \fn bool QWebElementCollection::iterator::operator>=(const iterator &other) const + + Returns true if the element pointed to by this iterator is greater than or equal to the + element pointed to by the \a other iterator. +*/ diff --git a/Source/WebKit/qt/Api/qwebelement.h b/Source/WebKit/qt/Api/qwebelement.h new file mode 100644 index 0000000..b94c372 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebelement.h @@ -0,0 +1,282 @@ +/* + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBELEMENT_H +#define QWEBELEMENT_H + +#include <QtCore/qstring.h> +#include <QtCore/qstringlist.h> +#include <QtCore/qrect.h> +#include <QtCore/qvariant.h> +#include <QtCore/qshareddata.h> + +#include "qwebkitglobal.h" +namespace WebCore { + class Element; + class Node; +} + + +#if defined(WTF_USE_V8) && WTF_USE_V8 +namespace V8 { + namespace Bindings { + class QtWebElementRuntime; + } +} +#else +namespace JSC { + namespace Bindings { + class QtWebElementRuntime; + } +} +#endif + +QT_BEGIN_NAMESPACE +class QPainter; +QT_END_NAMESPACE + +class QWebFrame; +class QWebElementCollection; +class QWebElementPrivate; + +class QWEBKIT_EXPORT QWebElement { +public: + QWebElement(); + QWebElement(const QWebElement&); + QWebElement &operator=(const QWebElement&); + ~QWebElement(); + + bool operator==(const QWebElement& o) const; + bool operator!=(const QWebElement& o) const; + + bool isNull() const; + + QWebElementCollection findAll(const QString &selectorQuery) const; + QWebElement findFirst(const QString &selectorQuery) const; + + void setPlainText(const QString& text); + QString toPlainText() const; + + void setOuterXml(const QString& markup); + QString toOuterXml() const; + + void setInnerXml(const QString& markup); + QString toInnerXml() const; + + void setAttribute(const QString& name, const QString& value); + void setAttributeNS(const QString& namespaceUri, const QString& name, const QString& value); + QString attribute(const QString& name, const QString& defaultValue = QString()) const; + QString attributeNS(const QString& namespaceUri, const QString& name, const QString& defaultValue = QString()) const; + bool hasAttribute(const QString& name) const; + bool hasAttributeNS(const QString& namespaceUri, const QString& name) const; + void removeAttribute(const QString& name); + void removeAttributeNS(const QString& namespaceUri, const QString& name); + bool hasAttributes() const; + QStringList attributeNames(const QString& namespaceUri = QString()) const; + + QStringList classes() const; + bool hasClass(const QString& name) const; + void addClass(const QString& name); + void removeClass(const QString& name); + void toggleClass(const QString& name); + + bool hasFocus() const; + void setFocus(); + + QRect geometry() const; + + QString tagName() const; + QString prefix() const; + QString localName() const; + QString namespaceUri() const; + + QWebElement parent() const; + QWebElement firstChild() const; + QWebElement lastChild() const; + QWebElement nextSibling() const; + QWebElement previousSibling() const; + QWebElement document() const; + QWebFrame *webFrame() const; + + // TODO: Add QWebElementCollection overloads + // docs need example snippet + void appendInside(const QString& markup); + void appendInside(const QWebElement& element); + + // docs need example snippet + void prependInside(const QString& markup); + void prependInside(const QWebElement& element); + + // docs need example snippet + void appendOutside(const QString& markup); + void appendOutside(const QWebElement& element); + + // docs need example snippet + void prependOutside(const QString& markup); + void prependOutside(const QWebElement& element); + + // docs need example snippet + void encloseContentsWith(const QWebElement& element); + void encloseContentsWith(const QString& markup); + void encloseWith(const QString& markup); + void encloseWith(const QWebElement& element); + + void replace(const QString& markup); + void replace(const QWebElement& element); + + QWebElement clone() const; + QWebElement& takeFromDocument(); + void removeFromDocument(); + void removeAllChildren(); + + QVariant evaluateJavaScript(const QString& scriptSource); + + enum StyleResolveStrategy { + InlineStyle, + CascadedStyle, + ComputedStyle, + }; + QString styleProperty(const QString& name, StyleResolveStrategy strategy) const; + void setStyleProperty(const QString& name, const QString& value); + + void render(QPainter* painter); + +private: + explicit QWebElement(WebCore::Element*); + explicit QWebElement(WebCore::Node*); + + static QWebElement enclosingElement(WebCore::Node*); + + friend class DumpRenderTreeSupportQt; + friend class QWebFrame; + friend class QWebElementCollection; + friend class QWebHitTestResult; + friend class QWebHitTestResultPrivate; + friend class QWebPage; + +#if defined(WTF_USE_V8) && WTF_USE_V8 + friend class V8::Bindings::QtWebElementRuntime; +#else + friend class JSC::Bindings::QtWebElementRuntime; +#endif + + QWebElementPrivate* d; + WebCore::Element* m_element; +}; + +class QWebElementCollectionPrivate; + +class QWEBKIT_EXPORT QWebElementCollection +{ +public: + QWebElementCollection(); + QWebElementCollection(const QWebElement &contextElement, const QString &query); + QWebElementCollection(const QWebElementCollection &); + QWebElementCollection &operator=(const QWebElementCollection &); + ~QWebElementCollection(); + + QWebElementCollection operator+(const QWebElementCollection &other) const; + inline QWebElementCollection &operator+=(const QWebElementCollection &other) + { + append(other); return *this; + } + + void append(const QWebElementCollection &collection); + + int count() const; + QWebElement at(int i) const; + inline QWebElement operator[](int i) const { return at(i); } + + inline QWebElement first() const { return at(0); } + inline QWebElement last() const { return at(count() - 1); } + + QList<QWebElement> toList() const; + + class const_iterator { + public: + inline const_iterator(const QWebElementCollection* collection, int index) : i(index), collection(collection) {} + inline const_iterator(const const_iterator& o) : i(o.i), collection(o.collection) {} + + inline const QWebElement operator*() const { return collection->at(i); } + + inline bool operator==(const const_iterator& o) const { return i == o.i && collection == o.collection; } + inline bool operator!=(const const_iterator& o) const { return i != o.i || collection != o.collection; } + inline bool operator<(const const_iterator& o) const { return i < o.i; } + inline bool operator<=(const const_iterator& o) const { return i <= o.i; } + inline bool operator>(const const_iterator& o) const { return i > o.i; } + inline bool operator>=(const const_iterator& o) const { return i >= o.i; } + + inline const_iterator& operator++() { ++i; return *this; } + inline const_iterator operator++(int) { const_iterator n(collection, i); ++i; return n; } + inline const_iterator& operator--() { i--; return *this; } + inline const_iterator operator--(int) { const_iterator n(collection, i); i--; return n; } + inline const_iterator& operator+=(int j) { i += j; return *this; } + inline const_iterator& operator-=(int j) { i -= j; return *this; } + inline const_iterator operator+(int j) const { return const_iterator(collection, i + j); } + inline const_iterator operator-(int j) const { return const_iterator(collection, i - j); } + inline int operator-(const_iterator j) const { return i - j.i; } + private: + int i; + const QWebElementCollection* const collection; + }; + friend class const_iterator; + + inline const_iterator begin() const { return constBegin(); } + inline const_iterator end() const { return constEnd(); } + inline const_iterator constBegin() const { return const_iterator(this, 0); } + inline const_iterator constEnd() const { return const_iterator(this, count()); }; + + class iterator { + public: + inline iterator(const QWebElementCollection* collection, int index) : i(index), collection(collection) {} + inline iterator(const iterator& o) : i(o.i), collection(o.collection) {} + + inline QWebElement operator*() const { return collection->at(i); } + + inline bool operator==(const iterator& o) const { return i == o.i && collection == o.collection; } + inline bool operator!=(const iterator& o) const { return i != o.i || collection != o.collection; } + inline bool operator<(const iterator& o) const { return i < o.i; } + inline bool operator<=(const iterator& o) const { return i <= o.i; } + inline bool operator>(const iterator& o) const { return i > o.i; } + inline bool operator>=(const iterator& o) const { return i >= o.i; } + + inline iterator& operator++() { ++i; return *this; } + inline iterator operator++(int) { iterator n(collection, i); ++i; return n; } + inline iterator& operator--() { i--; return *this; } + inline iterator operator--(int) { iterator n(collection, i); i--; return n; } + inline iterator& operator+=(int j) { i += j; return *this; } + inline iterator& operator-=(int j) { i -= j; return *this; } + inline iterator operator+(int j) const { return iterator(collection, i + j); } + inline iterator operator-(int j) const { return iterator(collection, i - j); } + inline int operator-(iterator j) const { return i - j.i; } + private: + int i; + const QWebElementCollection* const collection; + }; + friend class iterator; + + inline iterator begin() { return iterator(this, 0); } + inline iterator end() { return iterator(this, count()); } +private: + QExplicitlySharedDataPointer<QWebElementCollectionPrivate> d; +}; + +Q_DECLARE_METATYPE(QWebElement) + +#endif // QWEBELEMENT_H diff --git a/Source/WebKit/qt/Api/qwebframe.cpp b/Source/WebKit/qt/Api/qwebframe.cpp new file mode 100644 index 0000000..9c89a4c --- /dev/null +++ b/Source/WebKit/qt/Api/qwebframe.cpp @@ -0,0 +1,1931 @@ +/* + Copyright (C) 2008,2009 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2007 Staikos Computing Services Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qwebframe.h" + +#if USE(JSC) +#include "Bridge.h" +#include "CallFrame.h" +#elif USE(V8) +#include "V8Binding.h" +#endif +#include "Document.h" +#include "DocumentLoader.h" +#include "DragData.h" +#include "Element.h" +#include "FocusController.h" +#include "Frame.h" +#include "FrameLoaderClientQt.h" +#include "FrameTree.h" +#include "FrameView.h" +#if USE(JSC) +#include "GCController.h" +#elif USE(V8) +#include "V8GCController.h" +#endif +#include "GraphicsContext.h" +#include "HTMLMetaElement.h" +#include "HitTestResult.h" +#include "HTTPParsers.h" +#include "IconDatabase.h" +#include "InspectorController.h" +#if USE(JSC) +#include "JSDOMBinding.h" +#include "JSDOMWindowBase.h" +#include "JSLock.h" +#include "JSObject.h" +#elif USE(V8) +#include "V8DOMWrapper.h" +#include "V8DOMWindowShell.h" +#endif +#include "NetworkingContext.h" +#include "NodeList.h" +#include "Page.h" +#include "PlatformMouseEvent.h" +#include "PlatformWheelEvent.h" +#include "PrintContext.h" +#if USE(JSC) +#include "PutPropertySlot.h" +#endif +#include "RenderLayer.h" +#include "RenderTreeAsText.h" +#include "RenderView.h" +#include "ResourceRequest.h" +#include "ScriptController.h" +#include "ScriptSourceCode.h" +#include "ScriptValue.h" +#include "Scrollbar.h" +#include "Settings.h" +#include "SelectionController.h" +#include "SubstituteData.h" +#include "SVGSMILElement.h" +#include "TiledBackingStore.h" +#include "htmlediting.h" +#include "markup.h" +#if USE(JSC) +#include "qt_instance.h" +#include "qt_runtime.h" +#endif +#include "qwebelement.h" +#include "qwebframe_p.h" +#include "qwebpage.h" +#include "qwebpage_p.h" +#include "qwebsecurityorigin.h" +#include "qwebsecurityorigin_p.h" +#include "qwebscriptworld.h" +#include "qwebscriptworld_p.h" +#if USE(JSC) +#include "runtime_object.h" +#include "runtime_root.h" +#endif +#if USE(TEXTURE_MAPPER) +#include "texmap/TextureMapper.h" +#include "texmap/TextureMapperPlatformLayer.h" +#endif +#include "wtf/HashMap.h" +#include <QMultiMap> +#include <qdebug.h> +#include <qevent.h> +#include <qfileinfo.h> +#include <qpainter.h> +#include <qprinter.h> +#include <qregion.h> +#include <qnetworkrequest.h> + +using namespace WebCore; + +// from text/qfont.cpp +QT_BEGIN_NAMESPACE +extern Q_GUI_EXPORT int qt_defaultDpi(); +QT_END_NAMESPACE + +bool QWEBKIT_EXPORT qtwebkit_webframe_scrollOverflow(QWebFrame* qFrame, int dx, int dy, const QPoint& pos) +{ + WebCore::Frame* frame = QWebFramePrivate::core(qFrame); + if (!frame || !frame->document() || !frame->view() || !frame->eventHandler()) + return false; + + QPoint contentsPos = frame->view()->windowToContents(pos); + Node* node = frame->document()->elementFromPoint(contentsPos.x(), contentsPos.y()); + if (!node) + return false; + + RenderObject* renderer = node->renderer(); + if (!renderer) + return false; + + if (renderer->isListBox()) + return false; + + RenderLayer* renderLayer = renderer->enclosingLayer(); + if (!renderLayer) + return false; + + bool scrolledHorizontal = false; + bool scrolledVertical = false; + + do { + if (dx > 0) + scrolledHorizontal = renderLayer->scroll(ScrollRight, ScrollByPixel, dx); + else if (dx < 0) + scrolledHorizontal = renderLayer->scroll(ScrollLeft, ScrollByPixel, qAbs(dx)); + + if (dy > 0) + scrolledVertical = renderLayer->scroll(ScrollDown, ScrollByPixel, dy); + else if (dy < 0) + scrolledVertical = renderLayer->scroll(ScrollUp, ScrollByPixel, qAbs(dy)); + + if (scrolledHorizontal || scrolledVertical) + return true; + + renderLayer = renderLayer->parent(); + } while (renderLayer); + + return false; +} + + +/*! + \internal + Scrolls nested frames starting at this frame, \a dx pixels to the right + and \a dy pixels downward. Both \a dx and \a dy may be negative. First attempts + to scroll elements with CSS overflow at position pos, followed by this frame. If this + frame doesn't scroll, attempts to scroll the parent +*/ +void QWEBKIT_EXPORT qtwebkit_webframe_scrollRecursively(QWebFrame* qFrame, int dx, int dy, const QPoint& pos) +{ + if (!qFrame) + return; + + if (qtwebkit_webframe_scrollOverflow(qFrame, dx, dy, pos)) + return; + + bool scrollHorizontal = false; + bool scrollVertical = false; + + do { + if (dx > 0) // scroll right + scrollHorizontal = qFrame->scrollBarValue(Qt::Horizontal) < qFrame->scrollBarMaximum(Qt::Horizontal); + else if (dx < 0) // scroll left + scrollHorizontal = qFrame->scrollBarValue(Qt::Horizontal) > qFrame->scrollBarMinimum(Qt::Horizontal); + + if (dy > 0) // scroll down + scrollVertical = qFrame->scrollBarValue(Qt::Vertical) < qFrame->scrollBarMaximum(Qt::Vertical); + else if (dy < 0) //scroll up + scrollVertical = qFrame->scrollBarValue(Qt::Vertical) > qFrame->scrollBarMinimum(Qt::Vertical); + + if (scrollHorizontal || scrollVertical) { + qFrame->scroll(dx, dy); + return; + } + + qFrame = qFrame->parentFrame(); + } while (qFrame); +} + +static inline ResourceRequestCachePolicy cacheLoadControlToCachePolicy(uint cacheLoadControl) +{ + switch (cacheLoadControl) { + case QNetworkRequest::AlwaysNetwork: + return WebCore::ReloadIgnoringCacheData; + case QNetworkRequest::PreferCache: + return WebCore::ReturnCacheDataElseLoad; + case QNetworkRequest::AlwaysCache: + return WebCore::ReturnCacheDataDontLoad; + default: + break; + } + return WebCore::UseProtocolCachePolicy; +} + +QWebFrameData::QWebFrameData(WebCore::Page* parentPage, WebCore::Frame* parentFrame, + WebCore::HTMLFrameOwnerElement* ownerFrameElement, + const WTF::String& frameName) + : name(frameName) + , ownerElement(ownerFrameElement) + , page(parentPage) + , allowsScrolling(true) + , marginWidth(0) + , marginHeight(0) +{ + frameLoaderClient = new FrameLoaderClientQt(); + frame = Frame::create(page, ownerElement, frameLoaderClient); + + // FIXME: All of the below should probably be moved over into WebCore + frame->tree()->setName(name); + if (parentFrame) + parentFrame->tree()->appendChild(frame); +} + +void QWebFramePrivate::init(QWebFrame *qframe, QWebFrameData *frameData) +{ + q = qframe; + + allowsScrolling = frameData->allowsScrolling; + marginWidth = frameData->marginWidth; + marginHeight = frameData->marginHeight; + frame = frameData->frame.get(); + frameLoaderClient = frameData->frameLoaderClient; + frameLoaderClient->setFrame(qframe, frame); + + frame->init(); +} + +void QWebFramePrivate::setPage(QWebPage* newPage) +{ + if (page == newPage) + return; + + // The QWebFrame is created as a child of QWebPage or a parent QWebFrame. + // That adds it to QObject's internal children list and ensures it will be + // deleted when parent QWebPage is deleted. Reparent if needed. + if (q->parent() == qobject_cast<QObject*>(page)) + q->setParent(newPage); + + page = newPage; + emit q->pageChanged(); +} + +WebCore::Scrollbar* QWebFramePrivate::horizontalScrollBar() const +{ + if (!frame->view()) + return 0; + return frame->view()->horizontalScrollbar(); +} + +WebCore::Scrollbar* QWebFramePrivate::verticalScrollBar() const +{ + if (!frame->view()) + return 0; + return frame->view()->verticalScrollbar(); +} + +#if ENABLE(TILED_BACKING_STORE) +void QWebFramePrivate::renderFromTiledBackingStore(GraphicsContext* context, const QRegion& clip) +{ + ASSERT(frame->tiledBackingStore()); + + if (!frame->view() || !frame->contentRenderer()) + return; + + QVector<QRect> vector = clip.rects(); + if (vector.isEmpty()) + return; + + QPainter* painter = context->platformContext(); + + WebCore::FrameView* view = frame->view(); + + int scrollX = view->scrollX(); + int scrollY = view->scrollY(); + context->translate(-scrollX, -scrollY); + + for (int i = 0; i < vector.size(); ++i) { + const QRect& clipRect = vector.at(i); + + painter->save(); + + QRect rect = clipRect.translated(scrollX, scrollY); + painter->setClipRect(rect, Qt::IntersectClip); + + frame->tiledBackingStore()->paint(context, rect); + + painter->restore(); + } + +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) + renderCompositedLayers(context, IntRect(clip.boundingRect())); + renderRelativeCoords(context, (QWebFrame::RenderLayer)(QWebFrame::ScrollBarLayer | QWebFrame::PanIconLayer), clip); +#endif +} +#endif + +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) +void QWebFramePrivate::renderCompositedLayers(GraphicsContext* context, const IntRect& clip) +{ + if (!rootGraphicsLayer) + return; + + textureMapper->setGraphicsContext(context); + textureMapper->setImageInterpolationQuality(context->imageInterpolationQuality()); + textureMapper->setTextDrawingMode(context->textDrawingMode()); + QPainter* painter = context->platformContext(); + FrameView* view = frame->view(); + painter->save(); + painter->beginNativePainting(); + TextureMapperContentLayer::PaintOptions options; + options.visibleRect = clip; + options.targetRect = view->frameRect(); + options.viewportSize = view->size(); + options.opacity = painter->opacity(); + rootGraphicsLayer->paint(textureMapper.get(), options); + painter->endNativePainting(); + painter->restore(); +} +#endif + +void QWebFramePrivate::renderRelativeCoords(GraphicsContext* context, QWebFrame::RenderLayer layer, const QRegion& clip) +{ + if (!frame->view() || !frame->contentRenderer()) + return; + + QVector<QRect> vector = clip.rects(); + if (vector.isEmpty()) + return; + + QPainter* painter = context->platformContext(); + + WebCore::FrameView* view = frame->view(); + view->updateLayoutAndStyleIfNeededRecursive(); + + if (layer & QWebFrame::ContentsLayer) { + painter->save(); + for (int i = 0; i < vector.size(); ++i) { + const QRect& clipRect = vector.at(i); + + QRect intersectedRect = clipRect.intersected(view->frameRect()); + + context->save(); + painter->setClipRect(clipRect, Qt::IntersectClip); + + int x = view->x(); + int y = view->y(); + + int scrollX = view->scrollX(); + int scrollY = view->scrollY(); + + QRect rect = intersectedRect; + context->translate(x, y); + rect.translate(-x, -y); + context->translate(-scrollX, -scrollY); + rect.translate(scrollX, scrollY); + context->clip(view->visibleContentRect()); + + view->paintContents(context, rect); + + context->restore(); + } + painter->restore(); +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) + renderCompositedLayers(context, IntRect(clip.boundingRect())); +#endif + } + if (layer & (QWebFrame::PanIconLayer | QWebFrame::ScrollBarLayer)) { + for (int i = 0; i < vector.size(); ++i) { + const QRect& clipRect = vector.at(i); + + QRect intersectedRect = clipRect.intersected(view->frameRect()); + + painter->save(); + painter->setClipRect(clipRect, Qt::IntersectClip); + + int x = view->x(); + int y = view->y(); + + if (layer & QWebFrame::ScrollBarLayer + && !view->scrollbarsSuppressed() + && (view->horizontalScrollbar() || view->verticalScrollbar())) { + context->save(); + + QRect rect = intersectedRect; + context->translate(x, y); + rect.translate(-x, -y); + + view->paintScrollbars(context, rect); + + context->restore(); + } + +#if ENABLE(PAN_SCROLLING) + if (layer & QWebFrame::PanIconLayer) + view->paintPanScrollIcon(context); +#endif + + painter->restore(); + } + } +} + +void QWebFrame::orientationChanged() +{ +#if ENABLE(ORIENTATION_EVENTS) && ENABLE(DEVICE_ORIENTATION) + int orientation; + WebCore::Frame* frame = QWebFramePrivate::core(this); + + switch (d->m_orientation.reading()->orientation()) { + case QtMobility::QOrientationReading::TopUp: + orientation = 0; + break; + case QtMobility::QOrientationReading::TopDown: + orientation = 180; + break; + case QtMobility::QOrientationReading::LeftUp: + orientation = -90; + break; + case QtMobility::QOrientationReading::RightUp: + orientation = 90; + break; + case QtMobility::QOrientationReading::FaceUp: + case QtMobility::QOrientationReading::FaceDown: + // WebCore unable to handle it + default: + return; + } + frame->sendOrientationChangeEvent(orientation); +#endif +} +/*! + \class QWebFrame + \since 4.4 + \brief The QWebFrame class represents a frame in a web page. + + \inmodule QtWebKit + + QWebFrame represents a frame inside a web page. Each QWebPage + object contains at least one frame, the main frame, obtained using + QWebPage::mainFrame(). Additional frames will be created for HTML + \c{<frame>} or \c{<iframe>} elements. + + A frame can be loaded using load() or setUrl(). Alternatively, if you have + the HTML content readily available, you can use setHtml() instead. + + The page() function returns a pointer to the web page object. See + \l{QWebView}{Elements of QWebView} for an explanation of how web + frames are related to a web page and web view. + + The QWebFrame class also offers methods to retrieve both the URL currently + loaded by the frame (see url()) as well as the URL originally requested + to be loaded (see requestedUrl()). These methods make possible the retrieval + of the URL before and after a DNS resolution or a redirection occurs during + the load process. The requestedUrl() also matches to the URL added to the + frame history (\l{QWebHistory}) if load is successful. + + The title of an HTML frame can be accessed with the title() property. + Additionally, a frame may also specify an icon, which can be accessed + using the icon() property. If the title or the icon changes, the + corresponding titleChanged() and iconChanged() signals will be emitted. + The zoomFactor() property can be used to change the overall size + of the content displayed in the frame. + + QWebFrame objects are created and controlled by the web page. You + can connect to the web page's \l{QWebPage::}{frameCreated()} signal + to be notified when a new frame is created. + + There are multiple ways to programmatically examine the contents of a frame. + The hitTestContent() function can be used to find elements by coordinate. + For access to the underlying DOM tree, there is documentElement(), + findAllElements() and findFirstElement(). + + A QWebFrame can be printed onto a QPrinter using the print() function. + This function is marked as a slot and can be conveniently connected to + \l{QPrintPreviewDialog}'s \l{QPrintPreviewDialog::}{paintRequested()} + signal. + + \sa QWebPage +*/ + +/*! + \enum QWebFrame::RenderLayer + + This enum describes the layers available for rendering using \l{QWebFrame::}{render()}. + The layers can be OR-ed together from the following list: + + \value ContentsLayer The web content of the frame + \value ScrollBarLayer The scrollbars of the frame + \value PanIconLayer The icon used when panning the frame + + \value AllLayers Includes all the above layers +*/ + +QWebFrame::QWebFrame(QWebPage *parent, QWebFrameData *frameData) + : QObject(parent) + , d(new QWebFramePrivate) +{ + d->page = parent; + d->init(this, frameData); + + if (!frameData->url.isEmpty()) { + WebCore::ResourceRequest request(frameData->url, frameData->referrer); + d->frame->loader()->load(request, frameData->name, false); + } +#if ENABLE(ORIENTATION_EVENTS) && ENABLE(DEVICE_ORIENTATION) + connect(&d->m_orientation, SIGNAL(readingChanged()), this, SLOT(orientationChanged())); + d->m_orientation.start(); +#endif +} + +QWebFrame::QWebFrame(QWebFrame *parent, QWebFrameData *frameData) + : QObject(parent) + , d(new QWebFramePrivate) +{ + d->page = parent->d->page; + d->init(this, frameData); +#if ENABLE(ORIENTATION_EVENTS) && ENABLE(DEVICE_ORIENTATION) + connect(&d->m_orientation, SIGNAL(readingChanged()), this, SLOT(orientationChanged())); + d->m_orientation.start(); +#endif +} + +QWebFrame::~QWebFrame() +{ + if (d->frame && d->frame->loader() && d->frame->loader()->client()) + static_cast<FrameLoaderClientQt*>(d->frame->loader()->client())->m_webFrame = 0; + + delete d; +} + +/*! + Make \a object available under \a name from within the frame's JavaScript + context. The \a object will be inserted as a child of the frame's window + object. + + Qt properties will be exposed as JavaScript properties and slots as + JavaScript methods. + + If you want to ensure that your QObjects remain accessible after loading a + new URL, you should add them in a slot connected to the + javaScriptWindowObjectCleared() signal. + + If Javascript is not enabled for this page, then this method does nothing. + + The \a object will never be explicitly deleted by QtWebKit. +*/ +void QWebFrame::addToJavaScriptWindowObject(const QString &name, QObject *object) +{ + addToJavaScriptWindowObject(name, object, QScriptEngine::QtOwnership); +} + +/*! + \fn void QWebFrame::addToJavaScriptWindowObject(const QString &name, QObject *object, QScriptEngine::ValueOwnership own) + \overload + + Make \a object available under \a name from within the frame's JavaScript + context. The \a object will be inserted as a child of the frame's window + object. + + Qt properties will be exposed as JavaScript properties and slots as + JavaScript methods. + + If you want to ensure that your QObjects remain accessible after loading a + new URL, you should add them in a slot connected to the + javaScriptWindowObjectCleared() signal. + + If Javascript is not enabled for this page, then this method does nothing. + + The ownership of \a object is specified using \a own. +*/ +void QWebFrame::addToJavaScriptWindowObject(const QString &name, QObject *object, QScriptEngine::ValueOwnership ownership) +{ + if (!page()->settings()->testAttribute(QWebSettings::JavascriptEnabled)) + return; +#if USE(JSC) + JSC::JSLock lock(JSC::SilenceAssertionsOnly); + JSDOMWindow* window = toJSDOMWindow(d->frame, mainThreadNormalWorld()); + JSC::Bindings::RootObject* root; + if (ownership == QScriptEngine::QtOwnership) + root = d->frame->script()->cacheableBindingRootObject(); + else + root = d->frame->script()->bindingRootObject(); + + if (!window) { + qDebug() << "Warning: couldn't get window object"; + return; + } + if (!root) { + qDebug() << "Warning: couldn't get root object"; + return; + } + + JSC::ExecState* exec = window->globalExec(); + + JSC::JSObject* runtimeObject = + JSC::Bindings::QtInstance::getQtInstance(object, root, ownership)->createRuntimeObject(exec); + + JSC::PutPropertySlot slot; + window->put(exec, JSC::Identifier(exec, reinterpret_cast_ptr<const UChar*>(name.constData()), name.length()), runtimeObject, slot); +#elif USE(V8) + QScriptEngine* engine = d->frame->script()->qtScriptEngine(); + if (!engine) + return; + QScriptValue v = engine->newQObject(object, ownership); + engine->globalObject().property("window").setProperty(name, v); +#endif +} + +/*! + Returns the frame's content as HTML, enclosed in HTML and BODY tags. + + \sa setHtml(), toPlainText() +*/ +QString QWebFrame::toHtml() const +{ + if (!d->frame->document()) + return QString(); + return createMarkup(d->frame->document()); +} + +/*! + Returns the content of this frame converted to plain text, completely + stripped of all HTML formatting. + + \sa toHtml() +*/ +QString QWebFrame::toPlainText() const +{ + if (d->frame->view() && d->frame->view()->layoutPending()) + d->frame->view()->layout(); + + Element *documentElement = d->frame->document()->documentElement(); + if (documentElement) + return documentElement->innerText(); + return QString(); +} + +/*! + Returns a dump of the rendering tree. This is mainly useful for debugging + html. +*/ +QString QWebFrame::renderTreeDump() const +{ + if (d->frame->view() && d->frame->view()->layoutPending()) + d->frame->view()->layout(); + + return externalRepresentation(d->frame); +} + +/*! + \property QWebFrame::title + \brief the title of the frame as defined by the HTML <title> element + + \sa titleChanged() +*/ + +QString QWebFrame::title() const +{ + if (d->frame->document()) + return d->frame->loader()->documentLoader()->title(); + return QString(); +} + +/*! + \since 4.5 + \brief Returns the meta data in this frame as a QMultiMap + + The meta data consists of the name and content attributes of the + of the \c{<meta>} tags in the HTML document. + + For example: + + \code + <html> + <head> + <meta name="description" content="This document is a tutorial about Qt development"> + <meta name="keywords" content="Qt, WebKit, Programming"> + </head> + ... + </html> + \endcode + + Given the above HTML code the metaData() function will return a map with two entries: + \table + \header \o Key + \o Value + \row \o "description" + \o "This document is a tutorial about Qt development" + \row \o "keywords" + \o "Qt, WebKit, Programming" + \endtable + + This function returns a multi map to support multiple meta tags with the same attribute name. +*/ +QMultiMap<QString, QString> QWebFrame::metaData() const +{ + if (!d->frame->document()) + return QMap<QString, QString>(); + + QMultiMap<QString, QString> map; + Document* doc = d->frame->document(); + RefPtr<NodeList> list = doc->getElementsByTagName("meta"); + unsigned len = list->length(); + for (unsigned i = 0; i < len; i++) { + HTMLMetaElement* meta = static_cast<HTMLMetaElement*>(list->item(i)); + map.insert(meta->name(), meta->content()); + } + return map; +} + +static inline QUrl ensureAbsoluteUrl(const QUrl &url) +{ + if (!url.isRelative()) + return url; + + return QUrl::fromLocalFile(QFileInfo(url.toLocalFile()).absoluteFilePath()); +} + +/*! + \property QWebFrame::url + \brief the url of the frame currently viewed + + Setting this property clears the view and loads the URL. + + By default, this property contains an empty, invalid URL. + + \sa urlChanged() +*/ + +void QWebFrame::setUrl(const QUrl &url) +{ + const QUrl absolute = ensureAbsoluteUrl(url); + d->frame->loader()->writer()->begin(absolute); + d->frame->loader()->writer()->end(); + load(absolute); +} + +QUrl QWebFrame::url() const +{ + return d->frame->loader()->url(); +} + +/*! + \since 4.6 + \property QWebFrame::requestedUrl + + The URL requested to loaded by the frame currently viewed. The URL may differ from + the one returned by url() if a DNS resolution or a redirection occurs. + + \sa url(), setUrl() +*/ +QUrl QWebFrame::requestedUrl() const +{ + // There are some possible edge cases to be handled here, + // apart from checking if activeDocumentLoader is valid: + // + // * Method can be called while processing an unsucessful load. + // In this case, frameLoaderClient will hold the current error + // (m_loadError), and we will make use of it to recover the 'failingURL'. + // * If the 'failingURL' holds a null'ed string though, we fallback + // to 'outgoingReferrer' (it yet is safer than originalRequest). + FrameLoader* loader = d->frame->loader(); + FrameLoaderClientQt* loaderClient = d->frameLoaderClient; + + if (!loader->activeDocumentLoader() + || !loaderClient->m_loadError.isNull()) { + if (!loaderClient->m_loadError.failingURL().isNull()) + return QUrl(loaderClient->m_loadError.failingURL()); + else if (!loader->outgoingReferrer().isEmpty()) + return QUrl(loader->outgoingReferrer()); + } + + return loader->originalRequest().url(); +} +/*! + \since 4.6 + \property QWebFrame::baseUrl + \brief the base URL of the frame, can be used to resolve relative URLs + \since 4.6 +*/ + +QUrl QWebFrame::baseUrl() const +{ + return d->frame->loader()->baseURL(); +} + +/*! + \property QWebFrame::icon + \brief the icon associated with this frame + + \sa iconChanged(), QWebSettings::iconForUrl() +*/ + +QIcon QWebFrame::icon() const +{ + return QWebSettings::iconForUrl(d->frame->loader()->url()); +} + +/*! + The name of this frame as defined by the parent frame. +*/ +QString QWebFrame::frameName() const +{ + return d->frame->tree()->uniqueName(); +} + +/*! + The web page that contains this frame. + + \sa pageChanged() +*/ +QWebPage *QWebFrame::page() const +{ + return d->page; +} + +/*! + Loads \a url into this frame. + + \note The view remains the same until enough data has arrived to display the new \a url. + + \sa setUrl(), setHtml(), setContent() +*/ +void QWebFrame::load(const QUrl &url) +{ + // The load() overload ensures that the url is absolute. + load(QNetworkRequest(url)); +} + +/*! + Loads a network request, \a req, into this frame, using the method specified in \a + operation. + + \a body is optional and is only used for POST operations. + + \note The view remains the same until enough data has arrived to display the new content. + + \sa setUrl() +*/ +void QWebFrame::load(const QNetworkRequest &req, + QNetworkAccessManager::Operation operation, + const QByteArray &body) +{ + if (d->parentFrame()) + d->page->d->insideOpenCall = true; + + QUrl url = ensureAbsoluteUrl(req.url()); + + WebCore::ResourceRequest request(url); + + switch (operation) { + case QNetworkAccessManager::HeadOperation: + request.setHTTPMethod("HEAD"); + break; + case QNetworkAccessManager::GetOperation: + request.setHTTPMethod("GET"); + break; + case QNetworkAccessManager::PutOperation: + request.setHTTPMethod("PUT"); + break; + case QNetworkAccessManager::PostOperation: + request.setHTTPMethod("POST"); + break; + case QNetworkAccessManager::DeleteOperation: + request.setHTTPMethod("DELETE"); + break; +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) + case QNetworkAccessManager::CustomOperation: + request.setHTTPMethod(req.attribute(QNetworkRequest::CustomVerbAttribute).toByteArray().constData()); + break; +#endif + case QNetworkAccessManager::UnknownOperation: + // eh? + break; + } + + QVariant cacheLoad = req.attribute(QNetworkRequest::CacheLoadControlAttribute); + if (cacheLoad.isValid()) { + bool ok; + uint cacheLoadValue = cacheLoad.toUInt(&ok); + if (ok) + request.setCachePolicy(cacheLoadControlToCachePolicy(cacheLoadValue)); + } + + QList<QByteArray> httpHeaders = req.rawHeaderList(); + for (int i = 0; i < httpHeaders.size(); ++i) { + const QByteArray &headerName = httpHeaders.at(i); + request.addHTTPHeaderField(QString::fromLatin1(headerName), QString::fromLatin1(req.rawHeader(headerName))); + } + + if (!body.isEmpty()) + request.setHTTPBody(WebCore::FormData::create(body.constData(), body.size())); + + d->frame->loader()->load(request, false); + + if (d->parentFrame()) + d->page->d->insideOpenCall = false; +} + +/*! + Sets the content of this frame to \a html. \a baseUrl is optional and used to resolve relative + URLs in the document, such as referenced images or stylesheets. + + The \a html is loaded immediately; external objects are loaded asynchronously. + + If a script in the \a html runs longer than the default script timeout (currently 10 seconds), + for example due to being blocked by a modal JavaScript alert dialog, this method will return + as soon as possible after the timeout and any subsequent \a html will be loaded asynchronously. + + When using this method WebKit assumes that external resources such as JavaScript programs or style + sheets are encoded in UTF-8 unless otherwise specified. For example, the encoding of an external + script can be specified through the charset attribute of the HTML script tag. It is also possible + for the encoding to be specified by web server. + + This is a convenience function equivalent to setContent(html, "text/html", baseUrl). + + \note This method will not affect session or global history for the frame. + + \warning This function works only for HTML, for other mime types (i.e. XHTML, SVG) + setContent() should be used instead. + + \sa toHtml(), setContent(), load() +*/ +void QWebFrame::setHtml(const QString &html, const QUrl &baseUrl) +{ + KURL kurl(baseUrl); + WebCore::ResourceRequest request(kurl); + const QByteArray utf8 = html.toUtf8(); + WTF::RefPtr<WebCore::SharedBuffer> data = WebCore::SharedBuffer::create(utf8.constData(), utf8.length()); + WebCore::SubstituteData substituteData(data, WTF::String("text/html"), WTF::String("utf-8"), KURL()); + d->frame->loader()->load(request, substituteData, false); +} + +/*! + Sets the content of this frame to the specified content \a data. If the \a mimeType argument + is empty it is currently assumed that the content is HTML but in future versions we may introduce + auto-detection. + + External objects referenced in the content are located relative to \a baseUrl. + + The \a data is loaded immediately; external objects are loaded asynchronously. + + \note This method will not affect session or global history for the frame. + + \sa toHtml(), setHtml() +*/ +void QWebFrame::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl) +{ + KURL kurl(baseUrl); + WebCore::ResourceRequest request(kurl); + WTF::RefPtr<WebCore::SharedBuffer> buffer = WebCore::SharedBuffer::create(data.constData(), data.length()); + QString actualMimeType; + WTF::String encoding; + if (mimeType.isEmpty()) + actualMimeType = QLatin1String("text/html"); + else { + actualMimeType = extractMIMETypeFromMediaType(mimeType); + encoding = extractCharsetFromMediaType(mimeType); + } + WebCore::SubstituteData substituteData(buffer, WTF::String(actualMimeType), encoding, KURL()); + d->frame->loader()->load(request, substituteData, false); +} + +/*! + Returns the parent frame of this frame, or 0 if the frame is the web pages + main frame. + + This is equivalent to qobject_cast<QWebFrame*>(frame->parent()). + + \sa childFrames() +*/ +QWebFrame *QWebFrame::parentFrame() const +{ + return d->parentFrame(); +} + +/*! + Returns a list of all frames that are direct children of this frame. + + \sa parentFrame() +*/ +QList<QWebFrame*> QWebFrame::childFrames() const +{ + QList<QWebFrame*> rc; + if (d->frame) { + FrameTree *tree = d->frame->tree(); + for (Frame *child = tree->firstChild(); child; child = child->tree()->nextSibling()) { + FrameLoader *loader = child->loader(); + QWebFrame* webFrame = qobject_cast<QWebFrame*>(loader->networkingContext()->originatingObject()); + if (webFrame) + rc.append(webFrame); + } + + } + return rc; +} + +/*! + Returns the scrollbar policy for the scrollbar defined by \a orientation. +*/ +Qt::ScrollBarPolicy QWebFrame::scrollBarPolicy(Qt::Orientation orientation) const +{ + if (orientation == Qt::Horizontal) + return d->horizontalScrollBarPolicy; + return d->verticalScrollBarPolicy; +} + +/*! + Sets the scrollbar policy for the scrollbar defined by \a orientation to \a policy. +*/ +void QWebFrame::setScrollBarPolicy(Qt::Orientation orientation, Qt::ScrollBarPolicy policy) +{ + Q_ASSERT((int)ScrollbarAuto == (int)Qt::ScrollBarAsNeeded); + Q_ASSERT((int)ScrollbarAlwaysOff == (int)Qt::ScrollBarAlwaysOff); + Q_ASSERT((int)ScrollbarAlwaysOn == (int)Qt::ScrollBarAlwaysOn); + + if (orientation == Qt::Horizontal) { + d->horizontalScrollBarPolicy = policy; + if (d->frame->view()) { + d->frame->view()->setHorizontalScrollbarMode((ScrollbarMode)policy, policy != Qt::ScrollBarAsNeeded /* lock */); + d->frame->view()->updateCanHaveScrollbars(); + } + } else { + d->verticalScrollBarPolicy = policy; + if (d->frame->view()) { + d->frame->view()->setVerticalScrollbarMode((ScrollbarMode)policy, policy != Qt::ScrollBarAsNeeded /* lock */); + d->frame->view()->updateCanHaveScrollbars(); + } + } +} + +/*! + Sets the current \a value for the scrollbar with orientation \a orientation. + + The scrollbar forces the \a value to be within the legal range: minimum <= value <= maximum. + + Changing the value also updates the thumb position. + + \sa scrollBarMinimum(), scrollBarMaximum() +*/ +void QWebFrame::setScrollBarValue(Qt::Orientation orientation, int value) +{ + Scrollbar *sb; + sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar(); + if (sb) { + if (value < 0) + value = 0; + else if (value > scrollBarMaximum(orientation)) + value = scrollBarMaximum(orientation); + sb->setValue(value, Scrollbar::NotFromScrollAnimator); + } +} + +/*! + Returns the current value for the scrollbar with orientation \a orientation, or 0 + if no scrollbar is found for \a orientation. + + \sa scrollBarMinimum(), scrollBarMaximum() +*/ +int QWebFrame::scrollBarValue(Qt::Orientation orientation) const +{ + Scrollbar *sb; + sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar(); + if (sb) + return sb->value(); + return 0; +} + +/*! + Returns the maximum value for the scrollbar with orientation \a orientation, or 0 + if no scrollbar is found for \a orientation. + + \sa scrollBarMinimum() +*/ +int QWebFrame::scrollBarMaximum(Qt::Orientation orientation) const +{ + Scrollbar *sb; + sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar(); + if (sb) + return sb->maximum(); + return 0; +} + +/*! + Returns the minimum value for the scrollbar with orientation \a orientation. + + The minimum value is always 0. + + \sa scrollBarMaximum() +*/ +int QWebFrame::scrollBarMinimum(Qt::Orientation orientation) const +{ + Q_UNUSED(orientation) + return 0; +} + +/*! + \since 4.6 + Returns the geometry for the scrollbar with orientation \a orientation. + + If the scrollbar does not exist an empty rect is returned. +*/ +QRect QWebFrame::scrollBarGeometry(Qt::Orientation orientation) const +{ + Scrollbar *sb; + sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar(); + if (sb) + return sb->frameRect(); + return QRect(); +} + +/*! + \since 4.5 + Scrolls the frame \a dx pixels to the right and \a dy pixels downward. Both + \a dx and \a dy may be negative. + + \sa QWebFrame::scrollPosition +*/ + +void QWebFrame::scroll(int dx, int dy) +{ + if (!d->frame->view()) + return; + + d->frame->view()->scrollBy(IntSize(dx, dy)); +} + +/*! + \property QWebFrame::scrollPosition + \since 4.5 + \brief the position the frame is currently scrolled to. +*/ + +QPoint QWebFrame::scrollPosition() const +{ + if (!d->frame->view()) + return QPoint(0, 0); + + IntSize ofs = d->frame->view()->scrollOffset(); + return QPoint(ofs.width(), ofs.height()); +} + +void QWebFrame::setScrollPosition(const QPoint &pos) +{ + QPoint current = scrollPosition(); + int dx = pos.x() - current.x(); + int dy = pos.y() - current.y(); + scroll(dx, dy); +} + +/*! + \since 4.7 + Scrolls the frame to the given \a anchor name. +*/ +void QWebFrame::scrollToAnchor(const QString& anchor) +{ + FrameView *view = d->frame->view(); + if (view) + view->scrollToAnchor(anchor); +} + +/*! + \since 4.6 + Render the \a layer of the frame using \a painter clipping to \a clip. + + \sa print() +*/ + +void QWebFrame::render(QPainter* painter, RenderLayer layer, const QRegion& clip) +{ + GraphicsContext context(painter); + if (context.paintingDisabled() && !context.updatingControlTints()) + return; + + if (!clip.isEmpty()) + d->renderRelativeCoords(&context, layer, clip); + else if (d->frame->view()) + d->renderRelativeCoords(&context, layer, QRegion(d->frame->view()->frameRect())); +} + +/*! + Render the frame into \a painter clipping to \a clip. +*/ +void QWebFrame::render(QPainter* painter, const QRegion& clip) +{ + GraphicsContext context(painter); + if (context.paintingDisabled() && !context.updatingControlTints()) + return; + + d->renderRelativeCoords(&context, AllLayers, clip); +} + +/*! + Render the frame into \a painter. +*/ +void QWebFrame::render(QPainter* painter) +{ + if (!d->frame->view()) + return; + + GraphicsContext context(painter); + if (context.paintingDisabled() && !context.updatingControlTints()) + return; + + d->renderRelativeCoords(&context, AllLayers, QRegion(d->frame->view()->frameRect())); +} + +/*! + \property QWebFrame::textSizeMultiplier + \brief the scaling factor for all text in the frame + \obsolete + + Use setZoomFactor instead, in combination with the ZoomTextOnly attribute in + QWebSettings. + + \note Setting this property also enables the ZoomTextOnly attribute in + QWebSettings. +*/ + +/*! + Sets the value of the multiplier used to scale the text in a Web frame to + the \a factor specified. +*/ +void QWebFrame::setTextSizeMultiplier(qreal factor) +{ + page()->settings()->setAttribute(QWebSettings::ZoomTextOnly, true); + + d->frame->setPageAndTextZoomFactors(1, factor); +} + +/*! + Returns the value of the multiplier used to scale the text in a Web frame. +*/ +qreal QWebFrame::textSizeMultiplier() const +{ + return page()->settings()->testAttribute(QWebSettings::ZoomTextOnly) ? d->frame->textZoomFactor() : d->frame->pageZoomFactor(); +} + +/*! + \property QWebFrame::zoomFactor + \since 4.5 + \brief the zoom factor for the frame +*/ + +void QWebFrame::setZoomFactor(qreal factor) +{ + if (page()->settings()->testAttribute(QWebSettings::ZoomTextOnly)) + d->frame->setTextZoomFactor(factor); + else + d->frame->setPageZoomFactor(factor); +} + +qreal QWebFrame::zoomFactor() const +{ + return page()->settings()->testAttribute(QWebSettings::ZoomTextOnly) ? d->frame->textZoomFactor() : d->frame->pageZoomFactor(); +} + +/*! + \property QWebFrame::focus + \since 4.6 + + Returns true if this frame has keyboard input focus; otherwise, returns false. +*/ +bool QWebFrame::hasFocus() const +{ + WebCore::Frame* ff = d->frame->page()->focusController()->focusedFrame(); + return ff && QWebFramePrivate::kit(ff) == this; +} + +/*! + \since 4.6 + + Gives keyboard input focus to this frame. +*/ +void QWebFrame::setFocus() +{ + QWebFramePrivate::core(this)->page()->focusController()->setFocusedFrame(QWebFramePrivate::core(this)); +} + +/*! + Returns the position of the frame relative to it's parent frame. +*/ +QPoint QWebFrame::pos() const +{ + if (!d->frame->view()) + return QPoint(); + + return d->frame->view()->frameRect().topLeft(); +} + +/*! + Return the geometry of the frame relative to it's parent frame. +*/ +QRect QWebFrame::geometry() const +{ + if (!d->frame->view()) + return QRect(); + return d->frame->view()->frameRect(); +} + +/*! + \property QWebFrame::contentsSize + \brief the size of the contents in this frame + + \sa contentsSizeChanged() +*/ +QSize QWebFrame::contentsSize() const +{ + FrameView *view = d->frame->view(); + if (!view) + return QSize(); + return QSize(view->contentsWidth(), view->contentsHeight()); +} + +/*! + \since 4.6 + + Returns the document element of this frame. + + The document element provides access to the entire structured + content of the frame. +*/ +QWebElement QWebFrame::documentElement() const +{ + WebCore::Document *doc = d->frame->document(); + if (!doc) + return QWebElement(); + return QWebElement(doc->documentElement()); +} + +/*! + \since 4.6 + Returns a new list of elements matching the given CSS selector \a selectorQuery. + If there are no matching elements, an empty list is returned. + + \l{http://www.w3.org/TR/REC-CSS2/selector.html#q1}{Standard CSS2 selector} syntax is + used for the query. + + \sa QWebElement::findAll() +*/ +QWebElementCollection QWebFrame::findAllElements(const QString &selectorQuery) const +{ + return documentElement().findAll(selectorQuery); +} + +/*! + \since 4.6 + Returns the first element in the frame's document that matches the + given CSS selector \a selectorQuery. If there is no matching element, a + null element is returned. + + \l{http://www.w3.org/TR/REC-CSS2/selector.html#q1}{Standard CSS2 selector} syntax is + used for the query. + + \sa QWebElement::findFirst() +*/ +QWebElement QWebFrame::findFirstElement(const QString &selectorQuery) const +{ + return documentElement().findFirst(selectorQuery); +} + +/*! + Performs a hit test on the frame contents at the given position \a pos and returns the hit test result. +*/ +QWebHitTestResult QWebFrame::hitTestContent(const QPoint &pos) const +{ + if (!d->frame->view() || !d->frame->contentRenderer()) + return QWebHitTestResult(); + + HitTestResult result = d->frame->eventHandler()->hitTestResultAtPoint(d->frame->view()->windowToContents(pos), /*allowShadowContent*/ false, /*ignoreClipping*/ true); + + if (result.scrollbar()) + return QWebHitTestResult(); + + return QWebHitTestResult(new QWebHitTestResultPrivate(result)); +} + +/*! \reimp +*/ +bool QWebFrame::event(QEvent *e) +{ + return QObject::event(e); +} + +#ifndef QT_NO_PRINTER +/*! + Prints the frame to the given \a printer. + + \sa render() +*/ +void QWebFrame::print(QPrinter *printer) const +{ + QPainter painter; + if (!painter.begin(printer)) + return; + + const qreal zoomFactorX = (qreal)printer->logicalDpiX() / qt_defaultDpi(); + const qreal zoomFactorY = (qreal)printer->logicalDpiY() / qt_defaultDpi(); + + PrintContext printContext(d->frame); + float pageHeight = 0; + + QRect qprinterRect = printer->pageRect(); + + IntRect pageRect(0, 0, + int(qprinterRect.width() / zoomFactorX), + int(qprinterRect.height() / zoomFactorY)); + + printContext.begin(pageRect.width()); + + printContext.computePageRects(pageRect, /* headerHeight */ 0, /* footerHeight */ 0, /* userScaleFactor */ 1.0, pageHeight); + + int docCopies; + int pageCopies; + if (printer->collateCopies()) { + docCopies = 1; + pageCopies = printer->numCopies(); + } else { + docCopies = printer->numCopies(); + pageCopies = 1; + } + + int fromPage = printer->fromPage(); + int toPage = printer->toPage(); + bool ascending = true; + + if (fromPage == 0 && toPage == 0) { + fromPage = 1; + toPage = printContext.pageCount(); + } + // paranoia check + fromPage = qMax(1, fromPage); + toPage = qMin(static_cast<int>(printContext.pageCount()), toPage); + if (toPage < fromPage) { + // if the user entered a page range outside the actual number + // of printable pages, just return + return; + } + + if (printer->pageOrder() == QPrinter::LastPageFirst) { + int tmp = fromPage; + fromPage = toPage; + toPage = tmp; + ascending = false; + } + + painter.scale(zoomFactorX, zoomFactorY); + GraphicsContext ctx(&painter); + + for (int i = 0; i < docCopies; ++i) { + int page = fromPage; + while (true) { + for (int j = 0; j < pageCopies; ++j) { + if (printer->printerState() == QPrinter::Aborted + || printer->printerState() == QPrinter::Error) { + printContext.end(); + return; + } + printContext.spoolPage(ctx, page - 1, pageRect.width()); + if (j < pageCopies - 1) + printer->newPage(); + } + + if (page == toPage) + break; + + if (ascending) + ++page; + else + --page; + + printer->newPage(); + } + + if ( i < docCopies - 1) + printer->newPage(); + } + + printContext.end(); +} +#endif // QT_NO_PRINTER + +/*! + Evaluates the JavaScript defined by \a scriptSource using this frame as context + and returns the result of the last executed statement. + + \sa addToJavaScriptWindowObject(), javaScriptWindowObjectCleared() +*/ +QVariant QWebFrame::evaluateJavaScript(const QString& scriptSource) +{ + ScriptController *proxy = d->frame->script(); + QVariant rc; + if (proxy) { +#if USE(JSC) + int distance = 0; + JSC::JSValue v = d->frame->script()->executeScript(ScriptSourceCode(scriptSource)).jsValue(); + + rc = JSC::Bindings::convertValueToQVariant(proxy->globalObject(mainThreadNormalWorld())->globalExec(), v, QMetaType::Void, &distance); +#elif USE(V8) + QScriptEngine* engine = d->frame->script()->qtScriptEngine(); + if (!engine) + return rc; + rc = engine->evaluate(scriptSource).toVariant(); +#endif + } + return rc; +} + +/*! + \since 4.5 + + Returns the frame's security origin. +*/ +QWebSecurityOrigin QWebFrame::securityOrigin() const +{ + QWebFrame* that = const_cast<QWebFrame*>(this); + QWebSecurityOriginPrivate* priv = new QWebSecurityOriginPrivate(QWebFramePrivate::core(that)->document()->securityOrigin()); + return QWebSecurityOrigin(priv); +} + +WebCore::Frame* QWebFramePrivate::core(const QWebFrame* webFrame) +{ + return webFrame->d->frame; +} + +QWebFrame* QWebFramePrivate::kit(const WebCore::Frame* coreFrame) +{ + return qobject_cast<QWebFrame*>(coreFrame->loader()->networkingContext()->originatingObject()); +} + + +/*! + \fn void QWebFrame::javaScriptWindowObjectCleared() + + This signal is emitted whenever the global window object of the JavaScript + environment is cleared, e.g., before starting a new load. + + If you intend to add QObjects to a QWebFrame using + addToJavaScriptWindowObject(), you should add them in a slot connected + to this signal. This ensures that your objects remain accessible when + loading new URLs. +*/ + +/*! + \fn void QWebFrame::provisionalLoad() + \internal +*/ + +/*! + \fn void QWebFrame::titleChanged(const QString &title) + + This signal is emitted whenever the title of the frame changes. + The \a title string specifies the new title. + + \sa title() +*/ + +/*! + \fn void QWebFrame::urlChanged(const QUrl &url) + + This signal is emitted with the URL of the frame when the frame's title is + received. The new URL is specified by \a url. + + \sa url() +*/ + +/*! + \fn void QWebFrame::initialLayoutCompleted() + + This signal is emitted when the frame is laid out the first time. + This is the first time you will see contents displayed on the frame. + + \note A frame can be laid out multiple times. +*/ + +/*! + \fn void QWebFrame::iconChanged() + + This signal is emitted when the icon ("favicon") associated with the frame + has been loaded. + + \sa icon() +*/ + +/*! + \fn void QWebFrame::contentsSizeChanged(const QSize &size) + \since 4.6 + + This signal is emitted when the frame's contents size changes + to \a size. + + \sa contentsSize() +*/ + +/*! + \fn void QWebFrame::loadStarted() + \since 4.6 + + This signal is emitted when a new load of this frame is started. + + \sa loadFinished() +*/ + +/*! + \fn void QWebFrame::loadFinished(bool ok) + \since 4.6 + + This signal is emitted when a load of this frame is finished. + \a ok will indicate whether the load was successful or any error occurred. + + \sa loadStarted() +*/ + +/*! + \fn void QWebFrame::pageChanged() + \since 4.7 + + This signal is emitted when this frame has been moved to a different QWebPage. + + \sa page() +*/ + +/*! + \class QWebHitTestResult + \since 4.4 + \brief The QWebHitTestResult class provides information about the web + page content after a hit test. + + \inmodule QtWebKit + + QWebHitTestResult is returned by QWebFrame::hitTestContent() to provide + information about the content of the web page at the specified position. +*/ + +/*! + \internal +*/ +QWebHitTestResult::QWebHitTestResult(QWebHitTestResultPrivate *priv) + : d(priv) +{ +} + +QWebHitTestResultPrivate::QWebHitTestResultPrivate(const WebCore::HitTestResult &hitTest) + : isContentEditable(false) + , isContentSelected(false) + , isScrollBar(false) +{ + if (!hitTest.innerNode()) + return; + pos = hitTest.point(); + WebCore::TextDirection dir; + title = hitTest.title(dir); + linkText = hitTest.textContent(); + linkUrl = hitTest.absoluteLinkURL(); + linkTitle = hitTest.titleDisplayString(); + alternateText = hitTest.altDisplayString(); + imageUrl = hitTest.absoluteImageURL(); + innerNode = hitTest.innerNode(); + innerNonSharedNode = hitTest.innerNonSharedNode(); + boundingRect = innerNonSharedNode ? innerNonSharedNode->renderer()->absoluteBoundingBoxRect(true) : IntRect(); + WebCore::Image *img = hitTest.image(); + if (img) { + QPixmap *pix = img->nativeImageForCurrentFrame(); + if (pix) + pixmap = *pix; + } + WebCore::Frame *wframe = hitTest.targetFrame(); + if (wframe) + linkTargetFrame = QWebFramePrivate::kit(wframe); + linkElement = QWebElement(hitTest.URLElement()); + + isContentEditable = hitTest.isContentEditable(); + isContentSelected = hitTest.isSelected(); + isScrollBar = hitTest.scrollbar(); + + if (innerNonSharedNode && innerNonSharedNode->document() + && innerNonSharedNode->document()->frame()) + frame = QWebFramePrivate::kit(innerNonSharedNode->document()->frame()); + + enclosingBlock = QWebElement(WebCore::enclosingBlock(innerNode.get())); +} + +/*! + Constructs a null hit test result. +*/ +QWebHitTestResult::QWebHitTestResult() + : d(0) +{ +} + +/*! + Constructs a hit test result from \a other. +*/ +QWebHitTestResult::QWebHitTestResult(const QWebHitTestResult &other) + : d(0) +{ + if (other.d) + d = new QWebHitTestResultPrivate(*other.d); +} + +/*! + Assigns the \a other hit test result to this. +*/ +QWebHitTestResult &QWebHitTestResult::operator=(const QWebHitTestResult &other) +{ + if (this != &other) { + if (other.d) { + if (!d) + d = new QWebHitTestResultPrivate; + *d = *other.d; + } else { + delete d; + d = 0; + } + } + return *this; +} + +/*! + Destructor. +*/ +QWebHitTestResult::~QWebHitTestResult() +{ + delete d; +} + +/*! + Returns true if the hit test result is null; otherwise returns false. +*/ +bool QWebHitTestResult::isNull() const +{ + return !d; +} + +/*! + Returns the position where the hit test occured. +*/ +QPoint QWebHitTestResult::pos() const +{ + if (!d) + return QPoint(); + return d->pos; +} + +/*! + \since 4.5 + Returns the bounding rect of the element. +*/ +QRect QWebHitTestResult::boundingRect() const +{ + if (!d) + return QRect(); + return d->boundingRect; +} + +/*! + \since 4.6 + Returns the block element that encloses the element hit. + + A block element is an element that is rendered using the + CSS "block" style. This includes for example text + paragraphs. +*/ +QWebElement QWebHitTestResult::enclosingBlockElement() const +{ + if (!d) + return QWebElement(); + return d->enclosingBlock; +} + +/*! + Returns the title of the nearest enclosing HTML element. +*/ +QString QWebHitTestResult::title() const +{ + if (!d) + return QString(); + return d->title; +} + +/*! + Returns the text of the link. +*/ +QString QWebHitTestResult::linkText() const +{ + if (!d) + return QString(); + return d->linkText; +} + +/*! + Returns the url to which the link points to. +*/ +QUrl QWebHitTestResult::linkUrl() const +{ + if (!d) + return QUrl(); + return d->linkUrl; +} + +/*! + Returns the title of the link. +*/ +QUrl QWebHitTestResult::linkTitle() const +{ + if (!d) + return QUrl(); + return d->linkTitle; +} + +/*! + \since 4.6 + Returns the element that represents the link. + + \sa linkTargetFrame() +*/ +QWebElement QWebHitTestResult::linkElement() const +{ + if (!d) + return QWebElement(); + return d->linkElement; +} + +/*! + Returns the frame that will load the link if it is activated. + + \sa linkElement() +*/ +QWebFrame *QWebHitTestResult::linkTargetFrame() const +{ + if (!d) + return 0; + return d->linkTargetFrame; +} + +/*! + Returns the alternate text of the element. This corresponds to the HTML alt attribute. +*/ +QString QWebHitTestResult::alternateText() const +{ + if (!d) + return QString(); + return d->alternateText; +} + +/*! + Returns the url of the image. +*/ +QUrl QWebHitTestResult::imageUrl() const +{ + if (!d) + return QUrl(); + return d->imageUrl; +} + +/*! + Returns a QPixmap containing the image. A null pixmap is returned if the + element being tested is not an image. +*/ +QPixmap QWebHitTestResult::pixmap() const +{ + if (!d) + return QPixmap(); + return d->pixmap; +} + +/*! + Returns true if the content is editable by the user; otherwise returns false. +*/ +bool QWebHitTestResult::isContentEditable() const +{ + if (!d) + return false; + return d->isContentEditable; +} + +/*! + Returns true if the content tested is part of the selection; otherwise returns false. +*/ +bool QWebHitTestResult::isContentSelected() const +{ + if (!d) + return false; + return d->isContentSelected; +} + +/*! + \since 4.6 + Returns the underlying DOM element as QWebElement. +*/ +QWebElement QWebHitTestResult::element() const +{ + if (!d || !d->innerNonSharedNode || !d->innerNonSharedNode->isElementNode()) + return QWebElement(); + + return QWebElement(static_cast<WebCore::Element*>(d->innerNonSharedNode.get())); +} + +/*! + Returns the frame the hit test was executed in. +*/ +QWebFrame *QWebHitTestResult::frame() const +{ + if (!d) + return 0; + return d->frame; +} diff --git a/Source/WebKit/qt/Api/qwebframe.h b/Source/WebKit/qt/Api/qwebframe.h new file mode 100644 index 0000000..8410962 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebframe.h @@ -0,0 +1,242 @@ +/* + Copyright (C) 2008,2009 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2007 Staikos Computing Services Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBFRAME_H +#define QWEBFRAME_H + +#include <QtCore/qobject.h> +#include <QtCore/qurl.h> +#include <QtCore/qvariant.h> +#include <QtGui/qicon.h> +#include <QtScript/qscriptengine.h> +#include <QtNetwork/qnetworkaccessmanager.h> +#include "qwebkitglobal.h" + +QT_BEGIN_NAMESPACE +class QRect; +class QPoint; +class QPainter; +class QPixmap; +class QMouseEvent; +class QWheelEvent; +class QNetworkRequest; +class QRegion; +class QPrinter; +QT_END_NAMESPACE + +class QWebNetworkRequest; +class QWebFramePrivate; +class QWebPage; +class QWebHitTestResult; +class QWebHistoryItem; +class QWebSecurityOrigin; +class QWebElement; +class QWebElementCollection; +class QWebScriptWorld; + +class DumpRenderTreeSupportQt; +namespace WebCore { + class WidgetPrivate; + class FrameLoaderClientQt; + class ChromeClientQt; + class PlatformLayerProxyQt; +} +class QWebFrameData; +class QWebHitTestResultPrivate; +class QWebFrame; + +class QWEBKIT_EXPORT QWebHitTestResult { +public: + QWebHitTestResult(); + QWebHitTestResult(const QWebHitTestResult &other); + QWebHitTestResult &operator=(const QWebHitTestResult &other); + ~QWebHitTestResult(); + + bool isNull() const; + + QPoint pos() const; + QRect boundingRect() const; + QWebElement enclosingBlockElement() const; + QString title() const; + + QString linkText() const; + QUrl linkUrl() const; + QUrl linkTitle() const; + QWebFrame *linkTargetFrame() const; + QWebElement linkElement() const; + + QString alternateText() const; // for img, area, input and applet + + QUrl imageUrl() const; + QPixmap pixmap() const; + + bool isContentEditable() const; + bool isContentSelected() const; + + QWebElement element() const; + + QWebFrame *frame() const; + +private: + QWebHitTestResult(QWebHitTestResultPrivate *priv); + QWebHitTestResultPrivate *d; + + friend class QWebFrame; + friend class QWebPagePrivate; + friend class QWebPage; +}; + +class QWEBKIT_EXPORT QWebFrame : public QObject { + Q_OBJECT + Q_PROPERTY(qreal textSizeMultiplier READ textSizeMultiplier WRITE setTextSizeMultiplier DESIGNABLE false) + Q_PROPERTY(qreal zoomFactor READ zoomFactor WRITE setZoomFactor) + Q_PROPERTY(QString title READ title) + Q_PROPERTY(QUrl url READ url WRITE setUrl) + Q_PROPERTY(QUrl requestedUrl READ requestedUrl) + Q_PROPERTY(QUrl baseUrl READ baseUrl) + Q_PROPERTY(QIcon icon READ icon) + Q_PROPERTY(QSize contentsSize READ contentsSize) + Q_PROPERTY(QPoint scrollPosition READ scrollPosition WRITE setScrollPosition) + Q_PROPERTY(bool focus READ hasFocus) +private: + QWebFrame(QWebPage *parent, QWebFrameData *frameData); + QWebFrame(QWebFrame *parent, QWebFrameData *frameData); + ~QWebFrame(); + +public: + QWebPage *page() const; + + void load(const QUrl &url); + void load(const QNetworkRequest &request, + QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation, + const QByteArray &body = QByteArray()); + void setHtml(const QString &html, const QUrl &baseUrl = QUrl()); + void setContent(const QByteArray &data, const QString &mimeType = QString(), const QUrl &baseUrl = QUrl()); + + void addToJavaScriptWindowObject(const QString &name, QObject *object); + void addToJavaScriptWindowObject(const QString &name, QObject *object, QScriptEngine::ValueOwnership ownership); + QString toHtml() const; + QString toPlainText() const; + QString renderTreeDump() const; + + QString title() const; + void setUrl(const QUrl &url); + QUrl url() const; + QUrl requestedUrl() const; + QUrl baseUrl() const; + QIcon icon() const; + QMultiMap<QString, QString> metaData() const; + + QString frameName() const; + + QWebFrame *parentFrame() const; + QList<QWebFrame*> childFrames() const; + + Qt::ScrollBarPolicy scrollBarPolicy(Qt::Orientation orientation) const; + void setScrollBarPolicy(Qt::Orientation orientation, Qt::ScrollBarPolicy policy); + + void setScrollBarValue(Qt::Orientation orientation, int value); + int scrollBarValue(Qt::Orientation orientation) const; + int scrollBarMinimum(Qt::Orientation orientation) const; + int scrollBarMaximum(Qt::Orientation orientation) const; + QRect scrollBarGeometry(Qt::Orientation orientation) const; + + void scroll(int, int); + QPoint scrollPosition() const; + void setScrollPosition(const QPoint &pos); + + void scrollToAnchor(const QString& anchor); + + enum RenderLayer { + ContentsLayer = 0x10, + ScrollBarLayer = 0x20, + PanIconLayer = 0x40, + + AllLayers = 0xff + }; + + void render(QPainter*); + void render(QPainter*, const QRegion& clip); + void render(QPainter*, RenderLayer layer, const QRegion& clip = QRegion()); + + void setTextSizeMultiplier(qreal factor); + qreal textSizeMultiplier() const; + + qreal zoomFactor() const; + void setZoomFactor(qreal factor); + + bool hasFocus() const; + void setFocus(); + + QPoint pos() const; + QRect geometry() const; + QSize contentsSize() const; + + QWebElement documentElement() const; + QWebElementCollection findAllElements(const QString &selectorQuery) const; + QWebElement findFirstElement(const QString &selectorQuery) const; + + QWebHitTestResult hitTestContent(const QPoint &pos) const; + + virtual bool event(QEvent *); + + QWebSecurityOrigin securityOrigin() const; + +public Q_SLOTS: + QVariant evaluateJavaScript(const QString& scriptSource); +#ifndef QT_NO_PRINTER + void print(QPrinter *printer) const; +#endif + +private Q_SLOTS: + void orientationChanged(); + +Q_SIGNALS: + void javaScriptWindowObjectCleared(); + + void provisionalLoad(); + void titleChanged(const QString &title); + void urlChanged(const QUrl &url); + + void initialLayoutCompleted(); + + void iconChanged(); + + void contentsSizeChanged(const QSize &size); + + void loadStarted(); + void loadFinished(bool ok); + + void pageChanged(); + +private: + friend class QGraphicsWebView; + friend class QWebPage; + friend class QWebPagePrivate; + friend class QWebFramePrivate; + friend class DumpRenderTreeSupportQt; + friend class WebCore::WidgetPrivate; + friend class WebCore::FrameLoaderClientQt; + friend class WebCore::ChromeClientQt; + friend class WebCore::PlatformLayerProxyQt; + QWebFramePrivate *d; +}; + +#endif diff --git a/Source/WebKit/qt/Api/qwebframe_p.h b/Source/WebKit/qt/Api/qwebframe_p.h new file mode 100644 index 0000000..ee8c463 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebframe_p.h @@ -0,0 +1,152 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2007 Staikos Computing Services Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBFRAME_P_H +#define QWEBFRAME_P_H + +#include "qwebframe.h" +#include "qwebpage_p.h" + +#include "EventHandler.h" +#include "GraphicsContext.h" +#include "KURL.h" +#include "PlatformString.h" +#if ENABLE(ORIENTATION_EVENTS) && ENABLE(DEVICE_ORIENTATION) +#include "qorientationsensor.h" +#endif +#include "qwebelement.h" +#include "wtf/RefPtr.h" +#include "Frame.h" +#include "ViewportArguments.h" + +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) +#include "texmap/TextureMapper.h" +#endif + + +namespace WebCore { + class FrameLoaderClientQt; + class FrameView; + class HTMLFrameOwnerElement; + class Scrollbar; + class TextureMapperContentLayer; +} +class QWebPage; + +class QWebFrameData { +public: + QWebFrameData(WebCore::Page*, WebCore::Frame* parentFrame = 0, + WebCore::HTMLFrameOwnerElement* = 0, + const WTF::String& frameName = WTF::String()); + + WebCore::KURL url; + WTF::String name; + WebCore::HTMLFrameOwnerElement* ownerElement; + WebCore::Page* page; + RefPtr<WebCore::Frame> frame; + WebCore::FrameLoaderClientQt* frameLoaderClient; + + WTF::String referrer; + bool allowsScrolling; + int marginWidth; + int marginHeight; +}; + +class QWebFramePrivate { +public: + QWebFramePrivate() + : q(0) + , horizontalScrollBarPolicy(Qt::ScrollBarAsNeeded) + , verticalScrollBarPolicy(Qt::ScrollBarAsNeeded) + , frameLoaderClient(0) + , frame(0) + , page(0) + , allowsScrolling(true) + , marginWidth(-1) + , marginHeight(-1) +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) + , rootGraphicsLayer(0) +#endif + {} + void init(QWebFrame* qframe, QWebFrameData* frameData); + void setPage(QWebPage*); + + inline QWebFrame *parentFrame() { return qobject_cast<QWebFrame*>(q->parent()); } + + WebCore::Scrollbar* horizontalScrollBar() const; + WebCore::Scrollbar* verticalScrollBar() const; + + static WebCore::Frame* core(const QWebFrame*); + static QWebFrame* kit(const WebCore::Frame*); + + void renderRelativeCoords(WebCore::GraphicsContext*, QWebFrame::RenderLayer, const QRegion& clip); +#if ENABLE(TILED_BACKING_STORE) + void renderFromTiledBackingStore(WebCore::GraphicsContext*, const QRegion& clip); +#endif + +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) + void renderCompositedLayers(WebCore::GraphicsContext* context, const WebCore::IntRect& clip); +#endif + QWebFrame *q; + Qt::ScrollBarPolicy horizontalScrollBarPolicy; + Qt::ScrollBarPolicy verticalScrollBarPolicy; + WebCore::FrameLoaderClientQt *frameLoaderClient; + WebCore::Frame *frame; + QWebPage *page; + + bool allowsScrolling; + int marginWidth; + int marginHeight; +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) + WebCore::TextureMapperContentLayer* rootGraphicsLayer; + OwnPtr<WebCore::TextureMapper> textureMapper; +#endif + +#if ENABLE(ORIENTATION_EVENTS) && ENABLE(DEVICE_ORIENTATION) + QtMobility::QOrientationSensor m_orientation; +#endif +}; + +class QWebHitTestResultPrivate { +public: + QWebHitTestResultPrivate() : isContentEditable(false), isContentSelected(false), isScrollBar(false) {} + QWebHitTestResultPrivate(const WebCore::HitTestResult &hitTest); + + QPoint pos; + QRect boundingRect; + QWebElement enclosingBlock; + QString title; + QString linkText; + QUrl linkUrl; + QString linkTitle; + QPointer<QWebFrame> linkTargetFrame; + QWebElement linkElement; + QString alternateText; + QUrl imageUrl; + QPixmap pixmap; + bool isContentEditable; + bool isContentSelected; + bool isScrollBar; + QPointer<QWebFrame> frame; + RefPtr<WebCore::Node> innerNode; + RefPtr<WebCore::Node> innerNonSharedNode; +}; + +#endif diff --git a/Source/WebKit/qt/Api/qwebhistory.cpp b/Source/WebKit/qt/Api/qwebhistory.cpp new file mode 100644 index 0000000..a9761de --- /dev/null +++ b/Source/WebKit/qt/Api/qwebhistory.cpp @@ -0,0 +1,560 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qwebhistory.h" +#include "qwebhistory_p.h" +#include "qwebframe_p.h" + +#include "BackForwardListImpl.h" +#include "PlatformString.h" +#include "Image.h" +#include "KURL.h" +#include "Page.h" +#include "PageGroup.h" + +#include <QSharedData> +#include <QDebug> + +enum { + InitialHistoryVersion = 1, + DefaultHistoryVersion = InitialHistoryVersion +}; + +/*! + \class QWebHistoryItem + \since 4.4 + \brief The QWebHistoryItem class represents one item in the history of a QWebPage + + \inmodule QtWebKit + + Each QWebHistoryItem instance represents an entry in the history stack of a Web page, + containing information about the page, its location, and when it was last visited. + + The following table shows the properties of the page held by the history item, and + the functions used to access them. + + \table + \header \o Function \o Description + \row \o title() \o The page title. + \row \o url() \o The location of the page. + \row \o originalUrl() \o The URL used to access the page. + \row \o lastVisited() \o The date and time of the user's last visit to the page. + \row \o icon() \o The icon associated with the page that was provided by the server. + \row \o userData() \o The user specific data that was stored with the history item. + \endtable + + \note QWebHistoryItem objects are value based, but \e{explicitly shared}. Changing + a QWebHistoryItem instance by calling setUserData() will change all copies of that + instance. + + \sa QWebHistory, QWebPage::history(), QWebHistoryInterface +*/ + +/*! + Constructs a history item from \a other. The new item and \a other + will share their data, and modifying either this item or \a other will + modify both instances. +*/ +QWebHistoryItem::QWebHistoryItem(const QWebHistoryItem &other) + : d(other.d) +{ +} + +/*! + Assigns the \a other history item to this. This item and \a other + will share their data, and modifying either this item or \a other will + modify both instances. +*/ +QWebHistoryItem &QWebHistoryItem::operator=(const QWebHistoryItem &other) +{ + d = other.d; + return *this; +} + +/*! + Destroys the history item. +*/ +QWebHistoryItem::~QWebHistoryItem() +{ +} + +/*! + Returns the original URL associated with the history item. + + \sa url() +*/ +QUrl QWebHistoryItem::originalUrl() const +{ + if (d->item) + return d->item->originalURL(); + return QUrl(); +} + + +/*! + Returns the URL associated with the history item. + + \sa originalUrl(), title(), lastVisited() +*/ +QUrl QWebHistoryItem::url() const +{ + if (d->item) + return d->item->url(); + return QUrl(); +} + + +/*! + Returns the title of the page associated with the history item. + + \sa icon(), url(), lastVisited() +*/ +QString QWebHistoryItem::title() const +{ + if (d->item) + return d->item->title(); + return QString(); +} + + +/*! + Returns the date and time that the page associated with the item was last visited. + + \sa title(), icon(), url() +*/ +QDateTime QWebHistoryItem::lastVisited() const +{ + //FIXME : this will be wrong unless we correctly set lastVisitedTime ourselves + if (d->item) + return QDateTime::fromTime_t((uint)d->item->lastVisitedTime()); + return QDateTime(); +} + + +/*! + Returns the icon associated with the history item. + + \sa title(), url(), lastVisited() +*/ +QIcon QWebHistoryItem::icon() const +{ + if (d->item) + return *d->item->icon()->nativeImageForCurrentFrame(); + return QIcon(); +} + +/*! + \since 4.5 + Returns the user specific data that was stored with the history item. + + \sa setUserData() +*/ +QVariant QWebHistoryItem::userData() const +{ + if (d->item) + return d->item->userData(); + return QVariant(); +} + +/*! + \since 4.5 + + Stores user specific data \a userData with the history item. + + \note All copies of this item will be modified. + + \sa userData() +*/ +void QWebHistoryItem::setUserData(const QVariant& userData) +{ + if (d->item) + d->item->setUserData(userData); +} + +/*!* + \internal +*/ +QWebHistoryItem::QWebHistoryItem(QWebHistoryItemPrivate *priv) +{ + d = priv; +} + +/*! + \since 4.5 + Returns whether this is a valid history item. +*/ +bool QWebHistoryItem::isValid() const +{ + return d->item; +} + +/*! + \class QWebHistory + \since 4.4 + \brief The QWebHistory class represents the history of a QWebPage + + \inmodule QtWebKit + + Each QWebPage instance contains a history of visited pages that can be accessed + by QWebPage::history(). QWebHistory represents this history and makes it possible + to navigate it. + + The history uses the concept of a \e{current item}, dividing the pages visited + into those that can be visited by navigating \e back and \e forward using the + back() and forward() functions. The current item can be obtained by calling + currentItem(), and an arbitrary item in the history can be made the current + item by passing it to goToItem(). + + A list of items describing the pages that can be visited by going back can be + obtained by calling the backItems() function; similarly, items describing the + pages ahead of the current page can be obtained with the forwardItems() function. + The total list of items is obtained with the items() function. + + Just as with containers, functions are available to examine the history in terms + of a list. Arbitrary items in the history can be obtained with itemAt(), the total + number of items is given by count(), and the history can be cleared with the + clear() function. + + QWebHistory's state can be saved to a QDataStream using the >> operator and loaded + by using the << operator. + + \sa QWebHistoryItem, QWebHistoryInterface, QWebPage +*/ + + +QWebHistory::QWebHistory() + : d(0) +{ +} + +QWebHistory::~QWebHistory() +{ + delete d; +} + +/*! + Clears the history. + + \sa count(), items() +*/ +void QWebHistory::clear() +{ + //shortcut to private BackForwardListImpl + WebCore::BackForwardListImpl* lst = d->lst; + + //clear visited links + WebCore::Page* page = static_cast<WebCore::BackForwardListImpl*>(lst)->page(); + if (page && page->groupPtr()) + page->groupPtr()->removeVisitedLinks(); + + //if count() == 0 then just return + if (!lst->entries().size()) + return; + + RefPtr<WebCore::HistoryItem> current = lst->currentItem(); + int capacity = lst->capacity(); + lst->setCapacity(0); + + lst->setCapacity(capacity); //revert capacity + lst->addItem(current.get()); //insert old current item + lst->goToItem(current.get()); //and set it as current again + + d->page()->updateNavigationActions(); +} + +/*! + Returns a list of all items currently in the history. + + \sa count(), clear() +*/ +QList<QWebHistoryItem> QWebHistory::items() const +{ + const WebCore::HistoryItemVector &items = d->lst->entries(); + + QList<QWebHistoryItem> ret; + for (unsigned i = 0; i < items.size(); ++i) { + QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(items[i].get()); + ret.append(QWebHistoryItem(priv)); + } + return ret; +} + +/*! + Returns the list of items in the backwards history list. + At most \a maxItems entries are returned. + + \sa forwardItems() +*/ +QList<QWebHistoryItem> QWebHistory::backItems(int maxItems) const +{ + WebCore::HistoryItemVector items(maxItems); + d->lst->backListWithLimit(maxItems, items); + + QList<QWebHistoryItem> ret; + for (unsigned i = 0; i < items.size(); ++i) { + QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(items[i].get()); + ret.append(QWebHistoryItem(priv)); + } + return ret; +} + +/*! + Returns the list of items in the forward history list. + At most \a maxItems entries are returned. + + \sa backItems() +*/ +QList<QWebHistoryItem> QWebHistory::forwardItems(int maxItems) const +{ + WebCore::HistoryItemVector items(maxItems); + d->lst->forwardListWithLimit(maxItems, items); + + QList<QWebHistoryItem> ret; + for (unsigned i = 0; i < items.size(); ++i) { + QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(items[i].get()); + ret.append(QWebHistoryItem(priv)); + } + return ret; +} + +/*! + Returns true if there is an item preceding the current item in the history; + otherwise returns false. + + \sa canGoForward() +*/ +bool QWebHistory::canGoBack() const +{ + return d->lst->backListCount() > 0; +} + +/*! + Returns true if we have an item to go forward to; otherwise returns false. + + \sa canGoBack() +*/ +bool QWebHistory::canGoForward() const +{ + return d->lst->forwardListCount() > 0; +} + +/*! + Set the current item to be the previous item in the history and goes to the + corresponding page; i.e., goes back one history item. + + \sa forward(), goToItem() +*/ +void QWebHistory::back() +{ + if (canGoBack()) { + WebCore::Page* page = static_cast<WebCore::BackForwardListImpl*>(d->lst)->page(); + page->goToItem(d->lst->backItem(), WebCore::FrameLoadTypeIndexedBackForward); + } +} + +/*! + Sets the current item to be the next item in the history and goes to the + corresponding page; i.e., goes forward one history item. + + \sa back(), goToItem() +*/ +void QWebHistory::forward() +{ + if (canGoForward()) { + WebCore::Page* page = static_cast<WebCore::BackForwardListImpl*>(d->lst)->page(); + page->goToItem(d->lst->forwardItem(), WebCore::FrameLoadTypeIndexedBackForward); + } +} + +/*! + Sets the current item to be the specified \a item in the history and goes to the page. + + \sa back(), forward() +*/ +void QWebHistory::goToItem(const QWebHistoryItem &item) +{ + WebCore::Page* page = static_cast<WebCore::BackForwardListImpl*>(d->lst)->page(); + page->goToItem(item.d->item, WebCore::FrameLoadTypeIndexedBackForward); +} + +/*! + Returns the item before the current item in the history. +*/ +QWebHistoryItem QWebHistory::backItem() const +{ + WebCore::HistoryItem *i = d->lst->backItem(); + QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(i); + return QWebHistoryItem(priv); +} + +/*! + Returns the current item in the history. +*/ +QWebHistoryItem QWebHistory::currentItem() const +{ + WebCore::HistoryItem *i = d->lst->currentItem(); + QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(i); + return QWebHistoryItem(priv); +} + +/*! + Returns the item after the current item in the history. +*/ +QWebHistoryItem QWebHistory::forwardItem() const +{ + WebCore::HistoryItem *i = d->lst->forwardItem(); + QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(i); + return QWebHistoryItem(priv); +} + +/*! + \since 4.5 + Returns the index of the current item in history. +*/ +int QWebHistory::currentItemIndex() const +{ + return d->lst->backListCount(); +} + +/*! + Returns the item at index \a i in the history. +*/ +QWebHistoryItem QWebHistory::itemAt(int i) const +{ + QWebHistoryItemPrivate *priv; + if (i < 0 || i >= count()) + priv = new QWebHistoryItemPrivate(0); + else { + WebCore::HistoryItem *item = d->lst->entries()[i].get(); + priv = new QWebHistoryItemPrivate(item); + } + return QWebHistoryItem(priv); +} + +/*! + Returns the total number of items in the history. +*/ +int QWebHistory::count() const +{ + return d->lst->entries().size(); +} + +/*! + \since 4.5 + Returns the maximum number of items in the history. + + \sa setMaximumItemCount() +*/ +int QWebHistory::maximumItemCount() const +{ + return d->lst->capacity(); +} + +/*! + \since 4.5 + Sets the maximum number of items in the history to \a count. + + \sa maximumItemCount() +*/ +void QWebHistory::setMaximumItemCount(int count) +{ + d->lst->setCapacity(count); +} + +/*! + \since 4.6 + \fn QDataStream& operator<<(QDataStream& stream, const QWebHistory& history) + \relates QWebHistory + + \brief The operator<< function streams a history into a data stream. + + It saves the \a history into the specified \a stream. +*/ + +QDataStream& operator<<(QDataStream& target, const QWebHistory& history) +{ + QWebHistoryPrivate* d = history.d; + + int version = DefaultHistoryVersion; + + target << version; + target << history.count() << history.currentItemIndex(); + + const WebCore::HistoryItemVector &items = d->lst->entries(); + for (unsigned i = 0; i < items.size(); i++) + items[i].get()->saveState(target, version); + + return target; +} + +/*! + \fn QDataStream& operator>>(QDataStream& stream, QWebHistory& history) + \relates QWebHistory + \since 4.6 + + \brief The operator>> function loads a history from a data stream. + + Loads a QWebHistory from the specified \a stream into the given \a history. +*/ + +QDataStream& operator>>(QDataStream& source, QWebHistory& history) +{ + QWebHistoryPrivate* d = history.d; + + int version; + + source >> version; + + if (version == 1) { + int count; + int currentIndex; + source >> count >> currentIndex; + + history.clear(); + // only if there are elements + if (count) { + // after clear() is new clear HistoryItem (at the end we had to remove it) + WebCore::HistoryItem* nullItem = d->lst->currentItem(); + for (int i = 0; i < count; i++) { + WTF::PassRefPtr<WebCore::HistoryItem> item = WebCore::HistoryItem::create(); + item->restoreState(source, version); + d->lst->addItem(item); + } + d->lst->removeItem(nullItem); + // Update the HistoryController. + static_cast<WebCore::BackForwardListImpl*>(history.d->lst)->page()->mainFrame()->loader()->history()->setCurrentItem(history.d->lst->entries()[currentIndex].get()); + history.goToItem(history.itemAt(currentIndex)); + } + } + + d->page()->updateNavigationActions(); + + return source; +} + +QWebPagePrivate* QWebHistoryPrivate::page() +{ + return QWebFramePrivate::kit(static_cast<WebCore::BackForwardListImpl*>(lst)->page()->mainFrame())->page()->handle(); +} + +WebCore::HistoryItem* QWebHistoryItemPrivate::core(const QWebHistoryItem* q) +{ + return q->d->item; +} diff --git a/Source/WebKit/qt/Api/qwebhistory.h b/Source/WebKit/qt/Api/qwebhistory.h new file mode 100644 index 0000000..3456784 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebhistory.h @@ -0,0 +1,116 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBHISTORY_H +#define QWEBHISTORY_H + +#include <QtCore/qurl.h> +#include <QtCore/qstring.h> +#include <QtGui/qicon.h> +#include <QtCore/qdatetime.h> +#include <QtCore/qshareddata.h> + +#include "qwebkitglobal.h" + +class QWebPage; + +namespace WebCore { + class FrameLoaderClientQt; +} + +class QWebHistoryItemPrivate; + +class QWEBKIT_EXPORT QWebHistoryItem { +public: + QWebHistoryItem(const QWebHistoryItem &other); + QWebHistoryItem &operator=(const QWebHistoryItem &other); + ~QWebHistoryItem(); + + QUrl originalUrl() const; + QUrl url() const; + + QString title() const; + QDateTime lastVisited() const; + + QIcon icon() const; + + QVariant userData() const; + void setUserData(const QVariant& userData); + + bool isValid() const; + +private: + QWebHistoryItem(QWebHistoryItemPrivate *priv); + friend class QWebHistory; + friend class QWebPage; + friend class WebCore::FrameLoaderClientQt; + friend class QWebHistoryItemPrivate; + friend class DumpRenderTreeSupportQt; + //friend QDataStream & operator<<(QDataStream& out,const QWebHistoryItem& hist); + //friend QDataStream & operator>>(QDataStream& in,QWebHistoryItem& hist); + QExplicitlySharedDataPointer<QWebHistoryItemPrivate> d; +}; + + +class QWebHistoryPrivate; +class QWEBKIT_EXPORT QWebHistory { +public: + void clear(); + + QList<QWebHistoryItem> items() const; + QList<QWebHistoryItem> backItems(int maxItems) const; + QList<QWebHistoryItem> forwardItems(int maxItems) const; + + bool canGoBack() const; + bool canGoForward() const; + + void back(); + void forward(); + void goToItem(const QWebHistoryItem &item); + + QWebHistoryItem backItem() const; + QWebHistoryItem currentItem() const; + QWebHistoryItem forwardItem() const; + QWebHistoryItem itemAt(int i) const; + + int currentItemIndex() const; + + int count() const; + + int maximumItemCount() const; + void setMaximumItemCount(int count); + +private: + QWebHistory(); + ~QWebHistory(); + + friend class QWebPage; + friend class QWebPagePrivate; + friend QWEBKIT_EXPORT QDataStream& operator>>(QDataStream&, QWebHistory&); + friend QWEBKIT_EXPORT QDataStream& operator<<(QDataStream&, const QWebHistory&); + + Q_DISABLE_COPY(QWebHistory) + + QWebHistoryPrivate *d; +}; + +QWEBKIT_EXPORT QDataStream& operator<<(QDataStream& stream, const QWebHistory& history); +QWEBKIT_EXPORT QDataStream& operator>>(QDataStream& stream, QWebHistory& history); + +#endif diff --git a/Source/WebKit/qt/Api/qwebhistory_p.h b/Source/WebKit/qt/Api/qwebhistory_p.h new file mode 100644 index 0000000..44793b9 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebhistory_p.h @@ -0,0 +1,71 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBHISTORY_P_H +#define QWEBHISTORY_P_H + +#include "BackForwardListImpl.h" +#include "HistoryItem.h" +#include <QtCore/qglobal.h> +#include <QtCore/qshareddata.h> + +class QWebPagePrivate; + +class Q_AUTOTEST_EXPORT QWebHistoryItemPrivate : public QSharedData { +public: + static QExplicitlySharedDataPointer<QWebHistoryItemPrivate> get(QWebHistoryItem* q) + { + return q->d; + } + QWebHistoryItemPrivate(WebCore::HistoryItem* i) + { + if (i) + i->ref(); + item = i; + } + ~QWebHistoryItemPrivate() + { + if (item) + item->deref(); + } + + static WebCore::HistoryItem* core(const QWebHistoryItem* q); + + WebCore::HistoryItem* item; +}; + +class QWebHistoryPrivate : public QSharedData { +public: + QWebHistoryPrivate(WebCore::BackForwardListImpl* l) + { + l->ref(); + lst = l; + } + ~QWebHistoryPrivate() + { + lst->deref(); + } + + QWebPagePrivate* page(); + + WebCore::BackForwardListImpl* lst; +}; + + +#endif diff --git a/Source/WebKit/qt/Api/qwebhistoryinterface.cpp b/Source/WebKit/qt/Api/qwebhistoryinterface.cpp new file mode 100644 index 0000000..61cf5af --- /dev/null +++ b/Source/WebKit/qt/Api/qwebhistoryinterface.cpp @@ -0,0 +1,127 @@ +/* + Copyright (C) 2007 Staikos Computing Services Inc. <info@staikos.net> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for tracking global history. +*/ + +#include "config.h" +#include "qwebhistoryinterface.h" + +#include <QCoreApplication> + +#include "PageGroup.h" +#include "PlatformString.h" + + +static QWebHistoryInterface* default_interface; + +static bool gRoutineAdded; + +static void gCleanupInterface() +{ + if (default_interface && !default_interface->parent()) + delete default_interface; + default_interface = 0; +} + +/*! + Sets a new default interface, \a defaultInterface, that will be used by all of WebKit + to keep track of visited links. + + If an interface without a parent has already been set, the old interface will be deleted. + When the application exists QWebHistoryInterface will automatically delete the + \a defaultInterface if it does not have a parent. +*/ +void QWebHistoryInterface::setDefaultInterface(QWebHistoryInterface* defaultInterface) +{ + if (default_interface == defaultInterface) + return; + + if (default_interface && !default_interface->parent()) + delete default_interface; + + default_interface = defaultInterface; + WebCore::PageGroup::removeAllVisitedLinks(); + + //### enable after the introduction of a version + //WebCore::PageGroup::setShouldTrackVisitedLinks(true); + + if (!gRoutineAdded) { + qAddPostRoutine(gCleanupInterface); + gRoutineAdded = true; + } +} + +/*! + Returns the default interface that will be used by WebKit. If no default interface has been set, + Webkit will not keep track of visited links and a null pointer will be returned. + \sa setDefaultInterface +*/ +QWebHistoryInterface* QWebHistoryInterface::defaultInterface() +{ + return default_interface; +} + +/*! + \class QWebHistoryInterface + \since 4.4 + \brief The QWebHistoryInterface class provides an interface to implement link history. + + \inmodule QtWebKit + + The QWebHistoryInterface is an interface that can be used to + keep track of visited links. It contains two pure virtual methods that + are called by the WebKit engine: addHistoryEntry() is used to add + urls that have been visited to the interface, while + historyContains() is used to query whether the given url has been + visited by the user. By default the QWebHistoryInterface is not set, so WebKit does not keep + track of visited links. + + \note The history tracked by QWebHistoryInterface is not specific to an instance of QWebPage + but applies to all pages. +*/ + +/*! + Constructs a new QWebHistoryInterface with parent \a parent. +*/ +QWebHistoryInterface::QWebHistoryInterface(QObject* parent) + : QObject(parent) +{ +} + +/*! + Destroys the interface. If this is currently the default interface it will be unset. +*/ +QWebHistoryInterface::~QWebHistoryInterface() +{ + if (default_interface == this) + default_interface = 0; +} + +/*! + \fn bool QWebHistoryInterface::historyContains(const QString &url) const = 0 + + Called by the WebKit engine to query whether a certain \a url has been visited by the user already. + Returns true if the \a url is part of the history of visited links; otherwise returns false. +*/ + +/*! + \fn void QWebHistoryInterface::addHistoryEntry(const QString &url) = 0 + + Called by WebKit to add another \a url to the list of visited pages. +*/ diff --git a/Source/WebKit/qt/Api/qwebhistoryinterface.h b/Source/WebKit/qt/Api/qwebhistoryinterface.h new file mode 100644 index 0000000..a49c586 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebhistoryinterface.h @@ -0,0 +1,42 @@ +/* + Copyright (C) 2007 Staikos Computing Services, Inc. <info@staikos.net> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for tracking global history. +*/ + +#ifndef QWEBHISTORYINTERFACE_H +#define QWEBHISTORYINTERFACE_H + +#include <QtCore/qobject.h> + +#include "qwebkitglobal.h" + +class QWEBKIT_EXPORT QWebHistoryInterface : public QObject { + Q_OBJECT +public: + QWebHistoryInterface(QObject *parent = 0); + ~QWebHistoryInterface(); + + static void setDefaultInterface(QWebHistoryInterface *defaultInterface); + static QWebHistoryInterface *defaultInterface(); + + virtual bool historyContains(const QString &url) const = 0; + virtual void addHistoryEntry(const QString &url) = 0; +}; + +#endif diff --git a/Source/WebKit/qt/Api/qwebinspector.cpp b/Source/WebKit/qt/Api/qwebinspector.cpp new file mode 100644 index 0000000..6706f2a --- /dev/null +++ b/Source/WebKit/qt/Api/qwebinspector.cpp @@ -0,0 +1,231 @@ +/* + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qwebinspector.h" + +#include "Element.h" +#include "InspectorController.h" +#include "qwebelement.h" +#include "qwebinspector_p.h" +#include "qwebpage_p.h" + +#include <QResizeEvent> + +/*! + \class QWebInspector + \since 4.6 + \inmodule QtWebKit + \brief The QWebInspector class allows the placement and control of a + QWebPage's inspector. + The inspector can display a page's hierarchy, its loading statistics and + the current state of its individual elements. It is mostly used by web + developers. + + The QWebPage to be inspected must be specified using the setPage() method. + + A typical use of QWebInspector follows: + + \snippet webkitsnippets/qtwebkit_qwebinspector_snippet.cpp 0 + + A QWebInspector can be made visible either programmatically using + setVisible(), or by the user through the attached QWebPage's context + menu. + + \note A QWebInspector will display a blank widget if either: + \list + \o page() is null + \o QWebSettings::DeveloperExtrasEnabled is false + \endlist + + \section1 Resources + + This class acts mostly as a container and a controller for the inspector. + Most of the resources needed by the inspector are owned by the associated + QWebPage and are allocated the first time that: + \list + \o an element is inspected + \o the QWebInspector is shown. + \endlist + + \section1 Inspector configuration persistence + + The inspector allows the user to configure some options through its + user interface (e.g. the resource tracking "Always enable" option). + These settings will be persisted automatically by QtWebKit only if + your application previously called QCoreApplication::setOrganizationName() + and QCoreApplication::setApplicationName(). + See QSettings's default constructor documentation for an explanation + of why this is necessary. +*/ + +/*! + Constructs an unbound QWebInspector with \a parent as its parent. +*/ +QWebInspector::QWebInspector(QWidget* parent) + : QWidget(parent) + , d(new QWebInspectorPrivate(this)) +{ +} + +/*! + Destroys the inspector. +*/ +QWebInspector::~QWebInspector() +{ + // Remove association principally to prevent deleting a child frontend + setPage(0); + delete d; + d = 0; +} + +/*! + Bind this inspector to the QWebPage to be inspected. + + \bold {Notes:} + \list + \o There can only be one QWebInspector associated with a QWebPage + and vice versa. + \o Calling this method with a null \a page will break the current association, if any. + \o If \a page is already associated to another QWebInspector, the association + will be replaced and the previous QWebInspector will become unbound + \endlist + + \sa page() +*/ +void QWebInspector::setPage(QWebPage* page) +{ + if (d->page) { + // Break currentPage-->this + d->page->d->setInspector(0); + } + if (page && page->d->inspector && page->d->inspector != this) { + // Break newPage<->newPageCurrentInspector + page->d->inspector->setPage(0); + } + + d->page = page; + + if (page) { + // Setup the reciprocal association + page->d->setInspector(this); + } +} + +/*! + Returns the inspected QWebPage. + If no web page is currently associated, a null pointer is returned. +*/ +QWebPage* QWebInspector::page() const +{ + return d->page; +} + +/*! \reimp */ +QSize QWebInspector::sizeHint() const +{ + return QSize(450, 300); +} + +/*! \reimp */ +bool QWebInspector::event(QEvent* ev) +{ + return QWidget::event(ev); +} + +/*! \reimp */ +void QWebInspector::resizeEvent(QResizeEvent* event) +{ + d->adjustFrontendSize(event->size()); +} + +/*! \reimp */ +void QWebInspector::showEvent(QShowEvent* event) +{ +#if ENABLE(INSPECTOR) + // Allows QWebInspector::show() to init the inspector. + if (d->page) + d->page->d->inspectorController()->show(); +#endif +} + +/*! \reimp */ +void QWebInspector::hideEvent(QHideEvent* event) +{ +#if ENABLE(INSPECTOR) + if (d->page) + d->page->d->inspectorController()->close(); +#endif +} + +/*! \reimp */ +void QWebInspector::closeEvent(QCloseEvent* event) +{ +#if ENABLE(INSPECTOR) + if (d->page) + d->page->d->inspectorController()->close(); +#endif +} + +/*! \internal */ +void QWebInspectorPrivate::setFrontend(QWidget* newFrontend) +{ + if (frontend) + frontend->setParent(0); + + frontend = newFrontend; + + if (frontend) { + frontend->setParent(q); + frontend->show(); + adjustFrontendSize(q->size()); + } +} + +/*! + * \internal + */ +void QWebInspectorPrivate::attachAndReplaceRemoteFrontend(QObject* newRemoteFrontend) +{ + if (remoteFrontend) + remoteFrontend->setParent(0); + + remoteFrontend = newRemoteFrontend; + + if (remoteFrontend) + remoteFrontend->setParent(q); +} + +/*! + * \internal + */ +void QWebInspectorPrivate::detachRemoteFrontend() +{ + if (remoteFrontend) { + remoteFrontend->deleteLater(); + remoteFrontend = 0; + } +} + +void QWebInspectorPrivate::adjustFrontendSize(const QSize& size) +{ + if (frontend) + frontend->resize(size); +} + diff --git a/Source/WebKit/qt/Api/qwebinspector.h b/Source/WebKit/qt/Api/qwebinspector.h new file mode 100644 index 0000000..f192e92 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebinspector.h @@ -0,0 +1,57 @@ +/* + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBINSPECTOR_H +#define QWEBINSPECTOR_H + +#include "qwebkitglobal.h" +#include "qwebpage.h" + +#include "qwebview.h" + +class QWebInspectorPrivate; + +class QWEBKIT_EXPORT QWebInspector : public QWidget { + Q_OBJECT +public: + QWebInspector(QWidget* parent = 0); + ~QWebInspector(); + + void setPage(QWebPage* page); + QWebPage* page() const; + + QSize sizeHint() const; + bool event(QEvent*); + +protected: + void resizeEvent(QResizeEvent* event); + void showEvent(QShowEvent* event); + void hideEvent(QHideEvent* event); + void closeEvent(QCloseEvent* event); + +private: + QWebInspectorPrivate* d; + + friend class QWebInspectorPrivate; + friend class QWebPage; + friend class QWebPagePrivate; + friend class WebCore::InspectorClientQt; + friend class WebCore::InspectorFrontendClientQt; +}; +#endif diff --git a/Source/WebKit/qt/Api/qwebinspector_p.h b/Source/WebKit/qt/Api/qwebinspector_p.h new file mode 100644 index 0000000..3099eb1 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebinspector_p.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2008, 2009 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBINSPECTOR_P_H +#define QWEBINSPECTOR_P_H + +QT_BEGIN_NAMESPACE +class QSize; +class QWidget; +QT_END_NAMESPACE +class QWebInspector; +class QWebPage; + +class QWebInspectorPrivate { +public: + QWebInspectorPrivate(QWebInspector* qq) + : q(qq) + , page(0) + , frontend(0) + , remoteFrontend(0) + {} + + void setFrontend(QWidget* newFrontend); + void attachAndReplaceRemoteFrontend(QObject* newRemoteFrontend); + void detachRemoteFrontend(); + void adjustFrontendSize(const QSize& size); + + QWebInspector* q; + QWebPage* page; + QWidget* frontend; + QObject* remoteFrontend; +}; + +#endif diff --git a/Source/WebKit/qt/Api/qwebkitglobal.h b/Source/WebKit/qt/Api/qwebkitglobal.h new file mode 100644 index 0000000..7ee56de --- /dev/null +++ b/Source/WebKit/qt/Api/qwebkitglobal.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBKITGLOBAL_H +#define QWEBKITGLOBAL_H + +#include <QtCore/qglobal.h> + +#define QTWEBKIT_VERSION_STR "2.2.0" +// QTWEBKIT_VERSION is (major << 16) + (minor << 8) + patch. Similar to Qt. +#define QTWEBKIT_VERSION 0x020200 +// Use: #if (QTWEBKIT_VERSION >= QTWEBKIT_VERSION_CHECK(2, 0, 0)). Similar to Qt. +#define QTWEBKIT_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch)) + +#if defined(QT_MAKEDLL) /* create a Qt DLL library */ +# if defined(BUILDING_WEBKIT) +# define QWEBKIT_EXPORT Q_DECL_EXPORT +# else +# define QWEBKIT_EXPORT Q_DECL_IMPORT +# endif +#elif defined(QT_DLL) /* use a Qt DLL library */ +# define QWEBKIT_EXPORT Q_DECL_IMPORT +#endif + +#if !defined(QWEBKIT_EXPORT) +# if defined(QT_SHARED) +# define QWEBKIT_EXPORT Q_DECL_EXPORT +# else +# define QWEBKIT_EXPORT +# endif +#endif + +#endif // QWEBKITGLOBAL_H diff --git a/Source/WebKit/qt/Api/qwebkitplatformplugin.h b/Source/WebKit/qt/Api/qwebkitplatformplugin.h new file mode 100644 index 0000000..2a94e0c --- /dev/null +++ b/Source/WebKit/qt/Api/qwebkitplatformplugin.h @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef QWEBKITPLATFORMPLUGIN_H +#define QWEBKITPLATFORMPLUGIN_H + +/* + * Warning: The contents of this file is not part of the public QtWebKit API + * and may be changed from version to version or even be completely removed. +*/ + +#include <QObject> +#include <QUrl> +#if defined(ENABLE_QT_MULTIMEDIA) && ENABLE_QT_MULTIMEDIA +#include <QMediaPlayer> +#endif + +class QWebSelectData +{ +public: + virtual ~QWebSelectData() {} + + enum ItemType { Option, Group, Separator }; + + virtual ItemType itemType(int) const = 0; + virtual QString itemText(int index) const = 0; + virtual QString itemToolTip(int index) const = 0; + virtual bool itemIsEnabled(int index) const = 0; + virtual bool itemIsSelected(int index) const = 0; + virtual int itemCount() const = 0; + virtual bool multiple() const = 0; +}; + +class QWebSelectMethod : public QObject +{ + Q_OBJECT +public: + virtual ~QWebSelectMethod() {} + + virtual void show(const QWebSelectData&) = 0; + virtual void hide() = 0; + +Q_SIGNALS: + void selectItem(int index, bool allowMultiplySelections, bool shift); + void didHide(); +}; + +class QWebNotificationData +{ +public: + virtual ~QWebNotificationData() {} + + virtual const QString title() const = 0; + virtual const QString message() const = 0; + virtual const QByteArray iconData() const = 0; + virtual const QUrl openerPageUrl() const = 0; +}; + +class QWebNotificationPresenter : public QObject +{ + Q_OBJECT +public: + QWebNotificationPresenter() {} + virtual ~QWebNotificationPresenter() {} + + virtual void showNotification(const QWebNotificationData*) = 0; + +Q_SIGNALS: + void notificationClosed(); + void notificationClicked(); +}; + +class QWebHapticFeedbackPlayer: public QObject +{ + Q_OBJECT +public: + QWebHapticFeedbackPlayer() {} + virtual ~QWebHapticFeedbackPlayer() {} + + enum HapticStrength { + None, Weak, Medium, Strong + }; + + enum HapticEvent { + Press, Release + }; + + virtual void playHapticFeedback(const HapticEvent, const QString& hapticType, const HapticStrength) = 0; +}; + +class QWebTouchModifier : public QObject +{ + Q_OBJECT +public: + virtual ~QWebTouchModifier() {} + + enum PaddingDirection { + Up, Right, Down, Left + }; + + virtual unsigned hitTestPaddingForTouch(const PaddingDirection) const = 0; +}; + +#if defined(ENABLE_QT_MULTIMEDIA) && ENABLE_QT_MULTIMEDIA +class QWebFullScreenVideoHandler : public QObject { + Q_OBJECT +public: + QWebFullScreenVideoHandler() {} + virtual ~QWebFullScreenVideoHandler() {} + virtual bool requiresFullScreenForVideoPlayback() const = 0; + +Q_SIGNALS: + void fullScreenClosed(); + +public Q_SLOTS: + virtual void enterFullScreen(QMediaPlayer*) = 0; + virtual void exitFullScreen() = 0; +}; +#endif + +class QWebKitPlatformPlugin +{ +public: + virtual ~QWebKitPlatformPlugin() {} + + enum Extension { + MultipleSelections, + Notifications, + Haptics, + TouchInteraction, + FullScreenVideoPlayer + }; + + virtual bool supportsExtension(Extension extension) const = 0; + virtual QObject* createExtension(Extension extension) const = 0; +}; + +QT_BEGIN_NAMESPACE +Q_DECLARE_INTERFACE(QWebKitPlatformPlugin, "com.nokia.Qt.WebKit.PlatformPlugin/1.7"); +QT_END_NAMESPACE + +#endif // QWEBKITPLATFORMPLUGIN_H diff --git a/Source/WebKit/qt/Api/qwebkitversion.cpp b/Source/WebKit/qt/Api/qwebkitversion.cpp new file mode 100644 index 0000000..181913b --- /dev/null +++ b/Source/WebKit/qt/Api/qwebkitversion.cpp @@ -0,0 +1,114 @@ +/* + Copyright (C) 2009 Robert Hogan <robert@roberthogan.net> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include <qwebkitversion.h> +#include <WebKitVersion.h> + +/*! + \relates QWebPage + \since 4.6 + Returns the version number of WebKit at run-time as a string (for + example, "531.3"). + + This version is commonly used in WebKit based browsers as part + of the user agent string. Web servers and JavaScript might use + it to identify the presence of certain WebKit engine features + and behaviour. + + The evolution of this version is bound to the releases of Apple's + Safari browser. For a version specific to the QtWebKit library, + see QTWEBKIT_VERSION + + \sa QWebPage::userAgentForUrl() +*/ +QString qWebKitVersion() +{ + return QString("%1.%2").arg(WEBKIT_MAJOR_VERSION).arg(WEBKIT_MINOR_VERSION); +} + +/*! + \relates QWebPage + \since 4.6 + Returns the 'major' version number of WebKit at run-time as an integer + (for example, 531). This is the version of WebKit the application + was compiled against. + + \sa qWebKitVersion() +*/ +int qWebKitMajorVersion() +{ + return WEBKIT_MAJOR_VERSION; +} + +/*! + \relates QWebPage + \since 4.6 + Returns the 'minor' version number of WebKit at run-time as an integer + (for example, 3). This is the version of WebKit the application + was compiled against. + + \sa qWebKitVersion() +*/ +int qWebKitMinorVersion() +{ + return WEBKIT_MINOR_VERSION; +} + +/*! + \macro QTWEBKIT_VERSION + \relates QWebPage + + This macro expands a numeric value of the form 0xMMNNPP (MM = + major, NN = minor, PP = patch) that specifies QtWebKit's version + number. For example, if you compile your application against QtWebKit + 2.1.2, the QTWEBKIT_VERSION macro will expand to 0x020102. + + You can use QTWEBKIT_VERSION to use the latest QtWebKit API where + available. + + \sa QT_VERSION +*/ + +/*! + \macro QTWEBKIT_VERSION_STR + \relates QWebPage + + This macro expands to a string that specifies QtWebKit's version number + (for example, "2.1.2"). This is the version against which the + application is compiled. + + \sa QTWEBKIT_VERSION +*/ + +/*! + \macro QTWEBKIT_VERSION_CHECK + \relates QWebPage + + Turns the major, minor and patch numbers of a version into an + integer, 0xMMNNPP (MM = major, NN = minor, PP = patch). This can + be compared with another similarly processed version id, for example + in a preprocessor statement: + + \code + #if QTWEBKIT_VERSION >= QTWEBKIT_VERSION_CHECK(2, 1, 0) + // code to use API new in QtWebKit 2.1.0 + #endif + \endcode +*/ diff --git a/Source/WebKit/qt/Api/qwebkitversion.h b/Source/WebKit/qt/Api/qwebkitversion.h new file mode 100644 index 0000000..de79dd1 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebkitversion.h @@ -0,0 +1,32 @@ +/* + Copyright (C) 2009 Robert Hogan <robert@roberthogan.net> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <QtCore/qstring.h> + +#ifndef qwebkitversion_h +#define qwebkitversion_h + +#include <QtCore/qstring.h> +#include "qwebkitglobal.h" + +QWEBKIT_EXPORT QString qWebKitVersion(); +QWEBKIT_EXPORT int qWebKitMajorVersion(); +QWEBKIT_EXPORT int qWebKitMinorVersion(); + +#endif // qwebkitversion_h diff --git a/Source/WebKit/qt/Api/qwebpage.cpp b/Source/WebKit/qt/Api/qwebpage.cpp new file mode 100644 index 0000000..e80aac5 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebpage.cpp @@ -0,0 +1,4210 @@ +/* + Copyright (C) 2008, 2009 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2007 Staikos Computing Services Inc. + Copyright (C) 2007 Apple Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qwebpage.h" + +#include "qwebview.h" +#include "qwebframe.h" +#include "qwebpage_p.h" +#include "qwebframe_p.h" +#include "qwebhistory.h" +#include "qwebhistory_p.h" +#include "qwebinspector.h" +#include "qwebinspector_p.h" +#include "qwebsettings.h" +#include "qwebkitplatformplugin.h" +#include "qwebkitversion.h" + +#include "CSSComputedStyleDeclaration.h" +#include "CSSParser.h" +#include "ApplicationCacheStorage.h" +#include "BackForwardListImpl.h" +#include "MemoryCache.h" +#include "Chrome.h" +#include "ChromeClientQt.h" +#include "ClientRect.h" +#include "ContextMenu.h" +#include "ContextMenuClientQt.h" +#include "ContextMenuController.h" +#include "DeviceMotionClientQt.h" +#include "DeviceOrientationClientQt.h" +#include "DocumentLoader.h" +#include "DragClientQt.h" +#include "DragController.h" +#include "DragData.h" +#include "Editor.h" +#include "EditorClientQt.h" +#include "FocusController.h" +#include "FormState.h" +#include "Frame.h" +#include "FrameLoadRequest.h" +#include "FrameLoader.h" +#include "FrameLoader.h" +#include "FrameLoaderClientQt.h" +#include "FrameTree.h" +#include "FrameView.h" +#include "GeolocationPermissionClientQt.h" +#include "HTMLFormElement.h" +#include "HTMLFrameOwnerElement.h" +#include "HTMLInputElement.h" +#include "HTMLNames.h" +#include "HashMap.h" +#include "HitTestResult.h" +#include "Image.h" +#include "InspectorClientQt.h" +#include "InspectorController.h" +#include "InspectorServerQt.h" +#include "KURL.h" +#include "LocalizedStrings.h" +#include "Logging.h" +#include "MIMETypeRegistry.h" +#include "NavigationAction.h" +#include "NetworkingContext.h" +#include "NodeList.h" +#include "NotificationPresenterClientQt.h" +#include "NotImplemented.h" +#include "Page.h" +#include "PageClientQt.h" +#include "PageGroup.h" +#include "Pasteboard.h" +#include "PlatformKeyboardEvent.h" +#include "PlatformTouchEvent.h" +#include "PlatformWheelEvent.h" +#include "PluginDatabase.h" +#include "PluginDatabase.h" +#include "PluginPackage.h" +#include "ProgressTracker.h" +#include "QtPlatformPlugin.h" +#include "RefPtr.h" +#include "RenderTextControl.h" +#include "SchemeRegistry.h" +#include "Scrollbar.h" +#include "SecurityOrigin.h" +#include "Settings.h" +#include "TextIterator.h" +#include "WebPlatformStrategies.h" +#include "WindowFeatures.h" +#include "WorkerThread.h" +#include "runtime/InitializeThreading.h" +#include "wtf/Threading.h" + +#include <QApplication> +#include <QBasicTimer> +#include <QBitArray> +#include <QDebug> +#include <QDesktopWidget> +#include <QDragEnterEvent> +#include <QDragLeaveEvent> +#include <QDragMoveEvent> +#include <QDropEvent> +#include <QFileDialog> +#include <QHttpRequestHeader> +#include <QInputDialog> +#include <QLocale> +#include <QMessageBox> +#include <QNetworkProxy> +#include <QUndoStack> +#include <QUrl> +#include <QPainter> +#include <QClipboard> +#include <QSslSocket> +#include <QStyle> +#include <QSysInfo> +#include <QTextCharFormat> +#include <QTextDocument> +#include <QTouchEvent> +#include <QNetworkAccessManager> +#include <QNetworkRequest> +#if defined(Q_WS_X11) +#include <QX11Info> +#endif + + +using namespace WebCore; + +// from text/qfont.cpp +QT_BEGIN_NAMESPACE +extern Q_GUI_EXPORT int qt_defaultDpi(); +QT_END_NAMESPACE + +bool QWebPagePrivate::drtRun = false; + +// Lookup table mapping QWebPage::WebActions to the associated Editor commands +static const char* editorCommandWebActions[] = +{ + 0, // OpenLink, + + 0, // OpenLinkInNewWindow, + 0, // OpenFrameInNewWindow, + + 0, // DownloadLinkToDisk, + 0, // CopyLinkToClipboard, + + 0, // OpenImageInNewWindow, + 0, // DownloadImageToDisk, + 0, // CopyImageToClipboard, + + 0, // Back, + 0, // Forward, + 0, // Stop, + 0, // Reload, + + "Cut", // Cut, + "Copy", // Copy, + "Paste", // Paste, + + "Undo", // Undo, + "Redo", // Redo, + "MoveForward", // MoveToNextChar, + "MoveBackward", // MoveToPreviousChar, + "MoveWordForward", // MoveToNextWord, + "MoveWordBackward", // MoveToPreviousWord, + "MoveDown", // MoveToNextLine, + "MoveUp", // MoveToPreviousLine, + "MoveToBeginningOfLine", // MoveToStartOfLine, + "MoveToEndOfLine", // MoveToEndOfLine, + "MoveToBeginningOfParagraph", // MoveToStartOfBlock, + "MoveToEndOfParagraph", // MoveToEndOfBlock, + "MoveToBeginningOfDocument", // MoveToStartOfDocument, + "MoveToEndOfDocument", // MoveToEndOfDocument, + "MoveForwardAndModifySelection", // SelectNextChar, + "MoveBackwardAndModifySelection", // SelectPreviousChar, + "MoveWordForwardAndModifySelection", // SelectNextWord, + "MoveWordBackwardAndModifySelection", // SelectPreviousWord, + "MoveDownAndModifySelection", // SelectNextLine, + "MoveUpAndModifySelection", // SelectPreviousLine, + "MoveToBeginningOfLineAndModifySelection", // SelectStartOfLine, + "MoveToEndOfLineAndModifySelection", // SelectEndOfLine, + "MoveToBeginningOfParagraphAndModifySelection", // SelectStartOfBlock, + "MoveToEndOfParagraphAndModifySelection", // SelectEndOfBlock, + "MoveToBeginningOfDocumentAndModifySelection", //SelectStartOfDocument, + "MoveToEndOfDocumentAndModifySelection", // SelectEndOfDocument, + "DeleteWordBackward", // DeleteStartOfWord, + "DeleteWordForward", // DeleteEndOfWord, + + 0, // SetTextDirectionDefault, + 0, // SetTextDirectionLeftToRight, + 0, // SetTextDirectionRightToLeft, + + "ToggleBold", // ToggleBold, + "ToggleItalic", // ToggleItalic, + "ToggleUnderline", // ToggleUnderline, + + 0, // InspectElement, + + "InsertNewline", // InsertParagraphSeparator + "InsertLineBreak", // InsertLineSeparator + + "SelectAll", // SelectAll + 0, // ReloadAndBypassCache, + + "PasteAndMatchStyle", // PasteAndMatchStyle + "RemoveFormat", // RemoveFormat + "Strikethrough", // ToggleStrikethrough, + "Subscript", // ToggleSubscript + "Superscript", // ToggleSuperscript + "InsertUnorderedList", // InsertUnorderedList + "InsertOrderedList", // InsertOrderedList + "Indent", // Indent + "Outdent", // Outdent, + + "AlignCenter", // AlignCenter, + "AlignJustified", // AlignJustified, + "AlignLeft", // AlignLeft, + "AlignRight", // AlignRight, + + 0 // WebActionCount +}; + +// Lookup the appropriate editor command to use for WebAction \a action +const char* QWebPagePrivate::editorCommandForWebActions(QWebPage::WebAction action) +{ + if ((action > QWebPage::NoWebAction) && (action < int(sizeof(editorCommandWebActions) / sizeof(const char*)))) + return editorCommandWebActions[action]; + return 0; +} + +static inline DragOperation dropActionToDragOp(Qt::DropActions actions) +{ + unsigned result = 0; + if (actions & Qt::CopyAction) + result |= DragOperationCopy; + // DragOperationgeneric represents InternetExplorer's equivalent of Move operation, + // hence it should be considered as "move" + if (actions & Qt::MoveAction) + result |= (DragOperationMove | DragOperationGeneric); + if (actions & Qt::LinkAction) + result |= DragOperationLink; + return (DragOperation)result; +} + +static inline Qt::DropAction dragOpToDropAction(unsigned actions) +{ + Qt::DropAction result = Qt::IgnoreAction; + if (actions & DragOperationCopy) + result = Qt::CopyAction; + else if (actions & DragOperationMove) + result = Qt::MoveAction; + // DragOperationgeneric represents InternetExplorer's equivalent of Move operation, + // hence it should be considered as "move" + else if (actions & DragOperationGeneric) + result = Qt::MoveAction; + else if (actions & DragOperationLink) + result = Qt::LinkAction; + return result; +} + +QWebPagePrivate::QWebPagePrivate(QWebPage *qq) + : q(qq) + , page(0) + , client(0) + , mainFrame(0) +#ifndef QT_NO_UNDOSTACK + , undoStack(0) +#endif + , insideOpenCall(false) + , m_totalBytes(0) + , m_bytesReceived() + , clickCausedFocus(false) + , networkManager(0) + , forwardUnsupportedContent(false) + , smartInsertDeleteEnabled(true) + , selectTrailingWhitespaceEnabled(false) + , linkPolicy(QWebPage::DontDelegateLinks) + , viewportSize(QSize(0, 0)) + , pixelRatio(1) +#ifndef QT_NO_CONTEXTMENU + , currentContextMenu(0) +#endif + , settings(0) + , editable(false) + , useFixedLayout(false) + , pluginFactory(0) + , inspectorFrontend(0) + , inspector(0) + , inspectorIsInternalOnly(false) +{ + WebCore::InitializeLoggingChannelsIfNecessary(); + ScriptController::initializeThreading(); + WTF::initializeMainThread(); + WebCore::SecurityOrigin::setLocalLoadPolicy(WebCore::SecurityOrigin::AllowLocalLoadsForLocalAndSubstituteData); +#if QT_VERSION < QT_VERSION_CHECK(4, 7, 0) + WebCore::Font::setCodePath(WebCore::Font::Complex); +#endif + + WebPlatformStrategies::initialize(); + + Page::PageClients pageClients; + pageClients.chromeClient = new ChromeClientQt(q); + pageClients.contextMenuClient = new ContextMenuClientQt(); + pageClients.editorClient = new EditorClientQt(q); + pageClients.dragClient = new DragClientQt(q); + pageClients.inspectorClient = new InspectorClientQt(q); +#if ENABLE(DEVICE_ORIENTATION) + pageClients.deviceOrientationClient = new DeviceOrientationClientQt(q); + pageClients.deviceMotionClient = new DeviceMotionClientQt(q); +#endif + page = new Page(pageClients); + + settings = new QWebSettings(page->settings()); + + history.d = new QWebHistoryPrivate(static_cast<WebCore::BackForwardListImpl*>(page->backForwardList())); + memset(actions, 0, sizeof(actions)); + + PageGroup::setShouldTrackVisitedLinks(true); + +#if ENABLE(NOTIFICATIONS) + NotificationPresenterClientQt::notificationPresenter()->addClient(); +#endif +} + +QWebPagePrivate::~QWebPagePrivate() +{ + if (inspector && inspectorIsInternalOnly) { + // Since we have to delete an internal inspector, + // call setInspector(0) directly to prevent potential crashes + setInspector(0); + } +#ifndef QT_NO_CONTEXTMENU + delete currentContextMenu; +#endif +#ifndef QT_NO_UNDOSTACK + delete undoStack; +#endif + delete settings; + delete page; + + if (inspector) + inspector->setPage(0); + +#if ENABLE(NOTIFICATIONS) + NotificationPresenterClientQt::notificationPresenter()->removeClient(); +#endif +} + +WebCore::ViewportArguments QWebPagePrivate::viewportArguments() +{ + return page ? page->viewportArguments() : WebCore::ViewportArguments(); +} + +WebCore::Page* QWebPagePrivate::core(const QWebPage* page) +{ + return page->d->page; +} + +QWebPagePrivate* QWebPagePrivate::priv(QWebPage* page) +{ + return page->d; +} + +bool QWebPagePrivate::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type) +{ + if (insideOpenCall + && frame == mainFrame) + return true; + return q->acceptNavigationRequest(frame, request, type); +} + +void QWebPagePrivate::createMainFrame() +{ + if (!mainFrame) { + QWebFrameData frameData(page); + mainFrame = new QWebFrame(q, &frameData); + + emit q->frameCreated(mainFrame); + } +} + +static QWebPage::WebAction webActionForContextMenuAction(WebCore::ContextMenuAction action) +{ + switch (action) { + case WebCore::ContextMenuItemTagOpenLink: return QWebPage::OpenLink; + case WebCore::ContextMenuItemTagOpenLinkInNewWindow: return QWebPage::OpenLinkInNewWindow; + case WebCore::ContextMenuItemTagDownloadLinkToDisk: return QWebPage::DownloadLinkToDisk; + case WebCore::ContextMenuItemTagCopyLinkToClipboard: return QWebPage::CopyLinkToClipboard; + case WebCore::ContextMenuItemTagOpenImageInNewWindow: return QWebPage::OpenImageInNewWindow; + case WebCore::ContextMenuItemTagDownloadImageToDisk: return QWebPage::DownloadImageToDisk; + case WebCore::ContextMenuItemTagCopyImageToClipboard: return QWebPage::CopyImageToClipboard; + case WebCore::ContextMenuItemTagOpenFrameInNewWindow: return QWebPage::OpenFrameInNewWindow; + case WebCore::ContextMenuItemTagCopy: return QWebPage::Copy; + case WebCore::ContextMenuItemTagGoBack: return QWebPage::Back; + case WebCore::ContextMenuItemTagGoForward: return QWebPage::Forward; + case WebCore::ContextMenuItemTagStop: return QWebPage::Stop; + case WebCore::ContextMenuItemTagReload: return QWebPage::Reload; + case WebCore::ContextMenuItemTagCut: return QWebPage::Cut; + case WebCore::ContextMenuItemTagPaste: return QWebPage::Paste; + case WebCore::ContextMenuItemTagDefaultDirection: return QWebPage::SetTextDirectionDefault; + case WebCore::ContextMenuItemTagLeftToRight: return QWebPage::SetTextDirectionLeftToRight; + case WebCore::ContextMenuItemTagRightToLeft: return QWebPage::SetTextDirectionRightToLeft; + case WebCore::ContextMenuItemTagBold: return QWebPage::ToggleBold; + case WebCore::ContextMenuItemTagItalic: return QWebPage::ToggleItalic; + case WebCore::ContextMenuItemTagUnderline: return QWebPage::ToggleUnderline; + case WebCore::ContextMenuItemTagSelectAll: return QWebPage::SelectAll; +#if ENABLE(INSPECTOR) + case WebCore::ContextMenuItemTagInspectElement: return QWebPage::InspectElement; +#endif + default: break; + } + return QWebPage::NoWebAction; +} + +#ifndef QT_NO_CONTEXTMENU +QMenu *QWebPagePrivate::createContextMenu(const WebCore::ContextMenu *webcoreMenu, + const QList<WebCore::ContextMenuItem> *items, QBitArray *visitedWebActions) +{ + if (!client) + return 0; + + QMenu* menu = new QMenu(client->ownerWidget()); + for (int i = 0; i < items->count(); ++i) { + const ContextMenuItem &item = items->at(i); + switch (item.type()) { + case WebCore::CheckableActionType: /* fall through */ + case WebCore::ActionType: { + QWebPage::WebAction action = webActionForContextMenuAction(item.action()); + QAction *a = q->action(action); + if (a) { + ContextMenuItem it(item); + page->contextMenuController()->checkOrEnableIfNeeded(it); + PlatformMenuItemDescription desc = it.releasePlatformDescription(); + a->setEnabled(desc.enabled); + a->setChecked(desc.checked); + a->setCheckable(item.type() == WebCore::CheckableActionType); + + menu->addAction(a); + visitedWebActions->setBit(action); + } + break; + } + case WebCore::SeparatorType: + menu->addSeparator(); + break; + case WebCore::SubmenuType: { + QMenu *subMenu = createContextMenu(webcoreMenu, item.platformSubMenu(), visitedWebActions); + + bool anyEnabledAction = false; + + QList<QAction *> actions = subMenu->actions(); + for (int i = 0; i < actions.count(); ++i) { + if (actions.at(i)->isVisible()) + anyEnabledAction |= actions.at(i)->isEnabled(); + } + + // don't show sub-menus with just disabled actions + if (anyEnabledAction) { + subMenu->setTitle(item.title()); + menu->addAction(subMenu->menuAction()); + } else + delete subMenu; + break; + } + } + } + return menu; +} +#endif // QT_NO_CONTEXTMENU + +#ifndef QT_NO_ACTION +void QWebPagePrivate::_q_webActionTriggered(bool checked) +{ + QAction *a = qobject_cast<QAction *>(q->sender()); + if (!a) + return; + QWebPage::WebAction action = static_cast<QWebPage::WebAction>(a->data().toInt()); + q->triggerAction(action, checked); +} +#endif // QT_NO_ACTION + +void QWebPagePrivate::_q_cleanupLeakMessages() +{ +#ifndef NDEBUG + // Need this to make leak messages accurate. + memoryCache()->setCapacities(0, 0, 0); +#endif +} + +void QWebPagePrivate::updateAction(QWebPage::WebAction action) +{ +#ifdef QT_NO_ACTION + Q_UNUSED(action) +#else + QAction *a = actions[action]; + if (!a || !mainFrame) + return; + + WebCore::FrameLoader *loader = mainFrame->d->frame->loader(); + WebCore::Editor *editor = page->focusController()->focusedOrMainFrame()->editor(); + + bool enabled = a->isEnabled(); + bool checked = a->isChecked(); + + switch (action) { + case QWebPage::Back: + enabled = page->canGoBackOrForward(-1); + break; + case QWebPage::Forward: + enabled = page->canGoBackOrForward(1); + break; + case QWebPage::Stop: + enabled = loader->isLoading(); + break; + case QWebPage::Reload: + case QWebPage::ReloadAndBypassCache: + enabled = !loader->isLoading(); + break; +#ifndef QT_NO_UNDOSTACK + case QWebPage::Undo: + case QWebPage::Redo: + // those two are handled by QUndoStack + break; +#endif // QT_NO_UNDOSTACK + case QWebPage::SelectAll: // editor command is always enabled + break; + case QWebPage::SetTextDirectionDefault: + case QWebPage::SetTextDirectionLeftToRight: + case QWebPage::SetTextDirectionRightToLeft: + enabled = editor->canEdit(); + checked = false; + break; + default: { + // see if it's an editor command + const char* commandName = editorCommandForWebActions(action); + + // if it's an editor command, let it's logic determine state + if (commandName) { + Editor::Command command = editor->command(commandName); + enabled = command.isEnabled(); + if (enabled) + checked = command.state() != FalseTriState; + else + checked = false; + } + break; + } + } + + a->setEnabled(enabled); + + if (a->isCheckable()) + a->setChecked(checked); +#endif // QT_NO_ACTION +} + +void QWebPagePrivate::updateNavigationActions() +{ + updateAction(QWebPage::Back); + updateAction(QWebPage::Forward); + updateAction(QWebPage::Stop); + updateAction(QWebPage::Reload); + updateAction(QWebPage::ReloadAndBypassCache); +} + +void QWebPagePrivate::updateEditorActions() +{ + updateAction(QWebPage::Cut); + updateAction(QWebPage::Copy); + updateAction(QWebPage::Paste); + updateAction(QWebPage::MoveToNextChar); + updateAction(QWebPage::MoveToPreviousChar); + updateAction(QWebPage::MoveToNextWord); + updateAction(QWebPage::MoveToPreviousWord); + updateAction(QWebPage::MoveToNextLine); + updateAction(QWebPage::MoveToPreviousLine); + updateAction(QWebPage::MoveToStartOfLine); + updateAction(QWebPage::MoveToEndOfLine); + updateAction(QWebPage::MoveToStartOfBlock); + updateAction(QWebPage::MoveToEndOfBlock); + updateAction(QWebPage::MoveToStartOfDocument); + updateAction(QWebPage::MoveToEndOfDocument); + updateAction(QWebPage::SelectNextChar); + updateAction(QWebPage::SelectPreviousChar); + updateAction(QWebPage::SelectNextWord); + updateAction(QWebPage::SelectPreviousWord); + updateAction(QWebPage::SelectNextLine); + updateAction(QWebPage::SelectPreviousLine); + updateAction(QWebPage::SelectStartOfLine); + updateAction(QWebPage::SelectEndOfLine); + updateAction(QWebPage::SelectStartOfBlock); + updateAction(QWebPage::SelectEndOfBlock); + updateAction(QWebPage::SelectStartOfDocument); + updateAction(QWebPage::SelectEndOfDocument); + updateAction(QWebPage::DeleteStartOfWord); + updateAction(QWebPage::DeleteEndOfWord); + updateAction(QWebPage::SetTextDirectionDefault); + updateAction(QWebPage::SetTextDirectionLeftToRight); + updateAction(QWebPage::SetTextDirectionRightToLeft); + updateAction(QWebPage::ToggleBold); + updateAction(QWebPage::ToggleItalic); + updateAction(QWebPage::ToggleUnderline); + updateAction(QWebPage::InsertParagraphSeparator); + updateAction(QWebPage::InsertLineSeparator); + updateAction(QWebPage::PasteAndMatchStyle); + updateAction(QWebPage::RemoveFormat); + updateAction(QWebPage::ToggleStrikethrough); + updateAction(QWebPage::ToggleSubscript); + updateAction(QWebPage::ToggleSuperscript); + updateAction(QWebPage::InsertUnorderedList); + updateAction(QWebPage::InsertOrderedList); + updateAction(QWebPage::Indent); + updateAction(QWebPage::Outdent); + updateAction(QWebPage::AlignCenter); + updateAction(QWebPage::AlignJustified); + updateAction(QWebPage::AlignLeft); + updateAction(QWebPage::AlignRight); +} + +void QWebPagePrivate::timerEvent(QTimerEvent *ev) +{ + int timerId = ev->timerId(); + if (timerId == tripleClickTimer.timerId()) + tripleClickTimer.stop(); + else + q->timerEvent(ev); +} + +template<class T> +void QWebPagePrivate::mouseMoveEvent(T* ev) +{ + WebCore::Frame* frame = QWebFramePrivate::core(mainFrame); + if (!frame->view()) + return; + + bool accepted = frame->eventHandler()->mouseMoved(PlatformMouseEvent(ev, 0)); + ev->setAccepted(accepted); +} + +template<class T> +void QWebPagePrivate::mousePressEvent(T* ev) +{ + WebCore::Frame* frame = QWebFramePrivate::core(mainFrame); + if (!frame->view()) + return; + + RefPtr<WebCore::Node> oldNode; + Frame* focusedFrame = page->focusController()->focusedFrame(); + if (Document* focusedDocument = focusedFrame ? focusedFrame->document() : 0) + oldNode = focusedDocument->focusedNode(); + + if (tripleClickTimer.isActive() + && (ev->pos() - tripleClick).manhattanLength() + < QApplication::startDragDistance()) { + mouseTripleClickEvent(ev); + return; + } + + bool accepted = false; + adjustPointForClicking(ev); + PlatformMouseEvent mev(ev, 1); + // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton + if (mev.button() != NoButton) + accepted = frame->eventHandler()->handleMousePressEvent(mev); + ev->setAccepted(accepted); + + RefPtr<WebCore::Node> newNode; + focusedFrame = page->focusController()->focusedFrame(); + if (Document* focusedDocument = focusedFrame ? focusedFrame->document() : 0) + newNode = focusedDocument->focusedNode(); + + if (newNode && oldNode != newNode) + clickCausedFocus = true; +} + +template<class T> +void QWebPagePrivate::mouseDoubleClickEvent(T *ev) +{ + WebCore::Frame* frame = QWebFramePrivate::core(mainFrame); + if (!frame->view()) + return; + + bool accepted = false; + PlatformMouseEvent mev(ev, 2); + // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton + if (mev.button() != NoButton) + accepted = frame->eventHandler()->handleMousePressEvent(mev); + ev->setAccepted(accepted); + + tripleClickTimer.start(QApplication::doubleClickInterval(), q); + tripleClick = QPointF(ev->pos()).toPoint(); +} + +template<class T> +void QWebPagePrivate::mouseTripleClickEvent(T *ev) +{ + WebCore::Frame* frame = QWebFramePrivate::core(mainFrame); + if (!frame->view()) + return; + + bool accepted = false; + PlatformMouseEvent mev(ev, 3); + // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton + if (mev.button() != NoButton) + accepted = frame->eventHandler()->handleMousePressEvent(mev); + ev->setAccepted(accepted); +} + +void QWebPagePrivate::handleClipboard(QEvent* ev, Qt::MouseButton button) +{ +#ifndef QT_NO_CLIPBOARD + if (QApplication::clipboard()->supportsSelection()) { + bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode(); + Pasteboard::generalPasteboard()->setSelectionMode(true); + WebCore::Frame* focusFrame = page->focusController()->focusedOrMainFrame(); + if (button == Qt::LeftButton) { + if (focusFrame && (focusFrame->editor()->canCopy() || focusFrame->editor()->canDHTMLCopy())) { + focusFrame->editor()->copy(); + ev->setAccepted(true); + } + } else if (button == Qt::MidButton) { + if (focusFrame && (focusFrame->editor()->canPaste() || focusFrame->editor()->canDHTMLPaste())) { + focusFrame->editor()->paste(); + ev->setAccepted(true); + } + } + Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode); + } +#endif +} + +template<class T> +void QWebPagePrivate::mouseReleaseEvent(T *ev) +{ + WebCore::Frame* frame = QWebFramePrivate::core(mainFrame); + if (!frame->view()) + return; + + bool accepted = false; + adjustPointForClicking(ev); + PlatformMouseEvent mev(ev, 0); + // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton + if (mev.button() != NoButton) + accepted = frame->eventHandler()->handleMouseReleaseEvent(mev); + ev->setAccepted(accepted); + + handleClipboard(ev, ev->button()); + handleSoftwareInputPanel(ev->button(), QPointF(ev->pos()).toPoint()); +} + +void QWebPagePrivate::handleSoftwareInputPanel(Qt::MouseButton button, const QPoint& pos) +{ + Frame* frame = page->focusController()->focusedFrame(); + if (!frame) + return; + + if (client && client->inputMethodEnabled() + && frame->document()->focusedNode() + && button == Qt::LeftButton && qApp->autoSipEnabled()) { + QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel( + client->ownerWidget()->style()->styleHint(QStyle::SH_RequestSoftwareInputPanel)); + if (!clickCausedFocus || behavior == QStyle::RSIP_OnMouseClick) { + HitTestResult result = frame->eventHandler()->hitTestResultAtPoint(frame->view()->windowToContents(pos), false); + if (result.isContentEditable()) { + QEvent event(QEvent::RequestSoftwareInputPanel); + QApplication::sendEvent(client->ownerWidget(), &event); + } + } + } + + clickCausedFocus = false; +} + +#ifndef QT_NO_CONTEXTMENU +void QWebPagePrivate::contextMenuEvent(const QPoint& globalPos) +{ + QMenu *menu = q->createStandardContextMenu(); + if (menu) { + menu->exec(globalPos); + delete menu; + } +} +#endif // QT_NO_CONTEXTMENU + +/*! + \since 4.5 + This function creates the standard context menu which is shown when + the user clicks on the web page with the right mouse button. It is + called from the default contextMenuEvent() handler. The popup menu's + ownership is transferred to the caller. + */ +QMenu *QWebPage::createStandardContextMenu() +{ +#ifndef QT_NO_CONTEXTMENU + QMenu *menu = d->currentContextMenu; + d->currentContextMenu = 0; + return menu; +#else + return 0; +#endif +} + +#ifndef QT_NO_WHEELEVENT +template<class T> +void QWebPagePrivate::wheelEvent(T *ev) +{ + WebCore::Frame* frame = QWebFramePrivate::core(mainFrame); + if (!frame->view()) + return; + + WebCore::PlatformWheelEvent pev(ev); + bool accepted = frame->eventHandler()->handleWheelEvent(pev); + ev->setAccepted(accepted); +} +#endif // QT_NO_WHEELEVENT + +#ifndef QT_NO_SHORTCUT +QWebPage::WebAction QWebPagePrivate::editorActionForKeyEvent(QKeyEvent* event) +{ + static struct { + QKeySequence::StandardKey standardKey; + QWebPage::WebAction action; + } editorActions[] = { + { QKeySequence::Cut, QWebPage::Cut }, + { QKeySequence::Copy, QWebPage::Copy }, + { QKeySequence::Paste, QWebPage::Paste }, + { QKeySequence::Undo, QWebPage::Undo }, + { QKeySequence::Redo, QWebPage::Redo }, + { QKeySequence::MoveToNextChar, QWebPage::MoveToNextChar }, + { QKeySequence::MoveToPreviousChar, QWebPage::MoveToPreviousChar }, + { QKeySequence::MoveToNextWord, QWebPage::MoveToNextWord }, + { QKeySequence::MoveToPreviousWord, QWebPage::MoveToPreviousWord }, + { QKeySequence::MoveToNextLine, QWebPage::MoveToNextLine }, + { QKeySequence::MoveToPreviousLine, QWebPage::MoveToPreviousLine }, + { QKeySequence::MoveToStartOfLine, QWebPage::MoveToStartOfLine }, + { QKeySequence::MoveToEndOfLine, QWebPage::MoveToEndOfLine }, + { QKeySequence::MoveToStartOfBlock, QWebPage::MoveToStartOfBlock }, + { QKeySequence::MoveToEndOfBlock, QWebPage::MoveToEndOfBlock }, + { QKeySequence::MoveToStartOfDocument, QWebPage::MoveToStartOfDocument }, + { QKeySequence::MoveToEndOfDocument, QWebPage::MoveToEndOfDocument }, + { QKeySequence::SelectNextChar, QWebPage::SelectNextChar }, + { QKeySequence::SelectPreviousChar, QWebPage::SelectPreviousChar }, + { QKeySequence::SelectNextWord, QWebPage::SelectNextWord }, + { QKeySequence::SelectPreviousWord, QWebPage::SelectPreviousWord }, + { QKeySequence::SelectNextLine, QWebPage::SelectNextLine }, + { QKeySequence::SelectPreviousLine, QWebPage::SelectPreviousLine }, + { QKeySequence::SelectStartOfLine, QWebPage::SelectStartOfLine }, + { QKeySequence::SelectEndOfLine, QWebPage::SelectEndOfLine }, + { QKeySequence::SelectStartOfBlock, QWebPage::SelectStartOfBlock }, + { QKeySequence::SelectEndOfBlock, QWebPage::SelectEndOfBlock }, + { QKeySequence::SelectStartOfDocument, QWebPage::SelectStartOfDocument }, + { QKeySequence::SelectEndOfDocument, QWebPage::SelectEndOfDocument }, + { QKeySequence::DeleteStartOfWord, QWebPage::DeleteStartOfWord }, + { QKeySequence::DeleteEndOfWord, QWebPage::DeleteEndOfWord }, + { QKeySequence::InsertParagraphSeparator, QWebPage::InsertParagraphSeparator }, + { QKeySequence::InsertLineSeparator, QWebPage::InsertLineSeparator }, + { QKeySequence::SelectAll, QWebPage::SelectAll }, + { QKeySequence::UnknownKey, QWebPage::NoWebAction } + }; + + for (int i = 0; editorActions[i].standardKey != QKeySequence::UnknownKey; ++i) + if (event == editorActions[i].standardKey) + return editorActions[i].action; + + return QWebPage::NoWebAction; +} +#endif // QT_NO_SHORTCUT + +void QWebPagePrivate::keyPressEvent(QKeyEvent *ev) +{ + bool handled = false; + WebCore::Frame* frame = page->focusController()->focusedOrMainFrame(); + // we forward the key event to WebCore first to handle potential DOM + // defined event handlers and later on end up in EditorClientQt::handleKeyboardEvent + // to trigger editor commands via triggerAction(). + if (!handled) + handled = frame->eventHandler()->keyEvent(ev); + if (!handled) { + handled = true; + if (!handleScrolling(ev, frame)) { + switch (ev->key()) { + case Qt::Key_Back: + q->triggerAction(QWebPage::Back); + break; + case Qt::Key_Forward: + q->triggerAction(QWebPage::Forward); + break; + case Qt::Key_Stop: + q->triggerAction(QWebPage::Stop); + break; + case Qt::Key_Refresh: + q->triggerAction(QWebPage::Reload); + break; + case Qt::Key_Backspace: + if (ev->modifiers() == Qt::ShiftModifier) + q->triggerAction(QWebPage::Forward); + else + q->triggerAction(QWebPage::Back); + break; + default: + handled = false; + break; + } + } + } + + ev->setAccepted(handled); +} + +void QWebPagePrivate::keyReleaseEvent(QKeyEvent *ev) +{ + if (ev->isAutoRepeat()) { + ev->setAccepted(true); + return; + } + + WebCore::Frame* frame = page->focusController()->focusedOrMainFrame(); + bool handled = frame->eventHandler()->keyEvent(ev); + ev->setAccepted(handled); +} + +void QWebPagePrivate::focusInEvent(QFocusEvent*) +{ + FocusController *focusController = page->focusController(); + focusController->setActive(true); + focusController->setFocused(true); + if (!focusController->focusedFrame()) + focusController->setFocusedFrame(QWebFramePrivate::core(mainFrame)); +} + +void QWebPagePrivate::focusOutEvent(QFocusEvent*) +{ + // only set the focused frame inactive so that we stop painting the caret + // and the focus frame. But don't tell the focus controller so that upon + // focusInEvent() we can re-activate the frame. + FocusController *focusController = page->focusController(); + // Call setFocused first so that window.onblur doesn't get called twice + focusController->setFocused(false); + focusController->setActive(false); +} + +template<class T> +void QWebPagePrivate::dragEnterEvent(T* ev) +{ +#ifndef QT_NO_DRAGANDDROP + DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(), + QCursor::pos(), dropActionToDragOp(ev->possibleActions())); + Qt::DropAction action = dragOpToDropAction(page->dragController()->dragEntered(&dragData)); + ev->setDropAction(action); + if (action != Qt::IgnoreAction) + ev->acceptProposedAction(); +#endif +} + +template<class T> +void QWebPagePrivate::dragLeaveEvent(T *ev) +{ +#ifndef QT_NO_DRAGANDDROP + DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone); + page->dragController()->dragExited(&dragData); + ev->accept(); +#endif +} + +template<class T> +void QWebPagePrivate::dragMoveEvent(T *ev) +{ +#ifndef QT_NO_DRAGANDDROP + DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(), + QCursor::pos(), dropActionToDragOp(ev->possibleActions())); + Qt::DropAction action = dragOpToDropAction(page->dragController()->dragUpdated(&dragData)); + ev->setDropAction(action); + if (action != Qt::IgnoreAction) + ev->acceptProposedAction(); +#endif +} + +template<class T> +void QWebPagePrivate::dropEvent(T *ev) +{ +#ifndef QT_NO_DRAGANDDROP + DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(), + QCursor::pos(), dropActionToDragOp(ev->possibleActions())); + if (page->dragController()->performDrag(&dragData)) + ev->acceptProposedAction(); +#endif +} + +void QWebPagePrivate::leaveEvent(QEvent*) +{ + // Fake a mouse move event just outside of the widget, since all + // the interesting mouse-out behavior like invalidating scrollbars + // is handled by the WebKit event handler's mouseMoved function. + QMouseEvent fakeEvent(QEvent::MouseMove, QCursor::pos(), Qt::NoButton, Qt::NoButton, Qt::NoModifier); + mouseMoveEvent(&fakeEvent); +} + +/*! + \property QWebPage::palette + \brief the page's palette + + The base brush of the palette is used to draw the background of the main frame. + + By default, this property contains the application's default palette. +*/ +void QWebPage::setPalette(const QPalette &pal) +{ + d->palette = pal; + if (!d->mainFrame || !d->mainFrame->d->frame->view()) + return; + + QBrush brush = pal.brush(QPalette::Base); + QColor backgroundColor = brush.style() == Qt::SolidPattern ? brush.color() : QColor(); + QWebFramePrivate::core(d->mainFrame)->view()->updateBackgroundRecursively(backgroundColor, !backgroundColor.alpha()); +} + +QPalette QWebPage::palette() const +{ + return d->palette; +} + +void QWebPagePrivate::inputMethodEvent(QInputMethodEvent *ev) +{ + WebCore::Frame *frame = page->focusController()->focusedOrMainFrame(); + WebCore::Editor *editor = frame->editor(); + + if (!editor->canEdit()) { + ev->ignore(); + return; + } + + Node* node = 0; + if (frame->selection()->rootEditableElement()) + node = frame->selection()->rootEditableElement()->shadowAncestorNode(); + + Vector<CompositionUnderline> underlines; + bool hasSelection = false; + + for (int i = 0; i < ev->attributes().size(); ++i) { + const QInputMethodEvent::Attribute& a = ev->attributes().at(i); + switch (a.type) { + case QInputMethodEvent::TextFormat: { + QTextCharFormat textCharFormat = a.value.value<QTextFormat>().toCharFormat(); + QColor qcolor = textCharFormat.underlineColor(); + underlines.append(CompositionUnderline(qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)), Color(makeRGBA(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha())), false)); + break; + } + case QInputMethodEvent::Cursor: { + frame->selection()->setCaretVisible(a.length); //if length is 0 cursor is invisible + if (a.length > 0) { + RenderObject* caretRenderer = frame->selection()->caretRenderer(); + if (caretRenderer) { + QColor qcolor = a.value.value<QColor>(); + caretRenderer->style()->setColor(Color(makeRGBA(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha()))); + } + } + break; + } + case QInputMethodEvent::Selection: { + hasSelection = true; + // A selection in the inputMethodEvent is always reflected in the visible text + if (node) + setSelectionRange(node, qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length))); + + if (!ev->preeditString().isEmpty()) + editor->setComposition(ev->preeditString(), underlines, qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length))); + else { + // If we are in the middle of a composition, an empty pre-edit string and a selection of zero + // cancels the current composition + if (editor->hasComposition() && (a.start + a.length == 0)) + editor->setComposition(QString(), underlines, 0, 0); + } + break; + } + } + } + + if (node && ev->replacementLength() > 0) { + int cursorPos = frame->selection()->extent().offsetInContainerNode(); + int start = cursorPos + ev->replacementStart(); + setSelectionRange(node, start, start + ev->replacementLength()); + // Commit regardless of whether commitString is empty, to get rid of selection. + editor->confirmComposition(ev->commitString()); + } else if (!ev->commitString().isEmpty()) { + if (editor->hasComposition()) + editor->confirmComposition(ev->commitString()); + else + editor->insertText(ev->commitString(), 0); + } else if (!hasSelection && !ev->preeditString().isEmpty()) + editor->setComposition(ev->preeditString(), underlines, 0, 0); + else if (ev->preeditString().isEmpty() && editor->hasComposition()) + editor->confirmComposition(String()); + + ev->accept(); +} + +#ifndef QT_NO_PROPERTIES +typedef struct { + const char* name; + double deferredRepaintDelay; + double initialDeferredRepaintDelayDuringLoading; + double maxDeferredRepaintDelayDuringLoading; + double deferredRepaintDelayIncrementDuringLoading; +} QRepaintThrottlingPreset; + +void QWebPagePrivate::dynamicPropertyChangeEvent(QDynamicPropertyChangeEvent* event) +{ + if (event->propertyName() == "_q_viewMode") { + page->setViewMode(Page::stringToViewMode(q->property("_q_viewMode").toString())); + } else if (event->propertyName() == "_q_HTMLTokenizerChunkSize") { + int chunkSize = q->property("_q_HTMLTokenizerChunkSize").toInt(); + q->handle()->page->setCustomHTMLTokenizerChunkSize(chunkSize); + } else if (event->propertyName() == "_q_HTMLTokenizerTimeDelay") { + double timeDelay = q->property("_q_HTMLTokenizerTimeDelay").toDouble(); + q->handle()->page->setCustomHTMLTokenizerTimeDelay(timeDelay); + } else if (event->propertyName() == "_q_RepaintThrottlingDeferredRepaintDelay") { + double p = q->property("_q_RepaintThrottlingDeferredRepaintDelay").toDouble(); + FrameView::setRepaintThrottlingDeferredRepaintDelay(p); + } else if (event->propertyName() == "_q_RepaintThrottlingnInitialDeferredRepaintDelayDuringLoading") { + double p = q->property("_q_RepaintThrottlingnInitialDeferredRepaintDelayDuringLoading").toDouble(); + FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(p); + } else if (event->propertyName() == "_q_RepaintThrottlingMaxDeferredRepaintDelayDuringLoading") { + double p = q->property("_q_RepaintThrottlingMaxDeferredRepaintDelayDuringLoading").toDouble(); + FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(p); + } else if (event->propertyName() == "_q_RepaintThrottlingDeferredRepaintDelayIncrementDuringLoading") { + double p = q->property("_q_RepaintThrottlingDeferredRepaintDelayIncrementDuringLoading").toDouble(); + FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(p); + } else if (event->propertyName() == "_q_RepaintThrottlingPreset") { + static const QRepaintThrottlingPreset presets[] = { + { "NoThrottling", 0, 0, 0, 0 }, + { "Legacy", 0.025, 0, 2.5, 0.5 }, + { "Minimal", 0.01, 0, 1, 0.2 }, + { "Medium", 0.025, 1, 5, 0.5 }, + { "Heavy", 0.1, 2, 10, 1 } + }; + + QString p = q->property("_q_RepaintThrottlingPreset").toString(); + for(int i = 0; i < sizeof(presets) / sizeof(presets[0]); i++) { + if(p == presets[i].name) { + FrameView::setRepaintThrottlingDeferredRepaintDelay( + presets[i].deferredRepaintDelay); + FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading( + presets[i].initialDeferredRepaintDelayDuringLoading); + FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading( + presets[i].maxDeferredRepaintDelayDuringLoading); + FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading( + presets[i].deferredRepaintDelayIncrementDuringLoading); + break; + } + } + } +#if ENABLE(TILED_BACKING_STORE) + else if (event->propertyName() == "_q_TiledBackingStoreTileSize") { + WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame()); + if (!frame->tiledBackingStore()) + return; + QSize tileSize = q->property("_q_TiledBackingStoreTileSize").toSize(); + frame->tiledBackingStore()->setTileSize(tileSize); + } else if (event->propertyName() == "_q_TiledBackingStoreTileCreationDelay") { + WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame()); + if (!frame->tiledBackingStore()) + return; + int tileCreationDelay = q->property("_q_TiledBackingStoreTileCreationDelay").toInt(); + frame->tiledBackingStore()->setTileCreationDelay(static_cast<double>(tileCreationDelay) / 1000.); + } else if (event->propertyName() == "_q_TiledBackingStoreKeepAreaMultiplier") { + WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame()); + if (!frame->tiledBackingStore()) + return; + FloatSize keepMultiplier; + FloatSize coverMultiplier; + frame->tiledBackingStore()->getKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier); + QSizeF qSize = q->property("_q_TiledBackingStoreKeepAreaMultiplier").toSizeF(); + keepMultiplier = FloatSize(qSize.width(), qSize.height()); + frame->tiledBackingStore()->setKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier); + } else if (event->propertyName() == "_q_TiledBackingStoreCoverAreaMultiplier") { + WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame()); + if (!frame->tiledBackingStore()) + return; + FloatSize keepMultiplier; + FloatSize coverMultiplier; + frame->tiledBackingStore()->getKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier); + QSizeF qSize = q->property("_q_TiledBackingStoreCoverAreaMultiplier").toSizeF(); + coverMultiplier = FloatSize(qSize.width(), qSize.height()); + frame->tiledBackingStore()->setKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier); + } +#endif + else if (event->propertyName() == "_q_webInspectorServerPort") { + InspectorServerQt* inspectorServer = InspectorServerQt::server(); + inspectorServer->listen(inspectorServerPort()); + } +} +#endif + +void QWebPagePrivate::shortcutOverrideEvent(QKeyEvent* event) +{ + WebCore::Frame* frame = page->focusController()->focusedOrMainFrame(); + WebCore::Editor* editor = frame->editor(); + if (editor->canEdit()) { + if (event->modifiers() == Qt::NoModifier + || event->modifiers() == Qt::ShiftModifier + || event->modifiers() == Qt::KeypadModifier) { + if (event->key() < Qt::Key_Escape) { + event->accept(); + } else { + switch (event->key()) { + case Qt::Key_Return: + case Qt::Key_Enter: + case Qt::Key_Delete: + case Qt::Key_Home: + case Qt::Key_End: + case Qt::Key_Backspace: + case Qt::Key_Left: + case Qt::Key_Right: + case Qt::Key_Up: + case Qt::Key_Down: + case Qt::Key_Tab: + event->accept(); + default: + break; + } + } + } +#ifndef QT_NO_SHORTCUT + else if (editorActionForKeyEvent(event) != QWebPage::NoWebAction) + event->accept(); +#endif + } +} + +bool QWebPagePrivate::handleScrolling(QKeyEvent *ev, Frame *frame) +{ + ScrollDirection direction; + ScrollGranularity granularity; + +#ifndef QT_NO_SHORTCUT + if (ev == QKeySequence::MoveToNextPage + || (ev->key() == Qt::Key_Space && !(ev->modifiers() & Qt::ShiftModifier))) { + granularity = ScrollByPage; + direction = ScrollDown; + } else if (ev == QKeySequence::MoveToPreviousPage + || ((ev->key() == Qt::Key_Space) && (ev->modifiers() & Qt::ShiftModifier))) { + granularity = ScrollByPage; + direction = ScrollUp; + } else +#endif // QT_NO_SHORTCUT + if ((ev->key() == Qt::Key_Up && ev->modifiers() & Qt::ControlModifier) + || ev->key() == Qt::Key_Home) { + granularity = ScrollByDocument; + direction = ScrollUp; + } else if ((ev->key() == Qt::Key_Down && ev->modifiers() & Qt::ControlModifier) + || ev->key() == Qt::Key_End) { + granularity = ScrollByDocument; + direction = ScrollDown; + } else { + switch (ev->key()) { + case Qt::Key_Up: + granularity = ScrollByLine; + direction = ScrollUp; + break; + case Qt::Key_Down: + granularity = ScrollByLine; + direction = ScrollDown; + break; + case Qt::Key_Left: + granularity = ScrollByLine; + direction = ScrollLeft; + break; + case Qt::Key_Right: + granularity = ScrollByLine; + direction = ScrollRight; + break; + default: + return false; + } + } + + return frame->eventHandler()->scrollRecursively(direction, granularity); +} + +void QWebPagePrivate::adjustPointForClicking(QMouseEvent*) +{ + notImplemented(); +} + +#if !defined(QT_NO_GRAPHICSVIEW) +void QWebPagePrivate::adjustPointForClicking(QGraphicsSceneMouseEvent* ev) +{ + QtPlatformPlugin platformPlugin; + QWebTouchModifier* touchModifier = platformPlugin.createTouchModifier(); + if (!touchModifier) + return; + + unsigned topPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Up); + unsigned rightPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Right); + unsigned bottomPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Down); + unsigned leftPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Left); + + delete touchModifier; + touchModifier = 0; + + if (!topPadding && !rightPadding && !bottomPadding && !leftPadding) + return; + + Document* startingDocument = page->mainFrame()->document(); + if (!startingDocument) + return; + + IntPoint originalPoint(QPointF(ev->pos()).toPoint()); + TouchAdjuster touchAdjuster(topPadding, rightPadding, bottomPadding, leftPadding); + IntPoint adjustedPoint = touchAdjuster.findCandidatePointForTouch(originalPoint, startingDocument); + if (adjustedPoint == IntPoint::zero()) + return; + + ev->setPos(QPointF(adjustedPoint)); +} +#endif + +bool QWebPagePrivate::touchEvent(QTouchEvent* event) +{ +#if ENABLE(TOUCH_EVENTS) + WebCore::Frame* frame = QWebFramePrivate::core(mainFrame); + if (!frame->view()) + return false; + + // Always accept the QTouchEvent so that we'll receive also TouchUpdate and TouchEnd events + event->setAccepted(true); + + // Return whether the default action was cancelled in the JS event handler + return frame->eventHandler()->handleTouchEvent(PlatformTouchEvent(event)); +#else + event->ignore(); + return false; +#endif +} + +/*! + This method is used by the input method to query a set of properties of the page + to be able to support complex input method operations as support for surrounding + text and reconversions. + + \a property specifies which property is queried. + + \sa QWidget::inputMethodEvent(), QInputMethodEvent, QInputContext +*/ +QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const +{ + Frame* frame = d->page->focusController()->focusedFrame(); + if (!frame) + return QVariant(); + + WebCore::Editor* editor = frame->editor(); + + RenderObject* renderer = 0; + RenderTextControl* renderTextControl = 0; + + if (frame->selection()->rootEditableElement()) + renderer = frame->selection()->rootEditableElement()->shadowAncestorNode()->renderer(); + + if (renderer && renderer->isTextControl()) + renderTextControl = toRenderTextControl(renderer); + + switch (property) { + case Qt::ImMicroFocus: { + WebCore::FrameView* view = frame->view(); + if (view && view->needsLayout()) { + // We can't access absoluteCaretBounds() while the view needs to layout. + return QVariant(); + } + return QVariant(view->contentsToWindow(frame->selection()->absoluteCaretBounds())); + } + case Qt::ImFont: { + if (renderTextControl) { + RenderStyle* renderStyle = renderTextControl->style(); + return QVariant(QFont(renderStyle->font().font())); + } + return QVariant(QFont()); + } + case Qt::ImCursorPosition: { + if (editor->hasComposition()) + return QVariant(frame->selection()->end().offsetInContainerNode()); + return QVariant(frame->selection()->extent().offsetInContainerNode()); + } + case Qt::ImSurroundingText: { + if (renderTextControl) { + QString text = renderTextControl->text(); + RefPtr<Range> range = editor->compositionRange(); + if (range) + text.remove(range->startPosition().offsetInContainerNode(), TextIterator::rangeLength(range.get())); + return QVariant(text); + } + return QVariant(); + } + case Qt::ImCurrentSelection: { + if (!editor->hasComposition() && renderTextControl) { + int start = frame->selection()->start().offsetInContainerNode(); + int end = frame->selection()->end().offsetInContainerNode(); + if (end > start) + return QVariant(QString(renderTextControl->text()).mid(start, end - start)); + } + return QVariant(); + + } + case Qt::ImAnchorPosition: { + if (editor->hasComposition()) + return QVariant(frame->selection()->start().offsetInContainerNode()); + return QVariant(frame->selection()->base().offsetInContainerNode()); + } + case Qt::ImMaximumTextLength: { + if (frame->selection()->isContentEditable()) { + if (frame->document() && frame->document()->focusedNode()) { + if (frame->document()->focusedNode()->hasTagName(HTMLNames::inputTag)) { + HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(frame->document()->focusedNode()); + return QVariant(inputElement->maxLength()); + } + } + return QVariant(InputElement::s_maximumLength); + } + return QVariant(0); + } + default: + return QVariant(); + } +} + +/*! + \internal +*/ +void QWebPagePrivate::setInspector(QWebInspector* insp) +{ + if (inspector) + inspector->d->setFrontend(0); + + if (inspectorIsInternalOnly) { + QWebInspector* inspToDelete = inspector; + inspector = 0; + inspectorIsInternalOnly = false; + delete inspToDelete; // Delete after to prevent infinite recursion + } + + inspector = insp; + + // Give inspector frontend web view if previously created + if (inspector && inspectorFrontend) + inspector->d->setFrontend(inspectorFrontend); +} + +/*! + \internal + Returns the inspector and creates it if it wasn't created yet. + The instance created here will not be available through QWebPage's API. +*/ +QWebInspector* QWebPagePrivate::getOrCreateInspector() +{ +#if ENABLE(INSPECTOR) + if (!inspector) { + QWebInspector* insp = new QWebInspector; + insp->setPage(q); + inspectorIsInternalOnly = true; + + Q_ASSERT(inspector); // Associated through QWebInspector::setPage(q) + } +#endif + return inspector; +} + +/*! \internal */ +InspectorController* QWebPagePrivate::inspectorController() +{ +#if ENABLE(INSPECTOR) + return page->inspectorController(); +#else + return 0; +#endif +} + +quint16 QWebPagePrivate::inspectorServerPort() +{ +#if ENABLE(INSPECTOR) && !defined(QT_NO_PROPERTIES) + if (q && q->property("_q_webInspectorServerPort").isValid()) + return q->property("_q_webInspectorServerPort").toInt(); +#endif + return 0; +} + +static bool hasMouseListener(Element* element) +{ + ASSERT(element); + return element->hasEventListeners(eventNames().clickEvent) + || element->hasEventListeners(eventNames().mousedownEvent) + || element->hasEventListeners(eventNames().mouseupEvent); +} + +static bool isClickableElement(Element* element, RefPtr<NodeList> list) +{ + ASSERT(element); + bool isClickable = hasMouseListener(element); + if (!isClickable && list) { + Element* parent = element->parentElement(); + unsigned count = list->length(); + for (unsigned i = 0; i < count && parent; i++) { + if (list->item(i) != parent) + continue; + + isClickable = hasMouseListener(parent); + if (isClickable) + break; + + parent = parent->parentElement(); + } + } + + ExceptionCode ec = 0; + return isClickable + || element->webkitMatchesSelector("a,*:link,*:visited,*[role=button],button,input,select,label", ec) + || computedStyle(element)->getPropertyValue(cssPropertyID("cursor")) == "pointer"; +} + +static bool isValidFrameOwner(Element* element) +{ + ASSERT(element); + return element->isFrameOwnerElement() && static_cast<HTMLFrameOwnerElement*>(element)->contentFrame(); +} + +static Element* nodeToElement(Node* node) +{ + if (node && node->isElementNode()) + return static_cast<Element*>(node); + return 0; +} + +QWebPagePrivate::TouchAdjuster::TouchAdjuster(unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding) + : m_topPadding(topPadding) + , m_rightPadding(rightPadding) + , m_bottomPadding(bottomPadding) + , m_leftPadding(leftPadding) +{ +} + +IntPoint QWebPagePrivate::TouchAdjuster::findCandidatePointForTouch(const IntPoint& touchPoint, Document* document) const +{ + if (!document) + return IntPoint(); + + int x = touchPoint.x(); + int y = touchPoint.y(); + + RefPtr<NodeList> intersectedNodes = document->nodesFromRect(x, y, m_topPadding, m_rightPadding, m_bottomPadding, m_leftPadding, false); + if (!intersectedNodes) + return IntPoint(); + + Element* closestClickableElement = 0; + IntRect largestIntersectionRect; + FrameView* view = document->frame()->view(); + + // Touch rect in contents coordinates. + IntRect touchRect(HitTestResult::rectForPoint(view->windowToContents(IntPoint(x, y)), m_topPadding, m_rightPadding, m_bottomPadding, m_leftPadding)); + + // Iterate over the list of nodes hit looking for the one whose bounding area + // has largest intersection with the touch area (point + padding). + for (unsigned i = 0; i < intersectedNodes->length(); i++) { + Node* currentNode = intersectedNodes->item(i); + + Element* currentElement = nodeToElement(currentNode); + if (!currentElement || (!isClickableElement(currentElement, 0) && !isValidFrameOwner(currentElement))) + continue; + + IntRect currentElementBoundingRect = currentElement->getRect(); + currentElementBoundingRect.intersect(touchRect); + + if (currentElementBoundingRect.isEmpty()) + continue; + + int currentIntersectionRectArea = currentElementBoundingRect.width() * currentElementBoundingRect.height(); + int largestIntersectionRectArea = largestIntersectionRect.width() * largestIntersectionRect.height(); + if (currentIntersectionRectArea > largestIntersectionRectArea) { + closestClickableElement = currentElement; + largestIntersectionRect = currentElementBoundingRect; + } + } + + if (largestIntersectionRect.isEmpty()) + return IntPoint(); + + // Handle the case when user taps a inner frame. It is done in three steps: + // 1) Transform the original touch point to the inner document coordinates; + // 1) Call nodesFromRect for the inner document in case; + // 3) Re-add the inner frame offset (location) before passing the new clicking + // position to WebCore. + if (closestClickableElement->isFrameOwnerElement()) { + // Adjust client coordinates' origin to be top left of inner frame viewport. + PassRefPtr<ClientRect> rect = closestClickableElement->getBoundingClientRect(); + IntPoint newTouchPoint = touchPoint; + IntSize offset = IntSize(rect->left(), rect->top()); + newTouchPoint -= offset; + + HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(closestClickableElement); + Document* childDocument = owner->contentFrame()->document(); + return findCandidatePointForTouch(newTouchPoint, childDocument); + } + return view->contentsToWindow(largestIntersectionRect).center(); +} + +/*! + \enum QWebPage::FindFlag + + This enum describes the options available to the findText() function. The options + can be OR-ed together from the following list: + + \value FindBackward Searches backwards instead of forwards. + \value FindCaseSensitively By default findText() works case insensitive. Specifying this option + changes the behaviour to a case sensitive find operation. + \value FindWrapsAroundDocument Makes findText() restart from the beginning of the document if the end + was reached and the text was not found. + \value HighlightAllOccurrences Highlights all existing occurrences of a specific string. +*/ + +/*! + \enum QWebPage::LinkDelegationPolicy + + This enum defines the delegation policies a webpage can have when activating links and emitting + the linkClicked() signal. + + \value DontDelegateLinks No links are delegated. Instead, QWebPage tries to handle them all. + \value DelegateExternalLinks When activating links that point to documents not stored on the + local filesystem or an equivalent - such as the Qt resource system - then linkClicked() is emitted. + \value DelegateAllLinks Whenever a link is activated the linkClicked() signal is emitted. + + \sa QWebPage::linkDelegationPolicy +*/ + +/*! + \enum QWebPage::NavigationType + + This enum describes the types of navigation available when browsing through hyperlinked + documents. + + \value NavigationTypeLinkClicked The user clicked on a link or pressed return on a focused link. + \value NavigationTypeFormSubmitted The user activated a submit button for an HTML form. + \value NavigationTypeBackOrForward Navigation to a previously shown document in the back or forward history is requested. + \value NavigationTypeReload The user activated the reload action. + \value NavigationTypeFormResubmitted An HTML form was submitted a second time. + \value NavigationTypeOther A navigation to another document using a method not listed above. + + \sa acceptNavigationRequest() +*/ + +/*! + \enum QWebPage::WebAction + + This enum describes the types of action which can be performed on the web page. + + Actions only have an effect when they are applicable. The availability of + actions can be be determined by checking \l{QAction::}{isEnabled()} on the + action returned by action(). + + One method of enabling the text editing, cursor movement, and text selection actions + is by setting \l contentEditable to true. + + \value NoWebAction No action is triggered. + \value OpenLink Open the current link. + \value OpenLinkInNewWindow Open the current link in a new window. + \value OpenFrameInNewWindow Replicate the current frame in a new window. + \value DownloadLinkToDisk Download the current link to the disk. + \value CopyLinkToClipboard Copy the current link to the clipboard. + \value OpenImageInNewWindow Open the highlighted image in a new window. + \value DownloadImageToDisk Download the highlighted image to the disk. + \value CopyImageToClipboard Copy the highlighted image to the clipboard. + \value Back Navigate back in the history of navigated links. + \value Forward Navigate forward in the history of navigated links. + \value Stop Stop loading the current page. + \value StopScheduledPageRefresh Stop all pending page refresh/redirect requests. + \value Reload Reload the current page. + \value ReloadAndBypassCache Reload the current page, but do not use any local cache. (Added in Qt 4.6) + \value Cut Cut the content currently selected into the clipboard. + \value Copy Copy the content currently selected into the clipboard. + \value Paste Paste content from the clipboard. + \value Undo Undo the last editing action. + \value Redo Redo the last editing action. + \value MoveToNextChar Move the cursor to the next character. + \value MoveToPreviousChar Move the cursor to the previous character. + \value MoveToNextWord Move the cursor to the next word. + \value MoveToPreviousWord Move the cursor to the previous word. + \value MoveToNextLine Move the cursor to the next line. + \value MoveToPreviousLine Move the cursor to the previous line. + \value MoveToStartOfLine Move the cursor to the start of the line. + \value MoveToEndOfLine Move the cursor to the end of the line. + \value MoveToStartOfBlock Move the cursor to the start of the block. + \value MoveToEndOfBlock Move the cursor to the end of the block. + \value MoveToStartOfDocument Move the cursor to the start of the document. + \value MoveToEndOfDocument Move the cursor to the end of the document. + \value SelectNextChar Select to the next character. + \value SelectPreviousChar Select to the previous character. + \value SelectNextWord Select to the next word. + \value SelectPreviousWord Select to the previous word. + \value SelectNextLine Select to the next line. + \value SelectPreviousLine Select to the previous line. + \value SelectStartOfLine Select to the start of the line. + \value SelectEndOfLine Select to the end of the line. + \value SelectStartOfBlock Select to the start of the block. + \value SelectEndOfBlock Select to the end of the block. + \value SelectStartOfDocument Select to the start of the document. + \value SelectEndOfDocument Select to the end of the document. + \value DeleteStartOfWord Delete to the start of the word. + \value DeleteEndOfWord Delete to the end of the word. + \value SetTextDirectionDefault Set the text direction to the default direction. + \value SetTextDirectionLeftToRight Set the text direction to left-to-right. + \value SetTextDirectionRightToLeft Set the text direction to right-to-left. + \value ToggleBold Toggle the formatting between bold and normal weight. + \value ToggleItalic Toggle the formatting between italic and normal style. + \value ToggleUnderline Toggle underlining. + \value InspectElement Show the Web Inspector with the currently highlighted HTML element. + \value InsertParagraphSeparator Insert a new paragraph. + \value InsertLineSeparator Insert a new line. + \value SelectAll Selects all content. + \value PasteAndMatchStyle Paste content from the clipboard with current style. + \value RemoveFormat Removes formatting and style. + \value ToggleStrikethrough Toggle the formatting between strikethrough and normal style. + \value ToggleSubscript Toggle the formatting between subscript and baseline. + \value ToggleSuperscript Toggle the formatting between supercript and baseline. + \value InsertUnorderedList Toggles the selection between an ordered list and a normal block. + \value InsertOrderedList Toggles the selection between an ordered list and a normal block. + \value Indent Increases the indentation of the currently selected format block by one increment. + \value Outdent Decreases the indentation of the currently selected format block by one increment. + \value AlignCenter Applies center alignment to content. + \value AlignJustified Applies full justification to content. + \value AlignLeft Applies left justification to content. + \value AlignRight Applies right justification to content. + + + \omitvalue WebActionCount + +*/ + +/*! + \enum QWebPage::WebWindowType + + This enum describes the types of window that can be created by the createWindow() function. + + \value WebBrowserWindow The window is a regular web browser window. + \value WebModalDialog The window acts as modal dialog. +*/ + + +/*! + \class QWebPage::ViewportAttributes + \since 4.7 + \brief The QWebPage::ViewportAttributes class describes hints that can be applied to a viewport. + + QWebPage::ViewportAttributes provides a description of a viewport, such as viewport geometry, + initial scale factor with limits, plus information about whether a user should be able + to scale the contents in the viewport or not, ie. by zooming. + + ViewportAttributes can be set by a web author using the viewport meta tag extension, documented + at \l{http://developer.apple.com/safari/library/documentation/appleapplications/reference/safariwebcontent/usingtheviewport/usingtheviewport.html}{Safari Reference Library: Using the Viewport Meta Tag}. + + All values might not be set, as such when dealing with the hints, the developer needs to + check whether the values are valid. Negative values denote an invalid qreal value. + + \inmodule QtWebKit +*/ + +/*! + Constructs an empty QWebPage::ViewportAttributes. +*/ +QWebPage::ViewportAttributes::ViewportAttributes() + : d(0) + , m_initialScaleFactor(-1.0) + , m_minimumScaleFactor(-1.0) + , m_maximumScaleFactor(-1.0) + , m_devicePixelRatio(-1.0) + , m_isUserScalable(true) + , m_isValid(false) +{ + +} + +/*! + Constructs a QWebPage::ViewportAttributes which is a copy from \a other . +*/ +QWebPage::ViewportAttributes::ViewportAttributes(const QWebPage::ViewportAttributes& other) + : d(other.d) + , m_initialScaleFactor(other.m_initialScaleFactor) + , m_minimumScaleFactor(other.m_minimumScaleFactor) + , m_maximumScaleFactor(other.m_maximumScaleFactor) + , m_devicePixelRatio(other.m_devicePixelRatio) + , m_isUserScalable(other.m_isUserScalable) + , m_isValid(other.m_isValid) + , m_size(other.m_size) +{ + +} + +/*! + Destroys the QWebPage::ViewportAttributes. +*/ +QWebPage::ViewportAttributes::~ViewportAttributes() +{ + +} + +/*! + Assigns the given QWebPage::ViewportAttributes to this viewport hints and returns a + reference to this. +*/ +QWebPage::ViewportAttributes& QWebPage::ViewportAttributes::operator=(const QWebPage::ViewportAttributes& other) +{ + if (this != &other) { + d = other.d; + m_initialScaleFactor = other.m_initialScaleFactor; + m_minimumScaleFactor = other.m_minimumScaleFactor; + m_maximumScaleFactor = other.m_maximumScaleFactor; + m_isUserScalable = other.m_isUserScalable; + m_isValid = other.m_isValid; + m_size = other.m_size; + } + + return *this; +} + +/*! \fn inline bool QWebPage::ViewportAttributes::isValid() const + Returns whether this is a valid ViewportAttributes or not. + + An invalid ViewportAttributes will have an empty QSize, negative values for scale factors and + true for the boolean isUserScalable. +*/ + +/*! \fn inline QSize QWebPage::ViewportAttributes::size() const + Returns the size of the viewport. +*/ + +/*! \fn inline qreal QWebPage::ViewportAttributes::initialScaleFactor() const + Returns the initial scale of the viewport as a multiplier. +*/ + +/*! \fn inline qreal QWebPage::ViewportAttributes::minimumScaleFactor() const + Returns the minimum scale value of the viewport as a multiplier. +*/ + +/*! \fn inline qreal QWebPage::ViewportAttributes::maximumScaleFactor() const + Returns the maximum scale value of the viewport as a multiplier. +*/ + +/*! \fn inline bool QWebPage::ViewportAttributes::isUserScalable() const + Determines whether or not the scale can be modified by the user. +*/ + + +/*! + \class QWebPage + \since 4.4 + \brief The QWebPage class provides an object to view and edit web documents. + + \inmodule QtWebKit + + QWebPage holds a main frame responsible for web content, settings, the history + of navigated links and actions. This class can be used, together with QWebFrame, + to provide functionality like QWebView in a widget-less environment. + + QWebPage's API is very similar to QWebView, as you are still provided with + common functions like action() (known as + \l{QWebView::pageAction()}{pageAction}() in QWebView), triggerAction(), + findText() and settings(). More QWebView-like functions can be found in the + main frame of QWebPage, obtained via the mainFrame() function. For example, + the \l{QWebFrame::load()}{load}(), \l{QWebFrame::setUrl()}{setUrl}() and + \l{QWebFrame::setHtml()}{setHtml}() functions for QWebPage can be accessed + using QWebFrame. + + The loadStarted() signal is emitted when the page begins to load.The + loadProgress() signal, on the other hand, is emitted whenever an element + of the web page completes loading, such as an embedded image, a script, + etc. Finally, the loadFinished() signal is emitted when the page has + loaded completely. Its argument, either true or false, indicates whether + or not the load operation succeeded. + + \section1 Using QWebPage in a Widget-less Environment + + Before you begin painting a QWebPage object, you need to set the size of + the viewport by calling setViewportSize(). Then, you invoke the main + frame's render function (QWebFrame::render()). An example of this + is shown in the code snippet below. + + Suppose we have a \c Thumbnail class as follows: + + \snippet webkitsnippets/webpage/main.cpp 0 + + The \c Thumbnail's constructor takes in a \a url. We connect our QWebPage + object's \l{QWebPage::}{loadFinished()} signal to our private slot, + \c render(). + + \snippet webkitsnippets/webpage/main.cpp 1 + + The \c render() function shows how we can paint a thumbnail using a + QWebPage object. + + \snippet webkitsnippets/webpage/main.cpp 2 + + We begin by setting the \l{QWebPage::viewportSize()}{viewportSize} and + then we instantiate a QImage object, \c image, with the same size as our + \l{QWebPage::viewportSize()}{viewportSize}. This image is then sent + as a parameter to \c painter. Next, we render the contents of the main + frame and its subframes into \c painter. Finally, we save the scaled image. + + \sa QWebFrame +*/ + +/*! + Constructs an empty QWebPage with parent \a parent. +*/ +QWebPage::QWebPage(QObject *parent) + : QObject(parent) + , d(new QWebPagePrivate(this)) +{ + setView(qobject_cast<QWidget*>(parent)); + + connect(this, SIGNAL(loadProgress(int)), this, SLOT(_q_onLoadProgressChanged(int))); +#ifndef NDEBUG + connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(_q_cleanupLeakMessages())); +#endif +} + +/*! + Destroys the web page. +*/ +QWebPage::~QWebPage() +{ + d->createMainFrame(); + FrameLoader *loader = d->mainFrame->d->frame->loader(); + if (loader) + loader->detachFromParent(); + delete d; +} + +/*! + Returns the main frame of the page. + + The main frame provides access to the hierarchy of sub-frames and is also needed if you + want to explicitly render a web page into a given painter. + + \sa currentFrame() +*/ +QWebFrame *QWebPage::mainFrame() const +{ + d->createMainFrame(); + return d->mainFrame; +} + +/*! + Returns the frame currently active. + + \sa mainFrame(), frameCreated() +*/ +QWebFrame *QWebPage::currentFrame() const +{ + d->createMainFrame(); + WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame(); + return qobject_cast<QWebFrame*>(frame->loader()->networkingContext()->originatingObject()); +} + + +/*! + \since 4.6 + + Returns the frame at the given point \a pos, or 0 if there is no frame at + that position. + + \sa mainFrame(), currentFrame() +*/ +QWebFrame* QWebPage::frameAt(const QPoint& pos) const +{ + QWebFrame* webFrame = mainFrame(); + if (!webFrame->geometry().contains(pos)) + return 0; + QWebHitTestResult hitTestResult = webFrame->hitTestContent(pos); + return hitTestResult.frame(); +} + +/*! + Returns a pointer to the view's history of navigated web pages. +*/ +QWebHistory *QWebPage::history() const +{ + d->createMainFrame(); + return &d->history; +} + +/*! + Sets the \a view that is associated with the web page. + + \sa view() +*/ +void QWebPage::setView(QWidget* view) +{ + if (this->view() == view) + return; + + d->view = view; + setViewportSize(view ? view->size() : QSize(0, 0)); + + // If we have no client, we install a special client delegating + // the responsibility to the QWidget. This is the code path + // handling a.o. the "legacy" QWebView. + // + // If such a special delegate already exist, we substitute the view. + + if (d->client) { + if (d->client->isQWidgetClient()) + static_cast<PageClientQWidget*>(d->client.get())->view = view; + return; + } + + if (view) + d->client = new PageClientQWidget(view, this); +} + +/*! + Returns the view widget that is associated with the web page. + + \sa setView() +*/ +QWidget *QWebPage::view() const +{ + return d->view.data(); +} + +/*! + This function is called whenever a JavaScript program tries to print a \a message to the web browser's console. + + For example in case of evaluation errors the source URL may be provided in \a sourceID as well as the \a lineNumber. + + The default implementation prints nothing. +*/ +void QWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID) +{ + Q_UNUSED(sourceID) + + // Catch plugin logDestroy message for LayoutTests/plugins/open-and-close-window-with-plugin.html + // At this point DRT's WebPage has already been destroyed + if (QWebPagePrivate::drtRun) { + if (message == "PLUGIN: NPP_Destroy") + fprintf (stdout, "CONSOLE MESSAGE: line %d: %s\n", lineNumber, message.toUtf8().constData()); + } +} + +/*! + This function is called whenever a JavaScript program running inside \a frame calls the alert() function with + the message \a msg. + + The default implementation shows the message, \a msg, with QMessageBox::information. +*/ +void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg) +{ + Q_UNUSED(frame) +#ifndef QT_NO_MESSAGEBOX + QWidget* parent = (d->client) ? d->client->ownerWidget() : 0; + QMessageBox::information(parent, tr("JavaScript Alert - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QMessageBox::Ok); +#endif +} + +/*! + This function is called whenever a JavaScript program running inside \a frame calls the confirm() function + with the message, \a msg. Returns true if the user confirms the message; otherwise returns false. + + The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons. +*/ +bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg) +{ + Q_UNUSED(frame) +#ifdef QT_NO_MESSAGEBOX + return true; +#else + QWidget* parent = (d->client) ? d->client->ownerWidget() : 0; + return QMessageBox::Yes == QMessageBox::information(parent, tr("JavaScript Confirm - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QMessageBox::Yes, QMessageBox::No); +#endif +} + +/*! + This function is called whenever a JavaScript program running inside \a frame tries to prompt the user for input. + The program may provide an optional message, \a msg, as well as a default value for the input in \a defaultValue. + + If the prompt was cancelled by the user the implementation should return false; otherwise the + result should be written to \a result and true should be returned. If the prompt was not cancelled by the + user, the implementation should return true and the result string must not be null. + + The default implementation uses QInputDialog::getText(). +*/ +bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result) +{ + Q_UNUSED(frame) + bool ok = false; +#ifndef QT_NO_INPUTDIALOG + QWidget* parent = (d->client) ? d->client->ownerWidget() : 0; + QString x = QInputDialog::getText(parent, tr("JavaScript Prompt - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QLineEdit::Normal, defaultValue, &ok); + if (ok && result) + *result = x; +#endif + return ok; +} + +/*! + \fn bool QWebPage::shouldInterruptJavaScript() + \since 4.6 + This function is called when a JavaScript program is running for a long period of time. + + If the user wanted to stop the JavaScript the implementation should return true; otherwise false. + + The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons. + + \warning Because of binary compatibility constraints, this function is not virtual. If you want to + provide your own implementation in a QWebPage subclass, reimplement the shouldInterruptJavaScript() + slot in your subclass instead. QtWebKit will dynamically detect the slot and call it. +*/ +bool QWebPage::shouldInterruptJavaScript() +{ +#ifdef QT_NO_MESSAGEBOX + return false; +#else + QWidget* parent = (d->client) ? d->client->ownerWidget() : 0; + return QMessageBox::Yes == QMessageBox::information(parent, tr("JavaScript Problem - %1").arg(mainFrame()->url().host()), tr("The script on this page appears to have a problem. Do you want to stop the script?"), QMessageBox::Yes, QMessageBox::No); +#endif +} + +void QWebPage::setFeaturePermission(QWebFrame* frame, Feature feature, PermissionPolicy policy) +{ + switch (feature) { + case Notifications: +#if ENABLE(NOTIFICATIONS) + if (policy == PermissionGrantedByUser) + NotificationPresenterClientQt::notificationPresenter()->allowNotificationForFrame(frame->d->frame); +#endif + break; + case Geolocation: +#if ENABLE(GEOLOCATION) + GeolocationPermissionClientQt::geolocationPermissionClient()->setPermission(frame, policy); +#endif + break; + + default: + break; + } +} + +/*! + This function is called whenever WebKit wants to create a new window of the given \a type, for + example when a JavaScript program requests to open a document in a new window. + + If the new window can be created, the new window's QWebPage is returned; otherwise a null pointer is returned. + + If the view associated with the web page is a QWebView object, then the default implementation forwards + the request to QWebView's createWindow() function; otherwise it returns a null pointer. + + If \a type is WebModalDialog, the application must call setWindowModality(Qt::ApplicationModal) on the new window. + + \note In the cases when the window creation is being triggered by JavaScript, apart from + reimplementing this method application must also set the JavaScriptCanOpenWindows attribute + of QWebSettings to true in order for it to get called. + + \sa acceptNavigationRequest(), QWebView::createWindow() +*/ +QWebPage *QWebPage::createWindow(WebWindowType type) +{ + QWebView *webView = qobject_cast<QWebView*>(view()); + if (webView) { + QWebView *newView = webView->createWindow(type); + if (newView) + return newView->page(); + } + return 0; +} + +/*! + This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin". It is + called regardless of the value of QWebSettings::PluginsEnabled. The \a classid, \a url, \a paramNames and \a paramValues + correspond to the HTML object element attributes and child elements to configure the embeddable object. +*/ +QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues) +{ + Q_UNUSED(classid) + Q_UNUSED(url) + Q_UNUSED(paramNames) + Q_UNUSED(paramValues) + return 0; +} + +static void extractContentTypeFromHash(const HashSet<String>& types, QStringList* list) +{ + if (!list) + return; + + HashSet<String>::const_iterator endIt = types.end(); + for (HashSet<String>::const_iterator it = types.begin(); it != endIt; ++it) + *list << *it; +} + +static void extractContentTypeFromPluginVector(const Vector<PluginPackage*>& plugins, QStringList* list) +{ + if (!list) + return; + + for (unsigned int i = 0; i < plugins.size(); ++i) { + MIMEToDescriptionsMap::const_iterator map_it = plugins[i]->mimeToDescriptions().begin(); + MIMEToDescriptionsMap::const_iterator map_end = plugins[i]->mimeToDescriptions().end(); + for (; map_it != map_end; ++map_it) + *list << map_it->first; + } +} + +/*! + * Returns the list of all content types supported by QWebPage. + */ +QStringList QWebPage::supportedContentTypes() const +{ + QStringList mimeTypes; + + extractContentTypeFromHash(MIMETypeRegistry::getSupportedImageMIMETypes(), &mimeTypes); + extractContentTypeFromHash(MIMETypeRegistry::getSupportedNonImageMIMETypes(), &mimeTypes); + if (d->page->settings() && d->page->settings()->arePluginsEnabled()) + extractContentTypeFromPluginVector(PluginDatabase::installedPlugins()->plugins(), &mimeTypes); + + return mimeTypes; +} + +/*! + * Returns true if QWebPage can handle the given \a mimeType; otherwise, returns false. + */ +bool QWebPage::supportsContentType(const QString& mimeType) const +{ + const String type = mimeType.toLower(); + if (MIMETypeRegistry::isSupportedImageMIMEType(type)) + return true; + + if (MIMETypeRegistry::isSupportedNonImageMIMEType(type)) + return true; + + if (d->page->settings() && d->page->settings()->arePluginsEnabled() + && PluginDatabase::installedPlugins()->isMIMETypeRegistered(type)) + return true; + + return false; +} + +static WebCore::FrameLoadRequest frameLoadRequest(const QUrl &url, WebCore::Frame *frame) +{ + return WebCore::FrameLoadRequest(frame->document()->securityOrigin(), + WebCore::ResourceRequest(url, frame->loader()->outgoingReferrer())); +} + +static void openNewWindow(const QUrl& url, WebCore::Frame* frame) +{ + if (Page* oldPage = frame->page()) { + WindowFeatures features; + NavigationAction action; + FrameLoadRequest request = frameLoadRequest(url, frame); + if (Page* newPage = oldPage->chrome()->createWindow(frame, request, features, action)) { + newPage->mainFrame()->loader()->loadFrameRequest(request, false, false, 0, 0, SendReferrer); + newPage->chrome()->show(); + } + } +} + +static void collectChildFrames(QWebFrame* frame, QList<QWebFrame*>& list) +{ + list << frame->childFrames(); + QListIterator<QWebFrame*> it(frame->childFrames()); + while (it.hasNext()) { + collectChildFrames(it.next(), list); + } +} + +/*! + This function can be called to trigger the specified \a action. + It is also called by QtWebKit if the user triggers the action, for example + through a context menu item. + + If \a action is a checkable action then \a checked specified whether the action + is toggled or not. + + \sa action() +*/ +void QWebPage::triggerAction(WebAction action, bool) +{ + WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame(); + if (!frame) + return; + WebCore::Editor *editor = frame->editor(); + const char *command = 0; + + switch (action) { + case OpenLink: + if (QWebFrame *targetFrame = d->hitTestResult.linkTargetFrame()) { + WTF::RefPtr<WebCore::Frame> wcFrame = targetFrame->d->frame; + targetFrame->d->frame->loader()->loadFrameRequest(frameLoadRequest(d->hitTestResult.linkUrl(), wcFrame.get()), + /*lockHistory*/ false, /*lockBackForwardList*/ false, /*event*/ 0, + /*FormState*/ 0, SendReferrer); + break; + } + // fall through + case OpenLinkInNewWindow: + openNewWindow(d->hitTestResult.linkUrl(), frame); + break; + case OpenFrameInNewWindow: { + KURL url = frame->loader()->documentLoader()->unreachableURL(); + if (url.isEmpty()) + url = frame->loader()->documentLoader()->url(); + openNewWindow(url, frame); + break; + } + case CopyLinkToClipboard: { +#if defined(Q_WS_X11) + bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode(); + Pasteboard::generalPasteboard()->setSelectionMode(true); + editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText()); + Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode); +#endif + editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText()); + break; + } + case OpenImageInNewWindow: + openNewWindow(d->hitTestResult.imageUrl(), frame); + break; + case DownloadImageToDisk: + frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.imageUrl(), frame->loader()->outgoingReferrer())); + break; + case DownloadLinkToDisk: + frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.linkUrl(), frame->loader()->outgoingReferrer())); + break; +#ifndef QT_NO_CLIPBOARD + case CopyImageToClipboard: + QApplication::clipboard()->setPixmap(d->hitTestResult.pixmap()); + break; +#endif + case Back: + d->page->goBack(); + break; + case Forward: + d->page->goForward(); + break; + case Stop: + mainFrame()->d->frame->loader()->stopForUserCancel(); + d->updateNavigationActions(); + break; + case Reload: + mainFrame()->d->frame->loader()->reload(/*endtoendreload*/false); + break; + case ReloadAndBypassCache: + mainFrame()->d->frame->loader()->reload(/*endtoendreload*/true); + break; + case SetTextDirectionDefault: + editor->setBaseWritingDirection(NaturalWritingDirection); + break; + case SetTextDirectionLeftToRight: + editor->setBaseWritingDirection(LeftToRightWritingDirection); + break; + case SetTextDirectionRightToLeft: + editor->setBaseWritingDirection(RightToLeftWritingDirection); + break; + case InspectElement: { +#if ENABLE(INSPECTOR) + if (!d->hitTestResult.isNull()) { + d->getOrCreateInspector(); // Make sure the inspector is created + d->inspector->show(); // The inspector is expected to be shown on inspection + d->page->inspectorController()->inspect(d->hitTestResult.d->innerNonSharedNode.get()); + } +#endif + break; + } + case StopScheduledPageRefresh: { + QWebFrame* topFrame = mainFrame(); + topFrame->d->frame->navigationScheduler()->cancel(); + QList<QWebFrame*> childFrames; + collectChildFrames(topFrame, childFrames); + QListIterator<QWebFrame*> it(childFrames); + while (it.hasNext()) + it.next()->d->frame->navigationScheduler()->cancel(); + break; + } + default: + command = QWebPagePrivate::editorCommandForWebActions(action); + break; + } + + if (command) + editor->command(command).execute(); +} + +QSize QWebPage::viewportSize() const +{ + if (d->mainFrame && d->mainFrame->d->frame->view()) + return d->mainFrame->d->frame->view()->frameRect().size(); + + return d->viewportSize; +} + +/*! + \property QWebPage::viewportSize + \brief the size of the viewport + + The size affects for example the visibility of scrollbars + if the document is larger than the viewport. + + By default, for a newly-created Web page, this property contains a size with + zero width and height. + + \sa QWebFrame::render(), preferredContentsSize +*/ +void QWebPage::setViewportSize(const QSize &size) const +{ + d->viewportSize = size; + + QWebFrame *frame = mainFrame(); + if (frame->d->frame && frame->d->frame->view()) { + WebCore::FrameView* view = frame->d->frame->view(); + view->setFrameRect(QRect(QPoint(0, 0), size)); + view->adjustViewSize(); + } +} + +static int getintenv(const char* variable) +{ + bool ok; + int value = qgetenv(variable).toInt(&ok); + return (ok) ? value : -1; +} + +static QSize queryDeviceSizeForScreenContainingWidget(const QWidget* widget) +{ + QDesktopWidget* desktop = QApplication::desktop(); + if (!desktop) + return QSize(); + + QSize size; + + if (widget) { + // Returns the available geometry of the screen which contains widget. + // NOTE: this must be the the full screen size including any fixed status areas etc. + size = desktop->availableGeometry(widget).size(); + } else + size = desktop->availableGeometry().size(); + + // This must be in portrait mode, adjust if not. + if (size.width() > size.height()) { + int width = size.width(); + size.setWidth(size.height()); + size.setHeight(width); + } + + return size; +} + +/*! + Computes the optimal viewport configuration given the \a availableSize, when + user interface components are disregarded. + + The configuration is also dependent on the device screen size which is obtained + automatically. For testing purposes the size can be overridden by setting two + environment variables QTWEBKIT_DEVICE_WIDTH and QTWEBKIT_DEVICE_HEIGHT, which + both needs to be set. + + The ViewportAttributes includes a pixel density ratio, which will also be exposed to + the web author though the -webkit-pixel-ratio media feature. This is the ratio + between 1 density-independent pixel (DPI) and physical pixels. + + A density-independent pixel is equivalent to one physical pixel on a 160 DPI screen, + so on our platform assumes that as the baseline density. + + The conversion of DIP units to screen pixels is quite simple: + + pixels = DIPs * (density / 160). + + Thus, on a 240 DPI screen, 1 DIPs would equal 1.5 physical pixels. + + An invalid instance will be returned in the case an empty size is passed to the + method. + + \note The density is automatically obtained from the DPI of the screen where the page + is being shown, but as many X11 servers are reporting wrong DPI, it is possible to + override it using QX11Info::setAppDpiY(). +*/ + +QWebPage::ViewportAttributes QWebPage::viewportAttributesForSize(const QSize& availableSize) const +{ + static int desktopWidth = 980; + + ViewportAttributes result; + + if (availableSize.isEmpty()) + return result; // Returns an invalid instance. + + int deviceWidth = getintenv("QTWEBKIT_DEVICE_WIDTH"); + int deviceHeight = getintenv("QTWEBKIT_DEVICE_HEIGHT"); + + // Both environment variables need to be set - or they will be ignored. + if (deviceWidth < 0 && deviceHeight < 0) { + QSize size = queryDeviceSizeForScreenContainingWidget((d->client) ? d->client->ownerWidget() : 0); + deviceWidth = size.width(); + deviceHeight = size.height(); + } + + WebCore::ViewportAttributes conf = WebCore::computeViewportAttributes(d->viewportArguments(), desktopWidth, deviceWidth, deviceHeight, qt_defaultDpi(), availableSize); + + result.m_isValid = true; + result.m_size = conf.layoutSize; + result.m_initialScaleFactor = conf.initialScale; + result.m_minimumScaleFactor = conf.minimumScale; + result.m_maximumScaleFactor = conf.maximumScale; + result.m_devicePixelRatio = conf.devicePixelRatio; + result.m_isUserScalable = conf.userScalable; + + d->pixelRatio = conf.devicePixelRatio; + + return result; +} + +QSize QWebPage::preferredContentsSize() const +{ + QWebFrame* frame = d->mainFrame; + if (frame) { + WebCore::FrameView* view = frame->d->frame->view(); + if (view && view->useFixedLayout()) + return d->mainFrame->d->frame->view()->fixedLayoutSize(); + } + + return d->fixedLayoutSize; +} + +/*! + \property QWebPage::preferredContentsSize + \since 4.6 + \brief a custom size used for laying out the page contents. + + By default all pages are laid out using the viewport of the page as the base. + + As pages mostly are designed for desktop usage, they often do not layout properly + on small devices as the contents require a certain view width. For this reason + it is common to use a different layout size and then scale the contents to fit + within the actual view. + + If this property is set to a valid size, this size is used for all layout needs + instead of the size of the viewport. + + Setting an invalid size, makes the page fall back to using the viewport size for layout. + + \sa viewportSize +*/ +void QWebPage::setPreferredContentsSize(const QSize& size) const +{ + // FIXME: Rename this method to setCustomLayoutSize + + d->fixedLayoutSize = size; + + QWebFrame* frame = mainFrame(); + if (!frame->d->frame || !frame->d->frame->view()) + return; + + WebCore::FrameView* view = frame->d->frame->view(); + + if (size.isValid()) { + view->setUseFixedLayout(true); + view->setFixedLayoutSize(size); + } else if (view->useFixedLayout()) + view->setUseFixedLayout(false); + + view->layout(); +} + +/* + This function is to be called after any (animated) scroll/pan has ended, in the case the application handles the + scrolling/panning of the web contents. This is commonly used in combination with tiling where is it common for + the application to pan the actual view, which then resizes itself to the size of the contents. + + \note Calling this function makes WebKit stop trying to calculate the visibleContentRect. To turn that on + again, call this method with an empty rect. + + \sa QGraphicsWebView::resizesToContents, QWebSettings::TiledBackingStoreEnabled +*/ +void QWebPage::setActualVisibleContentRect(const QRect& rect) const +{ + QWebFrame* frame = mainFrame(); + if (!frame->d->frame || !frame->d->frame->view()) + return; + + WebCore::FrameView* view = frame->d->frame->view(); + view->setActualVisibleContentRect(rect); +} + +/*! + \fn bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type) + + This function is called whenever WebKit requests to navigate \a frame to the resource specified by \a request by means of + the specified navigation type \a type. + + If \a frame is a null pointer then navigation to a new window is requested. If the request is + accepted createWindow() will be called. + + The default implementation interprets the page's linkDelegationPolicy and emits linkClicked accordingly or returns true + to let QWebPage handle the navigation itself. + + \sa createWindow() +*/ +bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type) +{ + Q_UNUSED(frame) + if (type == NavigationTypeLinkClicked) { + switch (d->linkPolicy) { + case DontDelegateLinks: + return true; + + case DelegateExternalLinks: + if (WebCore::SchemeRegistry::shouldTreatURLSchemeAsLocal(request.url().scheme())) + return true; + emit linkClicked(request.url()); + return false; + + case DelegateAllLinks: + emit linkClicked(request.url()); + return false; + } + } + return true; +} + +/*! + \property QWebPage::hasSelection + \brief whether this page contains selected content or not. + + \sa selectionChanged() +*/ +bool QWebPage::hasSelection() const +{ + d->createMainFrame(); + WebCore::Frame* frame = d->page->focusController()->focusedOrMainFrame(); + if (frame) + return (frame->selection()->selection().selectionType() != VisibleSelection::NoSelection); + return false; +} + +/*! + \property QWebPage::selectedText + \brief the text currently selected + + By default, this property contains an empty string. + + \sa selectionChanged(), selectedHtml() +*/ +QString QWebPage::selectedText() const +{ + d->createMainFrame(); + WebCore::Frame* frame = d->page->focusController()->focusedOrMainFrame(); + if (frame->selection()->selection().selectionType() == VisibleSelection::NoSelection) + return QString(); + return frame->editor()->selectedText(); +} + +/*! + \since 4.8 + \property QWebPage::selectedHtml + \brief the HTML currently selected + + By default, this property contains an empty string. + + \sa selectionChanged(), selectedText() +*/ +QString QWebPage::selectedHtml() const +{ + d->createMainFrame(); + return d->page->focusController()->focusedOrMainFrame()->editor()->selectedRange()->toHTML(); +} + +#ifndef QT_NO_ACTION +/*! + Returns a QAction for the specified WebAction \a action. + + The action is owned by the QWebPage but you can customize the look by + changing its properties. + + QWebPage also takes care of implementing the action, so that upon + triggering the corresponding action is performed on the page. + + \sa triggerAction() +*/ +QAction *QWebPage::action(WebAction action) const +{ + if (action == QWebPage::NoWebAction) return 0; + if (d->actions[action]) + return d->actions[action]; + + QString text; + QIcon icon; + QStyle *style = d->client ? d->client->style() : qApp->style(); + bool checkable = false; + + switch (action) { + case OpenLink: + text = contextMenuItemTagOpenLink(); + break; + case OpenLinkInNewWindow: + text = contextMenuItemTagOpenLinkInNewWindow(); + break; + case OpenFrameInNewWindow: + text = contextMenuItemTagOpenFrameInNewWindow(); + break; + + case DownloadLinkToDisk: + text = contextMenuItemTagDownloadLinkToDisk(); + break; + case CopyLinkToClipboard: + text = contextMenuItemTagCopyLinkToClipboard(); + break; + + case OpenImageInNewWindow: + text = contextMenuItemTagOpenImageInNewWindow(); + break; + case DownloadImageToDisk: + text = contextMenuItemTagDownloadImageToDisk(); + break; + case CopyImageToClipboard: + text = contextMenuItemTagCopyImageToClipboard(); + break; + + case Back: + text = contextMenuItemTagGoBack(); + icon = style->standardIcon(QStyle::SP_ArrowBack); + break; + case Forward: + text = contextMenuItemTagGoForward(); + icon = style->standardIcon(QStyle::SP_ArrowForward); + break; + case Stop: + text = contextMenuItemTagStop(); + icon = style->standardIcon(QStyle::SP_BrowserStop); + break; + case Reload: + text = contextMenuItemTagReload(); + icon = style->standardIcon(QStyle::SP_BrowserReload); + break; + + case Cut: + text = contextMenuItemTagCut(); + break; + case Copy: + text = contextMenuItemTagCopy(); + break; + case Paste: + text = contextMenuItemTagPaste(); + break; + case SelectAll: + text = contextMenuItemTagSelectAll(); + break; +#ifndef QT_NO_UNDOSTACK + case Undo: { + QAction *a = undoStack()->createUndoAction(d->q); + d->actions[action] = a; + return a; + } + case Redo: { + QAction *a = undoStack()->createRedoAction(d->q); + d->actions[action] = a; + return a; + } +#endif // QT_NO_UNDOSTACK + case MoveToNextChar: + text = tr("Move the cursor to the next character"); + break; + case MoveToPreviousChar: + text = tr("Move the cursor to the previous character"); + break; + case MoveToNextWord: + text = tr("Move the cursor to the next word"); + break; + case MoveToPreviousWord: + text = tr("Move the cursor to the previous word"); + break; + case MoveToNextLine: + text = tr("Move the cursor to the next line"); + break; + case MoveToPreviousLine: + text = tr("Move the cursor to the previous line"); + break; + case MoveToStartOfLine: + text = tr("Move the cursor to the start of the line"); + break; + case MoveToEndOfLine: + text = tr("Move the cursor to the end of the line"); + break; + case MoveToStartOfBlock: + text = tr("Move the cursor to the start of the block"); + break; + case MoveToEndOfBlock: + text = tr("Move the cursor to the end of the block"); + break; + case MoveToStartOfDocument: + text = tr("Move the cursor to the start of the document"); + break; + case MoveToEndOfDocument: + text = tr("Move the cursor to the end of the document"); + break; + case SelectNextChar: + text = tr("Select to the next character"); + break; + case SelectPreviousChar: + text = tr("Select to the previous character"); + break; + case SelectNextWord: + text = tr("Select to the next word"); + break; + case SelectPreviousWord: + text = tr("Select to the previous word"); + break; + case SelectNextLine: + text = tr("Select to the next line"); + break; + case SelectPreviousLine: + text = tr("Select to the previous line"); + break; + case SelectStartOfLine: + text = tr("Select to the start of the line"); + break; + case SelectEndOfLine: + text = tr("Select to the end of the line"); + break; + case SelectStartOfBlock: + text = tr("Select to the start of the block"); + break; + case SelectEndOfBlock: + text = tr("Select to the end of the block"); + break; + case SelectStartOfDocument: + text = tr("Select to the start of the document"); + break; + case SelectEndOfDocument: + text = tr("Select to the end of the document"); + break; + case DeleteStartOfWord: + text = tr("Delete to the start of the word"); + break; + case DeleteEndOfWord: + text = tr("Delete to the end of the word"); + break; + + case SetTextDirectionDefault: + text = contextMenuItemTagDefaultDirection(); + break; + case SetTextDirectionLeftToRight: + text = contextMenuItemTagLeftToRight(); + checkable = true; + break; + case SetTextDirectionRightToLeft: + text = contextMenuItemTagRightToLeft(); + checkable = true; + break; + + case ToggleBold: + text = contextMenuItemTagBold(); + checkable = true; + break; + case ToggleItalic: + text = contextMenuItemTagItalic(); + checkable = true; + break; + case ToggleUnderline: + text = contextMenuItemTagUnderline(); + checkable = true; + break; + + case InspectElement: + text = contextMenuItemTagInspectElement(); + break; + + case InsertParagraphSeparator: + text = tr("Insert a new paragraph"); + break; + case InsertLineSeparator: + text = tr("Insert a new line"); + break; + + case PasteAndMatchStyle: + text = tr("Paste and Match Style"); + break; + case RemoveFormat: + text = tr("Remove formatting"); + break; + + case ToggleStrikethrough: + text = tr("Strikethrough"); + checkable = true; + break; + case ToggleSubscript: + text = tr("Subscript"); + checkable = true; + break; + case ToggleSuperscript: + text = tr("Superscript"); + checkable = true; + break; + case InsertUnorderedList: + text = tr("Insert Bulleted List"); + checkable = true; + break; + case InsertOrderedList: + text = tr("Insert Numbered List"); + checkable = true; + break; + case Indent: + text = tr("Indent"); + break; + case Outdent: + text = tr("Outdent"); + break; + case AlignCenter: + text = tr("Center"); + break; + case AlignJustified: + text = tr("Justify"); + break; + case AlignLeft: + text = tr("Align Left"); + break; + case AlignRight: + text = tr("Align Right"); + break; + + case NoWebAction: + return 0; + } + + if (text.isEmpty()) + return 0; + + QAction *a = new QAction(d->q); + a->setText(text); + a->setData(action); + a->setCheckable(checkable); + a->setIcon(icon); + + connect(a, SIGNAL(triggered(bool)), + this, SLOT(_q_webActionTriggered(bool))); + + d->actions[action] = a; + d->updateAction(action); + return a; +} +#endif // QT_NO_ACTION + +/*! + \property QWebPage::modified + \brief whether the page contains unsubmitted form data, or the contents have been changed. + + By default, this property is false. + + \sa contentsChanged(), contentEditable, undoStack() +*/ +bool QWebPage::isModified() const +{ +#ifdef QT_NO_UNDOSTACK + return false; +#else + if (!d->undoStack) + return false; + return d->undoStack->canUndo(); +#endif // QT_NO_UNDOSTACK +} + +#ifndef QT_NO_UNDOSTACK +/*! + Returns a pointer to the undo stack used for editable content. + + \sa modified +*/ +QUndoStack *QWebPage::undoStack() const +{ + if (!d->undoStack) + d->undoStack = new QUndoStack(const_cast<QWebPage *>(this)); + + return d->undoStack; +} +#endif // QT_NO_UNDOSTACK + +/*! \reimp +*/ +bool QWebPage::event(QEvent *ev) +{ + switch (ev->type()) { + case QEvent::Timer: + d->timerEvent(static_cast<QTimerEvent*>(ev)); + break; + case QEvent::MouseMove: + d->mouseMoveEvent(static_cast<QMouseEvent*>(ev)); + break; + case QEvent::MouseButtonPress: + d->mousePressEvent(static_cast<QMouseEvent*>(ev)); + break; + case QEvent::MouseButtonDblClick: + d->mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev)); + break; + case QEvent::MouseButtonRelease: + d->mouseReleaseEvent(static_cast<QMouseEvent*>(ev)); + break; +#if !defined(QT_NO_GRAPHICSVIEW) + case QEvent::GraphicsSceneMouseMove: + d->mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent*>(ev)); + break; + case QEvent::GraphicsSceneMousePress: + d->mousePressEvent(static_cast<QGraphicsSceneMouseEvent*>(ev)); + break; + case QEvent::GraphicsSceneMouseDoubleClick: + d->mouseDoubleClickEvent(static_cast<QGraphicsSceneMouseEvent*>(ev)); + break; + case QEvent::GraphicsSceneMouseRelease: + d->mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent*>(ev)); + break; +#endif +#ifndef QT_NO_CONTEXTMENU + case QEvent::ContextMenu: + d->contextMenuEvent(static_cast<QContextMenuEvent*>(ev)->globalPos()); + break; +#if !defined(QT_NO_GRAPHICSVIEW) + case QEvent::GraphicsSceneContextMenu: + d->contextMenuEvent(static_cast<QGraphicsSceneContextMenuEvent*>(ev)->screenPos()); + break; +#endif +#endif +#ifndef QT_NO_WHEELEVENT + case QEvent::Wheel: + d->wheelEvent(static_cast<QWheelEvent*>(ev)); + break; +#if !defined(QT_NO_GRAPHICSVIEW) + case QEvent::GraphicsSceneWheel: + d->wheelEvent(static_cast<QGraphicsSceneWheelEvent*>(ev)); + break; +#endif +#endif + case QEvent::KeyPress: + d->keyPressEvent(static_cast<QKeyEvent*>(ev)); + break; + case QEvent::KeyRelease: + d->keyReleaseEvent(static_cast<QKeyEvent*>(ev)); + break; + case QEvent::FocusIn: + d->focusInEvent(static_cast<QFocusEvent*>(ev)); + break; + case QEvent::FocusOut: + d->focusOutEvent(static_cast<QFocusEvent*>(ev)); + break; +#ifndef QT_NO_DRAGANDDROP + case QEvent::DragEnter: + d->dragEnterEvent(static_cast<QDragEnterEvent*>(ev)); + break; + case QEvent::DragLeave: + d->dragLeaveEvent(static_cast<QDragLeaveEvent*>(ev)); + break; + case QEvent::DragMove: + d->dragMoveEvent(static_cast<QDragMoveEvent*>(ev)); + break; + case QEvent::Drop: + d->dropEvent(static_cast<QDropEvent*>(ev)); + break; +#if !defined(QT_NO_GRAPHICSVIEW) + case QEvent::GraphicsSceneDragEnter: + d->dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev)); + break; + case QEvent::GraphicsSceneDragMove: + d->dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev)); + break; + case QEvent::GraphicsSceneDragLeave: + d->dragLeaveEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev)); + break; + case QEvent::GraphicsSceneDrop: + d->dropEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev)); + break; +#endif + +#endif + case QEvent::InputMethod: + d->inputMethodEvent(static_cast<QInputMethodEvent*>(ev)); + break; + case QEvent::ShortcutOverride: + d->shortcutOverrideEvent(static_cast<QKeyEvent*>(ev)); + break; + case QEvent::Leave: + d->leaveEvent(ev); + break; + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + // Return whether the default action was cancelled in the JS event handler + return d->touchEvent(static_cast<QTouchEvent*>(ev)); +#ifndef QT_NO_PROPERTIES + case QEvent::DynamicPropertyChange: + d->dynamicPropertyChangeEvent(static_cast<QDynamicPropertyChangeEvent*>(ev)); + break; +#endif + default: + return QObject::event(ev); + } + + return true; +} + +/*! + Similar to QWidget::focusNextPrevChild() it focuses the next focusable web element + if \a next is true; otherwise the previous element is focused. + + Returns true if it can find a new focusable element, or false if it can't. +*/ +bool QWebPage::focusNextPrevChild(bool next) +{ + QKeyEvent ev(QEvent::KeyPress, Qt::Key_Tab, Qt::KeyboardModifiers(next ? Qt::NoModifier : Qt::ShiftModifier)); + d->keyPressEvent(&ev); + bool hasFocusedNode = false; + Frame *frame = d->page->focusController()->focusedFrame(); + if (frame) { + Document *document = frame->document(); + hasFocusedNode = document && document->focusedNode(); + } + //qDebug() << "focusNextPrevChild(" << next << ") =" << ev.isAccepted() << "focusedNode?" << hasFocusedNode; + return hasFocusedNode; +} + +/*! + \property QWebPage::contentEditable + \brief whether the content in this QWebPage is editable or not + \since 4.5 + + If this property is enabled the contents of the page can be edited by the user through a visible + cursor. If disabled (the default) only HTML elements in the web page with their + \c{contenteditable} attribute set are editable. + + \sa modified, contentsChanged(), WebAction +*/ +void QWebPage::setContentEditable(bool editable) +{ + if (d->editable != editable) { + d->editable = editable; + d->page->setTabKeyCyclesThroughElements(!editable); + if (d->mainFrame) { + WebCore::Frame* frame = d->mainFrame->d->frame; + if (editable) { + frame->editor()->applyEditingStyleToBodyElement(); + // FIXME: mac port calls this if there is no selectedDOMRange + //frame->setSelectionFromNone(); + } + } + + d->updateEditorActions(); + } +} + +bool QWebPage::isContentEditable() const +{ + return d->editable; +} + +/*! + \property QWebPage::forwardUnsupportedContent + \brief whether QWebPage should forward unsupported content + + If enabled, the unsupportedContent() signal is emitted with a network reply that + can be used to read the content. + + If disabled, the download of such content is aborted immediately. + + By default unsupported content is not forwarded. +*/ + +void QWebPage::setForwardUnsupportedContent(bool forward) +{ + d->forwardUnsupportedContent = forward; +} + +bool QWebPage::forwardUnsupportedContent() const +{ + return d->forwardUnsupportedContent; +} + +/*! + \property QWebPage::linkDelegationPolicy + \brief how QWebPage should delegate the handling of links through the + linkClicked() signal + + The default is to delegate no links. +*/ + +void QWebPage::setLinkDelegationPolicy(LinkDelegationPolicy policy) +{ + d->linkPolicy = policy; +} + +QWebPage::LinkDelegationPolicy QWebPage::linkDelegationPolicy() const +{ + return d->linkPolicy; +} + +#ifndef QT_NO_CONTEXTMENU +/*! + Filters the context menu event, \a event, through handlers for scrollbars and + custom event handlers in the web page. Returns true if the event was handled; + otherwise false. + + A web page may swallow a context menu event through a custom event handler, allowing for context + menus to be implemented in HTML/JavaScript. This is used by \l{http://maps.google.com/}{Google + Maps}, for example. +*/ +bool QWebPage::swallowContextMenuEvent(QContextMenuEvent *event) +{ + d->page->contextMenuController()->clearContextMenu(); + + if (QWebFrame* webFrame = frameAt(event->pos())) { + Frame* frame = QWebFramePrivate::core(webFrame); + if (Scrollbar* scrollbar = frame->view()->scrollbarAtPoint(PlatformMouseEvent(event, 1).pos())) + return scrollbar->contextMenu(PlatformMouseEvent(event, 1)); + } + + WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame(); + focusedFrame->eventHandler()->sendContextMenuEvent(PlatformMouseEvent(event, 1)); + ContextMenu *menu = d->page->contextMenuController()->contextMenu(); + // If the website defines its own handler then sendContextMenuEvent takes care of + // calling/showing it and the context menu pointer will be zero. This is the case + // on maps.google.com for example. + + return !menu; +} +#endif // QT_NO_CONTEXTMENU + +/*! + Updates the page's actions depending on the position \a pos. For example if \a pos is over an image + element the CopyImageToClipboard action is enabled. +*/ +void QWebPage::updatePositionDependentActions(const QPoint &pos) +{ +#ifndef QT_NO_ACTION + // First we disable all actions, but keep track of which ones were originally enabled. + QBitArray originallyEnabledWebActions(QWebPage::WebActionCount); + for (int i = ContextMenuItemTagNoAction; i < ContextMenuItemBaseApplicationTag; ++i) { + QWebPage::WebAction action = webActionForContextMenuAction(WebCore::ContextMenuAction(i)); + if (QAction *a = this->action(action)) { + originallyEnabledWebActions.setBit(action, a->isEnabled()); + a->setEnabled(false); + } + } +#endif // QT_NO_ACTION + + d->createMainFrame(); + WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame(); + HitTestResult result = focusedFrame->eventHandler()->hitTestResultAtPoint(focusedFrame->view()->windowToContents(pos), /*allowShadowContent*/ false); + + if (result.scrollbar()) + d->hitTestResult = QWebHitTestResult(); + else + d->hitTestResult = QWebHitTestResult(new QWebHitTestResultPrivate(result)); + + d->page->contextMenuController()->setHitTestResult(result); + d->page->contextMenuController()->populate(); + +#if ENABLE(INSPECTOR) + if (d->page->inspectorController()->enabled()) + d->page->contextMenuController()->addInspectElementItem(); +#endif + + QBitArray visitedWebActions(QWebPage::WebActionCount); + +#ifndef QT_NO_CONTEXTMENU + delete d->currentContextMenu; + + // Then we let createContextMenu() enable the actions that are put into the menu + d->currentContextMenu = d->createContextMenu(d->page->contextMenuController()->contextMenu(), d->page->contextMenuController()->contextMenu()->platformDescription(), &visitedWebActions); +#endif // QT_NO_CONTEXTMENU + +#ifndef QT_NO_ACTION + // Finally, we restore the original enablement for the actions that were not put into the menu. + originallyEnabledWebActions &= ~visitedWebActions; // Mask out visited actions (they're part of the menu) + for (int i = 0; i < QWebPage::WebActionCount; ++i) { + if (originallyEnabledWebActions.at(i)) { + if (QAction *a = this->action(QWebPage::WebAction(i))) + a->setEnabled(true); + } + } +#endif // QT_NO_ACTION + + // This whole process ensures that any actions put into to the context menu has the right + // enablement, while also keeping the correct enablement for actions that were left out of + // the menu. + +} + + + +/*! + \enum QWebPage::Extension + + This enum describes the types of extensions that the page can support. Before using these extensions, you + should verify that the extension is supported by calling supportsExtension(). + + \value ChooseMultipleFilesExtension Whether the web page supports multiple file selection. + This extension is invoked when the web content requests one or more file names, for example + as a result of the user clicking on a "file upload" button in a HTML form where multiple + file selection is allowed. + + \value ErrorPageExtension Whether the web page can provide an error page when loading fails. + (introduced in Qt 4.6) + + \sa ChooseMultipleFilesExtensionOption, ChooseMultipleFilesExtensionReturn, ErrorPageExtensionOption, ErrorPageExtensionReturn +*/ + +/*! + \enum QWebPage::ErrorDomain + \since 4.6 + + This enum describes the domain of an ErrorPageExtensionOption object (i.e. the layer in which the error occurred). + + \value QtNetwork The error occurred in the QtNetwork layer; the error code is of type QNetworkReply::NetworkError. + \value Http The error occurred in the HTTP layer; the error code is a HTTP status code (see QNetworkRequest::HttpStatusCodeAttribute). + \value WebKit The error is an internal WebKit error. +*/ + +/*! + \class QWebPage::ExtensionOption + \since 4.4 + \brief The ExtensionOption class provides an extended input argument to QWebPage's extension support. + + \inmodule QtWebKit + + \sa QWebPage::extension() QWebPage::ExtensionReturn +*/ + + +/*! + \class QWebPage::ExtensionReturn + \since 4.4 + \brief The ExtensionReturn class provides an output result from a QWebPage's extension. + + \inmodule QtWebKit + + \sa QWebPage::extension() QWebPage::ExtensionOption +*/ + +/*! + \class QWebPage::ErrorPageExtensionOption + \since 4.6 + \brief The ErrorPageExtensionOption class describes the option + for the error page extension. + + \inmodule QtWebKit + + The ErrorPageExtensionOption class holds the \a url for which an error occurred as well as + the associated \a frame. + + The error itself is reported by an error \a domain, the \a error code as well as \a errorString. + + \sa QWebPage::extension() QWebPage::ErrorPageExtensionReturn +*/ + +/*! + \variable QWebPage::ErrorPageExtensionOption::url + \brief the url for which an error occurred +*/ + +/*! + \variable QWebPage::ErrorPageExtensionOption::frame + \brief the frame associated with the error +*/ + +/*! + \variable QWebPage::ErrorPageExtensionOption::domain + \brief the domain that reported the error +*/ + +/*! + \variable QWebPage::ErrorPageExtensionOption::error + \brief the error code. Interpretation of the value depends on the \a domain + \sa QWebPage::ErrorDomain +*/ + +/*! + \variable QWebPage::ErrorPageExtensionOption::errorString + \brief a string that describes the error +*/ + +/*! + \class QWebPage::ErrorPageExtensionReturn + \since 4.6 + \brief The ErrorPageExtensionReturn describes the error page, which will be shown for the + frame for which the error occured. + + \inmodule QtWebKit + + The ErrorPageExtensionReturn class holds the data needed for creating an error page. Some are + optional such as \a contentType, which defaults to "text/html", as well as the \a encoding, which + is assumed to be UTF-8 if not indicated otherwise. + + The error page is stored in the \a content byte array, as HTML content. In order to convert a + QString to a byte array, the QString::toUtf8() method can be used. + + External objects such as stylesheets or images referenced in the HTML are located relative to + \a baseUrl. + + \sa QWebPage::extension() QWebPage::ErrorPageExtensionOption, QString::toUtf8() +*/ + +/*! + \fn QWebPage::ErrorPageExtensionReturn::ErrorPageExtensionReturn() + + Constructs a new error page object. +*/ + + +/*! + \variable QWebPage::ErrorPageExtensionReturn::contentType + \brief the error page's content type +*/ + +/*! + \variable QWebPage::ErrorPageExtensionReturn::encoding + \brief the error page encoding +*/ + +/*! + \variable QWebPage::ErrorPageExtensionReturn::baseUrl + \brief the base url + + External objects such as stylesheets or images referenced in the HTML are located relative to this url. +*/ + +/*! + \variable QWebPage::ErrorPageExtensionReturn::content + \brief the HTML content of the error page +*/ + +/*! + \class QWebPage::ChooseMultipleFilesExtensionOption + \since 4.5 + \brief The ChooseMultipleFilesExtensionOption class describes the option + for the multiple files selection extension. + + \inmodule QtWebKit + + The ChooseMultipleFilesExtensionOption class holds the frame originating the request + and the suggested filenames which might be provided. + + \sa QWebPage::extension() QWebPage::chooseFile(), QWebPage::ChooseMultipleFilesExtensionReturn +*/ + +/*! + \variable QWebPage::ChooseMultipleFilesExtensionOption::parentFrame + \brief The frame in which the request originated +*/ + +/*! + \variable QWebPage::ChooseMultipleFilesExtensionOption::suggestedFileNames + \brief The suggested filenames +*/ + +/*! + \variable QWebPage::ChooseMultipleFilesExtensionReturn::fileNames + \brief The selected filenames +*/ + +/*! + \class QWebPage::ChooseMultipleFilesExtensionReturn + \since 4.5 + \brief The ChooseMultipleFilesExtensionReturn describes the return value + for the multiple files selection extension. + + \inmodule QtWebKit + + The ChooseMultipleFilesExtensionReturn class holds the filenames selected by the user + when the extension is invoked. + + \sa QWebPage::extension() QWebPage::ChooseMultipleFilesExtensionOption +*/ + +/*! + This virtual function can be reimplemented in a QWebPage subclass to provide support for extensions. The \a option + argument is provided as input to the extension; the output results can be stored in \a output. + + The behavior of this function is determined by \a extension. The \a option + and \a output values are typically casted to the corresponding types (for + example, ChooseMultipleFilesExtensionOption and + ChooseMultipleFilesExtensionReturn for ChooseMultipleFilesExtension). + + You can call supportsExtension() to check if an extension is supported by the page. + + Returns true if the extension was called successfully; otherwise returns false. + + \sa supportsExtension(), Extension +*/ +bool QWebPage::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output) +{ +#ifndef QT_NO_FILEDIALOG + if (extension == ChooseMultipleFilesExtension) { + // FIXME: do not ignore suggestedFiles + QStringList suggestedFiles = static_cast<const ChooseMultipleFilesExtensionOption*>(option)->suggestedFileNames; + QWidget* parent = (d->client) ? d->client->ownerWidget() : 0; + QStringList names = QFileDialog::getOpenFileNames(parent, QString::null); + static_cast<ChooseMultipleFilesExtensionReturn*>(output)->fileNames = names; + return true; + } +#endif + + return false; +} + +/*! + This virtual function returns true if the web page supports \a extension; otherwise false is returned. + + \sa extension() +*/ +bool QWebPage::supportsExtension(Extension extension) const +{ +#ifndef QT_NO_FILEDIALOG + return extension == ChooseMultipleFilesExtension; +#else + Q_UNUSED(extension); + return false; +#endif +} + +/*! + Finds the specified string, \a subString, in the page, using the given \a options. + + If the HighlightAllOccurrences flag is passed, the function will highlight all occurrences + that exist in the page. All subsequent calls will extend the highlight, rather than + replace it, with occurrences of the new string. + + If the HighlightAllOccurrences flag is not passed, the function will select an occurrence + and all subsequent calls will replace the current occurrence with the next one. + + To clear the selection, just pass an empty string. + + Returns true if \a subString was found; otherwise returns false. +*/ +bool QWebPage::findText(const QString &subString, FindFlags options) +{ + ::TextCaseSensitivity caseSensitivity = ::TextCaseInsensitive; + if (options & FindCaseSensitively) + caseSensitivity = ::TextCaseSensitive; + + if (options & HighlightAllOccurrences) { + if (subString.isEmpty()) { + d->page->unmarkAllTextMatches(); + return true; + } else + return d->page->markAllMatchesForText(subString, caseSensitivity, true, 0); + } else { + if (subString.isEmpty()) { + d->page->mainFrame()->selection()->clear(); + Frame* frame = d->page->mainFrame()->tree()->firstChild(); + while (frame) { + frame->selection()->clear(); + frame = frame->tree()->traverseNextWithWrap(false); + } + } + ::FindDirection direction = ::FindDirectionForward; + if (options & FindBackward) + direction = ::FindDirectionBackward; + + const bool shouldWrap = options & FindWrapsAroundDocument; + + return d->page->findString(subString, caseSensitivity, direction, shouldWrap); + } +} + +/*! + Returns a pointer to the page's settings object. + + \sa QWebSettings::globalSettings() +*/ +QWebSettings *QWebPage::settings() const +{ + return d->settings; +} + +/*! + This function is called when the web content requests a file name, for example + as a result of the user clicking on a "file upload" button in a HTML form. + + A suggested filename may be provided in \a suggestedFile. The frame originating the + request is provided as \a parentFrame. + + \sa ChooseMultipleFilesExtension +*/ +QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& suggestedFile) +{ + Q_UNUSED(parentFrame) +#ifndef QT_NO_FILEDIALOG + QWidget* parent = (d->client) ? d->client->ownerWidget() : 0; + return QFileDialog::getOpenFileName(parent, QString::null, suggestedFile); +#else + return QString::null; +#endif +} + +/*! + Sets the QNetworkAccessManager \a manager responsible for serving network requests for this + QWebPage. + + \note It is currently not supported to change the network access manager after the + QWebPage has used it. The results of doing this are undefined. + + \sa networkAccessManager() +*/ +void QWebPage::setNetworkAccessManager(QNetworkAccessManager *manager) +{ + if (manager == d->networkManager) + return; + if (d->networkManager && d->networkManager->parent() == this) + delete d->networkManager; + d->networkManager = manager; +} + +/*! + Returns the QNetworkAccessManager that is responsible for serving network + requests for this QWebPage. + + \sa setNetworkAccessManager() +*/ +QNetworkAccessManager *QWebPage::networkAccessManager() const +{ + if (!d->networkManager) { + QWebPage *that = const_cast<QWebPage *>(this); + that->d->networkManager = new QNetworkAccessManager(that); + } + return d->networkManager; +} + +/*! + Sets the QWebPluginFactory \a factory responsible for creating plugins embedded into this + QWebPage. + + Note: The plugin factory is only used if the QWebSettings::PluginsEnabled attribute is enabled. + + \sa pluginFactory() +*/ +void QWebPage::setPluginFactory(QWebPluginFactory *factory) +{ + d->pluginFactory = factory; +} + +/*! + Returns the QWebPluginFactory that is responsible for creating plugins embedded into + this QWebPage. If no plugin factory is installed a null pointer is returned. + + \sa setPluginFactory() +*/ +QWebPluginFactory *QWebPage::pluginFactory() const +{ + return d->pluginFactory; +} + +/*! + This function is called when a user agent for HTTP requests is needed. You can reimplement this + function to dynamically return different user agents for different URLs, based on the \a url parameter. + + The default implementation returns the following value: + + "Mozilla/5.0 (%Platform%; %Security%; %Subplatform%; %Locale%) AppleWebKit/%WebKitVersion% (KHTML, like Gecko) %AppVersion Safari/%WebKitVersion%" + + On mobile platforms such as Symbian S60 and Maemo, "Mobile Safari" is used instead of "Safari". + + In this string the following values are replaced at run-time: + \list + \o %Platform% and %Subplatform% are expanded to the windowing system and the operation system. + \o %Security% expands to U if SSL is enabled, otherwise N. SSL is enabled if QSslSocket::supportsSsl() returns true. + \o %Locale% is replaced with QLocale::name(). The locale is determined from the view of the QWebPage. If no view is set on the QWebPage, + then a default constructed QLocale is used instead. + \o %WebKitVersion% is the version of WebKit the application was compiled against. + \o %AppVersion% expands to QCoreApplication::applicationName()/QCoreApplication::applicationVersion() if they're set; otherwise defaulting to Qt and the current Qt version. + \endlist +*/ +QString QWebPage::userAgentForUrl(const QUrl&) const +{ + // splitting the string in three and user QStringBuilder is better than using QString::arg() + static QString firstPart; + static QString secondPart; + static QString thirdPart; + + if (firstPart.isNull() || secondPart.isNull() || thirdPart.isNull()) { + QString firstPartTemp; + firstPartTemp.reserve(150); + firstPartTemp += QString::fromLatin1("Mozilla/5.0 (" + + // Platform +#ifdef Q_WS_MAC + "Macintosh" +#elif defined Q_WS_QWS + "QtEmbedded" +#elif defined Q_WS_WIN + "Windows" +#elif defined Q_WS_X11 + "X11" +#elif defined Q_OS_SYMBIAN + "Symbian" +#else + "Unknown" +#endif + ); + +#if defined Q_OS_SYMBIAN + QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion(); + switch (symbianVersion) { + case QSysInfo::SV_9_2: + firstPartTemp += QString::fromLatin1("OS/9.2"); + break; + case QSysInfo::SV_9_3: + firstPartTemp += QString::fromLatin1("OS/9.3"); + break; + case QSysInfo::SV_9_4: + firstPartTemp += QString::fromLatin1("OS/9.4"); + break; + case QSysInfo::SV_SF_2: + firstPartTemp += QString::fromLatin1("/2"); + break; + case QSysInfo::SV_SF_3: + firstPartTemp += QString::fromLatin1("/3"); + break; + case QSysInfo::SV_SF_4: + firstPartTemp += QString::fromLatin1("/4"); + default: + break; + } +#endif + + firstPartTemp += QString::fromLatin1("; "); + + // SSL support +#if !defined(QT_NO_OPENSSL) + // we could check QSslSocket::supportsSsl() here, but this makes + // OpenSSL, certificates etc being loaded in all cases were QWebPage + // is used. This loading is not needed for non-https. + firstPartTemp += QString::fromLatin1("U; "); + // this may lead to a false positive: We indicate SSL since it is + // compiled in even though supportsSsl() might return false +#else + firstPartTemp += QString::fromLatin1("N; "); +#endif + + // Operating system +#ifdef Q_OS_AIX + firstPartTemp += QString::fromLatin1("AIX"); +#elif defined Q_OS_WIN32 + + switch (QSysInfo::WindowsVersion) { + case QSysInfo::WV_32s: + firstPartTemp += QString::fromLatin1("Windows 3.1"); + break; + case QSysInfo::WV_95: + firstPartTemp += QString::fromLatin1("Windows 95"); + break; + case QSysInfo::WV_98: + firstPartTemp += QString::fromLatin1("Windows 98"); + break; + case QSysInfo::WV_Me: + firstPartTemp += QString::fromLatin1("Windows 98; Win 9x 4.90"); + break; + case QSysInfo::WV_NT: + firstPartTemp += QString::fromLatin1("WinNT4.0"); + break; + case QSysInfo::WV_2000: + firstPartTemp += QString::fromLatin1("Windows NT 5.0"); + break; + case QSysInfo::WV_XP: + firstPartTemp += QString::fromLatin1("Windows NT 5.1"); + break; + case QSysInfo::WV_2003: + firstPartTemp += QString::fromLatin1("Windows NT 5.2"); + break; + case QSysInfo::WV_VISTA: + firstPartTemp += QString::fromLatin1("Windows NT 6.0"); + break; + case QSysInfo::WV_WINDOWS7: + firstPartTemp += QString::fromLatin1("Windows NT 6.1"); + break; + case QSysInfo::WV_CE: + firstPartTemp += QString::fromLatin1("Windows CE"); + break; + case QSysInfo::WV_CENET: + firstPartTemp += QString::fromLatin1("Windows CE .NET"); + break; + case QSysInfo::WV_CE_5: + firstPartTemp += QString::fromLatin1("Windows CE 5.x"); + break; + case QSysInfo::WV_CE_6: + firstPartTemp += QString::fromLatin1("Windows CE 6.x"); + break; + } + +#elif defined Q_OS_DARWIN +#ifdef __i386__ || __x86_64__ + firstPartTemp += QString::fromLatin1("Intel Mac OS X"); +#else + firstPartTemp += QString::fromLatin1("PPC Mac OS X"); +#endif + +#elif defined Q_OS_BSDI + firstPartTemp += QString::fromLatin1("BSD"); +#elif defined Q_OS_BSD4 + firstPartTemp += QString::fromLatin1("BSD Four"); +#elif defined Q_OS_CYGWIN + firstPartTemp += QString::fromLatin1("Cygwin"); +#elif defined Q_OS_DGUX + firstPartTemp += QString::fromLatin1("DG/UX"); +#elif defined Q_OS_DYNIX + firstPartTemp += QString::fromLatin1("DYNIX/ptx"); +#elif defined Q_OS_FREEBSD + firstPartTemp += QString::fromLatin1("FreeBSD"); +#elif defined Q_OS_HPUX + firstPartTemp += QString::fromLatin1("HP-UX"); +#elif defined Q_OS_HURD + firstPartTemp += QString::fromLatin1("GNU Hurd"); +#elif defined Q_OS_IRIX + firstPartTemp += QString::fromLatin1("SGI Irix"); +#elif defined Q_OS_LINUX + +#if defined(__x86_64__) + firstPartTemp += QString::fromLatin1("Linux x86_64"); +#elif defined(__i386__) + firstPartTemp += QString::fromLatin1("Linux i686"); +#else + firstPartTemp += QString::fromLatin1("Linux"); +#endif + +#elif defined Q_OS_LYNX + firstPartTemp += QString::fromLatin1("LynxOS"); +#elif defined Q_OS_NETBSD + firstPartTemp += QString::fromLatin1("NetBSD"); +#elif defined Q_OS_OS2 + firstPartTemp += QString::fromLatin1("OS/2"); +#elif defined Q_OS_OPENBSD + firstPartTemp += QString::fromLatin1("OpenBSD"); +#elif defined Q_OS_OS2EMX + firstPartTemp += QString::fromLatin1("OS/2"); +#elif defined Q_OS_OSF + firstPartTemp += QString::fromLatin1("HP Tru64 UNIX"); +#elif defined Q_OS_QNX6 + firstPartTemp += QString::fromLatin1("QNX RTP Six"); +#elif defined Q_OS_QNX + firstPartTemp += QString::fromLatin1("QNX"); +#elif defined Q_OS_RELIANT + firstPartTemp += QString::fromLatin1("Reliant UNIX"); +#elif defined Q_OS_SCO + firstPartTemp += QString::fromLatin1("SCO OpenServer"); +#elif defined Q_OS_SOLARIS + firstPartTemp += QString::fromLatin1("Sun Solaris"); +#elif defined Q_OS_ULTRIX + firstPartTemp += QString::fromLatin1("DEC Ultrix"); +#elif defined Q_OS_SYMBIAN + firstPartTemp += QLatin1Char(' '); + QSysInfo::S60Version s60Version = QSysInfo::s60Version(); + switch (s60Version) { + case QSysInfo::SV_S60_3_1: + firstPartTemp += QString::fromLatin1("Series60/3.1"); + break; + case QSysInfo::SV_S60_3_2: + firstPartTemp += QString::fromLatin1("Series60/3.2"); + break; + case QSysInfo::SV_S60_5_0: + firstPartTemp += QString::fromLatin1("Series60/5.0"); + break; + default: + break; + } +#elif defined Q_OS_UNIX + firstPartTemp += QString::fromLatin1("UNIX BSD/SYSV system"); +#elif defined Q_OS_UNIXWARE + firstPartTemp += QString::fromLatin1("UnixWare Seven, Open UNIX Eight"); +#else + firstPartTemp += QString::fromLatin1("Unknown"); +#endif + + // language is the split + firstPartTemp += QString::fromLatin1("; "); + firstPartTemp.squeeze(); + firstPart = firstPartTemp; + + QString secondPartTemp; + secondPartTemp.reserve(150); + secondPartTemp += QString::fromLatin1(") "); + + // webkit/qt version + secondPartTemp += QString::fromLatin1("AppleWebKit/"); + secondPartTemp += qWebKitVersion(); + secondPartTemp += QString::fromLatin1(" (KHTML, like Gecko) "); + + + // Application name split the third part + secondPartTemp.squeeze(); + secondPart = secondPartTemp; + + QString thirdPartTemp; + thirdPartTemp.reserve(150); +#if defined(Q_OS_SYMBIAN) || defined(Q_WS_MAEMO_5) + thirdPartTemp += QLatin1String(" Mobile Safari/"); +#else + thirdPartTemp += QLatin1String(" Safari/"); +#endif + thirdPartTemp += qWebKitVersion(); + thirdPartTemp.squeeze(); + thirdPart = thirdPartTemp; + Q_ASSERT(!firstPart.isNull()); + Q_ASSERT(!secondPart.isNull()); + Q_ASSERT(!thirdPart.isNull()); + } + + // Language + QString languageName; + if (d->client && d->client->ownerWidget()) + languageName = d->client->ownerWidget()->locale().name(); + else + languageName = QLocale().name(); + languageName.replace(QLatin1Char('_'), QLatin1Char('-')); + + // Application name/version + QString appName = QCoreApplication::applicationName(); + if (!appName.isEmpty()) { + QString appVer = QCoreApplication::applicationVersion(); + if (!appVer.isEmpty()) + appName.append(QLatin1Char('/') + appVer); + } else { + // Qt version + appName = QString::fromLatin1("Qt/") + QString::fromLatin1(qVersion()); + } + + return firstPart + languageName + secondPart + appName + thirdPart; +} + + +void QWebPagePrivate::_q_onLoadProgressChanged(int) +{ + m_totalBytes = page->progress()->totalPageAndResourceBytesToLoad(); + m_bytesReceived = page->progress()->totalBytesReceived(); +} + + +/*! + Returns the total number of bytes that were received from the network to render the current page, + including extra content such as embedded images. + + \sa bytesReceived() +*/ +quint64 QWebPage::totalBytes() const +{ + return d->m_totalBytes; +} + + +/*! + Returns the number of bytes that were received from the network to render the current page. + + \sa totalBytes(), loadProgress() +*/ +quint64 QWebPage::bytesReceived() const +{ + return d->m_bytesReceived; +} + +/*! + \since 4.7 + \fn void QWebPage::viewportChangeRequested() + + Page authors can provide the supplied values by using the viewport meta tag. More information + about this can be found at \l{http://developer.apple.com/safari/library/documentation/appleapplications/reference/safariwebcontent/usingtheviewport/usingtheviewport.html}{Safari Reference Library: Using the Viewport Meta Tag}. + + \sa QWebPage::ViewportAttributes, setPreferredContentsSize(), QGraphicsWebView::setScale() +*/ + +/*! + \fn void QWebPage::loadStarted() + + This signal is emitted when a new load of the page is started. + + \sa loadFinished() +*/ + +/*! + \fn void QWebPage::loadProgress(int progress) + + This signal is emitted when the global progress status changes. + The current value is provided by \a progress and scales from 0 to 100, + which is the default range of QProgressBar. + It accumulates changes from all the child frames. + + \sa bytesReceived() +*/ + +/*! + \fn void QWebPage::loadFinished(bool ok) + + This signal is emitted when a load of the page is finished. + \a ok will indicate whether the load was successful or any error occurred. + + \sa loadStarted(), ErrorPageExtension +*/ + +/*! + \fn void QWebPage::linkHovered(const QString &link, const QString &title, const QString &textContent) + + This signal is emitted when the mouse hovers over a link. + + \a link contains the link url. + \a title is the link element's title, if it is specified in the markup. + \a textContent provides text within the link element, e.g., text inside an HTML anchor tag. + + When the mouse leaves the link element the signal is emitted with empty parameters. + + \sa linkClicked() +*/ + +/*! + \fn void QWebPage::statusBarMessage(const QString& text) + + This signal is emitted when the statusbar \a text is changed by the page. +*/ + +/*! + \fn void QWebPage::frameCreated(QWebFrame *frame) + + This signal is emitted whenever the page creates a new \a frame. + + \sa currentFrame() +*/ + +/*! + \fn void QWebPage::selectionChanged() + + This signal is emitted whenever the selection changes, either interactively + or programmatically (e.g. by calling triggerAction() with a selection action). + + \sa selectedText() +*/ + +/*! + \fn void QWebPage::contentsChanged() + \since 4.5 + + This signal is emitted whenever the text in form elements changes + as well as other editable content. + + \sa contentEditable, modified, QWebFrame::toHtml(), QWebFrame::toPlainText() +*/ + +/*! + \fn void QWebPage::geometryChangeRequested(const QRect& geom) + + This signal is emitted whenever the document wants to change the position and size of the + page to \a geom. This can happen for example through JavaScript. +*/ + +/*! + \fn void QWebPage::repaintRequested(const QRect& dirtyRect) + + This signal is emitted whenever this QWebPage should be updated and no view was set. + \a dirtyRect contains the area that needs to be updated. To paint the QWebPage get + the mainFrame() and call the render(QPainter*, const QRegion&) method with the + \a dirtyRect as the second parameter. + + \sa mainFrame() + \sa view() +*/ + +/*! + \fn void QWebPage::scrollRequested(int dx, int dy, const QRect& rectToScroll) + + This signal is emitted whenever the content given by \a rectToScroll needs + to be scrolled \a dx and \a dy downwards and no view was set. + + \sa view() +*/ + +/*! + \fn void QWebPage::windowCloseRequested() + + This signal is emitted whenever the page requests the web browser window to be closed, + for example through the JavaScript \c{window.close()} call. +*/ + +/*! + \fn void QWebPage::printRequested(QWebFrame *frame) + + This signal is emitted whenever the page requests the web browser to print \a frame, + for example through the JavaScript \c{window.print()} call. + + \sa QWebFrame::print(), QPrintPreviewDialog +*/ + +/*! + \fn void QWebPage::unsupportedContent(QNetworkReply *reply) + + This signal is emitted when WebKit cannot handle a link the user navigated to or a + web server's response includes a "Content-Disposition" header with the 'attachment' + directive. If "Content-Disposition" is present in \a reply, the web server is indicating + that the client should prompt the user to save the content regardless of content-type. + See RFC 2616 sections 19.5.1 for details about Content-Disposition. + + At signal emission time the meta-data of the QNetworkReply \a reply is available. + + \note This signal is only emitted if the forwardUnsupportedContent property is set to true. + + \sa downloadRequested() +*/ + +/*! + \fn void QWebPage::downloadRequested(const QNetworkRequest &request) + + This signal is emitted when the user decides to download a link. The url of + the link as well as additional meta-information is contained in \a request. + + \sa unsupportedContent() +*/ + +/*! + \fn void QWebPage::microFocusChanged() + + This signal is emitted when for example the position of the cursor in an editable form + element changes. It is used to inform input methods about the new on-screen position where + the user is able to enter text. This signal is usually connected to the + QWidget::updateMicroFocus() slot. +*/ + +/*! + \fn void QWebPage::linkClicked(const QUrl &url) + + This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy + property is set to delegate the link handling for the specified \a url. + + By default no links are delegated and are handled by QWebPage instead. + + \note This signal possibly won't be emitted for clicked links which use + JavaScript to trigger navigation. + + \sa linkHovered() +*/ + +/*! + \fn void QWebPage::toolBarVisibilityChangeRequested(bool visible) + + This signal is emitted whenever the visibility of the toolbar in a web browser + window that hosts QWebPage should be changed to \a visible. +*/ + +/*! + \fn void QWebPage::statusBarVisibilityChangeRequested(bool visible) + + This signal is emitted whenever the visibility of the statusbar in a web browser + window that hosts QWebPage should be changed to \a visible. +*/ + +/*! + \fn void QWebPage::menuBarVisibilityChangeRequested(bool visible) + + This signal is emitted whenever the visibility of the menubar in a web browser + window that hosts QWebPage should be changed to \a visible. +*/ + +/*! + \fn void QWebPage::databaseQuotaExceeded(QWebFrame* frame, QString databaseName); + \since 4.5 + + This signal is emitted whenever the web site shown in \a frame is asking to store data + to the database \a databaseName and the quota allocated to that web site is exceeded. + + \sa QWebDatabase +*/ +/*! + \fn void QWebPage::applicationCacheQuotaExceeded(QWebSecurityOrigin* origin, quint64 defaultOriginQuota); + + This signal is emitted whenever the web site is asking to store data to the application cache + database databaseName and the quota allocated to that web site is exceeded. + +*/ + +/*! + \since 4.5 + \fn void QWebPage::saveFrameStateRequested(QWebFrame* frame, QWebHistoryItem* item); + + This signal is emitted shortly before the history of navigated pages + in \a frame is changed, for example when navigating back in the history. + + The provided QWebHistoryItem, \a item, holds the history entry of the frame before + the change. + + A potential use-case for this signal is to store custom data in + the QWebHistoryItem associated to the frame, using QWebHistoryItem::setUserData(). +*/ + +/*! + \since 4.5 + \fn void QWebPage::restoreFrameStateRequested(QWebFrame* frame); + + This signal is emitted when the load of \a frame is finished and the application may now update its state accordingly. +*/ + +/*! + \fn QWebPagePrivate* QWebPage::handle() const + \internal +*/ + +#include "moc_qwebpage.cpp" diff --git a/Source/WebKit/qt/Api/qwebpage.h b/Source/WebKit/qt/Api/qwebpage.h new file mode 100644 index 0000000..b66adb2 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebpage.h @@ -0,0 +1,449 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2007 Staikos Computing Services Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBPAGE_H +#define QWEBPAGE_H + +#include "qwebsettings.h" +#include "qwebkitglobal.h" + +#include <QtCore/qobject.h> +#include <QtCore/qurl.h> +#include <QtGui/qwidget.h> + +QT_BEGIN_NAMESPACE +class QNetworkProxy; +class QUndoStack; +class QMenu; +class QNetworkRequest; +class QNetworkReply; +class QNetworkAccessManager; +QT_END_NAMESPACE + +class QWebElement; +class QWebFrame; +class QWebNetworkRequest; +class QWebHistory; + +class QWebFrameData; +class QWebHistoryItem; +class QWebHitTestResult; +class QWebNetworkInterface; +class QWebPagePrivate; +class QWebPluginFactory; +class QWebSecurityOrigin; +class QtViewportAttributesPrivate; + +namespace WebCore { + class ChromeClientQt; + class EditorClientQt; + class FrameLoaderClientQt; + class InspectorClientQt; + class InspectorServerRequestHandlerQt; + class InspectorFrontendClientQt; + class NotificationPresenterClientQt; + class GeolocationPermissionClientQt; + class ResourceHandle; + class HitTestResult; + class QNetworkReplyHandler; + + struct FrameLoadRequest; +} + +class QWEBKIT_EXPORT QWebPage : public QObject { + Q_OBJECT + + Q_PROPERTY(bool modified READ isModified) + Q_PROPERTY(QString selectedText READ selectedText) + Q_PROPERTY(QString selectedHtml READ selectedHtml) + Q_PROPERTY(bool hasSelection READ hasSelection) + Q_PROPERTY(QSize viewportSize READ viewportSize WRITE setViewportSize) + Q_PROPERTY(QSize preferredContentsSize READ preferredContentsSize WRITE setPreferredContentsSize) + Q_PROPERTY(bool forwardUnsupportedContent READ forwardUnsupportedContent WRITE setForwardUnsupportedContent) + Q_PROPERTY(LinkDelegationPolicy linkDelegationPolicy READ linkDelegationPolicy WRITE setLinkDelegationPolicy) + Q_PROPERTY(QPalette palette READ palette WRITE setPalette) + Q_PROPERTY(bool contentEditable READ isContentEditable WRITE setContentEditable) + Q_ENUMS(LinkDelegationPolicy NavigationType WebAction) +public: + enum NavigationType { + NavigationTypeLinkClicked, + NavigationTypeFormSubmitted, + NavigationTypeBackOrForward, + NavigationTypeReload, + NavigationTypeFormResubmitted, + NavigationTypeOther + }; + + enum WebAction { + NoWebAction = - 1, + + OpenLink, + + OpenLinkInNewWindow, + OpenFrameInNewWindow, + + DownloadLinkToDisk, + CopyLinkToClipboard, + + OpenImageInNewWindow, + DownloadImageToDisk, + CopyImageToClipboard, + + Back, + Forward, + Stop, + Reload, + + Cut, + Copy, + Paste, + + Undo, + Redo, + MoveToNextChar, + MoveToPreviousChar, + MoveToNextWord, + MoveToPreviousWord, + MoveToNextLine, + MoveToPreviousLine, + MoveToStartOfLine, + MoveToEndOfLine, + MoveToStartOfBlock, + MoveToEndOfBlock, + MoveToStartOfDocument, + MoveToEndOfDocument, + SelectNextChar, + SelectPreviousChar, + SelectNextWord, + SelectPreviousWord, + SelectNextLine, + SelectPreviousLine, + SelectStartOfLine, + SelectEndOfLine, + SelectStartOfBlock, + SelectEndOfBlock, + SelectStartOfDocument, + SelectEndOfDocument, + DeleteStartOfWord, + DeleteEndOfWord, + + SetTextDirectionDefault, + SetTextDirectionLeftToRight, + SetTextDirectionRightToLeft, + + ToggleBold, + ToggleItalic, + ToggleUnderline, + + InspectElement, + + InsertParagraphSeparator, + InsertLineSeparator, + + SelectAll, + ReloadAndBypassCache, + + PasteAndMatchStyle, + RemoveFormat, + + ToggleStrikethrough, + ToggleSubscript, + ToggleSuperscript, + InsertUnorderedList, + InsertOrderedList, + Indent, + Outdent, + + AlignCenter, + AlignJustified, + AlignLeft, + AlignRight, + + StopScheduledPageRefresh, + + WebActionCount + }; + + enum FindFlag { + FindBackward = 1, + FindCaseSensitively = 2, + FindWrapsAroundDocument = 4, + HighlightAllOccurrences = 8 + }; + Q_DECLARE_FLAGS(FindFlags, FindFlag) + + enum LinkDelegationPolicy { + DontDelegateLinks, + DelegateExternalLinks, + DelegateAllLinks + }; + + enum WebWindowType { + WebBrowserWindow, + WebModalDialog + }; + + enum PermissionPolicy { + PermissionUnknown, + PermissionGrantedByUser, + PermissionDeniedByUser + }; + + enum Feature { + Notifications, + Geolocation + }; + + class QWEBKIT_EXPORT ViewportAttributes { + public: + ViewportAttributes(); + ViewportAttributes(const QWebPage::ViewportAttributes& other); + + ~ViewportAttributes(); + + QWebPage::ViewportAttributes& operator=(const QWebPage::ViewportAttributes& other); + + inline qreal initialScaleFactor() const { return m_initialScaleFactor; } + inline qreal minimumScaleFactor() const { return m_minimumScaleFactor; } + inline qreal maximumScaleFactor() const { return m_maximumScaleFactor; } + inline qreal devicePixelRatio() const { return m_devicePixelRatio; } + inline bool isUserScalable() const { return m_isUserScalable; } + inline bool isValid() const { return m_isValid; } + inline QSize size() const { return m_size; } + + private: + QSharedDataPointer<QtViewportAttributesPrivate> d; + qreal m_initialScaleFactor; + qreal m_minimumScaleFactor; + qreal m_maximumScaleFactor; + qreal m_devicePixelRatio; + bool m_isUserScalable; + bool m_isValid; + QSize m_size; + + friend class WebCore::ChromeClientQt; + friend class QWebPage; + }; + + + explicit QWebPage(QObject *parent = 0); + ~QWebPage(); + + QWebFrame *mainFrame() const; + QWebFrame *currentFrame() const; + QWebFrame* frameAt(const QPoint& pos) const; + + QWebHistory *history() const; + QWebSettings *settings() const; + + void setView(QWidget *view); + QWidget *view() const; + + bool isModified() const; +#ifndef QT_NO_UNDOSTACK + QUndoStack *undoStack() const; +#endif + + void setNetworkAccessManager(QNetworkAccessManager *manager); + QNetworkAccessManager *networkAccessManager() const; + + void setPluginFactory(QWebPluginFactory *factory); + QWebPluginFactory *pluginFactory() const; + + quint64 totalBytes() const; + quint64 bytesReceived() const; + + bool hasSelection() const; + QString selectedText() const; + QString selectedHtml() const; + +#ifndef QT_NO_ACTION + QAction *action(WebAction action) const; +#endif + virtual void triggerAction(WebAction action, bool checked = false); + + QSize viewportSize() const; + void setViewportSize(const QSize &size) const; + ViewportAttributes viewportAttributesForSize(const QSize& availableSize) const; + + QSize preferredContentsSize() const; + void setPreferredContentsSize(const QSize &size) const; + void setActualVisibleContentRect(const QRect& rect) const; + + virtual bool event(QEvent*); + bool focusNextPrevChild(bool next); + + QVariant inputMethodQuery(Qt::InputMethodQuery property) const; + + bool findText(const QString &subString, FindFlags options = 0); + + void setForwardUnsupportedContent(bool forward); + bool forwardUnsupportedContent() const; + + void setLinkDelegationPolicy(LinkDelegationPolicy policy); + LinkDelegationPolicy linkDelegationPolicy() const; + + void setPalette(const QPalette &palette); + QPalette palette() const; + + void setContentEditable(bool editable); + bool isContentEditable() const; + +#ifndef QT_NO_CONTEXTMENU + bool swallowContextMenuEvent(QContextMenuEvent *event); +#endif + void updatePositionDependentActions(const QPoint &pos); + + QMenu *createStandardContextMenu(); + + void setFeaturePermission(QWebFrame* frame, Feature feature, PermissionPolicy policy); + + QStringList supportedContentTypes() const; + bool supportsContentType(const QString& mimeType) const; + + enum Extension { + ChooseMultipleFilesExtension, + ErrorPageExtension + }; + class ExtensionOption + {}; + class ExtensionReturn + {}; + + class ChooseMultipleFilesExtensionOption : public ExtensionOption { + public: + QWebFrame *parentFrame; + QStringList suggestedFileNames; + }; + + class ChooseMultipleFilesExtensionReturn : public ExtensionReturn { + public: + QStringList fileNames; + }; + + enum ErrorDomain { QtNetwork, Http, WebKit }; + class ErrorPageExtensionOption : public ExtensionOption { + public: + QUrl url; + QWebFrame* frame; + ErrorDomain domain; + int error; + QString errorString; + }; + + class ErrorPageExtensionReturn : public ExtensionReturn { + public: + ErrorPageExtensionReturn() : contentType(QLatin1String("text/html")), encoding(QLatin1String("utf-8")) {}; + QString contentType; + QString encoding; + QUrl baseUrl; + QByteArray content; + }; + + + virtual bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0); + virtual bool supportsExtension(Extension extension) const; + + inline QWebPagePrivate* handle() const { return d; } + +public Q_SLOTS: + bool shouldInterruptJavaScript(); + +Q_SIGNALS: + void loadStarted(); + void loadProgress(int progress); + void loadFinished(bool ok); + + void linkHovered(const QString &link, const QString &title, const QString &textContent); + void statusBarMessage(const QString& text); + void selectionChanged(); + void frameCreated(QWebFrame *frame); + void geometryChangeRequested(const QRect& geom); + void repaintRequested(const QRect& dirtyRect); + void scrollRequested(int dx, int dy, const QRect& scrollViewRect); + void windowCloseRequested(); + void printRequested(QWebFrame *frame); + void linkClicked(const QUrl &url); + + void toolBarVisibilityChangeRequested(bool visible); + void statusBarVisibilityChangeRequested(bool visible); + void menuBarVisibilityChangeRequested(bool visible); + + void unsupportedContent(QNetworkReply *reply); + void downloadRequested(const QNetworkRequest &request); + + void microFocusChanged(); + void contentsChanged(); + void databaseQuotaExceeded(QWebFrame* frame, QString databaseName); + void applicationCacheQuotaExceeded(QWebSecurityOrigin* origin, quint64 defaultOriginQuota); + + void saveFrameStateRequested(QWebFrame* frame, QWebHistoryItem* item); + void restoreFrameStateRequested(QWebFrame* frame); + + void viewportChangeRequested(); + + void featurePermissionRequested(QWebFrame* frame, QWebPage::Feature feature); + void featurePermissionRequestCanceled(QWebFrame* frame, QWebPage::Feature feature); + +protected: + virtual QWebPage *createWindow(WebWindowType type); + virtual QObject *createPlugin(const QString &classid, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues); + + virtual bool acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type); + virtual QString chooseFile(QWebFrame *originatingFrame, const QString& oldFile); + virtual void javaScriptAlert(QWebFrame *originatingFrame, const QString& msg); + virtual bool javaScriptConfirm(QWebFrame *originatingFrame, const QString& msg); + virtual bool javaScriptPrompt(QWebFrame *originatingFrame, const QString& msg, const QString& defaultValue, QString* result); + virtual void javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID); + + virtual QString userAgentForUrl(const QUrl& url) const; + +private: + Q_PRIVATE_SLOT(d, void _q_onLoadProgressChanged(int)) +#ifndef QT_NO_ACTION + Q_PRIVATE_SLOT(d, void _q_webActionTriggered(bool checked)) +#endif + Q_PRIVATE_SLOT(d, void _q_cleanupLeakMessages()) + + QWebPagePrivate *d; + + friend class QWebFrame; + friend class QWebPagePrivate; + friend class QWebView; + friend class QWebViewPrivate; + friend class QGraphicsWebView; + friend class QGraphicsWebViewPrivate; + friend class QWebInspector; + friend class WebCore::ChromeClientQt; + friend class WebCore::EditorClientQt; + friend class WebCore::FrameLoaderClientQt; + friend class WebCore::InspectorClientQt; + friend class WebCore::InspectorServerRequestHandlerQt; + friend class WebCore::InspectorFrontendClientQt; + friend class WebCore::NotificationPresenterClientQt; + friend class WebCore::GeolocationPermissionClientQt; + friend class WebCore::ResourceHandle; + friend class WebCore::QNetworkReplyHandler; + friend class DumpRenderTreeSupportQt; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QWebPage::FindFlags) + +#endif diff --git a/Source/WebKit/qt/Api/qwebpage_p.h b/Source/WebKit/qt/Api/qwebpage_p.h new file mode 100644 index 0000000..7bd1252 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebpage_p.h @@ -0,0 +1,218 @@ +/* + Copyright (C) 2008, 2009 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2008 Holger Hans Peter Freyther + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBPAGE_P_H +#define QWEBPAGE_P_H + +#include <qbasictimer.h> +#include <qnetworkproxy.h> +#include <qpointer.h> +#include <qevent.h> +#include <qgraphicssceneevent.h> + +#include "qwebpage.h" +#include "qwebhistory.h" +#include "qwebframe.h" + +#include "IntPoint.h" +#include "KURL.h" +#include "PlatformString.h" + +#include <wtf/OwnPtr.h> +#include <wtf/RefPtr.h> + +#include "ViewportArguments.h" + +namespace WebCore { + class ChromeClientQt; + class ContextMenuClientQt; + class ContextMenuItem; + class ContextMenu; + class Document; + class EditorClientQt; + class Element; + class InspectorController; + class IntRect; + class Node; + class NodeList; + class Page; + class Frame; +} + +QT_BEGIN_NAMESPACE +class QUndoStack; +class QMenu; +class QBitArray; +QT_END_NAMESPACE + +class QWebInspector; +class QWebPageClient; + +class QtViewportAttributesPrivate : public QSharedData { +public: + QtViewportAttributesPrivate(QWebPage::ViewportAttributes* qq) + : q(qq) + { } + + QWebPage::ViewportAttributes* q; +}; + +class QWebPagePrivate { +public: + QWebPagePrivate(QWebPage*); + ~QWebPagePrivate(); + + static WebCore::Page* core(const QWebPage*); + static QWebPagePrivate* priv(QWebPage*); + + void createMainFrame(); +#ifndef QT_NO_CONTEXTMENU + QMenu* createContextMenu(const WebCore::ContextMenu* webcoreMenu, const QList<WebCore::ContextMenuItem>* items, QBitArray* visitedWebActions); +#endif + void _q_onLoadProgressChanged(int); + void _q_webActionTriggered(bool checked); + void _q_cleanupLeakMessages(); + void updateAction(QWebPage::WebAction action); + void updateNavigationActions(); + void updateEditorActions(); + + void timerEvent(QTimerEvent*); + + template<class T> void mouseMoveEvent(T*); + template<class T> void mousePressEvent(T*); + template<class T> void mouseDoubleClickEvent(T*); + template<class T> void mouseTripleClickEvent(T*); + template<class T> void mouseReleaseEvent(T*); +#ifndef QT_NO_CONTEXTMENU + void contextMenuEvent(const QPoint& globalPos); +#endif +#ifndef QT_NO_WHEELEVENT + template<class T> void wheelEvent(T*); +#endif + void keyPressEvent(QKeyEvent*); + void keyReleaseEvent(QKeyEvent*); + void focusInEvent(QFocusEvent*); + void focusOutEvent(QFocusEvent*); + + template<class T> void dragEnterEvent(T*); + template<class T> void dragLeaveEvent(T*); + template<class T> void dragMoveEvent(T*); + template<class T> void dropEvent(T*); + + void inputMethodEvent(QInputMethodEvent*); + +#ifndef QT_NO_PROPERTIES + void dynamicPropertyChangeEvent(QDynamicPropertyChangeEvent*); +#endif + + void shortcutOverrideEvent(QKeyEvent*); + void leaveEvent(QEvent*); + void handleClipboard(QEvent*, Qt::MouseButton); + void handleSoftwareInputPanel(Qt::MouseButton, const QPoint&); + bool handleScrolling(QKeyEvent*, WebCore::Frame*); + + // Returns whether the default action was cancelled in the JS event handler + bool touchEvent(QTouchEvent*); + + class TouchAdjuster { + public: + TouchAdjuster(unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding); + + WebCore::IntPoint findCandidatePointForTouch(const WebCore::IntPoint&, WebCore::Document*) const; + + private: + unsigned m_topPadding; + unsigned m_rightPadding; + unsigned m_bottomPadding; + unsigned m_leftPadding; + }; + + void adjustPointForClicking(QMouseEvent*); +#if !defined(QT_NO_GRAPHICSVIEW) + void adjustPointForClicking(QGraphicsSceneMouseEvent*); +#endif + + void setInspector(QWebInspector*); + QWebInspector* getOrCreateInspector(); + WebCore::InspectorController* inspectorController(); + quint16 inspectorServerPort(); + + WebCore::ViewportArguments viewportArguments(); + +#ifndef QT_NO_SHORTCUT + static QWebPage::WebAction editorActionForKeyEvent(QKeyEvent* event); +#endif + static const char* editorCommandForWebActions(QWebPage::WebAction action); + + QWebPage *q; + WebCore::Page *page; + OwnPtr<QWebPageClient> client; + QPointer<QWebFrame> mainFrame; + +#ifndef QT_NO_UNDOSTACK + QUndoStack *undoStack; +#endif + + QWeakPointer<QWidget> view; + + bool insideOpenCall; + quint64 m_totalBytes; + quint64 m_bytesReceived; + + QPoint tripleClick; + QBasicTimer tripleClickTimer; + + bool clickCausedFocus; + + bool acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type); + QNetworkAccessManager *networkManager; + + bool forwardUnsupportedContent; + bool smartInsertDeleteEnabled; + bool selectTrailingWhitespaceEnabled; + QWebPage::LinkDelegationPolicy linkPolicy; + + QSize viewportSize; + QSize fixedLayoutSize; + qreal pixelRatio; + + QWebHistory history; + QWebHitTestResult hitTestResult; +#ifndef QT_NO_CONTEXTMENU + QPointer<QMenu> currentContextMenu; +#endif + QWebSettings *settings; + QPalette palette; + bool editable; + bool useFixedLayout; + + QAction *actions[QWebPage::WebActionCount]; + + QWebPluginFactory *pluginFactory; + + QWidget* inspectorFrontend; + QWebInspector* inspector; + bool inspectorIsInternalOnly; // True if created through the Inspect context menu action + Qt::DropAction m_lastDropAction; + + static bool drtRun; +}; + +#endif diff --git a/Source/WebKit/qt/Api/qwebplugindatabase.cpp b/Source/WebKit/qt/Api/qwebplugindatabase.cpp new file mode 100644 index 0000000..a7a3b5f --- /dev/null +++ b/Source/WebKit/qt/Api/qwebplugindatabase.cpp @@ -0,0 +1,393 @@ +/* + Copyright (C) 2009 Jakub Wieczorek <faw217@gmail.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qwebplugindatabase_p.h" + +#include "PluginDatabase.h" +#include "PluginPackage.h" + +using namespace WebCore; + +/*! + \internal + \typedef QWebPluginInfo::MimeType + \since 4.6 + \brief Represents a single MIME type supported by a plugin. +*/ + +/*! + \class QWebPluginInfo + \internal + \since 4.6 + \brief The QWebPluginInfo class represents a single Netscape plugin. + + A QWebPluginInfo object represents a Netscape plugin picked up by WebKit + and included in the plugin database. This class contains information about + the plugin, such as its name(), description(), a list of MIME types that it + supports (can be accessed with mimeTypes()) and the path of the plugin + file. + + Plugins can be enabled and disabled with setEnabled(). If a plugin is + disabled, it will not be used by WebKit to handle supported MIME types. To + check if a plugin is enabled or not, use enabled(). + + \sa QWebPluginDatabase +*/ + +/*! + Constructs a null QWebPluginInfo. +*/ +QWebPluginInfo::QWebPluginInfo() + : m_package(0) +{ +} + +QWebPluginInfo::QWebPluginInfo(PluginPackage* package) + : m_package(package) +{ + if (m_package) + m_package->ref(); +} + +/*! + Contructs a copy of \a other. +*/ +QWebPluginInfo::QWebPluginInfo(const QWebPluginInfo& other) + : m_package(other.m_package) +{ + if (m_package) + m_package->ref(); +} + +/*! + Destroys the plugin info. +*/ +QWebPluginInfo::~QWebPluginInfo() +{ + if (m_package) + m_package->deref(); +} + +/*! + Returns the name of the plugin. + + \sa description() +*/ +QString QWebPluginInfo::name() const +{ + if (!m_package) + return QString(); + return m_package->name(); +} + +/*! + Returns the description of the plugin. + + \sa name() +*/ +QString QWebPluginInfo::description() const +{ + if (!m_package) + return QString(); + return m_package->description(); +} + +/*! + Returns a list of MIME types supported by the plugin. + + \sa supportsMimeType() +*/ +QList<QWebPluginInfo::MimeType> QWebPluginInfo::mimeTypes() const +{ + if (m_package && m_mimeTypes.isEmpty()) { + const MIMEToDescriptionsMap& mimeToDescriptions = m_package->mimeToDescriptions(); + MIMEToDescriptionsMap::const_iterator end = mimeToDescriptions.end(); + + for (MIMEToDescriptionsMap::const_iterator it = mimeToDescriptions.begin(); it != end; ++it) { + MimeType mimeType; + mimeType.name = it->first; + mimeType.description = it->second; + + QStringList fileExtensions; + Vector<String> extensions = m_package->mimeToExtensions().get(mimeType.name); + + for (unsigned i = 0; i < extensions.size(); ++i) + fileExtensions.append(extensions[i]); + + mimeType.fileExtensions = fileExtensions; + m_mimeTypes.append(mimeType); + } + } + + return m_mimeTypes; +} + +/*! + Returns true if the plugin supports a specific \a mimeType; otherwise + returns false. + + \sa mimeTypes() +*/ +bool QWebPluginInfo::supportsMimeType(const QString& mimeType) const +{ + if (!m_package) + return false; + return m_package->mimeToDescriptions().contains(mimeType); +} + +/*! + Returns an absolute path to the plugin file. +*/ +QString QWebPluginInfo::path() const +{ + if (!m_package) + return QString(); + return m_package->path(); +} + +/*! + Returns true if the plugin is a null plugin; otherwise returns false. +*/ +bool QWebPluginInfo::isNull() const +{ + return !m_package; +} + +/*! + Enables or disables the plugin, depending on the \a enabled parameter. + + Disabled plugins will not be picked up by WebKit when looking for a plugin + supporting a particular MIME type. + + \sa isEnabled() +*/ +void QWebPluginInfo::setEnabled(bool enabled) +{ + if (!m_package) + return; + m_package->setEnabled(enabled); +} + +/*! + Returns true if the plugin is enabled; otherwise returns false. + + \sa setEnabled() +*/ +bool QWebPluginInfo::isEnabled() const +{ + if (!m_package) + return false; + return m_package->isEnabled(); +} + +/*! + Returns true if this plugin info is the same as the \a other plugin info. +*/ +bool QWebPluginInfo::operator==(const QWebPluginInfo& other) const +{ + return m_package == other.m_package; +} + +/*! + Returns true if this plugin info is different from the \a other plugin info. +*/ +bool QWebPluginInfo::operator!=(const QWebPluginInfo& other) const +{ + return m_package != other.m_package; +} + +/*! + Assigns the \a other plugin info to this plugin info, and returns a reference + to this plugin info. +*/ +QWebPluginInfo &QWebPluginInfo::operator=(const QWebPluginInfo& other) +{ + if (this == &other) + return *this; + + if (m_package) + m_package->deref(); + m_package = other.m_package; + if (m_package) + m_package->ref(); + m_mimeTypes = other.m_mimeTypes; + + return *this; +} + +/*! + \class QWebPluginDatabase + \internal + \since 4.6 + \brief The QWebPluginDatabase class provides an interface for managing + Netscape plugins used by WebKit in QWebPages. + + The QWebPluginDatabase class is a database of Netscape plugins that are used + by WebKit. The plugins are picked up by WebKit by looking up a set of search paths. + The default set can be accessed using defaultSearchPaths(). The search paths + can be changed, see searchPaths() and setSearchPaths(). Additional search paths + can also be added using addSearchPath(). + + The plugins that have been detected are exposed by the plugins() method. + The list contains QWebPlugin objects that hold both the metadata and the MIME + types that are supported by particular plugins. + + WebKit specifies a plugin for a MIME type by looking for the first plugin that + supports the specific MIME type. To get a plugin, that is used by WebKit to + handle a specific MIME type, you can use the pluginForMimeType() function. + + To change the way of resolving MIME types ambiguity, you can explicitly set + a preferred plugin for a specific MIME type, using setPreferredPluginForMimeType(). + + \sa QWebPluginInfo, QWebSettings::pluginDatabase() +*/ + +QWebPluginDatabase::QWebPluginDatabase(QObject* parent) + : QObject(parent) + , m_database(PluginDatabase::installedPlugins()) +{ +} + +QWebPluginDatabase::~QWebPluginDatabase() +{ +} + +/*! + Returns a list of plugins installed in the search paths. + + This list will contain disabled plugins, although they will not be used by + WebKit. + + \sa pluginForMimeType() +*/ +QList<QWebPluginInfo> QWebPluginDatabase::plugins() const +{ + QList<QWebPluginInfo> qwebplugins; + const Vector<PluginPackage*>& plugins = m_database->plugins(); + + for (unsigned int i = 0; i < plugins.size(); ++i) { + PluginPackage* plugin = plugins[i]; +#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE) + if (!plugin->ensurePluginLoaded()) + continue; +#endif + qwebplugins.append(QWebPluginInfo(plugin)); + } + + return qwebplugins; +} + +/*! + Returns a default set of search paths. + + \sa searchPaths(), setSearchPaths() +*/ +QStringList QWebPluginDatabase::defaultSearchPaths() +{ + QStringList paths; + + const Vector<String>& directories = PluginDatabase::defaultPluginDirectories(); + for (unsigned int i = 0; i < directories.size(); ++i) + paths.append(directories[i]); + + return paths; +} + +/*! + Returns a list of search paths that are used by WebKit to look for plugins. + + \sa defaultSearchPaths(), setSearchPaths() +*/ +QStringList QWebPluginDatabase::searchPaths() const +{ + QStringList paths; + + const Vector<String>& directories = m_database->pluginDirectories(); + for (unsigned int i = 0; i < directories.size(); ++i) + paths.append(directories[i]); + + return paths; +} + +/*! + Changes the search paths to \a paths. + The database is automatically refreshed. + + \sa searchPaths(), defaultSearchPaths() +*/ +void QWebPluginDatabase::setSearchPaths(const QStringList& paths) +{ + Vector<String> directories; + + for (int i = 0; i < paths.count(); ++i) + directories.append(paths.at(i)); + + m_database->setPluginDirectories(directories); + // PluginDatabase::setPluginDirectories() does not refresh the database. + m_database->refresh(); +} + +/*! + Adds an additional \a path to the current set. + The database is automatically refreshed. + + \sa searchPaths(), setSearchPaths() +*/ +void QWebPluginDatabase::addSearchPath(const QString& path) +{ + m_database->addExtraPluginDirectory(path); + // PluginDatabase::addExtraPluginDirectory() does refresh the database. +} + +/*! + Refreshes the plugin database, adds new plugins that have been found and removes + the ones that are no longer available in the search paths. + + You can call this function when the set of plugins installed in the search paths + changes. You do not need to call this function when changing search paths, + in that case WebKit automatically refreshes the database. +*/ +void QWebPluginDatabase::refresh() +{ + m_database->refresh(); +} + +/*! + Returns the plugin that is currently used by WebKit for a given \a mimeType. + + \sa setPreferredPluginForMimeType() +*/ +QWebPluginInfo QWebPluginDatabase::pluginForMimeType(const QString& mimeType) +{ + return QWebPluginInfo(m_database->pluginForMIMEType(mimeType)); +} + +/*! + Changes the preferred plugin for a given \a mimeType to \a plugin. The \a plugin + has to support the given \a mimeType, otherwise the setting will have no effect. + + Calling the function with a null \a plugin resets the setting. + + \sa pluginForMimeType() +*/ +void QWebPluginDatabase::setPreferredPluginForMimeType(const QString& mimeType, const QWebPluginInfo& plugin) +{ + m_database->setPreferredPluginForMIMEType(mimeType, plugin.m_package); +} diff --git a/Source/WebKit/qt/Api/qwebplugindatabase_p.h b/Source/WebKit/qt/Api/qwebplugindatabase_p.h new file mode 100644 index 0000000..b22c3de --- /dev/null +++ b/Source/WebKit/qt/Api/qwebplugindatabase_p.h @@ -0,0 +1,98 @@ +/* + Copyright (C) 2009 Jakub Wieczorek <faw217@gmail.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBPLUGINDATABASE_H +#define QWEBPLUGINDATABASE_H + +#include "qwebkitglobal.h" +#include "qwebpluginfactory.h" + +#include <QtCore/qobject.h> +#include <QtCore/qstringlist.h> + +namespace WebCore { + class PluginDatabase; + class PluginPackage; +} + +class QWebPluginInfoPrivate; +class QWEBKIT_EXPORT QWebPluginInfo { +public: + QWebPluginInfo(); + QWebPluginInfo(const QWebPluginInfo& other); + QWebPluginInfo &operator=(const QWebPluginInfo& other); + ~QWebPluginInfo(); + +private: + QWebPluginInfo(WebCore::PluginPackage* package); + +public: + typedef QWebPluginFactory::MimeType MimeType; + + QString name() const; + QString description() const; + QList<MimeType> mimeTypes() const; + bool supportsMimeType(const QString& mimeType) const; + QString path() const; + + bool isNull() const; + + void setEnabled(bool enabled); + bool isEnabled() const; + + bool operator==(const QWebPluginInfo& other) const; + bool operator!=(const QWebPluginInfo& other) const; + + friend class QWebPluginDatabase; + +private: + QWebPluginInfoPrivate* d; + WebCore::PluginPackage* m_package; + mutable QList<MimeType> m_mimeTypes; +}; + +class QWebPluginDatabasePrivate; +class QWEBKIT_EXPORT QWebPluginDatabase : public QObject { + Q_OBJECT + +private: + QWebPluginDatabase(QObject* parent = 0); + ~QWebPluginDatabase(); + +public: + QList<QWebPluginInfo> plugins() const; + + static QStringList defaultSearchPaths(); + QStringList searchPaths() const; + void setSearchPaths(const QStringList& paths); + void addSearchPath(const QString& path); + + void refresh(); + + QWebPluginInfo pluginForMimeType(const QString& mimeType); + void setPreferredPluginForMimeType(const QString& mimeType, const QWebPluginInfo& plugin); + + friend class QWebSettings; + +private: + QWebPluginDatabasePrivate* d; + WebCore::PluginDatabase* m_database; +}; + +#endif // QWEBPLUGINDATABASE_H diff --git a/Source/WebKit/qt/Api/qwebpluginfactory.cpp b/Source/WebKit/qt/Api/qwebpluginfactory.cpp new file mode 100644 index 0000000..b9180be --- /dev/null +++ b/Source/WebKit/qt/Api/qwebpluginfactory.cpp @@ -0,0 +1,264 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qwebpluginfactory.h" + +/*! + \class QWebPluginFactory + \since 4.4 + \brief The QWebPluginFactory class is used to embed custom data types in web pages. + + \inmodule QtWebKit + + The HTML \c{<object>} tag is used to embed arbitrary content into a web page, + for example: + + \code + <object type="application/x-pdf" data="http://qt.nokia.com/document.pdf" width="500" height="400"></object> + \endcode + + QtWebkit will natively handle the most basic data types like \c{text/html} and + \c{image/jpeg}, but for any advanced or custom data types you will need to + provide a handler yourself. + + QWebPluginFactory is a factory for creating plugins for QWebPage, where each + plugin provides support for one or more data types. A plugin factory can be + installed on a QWebPage using QWebPage::setPluginFactory(). + + \note The plugin factory is only used if plugins are enabled through QWebSettings. + + You provide a QWebPluginFactory by implementing the plugins() and the + create() methods. For plugins() it is necessary to describe the plugins the + factory can create, including a description and the supported MIME types. + The MIME types each plugin can handle should match the ones specified in + in the HTML \c{<object>} tag of your content. + + The create() method is called if the requested MIME type is supported. The + implementation has to return a new instance of the plugin requested for the + given MIME type and the specified URL. + + The plugins themselves are subclasses of QObject, but currently only plugins + based on either QWidget or QGraphicsWidget are supported. + +*/ + + +/*! + \class QWebPluginFactory::Plugin + \since 4.4 + \brief The QWebPluginFactory::Plugin structure describes the properties of a plugin a QWebPluginFactory can create. + + \inmodule QtWebKit +*/ + +/*! + \variable QWebPluginFactory::Plugin::name + The name of the plugin. +*/ + +/*! + \variable QWebPluginFactory::Plugin::description + The description of the plugin. +*/ + +/*! + \variable QWebPluginFactory::Plugin::mimeTypes + The list of mime types supported by the plugin. +*/ + +/*! + \class QWebPluginFactory::MimeType + \since 4.4 + \brief The QWebPluginFactory::MimeType structure describes a mime type supported by a plugin. + + \inmodule QtWebKit +*/ + +/*! + Returns true if this mimetype is the same as the \a other mime type. +*/ +bool QWebPluginFactory::MimeType::operator==(const MimeType& other) const +{ + return name == other.name + && description == other.description + && fileExtensions == other.fileExtensions; +} + +/*! + \fn bool QWebPluginFactory::MimeType::operator!=(const MimeType& other) const + + Returns true if this mimetype is different from the \a other mime type. +*/ + +/*! + \variable QWebPluginFactory::MimeType::name + + The full name of the MIME type; e.g., \c{text/plain} or \c{image/png}. +*/ + +/*! + \variable QWebPluginFactory::MimeType::description + The description of the mime type. +*/ + +/*! + \variable QWebPluginFactory::MimeType::fileExtensions + The list of file extensions that are used by this mime type. + + For example, a mime type for PDF documents would return "pdf" as its file extension. +*/ + +/*! + Constructs a QWebPluginFactory with parent \a parent. +*/ +QWebPluginFactory::QWebPluginFactory(QObject *parent) + : QObject(parent) +{ +} + +/*! + Destructor. +*/ +QWebPluginFactory::~QWebPluginFactory() +{ +} + +/*! + \fn QList<Plugin> QWebPluginFactory::plugins() const = 0 + + This function is reimplemented in subclasses to return a list of + supported plugins the factory can create. + + \note Currently, this function is only called when JavaScript programs + access the global \c plugins or \c mimetypes objects. +*/ + +/*! + This function is called to refresh the list of supported plugins. It may be called after a new plugin + has been installed in the system. +*/ +void QWebPluginFactory::refreshPlugins() +{ +} + +/*! + \fn QObject *QWebPluginFactory::create(const QString &mimeType, const QUrl &url, + const QStringList &argumentNames, const QStringList &argumentValues) const = 0 + + Implemented in subclasses to create a new plugin that can display content of + the MIME type given by \a mimeType. The URL of the content is provided in \a url. + The returned object should be a QWidget. + + The HTML object element can provide parameters through the \c{<param>} tag. + The name and the value attributes of these tags are specified by the + \a argumentNames and \a argumentValues string lists. + + For example: + + \code + <object type="application/x-pdf" data="http://qt.nokia.com/document.pdf" width="500" height="400"> + <param name="showTableOfContents" value="true" /> + <param name="hideThumbnails" value="false" /> + </object> + \endcode + + The above object element will result in a call to create() with the following arguments: + \table + \header \o Parameter + \o Value + \row \o mimeType + \o "application/x-pdf" + \row \o url + \o "http://qt.nokia.com/document.pdf" + \row \o argumentNames + \o "showTableOfContents" "hideThumbnails" + \row \o argumentVaues + \o "true" "false" + \endtable + + \note Ownership of the returned object will be transferred to the caller. +*/ + +/*! + \enum QWebPluginFactory::Extension + \internal + + This enum describes the types of extensions that the plugin factory can support. Before using these extensions, you + should verify that the extension is supported by calling supportsExtension(). + + Currently there are no extensions. +*/ + +/*! + \class QWebPluginFactory::ExtensionOption + \internal + \since 4.4 + \brief The ExtensionOption class provides an extended input argument to QWebPluginFactory's extension support. + + \inmodule QtWebKit + + \sa QWebPluginFactory::extension() +*/ + +/*! + \class QWebPluginFactory::ExtensionReturn + \internal + \since 4.4 + \brief The ExtensionOption class provides an extended output argument to QWebPluginFactory's extension support. + + \inmodule QtWebKit + + \sa QWebPluginFactory::extension() +*/ + +/*! + This virtual function can be reimplemented in a QWebPluginFactory subclass to provide support for extensions. The \a option + argument is provided as input to the extension; the output results can be stored in \a output. + + \internal + + The behaviour of this function is determined by \a extension. + + You can call supportsExtension() to check if an extension is supported by the factory. + + By default, no extensions are supported, and this function returns false. + + \sa supportsExtension(), Extension +*/ +bool QWebPluginFactory::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output) +{ + Q_UNUSED(extension) + Q_UNUSED(option) + Q_UNUSED(output) + return false; +} + +/*! + This virtual function returns true if the plugin factory supports \a extension; otherwise false is returned. + + \internal + + \sa extension() +*/ +bool QWebPluginFactory::supportsExtension(Extension extension) const +{ + Q_UNUSED(extension) + return false; +} diff --git a/Source/WebKit/qt/Api/qwebpluginfactory.h b/Source/WebKit/qt/Api/qwebpluginfactory.h new file mode 100644 index 0000000..4a06b59 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebpluginfactory.h @@ -0,0 +1,75 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBPLUGINFACTORY_H +#define QWEBPLUGINFACTORY_H + +#include "qwebkitglobal.h" + +#include <QtCore/qobject.h> +#include <QtCore/qstringlist.h> + +QT_BEGIN_NAMESPACE +class QUrl; +class QString; +QT_END_NAMESPACE +class QWebPluginFactoryPrivate; + +class QWEBKIT_EXPORT QWebPluginFactory : public QObject { + Q_OBJECT +public: + struct QWEBKIT_EXPORT MimeType { + QString name; + QString description; + QStringList fileExtensions; + bool operator==(const MimeType& other) const; + inline bool operator!=(const MimeType& other) const { return !operator==(other); } + }; + + struct Plugin { + QString name; + QString description; + QList<MimeType> mimeTypes; + }; + + explicit QWebPluginFactory(QObject* parent = 0); + virtual ~QWebPluginFactory(); + + virtual QList<Plugin> plugins() const = 0; + virtual void refreshPlugins(); + + virtual QObject *create(const QString& mimeType, + const QUrl&, + const QStringList& argumentNames, + const QStringList& argumentValues) const = 0; + + enum Extension { + }; + class ExtensionOption + {}; + class ExtensionReturn + {}; + virtual bool extension(Extension extension, const ExtensionOption* option = 0, ExtensionReturn* output = 0); + virtual bool supportsExtension(Extension extension) const; + +private: + QWebPluginFactoryPrivate* d; +}; + +#endif diff --git a/Source/WebKit/qt/Api/qwebscriptworld.cpp b/Source/WebKit/qt/Api/qwebscriptworld.cpp new file mode 100644 index 0000000..7a44813 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebscriptworld.cpp @@ -0,0 +1,62 @@ +/* + Copyright (C) 2010 Robert Hogan <robert@roberthogan.net> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qwebscriptworld.h" +#include "qwebscriptworld_p.h" + +#include "KURL.h" +#include "ScriptController.h" +#include <QStringList> + +using namespace WebCore; + +/*! + Constructs a security origin from \a other. +*/ +QWebScriptWorld::QWebScriptWorld() +{ +#if USE(JSC) + d = new QWebScriptWorldPrivate(ScriptController::createWorld()); +#endif +} + +QWebScriptWorld::QWebScriptWorld(const QWebScriptWorld& other) + : d(other.d) +{ +} + +QWebScriptWorld &QWebScriptWorld::operator=(const QWebScriptWorld& other) +{ + d = other.d; + return *this; +} + +DOMWrapperWorld* QWebScriptWorld::world() const +{ + return d ? d->world.get() : 0; +} + +/*! + Destroys the security origin. +*/ +QWebScriptWorld::~QWebScriptWorld() +{ +} + diff --git a/Source/WebKit/qt/Api/qwebscriptworld.h b/Source/WebKit/qt/Api/qwebscriptworld.h new file mode 100644 index 0000000..6a9d6e0 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebscriptworld.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2010 Robert Hogan <robert@roberthogan.net> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWebScriptWorld_h_ +#define QWebScriptWorld_h_ + +#include <QtCore/qurl.h> +#include <QtCore/qshareddata.h> + +#include "qwebkitglobal.h" + +namespace WebCore { + class DOMWrapperWorld; +} + +class QWebScriptWorldPrivate; +class QWebFrame; + +class QWEBKIT_EXPORT QWebScriptWorld { +public: + QWebScriptWorld(); + QWebScriptWorld(const QWebScriptWorld&); + QWebScriptWorld &operator=(const QWebScriptWorld&); + ~QWebScriptWorld(); + + WebCore::DOMWrapperWorld* world() const; + +private: + QExplicitlySharedDataPointer<QWebScriptWorldPrivate> d; + + friend class QWebFrame; +}; + +#endif diff --git a/Source/WebKit/qt/Api/qwebscriptworld_p.h b/Source/WebKit/qt/Api/qwebscriptworld_p.h new file mode 100644 index 0000000..7115eb2 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebscriptworld_p.h @@ -0,0 +1,44 @@ +/* + Copyright (C) 2010 Robert Hogan <robert@roberthogan.net> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _QWEBSCRIPTWORLD_P_H_ +#define _QWEBSCRIPTWORLD_P_H_ + +#include "RefPtr.h" + +namespace WebCore { + class DOMWrapperWorld; +} + +class QWebScriptWorldPrivate : public QSharedData { +public: + QWebScriptWorldPrivate(WTF::PassRefPtr<WebCore::DOMWrapperWorld> o) + { + Q_ASSERT(o); + world = o; + } + + ~QWebScriptWorldPrivate() + { + } + + WTF::RefPtr<WebCore::DOMWrapperWorld> world; +}; + +#endif diff --git a/Source/WebKit/qt/Api/qwebsecurityorigin.cpp b/Source/WebKit/qt/Api/qwebsecurityorigin.cpp new file mode 100644 index 0000000..97f887a --- /dev/null +++ b/Source/WebKit/qt/Api/qwebsecurityorigin.cpp @@ -0,0 +1,269 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qwebsecurityorigin.h" + +#include "ApplicationCacheStorage.h" +#include "DatabaseTracker.h" +#include "KURL.h" +#include "SchemeRegistry.h" +#include "SecurityOrigin.h" +#include "qwebdatabase.h" +#include "qwebdatabase_p.h" +#include "qwebsecurityorigin_p.h" +#include <QStringList> + +using namespace WebCore; + +/*! + \class QWebSecurityOrigin + \since 4.5 + \brief The QWebSecurityOrigin class defines a security boundary for web sites. + + \inmodule QtWebKit + + QWebSecurityOrigin provides access to the security domains defined by web sites. + An origin consists of a host name, a scheme, and a port number. Web sites + with the same security origin can access each other's resources for client-side + scripting or databases. + + For example the site \c{http://www.example.com/my/page.html} is allowed to share the same + database as \c{http://www.example.com/my/overview.html}, or access each other's + documents when used in HTML frame sets and JavaScript. At the same time it prevents + \c{http://www.malicious.com/evil.html} from accessing \c{http://www.example.com/}'s resources, + because they are of a different security origin. + + By default local schemes like \c{file://} and \c{qrc://} are concidered to be in the same + security origin, and can access each other's resources. You can add additional local schemes + by using QWebSecurityOrigin::addLocalScheme(), or override the default same-origin behavior + by setting QWebSettings::LocalContentCanAccessFileUrls to \c{false}. + + \note Local resources are by default restricted from accessing remote content, which + means your \c{file://} will not be able to access \c{http://domain.com/foo.html}. You + can relax this restriction by setting QWebSettings::LocalContentCanAccessRemoteUrls to + \c{true}. + + Call QWebFrame::securityOrigin() to get the QWebSecurityOrigin for a frame in a + web page, and use host(), scheme() and port() to identify the security origin. + + Use databases() to access the databases defined within a security origin. The + disk usage of the origin's databases can be limited with setDatabaseQuota(). + databaseQuota() and databaseUsage() report the current limit as well as the + current usage. + + For more information refer to the + \l{http://en.wikipedia.org/wiki/Same_origin_policy}{"Same origin policy" Wikipedia Article}. + + \sa QWebFrame::securityOrigin() +*/ + +/*! + Constructs a security origin from \a other. +*/ +QWebSecurityOrigin::QWebSecurityOrigin(const QWebSecurityOrigin& other) : d(other.d) +{ +} + +/*! + Assigns the \a other security origin to this. +*/ +QWebSecurityOrigin& QWebSecurityOrigin::operator=(const QWebSecurityOrigin& other) +{ + d = other.d; + return *this; +} + +/*! + Returns the scheme defining the security origin. +*/ +QString QWebSecurityOrigin::scheme() const +{ + return d->origin->protocol(); +} + +/*! + Returns the host name defining the security origin. +*/ +QString QWebSecurityOrigin::host() const +{ + return d->origin->host(); +} + +/*! + Returns the port number defining the security origin. +*/ +int QWebSecurityOrigin::port() const +{ + return d->origin->port(); +} + +/*! + Returns the number of bytes all databases in the security origin + use on the disk. +*/ +qint64 QWebSecurityOrigin::databaseUsage() const +{ +#if ENABLE(DATABASE) + return DatabaseTracker::tracker().usageForOrigin(d->origin.get()); +#else + return 0; +#endif +} + +/*! + Returns the quota for the databases in the security origin. +*/ +qint64 QWebSecurityOrigin::databaseQuota() const +{ +#if ENABLE(DATABASE) + return DatabaseTracker::tracker().quotaForOrigin(d->origin.get()); +#else + return 0; +#endif +} + +/*! + Sets the quota for the databases in the security origin to \a quota bytes. + + If the quota is set to a value less than the current usage, the quota will remain + and no data will be purged to meet the new quota. However, no new data can be added + to databases in this origin. +*/ +void QWebSecurityOrigin::setDatabaseQuota(qint64 quota) +{ +#if ENABLE(DATABASE) + DatabaseTracker::tracker().setQuota(d->origin.get(), quota); +#endif +} + +void QWebSecurityOrigin::setApplicationCacheQuota(qint64 quota) +{ +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + WebCore::cacheStorage().storeUpdatedQuotaForOrigin(d->origin.get(), quota); +#endif +} +/*! + Destroys the security origin. +*/ +QWebSecurityOrigin::~QWebSecurityOrigin() +{ +} + +/*! + \internal +*/ +QWebSecurityOrigin::QWebSecurityOrigin(QWebSecurityOriginPrivate* priv) +{ + d = priv; +} + +/*! + Returns a list of all security origins with a database quota defined. +*/ +QList<QWebSecurityOrigin> QWebSecurityOrigin::allOrigins() +{ + QList<QWebSecurityOrigin> webOrigins; + +#if ENABLE(DATABASE) + Vector<RefPtr<SecurityOrigin> > coreOrigins; + DatabaseTracker::tracker().origins(coreOrigins); + + for (unsigned i = 0; i < coreOrigins.size(); ++i) { + QWebSecurityOriginPrivate* priv = new QWebSecurityOriginPrivate(coreOrigins[i].get()); + webOrigins.append(priv); + } +#endif + + return webOrigins; +} + +/*! + Returns a list of all databases defined in the security origin. +*/ +QList<QWebDatabase> QWebSecurityOrigin::databases() const +{ + QList<QWebDatabase> databases; + +#if ENABLE(DATABASE) + Vector<String> nameVector; + + if (!DatabaseTracker::tracker().databaseNamesForOrigin(d->origin.get(), nameVector)) + return databases; + for (unsigned i = 0; i < nameVector.size(); ++i) { + QWebDatabasePrivate* priv = new QWebDatabasePrivate(); + priv->name = nameVector[i]; + priv->origin = this->d->origin; + QWebDatabase webDatabase(priv); + databases.append(webDatabase); + } +#endif + + return databases; +} + +/*! + \since 4.6 + + Adds the given \a scheme to the list of schemes that are considered equivalent + to the \c file: scheme. + + Cross domain restrictions depend on the two web settings QWebSettings::LocalContentCanAccessFileUrls + and QWebSettings::LocalContentCanAccessFileUrls. By default all local schemes are concidered to be + in the same security origin, and local schemes can not access remote content. +*/ +void QWebSecurityOrigin::addLocalScheme(const QString& scheme) +{ + SchemeRegistry::registerURLSchemeAsLocal(scheme); +} + +/*! + \since 4.6 + + Removes the given \a scheme from the list of local schemes. + + \note You can not remove the \c{file://} scheme from the list + of local schemes. + + \sa addLocalScheme() +*/ +void QWebSecurityOrigin::removeLocalScheme(const QString& scheme) +{ + SchemeRegistry::removeURLSchemeRegisteredAsLocal(scheme); +} + +/*! + \since 4.6 + Returns a list of all the schemes concidered to be local. + + By default this is \c{file://} and \c{qrc://}. + + \sa addLocalScheme(), removeLocalScheme() +*/ +QStringList QWebSecurityOrigin::localSchemes() +{ + QStringList list; + const URLSchemesMap& map = SchemeRegistry::localSchemes(); + URLSchemesMap::const_iterator end = map.end(); + for (URLSchemesMap::const_iterator i = map.begin(); i != end; ++i) { + const QString scheme = *i; + list.append(scheme); + } + return list; +} diff --git a/Source/WebKit/qt/Api/qwebsecurityorigin.h b/Source/WebKit/qt/Api/qwebsecurityorigin.h new file mode 100644 index 0000000..7328680 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebsecurityorigin.h @@ -0,0 +1,70 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _WEBSECURITYORIGIN_H_ +#define _WEBSECURITYORIGIN_H_ + +#include <QtCore/qurl.h> +#include <QtCore/qshareddata.h> + +#include "qwebkitglobal.h" + +namespace WebCore { + class SecurityOrigin; + class ChromeClientQt; +} + +class QWebSecurityOriginPrivate; +class QWebDatabase; +class QWebFrame; + +class QWEBKIT_EXPORT QWebSecurityOrigin { +public: + static QList<QWebSecurityOrigin> allOrigins(); + static void addLocalScheme(const QString& scheme); + static void removeLocalScheme(const QString& scheme); + static QStringList localSchemes(); + + ~QWebSecurityOrigin(); + + QString scheme() const; + QString host() const; + int port() const; + + qint64 databaseUsage() const; + qint64 databaseQuota() const; + + void setDatabaseQuota(qint64 quota); + void setApplicationCacheQuota(qint64 quota); + + QList<QWebDatabase> databases() const; + + QWebSecurityOrigin(const QWebSecurityOrigin& other); + QWebSecurityOrigin &operator=(const QWebSecurityOrigin& other); +private: + friend class QWebDatabase; + friend class QWebFrame; + friend class WebCore::ChromeClientQt; + QWebSecurityOrigin(QWebSecurityOriginPrivate* priv); + +private: + QExplicitlySharedDataPointer<QWebSecurityOriginPrivate> d; +}; + +#endif diff --git a/Source/WebKit/qt/Api/qwebsecurityorigin_p.h b/Source/WebKit/qt/Api/qwebsecurityorigin_p.h new file mode 100644 index 0000000..cdc93bd --- /dev/null +++ b/Source/WebKit/qt/Api/qwebsecurityorigin_p.h @@ -0,0 +1,39 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _WEBSECURITYORIGIN_P_H_ +#define _WEBSECURITYORIGIN_P_H_ + +#include "SecurityOrigin.h" +#include "RefPtr.h" + +class QWebSecurityOriginPrivate : public QSharedData { +public: + QWebSecurityOriginPrivate(WebCore::SecurityOrigin* o) + { + Q_ASSERT(o); + origin = o; + } + ~QWebSecurityOriginPrivate() + { + } + WTF::RefPtr<WebCore::SecurityOrigin> origin; +}; + +#endif diff --git a/Source/WebKit/qt/Api/qwebsettings.cpp b/Source/WebKit/qt/Api/qwebsettings.cpp new file mode 100644 index 0000000..9bb187e --- /dev/null +++ b/Source/WebKit/qt/Api/qwebsettings.cpp @@ -0,0 +1,1130 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qwebsettings.h" + +#include "qwebpage.h" +#include "qwebpage_p.h" +#include "qwebplugindatabase_p.h" + +#include "AbstractDatabase.h" +#include "MemoryCache.h" +#include "CrossOriginPreflightResultCache.h" +#include "FontCache.h" +#include "Page.h" +#include "PageCache.h" +#include "Settings.h" +#include "KURL.h" +#include "PlatformString.h" +#include "IconDatabase.h" +#include "PluginDatabase.h" +#include "Image.h" +#include "IntSize.h" +#include "ApplicationCacheStorage.h" +#include "DatabaseTracker.h" +#include "FileSystem.h" + +#include <QApplication> +#include <QDesktopServices> +#include <QDir> +#include <QHash> +#include <QSharedData> +#include <QUrl> +#include <QFileInfo> +#include <QStyle> + +#include "NetworkStateNotifier.h" + +void QWEBKIT_EXPORT qt_networkAccessAllowed(bool isAllowed) +{ +#if ENABLE(QT_BEARER) + WebCore::networkStateNotifier().setNetworkAccessAllowed(isAllowed); +#endif +} + +class QWebSettingsPrivate { +public: + QWebSettingsPrivate(WebCore::Settings* wcSettings = 0) + : settings(wcSettings) + { + } + + QHash<int, QString> fontFamilies; + QHash<int, int> fontSizes; + QHash<int, bool> attributes; + QUrl userStyleSheetLocation; + QString defaultTextEncoding; + QString localStoragePath; + QString offlineWebApplicationCachePath; + qint64 offlineStorageDefaultQuota; + + void apply(); + WebCore::Settings* settings; +}; + +typedef QHash<int, QPixmap> WebGraphicHash; +Q_GLOBAL_STATIC(WebGraphicHash, _graphics) + +static void earlyClearGraphics() +{ + _graphics()->clear(); +} + +static WebGraphicHash* graphics() +{ + WebGraphicHash* hash = _graphics(); + + if (hash->isEmpty()) { + + // prevent ~QPixmap running after ~QApplication (leaks native pixmaps) + qAddPostRoutine(earlyClearGraphics); + + hash->insert(QWebSettings::MissingImageGraphic, QPixmap(QLatin1String(":webkit/resources/missingImage.png"))); + hash->insert(QWebSettings::MissingPluginGraphic, QPixmap(QLatin1String(":webkit/resources/nullPlugin.png"))); + hash->insert(QWebSettings::DefaultFrameIconGraphic, QPixmap(QLatin1String(":webkit/resources/urlIcon.png"))); + hash->insert(QWebSettings::TextAreaSizeGripCornerGraphic, QPixmap(QLatin1String(":webkit/resources/textAreaResizeCorner.png"))); + hash->insert(QWebSettings::DeleteButtonGraphic, QPixmap(QLatin1String(":webkit/resources/deleteButton.png"))); + hash->insert(QWebSettings::InputSpeechButtonGraphic, QPixmap(QLatin1String(":webkit/resources/inputSpeech.png"))); + hash->insert(QWebSettings::SearchCancelButtonGraphic, QApplication::style()->standardPixmap(QStyle::SP_DialogCloseButton)); + hash->insert(QWebSettings::SearchCancelButtonPressedGraphic, QApplication::style()->standardPixmap(QStyle::SP_DialogCloseButton)); + } + + return hash; +} + +Q_GLOBAL_STATIC(QList<QWebSettingsPrivate*>, allSettings); + +void QWebSettingsPrivate::apply() +{ + if (settings) { + settings->setTextAreasAreResizable(true); + + QWebSettingsPrivate* global = QWebSettings::globalSettings()->d; + + QString family = fontFamilies.value(QWebSettings::StandardFont, + global->fontFamilies.value(QWebSettings::StandardFont)); + settings->setStandardFontFamily(family); + + family = fontFamilies.value(QWebSettings::FixedFont, + global->fontFamilies.value(QWebSettings::FixedFont)); + settings->setFixedFontFamily(family); + + family = fontFamilies.value(QWebSettings::SerifFont, + global->fontFamilies.value(QWebSettings::SerifFont)); + settings->setSerifFontFamily(family); + + family = fontFamilies.value(QWebSettings::SansSerifFont, + global->fontFamilies.value(QWebSettings::SansSerifFont)); + settings->setSansSerifFontFamily(family); + + family = fontFamilies.value(QWebSettings::CursiveFont, + global->fontFamilies.value(QWebSettings::CursiveFont)); + settings->setCursiveFontFamily(family); + + family = fontFamilies.value(QWebSettings::FantasyFont, + global->fontFamilies.value(QWebSettings::FantasyFont)); + settings->setFantasyFontFamily(family); + + int size = fontSizes.value(QWebSettings::MinimumFontSize, + global->fontSizes.value(QWebSettings::MinimumFontSize)); + settings->setMinimumFontSize(size); + + size = fontSizes.value(QWebSettings::MinimumLogicalFontSize, + global->fontSizes.value(QWebSettings::MinimumLogicalFontSize)); + settings->setMinimumLogicalFontSize(size); + + size = fontSizes.value(QWebSettings::DefaultFontSize, + global->fontSizes.value(QWebSettings::DefaultFontSize)); + settings->setDefaultFontSize(size); + + size = fontSizes.value(QWebSettings::DefaultFixedFontSize, + global->fontSizes.value(QWebSettings::DefaultFixedFontSize)); + settings->setDefaultFixedFontSize(size); + + bool value = attributes.value(QWebSettings::AutoLoadImages, + global->attributes.value(QWebSettings::AutoLoadImages)); + settings->setLoadsImagesAutomatically(value); + + value = attributes.value(QWebSettings::JavascriptEnabled, + global->attributes.value(QWebSettings::JavascriptEnabled)); + settings->setJavaScriptEnabled(value); +#if USE(ACCELERATED_COMPOSITING) + value = attributes.value(QWebSettings::AcceleratedCompositingEnabled, + global->attributes.value(QWebSettings::AcceleratedCompositingEnabled)); + + settings->setAcceleratedCompositingEnabled(value); +#endif +#if ENABLE(3D_CANVAS) + value = attributes.value(QWebSettings::WebGLEnabled, + global->attributes.value(QWebSettings::WebGLEnabled)); + + settings->setWebGLEnabled(value); +#endif + + value = attributes.value(QWebSettings::HyperlinkAuditingEnabled, + global->attributes.value(QWebSettings::HyperlinkAuditingEnabled)); + + settings->setHyperlinkAuditingEnabled(value); + + value = attributes.value(QWebSettings::JavascriptCanOpenWindows, + global->attributes.value(QWebSettings::JavascriptCanOpenWindows)); + settings->setJavaScriptCanOpenWindowsAutomatically(value); + + value = attributes.value(QWebSettings::JavascriptCanCloseWindows, + global->attributes.value(QWebSettings::JavascriptCanCloseWindows)); + settings->setAllowScriptsToCloseWindows(value); + + value = attributes.value(QWebSettings::JavaEnabled, + global->attributes.value(QWebSettings::JavaEnabled)); + settings->setJavaEnabled(value); + + value = attributes.value(QWebSettings::PluginsEnabled, + global->attributes.value(QWebSettings::PluginsEnabled)); + settings->setPluginsEnabled(value); + + value = attributes.value(QWebSettings::PrivateBrowsingEnabled, + global->attributes.value(QWebSettings::PrivateBrowsingEnabled)); + settings->setPrivateBrowsingEnabled(value); + + value = attributes.value(QWebSettings::SpatialNavigationEnabled, + global->attributes.value(QWebSettings::SpatialNavigationEnabled)); + settings->setSpatialNavigationEnabled(value); + + value = attributes.value(QWebSettings::JavascriptCanAccessClipboard, + global->attributes.value(QWebSettings::JavascriptCanAccessClipboard)); + settings->setDOMPasteAllowed(value); + settings->setJavaScriptCanAccessClipboard(value); + + value = attributes.value(QWebSettings::DeveloperExtrasEnabled, + global->attributes.value(QWebSettings::DeveloperExtrasEnabled)); + settings->setDeveloperExtrasEnabled(value); + + value = attributes.value(QWebSettings::FrameFlatteningEnabled, + global->attributes.value(QWebSettings::FrameFlatteningEnabled)); + settings->setFrameFlatteningEnabled(value); + + QUrl location = !userStyleSheetLocation.isEmpty() ? userStyleSheetLocation : global->userStyleSheetLocation; + settings->setUserStyleSheetLocation(WebCore::KURL(location)); + + QString encoding = !defaultTextEncoding.isEmpty() ? defaultTextEncoding: global->defaultTextEncoding; + settings->setDefaultTextEncodingName(encoding); + + QString storagePath = !localStoragePath.isEmpty() ? localStoragePath : global->localStoragePath; + settings->setLocalStorageDatabasePath(storagePath); + + value = attributes.value(QWebSettings::PrintElementBackgrounds, + global->attributes.value(QWebSettings::PrintElementBackgrounds)); + settings->setShouldPrintBackgrounds(value); + +#if ENABLE(DATABASE) + value = attributes.value(QWebSettings::OfflineStorageDatabaseEnabled, + global->attributes.value(QWebSettings::OfflineStorageDatabaseEnabled)); + WebCore::AbstractDatabase::setIsAvailable(value); +#endif + + value = attributes.value(QWebSettings::OfflineWebApplicationCacheEnabled, + global->attributes.value(QWebSettings::OfflineWebApplicationCacheEnabled)); + settings->setOfflineWebApplicationCacheEnabled(value); + + value = attributes.value(QWebSettings::LocalStorageEnabled, + global->attributes.value(QWebSettings::LocalStorageEnabled)); + settings->setLocalStorageEnabled(value); + + value = attributes.value(QWebSettings::LocalContentCanAccessRemoteUrls, + global->attributes.value(QWebSettings::LocalContentCanAccessRemoteUrls)); + settings->setAllowUniversalAccessFromFileURLs(value); + + value = attributes.value(QWebSettings::LocalContentCanAccessFileUrls, + global->attributes.value(QWebSettings::LocalContentCanAccessFileUrls)); + settings->setAllowFileAccessFromFileURLs(value); + + value = attributes.value(QWebSettings::XSSAuditingEnabled, + global->attributes.value(QWebSettings::XSSAuditingEnabled)); + settings->setXSSAuditorEnabled(value); + +#if ENABLE(TILED_BACKING_STORE) + value = attributes.value(QWebSettings::TiledBackingStoreEnabled, + global->attributes.value(QWebSettings::TiledBackingStoreEnabled)); + settings->setTiledBackingStoreEnabled(value); +#endif + + value = attributes.value(QWebSettings::SiteSpecificQuirksEnabled, + global->attributes.value(QWebSettings::SiteSpecificQuirksEnabled)); + settings->setNeedsSiteSpecificQuirks(value); + + settings->setUsesPageCache(WebCore::pageCache()->capacity()); + } else { + QList<QWebSettingsPrivate*> settings = *::allSettings(); + for (int i = 0; i < settings.count(); ++i) + settings[i]->apply(); + } +} + +/*! + Returns the global settings object. + + Any setting changed on the default object is automatically applied to all + QWebPage instances where the particular setting is not overriden already. +*/ +QWebSettings* QWebSettings::globalSettings() +{ + static QWebSettings* global = 0; + if (!global) + global = new QWebSettings; + return global; +} + +/*! + \class QWebSettings + \since 4.4 + \brief The QWebSettings class provides an object to store the settings used + by QWebPage and QWebFrame. + + \inmodule QtWebKit + + Each QWebPage object has its own QWebSettings object, which configures the + settings for that page. If a setting is not configured, then it is looked + up in the global settings object, which can be accessed using + globalSettings(). + + QWebSettings allows configuration of browser properties, such as font sizes and + families, the location of a custom style sheet, and generic attributes like + JavaScript and plugins. Individual attributes are set using the setAttribute() + function. The \l{QWebSettings::WebAttribute}{WebAttribute} enum further describes + each attribute. + + QWebSettings also configures global properties such as the web page memory + cache, icon database, local database storage and offline + applications storage. + + \section1 Enabling Plugins + + Support for browser plugins can enabled by setting the + \l{QWebSettings::PluginsEnabled}{PluginsEnabled} attribute. For many applications, + this attribute is enabled for all pages by setting it on the + \l{globalSettings()}{global settings object}. QtWebKit will always ignore this setting + when processing Qt plugins. The decision to allow a Qt plugin is made by the client + in its reimplementation of QWebPage::createPlugin(). + + \section1 Web Application Support + + WebKit provides support for features specified in \l{HTML 5} that improve the + performance and capabilities of Web applications. These include client-side + (offline) storage and the use of a Web application cache. + + Client-side (offline) storage is an improvement over the use of cookies to + store persistent data in Web applications. Applications can configure and + enable the use of an offline storage database by calling the + setOfflineStoragePath() with an appropriate file path, and can limit the quota + for each application by calling setOfflineStorageDefaultQuota(). + + \sa QWebPage::settings(), QWebView::settings(), {Web Browser} +*/ + +/*! + \enum QWebSettings::FontFamily + + This enum describes the generic font families defined by CSS 2. + For more information see the + \l{http://www.w3.org/TR/REC-CSS2/fonts.html#generic-font-families}{CSS standard}. + + \value StandardFont + \value FixedFont + \value SerifFont + \value SansSerifFont + \value CursiveFont + \value FantasyFont +*/ + +/*! + \enum QWebSettings::FontSize + + This enum describes the font sizes configurable through QWebSettings. + + \value MinimumFontSize The hard minimum font size. + \value MinimumLogicalFontSize The minimum logical font size that is applied + when zooming out with QWebFrame::setTextSizeMultiplier(). + \value DefaultFontSize The default font size for regular text. + \value DefaultFixedFontSize The default font size for fixed-pitch text. +*/ + +/*! + \enum QWebSettings::WebGraphic + + This enums describes the standard graphical elements used in webpages. + + \value MissingImageGraphic The replacement graphic shown when an image could not be loaded. + \value MissingPluginGraphic The replacement graphic shown when a plugin could not be loaded. + \value DefaultFrameIconGraphic The default icon for QWebFrame::icon(). + \value TextAreaSizeGripCornerGraphic The graphic shown for the size grip of text areas. + \value DeleteButtonGraphic The graphic shown for the WebKit-Editing-Delete-Button in Deletion UI. + \value InputSpeechButtonGraphic The graphic shown in input fields that support speech recognition. + \value SearchCancelButtonGraphic The graphic shown for clearing the text in a search field. + \value SearchCancelButtonPressedGraphic The graphic shown when SearchCancelButtonGraphic is pressed. +*/ + +/*! + \enum QWebSettings::WebAttribute + + This enum describes various attributes that are configurable through QWebSettings. + + \value AutoLoadImages Specifies whether images are automatically loaded in + web pages. This is enabled by default. + \value DnsPrefetchEnabled Specifies whether QtWebkit will try to pre-fetch DNS entries to + speed up browsing. This only works as a global attribute. Only for Qt 4.6 and later. This is disabled by default. + \value JavascriptEnabled Enables or disables the running of JavaScript + programs. This is enabled by default + \value JavaEnabled Enables or disables Java applets. + Currently Java applets are not supported. + \value PluginsEnabled Enables or disables plugins in Web pages (e.g. using NPAPI). Qt plugins + with a mimetype such as "application/x-qt-plugin" are not affected by this setting. This is disabled by default. + \value PrivateBrowsingEnabled Private browsing prevents WebKit from + recording visited pages in the history and storing web page icons. This is disabled by default. + \value JavascriptCanOpenWindows Specifies whether JavaScript programs + can open new windows. This is disabled by default. + \value JavascriptCanCloseWindows Specifies whether JavaScript programs + can close windows. This is disabled by default. + \value JavascriptCanAccessClipboard Specifies whether JavaScript programs + can read or write to the clipboard. This is disabled by default. + \value DeveloperExtrasEnabled Enables extra tools for Web developers. + Currently this enables the "Inspect" element in the context menu as + well as the use of QWebInspector which controls the web inspector + for web site debugging. This is disabled by default. + \value SpatialNavigationEnabled Enables or disables the Spatial Navigation + feature, which consists in the ability to navigate between focusable + elements in a Web page, such as hyperlinks and form controls, by using + Left, Right, Up and Down arrow keys. For example, if a user presses the + Right key, heuristics determine whether there is an element he might be + trying to reach towards the right and which element he probably wants. + This is disabled by default. + \value LinksIncludedInFocusChain Specifies whether hyperlinks should be + included in the keyboard focus chain. This is enabled by default. + \value ZoomTextOnly Specifies whether the zoom factor on a frame applies + only to the text or to all content. This is disabled by default. + \value PrintElementBackgrounds Specifies whether the background color and images + are also drawn when the page is printed. This is enabled by default. + \value OfflineStorageDatabaseEnabled Specifies whether support for the HTML 5 + offline storage feature is enabled or not. This is disabled by default. + \value OfflineWebApplicationCacheEnabled Specifies whether support for the HTML 5 + web application cache feature is enabled or not. This is disabled by default. + \value LocalStorageEnabled Specifies whether support for the HTML 5 + local storage feature is enabled or not. This is disabled by default. + \value LocalStorageDatabaseEnabled \e{This enum value is deprecated.} Use + QWebSettings::LocalStorageEnabled instead. + \value LocalContentCanAccessRemoteUrls Specifies whether locally loaded documents are + allowed to access remote urls. This is disabled by default. For more information + about security origins and local vs. remote content see QWebSecurityOrigin. + \value LocalContentCanAccessFileUrls Specifies whether locally loaded documents are + allowed to access other local urls. This is enabled by default. For more information + about security origins and local vs. remote content see QWebSecurityOrigin. + \value XSSAuditingEnabled Specifies whether load requests should be monitored for cross-site + scripting attempts. Suspicious scripts will be blocked and reported in the inspector's + JavaScript console. Enabling this feature might have an impact on performance + and it is disabled by default. + \value AcceleratedCompositingEnabled This feature, when used in conjunction with + QGraphicsWebView, accelerates animations of web content. CSS animations of the transform and + opacity properties will be rendered by composing the cached content of the animated elements. + This is enabled by default. + \value TiledBackingStoreEnabled This setting enables the tiled backing store feature + for a QGraphicsWebView. With the tiled backing store enabled, the web page contents in and around + the current visible area is speculatively cached to bitmap tiles. The tiles are automatically kept + in sync with the web page as it changes. Enabling tiling can significantly speed up painting heavy + operations like scrolling. Enabling the feature increases memory consumption. It does not work well + with contents using CSS fixed positioning (see also \l{QGraphicsWebView::}{resizesToContents} property). + \l{QGraphicsWebView::}{tiledBackingStoreFrozen} property allows application to temporarily + freeze the contents of the backing store. This is disabled by default. + \value FrameFlatteningEnabled With this setting each subframe is expanded to its contents. + On touch devices, it is desired to not have any scrollable sub parts of the page + as it results in a confusing user experience, with scrolling sometimes scrolling sub parts + and at other times scrolling the page itself. For this reason iframes and framesets are + barely usable on touch devices. This will flatten all the frames to become one scrollable page. + This is disabled by default. + \value SiteSpecificQuirksEnabled This setting enables WebKit's workaround for broken sites. It is + enabled by default. +*/ + +/*! + \internal +*/ +QWebSettings::QWebSettings() + : d(new QWebSettingsPrivate) +{ + // Initialize our global defaults + d->fontSizes.insert(QWebSettings::MinimumFontSize, 0); + d->fontSizes.insert(QWebSettings::MinimumLogicalFontSize, 0); + d->fontSizes.insert(QWebSettings::DefaultFontSize, 16); + d->fontSizes.insert(QWebSettings::DefaultFixedFontSize, 13); + + QFont defaultFont; + defaultFont.setStyleHint(QFont::Serif); + d->fontFamilies.insert(QWebSettings::StandardFont, defaultFont.defaultFamily()); + d->fontFamilies.insert(QWebSettings::SerifFont, defaultFont.defaultFamily()); + +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) + defaultFont.setStyleHint(QFont::Fantasy); + d->fontFamilies.insert(QWebSettings::FantasyFont, defaultFont.defaultFamily()); + + defaultFont.setStyleHint(QFont::Cursive); + d->fontFamilies.insert(QWebSettings::CursiveFont, defaultFont.defaultFamily()); +#else + d->fontFamilies.insert(QWebSettings::FantasyFont, defaultFont.defaultFamily()); + d->fontFamilies.insert(QWebSettings::CursiveFont, defaultFont.defaultFamily()); +#endif + + defaultFont.setStyleHint(QFont::SansSerif); + d->fontFamilies.insert(QWebSettings::SansSerifFont, defaultFont.defaultFamily()); + +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) + defaultFont.setStyleHint(QFont::Monospace); +#else + defaultFont.setStyleHint(QFont::TypeWriter); +#endif + d->fontFamilies.insert(QWebSettings::FixedFont, defaultFont.defaultFamily()); + + d->attributes.insert(QWebSettings::AutoLoadImages, true); + d->attributes.insert(QWebSettings::DnsPrefetchEnabled, false); + d->attributes.insert(QWebSettings::JavascriptEnabled, true); + d->attributes.insert(QWebSettings::SpatialNavigationEnabled, false); + d->attributes.insert(QWebSettings::LinksIncludedInFocusChain, true); + d->attributes.insert(QWebSettings::ZoomTextOnly, false); + d->attributes.insert(QWebSettings::PrintElementBackgrounds, true); + d->attributes.insert(QWebSettings::OfflineStorageDatabaseEnabled, false); + d->attributes.insert(QWebSettings::OfflineWebApplicationCacheEnabled, false); + d->attributes.insert(QWebSettings::LocalStorageEnabled, false); + d->attributes.insert(QWebSettings::LocalContentCanAccessRemoteUrls, false); + d->attributes.insert(QWebSettings::LocalContentCanAccessFileUrls, true); + d->attributes.insert(QWebSettings::AcceleratedCompositingEnabled, true); + d->attributes.insert(QWebSettings::WebGLEnabled, false); + d->attributes.insert(QWebSettings::HyperlinkAuditingEnabled, false); + d->attributes.insert(QWebSettings::TiledBackingStoreEnabled, false); + d->attributes.insert(QWebSettings::FrameFlatteningEnabled, false); + d->attributes.insert(QWebSettings::SiteSpecificQuirksEnabled, true); + d->offlineStorageDefaultQuota = 5 * 1024 * 1024; + d->defaultTextEncoding = QLatin1String("iso-8859-1"); +} + +/*! + \internal +*/ +QWebSettings::QWebSettings(WebCore::Settings* settings) + : d(new QWebSettingsPrivate(settings)) +{ + d->settings = settings; + d->apply(); + allSettings()->append(d); +} + +/*! + \internal +*/ +QWebSettings::~QWebSettings() +{ + if (d->settings) + allSettings()->removeAll(d); + + delete d; +} + +/*! + Sets the font size for \a type to \a size. +*/ +void QWebSettings::setFontSize(FontSize type, int size) +{ + d->fontSizes.insert(type, size); + d->apply(); +} + +/*! + Returns the default font size for \a type. +*/ +int QWebSettings::fontSize(FontSize type) const +{ + int defaultValue = 0; + if (d->settings) { + QWebSettingsPrivate* global = QWebSettings::globalSettings()->d; + defaultValue = global->fontSizes.value(type); + } + return d->fontSizes.value(type, defaultValue); +} + +/*! + Resets the font size for \a type to the size specified in the global + settings object. + + This function has no effect on the global QWebSettings instance. +*/ +void QWebSettings::resetFontSize(FontSize type) +{ + if (d->settings) { + d->fontSizes.remove(type); + d->apply(); + } +} + +/*! + Specifies the location of a user stylesheet to load with every web page. + + The \a location must be either a path on the local filesystem, or a data URL + with UTF-8 and Base64 encoded data, such as: + + "data:text/css;charset=utf-8;base64,cCB7IGJhY2tncm91bmQtY29sb3I6IHJlZCB9Ow==" + + \note If the base64 data is not valid, the style will not be applied. + + \sa userStyleSheetUrl() +*/ +void QWebSettings::setUserStyleSheetUrl(const QUrl& location) +{ + d->userStyleSheetLocation = location; + d->apply(); +} + +/*! + Returns the location of the user stylesheet. + + \sa setUserStyleSheetUrl() +*/ +QUrl QWebSettings::userStyleSheetUrl() const +{ + return d->userStyleSheetLocation; +} + +/*! + \since 4.6 + Specifies the default text encoding system. + + The \a encoding, must be a string describing an encoding such as "utf-8", + "iso-8859-1", etc. If left empty a default value will be used. For a more + extensive list of encoding names see \l{QTextCodec} + + \sa defaultTextEncoding() +*/ +void QWebSettings::setDefaultTextEncoding(const QString& encoding) +{ + d->defaultTextEncoding = encoding; + d->apply(); +} + +/*! + \since 4.6 + Returns the default text encoding. + + \sa setDefaultTextEncoding() +*/ +QString QWebSettings::defaultTextEncoding() const +{ + return d->defaultTextEncoding; +} + +/*! + Sets the path of the icon database to \a path. The icon database is used + to store "favicons" associated with web sites. + + \a path must point to an existing directory. + + Setting an empty path disables the icon database. + + \sa iconDatabasePath(), clearIconDatabase() +*/ +void QWebSettings::setIconDatabasePath(const QString& path) +{ + WebCore::iconDatabase()->delayDatabaseCleanup(); + + if (!path.isEmpty()) { + WebCore::iconDatabase()->setEnabled(true); + QFileInfo info(path); + if (info.isDir() && info.isWritable()) + WebCore::iconDatabase()->open(path); + } else { + WebCore::iconDatabase()->setEnabled(false); + WebCore::iconDatabase()->close(); + } +} + +/*! + Returns the path of the icon database or an empty string if the icon + database is disabled. + + \sa setIconDatabasePath(), clearIconDatabase() +*/ +QString QWebSettings::iconDatabasePath() +{ + if (WebCore::iconDatabase()->isEnabled() && WebCore::iconDatabase()->isOpen()) + return WebCore::iconDatabase()->databasePath(); + else + return QString(); +} + +/*! + Clears the icon database. +*/ +void QWebSettings::clearIconDatabase() +{ + if (WebCore::iconDatabase()->isEnabled() && WebCore::iconDatabase()->isOpen()) + WebCore::iconDatabase()->removeAllIcons(); +} + +/*! + Returns the web site's icon for \a url. + + If the web site does not specify an icon \bold OR if the icon is not in the + database, a null QIcon is returned. + + \note The returned icon's size is arbitrary. + + \sa setIconDatabasePath() +*/ +QIcon QWebSettings::iconForUrl(const QUrl& url) +{ + WebCore::Image* image = WebCore::iconDatabase()->iconForPageURL(WebCore::KURL(url).string(), + WebCore::IntSize(16, 16)); + if (!image) + return QPixmap(); + + QPixmap* icon = image->nativeImageForCurrentFrame(); + if (!icon) + return QPixmap(); + + return* icon; +} + +/* + Returns the plugin database object. + +QWebPluginDatabase *QWebSettings::pluginDatabase() +{ + static QWebPluginDatabase* database = 0; + if (!database) + database = new QWebPluginDatabase(); + return database; +} +*/ + +/*! + Sets \a graphic to be drawn when QtWebKit needs to draw an image of the + given \a type. + + For example, when an image cannot be loaded, the pixmap specified by + \l{QWebSettings::WebGraphic}{MissingImageGraphic} is drawn instead. + + \sa webGraphic() +*/ +void QWebSettings::setWebGraphic(WebGraphic type, const QPixmap& graphic) +{ + WebGraphicHash* h = graphics(); + if (graphic.isNull()) + h->remove(type); + else + h->insert(type, graphic); +} + +/*! + Returns a previously set pixmap used to draw replacement graphics of the + specified \a type. + + \sa setWebGraphic() +*/ +QPixmap QWebSettings::webGraphic(WebGraphic type) +{ + return graphics()->value(type); +} + +/*! + Frees up as much memory as possible by cleaning all memory caches such + as page, object and font cache. + + \since 4.6 + */ +void QWebSettings::clearMemoryCaches() +{ + // Turn the cache on and off. Disabling the object cache will remove all + // resources from the cache. They may still live on if they are referenced + // by some Web page though. + if (!WebCore::memoryCache()->disabled()) { + WebCore::memoryCache()->setDisabled(true); + WebCore::memoryCache()->setDisabled(false); + } + + int pageCapacity = WebCore::pageCache()->capacity(); + // Setting size to 0, makes all pages be released. + WebCore::pageCache()->setCapacity(0); + WebCore::pageCache()->releaseAutoreleasedPagesNow(); + WebCore::pageCache()->setCapacity(pageCapacity); + + // Invalidating the font cache and freeing all inactive font data. + WebCore::fontCache()->invalidate(); + + // Empty the Cross-Origin Preflight cache + WebCore::CrossOriginPreflightResultCache::shared().empty(); +} + +/*! + Sets the maximum number of pages to hold in the memory page cache to \a pages. + + The Page Cache allows for a nicer user experience when navigating forth or back + to pages in the forward/back history, by pausing and resuming up to \a pages. + + For more information about the feature, please refer to: + + http://webkit.org/blog/427/webkit-page-cache-i-the-basics/ +*/ +void QWebSettings::setMaximumPagesInCache(int pages) +{ + QWebSettingsPrivate* global = QWebSettings::globalSettings()->d; + WebCore::pageCache()->setCapacity(qMax(0, pages)); + global->apply(); +} + +/*! + Returns the maximum number of web pages that are kept in the memory cache. +*/ +int QWebSettings::maximumPagesInCache() +{ + return WebCore::pageCache()->capacity(); +} + +/*! + Specifies the capacities for the memory cache for dead objects such as + stylesheets or scripts. + + The \a cacheMinDeadCapacity specifies the \e minimum number of bytes that + dead objects should consume when the cache is under pressure. + + \a cacheMaxDead is the \e maximum number of bytes that dead objects should + consume when the cache is \bold not under pressure. + + \a totalCapacity specifies the \e maximum number of bytes that the cache + should consume \bold overall. + + The cache is enabled by default. Calling setObjectCacheCapacities(0, 0, 0) + will disable the cache. Calling it with one non-zero enables it again. +*/ +void QWebSettings::setObjectCacheCapacities(int cacheMinDeadCapacity, int cacheMaxDead, int totalCapacity) +{ + bool disableCache = !cacheMinDeadCapacity && !cacheMaxDead && !totalCapacity; + WebCore::memoryCache()->setDisabled(disableCache); + + WebCore::memoryCache()->setCapacities(qMax(0, cacheMinDeadCapacity), + qMax(0, cacheMaxDead), + qMax(0, totalCapacity)); +} + +/*! + Sets the actual font family to \a family for the specified generic family, + \a which. +*/ +void QWebSettings::setFontFamily(FontFamily which, const QString& family) +{ + d->fontFamilies.insert(which, family); + d->apply(); +} + +/*! + Returns the actual font family for the specified generic font family, + \a which. +*/ +QString QWebSettings::fontFamily(FontFamily which) const +{ + QString defaultValue; + if (d->settings) { + QWebSettingsPrivate* global = QWebSettings::globalSettings()->d; + defaultValue = global->fontFamilies.value(which); + } + return d->fontFamilies.value(which, defaultValue); +} + +/*! + Resets the actual font family specified by \a which to the one set + in the global QWebSettings instance. + + This function has no effect on the global QWebSettings instance. +*/ +void QWebSettings::resetFontFamily(FontFamily which) +{ + if (d->settings) { + d->fontFamilies.remove(which); + d->apply(); + } +} + +/*! + \fn void QWebSettings::setAttribute(WebAttribute attribute, bool on) + + Enables or disables the specified \a attribute feature depending on the + value of \a on. +*/ +void QWebSettings::setAttribute(WebAttribute attr, bool on) +{ + d->attributes.insert(attr, on); + d->apply(); +} + +/*! + \fn bool QWebSettings::testAttribute(WebAttribute attribute) const + + Returns true if \a attribute is enabled; otherwise returns false. +*/ +bool QWebSettings::testAttribute(WebAttribute attr) const +{ + bool defaultValue = false; + if (d->settings) { + QWebSettingsPrivate* global = QWebSettings::globalSettings()->d; + defaultValue = global->attributes.value(attr); + } + return d->attributes.value(attr, defaultValue); +} + +/*! + \fn void QWebSettings::resetAttribute(WebAttribute attribute) + + Resets the setting of \a attribute to the value specified in the + global QWebSettings instance. + + This function has no effect on the global QWebSettings instance. + + \sa globalSettings() +*/ +void QWebSettings::resetAttribute(WebAttribute attr) +{ + if (d->settings) { + d->attributes.remove(attr); + d->apply(); + } +} + +/*! + \since 4.5 + + Sets \a path as the save location for HTML5 client-side database storage data. + + \a path must point to an existing directory. + + Setting an empty path disables the feature. + + Support for client-side databases can enabled by setting the + \l{QWebSettings::OfflineStorageDatabaseEnabled}{OfflineStorageDatabaseEnabled} attribute. + + \sa offlineStoragePath() +*/ +void QWebSettings::setOfflineStoragePath(const QString& path) +{ +#if ENABLE(DATABASE) + WebCore::DatabaseTracker::tracker().setDatabaseDirectoryPath(path); +#endif +} + +/*! + \since 4.5 + + Returns the path of the HTML5 client-side database storage or an empty string if the + feature is disabled. + + \sa setOfflineStoragePath() +*/ +QString QWebSettings::offlineStoragePath() +{ +#if ENABLE(DATABASE) + return WebCore::DatabaseTracker::tracker().databaseDirectoryPath(); +#else + return QString(); +#endif +} + +/*! + \since 4.5 + + Sets the value of the default quota for new offline storage databases + to \a maximumSize. +*/ +void QWebSettings::setOfflineStorageDefaultQuota(qint64 maximumSize) +{ + QWebSettings::globalSettings()->d->offlineStorageDefaultQuota = maximumSize; +} + +/*! + \since 4.5 + + Returns the value of the default quota for new offline storage databases. +*/ +qint64 QWebSettings::offlineStorageDefaultQuota() +{ + return QWebSettings::globalSettings()->d->offlineStorageDefaultQuota; +} + +/*! + \since 4.6 + + Sets the path for HTML5 offline web application cache storage to \a path. + + An application cache acts like an HTTP cache in some sense. For documents + that use the application cache via JavaScript, the loader engine will + first ask the application cache for the contents, before hitting the + network. + + The feature is described in details at: + http://dev.w3.org/html5/spec/Overview.html#appcache + + \a path must point to an existing directory. + + Setting an empty path disables the feature. + + Support for offline web application cache storage can enabled by setting the + \l{QWebSettings::OfflineWebApplicationCacheEnabled}{OfflineWebApplicationCacheEnabled} attribute. + + \sa offlineWebApplicationCachePath() +*/ +void QWebSettings::setOfflineWebApplicationCachePath(const QString& path) +{ +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + WebCore::cacheStorage().setCacheDirectory(path); +#endif +} + +/*! + \since 4.6 + + Returns the path of the HTML5 offline web application cache storage + or an empty string if the feature is disabled. + + \sa setOfflineWebApplicationCachePath() +*/ +QString QWebSettings::offlineWebApplicationCachePath() +{ +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + return WebCore::cacheStorage().cacheDirectory(); +#else + return QString(); +#endif +} + +/*! + \since 4.6 + + Sets the value of the quota for the offline web application cache + to \a maximumSize. +*/ +void QWebSettings::setOfflineWebApplicationCacheQuota(qint64 maximumSize) +{ +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + WebCore::cacheStorage().empty(); + WebCore::cacheStorage().vacuumDatabaseFile(); + WebCore::cacheStorage().setMaximumSize(maximumSize); +#endif +} + +/*! + \since 4.6 + + Returns the value of the quota for the offline web application cache. +*/ +qint64 QWebSettings::offlineWebApplicationCacheQuota() +{ +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + return WebCore::cacheStorage().maximumSize(); +#else + return 0; +#endif +} + +/*! + \since 4.6 + + Sets the path for HTML5 local storage to \a path. + + For more information on HTML5 local storage see the + \l{http://www.w3.org/TR/webstorage/#the-localstorage-attribute}{Web Storage standard}. + + Support for local storage can enabled by setting the + \l{QWebSettings::LocalStorageEnabled}{LocalStorageEnabled} attribute. + + \sa localStoragePath() +*/ +void QWebSettings::setLocalStoragePath(const QString& path) +{ + d->localStoragePath = path; + d->apply(); +} + +/*! + \since 4.6 + + Returns the path for HTML5 local storage. + + \sa setLocalStoragePath() +*/ +QString QWebSettings::localStoragePath() const +{ + return d->localStoragePath; +} + +/*! + \since 4.6 + + Enables WebKit data persistence and sets the path to \a path. + If \a path is empty, the user-specific data location specified by + \l{QDesktopServices::DataLocation}{DataLocation} will be used instead. + + This method will simultaneously set and enable the iconDatabasePath(), + localStoragePath(), offlineStoragePath() and offlineWebApplicationCachePath(). + + \sa localStoragePath() +*/ +void QWebSettings::enablePersistentStorage(const QString& path) +{ +#ifndef QT_NO_DESKTOPSERVICES + QString storagePath; + + if (path.isEmpty()) { + + storagePath = QDesktopServices::storageLocation(QDesktopServices::DataLocation); + if (storagePath.isEmpty()) + storagePath = WebCore::pathByAppendingComponent(QDir::homePath(), QCoreApplication::applicationName()); + } else + storagePath = path; + + WebCore::makeAllDirectories(storagePath); + + QWebSettings::setIconDatabasePath(storagePath); + QWebSettings::setOfflineWebApplicationCachePath(storagePath); + QWebSettings::setOfflineStoragePath(WebCore::pathByAppendingComponent(storagePath, "Databases")); + QWebSettings::globalSettings()->setLocalStoragePath(WebCore::pathByAppendingComponent(storagePath, "LocalStorage")); + QWebSettings::globalSettings()->setAttribute(QWebSettings::LocalStorageEnabled, true); + QWebSettings::globalSettings()->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, true); + QWebSettings::globalSettings()->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, true); + +#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE) + // All applications can share the common QtWebkit cache file(s). + // Path is not configurable and uses QDesktopServices::CacheLocation by default. + QString cachePath = QDesktopServices::storageLocation(QDesktopServices::CacheLocation); + WebCore::makeAllDirectories(cachePath); + + QFileInfo info(cachePath); + if (info.isDir() && info.isWritable()) { + WebCore::PluginDatabase::setPersistentMetadataCacheEnabled(true); + WebCore::PluginDatabase::setPersistentMetadataCachePath(cachePath); + } +#endif +#endif +} + +/*! + \fn QWebSettingsPrivate* QWebSettings::handle() const + \internal +*/ diff --git a/Source/WebKit/qt/Api/qwebsettings.h b/Source/WebKit/qt/Api/qwebsettings.h new file mode 100644 index 0000000..008035b --- /dev/null +++ b/Source/WebKit/qt/Api/qwebsettings.h @@ -0,0 +1,165 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBSETTINGS_H +#define QWEBSETTINGS_H + +#include "qwebkitglobal.h" + +#include <QtCore/qstring.h> +#include <QtGui/qpixmap.h> +#include <QtGui/qicon.h> +#include <QtCore/qshareddata.h> + +namespace WebCore { + class Settings; +} + +class QWebPage; +class QWebPluginDatabase; +class QWebSettingsPrivate; +QT_BEGIN_NAMESPACE +class QUrl; +QT_END_NAMESPACE + +class QWEBKIT_EXPORT QWebSettings { +public: + enum FontFamily { + StandardFont, + FixedFont, + SerifFont, + SansSerifFont, + CursiveFont, + FantasyFont + }; + enum WebAttribute { + AutoLoadImages, + JavascriptEnabled, + JavaEnabled, + PluginsEnabled, + PrivateBrowsingEnabled, + JavascriptCanOpenWindows, + JavascriptCanAccessClipboard, + DeveloperExtrasEnabled, + LinksIncludedInFocusChain, + ZoomTextOnly, + PrintElementBackgrounds, + OfflineStorageDatabaseEnabled, + OfflineWebApplicationCacheEnabled, + LocalStorageEnabled, +#if defined(QT_DEPRECATED) || defined(qdoc) + LocalStorageDatabaseEnabled = LocalStorageEnabled, +#endif + LocalContentCanAccessRemoteUrls, + DnsPrefetchEnabled, + XSSAuditingEnabled, + AcceleratedCompositingEnabled, + SpatialNavigationEnabled, + LocalContentCanAccessFileUrls, + TiledBackingStoreEnabled, + FrameFlatteningEnabled, + SiteSpecificQuirksEnabled, + JavascriptCanCloseWindows, + WebGLEnabled, + HyperlinkAuditingEnabled + }; + enum WebGraphic { + MissingImageGraphic, + MissingPluginGraphic, + DefaultFrameIconGraphic, + TextAreaSizeGripCornerGraphic, + DeleteButtonGraphic, + InputSpeechButtonGraphic, + SearchCancelButtonGraphic, + SearchCancelButtonPressedGraphic + }; + enum FontSize { + MinimumFontSize, + MinimumLogicalFontSize, + DefaultFontSize, + DefaultFixedFontSize + }; + + static QWebSettings *globalSettings(); + + void setFontFamily(FontFamily which, const QString &family); + QString fontFamily(FontFamily which) const; + void resetFontFamily(FontFamily which); + + void setFontSize(FontSize type, int size); + int fontSize(FontSize type) const; + void resetFontSize(FontSize type); + + void setAttribute(WebAttribute attr, bool on); + bool testAttribute(WebAttribute attr) const; + void resetAttribute(WebAttribute attr); + + void setUserStyleSheetUrl(const QUrl &location); + QUrl userStyleSheetUrl() const; + + void setDefaultTextEncoding(const QString &encoding); + QString defaultTextEncoding() const; + + static void setIconDatabasePath(const QString &location); + static QString iconDatabasePath(); + static void clearIconDatabase(); + static QIcon iconForUrl(const QUrl &url); + + //static QWebPluginDatabase *pluginDatabase(); + + static void setWebGraphic(WebGraphic type, const QPixmap &graphic); + static QPixmap webGraphic(WebGraphic type); + + static void setMaximumPagesInCache(int pages); + static int maximumPagesInCache(); + static void setObjectCacheCapacities(int cacheMinDeadCapacity, int cacheMaxDead, int totalCapacity); + + static void setOfflineStoragePath(const QString& path); + static QString offlineStoragePath(); + static void setOfflineStorageDefaultQuota(qint64 maximumSize); + static qint64 offlineStorageDefaultQuota(); + + static void setOfflineWebApplicationCachePath(const QString& path); + static QString offlineWebApplicationCachePath(); + static void setOfflineWebApplicationCacheQuota(qint64 maximumSize); + static qint64 offlineWebApplicationCacheQuota(); + + void setLocalStoragePath(const QString& path); + QString localStoragePath() const; + + static void clearMemoryCaches(); + + static void enablePersistentStorage(const QString& path = QString()); + + inline QWebSettingsPrivate* handle() const { return d; } + +private: + friend class QWebPagePrivate; + friend class QWebSettingsPrivate; + + Q_DISABLE_COPY(QWebSettings) + + QWebSettings(); + QWebSettings(WebCore::Settings *settings); + ~QWebSettings(); + + QWebSettingsPrivate *d; +}; + +#endif diff --git a/Source/WebKit/qt/Api/qwebview.cpp b/Source/WebKit/qt/Api/qwebview.cpp new file mode 100644 index 0000000..f4b23f3 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebview.cpp @@ -0,0 +1,1256 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2008 Holger Hans Peter Freyther + Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qwebview.h" + +#include "Page.h" +#include "QWebPageClient.h" +#include "Settings.h" +#include "qwebframe.h" +#include "qwebpage_p.h" +#include "qbitmap.h" +#include "qevent.h" +#include "qpainter.h" +#include "qprinter.h" +#include "qdir.h" +#include "qfile.h" + +class QWebViewPrivate { +public: + QWebViewPrivate(QWebView *view) + : view(view) + , page(0) + , renderHints(QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform) + { + Q_ASSERT(view); + } + + virtual ~QWebViewPrivate(); + + void _q_pageDestroyed(); + void detachCurrentPage(); + + QWebView *view; + QWebPage *page; + + QPainter::RenderHints renderHints; +}; + +QWebViewPrivate::~QWebViewPrivate() +{ + detachCurrentPage(); +} + +void QWebViewPrivate::_q_pageDestroyed() +{ + page = 0; + view->setPage(0); +} + +#ifdef Q_WS_MAEMO_5 +#include "qabstractkineticscroller.h" +#include "qapplication.h" + +// QCoreApplication::sendSpontaneousEvent() is private, hence this friend wrapper +bool qt_sendSpontaneousEvent(QObject* receiver, QEvent* ev) +{ + return QCoreApplication::sendSpontaneousEvent(receiver, ev); +} + +class QWebViewKineticScroller : public QObject, public QAbstractKineticScroller { +public: + QWebViewKineticScroller() + : QObject() + , QAbstractKineticScroller() + , m_view(0) + , m_ignoreEvents(false) + { + } + + void setWidget(QWebView* widget) + { + if (m_view) { + m_view->removeEventFilter(this); + QWebFrame* frame = m_view->page()->mainFrame(); + frame->setScrollBarPolicy(Qt::Vertical, m_oldVerticalScrollBarPolicy); + frame->setScrollBarPolicy(Qt::Horizontal, m_oldHorizontalScrollBarPolicy); + } + + m_view = widget; + setParent(m_view); + if (m_view) { + QWebFrame* frame = m_view->page()->mainFrame(); + m_oldHorizontalScrollBarPolicy = frame->scrollBarPolicy(Qt::Horizontal); + m_oldVerticalScrollBarPolicy = frame->scrollBarPolicy(Qt::Vertical); + frame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff); + frame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff); + m_view->installEventFilter(this); + } + } + +protected: + bool eventFilter(QObject* o, QEvent* ev) + { + if (!o || m_view != o || m_ignoreEvents || !m_view->isEnabled()) + return QObject::eventFilter(o, ev); + + bool res = false; + + switch (ev->type()) { + case QEvent::MouseButtonPress: { + // remember the frame where the button was pressed + QWebFrame* hitFrame = scrollingFrameAt(static_cast<QMouseEvent*>(ev)->pos()); + if (hitFrame) + m_frame = hitFrame; + // fall through + } + case QEvent::MouseMove: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + res = handleMouseEvent(static_cast<QMouseEvent*>(ev)); + break; + default: + break; + } + return res ? true : QObject::eventFilter(o, ev); + } + + void cancelLeftMouseButtonPress(const QPoint& /* globalPressPos */) + { + QMouseEvent cmem(QEvent::MouseMove, QPoint(-INT_MAX, -INT_MAX), Qt::LeftButton, QApplication::mouseButtons() | Qt::LeftButton, QApplication::keyboardModifiers()); + sendEvent(m_view, &cmem); + QMouseEvent cmer(QEvent::MouseButtonRelease, QPoint(-INT_MAX, -INT_MAX), Qt::LeftButton, QApplication::mouseButtons() & ~Qt::LeftButton, QApplication::keyboardModifiers()); + sendEvent(m_view, &cmer); + } + + QWebFrame* currentFrame() const + { + if (m_frame) + return m_frame; + + if (m_view) + return m_view->page()->mainFrame(); + + return 0; + } + + // Returns the innermost frame at the given position that can scroll. + QWebFrame* scrollingFrameAt(const QPoint& pos) const + { + QWebFrame* hitFrame = 0; + if (m_view) { + QWebFrame* frame = m_view->page()->mainFrame(); + hitFrame = frame->hitTestContent(pos).frame(); + QSize range = hitFrame->contentsSize() - hitFrame->geometry().size(); + + while (hitFrame && range.width() <= 1 && range.height() <= 1) + hitFrame = hitFrame->parentFrame(); + + return hitFrame; + } + } + + QPoint maximumScrollPosition() const + { + QWebFrame* frame = currentFrame(); + QSize s = frame ? frame->contentsSize() - frame->geometry().size() : QSize(0, 0); + return QPoint(qMax(0, s.width()), qMax(0, s.height())); + } + + QPoint scrollPosition() const + { + QWebFrame* frame = currentFrame(); + return frame ? frame->scrollPosition() : QPoint(); + } + + QSize viewportSize() const + { + return m_view ? m_view->page()->viewportSize() : QSize(); + } + + void setScrollPosition(const QPoint& point, const QPoint& /* overShootDelta */) + { + QWebFrame* frame = currentFrame(); + if (frame) + frame->setScrollPosition(point); + } + + void sendEvent(QWidget* w, QEvent* ev) + { + m_ignoreEvents = true; + qt_sendSpontaneousEvent(w, ev); + m_ignoreEvents = false; + } + + QWebView* m_view; + bool m_ignoreEvents; + QPointer<QWebFrame> m_frame; + Qt::ScrollBarPolicy m_oldVerticalScrollBarPolicy; + Qt::ScrollBarPolicy m_oldHorizontalScrollBarPolicy; +}; + +#endif // Q_WS_MAEMO_5 + + +/*! + \class QWebView + \since 4.4 + \brief The QWebView class provides a widget that is used to view and edit + web documents. + \ingroup advanced + + \inmodule QtWebKit + + QWebView is the main widget component of the QtWebKit web browsing module. + It can be used in various applications to display web content live from the + Internet. + + The image below shows QWebView previewed in \QD with a Nokia website. + + \image qwebview-url.png + + A web site can be loaded onto QWebView with the load() function. Like all + Qt widgets, the show() function must be invoked in order to display + QWebView. The snippet below illustrates this: + + \snippet webkitsnippets/simple/main.cpp Using QWebView + + Alternatively, setUrl() can also be used to load a web site. If you have + the HTML content readily available, you can use setHtml() instead. + + The loadStarted() signal is emitted when the view begins loading. The + loadProgress() signal, on the other hand, is emitted whenever an element of + the web view completes loading, such as an embedded image, a script, etc. + Finally, the loadFinished() signal is emitted when the view has loaded + completely. It's argument - either \c true or \c false - indicates + load success or failure. + + The page() function returns a pointer to the web page object. See + \l{Elements of QWebView} for an explanation of how the web page + is related to the view. To modify your web view's settings, you can access + the QWebSettings object with the settings() function. With QWebSettings, + you can change the default fonts, enable or disable features such as + JavaScript and plugins. + + The title of an HTML document can be accessed with the title() property. + Additionally, a web site may also specify an icon, which can be accessed + using the icon() property. If the title or the icon changes, the corresponding + titleChanged() and iconChanged() signals will be emitted. The + textSizeMultiplier() property can be used to change the overall size of + the text displayed in the web view. + + If you require a custom context menu, you can implement it by reimplementing + \l{QWidget::}{contextMenuEvent()} and populating your QMenu with the actions + obtained from pageAction(). More functionality such as reloading the view, + copying selected text to the clipboard, or pasting into the view, is also + encapsulated within the QAction objects returned by pageAction(). These + actions can be programmatically triggered using triggerPageAction(). + Alternatively, the actions can be added to a toolbar or a menu directly. + QWebView maintains the state of the returned actions but allows + modification of action properties such as \l{QAction::}{text} or + \l{QAction::}{icon}. + + A QWebView can be printed onto a QPrinter using the print() function. + This function is marked as a slot and can be conveniently connected to + \l{QPrintPreviewDialog}'s \l{QPrintPreviewDialog::}{paintRequested()} + signal. + + If you want to provide support for web sites that allow the user to open + new windows, such as pop-up windows, you can subclass QWebView and + reimplement the createWindow() function. + + \section1 Elements of QWebView + + QWebView consists of other objects such as QWebFrame and QWebPage. The + flowchart below shows these elements are related. + + \image qwebview-diagram.png + + \note It is possible to use QWebPage and QWebFrame, without using QWebView, + if you do not require QWidget attributes. Nevertheless, QtWebKit depends + on QtGui, so you should use a QApplication instead of QCoreApplication. + + \sa {Previewer Example}, {Web Browser}, {Form Extractor Example}, + {Google Chat Example}, {Fancy Browser Example} +*/ + +/*! + Constructs an empty QWebView with parent \a parent. + + \sa load() +*/ +QWebView::QWebView(QWidget *parent) + : QWidget(parent) +{ + d = new QWebViewPrivate(this); + +#if !defined(Q_WS_QWS) && !defined(Q_OS_SYMBIAN) + setAttribute(Qt::WA_InputMethodEnabled); +#endif + + setAttribute(Qt::WA_AcceptTouchEvents); +#if defined(Q_WS_MAEMO_5) + QAbstractKineticScroller* scroller = new QWebViewKineticScroller(); + static_cast<QWebViewKineticScroller*>(scroller)->setWidget(this); + setProperty("kineticScroller", QVariant::fromValue(scroller)); +#endif + setAcceptDrops(true); + + setMouseTracking(true); + setFocusPolicy(Qt::WheelFocus); +} + +/*! + Destroys the web view. +*/ +QWebView::~QWebView() +{ + delete d; +} + +/*! + Returns a pointer to the underlying web page. + + \sa setPage() +*/ +QWebPage *QWebView::page() const +{ + if (!d->page) { + QWebView *that = const_cast<QWebView *>(this); + that->setPage(new QWebPage(that)); + } + return d->page; +} + +void QWebViewPrivate::detachCurrentPage() +{ + if (!page) + return; + + page->d->view.clear(); + + // if the page client is the special client constructed for + // delegating the responsibilities to a QWidget, we need + // to destroy it. + + if (page->d->client && page->d->client->isQWidgetClient()) + page->d->client.clear(); + + page->d->client.release(); + + // if the page was created by us, we own it and need to + // destroy it as well. + + if (page->parent() == view) + delete page; + else + page->disconnect(view); + + page = 0; +} + +/*! + Makes \a page the new web page of the web view. + + The parent QObject of the provided page remains the owner + of the object. If the current document is a child of the web + view, it will be deleted. + + \sa page() +*/ +void QWebView::setPage(QWebPage* page) +{ + if (d->page == page) + return; + + d->detachCurrentPage(); + d->page = page; + + if (d->page) { + d->page->setView(this); + d->page->setPalette(palette()); + // #### connect signals + QWebFrame *mainFrame = d->page->mainFrame(); + connect(mainFrame, SIGNAL(titleChanged(QString)), + this, SIGNAL(titleChanged(QString))); + connect(mainFrame, SIGNAL(iconChanged()), + this, SIGNAL(iconChanged())); + connect(mainFrame, SIGNAL(urlChanged(QUrl)), + this, SIGNAL(urlChanged(QUrl))); + + connect(d->page, SIGNAL(loadStarted()), + this, SIGNAL(loadStarted())); + connect(d->page, SIGNAL(loadProgress(int)), + this, SIGNAL(loadProgress(int))); + connect(d->page, SIGNAL(loadFinished(bool)), + this, SIGNAL(loadFinished(bool))); + connect(d->page, SIGNAL(statusBarMessage(QString)), + this, SIGNAL(statusBarMessage(QString))); + connect(d->page, SIGNAL(linkClicked(QUrl)), + this, SIGNAL(linkClicked(QUrl))); + connect(d->page, SIGNAL(selectionChanged()), + this, SIGNAL(selectionChanged())); + + connect(d->page, SIGNAL(microFocusChanged()), + this, SLOT(updateMicroFocus())); + connect(d->page, SIGNAL(destroyed()), + this, SLOT(_q_pageDestroyed())); + } + setAttribute(Qt::WA_OpaquePaintEvent, d->page); + update(); +} + +/*! + Loads the specified \a url and displays it. + + \note The view remains the same until enough data has arrived to display the new \a url. + + \sa setUrl(), url(), urlChanged(), QUrl::fromUserInput() +*/ +void QWebView::load(const QUrl &url) +{ + page()->mainFrame()->load(url); +} + +/*! + \fn void QWebView::load(const QNetworkRequest &request, QNetworkAccessManager::Operation operation, const QByteArray &body) + + Loads a network request, \a request, using the method specified in \a operation. + + \a body is optional and is only used for POST operations. + + \note The view remains the same until enough data has arrived to display the new url. + + \sa url(), urlChanged() +*/ + +void QWebView::load(const QNetworkRequest &request, + QNetworkAccessManager::Operation operation, + const QByteArray &body) +{ + page()->mainFrame()->load(request, operation, body); +} + +/*! + Sets the content of the web view to the specified \a html. + + External objects such as stylesheets or images referenced in the HTML + document are located relative to \a baseUrl. + + The \a html is loaded immediately; external objects are loaded asynchronously. + + When using this method, WebKit assumes that external resources such as + JavaScript programs or style sheets are encoded in UTF-8 unless otherwise + specified. For example, the encoding of an external script can be specified + through the charset attribute of the HTML script tag. Alternatively, the + encoding can also be specified by the web server. + + This is a convenience function equivalent to setContent(html, "text/html", baseUrl). + + \warning This function works only for HTML, for other mime types (i.e. XHTML, SVG) + setContent() should be used instead. + + \sa load(), setContent(), QWebFrame::toHtml(), QWebFrame::setContent() +*/ +void QWebView::setHtml(const QString &html, const QUrl &baseUrl) +{ + page()->mainFrame()->setHtml(html, baseUrl); +} + +/*! + Sets the content of the web view to the specified content \a data. If the \a mimeType argument + is empty it is currently assumed that the content is HTML but in future versions we may introduce + auto-detection. + + External objects referenced in the content are located relative to \a baseUrl. + + The \a data is loaded immediately; external objects are loaded asynchronously. + + \sa load(), setHtml(), QWebFrame::toHtml() +*/ +void QWebView::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl) +{ + page()->mainFrame()->setContent(data, mimeType, baseUrl); +} + +/*! + Returns a pointer to the view's history of navigated web pages. + + It is equivalent to + + \snippet webkitsnippets/qtwebkit_qwebview_snippet.cpp 0 +*/ +QWebHistory *QWebView::history() const +{ + return page()->history(); +} + +/*! + Returns a pointer to the view/page specific settings object. + + It is equivalent to + + \snippet webkitsnippets/qtwebkit_qwebview_snippet.cpp 1 + + \sa QWebSettings::globalSettings() +*/ +QWebSettings *QWebView::settings() const +{ + return page()->settings(); +} + +/*! + \property QWebView::title + \brief the title of the web page currently viewed + + By default, this property contains an empty string. + + \sa titleChanged() +*/ +QString QWebView::title() const +{ + if (d->page) + return d->page->mainFrame()->title(); + return QString(); +} + +/*! + \property QWebView::url + \brief the url of the web page currently viewed + + Setting this property clears the view and loads the URL. + + By default, this property contains an empty, invalid URL. + + \sa load(), urlChanged() +*/ + +void QWebView::setUrl(const QUrl &url) +{ + page()->mainFrame()->setUrl(url); +} + +QUrl QWebView::url() const +{ + if (d->page) + return d->page->mainFrame()->url(); + return QUrl(); +} + +/*! + \property QWebView::icon + \brief the icon associated with the web page currently viewed + + By default, this property contains a null icon. + + \sa iconChanged(), QWebSettings::iconForUrl() +*/ +QIcon QWebView::icon() const +{ + if (d->page) + return d->page->mainFrame()->icon(); + return QIcon(); +} + +/*! + \property QWebView::hasSelection + \brief whether this page contains selected content or not. + + By default, this property is false. + + \sa selectionChanged() +*/ +bool QWebView::hasSelection() const +{ + if (d->page) + return d->page->hasSelection(); + return false; +} + +/*! + \property QWebView::selectedText + \brief the text currently selected + + By default, this property contains an empty string. + + \sa findText(), selectionChanged(), selectedHtml() +*/ +QString QWebView::selectedText() const +{ + if (d->page) + return d->page->selectedText(); + return QString(); +} + +/*! + \since 4.8 + \property QWebView::selectedHtml + \brief the HTML currently selected + + By default, this property contains an empty string. + + \sa findText(), selectionChanged(), selectedText() +*/ +QString QWebView::selectedHtml() const +{ + if (d->page) + return d->page->selectedHtml(); + return QString(); +} + +#ifndef QT_NO_ACTION +/*! + Returns a pointer to a QAction that encapsulates the specified web action \a action. +*/ +QAction *QWebView::pageAction(QWebPage::WebAction action) const +{ + return page()->action(action); +} +#endif + +/*! + Triggers the specified \a action. If it is a checkable action the specified + \a checked state is assumed. + + The following example triggers the copy action and therefore copies any + selected text to the clipboard. + + \snippet webkitsnippets/qtwebkit_qwebview_snippet.cpp 2 + + \sa pageAction() +*/ +void QWebView::triggerPageAction(QWebPage::WebAction action, bool checked) +{ + page()->triggerAction(action, checked); +} + +/*! + \property QWebView::modified + \brief whether the document was modified by the user + + Parts of HTML documents can be editable for example through the + \c{contenteditable} attribute on HTML elements. + + By default, this property is false. +*/ +bool QWebView::isModified() const +{ + if (d->page) + return d->page->isModified(); + return false; +} + +/* +Qt::TextInteractionFlags QWebView::textInteractionFlags() const +{ + // ### FIXME (add to page) + return Qt::TextInteractionFlags(); +} +*/ + +/* + \property QWebView::textInteractionFlags + \brief how the view should handle user input + + Specifies how the user can interact with the text on the page. +*/ + +/* +void QWebView::setTextInteractionFlags(Qt::TextInteractionFlags flags) +{ + Q_UNUSED(flags) + // ### FIXME (add to page) +} +*/ + +/*! + \reimp +*/ +QSize QWebView::sizeHint() const +{ + return QSize(800, 600); // ####... +} + +/*! + \property QWebView::zoomFactor + \since 4.5 + \brief the zoom factor for the view +*/ + +void QWebView::setZoomFactor(qreal factor) +{ + page()->mainFrame()->setZoomFactor(factor); +} + +qreal QWebView::zoomFactor() const +{ + return page()->mainFrame()->zoomFactor(); +} + +/*! + \property QWebView::textSizeMultiplier + \brief the scaling factor for all text in the frame + \obsolete + + Use setZoomFactor instead, in combination with the + ZoomTextOnly attribute in QWebSettings. + + \note Setting this property also enables the + ZoomTextOnly attribute in QWebSettings. + + By default, this property contains a value of 1.0. +*/ + +/*! + Sets the value of the multiplier used to scale the text in a Web page to + the \a factor specified. +*/ +void QWebView::setTextSizeMultiplier(qreal factor) +{ + page()->mainFrame()->setTextSizeMultiplier(factor); +} + +/*! + Returns the value of the multiplier used to scale the text in a Web page. +*/ +qreal QWebView::textSizeMultiplier() const +{ + return page()->mainFrame()->textSizeMultiplier(); +} + +/*! + \property QWebView::renderHints + \since 4.6 + \brief the default render hints for the view + + These hints are used to initialize QPainter before painting the Web page. + + QPainter::TextAntialiasing and QPainter::SmoothPixmapTransform are enabled by default. + + \note This property is not available on Symbian. However, the getter and + setter functions can still be used directly. + + \sa QPainter::renderHints() +*/ + +/*! + \since 4.6 + Returns the render hints used by the view to render content. + + \sa QPainter::renderHints() +*/ +QPainter::RenderHints QWebView::renderHints() const +{ + return d->renderHints; +} + +/*! + \since 4.6 + Sets the render hints used by the view to the specified \a hints. + + \sa QPainter::setRenderHints() +*/ +void QWebView::setRenderHints(QPainter::RenderHints hints) +{ + if (hints == d->renderHints) + return; + d->renderHints = hints; + update(); +} + +/*! + \since 4.6 + If \a enabled is true, enables the specified render \a hint; otherwise + disables it. + + \sa renderHints, QPainter::renderHints() +*/ +void QWebView::setRenderHint(QPainter::RenderHint hint, bool enabled) +{ + QPainter::RenderHints oldHints = d->renderHints; + if (enabled) + d->renderHints |= hint; + else + d->renderHints &= ~hint; + if (oldHints != d->renderHints) + update(); +} + + +/*! + Finds the specified string, \a subString, in the page, using the given \a options. + + If the HighlightAllOccurrences flag is passed, the function will highlight all occurrences + that exist in the page. All subsequent calls will extend the highlight, rather than + replace it, with occurrences of the new string. + + If the HighlightAllOccurrences flag is not passed, the function will select an occurrence + and all subsequent calls will replace the current occurrence with the next one. + + To clear the selection, just pass an empty string. + + Returns true if \a subString was found; otherwise returns false. + + \sa selectedText(), selectionChanged() +*/ +bool QWebView::findText(const QString &subString, QWebPage::FindFlags options) +{ + if (d->page) + return d->page->findText(subString, options); + return false; +} + +/*! \reimp +*/ +bool QWebView::event(QEvent *e) +{ + if (d->page) { +#ifndef QT_NO_CONTEXTMENU + if (e->type() == QEvent::ContextMenu) { + if (!isEnabled()) + return false; + QContextMenuEvent *event = static_cast<QContextMenuEvent *>(e); + if (d->page->swallowContextMenuEvent(event)) { + e->accept(); + return true; + } + d->page->updatePositionDependentActions(event->pos()); + } else +#endif // QT_NO_CONTEXTMENU + if (e->type() == QEvent::ShortcutOverride) { + d->page->event(e); +#ifndef QT_NO_CURSOR + } else if (e->type() == QEvent::CursorChange) { + // An unsetCursor will set the cursor to Qt::ArrowCursor. + // Thus this cursor change might be a QWidget::unsetCursor() + // If this is not the case and it came from WebCore, the + // QWebPageClient already has set its cursor internally + // to Qt::ArrowCursor, so updating the cursor is always + // right, as it falls back to the last cursor set by + // WebCore. + // FIXME: Add a QEvent::CursorUnset or similar to Qt. + if (cursor().shape() == Qt::ArrowCursor) + d->page->d->client->resetCursor(); +#endif + } else if (e->type() == QEvent::TouchBegin + || e->type() == QEvent::TouchEnd + || e->type() == QEvent::TouchUpdate) { + d->page->event(e); + + // Always return true so that we'll receive also TouchUpdate and TouchEnd events + return true; + } else if (e->type() == QEvent::Leave) + d->page->event(e); + } + + return QWidget::event(e); +} + +/*! + Prints the main frame to the given \a printer. + + \sa QWebFrame::print(), QPrintPreviewDialog +*/ +void QWebView::print(QPrinter *printer) const +{ +#ifndef QT_NO_PRINTER + page()->mainFrame()->print(printer); +#endif +} + +/*! + Convenience slot that stops loading the document. + + It is equivalent to + + \snippet webkitsnippets/qtwebkit_qwebview_snippet.cpp 3 + + \sa reload(), pageAction(), loadFinished() +*/ +void QWebView::stop() +{ + if (d->page) + d->page->triggerAction(QWebPage::Stop); +} + +/*! + Convenience slot that loads the previous document in the list of documents + built by navigating links. Does nothing if there is no previous document. + + It is equivalent to + + \snippet webkitsnippets/qtwebkit_qwebview_snippet.cpp 4 + + \sa forward(), pageAction() +*/ +void QWebView::back() +{ + if (d->page) + d->page->triggerAction(QWebPage::Back); +} + +/*! + Convenience slot that loads the next document in the list of documents + built by navigating links. Does nothing if there is no next document. + + It is equivalent to + + \snippet webkitsnippets/qtwebkit_qwebview_snippet.cpp 5 + + \sa back(), pageAction() +*/ +void QWebView::forward() +{ + if (d->page) + d->page->triggerAction(QWebPage::Forward); +} + +/*! + Reloads the current document. + + \sa stop(), pageAction(), loadStarted() +*/ +void QWebView::reload() +{ + if (d->page) + d->page->triggerAction(QWebPage::Reload); +} + +/*! \reimp +*/ +void QWebView::resizeEvent(QResizeEvent *e) +{ + if (d->page) + d->page->setViewportSize(e->size()); +} + +/*! \reimp +*/ +void QWebView::paintEvent(QPaintEvent *ev) +{ + if (!d->page) + return; +#ifdef QWEBKIT_TIME_RENDERING + QTime time; + time.start(); +#endif + + QWebFrame *frame = d->page->mainFrame(); + QPainter p(this); + p.setRenderHints(d->renderHints); + + frame->render(&p, ev->region()); + +#ifdef QWEBKIT_TIME_RENDERING + int elapsed = time.elapsed(); + qDebug() << "paint event on " << ev->region() << ", took to render = " << elapsed; +#endif +} + +/*! + This function is called from the createWindow() method of the associated QWebPage, + each time the page wants to create a new window of the given \a type. This might + be the result, for example, of a JavaScript request to open a document in a new window. + + \note If the createWindow() method of the associated page is reimplemented, this + method is not called, unless explicitly done so in the reimplementation. + + \note In the cases when the window creation is being triggered by JavaScript, apart from + reimplementing this method application must also set the JavaScriptCanOpenWindows attribute + of QWebSettings to true in order for it to get called. + + \sa QWebPage::createWindow(), QWebPage::acceptNavigationRequest() +*/ +QWebView *QWebView::createWindow(QWebPage::WebWindowType type) +{ + Q_UNUSED(type) + return 0; +} + +/*! \reimp +*/ +void QWebView::mouseMoveEvent(QMouseEvent* ev) +{ + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } +} + +/*! \reimp +*/ +void QWebView::mousePressEvent(QMouseEvent* ev) +{ + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } +} + +/*! \reimp +*/ +void QWebView::mouseDoubleClickEvent(QMouseEvent* ev) +{ + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } +} + +/*! \reimp +*/ +void QWebView::mouseReleaseEvent(QMouseEvent* ev) +{ + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } +} + +#ifndef QT_NO_CONTEXTMENU +/*! \reimp +*/ +void QWebView::contextMenuEvent(QContextMenuEvent* ev) +{ + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } +} +#endif // QT_NO_CONTEXTMENU + +#ifndef QT_NO_WHEELEVENT +/*! \reimp +*/ +void QWebView::wheelEvent(QWheelEvent* ev) +{ + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } +} +#endif // QT_NO_WHEELEVENT + +/*! \reimp +*/ +void QWebView::keyPressEvent(QKeyEvent* ev) +{ + if (d->page) + d->page->event(ev); + if (!ev->isAccepted()) + QWidget::keyPressEvent(ev); +} + +/*! \reimp +*/ +void QWebView::keyReleaseEvent(QKeyEvent* ev) +{ + if (d->page) + d->page->event(ev); + if (!ev->isAccepted()) + QWidget::keyReleaseEvent(ev); +} + +/*! \reimp +*/ +void QWebView::focusInEvent(QFocusEvent* ev) +{ + if (d->page) + d->page->event(ev); + else + QWidget::focusInEvent(ev); +} + +/*! \reimp +*/ +void QWebView::focusOutEvent(QFocusEvent* ev) +{ + if (d->page) + d->page->event(ev); + else + QWidget::focusOutEvent(ev); +} + +/*! \reimp +*/ +void QWebView::dragEnterEvent(QDragEnterEvent* ev) +{ +#ifndef QT_NO_DRAGANDDROP + if (d->page) + d->page->event(ev); +#endif +} + +/*! \reimp +*/ +void QWebView::dragLeaveEvent(QDragLeaveEvent* ev) +{ +#ifndef QT_NO_DRAGANDDROP + if (d->page) + d->page->event(ev); +#endif +} + +/*! \reimp +*/ +void QWebView::dragMoveEvent(QDragMoveEvent* ev) +{ +#ifndef QT_NO_DRAGANDDROP + if (d->page) + d->page->event(ev); +#endif +} + +/*! \reimp +*/ +void QWebView::dropEvent(QDropEvent* ev) +{ +#ifndef QT_NO_DRAGANDDROP + if (d->page) + d->page->event(ev); +#endif +} + +/*! \reimp +*/ +bool QWebView::focusNextPrevChild(bool next) +{ + if (d->page && d->page->focusNextPrevChild(next)) + return true; + return QWidget::focusNextPrevChild(next); +} + +/*!\reimp +*/ +QVariant QWebView::inputMethodQuery(Qt::InputMethodQuery property) const +{ + if (d->page) + return d->page->inputMethodQuery(property); + return QVariant(); +} + +/*!\reimp +*/ +void QWebView::inputMethodEvent(QInputMethodEvent *e) +{ + if (d->page) + d->page->event(e); +} + +/*!\reimp +*/ +void QWebView::changeEvent(QEvent *e) +{ + if (d->page && e->type() == QEvent::PaletteChange) + d->page->setPalette(palette()); + QWidget::changeEvent(e); +} + +/*! + \fn void QWebView::titleChanged(const QString &title) + + This signal is emitted whenever the \a title of the main frame changes. + + \sa title() +*/ + +/*! + \fn void QWebView::urlChanged(const QUrl &url) + + This signal is emitted when the \a url of the view changes. + + \sa url(), load() +*/ + +/*! + \fn void QWebView::statusBarMessage(const QString& text) + + This signal is emitted when the status bar \a text is changed by the page. +*/ + +/*! + \fn void QWebView::iconChanged() + + This signal is emitted whenever the icon of the page is loaded or changes. + + In order for icons to be loaded, you will need to set an icon database path + using QWebSettings::setIconDatabasePath(). + + \sa icon(), QWebSettings::setIconDatabasePath() +*/ + +/*! + \fn void QWebView::loadStarted() + + This signal is emitted when a new load of the page is started. + + \sa loadProgress(), loadFinished() +*/ + +/*! + \fn void QWebView::loadFinished(bool ok) + + This signal is emitted when a load of the page is finished. + \a ok will indicate whether the load was successful or any error occurred. + + \sa loadStarted() +*/ + +/*! + \fn void QWebView::selectionChanged() + + This signal is emitted whenever the selection changes. + + \sa selectedText() +*/ + +/*! + \fn void QWebView::loadProgress(int progress) + + This signal is emitted every time an element in the web page + completes loading and the overall loading progress advances. + + This signal tracks the progress of all child frames. + + The current value is provided by \a progress and scales from 0 to 100, + which is the default range of QProgressBar. + + \sa loadStarted(), loadFinished() +*/ + +/*! + \fn void QWebView::linkClicked(const QUrl &url) + + This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy + property is set to delegate the link handling for the specified \a url. + + \sa QWebPage::linkDelegationPolicy() +*/ + +#include "moc_qwebview.cpp" + diff --git a/Source/WebKit/qt/Api/qwebview.h b/Source/WebKit/qt/Api/qwebview.h new file mode 100644 index 0000000..8b28f62 --- /dev/null +++ b/Source/WebKit/qt/Api/qwebview.h @@ -0,0 +1,167 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2007 Staikos Computing Services Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBVIEW_H +#define QWEBVIEW_H + +#include "qwebkitglobal.h" +#include "qwebpage.h" +#include <QtGui/qwidget.h> +#include <QtGui/qicon.h> +#include <QtGui/qpainter.h> +#include <QtCore/qurl.h> +#include <QtNetwork/qnetworkaccessmanager.h> + +QT_BEGIN_NAMESPACE +class QNetworkRequest; +class QPrinter; +QT_END_NAMESPACE + +class QWebPage; +class QWebViewPrivate; +class QWebNetworkRequest; + +class QWEBKIT_EXPORT QWebView : public QWidget { + Q_OBJECT + Q_PROPERTY(QString title READ title) + Q_PROPERTY(QUrl url READ url WRITE setUrl) + Q_PROPERTY(QIcon icon READ icon) + Q_PROPERTY(QString selectedText READ selectedText) + Q_PROPERTY(QString selectedHtml READ selectedHtml) + Q_PROPERTY(bool hasSelection READ hasSelection) + Q_PROPERTY(bool modified READ isModified) + //Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags WRITE setTextInteractionFlags) + Q_PROPERTY(qreal textSizeMultiplier READ textSizeMultiplier WRITE setTextSizeMultiplier DESIGNABLE false) + Q_PROPERTY(qreal zoomFactor READ zoomFactor WRITE setZoomFactor) + + Q_PROPERTY(QPainter::RenderHints renderHints READ renderHints WRITE setRenderHints) + Q_FLAGS(QPainter::RenderHints) +public: + explicit QWebView(QWidget* parent = 0); + virtual ~QWebView(); + + QWebPage* page() const; + void setPage(QWebPage* page); + + void load(const QUrl& url); + void load(const QNetworkRequest& request, + QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation, + const QByteArray &body = QByteArray()); + void setHtml(const QString& html, const QUrl& baseUrl = QUrl()); + void setContent(const QByteArray& data, const QString& mimeType = QString(), const QUrl& baseUrl = QUrl()); + + QWebHistory* history() const; + QWebSettings* settings() const; + + QString title() const; + void setUrl(const QUrl &url); + QUrl url() const; + QIcon icon() const; + + bool hasSelection() const; + QString selectedText() const; + QString selectedHtml() const; + +#ifndef QT_NO_ACTION + QAction* pageAction(QWebPage::WebAction action) const; +#endif + void triggerPageAction(QWebPage::WebAction action, bool checked = false); + + bool isModified() const; + + /* + Qt::TextInteractionFlags textInteractionFlags() const; + void setTextInteractionFlags(Qt::TextInteractionFlags flags); + void setTextInteractionFlag(Qt::TextInteractionFlag flag); + */ + + QVariant inputMethodQuery(Qt::InputMethodQuery property) const; + + QSize sizeHint() const; + + qreal zoomFactor() const; + void setZoomFactor(qreal factor); + + void setTextSizeMultiplier(qreal factor); + qreal textSizeMultiplier() const; + + QPainter::RenderHints renderHints() const; + void setRenderHints(QPainter::RenderHints hints); + void setRenderHint(QPainter::RenderHint hint, bool enabled = true); + + bool findText(const QString& subString, QWebPage::FindFlags options = 0); + + virtual bool event(QEvent*); + +public Q_SLOTS: + void stop(); + void back(); + void forward(); + void reload(); + + void print(QPrinter*) const; + +Q_SIGNALS: + void loadStarted(); + void loadProgress(int progress); + void loadFinished(bool); + void titleChanged(const QString& title); + void statusBarMessage(const QString& text); + void linkClicked(const QUrl&); + void selectionChanged(); + void iconChanged(); + void urlChanged(const QUrl&); + +protected: + void resizeEvent(QResizeEvent*); + void paintEvent(QPaintEvent*); + + virtual QWebView *createWindow(QWebPage::WebWindowType type); + + virtual void changeEvent(QEvent*); + virtual void mouseMoveEvent(QMouseEvent*); + virtual void mousePressEvent(QMouseEvent*); + virtual void mouseDoubleClickEvent(QMouseEvent*); + virtual void mouseReleaseEvent(QMouseEvent*); +#ifndef QT_NO_CONTEXTMENU + virtual void contextMenuEvent(QContextMenuEvent*); +#endif +#ifndef QT_NO_WHEELEVENT + virtual void wheelEvent(QWheelEvent*); +#endif + virtual void keyPressEvent(QKeyEvent*); + virtual void keyReleaseEvent(QKeyEvent*); + virtual void dragEnterEvent(QDragEnterEvent*); + virtual void dragLeaveEvent(QDragLeaveEvent*); + virtual void dragMoveEvent(QDragMoveEvent*); + virtual void dropEvent(QDropEvent*); + virtual void focusInEvent(QFocusEvent*); + virtual void focusOutEvent(QFocusEvent*); + virtual void inputMethodEvent(QInputMethodEvent*); + + virtual bool focusNextPrevChild(bool next); + +private: + friend class QWebPage; + QWebViewPrivate* d; + Q_PRIVATE_SLOT(d, void _q_pageDestroyed()) +}; + +#endif // QWEBVIEW_H |