WebKit/qt/declarative/qdeclarativewebview.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2     Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
       
     3 
       
     4     This library is free software; you can redistribute it and/or
       
     5     modify it under the terms of the GNU Library General Public
       
     6     License as published by the Free Software Foundation; either
       
     7     version 2 of the License, or (at your option) any later version.
       
     8 
       
     9     This library is distributed in the hope that it will be useful,
       
    10     but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    12     Library General Public License for more details.
       
    13 
       
    14     You should have received a copy of the GNU Library General Public License
       
    15     along with this library; see the file COPYING.LIB.  If not, write to
       
    16     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
       
    17     Boston, MA 02110-1301, USA.
       
    18 */
       
    19 
       
    20 
       
    21 #include "qdeclarativewebview_p.h"
       
    22 
       
    23 #include <QtCore/QDebug>
       
    24 #include <QtCore/QEvent>
       
    25 #include <QtCore/QFile>
       
    26 #include <QtDeclarative/QDeclarativeContext>
       
    27 #include <QtDeclarative/QDeclarativeEngine>
       
    28 #include <QtDeclarative/qdeclarative.h>
       
    29 #include <QtGui/QApplication>
       
    30 #include <QtGui/QGraphicsSceneMouseEvent>
       
    31 #include <QtGui/QKeyEvent>
       
    32 #include <QtGui/QMouseEvent>
       
    33 #include <QtGui/QPen>
       
    34 #include "qwebelement.h"
       
    35 #include "qwebframe.h"
       
    36 #include "qwebpage.h"
       
    37 #include "qwebsettings.h"
       
    38 
       
    39 QT_BEGIN_NAMESPACE
       
    40 
       
    41 class QDeclarativeWebViewPrivate {
       
    42 public:
       
    43     QDeclarativeWebViewPrivate(QDeclarativeWebView* qq)
       
    44       : q(qq)
       
    45       , preferredwidth(0)
       
    46       , preferredheight(0)
       
    47       , progress(1.0)
       
    48       , status(QDeclarativeWebView::Null)
       
    49       , pending(PendingNone)
       
    50       , newWindowComponent(0)
       
    51       , newWindowParent(0)
       
    52       , rendering(true)
       
    53     {
       
    54     }
       
    55 
       
    56     QDeclarativeWebView* q;
       
    57 
       
    58     QUrl url; // page url might be different if it has not loaded yet
       
    59     GraphicsWebView* view;
       
    60 
       
    61     int preferredwidth, preferredheight;
       
    62     qreal progress;
       
    63     QDeclarativeWebView::Status status;
       
    64     QString statusText;
       
    65     enum { PendingNone, PendingUrl, PendingHtml, PendingContent } pending;
       
    66     QUrl pendingUrl;
       
    67     QString pendingString;
       
    68     QByteArray pendingData;
       
    69     mutable QDeclarativeWebSettings settings;
       
    70     QDeclarativeComponent* newWindowComponent;
       
    71     QDeclarativeItem* newWindowParent;
       
    72 
       
    73     static void windowObjectsAppend(QDeclarativeListProperty<QObject>* prop, QObject* o)
       
    74     {
       
    75         static_cast<QDeclarativeWebViewPrivate*>(prop->data)->windowObjects.append(o);
       
    76         static_cast<QDeclarativeWebViewPrivate*>(prop->data)->updateWindowObjects();
       
    77     }
       
    78 
       
    79     void updateWindowObjects();
       
    80     QObjectList windowObjects;
       
    81 
       
    82     bool rendering;
       
    83 };
       
    84 
       
    85 GraphicsWebView::GraphicsWebView(QDeclarativeWebView* parent)
       
    86     : QGraphicsWebView(parent)
       
    87     , parent(parent)
       
    88     , pressTime(400)
       
    89 {
       
    90 }
       
    91 
       
    92 void GraphicsWebView::mousePressEvent(QGraphicsSceneMouseEvent* event)
       
    93 {
       
    94     setFocus();
       
    95     pressPoint = event->pos();
       
    96     if (pressTime) {
       
    97         pressTimer.start(pressTime, this);
       
    98         parent->setKeepMouseGrab(false);
       
    99     } else {
       
   100         grabMouse();
       
   101         parent->setKeepMouseGrab(true);
       
   102     }
       
   103     QGraphicsWebView::mousePressEvent(event);
       
   104 }
       
   105 
       
   106 void GraphicsWebView::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
       
   107 {
       
   108     QGraphicsWebView::mouseReleaseEvent(event);
       
   109     pressTimer.stop();
       
   110     parent->setKeepMouseGrab(false);
       
   111     ungrabMouse();
       
   112 }
       
   113 
       
   114 void GraphicsWebView::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
       
   115 {
       
   116     QMouseEvent* me = new QMouseEvent(QEvent::MouseButtonDblClick, (event->pos() / parent->contentsScale()).toPoint(), event->button(), event->buttons(), 0);
       
   117     emit doubleClick(event->pos().x(), event->pos().y());
       
   118     delete me;
       
   119 }
       
   120 
       
   121 void GraphicsWebView::timerEvent(QTimerEvent* event)
       
   122 {
       
   123     if (event->timerId() == pressTimer.timerId()) {
       
   124         pressTimer.stop();
       
   125         grabMouse();
       
   126         parent->setKeepMouseGrab(true);
       
   127     }
       
   128 }
       
   129 
       
   130 void GraphicsWebView::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
       
   131 {
       
   132     if (pressTimer.isActive()) {
       
   133         if ((event->pos() - pressPoint).manhattanLength() > QApplication::startDragDistance())
       
   134             pressTimer.stop();
       
   135     }
       
   136     if (parent->keepMouseGrab())
       
   137         QGraphicsWebView::mouseMoveEvent(event);
       
   138 }
       
   139 
       
   140 /*!
       
   141     \qmlclass WebView QDeclarativeWebView
       
   142     \since 4.7
       
   143     \brief The WebView item allows you to add web content to a canvas.
       
   144     \inherits Item
       
   145 
       
   146     A WebView renders web content based on a URL.
       
   147 
       
   148     This type is made available by importing the \c QtWebKit module:
       
   149 
       
   150     \bold{import QtWebKit 1.0}
       
   151 
       
   152     If the width and height of the item is not set, they will
       
   153     dynamically adjust to a size appropriate for the content.
       
   154     This width may be large for typical online web pages.
       
   155 
       
   156     If the width or height is explictly set, the rendered website
       
   157     will be clipped, not scaled, to fit into the set dimensions.
       
   158 
       
   159     If the preferredWidth is set, the width will be this amount or larger,
       
   160     usually laying out the web content to fit the preferredWidth.
       
   161 
       
   162     \qml
       
   163     import QtWebKit 1.0
       
   164 
       
   165     WebView {
       
   166         url: "http://www.nokia.com"
       
   167         preferredWidth: 490
       
   168         preferredHeight: 400
       
   169         scale: 0.5
       
   170         smooth: false
       
   171         smoothCache: true
       
   172     }
       
   173     \endqml
       
   174 
       
   175     \image webview.png
       
   176 
       
   177     The item includes no scrolling, scaling,
       
   178     toolbars, etc., those must be implemented around WebView. See the WebBrowser example
       
   179     for a demonstration of this.
       
   180 
       
   181     When this item has keyboard focus, all keyboard input will be sent directly to the
       
   182     web page within.
       
   183 
       
   184     \sa {declarative/modelviews/webview}{WebView example}, {demos/declarative/webbrowser}{Web Browser demo}
       
   185 */
       
   186 
       
   187 /*!
       
   188     \internal
       
   189     \class QDeclarativeWebView
       
   190     \brief The QDeclarativeWebView class allows you to add web content to a QDeclarativeView.
       
   191 
       
   192     A WebView renders web content base on a URL.
       
   193 
       
   194     \image webview.png
       
   195 
       
   196     The item includes no scrolling, scaling,
       
   197     toolbars, etc., those must be implemented around WebView. See the WebBrowser example
       
   198     for a demonstration of this.
       
   199 
       
   200     A QDeclarativeWebView object can be instantiated in Qml using the tag \l WebView.
       
   201 */
       
   202 
       
   203 QDeclarativeWebView::QDeclarativeWebView(QDeclarativeItem *parent) : QDeclarativeItem(parent)
       
   204 {
       
   205     init();
       
   206 }
       
   207 
       
   208 QDeclarativeWebView::~QDeclarativeWebView()
       
   209 {
       
   210     delete d;
       
   211 }
       
   212 
       
   213 void QDeclarativeWebView::init()
       
   214 {
       
   215     d = new QDeclarativeWebViewPrivate(this);
       
   216 
       
   217     QWebSettings::enablePersistentStorage();
       
   218 
       
   219     setAcceptedMouseButtons(Qt::LeftButton);
       
   220     setFlag(QGraphicsItem::ItemHasNoContents, true);
       
   221     setClip(true);
       
   222 
       
   223     d->view = new GraphicsWebView(this);
       
   224     d->view->setResizesToContents(true);
       
   225     QWebPage* wp = new QDeclarativeWebPage(this);
       
   226     setPage(wp);
       
   227     connect(d->view, SIGNAL(geometryChanged()), this, SLOT(updateDeclarativeWebViewSize()));
       
   228     connect(d->view, SIGNAL(doubleClick(int, int)), this, SIGNAL(doubleClick(int, int)));
       
   229     connect(d->view, SIGNAL(scaleChanged()), this, SIGNAL(contentsScaleChanged()));
       
   230 }
       
   231 
       
   232 void QDeclarativeWebView::componentComplete()
       
   233 {
       
   234     QDeclarativeItem::componentComplete();
       
   235     page()->setNetworkAccessManager(qmlEngine(this)->networkAccessManager());
       
   236 
       
   237     switch (d->pending) {
       
   238     case QDeclarativeWebViewPrivate::PendingUrl:
       
   239         setUrl(d->pendingUrl);
       
   240         break;
       
   241     case QDeclarativeWebViewPrivate::PendingHtml:
       
   242         setHtml(d->pendingString, d->pendingUrl);
       
   243         break;
       
   244     case QDeclarativeWebViewPrivate::PendingContent:
       
   245         setContent(d->pendingData, d->pendingString, d->pendingUrl);
       
   246         break;
       
   247     default:
       
   248         break;
       
   249     }
       
   250     d->pending = QDeclarativeWebViewPrivate::PendingNone;
       
   251     d->updateWindowObjects();
       
   252 }
       
   253 
       
   254 QDeclarativeWebView::Status QDeclarativeWebView::status() const
       
   255 {
       
   256     return d->status;
       
   257 }
       
   258 
       
   259 
       
   260 /*!
       
   261     \qmlproperty real WebView::progress
       
   262     This property holds the progress of loading the current URL, from 0 to 1.
       
   263 
       
   264     If you just want to know when progress gets to 1, use
       
   265     WebView::onLoadFinished() or WebView::onLoadFailed() instead.
       
   266 */
       
   267 qreal QDeclarativeWebView::progress() const
       
   268 {
       
   269     return d->progress;
       
   270 }
       
   271 
       
   272 void QDeclarativeWebView::doLoadStarted()
       
   273 {
       
   274     if (!d->url.isEmpty()) {
       
   275         d->status = Loading;
       
   276         emit statusChanged(d->status);
       
   277     }
       
   278     emit loadStarted();
       
   279 }
       
   280 
       
   281 void QDeclarativeWebView::doLoadProgress(int p)
       
   282 {
       
   283     if (d->progress == p / 100.0)
       
   284         return;
       
   285     d->progress = p / 100.0;
       
   286     emit progressChanged();
       
   287 }
       
   288 
       
   289 void QDeclarativeWebView::pageUrlChanged()
       
   290 {
       
   291     updateContentsSize();
       
   292 
       
   293     if ((d->url.isEmpty() && page()->mainFrame()->url() != QUrl(QLatin1String("about:blank")))
       
   294         || (d->url != page()->mainFrame()->url() && !page()->mainFrame()->url().isEmpty()))
       
   295     {
       
   296         d->url = page()->mainFrame()->url();
       
   297         if (d->url == QUrl(QLatin1String("about:blank")))
       
   298             d->url = QUrl();
       
   299         emit urlChanged();
       
   300     }
       
   301 }
       
   302 
       
   303 void QDeclarativeWebView::doLoadFinished(bool ok)
       
   304 {
       
   305     if (ok) {
       
   306         d->status = d->url.isEmpty() ? Null : Ready;
       
   307         emit loadFinished();
       
   308     } else {
       
   309         d->status = Error;
       
   310         emit loadFailed();
       
   311     }
       
   312     emit statusChanged(d->status);
       
   313 }
       
   314 
       
   315 /*!
       
   316     \qmlproperty url WebView::url
       
   317     This property holds the URL to the page displayed in this item. It can be set,
       
   318     but also can change spontaneously (eg. because of network redirection).
       
   319 
       
   320     If the url is empty, the page is blank.
       
   321 
       
   322     The url is always absolute (QML will resolve relative URL strings in the context
       
   323     of the containing QML document).
       
   324 */
       
   325 QUrl QDeclarativeWebView::url() const
       
   326 {
       
   327     return d->url;
       
   328 }
       
   329 
       
   330 void QDeclarativeWebView::setUrl(const QUrl& url)
       
   331 {
       
   332     if (url == d->url)
       
   333         return;
       
   334 
       
   335     if (isComponentComplete()) {
       
   336         d->url = url;
       
   337         updateContentsSize();
       
   338         QUrl seturl = url;
       
   339         if (seturl.isEmpty())
       
   340             seturl = QUrl(QLatin1String("about:blank"));
       
   341 
       
   342         Q_ASSERT(!seturl.isRelative());
       
   343 
       
   344         page()->mainFrame()->load(seturl);
       
   345 
       
   346         emit urlChanged();
       
   347     } else {
       
   348         d->pending = d->PendingUrl;
       
   349         d->pendingUrl = url;
       
   350     }
       
   351 }
       
   352 
       
   353 /*!
       
   354     \qmlproperty int WebView::preferredWidth
       
   355     This property holds the ideal width for displaying the current URL.
       
   356 */
       
   357 int QDeclarativeWebView::preferredWidth() const
       
   358 {
       
   359     return d->preferredwidth;
       
   360 }
       
   361 
       
   362 void QDeclarativeWebView::setPreferredWidth(int width)
       
   363 {
       
   364     if (d->preferredwidth == width)
       
   365         return;
       
   366     d->preferredwidth = width;
       
   367     updateContentsSize();
       
   368     emit preferredWidthChanged();
       
   369 }
       
   370 
       
   371 /*!
       
   372     \qmlproperty int WebView::preferredHeight
       
   373     This property holds the ideal height for displaying the current URL.
       
   374     This only affects the area zoomed by heuristicZoom().
       
   375 */
       
   376 int QDeclarativeWebView::preferredHeight() const
       
   377 {
       
   378     return d->preferredheight;
       
   379 }
       
   380 
       
   381 void QDeclarativeWebView::setPreferredHeight(int height)
       
   382 {
       
   383     if (d->preferredheight == height)
       
   384         return;
       
   385     d->preferredheight = height;
       
   386     updateContentsSize();
       
   387     emit preferredHeightChanged();
       
   388 }
       
   389 
       
   390 /*!
       
   391     \qmlmethod bool WebView::evaluateJavaScript(string)
       
   392 
       
   393     Evaluates the \a scriptSource JavaScript inside the context of the
       
   394     main web frame, and returns the result of the last executed statement.
       
   395 
       
   396     Note that this JavaScript does \e not have any access to QML objects
       
   397     except as made available as windowObjects.
       
   398 */
       
   399 QVariant QDeclarativeWebView::evaluateJavaScript(const QString& scriptSource)
       
   400 {
       
   401     return this->page()->mainFrame()->evaluateJavaScript(scriptSource);
       
   402 }
       
   403 
       
   404 void QDeclarativeWebView::updateDeclarativeWebViewSize()
       
   405 {
       
   406     QSizeF size = d->view->geometry().size() * contentsScale();
       
   407     setImplicitWidth(size.width());
       
   408     setImplicitHeight(size.height());
       
   409 }
       
   410 
       
   411 void QDeclarativeWebView::initialLayout()
       
   412 {
       
   413     // nothing useful to do at this point
       
   414 }
       
   415 
       
   416 void QDeclarativeWebView::updateContentsSize()
       
   417 {
       
   418     if (page()) {
       
   419         page()->setPreferredContentsSize(QSize(
       
   420             d->preferredwidth>0 ? d->preferredwidth : width(),
       
   421             d->preferredheight>0 ? d->preferredheight : height()));
       
   422     }
       
   423 }
       
   424 
       
   425 void QDeclarativeWebView::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry)
       
   426 {
       
   427     QWebPage* webPage = page();
       
   428     if (newGeometry.size() != oldGeometry.size() && webPage) {
       
   429         QSize contentSize = webPage->preferredContentsSize();
       
   430         if (widthValid())
       
   431             contentSize.setWidth(width());
       
   432         if (heightValid())
       
   433             contentSize.setHeight(height());
       
   434         if (contentSize != webPage->preferredContentsSize())
       
   435             webPage->setPreferredContentsSize(contentSize);
       
   436     }
       
   437     QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
       
   438 }
       
   439 
       
   440 /*!
       
   441     \qmlproperty list<object> WebView::javaScriptWindowObjects
       
   442 
       
   443     A list of QML objects to expose to the web page.
       
   444 
       
   445     Each object will be added as a property of the web frame's window object.  The
       
   446     property name is controlled by the value of \c WebView.windowObjectName
       
   447     attached property.
       
   448 
       
   449     Exposing QML objects to a web page allows JavaScript executing in the web
       
   450     page itself to communicate with QML, by reading and writing properties and
       
   451     by calling methods of the exposed QML objects.
       
   452 
       
   453     This example shows how to call into a QML method using a window object.
       
   454 
       
   455     \qml
       
   456     WebView {
       
   457         javaScriptWindowObjects: QtObject {
       
   458             WebView.windowObjectName: "qml"
       
   459 
       
   460             function qmlCall() {
       
   461                 console.log("This call is in QML!");
       
   462             }
       
   463         }
       
   464 
       
   465         html: "<script>console.log(\"This is in WebKit!\"); window.qml.qmlCall();</script>"
       
   466     }
       
   467     \endqml
       
   468 
       
   469     The output of the example will be:
       
   470     \code
       
   471     This is in WebKit!
       
   472     This call is in QML!
       
   473     \endcode
       
   474 
       
   475     If Javascript is not enabled for the page, then this property does nothing.
       
   476 */
       
   477 QDeclarativeListProperty<QObject> QDeclarativeWebView::javaScriptWindowObjects()
       
   478 {
       
   479     return QDeclarativeListProperty<QObject>(this, d, &QDeclarativeWebViewPrivate::windowObjectsAppend);
       
   480 }
       
   481 
       
   482 QDeclarativeWebViewAttached* QDeclarativeWebView::qmlAttachedProperties(QObject* o)
       
   483 {
       
   484     return new QDeclarativeWebViewAttached(o);
       
   485 }
       
   486 
       
   487 void QDeclarativeWebViewPrivate::updateWindowObjects()
       
   488 {
       
   489     if (!q->isComponentCompletePublic() || !q->page())
       
   490         return;
       
   491 
       
   492     for (int i = 0; i < windowObjects.count(); ++i) {
       
   493         QObject* object = windowObjects.at(i);
       
   494         QDeclarativeWebViewAttached* attached = static_cast<QDeclarativeWebViewAttached *>(qmlAttachedPropertiesObject<QDeclarativeWebView>(object));
       
   495         if (attached && !attached->windowObjectName().isEmpty())
       
   496             q->page()->mainFrame()->addToJavaScriptWindowObject(attached->windowObjectName(), object);
       
   497     }
       
   498 }
       
   499 
       
   500 bool QDeclarativeWebView::renderingEnabled() const
       
   501 {
       
   502     return d->rendering;
       
   503 }
       
   504 
       
   505 void QDeclarativeWebView::setRenderingEnabled(bool enabled)
       
   506 {
       
   507     if (d->rendering == enabled)
       
   508         return;
       
   509     d->rendering = enabled;
       
   510     emit renderingEnabledChanged();
       
   511     d->view->setTiledBackingStoreFrozen(!enabled);
       
   512 }
       
   513 
       
   514 /*!
       
   515     \qmlsignal WebView::onDoubleClick(clickx, clicky)
       
   516 
       
   517     The WebView does not pass double-click events to the web engine, but rather
       
   518     emits this signals.
       
   519 */
       
   520 
       
   521 /*!
       
   522     \qmlmethod bool WebView::heuristicZoom(clickX,clickY,maxzoom)
       
   523 
       
   524     Finds a zoom that:
       
   525     \list
       
   526     \i shows a whole item
       
   527     \i includes (\a clickX, \a clickY)
       
   528     \i fits into the preferredWidth and preferredHeight
       
   529     \i zooms by no more than \a maxZoom
       
   530     \i is more than 10% above the current zoom
       
   531     \endlist
       
   532 
       
   533     If such a zoom exists, emits zoomTo(zoom,centerX,centerY) and returns true; otherwise,
       
   534     no signal is emitted and returns false.
       
   535 */
       
   536 bool QDeclarativeWebView::heuristicZoom(int clickX, int clickY, qreal maxZoom)
       
   537 {
       
   538     if (contentsScale() >= maxZoom / scale())
       
   539         return false;
       
   540     qreal ozf = contentsScale();
       
   541     QRect showArea = elementAreaAt(clickX, clickY, d->preferredwidth / maxZoom, d->preferredheight / maxZoom);
       
   542     qreal z = qMin(qreal(d->preferredwidth) / showArea.width(), qreal(d->preferredheight) / showArea.height());
       
   543     if (z > maxZoom / scale())
       
   544         z = maxZoom / scale();
       
   545     if (z / ozf > 1.2) {
       
   546         QRectF r(showArea.left() * z, showArea.top() * z, showArea.width() * z, showArea.height() * z);
       
   547         emit zoomTo(z, r.x() + r.width() / 2, r.y() + r.height() / 2);
       
   548         return true;
       
   549     }
       
   550     return false;
       
   551 }
       
   552 
       
   553 /*!
       
   554     \qmlproperty int WebView::pressGrabTime
       
   555 
       
   556     The number of milliseconds the user must press before the WebView
       
   557     starts passing move events through to the web engine (rather than
       
   558     letting other QML elements such as a Flickable take them).
       
   559 
       
   560     Defaults to 400ms. Set to 0 to always grab and pass move events to
       
   561     the web engine.
       
   562 */
       
   563 int QDeclarativeWebView::pressGrabTime() const
       
   564 {
       
   565     return d->view->pressTime;
       
   566 }
       
   567 
       
   568 void QDeclarativeWebView::setPressGrabTime(int millis)
       
   569 {
       
   570     if (d->view->pressTime == millis)
       
   571         return;
       
   572     d->view->pressTime = millis;
       
   573     emit pressGrabTimeChanged();
       
   574 }
       
   575 
       
   576 #ifndef QT_NO_ACTION
       
   577 /*!
       
   578     \qmlproperty action WebView::back
       
   579     This property holds the action for causing the previous URL in the history to be displayed.
       
   580 */
       
   581 QAction* QDeclarativeWebView::backAction() const
       
   582 {
       
   583     return page()->action(QWebPage::Back);
       
   584 }
       
   585 
       
   586 /*!
       
   587     \qmlproperty action WebView::forward
       
   588     This property holds the action for causing the next URL in the history to be displayed.
       
   589 */
       
   590 QAction* QDeclarativeWebView::forwardAction() const
       
   591 {
       
   592     return page()->action(QWebPage::Forward);
       
   593 }
       
   594 
       
   595 /*!
       
   596     \qmlproperty action WebView::reload
       
   597     This property holds the action for reloading with the current URL
       
   598 */
       
   599 QAction* QDeclarativeWebView::reloadAction() const
       
   600 {
       
   601     return page()->action(QWebPage::Reload);
       
   602 }
       
   603 
       
   604 /*!
       
   605     \qmlproperty action WebView::stop
       
   606     This property holds the action for stopping loading with the current URL
       
   607 */
       
   608 QAction* QDeclarativeWebView::stopAction() const
       
   609 {
       
   610     return page()->action(QWebPage::Stop);
       
   611 }
       
   612 #endif // QT_NO_ACTION
       
   613 
       
   614 /*!
       
   615     \qmlproperty string WebView::title
       
   616     This property holds the title of the web page currently viewed
       
   617 
       
   618     By default, this property contains an empty string.
       
   619 */
       
   620 QString QDeclarativeWebView::title() const
       
   621 {
       
   622     return page()->mainFrame()->title();
       
   623 }
       
   624 
       
   625 /*!
       
   626     \qmlproperty pixmap WebView::icon
       
   627     This property holds the icon associated with the web page currently viewed
       
   628 */
       
   629 QPixmap QDeclarativeWebView::icon() const
       
   630 {
       
   631     return page()->mainFrame()->icon().pixmap(QSize(256, 256));
       
   632 }
       
   633 
       
   634 /*!
       
   635     \qmlproperty string WebView::statusText
       
   636 
       
   637     This property is the current status suggested by the current web page. In a web browser,
       
   638     such status is often shown in some kind of status bar.
       
   639 */
       
   640 void QDeclarativeWebView::setStatusText(const QString& text)
       
   641 {
       
   642     d->statusText = text;
       
   643     emit statusTextChanged();
       
   644 }
       
   645 
       
   646 void QDeclarativeWebView::windowObjectCleared()
       
   647 {
       
   648     d->updateWindowObjects();
       
   649 }
       
   650 
       
   651 QString QDeclarativeWebView::statusText() const
       
   652 {
       
   653     return d->statusText;
       
   654 }
       
   655 
       
   656 QWebPage* QDeclarativeWebView::page() const
       
   657 {
       
   658     return d->view->page();
       
   659 }
       
   660 
       
   661 // The QObject interface to settings().
       
   662 /*!
       
   663     \qmlproperty string WebView::settings.standardFontFamily
       
   664     \qmlproperty string WebView::settings.fixedFontFamily
       
   665     \qmlproperty string WebView::settings.serifFontFamily
       
   666     \qmlproperty string WebView::settings.sansSerifFontFamily
       
   667     \qmlproperty string WebView::settings.cursiveFontFamily
       
   668     \qmlproperty string WebView::settings.fantasyFontFamily
       
   669 
       
   670     \qmlproperty int WebView::settings.minimumFontSize
       
   671     \qmlproperty int WebView::settings.minimumLogicalFontSize
       
   672     \qmlproperty int WebView::settings.defaultFontSize
       
   673     \qmlproperty int WebView::settings.defaultFixedFontSize
       
   674 
       
   675     \qmlproperty bool WebView::settings.autoLoadImages
       
   676     \qmlproperty bool WebView::settings.javascriptEnabled
       
   677     \qmlproperty bool WebView::settings.javaEnabled
       
   678     \qmlproperty bool WebView::settings.pluginsEnabled
       
   679     \qmlproperty bool WebView::settings.privateBrowsingEnabled
       
   680     \qmlproperty bool WebView::settings.javascriptCanOpenWindows
       
   681     \qmlproperty bool WebView::settings.javascriptCanAccessClipboard
       
   682     \qmlproperty bool WebView::settings.developerExtrasEnabled
       
   683     \qmlproperty bool WebView::settings.linksIncludedInFocusChain
       
   684     \qmlproperty bool WebView::settings.zoomTextOnly
       
   685     \qmlproperty bool WebView::settings.printElementBackgrounds
       
   686     \qmlproperty bool WebView::settings.offlineStorageDatabaseEnabled
       
   687     \qmlproperty bool WebView::settings.offlineWebApplicationCacheEnabled
       
   688     \qmlproperty bool WebView::settings.localStorageDatabaseEnabled
       
   689     \qmlproperty bool WebView::settings.localContentCanAccessRemoteUrls
       
   690 
       
   691     These properties give access to the settings controlling the web view.
       
   692 
       
   693     See QWebSettings for details of these properties.
       
   694 
       
   695     \qml
       
   696         WebView {
       
   697             settings.pluginsEnabled: true
       
   698             settings.standardFontFamily: "Arial"
       
   699             ...
       
   700         }
       
   701     \endqml
       
   702 */
       
   703 QDeclarativeWebSettings* QDeclarativeWebView::settingsObject() const
       
   704 {
       
   705     d->settings.s = page()->settings();
       
   706     return &d->settings;
       
   707 }
       
   708 
       
   709 void QDeclarativeWebView::setPage(QWebPage* page)
       
   710 {
       
   711     if (d->view->page() == page)
       
   712         return;
       
   713 
       
   714     d->view->setPage(page);
       
   715     updateContentsSize();
       
   716     page->mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
       
   717     page->mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
       
   718     connect(page->mainFrame(), SIGNAL(urlChanged(QUrl)), this, SLOT(pageUrlChanged()));
       
   719     connect(page->mainFrame(), SIGNAL(titleChanged(QString)), this, SIGNAL(titleChanged(QString)));
       
   720     connect(page->mainFrame(), SIGNAL(titleChanged(QString)), this, SIGNAL(iconChanged()));
       
   721     connect(page->mainFrame(), SIGNAL(iconChanged()), this, SIGNAL(iconChanged()));
       
   722     connect(page->mainFrame(), SIGNAL(initialLayoutCompleted()), this, SLOT(initialLayout()));
       
   723     connect(page->mainFrame(), SIGNAL(contentsSizeChanged(QSize)), this, SIGNAL(contentsSizeChanged(QSize)));
       
   724 
       
   725     connect(page, SIGNAL(loadStarted()), this, SLOT(doLoadStarted()));
       
   726     connect(page, SIGNAL(loadProgress(int)), this, SLOT(doLoadProgress(int)));
       
   727     connect(page, SIGNAL(loadFinished(bool)), this, SLOT(doLoadFinished(bool)));
       
   728     connect(page, SIGNAL(statusBarMessage(QString)), this, SLOT(setStatusText(QString)));
       
   729 
       
   730     connect(page->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(windowObjectCleared()));
       
   731 
       
   732     page->settings()->setAttribute(QWebSettings::TiledBackingStoreEnabled, true);
       
   733 
       
   734 }
       
   735 
       
   736 /*!
       
   737     \qmlsignal WebView::onLoadStarted()
       
   738 
       
   739     This handler is called when the web engine begins loading
       
   740     a page. Later, WebView::onLoadFinished() or WebView::onLoadFailed()
       
   741     will be emitted.
       
   742 */
       
   743 
       
   744 /*!
       
   745     \qmlsignal WebView::onLoadFinished()
       
   746 
       
   747     This handler is called when the web engine \e successfully
       
   748     finishes loading a page, including any component content
       
   749     (WebView::onLoadFailed() will be emitted otherwise).
       
   750 
       
   751     \sa progress
       
   752 */
       
   753 
       
   754 /*!
       
   755     \qmlsignal WebView::onLoadFailed()
       
   756 
       
   757     This handler is called when the web engine fails loading
       
   758     a page or any component content
       
   759     (WebView::onLoadFinished() will be emitted on success).
       
   760 */
       
   761 
       
   762 void QDeclarativeWebView::load(const QNetworkRequest& request, QNetworkAccessManager::Operation operation, const QByteArray& body)
       
   763 {
       
   764     page()->mainFrame()->load(request, operation, body);
       
   765 }
       
   766 
       
   767 QString QDeclarativeWebView::html() const
       
   768 {
       
   769     return page()->mainFrame()->toHtml();
       
   770 }
       
   771 
       
   772 /*!
       
   773     \qmlproperty string WebView::html
       
   774     This property holds HTML text set directly
       
   775 
       
   776     The html property can be set as a string.
       
   777 
       
   778     \qml
       
   779     WebView {
       
   780         html: "<p>This is <b>HTML</b>."
       
   781     }
       
   782     \endqml
       
   783 */
       
   784 void QDeclarativeWebView::setHtml(const QString& html, const QUrl& baseUrl)
       
   785 {
       
   786     updateContentsSize();
       
   787     if (isComponentComplete())
       
   788         page()->mainFrame()->setHtml(html, baseUrl);
       
   789     else {
       
   790         d->pending = d->PendingHtml;
       
   791         d->pendingUrl = baseUrl;
       
   792         d->pendingString = html;
       
   793     }
       
   794     emit htmlChanged();
       
   795 }
       
   796 
       
   797 void QDeclarativeWebView::setContent(const QByteArray& data, const QString& mimeType, const QUrl& baseUrl)
       
   798 {
       
   799     updateContentsSize();
       
   800 
       
   801     if (isComponentComplete())
       
   802         page()->mainFrame()->setContent(data, mimeType, qmlContext(this)->resolvedUrl(baseUrl));
       
   803     else {
       
   804         d->pending = d->PendingContent;
       
   805         d->pendingUrl = baseUrl;
       
   806         d->pendingString = mimeType;
       
   807         d->pendingData = data;
       
   808     }
       
   809 }
       
   810 
       
   811 QWebHistory* QDeclarativeWebView::history() const
       
   812 {
       
   813     return page()->history();
       
   814 }
       
   815 
       
   816 QWebSettings* QDeclarativeWebView::settings() const
       
   817 {
       
   818     return page()->settings();
       
   819 }
       
   820 
       
   821 QDeclarativeWebView* QDeclarativeWebView::createWindow(QWebPage::WebWindowType type)
       
   822 {
       
   823     switch (type) {
       
   824     case QWebPage::WebBrowserWindow: {
       
   825         if (!d->newWindowComponent && d->newWindowParent)
       
   826             qWarning("WebView::newWindowComponent not set - WebView::newWindowParent ignored");
       
   827         else if (d->newWindowComponent && !d->newWindowParent)
       
   828             qWarning("WebView::newWindowParent not set - WebView::newWindowComponent ignored");
       
   829         else if (d->newWindowComponent && d->newWindowParent) {
       
   830             QDeclarativeWebView* webview = 0;
       
   831             QDeclarativeContext* windowContext = new QDeclarativeContext(qmlContext(this));
       
   832 
       
   833             QObject* newObject = d->newWindowComponent->create(windowContext);
       
   834             if (newObject) {
       
   835                 windowContext->setParent(newObject);
       
   836                 QDeclarativeItem* item = qobject_cast<QDeclarativeItem *>(newObject);
       
   837                 if (!item)
       
   838                     delete newObject;
       
   839                 else {
       
   840                     webview = item->findChild<QDeclarativeWebView*>();
       
   841                     if (!webview)
       
   842                         delete item;
       
   843                     else {
       
   844                         newObject->setParent(d->newWindowParent);
       
   845                         static_cast<QGraphicsObject*>(item)->setParentItem(d->newWindowParent);
       
   846                     }
       
   847                 }
       
   848             } else
       
   849                 delete windowContext;
       
   850 
       
   851             return webview;
       
   852         }
       
   853     }
       
   854     break;
       
   855     case QWebPage::WebModalDialog: {
       
   856         // Not supported
       
   857     }
       
   858     }
       
   859     return 0;
       
   860 }
       
   861 
       
   862 /*!
       
   863     \qmlproperty component WebView::newWindowComponent
       
   864 
       
   865     This property holds the component to use for new windows.
       
   866     The component must have a WebView somewhere in its structure.
       
   867 
       
   868     When the web engine requests a new window, it will be an instance of
       
   869     this component.
       
   870 
       
   871     The parent of the new window is set by newWindowParent. It must be set.
       
   872 */
       
   873 QDeclarativeComponent* QDeclarativeWebView::newWindowComponent() const
       
   874 {
       
   875     return d->newWindowComponent;
       
   876 }
       
   877 
       
   878 void QDeclarativeWebView::setNewWindowComponent(QDeclarativeComponent* newWindow)
       
   879 {
       
   880     if (newWindow == d->newWindowComponent)
       
   881         return;
       
   882     d->newWindowComponent = newWindow;
       
   883     emit newWindowComponentChanged();
       
   884 }
       
   885 
       
   886 
       
   887 /*!
       
   888     \qmlproperty item WebView::newWindowParent
       
   889 
       
   890     The parent item for new windows.
       
   891 
       
   892     \sa newWindowComponent
       
   893 */
       
   894 QDeclarativeItem* QDeclarativeWebView::newWindowParent() const
       
   895 {
       
   896     return d->newWindowParent;
       
   897 }
       
   898 
       
   899 void QDeclarativeWebView::setNewWindowParent(QDeclarativeItem* parent)
       
   900 {
       
   901     if (parent == d->newWindowParent)
       
   902         return;
       
   903     if (d->newWindowParent && parent) {
       
   904         QList<QGraphicsItem *> children = d->newWindowParent->childItems();
       
   905         for (int i = 0; i < children.count(); ++i)
       
   906             children.at(i)->setParentItem(parent);
       
   907     }
       
   908     d->newWindowParent = parent;
       
   909     emit newWindowParentChanged();
       
   910 }
       
   911 
       
   912 QSize QDeclarativeWebView::contentsSize() const
       
   913 {
       
   914     return page()->mainFrame()->contentsSize() * contentsScale();
       
   915 }
       
   916 
       
   917 qreal QDeclarativeWebView::contentsScale() const
       
   918 {
       
   919     return d->view->scale();
       
   920 }
       
   921 
       
   922 void QDeclarativeWebView::setContentsScale(qreal scale)
       
   923 {
       
   924     if (scale == d->view->scale())
       
   925         return;
       
   926     d->view->setScale(scale);
       
   927     updateDeclarativeWebViewSize();
       
   928     emit contentsScaleChanged();
       
   929 }
       
   930 
       
   931 /*!
       
   932     Returns the area of the largest element at position (\a x,\a y) that is no larger
       
   933     than \a maxWidth by \a maxHeight pixels.
       
   934 
       
   935     May return an area larger in the case when no smaller element is at the position.
       
   936 */
       
   937 QRect QDeclarativeWebView::elementAreaAt(int x, int y, int maxWidth, int maxHeight) const
       
   938 {
       
   939     QWebHitTestResult hit = page()->mainFrame()->hitTestContent(QPoint(x, y));
       
   940     QRect hitRect = hit.boundingRect();
       
   941     QWebElement element = hit.enclosingBlockElement();
       
   942     if (maxWidth <= 0)
       
   943         maxWidth = INT_MAX;
       
   944     if (maxHeight <= 0)
       
   945         maxHeight = INT_MAX;
       
   946     while (!element.parent().isNull() && element.geometry().width() <= maxWidth && element.geometry().height() <= maxHeight) {
       
   947         hitRect = element.geometry();
       
   948         element = element.parent();
       
   949     }
       
   950     return hitRect;
       
   951 }
       
   952 
       
   953 /*!
       
   954     \internal
       
   955     \class QDeclarativeWebPage
       
   956     \brief The QDeclarativeWebPage class is a QWebPage that can create QML plugins.
       
   957 
       
   958     \sa QDeclarativeWebView
       
   959 */
       
   960 QDeclarativeWebPage::QDeclarativeWebPage(QDeclarativeWebView* parent) :
       
   961     QWebPage(parent)
       
   962 {
       
   963 }
       
   964 
       
   965 QDeclarativeWebPage::~QDeclarativeWebPage()
       
   966 {
       
   967 }
       
   968 
       
   969 QString QDeclarativeWebPage::chooseFile(QWebFrame* originatingFrame, const QString& oldFile)
       
   970 {
       
   971     // Not supported (it's modal)
       
   972     Q_UNUSED(originatingFrame)
       
   973     Q_UNUSED(oldFile)
       
   974     return oldFile;
       
   975 }
       
   976 
       
   977 /*!
       
   978     \qmlsignal WebView::onAlert(message)
       
   979 
       
   980     The handler is called when the web engine sends a JavaScript alert. The \a message is the text
       
   981     to be displayed in the alert to the user.
       
   982 */
       
   983 
       
   984 
       
   985 void QDeclarativeWebPage::javaScriptAlert(QWebFrame* originatingFrame, const QString& msg)
       
   986 {
       
   987     Q_UNUSED(originatingFrame)
       
   988     emit viewItem()->alert(msg);
       
   989 }
       
   990 
       
   991 bool QDeclarativeWebPage::javaScriptConfirm(QWebFrame* originatingFrame, const QString& msg)
       
   992 {
       
   993     // Not supported (it's modal)
       
   994     Q_UNUSED(originatingFrame)
       
   995     Q_UNUSED(msg)
       
   996     return false;
       
   997 }
       
   998 
       
   999 bool QDeclarativeWebPage::javaScriptPrompt(QWebFrame* originatingFrame, const QString& msg, const QString& defaultValue, QString* result)
       
  1000 {
       
  1001     // Not supported (it's modal)
       
  1002     Q_UNUSED(originatingFrame)
       
  1003     Q_UNUSED(msg)
       
  1004     Q_UNUSED(defaultValue)
       
  1005     Q_UNUSED(result)
       
  1006     return false;
       
  1007 }
       
  1008 
       
  1009 
       
  1010 QDeclarativeWebView* QDeclarativeWebPage::viewItem()
       
  1011 {
       
  1012     return static_cast<QDeclarativeWebView*>(parent());
       
  1013 }
       
  1014 
       
  1015 QWebPage* QDeclarativeWebPage::createWindow(WebWindowType type)
       
  1016 {
       
  1017     QDeclarativeWebView* newView = viewItem()->createWindow(type);
       
  1018     if (newView)
       
  1019         return newView->page();
       
  1020     return 0;
       
  1021 }
       
  1022 
       
  1023 QT_END_NAMESPACE
       
  1024