qdeclarativewebview.cpp revision 2fc2651226baac27029e38c9d6ef883fa32084db
1/* 2 Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) 3 4 This library is free software; you can redistribute it and/or 5 modify it under the terms of the GNU Library General Public 6 License as published by the Free Software Foundation; either 7 version 2 of the License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Library General Public License for more details. 13 14 You should have received a copy of the GNU Library General Public License 15 along with this library; see the file COPYING.LIB. If not, write to 16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 Boston, MA 02110-1301, USA. 18*/ 19 20 21#include "qdeclarativewebview_p.h" 22 23#include <QtCore/QDebug> 24#include <QtCore/QEvent> 25#include <QtCore/QFile> 26#include <QtDeclarative/QDeclarativeContext> 27#include <QtDeclarative/QDeclarativeEngine> 28#include <QtDeclarative/qdeclarative.h> 29#include <QtGui/QApplication> 30#include <QtGui/QGraphicsSceneMouseEvent> 31#include <QtGui/QKeyEvent> 32#include <QtGui/QMouseEvent> 33#include <QtGui/QPen> 34#include "qwebelement.h" 35#include "qwebframe.h" 36#include "qwebpage.h" 37#include "qwebsettings.h" 38 39QT_BEGIN_NAMESPACE 40 41class QDeclarativeWebViewPrivate { 42public: 43 QDeclarativeWebViewPrivate(QDeclarativeWebView* qq) 44 : q(qq) 45 , preferredwidth(0) 46 , preferredheight(0) 47 , progress(1.0) 48 , status(QDeclarativeWebView::Null) 49 , pending(PendingNone) 50 , newWindowComponent(0) 51 , newWindowParent(0) 52 , rendering(true) 53 { 54 } 55 56 QDeclarativeWebView* q; 57 58 QUrl url; // page url might be different if it has not loaded yet 59 GraphicsWebView* view; 60 61 int preferredwidth, preferredheight; 62 qreal progress; 63 QDeclarativeWebView::Status status; 64 QString statusText; 65 enum { PendingNone, PendingUrl, PendingHtml, PendingContent } pending; 66 QUrl pendingUrl; 67 QString pendingString; 68 QByteArray pendingData; 69 mutable QDeclarativeWebSettings settings; 70 QDeclarativeComponent* newWindowComponent; 71 QDeclarativeItem* newWindowParent; 72 73 static void windowObjectsAppend(QDeclarativeListProperty<QObject>* prop, QObject* o) 74 { 75 static_cast<QDeclarativeWebViewPrivate*>(prop->data)->windowObjects.append(o); 76 static_cast<QDeclarativeWebViewPrivate*>(prop->data)->updateWindowObjects(); 77 } 78 79 void updateWindowObjects(); 80 QObjectList windowObjects; 81 82 bool rendering; 83}; 84 85GraphicsWebView::GraphicsWebView(QDeclarativeWebView* parent) 86 : QGraphicsWebView(parent) 87 , parent(parent) 88 , pressTime(400) 89{ 90} 91 92void GraphicsWebView::mousePressEvent(QGraphicsSceneMouseEvent* event) 93{ 94 pressPoint = event->pos(); 95 if (pressTime) { 96 pressTimer.start(pressTime, this); 97 parent->setKeepMouseGrab(false); 98 } else { 99 grabMouse(); 100 parent->setKeepMouseGrab(true); 101 } 102 QGraphicsWebView::mousePressEvent(event); 103 104 QWebHitTestResult hit = page()->mainFrame()->hitTestContent(pressPoint.toPoint()); 105 if (hit.isContentEditable()) 106 parent->forceActiveFocus(); 107 setFocus(); 108} 109 110void GraphicsWebView::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) 111{ 112 QGraphicsWebView::mouseReleaseEvent(event); 113 pressTimer.stop(); 114 parent->setKeepMouseGrab(false); 115 ungrabMouse(); 116} 117 118void GraphicsWebView::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event) 119{ 120 QMouseEvent* me = new QMouseEvent(QEvent::MouseButtonDblClick, (event->pos() / parent->contentsScale()).toPoint(), event->button(), event->buttons(), 0); 121 emit doubleClick(event->pos().x(), event->pos().y()); 122 delete me; 123} 124 125void GraphicsWebView::timerEvent(QTimerEvent* event) 126{ 127 if (event->timerId() == pressTimer.timerId()) { 128 pressTimer.stop(); 129 grabMouse(); 130 parent->setKeepMouseGrab(true); 131 } 132} 133 134void GraphicsWebView::mouseMoveEvent(QGraphicsSceneMouseEvent* event) 135{ 136 if (pressTimer.isActive()) { 137 if ((event->pos() - pressPoint).manhattanLength() > QApplication::startDragDistance()) 138 pressTimer.stop(); 139 } 140 if (parent->keepMouseGrab()) 141 QGraphicsWebView::mouseMoveEvent(event); 142} 143 144bool GraphicsWebView::sceneEvent(QEvent *event) 145{ 146 bool rv = QGraphicsWebView::sceneEvent(event); 147 if (event->type() == QEvent::UngrabMouse) { 148 pressTimer.stop(); 149 parent->setKeepMouseGrab(false); 150 } 151 return rv; 152} 153 154/*! 155 \qmlclass WebView QDeclarativeWebView 156 \ingroup qml-view-elements 157 \since 4.7 158 \brief The WebView item allows you to add Web content to a canvas. 159 \inherits Item 160 161 A WebView renders Web content based on a URL. 162 163 This type is made available by importing the \c QtWebKit module: 164 165 \bold{import QtWebKit 1.0} 166 167 The WebView item includes no scrolling, scaling, toolbars, or other common browser 168 components. These must be implemented around WebView. See the \l{QML Web Browser} 169 example for a demonstration of this. 170 171 The page to be displayed by the item is specified using the \l url property, 172 and this can be changed to fetch and display a new page. While the page loads, 173 the \l progress property is updated to indicate how much of the page has been 174 loaded. 175 176 \section1 Appearance 177 178 If the width and height of the item is not set, they will dynamically adjust 179 to a size appropriate for the content. This width may be large for typical 180 online web pages, typically greater than 800 by 600 pixels. 181 182 If the \l{Item::}{width} or \l{Item::}{height} is explictly set, the rendered Web site will be 183 clipped, not scaled, to fit into the set dimensions. 184 185 If the preferredWidth property is set, the width will be this amount or larger, 186 usually laying out the Web content to fit the preferredWidth. 187 188 The appearance of the content can be controlled to a certain extent by changing 189 the settings.standardFontFamily property and other settings related to fonts. 190 191 The page can be zoomed by calling the heuristicZoom() method, which performs a 192 series of tests to determine whether zoomed content will be displayed in an 193 appropriate way in the space allocated to the item. 194 195 \section1 User Interaction and Navigation 196 197 By default, certain mouse and touch events are delivered to other items in 198 preference to the Web content. For example, when a scrolling view is created 199 by placing a WebView in a Flickable, move events are delivered to the Flickable 200 so that the user can scroll the page. This prevents the user from accidentally 201 selecting text in a Web page instead of scrolling. 202 203 The pressGrabTime property defines the time the user must touch or press a 204 mouse button over the WebView before the Web content will receive the move 205 events it needs to select text and images. 206 207 When this item has keyboard focus, all keyboard input will be sent directly to 208 the Web page within. 209 210 When the navigates by clicking on links, the item records the pages visited 211 in its internal history 212 213 Because this item is designed to be used as a component in a browser, it 214 exposes \l{Action}{actions} for \l back, \l forward, \l reload and \l stop. 215 These can be triggered to change the current page displayed by the item. 216 217 \section1 Example Usage 218 219 \beginfloatright 220 \inlineimage webview.png 221 \endfloat 222 223 The following example displays a scaled down Web page at a fixed size. 224 225 \snippet doc/src/snippets/declarative/webview/webview.qml document 226 227 \clearfloat 228 229 \sa {declarative/modelviews/webview}{WebView example}, {demos/declarative/webbrowser}{Web Browser demo} 230*/ 231 232/*! 233 \internal 234 \class QDeclarativeWebView 235 \brief The QDeclarativeWebView class allows you to add web content to a QDeclarativeView. 236 237 A WebView renders web content base on a URL. 238 239 \image webview.png 240 241 The item includes no scrolling, scaling, 242 toolbars, etc., those must be implemented around WebView. See the WebBrowser example 243 for a demonstration of this. 244 245 A QDeclarativeWebView object can be instantiated in Qml using the tag \l WebView. 246*/ 247 248QDeclarativeWebView::QDeclarativeWebView(QDeclarativeItem *parent) : QDeclarativeItem(parent) 249{ 250 init(); 251} 252 253QDeclarativeWebView::~QDeclarativeWebView() 254{ 255 delete d; 256} 257 258void QDeclarativeWebView::init() 259{ 260 d = new QDeclarativeWebViewPrivate(this); 261 262 if (QWebSettings::iconDatabasePath().isNull() && 263 QWebSettings::globalSettings()->localStoragePath().isNull() && 264 QWebSettings::offlineStoragePath().isNull() && 265 QWebSettings::offlineWebApplicationCachePath().isNull()) 266 QWebSettings::enablePersistentStorage(); 267 268 setAcceptedMouseButtons(Qt::LeftButton); 269 setFlag(QGraphicsItem::ItemHasNoContents, true); 270 setFlag(QGraphicsItem::ItemIsFocusScope, true); 271 setClip(true); 272 273 d->view = new GraphicsWebView(this); 274 d->view->setResizesToContents(true); 275 d->view->setFocus(); 276 QWebPage* wp = new QDeclarativeWebPage(this); 277 setPage(wp); 278 connect(d->view, SIGNAL(geometryChanged()), this, SLOT(updateDeclarativeWebViewSize())); 279 connect(d->view, SIGNAL(doubleClick(int, int)), this, SIGNAL(doubleClick(int, int))); 280 connect(d->view, SIGNAL(scaleChanged()), this, SIGNAL(contentsScaleChanged())); 281} 282 283void QDeclarativeWebView::componentComplete() 284{ 285 QDeclarativeItem::componentComplete(); 286 page()->setNetworkAccessManager(qmlEngine(this)->networkAccessManager()); 287 288 switch (d->pending) { 289 case QDeclarativeWebViewPrivate::PendingUrl: 290 setUrl(d->pendingUrl); 291 break; 292 case QDeclarativeWebViewPrivate::PendingHtml: 293 setHtml(d->pendingString, d->pendingUrl); 294 break; 295 case QDeclarativeWebViewPrivate::PendingContent: 296 setContent(d->pendingData, d->pendingString, d->pendingUrl); 297 break; 298 default: 299 break; 300 } 301 d->pending = QDeclarativeWebViewPrivate::PendingNone; 302 d->updateWindowObjects(); 303} 304 305QDeclarativeWebView::Status QDeclarativeWebView::status() const 306{ 307 return d->status; 308} 309 310 311/*! 312 \qmlproperty real WebView::progress 313 This property holds the progress of loading the current URL, from 0 to 1. 314 315 If you just want to know when progress gets to 1, use 316 WebView::onLoadFinished() or WebView::onLoadFailed() instead. 317*/ 318qreal QDeclarativeWebView::progress() const 319{ 320 return d->progress; 321} 322 323void QDeclarativeWebView::doLoadStarted() 324{ 325 if (!d->url.isEmpty()) { 326 d->status = Loading; 327 emit statusChanged(d->status); 328 } 329 emit loadStarted(); 330} 331 332void QDeclarativeWebView::doLoadProgress(int p) 333{ 334 if (d->progress == p / 100.0) 335 return; 336 d->progress = p / 100.0; 337 emit progressChanged(); 338} 339 340void QDeclarativeWebView::pageUrlChanged() 341{ 342 updateContentsSize(); 343 344 if ((d->url.isEmpty() && page()->mainFrame()->url() != QUrl(QLatin1String("about:blank"))) 345 || (d->url != page()->mainFrame()->url() && !page()->mainFrame()->url().isEmpty())) 346 { 347 d->url = page()->mainFrame()->url(); 348 if (d->url == QUrl(QLatin1String("about:blank"))) 349 d->url = QUrl(); 350 emit urlChanged(); 351 } 352} 353 354void QDeclarativeWebView::doLoadFinished(bool ok) 355{ 356 if (ok) { 357 d->status = d->url.isEmpty() ? Null : Ready; 358 emit loadFinished(); 359 } else { 360 d->status = Error; 361 emit loadFailed(); 362 } 363 emit statusChanged(d->status); 364} 365 366/*! 367 \qmlproperty url WebView::url 368 This property holds the URL to the page displayed in this item. It can be set, 369 but also can change spontaneously (eg. because of network redirection). 370 371 If the url is empty, the page is blank. 372 373 The url is always absolute (QML will resolve relative URL strings in the context 374 of the containing QML document). 375*/ 376QUrl QDeclarativeWebView::url() const 377{ 378 return d->url; 379} 380 381void QDeclarativeWebView::setUrl(const QUrl& url) 382{ 383 if (url == d->url) 384 return; 385 386 if (isComponentComplete()) { 387 d->url = url; 388 updateContentsSize(); 389 QUrl seturl = url; 390 if (seturl.isEmpty()) 391 seturl = QUrl(QLatin1String("about:blank")); 392 393 Q_ASSERT(!seturl.isRelative()); 394 395 page()->mainFrame()->load(seturl); 396 397 emit urlChanged(); 398 } else { 399 d->pending = d->PendingUrl; 400 d->pendingUrl = url; 401 } 402} 403 404/*! 405 \qmlproperty int WebView::preferredWidth 406 This property holds the ideal width for displaying the current URL. 407*/ 408int QDeclarativeWebView::preferredWidth() const 409{ 410 return d->preferredwidth; 411} 412 413void QDeclarativeWebView::setPreferredWidth(int width) 414{ 415 if (d->preferredwidth == width) 416 return; 417 d->preferredwidth = width; 418 updateContentsSize(); 419 emit preferredWidthChanged(); 420} 421 422/*! 423 \qmlproperty int WebView::preferredHeight 424 This property holds the ideal height for displaying the current URL. 425 This only affects the area zoomed by heuristicZoom(). 426*/ 427int QDeclarativeWebView::preferredHeight() const 428{ 429 return d->preferredheight; 430} 431 432void QDeclarativeWebView::setPreferredHeight(int height) 433{ 434 if (d->preferredheight == height) 435 return; 436 d->preferredheight = height; 437 updateContentsSize(); 438 emit preferredHeightChanged(); 439} 440 441/*! 442 \qmlmethod bool WebView::evaluateJavaScript(string scriptSource) 443 444 Evaluates the \a scriptSource JavaScript inside the context of the 445 main web frame, and returns the result of the last executed statement. 446 447 Note that this JavaScript does \e not have any access to QML objects 448 except as made available as windowObjects. 449*/ 450QVariant QDeclarativeWebView::evaluateJavaScript(const QString& scriptSource) 451{ 452 return this->page()->mainFrame()->evaluateJavaScript(scriptSource); 453} 454 455void QDeclarativeWebView::updateDeclarativeWebViewSize() 456{ 457 QSizeF size = d->view->geometry().size() * contentsScale(); 458 setImplicitWidth(size.width()); 459 setImplicitHeight(size.height()); 460} 461 462void QDeclarativeWebView::initialLayout() 463{ 464 // nothing useful to do at this point 465} 466 467void QDeclarativeWebView::updateContentsSize() 468{ 469 if (page()) { 470 page()->setPreferredContentsSize(QSize( 471 d->preferredwidth>0 ? d->preferredwidth : width(), 472 d->preferredheight>0 ? d->preferredheight : height())); 473 } 474} 475 476void QDeclarativeWebView::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry) 477{ 478 QWebPage* webPage = page(); 479 if (newGeometry.size() != oldGeometry.size() && webPage) { 480 QSize contentSize = webPage->preferredContentsSize(); 481 if (widthValid()) 482 contentSize.setWidth(width()); 483 if (heightValid()) 484 contentSize.setHeight(height()); 485 if (contentSize != webPage->preferredContentsSize()) 486 webPage->setPreferredContentsSize(contentSize); 487 } 488 QDeclarativeItem::geometryChanged(newGeometry, oldGeometry); 489} 490 491/*! 492 \qmlproperty list<object> WebView::javaScriptWindowObjects 493 494 A list of QML objects to expose to the web page. 495 496 Each object will be added as a property of the web frame's window object. The 497 property name is controlled by the value of \c WebView.windowObjectName 498 attached property. 499 500 Exposing QML objects to a web page allows JavaScript executing in the web 501 page itself to communicate with QML, by reading and writing properties and 502 by calling methods of the exposed QML objects. 503 504 This example shows how to call into a QML method using a window object. 505 506 \qml 507 WebView { 508 javaScriptWindowObjects: QtObject { 509 WebView.windowObjectName: "qml" 510 511 function qmlCall() { 512 console.log("This call is in QML!"); 513 } 514 } 515 516 html: "<script>console.log(\"This is in WebKit!\"); window.qml.qmlCall();</script>" 517 } 518 \endqml 519 520 The output of the example will be: 521 \code 522 This is in WebKit! 523 This call is in QML! 524 \endcode 525 526 If Javascript is not enabled for the page, then this property does nothing. 527*/ 528QDeclarativeListProperty<QObject> QDeclarativeWebView::javaScriptWindowObjects() 529{ 530 return QDeclarativeListProperty<QObject>(this, d, &QDeclarativeWebViewPrivate::windowObjectsAppend); 531} 532 533QDeclarativeWebViewAttached* QDeclarativeWebView::qmlAttachedProperties(QObject* o) 534{ 535 return new QDeclarativeWebViewAttached(o); 536} 537 538void QDeclarativeWebViewPrivate::updateWindowObjects() 539{ 540 if (!q->isComponentCompletePublic() || !q->page()) 541 return; 542 543 for (int i = 0; i < windowObjects.count(); ++i) { 544 QObject* object = windowObjects.at(i); 545 QDeclarativeWebViewAttached* attached = static_cast<QDeclarativeWebViewAttached *>(qmlAttachedPropertiesObject<QDeclarativeWebView>(object)); 546 if (attached && !attached->windowObjectName().isEmpty()) 547 q->page()->mainFrame()->addToJavaScriptWindowObject(attached->windowObjectName(), object); 548 } 549} 550 551bool QDeclarativeWebView::renderingEnabled() const 552{ 553 return d->rendering; 554} 555 556void QDeclarativeWebView::setRenderingEnabled(bool enabled) 557{ 558 if (d->rendering == enabled) 559 return; 560 d->rendering = enabled; 561 emit renderingEnabledChanged(); 562 d->view->setTiledBackingStoreFrozen(!enabled); 563} 564 565/*! 566 \qmlsignal WebView::onDoubleClick(int clickx, int clicky) 567 568 The WebView does not pass double-click events to the web engine, but rather 569 emits this signals. 570*/ 571 572/*! 573 \qmlmethod bool WebView::heuristicZoom(int clickX, int clickY, real maxzoom) 574 575 Finds a zoom that: 576 \list 577 \i shows a whole item 578 \i includes (\a clickX, \a clickY) 579 \i fits into the preferredWidth and preferredHeight 580 \i zooms by no more than \a maxZoom 581 \i is more than 10% above the current zoom 582 \endlist 583 584 If such a zoom exists, emits zoomTo(zoom,centerX,centerY) and returns true; otherwise, 585 no signal is emitted and returns false. 586*/ 587bool QDeclarativeWebView::heuristicZoom(int clickX, int clickY, qreal maxZoom) 588{ 589 if (contentsScale() >= maxZoom / scale()) 590 return false; 591 qreal ozf = contentsScale(); 592 QRect showArea = elementAreaAt(clickX, clickY, d->preferredwidth / maxZoom, d->preferredheight / maxZoom); 593 qreal z = qMin(qreal(d->preferredwidth) / showArea.width(), qreal(d->preferredheight) / showArea.height()); 594 if (z > maxZoom / scale()) 595 z = maxZoom / scale(); 596 if (z / ozf > 1.2) { 597 QRectF r(showArea.left() * z, showArea.top() * z, showArea.width() * z, showArea.height() * z); 598 emit zoomTo(z, r.x() + r.width() / 2, r.y() + r.height() / 2); 599 return true; 600 } 601 return false; 602} 603 604/*! 605 \qmlproperty int WebView::pressGrabTime 606 607 The number of milliseconds the user must press before the WebView 608 starts passing move events through to the Web engine (rather than 609 letting other QML elements such as a Flickable take them). 610 611 Defaults to 400ms. Set to 0 to always grab and pass move events to 612 the Web engine. 613*/ 614int QDeclarativeWebView::pressGrabTime() const 615{ 616 return d->view->pressTime; 617} 618 619void QDeclarativeWebView::setPressGrabTime(int millis) 620{ 621 if (d->view->pressTime == millis) 622 return; 623 d->view->pressTime = millis; 624 emit pressGrabTimeChanged(); 625} 626 627#ifndef QT_NO_ACTION 628/*! 629 \qmlproperty action WebView::back 630 This property holds the action for causing the previous URL in the history to be displayed. 631*/ 632QAction* QDeclarativeWebView::backAction() const 633{ 634 return page()->action(QWebPage::Back); 635} 636 637/*! 638 \qmlproperty action WebView::forward 639 This property holds the action for causing the next URL in the history to be displayed. 640*/ 641QAction* QDeclarativeWebView::forwardAction() const 642{ 643 return page()->action(QWebPage::Forward); 644} 645 646/*! 647 \qmlproperty action WebView::reload 648 This property holds the action for reloading with the current URL 649*/ 650QAction* QDeclarativeWebView::reloadAction() const 651{ 652 return page()->action(QWebPage::Reload); 653} 654 655/*! 656 \qmlproperty action WebView::stop 657 This property holds the action for stopping loading with the current URL 658*/ 659QAction* QDeclarativeWebView::stopAction() const 660{ 661 return page()->action(QWebPage::Stop); 662} 663#endif // QT_NO_ACTION 664 665/*! 666 \qmlproperty string WebView::title 667 This property holds the title of the web page currently viewed 668 669 By default, this property contains an empty string. 670*/ 671QString QDeclarativeWebView::title() const 672{ 673 return page()->mainFrame()->title(); 674} 675 676/*! 677 \qmlproperty pixmap WebView::icon 678 This property holds the icon associated with the web page currently viewed 679*/ 680QPixmap QDeclarativeWebView::icon() const 681{ 682 return page()->mainFrame()->icon().pixmap(QSize(256, 256)); 683} 684 685/*! 686 \qmlproperty string WebView::statusText 687 688 This property is the current status suggested by the current web page. In a web browser, 689 such status is often shown in some kind of status bar. 690*/ 691void QDeclarativeWebView::setStatusText(const QString& text) 692{ 693 d->statusText = text; 694 emit statusTextChanged(); 695} 696 697void QDeclarativeWebView::windowObjectCleared() 698{ 699 d->updateWindowObjects(); 700} 701 702QString QDeclarativeWebView::statusText() const 703{ 704 return d->statusText; 705} 706 707QWebPage* QDeclarativeWebView::page() const 708{ 709 return d->view->page(); 710} 711 712// The QObject interface to settings(). 713/*! 714 \qmlproperty string WebView::settings.standardFontFamily 715 \qmlproperty string WebView::settings.fixedFontFamily 716 \qmlproperty string WebView::settings.serifFontFamily 717 \qmlproperty string WebView::settings.sansSerifFontFamily 718 \qmlproperty string WebView::settings.cursiveFontFamily 719 \qmlproperty string WebView::settings.fantasyFontFamily 720 721 \qmlproperty int WebView::settings.minimumFontSize 722 \qmlproperty int WebView::settings.minimumLogicalFontSize 723 \qmlproperty int WebView::settings.defaultFontSize 724 \qmlproperty int WebView::settings.defaultFixedFontSize 725 726 \qmlproperty bool WebView::settings.autoLoadImages 727 \qmlproperty bool WebView::settings.javascriptEnabled 728 \qmlproperty bool WebView::settings.javaEnabled 729 \qmlproperty bool WebView::settings.pluginsEnabled 730 \qmlproperty bool WebView::settings.privateBrowsingEnabled 731 \qmlproperty bool WebView::settings.javascriptCanOpenWindows 732 \qmlproperty bool WebView::settings.javascriptCanAccessClipboard 733 \qmlproperty bool WebView::settings.developerExtrasEnabled 734 \qmlproperty bool WebView::settings.linksIncludedInFocusChain 735 \qmlproperty bool WebView::settings.zoomTextOnly 736 \qmlproperty bool WebView::settings.printElementBackgrounds 737 \qmlproperty bool WebView::settings.offlineStorageDatabaseEnabled 738 \qmlproperty bool WebView::settings.offlineWebApplicationCacheEnabled 739 \qmlproperty bool WebView::settings.localStorageDatabaseEnabled 740 \qmlproperty bool WebView::settings.localContentCanAccessRemoteUrls 741 742 These properties give access to the settings controlling the web view. 743 744 See QWebSettings for details of these properties. 745 746 \qml 747 WebView { 748 settings.pluginsEnabled: true 749 settings.standardFontFamily: "Arial" 750 // ... 751 } 752 \endqml 753*/ 754QDeclarativeWebSettings* QDeclarativeWebView::settingsObject() const 755{ 756 d->settings.s = page()->settings(); 757 return &d->settings; 758} 759 760void QDeclarativeWebView::setPage(QWebPage* page) 761{ 762 if (d->view->page() == page) 763 return; 764 765 d->view->setPage(page); 766 updateContentsSize(); 767 page->mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff); 768 page->mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff); 769 connect(page->mainFrame(), SIGNAL(urlChanged(QUrl)), this, SLOT(pageUrlChanged())); 770 connect(page->mainFrame(), SIGNAL(titleChanged(QString)), this, SIGNAL(titleChanged(QString))); 771 connect(page->mainFrame(), SIGNAL(titleChanged(QString)), this, SIGNAL(iconChanged())); 772 connect(page->mainFrame(), SIGNAL(iconChanged()), this, SIGNAL(iconChanged())); 773 connect(page->mainFrame(), SIGNAL(initialLayoutCompleted()), this, SLOT(initialLayout())); 774 connect(page->mainFrame(), SIGNAL(contentsSizeChanged(QSize)), this, SIGNAL(contentsSizeChanged(QSize))); 775 776 connect(page, SIGNAL(loadStarted()), this, SLOT(doLoadStarted())); 777 connect(page, SIGNAL(loadProgress(int)), this, SLOT(doLoadProgress(int))); 778 connect(page, SIGNAL(loadFinished(bool)), this, SLOT(doLoadFinished(bool))); 779 connect(page, SIGNAL(statusBarMessage(QString)), this, SLOT(setStatusText(QString))); 780 781 connect(page->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(windowObjectCleared())); 782 783 page->settings()->setAttribute(QWebSettings::TiledBackingStoreEnabled, true); 784 785} 786 787/*! 788 \qmlsignal WebView::onLoadStarted() 789 790 This handler is called when the web engine begins loading 791 a page. Later, WebView::onLoadFinished() or WebView::onLoadFailed() 792 will be emitted. 793*/ 794 795/*! 796 \qmlsignal WebView::onLoadFinished() 797 798 This handler is called when the web engine \e successfully 799 finishes loading a page, including any component content 800 (WebView::onLoadFailed() will be emitted otherwise). 801 802 \sa progress 803*/ 804 805/*! 806 \qmlsignal WebView::onLoadFailed() 807 808 This handler is called when the web engine fails loading 809 a page or any component content 810 (WebView::onLoadFinished() will be emitted on success). 811*/ 812 813void QDeclarativeWebView::load(const QNetworkRequest& request, QNetworkAccessManager::Operation operation, const QByteArray& body) 814{ 815 page()->mainFrame()->load(request, operation, body); 816} 817 818QString QDeclarativeWebView::html() const 819{ 820 return page()->mainFrame()->toHtml(); 821} 822 823/*! 824 \qmlproperty string WebView::html 825 This property holds HTML text set directly 826 827 The html property can be set as a string. 828 829 \qml 830 WebView { 831 html: "<p>This is <b>HTML</b>." 832 } 833 \endqml 834*/ 835void QDeclarativeWebView::setHtml(const QString& html, const QUrl& baseUrl) 836{ 837 updateContentsSize(); 838 if (isComponentComplete()) 839 page()->mainFrame()->setHtml(html, baseUrl); 840 else { 841 d->pending = d->PendingHtml; 842 d->pendingUrl = baseUrl; 843 d->pendingString = html; 844 } 845 emit htmlChanged(); 846} 847 848void QDeclarativeWebView::setContent(const QByteArray& data, const QString& mimeType, const QUrl& baseUrl) 849{ 850 updateContentsSize(); 851 852 if (isComponentComplete()) 853 page()->mainFrame()->setContent(data, mimeType, qmlContext(this)->resolvedUrl(baseUrl)); 854 else { 855 d->pending = d->PendingContent; 856 d->pendingUrl = baseUrl; 857 d->pendingString = mimeType; 858 d->pendingData = data; 859 } 860} 861 862QWebHistory* QDeclarativeWebView::history() const 863{ 864 return page()->history(); 865} 866 867QWebSettings* QDeclarativeWebView::settings() const 868{ 869 return page()->settings(); 870} 871 872QDeclarativeWebView* QDeclarativeWebView::createWindow(QWebPage::WebWindowType type) 873{ 874 switch (type) { 875 case QWebPage::WebBrowserWindow: { 876 if (!d->newWindowComponent && d->newWindowParent) 877 qWarning("WebView::newWindowComponent not set - WebView::newWindowParent ignored"); 878 else if (d->newWindowComponent && !d->newWindowParent) 879 qWarning("WebView::newWindowParent not set - WebView::newWindowComponent ignored"); 880 else if (d->newWindowComponent && d->newWindowParent) { 881 QDeclarativeWebView* webview = 0; 882 QDeclarativeContext* windowContext = new QDeclarativeContext(qmlContext(this)); 883 884 QObject* newObject = d->newWindowComponent->create(windowContext); 885 if (newObject) { 886 windowContext->setParent(newObject); 887 QDeclarativeItem* item = qobject_cast<QDeclarativeItem *>(newObject); 888 if (!item) 889 delete newObject; 890 else { 891 webview = item->findChild<QDeclarativeWebView*>(); 892 if (!webview) 893 delete item; 894 else { 895 newObject->setParent(d->newWindowParent); 896 static_cast<QGraphicsObject*>(item)->setParentItem(d->newWindowParent); 897 } 898 } 899 } else 900 delete windowContext; 901 902 return webview; 903 } 904 } 905 break; 906 case QWebPage::WebModalDialog: { 907 // Not supported 908 } 909 } 910 return 0; 911} 912 913/*! 914 \qmlproperty component WebView::newWindowComponent 915 916 This property holds the component to use for new windows. 917 The component must have a WebView somewhere in its structure. 918 919 When the web engine requests a new window, it will be an instance of 920 this component. 921 922 The parent of the new window is set by newWindowParent. It must be set. 923*/ 924QDeclarativeComponent* QDeclarativeWebView::newWindowComponent() const 925{ 926 return d->newWindowComponent; 927} 928 929void QDeclarativeWebView::setNewWindowComponent(QDeclarativeComponent* newWindow) 930{ 931 if (newWindow == d->newWindowComponent) 932 return; 933 d->newWindowComponent = newWindow; 934 emit newWindowComponentChanged(); 935} 936 937 938/*! 939 \qmlproperty item WebView::newWindowParent 940 941 The parent item for new windows. 942 943 \sa newWindowComponent 944*/ 945QDeclarativeItem* QDeclarativeWebView::newWindowParent() const 946{ 947 return d->newWindowParent; 948} 949 950void QDeclarativeWebView::setNewWindowParent(QDeclarativeItem* parent) 951{ 952 if (parent == d->newWindowParent) 953 return; 954 if (d->newWindowParent && parent) { 955 QList<QGraphicsItem *> children = d->newWindowParent->childItems(); 956 for (int i = 0; i < children.count(); ++i) 957 children.at(i)->setParentItem(parent); 958 } 959 d->newWindowParent = parent; 960 emit newWindowParentChanged(); 961} 962 963QSize QDeclarativeWebView::contentsSize() const 964{ 965 return page()->mainFrame()->contentsSize() * contentsScale(); 966} 967 968qreal QDeclarativeWebView::contentsScale() const 969{ 970 return d->view->scale(); 971} 972 973void QDeclarativeWebView::setContentsScale(qreal scale) 974{ 975 if (scale == d->view->scale()) 976 return; 977 d->view->setScale(scale); 978 updateDeclarativeWebViewSize(); 979 emit contentsScaleChanged(); 980} 981 982/*! 983 Returns the area of the largest element at position (\a x,\a y) that is no larger 984 than \a maxWidth by \a maxHeight pixels. 985 986 May return an area larger in the case when no smaller element is at the position. 987*/ 988QRect QDeclarativeWebView::elementAreaAt(int x, int y, int maxWidth, int maxHeight) const 989{ 990 QWebHitTestResult hit = page()->mainFrame()->hitTestContent(QPoint(x, y)); 991 QRect hitRect = hit.boundingRect(); 992 QWebElement element = hit.enclosingBlockElement(); 993 if (maxWidth <= 0) 994 maxWidth = INT_MAX; 995 if (maxHeight <= 0) 996 maxHeight = INT_MAX; 997 while (!element.parent().isNull() && element.geometry().width() <= maxWidth && element.geometry().height() <= maxHeight) { 998 hitRect = element.geometry(); 999 element = element.parent(); 1000 } 1001 return hitRect; 1002} 1003 1004/*! 1005 \internal 1006 \class QDeclarativeWebPage 1007 \brief The QDeclarativeWebPage class is a QWebPage that can create QML plugins. 1008 1009 \sa QDeclarativeWebView 1010*/ 1011QDeclarativeWebPage::QDeclarativeWebPage(QDeclarativeWebView* parent) : 1012 QWebPage(parent) 1013{ 1014} 1015 1016QDeclarativeWebPage::~QDeclarativeWebPage() 1017{ 1018} 1019 1020QString QDeclarativeWebPage::chooseFile(QWebFrame* originatingFrame, const QString& oldFile) 1021{ 1022 // Not supported (it's modal) 1023 Q_UNUSED(originatingFrame) 1024 Q_UNUSED(oldFile) 1025 return oldFile; 1026} 1027 1028/*! 1029 \qmlsignal WebView::onAlert(string message) 1030 1031 The handler is called when the web engine sends a JavaScript alert. The \a message is the text 1032 to be displayed in the alert to the user. 1033*/ 1034 1035 1036void QDeclarativeWebPage::javaScriptAlert(QWebFrame* originatingFrame, const QString& msg) 1037{ 1038 Q_UNUSED(originatingFrame) 1039 emit viewItem()->alert(msg); 1040} 1041 1042bool QDeclarativeWebPage::javaScriptConfirm(QWebFrame* originatingFrame, const QString& msg) 1043{ 1044 // Not supported (it's modal) 1045 Q_UNUSED(originatingFrame) 1046 Q_UNUSED(msg) 1047 return false; 1048} 1049 1050bool QDeclarativeWebPage::javaScriptPrompt(QWebFrame* originatingFrame, const QString& msg, const QString& defaultValue, QString* result) 1051{ 1052 // Not supported (it's modal) 1053 Q_UNUSED(originatingFrame) 1054 Q_UNUSED(msg) 1055 Q_UNUSED(defaultValue) 1056 Q_UNUSED(result) 1057 return false; 1058} 1059 1060 1061QDeclarativeWebView* QDeclarativeWebPage::viewItem() 1062{ 1063 return static_cast<QDeclarativeWebView*>(parent()); 1064} 1065 1066QWebPage* QDeclarativeWebPage::createWindow(WebWindowType type) 1067{ 1068 QDeclarativeWebView* newView = viewItem()->createWindow(type); 1069 if (newView) 1070 return newView->page(); 1071 return 0; 1072} 1073 1074QT_END_NAMESPACE 1075 1076