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