From 40736c5763bf61337c8c14e16d8587db021a87d4 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 6 Jan 2012 14:44:00 +0100 Subject: Imported WebKit commit 2ea9d364d0f6efa8fa64acf19f451504c59be0e4 (http://svn.webkit.org/repository/webkit/trunk@104285) --- Source/WebKit/qt/Api/qgraphicswebview.cpp | 1203 +++++++ Source/WebKit/qt/Api/qgraphicswebview.h | 172 + Source/WebKit/qt/Api/qwebdatabase.cpp | 198 ++ Source/WebKit/qt/Api/qwebdatabase.h | 59 + Source/WebKit/qt/Api/qwebdatabase_p.h | 37 + Source/WebKit/qt/Api/qwebelement.cpp | 2134 +++++++++++++ Source/WebKit/qt/Api/qwebelement.h | 264 ++ Source/WebKit/qt/Api/qwebelement_p.h | 38 + Source/WebKit/qt/Api/qwebframe.cpp | 2008 ++++++++++++ Source/WebKit/qt/Api/qwebframe.h | 242 ++ Source/WebKit/qt/Api/qwebframe_p.h | 167 + Source/WebKit/qt/Api/qwebhistory.cpp | 563 ++++ Source/WebKit/qt/Api/qwebhistory.h | 120 + Source/WebKit/qt/Api/qwebhistory_p.h | 71 + Source/WebKit/qt/Api/qwebhistoryinterface.cpp | 127 + Source/WebKit/qt/Api/qwebhistoryinterface.h | 42 + Source/WebKit/qt/Api/qwebinspector.cpp | 206 ++ Source/WebKit/qt/Api/qwebinspector.h | 57 + Source/WebKit/qt/Api/qwebinspector_p.h | 46 + Source/WebKit/qt/Api/qwebkitglobal.h | 49 + Source/WebKit/qt/Api/qwebkitplatformplugin.h | 186 ++ Source/WebKit/qt/Api/qwebkitversion.cpp | 114 + Source/WebKit/qt/Api/qwebkitversion.h | 32 + Source/WebKit/qt/Api/qwebpage.cpp | 4164 +++++++++++++++++++++++++ Source/WebKit/qt/Api/qwebpage.h | 455 +++ Source/WebKit/qt/Api/qwebpage_p.h | 217 ++ Source/WebKit/qt/Api/qwebplugindatabase.cpp | 393 +++ Source/WebKit/qt/Api/qwebplugindatabase_p.h | 98 + Source/WebKit/qt/Api/qwebpluginfactory.cpp | 264 ++ Source/WebKit/qt/Api/qwebpluginfactory.h | 72 + Source/WebKit/qt/Api/qwebscriptworld.cpp | 62 + Source/WebKit/qt/Api/qwebscriptworld.h | 50 + Source/WebKit/qt/Api/qwebscriptworld_p.h | 44 + Source/WebKit/qt/Api/qwebsecurityorigin.cpp | 267 ++ Source/WebKit/qt/Api/qwebsecurityorigin.h | 70 + Source/WebKit/qt/Api/qwebsecurityorigin_p.h | 39 + Source/WebKit/qt/Api/qwebsettings.cpp | 1185 +++++++ Source/WebKit/qt/Api/qwebsettings.h | 181 ++ Source/WebKit/qt/Api/qwebview.cpp | 1106 +++++++ Source/WebKit/qt/Api/qwebview.h | 170 + 40 files changed, 16972 insertions(+) create mode 100644 Source/WebKit/qt/Api/qgraphicswebview.cpp create mode 100644 Source/WebKit/qt/Api/qgraphicswebview.h create mode 100644 Source/WebKit/qt/Api/qwebdatabase.cpp create mode 100644 Source/WebKit/qt/Api/qwebdatabase.h create mode 100644 Source/WebKit/qt/Api/qwebdatabase_p.h create mode 100644 Source/WebKit/qt/Api/qwebelement.cpp create mode 100644 Source/WebKit/qt/Api/qwebelement.h create mode 100644 Source/WebKit/qt/Api/qwebelement_p.h create mode 100644 Source/WebKit/qt/Api/qwebframe.cpp create mode 100644 Source/WebKit/qt/Api/qwebframe.h create mode 100644 Source/WebKit/qt/Api/qwebframe_p.h create mode 100644 Source/WebKit/qt/Api/qwebhistory.cpp create mode 100644 Source/WebKit/qt/Api/qwebhistory.h create mode 100644 Source/WebKit/qt/Api/qwebhistory_p.h create mode 100644 Source/WebKit/qt/Api/qwebhistoryinterface.cpp create mode 100644 Source/WebKit/qt/Api/qwebhistoryinterface.h create mode 100644 Source/WebKit/qt/Api/qwebinspector.cpp create mode 100644 Source/WebKit/qt/Api/qwebinspector.h create mode 100644 Source/WebKit/qt/Api/qwebinspector_p.h create mode 100644 Source/WebKit/qt/Api/qwebkitglobal.h create mode 100644 Source/WebKit/qt/Api/qwebkitplatformplugin.h create mode 100644 Source/WebKit/qt/Api/qwebkitversion.cpp create mode 100644 Source/WebKit/qt/Api/qwebkitversion.h create mode 100644 Source/WebKit/qt/Api/qwebpage.cpp create mode 100644 Source/WebKit/qt/Api/qwebpage.h create mode 100644 Source/WebKit/qt/Api/qwebpage_p.h create mode 100644 Source/WebKit/qt/Api/qwebplugindatabase.cpp create mode 100644 Source/WebKit/qt/Api/qwebplugindatabase_p.h create mode 100644 Source/WebKit/qt/Api/qwebpluginfactory.cpp create mode 100644 Source/WebKit/qt/Api/qwebpluginfactory.h create mode 100644 Source/WebKit/qt/Api/qwebscriptworld.cpp create mode 100644 Source/WebKit/qt/Api/qwebscriptworld.h create mode 100644 Source/WebKit/qt/Api/qwebscriptworld_p.h create mode 100644 Source/WebKit/qt/Api/qwebsecurityorigin.cpp create mode 100644 Source/WebKit/qt/Api/qwebsecurityorigin.h create mode 100644 Source/WebKit/qt/Api/qwebsecurityorigin_p.h create mode 100644 Source/WebKit/qt/Api/qwebsettings.cpp create mode 100644 Source/WebKit/qt/Api/qwebsettings.h create mode 100644 Source/WebKit/qt/Api/qwebview.cpp create mode 100644 Source/WebKit/qt/Api/qwebview.h (limited to 'Source/WebKit/qt/Api') diff --git a/Source/WebKit/qt/Api/qgraphicswebview.cpp b/Source/WebKit/qt/Api/qgraphicswebview.cpp new file mode 100644 index 000000000..7811ab170 --- /dev/null +++ b/Source/WebKit/qt/Api/qgraphicswebview.cpp @@ -0,0 +1,1203 @@ +/* + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2009 Girish Ramakrishnan + + 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 "Page.h" +#include "PageClientQt.h" +#include "Frame.h" +#include "FrameView.h" +#include "GraphicsContext.h" +#include "IntRect.h" +#include "TiledBackingStore.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(Q_WS_X11) +#include +#endif +#include + +using namespace WebCore; + +class QGraphicsWebViewPrivate { +public: + QGraphicsWebViewPrivate(QGraphicsWebView* parent) + : q(parent) + , page(0) + , resizesToContents(false) + , renderHints(QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform) {} + + virtual ~QGraphicsWebViewPrivate(); + + void syncLayers(); + + void updateResizesToContentsForPage(); + + void detachCurrentPage(); + + void _q_doLoadFinished(bool success); + void _q_contentsSizeChanged(const QSize&); + void _q_scaleChanged(); + + void _q_pageDestroyed(); + + QGraphicsWebView* q; + QWebPage* page; + bool resizesToContents; + QPainter::RenderHints renderHints; + + QGraphicsItemOverlay* overlay() const + { + if (!page || !page->d->client) + return 0; + return pageClient()->overlay; + } + + PageClientQGraphicsWidget* pageClient() const + { + return static_cast (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); +} + +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 USE(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 USE(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(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*) +{ + QPainter::RenderHints oldHints = painter->renderHints(); + painter->setRenderHints(oldHints | d->renderHints); +#if USE(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()); + painter->setRenderHints(oldHints); + 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 + painter->setRenderHints(oldHints); +} + +/*! \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(); +} + +/*! + \property QGraphicsWebView::renderHints + \since 4.8 + \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 and will be + used to render the item in addition of what has been set on the painter given by QGraphicsScene. + + \note This property is not available on Symbian. However, the getter and + setter functions can still be used directly. + + \sa QPainter::renderHints() +*/ + +/*! + \since 4.8 + Returns the render hints used by the view to render content. + + \sa QPainter::renderHints() +*/ +QPainter::RenderHints QGraphicsWebView::renderHints() const +{ + return d->renderHints; +} + +/*! + \since 4.8 + Sets the render hints used by the view to the specified \a hints. + + \sa QPainter::setRenderHints() +*/ +void QGraphicsWebView::setRenderHints(QPainter::RenderHints hints) +{ + if (hints == d->renderHints) + return; + d->renderHints = hints; + update(); +} + +/*! + \since 4.8 + If \a enabled is true, enables the specified render \a hint; otherwise + disables it. + + \sa renderHints, QPainter::renderHints() +*/ +void QGraphicsWebView::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(); +} + +/*! \reimp +*/ +bool QGraphicsWebView::event(QEvent* event) +{ + // Re-implemented in order to allows fixing event-related bugs in patch releases. + + if (d->page) { + if (event->type() == QEvent::PaletteChange) + d->page->setPalette(palette()); +#ifndef QT_NO_CONTEXTMENU + if (event->type() == QEvent::GraphicsSceneContextMenu) { + if (!isEnabled()) + return false; + + QGraphicsSceneContextMenuEvent* ev = static_cast(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 = nullptr; + + // 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 = adoptPtr(new PageClientQGraphicsWidget(this, page)); + + 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)) + connect(d->page, SIGNAL(microFocusChanged()), + this, SLOT(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 USE(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 USE(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 000000000..29e7ffdac --- /dev/null +++ b/Source/WebKit/qt/Api/qgraphicswebview.h @@ -0,0 +1,172 @@ +/* + 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 +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) +#include +#include +#else +#include +#include +#endif +#include +#include +#include + +#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) + + Q_PROPERTY(QPainter::RenderHints renderHints READ renderHints WRITE setRenderHints) + Q_FLAGS(QPainter::RenderHints) + +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; + + QPainter::RenderHints renderHints() const; + void setRenderHints(QPainter::RenderHints); + void setRenderHint(QPainter::RenderHint, bool enabled = true); + +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)) + 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 000000000..b26772089 --- /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(SQL_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(SQL_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(SQL_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(SQL_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(SQL_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(SQL_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 000000000..875b2eb0c --- /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 +#include + +#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 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 000000000..ec03ea5e2 --- /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 +#include + +#include "PlatformString.h" +#include "SecurityOrigin.h" +#include "RefPtr.h" + + +class QWebDatabasePrivate : public QSharedData { +public: + WTF::String name; + WTF::RefPtr origin; +}; + +#endif + diff --git a/Source/WebKit/qt/Api/qwebelement.cpp b/Source/WebKit/qt/Api/qwebelement.cpp new file mode 100644 index 000000000..07716efba --- /dev/null +++ b/Source/WebKit/qt/Api/qwebelement.cpp @@ -0,0 +1,2134 @@ +/* + 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 "qwebelement_p.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 "Completion.h" +#include "JSGlobalObject.h" +#include "JSHTMLElement.h" +#include "JSObject.h" +#include "PropertyNameArray.h" +#include +#include "qt_runtime.h" +#elif USE(V8) +#include "V8DOMWindow.h" +#include "V8Binding.h" +#include "NotImplemented.h" +#endif +#include "NodeList.h" +#include "RenderImage.h" +#include "ScriptState.h" +#include "StaticNodeList.h" +#include "qwebframe.h" +#include "qwebframe_p.h" +#if USE(JSC) +#include "runtime_root.h" +#include +#endif +#include +#include + +#include + +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(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(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(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(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(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(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(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; + m_element->removeAttribute(name); +} + +/*! + 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; + m_element->removeAttributeNS(namespaceUri, name); +} + +/*! + 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(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(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(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(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, deprecatedGlobalObjectForPrototype(state), element); + if (!thisValue) + return false; + + return true; +} +#elif USE(V8) +static bool setupScriptContext(WebCore::Element* element, v8::Handle& 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 thisValue; +#endif + ScriptController* scriptController = 0; + + if (!setupScriptContext(m_element, thisValue, state, scriptController)) + return QVariant(); +#if USE(JSC) + JSC::ScopeChainNode* scopeChain = state->dynamicGlobalObject()->globalScopeChain(); + JSC::UString script(reinterpret_cast_ptr(scriptSource.data()), scriptSource.length()); + + JSC::JSValue evaluationException; + JSC::JSValue evaluationResult = JSC::evaluate(state, scopeChain, JSC::makeSource(script), thisValue, &evaluationException); + if (evaluationException) + return QVariant(); + + int distance = 0; + return JSC::Bindings::convertValueToQVariant(state, evaluationResult, 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(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 rules = doc->styleSelector()->styleRulesForElement(m_element, /*authorOnly*/ true)) { + for (int i = rules->length(); i > 0; --i) { + CSSStyleRule* rule = static_cast(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 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(m_element)->style(); + if (!propID || !style) + return; + + ExceptionCode exception = 0; + style->setProperty(name, value,emptyString(), 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; + + RefPtr fragment = Range::createDocumentFragmentForElement(markup, toHTMLElement(m_element)); + + 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; + + RefPtr fragment = Range::createDocumentFragmentForElement(markup, toHTMLElement(m_element)); + + 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; + + Node* parent = m_element->parentNode(); + if (!parent) + return; + + if (!parent->isHTMLElement()) + return; + + RefPtr fragment = Range::createDocumentFragmentForElement(markup, toHTMLElement(parent)); + + ExceptionCode exception = 0; + parent->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; + + Node* parent = m_element->parentNode(); + if (!parent) + return; + + if (!parent->isHTMLElement()) + return; + + RefPtr fragment = Range::createDocumentFragmentForElement(markup, toHTMLElement(parent)); + + ExceptionCode exception = 0; + if (!m_element->nextSibling()) + parent->appendChild(fragment, exception); + else + parent->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 findInsertionPoint(PassRefPtr root) +{ + RefPtr 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(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 insertionPoint = findInsertionPoint(element.m_element); + + if (!insertionPoint) + return; + + ExceptionCode exception = 0; + + // reparent children + for (RefPtr child = m_element->firstChild(); child;) { + RefPtr 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; + + RefPtr fragment = Range::createDocumentFragmentForElement(markup, toHTMLElement(m_element)); + + if (!fragment || !fragment->firstChild()) + return; + + RefPtr insertionPoint = findInsertionPoint(fragment->firstChild()); + + if (!insertionPoint) + return; + + ExceptionCode exception = 0; + + // reparent children + for (RefPtr child = m_element->firstChild(); child;) { + RefPtr 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 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; + + Node* parent = m_element->parentNode(); + if (!parent) + return; + + if (!parent->isHTMLElement()) + return; + + RefPtr fragment = Range::createDocumentFragmentForElement(markup, toHTMLElement(parent)); + + if (!fragment || !fragment->firstChild()) + return; + + RefPtr insertionPoint = findInsertionPoint(fragment->firstChild()); + + if (!insertionPoint) + return; + + // Keep reference to parent & siblingNode 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* 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 , or 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 , or 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) +{ + render(painter, QRect()); +} + +/*! + Render the element into \a painter clipping to \a clip. +*/ +void QWebElement::render(QPainter* painter, const QRect& clip) +{ + 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; + + QRect finalClipRect = rect; + if (!clip.isEmpty()) + rect.intersect(clip.translated(rect.location())); + + GraphicsContext context(painter); + + context.save(); + context.translate(-rect.x(), -rect.y()); + painter->setClipRect(finalClipRect, Qt::IntersectClip); + view->setNodeToDraw(e); + view->paintContents(&context, finalClipRect); + view->setNodeToDraw(0); + context.restore(); +} + +class QWebElementCollectionPrivate : public QSharedData +{ +public: + static QWebElementCollectionPrivate* create(const PassRefPtr &context, const QString &query); + + RefPtr m_result; + +private: + inline QWebElementCollectionPrivate() {} +}; + +QWebElementCollectionPrivate* QWebElementCollectionPrivate::create(const PassRefPtr &context, const QString &query) +{ + if (!context) + return 0; + + // Let WebKit do the hard work hehehe + ExceptionCode exception = 0; // ### + RefPtr 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::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 > nodes; + RefPtr 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(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 QWebElementCollection::toList() const +{ + if (!d) + return QList(); + QList elements; + int i = 0; + Node* n = d->m_result->item(i); + while (n) { + if (n->isElementNode()) + elements.append(QWebElement(static_cast(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. +*/ + +#if USE(JSC) +QWebElement QtWebElementRuntime::create(Element* element) +{ + return QWebElement(element); +} + +Element* QtWebElementRuntime::get(const QWebElement& element) +{ + return element.m_element; +} + +static QVariant convertJSValueToWebElementVariant(JSC::JSObject* object, int *distance, HashSet* visitedObjects) +{ + Element* element = 0; + QVariant ret; + if (object && object->inherits(&JSElement::s_info)) { + element =(static_cast(object))->impl(); + *distance = 0; + // Allow other objects to reach this one. This won't cause our algorithm to + // loop since when we find an Element we do not recurse. + visitedObjects->remove(object); + } else if (object && object->inherits(&JSDocument::s_info)) { + // To support LayoutTestControllerQt::nodesFromRect(), used in DRT, we do an implicit + // conversion from 'document' to the QWebElement representing the 'document.documentElement'. + // We can't simply use a QVariantMap in nodesFromRect() because it currently times out + // when serializing DOMMimeType and DOMPlugin, even if we limit the recursion. + element =(static_cast(object))->impl()->documentElement(); + } + + return QVariant::fromValue(QtWebElementRuntime::create(element)); +} + +static JSC::JSValue convertWebElementVariantToJSValue(JSC::ExecState* exec, WebCore::JSDOMGlobalObject* globalObject, const QVariant& variant) +{ + return WebCore::toJS(exec, globalObject, QtWebElementRuntime::get(variant.value())); +} +#endif + +void QtWebElementRuntime::initialize() +{ + static bool initialized = false; + if (initialized) + return; + initialized = true; +#if USE(JSC) + int id = qRegisterMetaType(); + JSC::Bindings::registerCustomType(id, convertJSValueToWebElementVariant, convertWebElementVariantToJSValue); +#endif +} diff --git a/Source/WebKit/qt/Api/qwebelement.h b/Source/WebKit/qt/Api/qwebelement.h new file mode 100644 index 000000000..efec5eb7c --- /dev/null +++ b/Source/WebKit/qt/Api/qwebelement.h @@ -0,0 +1,264 @@ +/* + 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 +#include +#include +#include +#include + +#include "qwebkitglobal.h" +namespace WebCore { + class Element; + class Node; +} + +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); + void render(QPainter* painter, const QRect& clipRect); + +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; + friend class QWebPagePrivate; + friend class QtWebElementRuntime; + + 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 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 d; +}; + +Q_DECLARE_METATYPE(QWebElement) + +#endif // QWEBELEMENT_H diff --git a/Source/WebKit/qt/Api/qwebelement_p.h b/Source/WebKit/qt/Api/qwebelement_p.h new file mode 100644 index 000000000..204a5c77b --- /dev/null +++ b/Source/WebKit/qt/Api/qwebelement_p.h @@ -0,0 +1,38 @@ +/* + Copyright (C) 2011 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_p_h +#define qwebelement_p_h + +class QWebElement; + +namespace WebCore { +class Element; +} + +// this is here as a proxy, so we'd have a class to friend in QWebElement, +// as getting/setting a WebCore in QWebElement is private +class QtWebElementRuntime { +public: + static void initialize(); + static QWebElement create(WebCore::Element*); + static WebCore::Element* get(const QWebElement&); +}; + +#endif // qwebelement_p_h diff --git a/Source/WebKit/qt/Api/qwebframe.cpp b/Source/WebKit/qt/Api/qwebframe.cpp new file mode 100644 index 000000000..c8e8dad5e --- /dev/null +++ b/Source/WebKit/qt/Api/qwebframe.cpp @@ -0,0 +1,2008 @@ +/* + 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 "APICast.h" +#include "BridgeJSC.h" +#include "CallFrame.h" +#elif USE(V8) +#include "V8Binding.h" +#include +#endif +#include "Document.h" +#include "DocumentLoader.h" +#include "DragData.h" +#include "Element.h" +#include "FocusController.h" +#include "Frame.h" +#include "FrameLoaderClientQt.h" +#include "FrameSelection.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 "JavaScript.h" +#include "JSDOMBinding.h" +#include "JSDOMWindowBase.h" +#include "JSLock.h" +#include "JSObject.h" +#include "JSRetainPtr.h" +#include "OpaqueJSString.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 "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/TextureMapperNode.h" +#endif +#include "wtf/HashMap.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#if ENABLE(ORIENTATION_EVENTS) && QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +QTM_USE_NAMESPACE +#endif + +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(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 USE(TILED_BACKING_STORE) +void QWebFramePrivate::renderFromTiledBackingStore(GraphicsContext* context, const QRegion& clip) +{ + ASSERT(frame->tiledBackingStore()); + + if (!frame->view() || !frame->contentRenderer()) + return; + + QVector 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())); + renderFrameExtras(context, QFlags(QWebFrame::ScrollBarLayer) | QWebFrame::PanIconLayer, clip); +#endif +} +#endif + +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) +void QWebFramePrivate::renderCompositedLayers(GraphicsContext* context, const IntRect& clip) +{ + if (!rootTextureMapperNode || !textureMapper) + return; + + textureMapper->setGraphicsContext(context); + textureMapper->setImageInterpolationQuality(context->imageInterpolationQuality()); + textureMapper->setTextDrawingMode(context->textDrawingMode()); + textureMapper->setViewportSize(frame->view()->frameRect().size()); + QPainter* painter = context->platformContext(); + const QTransform transform = painter->worldTransform(); + const TransformationMatrix matrix( + transform.m11(), transform.m12(), 0, transform.m13(), + transform.m21(), transform.m22(), 0, transform.m23(), + 0, 0, 1, 0, + transform.m31(), transform.m32(), 0, transform.m33() + ); + rootTextureMapperNode->setTransform(matrix); + rootTextureMapperNode->setOpacity(painter->opacity()); + textureMapper->beginPainting(); + textureMapper->beginClip(matrix, clip); + rootTextureMapperNode->paint(); + textureMapper->endClip(); + textureMapper->endPainting(); +} +#endif + +void QWebFramePrivate::renderRelativeCoords(GraphicsContext* context, QFlags layers, const QRegion& clip) +{ + if (!frame->view() || !frame->contentRenderer()) + return; + + QVector vector = clip.rects(); + if (vector.isEmpty()) + return; + + QPainter* painter = context->platformContext(); + + WebCore::FrameView* view = frame->view(); + view->updateLayoutAndStyleIfNeededRecursive(); + + if (layers & QWebFrame::ContentsLayer) { + for (int i = 0; i < vector.size(); ++i) { + const QRect& clipRect = vector.at(i); + + QRect rect = 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(); + + 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(); + } +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) + renderCompositedLayers(context, IntRect(clip.boundingRect())); +#endif + } + renderFrameExtras(context, layers, clip); +#if ENABLE(INSPECTOR) + if (frame->page()->inspectorController()->highlightedNode()) { + context->save(); + frame->page()->inspectorController()->drawHighlight(*context); + context->restore(); + } +#endif +} + +void QWebFramePrivate::renderFrameExtras(GraphicsContext* context, QFlags layers, const QRegion& clip) +{ + if (!(layers & (QWebFrame::PanIconLayer | QWebFrame::ScrollBarLayer))) + return; + QPainter* painter = context->platformContext(); + WebCore::FrameView* view = frame->view(); + QVector vector = clip.rects(); + 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 (layers & QWebFrame::ScrollBarLayer + && !view->scrollbarsSuppressed() + && (view->horizontalScrollbar() || view->verticalScrollbar())) { + + QRect rect = intersectedRect; + context->translate(x, y); + rect.translate(-x, -y); + view->paintScrollbars(context, rect); + context->translate(-x, -y); + } + +#if ENABLE(PAN_SCROLLING) + if (layers & QWebFrame::PanIconLayer) + view->paintPanScrollIcon(context); +#endif + + painter->restore(); + } +} + +void QWebFramePrivate::emitUrlChanged() +{ + url = frame->document()->url(); + emit q->urlChanged(url); +} + +void QWebFramePrivate::_q_orientationChanged() +{ +#if ENABLE(ORIENTATION_EVENTS) + int orientation; + WebCore::Frame* frame = core(q); + + switch (m_orientation.reading()->orientation()) { + case QOrientationReading::TopUp: + orientation = 0; + break; + case QOrientationReading::TopDown: + orientation = 180; + break; + case QOrientationReading::LeftUp: + orientation = -90; + break; + case QOrientationReading::RightUp: + orientation = 90; + break; + case QOrientationReading::FaceUp: + case QOrientationReading::FaceDown: + // WebCore unable to handle it + default: + return; + } + frame->sendOrientationChangeEvent(orientation); +#endif +} + +void QWebFramePrivate::didClearWindowObject() +{ +#if USE(JSC) + if (page->settings()->testAttribute(QWebSettings::JavascriptEnabled)) + addQtSenderToGlobalObject(); +#endif + emit q->javaScriptWindowObjectCleared(); +} + +#if USE(JSC) +static JSValueRef qtSenderCallback(JSContextRef context, JSObjectRef, JSObjectRef, size_t, const JSValueRef[], JSValueRef*) +{ + QObject* sender = JSC::Bindings::QtInstance::qtSenderStack()->top(); + if (!sender) + return JSValueMakeUndefined(context); + + JSC::ExecState* exec = ::toJS(context); + RefPtr rootObject = JSC::Bindings::findRootObject(exec->dynamicGlobalObject()); + JSC::JSObject* jsSender = JSC::Bindings::QtInstance::getQtInstance(sender, rootObject, QScriptEngine::QtOwnership)->createRuntimeObject(exec); + return ::toRef(jsSender); +} + +void QWebFramePrivate::addQtSenderToGlobalObject() +{ + JSC::JSLock lock(JSC::SilenceAssertionsOnly); + + JSDOMWindow* window = toJSDOMWindow(frame, mainThreadNormalWorld()); + Q_ASSERT(window); + + JSC::ExecState* exec = window->globalExec(); + Q_ASSERT(exec); + + JSContextRef context = ::toRef(exec); + JSRetainPtr propertyName(Adopt, JSStringCreateWithUTF8CString("__qt_sender__")); + JSObjectRef function = JSObjectMakeFunctionWithCallback(context, propertyName.get(), qtSenderCallback); + + // JSC public API doesn't support setting a Getter for a property of a given object, https://bugs.webkit.org/show_bug.cgi?id=61374. + window->methodTable()->defineGetter(window, exec, propertyName.get()->identifier(&exec->globalData()), ::toJS(function), + JSC::ReadOnly | JSC::DontEnum | JSC::DontDelete); +} +#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{} or \c{