From 94a4d1918d5fe0d6d094b3f3cbc9e763a50bb19f Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Wed, 26 Aug 2009 09:17:04 +1000 Subject: Avoid shadowing QWebPage::view(). --- src/declarative/fx/qfxwebview.cpp | 6 +++--- src/declarative/fx/qfxwebview.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/declarative/fx/qfxwebview.cpp b/src/declarative/fx/qfxwebview.cpp index 347c9c2..5e3ce29 100644 --- a/src/declarative/fx/qfxwebview.cpp +++ b/src/declarative/fx/qfxwebview.cpp @@ -1174,15 +1174,15 @@ private: QFxWebView *webview; }; -QFxWebView *QFxWebPage::view() +QFxWebView *QFxWebPage::viewItem() { return static_cast(parent()); } QObject *QFxWebPage::createPlugin(const QString &, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues) { - QUrl comp = qmlContext(view())->resolvedUrl(url); - return new QWidget_Dummy_Plugin(comp,view(),paramNames,paramValues); + QUrl comp = qmlContext(viewItem())->resolvedUrl(url); + return new QWidget_Dummy_Plugin(comp,viewItem(),paramNames,paramValues); } QT_END_NAMESPACE diff --git a/src/declarative/fx/qfxwebview.h b/src/declarative/fx/qfxwebview.h index 40c86b4..d7c9fd0 100644 --- a/src/declarative/fx/qfxwebview.h +++ b/src/declarative/fx/qfxwebview.h @@ -70,7 +70,7 @@ public: protected: QObject *createPlugin(const QString &classid, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues); private: - QFxWebView *view(); + QFxWebView *viewItem(); }; -- cgit v0.12 From 642440f41c5cd4b5f0ee66101b3ca32859293d29 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Wed, 26 Aug 2009 10:34:09 +1000 Subject: Fix handling of empty strings for URLs QUrl resolves empty to base, which is not desirable. Preserve emptiness of QUrl. Handle use of empty QUrl with WebView (WebKit doesn't handle empty URLs well either). --- src/declarative/fx/qfxwebview.cpp | 8 +++++++- src/declarative/qml/qmlcompiler.cpp | 2 +- src/declarative/qml/qmlcomponent.cpp | 2 +- src/declarative/qml/qmlcontext.cpp | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/declarative/fx/qfxwebview.cpp b/src/declarative/fx/qfxwebview.cpp index 4c1629e..04a4eef 100644 --- a/src/declarative/fx/qfxwebview.cpp +++ b/src/declarative/fx/qfxwebview.cpp @@ -325,6 +325,12 @@ QUrl QFxWebView::url() const void QFxWebView::setUrl(const QUrl &url) { + if (url.isEmpty()) { + // Make absolute. + setUrl(QUrl("about:blank")); + return; + } + Q_D(QFxWebView); if (url == page()->mainFrame()->url()) return; @@ -333,7 +339,7 @@ void QFxWebView::setUrl(const QUrl &url) d->idealwidth>0 ? d->idealwidth : width(), d->idealheight>0 ? d->idealheight : height())); - Q_ASSERT(url.isEmpty() || !url.isRelative()); + Q_ASSERT(!url.isRelative()); if (isComponentComplete()) page()->mainFrame()->load(url); diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index bbcc64d..4f96d12 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -365,7 +365,7 @@ void QmlCompiler::genLiteralAssignment(const QMetaProperty &prop, case QVariant::Url: { instr.type = QmlInstruction::StoreUrl; - QUrl u = output->url.resolved(QUrl(string)); + QUrl u = string.isEmpty() ? QUrl() : output->url.resolved(QUrl(string)); instr.storeUrl.propertyIndex = prop.propertyIndex(); instr.storeUrl.value = output->indexForString(u.toString()); } diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp index 0e141da..e277d91 100644 --- a/src/declarative/qml/qmlcomponent.cpp +++ b/src/declarative/qml/qmlcomponent.cpp @@ -355,7 +355,7 @@ void QmlComponent::loadUrl(const QUrl &url) d->clear(); - if (url.isRelative()) + if (url.isRelative() && !url.isEmpty()) d->url = d->engine->baseUrl().resolved(url); else d->url = url; diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index 61850c3..97ab375 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -422,7 +422,7 @@ void QmlContext::setContextProperty(const QString &name, QObject *value) QUrl QmlContext::resolvedUrl(const QUrl &src) { QmlContext *ctxt = this; - if (src.isRelative()) { + if (src.isRelative() && !src.isEmpty()) { if (ctxt) { while(ctxt) { if(ctxt->d_func()->url.isValid()) -- cgit v0.12 From 6467d58050ed7a865d0b69fa9f27c4a807e2c410 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Wed, 26 Aug 2009 14:16:39 +1000 Subject: Fix and test for multiple-access-to-same-URL Not reproduced (except by test), but may fix a Bauhaus issue. --- src/declarative/fx/qfxpixmapcache.cpp | 22 ++ src/declarative/fx/qfxpixmapcache.h | 4 +- .../declarative/qfxpixmapcache/data/exists.png | Bin 0 -> 2738 bytes .../declarative/qfxpixmapcache/data/exists1.png | Bin 0 -> 2738 bytes .../declarative/qfxpixmapcache/data/exists2.png | Bin 0 -> 2738 bytes .../declarative/qfxpixmapcache/qfxpixmapcache.pro | 9 + .../qfxpixmapcache/tst_qfxpixmapcache.cpp | 226 +++++++++++++++++++++ 7 files changed, 260 insertions(+), 1 deletion(-) create mode 100644 tests/auto/declarative/qfxpixmapcache/data/exists.png create mode 100644 tests/auto/declarative/qfxpixmapcache/data/exists1.png create mode 100644 tests/auto/declarative/qfxpixmapcache/data/exists2.png create mode 100644 tests/auto/declarative/qfxpixmapcache/qfxpixmapcache.pro create mode 100644 tests/auto/declarative/qfxpixmapcache/tst_qfxpixmapcache.cpp diff --git a/src/declarative/fx/qfxpixmapcache.cpp b/src/declarative/fx/qfxpixmapcache.cpp index 7fc713b..0cc09cd 100644 --- a/src/declarative/fx/qfxpixmapcache.cpp +++ b/src/declarative/fx/qfxpixmapcache.cpp @@ -63,6 +63,7 @@ public: reply->deleteLater(); } QNetworkReply *reply; + QPixmap pixmap; // ensure reference to pixmap to QPixmapCache does not discard int refCount; void addRef() @@ -169,6 +170,9 @@ bool QFxPixmapCache::find(const QUrl& url, QPixmap *pixmap) qWarning() << "Format error loading" << url; *pixmap = QPixmap(); ok = false; + } else { + if ((*iter)->refCount > 1) + (*iter)->pixmap = *pixmap; } (*iter)->release(); } @@ -176,6 +180,15 @@ bool QFxPixmapCache::find(const QUrl& url, QPixmap *pixmap) QPixmapCache::insert(key, *pixmap); } else { ok = !pixmap->isNull(); +#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML + if (url.scheme()!=QLatin1String("file")) +#endif + // We may be the second finder. Still need to check for active replies. + { + QFxSharedNetworkReplyHash::Iterator iter = qfxActiveNetworkReplies.find(key); + if (iter != qfxActiveNetworkReplies.end()) + (*iter)->release(); + } } return ok; } @@ -246,4 +259,13 @@ void QFxPixmapCache::cancelGet(const QUrl& url, QObject* obj) (*iter)->release(); } +/*! + This function is mainly for test verification. It returns the number of + requests that are still unfinished. +*/ +int QFxPixmapCache::pendingRequests() +{ + return qfxActiveNetworkReplies.count(); +} + QT_END_NAMESPACE diff --git a/src/declarative/fx/qfxpixmapcache.h b/src/declarative/fx/qfxpixmapcache.h index ca5d47b..fb5b88a 100644 --- a/src/declarative/fx/qfxpixmapcache.h +++ b/src/declarative/fx/qfxpixmapcache.h @@ -60,7 +60,9 @@ public: static QNetworkReply *get(QmlEngine *, const QUrl& url, QPixmap *pixmap); static void cancelGet(const QUrl& url, QObject* obj); - static bool find(const QUrl& url, QPixmap *pixmap); // url must have been passed to QFxPixmapCache::get, and finished. Or must be a local file. + static bool find(const QUrl& url, QPixmap *pixmap); // url must have been passed to QFxPixmapCache::get, and any returned reply finished. + + static int pendingRequests(); // mainly for test verification }; QT_END_NAMESPACE diff --git a/tests/auto/declarative/qfxpixmapcache/data/exists.png b/tests/auto/declarative/qfxpixmapcache/data/exists.png new file mode 100644 index 0000000..399bd0b Binary files /dev/null and b/tests/auto/declarative/qfxpixmapcache/data/exists.png differ diff --git a/tests/auto/declarative/qfxpixmapcache/data/exists1.png b/tests/auto/declarative/qfxpixmapcache/data/exists1.png new file mode 100644 index 0000000..399bd0b Binary files /dev/null and b/tests/auto/declarative/qfxpixmapcache/data/exists1.png differ diff --git a/tests/auto/declarative/qfxpixmapcache/data/exists2.png b/tests/auto/declarative/qfxpixmapcache/data/exists2.png new file mode 100644 index 0000000..399bd0b Binary files /dev/null and b/tests/auto/declarative/qfxpixmapcache/data/exists2.png differ diff --git a/tests/auto/declarative/qfxpixmapcache/qfxpixmapcache.pro b/tests/auto/declarative/qfxpixmapcache/qfxpixmapcache.pro new file mode 100644 index 0000000..e9b0417 --- /dev/null +++ b/tests/auto/declarative/qfxpixmapcache/qfxpixmapcache.pro @@ -0,0 +1,9 @@ +load(qttest_p4) +contains(QT_CONFIG,declarative): QT += declarative +QT += network +SOURCES += tst_qfxpixmapcache.cpp +HEADERS = +macx:CONFIG -= app_bundle + +# QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage +# LIBS += -lgcov diff --git a/tests/auto/declarative/qfxpixmapcache/tst_qfxpixmapcache.cpp b/tests/auto/declarative/qfxpixmapcache/tst_qfxpixmapcache.cpp new file mode 100644 index 0000000..4d3ad55 --- /dev/null +++ b/tests/auto/declarative/qfxpixmapcache/tst_qfxpixmapcache.cpp @@ -0,0 +1,226 @@ +#include +#include +#include +#include +#include + +// These don't let normal people run tests! +//#include "../network-settings.h" + +class tst_qfxpixmapcache : public QObject +{ + Q_OBJECT +public: + tst_qfxpixmapcache() : + thisfile("file://" __FILE__) + { + } + +private slots: + void single(); + void single_data(); + void parallel(); + void parallel_data(); + +private: + QmlEngine engine; + QUrl thisfile; +}; + + +static int slotters=0; + +class Slotter : public QObject +{ + Q_OBJECT +public: + Slotter() + { + gotslot = false; + slotters++; + } + bool gotslot; + +public slots: + void got() + { + gotslot = true; + --slotters; + if (slotters==0) + QTestEventLoop::instance().exitLoop(); + } +}; + +#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML +static const bool localfile_optimized = true; +#else +static const bool localfile_optimized = false; +#endif + +void tst_qfxpixmapcache::single_data() +{ + // Note, since QFxPixmapCache is shared, tests affect each other! + // so use different files fore all test functions. + + QTest::addColumn("target"); + QTest::addColumn("incache"); + QTest::addColumn("exists"); + + // File URLs are optimized + QTest::newRow("local") << thisfile.resolved(QUrl("data/exists.png")) << localfile_optimized << true; + QTest::newRow("local") << thisfile.resolved(QUrl("data/notexists.png")) << localfile_optimized << false; + QTest::newRow("remote") << QUrl("http://qt.nokia.com/logo.png") << false << true; + QTest::newRow("remote") << QUrl("http://qt.nokia.com/thereisnologo.png") << false << false; +} + +void tst_qfxpixmapcache::single() +{ + QFETCH(QUrl, target); + QFETCH(bool, incache); + QFETCH(bool, exists); + + QPixmap pixmap; + QVERIFY(pixmap.width() <= 0); // Check Qt assumption + QNetworkReply *reply= QFxPixmapCache::get(&engine, target, &pixmap); + + if (incache) { + QVERIFY(!reply); + if (exists) + QVERIFY(pixmap.width() > 0); + else + QVERIFY(pixmap.width() <= 0); + } else { + QVERIFY(reply); + QVERIFY(pixmap.width() <= 0); + + Slotter getter; + connect(reply, SIGNAL(finished()), &getter, SLOT(got())); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + QVERIFY(getter.gotslot); + if (exists) { + QVERIFY(QFxPixmapCache::find(target, &pixmap)); + QVERIFY(pixmap.width() > 0); + } else { + QVERIFY(!QFxPixmapCache::find(target, &pixmap)); + QVERIFY(pixmap.width() <= 0); + } + } + + QCOMPARE(QFxPixmapCache::pendingRequests(), 0); +} + +void tst_qfxpixmapcache::parallel_data() +{ + // Note, since QFxPixmapCache is shared, tests affect each other! + // so use different files fore all test functions. + + QTest::addColumn("target1"); + QTest::addColumn("target2"); + QTest::addColumn("incache"); + QTest::addColumn("cancel"); // which one to cancel + QTest::addColumn("requests"); + + QTest::newRow("local") + << thisfile.resolved(QUrl("data/exists1.png")) + << thisfile.resolved(QUrl("data/exists2.png")) + << (localfile_optimized ? 2 : 0) + << -1 + << (localfile_optimized ? 0 : 2) + ; + + QTest::newRow("remote") + << QUrl("http://qt.nokia.com/images/template/checkbox-on.png") + << QUrl("http://qt.nokia.com/images/products/qt-logo/image_tile") + << 0 + << -1 + << 2 + ; + + QTest::newRow("remoteagain") + << QUrl("http://qt.nokia.com/images/template/checkbox-on.png") + << QUrl("http://qt.nokia.com/images/products/qt-logo/image_tile") + << 2 + << -1 + << 0 + ; + + QTest::newRow("remotecopy") + << QUrl("http://qt.nokia.com/images/template/checkbox-off.png") + << QUrl("http://qt.nokia.com/images/template/checkbox-off.png") + << 0 + << -1 + << 1 + ; + + QTest::newRow("remotecopycancel") + << QUrl("http://qt.nokia.com/rounded_block_bg.png") + << QUrl("http://qt.nokia.com/rounded_block_bg.png") + << 0 + << 0 + << 1 + ; +} + +void tst_qfxpixmapcache::parallel() +{ + QFETCH(QUrl, target1); + QFETCH(QUrl, target2); + QFETCH(int, incache); + QFETCH(int, cancel); + QFETCH(int, requests); + + QList targets; + targets << target1 << target2; + + QList replies; + QList getters; + for (int i=0; i 0); + getters.append(0); + } else { + QVERIFY(pixmap.width() <= 0); + getters.append(new Slotter); + connect(reply, SIGNAL(finished()), getters[i], SLOT(got())); + } + } + + QCOMPARE(incache+slotters, targets.count()); + QCOMPARE(QFxPixmapCache::pendingRequests(), requests); + + if (cancel >= 0) { + QFxPixmapCache::cancelGet(targets.at(cancel), getters[cancel]); + slotters--; + } + + if (slotters) { + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + } + + for (int i=0; igotslot); + } else { + QVERIFY(getters[i]->gotslot); + QPixmap pixmap; + QVERIFY(QFxPixmapCache::find(targets[i], &pixmap)); + QVERIFY(pixmap.width() > 0); + } + delete getters[i]; + } + } + + QCOMPARE(QFxPixmapCache::pendingRequests(), 0); +} + +QTEST_MAIN(tst_qfxpixmapcache) + +#include "tst_qfxpixmapcache.moc" -- cgit v0.12