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