Home | History | Annotate | Download | only in Api
      1 /*
      2     Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
      3     Copyright (C) 2009 Girish Ramakrishnan <girish (at) forwardbias.in>
      4 
      5     This library is free software; you can redistribute it and/or
      6     modify it under the terms of the GNU Library General Public
      7     License as published by the Free Software Foundation; either
      8     version 2 of the License, or (at your option) any later version.
      9 
     10     This library is distributed in the hope that it will be useful,
     11     but WITHOUT ANY WARRANTY; without even the implied warranty of
     12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13     Library General Public License for more details.
     14 
     15     You should have received a copy of the GNU Library General Public License
     16     along with this library; see the file COPYING.LIB.  If not, write to
     17     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18     Boston, MA 02110-1301, USA.
     19 */
     20 
     21 #include "config.h"
     22 #include "qgraphicswebview.h"
     23 
     24 #include "qwebframe.h"
     25 #include "qwebframe_p.h"
     26 #include "qwebpage.h"
     27 #include "qwebpage_p.h"
     28 #include "QWebPageClient.h"
     29 #include <FrameView.h>
     30 #include <QtCore/qmetaobject.h>
     31 #include <QtCore/qsharedpointer.h>
     32 #include <QtCore/qtimer.h>
     33 #include <QtGui/qapplication.h>
     34 #include <QtGui/qgraphicsscene.h>
     35 #include <QtGui/qgraphicssceneevent.h>
     36 #include <QtGui/qgraphicsview.h>
     37 #include <QtGui/qpixmapcache.h>
     38 #include <QtGui/qstyleoption.h>
     39 #if defined(Q_WS_X11)
     40 #include <QX11Info>
     41 #endif
     42 #include <Settings.h>
     43 
     44 #if USE(ACCELERATED_COMPOSITING)
     45 
     46 // the overlay is here for one reason only: to have the scroll-bars and other
     47 // extra UI elements appear on top of any QGraphicsItems created by CSS compositing layers
     48 class QGraphicsWebViewOverlay : public QGraphicsItem {
     49     public:
     50     QGraphicsWebViewOverlay(QGraphicsWebView* view)
     51             :QGraphicsItem(view)
     52             , q(view)
     53     {
     54         setPos(0, 0);
     55         setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
     56         setCacheMode(QGraphicsItem::DeviceCoordinateCache);
     57     }
     58 
     59     QRectF boundingRect() const
     60     {
     61         return q->boundingRect();
     62     }
     63 
     64     void paint(QPainter* painter, const QStyleOptionGraphicsItem* options, QWidget*)
     65     {
     66         q->page()->mainFrame()->render(painter, static_cast<QWebFrame::RenderLayer>(QWebFrame::AllLayers&(~QWebFrame::ContentsLayer)), options->exposedRect.toRect());
     67     }
     68 
     69     friend class QGraphicsWebView;
     70     QGraphicsWebView* q;
     71 };
     72 
     73 #endif
     74 
     75 class QGraphicsWebViewPrivate : public QWebPageClient {
     76 public:
     77     QGraphicsWebViewPrivate(QGraphicsWebView* parent)
     78         : q(parent)
     79         , page(0)
     80 #if USE(ACCELERATED_COMPOSITING)
     81         , rootGraphicsLayer(0)
     82         , shouldSync(false)
     83 #endif
     84     {
     85 #if USE(ACCELERATED_COMPOSITING)
     86         // the overlay and stays alive for the lifetime of
     87         // this QGraphicsWebView as the scrollbars are needed when there's no compositing
     88         q->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
     89         syncMetaMethod = q->metaObject()->method(q->metaObject()->indexOfMethod("syncLayers()"));
     90 #endif
     91     }
     92 
     93     virtual ~QGraphicsWebViewPrivate();
     94     virtual void scroll(int dx, int dy, const QRect&);
     95     virtual void update(const QRect& dirtyRect);
     96     virtual void setInputMethodEnabled(bool enable);
     97     virtual bool inputMethodEnabled() const;
     98 #if QT_VERSION >= 0x040600
     99     virtual void setInputMethodHint(Qt::InputMethodHint hint, bool enable);
    100 #endif
    101 
    102 #ifndef QT_NO_CURSOR
    103     virtual QCursor cursor() const;
    104     virtual void updateCursor(const QCursor& cursor);
    105 #endif
    106 
    107     virtual QPalette palette() const;
    108     virtual int screenNumber() const;
    109     virtual QWidget* ownerWidget() const;
    110 
    111     virtual QObject* pluginParent() const;
    112 
    113     virtual QStyle* style() const;
    114 
    115 #if USE(ACCELERATED_COMPOSITING)
    116     virtual void setRootGraphicsLayer(QGraphicsItem* layer);
    117     virtual void markForSync(bool scheduleSync);
    118     void updateCompositingScrollPosition();
    119 #endif
    120 
    121     void syncLayers();
    122     void _q_doLoadFinished(bool success);
    123 
    124     QGraphicsWebView* q;
    125     QWebPage* page;
    126 #if USE(ACCELERATED_COMPOSITING)
    127     QGraphicsItem* rootGraphicsLayer;
    128 
    129     // the overlay gets instantiated when the root layer is attached, and get deleted when it's detached
    130     QSharedPointer<QGraphicsWebViewOverlay> overlay;
    131 
    132     // we need to sync the layers if we get a special call from the WebCore
    133     // compositor telling us to do so. We'll get that call from ChromeClientQt
    134     bool shouldSync;
    135 
    136     // we have to flush quite often, so we use a meta-method instead of QTimer::singleShot for putting the event in the queue
    137     QMetaMethod syncMetaMethod;
    138 
    139     // we need to put the root graphics layer behind the overlay (which contains the scrollbar)
    140     enum { RootGraphicsLayerZValue, OverlayZValue };
    141 #endif
    142 };
    143 
    144 QGraphicsWebViewPrivate::~QGraphicsWebViewPrivate()
    145 {
    146 #if USE(ACCELERATED_COMPOSITING)
    147     if (rootGraphicsLayer) {
    148         // we don't need to delete the root graphics layer
    149         // The lifecycle is managed in GraphicsLayerQt.cpp
    150         rootGraphicsLayer->setParentItem(0);
    151         q->scene()->removeItem(rootGraphicsLayer);
    152     }
    153 #endif
    154 }
    155 
    156 #if USE(ACCELERATED_COMPOSITING)
    157 void QGraphicsWebViewPrivate::setRootGraphicsLayer(QGraphicsItem* layer)
    158 {
    159     if (rootGraphicsLayer) {
    160         rootGraphicsLayer->setParentItem(0);
    161         q->scene()->removeItem(rootGraphicsLayer);
    162         QWebFramePrivate::core(q->page()->mainFrame())->view()->syncCompositingStateRecursive();
    163     }
    164 
    165     rootGraphicsLayer = layer;
    166 
    167     if (layer) {
    168         layer->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
    169         layer->setParentItem(q);
    170         layer->setZValue(RootGraphicsLayerZValue);
    171         if (!overlay) {
    172             overlay = QSharedPointer<QGraphicsWebViewOverlay>(new QGraphicsWebViewOverlay(q));
    173             overlay->setZValue(OverlayZValue);
    174         }
    175         updateCompositingScrollPosition();
    176     } else {
    177         // we don't have compositing layers, we can render the scrollbars and content in one go
    178         overlay.clear();
    179     }
    180 }
    181 
    182 void QGraphicsWebViewPrivate::markForSync(bool scheduleSync)
    183 {
    184     shouldSync = true;
    185     if (scheduleSync)
    186         syncMetaMethod.invoke(q, Qt::QueuedConnection);
    187 }
    188 
    189 void QGraphicsWebViewPrivate::updateCompositingScrollPosition()
    190 {
    191     if (rootGraphicsLayer && q->page() && q->page()->mainFrame()) {
    192         const QPoint scrollPosition = q->page()->mainFrame()->scrollPosition();
    193         rootGraphicsLayer->setPos(-scrollPosition);
    194     }
    195 }
    196 
    197 #endif
    198 
    199 void QGraphicsWebViewPrivate::syncLayers()
    200 {
    201 #if USE(ACCELERATED_COMPOSITING)
    202     if (shouldSync) {
    203         QWebFramePrivate::core(q->page()->mainFrame())->view()->syncCompositingStateRecursive();
    204         shouldSync = false;
    205     }
    206 #endif
    207 }
    208 
    209 void QGraphicsWebViewPrivate::_q_doLoadFinished(bool success)
    210 {
    211     // If the page had no title, still make sure it gets the signal
    212     if (q->title().isEmpty())
    213         emit q->urlChanged(q->url());
    214 
    215     emit q->loadFinished(success);
    216 }
    217 
    218 void QGraphicsWebViewPrivate::scroll(int dx, int dy, const QRect& rectToScroll)
    219 {
    220     q->scroll(qreal(dx), qreal(dy), QRectF(rectToScroll));
    221 #if USE(ACCELERATED_COMPOSITING)
    222     updateCompositingScrollPosition();
    223 #endif
    224 }
    225 
    226 void QGraphicsWebViewPrivate::update(const QRect & dirtyRect)
    227 {
    228     q->update(QRectF(dirtyRect));
    229 #if USE(ACCELERATED_COMPOSITING)
    230     if (overlay)
    231         overlay->update(QRectF(dirtyRect));
    232     syncLayers();
    233 #endif
    234 }
    235 
    236 
    237 void QGraphicsWebViewPrivate::setInputMethodEnabled(bool enable)
    238 {
    239 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
    240     q->setFlag(QGraphicsItem::ItemAcceptsInputMethod, enable);
    241 #endif
    242 }
    243 
    244 bool QGraphicsWebViewPrivate::inputMethodEnabled() const
    245 {
    246 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
    247     return q->flags() & QGraphicsItem::ItemAcceptsInputMethod;
    248 #else
    249     return false;
    250 #endif
    251 }
    252 
    253 #if QT_VERSION >= 0x040600
    254 void QGraphicsWebViewPrivate::setInputMethodHint(Qt::InputMethodHint hint, bool enable)
    255 {
    256     if (enable)
    257         q->setInputMethodHints(q->inputMethodHints() | hint);
    258     else
    259         q->setInputMethodHints(q->inputMethodHints() & ~hint);
    260 }
    261 #endif
    262 #ifndef QT_NO_CURSOR
    263 QCursor QGraphicsWebViewPrivate::cursor() const
    264 {
    265     return q->cursor();
    266 }
    267 
    268 void QGraphicsWebViewPrivate::updateCursor(const QCursor& cursor)
    269 {
    270     q->setCursor(cursor);
    271 }
    272 #endif
    273 
    274 QPalette QGraphicsWebViewPrivate::palette() const
    275 {
    276     return q->palette();
    277 }
    278 
    279 int QGraphicsWebViewPrivate::screenNumber() const
    280 {
    281 #if defined(Q_WS_X11)
    282     const QList<QGraphicsView*> views = q->scene()->views();
    283 
    284     if (!views.isEmpty())
    285         return views.at(0)->x11Info().screen();
    286 #endif
    287 
    288     return 0;
    289 }
    290 
    291 QWidget* QGraphicsWebViewPrivate::ownerWidget() const
    292 {
    293     const QList<QGraphicsView*> views = q->scene()->views();
    294     return views.value(0);
    295 }
    296 
    297 QObject* QGraphicsWebViewPrivate::pluginParent() const
    298 {
    299     return q;
    300 }
    301 
    302 QStyle* QGraphicsWebViewPrivate::style() const
    303 {
    304     return q->style();
    305 }
    306 
    307 /*!
    308     \class QGraphicsWebView
    309     \brief The QGraphicsWebView class allows Web content to be added to a GraphicsView.
    310     \since 4.6
    311 
    312     An instance of this class renders Web content from a URL or supplied as data, using
    313     features of the QtWebKit module.
    314 
    315     If the width and height of the item are not set, they will default to 800 and 600,
    316     respectively. If the Web page contents is larger than that, scrollbars will be shown
    317     if not disabled explicitly.
    318 
    319     \section1 Browser Features
    320 
    321     Many of the functions, signals and properties provided by QWebView are also available
    322     for this item, making it simple to adapt existing code to use QGraphicsWebView instead
    323     of QWebView.
    324 
    325     The item uses a QWebPage object to perform the rendering of Web content, and this can
    326     be obtained with the page() function, enabling the document itself to be accessed and
    327     modified.
    328 
    329     As with QWebView, the item records the browsing history using a QWebHistory object,
    330     accessible using the history() function. The QWebSettings object that defines the
    331     configuration of the browser can be obtained with the settings() function, enabling
    332     features like plugin support to be customized for each item.
    333 
    334     \sa QWebView, QGraphicsTextItem
    335 */
    336 
    337 /*!
    338     \fn void QGraphicsWebView::titleChanged(const QString &title)
    339 
    340     This signal is emitted whenever the \a title of the main frame changes.
    341 
    342     \sa title()
    343 */
    344 
    345 /*!
    346     \fn void QGraphicsWebView::urlChanged(const QUrl &url)
    347 
    348     This signal is emitted when the \a url of the view changes.
    349 
    350     \sa url(), load()
    351 */
    352 
    353 /*!
    354     \fn void QGraphicsWebView::iconChanged()
    355 
    356     This signal is emitted whenever the icon of the page is loaded or changes.
    357 
    358     In order for icons to be loaded, you will need to set an icon database path
    359     using QWebSettings::setIconDatabasePath().
    360 
    361     \sa icon(), QWebSettings::setIconDatabasePath()
    362 */
    363 
    364 /*!
    365     \fn void QGraphicsWebView::loadStarted()
    366 
    367     This signal is emitted when a new load of the page is started.
    368 
    369     \sa loadProgress(), loadFinished()
    370 */
    371 
    372 /*!
    373     \fn void QGraphicsWebView::loadFinished(bool ok)
    374 
    375     This signal is emitted when a load of the page is finished.
    376     \a ok will indicate whether the load was successful or any error occurred.
    377 
    378     \sa loadStarted()
    379 */
    380 
    381 /*!
    382     Constructs an empty QGraphicsWebView with parent \a parent.
    383 
    384     \sa load()
    385 */
    386 QGraphicsWebView::QGraphicsWebView(QGraphicsItem* parent)
    387     : QGraphicsWidget(parent)
    388     , d(new QGraphicsWebViewPrivate(this))
    389 {
    390 #if QT_VERSION >= 0x040600
    391     setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
    392 #endif
    393     setAcceptDrops(true);
    394     setAcceptHoverEvents(true);
    395 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
    396     setAcceptTouchEvents(true);
    397 #endif
    398     setFocusPolicy(Qt::StrongFocus);
    399     setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
    400 }
    401 
    402 /*!
    403     Destroys the item.
    404 */
    405 QGraphicsWebView::~QGraphicsWebView()
    406 {
    407     if (d->page) {
    408 #if QT_VERSION >= 0x040600
    409         d->page->d->view.clear();
    410 #else
    411         d->page->d->view = 0;
    412 #endif
    413         d->page->d->client = 0; // unset the page client
    414     }
    415 
    416     if (d->page && d->page->parent() == this)
    417         delete d->page;
    418 
    419     delete d;
    420 }
    421 
    422 /*!
    423     Returns a pointer to the underlying web page.
    424 
    425     \sa setPage()
    426 */
    427 QWebPage* QGraphicsWebView::page() const
    428 {
    429     if (!d->page) {
    430         QGraphicsWebView* that = const_cast<QGraphicsWebView*>(this);
    431         QWebPage* page = new QWebPage(that);
    432 
    433         // Default to not having a background, in the case
    434         // the page doesn't provide one.
    435         QPalette palette = QApplication::palette();
    436         palette.setBrush(QPalette::Base, QColor::fromRgbF(0, 0, 0, 0));
    437         page->setPalette(palette);
    438 
    439         that->setPage(page);
    440     }
    441 
    442     return d->page;
    443 }
    444 
    445 /*! \reimp
    446 */
    447 void QGraphicsWebView::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget*)
    448 {
    449 #if USE(ACCELERATED_COMPOSITING)
    450     page()->mainFrame()->render(painter, d->overlay ? QWebFrame::ContentsLayer : QWebFrame::AllLayers, option->exposedRect.toAlignedRect());
    451 #else
    452     page()->mainFrame()->render(painter, QWebFrame::AllLayers, option->exposedRect.toRect());
    453 #endif
    454 }
    455 
    456 /*! \reimp
    457 */
    458 bool QGraphicsWebView::sceneEvent(QEvent* event)
    459 {
    460     // Re-implemented in order to allows fixing event-related bugs in patch releases.
    461 
    462 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
    463     if (d->page && (event->type() == QEvent::TouchBegin
    464                 || event->type() == QEvent::TouchEnd
    465                 || event->type() == QEvent::TouchUpdate)) {
    466         d->page->event(event);
    467         if (event->isAccepted())
    468             return true;
    469     }
    470 #endif
    471 
    472     return QGraphicsWidget::sceneEvent(event);
    473 }
    474 
    475 /*! \reimp
    476 */
    477 QVariant QGraphicsWebView::itemChange(GraphicsItemChange change, const QVariant& value)
    478 {
    479     switch (change) {
    480     // Differently from QWebView, it is interesting to QGraphicsWebView to handle
    481     // post mouse cursor change notifications. Reason: 'ItemCursorChange' is sent
    482     // as the first action in QGraphicsItem::setCursor implementation, and at that
    483     // item widget's cursor has not been effectively changed yet.
    484     // After cursor is properly set (at 'ItemCursorHasChanged' emission time), we
    485     // fire 'CursorChange'.
    486     case ItemCursorChange:
    487         return value;
    488     case ItemCursorHasChanged:
    489         QEvent event(QEvent::CursorChange);
    490         QApplication::sendEvent(this, &event);
    491         return value;
    492     }
    493 
    494     return QGraphicsWidget::itemChange(change, value);
    495 }
    496 
    497 /*! \reimp
    498 */
    499 QSizeF QGraphicsWebView::sizeHint(Qt::SizeHint which, const QSizeF& constraint) const
    500 {
    501     if (which == Qt::PreferredSize)
    502         return QSizeF(800, 600); // ###
    503     return QGraphicsWidget::sizeHint(which, constraint);
    504 }
    505 
    506 /*! \reimp
    507 */
    508 QVariant QGraphicsWebView::inputMethodQuery(Qt::InputMethodQuery query) const
    509 {
    510     if (d->page)
    511         return d->page->inputMethodQuery(query);
    512     return QVariant();
    513 }
    514 
    515 /*! \reimp
    516 */
    517 bool QGraphicsWebView::event(QEvent* event)
    518 {
    519     // Re-implemented in order to allows fixing event-related bugs in patch releases.
    520 
    521     if (d->page) {
    522 #ifndef QT_NO_CONTEXTMENU
    523         if (event->type() == QEvent::GraphicsSceneContextMenu) {
    524             if (!isEnabled())
    525                 return false;
    526 
    527             QGraphicsSceneContextMenuEvent* ev = static_cast<QGraphicsSceneContextMenuEvent*>(event);
    528             QContextMenuEvent fakeEvent(QContextMenuEvent::Reason(ev->reason()), ev->pos().toPoint());
    529             if (d->page->swallowContextMenuEvent(&fakeEvent)) {
    530                 event->accept();
    531                 return true;
    532             }
    533             d->page->updatePositionDependentActions(fakeEvent.pos());
    534         } else
    535 #endif // QT_NO_CONTEXTMENU
    536         {
    537 #ifndef QT_NO_CURSOR
    538             if (event->type() == QEvent::CursorChange) {
    539                 // An unsetCursor will set the cursor to Qt::ArrowCursor.
    540                 // Thus this cursor change might be a QWidget::unsetCursor()
    541                 // If this is not the case and it came from WebCore, the
    542                 // QWebPageClient already has set its cursor internally
    543                 // to Qt::ArrowCursor, so updating the cursor is always
    544                 // right, as it falls back to the last cursor set by
    545                 // WebCore.
    546                 // FIXME: Add a QEvent::CursorUnset or similar to Qt.
    547                 if (cursor().shape() == Qt::ArrowCursor)
    548                     d->resetCursor();
    549             }
    550 #endif
    551         }
    552     }
    553     return QGraphicsWidget::event(event);
    554 }
    555 
    556 /*!
    557     Makes \a page the new web page of the web graphicsitem.
    558 
    559     The parent QObject of the provided page remains the owner
    560     of the object. If the current document is a child of the web
    561     view, it will be deleted.
    562 
    563     \sa page()
    564 */
    565 void QGraphicsWebView::setPage(QWebPage* page)
    566 {
    567     if (d->page == page)
    568         return;
    569 
    570     if (d->page) {
    571         d->page->d->client = 0; // unset the page client
    572         if (d->page->parent() == this)
    573             delete d->page;
    574         else
    575             d->page->disconnect(this);
    576     }
    577 
    578     d->page = page;
    579     if (!d->page)
    580         return;
    581 #if USE(ACCELERATED_COMPOSITING)
    582     if (d->overlay)
    583         d->overlay->prepareGeometryChange();
    584 #endif
    585     d->page->d->client = d; // set the page client
    586 
    587     QSize size = geometry().size().toSize();
    588     page->setViewportSize(size);
    589 
    590     QWebFrame* mainFrame = d->page->mainFrame();
    591 
    592     connect(mainFrame, SIGNAL(titleChanged(QString)),
    593             this, SIGNAL(titleChanged(QString)));
    594     connect(mainFrame, SIGNAL(iconChanged()),
    595             this, SIGNAL(iconChanged()));
    596     connect(mainFrame, SIGNAL(urlChanged(QUrl)),
    597             this, SIGNAL(urlChanged(QUrl)));
    598     connect(d->page, SIGNAL(loadStarted()),
    599             this, SIGNAL(loadStarted()));
    600     connect(d->page, SIGNAL(loadProgress(int)),
    601             this, SIGNAL(loadProgress(int)));
    602     connect(d->page, SIGNAL(loadFinished(bool)),
    603             this, SLOT(_q_doLoadFinished(bool)));
    604     connect(d->page, SIGNAL(statusBarMessage(QString)),
    605             this, SIGNAL(statusBarMessage(QString)));
    606     connect(d->page, SIGNAL(linkClicked(QUrl)),
    607             this, SIGNAL(linkClicked(QUrl)));
    608 }
    609 
    610 /*!
    611     \property QGraphicsWebView::url
    612     \brief the url of the web page currently viewed
    613 
    614     Setting this property clears the view and loads the URL.
    615 
    616     By default, this property contains an empty, invalid URL.
    617 
    618     \sa load(), urlChanged()
    619 */
    620 
    621 void QGraphicsWebView::setUrl(const QUrl &url)
    622 {
    623     page()->mainFrame()->setUrl(url);
    624 }
    625 
    626 QUrl QGraphicsWebView::url() const
    627 {
    628     if (d->page)
    629         return d->page->mainFrame()->url();
    630 
    631     return QUrl();
    632 }
    633 
    634 /*!
    635     \property QGraphicsWebView::title
    636     \brief the title of the web page currently viewed
    637 
    638     By default, this property contains an empty string.
    639 
    640     \sa titleChanged()
    641 */
    642 QString QGraphicsWebView::title() const
    643 {
    644     if (d->page)
    645         return d->page->mainFrame()->title();
    646 
    647     return QString();
    648 }
    649 
    650 /*!
    651     \property QGraphicsWebView::icon
    652     \brief the icon associated with the web page currently viewed
    653 
    654     By default, this property contains a null icon.
    655 
    656     \sa iconChanged(), QWebSettings::iconForUrl()
    657 */
    658 QIcon QGraphicsWebView::icon() const
    659 {
    660     if (d->page)
    661         return d->page->mainFrame()->icon();
    662 
    663     return QIcon();
    664 }
    665 
    666 /*!
    667     \property QGraphicsWebView::zoomFactor
    668     \brief the zoom factor for the view
    669 */
    670 
    671 void QGraphicsWebView::setZoomFactor(qreal factor)
    672 {
    673     if (factor == page()->mainFrame()->zoomFactor())
    674         return;
    675 
    676     page()->mainFrame()->setZoomFactor(factor);
    677 }
    678 
    679 qreal QGraphicsWebView::zoomFactor() const
    680 {
    681     return page()->mainFrame()->zoomFactor();
    682 }
    683 
    684 /*! \reimp
    685 */
    686 void QGraphicsWebView::updateGeometry()
    687 {
    688 
    689 #if USE(ACCELERATED_COMPOSITING)
    690     if (d->overlay)
    691         d->overlay->prepareGeometryChange();
    692 #endif
    693 
    694     QGraphicsWidget::updateGeometry();
    695 
    696     if (!d->page)
    697         return;
    698 
    699     QSize size = geometry().size().toSize();
    700     d->page->setViewportSize(size);
    701 }
    702 
    703 /*! \reimp
    704 */
    705 void QGraphicsWebView::setGeometry(const QRectF& rect)
    706 {
    707     QGraphicsWidget::setGeometry(rect);
    708 
    709 #if USE(ACCELERATED_COMPOSITING)
    710     if (d->overlay)
    711         d->overlay->prepareGeometryChange();
    712 #endif
    713 
    714     if (!d->page)
    715         return;
    716 
    717     // NOTE: call geometry() as setGeometry ensures that
    718     // the geometry is within legal bounds (minimumSize, maximumSize)
    719     QSize size = geometry().size().toSize();
    720     d->page->setViewportSize(size);
    721 }
    722 
    723 /*!
    724     Convenience slot that stops loading the document.
    725 
    726     \sa reload(), loadFinished()
    727 */
    728 void QGraphicsWebView::stop()
    729 {
    730     if (d->page)
    731         d->page->triggerAction(QWebPage::Stop);
    732 }
    733 
    734 /*!
    735     Convenience slot that loads the previous document in the list of documents
    736     built by navigating links. Does nothing if there is no previous document.
    737 
    738     \sa forward()
    739 */
    740 void QGraphicsWebView::back()
    741 {
    742     if (d->page)
    743         d->page->triggerAction(QWebPage::Back);
    744 }
    745 
    746 /*!
    747     Convenience slot that loads the next document in the list of documents
    748     built by navigating links. Does nothing if there is no next document.
    749 
    750     \sa back()
    751 */
    752 void QGraphicsWebView::forward()
    753 {
    754     if (d->page)
    755         d->page->triggerAction(QWebPage::Forward);
    756 }
    757 
    758 /*!
    759     Reloads the current document.
    760 
    761     \sa stop(), loadStarted()
    762 */
    763 void QGraphicsWebView::reload()
    764 {
    765     if (d->page)
    766         d->page->triggerAction(QWebPage::Reload);
    767 }
    768 
    769 /*!
    770     Loads the specified \a url and displays it.
    771 
    772     \note The view remains the same until enough data has arrived to display the new \a url.
    773 
    774     \sa setUrl(), url(), urlChanged()
    775 */
    776 void QGraphicsWebView::load(const QUrl& url)
    777 {
    778     page()->mainFrame()->load(url);
    779 }
    780 
    781 /*!
    782     \fn void QGraphicsWebView::load(const QNetworkRequest &request, QNetworkAccessManager::Operation operation, const QByteArray &body)
    783 
    784     Loads a network request, \a request, using the method specified in \a operation.
    785 
    786     \a body is optional and is only used for POST operations.
    787 
    788     \note The view remains the same until enough data has arrived to display the new url.
    789 
    790     \sa url(), urlChanged()
    791 */
    792 
    793 void QGraphicsWebView::load(const QNetworkRequest& request,
    794                     QNetworkAccessManager::Operation operation,
    795                     const QByteArray& body)
    796 {
    797     page()->mainFrame()->load(request, operation, body);
    798 }
    799 
    800 /*!
    801     Sets the content of the web view to the specified \a html.
    802 
    803     External objects such as stylesheets or images referenced in the HTML
    804     document are located relative to \a baseUrl.
    805 
    806     The \a html is loaded immediately; external objects are loaded asynchronously.
    807 
    808     When using this method, WebKit assumes that external resources such as
    809     JavaScript programs or style sheets are encoded in UTF-8 unless otherwise
    810     specified. For example, the encoding of an external script can be specified
    811     through the charset attribute of the HTML script tag. Alternatively, the
    812     encoding can also be specified by the web server.
    813 
    814     \sa load(), setContent(), QWebFrame::toHtml()
    815 */
    816 void QGraphicsWebView::setHtml(const QString& html, const QUrl& baseUrl)
    817 {
    818     page()->mainFrame()->setHtml(html, baseUrl);
    819 }
    820 
    821 /*!
    822     Sets the content of the web graphicsitem to the specified content \a data. If the \a mimeType argument
    823     is empty it is currently assumed that the content is HTML but in future versions we may introduce
    824     auto-detection.
    825 
    826     External objects referenced in the content are located relative to \a baseUrl.
    827 
    828     The \a data is loaded immediately; external objects are loaded asynchronously.
    829 
    830     \sa load(), setHtml(), QWebFrame::toHtml()
    831 */
    832 void QGraphicsWebView::setContent(const QByteArray& data, const QString& mimeType, const QUrl& baseUrl)
    833 {
    834     page()->mainFrame()->setContent(data, mimeType, baseUrl);
    835 }
    836 
    837 /*!
    838     Returns a pointer to the view's history of navigated web pages.
    839 
    840     It is equivalent to
    841 
    842     \snippet webkitsnippets/qtwebkit_qwebview_snippet.cpp 0
    843 */
    844 QWebHistory* QGraphicsWebView::history() const
    845 {
    846     return page()->history();
    847 }
    848 
    849 /*!
    850     \property QGraphicsWebView::modified
    851     \brief whether the document was modified by the user
    852 
    853     Parts of HTML documents can be editable for example through the
    854     \c{contenteditable} attribute on HTML elements.
    855 
    856     By default, this property is false.
    857 */
    858 bool QGraphicsWebView::isModified() const
    859 {
    860     if (d->page)
    861         return d->page->isModified();
    862     return false;
    863 }
    864 
    865 /*!
    866     Returns a pointer to the view/page specific settings object.
    867 
    868     It is equivalent to
    869 
    870     \snippet webkitsnippets/qtwebkit_qwebview_snippet.cpp 1
    871 
    872     \sa QWebSettings::globalSettings()
    873 */
    874 QWebSettings* QGraphicsWebView::settings() const
    875 {
    876     return page()->settings();
    877 }
    878 
    879 /*!
    880     Returns a pointer to a QAction that encapsulates the specified web action \a action.
    881 */
    882 QAction *QGraphicsWebView::pageAction(QWebPage::WebAction action) const
    883 {
    884     return page()->action(action);
    885 }
    886 
    887 /*!
    888     Triggers the specified \a action. If it is a checkable action the specified
    889     \a checked state is assumed.
    890 
    891     \sa pageAction()
    892 */
    893 void QGraphicsWebView::triggerPageAction(QWebPage::WebAction action, bool checked)
    894 {
    895     page()->triggerAction(action, checked);
    896 }
    897 
    898 /*!
    899     Finds the specified string, \a subString, in the page, using the given \a options.
    900 
    901     If the HighlightAllOccurrences flag is passed, the function will highlight all occurrences
    902     that exist in the page. All subsequent calls will extend the highlight, rather than
    903     replace it, with occurrences of the new string.
    904 
    905     If the HighlightAllOccurrences flag is not passed, the function will select an occurrence
    906     and all subsequent calls will replace the current occurrence with the next one.
    907 
    908     To clear the selection, just pass an empty string.
    909 
    910     Returns true if \a subString was found; otherwise returns false.
    911 
    912     \sa QWebPage::selectedText(), QWebPage::selectionChanged()
    913 */
    914 bool QGraphicsWebView::findText(const QString &subString, QWebPage::FindFlags options)
    915 {
    916     if (d->page)
    917         return d->page->findText(subString, options);
    918     return false;
    919 }
    920 
    921 /*! \reimp
    922 */
    923 void QGraphicsWebView::hoverMoveEvent(QGraphicsSceneHoverEvent* ev)
    924 {
    925     if (d->page) {
    926         const bool accepted = ev->isAccepted();
    927         QMouseEvent me = QMouseEvent(QEvent::MouseMove,
    928                 ev->pos().toPoint(), Qt::NoButton,
    929                 Qt::NoButton, Qt::NoModifier);
    930         d->page->event(&me);
    931         ev->setAccepted(accepted);
    932     }
    933 
    934     if (!ev->isAccepted())
    935         QGraphicsItem::hoverMoveEvent(ev);
    936 }
    937 
    938 /*! \reimp
    939 */
    940 void QGraphicsWebView::hoverLeaveEvent(QGraphicsSceneHoverEvent* ev)
    941 {
    942     Q_UNUSED(ev);
    943 }
    944 
    945 /*! \reimp
    946 */
    947 void QGraphicsWebView::mouseMoveEvent(QGraphicsSceneMouseEvent* ev)
    948 {
    949     if (d->page) {
    950         const bool accepted = ev->isAccepted();
    951         d->page->event(ev);
    952         ev->setAccepted(accepted);
    953     }
    954 
    955     if (!ev->isAccepted())
    956         QGraphicsItem::mouseMoveEvent(ev);
    957 }
    958 
    959 /*! \reimp
    960 */
    961 void QGraphicsWebView::mousePressEvent(QGraphicsSceneMouseEvent* ev)
    962 {
    963     if (d->page) {
    964         const bool accepted = ev->isAccepted();
    965         d->page->event(ev);
    966         ev->setAccepted(accepted);
    967     }
    968 
    969     if (!ev->isAccepted())
    970         QGraphicsItem::mousePressEvent(ev);
    971 }
    972 
    973 /*! \reimp
    974 */
    975 void QGraphicsWebView::mouseReleaseEvent(QGraphicsSceneMouseEvent* ev)
    976 {
    977     if (d->page) {
    978         const bool accepted = ev->isAccepted();
    979         d->page->event(ev);
    980         ev->setAccepted(accepted);
    981     }
    982 
    983     if (!ev->isAccepted())
    984         QGraphicsItem::mouseReleaseEvent(ev);
    985 }
    986 
    987 /*! \reimp
    988 */
    989 void QGraphicsWebView::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* ev)
    990 {
    991     if (d->page) {
    992         const bool accepted = ev->isAccepted();
    993         d->page->event(ev);
    994         ev->setAccepted(accepted);
    995     }
    996 
    997     if (!ev->isAccepted())
    998         QGraphicsItem::mouseDoubleClickEvent(ev);
    999 }
   1000 
   1001 /*! \reimp
   1002 */
   1003 void QGraphicsWebView::keyPressEvent(QKeyEvent* ev)
   1004 {
   1005     if (d->page)
   1006         d->page->event(ev);
   1007 
   1008     if (!ev->isAccepted())
   1009         QGraphicsItem::keyPressEvent(ev);
   1010 }
   1011 
   1012 /*! \reimp
   1013 */
   1014 void QGraphicsWebView::keyReleaseEvent(QKeyEvent* ev)
   1015 {
   1016     if (d->page)
   1017         d->page->event(ev);
   1018 
   1019     if (!ev->isAccepted())
   1020         QGraphicsItem::keyReleaseEvent(ev);
   1021 }
   1022 
   1023 /*! \reimp
   1024 */
   1025 void QGraphicsWebView::focusInEvent(QFocusEvent* ev)
   1026 {
   1027     if (d->page)
   1028         d->page->event(ev);
   1029     else
   1030         QGraphicsItem::focusInEvent(ev);
   1031 }
   1032 
   1033 /*! \reimp
   1034 */
   1035 void QGraphicsWebView::focusOutEvent(QFocusEvent* ev)
   1036 {
   1037     if (d->page)
   1038         d->page->event(ev);
   1039     else
   1040         QGraphicsItem::focusOutEvent(ev);
   1041 }
   1042 
   1043 /*! \reimp
   1044 */
   1045 bool QGraphicsWebView::focusNextPrevChild(bool next)
   1046 {
   1047     if (d->page)
   1048         return d->page->focusNextPrevChild(next);
   1049 
   1050     return QGraphicsWidget::focusNextPrevChild(next);
   1051 }
   1052 
   1053 /*! \reimp
   1054 */
   1055 void QGraphicsWebView::dragEnterEvent(QGraphicsSceneDragDropEvent* ev)
   1056 {
   1057 #ifndef QT_NO_DRAGANDDROP
   1058     if (d->page)
   1059         d->page->event(ev);
   1060 #else
   1061     Q_UNUSED(ev);
   1062 #endif
   1063 }
   1064 
   1065 /*! \reimp
   1066 */
   1067 void QGraphicsWebView::dragLeaveEvent(QGraphicsSceneDragDropEvent* ev)
   1068 {
   1069 #ifndef QT_NO_DRAGANDDROP
   1070     if (d->page) {
   1071         const bool accepted = ev->isAccepted();
   1072         d->page->event(ev);
   1073         ev->setAccepted(accepted);
   1074     }
   1075 
   1076     if (!ev->isAccepted())
   1077         QGraphicsWidget::dragLeaveEvent(ev);
   1078 #else
   1079     Q_UNUSED(ev);
   1080 #endif
   1081 }
   1082 
   1083 /*! \reimp
   1084 */
   1085 void QGraphicsWebView::dragMoveEvent(QGraphicsSceneDragDropEvent* ev)
   1086 {
   1087 #ifndef QT_NO_DRAGANDDROP
   1088     if (d->page) {
   1089         const bool accepted = ev->isAccepted();
   1090         d->page->event(ev);
   1091         ev->setAccepted(accepted);
   1092     }
   1093 
   1094     if (!ev->isAccepted())
   1095         QGraphicsWidget::dragMoveEvent(ev);
   1096 #else
   1097     Q_UNUSED(ev);
   1098 #endif
   1099 }
   1100 
   1101 /*! \reimp
   1102 */
   1103 void QGraphicsWebView::dropEvent(QGraphicsSceneDragDropEvent* ev)
   1104 {
   1105 #ifndef QT_NO_DRAGANDDROP
   1106     if (d->page) {
   1107         const bool accepted = ev->isAccepted();
   1108         d->page->event(ev);
   1109         ev->setAccepted(accepted);
   1110     }
   1111 
   1112     if (!ev->isAccepted())
   1113         QGraphicsWidget::dropEvent(ev);
   1114 #else
   1115     Q_UNUSED(ev);
   1116 #endif
   1117 }
   1118 
   1119 #ifndef QT_NO_CONTEXTMENU
   1120 /*! \reimp
   1121 */
   1122 void QGraphicsWebView::contextMenuEvent(QGraphicsSceneContextMenuEvent* ev)
   1123 {
   1124     if (d->page) {
   1125         const bool accepted = ev->isAccepted();
   1126         d->page->event(ev);
   1127         ev->setAccepted(accepted);
   1128     }
   1129 }
   1130 #endif // QT_NO_CONTEXTMENU
   1131 
   1132 #ifndef QT_NO_WHEELEVENT
   1133 /*! \reimp
   1134 */
   1135 void QGraphicsWebView::wheelEvent(QGraphicsSceneWheelEvent* ev)
   1136 {
   1137     if (d->page) {
   1138         const bool accepted = ev->isAccepted();
   1139         d->page->event(ev);
   1140         ev->setAccepted(accepted);
   1141     }
   1142 
   1143     if (!ev->isAccepted())
   1144         QGraphicsItem::wheelEvent(ev);
   1145 }
   1146 #endif // QT_NO_WHEELEVENT
   1147 
   1148 /*! \reimp
   1149 */
   1150 void QGraphicsWebView::inputMethodEvent(QInputMethodEvent* ev)
   1151 {
   1152     if (d->page)
   1153         d->page->event(ev);
   1154 
   1155     if (!ev->isAccepted())
   1156         QGraphicsItem::inputMethodEvent(ev);
   1157 }
   1158 
   1159 /*!
   1160     \fn void QGraphicsWebView::statusBarMessage(const QString& text)
   1161 
   1162     This signal is emitted when the statusbar \a text is changed by the page.
   1163 */
   1164 
   1165 /*!
   1166     \fn void QGraphicsWebView::loadProgress(int progress)
   1167 
   1168     This signal is emitted every time an element in the web page
   1169     completes loading and the overall loading progress advances.
   1170 
   1171     This signal tracks the progress of all child frames.
   1172 
   1173     The current value is provided by \a progress and scales from 0 to 100,
   1174     which is the default range of QProgressBar.
   1175 
   1176     \sa loadStarted(), loadFinished()
   1177 */
   1178 
   1179 /*!
   1180     \fn void QGraphicsWebView::linkClicked(const QUrl &url)
   1181 
   1182     This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy
   1183     property is set to delegate the link handling for the specified \a url.
   1184 
   1185     \sa QWebPage::linkDelegationPolicy()
   1186 */
   1187 
   1188 #include "moc_qgraphicswebview.cpp"
   1189