File indexing completed on 2024-11-24 04:53:25

0001 /*
0002     Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
0003 
0004     This library is free software; you can redistribute it and/or
0005     modify it under the terms of the GNU Library General Public
0006     License as published by the Free Software Foundation; either
0007     version 2 of the License, or (at your option) any later version.
0008 
0009     This library is distributed in the hope that it will be useful,
0010     but WITHOUT ANY WARRANTY; without even the implied warranty of
0011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012     Library General Public License for more details.
0013 
0014     You should have received a copy of the GNU Library General Public License
0015     along with this library; see the file COPYING.LIB.  If not, write to
0016     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017     Boston, MA 02110-1301, USA.
0018 */
0019 
0020 
0021 #include "qdeclarativewebview_p.h"
0022 
0023 #include <QtCore/QDebug>
0024 #include <QtCore/QEvent>
0025 #include <QtCore/QFile>
0026 #include <QtDeclarative/QDeclarativeContext>
0027 #include <QtDeclarative/QDeclarativeEngine>
0028 #include <QtDeclarative/qdeclarative.h>
0029 #include <QtGui/QApplication>
0030 #include <QtGui/QGraphicsSceneMouseEvent>
0031 #include <QtGui/QKeyEvent>
0032 #include <QtGui/QMouseEvent>
0033 #include <QtGui/QPen>
0034 #include "qwebelement.h"
0035 #include "qwebframe.h"
0036 #include "qwebpage.h"
0037 #include "qwebsettings.h"
0038 
0039 QT_BEGIN_NAMESPACE
0040 
0041 class TrojitaQNAMDeclarativeWebViewPrivate {
0042 public:
0043     TrojitaQNAMDeclarativeWebViewPrivate(TrojitaQNAMDeclarativeWebView* qq)
0044       : q(qq)
0045       , preferredwidth(0)
0046       , preferredheight(0)
0047       , progress(1.0)
0048       , status(TrojitaQNAMDeclarativeWebView::Null)
0049       , pending(PendingNone)
0050       , newWindowComponent(0)
0051       , newWindowParent(0)
0052       , networkAccessManager(0)
0053       , rendering(true)
0054     {
0055     }
0056 
0057     TrojitaQNAMDeclarativeWebView* q;
0058 
0059     QUrl url; // page url might be different if it has not loaded yet
0060     TrojitaQNAMGraphicsWebView* view;
0061 
0062     int preferredwidth, preferredheight;
0063     qreal progress;
0064     TrojitaQNAMDeclarativeWebView::Status status;
0065     QString statusText;
0066     enum { PendingNone, PendingUrl, PendingHtml, PendingContent } pending;
0067     QUrl pendingUrl;
0068     QString pendingString;
0069     QByteArray pendingData;
0070     mutable TrojitaDeclarativeWebSettings settings;
0071     QDeclarativeComponent* newWindowComponent;
0072     QDeclarativeItem* newWindowParent;
0073     QNetworkAccessManager* networkAccessManager;
0074 
0075     static void windowObjectsAppend(QDeclarativeListProperty<QObject>* prop, QObject* o)
0076     {
0077         static_cast<TrojitaQNAMDeclarativeWebViewPrivate*>(prop->data)->windowObjects.append(o);
0078         static_cast<TrojitaQNAMDeclarativeWebViewPrivate*>(prop->data)->updateWindowObjects();
0079     }
0080 
0081     void updateWindowObjects();
0082     QObjectList windowObjects;
0083 
0084     bool rendering;
0085 };
0086 
0087 TrojitaQNAMGraphicsWebView::TrojitaQNAMGraphicsWebView(TrojitaQNAMDeclarativeWebView* parent)
0088     : QGraphicsWebView(parent)
0089     , parent(parent)
0090     , pressTime(400)
0091 {
0092 }
0093 
0094 void TrojitaQNAMGraphicsWebView::mousePressEvent(QGraphicsSceneMouseEvent* event)
0095 {
0096     pressPoint = event->pos();
0097     if (pressTime) {
0098         pressTimer.start(pressTime, this);
0099         parent->setKeepMouseGrab(false);
0100     } else {
0101         grabMouse();
0102         parent->setKeepMouseGrab(true);
0103     }
0104     QGraphicsWebView::mousePressEvent(event);
0105 
0106     QWebHitTestResult hit = page()->mainFrame()->hitTestContent(pressPoint.toPoint());
0107     if (hit.isContentEditable())
0108         parent->forceActiveFocus();
0109     setFocus();
0110 }
0111 
0112 void TrojitaQNAMGraphicsWebView::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
0113 {
0114     QGraphicsWebView::mouseReleaseEvent(event);
0115     pressTimer.stop();
0116     parent->setKeepMouseGrab(false);
0117     ungrabMouse();
0118 }
0119 
0120 void TrojitaQNAMGraphicsWebView::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
0121 {
0122     QMouseEvent* me = new QMouseEvent(QEvent::MouseButtonDblClick, (event->pos() / parent->contentsScale()).toPoint(), event->button(), event->buttons(), 0);
0123     emit doubleClick(event->pos().x(), event->pos().y());
0124     delete me;
0125 }
0126 
0127 void TrojitaQNAMGraphicsWebView::timerEvent(QTimerEvent* event)
0128 {
0129     if (event->timerId() == pressTimer.timerId()) {
0130         pressTimer.stop();
0131         grabMouse();
0132         parent->setKeepMouseGrab(true);
0133     }
0134 }
0135 
0136 void TrojitaQNAMGraphicsWebView::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
0137 {
0138     if (pressTimer.isActive()) {
0139         if ((event->pos() - pressPoint).manhattanLength() > QApplication::startDragDistance())
0140             pressTimer.stop();
0141     }
0142     if (parent->keepMouseGrab())
0143         QGraphicsWebView::mouseMoveEvent(event);
0144 }
0145 
0146 bool TrojitaQNAMGraphicsWebView::sceneEvent(QEvent *event)
0147 {
0148     bool rv = QGraphicsWebView::sceneEvent(event);
0149     if (event->type() == QEvent::UngrabMouse) {
0150         pressTimer.stop();
0151         parent->setKeepMouseGrab(false);
0152     }
0153     return rv;
0154 }
0155 
0156 /*!
0157     \qmlclass WebView QDeclarativeWebView
0158     \ingroup qml-view-elements
0159     \since 4.7
0160     \brief The WebView item allows you to add Web content to a canvas.
0161     \inherits Item
0162 
0163     A WebView renders Web content based on a URL.
0164 
0165     This type is made available by importing the \c QtWebKit module:
0166 
0167     \bold{import QtWebKit 1.0}
0168 
0169     The WebView item includes no scrolling, scaling, toolbars, or other common browser
0170     components. These must be implemented around WebView. See the \l{QML Web Browser}
0171     example for a demonstration of this.
0172 
0173     The page to be displayed by the item is specified using the \l url property,
0174     and this can be changed to fetch and display a new page. While the page loads,
0175     the \l progress property is updated to indicate how much of the page has been
0176     loaded.
0177 
0178     \section1 Appearance
0179 
0180     If the width and height of the item is not set, they will dynamically adjust
0181     to a size appropriate for the content. This width may be large for typical
0182     online web pages, typically greater than 800 by 600 pixels.
0183 
0184     If the \l{Item::}{width} or \l{Item::}{height} is explictly set, the rendered Web site will be
0185     clipped, not scaled, to fit into the set dimensions.
0186 
0187     If the preferredWidth property is set, the width will be this amount or larger,
0188     usually laying out the Web content to fit the preferredWidth.
0189 
0190     The appearance of the content can be controlled to a certain extent by changing
0191     the settings.standardFontFamily property and other settings related to fonts.
0192 
0193     The page can be zoomed by calling the heuristicZoom() method, which performs a
0194     series of tests to determine whether zoomed content will be displayed in an
0195     appropriate way in the space allocated to the item.
0196 
0197     \section1 User Interaction and Navigation
0198 
0199     By default, certain mouse and touch events are delivered to other items in
0200     preference to the Web content. For example, when a scrolling view is created
0201     by placing a WebView in a Flickable, move events are delivered to the Flickable
0202     so that the user can scroll the page. This prevents the user from accidentally
0203     selecting text in a Web page instead of scrolling.
0204 
0205     The pressGrabTime property defines the time the user must touch or press a
0206     mouse button over the WebView before the Web content will receive the move
0207     events it needs to select text and images.
0208 
0209     When this item has keyboard focus, all keyboard input will be sent directly to
0210     the Web page within.
0211 
0212     When the navigates by clicking on links, the item records the pages visited
0213     in its internal history
0214 
0215     Because this item is designed to be used as a component in a browser, it
0216     exposes \l{Action}{actions} for \l back, \l forward, \l reload and \l stop.
0217     These can be triggered to change the current page displayed by the item.
0218 
0219     \section1 Example Usage
0220 
0221     \beginfloatright
0222     \inlineimage webview.png
0223     \endfloat
0224 
0225     The following example displays a scaled down Web page at a fixed size.
0226 
0227     \snippet doc/src/snippets/declarative/webview/webview.qml document
0228 
0229     \clearfloat
0230 
0231     \sa {declarative/modelviews/webview}{WebView example}, {demos/declarative/webbrowser}{Web Browser demo}
0232 */
0233 
0234 /*!
0235     \internal
0236     \class QDeclarativeWebView
0237     \brief The QDeclarativeWebView class allows you to add web content to a QDeclarativeView.
0238 
0239     A WebView renders web content base on a URL.
0240 
0241     \image webview.png
0242 
0243     The item includes no scrolling, scaling,
0244     toolbars, etc., those must be implemented around WebView. See the WebBrowser example
0245     for a demonstration of this.
0246 
0247     A QDeclarativeWebView object can be instantiated in Qml using the tag \l WebView.
0248 */
0249 
0250 TrojitaQNAMDeclarativeWebView::TrojitaQNAMDeclarativeWebView(QDeclarativeItem *parent) : QDeclarativeItem(parent)
0251 {
0252     init();
0253 }
0254 
0255 TrojitaQNAMDeclarativeWebView::~TrojitaQNAMDeclarativeWebView()
0256 {
0257     delete d;
0258 }
0259 
0260 void TrojitaQNAMDeclarativeWebView::init()
0261 {
0262     d = new TrojitaQNAMDeclarativeWebViewPrivate(this);
0263 
0264     if (QWebSettings::iconDatabasePath().isNull() &&
0265         QWebSettings::globalSettings()->localStoragePath().isNull() &&
0266         QWebSettings::offlineStoragePath().isNull() &&
0267         QWebSettings::offlineWebApplicationCachePath().isNull()) 
0268         QWebSettings::enablePersistentStorage();
0269 
0270     setAcceptedMouseButtons(Qt::LeftButton);
0271     setFlag(QGraphicsItem::ItemHasNoContents, true);
0272     setClip(true);
0273 
0274     d->view = new TrojitaQNAMGraphicsWebView(this);
0275     d->view->setResizesToContents(true);
0276     QWebPage* wp = new TrojitaQNAMDeclarativeWebPage(this);
0277     setPage(wp);
0278     connect(d->view, SIGNAL(geometryChanged()), this, SLOT(updateDeclarativeWebViewSize()));
0279     connect(d->view, SIGNAL(doubleClick(int, int)), this, SIGNAL(doubleClick(int, int)));
0280     connect(d->view, SIGNAL(scaleChanged()), this, SIGNAL(contentsScaleChanged()));
0281 }
0282 
0283 void TrojitaQNAMDeclarativeWebView::componentComplete()
0284 {
0285     QDeclarativeItem::componentComplete();
0286 
0287     if (networkAccessManager())
0288         page()->setNetworkAccessManager(networkAccessManager());
0289     else
0290         page()->setNetworkAccessManager(qmlEngine(this)->networkAccessManager());
0291 
0292     switch (d->pending) {
0293     case TrojitaQNAMDeclarativeWebViewPrivate::PendingUrl:
0294         setUrl(d->pendingUrl);
0295         break;
0296     case TrojitaQNAMDeclarativeWebViewPrivate::PendingHtml:
0297         setHtml(d->pendingString, d->pendingUrl);
0298         break;
0299     case TrojitaQNAMDeclarativeWebViewPrivate::PendingContent:
0300         setContent(d->pendingData, d->pendingString, d->pendingUrl);
0301         break;
0302     default:
0303         break;
0304     }
0305     d->pending = TrojitaQNAMDeclarativeWebViewPrivate::PendingNone;
0306     d->updateWindowObjects();
0307 }
0308 
0309 TrojitaQNAMDeclarativeWebView::Status TrojitaQNAMDeclarativeWebView::status() const
0310 {
0311     return d->status;
0312 }
0313 
0314 
0315 /*!
0316     \qmlproperty real WebView::progress
0317     This property holds the progress of loading the current URL, from 0 to 1.
0318 
0319     If you just want to know when progress gets to 1, use
0320     WebView::onLoadFinished() or WebView::onLoadFailed() instead.
0321 */
0322 qreal TrojitaQNAMDeclarativeWebView::progress() const
0323 {
0324     return d->progress;
0325 }
0326 
0327 void TrojitaQNAMDeclarativeWebView::doLoadStarted()
0328 {
0329     if (!d->url.isEmpty()) {
0330         d->status = Loading;
0331         emit statusChanged(d->status);
0332     }
0333     emit loadStarted();
0334 }
0335 
0336 void TrojitaQNAMDeclarativeWebView::doLoadProgress(int p)
0337 {
0338     if (d->progress == p / 100.0)
0339         return;
0340     d->progress = p / 100.0;
0341     emit progressChanged();
0342 }
0343 
0344 void TrojitaQNAMDeclarativeWebView::pageUrlChanged()
0345 {
0346     updateContentsSize();
0347 
0348     if ((d->url.isEmpty() && page()->mainFrame()->url() != QUrl(QLatin1String("about:blank")))
0349         || (d->url != page()->mainFrame()->url() && !page()->mainFrame()->url().isEmpty()))
0350     {
0351         d->url = page()->mainFrame()->url();
0352         if (d->url == QUrl(QLatin1String("about:blank")))
0353             d->url = QUrl();
0354         emit urlChanged();
0355     }
0356 }
0357 
0358 void TrojitaQNAMDeclarativeWebView::doLoadFinished(bool ok)
0359 {
0360     if (ok) {
0361         d->status = d->url.isEmpty() ? Null : Ready;
0362         emit loadFinished();
0363     } else {
0364         d->status = Error;
0365         emit loadFailed();
0366     }
0367     emit statusChanged(d->status);
0368 }
0369 
0370 /*!
0371     \qmlproperty url WebView::url
0372     This property holds the URL to the page displayed in this item. It can be set,
0373     but also can change spontaneously (eg. because of network redirection).
0374 
0375     If the url is empty, the page is blank.
0376 
0377     The url is always absolute (QML will resolve relative URL strings in the context
0378     of the containing QML document).
0379 */
0380 QUrl TrojitaQNAMDeclarativeWebView::url() const
0381 {
0382     return d->url;
0383 }
0384 
0385 void TrojitaQNAMDeclarativeWebView::setUrl(const QUrl& url)
0386 {
0387     if (url == d->url)
0388         return;
0389 
0390     if (isComponentComplete()) {
0391         d->url = url;
0392         updateContentsSize();
0393         QUrl seturl = url;
0394         if (seturl.isEmpty())
0395             seturl = QUrl(QLatin1String("about:blank"));
0396 
0397         Q_ASSERT(!seturl.isRelative());
0398 
0399         page()->mainFrame()->load(seturl);
0400 
0401         emit urlChanged();
0402 
0403     } else {
0404         d->pending = d->PendingUrl;
0405         d->pendingUrl = url;
0406     }
0407 }
0408 
0409 /*!
0410     \qmlproperty int WebView::preferredWidth
0411     This property holds the ideal width for displaying the current URL.
0412 */
0413 int TrojitaQNAMDeclarativeWebView::preferredWidth() const
0414 {
0415     return d->preferredwidth;
0416 }
0417 
0418 void TrojitaQNAMDeclarativeWebView::setPreferredWidth(int width)
0419 {
0420     if (d->preferredwidth == width)
0421         return;
0422     d->preferredwidth = width;
0423     updateContentsSize();
0424     emit preferredWidthChanged();
0425 }
0426 
0427 /*!
0428     \qmlproperty int WebView::preferredHeight
0429     This property holds the ideal height for displaying the current URL.
0430     This only affects the area zoomed by heuristicZoom().
0431 */
0432 int TrojitaQNAMDeclarativeWebView::preferredHeight() const
0433 {
0434     return d->preferredheight;
0435 }
0436 
0437 void TrojitaQNAMDeclarativeWebView::setPreferredHeight(int height)
0438 {
0439     if (d->preferredheight == height)
0440         return;
0441     d->preferredheight = height;
0442     updateContentsSize();
0443     emit preferredHeightChanged();
0444 }
0445 
0446 /*!
0447     \qmlmethod bool WebView::evaluateJavaScript(string scriptSource)
0448 
0449     Evaluates the \a scriptSource JavaScript inside the context of the
0450     main web frame, and returns the result of the last executed statement.
0451 
0452     Note that this JavaScript does \e not have any access to QML objects
0453     except as made available as windowObjects.
0454 */
0455 QVariant TrojitaQNAMDeclarativeWebView::evaluateJavaScript(const QString& scriptSource)
0456 {
0457     return this->page()->mainFrame()->evaluateJavaScript(scriptSource);
0458 }
0459 
0460 void TrojitaQNAMDeclarativeWebView::updateDeclarativeWebViewSize()
0461 {
0462     QSizeF size = d->view->geometry().size() * contentsScale();
0463     setImplicitWidth(size.width());
0464     setImplicitHeight(size.height());
0465 }
0466 
0467 void TrojitaQNAMDeclarativeWebView::initialLayout()
0468 {
0469     // nothing useful to do at this point
0470 }
0471 
0472 void TrojitaQNAMDeclarativeWebView::updateContentsSize()
0473 {
0474     if (page()) {
0475         page()->setPreferredContentsSize(QSize(
0476             d->preferredwidth>0 ? d->preferredwidth : width(),
0477             d->preferredheight>0 ? d->preferredheight : height()));
0478     }
0479 }
0480 
0481 void TrojitaQNAMDeclarativeWebView::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry)
0482 {
0483     QWebPage* webPage = page();
0484     if (newGeometry.size() != oldGeometry.size() && webPage) {
0485         QSize contentSize = webPage->preferredContentsSize();
0486         if (widthValid())
0487             contentSize.setWidth(width());
0488         if (heightValid())
0489             contentSize.setHeight(height());
0490         if (contentSize != webPage->preferredContentsSize())
0491             webPage->setPreferredContentsSize(contentSize);
0492     }
0493     QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
0494 }
0495 
0496 /*!
0497     \qmlproperty list<object> WebView::javaScriptWindowObjects
0498 
0499     A list of QML objects to expose to the web page.
0500 
0501     Each object will be added as a property of the web frame's window object.  The
0502     property name is controlled by the value of \c WebView.windowObjectName
0503     attached property.
0504 
0505     Exposing QML objects to a web page allows JavaScript executing in the web
0506     page itself to communicate with QML, by reading and writing properties and
0507     by calling methods of the exposed QML objects.
0508 
0509     This example shows how to call into a QML method using a window object.
0510 
0511     \qml
0512     WebView {
0513         javaScriptWindowObjects: QtObject {
0514             WebView.windowObjectName: "qml"
0515 
0516             function qmlCall() {
0517                 console.log("This call is in QML!");
0518             }
0519         }
0520 
0521         html: "<script>console.log(\"This is in WebKit!\"); window.qml.qmlCall();</script>"
0522     }
0523     \endqml
0524 
0525     The output of the example will be:
0526     \code
0527     This is in WebKit!
0528     This call is in QML!
0529     \endcode
0530 
0531     If Javascript is not enabled for the page, then this property does nothing.
0532 */
0533 QDeclarativeListProperty<QObject> TrojitaQNAMDeclarativeWebView::javaScriptWindowObjects()
0534 {
0535     return QDeclarativeListProperty<QObject>(this, d, &TrojitaQNAMDeclarativeWebViewPrivate::windowObjectsAppend);
0536 }
0537 
0538 TrojitaQNAMDeclarativeWebViewAttached* TrojitaQNAMDeclarativeWebView::qmlAttachedProperties(QObject* o)
0539 {
0540     return new TrojitaQNAMDeclarativeWebViewAttached(o);
0541 }
0542 
0543 void TrojitaQNAMDeclarativeWebViewPrivate::updateWindowObjects()
0544 {
0545     if (!q->isComponentCompletePublic() || !q->page())
0546         return;
0547 
0548     for (int i = 0; i < windowObjects.count(); ++i) {
0549         QObject* object = windowObjects.at(i);
0550         TrojitaQNAMDeclarativeWebViewAttached* attached = static_cast<TrojitaQNAMDeclarativeWebViewAttached *>(qmlAttachedPropertiesObject<TrojitaQNAMDeclarativeWebView>(object));
0551         if (attached && !attached->windowObjectName().isEmpty())
0552             q->page()->mainFrame()->addToJavaScriptWindowObject(attached->windowObjectName(), object);
0553     }
0554 }
0555 
0556 bool TrojitaQNAMDeclarativeWebView::renderingEnabled() const
0557 {
0558     return d->rendering;
0559 }
0560 
0561 void TrojitaQNAMDeclarativeWebView::setRenderingEnabled(bool enabled)
0562 {
0563     if (d->rendering == enabled)
0564         return;
0565     d->rendering = enabled;
0566     emit renderingEnabledChanged();
0567     d->view->setTiledBackingStoreFrozen(!enabled);
0568 }
0569 
0570 /*!
0571     \qmlsignal WebView::onDoubleClick(int clickx, int clicky)
0572 
0573     The WebView does not pass double-click events to the web engine, but rather
0574     emits this signals.
0575 */
0576 
0577 /*!
0578     \qmlmethod bool WebView::heuristicZoom(int clickX, int clickY, real maxzoom)
0579 
0580     Finds a zoom that:
0581     \list
0582     \i shows a whole item
0583     \i includes (\a clickX, \a clickY)
0584     \i fits into the preferredWidth and preferredHeight
0585     \i zooms by no more than \a maxZoom
0586     \i is more than 10% above the current zoom
0587     \endlist
0588 
0589     If such a zoom exists, emits zoomTo(zoom,centerX,centerY) and returns true; otherwise,
0590     no signal is emitted and returns false.
0591 */
0592 bool TrojitaQNAMDeclarativeWebView::heuristicZoom(int clickX, int clickY, qreal maxZoom)
0593 {
0594     if (contentsScale() >= maxZoom / scale())
0595         return false;
0596     qreal ozf = contentsScale();
0597     QRect showArea = elementAreaAt(clickX, clickY, d->preferredwidth / maxZoom, d->preferredheight / maxZoom);
0598     qreal z = qMin(qreal(d->preferredwidth) / showArea.width(), qreal(d->preferredheight) / showArea.height());
0599     if (z > maxZoom / scale())
0600         z = maxZoom / scale();
0601     if (z / ozf > 1.2) {
0602         QRectF r(showArea.left() * z, showArea.top() * z, showArea.width() * z, showArea.height() * z);
0603         emit zoomTo(z, r.x() + r.width() / 2, r.y() + r.height() / 2);
0604         return true;
0605     }
0606     return false;
0607 }
0608 
0609 /*!
0610     \qmlproperty int WebView::pressGrabTime
0611 
0612     The number of milliseconds the user must press before the WebView
0613     starts passing move events through to the Web engine (rather than
0614     letting other QML elements such as a Flickable take them).
0615 
0616     Defaults to 400ms. Set to 0 to always grab and pass move events to
0617     the Web engine.
0618 */
0619 int TrojitaQNAMDeclarativeWebView::pressGrabTime() const
0620 {
0621     return d->view->pressTime;
0622 }
0623 
0624 void TrojitaQNAMDeclarativeWebView::setPressGrabTime(int millis)
0625 {
0626     if (d->view->pressTime == millis)
0627         return;
0628     d->view->pressTime = millis;
0629     emit pressGrabTimeChanged();
0630 }
0631 
0632 #ifndef QT_NO_ACTION
0633 /*!
0634     \qmlproperty action WebView::back
0635     This property holds the action for causing the previous URL in the history to be displayed.
0636 */
0637 QAction* TrojitaQNAMDeclarativeWebView::backAction() const
0638 {
0639     return page()->action(QWebPage::Back);
0640 }
0641 
0642 /*!
0643     \qmlproperty action WebView::forward
0644     This property holds the action for causing the next URL in the history to be displayed.
0645 */
0646 QAction* TrojitaQNAMDeclarativeWebView::forwardAction() const
0647 {
0648     return page()->action(QWebPage::Forward);
0649 }
0650 
0651 /*!
0652     \qmlproperty action WebView::reload
0653     This property holds the action for reloading with the current URL
0654 */
0655 QAction* TrojitaQNAMDeclarativeWebView::reloadAction() const
0656 {
0657     return page()->action(QWebPage::Reload);
0658 }
0659 
0660 /*!
0661     \qmlproperty action WebView::stop
0662     This property holds the action for stopping loading with the current URL
0663 */
0664 QAction* TrojitaQNAMDeclarativeWebView::stopAction() const
0665 {
0666     return page()->action(QWebPage::Stop);
0667 }
0668 #endif // QT_NO_ACTION
0669 
0670 /*!
0671     \qmlproperty string WebView::title
0672     This property holds the title of the web page currently viewed
0673 
0674     By default, this property contains an empty string.
0675 */
0676 QString TrojitaQNAMDeclarativeWebView::title() const
0677 {
0678     return page()->mainFrame()->title();
0679 }
0680 
0681 /*!
0682     \qmlproperty pixmap WebView::icon
0683     This property holds the icon associated with the web page currently viewed
0684 */
0685 QPixmap TrojitaQNAMDeclarativeWebView::icon() const
0686 {
0687     return page()->mainFrame()->icon().pixmap(QSize(256, 256));
0688 }
0689 
0690 /*!
0691     \qmlproperty string WebView::statusText
0692 
0693     This property is the current status suggested by the current web page. In a web browser,
0694     such status is often shown in some kind of status bar.
0695 */
0696 void TrojitaQNAMDeclarativeWebView::setStatusText(const QString& text)
0697 {
0698     d->statusText = text;
0699     emit statusTextChanged();
0700 }
0701 
0702 void TrojitaQNAMDeclarativeWebView::windowObjectCleared()
0703 {
0704     d->updateWindowObjects();
0705 }
0706 
0707 QString TrojitaQNAMDeclarativeWebView::statusText() const
0708 {
0709     return d->statusText;
0710 }
0711 
0712 QWebPage* TrojitaQNAMDeclarativeWebView::page() const
0713 {
0714     return d->view->page();
0715 }
0716 
0717 // The QObject interface to settings().
0718 /*!
0719     \qmlproperty string WebView::settings.standardFontFamily
0720     \qmlproperty string WebView::settings.fixedFontFamily
0721     \qmlproperty string WebView::settings.serifFontFamily
0722     \qmlproperty string WebView::settings.sansSerifFontFamily
0723     \qmlproperty string WebView::settings.cursiveFontFamily
0724     \qmlproperty string WebView::settings.fantasyFontFamily
0725 
0726     \qmlproperty int WebView::settings.minimumFontSize
0727     \qmlproperty int WebView::settings.minimumLogicalFontSize
0728     \qmlproperty int WebView::settings.defaultFontSize
0729     \qmlproperty int WebView::settings.defaultFixedFontSize
0730 
0731     \qmlproperty bool WebView::settings.autoLoadImages
0732     \qmlproperty bool WebView::settings.javascriptEnabled
0733     \qmlproperty bool WebView::settings.javaEnabled
0734     \qmlproperty bool WebView::settings.pluginsEnabled
0735     \qmlproperty bool WebView::settings.privateBrowsingEnabled
0736     \qmlproperty bool WebView::settings.javascriptCanOpenWindows
0737     \qmlproperty bool WebView::settings.javascriptCanAccessClipboard
0738     \qmlproperty bool WebView::settings.developerExtrasEnabled
0739     \qmlproperty bool WebView::settings.linksIncludedInFocusChain
0740     \qmlproperty bool WebView::settings.zoomTextOnly
0741     \qmlproperty bool WebView::settings.printElementBackgrounds
0742     \qmlproperty bool WebView::settings.offlineStorageDatabaseEnabled
0743     \qmlproperty bool WebView::settings.offlineWebApplicationCacheEnabled
0744     \qmlproperty bool WebView::settings.localStorageDatabaseEnabled
0745     \qmlproperty bool WebView::settings.localContentCanAccessRemoteUrls
0746 
0747     These properties give access to the settings controlling the web view.
0748 
0749     See QWebSettings for details of these properties.
0750 
0751     \qml
0752     WebView {
0753         settings.pluginsEnabled: true
0754         settings.standardFontFamily: "Arial"
0755         // ...
0756     }
0757     \endqml
0758 */
0759 TrojitaDeclarativeWebSettings* TrojitaQNAMDeclarativeWebView::settingsObject() const
0760 {
0761     d->settings.s = page()->settings();
0762     return &d->settings;
0763 }
0764 
0765 void TrojitaQNAMDeclarativeWebView::setPage(QWebPage* page)
0766 {
0767     if (d->view->page() == page)
0768         return;
0769 
0770     d->view->setPage(page);
0771     updateContentsSize();
0772     page->mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
0773     page->mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
0774     connect(page->mainFrame(), SIGNAL(urlChanged(QUrl)), this, SLOT(pageUrlChanged()));
0775     connect(page->mainFrame(), SIGNAL(titleChanged(QString)), this, SIGNAL(titleChanged(QString)));
0776     connect(page->mainFrame(), SIGNAL(titleChanged(QString)), this, SIGNAL(iconChanged()));
0777     connect(page->mainFrame(), SIGNAL(iconChanged()), this, SIGNAL(iconChanged()));
0778     connect(page->mainFrame(), SIGNAL(initialLayoutCompleted()), this, SLOT(initialLayout()));
0779     connect(page->mainFrame(), SIGNAL(contentsSizeChanged(QSize)), this, SIGNAL(contentsSizeChanged(QSize)));
0780 
0781     connect(page, SIGNAL(loadStarted()), this, SLOT(doLoadStarted()));
0782     connect(page, SIGNAL(loadProgress(int)), this, SLOT(doLoadProgress(int)));
0783     connect(page, SIGNAL(loadFinished(bool)), this, SLOT(doLoadFinished(bool)));
0784     connect(page, SIGNAL(statusBarMessage(QString)), this, SLOT(setStatusText(QString)));
0785 
0786     connect(page->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(windowObjectCleared()));
0787 
0788     page->settings()->setAttribute(QWebSettings::TiledBackingStoreEnabled, true);
0789 }
0790 
0791 /*!
0792     \qmlsignal WebView::onLoadStarted()
0793 
0794     This handler is called when the web engine begins loading
0795     a page. Later, WebView::onLoadFinished() or WebView::onLoadFailed()
0796     will be emitted.
0797 */
0798 
0799 /*!
0800     \qmlsignal WebView::onLoadFinished()
0801 
0802     This handler is called when the web engine \e successfully
0803     finishes loading a page, including any component content
0804     (WebView::onLoadFailed() will be emitted otherwise).
0805 
0806     \sa progress
0807 */
0808 
0809 /*!
0810     \qmlsignal WebView::onLoadFailed()
0811 
0812     This handler is called when the web engine fails loading
0813     a page or any component content
0814     (WebView::onLoadFinished() will be emitted on success).
0815 */
0816 
0817 void TrojitaQNAMDeclarativeWebView::load(const QNetworkRequest& request, QNetworkAccessManager::Operation operation, const QByteArray& body)
0818 {
0819     page()->mainFrame()->load(request, operation, body);
0820 }
0821 
0822 QString TrojitaQNAMDeclarativeWebView::html() const
0823 {
0824     return page()->mainFrame()->toHtml();
0825 }
0826 
0827 /*!
0828     \qmlproperty string WebView::html
0829     This property holds HTML text set directly
0830 
0831     The html property can be set as a string.
0832 
0833     \qml
0834     WebView {
0835         html: "<p>This is <b>HTML</b>."
0836     }
0837     \endqml
0838 */
0839 void TrojitaQNAMDeclarativeWebView::setHtml(const QString& html, const QUrl& baseUrl)
0840 {
0841     updateContentsSize();
0842     if (isComponentComplete())
0843         page()->mainFrame()->setHtml(html, baseUrl);
0844     else {
0845         d->pending = d->PendingHtml;
0846         d->pendingUrl = baseUrl;
0847         d->pendingString = html;
0848     }
0849     emit htmlChanged();
0850 }
0851 
0852 void TrojitaQNAMDeclarativeWebView::setContent(const QByteArray& data, const QString& mimeType, const QUrl& baseUrl)
0853 {
0854     updateContentsSize();
0855 
0856     if (isComponentComplete())
0857         page()->mainFrame()->setContent(data, mimeType, qmlContext(this)->resolvedUrl(baseUrl));
0858     else {
0859         d->pending = d->PendingContent;
0860         d->pendingUrl = baseUrl;
0861         d->pendingString = mimeType;
0862         d->pendingData = data;
0863     }
0864 }
0865 
0866 QWebHistory* TrojitaQNAMDeclarativeWebView::history() const
0867 {
0868     return page()->history();
0869 }
0870 
0871 QWebSettings* TrojitaQNAMDeclarativeWebView::settings() const
0872 {
0873     return page()->settings();
0874 }
0875 
0876 TrojitaQNAMDeclarativeWebView* TrojitaQNAMDeclarativeWebView::createWindow(QWebPage::WebWindowType type)
0877 {
0878     switch (type) {
0879     case QWebPage::WebBrowserWindow: {
0880         if (!d->newWindowComponent && d->newWindowParent)
0881             qWarning("WebView::newWindowComponent not set - WebView::newWindowParent ignored");
0882         else if (d->newWindowComponent && !d->newWindowParent)
0883             qWarning("WebView::newWindowParent not set - WebView::newWindowComponent ignored");
0884         else if (d->newWindowComponent && d->newWindowParent) {
0885             TrojitaQNAMDeclarativeWebView* webview = 0;
0886             QDeclarativeContext* windowContext = new QDeclarativeContext(qmlContext(this));
0887 
0888             QObject* newObject = d->newWindowComponent->create(windowContext);
0889             if (newObject) {
0890                 windowContext->setParent(newObject);
0891                 QDeclarativeItem* item = qobject_cast<QDeclarativeItem *>(newObject);
0892                 if (!item)
0893                     delete newObject;
0894                 else {
0895                     webview = item->findChild<TrojitaQNAMDeclarativeWebView*>();
0896                     if (!webview)
0897                         delete item;
0898                     else {
0899                         newObject->setParent(d->newWindowParent);
0900                         static_cast<QGraphicsObject*>(item)->setParentItem(d->newWindowParent);
0901                     }
0902                 }
0903             } else
0904                 delete windowContext;
0905 
0906             return webview;
0907         }
0908     }
0909     break;
0910     case QWebPage::WebModalDialog: {
0911         // Not supported
0912     }
0913     }
0914     return 0;
0915 }
0916 
0917 /*!
0918     \qmlproperty component WebView::newWindowComponent
0919 
0920     This property holds the component to use for new windows.
0921     The component must have a WebView somewhere in its structure.
0922 
0923     When the web engine requests a new window, it will be an instance of
0924     this component.
0925 
0926     The parent of the new window is set by newWindowParent. It must be set.
0927 */
0928 QDeclarativeComponent* TrojitaQNAMDeclarativeWebView::newWindowComponent() const
0929 {
0930     return d->newWindowComponent;
0931 }
0932 
0933 void TrojitaQNAMDeclarativeWebView::setNewWindowComponent(QDeclarativeComponent* newWindow)
0934 {
0935     if (newWindow == d->newWindowComponent)
0936         return;
0937     d->newWindowComponent = newWindow;
0938     emit newWindowComponentChanged();
0939 }
0940 
0941 
0942 /*!
0943     \qmlproperty item WebView::newWindowParent
0944 
0945     The parent item for new windows.
0946 
0947     \sa newWindowComponent
0948 */
0949 QDeclarativeItem* TrojitaQNAMDeclarativeWebView::newWindowParent() const
0950 {
0951     return d->newWindowParent;
0952 }
0953 
0954 void TrojitaQNAMDeclarativeWebView::setNewWindowParent(QDeclarativeItem* parent)
0955 {
0956     if (parent == d->newWindowParent)
0957         return;
0958     if (d->newWindowParent && parent) {
0959         QList<QGraphicsItem *> children = d->newWindowParent->childItems();
0960         for (int i = 0; i < children.count(); ++i)
0961             children.at(i)->setParentItem(parent);
0962     }
0963     d->newWindowParent = parent;
0964     emit newWindowParentChanged();
0965 }
0966 
0967 QSize TrojitaQNAMDeclarativeWebView::contentsSize() const
0968 {
0969     return page()->mainFrame()->contentsSize() * contentsScale();
0970 }
0971 
0972 qreal TrojitaQNAMDeclarativeWebView::contentsScale() const
0973 {
0974     return d->view->scale();
0975 }
0976 
0977 void TrojitaQNAMDeclarativeWebView::setContentsScale(qreal scale)
0978 {
0979     if (scale == d->view->scale())
0980         return;
0981     d->view->setScale(scale);
0982     updateDeclarativeWebViewSize();
0983     emit contentsScaleChanged();
0984 }
0985 
0986 /*!
0987     Returns the area of the largest element at position (\a x,\a y) that is no larger
0988     than \a maxWidth by \a maxHeight pixels.
0989 
0990     May return an area larger in the case when no smaller element is at the position.
0991 */
0992 QRect TrojitaQNAMDeclarativeWebView::elementAreaAt(int x, int y, int maxWidth, int maxHeight) const
0993 {
0994     QWebHitTestResult hit = page()->mainFrame()->hitTestContent(QPoint(x, y));
0995     QRect hitRect = hit.boundingRect();
0996     QWebElement element = hit.enclosingBlockElement();
0997     if (maxWidth <= 0)
0998         maxWidth = INT_MAX;
0999     if (maxHeight <= 0)
1000         maxHeight = INT_MAX;
1001     while (!element.parent().isNull() && element.geometry().width() <= maxWidth && element.geometry().height() <= maxHeight) {
1002         hitRect = element.geometry();
1003         element = element.parent();
1004     }
1005     return hitRect;
1006 }
1007 
1008 QNetworkAccessManager *TrojitaQNAMDeclarativeWebView::networkAccessManager() const
1009 {
1010     return d->networkAccessManager;
1011 }
1012 
1013 void TrojitaQNAMDeclarativeWebView::setNetworkAccessManager(QNetworkAccessManager *manager)
1014 {
1015     if (manager) {
1016         d->networkAccessManager = manager;
1017         page()->setNetworkAccessManager(manager);
1018     }
1019 }
1020 
1021 /*!
1022     \internal
1023     \class TrojitaQNAMDeclarativeWebPage
1024     \brief The TrojitaQNAMDeclarativeWebPage class is a QWebPage that can create QML plugins.
1025 
1026     \sa QDeclarativeWebView
1027 */
1028 TrojitaQNAMDeclarativeWebPage::TrojitaQNAMDeclarativeWebPage(TrojitaQNAMDeclarativeWebView* parent) :
1029     QWebPage(parent)
1030 {
1031 }
1032 
1033 TrojitaQNAMDeclarativeWebPage::~TrojitaQNAMDeclarativeWebPage()
1034 {
1035 }
1036 
1037 QString TrojitaQNAMDeclarativeWebPage::chooseFile(QWebFrame* originatingFrame, const QString& oldFile)
1038 {
1039     // Not supported (it's modal)
1040     Q_UNUSED(originatingFrame)
1041     Q_UNUSED(oldFile)
1042     return oldFile;
1043 }
1044 
1045 /*!
1046     \qmlsignal WebView::onAlert(string message)
1047 
1048     The handler is called when the web engine sends a JavaScript alert. The \a message is the text
1049     to be displayed in the alert to the user.
1050 */
1051 
1052 
1053 void TrojitaQNAMDeclarativeWebPage::javaScriptAlert(QWebFrame* originatingFrame, const QString& msg)
1054 {
1055     Q_UNUSED(originatingFrame)
1056     emit viewItem()->alert(msg);
1057 }
1058 
1059 bool TrojitaQNAMDeclarativeWebPage::javaScriptConfirm(QWebFrame* originatingFrame, const QString& msg)
1060 {
1061     // Not supported (it's modal)
1062     Q_UNUSED(originatingFrame)
1063     Q_UNUSED(msg)
1064     return false;
1065 }
1066 
1067 bool TrojitaQNAMDeclarativeWebPage::javaScriptPrompt(QWebFrame* originatingFrame, const QString& msg, const QString& defaultValue, QString* result)
1068 {
1069     // Not supported (it's modal)
1070     Q_UNUSED(originatingFrame)
1071     Q_UNUSED(msg)
1072     Q_UNUSED(defaultValue)
1073     Q_UNUSED(result)
1074     return false;
1075 }
1076 
1077 
1078 TrojitaQNAMDeclarativeWebView* TrojitaQNAMDeclarativeWebPage::viewItem()
1079 {
1080     return static_cast<TrojitaQNAMDeclarativeWebView*>(parent());
1081 }
1082 
1083 QWebPage* TrojitaQNAMDeclarativeWebPage::createWindow(WebWindowType type)
1084 {
1085     TrojitaQNAMDeclarativeWebView* newView = viewItem()->createWindow(type);
1086     if (newView)
1087         return newView->page();
1088     return 0;
1089 }
1090 
1091 QT_END_NAMESPACE
1092