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