aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/quick/demos/photosurface/photosurface.qml4
-rw-r--r--src/qml/qml/qqmlimport.cpp31
-rw-r--r--src/qml/qml/qqmlimport_p.h1
-rw-r--r--src/qml/qml/qqmltypeloader.cpp48
-rw-r--r--src/quick/items/qquickflickable.cpp16
-rw-r--r--src/quick/items/qquickitemsmodule.cpp3
-rw-r--r--src/quick/items/qquickmultipointtoucharea.cpp37
-rw-r--r--src/quick/items/qquickopenglshadereffect.cpp2
-rw-r--r--src/quick/util/qquickanimatorcontroller.cpp4
-rw-r--r--src/quick/util/qquickshortcut.cpp3
-rw-r--r--tests/auto/qml/qqmltypeloader/data/Intercept.qml41
-rw-r--r--tests/auto/qml/qqmltypeloader/data/test_intercept.qml53
-rw-r--r--tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp201
-rw-r--r--tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp6
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp17
-rw-r--r--tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp8
-rw-r--r--tests/auto/quick/quick.pro2
17 files changed, 435 insertions, 42 deletions
diff --git a/examples/quick/demos/photosurface/photosurface.qml b/examples/quick/demos/photosurface/photosurface.qml
index 8057bb8400..5d1445d776 100644
--- a/examples/quick/demos/photosurface/photosurface.qml
+++ b/examples/quick/demos/photosurface/photosurface.qml
@@ -181,7 +181,7 @@ Window {
radius: 2
antialiasing: true
height: flick.height * (flick.height / flick.contentHeight) - (width - anchors.margins) * 2
- y: flick.contentY * (flick.height / flick.contentHeight)
+ y: (flick.contentY - flick.originY) * (flick.height / flick.contentHeight)
NumberAnimation on opacity { id: vfade; to: 0; duration: 500 }
onYChanged: { opacity = 1.0; scrollFadeTimer.restart() }
}
@@ -197,7 +197,7 @@ Window {
radius: 2
antialiasing: true
width: flick.width * (flick.width / flick.contentWidth) - (height - anchors.margins) * 2
- x: flick.contentX * (flick.width / flick.contentWidth)
+ x: (flick.contentX - flick.originY) * (flick.width / flick.contentWidth)
NumberAnimation on opacity { id: hfade; to: 0; duration: 500 }
onXChanged: { opacity = 1.0; scrollFadeTimer.restart() }
}
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 4e3b25070f..c8d17c4b8e 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -1266,11 +1266,20 @@ bool QQmlImportsPrivate::locateQmldir(const QString &uri, int vmaj, int vmin, QQ
QQmlTypeLoader &typeLoader = QQmlEnginePrivate::get(database->engine)->typeLoader;
- QStringList localImportPaths = database->importPathList(QQmlImportDatabase::Local);
+ // Interceptor might redirect remote files to local ones.
+ QQmlAbstractUrlInterceptor *interceptor = typeLoader.engine()->urlInterceptor();
+ QStringList localImportPaths = database->importPathList(
+ interceptor ? QQmlImportDatabase::LocalOrRemote : QQmlImportDatabase::Local);
// Search local import paths for a matching version
const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(uri, localImportPaths, vmaj, vmin);
- for (const QString &qmldirPath : qmlDirPaths) {
+ for (QString qmldirPath : qmlDirPaths) {
+ if (interceptor) {
+ qmldirPath = QQmlFile::urlToLocalFileOrQrc(
+ interceptor->intercept(QQmlImports::urlFromLocalFileOrQrcOrUrl(qmldirPath),
+ QQmlAbstractUrlInterceptor::QmldirFile));
+ }
+
QString absoluteFilePath = typeLoader.absoluteFilePath(qmldirPath);
if (!absoluteFilePath.isEmpty()) {
QString url;
@@ -1479,6 +1488,10 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix
QString qmldirUrl = resolveLocalUrl(base, importUri + (importUri.endsWith(Slash)
? String_qmldir
: Slash_qmldir));
+ if (QQmlAbstractUrlInterceptor *interceptor = typeLoader->engine()->urlInterceptor()) {
+ qmldirUrl = interceptor->intercept(QUrl(qmldirUrl),
+ QQmlAbstractUrlInterceptor::QmldirFile).toString();
+ }
QString qmldirIdentifier;
if (QQmlFile::isLocalFile(qmldirUrl)) {
@@ -1564,8 +1577,8 @@ bool QQmlImportsPrivate::updateQmldirContent(const QString &uri, const QString &
if (import->setQmldirContent(qmldirUrl, qmldir, nameSpace, errors)) {
if (import->qmlDirComponents.isEmpty() && import->qmlDirScripts.isEmpty()) {
- // The implicit import qmldir can be empty
- if (uri != QLatin1String(".")) {
+ // The implicit import qmldir can be empty, and plugins have no extra versions
+ if (uri != QLatin1String(".") && !QQmlMetaType::isModule(uri, vmaj, vmin)) {
QQmlError error;
if (QQmlMetaType::isAnyModule(uri))
error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri).arg(vmaj).arg(vmin));
@@ -1693,6 +1706,16 @@ bool QQmlImports::isLocal(const QUrl &url)
return !QQmlFile::urlToLocalFileOrQrc(url).isEmpty();
}
+QUrl QQmlImports::urlFromLocalFileOrQrcOrUrl(const QString &file)
+{
+ QUrl url(QLatin1String(file.at(0) == Colon ? "qrc" : "") + file);
+
+ // We don't support single character schemes as those conflict with windows drive letters.
+ if (url.scheme().length() < 2)
+ return QUrl::fromLocalFile(file);
+ return url;
+}
+
void QQmlImports::setDesignerSupportRequired(bool b)
{
designerSupportRequired = b;
diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h
index 1bdd287690..9cb5340c68 100644
--- a/src/qml/qml/qqmlimport_p.h
+++ b/src/qml/qml/qqmlimport_p.h
@@ -184,6 +184,7 @@ public:
static bool isLocal(const QString &url);
static bool isLocal(const QUrl &url);
+ static QUrl urlFromLocalFileOrQrcOrUrl(const QString &);
static void setDesignerSupportRequired(bool b);
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 842cf74887..f3077f673b 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -1436,8 +1436,13 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL
// We haven't yet resolved this import
m_unresolvedImports.insert(import, 0);
- // Query any network import paths for this library
- QStringList remotePathList = importDatabase->importPathList(QQmlImportDatabase::Remote);
+ QQmlAbstractUrlInterceptor *interceptor = typeLoader()->engine()->urlInterceptor();
+
+ // Query any network import paths for this library.
+ // Interceptor might redirect local paths.
+ QStringList remotePathList = importDatabase->importPathList(
+ interceptor ? QQmlImportDatabase::LocalOrRemote
+ : QQmlImportDatabase::Remote);
if (!remotePathList.isEmpty()) {
// Add this library and request the possible locations for it
if (!m_importCache.addLibraryImport(importDatabase, importUri, importQualifier, import->majorVersion,
@@ -1448,8 +1453,18 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL
int priority = 0;
const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(importUri, remotePathList, import->majorVersion, import->minorVersion);
for (const QString &qmldirPath : qmlDirPaths) {
- if (!fetchQmldir(QUrl(qmldirPath), import, ++priority, errors))
+ if (interceptor) {
+ QUrl url = interceptor->intercept(
+ QQmlImports::urlFromLocalFileOrQrcOrUrl(qmldirPath),
+ QQmlAbstractUrlInterceptor::QmldirFile);
+ if (!QQmlFile::isLocalFile(url)
+ && !fetchQmldir(url, import, ++priority, errors)) {
+ return false;
+ }
+ } else if (!fetchQmldir(QUrl(qmldirPath), import, ++priority, errors)) {
return false;
+ }
+
}
}
}
@@ -1872,19 +1887,22 @@ It can also be a remote path for a remote directory import, but it will have bee
*/
const QQmlTypeLoaderQmldirContent *QQmlTypeLoader::qmldirContent(const QString &filePathIn)
{
- QUrl url(filePathIn); //May already contain http scheme
- if (url.scheme() == QLatin1String("http") || url.scheme() == QLatin1String("https"))
- return *(m_importQmlDirCache.value(filePathIn)); //Can't load the remote here, but should be cached
- else
- url = QUrl::fromLocalFile(filePathIn);
- if (engine() && engine()->urlInterceptor())
- url = engine()->urlInterceptor()->intercept(url, QQmlAbstractUrlInterceptor::QmldirFile);
- Q_ASSERT(url.scheme() == QLatin1String("file"));
QString filePath;
- if (url.scheme() == QLatin1String("file"))
- filePath = url.toLocalFile();
- else
- filePath = url.path();
+
+ // Try to guess if filePathIn is already a URL. This is necessarily fragile, because
+ // - paths can contain ':', which might make them appear as URLs with schemes.
+ // - windows drive letters appear as schemes (thus "< 2" below).
+ // - a "file:" URL is equivalent to the respective file, but will be treated differently.
+ // Yet, this heuristic is the best we can do until we pass more structured information here,
+ // for example a QUrl also for local files.
+ QUrl url(filePathIn);
+ if (url.scheme().length() < 2) {
+ filePath = filePathIn;
+ } else {
+ filePath = QQmlFile::urlToLocalFileOrQrc(url);
+ if (filePath.isEmpty()) // Can't load the remote here, but should be cached
+ return *(m_importQmlDirCache.value(filePathIn));
+ }
QQmlTypeLoaderQmldirContent *qmldir;
QQmlTypeLoaderQmldirContent **val = m_importQmlDirCache.value(filePath);
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index e0f8b6de00..3662827973 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -734,7 +734,19 @@ QQuickFlickable::~QQuickFlickable()
These properties hold the surface coordinate currently at the top-left
corner of the Flickable. For example, if you flick an image up 100 pixels,
- \c contentY will be 100.
+ \c contentY will increase by 100.
+
+ \note If you flick back to the origin (the top-left corner), after the
+ rebound animation, \c contentX will settle to the same value as \c originX,
+ and \c contentY to \c originY. These are usually (0,0), however ListView
+ and GridView may have an arbitrary origin due to delegate size variation,
+ or item insertion/removal outside the visible region. So if you want to
+ implement something like a vertical scrollbar, one way is to use
+ \c {y: (contentY - originY) * (height / contentHeight)}
+ for the position; another way is to use the normalized values in
+ \l {QtQuick::Flickable::visibleArea}{visibleArea}.
+
+ \sa originX, originY
*/
qreal QQuickFlickable::contentX() const
{
@@ -2153,6 +2165,8 @@ void QQuickFlickable::setRightMargin(qreal m)
This is usually (0,0), however ListView and GridView may have an arbitrary
origin due to delegate size variation, or item insertion/removal outside
the visible region.
+
+ \sa contentX, contentY
*/
qreal QQuickFlickable::originY() const
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index 5f6d44b54d..489b1cbd03 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -287,7 +287,8 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickMultiPointTouchArea>("QtQuick", 2, 0, "MultiPointTouchArea");
qmlRegisterType<QQuickTouchPoint>("QtQuick", 2, 0, "TouchPoint");
- qmlRegisterType<QQuickGrabGestureEvent>();
+ qmlRegisterUncreatableType<QQuickGrabGestureEvent>(uri,major,minor, "GestureEvent",
+ QQuickMouseEvent::tr("GestureEvent is only available in the context of handling the gestureStarted signal from MultiPointTouchArea"));
#if QT_CONFIG(accessibility)
qmlRegisterUncreatableType<QQuickAccessibleAttached>("QtQuick", 2, 0, "Accessible",QQuickAccessibleAttached::tr("Accessible is only available via attached properties"));
diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp
index d4c447a384..8866ca2be5 100644
--- a/src/quick/items/qquickmultipointtoucharea.cpp
+++ b/src/quick/items/qquickmultipointtoucharea.cpp
@@ -285,6 +285,43 @@ void QQuickTouchPoint::setUniqueId(const QPointingDeviceUniqueId &id)
emit uniqueIdChanged();
}
+
+/*!
+ \qmltype GestureEvent
+ \instantiates QQuickGrabGestureEvent
+ \inqmlmodule QtQuick
+ \ingroup qtquick-input-events
+ \brief The parameter given with the gestureStarted signal
+
+ The GestureEvent object has the current touch points, which you may choose
+ to interpret as a gesture, and an invokable method to grab the involved
+ points exclusively.
+*/
+
+/*!
+ \qmlproperty real QtQuick::GestureEvent::dragThreshold
+
+ This property holds the system setting for the distance a finger must move
+ before it is interpreted as a drag. It comes from
+ QStyleHints::startDragDistance().
+*/
+
+/*!
+ \qmlproperty list<TouchPoint> QtQuick::GestureEvent::touchPoints
+
+ This property holds the set of current touch points.
+*/
+
+/*!
+ \qmlmethod QtQuick::GestureEvent::grab()
+
+ Acquires an exclusive grab of the mouse and all the \l touchPoints, and
+ calls \l {QQuickItem::setKeepTouchGrab()}{setKeepTouchGrab()} and
+ \l {QQuickItem::setKeepMouseGrab()}{setKeepMouseGrab()} so that any
+ parent Item that \l {QQuickItem::filtersChildMouseEvents()}{filters} its
+ children's events will not be allowed to take over the grabs.
+*/
+
/*!
\qmltype MultiPointTouchArea
\instantiates QQuickMultiPointTouchArea
diff --git a/src/quick/items/qquickopenglshadereffect.cpp b/src/quick/items/qquickopenglshadereffect.cpp
index 4fcfe04b55..193478484e 100644
--- a/src/quick/items/qquickopenglshadereffect.cpp
+++ b/src/quick/items/qquickopenglshadereffect.cpp
@@ -890,7 +890,7 @@ QSGNode *QQuickOpenGLShaderEffect::handleUpdatePaintNode(QSGNode *oldNode, QQuic
bool geometryUsesTextureSubRect = false;
if (m_supportsAtlasTextures && material->textureProviders.size() == 1) {
QSGTextureProvider *provider = material->textureProviders.at(0);
- if (provider->texture()) {
+ if (provider && provider->texture()) {
srcRect = provider->texture()->normalizedTextureSubRect();
geometryUsesTextureSubRect = true;
}
diff --git a/src/quick/util/qquickanimatorcontroller.cpp b/src/quick/util/qquickanimatorcontroller.cpp
index 3f7347c01d..5cf8051922 100644
--- a/src/quick/util/qquickanimatorcontroller.cpp
+++ b/src/quick/util/qquickanimatorcontroller.cpp
@@ -123,8 +123,10 @@ static void qquickanimator_sync_before_start(QAbstractAnimationJob *job)
void QQuickAnimatorController::beforeNodeSync()
{
- for (const QSharedPointer<QAbstractAnimationJob> &toStop : qAsConst(m_rootsPendingStop))
+ for (const QSharedPointer<QAbstractAnimationJob> &toStop : qAsConst(m_rootsPendingStop)) {
toStop->stop();
+ m_animationRoots.remove(toStop.data());
+ }
m_rootsPendingStop.clear();
diff --git a/src/quick/util/qquickshortcut.cpp b/src/quick/util/qquickshortcut.cpp
index 2fe4962b1a..58f7fc8439 100644
--- a/src/quick/util/qquickshortcut.cpp
+++ b/src/quick/util/qquickshortcut.cpp
@@ -41,6 +41,7 @@
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickwindow.h>
+#include <QtQuick/qquickrendercontrol.h>
#include <QtQuick/private/qtquickglobal_p.h>
#include <QtGui/private/qguiapplication_p.h>
@@ -102,6 +103,8 @@ static bool qQuickShortcutContextMatcher(QObject *obj, Qt::ShortcutContext conte
if (QQuickItem *item = qobject_cast<QQuickItem *>(obj))
obj = item->window();
}
+ if (QWindow *renderWindow = QQuickRenderControl::renderWindowFor(qobject_cast<QQuickWindow *>(obj)))
+ obj = renderWindow;
return obj && obj == QGuiApplication::focusWindow();
default:
return false;
diff --git a/tests/auto/qml/qqmltypeloader/data/Intercept.qml b/tests/auto/qml/qqmltypeloader/data/Intercept.qml
new file mode 100644
index 0000000000..b557b4b941
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/Intercept.qml
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import Fast 1.0
+
+Item {
+ Rectangle {
+ color: "red"
+ width: 100
+ height: 100
+ }
+ Fast {
+
+ }
+}
diff --git a/tests/auto/qml/qqmltypeloader/data/test_intercept.qml b/tests/auto/qml/qqmltypeloader/data/test_intercept.qml
new file mode 100644
index 0000000000..0d64cb7e28
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/test_intercept.qml
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+ListView {
+ width: 400
+ height: 500
+ model: 2
+
+ id: test
+ property int created: 0
+ property int loaded: 0
+
+ delegate: Loader {
+ width: ListView.view.width
+ height: 100
+ asynchronous: true
+ source: index == 0 ? "Intercept.qml" : "GenericView.qml"
+
+ onLoaded: {
+ test.loaded++
+ }
+ Component.onCompleted: {
+ test.created++
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
index 68b450ab26..5ab729042f 100644
--- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
+++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
@@ -28,6 +28,7 @@
#include <QtTest/QtTest>
#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlnetworkaccessmanagerfactory.h>
#include <QtQuick/qquickview.h>
#include <QtQuick/qquickitem.h>
#include <QtQml/private/qqmlengine_p.h>
@@ -45,6 +46,7 @@ private slots:
void trimCache2();
void keepSingleton();
void keepRegistrations();
+ void intercept();
};
void tst_QQMLTypeLoader::testLoadComplete()
@@ -70,7 +72,7 @@ void tst_QQMLTypeLoader::loadComponentSynchronously()
QTest::ignoreMessage(QtWarningMsg, QRegularExpression(
QLatin1String(".*nonprotocol::1:1: QtObject is not a type.*")));
QQmlComponent component(&engine, testFileUrl("load_synchronous.qml"));
- QObject *o = component.create();
+ QScopedPointer<QObject> o(component.create());
QVERIFY(o);
}
@@ -111,7 +113,7 @@ void tst_QQMLTypeLoader::trimCache()
void tst_QQMLTypeLoader::trimCache2()
{
- QQuickView *window = new QQuickView();
+ QScopedPointer<QQuickView> window(new QQuickView());
window->setSource(testFileUrl("trim_cache2.qml"));
QQmlTypeLoader &loader = QQmlEnginePrivate::get(window->engine())->typeLoader;
// in theory if gc has already run this could be false
@@ -192,6 +194,201 @@ void tst_QQMLTypeLoader::keepRegistrations()
verifyTypes(true, false); // qmlRegisterType creates an undeletable type.
}
+class NetworkReply : public QNetworkReply
+{
+public:
+ NetworkReply()
+ {
+ open(QIODevice::ReadOnly);
+ }
+
+ void setData(const QByteArray &data)
+ {
+ if (isFinished())
+ return;
+ m_buffer = data;
+ emit readyRead();
+ setFinished(true);
+ emit finished();
+ }
+
+ void fail()
+ {
+ if (isFinished())
+ return;
+ m_buffer.clear();
+ setError(ContentNotFoundError, "content not found");
+ emit error(ContentNotFoundError);
+ setFinished(true);
+ emit finished();
+ }
+
+ qint64 bytesAvailable() const override
+ {
+ return m_buffer.size();
+ }
+
+ qint64 readData(char *data, qint64 maxlen) override
+ {
+ if (m_buffer.length() < maxlen)
+ maxlen = m_buffer.length();
+ std::memcpy(data, m_buffer.data(), maxlen);
+ m_buffer.remove(0, maxlen);
+ return maxlen;
+ }
+
+ void abort() override
+ {
+ if (isFinished())
+ return;
+ m_buffer.clear();
+ setFinished(true);
+ emit finished();
+ }
+
+private:
+ QByteArray m_buffer;
+};
+
+class NetworkAccessManager : public QNetworkAccessManager
+{
+ Q_OBJECT
+public:
+
+ NetworkAccessManager(QObject *parent) : QNetworkAccessManager(parent)
+ {
+ }
+
+ QNetworkReply *createRequest(Operation op, const QNetworkRequest &request,
+ QIODevice *outgoingData) override
+ {
+ QUrl url = request.url();
+ QString scheme = url.scheme();
+ if (op != GetOperation || !scheme.endsWith("+debug"))
+ return QNetworkAccessManager::createRequest(op, request, outgoingData);
+
+ scheme.chop(sizeof("+debug") - 1);
+ url.setScheme(scheme);
+
+ NetworkReply *reply = new NetworkReply;
+ QString filename = QQmlFile::urlToLocalFileOrQrc(url);
+ QTimer::singleShot(10, reply, [this, reply, filename]() {
+ if (filename.isEmpty()) {
+ reply->fail();
+ } else {
+ QFile file(filename);
+ if (file.open(QIODevice::ReadOnly)) {
+ emit loaded(filename);
+ reply->setData(transformQmldir(filename, file.readAll()));
+ } else
+ reply->fail();
+ }
+ });
+ return reply;
+ }
+
+ QByteArray transformQmldir(const QString &filename, const QByteArray &content)
+ {
+ if (!filename.endsWith("/qmldir"))
+ return content;
+
+ // Make qmldir plugin paths absolute, so that we don't try to load them over the network
+ QByteArray result;
+ QByteArray path = filename.toUtf8();
+ path.chop(sizeof("qmldir") - 1);
+ for (QByteArray line : content.split('\n')) {
+ if (line.isEmpty())
+ continue;
+ QList<QByteArray> segments = line.split(' ');
+ if (segments.startsWith("plugin")) {
+ if (segments.length() == 2) {
+ segments.append(path);
+ } else if (segments.length() == 3) {
+ if (!segments[2].startsWith('/'))
+ segments[2] = path + segments[2];
+ } else {
+ // Invalid plugin declaration. Ignore
+ }
+ result.append(segments.join(' '));
+ } else {
+ result.append(line);
+ }
+ result.append('\n');
+ }
+ return result;
+ }
+
+signals:
+ void loaded(const QString &filename);
+};
+
+class NetworkAccessManagerFactory : public QQmlNetworkAccessManagerFactory
+{
+public:
+ QStringList loadedFiles;
+
+ QNetworkAccessManager *create(QObject *parent) override
+ {
+ NetworkAccessManager *manager = new NetworkAccessManager(parent);
+ QObject::connect(manager, &NetworkAccessManager::loaded, [this](const QString &filename) {
+ loadedFiles.append(filename);
+ });
+ return manager;
+ }
+};
+
+class UrlInterceptor : public QQmlAbstractUrlInterceptor
+{
+public:
+ QUrl intercept(const QUrl &path, DataType type) override
+ {
+ Q_UNUSED(type);
+ if (!QQmlFile::isLocalFile(path))
+ return path;
+
+ QUrl result = path;
+ QString scheme = result.scheme();
+ if (!scheme.endsWith("+debug"))
+ result.setScheme(scheme + "+debug");
+ return result;
+ }
+};
+
+void tst_QQMLTypeLoader::intercept()
+{
+ qmlClearTypeRegistrations();
+
+ QQmlEngine engine;
+ engine.addImportPath(dataDirectory());
+ engine.addImportPath(QT_TESTCASE_BUILDDIR);
+
+ UrlInterceptor interceptor;
+ NetworkAccessManagerFactory factory;
+
+ engine.setUrlInterceptor(&interceptor);
+ engine.setNetworkAccessManagerFactory(&factory);
+
+ QQmlComponent component(&engine, testFileUrl("test_intercept.qml"));
+
+ QVERIFY(component.status() != QQmlComponent::Ready);
+ QTRY_VERIFY2(component.status() == QQmlComponent::Ready,
+ component.errorString().toUtf8().constData());
+
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(o.data());
+
+ QTRY_COMPARE(o->property("created").toInt(), 2);
+ QTRY_COMPARE(o->property("loaded").toInt(), 2);
+
+ QVERIFY(factory.loadedFiles.length() >= 6);
+ QVERIFY(factory.loadedFiles.contains(dataDirectory() + "/test_intercept.qml"));
+ QVERIFY(factory.loadedFiles.contains(dataDirectory() + "/Intercept.qml"));
+ QVERIFY(factory.loadedFiles.contains(dataDirectory() + "/Fast/qmldir"));
+ QVERIFY(factory.loadedFiles.contains(dataDirectory() + "/Fast/Fast.qml"));
+ QVERIFY(factory.loadedFiles.contains(dataDirectory() + "/GenericView.qml"));
+ QVERIFY(factory.loadedFiles.contains(QLatin1String(QT_TESTCASE_BUILDDIR) + "/Slow/qmldir"));
+}
+
QTEST_MAIN(tst_QQMLTypeLoader)
#include "tst_qqmltypeloader.moc"
diff --git a/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp b/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
index d4922599be..363064aa31 100644
--- a/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
+++ b/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
@@ -192,7 +192,8 @@ void tst_QQuickFramebufferObject::testThatStuffWorks()
item->setMsaa(msaa);
view.show();
- QTest::qWaitForWindowExposed(&view);
+ view.requestActivate();
+ QTest::qWaitForWindowActive(&view);
QImage result = view.grabWindow();
@@ -231,7 +232,8 @@ void tst_QQuickFramebufferObject::testInvalidate()
item->setTextureSize(QSize(200, 200));
view.show();
- QTest::qWaitForWindowExposed(&view);
+ view.requestActivate();
+ QTest::qWaitForWindowActive(&view);
QCOMPARE(frameInfo.fboSize, QSize(200, 200));
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index c08d5d31b4..f06a118976 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -8658,9 +8658,9 @@ void tst_QQuickListView::QTBUG_34576_velocityZero()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QVERIFY(listview);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QVERIFY(contentItem);
QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
QSignalSpy horizontalVelocitySpy(listview, SIGNAL(horizontalVelocityChanged()));
@@ -8672,20 +8672,21 @@ void tst_QQuickListView::QTBUG_34576_velocityZero()
window->rootObject()->setProperty("horizontalVelocityZeroCount", QVariant(0));
listview->setCurrentIndex(2);
QTRY_COMPARE(window->rootObject()->property("current").toInt(), 2);
- QTRY_COMPARE(horizontalVelocitySpy.count(), 0);
- QTRY_COMPARE(window->rootObject()->property("horizontalVelocityZeroCount").toInt(), 0);
+ QCOMPARE(horizontalVelocitySpy.count(), 0);
+ QCOMPARE(window->rootObject()->property("horizontalVelocityZeroCount").toInt(), 0);
+
+ QSignalSpy currentIndexChangedSpy(listview, SIGNAL(currentIndexChanged()));
// click button which increases currentIndex
QTest::mousePress(window, Qt::LeftButton, 0, QPoint(295,215));
QTest::mouseRelease(window, Qt::LeftButton, 0, QPoint(295,215));
// verify that currentIndexChanged is triggered
- QVERIFY(horizontalVelocitySpy.wait());
+ QTRY_VERIFY(currentIndexChangedSpy.count() > 0);
- // set currentIndex to item out of view to cause listview scroll
+ // since we have set currentIndex to an item out of view, the listview will scroll
QTRY_COMPARE(window->rootObject()->property("current").toInt(), 3);
- QTRY_COMPARE(horizontalVelocitySpy.count() > 0, true);
- QVERIFY(horizontalVelocitySpy.wait(1000));
+ QTRY_VERIFY(horizontalVelocitySpy.count() > 0);
// velocity should be always > 0.0
QTRY_COMPARE(window->rootObject()->property("horizontalVelocityZeroCount").toInt(), 0);
diff --git a/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp b/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
index fe33dbd4d8..1731253da6 100644
--- a/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
+++ b/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
@@ -52,8 +52,8 @@ public:
int signalsConnected = 0;
protected:
- void connectNotify(const QMetaMethod &) { ++signalsConnected; }
- void disconnectNotify(const QMetaMethod &) { --signalsConnected; }
+ void connectNotify(const QMetaMethod &) override { ++signalsConnected; }
+ void disconnectNotify(const QMetaMethod &) override { --signalsConnected; }
signals:
void dummyChanged();
@@ -257,7 +257,7 @@ void tst_qquickshadereffect::lookThroughShaderCode()
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0\nimport ShaderEffectTest 1.0\nTestShaderEffect {}", QUrl());
QScopedPointer<TestShaderEffect> item(qobject_cast<TestShaderEffect*>(component.create()));
- QCOMPARE(item->signalsConnected, 1);
+ QCOMPARE(item->signalsConnected, 0);
QString expected;
if ((presenceFlags & VertexPresent) == 0)
@@ -274,7 +274,7 @@ void tst_qquickshadereffect::lookThroughShaderCode()
QCOMPARE(item->parseLog(), expected);
// If the uniform was successfully parsed, the notify signal has been connected to an update slot.
- QCOMPARE(item->signalsConnected, (presenceFlags & SourcePresent) ? 2 : 1);
+ QCOMPARE(item->signalsConnected, (presenceFlags & SourcePresent) ? 1 : 0);
}
void tst_qquickshadereffect::deleteSourceItem()
diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro
index 00be8240e5..4c1c667489 100644
--- a/tests/auto/quick/quick.pro
+++ b/tests/auto/quick/quick.pro
@@ -46,7 +46,7 @@ PRIVATETESTS += \
# This test requires the xmlpatterns module
!qtHaveModule(xmlpatterns): PRIVATETESTS -= qquickxmllistmodel
-QUICKTESTS = \
+QUICKTESTS += \
qquickaccessible \
qquickanchors \
qquickanimatedimage \