• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #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:
QGraphicsWebViewOverlay(QGraphicsWebView * view)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 
boundingRect() const59     QRectF boundingRect() const
60     {
61         return q->boundingRect();
62     }
63 
paint(QPainter * painter,const QStyleOptionGraphicsItem * options,QWidget *)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:
QGraphicsWebViewPrivate(QGraphicsWebView * parent)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 
~QGraphicsWebViewPrivate()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)
setRootGraphicsLayer(QGraphicsItem * layer)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 
markForSync(bool scheduleSync)182 void QGraphicsWebViewPrivate::markForSync(bool scheduleSync)
183 {
184     shouldSync = true;
185     if (scheduleSync)
186         syncMetaMethod.invoke(q, Qt::QueuedConnection);
187 }
188 
updateCompositingScrollPosition()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 
syncLayers()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 
_q_doLoadFinished(bool success)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 
scroll(int dx,int dy,const QRect & rectToScroll)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 
update(const QRect & dirtyRect)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 
setInputMethodEnabled(bool enable)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 
inputMethodEnabled() const244 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
setInputMethodHint(Qt::InputMethodHint hint,bool enable)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
cursor() const263 QCursor QGraphicsWebViewPrivate::cursor() const
264 {
265     return q->cursor();
266 }
267 
updateCursor(const QCursor & cursor)268 void QGraphicsWebViewPrivate::updateCursor(const QCursor& cursor)
269 {
270     q->setCursor(cursor);
271 }
272 #endif
273 
palette() const274 QPalette QGraphicsWebViewPrivate::palette() const
275 {
276     return q->palette();
277 }
278 
screenNumber() const279 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 
ownerWidget() const291 QWidget* QGraphicsWebViewPrivate::ownerWidget() const
292 {
293     const QList<QGraphicsView*> views = q->scene()->views();
294     return views.value(0);
295 }
296 
pluginParent() const297 QObject* QGraphicsWebViewPrivate::pluginParent() const
298 {
299     return q;
300 }
301 
style() const302 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 */
QGraphicsWebView(QGraphicsItem * parent)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 */
~QGraphicsWebView()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 */
page() const427 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 */
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget *)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 */
sceneEvent(QEvent * event)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 */
itemChange(GraphicsItemChange change,const QVariant & value)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 */
sizeHint(Qt::SizeHint which,const QSizeF & constraint) const499 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 */
inputMethodQuery(Qt::InputMethodQuery query) const508 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 */
event(QEvent * event)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 */
setPage(QWebPage * page)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 
setUrl(const QUrl & url)621 void QGraphicsWebView::setUrl(const QUrl &url)
622 {
623     page()->mainFrame()->setUrl(url);
624 }
625 
url() const626 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 */
title() const642 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 */
icon() const658 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 
setZoomFactor(qreal factor)671 void QGraphicsWebView::setZoomFactor(qreal factor)
672 {
673     if (factor == page()->mainFrame()->zoomFactor())
674         return;
675 
676     page()->mainFrame()->setZoomFactor(factor);
677 }
678 
zoomFactor() const679 qreal QGraphicsWebView::zoomFactor() const
680 {
681     return page()->mainFrame()->zoomFactor();
682 }
683 
684 /*! \reimp
685 */
updateGeometry()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 */
setGeometry(const QRectF & rect)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 */
stop()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 */
back()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 */
forward()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 */
reload()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 */
load(const QUrl & url)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 
load(const QNetworkRequest & request,QNetworkAccessManager::Operation operation,const QByteArray & body)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 */
setHtml(const QString & html,const QUrl & baseUrl)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 */
setContent(const QByteArray & data,const QString & mimeType,const QUrl & baseUrl)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 */
history() const844 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 */
isModified() const858 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 */
settings() const874 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 */
pageAction(QWebPage::WebAction action) const882 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 */
triggerPageAction(QWebPage::WebAction action,bool checked)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 */
findText(const QString & subString,QWebPage::FindFlags options)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 */
hoverMoveEvent(QGraphicsSceneHoverEvent * ev)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 */
hoverLeaveEvent(QGraphicsSceneHoverEvent * ev)940 void QGraphicsWebView::hoverLeaveEvent(QGraphicsSceneHoverEvent* ev)
941 {
942     Q_UNUSED(ev);
943 }
944 
945 /*! \reimp
946 */
mouseMoveEvent(QGraphicsSceneMouseEvent * ev)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 */
mousePressEvent(QGraphicsSceneMouseEvent * ev)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 */
mouseReleaseEvent(QGraphicsSceneMouseEvent * ev)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 */
mouseDoubleClickEvent(QGraphicsSceneMouseEvent * ev)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 */
keyPressEvent(QKeyEvent * ev)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 */
keyReleaseEvent(QKeyEvent * ev)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 */
focusInEvent(QFocusEvent * ev)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 */
focusOutEvent(QFocusEvent * ev)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 */
focusNextPrevChild(bool next)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 */
dragEnterEvent(QGraphicsSceneDragDropEvent * ev)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 */
dragLeaveEvent(QGraphicsSceneDragDropEvent * ev)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 */
dragMoveEvent(QGraphicsSceneDragDropEvent * ev)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 */
dropEvent(QGraphicsSceneDragDropEvent * ev)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 */
contextMenuEvent(QGraphicsSceneContextMenuEvent * ev)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 */
wheelEvent(QGraphicsSceneWheelEvent * ev)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 */
inputMethodEvent(QInputMethodEvent * ev)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