diff options
Diffstat (limited to 'Source/WebKit/qt/Api/qwebframe.cpp')
-rw-r--r-- | Source/WebKit/qt/Api/qwebframe.cpp | 1931 |
1 files changed, 1931 insertions, 0 deletions
diff --git a/Source/WebKit/qt/Api/qwebframe.cpp b/Source/WebKit/qt/Api/qwebframe.cpp new file mode 100644 index 0000000..9c89a4c --- /dev/null +++ b/Source/WebKit/qt/Api/qwebframe.cpp @@ -0,0 +1,1931 @@ +/* + Copyright (C) 2008,2009 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2007 Staikos Computing Services Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qwebframe.h" + +#if USE(JSC) +#include "Bridge.h" +#include "CallFrame.h" +#elif USE(V8) +#include "V8Binding.h" +#endif +#include "Document.h" +#include "DocumentLoader.h" +#include "DragData.h" +#include "Element.h" +#include "FocusController.h" +#include "Frame.h" +#include "FrameLoaderClientQt.h" +#include "FrameTree.h" +#include "FrameView.h" +#if USE(JSC) +#include "GCController.h" +#elif USE(V8) +#include "V8GCController.h" +#endif +#include "GraphicsContext.h" +#include "HTMLMetaElement.h" +#include "HitTestResult.h" +#include "HTTPParsers.h" +#include "IconDatabase.h" +#include "InspectorController.h" +#if USE(JSC) +#include "JSDOMBinding.h" +#include "JSDOMWindowBase.h" +#include "JSLock.h" +#include "JSObject.h" +#elif USE(V8) +#include "V8DOMWrapper.h" +#include "V8DOMWindowShell.h" +#endif +#include "NetworkingContext.h" +#include "NodeList.h" +#include "Page.h" +#include "PlatformMouseEvent.h" +#include "PlatformWheelEvent.h" +#include "PrintContext.h" +#if USE(JSC) +#include "PutPropertySlot.h" +#endif +#include "RenderLayer.h" +#include "RenderTreeAsText.h" +#include "RenderView.h" +#include "ResourceRequest.h" +#include "ScriptController.h" +#include "ScriptSourceCode.h" +#include "ScriptValue.h" +#include "Scrollbar.h" +#include "Settings.h" +#include "SelectionController.h" +#include "SubstituteData.h" +#include "SVGSMILElement.h" +#include "TiledBackingStore.h" +#include "htmlediting.h" +#include "markup.h" +#if USE(JSC) +#include "qt_instance.h" +#include "qt_runtime.h" +#endif +#include "qwebelement.h" +#include "qwebframe_p.h" +#include "qwebpage.h" +#include "qwebpage_p.h" +#include "qwebsecurityorigin.h" +#include "qwebsecurityorigin_p.h" +#include "qwebscriptworld.h" +#include "qwebscriptworld_p.h" +#if USE(JSC) +#include "runtime_object.h" +#include "runtime_root.h" +#endif +#if USE(TEXTURE_MAPPER) +#include "texmap/TextureMapper.h" +#include "texmap/TextureMapperPlatformLayer.h" +#endif +#include "wtf/HashMap.h" +#include <QMultiMap> +#include <qdebug.h> +#include <qevent.h> +#include <qfileinfo.h> +#include <qpainter.h> +#include <qprinter.h> +#include <qregion.h> +#include <qnetworkrequest.h> + +using namespace WebCore; + +// from text/qfont.cpp +QT_BEGIN_NAMESPACE +extern Q_GUI_EXPORT int qt_defaultDpi(); +QT_END_NAMESPACE + +bool QWEBKIT_EXPORT qtwebkit_webframe_scrollOverflow(QWebFrame* qFrame, int dx, int dy, const QPoint& pos) +{ + WebCore::Frame* frame = QWebFramePrivate::core(qFrame); + if (!frame || !frame->document() || !frame->view() || !frame->eventHandler()) + return false; + + QPoint contentsPos = frame->view()->windowToContents(pos); + Node* node = frame->document()->elementFromPoint(contentsPos.x(), contentsPos.y()); + if (!node) + return false; + + RenderObject* renderer = node->renderer(); + if (!renderer) + return false; + + if (renderer->isListBox()) + return false; + + RenderLayer* renderLayer = renderer->enclosingLayer(); + if (!renderLayer) + return false; + + bool scrolledHorizontal = false; + bool scrolledVertical = false; + + do { + if (dx > 0) + scrolledHorizontal = renderLayer->scroll(ScrollRight, ScrollByPixel, dx); + else if (dx < 0) + scrolledHorizontal = renderLayer->scroll(ScrollLeft, ScrollByPixel, qAbs(dx)); + + if (dy > 0) + scrolledVertical = renderLayer->scroll(ScrollDown, ScrollByPixel, dy); + else if (dy < 0) + scrolledVertical = renderLayer->scroll(ScrollUp, ScrollByPixel, qAbs(dy)); + + if (scrolledHorizontal || scrolledVertical) + return true; + + renderLayer = renderLayer->parent(); + } while (renderLayer); + + return false; +} + + +/*! + \internal + Scrolls nested frames starting at this frame, \a dx pixels to the right + and \a dy pixels downward. Both \a dx and \a dy may be negative. First attempts + to scroll elements with CSS overflow at position pos, followed by this frame. If this + frame doesn't scroll, attempts to scroll the parent +*/ +void QWEBKIT_EXPORT qtwebkit_webframe_scrollRecursively(QWebFrame* qFrame, int dx, int dy, const QPoint& pos) +{ + if (!qFrame) + return; + + if (qtwebkit_webframe_scrollOverflow(qFrame, dx, dy, pos)) + return; + + bool scrollHorizontal = false; + bool scrollVertical = false; + + do { + if (dx > 0) // scroll right + scrollHorizontal = qFrame->scrollBarValue(Qt::Horizontal) < qFrame->scrollBarMaximum(Qt::Horizontal); + else if (dx < 0) // scroll left + scrollHorizontal = qFrame->scrollBarValue(Qt::Horizontal) > qFrame->scrollBarMinimum(Qt::Horizontal); + + if (dy > 0) // scroll down + scrollVertical = qFrame->scrollBarValue(Qt::Vertical) < qFrame->scrollBarMaximum(Qt::Vertical); + else if (dy < 0) //scroll up + scrollVertical = qFrame->scrollBarValue(Qt::Vertical) > qFrame->scrollBarMinimum(Qt::Vertical); + + if (scrollHorizontal || scrollVertical) { + qFrame->scroll(dx, dy); + return; + } + + qFrame = qFrame->parentFrame(); + } while (qFrame); +} + +static inline ResourceRequestCachePolicy cacheLoadControlToCachePolicy(uint cacheLoadControl) +{ + switch (cacheLoadControl) { + case QNetworkRequest::AlwaysNetwork: + return WebCore::ReloadIgnoringCacheData; + case QNetworkRequest::PreferCache: + return WebCore::ReturnCacheDataElseLoad; + case QNetworkRequest::AlwaysCache: + return WebCore::ReturnCacheDataDontLoad; + default: + break; + } + return WebCore::UseProtocolCachePolicy; +} + +QWebFrameData::QWebFrameData(WebCore::Page* parentPage, WebCore::Frame* parentFrame, + WebCore::HTMLFrameOwnerElement* ownerFrameElement, + const WTF::String& frameName) + : name(frameName) + , ownerElement(ownerFrameElement) + , page(parentPage) + , allowsScrolling(true) + , marginWidth(0) + , marginHeight(0) +{ + frameLoaderClient = new FrameLoaderClientQt(); + frame = Frame::create(page, ownerElement, frameLoaderClient); + + // FIXME: All of the below should probably be moved over into WebCore + frame->tree()->setName(name); + if (parentFrame) + parentFrame->tree()->appendChild(frame); +} + +void QWebFramePrivate::init(QWebFrame *qframe, QWebFrameData *frameData) +{ + q = qframe; + + allowsScrolling = frameData->allowsScrolling; + marginWidth = frameData->marginWidth; + marginHeight = frameData->marginHeight; + frame = frameData->frame.get(); + frameLoaderClient = frameData->frameLoaderClient; + frameLoaderClient->setFrame(qframe, frame); + + frame->init(); +} + +void QWebFramePrivate::setPage(QWebPage* newPage) +{ + if (page == newPage) + return; + + // The QWebFrame is created as a child of QWebPage or a parent QWebFrame. + // That adds it to QObject's internal children list and ensures it will be + // deleted when parent QWebPage is deleted. Reparent if needed. + if (q->parent() == qobject_cast<QObject*>(page)) + q->setParent(newPage); + + page = newPage; + emit q->pageChanged(); +} + +WebCore::Scrollbar* QWebFramePrivate::horizontalScrollBar() const +{ + if (!frame->view()) + return 0; + return frame->view()->horizontalScrollbar(); +} + +WebCore::Scrollbar* QWebFramePrivate::verticalScrollBar() const +{ + if (!frame->view()) + return 0; + return frame->view()->verticalScrollbar(); +} + +#if ENABLE(TILED_BACKING_STORE) +void QWebFramePrivate::renderFromTiledBackingStore(GraphicsContext* context, const QRegion& clip) +{ + ASSERT(frame->tiledBackingStore()); + + if (!frame->view() || !frame->contentRenderer()) + return; + + QVector<QRect> vector = clip.rects(); + if (vector.isEmpty()) + return; + + QPainter* painter = context->platformContext(); + + WebCore::FrameView* view = frame->view(); + + int scrollX = view->scrollX(); + int scrollY = view->scrollY(); + context->translate(-scrollX, -scrollY); + + for (int i = 0; i < vector.size(); ++i) { + const QRect& clipRect = vector.at(i); + + painter->save(); + + QRect rect = clipRect.translated(scrollX, scrollY); + painter->setClipRect(rect, Qt::IntersectClip); + + frame->tiledBackingStore()->paint(context, rect); + + painter->restore(); + } + +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) + renderCompositedLayers(context, IntRect(clip.boundingRect())); + renderRelativeCoords(context, (QWebFrame::RenderLayer)(QWebFrame::ScrollBarLayer | QWebFrame::PanIconLayer), clip); +#endif +} +#endif + +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) +void QWebFramePrivate::renderCompositedLayers(GraphicsContext* context, const IntRect& clip) +{ + if (!rootGraphicsLayer) + return; + + textureMapper->setGraphicsContext(context); + textureMapper->setImageInterpolationQuality(context->imageInterpolationQuality()); + textureMapper->setTextDrawingMode(context->textDrawingMode()); + QPainter* painter = context->platformContext(); + FrameView* view = frame->view(); + painter->save(); + painter->beginNativePainting(); + TextureMapperContentLayer::PaintOptions options; + options.visibleRect = clip; + options.targetRect = view->frameRect(); + options.viewportSize = view->size(); + options.opacity = painter->opacity(); + rootGraphicsLayer->paint(textureMapper.get(), options); + painter->endNativePainting(); + painter->restore(); +} +#endif + +void QWebFramePrivate::renderRelativeCoords(GraphicsContext* context, QWebFrame::RenderLayer layer, const QRegion& clip) +{ + if (!frame->view() || !frame->contentRenderer()) + return; + + QVector<QRect> vector = clip.rects(); + if (vector.isEmpty()) + return; + + QPainter* painter = context->platformContext(); + + WebCore::FrameView* view = frame->view(); + view->updateLayoutAndStyleIfNeededRecursive(); + + if (layer & QWebFrame::ContentsLayer) { + painter->save(); + for (int i = 0; i < vector.size(); ++i) { + const QRect& clipRect = vector.at(i); + + QRect intersectedRect = clipRect.intersected(view->frameRect()); + + context->save(); + painter->setClipRect(clipRect, Qt::IntersectClip); + + int x = view->x(); + int y = view->y(); + + int scrollX = view->scrollX(); + int scrollY = view->scrollY(); + + QRect rect = intersectedRect; + context->translate(x, y); + rect.translate(-x, -y); + context->translate(-scrollX, -scrollY); + rect.translate(scrollX, scrollY); + context->clip(view->visibleContentRect()); + + view->paintContents(context, rect); + + context->restore(); + } + painter->restore(); +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) + renderCompositedLayers(context, IntRect(clip.boundingRect())); +#endif + } + if (layer & (QWebFrame::PanIconLayer | QWebFrame::ScrollBarLayer)) { + for (int i = 0; i < vector.size(); ++i) { + const QRect& clipRect = vector.at(i); + + QRect intersectedRect = clipRect.intersected(view->frameRect()); + + painter->save(); + painter->setClipRect(clipRect, Qt::IntersectClip); + + int x = view->x(); + int y = view->y(); + + if (layer & QWebFrame::ScrollBarLayer + && !view->scrollbarsSuppressed() + && (view->horizontalScrollbar() || view->verticalScrollbar())) { + context->save(); + + QRect rect = intersectedRect; + context->translate(x, y); + rect.translate(-x, -y); + + view->paintScrollbars(context, rect); + + context->restore(); + } + +#if ENABLE(PAN_SCROLLING) + if (layer & QWebFrame::PanIconLayer) + view->paintPanScrollIcon(context); +#endif + + painter->restore(); + } + } +} + +void QWebFrame::orientationChanged() +{ +#if ENABLE(ORIENTATION_EVENTS) && ENABLE(DEVICE_ORIENTATION) + int orientation; + WebCore::Frame* frame = QWebFramePrivate::core(this); + + switch (d->m_orientation.reading()->orientation()) { + case QtMobility::QOrientationReading::TopUp: + orientation = 0; + break; + case QtMobility::QOrientationReading::TopDown: + orientation = 180; + break; + case QtMobility::QOrientationReading::LeftUp: + orientation = -90; + break; + case QtMobility::QOrientationReading::RightUp: + orientation = 90; + break; + case QtMobility::QOrientationReading::FaceUp: + case QtMobility::QOrientationReading::FaceDown: + // WebCore unable to handle it + default: + return; + } + frame->sendOrientationChangeEvent(orientation); +#endif +} +/*! + \class QWebFrame + \since 4.4 + \brief The QWebFrame class represents a frame in a web page. + + \inmodule QtWebKit + + QWebFrame represents a frame inside a web page. Each QWebPage + object contains at least one frame, the main frame, obtained using + QWebPage::mainFrame(). Additional frames will be created for HTML + \c{<frame>} or \c{<iframe>} elements. + + A frame can be loaded using load() or setUrl(). Alternatively, if you have + the HTML content readily available, you can use setHtml() instead. + + The page() function returns a pointer to the web page object. See + \l{QWebView}{Elements of QWebView} for an explanation of how web + frames are related to a web page and web view. + + The QWebFrame class also offers methods to retrieve both the URL currently + loaded by the frame (see url()) as well as the URL originally requested + to be loaded (see requestedUrl()). These methods make possible the retrieval + of the URL before and after a DNS resolution or a redirection occurs during + the load process. The requestedUrl() also matches to the URL added to the + frame history (\l{QWebHistory}) if load is successful. + + The title of an HTML frame can be accessed with the title() property. + Additionally, a frame may also specify an icon, which can be accessed + using the icon() property. If the title or the icon changes, the + corresponding titleChanged() and iconChanged() signals will be emitted. + The zoomFactor() property can be used to change the overall size + of the content displayed in the frame. + + QWebFrame objects are created and controlled by the web page. You + can connect to the web page's \l{QWebPage::}{frameCreated()} signal + to be notified when a new frame is created. + + There are multiple ways to programmatically examine the contents of a frame. + The hitTestContent() function can be used to find elements by coordinate. + For access to the underlying DOM tree, there is documentElement(), + findAllElements() and findFirstElement(). + + A QWebFrame can be printed onto a QPrinter using the print() function. + This function is marked as a slot and can be conveniently connected to + \l{QPrintPreviewDialog}'s \l{QPrintPreviewDialog::}{paintRequested()} + signal. + + \sa QWebPage +*/ + +/*! + \enum QWebFrame::RenderLayer + + This enum describes the layers available for rendering using \l{QWebFrame::}{render()}. + The layers can be OR-ed together from the following list: + + \value ContentsLayer The web content of the frame + \value ScrollBarLayer The scrollbars of the frame + \value PanIconLayer The icon used when panning the frame + + \value AllLayers Includes all the above layers +*/ + +QWebFrame::QWebFrame(QWebPage *parent, QWebFrameData *frameData) + : QObject(parent) + , d(new QWebFramePrivate) +{ + d->page = parent; + d->init(this, frameData); + + if (!frameData->url.isEmpty()) { + WebCore::ResourceRequest request(frameData->url, frameData->referrer); + d->frame->loader()->load(request, frameData->name, false); + } +#if ENABLE(ORIENTATION_EVENTS) && ENABLE(DEVICE_ORIENTATION) + connect(&d->m_orientation, SIGNAL(readingChanged()), this, SLOT(orientationChanged())); + d->m_orientation.start(); +#endif +} + +QWebFrame::QWebFrame(QWebFrame *parent, QWebFrameData *frameData) + : QObject(parent) + , d(new QWebFramePrivate) +{ + d->page = parent->d->page; + d->init(this, frameData); +#if ENABLE(ORIENTATION_EVENTS) && ENABLE(DEVICE_ORIENTATION) + connect(&d->m_orientation, SIGNAL(readingChanged()), this, SLOT(orientationChanged())); + d->m_orientation.start(); +#endif +} + +QWebFrame::~QWebFrame() +{ + if (d->frame && d->frame->loader() && d->frame->loader()->client()) + static_cast<FrameLoaderClientQt*>(d->frame->loader()->client())->m_webFrame = 0; + + delete d; +} + +/*! + Make \a object available under \a name from within the frame's JavaScript + context. The \a object will be inserted as a child of the frame's window + object. + + Qt properties will be exposed as JavaScript properties and slots as + JavaScript methods. + + If you want to ensure that your QObjects remain accessible after loading a + new URL, you should add them in a slot connected to the + javaScriptWindowObjectCleared() signal. + + If Javascript is not enabled for this page, then this method does nothing. + + The \a object will never be explicitly deleted by QtWebKit. +*/ +void QWebFrame::addToJavaScriptWindowObject(const QString &name, QObject *object) +{ + addToJavaScriptWindowObject(name, object, QScriptEngine::QtOwnership); +} + +/*! + \fn void QWebFrame::addToJavaScriptWindowObject(const QString &name, QObject *object, QScriptEngine::ValueOwnership own) + \overload + + Make \a object available under \a name from within the frame's JavaScript + context. The \a object will be inserted as a child of the frame's window + object. + + Qt properties will be exposed as JavaScript properties and slots as + JavaScript methods. + + If you want to ensure that your QObjects remain accessible after loading a + new URL, you should add them in a slot connected to the + javaScriptWindowObjectCleared() signal. + + If Javascript is not enabled for this page, then this method does nothing. + + The ownership of \a object is specified using \a own. +*/ +void QWebFrame::addToJavaScriptWindowObject(const QString &name, QObject *object, QScriptEngine::ValueOwnership ownership) +{ + if (!page()->settings()->testAttribute(QWebSettings::JavascriptEnabled)) + return; +#if USE(JSC) + JSC::JSLock lock(JSC::SilenceAssertionsOnly); + JSDOMWindow* window = toJSDOMWindow(d->frame, mainThreadNormalWorld()); + JSC::Bindings::RootObject* root; + if (ownership == QScriptEngine::QtOwnership) + root = d->frame->script()->cacheableBindingRootObject(); + else + root = d->frame->script()->bindingRootObject(); + + if (!window) { + qDebug() << "Warning: couldn't get window object"; + return; + } + if (!root) { + qDebug() << "Warning: couldn't get root object"; + return; + } + + JSC::ExecState* exec = window->globalExec(); + + JSC::JSObject* runtimeObject = + JSC::Bindings::QtInstance::getQtInstance(object, root, ownership)->createRuntimeObject(exec); + + JSC::PutPropertySlot slot; + window->put(exec, JSC::Identifier(exec, reinterpret_cast_ptr<const UChar*>(name.constData()), name.length()), runtimeObject, slot); +#elif USE(V8) + QScriptEngine* engine = d->frame->script()->qtScriptEngine(); + if (!engine) + return; + QScriptValue v = engine->newQObject(object, ownership); + engine->globalObject().property("window").setProperty(name, v); +#endif +} + +/*! + Returns the frame's content as HTML, enclosed in HTML and BODY tags. + + \sa setHtml(), toPlainText() +*/ +QString QWebFrame::toHtml() const +{ + if (!d->frame->document()) + return QString(); + return createMarkup(d->frame->document()); +} + +/*! + Returns the content of this frame converted to plain text, completely + stripped of all HTML formatting. + + \sa toHtml() +*/ +QString QWebFrame::toPlainText() const +{ + if (d->frame->view() && d->frame->view()->layoutPending()) + d->frame->view()->layout(); + + Element *documentElement = d->frame->document()->documentElement(); + if (documentElement) + return documentElement->innerText(); + return QString(); +} + +/*! + Returns a dump of the rendering tree. This is mainly useful for debugging + html. +*/ +QString QWebFrame::renderTreeDump() const +{ + if (d->frame->view() && d->frame->view()->layoutPending()) + d->frame->view()->layout(); + + return externalRepresentation(d->frame); +} + +/*! + \property QWebFrame::title + \brief the title of the frame as defined by the HTML <title> element + + \sa titleChanged() +*/ + +QString QWebFrame::title() const +{ + if (d->frame->document()) + return d->frame->loader()->documentLoader()->title(); + return QString(); +} + +/*! + \since 4.5 + \brief Returns the meta data in this frame as a QMultiMap + + The meta data consists of the name and content attributes of the + of the \c{<meta>} tags in the HTML document. + + For example: + + \code + <html> + <head> + <meta name="description" content="This document is a tutorial about Qt development"> + <meta name="keywords" content="Qt, WebKit, Programming"> + </head> + ... + </html> + \endcode + + Given the above HTML code the metaData() function will return a map with two entries: + \table + \header \o Key + \o Value + \row \o "description" + \o "This document is a tutorial about Qt development" + \row \o "keywords" + \o "Qt, WebKit, Programming" + \endtable + + This function returns a multi map to support multiple meta tags with the same attribute name. +*/ +QMultiMap<QString, QString> QWebFrame::metaData() const +{ + if (!d->frame->document()) + return QMap<QString, QString>(); + + QMultiMap<QString, QString> map; + Document* doc = d->frame->document(); + RefPtr<NodeList> list = doc->getElementsByTagName("meta"); + unsigned len = list->length(); + for (unsigned i = 0; i < len; i++) { + HTMLMetaElement* meta = static_cast<HTMLMetaElement*>(list->item(i)); + map.insert(meta->name(), meta->content()); + } + return map; +} + +static inline QUrl ensureAbsoluteUrl(const QUrl &url) +{ + if (!url.isRelative()) + return url; + + return QUrl::fromLocalFile(QFileInfo(url.toLocalFile()).absoluteFilePath()); +} + +/*! + \property QWebFrame::url + \brief the url of the frame currently viewed + + Setting this property clears the view and loads the URL. + + By default, this property contains an empty, invalid URL. + + \sa urlChanged() +*/ + +void QWebFrame::setUrl(const QUrl &url) +{ + const QUrl absolute = ensureAbsoluteUrl(url); + d->frame->loader()->writer()->begin(absolute); + d->frame->loader()->writer()->end(); + load(absolute); +} + +QUrl QWebFrame::url() const +{ + return d->frame->loader()->url(); +} + +/*! + \since 4.6 + \property QWebFrame::requestedUrl + + The URL requested to loaded by the frame currently viewed. The URL may differ from + the one returned by url() if a DNS resolution or a redirection occurs. + + \sa url(), setUrl() +*/ +QUrl QWebFrame::requestedUrl() const +{ + // There are some possible edge cases to be handled here, + // apart from checking if activeDocumentLoader is valid: + // + // * Method can be called while processing an unsucessful load. + // In this case, frameLoaderClient will hold the current error + // (m_loadError), and we will make use of it to recover the 'failingURL'. + // * If the 'failingURL' holds a null'ed string though, we fallback + // to 'outgoingReferrer' (it yet is safer than originalRequest). + FrameLoader* loader = d->frame->loader(); + FrameLoaderClientQt* loaderClient = d->frameLoaderClient; + + if (!loader->activeDocumentLoader() + || !loaderClient->m_loadError.isNull()) { + if (!loaderClient->m_loadError.failingURL().isNull()) + return QUrl(loaderClient->m_loadError.failingURL()); + else if (!loader->outgoingReferrer().isEmpty()) + return QUrl(loader->outgoingReferrer()); + } + + return loader->originalRequest().url(); +} +/*! + \since 4.6 + \property QWebFrame::baseUrl + \brief the base URL of the frame, can be used to resolve relative URLs + \since 4.6 +*/ + +QUrl QWebFrame::baseUrl() const +{ + return d->frame->loader()->baseURL(); +} + +/*! + \property QWebFrame::icon + \brief the icon associated with this frame + + \sa iconChanged(), QWebSettings::iconForUrl() +*/ + +QIcon QWebFrame::icon() const +{ + return QWebSettings::iconForUrl(d->frame->loader()->url()); +} + +/*! + The name of this frame as defined by the parent frame. +*/ +QString QWebFrame::frameName() const +{ + return d->frame->tree()->uniqueName(); +} + +/*! + The web page that contains this frame. + + \sa pageChanged() +*/ +QWebPage *QWebFrame::page() const +{ + return d->page; +} + +/*! + Loads \a url into this frame. + + \note The view remains the same until enough data has arrived to display the new \a url. + + \sa setUrl(), setHtml(), setContent() +*/ +void QWebFrame::load(const QUrl &url) +{ + // The load() overload ensures that the url is absolute. + load(QNetworkRequest(url)); +} + +/*! + Loads a network request, \a req, into this frame, using the method specified in \a + operation. + + \a body is optional and is only used for POST operations. + + \note The view remains the same until enough data has arrived to display the new content. + + \sa setUrl() +*/ +void QWebFrame::load(const QNetworkRequest &req, + QNetworkAccessManager::Operation operation, + const QByteArray &body) +{ + if (d->parentFrame()) + d->page->d->insideOpenCall = true; + + QUrl url = ensureAbsoluteUrl(req.url()); + + WebCore::ResourceRequest request(url); + + switch (operation) { + case QNetworkAccessManager::HeadOperation: + request.setHTTPMethod("HEAD"); + break; + case QNetworkAccessManager::GetOperation: + request.setHTTPMethod("GET"); + break; + case QNetworkAccessManager::PutOperation: + request.setHTTPMethod("PUT"); + break; + case QNetworkAccessManager::PostOperation: + request.setHTTPMethod("POST"); + break; + case QNetworkAccessManager::DeleteOperation: + request.setHTTPMethod("DELETE"); + break; +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) + case QNetworkAccessManager::CustomOperation: + request.setHTTPMethod(req.attribute(QNetworkRequest::CustomVerbAttribute).toByteArray().constData()); + break; +#endif + case QNetworkAccessManager::UnknownOperation: + // eh? + break; + } + + QVariant cacheLoad = req.attribute(QNetworkRequest::CacheLoadControlAttribute); + if (cacheLoad.isValid()) { + bool ok; + uint cacheLoadValue = cacheLoad.toUInt(&ok); + if (ok) + request.setCachePolicy(cacheLoadControlToCachePolicy(cacheLoadValue)); + } + + QList<QByteArray> httpHeaders = req.rawHeaderList(); + for (int i = 0; i < httpHeaders.size(); ++i) { + const QByteArray &headerName = httpHeaders.at(i); + request.addHTTPHeaderField(QString::fromLatin1(headerName), QString::fromLatin1(req.rawHeader(headerName))); + } + + if (!body.isEmpty()) + request.setHTTPBody(WebCore::FormData::create(body.constData(), body.size())); + + d->frame->loader()->load(request, false); + + if (d->parentFrame()) + d->page->d->insideOpenCall = false; +} + +/*! + Sets the content of this frame to \a html. \a baseUrl is optional and used to resolve relative + URLs in the document, such as referenced images or stylesheets. + + The \a html is loaded immediately; external objects are loaded asynchronously. + + If a script in the \a html runs longer than the default script timeout (currently 10 seconds), + for example due to being blocked by a modal JavaScript alert dialog, this method will return + as soon as possible after the timeout and any subsequent \a html will be loaded asynchronously. + + When using this method WebKit assumes that external resources such as JavaScript programs or style + sheets are encoded in UTF-8 unless otherwise specified. For example, the encoding of an external + script can be specified through the charset attribute of the HTML script tag. It is also possible + for the encoding to be specified by web server. + + This is a convenience function equivalent to setContent(html, "text/html", baseUrl). + + \note This method will not affect session or global history for the frame. + + \warning This function works only for HTML, for other mime types (i.e. XHTML, SVG) + setContent() should be used instead. + + \sa toHtml(), setContent(), load() +*/ +void QWebFrame::setHtml(const QString &html, const QUrl &baseUrl) +{ + KURL kurl(baseUrl); + WebCore::ResourceRequest request(kurl); + const QByteArray utf8 = html.toUtf8(); + WTF::RefPtr<WebCore::SharedBuffer> data = WebCore::SharedBuffer::create(utf8.constData(), utf8.length()); + WebCore::SubstituteData substituteData(data, WTF::String("text/html"), WTF::String("utf-8"), KURL()); + d->frame->loader()->load(request, substituteData, false); +} + +/*! + Sets the content of this frame to the specified content \a data. If the \a mimeType argument + is empty it is currently assumed that the content is HTML but in future versions we may introduce + auto-detection. + + External objects referenced in the content are located relative to \a baseUrl. + + The \a data is loaded immediately; external objects are loaded asynchronously. + + \note This method will not affect session or global history for the frame. + + \sa toHtml(), setHtml() +*/ +void QWebFrame::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl) +{ + KURL kurl(baseUrl); + WebCore::ResourceRequest request(kurl); + WTF::RefPtr<WebCore::SharedBuffer> buffer = WebCore::SharedBuffer::create(data.constData(), data.length()); + QString actualMimeType; + WTF::String encoding; + if (mimeType.isEmpty()) + actualMimeType = QLatin1String("text/html"); + else { + actualMimeType = extractMIMETypeFromMediaType(mimeType); + encoding = extractCharsetFromMediaType(mimeType); + } + WebCore::SubstituteData substituteData(buffer, WTF::String(actualMimeType), encoding, KURL()); + d->frame->loader()->load(request, substituteData, false); +} + +/*! + Returns the parent frame of this frame, or 0 if the frame is the web pages + main frame. + + This is equivalent to qobject_cast<QWebFrame*>(frame->parent()). + + \sa childFrames() +*/ +QWebFrame *QWebFrame::parentFrame() const +{ + return d->parentFrame(); +} + +/*! + Returns a list of all frames that are direct children of this frame. + + \sa parentFrame() +*/ +QList<QWebFrame*> QWebFrame::childFrames() const +{ + QList<QWebFrame*> rc; + if (d->frame) { + FrameTree *tree = d->frame->tree(); + for (Frame *child = tree->firstChild(); child; child = child->tree()->nextSibling()) { + FrameLoader *loader = child->loader(); + QWebFrame* webFrame = qobject_cast<QWebFrame*>(loader->networkingContext()->originatingObject()); + if (webFrame) + rc.append(webFrame); + } + + } + return rc; +} + +/*! + Returns the scrollbar policy for the scrollbar defined by \a orientation. +*/ +Qt::ScrollBarPolicy QWebFrame::scrollBarPolicy(Qt::Orientation orientation) const +{ + if (orientation == Qt::Horizontal) + return d->horizontalScrollBarPolicy; + return d->verticalScrollBarPolicy; +} + +/*! + Sets the scrollbar policy for the scrollbar defined by \a orientation to \a policy. +*/ +void QWebFrame::setScrollBarPolicy(Qt::Orientation orientation, Qt::ScrollBarPolicy policy) +{ + Q_ASSERT((int)ScrollbarAuto == (int)Qt::ScrollBarAsNeeded); + Q_ASSERT((int)ScrollbarAlwaysOff == (int)Qt::ScrollBarAlwaysOff); + Q_ASSERT((int)ScrollbarAlwaysOn == (int)Qt::ScrollBarAlwaysOn); + + if (orientation == Qt::Horizontal) { + d->horizontalScrollBarPolicy = policy; + if (d->frame->view()) { + d->frame->view()->setHorizontalScrollbarMode((ScrollbarMode)policy, policy != Qt::ScrollBarAsNeeded /* lock */); + d->frame->view()->updateCanHaveScrollbars(); + } + } else { + d->verticalScrollBarPolicy = policy; + if (d->frame->view()) { + d->frame->view()->setVerticalScrollbarMode((ScrollbarMode)policy, policy != Qt::ScrollBarAsNeeded /* lock */); + d->frame->view()->updateCanHaveScrollbars(); + } + } +} + +/*! + Sets the current \a value for the scrollbar with orientation \a orientation. + + The scrollbar forces the \a value to be within the legal range: minimum <= value <= maximum. + + Changing the value also updates the thumb position. + + \sa scrollBarMinimum(), scrollBarMaximum() +*/ +void QWebFrame::setScrollBarValue(Qt::Orientation orientation, int value) +{ + Scrollbar *sb; + sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar(); + if (sb) { + if (value < 0) + value = 0; + else if (value > scrollBarMaximum(orientation)) + value = scrollBarMaximum(orientation); + sb->setValue(value, Scrollbar::NotFromScrollAnimator); + } +} + +/*! + Returns the current value for the scrollbar with orientation \a orientation, or 0 + if no scrollbar is found for \a orientation. + + \sa scrollBarMinimum(), scrollBarMaximum() +*/ +int QWebFrame::scrollBarValue(Qt::Orientation orientation) const +{ + Scrollbar *sb; + sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar(); + if (sb) + return sb->value(); + return 0; +} + +/*! + Returns the maximum value for the scrollbar with orientation \a orientation, or 0 + if no scrollbar is found for \a orientation. + + \sa scrollBarMinimum() +*/ +int QWebFrame::scrollBarMaximum(Qt::Orientation orientation) const +{ + Scrollbar *sb; + sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar(); + if (sb) + return sb->maximum(); + return 0; +} + +/*! + Returns the minimum value for the scrollbar with orientation \a orientation. + + The minimum value is always 0. + + \sa scrollBarMaximum() +*/ +int QWebFrame::scrollBarMinimum(Qt::Orientation orientation) const +{ + Q_UNUSED(orientation) + return 0; +} + +/*! + \since 4.6 + Returns the geometry for the scrollbar with orientation \a orientation. + + If the scrollbar does not exist an empty rect is returned. +*/ +QRect QWebFrame::scrollBarGeometry(Qt::Orientation orientation) const +{ + Scrollbar *sb; + sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar(); + if (sb) + return sb->frameRect(); + return QRect(); +} + +/*! + \since 4.5 + Scrolls the frame \a dx pixels to the right and \a dy pixels downward. Both + \a dx and \a dy may be negative. + + \sa QWebFrame::scrollPosition +*/ + +void QWebFrame::scroll(int dx, int dy) +{ + if (!d->frame->view()) + return; + + d->frame->view()->scrollBy(IntSize(dx, dy)); +} + +/*! + \property QWebFrame::scrollPosition + \since 4.5 + \brief the position the frame is currently scrolled to. +*/ + +QPoint QWebFrame::scrollPosition() const +{ + if (!d->frame->view()) + return QPoint(0, 0); + + IntSize ofs = d->frame->view()->scrollOffset(); + return QPoint(ofs.width(), ofs.height()); +} + +void QWebFrame::setScrollPosition(const QPoint &pos) +{ + QPoint current = scrollPosition(); + int dx = pos.x() - current.x(); + int dy = pos.y() - current.y(); + scroll(dx, dy); +} + +/*! + \since 4.7 + Scrolls the frame to the given \a anchor name. +*/ +void QWebFrame::scrollToAnchor(const QString& anchor) +{ + FrameView *view = d->frame->view(); + if (view) + view->scrollToAnchor(anchor); +} + +/*! + \since 4.6 + Render the \a layer of the frame using \a painter clipping to \a clip. + + \sa print() +*/ + +void QWebFrame::render(QPainter* painter, RenderLayer layer, const QRegion& clip) +{ + GraphicsContext context(painter); + if (context.paintingDisabled() && !context.updatingControlTints()) + return; + + if (!clip.isEmpty()) + d->renderRelativeCoords(&context, layer, clip); + else if (d->frame->view()) + d->renderRelativeCoords(&context, layer, QRegion(d->frame->view()->frameRect())); +} + +/*! + Render the frame into \a painter clipping to \a clip. +*/ +void QWebFrame::render(QPainter* painter, const QRegion& clip) +{ + GraphicsContext context(painter); + if (context.paintingDisabled() && !context.updatingControlTints()) + return; + + d->renderRelativeCoords(&context, AllLayers, clip); +} + +/*! + Render the frame into \a painter. +*/ +void QWebFrame::render(QPainter* painter) +{ + if (!d->frame->view()) + return; + + GraphicsContext context(painter); + if (context.paintingDisabled() && !context.updatingControlTints()) + return; + + d->renderRelativeCoords(&context, AllLayers, QRegion(d->frame->view()->frameRect())); +} + +/*! + \property QWebFrame::textSizeMultiplier + \brief the scaling factor for all text in the frame + \obsolete + + Use setZoomFactor instead, in combination with the ZoomTextOnly attribute in + QWebSettings. + + \note Setting this property also enables the ZoomTextOnly attribute in + QWebSettings. +*/ + +/*! + Sets the value of the multiplier used to scale the text in a Web frame to + the \a factor specified. +*/ +void QWebFrame::setTextSizeMultiplier(qreal factor) +{ + page()->settings()->setAttribute(QWebSettings::ZoomTextOnly, true); + + d->frame->setPageAndTextZoomFactors(1, factor); +} + +/*! + Returns the value of the multiplier used to scale the text in a Web frame. +*/ +qreal QWebFrame::textSizeMultiplier() const +{ + return page()->settings()->testAttribute(QWebSettings::ZoomTextOnly) ? d->frame->textZoomFactor() : d->frame->pageZoomFactor(); +} + +/*! + \property QWebFrame::zoomFactor + \since 4.5 + \brief the zoom factor for the frame +*/ + +void QWebFrame::setZoomFactor(qreal factor) +{ + if (page()->settings()->testAttribute(QWebSettings::ZoomTextOnly)) + d->frame->setTextZoomFactor(factor); + else + d->frame->setPageZoomFactor(factor); +} + +qreal QWebFrame::zoomFactor() const +{ + return page()->settings()->testAttribute(QWebSettings::ZoomTextOnly) ? d->frame->textZoomFactor() : d->frame->pageZoomFactor(); +} + +/*! + \property QWebFrame::focus + \since 4.6 + + Returns true if this frame has keyboard input focus; otherwise, returns false. +*/ +bool QWebFrame::hasFocus() const +{ + WebCore::Frame* ff = d->frame->page()->focusController()->focusedFrame(); + return ff && QWebFramePrivate::kit(ff) == this; +} + +/*! + \since 4.6 + + Gives keyboard input focus to this frame. +*/ +void QWebFrame::setFocus() +{ + QWebFramePrivate::core(this)->page()->focusController()->setFocusedFrame(QWebFramePrivate::core(this)); +} + +/*! + Returns the position of the frame relative to it's parent frame. +*/ +QPoint QWebFrame::pos() const +{ + if (!d->frame->view()) + return QPoint(); + + return d->frame->view()->frameRect().topLeft(); +} + +/*! + Return the geometry of the frame relative to it's parent frame. +*/ +QRect QWebFrame::geometry() const +{ + if (!d->frame->view()) + return QRect(); + return d->frame->view()->frameRect(); +} + +/*! + \property QWebFrame::contentsSize + \brief the size of the contents in this frame + + \sa contentsSizeChanged() +*/ +QSize QWebFrame::contentsSize() const +{ + FrameView *view = d->frame->view(); + if (!view) + return QSize(); + return QSize(view->contentsWidth(), view->contentsHeight()); +} + +/*! + \since 4.6 + + Returns the document element of this frame. + + The document element provides access to the entire structured + content of the frame. +*/ +QWebElement QWebFrame::documentElement() const +{ + WebCore::Document *doc = d->frame->document(); + if (!doc) + return QWebElement(); + return QWebElement(doc->documentElement()); +} + +/*! + \since 4.6 + Returns a new list of elements matching the given CSS selector \a selectorQuery. + If there are no matching elements, an empty list is returned. + + \l{http://www.w3.org/TR/REC-CSS2/selector.html#q1}{Standard CSS2 selector} syntax is + used for the query. + + \sa QWebElement::findAll() +*/ +QWebElementCollection QWebFrame::findAllElements(const QString &selectorQuery) const +{ + return documentElement().findAll(selectorQuery); +} + +/*! + \since 4.6 + Returns the first element in the frame's document that matches the + given CSS selector \a selectorQuery. If there is no matching element, a + null element is returned. + + \l{http://www.w3.org/TR/REC-CSS2/selector.html#q1}{Standard CSS2 selector} syntax is + used for the query. + + \sa QWebElement::findFirst() +*/ +QWebElement QWebFrame::findFirstElement(const QString &selectorQuery) const +{ + return documentElement().findFirst(selectorQuery); +} + +/*! + Performs a hit test on the frame contents at the given position \a pos and returns the hit test result. +*/ +QWebHitTestResult QWebFrame::hitTestContent(const QPoint &pos) const +{ + if (!d->frame->view() || !d->frame->contentRenderer()) + return QWebHitTestResult(); + + HitTestResult result = d->frame->eventHandler()->hitTestResultAtPoint(d->frame->view()->windowToContents(pos), /*allowShadowContent*/ false, /*ignoreClipping*/ true); + + if (result.scrollbar()) + return QWebHitTestResult(); + + return QWebHitTestResult(new QWebHitTestResultPrivate(result)); +} + +/*! \reimp +*/ +bool QWebFrame::event(QEvent *e) +{ + return QObject::event(e); +} + +#ifndef QT_NO_PRINTER +/*! + Prints the frame to the given \a printer. + + \sa render() +*/ +void QWebFrame::print(QPrinter *printer) const +{ + QPainter painter; + if (!painter.begin(printer)) + return; + + const qreal zoomFactorX = (qreal)printer->logicalDpiX() / qt_defaultDpi(); + const qreal zoomFactorY = (qreal)printer->logicalDpiY() / qt_defaultDpi(); + + PrintContext printContext(d->frame); + float pageHeight = 0; + + QRect qprinterRect = printer->pageRect(); + + IntRect pageRect(0, 0, + int(qprinterRect.width() / zoomFactorX), + int(qprinterRect.height() / zoomFactorY)); + + printContext.begin(pageRect.width()); + + printContext.computePageRects(pageRect, /* headerHeight */ 0, /* footerHeight */ 0, /* userScaleFactor */ 1.0, pageHeight); + + int docCopies; + int pageCopies; + if (printer->collateCopies()) { + docCopies = 1; + pageCopies = printer->numCopies(); + } else { + docCopies = printer->numCopies(); + pageCopies = 1; + } + + int fromPage = printer->fromPage(); + int toPage = printer->toPage(); + bool ascending = true; + + if (fromPage == 0 && toPage == 0) { + fromPage = 1; + toPage = printContext.pageCount(); + } + // paranoia check + fromPage = qMax(1, fromPage); + toPage = qMin(static_cast<int>(printContext.pageCount()), toPage); + if (toPage < fromPage) { + // if the user entered a page range outside the actual number + // of printable pages, just return + return; + } + + if (printer->pageOrder() == QPrinter::LastPageFirst) { + int tmp = fromPage; + fromPage = toPage; + toPage = tmp; + ascending = false; + } + + painter.scale(zoomFactorX, zoomFactorY); + GraphicsContext ctx(&painter); + + for (int i = 0; i < docCopies; ++i) { + int page = fromPage; + while (true) { + for (int j = 0; j < pageCopies; ++j) { + if (printer->printerState() == QPrinter::Aborted + || printer->printerState() == QPrinter::Error) { + printContext.end(); + return; + } + printContext.spoolPage(ctx, page - 1, pageRect.width()); + if (j < pageCopies - 1) + printer->newPage(); + } + + if (page == toPage) + break; + + if (ascending) + ++page; + else + --page; + + printer->newPage(); + } + + if ( i < docCopies - 1) + printer->newPage(); + } + + printContext.end(); +} +#endif // QT_NO_PRINTER + +/*! + Evaluates the JavaScript defined by \a scriptSource using this frame as context + and returns the result of the last executed statement. + + \sa addToJavaScriptWindowObject(), javaScriptWindowObjectCleared() +*/ +QVariant QWebFrame::evaluateJavaScript(const QString& scriptSource) +{ + ScriptController *proxy = d->frame->script(); + QVariant rc; + if (proxy) { +#if USE(JSC) + int distance = 0; + JSC::JSValue v = d->frame->script()->executeScript(ScriptSourceCode(scriptSource)).jsValue(); + + rc = JSC::Bindings::convertValueToQVariant(proxy->globalObject(mainThreadNormalWorld())->globalExec(), v, QMetaType::Void, &distance); +#elif USE(V8) + QScriptEngine* engine = d->frame->script()->qtScriptEngine(); + if (!engine) + return rc; + rc = engine->evaluate(scriptSource).toVariant(); +#endif + } + return rc; +} + +/*! + \since 4.5 + + Returns the frame's security origin. +*/ +QWebSecurityOrigin QWebFrame::securityOrigin() const +{ + QWebFrame* that = const_cast<QWebFrame*>(this); + QWebSecurityOriginPrivate* priv = new QWebSecurityOriginPrivate(QWebFramePrivate::core(that)->document()->securityOrigin()); + return QWebSecurityOrigin(priv); +} + +WebCore::Frame* QWebFramePrivate::core(const QWebFrame* webFrame) +{ + return webFrame->d->frame; +} + +QWebFrame* QWebFramePrivate::kit(const WebCore::Frame* coreFrame) +{ + return qobject_cast<QWebFrame*>(coreFrame->loader()->networkingContext()->originatingObject()); +} + + +/*! + \fn void QWebFrame::javaScriptWindowObjectCleared() + + This signal is emitted whenever the global window object of the JavaScript + environment is cleared, e.g., before starting a new load. + + If you intend to add QObjects to a QWebFrame using + addToJavaScriptWindowObject(), you should add them in a slot connected + to this signal. This ensures that your objects remain accessible when + loading new URLs. +*/ + +/*! + \fn void QWebFrame::provisionalLoad() + \internal +*/ + +/*! + \fn void QWebFrame::titleChanged(const QString &title) + + This signal is emitted whenever the title of the frame changes. + The \a title string specifies the new title. + + \sa title() +*/ + +/*! + \fn void QWebFrame::urlChanged(const QUrl &url) + + This signal is emitted with the URL of the frame when the frame's title is + received. The new URL is specified by \a url. + + \sa url() +*/ + +/*! + \fn void QWebFrame::initialLayoutCompleted() + + This signal is emitted when the frame is laid out the first time. + This is the first time you will see contents displayed on the frame. + + \note A frame can be laid out multiple times. +*/ + +/*! + \fn void QWebFrame::iconChanged() + + This signal is emitted when the icon ("favicon") associated with the frame + has been loaded. + + \sa icon() +*/ + +/*! + \fn void QWebFrame::contentsSizeChanged(const QSize &size) + \since 4.6 + + This signal is emitted when the frame's contents size changes + to \a size. + + \sa contentsSize() +*/ + +/*! + \fn void QWebFrame::loadStarted() + \since 4.6 + + This signal is emitted when a new load of this frame is started. + + \sa loadFinished() +*/ + +/*! + \fn void QWebFrame::loadFinished(bool ok) + \since 4.6 + + This signal is emitted when a load of this frame is finished. + \a ok will indicate whether the load was successful or any error occurred. + + \sa loadStarted() +*/ + +/*! + \fn void QWebFrame::pageChanged() + \since 4.7 + + This signal is emitted when this frame has been moved to a different QWebPage. + + \sa page() +*/ + +/*! + \class QWebHitTestResult + \since 4.4 + \brief The QWebHitTestResult class provides information about the web + page content after a hit test. + + \inmodule QtWebKit + + QWebHitTestResult is returned by QWebFrame::hitTestContent() to provide + information about the content of the web page at the specified position. +*/ + +/*! + \internal +*/ +QWebHitTestResult::QWebHitTestResult(QWebHitTestResultPrivate *priv) + : d(priv) +{ +} + +QWebHitTestResultPrivate::QWebHitTestResultPrivate(const WebCore::HitTestResult &hitTest) + : isContentEditable(false) + , isContentSelected(false) + , isScrollBar(false) +{ + if (!hitTest.innerNode()) + return; + pos = hitTest.point(); + WebCore::TextDirection dir; + title = hitTest.title(dir); + linkText = hitTest.textContent(); + linkUrl = hitTest.absoluteLinkURL(); + linkTitle = hitTest.titleDisplayString(); + alternateText = hitTest.altDisplayString(); + imageUrl = hitTest.absoluteImageURL(); + innerNode = hitTest.innerNode(); + innerNonSharedNode = hitTest.innerNonSharedNode(); + boundingRect = innerNonSharedNode ? innerNonSharedNode->renderer()->absoluteBoundingBoxRect(true) : IntRect(); + WebCore::Image *img = hitTest.image(); + if (img) { + QPixmap *pix = img->nativeImageForCurrentFrame(); + if (pix) + pixmap = *pix; + } + WebCore::Frame *wframe = hitTest.targetFrame(); + if (wframe) + linkTargetFrame = QWebFramePrivate::kit(wframe); + linkElement = QWebElement(hitTest.URLElement()); + + isContentEditable = hitTest.isContentEditable(); + isContentSelected = hitTest.isSelected(); + isScrollBar = hitTest.scrollbar(); + + if (innerNonSharedNode && innerNonSharedNode->document() + && innerNonSharedNode->document()->frame()) + frame = QWebFramePrivate::kit(innerNonSharedNode->document()->frame()); + + enclosingBlock = QWebElement(WebCore::enclosingBlock(innerNode.get())); +} + +/*! + Constructs a null hit test result. +*/ +QWebHitTestResult::QWebHitTestResult() + : d(0) +{ +} + +/*! + Constructs a hit test result from \a other. +*/ +QWebHitTestResult::QWebHitTestResult(const QWebHitTestResult &other) + : d(0) +{ + if (other.d) + d = new QWebHitTestResultPrivate(*other.d); +} + +/*! + Assigns the \a other hit test result to this. +*/ +QWebHitTestResult &QWebHitTestResult::operator=(const QWebHitTestResult &other) +{ + if (this != &other) { + if (other.d) { + if (!d) + d = new QWebHitTestResultPrivate; + *d = *other.d; + } else { + delete d; + d = 0; + } + } + return *this; +} + +/*! + Destructor. +*/ +QWebHitTestResult::~QWebHitTestResult() +{ + delete d; +} + +/*! + Returns true if the hit test result is null; otherwise returns false. +*/ +bool QWebHitTestResult::isNull() const +{ + return !d; +} + +/*! + Returns the position where the hit test occured. +*/ +QPoint QWebHitTestResult::pos() const +{ + if (!d) + return QPoint(); + return d->pos; +} + +/*! + \since 4.5 + Returns the bounding rect of the element. +*/ +QRect QWebHitTestResult::boundingRect() const +{ + if (!d) + return QRect(); + return d->boundingRect; +} + +/*! + \since 4.6 + Returns the block element that encloses the element hit. + + A block element is an element that is rendered using the + CSS "block" style. This includes for example text + paragraphs. +*/ +QWebElement QWebHitTestResult::enclosingBlockElement() const +{ + if (!d) + return QWebElement(); + return d->enclosingBlock; +} + +/*! + Returns the title of the nearest enclosing HTML element. +*/ +QString QWebHitTestResult::title() const +{ + if (!d) + return QString(); + return d->title; +} + +/*! + Returns the text of the link. +*/ +QString QWebHitTestResult::linkText() const +{ + if (!d) + return QString(); + return d->linkText; +} + +/*! + Returns the url to which the link points to. +*/ +QUrl QWebHitTestResult::linkUrl() const +{ + if (!d) + return QUrl(); + return d->linkUrl; +} + +/*! + Returns the title of the link. +*/ +QUrl QWebHitTestResult::linkTitle() const +{ + if (!d) + return QUrl(); + return d->linkTitle; +} + +/*! + \since 4.6 + Returns the element that represents the link. + + \sa linkTargetFrame() +*/ +QWebElement QWebHitTestResult::linkElement() const +{ + if (!d) + return QWebElement(); + return d->linkElement; +} + +/*! + Returns the frame that will load the link if it is activated. + + \sa linkElement() +*/ +QWebFrame *QWebHitTestResult::linkTargetFrame() const +{ + if (!d) + return 0; + return d->linkTargetFrame; +} + +/*! + Returns the alternate text of the element. This corresponds to the HTML alt attribute. +*/ +QString QWebHitTestResult::alternateText() const +{ + if (!d) + return QString(); + return d->alternateText; +} + +/*! + Returns the url of the image. +*/ +QUrl QWebHitTestResult::imageUrl() const +{ + if (!d) + return QUrl(); + return d->imageUrl; +} + +/*! + Returns a QPixmap containing the image. A null pixmap is returned if the + element being tested is not an image. +*/ +QPixmap QWebHitTestResult::pixmap() const +{ + if (!d) + return QPixmap(); + return d->pixmap; +} + +/*! + Returns true if the content is editable by the user; otherwise returns false. +*/ +bool QWebHitTestResult::isContentEditable() const +{ + if (!d) + return false; + return d->isContentEditable; +} + +/*! + Returns true if the content tested is part of the selection; otherwise returns false. +*/ +bool QWebHitTestResult::isContentSelected() const +{ + if (!d) + return false; + return d->isContentSelected; +} + +/*! + \since 4.6 + Returns the underlying DOM element as QWebElement. +*/ +QWebElement QWebHitTestResult::element() const +{ + if (!d || !d->innerNonSharedNode || !d->innerNonSharedNode->isElementNode()) + return QWebElement(); + + return QWebElement(static_cast<WebCore::Element*>(d->innerNonSharedNode.get())); +} + +/*! + Returns the frame the hit test was executed in. +*/ +QWebFrame *QWebHitTestResult::frame() const +{ + if (!d) + return 0; + return d->frame; +} |