/* | |
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" | |
#include "Bridge.h" | |
#include "CallFrame.h" | |
#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" | |
#include "GCController.h" | |
#include "GraphicsContext.h" | |
#include "HTMLMetaElement.h" | |
#include "HitTestResult.h" | |
#include "IconDatabase.h" | |
#include "InspectorController.h" | |
#include "JSDOMBinding.h" | |
#include "JSDOMWindowBase.h" | |
#include "JSLock.h" | |
#include "JSObject.h" | |
#include "NodeList.h" | |
#include "Page.h" | |
#include "PlatformMouseEvent.h" | |
#include "PlatformWheelEvent.h" | |
#include "PrintContext.h" | |
#include "PutPropertySlot.h" | |
#include "RenderTreeAsText.h" | |
#include "RenderView.h" | |
#include "ResourceRequest.h" | |
#include "ScriptController.h" | |
#include "ScriptSourceCode.h" | |
#include "ScriptValue.h" | |
#include "Scrollbar.h" | |
#include "SelectionController.h" | |
#include "SubstituteData.h" | |
#include "SVGSMILElement.h" | |
#include "TiledBackingStore.h" | |
#include "htmlediting.h" | |
#include "markup.h" | |
#include "qt_instance.h" | |
#include "qt_runtime.h" | |
#include "qwebelement.h" | |
#include "qwebframe_p.h" | |
#include "qwebpage.h" | |
#include "qwebpage_p.h" | |
#include "qwebsecurityorigin.h" | |
#include "qwebsecurityorigin_p.h" | |
#include "runtime_object.h" | |
#include "runtime_root.h" | |
#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 | |
void QWEBKIT_EXPORT qt_drt_setMediaType(QWebFrame* qframe, const QString& type) | |
{ | |
WebCore::Frame* frame = QWebFramePrivate::core(qframe); | |
WebCore::FrameView* view = frame->view(); | |
view->setMediaType(type); | |
frame->document()->updateStyleSelector(); | |
view->forceLayout(); | |
} | |
bool QWEBKIT_EXPORT qt_drt_hasDocumentElement(QWebFrame* qframe) | |
{ | |
return QWebFramePrivate::core(qframe)->document()->documentElement(); | |
} | |
void QWEBKIT_EXPORT qt_drt_setJavaScriptProfilingEnabled(QWebFrame* qframe, bool enabled) | |
{ | |
#if ENABLE(JAVASCRIPT_DEBUGGER) | |
Frame* frame = QWebFramePrivate::core(qframe); | |
InspectorController* controller = frame->page()->inspectorController(); | |
if (!controller) | |
return; | |
if (enabled) | |
controller->enableProfiler(); | |
else | |
controller->disableProfiler(); | |
#endif | |
} | |
// Pause a given CSS animation or transition on the target node at a specific time. | |
// If the animation or transition is already paused, it will update its pause time. | |
// This method is only intended to be used for testing the CSS animation and transition system. | |
bool QWEBKIT_EXPORT qt_drt_pauseAnimation(QWebFrame *qframe, const QString &animationName, double time, const QString &elementId) | |
{ | |
Frame* frame = QWebFramePrivate::core(qframe); | |
if (!frame) | |
return false; | |
AnimationController* controller = frame->animation(); | |
if (!controller) | |
return false; | |
Document* doc = frame->document(); | |
Q_ASSERT(doc); | |
Node* coreNode = doc->getElementById(elementId); | |
if (!coreNode || !coreNode->renderer()) | |
return false; | |
return controller->pauseAnimationAtTime(coreNode->renderer(), animationName, time); | |
} | |
bool QWEBKIT_EXPORT qt_drt_pauseTransitionOfProperty(QWebFrame *qframe, const QString &propertyName, double time, const QString &elementId) | |
{ | |
Frame* frame = QWebFramePrivate::core(qframe); | |
if (!frame) | |
return false; | |
AnimationController* controller = frame->animation(); | |
if (!controller) | |
return false; | |
Document* doc = frame->document(); | |
Q_ASSERT(doc); | |
Node* coreNode = doc->getElementById(elementId); | |
if (!coreNode || !coreNode->renderer()) | |
return false; | |
return controller->pauseTransitionAtTime(coreNode->renderer(), propertyName, time); | |
} | |
// Pause a given SVG animation on the target node at a specific time. | |
// This method is only intended to be used for testing the SVG animation system. | |
bool QWEBKIT_EXPORT qt_drt_pauseSVGAnimation(QWebFrame *qframe, const QString &animationId, double time, const QString &elementId) | |
{ | |
#if !ENABLE(SVG) | |
return false; | |
#else | |
Frame* frame = QWebFramePrivate::core(qframe); | |
if (!frame) | |
return false; | |
Document* doc = frame->document(); | |
Q_ASSERT(doc); | |
if (!doc->svgExtensions()) | |
return false; | |
Node* coreNode = doc->getElementById(animationId); | |
if (!coreNode || !SVGSMILElement::isSMILElement(coreNode)) | |
return false; | |
return doc->accessSVGExtensions()->sampleAnimationAtTime(elementId, static_cast<SVGSMILElement*>(coreNode), time); | |
#endif | |
} | |
// Returns the total number of currently running animations (includes both CSS transitions and CSS animations). | |
int QWEBKIT_EXPORT qt_drt_numberOfActiveAnimations(QWebFrame *qframe) | |
{ | |
Frame* frame = QWebFramePrivate::core(qframe); | |
if (!frame) | |
return false; | |
AnimationController* controller = frame->animation(); | |
if (!controller) | |
return false; | |
return controller->numberOfActiveAnimations(); | |
} | |
void QWEBKIT_EXPORT qt_drt_clearFrameName(QWebFrame* qFrame) | |
{ | |
Frame* frame = QWebFramePrivate::core(qFrame); | |
frame->tree()->clearName(); | |
} | |
int QWEBKIT_EXPORT qt_drt_javaScriptObjectsCount() | |
{ | |
return JSDOMWindowBase::commonJSGlobalData()->heap.globalObjectCount(); | |
} | |
void QWEBKIT_EXPORT qt_drt_garbageCollector_collect() | |
{ | |
gcController().garbageCollectNow(); | |
} | |
void QWEBKIT_EXPORT qt_drt_garbageCollector_collectOnAlternateThread(bool waitUntilDone) | |
{ | |
gcController().garbageCollectOnAlternateThreadForDebugging(waitUntilDone); | |
} | |
// Returns the value of counter in the element specified by \a id. | |
QString QWEBKIT_EXPORT qt_drt_counterValueForElementById(QWebFrame* qFrame, const QString& id) | |
{ | |
Frame* frame = QWebFramePrivate::core(qFrame); | |
if (Document* document = frame->document()) { | |
Element* element = document->getElementById(id); | |
return WebCore::counterValueForElement(element); | |
} | |
return QString(); | |
} | |
int QWEBKIT_EXPORT qt_drt_pageNumberForElementById(QWebFrame* qFrame, const QString& id, float width, float height) | |
{ | |
Frame* frame = QWebFramePrivate::core(qFrame); | |
if (!frame) | |
return -1; | |
Element* element = frame->document()->getElementById(AtomicString(id)); | |
if (!element) | |
return -1; | |
return PrintContext::pageNumberForElement(element, FloatSize(width, height)); | |
} | |
int QWEBKIT_EXPORT qt_drt_numberOfPages(QWebFrame* qFrame, float width, float height) | |
{ | |
Frame* frame = QWebFramePrivate::core(qFrame); | |
if (!frame) | |
return -1; | |
return PrintContext::numberOfPages(frame, FloatSize(width, height)); | |
} | |
// Suspend active DOM objects in this frame. | |
void QWEBKIT_EXPORT qt_suspendActiveDOMObjects(QWebFrame* qFrame) | |
{ | |
Frame* frame = QWebFramePrivate::core(qFrame); | |
if (frame->document()) | |
frame->document()->suspendActiveDOMObjects(); | |
} | |
// Resume active DOM objects in this frame. | |
void QWEBKIT_EXPORT qt_resumeActiveDOMObjects(QWebFrame* qFrame) | |
{ | |
Frame* frame = QWebFramePrivate::core(qFrame); | |
if (frame->document()) | |
frame->document()->resumeActiveDOMObjects(); | |
} | |
void QWEBKIT_EXPORT qt_drt_evaluateScriptInIsolatedWorld(QWebFrame* qFrame, int worldId, const QString& script) | |
{ | |
Frame* frame = QWebFramePrivate::core(qFrame); | |
if (frame) | |
JSC::JSValue result = frame->script()->executeScriptInWorld(mainThreadNormalWorld(), script, true).jsValue(); | |
} | |
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); | |
} | |
QWebFrameData::QWebFrameData(WebCore::Page* parentPage, WebCore::Frame* parentFrame, | |
WebCore::HTMLFrameOwnerElement* ownerFrameElement, | |
const WebCore::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(); | |
} | |
} | |
#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->layoutIfNeededRecursive(); | |
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::ContentsLayer) { | |
context->save(); | |
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(); | |
} | |
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(); | |
} | |
} | |
/*! | |
\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); | |
} | |
} | |
QWebFrame::QWebFrame(QWebFrame *parent, QWebFrameData *frameData) | |
: QObject(parent) | |
, d(new QWebFramePrivate) | |
{ | |
d->page = parent->d->page; | |
d->init(this, frameData); | |
} | |
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; | |
JSC::JSLock lock(JSC::SilenceAssertionsOnly); | |
JSDOMWindow* window = toJSDOMWindow(d->frame, mainThreadNormalWorld()); | |
JSC::Bindings::RootObject* root = d->frame->script()->bindingRootObject(); | |
if (!window) { | |
qDebug() << "Warning: couldn't get window 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, (const UChar *) name.constData(), name.length()), runtimeObject, slot); | |
} | |
/*! | |
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) | |
{ | |
d->frame->loader()->begin(ensureAbsoluteUrl(url)); | |
d->frame->loader()->end(); | |
load(ensureAbsoluteUrl(url)); | |
} | |
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()->name(); | |
} | |
/*! | |
The web page that contains this frame. | |
*/ | |
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) | |
{ | |
load(QNetworkRequest(ensureAbsoluteUrl(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; | |
#if QT_VERSION >= 0x040600 | |
case QNetworkAccessManager::DeleteOperation: | |
request.setHTTPMethod("DELETE"); | |
break; | |
#endif | |
case QNetworkAccessManager::UnknownOperation: | |
// eh? | |
break; | |
} | |
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. | |
\note This method will not affect session or global history for the frame. | |
\sa toHtml(), setContent() | |
*/ | |
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, WebCore::String("text/html"), WebCore::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 = mimeType; | |
if (actualMimeType.isEmpty()) | |
actualMimeType = QLatin1String("text/html"); | |
WebCore::SubstituteData substituteData(buffer, WebCore::String(actualMimeType), WebCore::String(), 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(); | |
FrameLoaderClientQt *client = static_cast<FrameLoaderClientQt*>(loader->client()); | |
if (client) | |
rc.append(client->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); | |
} | |
} | |
/*! | |
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) | |
{ | |
d->frame->setZoomFactor(factor, ZoomTextOnly); | |
} | |
/*! | |
Returns the value of the multiplier used to scale the text in a Web frame. | |
*/ | |
qreal QWebFrame::textSizeMultiplier() const | |
{ | |
return d->frame->zoomFactor(); | |
} | |
/*! | |
\property QWebFrame::zoomFactor | |
\since 4.5 | |
\brief the zoom factor for the frame | |
*/ | |
void QWebFrame::setZoomFactor(qreal factor) | |
{ | |
d->frame->setZoomFactor(factor, d->frame->zoomMode()); | |
} | |
qreal QWebFrame::zoomFactor() const | |
{ | |
return d->frame->zoomFactor(); | |
} | |
/*! | |
\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(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) { | |
JSC::JSValue v = d->frame->script()->executeScript(ScriptSourceCode(scriptSource)).jsValue(); | |
int distance = 0; | |
rc = JSC::Bindings::convertValueToQVariant(proxy->globalObject(mainThreadNormalWorld())->globalExec(), v, QMetaType::Void, &distance); | |
} | |
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(QWebFrame* webFrame) | |
{ | |
return webFrame->d->frame; | |
} | |
QWebFrame* QWebFramePrivate::kit(WebCore::Frame* coreFrame) | |
{ | |
return static_cast<FrameLoaderClientQt*>(coreFrame->loader()->client())->webFrame(); | |
} | |
/*! | |
\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() | |
*/ | |
/*! | |
\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; | |
} |