From 98092546c0f3c7857d82711174df9ade9ea7136b Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Mon, 31 Aug 2009 15:54:32 +1000 Subject: Simplify zooming mechanism - put more IQ in WebView. No animated zooming for now. --- demos/declarative/webbrowser/webbrowser.qml | 69 ++-------------- src/declarative/fx/qfxwebview.cpp | 123 ++++++++++++++++++---------- src/declarative/fx/qfxwebview.h | 10 ++- 3 files changed, 91 insertions(+), 111 deletions(-) diff --git a/demos/declarative/webbrowser/webbrowser.qml b/demos/declarative/webbrowser/webbrowser.qml index 278bc43..2cd9f57 100644 --- a/demos/declarative/webbrowser/webbrowser.qml +++ b/demos/declarative/webbrowser/webbrowser.qml @@ -13,21 +13,6 @@ Item { width: 640 height: 480 - Script { - function zoomOut() { - WebBrowser.state = "ZoomedOut"; - } - function toggleZoom(x,y) { - if(WebBrowser.state == "ZoomedOut") { - Flick.centerX = x - Flick.centerY = y - WebBrowser.state = "Normal"; - } else { - zoomOut(); - } - } - } - Item { id: WebPanel anchors.fill: parent @@ -183,9 +168,6 @@ Item { anchors.left: parent.left anchors.right: parent.right - property real centerX : 0 - property real centerY : 0 - WebView { id: MyWebView pixelCacheSize: 4000000 @@ -213,13 +195,14 @@ Item { focus: true preferredWidth: Flick.width - preferredHeight: Flick.height/scale - scale: (width > 0) ? Flick.width/width*zoomedOut+(1-zoomedOut) : 1 + webPageWidth: 980 onUrlChanged: { if (url != null) { WebBrowser.urlString = url.toString(); } } - onDoubleClick: { toggleZoom(clickX,clickY) } + onDoubleClick: { heuristicZoom(clickX,clickY) } + + onZooming: { Flick.viewportX=Math.min(MyWebView.width-Flick.width,Math.max(0,centerX-Flick.width/2)); + Flick.viewportY=Math.max(0,Math.min(MyWebView.height-Flick.height,centerY-Flick.height/2)) } - property real zoomedOut : 1 } Rectangle { id: WebViewTint @@ -347,46 +330,4 @@ Item { } } } - states: [ - State { - name: "Normal" - PropertyChanges { target: MyWebView; zoomedOut: 0 } - PropertyChanges { target: Flick; explicit: true; viewportX: Math.min(MyWebView.width-Flick.width,Math.max(0,Flick.centerX-Flick.width/2)) } - PropertyChanges { target: Flick; explicit: true; viewportY: Math.min(MyWebView.height-Flick.height,Math.max(0,Flick.centerY-Flick.height/2)) } - }, - State { - name: "ZoomedOut" - PropertyChanges { target: MyWebView; zoomedOut: 1 } - } - ] - transitions: [ - Transition { - SequentialAnimation { - PropertyAction { - target: MyWebView - property: "smooth" - value: false - } - ParallelAnimation { - NumberAnimation { - target: MyWebView - properties: "zoomedOut" - easing: "easeInOutQuad" - duration: 200 - } - NumberAnimation { - target: Flick - properties: "viewportX,viewportY" - easing: "easeInOutQuad" - duration: 200 - } - } - PropertyAction { - target: MyWebView - property: "smooth" - value: !Flick.moving - } - } - } - ] } diff --git a/src/declarative/fx/qfxwebview.cpp b/src/declarative/fx/qfxwebview.cpp index cd60a76..ba39040 100644 --- a/src/declarative/fx/qfxwebview.cpp +++ b/src/declarative/fx/qfxwebview.cpp @@ -166,7 +166,7 @@ class QFxWebViewPrivate : public QFxPaintedItemPrivate public: QFxWebViewPrivate() - : QFxPaintedItemPrivate(), page(0), idealwidth(0), idealheight(0), + : QFxPaintedItemPrivate(), page(0), preferredwidth(0), pagewidth(0), progress(1.0), status(QFxWebView::Null), pending(PendingNone), newWindowComponent(0), newWindowParent(0), windowObjects(this) @@ -176,8 +176,8 @@ public: QUrl url; // page url might be different if it has not loaded yet QWebPage *page; - int idealwidth; - int idealheight; + int preferredwidth; + int pagewidth; qreal progress; QFxWebView::Status status; QString statusText; @@ -213,15 +213,11 @@ public: If the width and height of the item is not set, they will dynamically adjust to a size appropriate for the content. - This width may be large (eg. 980) for typical online web pages. + This width may be large for typical online web pages. If the preferredWidth is set, the width will be this amount or larger, usually laying out the web content to fit the preferredWidth. - If the preferredHeight is set, the height will be this amount or larger. - Due to WebKit limitations, the height may be more than necessary - if the preferredHeight is changed after the content is loaded. - \qml WebView { url: "http://www.nokia.com" @@ -327,6 +323,7 @@ qreal QFxWebView::progress() const void QFxWebView::doLoadStarted() { Q_D(QFxWebView); + if (!d->url.isEmpty()) { d->status = Loading; emit statusChanged(d->status); @@ -340,13 +337,27 @@ void QFxWebView::doLoadProgress(int p) if (d->progress == p/100.0) return; d->progress = p/100.0; - expandToWebPage(); emit progressChanged(); } void QFxWebView::pageUrlChanged() { Q_D(QFxWebView); + + // Reset zooming to full + qreal zf = 1.0; + if (d->preferredwidth) { + if (d->pagewidth) + zf = qreal(d->preferredwidth)/d->pagewidth; + page()->mainFrame()->setZoomFactor(zf); + page()->setViewportSize(QSize(d->preferredwidth,-1)); + } else { + page()->mainFrame()->setZoomFactor(zf); + page()->setViewportSize(QSize(-1,-1)); + } + emit zooming(0,0); + expandToWebPage(); + if ((d->url.isEmpty() && page()->mainFrame()->url() != QUrl(QLatin1String("about:blank"))) || d->url != page()->mainFrame()->url()) { @@ -360,6 +371,7 @@ void QFxWebView::pageUrlChanged() void QFxWebView::doLoadFinished(bool ok) { Q_D(QFxWebView); + if (title().isEmpty()) pageUrlChanged(); // XXX bug 232556 - pages with no title never get urlChanged() @@ -397,10 +409,15 @@ void QFxWebView::setUrl(const QUrl &url) if (isComponentComplete()) { d->url = url; - page()->setViewportSize(QSize( - d->idealwidth>0 ? d->idealwidth : width(), - d->idealheight>0 ? d->idealheight : height())); - + qreal zf = 1.0; + if (d->preferredwidth) { + if (d->pagewidth) + zf = qreal(d->preferredwidth)/d->pagewidth; + page()->setViewportSize(QSize(d->preferredwidth,-1)); + } else { + page()->setViewportSize(QSize(-1,-1)); + } + page()->mainFrame()->setZoomFactor(zf); QUrl seturl = url; if (seturl.isEmpty()) seturl = QUrl(QLatin1String("about:blank")); @@ -423,35 +440,41 @@ void QFxWebView::setUrl(const QUrl &url) int QFxWebView::preferredWidth() const { Q_D(const QFxWebView); - return d->idealwidth; + return d->preferredwidth; } void QFxWebView::setPreferredWidth(int iw) { Q_D(QFxWebView); - if (d->idealwidth == iw) return; - d->idealwidth = iw; + if (d->preferredwidth == iw) return; + if (d->pagewidth) { + if (d->preferredwidth) { + setZoomFactor(zoomFactor()*iw/d->preferredwidth); + } else { + setZoomFactor(qreal(iw)/d->pagewidth); + } + } + d->preferredwidth = iw; expandToWebPage(); emit preferredWidthChanged(); } /*! - \qmlproperty int WebView::preferredHeight - This property holds the ideal height for displaying the current URL. + \qmlproperty int WebView::webPageWidth + This property holds the page width suggested to the web engine. */ -int QFxWebView::preferredHeight() const +int QFxWebView::webPageWidth() const { Q_D(const QFxWebView); - return d->idealheight; + return d->pagewidth; } -void QFxWebView::setPreferredHeight(int ih) +void QFxWebView::setWebPageWidth(int pw) { Q_D(QFxWebView); - if (d->idealheight == ih) return; - d->idealheight = ih; + if (d->pagewidth == pw) return; + d->pagewidth = pw; expandToWebPage(); - emit preferredHeightChanged(); } /*! @@ -470,17 +493,21 @@ void QFxWebView::focusChanged(bool hasFocus) QFxItem::focusChanged(hasFocus); } +void QFxWebView::contentsSizeChanged(const QSize& sz) +{ + expandToWebPage(); +} + void QFxWebView::expandToWebPage() { Q_D(QFxWebView); QSize cs = page()->mainFrame()->contentsSize(); - if (cs.width() < d->idealwidth) - cs.setWidth(d->idealwidth); - if (cs.height() < d->idealheight) - cs.setHeight(d->idealheight); - if (widthValid() && cs.width() < width()) + qreal zoom = zoomFactor(); + if (cs.width() < d->preferredwidth*zoom) + cs.setWidth(d->preferredwidth*zoom); + if (widthValid()) cs.setWidth(width()); - if (heightValid() && cs.height() < height()) + if (heightValid()) cs.setHeight(height()); if (cs != page()->viewportSize()) { page()->setViewportSize(cs); @@ -659,7 +686,7 @@ static QMouseEvent *sceneHoverMoveEventToMouseEvent(QGraphicsSceneHoverEvent *e) /*! \qmlsignal WebView::onDoubleClick(clickx,clicky) - The WebView does not pass double-click events to the engine, but rather + The WebView does not pass double-click events to the web engine, but rather emits this signals. */ @@ -670,6 +697,21 @@ void QFxWebView::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) delete me; } +void QFxWebView::heuristicZoom(int clickX, int clickY) +{ + Q_D(QFxWebView); + qreal ozf = zoomFactor(); + QRect showarea = elementAreaAt(clickX, clickY, 1, 1); + qreal z = qreal(preferredWidth())*ozf/showarea.width()*.95; + if ((z/ozf > 0.99 && z/ozf <1.01) || z < qreal(d->preferredwidth)/d->pagewidth) { + // zoom out + z = qreal(d->preferredwidth)/d->pagewidth; + } + setZoomFactor(z); + QRectF r(showarea.left()/ozf*z, showarea.top()/ozf*z, showarea.width()/ozf*z, showarea.height()/ozf*z); + emit zooming(r.x()+r.width()/2, r.y()+r.height()/2); +} + void QFxWebView::mousePressEvent(QGraphicsSceneMouseEvent *event) { setFocus (true); @@ -865,13 +907,10 @@ void QFxWebView::setZoomFactor(qreal factor) if (factor == page()->mainFrame()->zoomFactor()) return; - //reset viewport size so we resize correctly - page()->setViewportSize(QSize( - d->idealwidth>0 ? d->idealwidth : -1, - d->idealheight>0 ? d->idealheight : -1)); - page()->mainFrame()->setZoomFactor(factor); + page()->setViewportSize(QSize(d->pagewidth*factor,-1)); expandToWebPage(); + emit zoomFactorChanged(); } @@ -993,14 +1032,14 @@ void QFxWebView::setPage(QWebPage *page) } d->page = page; d->page->setViewportSize(QSize( - d->idealwidth>0 ? d->idealwidth : -1, - d->idealheight>0 ? d->idealheight : -1)); + d->preferredwidth>0 ? d->preferredwidth : -1, -1)); d->page->mainFrame()->setScrollBarPolicy(Qt::Horizontal,Qt::ScrollBarAlwaysOff); d->page->mainFrame()->setScrollBarPolicy(Qt::Vertical,Qt::ScrollBarAlwaysOff); connect(d->page,SIGNAL(repaintRequested(QRect)),this,SLOT(paintPage(QRect))); connect(d->page->mainFrame(),SIGNAL(urlChanged(QUrl)),this,SLOT(pageUrlChanged())); connect(d->page->mainFrame(), SIGNAL(titleChanged(QString)), this, SIGNAL(titleChanged(QString))); connect(d->page->mainFrame(), SIGNAL(iconChanged()), this, SIGNAL(iconChanged())); + connect(d->page->mainFrame(), SIGNAL(contentsSizeChanged(QSize)), this, SLOT(contentsSizeChanged(QSize))); connect(d->page,SIGNAL(loadStarted()),this,SLOT(doLoadStarted())); connect(d->page,SIGNAL(loadProgress(int)),this,SLOT(doLoadProgress(int))); @@ -1065,8 +1104,7 @@ void QFxWebView::setHtml(const QString &html, const QUrl &baseUrl) { Q_D(QFxWebView); page()->setViewportSize(QSize( - d->idealwidth>0 ? d->idealwidth : width(), - d->idealheight>0 ? d->idealheight : height())); + d->preferredwidth>0 ? d->preferredwidth : width(), height())); if (isComponentComplete()) page()->mainFrame()->setHtml(html, baseUrl); else { @@ -1080,8 +1118,7 @@ void QFxWebView::setContent(const QByteArray &data, const QString &mimeType, con { Q_D(QFxWebView); page()->setViewportSize(QSize( - d->idealwidth>0 ? d->idealwidth : width(), - d->idealheight>0 ? d->idealheight : height())); + d->preferredwidth>0 ? d->preferredwidth : width(), height())); if (isComponentComplete()) page()->mainFrame()->setContent(data,mimeType,qmlContext(this)->resolvedUrl(baseUrl)); @@ -1210,8 +1247,6 @@ QRect QFxWebView::elementAreaAt(int x, int y, int maxwidth, int maxheight) const return element.geometry(); } - - /*! \internal \class QFxWebPage diff --git a/src/declarative/fx/qfxwebview.h b/src/declarative/fx/qfxwebview.h index 29284a4..4a81be8 100644 --- a/src/declarative/fx/qfxwebview.h +++ b/src/declarative/fx/qfxwebview.h @@ -97,7 +97,7 @@ class Q_DECLARATIVE_EXPORT QFxWebView : public QFxPaintedItem Q_PROPERTY(QString html READ html WRITE setHtml) Q_PROPERTY(int preferredWidth READ preferredWidth WRITE setPreferredWidth NOTIFY preferredWidthChanged) - Q_PROPERTY(int preferredHeight READ preferredHeight WRITE setPreferredHeight NOTIFY preferredHeightChanged) + Q_PROPERTY(int webPageWidth READ webPageWidth WRITE setWebPageWidth) Q_PROPERTY(int pixelCacheSize READ pixelCacheSize WRITE setPixelCacheSize) Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged) Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged) @@ -134,8 +134,8 @@ public: int preferredWidth() const; void setPreferredWidth(int); - int preferredHeight() const; - void setPreferredHeight(int); + int webPageWidth() const; + void setWebPageWidth(int); enum Status { Null, Ready, Loading, Error }; Status status() const; @@ -192,8 +192,11 @@ Q_SIGNALS: void doubleClick(int clickX, int clickY); + void zooming(int centerX, int centerY); + public Q_SLOTS: QVariant evaluateJavaScript(const QString&); + void heuristicZoom(int clickX, int clickY); private Q_SLOTS: void expandToWebPage(); @@ -204,6 +207,7 @@ private Q_SLOTS: void setStatusText(const QString&); void windowObjectCleared(); void pageUrlChanged(); + void contentsSizeChanged(const QSize&); protected: QFxWebView(QFxWebViewPrivate &dd, QFxItem *parent); -- cgit v0.12