| /* |
| 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 "BridgeJSC.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())); |
| renderFrameExtras(context, QFlags<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, QFlags<QWebFrame::RenderLayer> layers, 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 (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()->drawNodeHighlight(*context); |
| context->restore(); |
| } |
| #endif |
| } |
| |
| void QWebFramePrivate::renderFrameExtras(GraphicsContext* context, QFlags<QWebFrame::RenderLayer> layers, const QRegion& clip) |
| { |
| if (!(layers & (QWebFrame::PanIconLayer | QWebFrame::ScrollBarLayer))) |
| return; |
| QPainter* painter = context->platformContext(); |
| WebCore::FrameView* view = frame->view(); |
| QVector<QRect> 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) && ENABLE(DEVICE_ORIENTATION) |
| int orientation; |
| WebCore::Frame* frame = core(q); |
| |
| switch (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(_q_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(_q_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. |
| The interaction between C++ and JavaScript is explained in the documentation of the \l{The QtWebKit Bridge}{QtWebKit bridge}. |
| |
| 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. |
| The interaction between C++ and JavaScript is explained in the documentation of the \l{The QtWebKit Bridge}{QtWebKit bridge}. |
| |
| 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().string(); |
| 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 void clearCoreFrame(WebCore::Frame* frame) |
| { |
| frame->loader()->activeDocumentLoader()->writer()->begin(); |
| frame->loader()->activeDocumentLoader()->writer()->end(); |
| } |
| |
| static inline bool isCoreFrameClear(WebCore::Frame* frame) |
| { |
| return frame->document()->url().isEmpty(); |
| } |
| |
| static inline QUrl ensureAbsoluteUrl(const QUrl &url) |
| { |
| if (!url.isValid() || !url.isRelative()) |
| return url; |
| |
| // This contains the URL with absolute path but without |
| // the query and the fragment part. |
| QUrl baseUrl = QUrl::fromLocalFile(QFileInfo(url.toLocalFile()).absoluteFilePath()); |
| |
| // The path is removed so the query and the fragment parts are there. |
| QString pathRemoved = url.toString(QUrl::RemovePath); |
| QUrl toResolve(pathRemoved); |
| |
| return baseUrl.resolved(toResolve); |
| } |
| |
| /*! |
| \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) |
| { |
| clearCoreFrame(d->frame); |
| const QUrl absolute = ensureAbsoluteUrl(url); |
| d->url = absolute; |
| load(absolute); |
| } |
| |
| QUrl QWebFrame::url() const |
| { |
| return d->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 |
| { |
| return d->frameLoaderClient->lastRequestedUrl(); |
| } |
| /*! |
| \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 |
| { |
| if (isCoreFrameClear(d->frame)) |
| return QUrl(d->url).resolved(QUrl()); |
| return d->frame->document()->baseURL(); |
| } |
| |
| /*! |
| \property QWebFrame::icon |
| \brief the icon associated with this frame |
| |
| \sa iconChanged(), QWebSettings::iconForUrl() |
| */ |
| |
| QIcon QWebFrame::icon() const |
| { |
| return QWebSettings::iconForUrl(d->frame->document()->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; |
| case QNetworkAccessManager::CustomOperation: |
| request.setHTTPMethod(req.attribute(QNetworkRequest::CustomVerbAttribute).toByteArray().constData()); |
| break; |
| 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->scrollableArea()->scrollToOffsetWithoutAnimation(orientation == Qt::Horizontal ? HorizontalScrollbar : VerticalScrollbar, value); |
| } |
| } |
| |
| /*! |
| 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().location(); |
| } |
| |
| /*! |
| 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; |
| } |
| |
| #include "moc_qwebframe.cpp" |