From 6a294f8f19763c7fa9e80fcbe9b2e7d7b521e780 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Mon, 31 Aug 2009 10:02:31 +1000 Subject: Element-at functionality Not used yet. --- src/declarative/fx/qfxwebview.cpp | 20 ++++++++++++++++++++ src/declarative/fx/qfxwebview.h | 1 + 2 files changed, 21 insertions(+) diff --git a/src/declarative/fx/qfxwebview.cpp b/src/declarative/fx/qfxwebview.cpp index b150ca0..cd60a76 100644 --- a/src/declarative/fx/qfxwebview.cpp +++ b/src/declarative/fx/qfxwebview.cpp @@ -1190,6 +1190,26 @@ void QFxWebView::setNewWindowParent(QFxItem *parent) d->newWindowParent = parent; } +/*! + Returns the area of the largest element at position (\a x,\a y) that is no larger + than \a maxwidth by \a maxheight pixels. + + May return an area larger in the case when no smaller element is at the position. +*/ +QRect QFxWebView::elementAreaAt(int x, int y, int maxwidth, int maxheight) const +{ + QWebHitTestResult hit = page()->mainFrame()->hitTestContent(QPoint(x,y)); + QWebElement element = hit.enclosingBlockElement(); + QWebElement parent = element.parent(); + if (maxwidth<=0) maxwidth = INT_MAX; + if (maxheight<=0) maxheight = INT_MAX; + while (!parent.isNull() && parent.geometry().width() <= maxwidth && parent.geometry().height() <= maxheight) { + element = parent; + parent = element.parent(); + } + return element.geometry(); +} + /*! diff --git a/src/declarative/fx/qfxwebview.h b/src/declarative/fx/qfxwebview.h index f084d61..29284a4 100644 --- a/src/declarative/fx/qfxwebview.h +++ b/src/declarative/fx/qfxwebview.h @@ -222,6 +222,7 @@ protected: virtual void focusChanged(bool); virtual bool sceneEvent(QEvent *event); QFxWebView *createWindow(QWebPage::WebWindowType type); + QRect elementAreaAt(int x, int y, int minwidth, int minheight) const; private: void init(); -- cgit v0.12 From 07ef9e3022565017709668d637ed13d0f26b7505 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Mon, 31 Aug 2009 13:25:14 +1000 Subject: Optimize case of cache rects needing minor repaints. Especially obvious when WebView link hovered. --- src/declarative/fx/qfxpainteditem.cpp | 14 +++++++++++++- src/declarative/fx/qfxpainteditem_p.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/declarative/fx/qfxpainteditem.cpp b/src/declarative/fx/qfxpainteditem.cpp index 8c04074..3d313c2 100644 --- a/src/declarative/fx/qfxpainteditem.cpp +++ b/src/declarative/fx/qfxpainteditem.cpp @@ -94,9 +94,12 @@ void QFxPaintedItem::dirtyCache(const QRect& rect) { Q_D(QFxPaintedItem); for (int i=0; i < d->imagecache.count(); ) { - if (d->imagecache[i]->area.intersects(rect)) { + QFxPaintedItemPrivate::ImageCacheItem *c = d->imagecache[i]; + QRect isect = (c->area & rect) | c->dirty; + if (isect == c->area) { d->imagecache.removeAt(i); } else { + c->dirty = isect; ++i; } } @@ -209,6 +212,15 @@ void QFxPaintedItem::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidge QRect area = d->imagecache[i]->area; if (topaint.contains(area)) { QRectF target(area.x(), area.y(), area.width(), area.height()); + if (!d->imagecache[i]->dirty.isNull() && topaint.contains(d->imagecache[i]->dirty)) { + QPainter qp(&d->imagecache[i]->image); + qp.translate(-area.x(), -area.y()); + if (d->fillColor.isValid()) + qp.fillRect(d->imagecache[i]->dirty,d->fillColor); + qp.setClipRect(d->imagecache[i]->dirty); + drawContents(&qp, d->imagecache[i]->dirty); + d->imagecache[i]->dirty = QRect(); + } p->drawPixmap(target.toRect(), d->imagecache[i]->image); topaint -= area; d->imagecache[i]->age=0; diff --git a/src/declarative/fx/qfxpainteditem_p.h b/src/declarative/fx/qfxpainteditem_p.h index f01936d..2718e57 100644 --- a/src/declarative/fx/qfxpainteditem_p.h +++ b/src/declarative/fx/qfxpainteditem_p.h @@ -72,6 +72,7 @@ public: ~ImageCacheItem() { } int age; QRect area; + QRect dirty; // one dirty area (allows optimization of common cases) QPixmap image; }; -- cgit v0.12 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 From 0c6dfd680fa1e970c6bbb425cf05c9d42d70fe6f Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Mon, 31 Aug 2009 15:55:19 +1000 Subject: Workaround possible webkit bug. (discussing with Simon) --- src/declarative/fx/qfxpainteditem.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/declarative/fx/qfxpainteditem.cpp b/src/declarative/fx/qfxpainteditem.cpp index 3d313c2..13f7e58 100644 --- a/src/declarative/fx/qfxpainteditem.cpp +++ b/src/declarative/fx/qfxpainteditem.cpp @@ -84,6 +84,10 @@ QT_BEGIN_NAMESPACE item in regards to height() and width(). */ +// XXX bug in WebKit - can call repaintRequested and other cache-changing functions from within render! +static int inpaint=0; +static int inpaint_clearcache=0; + /*! Marks areas of the cache that intersect with the given \a rect as dirty and in need of being refreshed. @@ -96,7 +100,7 @@ void QFxPaintedItem::dirtyCache(const QRect& rect) for (int i=0; i < d->imagecache.count(); ) { QFxPaintedItemPrivate::ImageCacheItem *c = d->imagecache[i]; QRect isect = (c->area & rect) | c->dirty; - if (isect == c->area) { + if (isect == c->area && !inpaint) { d->imagecache.removeAt(i); } else { c->dirty = isect; @@ -112,6 +116,10 @@ void QFxPaintedItem::dirtyCache(const QRect& rect) */ void QFxPaintedItem::clearCache() { + if (inpaint) { + inpaint_clearcache=1; + return; + } Q_D(QFxPaintedItem); qDeleteAll(d->imagecache); d->imagecache.clear(); @@ -189,6 +197,8 @@ void QFxPaintedItem::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidge if (content.width() <= 0 || content.height() <= 0) return; + ++inpaint; + bool oldAntiAliasing = p->testRenderHint(QPainter::Antialiasing); bool oldSmoothPixmap = p->testRenderHint(QPainter::SmoothPixmapTransform); if (oldAntiAliasing) @@ -274,6 +284,13 @@ void QFxPaintedItem::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidge p->setRenderHints(QPainter::Antialiasing, oldAntiAliasing); if (d->smooth) p->setRenderHints(QPainter::SmoothPixmapTransform, oldSmoothPixmap); + + if (inpaint_clearcache) { + clearCache(); + inpaint_clearcache = 0; + } + + --inpaint; } /*! -- cgit v0.12 From 9c8f0d49aa62c3f9bee47f5eacbc0c2d8bb16031 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Mon, 31 Aug 2009 10:11:15 +0200 Subject: Fixing layout margins for QWidgets in QFxView Reviewed-by: Kai Koehne --- src/declarative/util/qfxview.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/declarative/util/qfxview.cpp b/src/declarative/util/qfxview.cpp index 3acbf56..9291e1a 100644 --- a/src/declarative/util/qfxview.cpp +++ b/src/declarative/util/qfxview.cpp @@ -294,6 +294,7 @@ void QFxView::continueExecute() window()->setAttribute(Qt::WA_NoSystemBackground, false); if (!layout()) { setLayout(new QVBoxLayout); + layout()->setContentsMargins(0, 0, 0, 0); } else if (layout()->count()) { // Hide the QGraphicsView in GV mode. QLayoutItem *item = layout()->itemAt(0); -- cgit v0.12 From 6c01a596f9b2bf51add0a3f69faf15435f041b4f Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Mon, 31 Aug 2009 18:33:17 +1000 Subject: Revive animated zooming. Now uses scale for transition while static uses zoomFactor. QFxPaintedItem assists by being able to freeze the cache - useful anywhere that dirty cache data is okay to use (i.e. during brief animations). --- demos/declarative/webbrowser/webbrowser.qml | 68 +++++++++++++++++++- src/declarative/fx/qfxpainteditem.cpp | 96 +++++++++++++++++------------ src/declarative/fx/qfxpainteditem.h | 2 + src/declarative/fx/qfxpainteditem_p.h | 3 +- src/declarative/fx/qfxwebview.cpp | 34 ++++++++-- src/declarative/fx/qfxwebview.h | 7 ++- 6 files changed, 159 insertions(+), 51 deletions(-) diff --git a/demos/declarative/webbrowser/webbrowser.qml b/demos/declarative/webbrowser/webbrowser.qml index 2cd9f57..4c4ad7c 100644 --- a/demos/declarative/webbrowser/webbrowser.qml +++ b/demos/declarative/webbrowser/webbrowser.qml @@ -190,7 +190,7 @@ Item { } url: fixUrl(WebBrowser.urlString) - smooth: !Flick.moving + smooth: false fillColor: "white" focus: true @@ -200,9 +200,71 @@ Item { onUrlChanged: { if (url != null) { WebBrowser.urlString = url.toString(); } } 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)) } + SequentialAnimation { + id: QuickZoom + PropertyAction { + target: MyWebView + property: "renderingEnabled" + value: false + } + ParallelAnimation { + NumberAnimation { + id: ScaleAnim + target: MyWebView + property: "scale" + from: 1 + to: 0 // set before calling + easing: "easeInOutQuad" + duration: 200 + } + NumberAnimation { + id: FlickVX + target: Flick + property: "viewportX" + easing: "easeInOutQuad" + duration: 200 + from: 0 // set before calling + to: 0 // set before calling + } + NumberAnimation { + id: FlickVY + target: Flick + property: "viewportY" + easing: "easeInOutQuad" + duration: 200 + from: 0 // set before calling + to: 0 // set before calling + } + } + PropertyAction { + target: MyWebView + property: "scale" + value: 1.0 + } + PropertyAction { + id: FinalZoom + target: MyWebView + property: "zoomFactor" + } + PropertyAction { + target: MyWebView + property: "renderingEnabled" + value: true + } + } + onZooming: { + if (centerX) { + sc = zoom/zoomFactor; + ScaleAnim.to = sc; + FlickVX.from = Flick.viewportX + FlickVX.to = Math.min(Math.max(0,centerX-Flick.width/2),MyWebView.width*sc-Flick.width) + FlickVY.from = Flick.viewportY + FlickVY.to = Math.min(Math.max(0,centerY-Flick.height/2),MyWebView.height*sc-Flick.height) + FinalZoom.value = zoom + QuickZoom.start() + } + } } Rectangle { id: WebViewTint diff --git a/src/declarative/fx/qfxpainteditem.cpp b/src/declarative/fx/qfxpainteditem.cpp index 13f7e58..695236d 100644 --- a/src/declarative/fx/qfxpainteditem.cpp +++ b/src/declarative/fx/qfxpainteditem.cpp @@ -187,6 +187,15 @@ void QFxPaintedItem::init() connect(this,SIGNAL(visibleChanged()),this,SLOT(clearCache())); } +void QFxPaintedItem::setCacheFrozen(bool frozen) +{ + Q_D(QFxPaintedItem); + if (d->cachefrozen == frozen) + return; + d->cachefrozen = frozen; + // XXX clear cache? +} + /*! \reimp */ @@ -222,14 +231,16 @@ void QFxPaintedItem::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidge QRect area = d->imagecache[i]->area; if (topaint.contains(area)) { QRectF target(area.x(), area.y(), area.width(), area.height()); - if (!d->imagecache[i]->dirty.isNull() && topaint.contains(d->imagecache[i]->dirty)) { - QPainter qp(&d->imagecache[i]->image); - qp.translate(-area.x(), -area.y()); - if (d->fillColor.isValid()) - qp.fillRect(d->imagecache[i]->dirty,d->fillColor); - qp.setClipRect(d->imagecache[i]->dirty); - drawContents(&qp, d->imagecache[i]->dirty); - d->imagecache[i]->dirty = QRect(); + if (!d->cachefrozen) { + if (!d->imagecache[i]->dirty.isNull() && topaint.contains(d->imagecache[i]->dirty)) { + QPainter qp(&d->imagecache[i]->image); + qp.translate(-area.x(), -area.y()); + if (d->fillColor.isValid()) + qp.fillRect(d->imagecache[i]->dirty,d->fillColor); + qp.setClipRect(d->imagecache[i]->dirty); + drawContents(&qp, d->imagecache[i]->dirty); + d->imagecache[i]->dirty = QRect(); + } } p->drawPixmap(target.toRect(), d->imagecache[i]->image); topaint -= area; @@ -242,41 +253,46 @@ void QFxPaintedItem::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidge } if (!topaint.isEmpty()) { - // Find a sensible larger area, otherwise will paint lots of tiny images. - QRect biggerrect = topaint.boundingRect().adjusted(-64,-64,128,128); - cachesize += biggerrect.width() * biggerrect.height(); - while (d->imagecache.count() && cachesize > d->max_imagecache_size) { - int oldest=-1; - int age=-1; - for (int i=0; iimagecache.count(); ++i) { - int a = d->imagecache[i]->age; - if (a > age) { - oldest = i; - age = a; + if (!d->cachefrozen) { + // Find a sensible larger area, otherwise will paint lots of tiny images. + QRect biggerrect = topaint.boundingRect().adjusted(-64,-64,128,128); + cachesize += biggerrect.width() * biggerrect.height(); + while (d->imagecache.count() && cachesize > d->max_imagecache_size) { + int oldest=-1; + int age=-1; + for (int i=0; iimagecache.count(); ++i) { + int a = d->imagecache[i]->age; + if (a > age) { + oldest = i; + age = a; + } } + cachesize -= d->imagecache[oldest]->area.width()*d->imagecache[oldest]->area.height(); + uncached += d->imagecache[oldest]->area; + d->imagecache.removeAt(oldest); } - cachesize -= d->imagecache[oldest]->area.width()*d->imagecache[oldest]->area.height(); - uncached += d->imagecache[oldest]->area; - d->imagecache.removeAt(oldest); - } - const QRegion bigger = QRegion(biggerrect) & uncached; - const QVector rects = bigger.rects(); - for (int i = 0; i < rects.count(); ++i) { - const QRect &r = rects.at(i); - QPixmap img(r.size()); - if (d->fillColor.isValid()) - img.fill(d->fillColor); - { - QPainter qp(&img); - qp.translate(-r.x(),-r.y()); - drawContents(&qp, r); + const QRegion bigger = QRegion(biggerrect) & uncached; + const QVector rects = bigger.rects(); + for (int i = 0; i < rects.count(); ++i) { + const QRect &r = rects.at(i); + QPixmap img(r.size()); + if (d->fillColor.isValid()) + img.fill(d->fillColor); + { + QPainter qp(&img); + qp.translate(-r.x(),-r.y()); + drawContents(&qp, r); + } + QFxPaintedItemPrivate::ImageCacheItem *newitem = new QFxPaintedItemPrivate::ImageCacheItem; + newitem->area = r; + newitem->image = img; + d->imagecache.append(newitem); + p->drawPixmap(r, newitem->image); } - QFxPaintedItemPrivate::ImageCacheItem *newitem = new QFxPaintedItemPrivate::ImageCacheItem; - newitem->area = r; - newitem->image = img; - d->imagecache.append(newitem); - QRectF target(r.x(), r.y(), r.width(), r.height()); - p->drawPixmap(target.toRect(), newitem->image); + } else { + const QVector rects = uncached.rects(); + for (int i = 0; i < rects.count(); ++i) + p->fillRect(rects.at(i), Qt::lightGray); } } diff --git a/src/declarative/fx/qfxpainteditem.h b/src/declarative/fx/qfxpainteditem.h index 776ef329..13c6b15 100644 --- a/src/declarative/fx/qfxpainteditem.h +++ b/src/declarative/fx/qfxpainteditem.h @@ -81,6 +81,8 @@ protected: virtual void drawContents(QPainter *p, const QRect &) = 0; + void setCacheFrozen(bool); + Q_SIGNALS: void fillColorChanged(); diff --git a/src/declarative/fx/qfxpainteditem_p.h b/src/declarative/fx/qfxpainteditem_p.h index 2718e57..179fd61 100644 --- a/src/declarative/fx/qfxpainteditem_p.h +++ b/src/declarative/fx/qfxpainteditem_p.h @@ -63,7 +63,7 @@ class QFxPaintedItemPrivate : public QFxItemPrivate public: QFxPaintedItemPrivate() - : max_imagecache_size(100000), fillColor(Qt::transparent) + : max_imagecache_size(100000), fillColor(Qt::transparent), cachefrozen(false) { } @@ -81,6 +81,7 @@ public: int max_imagecache_size; QSize contentsSize; QColor fillColor; + bool cachefrozen; }; QT_END_NAMESPACE diff --git a/src/declarative/fx/qfxwebview.cpp b/src/declarative/fx/qfxwebview.cpp index ba39040..bcbedfb 100644 --- a/src/declarative/fx/qfxwebview.cpp +++ b/src/declarative/fx/qfxwebview.cpp @@ -169,7 +169,8 @@ public: : QFxPaintedItemPrivate(), page(0), preferredwidth(0), pagewidth(0), progress(1.0), status(QFxWebView::Null), pending(PendingNone), newWindowComponent(0), newWindowParent(0), - windowObjects(this) + windowObjects(this), + rendering(true) { } @@ -202,6 +203,8 @@ public: private: QFxWebViewPrivate *priv; } windowObjects; + + bool rendering; }; /*! @@ -355,7 +358,7 @@ void QFxWebView::pageUrlChanged() page()->mainFrame()->setZoomFactor(zf); page()->setViewportSize(QSize(-1,-1)); } - emit zooming(0,0); + emit zooming(zf,0,0); expandToWebPage(); if ((d->url.isEmpty() && page()->mainFrame()->url() != QUrl(QLatin1String("about:blank"))) @@ -493,7 +496,7 @@ void QFxWebView::focusChanged(bool hasFocus) QFxItem::focusChanged(hasFocus); } -void QFxWebView::contentsSizeChanged(const QSize& sz) +void QFxWebView::contentsSizeChanged(const QSize&) { expandToWebPage(); } @@ -645,9 +648,29 @@ void QFxWebViewPrivate::updateWindowObjects() } } +bool QFxWebView::renderingEnabled() const +{ + Q_D(const QFxWebView); + return d->rendering; +} + +void QFxWebView::setRenderingEnabled(bool enabled) +{ + Q_D(QFxWebView); + if (d->rendering == enabled) + return; + d->rendering = enabled; + setCacheFrozen(!enabled); + if (enabled) + clearCache(); +} + + void QFxWebView::drawContents(QPainter *p, const QRect &r) { - page()->mainFrame()->render(p,r); + Q_D(QFxWebView); + if (d->rendering) + page()->mainFrame()->render(p,r); } static QMouseEvent *sceneMouseEventToMouseEvent(QGraphicsSceneMouseEvent *e) @@ -707,9 +730,8 @@ void QFxWebView::heuristicZoom(int clickX, int clickY) // 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); + emit zooming(z,r.x()+r.width()/2, r.y()+r.height()/2); } void QFxWebView::mousePressEvent(QGraphicsSceneMouseEvent *event) diff --git a/src/declarative/fx/qfxwebview.h b/src/declarative/fx/qfxwebview.h index 4a81be8..3dd1b65 100644 --- a/src/declarative/fx/qfxwebview.h +++ b/src/declarative/fx/qfxwebview.h @@ -115,6 +115,8 @@ class Q_DECLARATIVE_EXPORT QFxWebView : public QFxPaintedItem Q_PROPERTY(QmlComponent* newWindowComponent READ newWindowComponent WRITE setNewWindowComponent) Q_PROPERTY(QFxItem* newWindowParent READ newWindowParent WRITE setNewWindowParent) + Q_PROPERTY(bool renderingEnabled READ renderingEnabled WRITE setRenderingEnabled) + public: QFxWebView(QFxItem *parent=0); ~QFxWebView(); @@ -166,6 +168,9 @@ public: int pixelCacheSize() const; void setPixelCacheSize(int pixels); + bool renderingEnabled() const; + void setRenderingEnabled(bool); + QmlList *javaScriptWindowObjects(); static QFxWebViewAttached *qmlAttachedProperties(QObject *); @@ -192,7 +197,7 @@ Q_SIGNALS: void doubleClick(int clickX, int clickY); - void zooming(int centerX, int centerY); + void zooming(qreal zoom, int centerX, int centerY); public Q_SLOTS: QVariant evaluateJavaScript(const QString&); -- cgit v0.12