diff options
Diffstat (limited to 'WebKit/qt/Api')
25 files changed, 9331 insertions, 0 deletions
diff --git a/WebKit/qt/Api/headers.pri b/WebKit/qt/Api/headers.pri new file mode 100644 index 0000000..1e70072 --- /dev/null +++ b/WebKit/qt/Api/headers.pri @@ -0,0 +1,11 @@ +WEBKIT_API_HEADERS = $$PWD/qcookiejar.h \ + $$PWD/qwebframe.h \ + $$PWD/qwebkitglobal.h \ + $$PWD/qwebnetworkinterface.h \ + $$PWD/qwebobjectplugin.h \ + $$PWD/qwebobjectpluginconnector.h \ + $$PWD/qwebpage.h \ + $$PWD/qwebview.h \ + $$PWD/qwebpagehistory.h \ + $$PWD/qwebsettings.h \ + $$PWD/qwebhistoryinterface.h diff --git a/WebKit/qt/Api/qcookiejar.cpp b/WebKit/qt/Api/qcookiejar.cpp new file mode 100644 index 0000000..a6cbdab --- /dev/null +++ b/WebKit/qt/Api/qcookiejar.cpp @@ -0,0 +1,105 @@ +/* + 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 "qcookiejar.h" +#include <QCoreApplication> +uint qHash(const QUrl&); +#include <QHash> +#include <QPointer> + +class QCookieJarPrivate { + public: + QCookieJarPrivate() { + enabled = true; + } + bool enabled; + QHash<QUrl, QString> jar; +}; + + +uint qHash(const QUrl& url) { + return qHash(url.toString()); +} + + +QCookieJar::QCookieJar() +: QObject(), d(new QCookieJarPrivate) +{ +} + + +QCookieJar::~QCookieJar() +{ + delete d; +} + + +void QCookieJar::setCookies(const QUrl& url, const QUrl& policyUrl, const QString& value) +{ + Q_UNUSED(policyUrl) + d->jar.insert(url, value); +} + + +QString QCookieJar::cookies(const QUrl& url) +{ + return d->jar.value(url); +} + + +bool QCookieJar::isEnabled() const +{ + return d->enabled; +} + + +void QCookieJar::setEnabled(bool enabled) +{ + d->enabled = enabled; +} + + +static QPointer<QCookieJar> gJar; +static bool gRoutineAdded = false; + +static void gCleanupJar() +{ + delete gJar; +} + + +void QCookieJar::setCookieJar(QCookieJar *jar) +{ + if (!gRoutineAdded) { + qAddPostRoutine(gCleanupJar); + gRoutineAdded = true; + } + delete gJar; + gJar = jar; +} + + +QCookieJar *QCookieJar::cookieJar() +{ + if (!gJar) { + setCookieJar(new QCookieJar); + } + return gJar; +} diff --git a/WebKit/qt/Api/qcookiejar.h b/WebKit/qt/Api/qcookiejar.h new file mode 100644 index 0000000..0ca00bd --- /dev/null +++ b/WebKit/qt/Api/qcookiejar.h @@ -0,0 +1,55 @@ +/* + Copyright (C) 2007 Staikos Computing Services Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QCOOKIEJAR_H +#define QCOOKIEJAR_H + +#include <QtCore/qobject.h> +#include <QtCore/qurl.h> +#include "qwebkitglobal.h" + +class QCookieJarPrivate; + +class QWEBKIT_EXPORT QCookieJar : public QObject +{ + Q_OBJECT + + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) +public: + QCookieJar(); + ~QCookieJar(); + + virtual void setCookies(const QUrl& url, const QUrl& policyUrl, const QString& value); + virtual QString cookies(const QUrl& url); + + bool isEnabled() const; + + static void setCookieJar(QCookieJar *jar); + static QCookieJar *cookieJar(); + +public slots: + virtual void setEnabled(bool enabled); + +private: + friend class QCookieJarPrivate; + QCookieJarPrivate *d; +}; + + +#endif diff --git a/WebKit/qt/Api/qtwebkit.prf b/WebKit/qt/Api/qtwebkit.prf new file mode 100644 index 0000000..37417c6 --- /dev/null +++ b/WebKit/qt/Api/qtwebkit.prf @@ -0,0 +1,4 @@ + +qtAddLibrary(QtWebKit) + +QT += network diff --git a/WebKit/qt/Api/qwebframe.cpp b/WebKit/qt/Api/qwebframe.cpp new file mode 100644 index 0000000..892949d --- /dev/null +++ b/WebKit/qt/Api/qwebframe.cpp @@ -0,0 +1,1207 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2007 Staikos Computing Services Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qwebframe.h" +#include "qwebpage.h" +#include "qwebpage_p.h" +#include "qwebframe_p.h" + +#include "DocumentLoader.h" +#include "FocusController.h" +#include "FrameLoaderClientQt.h" +#include "Frame.h" +#include "FrameTree.h" +#include "FrameView.h" +#include "IconDatabase.h" +#include "Page.h" +#include "PutPropertySlot.h" +#include "ResourceRequest.h" +#include "RenderView.h" +#include "SelectionController.h" +#include "Scrollbar.h" +#include "PrintContext.h" +#include "SubstituteData.h" + +#include "markup.h" +#include "RenderTreeAsText.h" +#include "Element.h" +#include "Document.h" +#include "DragData.h" +#include "RenderView.h" +#include "GraphicsContext.h" +#include "PlatformMouseEvent.h" +#include "PlatformWheelEvent.h" +#include "GraphicsContext.h" +#include "HitTestResult.h" + +#include "runtime.h" +#include "runtime_object.h" +#include "runtime_root.h" +#include "JSDOMWindow.h" +#include "qt_instance.h" +#include "ScriptController.h" +#include "JSDOMBinding.h" +#include "ExecState.h" +#include "JSLock.h" +#include "JSObject.h" +#include "qt_runtime.h" + +#include "wtf/HashMap.h" + +#include <qdebug.h> +#include <qevent.h> +#include <qfileinfo.h> +#include <qpainter.h> +#if QT_VERSION >= 0x040400 +#include <qnetworkrequest.h> +#else +#include "qwebnetworkinterface.h" +#endif +#include <qregion.h> +#include <qprinter.h> + +using namespace WebCore; + +// from text/qfont.cpp +QT_BEGIN_NAMESPACE +extern Q_GUI_EXPORT int qt_defaultDpi(); +QT_END_NAMESPACE + +void QWebFramePrivate::init(QWebFrame *qframe, WebCore::Page *webcorePage, QWebFrameData *frameData) +{ + q = qframe; + + allowsScrolling = frameData->allowsScrolling; + marginWidth = frameData->marginWidth; + marginHeight = frameData->marginHeight; + + frameLoaderClient = new FrameLoaderClientQt(); + RefPtr<Frame> newFrame = Frame::create(webcorePage, frameData->ownerElement, frameLoaderClient); + frame = newFrame.get(); + if (frameData->ownerElement) + frame->ref(); // balanced by adoptRef in FrameLoaderClientQt::createFrame + frameLoaderClient->setFrame(qframe, frame); + frame->init(); +} + +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(); +} + +void QWebFramePrivate::updateBackground() +{ + WebCore::FrameView *view = frame->view(); + if (!view) + return; + QBrush brush = page->palette().brush(QPalette::Background); + if (brush.style() == Qt::SolidPattern) { + view->setBaseBackgroundColor(brush.color()); + if (!brush.color().alpha()) + view->setTransparent(true); + } +} + +/*! + \class QWebFrame + \since 4.4 + \brief The QWebFrame class represents a frame in a web page. + + 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{Elements of QWebView} for an explanation of how web + frames are related to a web page and web view. + + 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. + + The hitTestContent() function can be used to programmatically examine the + contents of a frame. + + 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 +*/ + +QWebFrame::QWebFrame(QWebPage *parent, QWebFrameData *frameData) + : QObject(parent) + , d(new QWebFramePrivate) +{ + d->page = parent; + d->init(this, parent->d->page, frameData); + + if (!frameData->url.isEmpty()) { + WebCore::ResourceRequest request(frameData->url, frameData->referrer); + d->frame->loader()->load(request, frameData->name); + } +} + +QWebFrame::QWebFrame(QWebFrame *parent, QWebFrameData *frameData) + : QObject(parent) + , d(new QWebFramePrivate) +{ + d->page = parent->d->page; + d->init(this, parent->d->page->d->page, 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. +*/ +void QWebFrame::addToJavaScriptWindowObject(const QString &name, QObject *object) +{ + JSC::JSLock lock(false); + JSDOMWindow *window = toJSDOMWindow(d->frame); + 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::Instance::createRuntimeObject(exec, JSC::Bindings::QtInstance::getQtInstance(object, root)); + + JSC::PutPropertySlot slot; + window->put(exec, JSC::Identifier(exec, (const UChar *) name.constData(), name.length()), runtimeObject, slot); +} + +/*! + Returns the frame's content, converted to HTML. + + \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. + + \sa toHtml() +*/ +QString QWebFrame::toPlainText() const +{ + if (d->frame->view() && d->frame->view()->layoutPending()) + d->frame->view()->layout(); + + Element *documentElement = d->frame->document()->documentElement(); + return documentElement->innerText(); +} + +/*! + 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->contentRenderer()); +} + +/*! + \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(); + else return QString(); +} + +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 + + \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(); +} + +/*! + \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) +{ +#if QT_VERSION < 0x040400 + load(QWebNetworkRequest(ensureAbsoluteUrl(url))); +#else + load(QNetworkRequest(ensureAbsoluteUrl(url))); +#endif +} + +#if QT_VERSION < 0x040400 +/*! + Loads a network request, \a req, into this frame. + + \note The view remains the same until enough data has arrived to display the new url. +*/ +void QWebFrame::load(const QWebNetworkRequest &req) +{ + if (d->parentFrame()) + d->page->d->insideOpenCall = true; + + QUrl url = ensureAbsoluteUrl(req.url()); + QHttpRequestHeader httpHeader = req.httpHeader(); + QByteArray postData = req.postData(); + + WebCore::ResourceRequest request(url); + + QString method = httpHeader.method(); + if (!method.isEmpty()) + request.setHTTPMethod(method); + + QList<QPair<QString, QString> > values = httpHeader.values(); + for (int i = 0; i < values.size(); ++i) { + const QPair<QString, QString> &val = values.at(i); + request.addHTTPHeaderField(val.first, val.second); + } + + if (!postData.isEmpty()) + request.setHTTPBody(WebCore::FormData::create(postData.constData(), postData.size())); + + d->frame->loader()->load(request); + + if (d->parentFrame()) + d->page->d->insideOpenCall = false; +} + +#else + +/*! + 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 \a url. + + \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::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); + + if (d->parentFrame()) + d->page->d->insideOpenCall = false; +} +#endif + +/*! + Sets the content of this frame to \a html. \a baseUrl is optional and used to resolve relative + URLs in the document. + + 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. + + \sa toHtml() +*/ +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); +} + +/*! + 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. + + \sa toHtml() +*/ +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); +} + + +/*! + 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); + } else { + d->verticalScrollBarPolicy = policy; + if (d->frame->view()) + d->frame->view()->setVerticalScrollbarMode((ScrollbarMode)policy); + } +} + +/*! + 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 +{ + return 0; +} + +/*! + \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::scrollOffset +*/ + +void QWebFrame::scroll(int dx, int dy) const +{ + if (!d->frame->view()) + return; + + d->frame->view()->scrollBy(IntSize(dx, dy)); +} + +/*! + \property QWebFrame::scrollOffset + \brief The offset from the start this frame is currently scrolled to. +*/ + +QSize QWebFrame::scrollOffset() const +{ + if (!d->frame->view()) + return QSize(0,0); + + return d->frame->view()->scrollOffset(); +} + +void QWebFrame::setScrollOffset(const QSize &offset) const +{ + QSize current = scrollOffset(); + int dx = offset.width() - current.width(); + int dy = offset.height() - current.height(); + scroll(dx, dy); +} + +/*! + Render the frame into \a painter clipping to \a clip. + + \sa print() +*/ +void QWebFrame::render(QPainter *painter, const QRegion &clip) +{ + if (!d->frame->view() || !d->frame->contentRenderer()) + return; + + d->frame->view()->layoutIfNeededRecursive(); + + GraphicsContext ctx(painter); + QVector<QRect> vector = clip.rects(); + WebCore::FrameView* view = d->frame->view(); + for (int i = 0; i < vector.size(); ++i) { + if (i > 0) { + painter->save(); + painter->setClipRect(vector.at(i), Qt::IntersectClip); + } + + view->paint(&ctx, vector.at(i)); + + if (i > 0) + painter->restore(); + } +} + +/*! + Render the frame into \a painter. +*/ +void QWebFrame::render(QPainter *painter) +{ + if (!d->frame->view() || !d->frame->contentRenderer()) + return; + + d->frame->view()->layoutIfNeededRecursive(); + + GraphicsContext ctx(painter); + WebCore::FrameView* view = d->frame->view(); + view->paint(&ctx, 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. +*/ + +void QWebFrame::setTextSizeMultiplier(qreal factor) +{ + d->frame->setZoomFactor(factor, /*isTextOnly*/true); +} + +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->isZoomFactorTextOnly()); +} + +qreal QWebFrame::zoomFactor() const +{ + return d->frame->zoomFactor(); +} + +/*! + 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 +*/ +QSize QWebFrame::contentsSize() const +{ + FrameView *view = d->frame->view(); + if (!view) + return QSize(); + return QSize(view->contentsWidth(), view->contentsHeight()); +} + +/*! + 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); + 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 +{ + const qreal zoomFactorX = printer->logicalDpiX() / qt_defaultDpi(); + const qreal zoomFactorY = 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() == true){ + 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 (printer->pageOrder() == QPrinter::LastPageFirst) { + int tmp = fromPage; + fromPage = toPage; + toPage = tmp; + ascending = false; + } + + QPainter painter(printer); + 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 + +/*! + Evaluate JavaScript defined by \a scriptSource using this frame as context. + + \sa addToJavaScriptWindowObject(), javaScriptWindowObjectCleared() +*/ +QVariant QWebFrame::evaluateJavaScript(const QString& scriptSource) +{ + ScriptController *proxy = d->frame->script(); + QVariant rc; + if (proxy) { + JSC::JSValue* v = proxy->evaluate(String(), 1, scriptSource); + if (v) { + int distance = 0; + rc = JSC::Bindings::convertValueToQVariant(proxy->globalObject()->globalExec(), v, QMetaType::Void, &distance); + } + } + return rc; +} + +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() +*/ + +/*! + \since 4.5 + \fn void QWebFrame::aboutToUpdateHistory(QWebHistoryItem* item); + + This signal is emitted shortly before the history of navigated pages + is changed, for example when navigating back in the history. + + A potential use-case for this signal is to store custom data in + the QWebHistoryItem associated to the frame, using QWebHistoryItem::setUserData(). +*/ + +/*! + \class QWebHitTestResult + \since 4.4 + \brief The QWebHitTestResult class provides information about the web + page content after a hit test. + + 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) +{ + if (!hitTest.innerNode()) + return; + pos = hitTest.point(); + boundingRect = hitTest.boundingBox(); + title = hitTest.title(); + linkText = hitTest.textContent(); + linkUrl = hitTest.absoluteLinkURL(); + linkTitle = hitTest.titleDisplayString(); + alternateText = hitTest.altDisplayString(); + imageUrl = hitTest.absoluteImageURL(); + innerNonSharedNode = hitTest.innerNonSharedNode(); + 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); + + isContentEditable = hitTest.isContentEditable(); + isContentSelected = hitTest.isSelected(); + + if (innerNonSharedNode && innerNonSharedNode->document() + && innerNonSharedNode->document()->frame()) + frame = QWebFramePrivate::kit(innerNonSharedNode->document()->frame()); +} + +/*! + 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 box of the element. +*/ +QRect QWebHitTestResult::boundingRect() const +{ + if (!d) + return QRect(); + return d->boundingRect; +} + +/*! + 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; +} + +/*! + Returns the frame that will load the link if it is activated. +*/ +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; +} + +/*! + Returns the frame the hit test was executed in. +*/ +QWebFrame *QWebHitTestResult::frame() const +{ + if (!d) + return 0; + return d->frame; +} + diff --git a/WebKit/qt/Api/qwebframe.h b/WebKit/qt/Api/qwebframe.h new file mode 100644 index 0000000..4d37205 --- /dev/null +++ b/WebKit/qt/Api/qwebframe.h @@ -0,0 +1,200 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2007 Staikos Computing Services Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBFRAME_H +#define QWEBFRAME_H + +#include <QtCore/qobject.h> +#include <QtCore/qurl.h> +#include <QtCore/qvariant.h> +#include <QtGui/qicon.h> +#if QT_VERSION >= 0x040400 +#include <QtNetwork/qnetworkaccessmanager.h> +#endif +#include "qwebkitglobal.h" + +QT_BEGIN_NAMESPACE +class QRect; +class QPoint; +class QPainter; +class QPixmap; +class QMouseEvent; +class QWheelEvent; +class QNetworkRequest; +class QRegion; +class QPrinter; +QT_END_NAMESPACE + +class QWebNetworkRequest; +class QWebFramePrivate; +class QWebPage; +class QWebHitTestResult; +class QWebHistoryItem; + +namespace WebCore { + class WidgetPrivate; + class FrameLoaderClientQt; + class ChromeClientQt; +} +class QWebFrameData; +class QWebHitTestResultPrivate; +class QWebFrame; + +class QWEBKIT_EXPORT QWebHitTestResult +{ +public: + QWebHitTestResult(); + QWebHitTestResult(const QWebHitTestResult &other); + QWebHitTestResult &operator=(const QWebHitTestResult &other); + ~QWebHitTestResult(); + + bool isNull() const; + + QPoint pos() const; + QRect boundingRect() const; + QString title() const; + + QString linkText() const; + QUrl linkUrl() const; + QUrl linkTitle() const; + QWebFrame *linkTargetFrame() const; + + QString alternateText() const; // for img, area, input and applet + + QUrl imageUrl() const; + QPixmap pixmap() const; + + bool isContentEditable() const; + bool isContentSelected() const; + + QWebFrame *frame() const; + +private: + QWebHitTestResult(QWebHitTestResultPrivate *priv); + QWebHitTestResultPrivate *d; + + friend class QWebFrame; + friend class QWebPagePrivate; + friend class QWebPage; +}; + +class QWEBKIT_EXPORT QWebFrame : public QObject +{ + Q_OBJECT + Q_PROPERTY(qreal textSizeMultiplier READ textSizeMultiplier WRITE setTextSizeMultiplier DESIGNABLE false) + Q_PROPERTY(qreal zoomFactor READ zoomFactor WRITE setZoomFactor) + Q_PROPERTY(QString title READ title) + Q_PROPERTY(QUrl url READ url WRITE setUrl) + Q_PROPERTY(QIcon icon READ icon) + Q_PROPERTY(QSize contentsSize READ contentsSize) + Q_PROPERTY(QSize scrollOffset READ scrollOffset WRITE setScrollOffset) +private: + QWebFrame(QWebPage *parent, QWebFrameData *frameData); + QWebFrame(QWebFrame *parent, QWebFrameData *frameData); + ~QWebFrame(); + +public: + QWebPage *page() const; + + void load(const QUrl &url); +#if QT_VERSION < 0x040400 + void load(const QWebNetworkRequest &request); +#else + void load(const QNetworkRequest &request, + QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation, + const QByteArray &body = QByteArray()); +#endif + void setHtml(const QString &html, const QUrl &baseUrl = QUrl()); + void setContent(const QByteArray &data, const QString &mimeType = QString(), const QUrl &baseUrl = QUrl()); + + void addToJavaScriptWindowObject(const QString &name, QObject *object); + QString toHtml() const; + QString toPlainText() const; + QString renderTreeDump() const; + + QString title() const; + void setUrl(const QUrl &url); + QUrl url() const; + QIcon icon() const; + + QString frameName() const; + + QWebFrame *parentFrame() const; + QList<QWebFrame*> childFrames() const; + + Qt::ScrollBarPolicy scrollBarPolicy(Qt::Orientation orientation) const; + void setScrollBarPolicy(Qt::Orientation orientation, Qt::ScrollBarPolicy policy); + + void setScrollBarValue(Qt::Orientation orientation, int value); + int scrollBarValue(Qt::Orientation orientation) const; + int scrollBarMinimum(Qt::Orientation orientation) const; + int scrollBarMaximum(Qt::Orientation orientation) const; + + void scroll(int, int) const; + QSize scrollOffset() const; + void setScrollOffset(const QSize &offset) const; + + void render(QPainter *painter, const QRegion &clip); + void render(QPainter *painter); + + void setTextSizeMultiplier(qreal factor); + qreal textSizeMultiplier() const; + + qreal zoomFactor() const; + void setZoomFactor(qreal factor); + + QPoint pos() const; + QRect geometry() const; + QSize contentsSize() const; + + QWebHitTestResult hitTestContent(const QPoint &pos) const; + + virtual bool event(QEvent *); + +public Q_SLOTS: + QVariant evaluateJavaScript(const QString& scriptSource); +#ifndef QT_NO_PRINTER + void print(QPrinter *printer) const; +#endif + +Q_SIGNALS: + void javaScriptWindowObjectCleared(); + + void provisionalLoad(); + void titleChanged(const QString &title); + void urlChanged(const QUrl &url); + + void initialLayoutCompleted(); + + void iconChanged(); + + void aboutToUpdateHistory(QWebHistoryItem* item); + +private: + friend class QWebPage; + friend class QWebPagePrivate; + friend class QWebFramePrivate; + friend class WebCore::WidgetPrivate; + friend class WebCore::FrameLoaderClientQt; + friend class WebCore::ChromeClientQt; + QWebFramePrivate *d; +}; + +#endif diff --git a/WebKit/qt/Api/qwebframe_p.h b/WebKit/qt/Api/qwebframe_p.h new file mode 100644 index 0000000..2b497e6 --- /dev/null +++ b/WebKit/qt/Api/qwebframe_p.h @@ -0,0 +1,118 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2007 Staikos Computing Services Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBFRAME_P_H +#define QWEBFRAME_P_H + +#include "qwebframe.h" +#include "qwebpage_p.h" + +#include "EventHandler.h" +#include "KURL.h" +#include "PlatformString.h" +#include "wtf/RefPtr.h" +#include "Frame.h" + +namespace WebCore +{ + class FrameLoaderClientQt; + class FrameView; + class HTMLFrameOwnerElement; + class Scrollbar; +} +class QWebPage; + + +class QWebFrameData +{ +public: + WebCore::KURL url; + WebCore::String name; + WebCore::HTMLFrameOwnerElement* ownerElement; + + WebCore::String referrer; + bool allowsScrolling; + int marginWidth; + int marginHeight; +}; + +class QWebFramePrivate +{ +public: + QWebFramePrivate() + : q(0) + , horizontalScrollBarPolicy(Qt::ScrollBarAsNeeded) + , verticalScrollBarPolicy(Qt::ScrollBarAsNeeded) + , frameLoaderClient(0) + , frame(0) + , page(0) + , allowsScrolling(true) + , marginWidth(-1) + , marginHeight(-1) + {} + void init(QWebFrame *qframe, WebCore::Page *page, + QWebFrameData *frameData); + + inline QWebFrame *parentFrame() { return qobject_cast<QWebFrame*>(q->parent()); } + + WebCore::Scrollbar* horizontalScrollBar() const; + WebCore::Scrollbar* verticalScrollBar() const; + + Qt::ScrollBarPolicy horizontalScrollBarPolicy; + Qt::ScrollBarPolicy verticalScrollBarPolicy; + + void updateBackground(); + + static WebCore::Frame* core(QWebFrame*); + static QWebFrame* kit(WebCore::Frame*); + + QWebFrame *q; + WebCore::FrameLoaderClientQt *frameLoaderClient; + WebCore::Frame *frame; + QWebPage *page; + + bool allowsScrolling; + int marginWidth; + int marginHeight; +}; + +class QWebHitTestResultPrivate +{ +public: + QWebHitTestResultPrivate() : isContentEditable(false), isContentSelected(false) {} + QWebHitTestResultPrivate(const WebCore::HitTestResult &hitTest); + + QPoint pos; + QRect boundingRect; + QString title; + QString linkText; + QUrl linkUrl; + QString linkTitle; + QPointer<QWebFrame> linkTargetFrame; + QString alternateText; + QUrl imageUrl; + QPixmap pixmap; + bool isContentEditable; + bool isContentSelected; + QPointer<QWebFrame> frame; + RefPtr<WebCore::Node> innerNonSharedNode; +}; + +#endif diff --git a/WebKit/qt/Api/qwebhistory.cpp b/WebKit/qt/Api/qwebhistory.cpp new file mode 100644 index 0000000..962aeb2 --- /dev/null +++ b/WebKit/qt/Api/qwebhistory.cpp @@ -0,0 +1,442 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qwebhistory.h" +#include "qwebhistory_p.h" + +#include "PlatformString.h" +#include "Image.h" +#include "Page.h" +#include "PageGroup.h" + +#include <QSharedData> + +/*! + \class QWebHistoryItem + \ingroup explicitly-shared + \since 4.4 + \brief The QWebHistoryItem class represents one item in the history of a QWebPage + + Each QWebHistoryItem instance represents an entry in the history stack of a Web page, + containing information about the page, its location, and when it was last visited. + + The following table shows the properties of the page held by the history item, and + the functions used to access them. + + \table + \header \o Function \o Description + \row \o title() \o The page title. + \row \o url() \o The location of the page. + \row \o originalUrl() \o The URL used to access the page. + \row \o lastVisited() \o The date and time of the user's last visit to the page. + \row \o icon() \o The icon associated with the page that was provided by the server. + \row \o userData() \o The user specific data that was stored with the history item. + \endtable + + \note QWebHistoryItem objects are value based and \l{explicitly shared}. + + \sa QWebHistory, QWebPage::history(), QWebHistoryInterface +*/ + +/*! + Constructs a history item from \a other. +*/ +QWebHistoryItem::QWebHistoryItem(const QWebHistoryItem &other) + : d(other.d) +{ +} + +/*! + Assigns the \a other history item to this. +*/ +QWebHistoryItem &QWebHistoryItem::operator=(const QWebHistoryItem &other) +{ + d = other.d; + return *this; +} + +/*! + Destroys the history item. +*/ +QWebHistoryItem::~QWebHistoryItem() +{ +} + +/*! + Returns the original URL associated with the history item. + + \sa url() +*/ +QUrl QWebHistoryItem::originalUrl() const +{ + if (d->item) + return QUrl(d->item->originalURL().string()); + return QUrl(); +} + + +/*! + Returns the URL associated with the history item. + + \sa originalUrl(), title(), lastVisited() +*/ +QUrl QWebHistoryItem::url() const +{ + if (d->item) + return QUrl(d->item->url().string()); + return QUrl(); +} + + +/*! + Returns the title of the page associated with the history item. + + \sa icon(), url(), lastVisited() +*/ +QString QWebHistoryItem::title() const +{ + if (d->item) + return d->item->title(); + return QString(); +} + + +/*! + Returns the date and time that the page associated with the item was last visited. + + \sa title(), icon(), url() +*/ +QDateTime QWebHistoryItem::lastVisited() const +{ + //FIXME : this will be wrong unless we correctly set lastVisitedTime ourselves + if (d->item) + return QDateTime::fromTime_t((uint)d->item->lastVisitedTime()); + return QDateTime(); +} + + +/*! + Returns the icon associated with the history item. + + \sa title(), url(), lastVisited() +*/ +QIcon QWebHistoryItem::icon() const +{ + if (d->item) + return *d->item->icon()->nativeImageForCurrentFrame(); + return QIcon(); +} + +/*! + \since 4.5 + Returns the user specific data that was stored with the history item. + + \sa setUserData() +*/ +QVariant QWebHistoryItem::userData() const +{ + if (d->item) + return d->item->userData(); + return QVariant(); +} + +/*! + \since 4.5 + + Stores user specific data with the history item. + + \sa userData() +*/ +void QWebHistoryItem::setUserData(const QVariant& userData) +{ + if (d->item) + d->item->setUserData(userData); +} + +/*!* + \internal +*/ +QWebHistoryItem::QWebHistoryItem(QWebHistoryItemPrivate *priv) +{ + d = priv; +} + +/*! + \since 4.5 + Returns whether this is a valid history item. +*/ +bool QWebHistoryItem::isValid() const +{ + return d->item; +} + +/*! + \class QWebHistory + \since 4.4 + \brief The QWebHistory class represents the history of a QWebPage + + Each QWebPage instance contains a history of visited pages that can be accessed + by QWebPage::history(). QWebHistory represents this history and makes it possible + to navigate it. + + The history uses the concept of a \e{current item}, dividing the pages visited + into those that can be visited by navigating \e back and \e forward using the + back() and forward() functions. The current item can be obtained by calling + currentItem(), and an arbitrary item in the history can be made the current + item by passing it to goToItem(). + + A list of items describing the pages that can be visited by going back can be + obtained by calling the backItems() function; similarly, items describing the + pages ahead of the current page can be obtained with the forwardItems() function. + The total list of items is obtained with the items() function. + + Just as with containers, functions are available to examine the history in terms + of a list. Arbitrary items in the history can be obtained with itemAt(), the total + number of items is given by count(), and the history can be cleared with the + clear() function. + + \sa QWebHistoryItem, QWebHistoryInterface, QWebPage +*/ + + +QWebHistory::QWebHistory() + : d(0) +{ +} + +QWebHistory::~QWebHistory() +{ + delete d; +} + +/*! + Clears the history. + + \sa count(), items() +*/ +void QWebHistory::clear() +{ + RefPtr<WebCore::HistoryItem> current = d->lst->currentItem(); + int capacity = d->lst->capacity(); + d->lst->setCapacity(0); + + WebCore::Page* page = d->lst->page(); + if (page && page->groupPtr()) + page->groupPtr()->removeVisitedLinks(); + + d->lst->setCapacity(capacity); + d->lst->addItem(current.get()); + d->lst->goToItem(current.get()); +} + +/*! + Returns a list of all items currently in the history. + + \sa count(), clear() +*/ +QList<QWebHistoryItem> QWebHistory::items() const +{ + const WebCore::HistoryItemVector &items = d->lst->entries(); + + QList<QWebHistoryItem> ret; + for (int i = 0; i < items.size(); ++i) { + QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(items[i].get()); + ret.append(QWebHistoryItem(priv)); + } + return ret; +} + +/*! + Returns the list of items in the backwards history list. + At most \a maxItems entries are returned. + + \sa forwardItems() +*/ +QList<QWebHistoryItem> QWebHistory::backItems(int maxItems) const +{ + WebCore::HistoryItemVector items(maxItems); + d->lst->backListWithLimit(maxItems, items); + + QList<QWebHistoryItem> ret; + for (int i = 0; i < items.size(); ++i) { + QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(items[i].get()); + ret.append(QWebHistoryItem(priv)); + } + return ret; +} + +/*! + Returns the list of items in the forward history list. + At most \a maxItems entries are returned. + + \sa backItems() +*/ +QList<QWebHistoryItem> QWebHistory::forwardItems(int maxItems) const +{ + WebCore::HistoryItemVector items(maxItems); + d->lst->forwardListWithLimit(maxItems, items); + + QList<QWebHistoryItem> ret; + for (int i = 0; i < items.size(); ++i) { + QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(items[i].get()); + ret.append(QWebHistoryItem(priv)); + } + return ret; +} + +/*! + Returns true if there is an item preceding the current item in the history; + otherwise returns false. + + \sa canGoForward() +*/ +bool QWebHistory::canGoBack() const +{ + return d->lst->backListCount() > 0; +} + +/*! + Returns true if we have an item to go forward to; otherwise returns false. + + \sa canGoBack() +*/ +bool QWebHistory::canGoForward() const +{ + return d->lst->forwardListCount() > 0; +} + +/*! + Set the current item to be the previous item in the history and goes to the + corresponding page; i.e., goes back one history item. + + \sa forward(), goToItem() +*/ +void QWebHistory::back() +{ + d->lst->goBack(); + WebCore::Page* page = d->lst->page(); + page->goToItem(currentItem().d->item, WebCore::FrameLoadTypeIndexedBackForward); +} + +/*! + Sets the current item to be the next item in the history and goes to the + corresponding page; i.e., goes forward one history item. + + \sa back(), goToItem() +*/ +void QWebHistory::forward() +{ + d->lst->goForward(); + WebCore::Page* page = d->lst->page(); + page->goToItem(currentItem().d->item, WebCore::FrameLoadTypeIndexedBackForward); +} + +/*! + Sets the current item to be the specified \a item in the history and goes to the page. + + \sa back(), forward() +*/ +void QWebHistory::goToItem(const QWebHistoryItem &item) +{ + d->lst->goToItem(item.d->item); + WebCore::Page* page = d->lst->page(); + page->goToItem(currentItem().d->item, WebCore::FrameLoadTypeIndexedBackForward); +} + +/*! + Returns the item before the current item in the history. +*/ +QWebHistoryItem QWebHistory::backItem() const +{ + WebCore::HistoryItem *i = d->lst->backItem(); + QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(i); + return QWebHistoryItem(priv); +} + +/*! + Returns the current item in the history. +*/ +QWebHistoryItem QWebHistory::currentItem() const +{ + WebCore::HistoryItem *i = d->lst->currentItem(); + QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(i); + return QWebHistoryItem(priv); +} + +/*! + Returns the item after the current item in the history. +*/ +QWebHistoryItem QWebHistory::forwardItem() const +{ + WebCore::HistoryItem *i = d->lst->forwardItem(); + QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(i); + return QWebHistoryItem(priv); +} + +/*! + \since 4.5 + Returns the index of the current item in history. +*/ +int QWebHistory::currentItemIndex() const +{ + return d->lst->backListCount(); +} + +/*! + Returns the item at index \a i in the history. +*/ +QWebHistoryItem QWebHistory::itemAt(int i) const +{ + WebCore::HistoryItem *item = d->lst->itemAtIndex(i); + + QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(item); + return QWebHistoryItem(priv); +} + +/*! + Returns the total number of items in the history. +*/ +int QWebHistory::count() const +{ + return d->lst->entries().size(); +} + +/*! + \since 4.5 + Returns the maximum number of items in the history. + + \sa setMaximumItemCount() +*/ +int QWebHistory::maximumItemCount() const +{ + return d->lst->capacity(); +} + +/*! + \since 4.5 + Sets the maximum number of items in the history. + + \sa maximumItemCount() +*/ +void QWebHistory::setMaximumItemCount(int count) +{ + d->lst->setCapacity(count); +} + diff --git a/WebKit/qt/Api/qwebhistory.h b/WebKit/qt/Api/qwebhistory.h new file mode 100644 index 0000000..2747c90 --- /dev/null +++ b/WebKit/qt/Api/qwebhistory.h @@ -0,0 +1,107 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBHISTORY_H +#define QWEBHISTORY_H + +#include <QtCore/qurl.h> +#include <QtCore/qstring.h> +#include <QtGui/qicon.h> +#include <QtCore/qdatetime.h> +#include <QtCore/qshareddata.h> + +#include "qwebkitglobal.h" + +class QWebPage; + +namespace WebCore { + class FrameLoaderClientQt; +}; + +class QWebHistoryItemPrivate; +class QWEBKIT_EXPORT QWebHistoryItem +{ +public: + QWebHistoryItem(const QWebHistoryItem &other); + QWebHistoryItem &operator=(const QWebHistoryItem &other); + ~QWebHistoryItem(); + + QUrl originalUrl() const; + QUrl url() const; + + QString title() const; + QDateTime lastVisited() const; + + QIcon icon() const; + + QVariant userData() const; + void setUserData(const QVariant& userData); + + bool isValid() const; + +private: + QWebHistoryItem(QWebHistoryItemPrivate *priv); + friend class QWebHistory; + friend class QWebPage; + friend class WebCore::FrameLoaderClientQt; + QExplicitlySharedDataPointer<QWebHistoryItemPrivate> d; +}; + +class QWebHistoryPrivate; +class QWEBKIT_EXPORT QWebHistory +{ +public: + void clear(); + + QList<QWebHistoryItem> items() const; + QList<QWebHistoryItem> backItems(int maxItems) const; + QList<QWebHistoryItem> forwardItems(int maxItems) const; + + bool canGoBack() const; + bool canGoForward() const; + + void back(); + void forward(); + void goToItem(const QWebHistoryItem &item); + + QWebHistoryItem backItem() const; + QWebHistoryItem currentItem() const; + QWebHistoryItem forwardItem() const; + QWebHistoryItem itemAt(int i) const; + + int currentItemIndex() const; + + int count() const; + + int maximumItemCount() const; + void setMaximumItemCount(int count); + +private: + QWebHistory(); + ~QWebHistory(); + + friend class QWebPage; + friend class QWebPagePrivate; + + Q_DISABLE_COPY(QWebHistory) + + QWebHistoryPrivate *d; +}; + +#endif diff --git a/WebKit/qt/Api/qwebhistory_p.h b/WebKit/qt/Api/qwebhistory_p.h new file mode 100644 index 0000000..32e69fe --- /dev/null +++ b/WebKit/qt/Api/qwebhistory_p.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBHISTORY_P_H +#define QWEBHISTORY_P_H + +#include "BackForwardList.h" +#include "HistoryItem.h" + +class QWebHistoryItemPrivate : public QSharedData +{ +public: + QWebHistoryItemPrivate(WebCore::HistoryItem *i) + { + if (i) + i->ref(); + item = i; + } + ~QWebHistoryItemPrivate() + { + if (item) + item->deref(); + } + WebCore::HistoryItem *item; +}; + +class QWebHistoryPrivate : public QSharedData +{ +public: + QWebHistoryPrivate(WebCore::BackForwardList *l) + { + l->ref(); + lst = l; + } + ~QWebHistoryPrivate() + { + lst->deref(); + } + WebCore::BackForwardList *lst; +}; + + +#endif diff --git a/WebKit/qt/Api/qwebhistoryinterface.cpp b/WebKit/qt/Api/qwebhistoryinterface.cpp new file mode 100644 index 0000000..8e2d35c --- /dev/null +++ b/WebKit/qt/Api/qwebhistoryinterface.cpp @@ -0,0 +1,129 @@ +/* + Copyright (C) 2007 Staikos Computing Services Inc. <info@staikos.net> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for tracking global history. +*/ + +#include "config.h" +#include "qwebhistoryinterface.h" + +#include <QCoreApplication> + +#include "PageGroup.h" +#include "PlatformString.h" + +// FIXME: It's not correct to just implement a WebCore function in WebKit! +// This needs to be fixed to match other platforms. + +namespace WebCore { + +bool historyContains(const UChar* characters, unsigned length) +{ + if (!QWebHistoryInterface::defaultInterface()) + return false; + + return QWebHistoryInterface::defaultInterface()->historyContains(QString(reinterpret_cast<const QChar*>(characters), length)); +} + +} // namespace WebCore + +static QWebHistoryInterface *default_interface; + +static bool gRoutineAdded; + +static void gCleanupInterface() +{ + if (default_interface && default_interface->parent() == 0) + delete default_interface; + default_interface = 0; +} + +/*! + Sets a new default interface, \a defaultInterface, that will be used by all of WebKit + for managing history. + + If an interface without a parent has already been set, the old interface will be deleted. + When the application exists QWebHistoryInterface will automatically delete the + \a defaultInterface if it does not have a parent. +*/ +void QWebHistoryInterface::setDefaultInterface(QWebHistoryInterface *defaultInterface) +{ + if (default_interface == defaultInterface) + return; + if (default_interface && default_interface->parent() == 0) + delete default_interface; + + default_interface = defaultInterface; + WebCore::PageGroup::removeAllVisitedLinks(); + + if (!gRoutineAdded) { + qAddPostRoutine(gCleanupInterface); + gRoutineAdded = true; + } +} + +/*! + Returns the default interface that will be used by WebKit. If no + default interface has been set, QtWebkit will not track history. +*/ +QWebHistoryInterface *QWebHistoryInterface::defaultInterface() +{ + return default_interface; +} + +/*! + \class QWebHistoryInterface + \since 4.4 + \brief The QWebHistoryInterface class provides an interface to implement link history. + + The QWebHistoryInterface is an interface that can be used to + implement link history. It contains two pure virtual methods that + are called by the WebKit engine. addHistoryEntry() is used to add + pages that have been visited to the interface, while + historyContains() is used to query whether this page has been + visited by the user. +*/ + +/*! + Constructs a new QWebHistoryInterface with parent \a parent. +*/ +QWebHistoryInterface::QWebHistoryInterface(QObject *parent) : QObject(parent) +{ +} + +/*! + Destructor. If this is currently the default interface it will be unset. +*/ +QWebHistoryInterface::~QWebHistoryInterface() +{ + if (default_interface == this) + default_interface = 0; +} + +/*! + \fn bool QWebHistoryInterface::historyContains(const QString &url) const = 0 + + Called by the WebKit engine to query whether a certain \a url has been visited by the user already. + Returns true if the \a url is part of the history of visited links; otherwise returns false. +*/ + +/*! + \fn void QWebHistoryInterface::addHistoryEntry(const QString &url) = 0 + + Called by WebKit to add another \a url to the list of visited pages. +*/ diff --git a/WebKit/qt/Api/qwebhistoryinterface.h b/WebKit/qt/Api/qwebhistoryinterface.h new file mode 100644 index 0000000..670fca0 --- /dev/null +++ b/WebKit/qt/Api/qwebhistoryinterface.h @@ -0,0 +1,43 @@ +/* + Copyright (C) 2007 Staikos Computing Services, Inc. <info@staikos.net> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for tracking global history. +*/ + +#ifndef QWEBHISTORYINTERFACE_H +#define QWEBHISTORYINTERFACE_H + +#include <QtCore/qobject.h> + +#include "qwebkitglobal.h" + +class QWEBKIT_EXPORT QWebHistoryInterface : public QObject +{ + Q_OBJECT +public: + QWebHistoryInterface(QObject *parent = 0); + ~QWebHistoryInterface(); + + static void setDefaultInterface(QWebHistoryInterface *defaultInterface); + static QWebHistoryInterface *defaultInterface(); + + virtual bool historyContains(const QString &url) const = 0; + virtual void addHistoryEntry(const QString &url) = 0; +}; + +#endif diff --git a/WebKit/qt/Api/qwebkitglobal.h b/WebKit/qt/Api/qwebkitglobal.h new file mode 100644 index 0000000..2486fb6 --- /dev/null +++ b/WebKit/qt/Api/qwebkitglobal.h @@ -0,0 +1,48 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBKITGLOBAL_H +#define QWEBKITGLOBAL_H + +#include <QtCore/qglobal.h> + +#if defined(Q_OS_WIN) +# if defined(BUILD_WEBKIT) +# define QWEBKIT_EXPORT Q_DECL_EXPORT +# else +# define QWEBKIT_EXPORT Q_DECL_IMPORT +# endif +#endif + +#if !defined(QWEBKIT_EXPORT) +#define QWEBKIT_EXPORT Q_DECL_EXPORT +#endif + +#if QT_VERSION < 0x040400 + #ifndef QT_BEGIN_NAMESPACE + #define QT_BEGIN_NAMESPACE + #endif + + #ifndef QT_END_NAMESPACE + #define QT_END_NAMESPACE + #endif +#endif + + +#endif // QWEBKITGLOBAL_H diff --git a/WebKit/qt/Api/qwebnetworkinterface.cpp b/WebKit/qt/Api/qwebnetworkinterface.cpp new file mode 100644 index 0000000..8fba915 --- /dev/null +++ b/WebKit/qt/Api/qwebnetworkinterface.cpp @@ -0,0 +1,1263 @@ +/* + Copyright (C) 2006 Enrico Ros <enrico.ros@m31engineering.it> + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2007 Staikos Computing Services Inc. <info@staikos.net> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qglobal.h> +#if QT_VERSION < 0x040400 +#include "qwebframe.h" +#include "qwebnetworkinterface.h" +#include "qwebnetworkinterface_p.h" +#include "qwebpage.h" +#include "qcookiejar.h" +#include <qdebug.h> +#include <qfile.h> +#include <qnetworkproxy.h> +#include <qurl.h> +#include <QAuthenticator> +#include <QCoreApplication> +#include <QSslError> + +#include "ResourceHandle.h" +#include "ResourceHandleClient.h" +#include "ResourceHandleInternal.h" +#include "MIMETypeRegistry.h" +#include "CookieJar.h" + +#if 0 +#define DEBUG qDebug +#else +#define DEBUG if (1) {} else qDebug +#endif + +static QWebNetworkInterface *s_default_interface = 0; +static QWebNetworkManager *s_manager = 0; + +using namespace WebCore; + +uint qHash(const HostInfo &info) +{ + return qHash(info.host) + info.port; +} + +static bool operator==(const HostInfo &i1, const HostInfo &i2) +{ + return i1.port == i2.port && i1.host == i2.host; +} + +enum ParserState { + State_Begin, + State_FirstChar, + State_SecondChar +}; + +/* + * Decode URLs without doing any charset conversion. + * + * Most simple approach to do it without any lookahead. + */ +static QByteArray decodePercentEncoding(const QByteArray& input) +{ + int actualLength = 0; + QByteArray tmpVal; + QByteArray output; + ParserState state = State_Begin; + + output.resize(input.length()); + tmpVal.resize(2); + + for (int i = 0; i < input.length(); ++i) + if (state == State_Begin) { + if (input.at(i) == '%') { + state = State_FirstChar; + } else { + output[actualLength++] = input[i]; + } + } else if (state == State_FirstChar) { + state = State_SecondChar; + tmpVal[0] = input[i]; + } else if (state == State_SecondChar) { + state = State_Begin; + tmpVal[1] = input[i]; + output[actualLength++] = tmpVal.toShort(0, 16); + } + + output.resize(actualLength); + return output; +} + +void QWebNetworkRequestPrivate::init(const WebCore::ResourceRequest &resourceRequest) +{ + KURL url = resourceRequest.url(); + QUrl qurl = QString(url.string()); + init(resourceRequest.httpMethod(), qurl, &resourceRequest); +} + +void QWebNetworkRequestPrivate::init(const QString &method, const QUrl &url, const WebCore::ResourceRequest *resourceRequest) +{ + httpHeader = QHttpRequestHeader(method, url.toString(QUrl::RemoveScheme|QUrl::RemoveAuthority)); + httpHeader.setValue(QLatin1String("Connection"), QLatin1String("Keep-Alive")); + setURL(url); + + if (resourceRequest) { + httpHeader.setValue(QLatin1String("User-Agent"), resourceRequest->httpUserAgent()); + const QString scheme = url.scheme().toLower(); + if (scheme == QLatin1String("http") || scheme == QLatin1String("https")) { + QString cookies = QCookieJar::cookieJar()->cookies(resourceRequest->url()); + if (!cookies.isEmpty()) + httpHeader.setValue(QLatin1String("Cookie"), cookies); + } + + + const HTTPHeaderMap& loaderHeaders = resourceRequest->httpHeaderFields(); + HTTPHeaderMap::const_iterator end = loaderHeaders.end(); + for (HTTPHeaderMap::const_iterator it = loaderHeaders.begin(); it != end; ++it) + httpHeader.setValue(it->first, it->second); + + // handle and perform a 'POST' request + if (method == "POST") { + Vector<char> data; + resourceRequest->httpBody()->flatten(data); + postData = QByteArray(data.data(), data.size()); + httpHeader.setValue(QLatin1String("content-length"), QString::number(postData.size())); + } + } +} + +void QWebNetworkRequestPrivate::setURL(const QUrl &u) +{ + url = u; + int port = url.port(); + const QString scheme = u.scheme(); + if (port > 0 && (port != 80 || scheme != "http") && (port != 443 || scheme != "https")) + httpHeader.setValue(QLatin1String("Host"), url.host() + QLatin1Char(':') + QString::number(port)); + else + httpHeader.setValue(QLatin1String("Host"), url.host()); +} + +/*! + \class QWebNetworkRequest + + The QWebNetworkRequest class represents a request for data from the network with all the + necessary information needed for retrieval. This includes the url, extra HTTP header fields + as well as data for a HTTP POST request. +*/ + +QWebNetworkRequest::QWebNetworkRequest() + : d(new QWebNetworkRequestPrivate) +{ +} + +QWebNetworkRequest::QWebNetworkRequest(const QUrl &url, Method method, const QByteArray &postData) + : d(new QWebNetworkRequestPrivate) +{ + d->init(method == Get ? "GET" : "POST", url); + d->postData = postData; +} + +QWebNetworkRequest::QWebNetworkRequest(const QWebNetworkRequest &other) + : d(new QWebNetworkRequestPrivate(*other.d)) +{ +} + +QWebNetworkRequest &QWebNetworkRequest::operator=(const QWebNetworkRequest &other) +{ + *d = *other.d; + return *this; +} + +/*! + \internal +*/ +QWebNetworkRequest::QWebNetworkRequest(const QWebNetworkRequestPrivate &priv) + : d(new QWebNetworkRequestPrivate(priv)) +{ +} + +/*! + \internal +*/ +QWebNetworkRequest::QWebNetworkRequest(const WebCore::ResourceRequest &request) + : d(new QWebNetworkRequestPrivate) +{ + d->init(request); +} + +QWebNetworkRequest::~QWebNetworkRequest() +{ + delete d; +} + +/*! + The requested URL +*/ +QUrl QWebNetworkRequest::url() const +{ + return d->url; +} + +/*! + Sets the URL to request. + + Note that setting the URL also sets the "Host" field in the HTTP header. +*/ +void QWebNetworkRequest::setUrl(const QUrl &url) +{ + d->setURL(url); +} + +/*! + The http request header information. +*/ +QHttpRequestHeader QWebNetworkRequest::httpHeader() const +{ + return d->httpHeader; +} + +void QWebNetworkRequest::setHttpHeader(const QHttpRequestHeader &header) const +{ + d->httpHeader = header; +} + +QString QWebNetworkRequest::httpHeaderField(const QString &key) const +{ + return d->httpHeader.value(key); +} + +void QWebNetworkRequest::setHttpHeaderField(const QString &key, const QString &value) +{ + d->httpHeader.setValue(key, value); +} + +/*! + Post data sent with HTTP POST requests. +*/ +QByteArray QWebNetworkRequest::postData() const +{ + return d->postData; +} + +void QWebNetworkRequest::setPostData(const QByteArray &data) +{ + d->postData = data; +} + +/*! + \class QWebNetworkJob + + The QWebNetworkJob class represents a network job, that needs to be + processed by the QWebNetworkInterface. + + This class is only required when implementing a new network layer (or + support for a special protocol) using QWebNetworkInterface. + + QWebNetworkJob objects are created and owned by the QtWebKit library. + Most of it's properties are read-only. + + The job is reference counted. This can be used to ensure that the job doesn't + get deleted while it's still stored in some data structure. +*/ + +/*! + \internal +*/ +QWebNetworkJob::QWebNetworkJob() + : d(new QWebNetworkJobPrivate) +{ +} + +/*! + \internal +*/ +QWebNetworkJob::~QWebNetworkJob() +{ + delete d; + d = 0; +} + +/*! + The requested URL +*/ +QUrl QWebNetworkJob::url() const +{ + return d->request.url; +} + +/*! + Post data associated with the job +*/ +QByteArray QWebNetworkJob::postData() const +{ + return d->request.postData; +} + +/*! + The HTTP request header that should be used to download the job. +*/ +QHttpRequestHeader QWebNetworkJob::httpHeader() const +{ + return d->request.httpHeader; +} + +/*! + The complete network request that should be used to download the job. +*/ +QWebNetworkRequest QWebNetworkJob::request() const +{ + return QWebNetworkRequest(d->request); +} + +/*! + The HTTP response header received from the network. +*/ +QHttpResponseHeader QWebNetworkJob::response() const +{ + return d->response; +} + +/*! + The last error of the Job. +*/ +QString QWebNetworkJob::errorString() const +{ + return d->errorString; +} + +/*! + Sets the HTTP reponse header. The response header has to be called before + emitting QWebNetworkInterface::started. +*/ +void QWebNetworkJob::setResponse(const QHttpResponseHeader &response) +{ + d->response = response; +} + +void QWebNetworkJob::setErrorString(const QString& errorString) +{ + d->errorString = errorString; +} + +/*! + returns true if the job has been cancelled by the WebKit framework +*/ +bool QWebNetworkJob::cancelled() const +{ + return !d->resourceHandle; +} + +/*! + reference the job. +*/ +void QWebNetworkJob::ref() +{ + ++d->ref; +} + +/*! + derefence the job. + + If the reference count drops to 0 this method also deletes the job. + + Returns false if the reference count has dropped to 0. +*/ +bool QWebNetworkJob::deref() +{ + if (!--d->ref) { + delete this; + return false; + } + return true; +} + +/*! + Returns the network interface that is associated with this job. +*/ +QWebNetworkInterface *QWebNetworkJob::networkInterface() const +{ + return d->interface; +} + +/*! + Returns the network interface that is associated with this job. +*/ +QWebFrame *QWebNetworkJob::frame() const +{ + if (d->resourceHandle) { + ResourceHandleInternal *rhi = d->resourceHandle->getInternal(); + if (rhi) { + return rhi->m_frame; + } + } + return 0; +} + +QWebNetworkJob::JobStatus QWebNetworkJob::status() const +{ + return d->jobStatus; +} + +void QWebNetworkJob::setStatus(const JobStatus& status) +{ + d->jobStatus = status; +} + +/*! + \class QWebNetworkManager + \internal +*/ +QWebNetworkManager::QWebNetworkManager() + : QObject(0) + , m_scheduledWork(false) +{ + connect(this, SIGNAL(scheduleWork()), SLOT(doWork()), Qt::QueuedConnection); +} + +QWebNetworkManager *QWebNetworkManager::self() +{ + // ensure everything's constructed and connected + QWebNetworkInterface::defaultInterface(); + + return s_manager; +} + +bool QWebNetworkManager::add(ResourceHandle *handle, QWebNetworkInterface *interface, JobMode jobMode) +{ + if (!interface) + interface = s_default_interface; + + ASSERT(interface); + + QWebNetworkJob *job = new QWebNetworkJob(); + handle->getInternal()->m_job = job; + job->d->resourceHandle = handle; + job->d->interface = interface; + + job->d->request.init(handle->request()); + + const QString method = handle->getInternal()->m_request.httpMethod(); + if (method != "POST" && method != "GET" && method != "HEAD") { + qWarning("REQUEST: [%s]\n", qPrintable(job->d->request.httpHeader.toString())); + return false; + } + + DEBUG() << "QWebNetworkManager::add:" << job->d->request.httpHeader.toString(); + + if (jobMode == SynchronousJob) { + Q_ASSERT(!m_synchronousJobs.contains(job)); + m_synchronousJobs[job] = 1; + } + + interface->addJob(job); + + return true; +} + +void QWebNetworkManager::cancel(ResourceHandle *handle) +{ + QWebNetworkJob *job = handle->getInternal()->m_job; + if (!job) + return; + DEBUG() << "QWebNetworkManager::cancel:" << job->d->request.httpHeader.toString(); + job->d->resourceHandle = 0; + job->d->interface->cancelJob(job); + handle->getInternal()->m_job = 0; +} + +void QWebNetworkManager::started(QWebNetworkJob *job) +{ + Q_ASSERT(job->d); + Q_ASSERT(job->status() == QWebNetworkJob::JobCreated || + job->status() == QWebNetworkJob::JobRecreated); + + job->setStatus(QWebNetworkJob::JobStarted); + ResourceHandleClient* client = 0; + if (job->d->resourceHandle) { + client = job->d->resourceHandle->client(); + if (!client) + return; + } else { + return; + } + + DEBUG() << "ResourceHandleManager::receivedResponse:"; + DEBUG() << job->d->response.toString(); + + QStringList cookies = job->d->response.allValues("Set-Cookie"); + KURL url(job->url()); + foreach (QString c, cookies) { + QCookieJar::cookieJar()->setCookies(url, url, c); + } + QString contentType = job->d->response.value("Content-Type"); + QString encoding; + int idx = contentType.indexOf(QLatin1Char(';')); + if (idx > 0) { + QString remainder = contentType.mid(idx + 1).toLower(); + contentType = contentType.left(idx).trimmed(); + + idx = remainder.indexOf("charset"); + if (idx >= 0) { + idx = remainder.indexOf(QLatin1Char('='), idx); + if (idx >= 0) + encoding = remainder.mid(idx + 1).trimmed(); + } + } + if (contentType.isEmpty()) { + // let's try to guess from the extension + QString extension = job->d->request.url.path(); + int index = extension.lastIndexOf(QLatin1Char('.')); + if (index > 0) { + extension = extension.mid(index + 1); + contentType = MIMETypeRegistry::getMIMETypeForExtension(extension); + } + } +// qDebug() << "Content-Type=" << contentType; +// qDebug() << "Encoding=" << encoding; + + + ResourceResponse response(url, contentType, + 0 /* FIXME */, + encoding, + String() /* FIXME */); + + int statusCode = job->d->response.statusCode(); + if (job->url().scheme() != QLatin1String("file")) + response.setHTTPStatusCode(statusCode); + else if (statusCode == 404) + response.setHTTPStatusCode(statusCode); + + /* Fill in the other fields */ + + if (statusCode >= 300 && statusCode < 400) { + // we're on a redirect page! if the 'Location:' field is valid, we redirect + QString location = job->d->response.value("location"); + DEBUG() << "Redirection"; + if (!location.isEmpty()) { + QUrl newUrl = job->d->request.url.resolved(location); + if (job->d->resourceHandle) { + ResourceRequest newRequest = job->d->resourceHandle->request(); + newRequest.setURL(KURL(newUrl)); + if (client) + client->willSendRequest(job->d->resourceHandle, newRequest, response); + } + + QString method; + if (statusCode == 302 || statusCode == 303) { + // this is standard-correct for 303 and practically-correct (no standard-correct) for 302 + // also, it's required for Yahoo's login process for flickr.com which responds to a POST + // with a 302 which must be GET'ed + method = "GET"; + job->d->request.httpHeader.setContentLength(0); + } else { + method = job->d->request.httpHeader.method(); + } + job->d->request.httpHeader.setRequest(method, + newUrl.toString(QUrl::RemoveScheme|QUrl::RemoveAuthority)); + job->d->request.setURL(newUrl); + job->d->redirected = true; + return; + } + } + + if (client) + client->didReceiveResponse(job->d->resourceHandle, response); + +} + +void QWebNetworkManager::data(QWebNetworkJob *job, const QByteArray &data) +{ + Q_ASSERT(job->status() == QWebNetworkJob::JobStarted || + job->status() == QWebNetworkJob::JobReceivingData); + + job->setStatus(QWebNetworkJob::JobReceivingData); + ResourceHandleClient* client = 0; + if (job->d->resourceHandle) { + client = job->d->resourceHandle->client(); + if (!client) + return; + } else { + return; + } + + if (job->d->redirected) + return; // don't emit the "Document has moved here" type of HTML + + DEBUG() << "receivedData" << job->d->request.url.path(); + if (client) + client->didReceiveData(job->d->resourceHandle, data.constData(), data.length(), data.length() /*FixMe*/); + +} + +void QWebNetworkManager::finished(QWebNetworkJob *job, int errorCode) +{ + Q_ASSERT(errorCode == 1 || + job->status() == QWebNetworkJob::JobStarted || + job->status() == QWebNetworkJob::JobReceivingData); + + if (m_synchronousJobs.contains(job)) + m_synchronousJobs.remove(job); + + job->setStatus(QWebNetworkJob::JobFinished); + ResourceHandleClient* client = 0; + if (job->d->resourceHandle) { + client = job->d->resourceHandle->client(); + if (!client) + return; + } else { + job->deref(); + return; + } + + DEBUG() << "receivedFinished" << errorCode << job->url(); + + if (job->d->redirected) { + job->d->redirected = false; + job->setStatus(QWebNetworkJob::JobRecreated); + job->d->interface->addJob(job); + return; + } + + if (job->d->resourceHandle) + job->d->resourceHandle->getInternal()->m_job = 0; + + if (client) { + if (errorCode) { + //FIXME: error setting error was removed from ResourceHandle + client->didFail(job->d->resourceHandle, + ResourceError(job->d->request.url.host(), job->d->response.statusCode(), + job->d->request.url.toString(), job->d->errorString)); + } else { + client->didFinishLoading(job->d->resourceHandle); + } + } + + DEBUG() << "receivedFinished done" << job->d->request.url; + + job->deref(); +} + +void QWebNetworkManager::addHttpJob(QWebNetworkJob *job) +{ + HostInfo hostInfo(job->url()); + WebCoreHttp *httpConnection = m_hostMapping.value(hostInfo); + if (!httpConnection) { + // #### fix custom ports + DEBUG() << " new connection to" << hostInfo.host << hostInfo.port; + httpConnection = new WebCoreHttp(this, hostInfo); + QObject::connect(httpConnection, SIGNAL(connectionClosed(const WebCore::HostInfo&)), + this, SLOT(httpConnectionClosed(const WebCore::HostInfo&))); + + m_hostMapping[hostInfo] = httpConnection; + } + httpConnection->request(job); +} + +void QWebNetworkManager::cancelHttpJob(QWebNetworkJob *job) +{ + WebCoreHttp *httpConnection = m_hostMapping.value(job->url()); + if (httpConnection) + httpConnection->cancel(job); +} + +void QWebNetworkManager::httpConnectionClosed(const WebCore::HostInfo &info) +{ + WebCoreHttp *connection = m_hostMapping.take(info); + connection->deleteLater(); +} + +void QWebNetworkInterfacePrivate::sendFileData(QWebNetworkJob* job, int statusCode, const QByteArray &data) +{ + int error = statusCode >= 400 ? 1 : 0; + if (!job->cancelled()) { + QHttpResponseHeader response; + response.setStatusLine(statusCode); + response.setContentLength(data.length()); + job->setResponse(response); + q->started(job); + if (!data.isEmpty()) + q->data(job, data); + } + q->finished(job, error); +} + +void QWebNetworkInterfacePrivate::parseDataUrl(QWebNetworkJob* job) +{ + QByteArray data = job->url().toString().toLatin1(); + //qDebug() << "handling data url:" << data; + + ASSERT(data.startsWith("data:")); + + // Here's the syntax of data URLs: + // dataurl := "data:" [ mediatype ] [ ";base64" ] "," data + // mediatype := [ type "/" subtype ] *( ";" parameter ) + // data := *urlchar + // parameter := attribute "=" value + QByteArray header; + bool base64 = false; + + int index = data.indexOf(','); + if (index != -1) { + header = data.mid(5, index - 5).toLower(); + //qDebug() << "header=" << header; + data = data.mid(index+1); + //qDebug() << "data=" << data; + + if (header.endsWith(";base64")) { + //qDebug() << "base64"; + base64 = true; + header = header.left(header.length() - 7); + //qDebug() << "mime=" << header; + } + } else { + data = QByteArray(); + } + + if (base64) { + data = QByteArray::fromBase64(data); + } else { + data = decodePercentEncoding(data); + } + + if (header.isEmpty()) + header = "text/plain;charset=US-ASCII"; + int statusCode = 200; + QHttpResponseHeader response; + response.setContentType(header); + response.setContentLength(data.size()); + job->setResponse(response); + + int error = statusCode >= 400 ? 1 : 0; + q->started(job); + if (!data.isEmpty()) + q->data(job, data); + q->finished(job, error); +} + +void QWebNetworkManager::queueStart(QWebNetworkJob* job) +{ + Q_ASSERT(job->d); + + QMutexLocker locker(&m_queueMutex); + job->ref(); + m_pendingWork.append(new JobWork(job)); + doScheduleWork(); +} + +void QWebNetworkManager::queueData(QWebNetworkJob* job, const QByteArray& data) +{ + ASSERT(job->d); + + QMutexLocker locker(&m_queueMutex); + job->ref(); + m_pendingWork.append(new JobWork(job, data)); + doScheduleWork(); +} + +void QWebNetworkManager::queueFinished(QWebNetworkJob* job, int errorCode) +{ + Q_ASSERT(job->d); + + QMutexLocker locker(&m_queueMutex); + job->ref(); + m_pendingWork.append(new JobWork(job, errorCode)); + doScheduleWork(); +} + +void QWebNetworkManager::doScheduleWork() +{ + if (!m_scheduledWork) { + m_scheduledWork = true; + emit scheduleWork(); + } +} + + +/* + * We will work on a copy of m_pendingWork. While dispatching m_pendingWork + * new work will be added that will be handled at a later doWork call. doWork + * will be called we set m_scheduledWork to false early in this method. + */ +void QWebNetworkManager::doWork() +{ + m_queueMutex.lock(); + m_scheduledWork = false; + bool hasSyncJobs = m_synchronousJobs.size(); + const QHash<QWebNetworkJob*, int> syncJobs = m_synchronousJobs; + m_queueMutex.unlock(); + + foreach (JobWork* work, m_pendingWork) { + if (hasSyncJobs && !syncJobs.contains(work->job)) + continue; + + if (work->workType == JobWork::JobStarted) + started(work->job); + else if (work->workType == JobWork::JobData) { + // This job was not yet started + if (static_cast<int>(work->job->status()) < QWebNetworkJob::JobStarted) + continue; + + data(work->job, work->data); + } else if (work->workType == JobWork::JobFinished) { + // This job was not yet started... we have no idea if data comes by... + // and it won't start in case of errors + if (static_cast<int>(work->job->status()) < QWebNetworkJob::JobStarted && work->errorCode != 1) + continue; + + finished(work->job, work->errorCode); + } + + m_queueMutex.lock(); + m_pendingWork.removeAll(work); + m_queueMutex.unlock(); + + work->job->deref(); + delete work; + } + + m_queueMutex.lock(); + if (hasSyncJobs && m_synchronousJobs.size() == 0) + doScheduleWork(); + m_queueMutex.unlock(); +} + +/*! + \class QWebNetworkInterface + + The QWebNetworkInterface class provides an abstraction layer for + WebKit's network interface. It allows to completely replace or + extend the builtin network layer. + + QWebNetworkInterface contains two virtual methods, addJob and + cancelJob that have to be reimplemented when implementing your own + networking layer. + + QWebNetworkInterface can by default handle the http, https, file and + data URI protocols. + +*/ + +static bool gRoutineAdded = false; + +static void gCleanupInterface() +{ + delete s_default_interface; + s_default_interface = 0; +} + +/*! + Sets a new default interface that will be used by all of WebKit + for downloading data from the internet. +*/ +void QWebNetworkInterface::setDefaultInterface(QWebNetworkInterface *defaultInterface) +{ + if (s_default_interface == defaultInterface) + return; + if (s_default_interface) + delete s_default_interface; + s_default_interface = defaultInterface; + if (!gRoutineAdded) { + qAddPostRoutine(gCleanupInterface); + gRoutineAdded = true; + } +} + +/*! + Returns the default interface that will be used by WebKit. If no + default interface has been set, QtWebkit will create an instance of + QWebNetworkInterface to do the work. +*/ +QWebNetworkInterface *QWebNetworkInterface::defaultInterface() +{ + if (!s_default_interface) { + setDefaultInterface(new QWebNetworkInterface); + } + return s_default_interface; +} + + +/*! + Constructs a QWebNetworkInterface object. +*/ +QWebNetworkInterface::QWebNetworkInterface(QObject *parent) + : QObject(parent) +{ + d = new QWebNetworkInterfacePrivate; + d->q = this; + + if (!s_manager) + s_manager = new QWebNetworkManager; +} + +/*! + Destructs the QWebNetworkInterface object. +*/ +QWebNetworkInterface::~QWebNetworkInterface() +{ + delete d; +} + +/*! + This virtual method gets called whenever QtWebkit needs to add a + new job to download. + + The QWebNetworkInterface should process this job, by first emitting + the started signal, then emitting data repeatedly as new data for + the Job is available, and finally ending the job with emitting a + finished signal. + + After the finished signal has been emitted, the QWebNetworkInterface + is not allowed to access the job anymore. +*/ +void QWebNetworkInterface::addJob(QWebNetworkJob *job) +{ + QString protocol = job->url().scheme(); + if (protocol == QLatin1String("http") || protocol == QLatin1String("https")) { + QWebNetworkManager::self()->addHttpJob(job); + return; + } + + // "file", "data" and all unhandled stuff go through here + //DEBUG() << "fileRequest"; + DEBUG() << "FileLoader::request" << job->url(); + + if (job->cancelled()) { + d->sendFileData(job, 400, QByteArray()); + return; + } + + QUrl url = job->url(); + if (protocol == QLatin1String("data")) { + d->parseDataUrl(job); + return; + } + + int statusCode = 200; + QByteArray data; + QString path = url.path(); + if (protocol == QLatin1String("qrc")) { + protocol = "file"; + path.prepend(QLatin1Char(':')); + } + + if (!(protocol.isEmpty() || protocol == QLatin1String("file"))) { + statusCode = 404; + } else { + // we simply ignore post data here. + QFile f(path); + DEBUG() << "opening" << QString(url.path()); + + if (f.open(QIODevice::ReadOnly)) { + QHttpResponseHeader response; + response.setStatusLine(200); + job->setResponse(response); + data = f.readAll(); + } else { + statusCode = 404; + } + } + + if (statusCode == 404) { + QHttpResponseHeader response; + response.setStatusLine(404); + job->setResponse(response); + } + + d->sendFileData(job, statusCode, data); +} + +/*! + This virtual method gets called whenever QtWebkit needs to cancel a + new job. + + The QWebNetworkInterface acknowledge the canceling of the job, by + emitting the finished signal with an error code of 1. After emitting + the finished signal, the interface should not access the job + anymore. +*/ +void QWebNetworkInterface::cancelJob(QWebNetworkJob *job) +{ + QString protocol = job->url().scheme(); + if (protocol == QLatin1String("http") || protocol == QLatin1String("https")) + QWebNetworkManager::self()->cancelHttpJob(job); +} + +void QWebNetworkInterface::started(QWebNetworkJob* job) +{ + Q_ASSERT(s_manager); + s_manager->queueStart(job); +} + +void QWebNetworkInterface::data(QWebNetworkJob* job, const QByteArray& data) +{ + Q_ASSERT(s_manager); + s_manager->queueData(job, data); +} + +void QWebNetworkInterface::finished(QWebNetworkJob* job, int errorCode) +{ + Q_ASSERT(s_manager); + s_manager->queueFinished(job, errorCode); +} + +///////////////////////////////////////////////////////////////////////////// +WebCoreHttp::WebCoreHttp(QObject* parent, const HostInfo &hi) + : QObject(parent), info(hi), + m_inCancel(false) +{ + for (int i = 0; i < 2; ++i) { + connection[i].http = new QHttp(info.host, (hi.protocol == QLatin1String("https")) ? QHttp::ConnectionModeHttps : QHttp::ConnectionModeHttp, info.port); + connect(connection[i].http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader&)), + this, SLOT(onResponseHeaderReceived(const QHttpResponseHeader&))); + connect(connection[i].http, SIGNAL(readyRead(const QHttpResponseHeader&)), + this, SLOT(onReadyRead())); + connect(connection[i].http, SIGNAL(requestFinished(int, bool)), + this, SLOT(onRequestFinished(int, bool))); + connect(connection[i].http, SIGNAL(done(bool)), + this, SLOT(onDone(bool))); + connect(connection[i].http, SIGNAL(stateChanged(int)), + this, SLOT(onStateChanged(int))); + connect(connection[i].http, SIGNAL(authenticationRequired(const QString&, quint16, QAuthenticator*)), + this, SLOT(onAuthenticationRequired(const QString&, quint16, QAuthenticator*))); + connect(connection[i].http, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)), + this, SLOT(onProxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*))); + connect(connection[i].http, SIGNAL(sslErrors(const QList<QSslError>&)), + this, SLOT(onSslErrors(const QList<QSslError>&))); + } +} + +WebCoreHttp::~WebCoreHttp() +{ + connection[0].http->deleteLater(); + connection[1].http->deleteLater(); +} + +void WebCoreHttp::request(QWebNetworkJob *job) +{ + m_pendingRequests.append(job); + scheduleNextRequest(); +} + +void WebCoreHttp::scheduleNextRequest() +{ + int c = 0; + for (; c < 2; ++c) { + if (!connection[c].current) + break; + } + if (c >= 2) + return; + + QWebNetworkJob *job = 0; + while (!job && !m_pendingRequests.isEmpty()) { + job = m_pendingRequests.takeFirst(); + if (job->cancelled()) { + job->networkInterface()->finished(job, 1); + job = 0; + } + } + if (!job) + return; + + QHttp *http = connection[c].http; + + connection[c].current = job; + connection[c].id = -1; +#ifndef QT_NO_NETWORKPROXY + int proxyId = http->setProxy(job->frame()->page()->networkProxy()); +#endif + + QByteArray postData = job->postData(); + if (!postData.isEmpty()) + connection[c].id = http->request(job->httpHeader(), postData); + else + connection[c].id = http->request(job->httpHeader()); + + DEBUG() << "WebCoreHttp::scheduleNextRequest: using connection" << c; + DEBUG() << job->httpHeader().toString(); +// DEBUG() << job->request.toString(); +} + +int WebCoreHttp::getConnection() +{ + QObject *o = sender(); + int c; + if (o == connection[0].http) { + c = 0; + } else { + Q_ASSERT(o == connection[1].http); + c = 1; + } + Q_ASSERT(connection[c].current); + return c; +} + +void WebCoreHttp::onResponseHeaderReceived(const QHttpResponseHeader &resp) +{ + QHttp *http = qobject_cast<QHttp*>(sender()); + if (http->currentId() == 0) { + qDebug() << "ERROR! Invalid job id. Why?"; // foxnews.com triggers this + return; + } + int c = getConnection(); + QWebNetworkJob *job = connection[c].current; + DEBUG() << "WebCoreHttp::slotResponseHeaderReceived connection=" << c; + DEBUG() << resp.toString(); + + job->setResponse(resp); + + job->networkInterface()->started(job); +} + +void WebCoreHttp::onReadyRead() +{ + QHttp *http = qobject_cast<QHttp*>(sender()); + if (http->currentId() == 0) { + qDebug() << "ERROR! Invalid job id. Why?"; // foxnews.com triggers this + return; + } + int c = getConnection(); + QWebNetworkJob *job = connection[c].current; + Q_ASSERT(http == connection[c].http); + //DEBUG() << "WebCoreHttp::slotReadyRead connection=" << c; + + QByteArray data; + data.resize(http->bytesAvailable()); + http->read(data.data(), data.length()); + job->networkInterface()->data(job, data); +} + +void WebCoreHttp::onRequestFinished(int id, bool error) +{ + int c = getConnection(); + if (connection[c].id != id) { + return; + } + + QWebNetworkJob *job = connection[c].current; + if (!job) { + scheduleNextRequest(); + return; + } + + QHttp *http = connection[c].http; + DEBUG() << "WebCoreHttp::slotFinished connection=" << c << error << job; + if (error) { + DEBUG() << " error: " << http->errorString(); + job->setErrorString(http->errorString()); + } + + if (!error && http->bytesAvailable()) { + QByteArray data; + data.resize(http->bytesAvailable()); + http->read(data.data(), data.length()); + job->networkInterface()->data(job, data); + } + + job->networkInterface()->finished(job, error ? 1 : 0); + connection[c].current = 0; + connection[c].id = -1; + scheduleNextRequest(); +} + +void WebCoreHttp::onDone(bool error) +{ + DEBUG() << "WebCoreHttp::onDone" << error; +} + +void WebCoreHttp::onStateChanged(int state) +{ + DEBUG() << "State changed to" << state << "and connections are" << connection[0].current << connection[1].current; + if (state == QHttp::Closing || state == QHttp::Unconnected) { + if (!m_inCancel && m_pendingRequests.isEmpty() + && !connection[0].current && !connection[1].current) + emit connectionClosed(info); + } +} + +void WebCoreHttp::cancel(QWebNetworkJob* request) +{ + bool doEmit = true; + m_inCancel = true; + for (int i = 0; i < 2; ++i) { + if (request == connection[i].current) { + connection[i].http->abort(); + doEmit = false; + } + } + if (!m_pendingRequests.removeAll(request)) + doEmit = false; + m_inCancel = false; + + if (doEmit) + request->networkInterface()->finished(request, 1); + + if (m_pendingRequests.isEmpty() + && !connection[0].current && !connection[1].current) + emit connectionClosed(info); +} + +void WebCoreHttp::onSslErrors(const QList<QSslError>& errors) +{ + int c = getConnection(); + QWebNetworkJob *job = connection[c].current; + if (job) { + bool continueAnyway = false; + emit job->networkInterface()->sslErrors(job->frame(), job->url(), errors, &continueAnyway); +#ifndef QT_NO_OPENSSL + if (continueAnyway) + connection[c].http->ignoreSslErrors(); +#endif + } +} + +void WebCoreHttp::onAuthenticationRequired(const QString& hostname, quint16 port, QAuthenticator *auth) +{ + int c = getConnection(); + QWebNetworkJob *job = connection[c].current; + if (job) { + emit job->networkInterface()->authenticate(job->frame(), job->url(), hostname, port, auth); + if (auth->isNull()) + connection[c].http->abort(); + } +} + +void WebCoreHttp::onProxyAuthenticationRequired(const QNetworkProxy& proxy, QAuthenticator *auth) +{ + int c = getConnection(); + QWebNetworkJob *job = connection[c].current; + if (job) { + emit job->networkInterface()->authenticateProxy(job->frame(), job->url(), proxy, auth); + if (auth->isNull()) + connection[c].http->abort(); + } +} + +HostInfo::HostInfo(const QUrl& url) + : protocol(url.scheme()) + , host(url.host()) + , port(url.port()) +{ + if (port < 0) { + if (protocol == QLatin1String("http")) + port = 80; + else if (protocol == QLatin1String("https")) + port = 443; + } +} + +#endif diff --git a/WebKit/qt/Api/qwebnetworkinterface.h b/WebKit/qt/Api/qwebnetworkinterface.h new file mode 100644 index 0000000..b603e37 --- /dev/null +++ b/WebKit/qt/Api/qwebnetworkinterface.h @@ -0,0 +1,173 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBNETWORKINTERFACE_H +#define QWEBNETWORKINTERFACE_H + +#include <QtCore/qobject.h> +#include <QtCore/qurl.h> +#include <QtNetwork/qhttp.h> +#include <QtCore/qbytearray.h> + +#include "qwebkitglobal.h" + +#if QT_VERSION < 0x040400 + +class QAuthenticator; +class QNetworkProxy; +class QSslError; +class QWebFrame; +class QWebNetworkJobPrivate; +class QWebNetworkInterface; +class QWebObjectPluginConnector; + +namespace WebCore { + class WebCoreHttp; + class ResourceRequest; + class FrameLoaderClientQt; +} + +struct QWebNetworkRequestPrivate; +class QWEBKIT_EXPORT QWebNetworkRequest +{ +public: + enum Method { + Get, + Post + //Head + }; + + QWebNetworkRequest(); + explicit QWebNetworkRequest(const QUrl &url, Method method = Get, const QByteArray &postData = QByteArray()); + QWebNetworkRequest(const QWebNetworkRequest &other); + + QWebNetworkRequest &operator=(const QWebNetworkRequest &other); + ~QWebNetworkRequest(); + + QUrl url() const; + void setUrl(const QUrl &url); + + QHttpRequestHeader httpHeader() const; + void setHttpHeader(const QHttpRequestHeader &header) const; + + QString httpHeaderField(const QString &key) const; + void setHttpHeaderField(const QString &key, const QString &value); + + QByteArray postData() const; + void setPostData(const QByteArray &data); + +private: + explicit QWebNetworkRequest(const QWebNetworkRequestPrivate &priv); + explicit QWebNetworkRequest(const WebCore::ResourceRequest &request); + friend class QWebNetworkJob; + friend class WebCore::FrameLoaderClientQt; + + QWebNetworkRequestPrivate *d; + friend class QWebObjectPluginConnector; +}; + +class QWEBKIT_EXPORT QWebNetworkJob +{ +public: + + QUrl url() const; + QByteArray postData() const; + QHttpRequestHeader httpHeader() const; + QWebNetworkRequest request() const; + QString errorString() const; + + QHttpResponseHeader response() const; + void setResponse(const QHttpResponseHeader &response); + void setErrorString(const QString&); + + bool cancelled() const; + + void ref(); + bool deref(); + + QWebNetworkInterface *networkInterface() const; + + QWebFrame *frame() const; + +protected: + enum JobStatus { + JobCreated, + JobRecreated, + JobStarted, + JobReceivingData, + JobFinished + }; + + JobStatus status() const; + void setStatus(const JobStatus&); + +private: + QWebNetworkJob(); + ~QWebNetworkJob(); + + friend class QWebNetworkManager; + friend class QWebObjectPluginConnector; + friend class QWebNetworkJobPrivate; + + QWebNetworkJobPrivate *d; +}; + +class QWebNetworkInterfacePrivate; + +class QWEBKIT_EXPORT QWebNetworkInterface : public QObject +{ + Q_OBJECT +public: + QWebNetworkInterface(QObject *parent = 0); + ~QWebNetworkInterface(); + + static void setDefaultInterface(QWebNetworkInterface *defaultInterface); + static QWebNetworkInterface *defaultInterface(); + + virtual void addJob(QWebNetworkJob *job); + virtual void cancelJob(QWebNetworkJob *job); + +protected: + void started(QWebNetworkJob*); + void data(QWebNetworkJob*, const QByteArray &data); + void finished(QWebNetworkJob*, int errorCode); + +signals: + /** + * Signal is emitted when an SSL error occurs. + */ + void sslErrors(QWebFrame *frame, const QUrl& url, const QList<QSslError>& errors, bool *continueAnyway); + /** + * Signal is emitted when network authentication is required. + */ + void authenticate(QWebFrame *frame, const QUrl& url, const QString& hostname, quint16 port, QAuthenticator *auth); + /** + * Signal is emitted when proxy authentication is required. + */ + void authenticateProxy(QWebFrame *frame, const QUrl& url, const QNetworkProxy& proxy, QAuthenticator *auth); + +private: + friend class QWebNetworkInterfacePrivate; + friend class WebCore::WebCoreHttp; + QWebNetworkInterfacePrivate *d; +}; + +#endif + +#endif diff --git a/WebKit/qt/Api/qwebnetworkinterface_p.h b/WebKit/qt/Api/qwebnetworkinterface_p.h new file mode 100644 index 0000000..56e8617 --- /dev/null +++ b/WebKit/qt/Api/qwebnetworkinterface_p.h @@ -0,0 +1,219 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBNETWORKINTERFACE_P_H +#define QWEBNETWORKINTERFACE_P_H + +#include "qwebnetworkinterface.h" +#if QT_VERSION < 0x040400 +#include <qthread.h> +#include <qmutex.h> + +namespace WebCore { + struct HostInfo; + class ResourceRequest; +}; +uint qHash(const WebCore::HostInfo &info); +#include <qhash.h> + +namespace WebCore { + class ResourceHandle; +} + +struct QWebNetworkRequestPrivate +{ + QUrl url; + QHttpRequestHeader httpHeader; + QByteArray postData; + + void init(const WebCore::ResourceRequest &resourceRequest); + void init(const QString &method, const QUrl &url, const WebCore::ResourceRequest *resourceRequest = 0); + void setURL(const QUrl &u); +}; + +class QWebNetworkJobPrivate +{ +public: + QWebNetworkJobPrivate() + : ref(1) + , resourceHandle(0) + , redirected(false) + , interface(0) + , jobStatus(QWebNetworkJob::JobCreated) + {} + int ref; + + QWebNetworkRequestPrivate request; + QHttpResponseHeader response; + + WebCore::ResourceHandle *resourceHandle; + bool redirected; + + QWebNetworkInterface *interface; + QWebNetworkJob::JobStatus jobStatus; + QString errorString; +}; + +class QWebNetworkManager : public QObject +{ + Q_OBJECT +public: + enum JobMode { + AsynchronousJob, + SynchronousJob + }; + + static QWebNetworkManager *self(); + + bool add(WebCore::ResourceHandle *resourceHandle, QWebNetworkInterface *interface, JobMode = AsynchronousJob); + void cancel(WebCore::ResourceHandle *resourceHandle); + + void addHttpJob(QWebNetworkJob *job); + void cancelHttpJob(QWebNetworkJob *job); + +protected: + void queueStart(QWebNetworkJob*); + void queueData(QWebNetworkJob*, const QByteArray&); + void queueFinished(QWebNetworkJob*, int errorCode); + +private: + void started(QWebNetworkJob *); + void data(QWebNetworkJob *, const QByteArray &data); + void finished(QWebNetworkJob *, int errorCode); + void doScheduleWork(); + +signals: + void fileRequest(QWebNetworkJob*); + void scheduleWork(); + +private slots: + void httpConnectionClosed(const WebCore::HostInfo &); + void doWork(); + +private: + friend class QWebNetworkInterface; + QWebNetworkManager(); + QHash<WebCore::HostInfo, WebCore::WebCoreHttp *> m_hostMapping; + + struct JobWork { + enum WorkType { + JobStarted, + JobData, + JobFinished + }; + + explicit JobWork(QWebNetworkJob* _job) + : workType(JobStarted) + , errorCode(-1) + , job(_job) + {} + + explicit JobWork(QWebNetworkJob* _job, int _errorCode) + : workType(JobFinished) + , errorCode(_errorCode) + , job(_job) + {} + + explicit JobWork(QWebNetworkJob* _job, const QByteArray& _data) + : workType(JobData) + , errorCode(-1) + , job(_job) + , data(_data) + {} + + const WorkType workType; + int errorCode; + QByteArray data; + QWebNetworkJob* job; + }; + + QMutex m_queueMutex; + bool m_scheduledWork; + QList<JobWork*> m_pendingWork; + QHash<QWebNetworkJob*, int> m_synchronousJobs; +}; + + +namespace WebCore { + + class NetworkLoader; + + struct HostInfo { + HostInfo() {} + HostInfo(const QUrl& url); + QString protocol; + QString host; + int port; + }; + + class WebCoreHttp : public QObject + { + Q_OBJECT + public: + WebCoreHttp(QObject *parent, const HostInfo&); + ~WebCoreHttp(); + + void request(QWebNetworkJob* resource); + void cancel(QWebNetworkJob*); + + signals: + void connectionClosed(const WebCore::HostInfo &); + + private slots: + void onResponseHeaderReceived(const QHttpResponseHeader& resp); + void onReadyRead(); + void onRequestFinished(int, bool); + void onDone(bool); + void onStateChanged(int); + void onSslErrors(const QList<QSslError>&); + void onAuthenticationRequired(const QString& hostname, quint16 port, QAuthenticator *); + void onProxyAuthenticationRequired(const QNetworkProxy& proxy, QAuthenticator *); + + void scheduleNextRequest(); + + int getConnection(); + + public: + HostInfo info; + private: + QList<QWebNetworkJob *> m_pendingRequests; + struct HttpConnection { + HttpConnection() : http(0), current(0), id(-1) {} + QHttp *http; + QWebNetworkJob *current; + int id; // the QHttp id + }; + HttpConnection connection[2]; + bool m_inCancel; + }; + +} + +class QWebNetworkInterfacePrivate +{ +public: + void sendFileData(QWebNetworkJob* job, int statusCode, const QByteArray &data); + void parseDataUrl(QWebNetworkJob* job); + + QWebNetworkInterface *q; +}; + +#endif + +#endif diff --git a/WebKit/qt/Api/qwebpage.cpp b/WebKit/qt/Api/qwebpage.cpp new file mode 100644 index 0000000..b7285d6 --- /dev/null +++ b/WebKit/qt/Api/qwebpage.cpp @@ -0,0 +1,2543 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2007 Staikos Computing Services Inc. + Copyright (C) 2007 Apple Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qwebpage.h" +#include "qwebview.h" +#include "qwebframe.h" +#include "qwebpage_p.h" +#include "qwebframe_p.h" +#include "qwebhistory.h" +#include "qwebhistory_p.h" +#include "qwebsettings.h" + +#include "Frame.h" +#include "FrameTree.h" +#include "FrameLoaderClientQt.h" +#include "FrameView.h" +#include "ChromeClientQt.h" +#include "ContextMenu.h" +#include "ContextMenuClientQt.h" +#include "DocumentLoader.h" +#include "DragClientQt.h" +#include "DragController.h" +#include "DragData.h" +#include "EditorClientQt.h" +#include "Settings.h" +#include "Page.h" +#include "PageGroup.h" +#include "Pasteboard.h" +#include "FrameLoader.h" +#include "FrameLoadRequest.h" +#include "KURL.h" +#include "Logging.h" +#include "Image.h" +#include "InspectorClientQt.h" +#include "InspectorController.h" +#include "FocusController.h" +#include "Editor.h" +#include "Scrollbar.h" +#include "PlatformKeyboardEvent.h" +#include "PlatformWheelEvent.h" +#include "ProgressTracker.h" +#include "RefPtr.h" +#include "HashMap.h" +#include "HitTestResult.h" +#include "WindowFeatures.h" +#include "LocalizedStrings.h" +#include "runtime/InitializeThreading.h" + +#include <QApplication> +#include <QBasicTimer> +#include <QBitArray> +#include <QDebug> +#include <QDragEnterEvent> +#include <QDragLeaveEvent> +#include <QDragMoveEvent> +#include <QDropEvent> +#include <QFileDialog> +#include <QHttpRequestHeader> +#include <QInputDialog> +#include <QLocale> +#include <QMessageBox> +#include <QNetworkProxy> +#include <QUndoStack> +#include <QUrl> +#include <QPainter> +#include <QClipboard> +#include <QSslSocket> +#include <QStyle> +#include <QSysInfo> +#if QT_VERSION >= 0x040400 +#include <QNetworkAccessManager> +#include <QNetworkRequest> +#else +#include "qwebnetworkinterface.h" +#endif + +using namespace WebCore; + +// Lookup table mapping QWebPage::WebActions to the associated Editor commands +static const char* editorCommandWebActions[] = +{ + 0, // OpenLink, + + 0, // OpenLinkInNewWindow, + 0, // OpenFrameInNewWindow, + + 0, // DownloadLinkToDisk, + 0, // CopyLinkToClipboard, + + 0, // OpenImageInNewWindow, + 0, // DownloadImageToDisk, + 0, // CopyImageToClipboard, + + 0, // Back, + 0, // Forward, + 0, // Stop, + 0, // Reload, + + "Cut", // Cut, + "Copy", // Copy, + "Paste", // Paste, + + "Undo", // Undo, + "Redo", // Redo, + "MoveForward", // MoveToNextChar, + "MoveBackward", // MoveToPreviousChar, + "MoveWordForward", // MoveToNextWord, + "MoveWordBackward", // MoveToPreviousWord, + "MoveDown", // MoveToNextLine, + "MoveUp", // MoveToPreviousLine, + "MoveToBeginningOfLine", // MoveToStartOfLine, + "MoveToEndOfLine", // MoveToEndOfLine, + "MoveToBeginningOfParagraph", // MoveToStartOfBlock, + "MoveToEndOfParagraph", // MoveToEndOfBlock, + "MoveToBeginningOfDocument", // MoveToStartOfDocument, + "MoveToEndOfDocument", // MoveToEndOfDocument, + "MoveForwardAndModifySelection", // SelectNextChar, + "MoveBackwardAndModifySelection", // SelectPreviousChar, + "MoveWordForwardAndModifySelection", // SelectNextWord, + "MoveWordBackwardAndModifySelection", // SelectPreviousWord, + "MoveDownAndModifySelection", // SelectNextLine, + "MoveUpAndModifySelection", // SelectPreviousLine, + "MoveToBeginningOfLineAndModifySelection", // SelectStartOfLine, + "MoveToEndOfLineAndModifySelection", // SelectEndOfLine, + "MoveToBeginningOfParagraphAndModifySelection", // SelectStartOfBlock, + "MoveToEndOfParagraphAndModifySelection", // SelectEndOfBlock, + "MoveToBeginningOfDocumentAndModifySelection", //SelectStartOfDocument, + "MoveToEndOfDocumentAndModifySelection", // SelectEndOfDocument, + "DeleteWordBackward", // DeleteStartOfWord, + "DeleteWordForward", // DeleteEndOfWord, + + 0, // SetTextDirectionDefault, + 0, // SetTextDirectionLeftToRight, + 0, // SetTextDirectionRightToLeft, + + "ToggleBold", // ToggleBold, + "ToggleItalic", // ToggleItalic, + "ToggleUnderline", // ToggleUnderline, + + 0, // InspectElement, + + "InsertNewline", // InsertParagraphSeparator + "InsertLineBreak", // InsertLineSeparator + + 0 // WebActionCount +}; + +// Lookup the appropriate editor command to use for WebAction \a action +static const char* editorCommandForWebActions(QWebPage::WebAction action) +{ + if ((action > QWebPage::NoWebAction) && (action < int(sizeof(editorCommandWebActions) / sizeof(const char*)))) + return editorCommandWebActions[action]; + + return 0; +} + +#ifndef QT_NO_CURSOR +SetCursorEvent::SetCursorEvent(const QCursor& cursor) + : QEvent(static_cast<QEvent::Type>(EventType)) + , m_cursor(cursor) +{} + +QCursor SetCursorEvent::cursor() const +{ + return m_cursor; +} +#endif + +// If you change this make sure to also adjust the docs for QWebPage::userAgentForUrl +#define WEBKIT_VERSION "527+" + +static inline DragOperation dropActionToDragOp(Qt::DropActions actions) +{ + unsigned result = 0; + if (actions & Qt::CopyAction) + result |= DragOperationCopy; + if (actions & Qt::MoveAction) + result |= DragOperationMove; + if (actions & Qt::LinkAction) + result |= DragOperationLink; + return (DragOperation)result; +} + +static inline Qt::DropAction dragOpToDropAction(unsigned actions) +{ + Qt::DropAction result = Qt::IgnoreAction; + if (actions & DragOperationCopy) + result = Qt::CopyAction; + else if (actions & DragOperationMove) + result = Qt::MoveAction; + else if (actions & DragOperationLink) + result = Qt::LinkAction; + return result; +} + +QWebPagePrivate::QWebPagePrivate(QWebPage *qq) + : q(qq) + , view(0) + , viewportSize(QSize(0,0)) +{ + WebCore::InitializeLoggingChannelsIfNecessary(); + WebCore::PageGroup::setShouldTrackVisitedLinks(true); + JSC::initializeThreading(); + + chromeClient = new ChromeClientQt(q); + contextMenuClient = new ContextMenuClientQt(); + editorClient = new EditorClientQt(q); + page = new Page(chromeClient, contextMenuClient, editorClient, + new DragClientQt(q), new InspectorClientQt(q)); + + // ### should be configurable + page->settings()->setDefaultTextEncodingName("iso-8859-1"); + + settings = new QWebSettings(page->settings()); + +#ifndef QT_NO_UNDOSTACK + undoStack = 0; +#endif + mainFrame = 0; +#if QT_VERSION < 0x040400 + networkInterface = 0; +#else + networkManager = 0; +#endif + pluginFactory = 0; + insideOpenCall = false; + forwardUnsupportedContent = false; + editable = false; + linkPolicy = QWebPage::DontDelegateLinks; +#ifndef QT_NO_CONTEXTMENU + currentContextMenu = 0; +#endif + + history.d = new QWebHistoryPrivate(page->backForwardList()); + memset(actions, 0, sizeof(actions)); +} + +QWebPagePrivate::~QWebPagePrivate() +{ +#ifndef QT_NO_CONTEXTMENU + delete currentContextMenu; +#endif +#ifndef QT_NO_UNDOSTACK + delete undoStack; +#endif + delete settings; + delete page; +} + +#if QT_VERSION < 0x040400 +bool QWebPagePrivate::acceptNavigationRequest(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type) +{ + if (insideOpenCall + && frame == mainFrame) + return true; + return q->acceptNavigationRequest(frame, request, type); +} +#else +bool QWebPagePrivate::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type) +{ + if (insideOpenCall + && frame == mainFrame) + return true; + return q->acceptNavigationRequest(frame, request, type); +} +#endif + +void QWebPagePrivate::createMainFrame() +{ + if (!mainFrame) { + QWebFrameData frameData; + frameData.ownerElement = 0; + frameData.allowsScrolling = true; + frameData.marginWidth = 0; + frameData.marginHeight = 0; + mainFrame = new QWebFrame(q, &frameData); + + emit q->frameCreated(mainFrame); + } +} + +static QWebPage::WebAction webActionForContextMenuAction(WebCore::ContextMenuAction action) +{ + switch (action) { + case WebCore::ContextMenuItemTagOpenLink: return QWebPage::OpenLink; + case WebCore::ContextMenuItemTagOpenLinkInNewWindow: return QWebPage::OpenLinkInNewWindow; + case WebCore::ContextMenuItemTagDownloadLinkToDisk: return QWebPage::DownloadLinkToDisk; + case WebCore::ContextMenuItemTagCopyLinkToClipboard: return QWebPage::CopyLinkToClipboard; + case WebCore::ContextMenuItemTagOpenImageInNewWindow: return QWebPage::OpenImageInNewWindow; + case WebCore::ContextMenuItemTagDownloadImageToDisk: return QWebPage::DownloadImageToDisk; + case WebCore::ContextMenuItemTagCopyImageToClipboard: return QWebPage::CopyImageToClipboard; + case WebCore::ContextMenuItemTagOpenFrameInNewWindow: return QWebPage::OpenFrameInNewWindow; + case WebCore::ContextMenuItemTagCopy: return QWebPage::Copy; + case WebCore::ContextMenuItemTagGoBack: return QWebPage::Back; + case WebCore::ContextMenuItemTagGoForward: return QWebPage::Forward; + case WebCore::ContextMenuItemTagStop: return QWebPage::Stop; + case WebCore::ContextMenuItemTagReload: return QWebPage::Reload; + case WebCore::ContextMenuItemTagCut: return QWebPage::Cut; + case WebCore::ContextMenuItemTagPaste: return QWebPage::Paste; + case WebCore::ContextMenuItemTagDefaultDirection: return QWebPage::SetTextDirectionDefault; + case WebCore::ContextMenuItemTagLeftToRight: return QWebPage::SetTextDirectionLeftToRight; + case WebCore::ContextMenuItemTagRightToLeft: return QWebPage::SetTextDirectionRightToLeft; + case WebCore::ContextMenuItemTagBold: return QWebPage::ToggleBold; + case WebCore::ContextMenuItemTagItalic: return QWebPage::ToggleItalic; + case WebCore::ContextMenuItemTagUnderline: return QWebPage::ToggleUnderline; + case WebCore::ContextMenuItemTagInspectElement: return QWebPage::InspectElement; + default: break; + } + return QWebPage::NoWebAction; +} + +#ifndef QT_NO_CONTEXTMENU +QMenu *QWebPagePrivate::createContextMenu(const WebCore::ContextMenu *webcoreMenu, + const QList<WebCore::ContextMenuItem> *items, QBitArray *visitedWebActions) +{ + QMenu* menu = new QMenu(view); + for (int i = 0; i < items->count(); ++i) { + const ContextMenuItem &item = items->at(i); + switch (item.type()) { + case WebCore::CheckableActionType: /* fall through */ + case WebCore::ActionType: { + QWebPage::WebAction action = webActionForContextMenuAction(item.action()); + QAction *a = q->action(action); + if (a) { + ContextMenuItem it(item); + webcoreMenu->checkOrEnableIfNeeded(it); + PlatformMenuItemDescription desc = it.releasePlatformDescription(); + a->setEnabled(desc.enabled); + a->setChecked(desc.checked); + a->setCheckable(item.type() == WebCore::CheckableActionType); + + menu->addAction(a); + visitedWebActions->setBit(action); + } + break; + } + case WebCore::SeparatorType: + menu->addSeparator(); + break; + case WebCore::SubmenuType: { + QMenu *subMenu = createContextMenu(webcoreMenu, item.platformSubMenu(), visitedWebActions); + + bool anyEnabledAction = false; + + QList<QAction *> actions = subMenu->actions(); + for (int i = 0; i < actions.count(); ++i) { + if (actions.at(i)->isVisible()) + anyEnabledAction |= actions.at(i)->isEnabled(); + } + + // don't show sub-menus with just disabled actions + if (anyEnabledAction) { + subMenu->setTitle(item.title()); + menu->addAction(subMenu->menuAction()); + } else { + delete subMenu; + } + break; + } + } + } + return menu; +} +#endif // QT_NO_CONTEXTMENU + +QWebFrame *QWebPagePrivate::frameAt(const QPoint &pos) const +{ + QWebFrame *frame = mainFrame; + +redo: + QList<QWebFrame*> children = frame->childFrames(); + for (int i = 0; i < children.size(); ++i) { + if (children.at(i)->geometry().contains(pos)) { + frame = children.at(i); + goto redo; + } + } + if (frame->geometry().contains(pos)) + return frame; + return 0; +} + +void QWebPagePrivate::_q_webActionTriggered(bool checked) +{ + QAction *a = qobject_cast<QAction *>(q->sender()); + if (!a) + return; + QWebPage::WebAction action = static_cast<QWebPage::WebAction>(a->data().toInt()); + q->triggerAction(action, checked); +} + +void QWebPagePrivate::updateAction(QWebPage::WebAction action) +{ + QAction *a = actions[action]; + if (!a || !mainFrame) + return; + + WebCore::FrameLoader *loader = mainFrame->d->frame->loader(); + WebCore::Editor *editor = page->focusController()->focusedOrMainFrame()->editor(); + + bool enabled = a->isEnabled(); + bool checked = a->isChecked(); + + switch (action) { + case QWebPage::Back: + enabled = loader->canGoBackOrForward(-1); + break; + case QWebPage::Forward: + enabled = loader->canGoBackOrForward(1); + break; + case QWebPage::Stop: + enabled = loader->isLoading(); + break; + case QWebPage::Reload: + enabled = !loader->isLoading(); + break; + case QWebPage::Cut: + enabled = editor->canCut(); + break; + case QWebPage::Copy: + enabled = editor->canCopy(); + break; + case QWebPage::Paste: + enabled = editor->canPaste(); + break; +#ifndef QT_NO_UNDOSTACK + case QWebPage::Undo: + case QWebPage::Redo: + // those two are handled by QUndoStack + break; +#endif // QT_NO_UNDOSTACK + case QWebPage::ToggleBold: + case QWebPage::ToggleItalic: + case QWebPage::ToggleUnderline: + enabled = editor->canEditRichly(); + if (enabled) + checked = editor->command(editorCommandForWebActions(action)).state() != FalseTriState; + else + checked = false; + break; + default: break; + } + + a->setEnabled(enabled); + + if (a->isCheckable()) + a->setChecked(checked); +} + +void QWebPagePrivate::updateNavigationActions() +{ + updateAction(QWebPage::Back); + updateAction(QWebPage::Forward); + updateAction(QWebPage::Stop); + updateAction(QWebPage::Reload); +} + +void QWebPagePrivate::updateEditorActions() +{ + updateAction(QWebPage::Cut); + updateAction(QWebPage::Copy); + updateAction(QWebPage::Paste); + updateAction(QWebPage::ToggleBold); + updateAction(QWebPage::ToggleItalic); + updateAction(QWebPage::ToggleUnderline); +} + +void QWebPagePrivate::timerEvent(QTimerEvent *ev) +{ + int timerId = ev->timerId(); + if (timerId == tripleClickTimer.timerId()) + tripleClickTimer.stop(); + else + q->QObject::timerEvent(ev); +} + +void QWebPagePrivate::mouseMoveEvent(QMouseEvent *ev) +{ + WebCore::Frame* frame = QWebFramePrivate::core(mainFrame); + if (!frame->view()) + return; + + bool accepted = frame->eventHandler()->mouseMoved(PlatformMouseEvent(ev, 0)); + ev->setAccepted(accepted); +} + +void QWebPagePrivate::mousePressEvent(QMouseEvent *ev) +{ + WebCore::Frame* frame = QWebFramePrivate::core(mainFrame); + if (!frame->view()) + return; + + if (tripleClickTimer.isActive() + && (ev->pos() - tripleClick).manhattanLength() + < QApplication::startDragDistance()) { + mouseTripleClickEvent(ev); + return; + } + + bool accepted = frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(ev, 1)); + ev->setAccepted(accepted); +} + +void QWebPagePrivate::mouseDoubleClickEvent(QMouseEvent *ev) +{ + WebCore::Frame* frame = QWebFramePrivate::core(mainFrame); + if (!frame->view()) + return; + + bool accepted = frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(ev, 2)); + ev->setAccepted(accepted); + + tripleClickTimer.start(QApplication::doubleClickInterval(), q); + tripleClick = ev->pos(); +} + +void QWebPagePrivate::mouseTripleClickEvent(QMouseEvent *ev) +{ + WebCore::Frame* frame = QWebFramePrivate::core(mainFrame); + if (!frame->view()) + return; + + bool accepted = frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(ev, 3)); + ev->setAccepted(accepted); +} + +void QWebPagePrivate::mouseReleaseEvent(QMouseEvent *ev) +{ + WebCore::Frame* frame = QWebFramePrivate::core(mainFrame); + if (!frame->view()) + return; + + bool accepted = frame->eventHandler()->handleMouseReleaseEvent(PlatformMouseEvent(ev, 0)); + ev->setAccepted(accepted); + +#ifndef QT_NO_CLIPBOARD + if (QApplication::clipboard()->supportsSelection()) { + bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode(); + Pasteboard::generalPasteboard()->setSelectionMode(true); + WebCore::Frame* focusFrame = page->focusController()->focusedOrMainFrame(); + if (ev->button() == Qt::LeftButton) { + if(focusFrame && (focusFrame->editor()->canCopy() || focusFrame->editor()->canDHTMLCopy())) { + focusFrame->editor()->copy(); + ev->setAccepted(true); + } + } else if (ev->button() == Qt::MidButton) { + if(focusFrame && (focusFrame->editor()->canPaste() || focusFrame->editor()->canDHTMLPaste())) { + focusFrame->editor()->paste(); + ev->setAccepted(true); + } + } + Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode); + } +#endif +} + +#ifndef QT_NO_CONTEXTMENU +void QWebPagePrivate::contextMenuEvent(QContextMenuEvent *ev) +{ + QMenu *menu = q->createStandardContextMenu(); + if (menu) { + menu->exec(ev->globalPos()); + delete menu; + } +} +#endif // QT_NO_CONTEXTMENU + +/*! + \since 4.5 + This function creates the standard context menu which is shown when + the user clicks on the web page with the right mouse button. It is + called from the default contextMenuEvent() handler. The popup menu's + ownership is transferred to the caller. + */ +QMenu *QWebPage::createStandardContextMenu() +{ +#ifndef QT_NO_CONTEXTMENU + QMenu *menu = d->currentContextMenu; + d->currentContextMenu = 0; + return menu; +#else + return 0; +#endif +} + +#ifndef QT_NO_WHEELEVENT +void QWebPagePrivate::wheelEvent(QWheelEvent *ev) +{ + WebCore::Frame* frame = QWebFramePrivate::core(mainFrame); + if (!frame->view()) + return; + + WebCore::PlatformWheelEvent pev(ev); + bool accepted = frame->eventHandler()->handleWheelEvent(pev); + ev->setAccepted(accepted); +} +#endif // QT_NO_WHEELEVENT + +#ifndef QT_NO_SHORTCUT +static QWebPage::WebAction editorActionForKeyEvent(QKeyEvent* event) +{ + static struct { + QKeySequence::StandardKey standardKey; + QWebPage::WebAction action; + } editorActions[] = { + { QKeySequence::Cut, QWebPage::Cut }, + { QKeySequence::Copy, QWebPage::Copy }, + { QKeySequence::Paste, QWebPage::Paste }, + { QKeySequence::Undo, QWebPage::Undo }, + { QKeySequence::Redo, QWebPage::Redo }, + { QKeySequence::MoveToNextChar, QWebPage::MoveToNextChar }, + { QKeySequence::MoveToPreviousChar, QWebPage::MoveToPreviousChar }, + { QKeySequence::MoveToNextWord, QWebPage::MoveToNextWord }, + { QKeySequence::MoveToPreviousWord, QWebPage::MoveToPreviousWord }, + { QKeySequence::MoveToNextLine, QWebPage::MoveToNextLine }, + { QKeySequence::MoveToPreviousLine, QWebPage::MoveToPreviousLine }, + { QKeySequence::MoveToStartOfLine, QWebPage::MoveToStartOfLine }, + { QKeySequence::MoveToEndOfLine, QWebPage::MoveToEndOfLine }, + { QKeySequence::MoveToStartOfBlock, QWebPage::MoveToStartOfBlock }, + { QKeySequence::MoveToEndOfBlock, QWebPage::MoveToEndOfBlock }, + { QKeySequence::MoveToStartOfDocument, QWebPage::MoveToStartOfDocument }, + { QKeySequence::MoveToEndOfDocument, QWebPage::MoveToEndOfDocument }, + { QKeySequence::SelectNextChar, QWebPage::SelectNextChar }, + { QKeySequence::SelectPreviousChar, QWebPage::SelectPreviousChar }, + { QKeySequence::SelectNextWord, QWebPage::SelectNextWord }, + { QKeySequence::SelectPreviousWord, QWebPage::SelectPreviousWord }, + { QKeySequence::SelectNextLine, QWebPage::SelectNextLine }, + { QKeySequence::SelectPreviousLine, QWebPage::SelectPreviousLine }, + { QKeySequence::SelectStartOfLine, QWebPage::SelectStartOfLine }, + { QKeySequence::SelectEndOfLine, QWebPage::SelectEndOfLine }, + { QKeySequence::SelectStartOfBlock, QWebPage::SelectStartOfBlock }, + { QKeySequence::SelectEndOfBlock, QWebPage::SelectEndOfBlock }, + { QKeySequence::SelectStartOfDocument, QWebPage::SelectStartOfDocument }, + { QKeySequence::SelectEndOfDocument, QWebPage::SelectEndOfDocument }, + { QKeySequence::DeleteStartOfWord, QWebPage::DeleteStartOfWord }, + { QKeySequence::DeleteEndOfWord, QWebPage::DeleteEndOfWord }, +#if QT_VERSION >= 0x040500 + { QKeySequence::InsertParagraphSeparator, QWebPage::InsertParagraphSeparator }, + { QKeySequence::InsertLineSeparator, QWebPage::InsertLineSeparator }, +#endif + { QKeySequence::UnknownKey, QWebPage::NoWebAction } + }; + + for (int i = 0; editorActions[i].standardKey != QKeySequence::UnknownKey; ++i) + if (event == editorActions[i].standardKey) + return editorActions[i].action; + + return QWebPage::NoWebAction; +} +#endif // QT_NO_SHORTCUT + +void QWebPagePrivate::keyPressEvent(QKeyEvent *ev) +{ + bool handled = false; + WebCore::Frame* frame = page->focusController()->focusedOrMainFrame(); + WebCore::Editor* editor = frame->editor(); +#ifndef QT_NO_SHORTCUT + if (editor->canEdit()) { + QWebPage::WebAction action = editorActionForKeyEvent(ev); + if (action != QWebPage::NoWebAction) { + q->triggerAction(action); + handled = true; + } + } else { + if (ev == QKeySequence::Copy) { + q->triggerAction(QWebPage::Copy); + handled = true; + } + } +#endif // QT_NO_SHORTCUT + if (!handled) + handled = frame->eventHandler()->keyEvent(ev); + if (!handled) { + handled = true; + QFont defaultFont; + if (view) + defaultFont = view->font(); + QFontMetrics fm(defaultFont); + int fontHeight = fm.height(); + if (!handleScrolling(ev)) { + switch (ev->key()) { + case Qt::Key_Backspace: + if (ev->modifiers() == Qt::ShiftModifier) + q->triggerAction(QWebPage::Forward); + else + q->triggerAction(QWebPage::Back); + default: + handled = false; + break; + } + } + } + + ev->setAccepted(handled); +} + +void QWebPagePrivate::keyReleaseEvent(QKeyEvent *ev) +{ + if (ev->isAutoRepeat()) { + ev->setAccepted(true); + return; + } + + WebCore::Frame* frame = page->focusController()->focusedOrMainFrame(); + bool handled = frame->eventHandler()->keyEvent(ev); + ev->setAccepted(handled); +} + +void QWebPagePrivate::focusInEvent(QFocusEvent *ev) +{ + if (ev->reason() == Qt::PopupFocusReason) + return; + + FocusController *focusController = page->focusController(); + Frame *frame = focusController->focusedFrame(); + focusController->setActive(true); + if (frame) { + frame->selection()->setFocused(true); + } else { + focusController->setFocusedFrame(QWebFramePrivate::core(mainFrame)); + } +} + +void QWebPagePrivate::focusOutEvent(QFocusEvent *ev) +{ + if (ev->reason() == Qt::PopupFocusReason) + return; + + // only set the focused frame inactive so that we stop painting the caret + // and the focus frame. But don't tell the focus controller so that upon + // focusInEvent() we can re-activate the frame. + FocusController *focusController = page->focusController(); + focusController->setActive(false); + Frame *frame = focusController->focusedFrame(); + if (frame) { + frame->selection()->setFocused(false); + } +} + +void QWebPagePrivate::dragEnterEvent(QDragEnterEvent *ev) +{ +#ifndef QT_NO_DRAGANDDROP + DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(), + dropActionToDragOp(ev->possibleActions())); + Qt::DropAction action = dragOpToDropAction(page->dragController()->dragEntered(&dragData)); + ev->setDropAction(action); + if (action != Qt::IgnoreAction) + ev->accept(); +#endif +} + +void QWebPagePrivate::dragLeaveEvent(QDragLeaveEvent *ev) +{ +#ifndef QT_NO_DRAGANDDROP + DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone); + page->dragController()->dragExited(&dragData); + ev->accept(); +#endif +} + +void QWebPagePrivate::dragMoveEvent(QDragMoveEvent *ev) +{ +#ifndef QT_NO_DRAGANDDROP + DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(), + dropActionToDragOp(ev->possibleActions())); + Qt::DropAction action = dragOpToDropAction(page->dragController()->dragUpdated(&dragData)); + ev->setDropAction(action); + if (action != Qt::IgnoreAction) + ev->accept(); +#endif +} + +void QWebPagePrivate::dropEvent(QDropEvent *ev) +{ +#ifndef QT_NO_DRAGANDDROP + DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(), + dropActionToDragOp(ev->possibleActions())); + Qt::DropAction action = dragOpToDropAction(page->dragController()->performDrag(&dragData)); + if (action != Qt::IgnoreAction) + ev->accept(); +#endif +} + +void QWebPagePrivate::leaveEvent(QEvent *ev) +{ + // Fake a mouse move event just outside of the widget, since all + // the interesting mouse-out behavior like invalidating scrollbars + // is handled by the WebKit event handler's mouseMoved function. + QMouseEvent fakeEvent(QEvent::MouseMove, QCursor::pos(), Qt::NoButton, Qt::NoButton, Qt::NoModifier); + mouseMoveEvent(&fakeEvent); +} + +/*! + \property QWebPage::palette + \brief the page's palette + + The background brush of the palette is used to draw the background of the main frame. + + By default, this property contains the application's default palette. +*/ +void QWebPage::setPalette(const QPalette &pal) +{ + d->palette = pal; + if (d->mainFrame) + d->mainFrame->d->updateBackground(); +} + +QPalette QWebPage::palette() const +{ + return d->palette; +} + +void QWebPagePrivate::inputMethodEvent(QInputMethodEvent *ev) +{ + WebCore::Frame *frame = page->focusController()->focusedOrMainFrame(); + WebCore::Editor *editor = frame->editor(); + + if (!editor->canEdit()) { + ev->ignore(); + return; + } + + if (!ev->preeditString().isEmpty()) { + QString preedit = ev->preeditString(); + // ### FIXME: use the provided QTextCharFormat (use color at least) + Vector<CompositionUnderline> underlines; + underlines.append(CompositionUnderline(0, preedit.length(), Color(0,0,0), false)); + editor->setComposition(preedit, underlines, preedit.length(), 0); + } else if (!ev->commitString().isEmpty()) { + editor->confirmComposition(ev->commitString()); + } + ev->accept(); +} + +void QWebPagePrivate::shortcutOverrideEvent(QKeyEvent* event) +{ + WebCore::Frame* frame = page->focusController()->focusedOrMainFrame(); + WebCore::Editor* editor = frame->editor(); + if (editor->canEdit()) { + if (event->modifiers() == Qt::NoModifier + || event->modifiers() == Qt::ShiftModifier + || event->modifiers() == Qt::KeypadModifier) { + if (event->key() < Qt::Key_Escape) { + event->accept(); + } else { + switch (event->key()) { + case Qt::Key_Return: + case Qt::Key_Enter: + case Qt::Key_Delete: + case Qt::Key_Home: + case Qt::Key_End: + case Qt::Key_Backspace: + case Qt::Key_Left: + case Qt::Key_Right: + case Qt::Key_Up: + case Qt::Key_Down: + case Qt::Key_Tab: + event->accept(); + default: + break; + } + } + } +#ifndef QT_NO_SHORTCUT + else if (editorActionForKeyEvent(event) != QWebPage::NoWebAction) { + event->accept(); + } +#endif + } +} + +bool QWebPagePrivate::handleScrolling(QKeyEvent *ev) +{ + ScrollDirection direction; + ScrollGranularity granularity; + +#ifndef QT_NO_SHORTCUT + if (ev == QKeySequence::MoveToNextPage + || (ev->key() == Qt::Key_Space && !(ev->modifiers() & Qt::ShiftModifier))) { + granularity = ScrollByPage; + direction = ScrollDown; + } else if (ev == QKeySequence::MoveToPreviousPage + || (ev->key() == Qt::Key_Space) && (ev->modifiers() & Qt::ShiftModifier)) { + granularity = ScrollByPage; + direction = ScrollUp; + } else +#endif // QT_NO_SHORTCUT + if (ev->key() == Qt::Key_Up && ev->modifiers() & Qt::ControlModifier + || ev->key() == Qt::Key_Home) { + granularity = ScrollByDocument; + direction = ScrollUp; + } else if (ev->key() == Qt::Key_Down && ev->modifiers() & Qt::ControlModifier + || ev->key() == Qt::Key_End) { + granularity = ScrollByDocument; + direction = ScrollDown; + } else { + switch (ev->key()) { + case Qt::Key_Up: + granularity = ScrollByLine; + direction = ScrollUp; + break; + case Qt::Key_Down: + granularity = ScrollByLine; + direction = ScrollDown; + break; + case Qt::Key_Left: + granularity = ScrollByLine; + direction = ScrollLeft; + break; + case Qt::Key_Right: + granularity = ScrollByLine; + direction = ScrollRight; + break; + default: + return false; + } + } + + if (!mainFrame->d->frame->eventHandler()->scrollOverflow(direction, granularity)) + mainFrame->d->frame->view()->scroll(direction, granularity); + + return true; +} + +/*! + This method is used by the input method to query a set of properties of the page + to be able to support complex input method operations as support for surrounding + text and reconversions. + + \a property specifies which property is queried. + + \sa QWidget::inputMethodEvent(), QInputMethodEvent, QInputContext +*/ +QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const +{ + switch(property) { + case Qt::ImMicroFocus: { + Frame *frame = d->page->focusController()->focusedFrame(); + if (frame) { + return QVariant(frame->selection()->caretRect()); + } + return QVariant(); + } + case Qt::ImFont: { + QWebView *webView = qobject_cast<QWebView *>(d->view); + if (webView) + return QVariant(webView->font()); + return QVariant(); + } + case Qt::ImCursorPosition: { + Frame *frame = d->page->focusController()->focusedFrame(); + if (frame) { + Selection selection = frame->selection()->selection(); + if (selection.isCaret()) { + return QVariant(selection.start().offset()); + } + } + return QVariant(); + } + case Qt::ImSurroundingText: { + Frame *frame = d->page->focusController()->focusedFrame(); + if (frame) { + Document *document = frame->document(); + if (document->focusedNode()) { + return QVariant(document->focusedNode()->nodeValue()); + } + } + return QVariant(); + } + case Qt::ImCurrentSelection: + return QVariant(selectedText()); + default: + return QVariant(); + } +} + +/*! + \enum QWebPage::FindFlag + + This enum describes the options available to QWebPage's findText() function. The options + can be OR-ed together from the following list: + + \value FindBackward Searches backwards instead of forwards. + \value FindCaseSensitively By default findText() works case insensitive. Specifying this option + changes the behaviour to a case sensitive find operation. + \value FindWrapsAroundDocument Makes findText() restart from the beginning of the document if the end + was reached and the text was not found. +*/ + +/*! + \enum QWebPage::LinkDelegationPolicy + + This enum defines the delegation policies a webpage can have when activating links and emitting + the linkClicked() signal. + + \value DontDelegateLinks No links are delegated. Instead, QWebPage tries to handle them all. + \value DelegateExternalLinks When activating links that point to documents not stored on the + local filesystem or an equivalent - such as the Qt resource system - then linkClicked() is emitted. + \value DelegateAllLinks Whenever a link is activated the linkClicked() signal is emitted. +*/ + +/*! + \enum QWebPage::NavigationType + + This enum describes the types of navigation available when browsing through hyperlinked + documents. + + \value NavigationTypeLinkClicked The user clicked on a link or pressed return on a focused link. + \value NavigationTypeFormSubmitted The user activated a submit button for an HTML form. + \value NavigationTypeBackOrForward Navigation to a previously shown document in the back or forward history is requested. + \value NavigationTypeReload The user activated the reload action. + \value NavigationTypeFormResubmitted An HTML form was submitted a second time. + \value NavigationTypeOther A navigation to another document using a method not listed above. +*/ + +/*! + \enum QWebPage::WebAction + + \value NoWebAction No action is triggered. + \value OpenLink Open the current link. + \value OpenLinkInNewWindow Open the current link in a new window. + \value OpenFrameInNewWindow Replicate the current frame in a new window. + \value DownloadLinkToDisk Download the current link to the disk. + \value CopyLinkToClipboard Copy the current link to the clipboard. + \value OpenImageInNewWindow Open the highlighted image in a new window. + \value DownloadImageToDisk Download the highlighted image to the disk. + \value CopyImageToClipboard Copy the highlighted image to the clipboard. + \value Back Navigate back in the history of navigated links. + \value Forward Navigate forward in the history of navigated links. + \value Stop Stop loading the current page. + \value Reload Reload the current page. + \value Cut Cut the content currently selected into the clipboard. + \value Copy Copy the content currently selected into the clipboard. + \value Paste Paste content from the clipboard. + \value Undo Undo the last editing action. + \value Redo Redo the last editing action. + \value MoveToNextChar Move the cursor to the next character. + \value MoveToPreviousChar Move the cursor to the previous character. + \value MoveToNextWord Move the cursor to the next word. + \value MoveToPreviousWord Move the cursor to the previous word. + \value MoveToNextLine Move the cursor to the next line. + \value MoveToPreviousLine Move the cursor to the previous line. + \value MoveToStartOfLine Move the cursor to the start of the line. + \value MoveToEndOfLine Move the cursor to the end of the line. + \value MoveToStartOfBlock Move the cursor to the start of the block. + \value MoveToEndOfBlock Move the cursor to the end of the block. + \value MoveToStartOfDocument Move the cursor to the start of the document. + \value MoveToEndOfDocument Move the cursor to the end of the document. + \value SelectNextChar Select to the next character. + \value SelectPreviousChar Select to the previous character. + \value SelectNextWord Select to the next word. + \value SelectPreviousWord Select to the previous word. + \value SelectNextLine Select to the next line. + \value SelectPreviousLine Select to the previous line. + \value SelectStartOfLine Select to the start of the line. + \value SelectEndOfLine Select to the end of the line. + \value SelectStartOfBlock Select to the start of the block. + \value SelectEndOfBlock Select to the end of the block. + \value SelectStartOfDocument Select to the start of the document. + \value SelectEndOfDocument Select to the end of the document. + \value DeleteStartOfWord Delete to the start of the word. + \value DeleteEndOfWord Delete to the end of the word. + \value SetTextDirectionDefault Set the text direction to the default direction. + \value SetTextDirectionLeftToRight Set the text direction to left-to-right. + \value SetTextDirectionRightToLeft Set the text direction to right-to-left. + \value ToggleBold Toggle the formatting between bold and normal weight. + \value ToggleItalic Toggle the formatting between italic and normal style. + \value ToggleUnderline Toggle underlining. + \value InspectElement Show the Web Inspector with the currently highlighted HTML element. + \value InsertParagraphSeparator Insert a new paragraph. + \value InsertLineSeparator Insert a new line. + \omitvalue WebActionCount + +*/ + +/*! + \enum QWebPage::WebWindowType + + \value WebBrowserWindow The window is a regular web browser window. + \value WebModalDialog The window acts as modal dialog. +*/ + +/*! + \class QWebPage + \since 4.4 + \brief The QWebPage class provides an object to view and edit web documents. + + QWebPage holds a main frame responsible for web content, settings, the history + of navigated links and actions. This class can be used, together with QWebFrame, + to provide functionality like QWebView in a widget-less environment. + + QWebPage's API is very similar to QWebView, as you are still provided with + common functions like action() (known as \l{QWebView::}{pageAction()} in + QWebView), triggerAction(), findText() and settings(). More QWebView-like + functions can be found in the main frame of QWebPage, obtained via + QWebPage::mainFrame(). For example, the load(), setUrl() and setHtml() + unctions for QWebPage can be accessed using QWebFrame. + + The loadStarted() signal is emitted when the page begins to load.The + loadProgress() signal, on the other hand, is emitted whenever an element + of the web page completes loading, such as an embedded image, a script, + etc. Finally, the loadFinished() signal is emitted when the page has + loaded completely. Its argument, either true or false, indicates whether + or not the load operation succeeded. + + \section1 Using QWebPage in a Widget-less Environment + + Before you begin painting a QWebPage object, you need to set the size of + the viewport by calling setViewportSize(). Then, you invoke the main + frame's render function (QWebFrame::render()). An example of this + is shown in the code snippet below. + + Suppose we have a \c Thumbnail class as follows: + + \snippet doc/src/snippets/webkit/webpage/main.cpp 0 + + The \c Thumbnail's constructor takes in a \a url. We connect our QWebPage + object's \l{QWebPage::}{loadFinished()} signal to our private slot, + \c render(). + + \snippet doc/src/snippets/webkit/webpage/main.cpp 1 + + The \c render() function shows how we can paint a thumbnail using a + QWebPage object. + + \snippet doc/src/snippets/webkit/webpage/main.cpp 2 + + We begin by setting the \l{QWebPage::viewportSize()}{viewportSize} and + then we instantiate a QImage object, \c image, with the same size as our + \l{QWebPage::viewportSize()}{viewportSize}. This image is then sent + as a parameter to \c painter. Next, we render the contents of the main + frame and its subframes into \c painter. Finally, we save the scaled image. + + \sa QWebFrame +*/ + +/*! + Constructs an empty QWebView with parent \a parent. +*/ +QWebPage::QWebPage(QObject *parent) + : QObject(parent) + , d(new QWebPagePrivate(this)) +{ + setView(qobject_cast<QWidget *>(parent)); + + connect(this, SIGNAL(loadProgress(int)), this, SLOT(_q_onLoadProgressChanged(int))); +} + +/*! + Destroys the web page. +*/ +QWebPage::~QWebPage() +{ + FrameLoader *loader = d->mainFrame->d->frame->loader(); + if (loader) + loader->detachFromParent(); + delete d; +} + +/*! + Returns the main frame of the page. + + The main frame provides access to the hierarchy of sub-frames and is also needed if you + want to explicitly render a web page into a given painter. + + \sa currentFrame() +*/ +QWebFrame *QWebPage::mainFrame() const +{ + d->createMainFrame(); + return d->mainFrame; +} + +/*! + Returns the frame currently active. + + \sa mainFrame(), frameCreated() +*/ +QWebFrame *QWebPage::currentFrame() const +{ + return static_cast<WebCore::FrameLoaderClientQt *>(d->page->focusController()->focusedOrMainFrame()->loader()->client())->webFrame(); +} + +/*! + Returns a pointer to the view's history of navigated web pages. +*/ +QWebHistory *QWebPage::history() const +{ + return &d->history; +} + +/*! + Sets the \a view that is associated with the web page. + + \sa view() +*/ +void QWebPage::setView(QWidget *view) +{ + d->view = view; + setViewportSize(view ? view->size() : QSize(0, 0)); +} + +/*! + Returns the view widget that is associated with the web page. + + \sa setView() +*/ +QWidget *QWebPage::view() const +{ + return d->view; +} + +/*! + This function is called whenever a JavaScript program tries to print a \a message to the web browser's console. + + For example in case of evaluation errors the source URL may be provided in \a sourceID as well as the \a lineNumber. + + The default implementation prints nothing. +*/ +void QWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID) +{ + Q_UNUSED(message) + Q_UNUSED(lineNumber) + Q_UNUSED(sourceID) +} + +/*! + This function is called whenever a JavaScript program running inside \a frame calls the alert() function with + the message \a msg. + + The default implementation shows the message, \a msg, with QMessageBox::information. +*/ +void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg) +{ +#ifndef QT_NO_MESSAGEBOX + QMessageBox::information(d->view, mainFrame()->title(), msg, QMessageBox::Ok); +#endif +} + +/*! + This function is called whenever a JavaScript program running inside \a frame calls the confirm() function + with the message, \a msg. Returns true if the user confirms the message; otherwise returns false. + + The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons. +*/ +bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg) +{ +#ifdef QT_NO_MESSAGEBOX + return true; +#else + return QMessageBox::Yes == QMessageBox::information(d->view, mainFrame()->title(), msg, QMessageBox::Yes, QMessageBox::No); +#endif +} + +/*! + This function is called whenever a JavaScript program running inside \a frame tries to prompt the user for input. + The program may provide an optional message, \a msg, as well as a default value for the input in \a defaultValue. + + If the prompt was cancelled by the user the implementation should return false; otherwise the + result should be written to \a result and true should be returned. + + The default implementation uses QInputDialog::getText. +*/ +bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result) +{ + bool ok = false; +#ifndef QT_NO_INPUTDIALOG + QString x = QInputDialog::getText(d->view, mainFrame()->title(), msg, QLineEdit::Normal, defaultValue, &ok); + if (ok && result) { + *result = x; + } +#endif + return ok; +} + +/*! + This function is called whenever WebKit wants to create a new window of the given \a type, for + example when a JavaScript program requests to open a document in a new window. + + If the new window can be created, the new window's QWebPage is returned; otherwise a null pointer is returned. + + If the view associated with the web page is a QWebView object, then the default implementation forwards + the request to QWebView's createWindow() function; otherwise it returns a null pointer. + + \sa acceptNavigationRequest() +*/ +QWebPage *QWebPage::createWindow(WebWindowType type) +{ + QWebView *webView = qobject_cast<QWebView *>(d->view); + if (webView) { + QWebView *newView = webView->createWindow(type); + if (newView) + return newView->page(); + } + return 0; +} + +/*! + This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin". + The \a classid, \a url, \a paramNames and \a paramValues correspond to the HTML object element attributes and + child elements to configure the embeddable object. +*/ +QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues) +{ + Q_UNUSED(classid) + Q_UNUSED(url) + Q_UNUSED(paramNames) + Q_UNUSED(paramValues) + return 0; +} + +static WebCore::FrameLoadRequest frameLoadRequest(const QUrl &url, WebCore::Frame *frame) +{ + WebCore::ResourceRequest rr(url, frame->loader()->outgoingReferrer()); + return WebCore::FrameLoadRequest(rr); +} + +static void openNewWindow(const QUrl& url, WebCore::Frame* frame) +{ + if (Page* oldPage = frame->page()) { + WindowFeatures features; + if (Page* newPage = oldPage->chrome()->createWindow(frame, + frameLoadRequest(url, frame), features)) + newPage->chrome()->show(); + } +} + +/*! + This function can be called to trigger the specified \a action. + It is also called by QtWebKit if the user triggers the action, for example + through a context menu item. + + If \a action is a checkable action then \a checked specified whether the action + is toggled or not. + + \sa action() +*/ +void QWebPage::triggerAction(WebAction action, bool checked) +{ + WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame(); + if (!frame) + return; + WebCore::Editor *editor = frame->editor(); + const char *command = 0; + + switch (action) { + case OpenLink: + if (QWebFrame *targetFrame = d->hitTestResult.linkTargetFrame()) { + WTF::RefPtr<WebCore::Frame> wcFrame = targetFrame->d->frame; + targetFrame->d->frame->loader()->loadFrameRequestWithFormAndValues(frameLoadRequest(d->hitTestResult.linkUrl(), wcFrame.get()), + /*lockHistory*/ false, /*event*/ 0, + /*HTMLFormElement*/ 0, /*formValues*/ + WTF::HashMap<String, String>()); + break; + } + // fall through + case OpenLinkInNewWindow: + openNewWindow(d->hitTestResult.linkUrl(), frame); + break; + case OpenFrameInNewWindow: { + KURL url = frame->loader()->documentLoader()->unreachableURL(); + if (url.isEmpty()) + url = frame->loader()->documentLoader()->url(); + openNewWindow(url, frame); + break; + } + case CopyLinkToClipboard: + editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText()); + break; + case OpenImageInNewWindow: + openNewWindow(d->hitTestResult.imageUrl(), frame); + break; + case DownloadImageToDisk: + frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.imageUrl(), frame->loader()->outgoingReferrer())); + break; + case DownloadLinkToDisk: + frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.linkUrl(), frame->loader()->outgoingReferrer())); + break; +#ifndef QT_NO_CLIPBOARD + case CopyImageToClipboard: + QApplication::clipboard()->setPixmap(d->hitTestResult.pixmap()); + break; +#endif + case Back: + d->page->goBack(); + break; + case Forward: + d->page->goForward(); + break; + case Stop: + mainFrame()->d->frame->loader()->stopForUserCancel(); + break; + case Reload: + mainFrame()->d->frame->loader()->reload(); + break; + case SetTextDirectionDefault: + editor->setBaseWritingDirection(NaturalWritingDirection); + break; + case SetTextDirectionLeftToRight: + editor->setBaseWritingDirection(LeftToRightWritingDirection); + break; + case SetTextDirectionRightToLeft: + editor->setBaseWritingDirection(RightToLeftWritingDirection); + break; + case InspectElement: + d->page->inspectorController()->inspect(d->hitTestResult.d->innerNonSharedNode.get()); + break; + default: + command = editorCommandForWebActions(action); + break; + } + + if (command) + editor->command(command).execute(); +} + +QSize QWebPage::viewportSize() const +{ + if (d->mainFrame && d->mainFrame->d->frame->view()) + return d->mainFrame->d->frame->view()->frameRect().size(); + + return d->viewportSize; +} + +/*! + \property QWebPage::viewportSize + \brief the size of the viewport + + The size affects for example the visibility of scrollbars + if the document is larger than the viewport. + + By default, for a newly-created Web page, this property contains a size with + zero width and height. +*/ +void QWebPage::setViewportSize(const QSize &size) const +{ + d->viewportSize = size; + + QWebFrame *frame = mainFrame(); + if (frame->d->frame && frame->d->frame->view()) { + WebCore::FrameView* view = frame->d->frame->view(); + view->setFrameRect(QRect(QPoint(0, 0), size)); + frame->d->frame->forceLayout(); + view->adjustViewSize(); + } +} + + +/*! + \fn bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type) + + This function is called whenever WebKit requests to navigate \a frame to the resource specified by \a request by means of + the specified navigation type \a type. + + If \a frame is a null pointer then navigation to a new window is requested. If the request is + accepted createWindow() will be called. + + The default implementation interprets the page's linkDelegationPolicy and emits linkClicked accordingly or returns true + to let QWebPage handle the navigation itself. + + \sa createWindow() +*/ +#if QT_VERSION >= 0x040400 +bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type) +#else +bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type) +#endif +{ + if (type == NavigationTypeLinkClicked) { + switch (d->linkPolicy) { + case DontDelegateLinks: + return true; + + case DelegateExternalLinks: + if (WebCore::FrameLoader::shouldTreatSchemeAsLocal(request.url().scheme())) + return true; + emit linkClicked(request.url()); + return false; + + case DelegateAllLinks: + emit linkClicked(request.url()); + return false; + } + } + return true; +} + +/*! + \property QWebPage::selectedText + \brief the text currently selected + + By default, this property contains an empty string. + + \sa selectionChanged() +*/ +QString QWebPage::selectedText() const +{ + return d->page->focusController()->focusedOrMainFrame()->selectedText(); +} + +/*! + Returns a QAction for the specified WebAction \a action. + + The action is owned by the QWebPage but you can customize the look by + changing its properties. + + QWebPage also takes care of implementing the action, so that upon + triggering the corresponding action is performed on the page. + + \sa triggerAction() +*/ +QAction *QWebPage::action(WebAction action) const +{ + if (action == QWebPage::NoWebAction) return 0; + if (d->actions[action]) + return d->actions[action]; + + QString text; + QIcon icon; + QStyle *style = view() ? view()->style() : qApp->style(); + bool checkable = false; + + switch (action) { + case OpenLink: + text = contextMenuItemTagOpenLink(); + break; + case OpenLinkInNewWindow: + text = contextMenuItemTagOpenLinkInNewWindow(); + break; + case OpenFrameInNewWindow: + text = contextMenuItemTagOpenFrameInNewWindow(); + break; + + case DownloadLinkToDisk: + text = contextMenuItemTagDownloadLinkToDisk(); + break; + case CopyLinkToClipboard: + text = contextMenuItemTagCopyLinkToClipboard(); + break; + + case OpenImageInNewWindow: + text = contextMenuItemTagOpenImageInNewWindow(); + break; + case DownloadImageToDisk: + text = contextMenuItemTagDownloadImageToDisk(); + break; + case CopyImageToClipboard: + text = contextMenuItemTagCopyImageToClipboard(); + break; + + case Back: + text = contextMenuItemTagGoBack(); +#if QT_VERSION >= 0x040400 + icon = style->standardIcon(QStyle::SP_ArrowBack); +#endif + break; + case Forward: + text = contextMenuItemTagGoForward(); +#if QT_VERSION >= 0x040400 + icon = style->standardIcon(QStyle::SP_ArrowForward); +#endif + break; + case Stop: + text = contextMenuItemTagStop(); +#if QT_VERSION >= 0x040400 + icon = style->standardIcon(QStyle::SP_BrowserStop); +#endif + break; + case Reload: + text = contextMenuItemTagReload(); +#if QT_VERSION >= 0x040400 + icon = style->standardIcon(QStyle::SP_BrowserReload); +#endif + break; + + case Cut: + text = contextMenuItemTagCut(); + break; + case Copy: + text = contextMenuItemTagCopy(); + break; + case Paste: + text = contextMenuItemTagPaste(); + break; +#ifndef QT_NO_UNDOSTACK + case Undo: { + QAction *a = undoStack()->createUndoAction(d->q); + d->actions[action] = a; + return a; + } + case Redo: { + QAction *a = undoStack()->createRedoAction(d->q); + d->actions[action] = a; + return a; + } +#endif // QT_NO_UNDOSTACK + case MoveToNextChar: + case MoveToPreviousChar: + case MoveToNextWord: + case MoveToPreviousWord: + case MoveToNextLine: + case MoveToPreviousLine: + case MoveToStartOfLine: + case MoveToEndOfLine: + case MoveToStartOfBlock: + case MoveToEndOfBlock: + case MoveToStartOfDocument: + case MoveToEndOfDocument: + case SelectNextChar: + case SelectPreviousChar: + case SelectNextWord: + case SelectPreviousWord: + case SelectNextLine: + case SelectPreviousLine: + case SelectStartOfLine: + case SelectEndOfLine: + case SelectStartOfBlock: + case SelectEndOfBlock: + case SelectStartOfDocument: + case SelectEndOfDocument: + case DeleteStartOfWord: + case DeleteEndOfWord: + break; // #### + + case SetTextDirectionDefault: + text = contextMenuItemTagDefaultDirection(); + break; + case SetTextDirectionLeftToRight: + text = contextMenuItemTagLeftToRight(); + checkable = true; + break; + case SetTextDirectionRightToLeft: + text = contextMenuItemTagRightToLeft(); + checkable = true; + break; + + case ToggleBold: + text = contextMenuItemTagBold(); + checkable = true; + break; + case ToggleItalic: + text = contextMenuItemTagItalic(); + checkable = true; + break; + case ToggleUnderline: + text = contextMenuItemTagUnderline(); + checkable = true; + break; + + case InspectElement: + text = contextMenuItemTagInspectElement(); + break; + + case NoWebAction: + return 0; + } + + if (text.isEmpty()) + return 0; + + QAction *a = new QAction(d->q); + a->setText(text); + a->setData(action); + a->setCheckable(checkable); + a->setIcon(icon); + + connect(a, SIGNAL(triggered(bool)), + this, SLOT(_q_webActionTriggered(bool))); + + d->actions[action] = a; + d->updateAction(action); + return a; +} + +/*! + \property QWebPage::modified + \brief whether the page contains unsubmitted form data + + By default, this property is false. +*/ +bool QWebPage::isModified() const +{ +#ifdef QT_NO_UNDOSTACK + return false; +#else + if (!d->undoStack) + return false; + return d->undoStack->canUndo(); +#endif // QT_NO_UNDOSTACK +} + +#ifndef QT_NO_UNDOSTACK +/*! + Returns a pointer to the undo stack used for editable content. +*/ +QUndoStack *QWebPage::undoStack() const +{ + if (!d->undoStack) + d->undoStack = new QUndoStack(const_cast<QWebPage *>(this)); + + return d->undoStack; +} +#endif // QT_NO_UNDOSTACK + +/*! \reimp +*/ +bool QWebPage::event(QEvent *ev) +{ + switch (ev->type()) { + case QEvent::Timer: + d->timerEvent(static_cast<QTimerEvent*>(ev)); + break; + case QEvent::MouseMove: + d->mouseMoveEvent(static_cast<QMouseEvent*>(ev)); + break; + case QEvent::MouseButtonPress: + d->mousePressEvent(static_cast<QMouseEvent*>(ev)); + break; + case QEvent::MouseButtonDblClick: + d->mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev)); + break; + case QEvent::MouseButtonRelease: + d->mouseReleaseEvent(static_cast<QMouseEvent*>(ev)); + break; +#ifndef QT_NO_CONTEXTMENU + case QEvent::ContextMenu: + d->contextMenuEvent(static_cast<QContextMenuEvent*>(ev)); + break; +#endif +#ifndef QT_NO_WHEELEVENT + case QEvent::Wheel: + d->wheelEvent(static_cast<QWheelEvent*>(ev)); + break; +#endif + case QEvent::KeyPress: + d->keyPressEvent(static_cast<QKeyEvent*>(ev)); + break; + case QEvent::KeyRelease: + d->keyReleaseEvent(static_cast<QKeyEvent*>(ev)); + break; + case QEvent::FocusIn: + d->focusInEvent(static_cast<QFocusEvent*>(ev)); + break; + case QEvent::FocusOut: + d->focusOutEvent(static_cast<QFocusEvent*>(ev)); + break; +#ifndef QT_NO_DRAGANDDROP + case QEvent::DragEnter: + d->dragEnterEvent(static_cast<QDragEnterEvent*>(ev)); + break; + case QEvent::DragLeave: + d->dragLeaveEvent(static_cast<QDragLeaveEvent*>(ev)); + break; + case QEvent::DragMove: + d->dragMoveEvent(static_cast<QDragMoveEvent*>(ev)); + break; + case QEvent::Drop: + d->dropEvent(static_cast<QDropEvent*>(ev)); + break; +#endif + case QEvent::InputMethod: + d->inputMethodEvent(static_cast<QInputMethodEvent*>(ev)); + case QEvent::ShortcutOverride: + d->shortcutOverrideEvent(static_cast<QKeyEvent*>(ev)); + break; + case QEvent::Leave: + d->leaveEvent(ev); + break; + default: + return QObject::event(ev); + } + + return true; +} + +/*! + Similar to QWidget::focusNextPrevChild it focuses the next focusable web element + if \a next is true; otherwise the previous element is focused. + + Returns true if it can find a new focusable element, or false if it can't. +*/ +bool QWebPage::focusNextPrevChild(bool next) +{ + QKeyEvent ev(QEvent::KeyPress, Qt::Key_Tab, Qt::KeyboardModifiers(next ? Qt::NoModifier : Qt::ShiftModifier)); + d->keyPressEvent(&ev); + bool hasFocusedNode = false; + Frame *frame = d->page->focusController()->focusedFrame(); + if (frame) { + Document *document = frame->document(); + hasFocusedNode = document && document->focusedNode(); + } + //qDebug() << "focusNextPrevChild(" << next << ") =" << ev.isAccepted() << "focusedNode?" << hasFocusedNode; + return hasFocusedNode; +} + +/*! + \property QWebPage::editable + \brief whether the content in this QWebPage is editable or not + \since 4.5 + + If this property is enabled the contents of the page can be edited by the user through a visible + cursor. If disabled (the default) only HTML elements in the web page with their + \c{contenteditable} attribute set are editable. +*/ +void QWebPage::setEditable(bool editable) +{ + if (d->editable != editable) { + d->editable = editable; + d->page->setTabKeyCyclesThroughElements(!editable); + if (d->mainFrame) { + WebCore::Frame* frame = d->mainFrame->d->frame; + if (editable) { + frame->applyEditingStyleToBodyElement(); + // FIXME: mac port calls this if there is no selectedDOMRange + //frame->setSelectionFromNone(); + } else { + frame->removeEditingStyleFromBodyElement(); + } + } + + d->updateEditorActions(); + } +} + +bool QWebPage::isEditable() const +{ + return d->editable; +} + +/*! + \property QWebPage::forwardUnsupportedContent + \brief whether QWebPage should forward unsupported content through the + unsupportedContent signal + + If disabled the download of such content is aborted immediately. + + By default unsupported content is not forwarded. +*/ + +void QWebPage::setForwardUnsupportedContent(bool forward) +{ + d->forwardUnsupportedContent = forward; +} + +bool QWebPage::forwardUnsupportedContent() const +{ + return d->forwardUnsupportedContent; +} + +/*! + \property QWebPage::linkDelegationPolicy + \brief how QWebPage should delegate the handling of links through the + linkClicked() signal + + The default is to delegate no links. +*/ + +void QWebPage::setLinkDelegationPolicy(LinkDelegationPolicy policy) +{ + d->linkPolicy = policy; +} + +QWebPage::LinkDelegationPolicy QWebPage::linkDelegationPolicy() const +{ + return d->linkPolicy; +} + +#ifndef QT_NO_CONTEXTMENU +/*! + Filters the context menu event, \a event, through handlers for scrollbars and + custom event handlers in the web page. Returns true if the event was handled; + otherwise false. + + A web page may swallow a context menu event through a custom event handler, allowing for context + menus to be implemented in HTML/JavaScript. This is used by \l{http://maps.google.com/}{Google + Maps}, for example. +*/ +bool QWebPage::swallowContextMenuEvent(QContextMenuEvent *event) +{ + d->page->contextMenuController()->clearContextMenu(); + + if (QWebFrame* webFrame = d->frameAt(event->pos())) { + Frame* frame = QWebFramePrivate::core(webFrame); + if (Scrollbar* scrollbar = frame->view()->scrollbarUnderMouse(PlatformMouseEvent(event, 1))) { + return scrollbar->contextMenu(PlatformMouseEvent(event, 1)); + } + } + + WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame(); + focusedFrame->eventHandler()->sendContextMenuEvent(PlatformMouseEvent(event, 1)); + ContextMenu *menu = d->page->contextMenuController()->contextMenu(); + // If the website defines its own handler then sendContextMenuEvent takes care of + // calling/showing it and the context menu pointer will be zero. This is the case + // on maps.google.com for example. + + return !menu; +} +#endif // QT_NO_CONTEXTMENU + +/*! + Updates the page's actions depending on the position \a pos. For example if \a pos is over an image + element the CopyImageToClipboard action is enabled. +*/ +void QWebPage::updatePositionDependentActions(const QPoint &pos) +{ + // First we disable all actions, but keep track of which ones were originally enabled. + QBitArray originallyEnabledWebActions(QWebPage::WebActionCount); + for (int i = ContextMenuItemTagNoAction; i < ContextMenuItemBaseApplicationTag; ++i) { + QWebPage::WebAction action = webActionForContextMenuAction(WebCore::ContextMenuAction(i)); + if (QAction *a = this->action(action)) { + originallyEnabledWebActions.setBit(action, a->isEnabled()); + a->setEnabled(false); + } + } + + WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame(); + HitTestResult result = focusedFrame->eventHandler()->hitTestResultAtPoint(focusedFrame->view()->windowToContents(pos), /*allowShadowContent*/ false); + + d->hitTestResult = QWebHitTestResult(new QWebHitTestResultPrivate(result)); + WebCore::ContextMenu menu(result); + menu.populate(); + if (d->page->inspectorController()->enabled()) + menu.addInspectElementItem(); + + QBitArray visitedWebActions(QWebPage::WebActionCount); + +#ifndef QT_NO_CONTEXTMENU + delete d->currentContextMenu; + + // Then we let createContextMenu() enable the actions that are put into the menu + d->currentContextMenu = d->createContextMenu(&menu, menu.platformDescription(), &visitedWebActions); +#endif // QT_NO_CONTEXTMENU + + // Finally, we restore the original enablement for the actions that were not put into the menu. + originallyEnabledWebActions &= ~visitedWebActions; // Mask out visited actions (they're part of the menu) + for (int i = 0; i < QWebPage::WebActionCount; ++i) { + if (originallyEnabledWebActions.at(i)) { + if (QAction *a = this->action(QWebPage::WebAction(i))) { + a->setEnabled(true); + } + } + } + + // This whole process ensures that any actions put into to the context menu has the right + // enablement, while also keeping the correct enablement for actions that were left out of + // the menu. + +} + + + +/*! + \enum QWebPage::Extension + + This enum describes the types of extensions that the page can support. Before using these extensions, you + should verify that the extension is supported by calling supportsExtension(). + + Currently there are no extensions. +*/ + +/*! + \class QWebPage::ExtensionOption + \since 4.4 + \brief The ExtensionOption class provides an extended input argument to QWebPage's extension support. + + \sa QWebPage::extension() +*/ + +/*! + \class QWebPage::ExtensionReturn + \since 4.4 + \brief The ExtensionOption class provides an extended output argument to QWebPage's extension support. + + \sa QWebPage::extension() +*/ + +/*! + This virtual function can be reimplemented in a QWebPage subclass to provide support for extensions. The \a option + argument is provided as input to the extension; the output results can be stored in \a output. + + The behavior of this function is determined by \a extension. + + You can call supportsExtension() to check if an extension is supported by the page. + + By default, no extensions are supported, and this function returns false. + + \sa supportsExtension(), Extension +*/ +bool QWebPage::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output) +{ + Q_UNUSED(extension) + Q_UNUSED(option) + Q_UNUSED(output) + return false; +} + +/*! + This virtual function returns true if the web page supports \a extension; otherwise false is returned. + + \sa extension() +*/ +bool QWebPage::supportsExtension(Extension extension) const +{ + Q_UNUSED(extension) + return false; +} + +/*! + Finds the next occurrence of the string, \a subString, in the page, using the given \a options. + Returns true of \a subString was found and selects the match visually; otherwise returns false. +*/ +bool QWebPage::findText(const QString &subString, FindFlags options) +{ + ::TextCaseSensitivity caseSensitivity = ::TextCaseInsensitive; + if (options & FindCaseSensitively) + caseSensitivity = ::TextCaseSensitive; + + ::FindDirection direction = ::FindDirectionForward; + if (options & FindBackward) + direction = ::FindDirectionBackward; + + const bool shouldWrap = options & FindWrapsAroundDocument; + + return d->page->findString(subString, caseSensitivity, direction, shouldWrap); +} + +/*! + Returns a pointer to the page's settings object. + + \sa QWebSettings::globalSettings() +*/ +QWebSettings *QWebPage::settings() const +{ + return d->settings; +} + +/*! + This function is called when the web content requests a file name, for example + as a result of the user clicking on a "file upload" button in a HTML form. + + A suggested filename may be provided in \a suggestedFile. The frame originating the + request is provided as \a parentFrame. +*/ +QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& suggestedFile) +{ +#ifndef QT_NO_FILEDIALOG + return QFileDialog::getOpenFileName(d->view, QString::null, suggestedFile); +#else + return QString::null; +#endif +} + +#if QT_VERSION < 0x040400 && !defined qdoc + +void QWebPage::setNetworkInterface(QWebNetworkInterface *interface) +{ + d->networkInterface = interface; +} + +QWebNetworkInterface *QWebPage::networkInterface() const +{ + if (d->networkInterface) + return d->networkInterface; + else + return QWebNetworkInterface::defaultInterface(); +} + +#ifndef QT_NO_NETWORKPROXY +void QWebPage::setNetworkProxy(const QNetworkProxy& proxy) +{ + d->networkProxy = proxy; +} + +QNetworkProxy QWebPage::networkProxy() const +{ + return d->networkProxy; +} +#endif + +#else + +/*! + Sets the QNetworkAccessManager \a manager responsible for serving network requests for this + QWebPage. + + \sa networkAccessManager() +*/ +void QWebPage::setNetworkAccessManager(QNetworkAccessManager *manager) +{ + if (manager == d->networkManager) + return; + if (d->networkManager && d->networkManager->parent() == this) + delete d->networkManager; + d->networkManager = manager; +} + +/*! + Returns the QNetworkAccessManager that is responsible for serving network + requests for this QWebPage. + + \sa setNetworkAccessManager() +*/ +QNetworkAccessManager *QWebPage::networkAccessManager() const +{ + if (!d->networkManager) { + QWebPage *that = const_cast<QWebPage *>(this); + that->d->networkManager = new QNetworkAccessManager(that); + } + return d->networkManager; +} + +#endif + +/*! + Sets the QWebPluginFactory \a factory responsible for creating plugins embedded into this + QWebPage. + + Note: The plugin factory is only used if the QWebSettings::PluginsEnabled attribute is enabled. + + \sa pluginFactory() +*/ +void QWebPage::setPluginFactory(QWebPluginFactory *factory) +{ + d->pluginFactory = factory; +} + +/*! + Returns the QWebPluginFactory that is responsible for creating plugins embedded into + this QWebPage. If no plugin factory is installed a null pointer is returned. + + \sa setPluginFactory() +*/ +QWebPluginFactory *QWebPage::pluginFactory() const +{ + return d->pluginFactory; +} + +/*! + This function is called when a user agent for HTTP requests is needed. You can re-implement this + function to dynamically return different user agent's for different urls, based on the \a url parameter. + + The default implementation returns the following value: + + "Mozilla/5.0 (%Platform%; %Security%; %Subplatform%; %Locale%) AppleWebKit/%WebKitVersion% (KHTML, like Gecko, Safari/419.3) %AppVersion" + + In this string the following values are replaced at run-time: + \list + \o %Platform% and %Subplatform% are expanded to the windowing system and the operation system. + \o %Security% expands to U if SSL is enabled, otherwise N. SSL is enabled if QSslSocket::supportsSsl() returns true. + \o %Locale% is replaced with QLocale::name(). + \o %WebKitVersion% currently expands to 527+ + \o %AppVersion% expands to QCoreApplication::applicationName()/QCoreApplication::applicationVersion() if they're set; otherwise defaulting to Qt and the current Qt version. + \endlist +*/ +QString QWebPage::userAgentForUrl(const QUrl& url) const +{ + Q_UNUSED(url) + QString ua = QLatin1String("Mozilla/5.0 (" + + // Plastform +#ifdef Q_WS_MAC + "Macintosh" +#elif defined Q_WS_QWS + "QtEmbedded" +#elif defined Q_WS_WIN + "Windows" +#elif defined Q_WS_X11 + "X11" +#else + "Unknown" +#endif + "; " + + // Placeholder for security strength (N or U) + "%1; " + + // Subplatform" +#ifdef Q_OS_AIX + "AIX" +#elif defined Q_OS_WIN32 + "%2" +#elif defined Q_OS_DARWIN +#ifdef __i386__ || __x86_64__ + "Intel Mac OS X" +#else + "PPC Mac OS X" +#endif + +#elif defined Q_OS_BSDI + "BSD" +#elif defined Q_OS_BSD4 + "BSD Four" +#elif defined Q_OS_CYGWIN + "Cygwin" +#elif defined Q_OS_DGUX + "DG/UX" +#elif defined Q_OS_DYNIX + "DYNIX/ptx" +#elif defined Q_OS_FREEBSD + "FreeBSD" +#elif defined Q_OS_HPUX + "HP-UX" +#elif defined Q_OS_HURD + "GNU Hurd" +#elif defined Q_OS_IRIX + "SGI Irix" +#elif defined Q_OS_LINUX + "Linux" +#elif defined Q_OS_LYNX + "LynxOS" +#elif defined Q_OS_NETBSD + "NetBSD" +#elif defined Q_OS_OS2 + "OS/2" +#elif defined Q_OS_OPENBSD + "OpenBSD" +#elif defined Q_OS_OS2EMX + "OS/2" +#elif defined Q_OS_OSF + "HP Tru64 UNIX" +#elif defined Q_OS_QNX6 + "QNX RTP Six" +#elif defined Q_OS_QNX + "QNX" +#elif defined Q_OS_RELIANT + "Reliant UNIX" +#elif defined Q_OS_SCO + "SCO OpenServer" +#elif defined Q_OS_SOLARIS + "Sun Solaris" +#elif defined Q_OS_ULTRIX + "DEC Ultrix" +#elif defined Q_OS_UNIX + "UNIX BSD/SYSV system" +#elif defined Q_OS_UNIXWARE + "UnixWare Seven, Open UNIX Eight" +#else + "Unknown" +#endif + "; "); + + QChar securityStrength(QLatin1Char('N')); +#if !defined(QT_NO_OPENSSL) + if (QSslSocket::supportsSsl()) + securityStrength = QLatin1Char('U'); +#endif + ua = ua.arg(securityStrength); + +#if defined Q_OS_WIN32 + QString ver; + switch(QSysInfo::WindowsVersion) { + case QSysInfo::WV_32s: + ver = "Windows 3.1"; + break; + case QSysInfo::WV_95: + ver = "Windows 95"; + break; + case QSysInfo::WV_98: + ver = "Windows 98"; + break; + case QSysInfo::WV_Me: + ver = "Windows 98; Win 9x 4.90"; + break; + case QSysInfo::WV_NT: + ver = "WinNT4.0"; + break; + case QSysInfo::WV_2000: + ver = "Windows NT 5.0"; + break; + case QSysInfo::WV_XP: + ver = "Windows NT 5.1"; + break; + case QSysInfo::WV_2003: + ver = "Windows NT 5.2"; + break; + case QSysInfo::WV_VISTA: + ver = "Windows NT 6.0"; + break; + case QSysInfo::WV_CE: + ver = "Windows CE"; + break; + case QSysInfo::WV_CENET: + ver = "Windows CE .NET"; + break; + case QSysInfo::WV_CE_5: + ver = "Windows CE 5.x"; + break; + case QSysInfo::WV_CE_6: + ver = "Windows CE 6.x"; + break; + } + ua = QString(ua).arg(ver); +#endif + + // Language + QLocale locale; + if (d->view) + locale = d->view->locale(); + QString name = locale.name(); + name[2] = QLatin1Char('-'); + ua.append(name); + ua.append(QLatin1String(") ")); + + // webkit/qt version + ua.append(QLatin1String("AppleWebKit/" WEBKIT_VERSION " (KHTML, like Gecko, Safari/419.3) ")); + + // Application name/version + QString appName = QCoreApplication::applicationName(); + if (!appName.isEmpty()) { + ua.append(QLatin1Char(' ') + appName); +#if QT_VERSION >= 0x040400 + QString appVer = QCoreApplication::applicationVersion(); + if (!appVer.isEmpty()) + ua.append(QLatin1Char('/') + appVer); +#endif + } else { + // Qt version + ua.append(QLatin1String("Qt/")); + ua.append(QLatin1String(qVersion())); + } + return ua; +} + + +void QWebPagePrivate::_q_onLoadProgressChanged(int) { + m_totalBytes = page->progress()->totalPageAndResourceBytesToLoad(); + m_bytesReceived = page->progress()->totalBytesReceived(); +} + + +/*! + Returns the total number of bytes that were received from the network to render the current page, + including extra content such as embedded images. + + \sa bytesReceived() +*/ +quint64 QWebPage::totalBytes() const { + return d->m_bytesReceived; +} + + +/*! + Returns the number of bytes that were received from the network to render the current page. + + \sa totalBytes() +*/ +quint64 QWebPage::bytesReceived() const { + return d->m_totalBytes; +} + +/*! + \fn void QWebPage::loadStarted() + + This signal is emitted when a new load of the page is started. + + \sa loadFinished() +*/ + +/*! + \fn void QWebPage::loadProgress(int progress) + + This signal is emitted when the global progress status changes. + The current value is provided by \a progress and scales from 0 to 100, + which is the default range of QProgressBar. + It accumulates changes from all the child frames. + + \sa bytesReceived() +*/ + +/*! + \fn void QWebPage::loadFinished(bool ok) + + This signal is emitted when a load of the page is finished. + \a ok will indicate whether the load was successful or any error occurred. + + \sa loadStarted() +*/ + +/*! + \fn void QWebPage::linkHovered(const QString &link, const QString &title, const QString &textContent) + + This signal is emitted when the mouse is hovering over a link. + The first parameter is the \a link url, the second is the link \a title + if any, and third \a textContent is the text content. Method is emitter with both + empty parameters when the mouse isn't hovering over any link element. + + \sa linkClicked() +*/ + +/*! + \fn void QWebPage::statusBarMessage(const QString& text) + + This signal is emitted when the statusbar \a text is changed by the page. +*/ + +/*! + \fn void QWebPage::frameCreated(QWebFrame *frame) + + This signal is emitted whenever the page creates a new \a frame. +*/ + +/*! + \fn void QWebPage::selectionChanged() + + This signal is emitted whenever the selection changes. + + \sa selectedText() +*/ + +/*! + \fn void QWebPage::contentsChanged() + + This signal is emitted whenever the content changes during editing. + + \sa selectedText() +*/ + +/*! + \fn void QWebPage::geometryChangeRequested(const QRect& geom) + + This signal is emitted whenever the document wants to change the position and size of the + page to \a geom. This can happen for example through JavaScript. +*/ + +/*! + \fn void QWebPage::repaintRequested(const QRect& dirtyRect) + + This signal is emitted whenever this QWebPage should be updated and no view was set. + \a dirtyRect contains the area that needs to be updated. To paint the QWebPage get + the mainFrame() and call the render(QPainter*, const QRegion&) method with the + \a dirtyRect as the second parameter. + + \sa mainFrame() + \sa view() +*/ + +/*! + \fn void QWebPage::scrollRequested(int dx, int dy, const QRect& rectToScroll) + + This signal is emitted whenever the content given by \a rectToScroll needs + to be scrolled \a dx and \a dy downwards and no view was set. + + \sa view() +*/ + +/*! + \fn void QWebPage::windowCloseRequested() + + This signal is emitted whenever the page requests the web browser window to be closed, + for example through the JavaScript \c{window.close()} call. +*/ + +/*! + \fn void QWebPage::printRequested(QWebFrame *frame) + + This signal is emitted whenever the page requests the web browser to print \a frame, + for example through the JavaScript \c{window.print()} call. + + \sa QWebFrame::print(), QPrintPreviewDialog +*/ + +/*! + \fn void QWebPage::unsupportedContent(QNetworkReply *reply) + + This signals is emitted when webkit cannot handle a link the user navigated to. + + At signal emissions time the meta data of the QNetworkReply \a reply is available. + + \note This signal is only emitted if the forwardUnsupportedContent property is set to true. + + \sa downloadRequested() +*/ + +/*! + \fn void QWebPage::downloadRequested(const QNetworkRequest &request) + + This signal is emitted when the user decides to download a link. The url of + the link as well as additional meta-information is contained in \a request. + + \sa unsupportedContent() +*/ + +/*! + \fn void QWebPage::microFocusChanged() + + This signal is emitted when for example the position of the cursor in an editable form + element changes. It is used inform input methods about the new on-screen position where + the user is able to enter text. This signal is usually connected to QWidget's updateMicroFocus() + slot. +*/ + +/*! + \fn void QWebPage::linkClicked(const QUrl &url) + + This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy + property is set to delegate the link handling for the specified \a url. + + By default no links are delegated and are handled by QWebPage instead. + + \sa linkHovered() +*/ + +/*! + \fn void QWebPage::toolBarVisibilityChangeRequested(bool visible) + + This signal is emitted whenever the visibility of the toolbar in a web browser + window that hosts QWebPage should be changed to \a visible. +*/ + +/*! + \fn void QWebPage::statusBarVisibilityChangeRequested(bool visible) + + This signal is emitted whenever the visibility of the statusbar in a web browser + window that hosts QWebPage should be changed to \a visible. +*/ + +/*! + \fn void QWebPage::menuBarVisibilityChangeRequested(bool visible) + + This signal is emitted whenever the visibility of the menubar in a web browser + window that hosts QWebPage should be changed to \a visible. +*/ + +#include "moc_qwebpage.cpp" diff --git a/WebKit/qt/Api/qwebpage.h b/WebKit/qt/Api/qwebpage.h new file mode 100644 index 0000000..5b978d8 --- /dev/null +++ b/WebKit/qt/Api/qwebpage.h @@ -0,0 +1,312 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2007 Staikos Computing Services Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBPAGE_H +#define QWEBPAGE_H + +#include "qwebsettings.h" +#include "qwebkitglobal.h" + +#include <QtCore/qobject.h> +#include <QtGui/qwidget.h> + +QT_BEGIN_NAMESPACE +class QNetworkProxy; +class QUndoStack; +class QUrl; +class QMenu; +class QNetworkRequest; +class QNetworkReply; +class QNetworkAccessManager; +QT_END_NAMESPACE + +class QWebFrame; +class QWebNetworkRequest; +class QWebHistory; + +class QWebPagePrivate; +class QWebFrameData; +class QWebNetworkInterface; +class QWebPluginFactory; +class QWebHitTestResult; + +namespace WebCore { + class ChromeClientQt; + class EditorClientQt; + class FrameLoaderClientQt; + class FrameLoadRequest; + class InspectorClientQt; + class ResourceHandle; + class HitTestResult; +} + +class QWEBKIT_EXPORT QWebPage : public QObject +{ + Q_OBJECT + + Q_PROPERTY(bool modified READ isModified) + Q_PROPERTY(QString selectedText READ selectedText) + Q_PROPERTY(QSize viewportSize READ viewportSize WRITE setViewportSize) + Q_PROPERTY(bool forwardUnsupportedContent READ forwardUnsupportedContent WRITE setForwardUnsupportedContent) + Q_PROPERTY(LinkDelegationPolicy linkDelegationPolicy READ linkDelegationPolicy WRITE setLinkDelegationPolicy) + Q_PROPERTY(QPalette palette READ palette WRITE setPalette) + Q_PROPERTY(bool editable READ isEditable WRITE setEditable) + Q_ENUMS(LinkDelegationPolicy NavigationType WebAction) +public: + enum NavigationType { + NavigationTypeLinkClicked, + NavigationTypeFormSubmitted, + NavigationTypeBackOrForward, + NavigationTypeReload, + NavigationTypeFormResubmitted, + NavigationTypeOther + }; + + enum WebAction { + NoWebAction = - 1, + + OpenLink, + + OpenLinkInNewWindow, + OpenFrameInNewWindow, + + DownloadLinkToDisk, + CopyLinkToClipboard, + + OpenImageInNewWindow, + DownloadImageToDisk, + CopyImageToClipboard, + + Back, + Forward, + Stop, + Reload, + + Cut, + Copy, + Paste, + + Undo, + Redo, + MoveToNextChar, + MoveToPreviousChar, + MoveToNextWord, + MoveToPreviousWord, + MoveToNextLine, + MoveToPreviousLine, + MoveToStartOfLine, + MoveToEndOfLine, + MoveToStartOfBlock, + MoveToEndOfBlock, + MoveToStartOfDocument, + MoveToEndOfDocument, + SelectNextChar, + SelectPreviousChar, + SelectNextWord, + SelectPreviousWord, + SelectNextLine, + SelectPreviousLine, + SelectStartOfLine, + SelectEndOfLine, + SelectStartOfBlock, + SelectEndOfBlock, + SelectStartOfDocument, + SelectEndOfDocument, + DeleteStartOfWord, + DeleteEndOfWord, + + SetTextDirectionDefault, + SetTextDirectionLeftToRight, + SetTextDirectionRightToLeft, + + ToggleBold, + ToggleItalic, + ToggleUnderline, + + InspectElement, + + InsertParagraphSeparator, + InsertLineSeparator, + + WebActionCount + }; + + enum FindFlag { + FindBackward = 1, + FindCaseSensitively = 2, + FindWrapsAroundDocument = 4 + }; + Q_DECLARE_FLAGS(FindFlags, FindFlag) + + enum LinkDelegationPolicy { + DontDelegateLinks, + DelegateExternalLinks, + DelegateAllLinks + }; + + enum WebWindowType { + WebBrowserWindow, + WebModalDialog + }; + + explicit QWebPage(QObject *parent = 0); + ~QWebPage(); + + QWebFrame *mainFrame() const; + QWebFrame *currentFrame() const; + + QWebHistory *history() const; + QWebSettings *settings() const; + + void setView(QWidget *view); + QWidget *view() const; + + bool isModified() const; +#ifndef QT_NO_UNDOSTACK + QUndoStack *undoStack() const; +#endif + +#if QT_VERSION < 0x040400 && !defined(qdoc) + void setNetworkInterface(QWebNetworkInterface *interface); + QWebNetworkInterface *networkInterface() const; + + // #### why is this in the page itself? +#ifndef QT_NO_NETWORKPROXY + void setNetworkProxy(const QNetworkProxy& proxy); + QNetworkProxy networkProxy() const; +#endif + +#else + void setNetworkAccessManager(QNetworkAccessManager *manager); + QNetworkAccessManager *networkAccessManager() const; +#endif + + void setPluginFactory(QWebPluginFactory *factory); + QWebPluginFactory *pluginFactory() const; + + quint64 totalBytes() const; + quint64 bytesReceived() const; + + QString selectedText() const; + + QAction *action(WebAction action) const; + virtual void triggerAction(WebAction action, bool checked = false); + + QSize viewportSize() const; + void setViewportSize(const QSize &size) const; + + virtual bool event(QEvent*); + bool focusNextPrevChild(bool next); + + QVariant inputMethodQuery(Qt::InputMethodQuery property) const; + + bool findText(const QString &subString, FindFlags options = 0); + + void setForwardUnsupportedContent(bool forward); + bool forwardUnsupportedContent() const; + + void setLinkDelegationPolicy(LinkDelegationPolicy policy); + LinkDelegationPolicy linkDelegationPolicy() const; + + void setPalette(const QPalette &palette); + QPalette palette() const; + + void setEditable(bool editable); + bool isEditable() const; + +#ifndef QT_NO_CONTEXTMENU + bool swallowContextMenuEvent(QContextMenuEvent *event); +#endif + void updatePositionDependentActions(const QPoint &pos); + + QMenu *createStandardContextMenu(); + + enum Extension { + }; + class ExtensionOption + {}; + class ExtensionReturn + {}; + virtual bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0); + virtual bool supportsExtension(Extension extension) const; + +Q_SIGNALS: + void loadStarted(); + void loadProgress(int progress); + void loadFinished(bool ok); + + void linkHovered(const QString &link, const QString &title, const QString &textContent); + void statusBarMessage(const QString& text); + void selectionChanged(); + void frameCreated(QWebFrame *frame); + void geometryChangeRequested(const QRect& geom); + void repaintRequested(const QRect& dirtyRect); + void scrollRequested(int dx, int dy, const QRect& scrollViewRect); + void windowCloseRequested(); + void printRequested(QWebFrame *frame); + void linkClicked(const QUrl &url); + + void toolBarVisibilityChangeRequested(bool visible); + void statusBarVisibilityChangeRequested(bool visible); + void menuBarVisibilityChangeRequested(bool visible); + +#if QT_VERSION >= 0x040400 + void unsupportedContent(QNetworkReply *reply); + void downloadRequested(const QNetworkRequest &request); +#endif + + void microFocusChanged(); + void contentsChanged(); + +protected: + virtual QWebPage *createWindow(WebWindowType type); + virtual QObject *createPlugin(const QString &classid, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues); + +#if QT_VERSION >= 0x040400 + virtual bool acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type); +#else + virtual bool acceptNavigationRequest(QWebFrame *frame, const QWebNetworkRequest &request, NavigationType type); +#endif + virtual QString chooseFile(QWebFrame *originatingFrame, const QString& oldFile); + virtual void javaScriptAlert(QWebFrame *originatingFrame, const QString& msg); + virtual bool javaScriptConfirm(QWebFrame *originatingFrame, const QString& msg); + virtual bool javaScriptPrompt(QWebFrame *originatingFrame, const QString& msg, const QString& defaultValue, QString* result); + virtual void javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID); + + virtual QString userAgentForUrl(const QUrl& url) const; + +private: + Q_PRIVATE_SLOT(d, void _q_onLoadProgressChanged(int)) + Q_PRIVATE_SLOT(d, void _q_webActionTriggered(bool checked)) + QWebPagePrivate *d; + + friend class QWebFrame; + friend class QWebPagePrivate; + friend class QWebView; + friend class WebCore::ChromeClientQt; + friend class WebCore::EditorClientQt; + friend class WebCore::FrameLoaderClientQt; + friend class WebCore::InspectorClientQt; + friend class WebCore::ResourceHandle; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QWebPage::FindFlags) + +#endif diff --git a/WebKit/qt/Api/qwebpage_p.h b/WebKit/qt/Api/qwebpage_p.h new file mode 100644 index 0000000..8fae81c --- /dev/null +++ b/WebKit/qt/Api/qwebpage_p.h @@ -0,0 +1,166 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2008 Holger Hans Peter Freyther + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBPAGE_P_H +#define QWEBPAGE_P_H + +#include <qbasictimer.h> +#include <qnetworkproxy.h> +#include <qpointer.h> +#include <qevent.h> + +#include "qwebpage.h" +#include "qwebhistory.h" +#include "qwebframe.h" + +#include "KURL.h" +#include "PlatformString.h" + +#include <wtf/RefPtr.h> + +namespace WebCore +{ + class ChromeClientQt; + class ContextMenuClientQt; + class ContextMenuItem; + class ContextMenu; + class EditorClientQt; + class Element; + class Node; + class Page; + +#ifndef QT_NO_CURSOR + class SetCursorEvent : public QEvent { + public: + static const int EventType = 724; + SetCursorEvent(const QCursor&); + + QCursor cursor() const; + private: + QCursor m_cursor; + }; +#endif +} + +QT_BEGIN_NAMESPACE +class QUndoStack; +class QMenu; +class QBitArray; +QT_END_NAMESPACE + +class QWebPagePrivate +{ +public: + QWebPagePrivate(QWebPage *); + ~QWebPagePrivate(); + void createMainFrame(); +#ifndef QT_NO_CONTEXTMENU + QMenu *createContextMenu(const WebCore::ContextMenu *webcoreMenu, const QList<WebCore::ContextMenuItem> *items, QBitArray *visitedWebActions); +#endif + + QWebFrame *frameAt(const QPoint &pos) const; + + void _q_onLoadProgressChanged(int); + void _q_webActionTriggered(bool checked); + void updateAction(QWebPage::WebAction action); + void updateNavigationActions(); + void updateEditorActions(); + + void timerEvent(QTimerEvent*); + + void mouseMoveEvent(QMouseEvent*); + void mousePressEvent(QMouseEvent*); + void mouseDoubleClickEvent(QMouseEvent*); + void mouseTripleClickEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); +#ifndef QT_NO_CONTEXTMENU + void contextMenuEvent(QContextMenuEvent*); +#endif +#ifndef QT_NO_WHEELEVENT + void wheelEvent(QWheelEvent*); +#endif + void keyPressEvent(QKeyEvent*); + void keyReleaseEvent(QKeyEvent*); + void focusInEvent(QFocusEvent*); + void focusOutEvent(QFocusEvent*); + + void dragEnterEvent(QDragEnterEvent *); + void dragLeaveEvent(QDragLeaveEvent *); + void dragMoveEvent(QDragMoveEvent *); + void dropEvent(QDropEvent *); + + void inputMethodEvent(QInputMethodEvent*); + + void shortcutOverrideEvent(QKeyEvent*); + void leaveEvent(QEvent *); + bool handleScrolling(QKeyEvent*); + + WebCore::ChromeClientQt *chromeClient; + WebCore::ContextMenuClientQt *contextMenuClient; + WebCore::EditorClientQt *editorClient; + WebCore::Page *page; + + QPointer<QWebFrame> mainFrame; + + QWebPage *q; +#ifndef QT_NO_UNDOSTACK + QUndoStack *undoStack; +#endif + QWidget *view; + + bool insideOpenCall; + quint64 m_totalBytes; + quint64 m_bytesReceived; + + QPoint tripleClick; + QBasicTimer tripleClickTimer; + +#if QT_VERSION < 0x040400 + bool acceptNavigationRequest(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type); + + QWebNetworkInterface *networkInterface; +#ifndef QT_NO_NETWORKPROXY + QNetworkProxy networkProxy; +#endif + +#else + bool acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type); + QNetworkAccessManager *networkManager; +#endif + + bool forwardUnsupportedContent; + QWebPage::LinkDelegationPolicy linkPolicy; + + QSize viewportSize; + QWebHistory history; + QWebHitTestResult hitTestResult; +#ifndef QT_NO_CONTEXTMENU + QPointer<QMenu> currentContextMenu; +#endif + QWebSettings *settings; + QPalette palette; + bool editable; + + QAction *actions[QWebPage::WebActionCount]; + + QWebPluginFactory *pluginFactory; +}; + +#endif diff --git a/WebKit/qt/Api/qwebpluginfactory.cpp b/WebKit/qt/Api/qwebpluginfactory.cpp new file mode 100644 index 0000000..0d2390c --- /dev/null +++ b/WebKit/qt/Api/qwebpluginfactory.cpp @@ -0,0 +1,216 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qwebpluginfactory.h" + +/*! + \class QWebPluginFactory + \since 4.4 + \brief The QWebPluginFactory class creates plugins to be embedded into web + pages. + + QWebPluginFactory is a factory for creating plugins for QWebPage. A plugin + factory can be installed on a QWebPage using QWebPage::setPluginFactory(). + + \note The plugin factory is only used if plugins are enabled through QWebSettings. + + You can provide a QWebPluginFactory by implementing the plugins() and the + create() method. For plugins() it is necessary to describe the plugins the + factory can create, including a description and the supported MIME types. + The MIME types each plugin can handle should match the ones specified in + in the HTML \c{<object>} tag. + + The create() method is called if the requested MIME type is supported. The + implementation has to return a new instance of the plugin requested for the + given MIME type and the specified URL. +*/ + + +/*! + \class QWebPluginFactory::Plugin + \since 4.4 + \brief the QWebPluginFactory::Plugin structure describes the properties of a plugin a QWebPluginFactory can create. +*/ + +/*! + \variable QWebPluginFactory::Plugin::name + The name of the plugin. +*/ + +/*! + \variable QWebPluginFactory::Plugin::description + The description of the plugin. +*/ + +/*! + \variable QWebPluginFactory::Plugin::mimeTypes + The list of mime types supported by the plugin. +*/ + +/*! + \class QWebPluginFactory::MimeType + \since 4.4 + \brief The QWebPluginFactory::MimeType structure describes a mime type supported by a plugin. +*/ + +/*! + \variable QWebPluginFactory::MimeType::name + + The full name of the MIME type; e.g., \c{text/plain} or \c{image/png}. +*/ + +/*! + \variable QWebPluginFactory::MimeType::description + The description of the mime type. +*/ + +/*! + \variable QWebPluginFactory::MimeType::fileExtensions + The list of file extensions that are used by this mime type. + + For example, a mime type for PDF documents would return "pdf" as its file extension. +*/ + +/*! + Constructs a QWebPluginFactory with parent \a parent. +*/ +QWebPluginFactory::QWebPluginFactory(QObject *parent) + : QObject(parent) +{ +} + +/*! + Destructor. +*/ +QWebPluginFactory::~QWebPluginFactory() +{ +} + +/*! + \fn QList<Plugin> QWebPluginFactory::plugins() const = 0 + + This function is reimplemented in subclasses to return a list of + supported plugins the factory can create. + + \note Currently, this function is only called when JavaScript programs + access the global \c plugins or \c mimetypes objects. +*/ + +/*! + This function is called to refresh the list of supported plugins. It may be called after a new plugin + has been installed in the system. +*/ +void QWebPluginFactory::refreshPlugins() +{ +} + +/*! + \fn QObject *QWebPluginFactory::create(const QString &mimeType, const QUrl &url, + const QStringList &argumentNames, const QStringList &argumentValues) const = 0 + + Implemented in subclasses to create a new plugin that can display content of + the MIME type given by \a mimeType. The URL of the content is provided in \a url. + The returned object should be a QWidget. + + The HTML object element can provide parameters through the \c{<param>} tag. + The name and the value attributes of these tags are specified by the + \a argumentNames and \a argumentValues string lists. + + For example: + + \code + <object type="application/x-pdf" data="http://www.trolltech.com/document.pdf" width="500" height="400"> + <param name="showTableOfContents" value="true" /> + <param name="hideThumbnails" value="false" /> + </object> + \endcode + + The above object element will result in a call to create() with the following arguments: + \table + \header \o Parameter + \o Value + \row \o mimeType + \o "application/x-pdf" + \row \o url + \o "http://www.trolltech.com/document.pdf" + \row \o argumentNames + \o "showTableOfContents" "hideThumbnails" + \row \o argumentVaues + \o "true" "false" + \endtable + + \note Ownership of the returned object will be transferred to the caller. +*/ + +/*! + \enum QWebPluginFactory::Extension + + This enum describes the types of extensions that the plugin factory can support. Before using these extensions, you + should verify that the extension is supported by calling supportsExtension(). + + Currently there are no extensions. +*/ + +/*! + \class QWebPluginFactory::ExtensionOption + \since 4.4 + \brief The ExtensionOption class provides an extended input argument to QWebPluginFactory's extension support. + + \sa QWebPluginFactory::extension() +*/ + +/*! + \class QWebPluginFactory::ExtensionReturn + \since 4.4 + \brief The ExtensionOption class provides an extended output argument to QWebPluginFactory's extension support. + + \sa QWebPluginFactory::extension() +*/ + +/*! + This virtual function can be reimplemented in a QWebPluginFactory subclass to provide support for extensions. The \a option + argument is provided as input to the extension; the output results can be stored in \a output. + + The behaviour of this function is determined by \a extension. + + You can call supportsExtension() to check if an extension is supported by the factory. + + By default, no extensions are supported, and this function returns false. + + \sa supportsExtension(), Extension +*/ +bool QWebPluginFactory::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output) +{ + Q_UNUSED(extension) + Q_UNUSED(option) + Q_UNUSED(output) + return false; +} + +/*! + This virtual function returns true if the plugin factory supports \a extension; otherwise false is returned. + + \sa extension() +*/ +bool QWebPluginFactory::supportsExtension(Extension extension) const +{ + Q_UNUSED(extension) + return false; +} diff --git a/WebKit/qt/Api/qwebpluginfactory.h b/WebKit/qt/Api/qwebpluginfactory.h new file mode 100644 index 0000000..3531b06 --- /dev/null +++ b/WebKit/qt/Api/qwebpluginfactory.h @@ -0,0 +1,74 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBPLUGINFACTORY_H +#define QWEBPLUGINFACTORY_H + +#include "qwebkitglobal.h" + +#include <QtCore/qobject.h> +#include <QtCore/qstringlist.h> + +QT_BEGIN_NAMESPACE +class QUrl; +class QString; +QT_END_NAMESPACE +class QWebPluginFactoryPrivate; + +class QWEBKIT_EXPORT QWebPluginFactory : public QObject +{ + Q_OBJECT +public: + struct MimeType { + QString name; + QString description; + QStringList fileExtensions; + }; + + struct Plugin { + QString name; + QString description; + QList<MimeType> mimeTypes; + }; + + explicit QWebPluginFactory(QObject *parent = 0); + virtual ~QWebPluginFactory(); + + virtual QList<Plugin> plugins() const = 0; + virtual void refreshPlugins(); + + virtual QObject *create(const QString &mimeType, + const QUrl &url, + const QStringList &argumentNames, + const QStringList &argumentValues) const = 0; + + enum Extension { + }; + class ExtensionOption + {}; + class ExtensionReturn + {}; + virtual bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0); + virtual bool supportsExtension(Extension extension) const; + +private: + QWebPluginFactoryPrivate *d; +}; + +#endif diff --git a/WebKit/qt/Api/qwebsettings.cpp b/WebKit/qt/Api/qwebsettings.cpp new file mode 100644 index 0000000..132eb0c --- /dev/null +++ b/WebKit/qt/Api/qwebsettings.cpp @@ -0,0 +1,602 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qwebsettings.h" + +#include "qwebpage.h" +#include "qwebpage_p.h" + +#include "Cache.h" +#include "Page.h" +#include "PageCache.h" +#include "Settings.h" +#include "KURL.h" +#include "PlatformString.h" +#include "IconDatabase.h" +#include "Image.h" +#include "IntSize.h" + +#include <QHash> +#include <QSharedData> +#include <QUrl> +#include <QFileInfo> + +class QWebSettingsPrivate +{ +public: + QWebSettingsPrivate(WebCore::Settings *wcSettings = 0) + : settings(wcSettings) + { + } + + QHash<int, QString> fontFamilies; + QHash<int, int> fontSizes; + QHash<int, bool> attributes; + QUrl userStyleSheetLocation; + + void apply(); + WebCore::Settings *settings; +}; + +typedef QHash<int, QPixmap> WebGraphicHash; +Q_GLOBAL_STATIC(WebGraphicHash, _graphics) + +static WebGraphicHash* graphics() +{ + WebGraphicHash* hash = _graphics(); + + if (hash->isEmpty()) { + hash->insert(QWebSettings::MissingImageGraphic, QPixmap(QLatin1String(":webkit/resources/missingImage.png"))); + hash->insert(QWebSettings::MissingPluginGraphic, QPixmap(QLatin1String(":webkit/resources/nullPlugin.png"))); + hash->insert(QWebSettings::DefaultFrameIconGraphic, QPixmap(QLatin1String(":webkit/resources/urlIcon.png"))); + hash->insert(QWebSettings::TextAreaSizeGripCornerGraphic, QPixmap(QLatin1String(":webkit/resources/textAreaResizeCorner.png"))); + } + + return hash; +} + +Q_GLOBAL_STATIC(QList<QWebSettingsPrivate *>, allSettings); + +void QWebSettingsPrivate::apply() +{ + if (settings) { + settings->setTextAreasAreResizable(true); + + QWebSettingsPrivate *global = QWebSettings::globalSettings()->d; + + QString family = fontFamilies.value(QWebSettings::StandardFont, + global->fontFamilies.value(QWebSettings::StandardFont)); + settings->setStandardFontFamily(family); + + family = fontFamilies.value(QWebSettings::FixedFont, + global->fontFamilies.value(QWebSettings::FixedFont)); + settings->setFixedFontFamily(family); + + family = fontFamilies.value(QWebSettings::SerifFont, + global->fontFamilies.value(QWebSettings::SerifFont)); + settings->setSerifFontFamily(family); + + family = fontFamilies.value(QWebSettings::SansSerifFont, + global->fontFamilies.value(QWebSettings::SansSerifFont)); + settings->setSansSerifFontFamily(family); + + family = fontFamilies.value(QWebSettings::CursiveFont, + global->fontFamilies.value(QWebSettings::CursiveFont)); + settings->setCursiveFontFamily(family); + + family = fontFamilies.value(QWebSettings::FantasyFont, + global->fontFamilies.value(QWebSettings::FantasyFont)); + settings->setFantasyFontFamily(family); + + int size = fontSizes.value(QWebSettings::MinimumFontSize, + global->fontSizes.value(QWebSettings::MinimumFontSize)); + settings->setMinimumFontSize(size); + + size = fontSizes.value(QWebSettings::MinimumLogicalFontSize, + global->fontSizes.value(QWebSettings::MinimumLogicalFontSize)); + settings->setMinimumLogicalFontSize(size); + + size = fontSizes.value(QWebSettings::DefaultFontSize, + global->fontSizes.value(QWebSettings::DefaultFontSize)); + settings->setDefaultFontSize(size); + + size = fontSizes.value(QWebSettings::DefaultFixedFontSize, + global->fontSizes.value(QWebSettings::DefaultFixedFontSize)); + settings->setDefaultFixedFontSize(size); + + bool value = attributes.value(QWebSettings::AutoLoadImages, + global->attributes.value(QWebSettings::AutoLoadImages)); + settings->setLoadsImagesAutomatically(value); + + value = attributes.value(QWebSettings::JavascriptEnabled, + global->attributes.value(QWebSettings::JavascriptEnabled)); + settings->setJavaScriptEnabled(value); + + value = attributes.value(QWebSettings::JavascriptCanOpenWindows, + global->attributes.value(QWebSettings::JavascriptCanOpenWindows)); + settings->setJavaScriptCanOpenWindowsAutomatically(value); + + value = attributes.value(QWebSettings::JavaEnabled, + global->attributes.value(QWebSettings::JavaEnabled)); + settings->setJavaEnabled(value); + + value = attributes.value(QWebSettings::PluginsEnabled, + global->attributes.value(QWebSettings::PluginsEnabled)); + settings->setPluginsEnabled(value); + + value = attributes.value(QWebSettings::PrivateBrowsingEnabled, + global->attributes.value(QWebSettings::PrivateBrowsingEnabled)); + settings->setPrivateBrowsingEnabled(value); + + value = attributes.value(QWebSettings::JavascriptCanAccessClipboard, + global->attributes.value(QWebSettings::JavascriptCanAccessClipboard)); + settings->setDOMPasteAllowed(value); + + value = attributes.value(QWebSettings::DeveloperExtrasEnabled, + global->attributes.value(QWebSettings::DeveloperExtrasEnabled)); + settings->setDeveloperExtrasEnabled(value); + + QUrl location = !userStyleSheetLocation.isEmpty() ? userStyleSheetLocation : global->userStyleSheetLocation; + settings->setUserStyleSheetLocation(WebCore::KURL(location)); + + value = attributes.value(QWebSettings::ZoomTextOnly, + global->attributes.value(QWebSettings::ZoomTextOnly)); + settings->setZoomsTextOnly(value); + } else { + QList<QWebSettingsPrivate *> settings = *::allSettings(); + for (int i = 0; i < settings.count(); ++i) + settings[i]->apply(); + } +} + +/*! + Returns the global settings object. + + Any setting changed on the default object is automatically applied to all + QWebPage instances where the particular setting is not overriden already. +*/ +QWebSettings *QWebSettings::globalSettings() +{ + static QWebSettings *global = 0; + if (!global) + global = new QWebSettings; + return global; +} + +/*! + \class QWebSettings + \since 4.4 + \brief The QWebSettings class provides an object to store the settings used + by QWebPage and QWebFrame. + + Each QWebPage object has its own QWebSettings object, which configures the + settings for that page. If a setting is not configured, then it is looked + up in the global settings object, which can be accessed using + QWebSettings::globalSettings(). + + QWebSettings allows configuring font properties such as font size and font + family, the location of a custom stylesheet, and generic attributes like java + script, plugins, etc. The \l{QWebSettings::WebAttribute}{WebAttribute} + enum further describes this. + + QWebSettings also configures global properties such as the web page memory + cache and the web page icon database. + + \sa QWebPage::settings(), QWebView::settings(), {Browser} +*/ + +/*! + \enum QWebSettings::FontFamily + + This enum describes the generic font families defined by CSS 2. + For more information see the + \l{http://www.w3.org/TR/REC-CSS2/fonts.html#generic-font-families}{CSS standard}. + + \value StandardFont + \value FixedFont + \value SerifFont + \value SansSerifFont + \value CursiveFont + \value FantasyFont +*/ + +/*! + \enum QWebSettings::FontSize + + This enum describes the font sizes configurable through QWebSettings. + + \value MinimumFontSize The hard minimum font size. + \value MinimumLogicalFontSize The minimum logical font size that is applied + after zooming with QWebFrame's textSizeMultiplier(). + \value DefaultFontSize The default font size for regular text. + \value DefaultFixedFontSize The default font size for fixed-pitch text. +*/ + +/*! + \enum QWebSettings::WebGraphic + + This enums describes the standard graphical elements used in webpages. + + \value MissingImageGraphic The replacement graphic shown when an image could not be loaded. + \value MissingPluginGraphic The replacement graphic shown when a plugin could not be loaded. + \value DefaultFrameIconGraphic The default icon for QWebFrame::icon(). + \value TextAreaSizeGripCornerGraphic The graphic shown for the size grip of text areas. +*/ + +/*! + \enum QWebSettings::WebAttribute + + This enum describes various attributes that are configurable through QWebSettings. + + \value AutoLoadImages Specifies whether images are automatically loaded in + web pages. + \value JavascriptEnabled Enables or disables the running of JavaScript + programs. + \value JavaEnabled Enables or disables Java applets. + Currently Java applets are not supported. + \value PluginsEnabled Enables or disables plugins in web pages. + Currently Flash and other plugins are not supported. + \value PrivateBrowsingEnabled Private browsing prevents WebKit from + recording visited pages in the history and storing web page icons. + \value JavascriptCanOpenWindows Specifies whether JavaScript programs + can open new windows. + \value JavascriptCanAccessClipboard Specifies whether JavaScript programs + can read or write to the clipboard. + \value DeveloperExtrasEnabled Enables extra tools for Web developers. + Currently this enables the "Inspect" element in the context menu, + which shows the WebKit WebInspector for web site debugging. + \value LinksIncludedInFocusChain Specifies whether hyperlinks should be + included in the keyboard focus chain. + \value ZoomTextOnly Specifies whether the zoom factor on a frame applies to + only the text or all content. +*/ + +/*! + \internal +*/ +QWebSettings::QWebSettings() + : d(new QWebSettingsPrivate) +{ + // Initialize our global defaults + // changing any of those will likely break the LayoutTests + d->fontSizes.insert(QWebSettings::MinimumFontSize, 5); + d->fontSizes.insert(QWebSettings::MinimumLogicalFontSize, 5); + d->fontSizes.insert(QWebSettings::DefaultFontSize, 14); + d->fontSizes.insert(QWebSettings::DefaultFixedFontSize, 14); + d->fontFamilies.insert(QWebSettings::StandardFont, QLatin1String("Arial")); + d->fontFamilies.insert(QWebSettings::FixedFont, QLatin1String("Courier New")); + d->fontFamilies.insert(QWebSettings::SerifFont, QLatin1String("Times New Roman")); + d->fontFamilies.insert(QWebSettings::SansSerifFont, QLatin1String("Arial")); + d->fontFamilies.insert(QWebSettings::CursiveFont, QLatin1String("Arial")); + d->fontFamilies.insert(QWebSettings::FantasyFont, QLatin1String("Arial")); + + d->attributes.insert(QWebSettings::AutoLoadImages, true); + d->attributes.insert(QWebSettings::JavascriptEnabled, true); + d->attributes.insert(QWebSettings::LinksIncludedInFocusChain, true); + d->attributes.insert(QWebSettings::ZoomTextOnly, false); +} + +/*! + \internal +*/ +QWebSettings::QWebSettings(WebCore::Settings *settings) + : d(new QWebSettingsPrivate(settings)) +{ + d->settings = settings; + d->apply(); + allSettings()->append(d); +} + +/*! + \internal +*/ +QWebSettings::~QWebSettings() +{ + if (d->settings) + allSettings()->removeAll(d); + + delete d; +} + +/*! + Sets the font size for \a type to \a size. +*/ +void QWebSettings::setFontSize(FontSize type, int size) +{ + d->fontSizes.insert(type, size); + d->apply(); +} + +/*! + Returns the default font size for \a type. +*/ +int QWebSettings::fontSize(FontSize type) const +{ + int defaultValue = 0; + if (d->settings) { + QWebSettingsPrivate *global = QWebSettings::globalSettings()->d; + defaultValue = global->fontSizes.value(type); + } + return d->fontSizes.value(type, defaultValue); +} + +/*! + Resets the font size for \a type to the size specified in the global + settings object. + + This function has no effect on the global QWebSettings instance. +*/ +void QWebSettings::resetFontSize(FontSize type) +{ + if (d->settings) { + d->fontSizes.remove(type); + d->apply(); + } +} + +/*! + Specifies the location of a user stylesheet to load with every web page. + + The \a location can be a URL or a path on the local filesystem. + + \sa userStyleSheetUrl() +*/ +void QWebSettings::setUserStyleSheetUrl(const QUrl &location) +{ + d->userStyleSheetLocation = location; + d->apply(); +} + +/*! + Returns the location of the user stylesheet. + + \sa setUserStyleSheetUrl() +*/ +QUrl QWebSettings::userStyleSheetUrl() const +{ + return d->userStyleSheetLocation; +} + +/*! + Sets the path of the icon database to \a path. The icon database is used + to store "favicons" associated with web sites. + + \a path must point to an existing directory where the icons are stored. + + Setting an empty path disables the icon database. +*/ +void QWebSettings::setIconDatabasePath(const QString &path) +{ + WebCore::iconDatabase()->delayDatabaseCleanup(); + + if (!path.isEmpty()) { + WebCore::iconDatabase()->setEnabled(true); + QFileInfo info(path); + if (info.isDir() && info.isWritable()) + WebCore::iconDatabase()->open(path); + } else { + WebCore::iconDatabase()->setEnabled(false); + WebCore::iconDatabase()->close(); + } +} + +/*! + Returns the path of the icon database or an empty string if the icon + database is disabled. + + \sa setIconDatabasePath(), clearIconDatabase() +*/ +QString QWebSettings::iconDatabasePath() +{ + if (WebCore::iconDatabase()->isEnabled() && WebCore::iconDatabase()->isOpen()) { + return WebCore::iconDatabase()->databasePath(); + } else { + return QString(); + } +} + +/*! + Clears the icon database. +*/ +void QWebSettings::clearIconDatabase() +{ + if (WebCore::iconDatabase()->isEnabled() && WebCore::iconDatabase()->isOpen()) + WebCore::iconDatabase()->removeAllIcons(); +} + +/*! + Returns the web site's icon for \a url. + + If the web site does not specify an icon, or the icon is not in the + database, a null QIcon is returned. + + \note The returned icon's size is arbitrary. + + \sa setIconDatabasePath() +*/ +QIcon QWebSettings::iconForUrl(const QUrl &url) +{ + WebCore::Image* image = WebCore::iconDatabase()->iconForPageURL(WebCore::KURL(url).string(), + WebCore::IntSize(16, 16)); + if (!image) { + return QPixmap(); + } + QPixmap *icon = image->nativeImageForCurrentFrame(); + if (!icon) { + return QPixmap(); + } + return *icon; +} + +/*! + Sets \a graphic to be drawn when QtWebKit needs to draw an image of the + given \a type. + + For example, when an image cannot be loaded the pixmap specified by + \l{QWebSettings::WebGraphic}{MissingImageGraphic} is drawn instead. + + \sa webGraphic() +*/ +void QWebSettings::setWebGraphic(WebGraphic type, const QPixmap &graphic) +{ + WebGraphicHash *h = graphics(); + if (graphic.isNull()) + h->remove(type); + else + h->insert(type, graphic); +} + +/*! + Returns a previously set pixmap used to draw replacement graphics of the + specified \a type. + + For example, when an image cannot be loaded the pixmap specified by + \l{QWebSettings::WebGraphic}{MissingImageGraphic} is drawn instead. + + \sa setWebGraphic() +*/ +QPixmap QWebSettings::webGraphic(WebGraphic type) +{ + return graphics()->value(type); +} + +/*! + Sets the maximum number of pages to hold in the memory cache to \a pages. +*/ +void QWebSettings::setMaximumPagesInCache(int pages) +{ + WebCore::pageCache()->setCapacity(qMax(0, pages)); +} + +/*! + Returns the maximum number of web pages that are kept in the memory cache. +*/ +int QWebSettings::maximumPagesInCache() +{ + return WebCore::pageCache()->capacity(); +} + +/*! + Specifies the capacities for the memory cache for dead objects such as + stylesheets or scripts. + + The \a cacheMinDeadCapacity specifies the \e minimum number of bytes that + dead objects should consume when the cache is under pressure. + + \a cacheMaxDead is the \e maximum number of bytes that dead objects should + consume when the cache is \bold not under pressure. + + \a totalCapacity specifies the \e maximum number of bytes that the cache + should consume \bold overall. + + The cache is enabled by default. Calling setObjectCacheCapacities(0, 0, 0) + will disable the cache. Calling it with one non-zero enables it again. +*/ +void QWebSettings::setObjectCacheCapacities(int cacheMinDeadCapacity, int cacheMaxDead, int totalCapacity) +{ + bool disableCache = cacheMinDeadCapacity == 0 && cacheMaxDead == 0 && totalCapacity == 0; + WebCore::cache()->setDisabled(disableCache); + + WebCore::cache()->setCapacities(qMax(0, cacheMinDeadCapacity), + qMax(0, cacheMaxDead), + qMax(0, totalCapacity)); +} + +/*! + Sets the actual font family to \a family for the specified generic family, + \a which. +*/ +void QWebSettings::setFontFamily(FontFamily which, const QString &family) +{ + d->fontFamilies.insert(which, family); + d->apply(); +} + +/*! + Returns the actual font family for the specified generic font family, + \a which. +*/ +QString QWebSettings::fontFamily(FontFamily which) const +{ + QString defaultValue; + if (d->settings) { + QWebSettingsPrivate *global = QWebSettings::globalSettings()->d; + defaultValue = global->fontFamilies.value(which); + } + return d->fontFamilies.value(which, defaultValue); +} + +/*! + Resets the actual font family to the default font family, specified by + \a which. + + This function has no effect on the global QWebSettings instance. +*/ +void QWebSettings::resetFontFamily(FontFamily which) +{ + if (d->settings) { + d->fontFamilies.remove(which); + d->apply(); + } +} + +/*! + \fn void QWebSettings::setAttribute(WebAttribute attribute, bool on) + + Enables or disables the specified \a attribute feature depending on the + value of \a on. +*/ +void QWebSettings::setAttribute(WebAttribute attr, bool on) +{ + d->attributes.insert(attr, on); + d->apply(); +} + +/*! + \fn bool QWebSettings::testAttribute(WebAttribute attribute) const + + Returns true if \a attribute is enabled; otherwise returns false. +*/ +bool QWebSettings::testAttribute(WebAttribute attr) const +{ + bool defaultValue = false; + if (d->settings) { + QWebSettingsPrivate *global = QWebSettings::globalSettings()->d; + defaultValue = global->attributes.value(attr); + } + return d->attributes.value(attr, defaultValue); +} + +/*! + \fn void QWebSettings::resetAttribute(WebAttribute attribute) + + Resets the setting of \a attribute. + This function has no effect on the global QWebSettings instance. + + \sa globalSettings() +*/ +void QWebSettings::resetAttribute(WebAttribute attr) +{ + if (d->settings) { + d->attributes.remove(attr); + d->apply(); + } +} + diff --git a/WebKit/qt/Api/qwebsettings.h b/WebKit/qt/Api/qwebsettings.h new file mode 100644 index 0000000..9a75dbf --- /dev/null +++ b/WebKit/qt/Api/qwebsettings.h @@ -0,0 +1,119 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBSETTINGS_H +#define QWEBSETTINGS_H + +#include "qwebkitglobal.h" + +#include <QtCore/qstring.h> +#include <QtGui/qpixmap.h> +#include <QtGui/qicon.h> +#include <QtCore/qshareddata.h> + +namespace WebCore +{ + class Settings; +} + +class QWebPage; +class QWebSettingsPrivate; +QT_BEGIN_NAMESPACE +class QUrl; +QT_END_NAMESPACE + +class QWEBKIT_EXPORT QWebSettings +{ +public: + enum FontFamily { + StandardFont, + FixedFont, + SerifFont, + SansSerifFont, + CursiveFont, + FantasyFont + }; + enum WebAttribute { + AutoLoadImages, + JavascriptEnabled, + JavaEnabled, + PluginsEnabled, + PrivateBrowsingEnabled, + JavascriptCanOpenWindows, + JavascriptCanAccessClipboard, + DeveloperExtrasEnabled, + LinksIncludedInFocusChain, + ZoomTextOnly + }; + enum WebGraphic { + MissingImageGraphic, + MissingPluginGraphic, + DefaultFrameIconGraphic, + TextAreaSizeGripCornerGraphic + }; + enum FontSize { + MinimumFontSize, + MinimumLogicalFontSize, + DefaultFontSize, + DefaultFixedFontSize + }; + + static QWebSettings *globalSettings(); + + void setFontFamily(FontFamily which, const QString &family); + QString fontFamily(FontFamily which) const; + void resetFontFamily(FontFamily which); + + void setFontSize(FontSize type, int size); + int fontSize(FontSize type) const; + void resetFontSize(FontSize type); + + void setAttribute(WebAttribute attr, bool on); + bool testAttribute(WebAttribute attr) const; + void resetAttribute(WebAttribute attr); + + void setUserStyleSheetUrl(const QUrl &location); + QUrl userStyleSheetUrl() const; + + static void setIconDatabasePath(const QString &location); + static QString iconDatabasePath(); + static void clearIconDatabase(); + static QIcon iconForUrl(const QUrl &url); + + static void setWebGraphic(WebGraphic type, const QPixmap &graphic); + static QPixmap webGraphic(WebGraphic type); + + static void setMaximumPagesInCache(int pages); + static int maximumPagesInCache(); + static void setObjectCacheCapacities(int cacheMinDeadCapacity, int cacheMaxDead, int totalCapacity); + +private: + friend class QWebPagePrivate; + friend class QWebSettingsPrivate; + + Q_DISABLE_COPY(QWebSettings) + + QWebSettings(); + QWebSettings(WebCore::Settings *settings); + ~QWebSettings(); + + QWebSettingsPrivate *d; +}; + +#endif diff --git a/WebKit/qt/Api/qwebview.cpp b/WebKit/qt/Api/qwebview.cpp new file mode 100644 index 0000000..ad0b12a --- /dev/null +++ b/WebKit/qt/Api/qwebview.cpp @@ -0,0 +1,957 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2008 Holger Hans Peter Freyther + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qwebview.h" +#include "qwebframe.h" +#include "qwebpage_p.h" + +#include "qbitmap.h" +#include "qevent.h" +#include "qpainter.h" +#include "qprinter.h" + +class QWebViewPrivate +{ +public: + QWebViewPrivate(QWebView *view) + : view(view) + , page(0) +#ifndef QT_NO_CURSOR + , cursorSetByWebCore(false) + , usesWebCoreCursor(true) +#endif + {} + + QWebView *view; + QWebPage *page; + + +#ifndef QT_NO_CURSOR + /* + * We keep track of if we have called setCursor and if the CursorChange + * event is sent due our setCursor call and if we currently use the WebCore + * Cursor and use it to decide if we can update to another WebCore Cursor. + */ + bool cursorSetByWebCore; + bool usesWebCoreCursor; + + void setCursor(const QCursor& newCursor) + { + webCoreCursor = newCursor; + + if (usesWebCoreCursor) { + cursorSetByWebCore = true; + view->setCursor(webCoreCursor); + } + } + + QCursor webCoreCursor; +#endif +}; + +/*! + \class QWebView + \since 4.4 + \brief The QWebView class provides a widget that is used to view and edit + web documents. + \ingroup advanced + + QWebView is the main widget component of the QtWebKit web browsing module. + It can be used in various applications to display web content live from the + Internet. + + The image below shows QWebView previewed in \QD with the Trolltech website. + + \image qwebview-url.png + + A web site can be loaded onto QWebView with the load() function. Like all + Qt Widgets, the show() function must be invoked in order to display + QWebView. The snippet below illustrates this: + + \snippet doc/src/snippets/webkit/simple/main.cpp Using QWebView + + Alternatively, setUrl() can also be used to load a web site. If you have + the HTML content readily available, you can use setHtml() instead. + + The loadStarted() signal is emitted when the view begins loading. The + loadProgress() signal, on the other hand, is emitted whenever an element of + the web view completes loading, such as an embedded image, a script, etc. + Finally, the loadFinished() signal is emitted when the view has loaded + completely. It's argument - either \c true or \c false - indicates + load success or failure. + + The page() function returns a pointer to the web page object. See + \l{Elements of QWebView} for an explanation of how the web page + is related to the view. To modify your web view's settings, you can access + the QWebSettings object with the settings() function. With QWebSettings, + you can change the default fonts, enable or disable features such as + JavaScript and plugins. + + The title of an HTML document can be accessed with the title() property. + Additionally, a web site may also specify an icon, which can be accessed + using the icon() property. If the title or the icon changes, the corresponding + titleChanged() and iconChanged() signals will be emitted. The + textSizeMultiplier() property can be used to change the overall size of + the text displayed in the web view. + + If you require a custom context menu, you can implement it by reimplementing + \l{QWidget::}{contextMenuEvent()} and populating your QMenu with the actions + obtained from pageAction(). More functionality such as reloading the view, + copying selected text to the clipboard, or pasting into the view, is also + encapsulated within the QAction objects returned by pageAction(). These + actions can be programmatically triggered using triggerPageAction(). + Alternatively, the actions can be added to a toolbar or a menu directly. + QWebView maintains the state of the returned actions but allows + modification of action properties such as \l{QAction::}{text} or + \l{QAction::}{icon}. + + A QWebView can be printed onto a QPrinter using the print() function. + This function is marked as a slot and can be conveniently connected to + \l{QPrintPreviewDialog}'s \l{QPrintPreviewDialog::}{paintRequested()} + signal. + + If you want to provide support for web sites that allow the user to open + new windows, such as pop-up windows, you can subclass QWebView and + reimplement the createWindow() function. + + \section1 Elements of QWebView + + QWebView consists of other objects such as QWebFrame and QWebPage. The + flowchart below shows these elements are related. + + \image qwebview-diagram.png + + \note It is possible to use QWebPage and QWebFrame, without using QWebView, + if you do not require QWidget attributes. Nevertheless, QtWebKit depends + on QtGui, so you should use a QApplication instead of QCoreApplication. + + \sa {Previewer Example}, {Browser} +*/ + +/*! + Constructs an empty QWebView with parent \a parent. + + \sa load() +*/ +QWebView::QWebView(QWidget *parent) + : QWidget(parent) +{ + d = new QWebViewPrivate(this); + + QPalette pal = palette(); + pal.setBrush(QPalette::Background, Qt::white); + + setAttribute(Qt::WA_OpaquePaintEvent); +#if !defined(Q_WS_QWS) + setAttribute(Qt::WA_InputMethodEnabled); +#endif + + setPalette(pal); + setAcceptDrops(true); + + setMouseTracking(true); + setFocusPolicy(Qt::WheelFocus); +} + +/*! + Destroys the web view. +*/ +QWebView::~QWebView() +{ + if (d->page) + d->page->d->view = 0; + + if (d->page && d->page->parent() == this) + delete d->page; + delete d; +} + +/*! + Returns a pointer to the underlying web page. + + \sa setPage() +*/ +QWebPage *QWebView::page() const +{ + if (!d->page) { + QWebView *that = const_cast<QWebView *>(this); + that->setPage(new QWebPage(that)); + } + return d->page; +} + +/*! + Makes \a page the new web page of the web view. + + The parent QObject of the provided page remains the owner + of the object. If the current document is a child of the web + view, it will be deleted. + + \sa page() +*/ +void QWebView::setPage(QWebPage *page) +{ + if (d->page == page) + return; + if (d->page) { + if (d->page->parent() == this) { + delete d->page; + } else { + d->page->disconnect(this); + } + } + d->page = page; + if (d->page) { + d->page->setView(this); + d->page->setPalette(palette()); + // #### connect signals + QWebFrame *mainFrame = d->page->mainFrame(); + connect(mainFrame, SIGNAL(titleChanged(const QString&)), + this, SIGNAL(titleChanged(const QString&))); + connect(mainFrame, SIGNAL(iconChanged()), + this, SIGNAL(iconChanged())); + connect(mainFrame, SIGNAL(urlChanged(const QUrl &)), + this, SIGNAL(urlChanged(const QUrl &))); + + connect(d->page, SIGNAL(loadStarted()), + this, SIGNAL(loadStarted())); + connect(d->page, SIGNAL(loadProgress(int)), + this, SIGNAL(loadProgress(int))); + connect(d->page, SIGNAL(loadFinished(bool)), + this, SIGNAL(loadFinished(bool))); + connect(d->page, SIGNAL(statusBarMessage(const QString &)), + this, SIGNAL(statusBarMessage(const QString &))); + connect(d->page, SIGNAL(linkClicked(const QUrl &)), + this, SIGNAL(linkClicked(const QUrl &))); + + connect(d->page, SIGNAL(microFocusChanged()), + this, SLOT(updateMicroFocus())); + } + update(); +} + +/*! + Loads the specified \a url and displays it. + + \note The view remains the same until enough data has arrived to display the new \a url. + + \sa setUrl(), url(), urlChanged() +*/ +void QWebView::load(const QUrl &url) +{ + page()->mainFrame()->load(url); +} + +/*! + \fn void QWebView::load(const QNetworkRequest &request, QNetworkAccessManager::Operation operation, const QByteArray &body) + + Loads a network request, \a request, using the method specified in \a operation. + + \a body is optional and is only used for POST operations. + + \note The view remains the same until enough data has arrived to display the new url. + + \sa url(), urlChanged() +*/ + +#if QT_VERSION < 0x040400 && !defined(qdoc) +void QWebView::load(const QWebNetworkRequest &request) +#else +void QWebView::load(const QNetworkRequest &request, + QNetworkAccessManager::Operation operation, + const QByteArray &body) +#endif +{ + page()->mainFrame()->load(request +#if QT_VERSION >= 0x040400 + , operation, body +#endif + ); +} + +/*! + Sets the content of the web view to the specified \a html. + + External objects referenced in the HTML document are located relative to + \a baseUrl. + + When using this method, WebKit assumes that external resources such as + JavaScript programs or style sheets are encoded in UTF-8 unless otherwise + specified. For example, the encoding of an external script can be specified + through the charset attribute of the HTML script tag. Alternatively, the + encoding can also be specified by the web server. + + \sa load(), setContent(), QWebFrame::toHtml() +*/ +void QWebView::setHtml(const QString &html, const QUrl &baseUrl) +{ + page()->mainFrame()->setHtml(html, baseUrl); +} + +/*! + Sets the content of the web view to the specified content \a data. If the \a mimeType argument + is empty it is currently assumed that the content is HTML but in future versions we may introduce + auto-detection. + + External objects referenced in the content are located relative to \a baseUrl. + + \sa load(), setHtml(), QWebFrame::toHtml() +*/ +void QWebView::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl) +{ + page()->mainFrame()->setContent(data, mimeType, baseUrl); +} + +/*! + Returns a pointer to the view's history of navigated web pages. + + It is equivalent to + + \snippet doc/src/snippets/code/src_3rdparty_webkit_WebKit_qt_Api_qwebview.cpp 0 +*/ +QWebHistory *QWebView::history() const +{ + return page()->history(); +} + +/*! + Returns a pointer to the view/page specific settings object. + + It is equivalent to + + \snippet doc/src/snippets/code/src_3rdparty_webkit_WebKit_qt_Api_qwebview.cpp 1 + + \sa QWebSettings::globalSettings() +*/ +QWebSettings *QWebView::settings() const +{ + return page()->settings(); +} + +/*! + \property QWebView::title + \brief the title of the web page currently viewed + + By default, this property contains an empty string. + + \sa titleChanged() +*/ +QString QWebView::title() const +{ + if (d->page) + return d->page->mainFrame()->title(); + return QString(); +} + +/*! + \property QWebView::url + \brief the url of the web page currently viewed + + Setting this property clears the view and loads the URL. + + By default, this property contains an empty, invalid URL. + + \sa load(), urlChanged() +*/ + +void QWebView::setUrl(const QUrl &url) +{ + page()->mainFrame()->setUrl(url); +} + +QUrl QWebView::url() const +{ + if (d->page) + return d->page->mainFrame()->url(); + return QUrl(); +} + +/*! + \property QWebView::icon + \brief the icon associated with the web page currently viewed + + By default, this property contains a null icon. + + \sa iconChanged(), QWebSettings::iconForUrl() +*/ +QIcon QWebView::icon() const +{ + if (d->page) + return d->page->mainFrame()->icon(); + return QIcon(); +} + +/*! + \property QWebView::selectedText + \brief the text currently selected + + By default, this property contains an empty string. + + \sa findText(), selectionChanged() +*/ +QString QWebView::selectedText() const +{ + if (d->page) + return d->page->selectedText(); + return QString(); +} + +/*! + Returns a pointer to a QAction that encapsulates the specified web action \a action. +*/ +QAction *QWebView::pageAction(QWebPage::WebAction action) const +{ + return page()->action(action); +} + +/*! + Triggers the specified \a action. If it is a checkable action the specified + \a checked state is assumed. + + The following example triggers the copy action and therefore copies any + selected text to the clipboard. + + \snippet doc/src/snippets/code/src_3rdparty_webkit_WebKit_qt_Api_qwebview.cpp 2 + + \sa pageAction() +*/ +void QWebView::triggerPageAction(QWebPage::WebAction action, bool checked) +{ + page()->triggerAction(action, checked); +} + +/*! + \property QWebView::modified + \brief whether the document was modified by the user + + Parts of HTML documents can be editable for example through the + \c{contenteditable} attribute on HTML elements. + + By default, this property is false. +*/ +bool QWebView::isModified() const +{ + if (d->page) + return d->page->isModified(); + return false; +} + +/* +Qt::TextInteractionFlags QWebView::textInteractionFlags() const +{ + // ### FIXME (add to page) + return Qt::TextInteractionFlags(); +} +*/ + +/* + \property QWebView::textInteractionFlags + \brief how the view should handle user input + + Specifies how the user can interact with the text on the page. +*/ + +/* +void QWebView::setTextInteractionFlags(Qt::TextInteractionFlags flags) +{ + Q_UNUSED(flags) + // ### FIXME (add to page) +} +*/ + +/*! + \reimp +*/ +QSize QWebView::sizeHint() const +{ + return QSize(800, 600); // ####... +} + +/*! + \property QWebView::zoomFactor + \since 4.5 + \brief the zoom factor for the view +*/ + +void QWebView::setZoomFactor(qreal factor) +{ + page()->mainFrame()->setZoomFactor(factor); +} + +qreal QWebView::zoomFactor() const +{ + return page()->mainFrame()->zoomFactor(); +} + +/*! + \property QWebView::textSizeMultiplier + \brief the scaling factor for all text in the frame + \obsolete + + Use setZoomFactor instead, in combination with the + ZoomTextOnly attribute in QWebSettings. + + \note Setting this property also enables the + ZoomTextOnly attribute in QWebSettings. + + By default, this property contains a value of 1.0. +*/ + +void QWebView::setTextSizeMultiplier(qreal factor) +{ + page()->mainFrame()->setTextSizeMultiplier(factor); +} + +qreal QWebView::textSizeMultiplier() const +{ + return page()->mainFrame()->textSizeMultiplier(); +} + +/*! + Finds the next occurrence of the string, \a subString, in the page, using + the given \a options. Returns true of \a subString was found and selects + the match visually; otherwise returns false. + + \sa selectedText(), selectionChanged() +*/ +bool QWebView::findText(const QString &subString, QWebPage::FindFlags options) +{ + if (d->page) + return d->page->findText(subString, options); + return false; +} + +/*! \reimp +*/ +bool QWebView::event(QEvent *e) +{ + if (d->page) { +#ifndef QT_NO_CONTEXTMENU + if (e->type() == QEvent::ContextMenu) { + QContextMenuEvent *event = static_cast<QContextMenuEvent *>(e); + if (d->page->swallowContextMenuEvent(event)) { + e->accept(); + return true; + } + d->page->updatePositionDependentActions(event->pos()); + } else +#endif // QT_NO_CONTEXTMENU + if (e->type() == QEvent::ShortcutOverride) { + d->page->event(e); +#ifndef QT_NO_CURSOR + } else if (e->type() == static_cast<QEvent::Type>(WebCore::SetCursorEvent::EventType)) { + d->setCursor(static_cast<WebCore::SetCursorEvent*>(e)->cursor()); +#if QT_VERSION >= 0x040400 + } else if (e->type() == QEvent::CursorChange) { + // Okay we might use the WebCore Cursor now. + d->usesWebCoreCursor = d->cursorSetByWebCore; + d->cursorSetByWebCore = false; + + // Go back to the WebCore Cursor. QWidget::unsetCursor is appromixated with this + if (!d->usesWebCoreCursor && cursor().shape() == Qt::ArrowCursor) { + d->usesWebCoreCursor = true; + d->setCursor(d->webCoreCursor); + } +#endif +#endif + } else if (e->type() == QEvent::Leave) { + d->page->event(e); + } + } + + return QWidget::event(e); +} + +/*! + Prints the main frame to the given \a printer. + + \sa QWebFrame::print(), QPrintPreviewDialog +*/ +void QWebView::print(QPrinter *printer) const +{ +#ifndef QT_NO_PRINTER + page()->mainFrame()->print(printer); +#endif +} + +/*! + Convenience slot that stops loading the document. + + It is equivalent to + + \snippet doc/src/snippets/code/src_3rdparty_webkit_WebKit_qt_Api_qwebview.cpp 3 + + \sa reload(), pageAction(), loadFinished() +*/ +void QWebView::stop() +{ + if (d->page) + d->page->triggerAction(QWebPage::Stop); +} + +/*! + Convenience slot that loads the previous document in the list of documents + built by navigating links. Does nothing if there is no previous document. + + It is equivalent to + + \snippet doc/src/snippets/code/src_3rdparty_webkit_WebKit_qt_Api_qwebview.cpp 4 + + \sa forward(), pageAction() +*/ +void QWebView::back() +{ + if (d->page) + d->page->triggerAction(QWebPage::Back); +} + +/*! + Convenience slot that loads the next document in the list of documents + built by navigating links. Does nothing if there is no next document. + + It is equivalent to + + \snippet doc/src/snippets/code/src_3rdparty_webkit_WebKit_qt_Api_qwebview.cpp 5 + + \sa back(), pageAction() +*/ +void QWebView::forward() +{ + if (d->page) + d->page->triggerAction(QWebPage::Forward); +} + +/*! + Reloads the current document. + + \sa stop(), pageAction(), loadStarted() +*/ +void QWebView::reload() +{ + if (d->page) + d->page->triggerAction(QWebPage::Reload); +} + +/*! \reimp +*/ +void QWebView::resizeEvent(QResizeEvent *e) +{ + if (d->page) + d->page->setViewportSize(e->size()); +} + +/*! \reimp +*/ +void QWebView::paintEvent(QPaintEvent *ev) +{ + if (!d->page) + return; +#ifdef QWEBKIT_TIME_RENDERING + QTime time; + time.start(); +#endif + + QWebFrame *frame = d->page->mainFrame(); + QPainter p(this); + + frame->render(&p, ev->region()); + +#ifdef QWEBKIT_TIME_RENDERING + int elapsed = time.elapsed(); + qDebug()<<"paint event on "<<ev->region()<<", took to render = "<<elapsed; +#endif +} + +/*! + This function is called whenever WebKit wants to create a new window of the given \a type, for example as a result of + a JavaScript request to open a document in a new window. + + \sa QWebPage::createWindow() +*/ +QWebView *QWebView::createWindow(QWebPage::WebWindowType type) +{ + Q_UNUSED(type) + return 0; +} + +/*! \reimp +*/ +void QWebView::mouseMoveEvent(QMouseEvent* ev) +{ + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } +} + +/*! \reimp +*/ +void QWebView::mousePressEvent(QMouseEvent* ev) +{ + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } +} + +/*! \reimp +*/ +void QWebView::mouseDoubleClickEvent(QMouseEvent* ev) +{ + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } +} + +/*! \reimp +*/ +void QWebView::mouseReleaseEvent(QMouseEvent* ev) +{ + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } +} + +#ifndef QT_NO_CONTEXTMENU +/*! \reimp +*/ +void QWebView::contextMenuEvent(QContextMenuEvent* ev) +{ + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } +} +#endif // QT_NO_CONTEXTMENU + +#ifndef QT_NO_WHEELEVENT +/*! \reimp +*/ +void QWebView::wheelEvent(QWheelEvent* ev) +{ + if (d->page) { + const bool accepted = ev->isAccepted(); + d->page->event(ev); + ev->setAccepted(accepted); + } +} +#endif // QT_NO_WHEELEVENT + +/*! \reimp +*/ +void QWebView::keyPressEvent(QKeyEvent* ev) +{ + if (d->page) + d->page->event(ev); + if (!ev->isAccepted()) + QWidget::keyPressEvent(ev); +} + +/*! \reimp +*/ +void QWebView::keyReleaseEvent(QKeyEvent* ev) +{ + if (d->page) + d->page->event(ev); + if (!ev->isAccepted()) + QWidget::keyReleaseEvent(ev); +} + +/*! \reimp +*/ +void QWebView::focusInEvent(QFocusEvent* ev) +{ + if (d->page) + d->page->event(ev); + else + QWidget::focusInEvent(ev); +} + +/*! \reimp +*/ +void QWebView::focusOutEvent(QFocusEvent* ev) +{ + if (d->page) + d->page->event(ev); + else + QWidget::focusOutEvent(ev); +} + +/*! \reimp +*/ +void QWebView::dragEnterEvent(QDragEnterEvent* ev) +{ +#ifndef QT_NO_DRAGANDDROP + if (d->page) + d->page->event(ev); +#endif +} + +/*! \reimp +*/ +void QWebView::dragLeaveEvent(QDragLeaveEvent* ev) +{ +#ifndef QT_NO_DRAGANDDROP + if (d->page) + d->page->event(ev); +#endif +} + +/*! \reimp +*/ +void QWebView::dragMoveEvent(QDragMoveEvent* ev) +{ +#ifndef QT_NO_DRAGANDDROP + if (d->page) + d->page->event(ev); +#endif +} + +/*! \reimp +*/ +void QWebView::dropEvent(QDropEvent* ev) +{ +#ifndef QT_NO_DRAGANDDROP + if (d->page) + d->page->event(ev); +#endif +} + +/*! \reimp +*/ +bool QWebView::focusNextPrevChild(bool next) +{ + if (d->page && d->page->focusNextPrevChild(next)) + return true; + return QWidget::focusNextPrevChild(next); +} + +/*!\reimp +*/ +QVariant QWebView::inputMethodQuery(Qt::InputMethodQuery property) const +{ + if (d->page) + return d->page->inputMethodQuery(property); + return QVariant(); +} + +/*!\reimp +*/ +void QWebView::inputMethodEvent(QInputMethodEvent *e) +{ + if (d->page) + d->page->event(e); +} + +/*!\reimp +*/ +void QWebView::changeEvent(QEvent *e) +{ + if (d->page && e->type() == QEvent::PaletteChange) { + d->page->setPalette(palette()); + } + QWidget::changeEvent(e); +} + +/*! + \fn void QWebView::titleChanged(const QString &title) + + This signal is emitted whenever the \a title of the main frame changes. + + \sa title() +*/ + +/*! + \fn void QWebView::urlChanged(const QUrl &url) + + This signal is emitted when the \a url of the view changes. + + \sa url(), load() +*/ + +/*! + \fn void QWebView::statusBarMessage(const QString& text) + + This signal is emitted when the statusbar \a text is changed by the page. +*/ + +/*! + \fn void QWebView::iconChanged() + + This signal is emitted whenever the icon of the page is loaded or changes. + + \sa icon() +*/ + +/*! + \fn void QWebView::loadStarted() + + This signal is emitted when a new load of the page is started. + + \sa loadProgress(), loadFinished() +*/ + +/*! + \fn void QWebView::loadFinished(bool ok) + + This signal is emitted when a load of the page is finished. + \a ok will indicate whether the load was successful or any error occurred. + + \sa loadStarted() +*/ + +/*! + \fn void QWebView::selectionChanged() + + This signal is emitted whenever the selection changes. + + \sa selectedText() +*/ + +/*! + \fn void QWebView::loadProgress(int progress) + + This signal is emitted every time an element in the web page + completes loading and the overall loading progress advances. + + This signal tracks the progress of all child frames. + + The current value is provided by \a progress and scales from 0 to 100, + which is the default range of QProgressBar. + + \sa loadStarted(), loadFinished() +*/ + +/*! + \fn void QWebView::linkClicked(const QUrl &url) + + This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy + property is set to delegate the link handling for the specified \a url. + + \sa QWebPage::linkDelegationPolicy() +*/ diff --git a/WebKit/qt/Api/qwebview.h b/WebKit/qt/Api/qwebview.h new file mode 100644 index 0000000..1172f39 --- /dev/null +++ b/WebKit/qt/Api/qwebview.h @@ -0,0 +1,159 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2007 Staikos Computing Services Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QWEBVIEW_H +#define QWEBVIEW_H + +#include "qwebkitglobal.h" +#include "qwebpage.h" +#include <QtGui/qwidget.h> +#include <QtGui/qicon.h> +#include <QtCore/qurl.h> +#if QT_VERSION >= 0x040400 +#include <QtNetwork/qnetworkaccessmanager.h> +#endif + +QT_BEGIN_NAMESPACE +class QNetworkRequest; +class QPrinter; +QT_END_NAMESPACE + +class QWebPage; +class QWebViewPrivate; +class QWebNetworkRequest; + +class QWEBKIT_EXPORT QWebView : public QWidget +{ + Q_OBJECT + Q_PROPERTY(QString title READ title) + Q_PROPERTY(QUrl url READ url WRITE setUrl) + Q_PROPERTY(QIcon icon READ icon) + Q_PROPERTY(QString selectedText READ selectedText) + Q_PROPERTY(bool modified READ isModified) + //Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags WRITE setTextInteractionFlags) + Q_PROPERTY(qreal textSizeMultiplier READ textSizeMultiplier WRITE setTextSizeMultiplier DESIGNABLE false) + Q_PROPERTY(qreal zoomFactor READ zoomFactor WRITE setZoomFactor) +public: + explicit QWebView(QWidget *parent = 0); + virtual ~QWebView(); + + QWebPage *page() const; + void setPage(QWebPage *page); + + void load(const QUrl &url); +#if QT_VERSION < 0x040400 && !defined(qdoc) + void load(const QWebNetworkRequest &request); +#else + void load(const QNetworkRequest &request, + QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation, + const QByteArray &body = QByteArray()); +#endif + void setHtml(const QString &html, const QUrl &baseUrl = QUrl()); + void setContent(const QByteArray &data, const QString &mimeType = QString(), const QUrl &baseUrl = QUrl()); + + QWebHistory *history() const; + QWebSettings *settings() const; + + QString title() const; + void setUrl(const QUrl &url); + QUrl url() const; + QIcon icon() const; + + QString selectedText() const; + + QAction *pageAction(QWebPage::WebAction action) const; + void triggerPageAction(QWebPage::WebAction action, bool checked = false); + + bool isModified() const; + + /* + Qt::TextInteractionFlags textInteractionFlags() const; + void setTextInteractionFlags(Qt::TextInteractionFlags flags); + void setTextInteractionFlag(Qt::TextInteractionFlag flag); + */ + + QVariant inputMethodQuery(Qt::InputMethodQuery property) const; + + QSize sizeHint() const; + + qreal zoomFactor() const; + void setZoomFactor(qreal factor); + + void setTextSizeMultiplier(qreal factor); + qreal textSizeMultiplier() const; + + bool findText(const QString &subString, QWebPage::FindFlags options = 0); + + virtual bool event(QEvent *); + +public Q_SLOTS: + void stop(); + void back(); + void forward(); + void reload(); + + void print(QPrinter *printer) const; + +Q_SIGNALS: + void loadStarted(); + void loadProgress(int progress); + void loadFinished(bool); + void titleChanged(const QString& title); + void statusBarMessage(const QString& text); + void linkClicked(const QUrl &url); + void selectionChanged(); + void iconChanged(); + void urlChanged(const QUrl &url); + +protected: + void resizeEvent(QResizeEvent *e); + void paintEvent(QPaintEvent *ev); + + virtual QWebView *createWindow(QWebPage::WebWindowType type); + + virtual void changeEvent(QEvent*); + virtual void mouseMoveEvent(QMouseEvent*); + virtual void mousePressEvent(QMouseEvent*); + virtual void mouseDoubleClickEvent(QMouseEvent*); + virtual void mouseReleaseEvent(QMouseEvent*); +#ifndef QT_NO_CONTEXTMENU + virtual void contextMenuEvent(QContextMenuEvent*); +#endif +#ifndef QT_NO_WHEELEVENT + virtual void wheelEvent(QWheelEvent*); +#endif + virtual void keyPressEvent(QKeyEvent*); + virtual void keyReleaseEvent(QKeyEvent*); + virtual void dragEnterEvent(QDragEnterEvent *); + virtual void dragLeaveEvent(QDragLeaveEvent *); + virtual void dragMoveEvent(QDragMoveEvent *); + virtual void dropEvent(QDropEvent *); + virtual void focusInEvent(QFocusEvent*); + virtual void focusOutEvent(QFocusEvent*); + virtual void inputMethodEvent(QInputMethodEvent*); + + virtual bool focusNextPrevChild(bool next); + +private: + friend class QWebPage; + QWebViewPrivate *d; +}; + +#endif // QWEBVIEW_H |