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