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