diff options
176 files changed, 2356 insertions, 959 deletions
diff --git a/examples/qml/qmlextensionplugins/plugin.cpp b/examples/qml/qmlextensionplugins/plugin.cpp index 56057b7f06..e04cfa57d8 100644 --- a/examples/qml/qmlextensionplugins/plugin.cpp +++ b/examples/qml/qmlextensionplugins/plugin.cpp @@ -141,7 +141,7 @@ MinuteTimer *TimeModel::timer=0; class QExampleQmlPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: void registerTypes(const char *uri) diff --git a/examples/qml/tutorials/extending-qml/chapter6-plugins/app.pro b/examples/qml/tutorials/extending-qml/chapter6-plugins/app.pro index c55db00d27..4d0e807417 100644 --- a/examples/qml/tutorials/extending-qml/chapter6-plugins/app.pro +++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/app.pro @@ -1,10 +1,15 @@ TARGET = chapter6-plugins QT += qml quick -# Avoid going to debug/release subdirectory -# so that our application will see the -# import path for the Charts module. +# Ensure that the application will see the import path for the Charts module: +# * On Windows, do not build into a debug/release subdirectory. +# * On OS X, add the plugin files into the bundle. win32: DESTDIR = ./ +osx { + charts.files = $$OUT_PWD/Charts + charts.path = Contents/PlugIns + QMAKE_BUNDLE_DATA += charts +} SOURCES += main.cpp RESOURCES += app.qrc diff --git a/examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.h b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.h index 3c0f84fe34..2a9c2446bd 100644 --- a/examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.h +++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.h @@ -46,7 +46,7 @@ class ChartsPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: void registerTypes(const char *uri); diff --git a/examples/qml/tutorials/extending-qml/chapter6-plugins/main.cpp b/examples/qml/tutorials/extending-qml/chapter6-plugins/main.cpp index b20ae35f92..d165513861 100644 --- a/examples/qml/tutorials/extending-qml/chapter6-plugins/main.cpp +++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. @@ -37,17 +37,21 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -//![0] #include <QtQuick/QQuickView> #include <QGuiApplication> +#include <QQmlEngine> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); +//![0] QQuickView view; +#ifdef Q_OS_OSX + view.engine()->addImportPath(app.applicationDirPath() + "/../PlugIns"); +#endif +//![0] view.setResizeMode(QQuickView::SizeRootObjectToView); view.setSource(QUrl("qrc:///app.qml")); view.show(); return app.exec(); } -//![0] diff --git a/examples/quick/customitems/painteditem/TextBalloonPlugin/plugin.h b/examples/quick/customitems/painteditem/TextBalloonPlugin/plugin.h index 3a2ddae871..d3a1f4ba91 100644 --- a/examples/quick/customitems/painteditem/TextBalloonPlugin/plugin.h +++ b/examples/quick/customitems/painteditem/TextBalloonPlugin/plugin.h @@ -55,7 +55,7 @@ class TextBalloonPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: void registerTypes(const char *uri) { diff --git a/examples/quick/imageprovider/imageprovider.cpp b/examples/quick/imageprovider/imageprovider.cpp index f402ce0ce8..1e4f53e736 100644 --- a/examples/quick/imageprovider/imageprovider.cpp +++ b/examples/quick/imageprovider/imageprovider.cpp @@ -87,7 +87,7 @@ public: class ImageProviderExtensionPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: void registerTypes(const char *uri) { @@ -103,7 +103,4 @@ public: }; -#define QQmlExtensionInterface_iid "org.qt-project.Qt.QQmlExtensionInterface" - - #include "imageprovider.moc" diff --git a/examples/quick/imageresponseprovider/imageresponseprovider.cpp b/examples/quick/imageresponseprovider/imageresponseprovider.cpp index bdec29114b..a888c823a6 100644 --- a/examples/quick/imageresponseprovider/imageresponseprovider.cpp +++ b/examples/quick/imageresponseprovider/imageresponseprovider.cpp @@ -102,7 +102,7 @@ private: class ImageProviderExtensionPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: void registerTypes(const char *uri) { @@ -117,7 +117,4 @@ public: }; - -#define QQmlExtensionInterface_iid "org.qt-project.Qt.QQmlExtensionInterface" - #include "imageresponseprovider.moc" diff --git a/src/3rdparty/masm/wtf/Compiler.h b/src/3rdparty/masm/wtf/Compiler.h index b886f37151..fc3b5c5c08 100644 --- a/src/3rdparty/masm/wtf/Compiler.h +++ b/src/3rdparty/masm/wtf/Compiler.h @@ -74,12 +74,15 @@ /* COMPILER(MSVC) - Microsoft Visual C++ */ /* COMPILER(MSVC7_OR_LOWER) - Microsoft Visual C++ 2003 or lower*/ /* COMPILER(MSVC9_OR_LOWER) - Microsoft Visual C++ 2008 or lower*/ +/* COMPILER(MSVC12_OR_LOWER) - Microsoft Visual C++ 2013 or lower*/ #if defined(_MSC_VER) #define WTF_COMPILER_MSVC 1 #if _MSC_VER < 1400 #define WTF_COMPILER_MSVC7_OR_LOWER 1 #elif _MSC_VER < 1600 #define WTF_COMPILER_MSVC9_OR_LOWER 1 +#elif _MSC_VER < 1800 +#define WTF_COMPILER_MSVC12_OR_LOWER 1 #endif /* Specific compiler features */ diff --git a/src/3rdparty/masm/wtf/MathExtras.h b/src/3rdparty/masm/wtf/MathExtras.h index 9a85291ae2..9ded0ab736 100644 --- a/src/3rdparty/masm/wtf/MathExtras.h +++ b/src/3rdparty/masm/wtf/MathExtras.h @@ -173,11 +173,15 @@ inline float log2f(float num) inline long long abs(long long num) { return _abs64(num); } #endif +#if COMPILER(MSVC12_OR_LOWER) + inline double nextafter(double x, double y) { return _nextafter(x, y); } inline float nextafterf(float x, float y) { return x > y ? x - FLT_EPSILON : x + FLT_EPSILON; } inline double copysign(double x, double y) { return _copysign(x, y); } +#endif // COMPILER(MSVC12_OR_LOWER) + // Work around a bug in Win, where atan2(+-infinity, +-infinity) yields NaN instead of specific values. inline double wtf_atan2(double x, double y) { @@ -211,6 +215,8 @@ inline double wtf_pow(double x, double y) { return y == 0 ? 1 : pow(x, y); } #define fmod(x, y) wtf_fmod(x, y) #define pow(x, y) wtf_pow(x, y) +#if COMPILER(MSVC12_OR_LOWER) + // MSVC's math functions do not bring lrint. inline long int lrint(double flt) { @@ -233,6 +239,7 @@ inline long int lrint(double flt) return static_cast<long int>(intgr); } +#endif // COMPILER(MSVC12_OR_LOWER) #endif // COMPILER(MSVC) inline double deg2rad(double d) { return d * piDouble / 180.0; } diff --git a/src/imports/folderlistmodel/plugin.cpp b/src/imports/folderlistmodel/plugin.cpp index 38de232dc0..affde1c3aa 100644 --- a/src/imports/folderlistmodel/plugin.cpp +++ b/src/imports/folderlistmodel/plugin.cpp @@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE class QmlFolderListModelPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: QmlFolderListModelPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } diff --git a/src/imports/layouts/plugin.cpp b/src/imports/layouts/plugin.cpp index 64d687cf3b..da5f264ab5 100644 --- a/src/imports/layouts/plugin.cpp +++ b/src/imports/layouts/plugin.cpp @@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE class QtQuickLayoutsPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: QtQuickLayoutsPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp index 8780dcc757..3fd36f3f0d 100644 --- a/src/imports/localstorage/plugin.cpp +++ b/src/imports/localstorage/plugin.cpp @@ -754,7 +754,7 @@ static QObject *module_api_factory(QQmlEngine *engine, QJSEngine *scriptEngine) class QQmlLocalStoragePlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: QQmlLocalStoragePlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) diff --git a/src/imports/models/plugin.cpp b/src/imports/models/plugin.cpp index 046d69cbc5..dbb62cd25d 100644 --- a/src/imports/models/plugin.cpp +++ b/src/imports/models/plugin.cpp @@ -75,7 +75,7 @@ QT_BEGIN_NAMESPACE class QtQmlModelsPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: QtQmlModelsPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } void registerTypes(const char *uri) Q_DECL_OVERRIDE diff --git a/src/imports/particles/plugin.cpp b/src/imports/particles/plugin.cpp index 22eea16d4c..28ce0f7796 100644 --- a/src/imports/particles/plugin.cpp +++ b/src/imports/particles/plugin.cpp @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE class QtQuick2ParticlesPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: QtQuick2ParticlesPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } void registerTypes(const char *uri) Q_DECL_OVERRIDE diff --git a/src/imports/qtquick2/plugin.cpp b/src/imports/qtquick2/plugin.cpp index 1e3ff255f8..e56027c1bb 100644 --- a/src/imports/qtquick2/plugin.cpp +++ b/src/imports/qtquick2/plugin.cpp @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE class QtQuick2Plugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: QtQuick2Plugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } void registerTypes(const char *uri) Q_DECL_OVERRIDE diff --git a/src/imports/settings/plugin.cpp b/src/imports/settings/plugin.cpp index ce498774d2..c422296446 100644 --- a/src/imports/settings/plugin.cpp +++ b/src/imports/settings/plugin.cpp @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE class QmlSettingsPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: QmlSettingsPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } diff --git a/src/imports/statemachine/plugin.cpp b/src/imports/statemachine/plugin.cpp index c061607f40..ae32f6446a 100644 --- a/src/imports/statemachine/plugin.cpp +++ b/src/imports/statemachine/plugin.cpp @@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE class QtQmlStateMachinePlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtQml.StateMachine/1.0") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: QtQmlStateMachinePlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } diff --git a/src/imports/testlib/main.cpp b/src/imports/testlib/main.cpp index 1632d7ba64..4e2bd919e9 100644 --- a/src/imports/testlib/main.cpp +++ b/src/imports/testlib/main.cpp @@ -147,7 +147,7 @@ QT_BEGIN_NAMESPACE class QTestQmlModule : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: QTestQmlModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } diff --git a/src/imports/window/plugin.cpp b/src/imports/window/plugin.cpp index b85ccc6dc7..200f6f7b08 100644 --- a/src/imports/window/plugin.cpp +++ b/src/imports/window/plugin.cpp @@ -70,7 +70,7 @@ QT_BEGIN_NAMESPACE class QtQuick2WindowPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: QtQuick2WindowPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } void registerTypes(const char *uri) Q_DECL_OVERRIDE diff --git a/src/imports/xmllistmodel/plugin.cpp b/src/imports/xmllistmodel/plugin.cpp index ca676c36b0..af7625c96a 100644 --- a/src/imports/xmllistmodel/plugin.cpp +++ b/src/imports/xmllistmodel/plugin.cpp @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE class QmlXmlListModelPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: QmlXmlListModelPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } diff --git a/src/particles/qquickcustomparticle.cpp b/src/particles/qquickcustomparticle.cpp index 32b2fd847e..3cb7f6c2bf 100644 --- a/src/particles/qquickcustomparticle.cpp +++ b/src/particles/qquickcustomparticle.cpp @@ -290,8 +290,6 @@ QQuickShaderEffectNode *QQuickCustomParticle::prepareNextFrame(QQuickShaderEffec builder.appendSourceFile(QStringLiteral(":/particles/shaders/customparticle.vert")); s.sourceCode[Key::VertexShader] = builder.source() + s.sourceCode[Key::VertexShader]; - s.className = metaObject()->className(); - material->setProgramSource(s); material->attributes = m_common.attributes; foreach (QQuickShaderEffectNode* node, m_nodes) diff --git a/src/particles/qquickparticleemitter_p.h b/src/particles/qquickparticleemitter_p.h index 9b114ad46b..dd55fdc7a6 100644 --- a/src/particles/qquickparticleemitter_p.h +++ b/src/particles/qquickparticleemitter_p.h @@ -322,6 +322,8 @@ public: return m_startTime; } + void reclaculateGroupId() const; + protected: qreal m_particlesPerSecond; int m_particleDuration; @@ -359,9 +361,6 @@ protected: bool isEmitConnected(); -private: // methods - void reclaculateGroupId() const; - private: // data QString m_group; mutable bool m_groupIdNeedRecalculation; diff --git a/src/particles/qquickparticlesystem.cpp b/src/particles/qquickparticlesystem.cpp index 17d9e49d63..b60180b2ed 100644 --- a/src/particles/qquickparticlesystem.cpp +++ b/src/particles/qquickparticlesystem.cpp @@ -597,6 +597,13 @@ void QQuickParticleSystem::initGroups() groupIds.clear(); nextFreeGroupId = 0; + for (auto e : qAsConst(m_emitters)) { + e->reclaculateGroupId(); + } + foreach (QQuickParticlePainter *p, m_painters) { + p->recalculateGroupIds(); + } + QQuickParticleGroupData *pd = new QQuickParticleGroupData(QString(), this); // Default group Q_ASSERT(pd->index == 0); Q_UNUSED(pd); diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp index a9996da7f4..ff4e30835d 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp @@ -683,11 +683,13 @@ bool QQmlEngineDebugServiceImpl::resetBinding(int objectId, const QString &prope QQmlContext *context = qmlContext(object); if (object && context) { - QString parentProperty = propertyName; - if (propertyName.indexOf(QLatin1Char('.')) != -1) - parentProperty = propertyName.left(propertyName.indexOf(QLatin1Char('.'))); + QStringRef parentPropertyRef(&propertyName); + const int idx = parentPropertyRef.indexOf(QLatin1Char('.')); + if (idx != -1) + parentPropertyRef = parentPropertyRef.left(idx); - if (object->property(parentProperty.toLatin1()).isValid()) { + const QByteArray parentProperty = parentPropertyRef.toLatin1(); + if (object->property(parentProperty).isValid()) { QQmlProperty property(object, propertyName); QQmlPropertyPrivate::removeBinding(property); if (property.isResettable()) { @@ -700,7 +702,7 @@ bool QQmlEngineDebugServiceImpl::resetBinding(int objectId, const QString &prope // overwrite with default value if (QQmlType *objType = QQmlMetaType::qmlType(object->metaObject())) { if (QObject *emptyObject = objType->create()) { - if (emptyObject->property(parentProperty.toLatin1()).isValid()) { + if (emptyObject->property(parentProperty).isValid()) { QVariant defaultValue = QQmlProperty(emptyObject, propertyName).read(); if (defaultValue.isValid()) { setBinding(objectId, propertyName, defaultValue, true); diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp index 075f56226d..99f5b760ba 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp @@ -704,7 +704,7 @@ bool NativeDebugger::reallyHitTheBreakPoint(const QV4::Function *function, int l const BreakPoint &bp = m_service->m_breakHandler->m_breakPoints.at(i); if (bp.lineNumber == lineNumber) { const QString fileName = function->sourceFile(); - const QString base = fileName.mid(fileName.lastIndexOf('/') + 1); + const QStringRef base = fileName.midRef(fileName.lastIndexOf('/') + 1); if (bp.fileName.endsWith(base)) { if (bp.condition.isEmpty() || checkCondition(bp.condition)) { BreakPoint &mbp = m_service->m_breakHandler->m_breakPoints[i]; diff --git a/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp b/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp index cc0118f0c2..3145601612 100644 --- a/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp +++ b/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp @@ -49,6 +49,7 @@ #include <QtCore/qjsonobject.h> #include <QtCore/qjsonvalue.h> #include <QtCore/qpointer.h> +#include <QtCore/qvector.h> //#define TRACE_PROTOCOL(s) qDebug() << s #define TRACE_PROTOCOL(s) @@ -182,24 +183,21 @@ QQmlNativeDebugConnector::QQmlNativeDebugConnector() : m_blockingMode(false) { const QString args = commandLineArguments(); - const QStringList lstjsDebugArguments = args.split(QLatin1Char(',')); + const auto lstjsDebugArguments = args.splitRef(QLatin1Char(',')); QStringList services; - QStringList::const_iterator argsItEnd = lstjsDebugArguments.cend(); - QStringList::const_iterator argsIt = lstjsDebugArguments.cbegin(); - for (; argsIt != argsItEnd; ++argsIt) { - const QString strArgument = *argsIt; + for (const QStringRef &strArgument : lstjsDebugArguments) { if (strArgument == QLatin1String("block")) { m_blockingMode = true; } else if (strArgument == QLatin1String("native")) { // Ignore. This is used to signal that this connector // should be loaded and that has already happened. } else if (strArgument.startsWith(QLatin1String("services:"))) { - services.append(strArgument.mid(9)); + services.append(strArgument.mid(9).toString()); } else if (!services.isEmpty()) { - services.append(strArgument); + services.append(strArgument.toString()); } else { qWarning("QML Debugger: Invalid argument \"%s\" detected. Ignoring the same.", - qUtf8Printable(strArgument)); + strArgument.toUtf8().constData()); } } setServices(services); diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp index 688ced26ec..a193ddea0b 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp @@ -58,71 +58,81 @@ QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEngin connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData())); connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)), engine->profiler, SLOT(setTimer(QElapsedTimer))); - connect(engine->profiler, SIGNAL(dataReady(QVector<QQmlProfilerData>)), - this, SLOT(receiveData(QVector<QQmlProfilerData>))); + connect(engine->profiler, + SIGNAL(dataReady(QVector<QQmlProfilerData>,QQmlProfiler::LocationHash)), + this, + SLOT(receiveData(QVector<QQmlProfilerData>,QQmlProfiler::LocationHash))); } // convert to QByteArrays that can be sent to the debug client // use of QDataStream can skew results // (see tst_qqmldebugtrace::trace() benchmark) -static void qQmlProfilerDataToByteArrays(const QQmlProfilerData *d, QList<QByteArray> &messages) +static void qQmlProfilerDataToByteArrays(const QQmlProfilerData &d, + const QQmlProfiler::LocationHash &locations, + QList<QByteArray> &messages) { QQmlDebugPacket ds; - Q_ASSERT_X(((d->messageType | d->detailType) & (1 << 31)) == 0, Q_FUNC_INFO, - "You can use at most 31 message types and 31 detail types."); - for (uint decodedMessageType = 0; (d->messageType >> decodedMessageType) != 0; + Q_ASSERT_X((d.messageType & (1 << 31)) == 0, Q_FUNC_INFO, + "You can use at most 31 message types."); + for (quint32 decodedMessageType = 0; (d.messageType >> decodedMessageType) != 0; ++decodedMessageType) { - if ((d->messageType & (1 << decodedMessageType)) == 0) + if ((d.messageType & (1 << decodedMessageType)) == 0) continue; - for (uint decodedDetailType = 0; (d->detailType >> decodedDetailType) != 0; - ++decodedDetailType) { - if ((d->detailType & (1 << decodedDetailType)) == 0) - continue; + //### using QDataStream is relatively expensive + ds << d.time << decodedMessageType << static_cast<quint32>(d.detailType); - //### using QDataStream is relatively expensive - ds << d->time << decodedMessageType << decodedDetailType; + QQmlProfiler::Location l = locations.value(d.locationId); - switch (decodedMessageType) { - case QQmlProfilerDefinitions::RangeStart: - case QQmlProfilerDefinitions::RangeEnd: - break; - case QQmlProfilerDefinitions::RangeData: - ds << (d->detailString.isEmpty() ? d->detailUrl.toString() : d->detailString); - break; - case QQmlProfilerDefinitions::RangeLocation: - ds << (d->detailUrl.isEmpty() ? d->detailString : d->detailUrl.toString()) << d->x - << d->y; - break; - default: - Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type."); - break; - } - messages.append(ds.squeezedData()); - ds.clear(); + switch (decodedMessageType) { + case QQmlProfilerDefinitions::RangeStart: + case QQmlProfilerDefinitions::RangeEnd: + break; + case QQmlProfilerDefinitions::RangeData: + ds << (l.location.sourceFile.isEmpty() ? l.url.toString() : l.location.sourceFile); + break; + case QQmlProfilerDefinitions::RangeLocation: + ds << (l.url.isEmpty() ? l.location.sourceFile : l.url.toString()) + << static_cast<qint32>(l.location.line) << static_cast<qint32>(l.location.column); + break; + default: + Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type."); + break; } + messages.append(ds.squeezedData()); + ds.clear(); } } qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages) { while (next != data.length()) { - if (data[next].time > until || messages.length() > s_numMessagesPerBatch) - return data[next].time; - qQmlProfilerDataToByteArrays(&(data[next++]), messages); + const QQmlProfilerData &nextData = data.at(next); + if (nextData.time > until || messages.length() > s_numMessagesPerBatch) + return nextData.time; + qQmlProfilerDataToByteArrays(nextData, locations, messages); + ++next; } next = 0; data.clear(); + locations.clear(); return -1; } -void QQmlProfilerAdapter::receiveData(const QVector<QQmlProfilerData> &new_data) +void QQmlProfilerAdapter::receiveData(const QVector<QQmlProfilerData> &new_data, + const QQmlProfiler::LocationHash &new_locations) { if (data.isEmpty()) data = new_data; else data.append(new_data); + + if (locations.isEmpty()) + locations = new_locations; + else + locations.unite(new_locations); + service->dataReady(this); } diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h index 2d93efba1b..7e13b6c479 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h @@ -63,10 +63,12 @@ public: qint64 sendMessages(qint64 until, QList<QByteArray> &messages) Q_DECL_OVERRIDE; public slots: - void receiveData(const QVector<QQmlProfilerData> &new_data); + void receiveData(const QVector<QQmlProfilerData> &new_data, + const QQmlProfiler::LocationHash &locations); private: QVector<QQmlProfilerData> data; + QQmlProfiler::LocationHash locations; int next; }; diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp index b50eef5545..68a71a5524 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp +++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp @@ -61,29 +61,35 @@ QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::Execut connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData())); connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)), engine->profiler, SLOT(setTimer(QElapsedTimer))); - connect(engine->profiler, SIGNAL(dataReady(QVector<QV4::Profiling::FunctionCallProperties>, + connect(engine->profiler, SIGNAL(dataReady(QV4::Profiling::FunctionLocationHash, + QVector<QV4::Profiling::FunctionCallProperties>, QVector<QV4::Profiling::MemoryAllocationProperties>)), - this, SLOT(receiveData(QVector<QV4::Profiling::FunctionCallProperties>, + this, SLOT(receiveData(QV4::Profiling::FunctionLocationHash, + QVector<QV4::Profiling::FunctionCallProperties>, QVector<QV4::Profiling::MemoryAllocationProperties>))); } qint64 QV4ProfilerAdapter::appendMemoryEvents(qint64 until, QList<QByteArray> &messages, QQmlDebugPacket &d) { - while (m_memoryData.length() > m_memoryPos && m_memoryData[m_memoryPos].timestamp <= until) { - QV4::Profiling::MemoryAllocationProperties &props = m_memoryData[m_memoryPos]; + // Make it const, so that we cannot accidentally detach it. + const QVector<QV4::Profiling::MemoryAllocationProperties> &memoryData = m_memoryData; + + while (memoryData.length() > m_memoryPos && memoryData[m_memoryPos].timestamp <= until) { + const QV4::Profiling::MemoryAllocationProperties &props = memoryData[m_memoryPos]; d << props.timestamp << MemoryAllocation << props.type << props.size; ++m_memoryPos; messages.append(d.squeezedData()); d.clear(); } - return m_memoryData.length() == m_memoryPos ? -1 : m_memoryData[m_memoryPos].timestamp; + return memoryData.length() == m_memoryPos ? -1 : memoryData[m_memoryPos].timestamp; } qint64 QV4ProfilerAdapter::finalizeMessages(qint64 until, QList<QByteArray> &messages, qint64 callNext, QQmlDebugPacket &d) { if (callNext == -1) { + m_functionLocations.clear(); m_functionCallData.clear(); m_functionCallPos = 0; } @@ -102,10 +108,15 @@ qint64 QV4ProfilerAdapter::finalizeMessages(qint64 until, QList<QByteArray> &mes qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages) { QQmlDebugPacket d; + + // Make it const, so that we cannot accidentally detach it. + const QVector<QV4::Profiling::FunctionCallProperties> &functionCallData = m_functionCallData; + const QV4::Profiling::FunctionLocationHash &functionLocations = m_functionLocations; + while (true) { while (!m_stack.isEmpty() && - (m_functionCallPos == m_functionCallData.length() || - m_stack.top() <= m_functionCallData[m_functionCallPos].start)) { + (m_functionCallPos == functionCallData.length() || + m_stack.top() <= functionCallData[m_functionCallPos].start)) { if (m_stack.top() > until || messages.length() > s_numMessagesPerBatch) return finalizeMessages(until, messages, m_stack.top(), d); @@ -114,39 +125,46 @@ qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &message messages.append(d.squeezedData()); d.clear(); } - while (m_functionCallPos != m_functionCallData.length() && - (m_stack.empty() || m_functionCallData[m_functionCallPos].start < m_stack.top())) { + while (m_functionCallPos != functionCallData.length() && + (m_stack.empty() || functionCallData[m_functionCallPos].start < m_stack.top())) { const QV4::Profiling::FunctionCallProperties &props = - m_functionCallData[m_functionCallPos]; + functionCallData[m_functionCallPos]; if (props.start > until || messages.length() > s_numMessagesPerBatch) return finalizeMessages(until, messages, props.start, d); appendMemoryEvents(props.start, messages, d); + auto location = functionLocations.constFind(props.id); + Q_ASSERT(location != functionLocations.constEnd()); d << props.start << RangeStart << Javascript; messages.push_back(d.squeezedData()); d.clear(); - d << props.start << RangeLocation << Javascript << props.file << props.line - << props.column; + d << props.start << RangeLocation << Javascript << location->file << location->line + << location->column; messages.push_back(d.squeezedData()); d.clear(); - d << props.start << RangeData << Javascript << props.name; + d << props.start << RangeData << Javascript << location->name; messages.push_back(d.squeezedData()); d.clear(); m_stack.push(props.end); ++m_functionCallPos; } - if (m_stack.empty() && m_functionCallPos == m_functionCallData.length()) + if (m_stack.empty() && m_functionCallPos == functionCallData.length()) return finalizeMessages(until, messages, -1, d); } } void QV4ProfilerAdapter::receiveData( + const QV4::Profiling::FunctionLocationHash &locations, const QVector<QV4::Profiling::FunctionCallProperties> &functionCallData, const QVector<QV4::Profiling::MemoryAllocationProperties> &memoryData) { // In rare cases it could be that another flush or stop event is processed while data from // the previous one is still pending. In that case we just append the data. + if (m_functionLocations.isEmpty()) + m_functionLocations = locations; + else + m_functionLocations.unite(locations); if (m_functionCallData.isEmpty()) m_functionCallData = functionCallData; diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h index f2985af98b..968825c346 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h +++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h @@ -74,7 +74,8 @@ signals: void v4ProfilingEnabledWhileWaiting(quint64 v4Features); public slots: - void receiveData(const QVector<QV4::Profiling::FunctionCallProperties> &, + void receiveData(const QV4::Profiling::FunctionLocationHash &, + const QVector<QV4::Profiling::FunctionCallProperties> &, const QVector<QV4::Profiling::MemoryAllocationProperties> &); private slots: @@ -82,6 +83,7 @@ private slots: void forwardEnabledWhileWaiting(quint64 features); private: + QV4::Profiling::FunctionLocationHash m_functionLocations; QVector<QV4::Profiling::FunctionCallProperties> m_functionCallData; QVector<QV4::Profiling::MemoryAllocationProperties> m_memoryData; int m_functionCallPos; diff --git a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp index bc259afaa4..a6d93e85ae 100644 --- a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp +++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp @@ -53,6 +53,7 @@ #include <QtCore/QDir> #include <QtCore/QPluginLoader> #include <QtCore/QStringList> +#include <QtCore/QVector> #include <QtCore/qwaitcondition.h> QT_BEGIN_NAMESPACE @@ -345,40 +346,40 @@ void QQmlDebugServerImpl::parseArguments() QString fileName; QStringList services; - const QStringList lstjsDebugArguments = args.split(QLatin1Char(',')); - QStringList::const_iterator argsItEnd = lstjsDebugArguments.cend(); - QStringList::const_iterator argsIt = lstjsDebugArguments.cbegin(); - for (; argsIt != argsItEnd; ++argsIt) { - const QString strArgument = *argsIt; + const auto lstjsDebugArguments = args.splitRef(QLatin1Char(',')); + for (auto argsIt = lstjsDebugArguments.begin(), argsItEnd = lstjsDebugArguments.end(); argsIt != argsItEnd; ++argsIt) { + const QStringRef &strArgument = *argsIt; if (strArgument.startsWith(QLatin1String("port:"))) { - portFrom = strArgument.midRef(5).toInt(&ok); + portFrom = strArgument.mid(5).toInt(&ok); portTo = portFrom; - QStringList::const_iterator argsNext = argsIt + 1; + const auto argsNext = argsIt + 1; if (argsNext == argsItEnd) break; - const QString nextArgument = *argsNext; - - // Don't use QStringLiteral here. QRegExp has a global cache and will save an implicitly - // shared copy of the passed string. That copy isn't properly detached when the library - // is unloaded if the original string lives in the library's .rodata - if (ok && nextArgument.contains(QRegExp(QLatin1String("^\\s*\\d+\\s*$")))) { - portTo = nextArgument.toInt(&ok); - ++argsIt; + if (ok) { + const QString nextArgument = argsNext->toString(); + + // Don't use QStringLiteral here. QRegExp has a global cache and will save an implicitly + // shared copy of the passed string. That copy isn't properly detached when the library + // is unloaded if the original string lives in the library's .rodata + if (nextArgument.contains(QRegExp(QLatin1String("^\\s*\\d+\\s*$")))) { + portTo = nextArgument.toInt(&ok); + ++argsIt; + } } } else if (strArgument.startsWith(QLatin1String("host:"))) { - hostAddress = strArgument.mid(5); + hostAddress = strArgument.mid(5).toString(); } else if (strArgument == QLatin1String("block")) { block = true; } else if (strArgument.startsWith(QLatin1String("file:"))) { - fileName = strArgument.mid(5); + fileName = strArgument.mid(5).toString(); ok = !fileName.isEmpty(); } else if (strArgument.startsWith(QLatin1String("services:"))) { - services.append(strArgument.mid(9)); + services.append(strArgument.mid(9).toString()); } else if (!services.isEmpty()) { - services.append(strArgument); + services.append(strArgument.toString()); } else { const QString message = tr("QML Debugger: Invalid argument \"%1\" detected." - " Ignoring the same.").arg(strArgument); + " Ignoring the same.").arg(strArgument.toString()); qWarning("%s", qPrintable(message)); } } @@ -423,7 +424,7 @@ void QQmlDebugServerImpl::parseArguments() //: Please preserve the line breaks and formatting << tr("Sends qDebug() and similar messages over the QML debug\n" "\t\t connection. QtCreator uses this for showing debug\n" - "\t\t messages in the JavaScript console.") << '\n' + "\t\t messages in the debugger console.") << '\n' << tr("Other services offered by qmltooling plugins that implement " "QQmlDebugServiceFactory and which can be found in the standard plugin " "paths will also be available and can be specified. If no \"services\" " diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 6b83bdc7b6..df0b1f67b1 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -249,8 +249,8 @@ void Document::collectTypeReferences() void Document::removeScriptPragmas(QString &script) { - const QString pragma(QLatin1String("pragma")); - const QString library(QLatin1String("library")); + const QLatin1String pragma("pragma"); + const QLatin1String library("library"); QQmlJS::Lexer l(0); l.setCode(script, 0); @@ -268,7 +268,7 @@ void Document::removeScriptPragmas(QString &script) if (token != QQmlJSGrammar::T_PRAGMA || l.tokenStartLine() != startLine || - script.mid(l.tokenOffset(), l.tokenLength()) != pragma) + script.midRef(l.tokenOffset(), l.tokenLength()) != pragma) return; token = l.lex(); @@ -277,7 +277,7 @@ void Document::removeScriptPragmas(QString &script) l.tokenStartLine() != startLine) return; - QString pragmaValue = script.mid(l.tokenOffset(), l.tokenLength()); + const QStringRef pragmaValue = script.midRef(l.tokenOffset(), l.tokenLength()); int endOffset = l.tokenLength() + l.tokenOffset(); token = l.lex(); diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index a71793f2b6..da00496cb2 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -179,16 +179,16 @@ bool QQmlTypeCompiler::compile() for (int scriptIndex = 0; scriptIndex < scripts.count(); ++scriptIndex) { const QQmlTypeData::ScriptReference &script = scripts.at(scriptIndex); - QString qualifier = script.qualifier; + QStringRef qualifier(&script.qualifier); QString enclosingNamespace; const int lastDotIndex = qualifier.lastIndexOf(QLatin1Char('.')); if (lastDotIndex != -1) { - enclosingNamespace = qualifier.left(lastDotIndex); + enclosingNamespace = qualifier.left(lastDotIndex).toString(); qualifier = qualifier.mid(lastDotIndex+1); } - compiledData->importCache->add(qualifier, scriptIndex, enclosingNamespace); + compiledData->importCache->add(qualifier.toString(), scriptIndex, enclosingNamespace); QQmlScriptData *scriptData = script.script->scriptData(); scriptData->addref(); compiledData->scripts << scriptData; @@ -624,7 +624,7 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob QString path = compiler->url().path(); int lastSlash = path.lastIndexOf(QLatin1Char('/')); if (lastSlash > -1) { - QString nameBase = path.mid(lastSlash + 1, path.length()-lastSlash-5); + const QStringRef nameBase = path.midRef(lastSlash + 1, path.length() - lastSlash - 5); if (!nameBase.isEmpty() && nameBase.at(0).isUpper()) newClassName = nameBase.toUtf8() + "_QMLTYPE_" + QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1)); @@ -1163,10 +1163,10 @@ struct StaticQtMetaObject : public QObject { return &staticQtMetaObject; } }; -bool QQmlEnumTypeResolver::assignEnumToBinding(QmlIR::Binding *binding, const QString &enumName, int enumValue, bool isQtObject) +bool QQmlEnumTypeResolver::assignEnumToBinding(QmlIR::Binding *binding, const QStringRef &enumName, int enumValue, bool isQtObject) { if (enumName.length() > 0 && enumName[0].isLower() && !isQtObject) { - COMPILE_EXCEPTION(binding, tr("Invalid property assignment: Enum value \"%1\" cannot start with a lowercase letter").arg(enumName)); + COMPILE_EXCEPTION(binding, tr("Invalid property assignment: Enum value \"%1\" cannot start with a lowercase letter").arg(enumName.toString())); } binding->type = QV4::CompiledData::Binding::Type_Number; binding->value.d = (double)enumValue; @@ -1197,7 +1197,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj, QHashedStringRef typeName(string.constData(), dot); const bool isQtObject = (typeName == QLatin1String("Qt")); - QString enumValue = string.mid(dot+1); + const QStringRef enumValue = string.midRef(dot + 1); if (isIntProp) { // Allow enum assignment to ints. diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h index 240f591f91..273ba01a88 100644 --- a/src/qml/compiler/qqmltypecompiler_p.h +++ b/src/qml/compiler/qqmltypecompiler_p.h @@ -196,7 +196,11 @@ public: bool resolveEnumBindings(); private: - bool assignEnumToBinding(QmlIR::Binding *binding, const QString &enumName, int enumValue, bool isQtObject); + bool assignEnumToBinding(QmlIR::Binding *binding, const QStringRef &enumName, int enumValue, bool isQtObject); + bool assignEnumToBinding(QmlIR::Binding *binding, const QString &enumName, int enumValue, bool isQtObject) + { + return assignEnumToBinding(binding, QStringRef(&enumName), enumValue, isQtObject); + } bool tryQualifiedEnumAssignment(const QmlIR::Object *obj, const QQmlPropertyCache *propertyCache, const QQmlPropertyData *prop, QmlIR::Binding *binding); diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 4d0361302e..a63f35152a 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -221,8 +221,8 @@ QString Binding::valueAsString(const Unit *unit) const // This code must match that in the qsTr() implementation const QString &path = unit->stringAt(unit->sourceFileIndex); int lastSlash = path.lastIndexOf(QLatin1Char('/')); - QString context = (lastSlash > -1) ? path.mid(lastSlash + 1, path.length()-lastSlash-5) : - QString(); + QStringRef context = (lastSlash > -1) ? path.midRef(lastSlash + 1, path.length() - lastSlash - 5) + : QStringRef(); QByteArray contextUtf8 = context.toUtf8(); QByteArray comment = unit->stringAt(value.translationData.commentIndex).toUtf8(); QByteArray text = unit->stringAt(stringIndex).toUtf8(); diff --git a/src/qml/debugger/qqmlprofiler.cpp b/src/qml/debugger/qqmlprofiler.cpp index 8d60325a19..629d5cb7b8 100644 --- a/src/qml/debugger/qqmlprofiler.cpp +++ b/src/qml/debugger/qqmlprofiler.cpp @@ -45,7 +45,9 @@ QT_BEGIN_NAMESPACE QQmlProfiler::QQmlProfiler() : featuresEnabled(0) { static int metatype = qRegisterMetaType<QVector<QQmlProfilerData> >(); + static int metatype2 = qRegisterMetaType<QQmlProfiler::LocationHash> (); Q_UNUSED(metatype); + Q_UNUSED(metatype2); m_timer.start(); } @@ -62,8 +64,18 @@ void QQmlProfiler::stopProfiling() void QQmlProfiler::reportData() { - emit dataReady(m_data); - m_data.clear(); + LocationHash resolved; + resolved.reserve(m_locations.size()); + for (auto it = m_locations.constBegin(), end = m_locations.constEnd(); it != end; ++it) + resolved.insert(it.key(), it.value()); + + // This unrefs all the objects. We have to make sure we do this in the GUI thread. Also, it's + // a good idea to release the memory before creating the packets to be sent. + m_locations.clear(); + + QVector<QQmlProfilerData> data; + data.swap(m_data); + emit dataReady(data, resolved); } QT_END_NAMESPACE diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h index 24001159f3..1380599fb7 100644 --- a/src/qml/debugger/qqmlprofiler_p.h +++ b/src/qml/debugger/qqmlprofiler_p.h @@ -54,6 +54,8 @@ #include <private/qv4function_p.h> #include <private/qqmlboundsignal_p.h> #include <private/qfinitestack_p.h> +#include <private/qqmlbinding_p.h> +#include <private/qqmlcompiler_p.h> #include "qqmlprofilerdefinitions_p.h" #include "qqmlabstractprofileradapter_p.h" @@ -77,40 +79,18 @@ QT_BEGIN_NAMESPACE // independently when converting to QByteArrays. Thus you can only pack // messages if their data doesn't overlap. It's up to you to figure that // out. -struct Q_AUTOTEST_EXPORT QQmlProfilerData +struct Q_AUTOTEST_EXPORT QQmlProfilerData : public QQmlProfilerDefinitions { - QQmlProfilerData() {} - - QQmlProfilerData(qint64 time, int messageType, int detailType, const QUrl &url, - int x = 0, int y = 0) : - time(time), messageType(messageType), detailType(detailType), detailUrl(url), - x(x), y(y) {} - - QQmlProfilerData(qint64 time, int messageType, int detailType, const QString &str, - int x = 0, int y = 0) : - time(time), messageType(messageType), detailType(detailType),detailString(str), - x(x), y(y) {} - - QQmlProfilerData(qint64 time, int messageType, int detailType, const QString &str, - const QUrl &url, int x = 0, int y = 0) : - time(time), messageType(messageType), detailType(detailType), detailString(str), - detailUrl(url), x(x), y(y) {} - - - QQmlProfilerData(qint64 time, int messageType, int detailType) : - time(time), messageType(messageType), detailType(detailType) {} - + QQmlProfilerData(qint64 time = -1, int messageType = -1, + RangeType detailType = MaximumRangeType, quintptr locationId = 0) : + time(time), locationId(locationId), messageType(messageType), detailType(detailType) + {} qint64 time; - int messageType; //bit field of QQmlProfilerService::Message - int detailType; + quintptr locationId; - // RangeData prefers detailString; RangeLocation prefers detailUrl. - QString detailString; //used by RangeData and possibly by RangeLocation - QUrl detailUrl; //used by RangeLocation and possibly by RangeData - - int x; //used by RangeLocation - int y; //used by RangeLocation + int messageType; //bit field of QQmlProfilerService::Message + RangeType detailType; }; Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE); @@ -118,58 +98,166 @@ Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE); class QQmlProfiler : public QObject, public QQmlProfilerDefinitions { Q_OBJECT public: - void startBinding(const QQmlSourceLocation &location) + + class BindingRefCount : public QQmlRefCount { + public: + BindingRefCount(QQmlBinding *binding): + m_binding(binding) + { + m_binding->ref.ref(); + } + + BindingRefCount(const BindingRefCount &other) : + QQmlRefCount(other), m_binding(other.m_binding) + { + m_binding->ref.ref(); + } + + BindingRefCount &operator=(const BindingRefCount &other) + { + if (this != &other) { + QQmlRefCount::operator=(other); + other.m_binding->ref.ref(); + if (!m_binding->ref.deref()) + delete m_binding; + m_binding = other.m_binding; + } + return *this; + } + + ~BindingRefCount() + { + if (!m_binding->ref.deref()) + delete m_binding; + } + + private: + QQmlBinding *m_binding; + }; + + struct Location { + Location(const QQmlSourceLocation &location = QQmlSourceLocation(), + const QUrl &url = QUrl()) : + location(location), url(url) {} + QQmlSourceLocation location; + QUrl url; + }; + + // Unfortunately we have to resolve the locations right away because the QML context might not + // be available anymore when we send the data. + struct RefLocation : public Location { + RefLocation() : Location(), locationType(MaximumRangeType), ref(nullptr) + {} + + RefLocation(QQmlBinding *binding, QV4::FunctionObject *function) : + Location(function->sourceLocation()), locationType(Binding), + ref(new BindingRefCount(binding), QQmlRefPointer<QQmlRefCount>::Adopt) + {} + + RefLocation(QQmlCompiledData *ref, const QUrl &url, const QV4::CompiledData::Object *obj, + const QString &type) : + Location(QQmlSourceLocation(type, obj->location.line, obj->location.column), url), + locationType(Creating), ref(ref) + {} + + RefLocation(QQmlBoundSignalExpression *ref) : + Location(ref->sourceLocation()), locationType(HandlingSignal), ref(ref) + {} + + RefLocation(QQmlDataBlob *ref) : + Location(QQmlSourceLocation(), ref->url()), locationType(Compiling), ref(ref) + {} + + bool isValid() const + { + return locationType != MaximumRangeType; + } + + RangeType locationType; + QQmlRefPointer<QQmlRefCount> ref; + }; + + typedef QHash<quintptr, Location> LocationHash; + + void startBinding(QQmlBinding *binding, QV4::FunctionObject *function) { + quintptr locationId(id(binding)); m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), - (1 << RangeStart | 1 << RangeLocation), 1 << Binding, - location.sourceFile, qmlSourceCoordinate(location.line), qmlSourceCoordinate(location.column))); + (1 << RangeStart | 1 << RangeLocation), Binding, + locationId)); + + RefLocation &location = m_locations[locationId]; + if (!location.isValid()) + location = RefLocation(binding, function); } // Have toByteArrays() construct another RangeData event from the same QString later. // This is somewhat pointless but important for backwards compatibility. - void startCompiling(const QUrl &url) + void startCompiling(QQmlDataBlob *blob) { + quintptr locationId(id(blob)); m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), (1 << RangeStart | 1 << RangeLocation | 1 << RangeData), - 1 << Compiling, url, 1, 1)); + Compiling, locationId)); + + RefLocation &location = m_locations[locationId]; + if (!location.isValid()) + location = RefLocation(blob); } - void startHandlingSignal(const QQmlSourceLocation &location) + void startHandlingSignal(QQmlBoundSignalExpression *expression) { + quintptr locationId(id(expression)); m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), - (1 << RangeStart | 1 << RangeLocation), 1 << HandlingSignal, - location.sourceFile, location.line, location.column)); + (1 << RangeStart | 1 << RangeLocation), HandlingSignal, + locationId)); + + RefLocation &location = m_locations[locationId]; + if (!location.isValid()) + location = RefLocation(expression); } void startCreating() { - m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeStart, 1 << Creating)); + m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeStart, Creating)); } - void startCreating(const QString &typeName, const QUrl &fileName, int line, int column) + void startCreating(const QV4::CompiledData::Object *obj) { m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), (1 << RangeStart | 1 << RangeLocation | 1 << RangeData), - 1 << Creating, typeName, fileName, line, column)); + Creating, id(obj))); } - void updateCreating(const QString &typeName, const QUrl &fileName, int line, int column) + void updateCreating(const QV4::CompiledData::Object *obj, QQmlCompiledData *ref, + const QUrl &url, const QString &type) { + quintptr locationId(id(obj)); m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), (1 << RangeLocation | 1 << RangeData), - 1 << Creating, typeName, fileName, line, column)); + Creating, locationId)); + + RefLocation &location = m_locations[locationId]; + if (!location.isValid()) + location = RefLocation(ref, url, obj, type); } template<RangeType Range> void endRange() { - m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeEnd, 1 << Range)); + m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeEnd, Range)); } QQmlProfiler(); quint64 featuresEnabled; + template<typename Object> + static quintptr id(const Object *pointer) + { + return reinterpret_cast<quintptr>(pointer); + } + public slots: void startProfiling(quint64 features); void stopProfiling(); @@ -177,10 +265,11 @@ public slots: void setTimer(const QElapsedTimer &timer) { m_timer = timer; } signals: - void dataReady(const QVector<QQmlProfilerData> &); + void dataReady(const QVector<QQmlProfilerData> &, const QQmlProfiler::LocationHash &); protected: QElapsedTimer m_timer; + QHash<quintptr, RefLocation> m_locations; QVector<QQmlProfilerData> m_data; }; @@ -194,11 +283,12 @@ struct QQmlProfilerHelper : public QQmlProfilerDefinitions { }; struct QQmlBindingProfiler : public QQmlProfilerHelper { - QQmlBindingProfiler(QQmlProfiler *profiler, const QV4::FunctionObject *function) : + QQmlBindingProfiler(QQmlProfiler *profiler, QQmlBinding *binding, + QV4::FunctionObject *function) : QQmlProfilerHelper(profiler) { Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileBinding, profiler, - startBinding(function->sourceLocation())); + startBinding(binding, function)); } ~QQmlBindingProfiler() @@ -213,7 +303,7 @@ struct QQmlHandlingSignalProfiler : public QQmlProfilerHelper { QQmlProfilerHelper(profiler) { Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileHandlingSignal, profiler, - startHandlingSignal(expression->sourceLocation())); + startHandlingSignal(expression)); } ~QQmlHandlingSignalProfiler() @@ -224,10 +314,10 @@ struct QQmlHandlingSignalProfiler : public QQmlProfilerHelper { }; struct QQmlCompilingProfiler : public QQmlProfilerHelper { - QQmlCompilingProfiler(QQmlProfiler *profiler, const QUrl &url) : + QQmlCompilingProfiler(QQmlProfiler *profiler, QQmlDataBlob *blob) : QQmlProfilerHelper(profiler) { - Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCompiling, profiler, startCompiling(url)); + Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCompiling, profiler, startCompiling(blob)); } ~QQmlCompilingProfiler() @@ -239,14 +329,6 @@ struct QQmlCompilingProfiler : public QQmlProfilerHelper { struct QQmlVmeProfiler : public QQmlProfilerDefinitions { public: - struct Data { - Data() : m_line(0), m_column(0) {} - QUrl m_url; - int m_line; - int m_column; - QString m_typeName; - }; - QQmlVmeProfiler() : profiler(0) {} void init(QQmlProfiler *p, int maxDepth) @@ -255,30 +337,30 @@ public: ranges.allocate(maxDepth); } - Data pop() + const QV4::CompiledData::Object *pop() { if (ranges.count() > 0) return ranges.pop(); else - return Data(); + return nullptr; } - void push(const Data &data) + void push(const QV4::CompiledData::Object *object) { if (ranges.capacity() > ranges.count()) - ranges.push(data); + ranges.push(object); } QQmlProfiler *profiler; private: - QFiniteStack<Data> ranges; + QFiniteStack<const QV4::CompiledData::Object *> ranges; }; #define Q_QML_OC_PROFILE(member, Code)\ Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, member.profiler, Code) -class QQmlObjectCreationProfiler : public QQmlVmeProfiler::Data { +class QQmlObjectCreationProfiler { public: QQmlObjectCreationProfiler(QQmlProfiler *profiler) : profiler(profiler) @@ -291,13 +373,10 @@ public: Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler, endRange<QQmlProfilerDefinitions::Creating>()); } - void update(const QString &typeName, const QUrl &url, int line, int column) + void update(QQmlCompiledData *ref, const QV4::CompiledData::Object *obj, + const QString &typeName, const QUrl &url) { - profiler->updateCreating(typeName, url, line, column); - m_typeName = typeName; - m_url = url; - m_line = line; - m_column = column; + profiler->updateCreating(obj, ref, url, typeName); } private: @@ -310,8 +389,7 @@ public: profiler(parent->profiler) { Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, profiler, { - QQmlVmeProfiler::Data data = parent->pop(); - profiler->startCreating(data.m_typeName, data.m_url, data.m_line, data.m_column); + profiler->startCreating(parent->pop()); }); } @@ -326,5 +404,6 @@ private: QT_END_NAMESPACE Q_DECLARE_METATYPE(QVector<QQmlProfilerData>) +Q_DECLARE_METATYPE(QQmlProfiler::LocationHash) #endif // QQMLPROFILER_P_H diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc index e153ca3d8b..0d875bd10f 100644 --- a/src/qml/doc/src/cppintegration/data.qdoc +++ b/src/qml/doc/src/cppintegration/data.qdoc @@ -112,7 +112,7 @@ when passed from C++ to QML and vice-versa: \li QVector2D, QVector3D, QVector4D \li \l vector2d, \l vector3d, \l vector4d \row - \li Enums declared with Q_ENUMS() + \li Enums declared with Q_ENUM() or Q_ENUMS() \li \l enumeration \endtable @@ -261,6 +261,9 @@ In particular, QML currently supports: \li \c {QList<bool>} \li \c {QList<QString>} and \c{QStringList} \li \c {QList<QUrl>} + \li \c {QVector<int>} + \li \c {QVector<qreal>} + \li \c {QVector<bool>} \endlist These sequence types are implemented directly in terms of the underlying C++ @@ -303,6 +306,9 @@ The default-constructed values for each sequence type are as follows: \row \li QList<bool> \li boolean value \c {false} \row \li QList<QString> and QStringList \li empty QString \row \li QList<QUrl> \li empty QUrl +\row \li QVector<int> \li integer value 0 +\row \li QVector<qreal> \li real value 0.0 +\row \li QVector<bool> \li boolean value \c {false} \endtable If you wish to remove elements from a sequence rather than simply replace @@ -341,7 +347,7 @@ properties: \section1 Enumeration Types To use a custom enumeration as a data type, its class must be registered and -the enumeration must also be declared with Q_ENUMS() to register it with Qt's +the enumeration must also be declared with Q_ENUM() to register it with Qt's meta object system. For example, the \c Message class below has a \c Status enum: @@ -349,7 +355,6 @@ enum: class Message : public QObject { Q_OBJECT - Q_ENUMS(Status) Q_PROPERTY(Status status READ status NOTIFY statusChanged) public: enum Status { @@ -357,6 +362,7 @@ enum: Loading, Error }; + Q_ENUM(Status) Status status() const; signals: void statusChanged(); diff --git a/src/qml/doc/src/cppintegration/extending-tutorial.qdoc b/src/qml/doc/src/cppintegration/extending-tutorial.qdoc index d862b50fcb..c0cfc3e1aa 100644 --- a/src/qml/doc/src/cppintegration/extending-tutorial.qdoc +++ b/src/qml/doc/src/cppintegration/extending-tutorial.qdoc @@ -386,12 +386,26 @@ directory. \quotefile tutorials/extending-qml/chapter6-plugins/import/import.pro -In this example, the \c Charts directory is located at the same level as the application -that uses our new import module. This way, the QML engine will find our module -as the default search path for QML imports includes the directory of the application -executable. Alternatively, we could control what directories the \l {QML Import Path} -{QML import path} contains, useful if there are multiple QML applications using the -same QML imports. +When building this example on Windows or Linux, the \c Charts directory will be +located at the same level as the application that uses our new import module. +This way, the QML engine will find our module as the default search path for QML +imports includes the directory of the application executable. On OS X, the +plugin binary is copied to \c Contents/PlugIns in the the application bundle; +this path is set in \l {tutorials/extending-qml/chapter6-plugins/app.pro} +{chapter6-plugins/app.pro}: + +\quotefromfile tutorials/extending-qml/chapter6-plugins/app.pro +\skipto osx +\printuntil } + +To account for this, we also need to add this location as a +\l {QML Import Path}{QML import path} in \c main.cpp: + +\snippet tutorials/extending-qml/chapter6-plugins/main.cpp 0 +\dots + +Defining custom import paths is useful also when there are multiple +applications using the same QML imports. The \c .pro file also contains additional magic to ensure that the \l {Module Definition qmldir Files}{module definition qmldir file} is always copied diff --git a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc index 04d769e4dc..04d0d0ed2e 100644 --- a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc +++ b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc @@ -508,7 +508,7 @@ built-in \l {Rectangle::color} property: Any object that use this type and refer to its \c color property will be referring to the alias rather than the ordinary \l {Rectangle::color} property. -Internally, however, the red can correctly set its \c color +Internally, however, the rectangle can correctly set its \c color property and refer to the actual defined property rather than the alias. diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp index 424d5548a1..257dd357fd 100644 --- a/src/qml/jsapi/qjsengine.cpp +++ b/src/qml/jsapi/qjsengine.cpp @@ -247,6 +247,11 @@ Q_DECLARE_METATYPE(QList<int>) QT_BEGIN_NAMESPACE +static void checkForApplicationInstance() +{ + if (!QCoreApplication::instance()) + qFatal("QJSEngine: Must construct a QCoreApplication before a QJSEngine"); +} /*! Constructs a QJSEngine object. @@ -270,6 +275,8 @@ QJSEngine::QJSEngine(QObject *parent) : QObject(*new QJSEnginePrivate, parent) , d(new QV8Engine(this)) { + checkForApplicationInstance(); + QJSEnginePrivate::addToDebugServer(this); } @@ -280,6 +287,7 @@ QJSEngine::QJSEngine(QJSEnginePrivate &dd, QObject *parent) : QObject(dd, parent) , d(new QV8Engine(this)) { + checkForApplicationInstance(); } /*! diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index 73aa7047b8..4c4639c94f 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -287,7 +287,13 @@ void SimpleArrayData::push_front(Object *o, const Value *values, uint n) Q_ASSERT(o->d()->arrayData->type == Heap::ArrayData::Simple); dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); } - dd->offset = (dd->offset - n) % dd->alloc; + if (n <= dd->offset) { + dd->offset -= n; // there is enough space left in front + } else { + // we need to wrap around, so: + dd->offset = dd->alloc - // start at the back, but subtract: + (n - dd->offset); // the number of items we can put in the free space at the start of the allocated array + } dd->len += n; for (uint i = 0; i < n; ++i) dd->data(i) = values[i].asReturnedValue(); diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index 5783e8fa2b..0cd72d6811 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -338,7 +338,7 @@ static inline double currentTime() static inline double TimeClip(double t) { - if (! qIsFinite(t) || fabs(t) > 8.64e15) + if (! qt_is_finite(t) || fabs(t) > 8.64e15) return qt_qnan(); return Primitive::toInteger(t); } diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp index c0a4129d9d..a59190b846 100644 --- a/src/qml/jsruntime/qv4profiling.cpp +++ b/src/qml/jsruntime/qv4profiling.cpp @@ -46,26 +46,35 @@ QT_BEGIN_NAMESPACE namespace QV4 { namespace Profiling { -FunctionCallProperties FunctionCall::resolve() const +FunctionLocation FunctionCall::resolveLocation() const { - FunctionCallProperties props = { - m_start, - m_end, + FunctionLocation location = { m_function->name()->toQString(), m_function->compilationUnit->fileName(), m_function->compiledFunction->location.line, m_function->compiledFunction->location.column }; - return props; + return location; } +FunctionCallProperties FunctionCall::properties() const +{ + FunctionCallProperties props = { + m_start, + m_end, + reinterpret_cast<quintptr>(m_function) + }; + return props; +} Profiler::Profiler(QV4::ExecutionEngine *engine) : featuresEnabled(0), m_engine(engine) { - static int meta = qRegisterMetaType<QVector<QV4::Profiling::FunctionCallProperties> >(); - static int meta2 = qRegisterMetaType<QVector<QV4::Profiling::MemoryAllocationProperties> >(); - Q_UNUSED(meta); - Q_UNUSED(meta2); + static const int metatypes[] = { + qRegisterMetaType<QVector<QV4::Profiling::FunctionCallProperties> >(), + qRegisterMetaType<QVector<QV4::Profiling::MemoryAllocationProperties> >(), + qRegisterMetaType<FunctionLocationHash>() + }; + Q_UNUSED(metatypes); m_timer.start(); } @@ -85,13 +94,16 @@ bool operator<(const FunctionCall &call1, const FunctionCall &call2) void Profiler::reportData() { std::sort(m_data.begin(), m_data.end()); - QVector<FunctionCallProperties> resolved; - resolved.reserve(m_data.size()); + QVector<FunctionCallProperties> properties; + QHash<qint64, FunctionLocation> locations; + properties.reserve(m_data.size()); - foreach (const FunctionCall &call, m_data) - resolved.append(call.resolve()); + foreach (const FunctionCall &call, m_data) { + properties.append(call.properties()); + locations[properties.constLast().id] = call.resolveLocation(); + } - emit dataReady(resolved, m_memory_data); + emit dataReady(locations, properties, m_memory_data); m_data.clear(); m_memory_data.clear(); } diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h index 25ef8223bf..0b4193204f 100644 --- a/src/qml/jsruntime/qv4profiling_p.h +++ b/src/qml/jsruntime/qv4profiling_p.h @@ -77,12 +77,18 @@ enum MemoryType { struct FunctionCallProperties { qint64 start; qint64 end; + quintptr id; +}; + +struct FunctionLocation { QString name; QString file; int line; int column; }; +typedef QHash<qint64, QV4::Profiling::FunctionLocation> FunctionLocationHash; + struct MemoryAllocationProperties { qint64 timestamp; qint64 size; @@ -118,7 +124,8 @@ public: return *this; } - FunctionCallProperties resolve() const; + FunctionLocation resolveLocation() const; + FunctionCallProperties properties() const; private: friend bool operator<(const FunctionCall &call1, const FunctionCall &call2); @@ -173,7 +180,8 @@ public slots: void setTimer(const QElapsedTimer &timer) { m_timer = timer; } signals: - void dataReady(const QVector<QV4::Profiling::FunctionCallProperties> &, + void dataReady(const QV4::Profiling::FunctionLocationHash &, + const QVector<QV4::Profiling::FunctionCallProperties> &, const QVector<QV4::Profiling::MemoryAllocationProperties> &); private: @@ -218,8 +226,10 @@ public: Q_DECLARE_TYPEINFO(QV4::Profiling::MemoryAllocationProperties, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCallProperties, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCall, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionLocation, Q_MOVABLE_TYPE); QT_END_NAMESPACE +Q_DECLARE_METATYPE(QV4::Profiling::FunctionLocationHash) Q_DECLARE_METATYPE(QVector<QV4::Profiling::FunctionCallProperties>) Q_DECLARE_METATYPE(QVector<QV4::Profiling::MemoryAllocationProperties>) diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index df58ab5060..35fcd00eb7 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -1285,6 +1285,8 @@ static int MatchScore(const QV4::Value &actual, int conversionType) return 10; } else if (conversionType == QMetaType::QJsonObject) { return 5; + } else if (conversionType == qMetaTypeId<QJSValue>()) { + return 0; } else { return 10; } diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index dfac2d9bd9..b7543692d5 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -984,10 +984,9 @@ ReturnedValue Runtime::method_callQmlScopeObjectProperty(ExecutionEngine *engine Scope scope(engine); ScopedFunctionObject o(scope, method_getQmlScopeObjectProperty(engine, callData->thisObject, propertyIndex)); if (!o) { - QString error = QStringLiteral("Property '%1' of object %2 is not a function").arg(propertyIndex).arg(callData->thisObject.toQStringNoThrow()); + QString error = QStringLiteral("Property '%1' of scope object is not a function").arg(propertyIndex); return engine->throwTypeError(error); } - return o->call(callData); } @@ -996,7 +995,7 @@ ReturnedValue Runtime::method_callQmlContextObjectProperty(ExecutionEngine *engi Scope scope(engine); ScopedFunctionObject o(scope, method_getQmlContextObjectProperty(engine, callData->thisObject, propertyIndex)); if (!o) { - QString error = QStringLiteral("Property '%1' of object %2 is not a function").arg(propertyIndex).arg(callData->thisObject.toQStringNoThrow()); + QString error = QStringLiteral("Property '%1' of context object is not a function").arg(propertyIndex); return engine->throwTypeError(error); } diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index b97310c5b9..fa2409a85c 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -75,6 +75,9 @@ static void generateWarning(QV4::ExecutionEngine *v4, const QString& description // F(elementType, elementTypeName, sequenceType, defaultValue) #define FOREACH_QML_SEQUENCE_TYPE(F) \ + F(int, IntVector, QVector<int>, 0) \ + F(qreal, RealVector, QVector<qreal>, 0.0) \ + F(bool, BoolVector, QVector<bool>, false) \ F(int, Int, QList<int>, 0) \ F(qreal, Real, QList<qreal>, 0.0) \ F(bool, Bool, QList<bool>, false) \ @@ -578,6 +581,15 @@ Heap::QQmlSequence<Container>::QQmlSequence(QObject *object, int propertyIndex) namespace QV4 { +typedef QQmlSequence<QVector<int> > QQmlIntVectorList; +template<> +DEFINE_OBJECT_VTABLE(QQmlIntVectorList); +typedef QQmlSequence<QVector<qreal> > QQmlRealVectorList; +template<> +DEFINE_OBJECT_VTABLE(QQmlRealVectorList); +typedef QQmlSequence<QVector<bool> > QQmlBoolVectorList; +template<> +DEFINE_OBJECT_VTABLE(QQmlBoolVectorList); typedef QQmlSequence<QStringList> QQmlQStringList; template<> DEFINE_OBJECT_VTABLE(QQmlQStringList); diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index e8ddfecbe3..1249e1b6c8 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -168,7 +168,7 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags) return; } - QQmlBindingProfiler prof(ep->profiler, f); + QQmlBindingProfiler prof(ep->profiler, this, f); setUpdatingFlag(true); QQmlJavaScriptExpression::DeleteWatcher watcher(this); diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h index 440840d3c9..18bee387dd 100644 --- a/src/qml/qml/qqmlengine_p.h +++ b/src/qml/qml/qqmlengine_p.h @@ -293,7 +293,7 @@ inline void QQmlEnginePrivate::dereferenceScarceResources() // if the refcount is zero, then evaluation of the "top level" // expression must have completed. We can safely release the // scarce resources. - if (scarceResourcesRefCount == 0) { + if (Q_LIKELY(scarceResourcesRefCount == 0)) { QV4::ExecutionEngine *engine = QV8Engine::getV4(v8engine()); if (Q_UNLIKELY(!engine->scarceResources.isEmpty())) { cleanupScarceResources(); diff --git a/src/qml/qml/qqmlerror.cpp b/src/qml/qml/qqmlerror.cpp index 47c85c907c..74ceeabeb4 100644 --- a/src/qml/qml/qqmlerror.cpp +++ b/src/qml/qml/qqmlerror.cpp @@ -43,6 +43,7 @@ #include <QtCore/qdebug.h> #include <QtCore/qfile.h> #include <QtCore/qstringlist.h> +#include <QtCore/qvector.h> #include <private/qv4errorobject_p.h> @@ -288,11 +289,11 @@ QDebug operator<<(QDebug debug, const QQmlError &error) stream.setCodec("UTF-8"); #endif const QString code = stream.readAll(); - const QStringList lines = code.split(QLatin1Char('\n')); + const auto lines = code.splitRef(QLatin1Char('\n')); if (lines.count() >= error.line()) { - const QString &line = lines.at(error.line() - 1); - debug << "\n " << qPrintable(line); + const QStringRef &line = lines.at(error.line() - 1); + debug << "\n " << line.toLocal8Bit().constData(); if(error.column() > 0) { int column = qMax(0, error.column() - 1); diff --git a/src/qml/qml/qqmlextensioninterface.h b/src/qml/qml/qqmlextensioninterface.h index 73e41a3b80..ef56d5e312 100644 --- a/src/qml/qml/qqmlextensioninterface.h +++ b/src/qml/qml/qqmlextensioninterface.h @@ -66,7 +66,7 @@ public: Q_DECLARE_INTERFACE(QQmlTypesExtensionInterface, "org.qt-project.Qt.QQmlTypesExtensionInterface/1.0") -#define QQmlExtensionInterface_iid "org.qt-project.Qt.QQmlExtensionInterface" +#define QQmlExtensionInterface_iid "org.qt-project.Qt.QQmlExtensionInterface/1.0" Q_DECLARE_INTERFACE(QQmlExtensionInterface, QQmlExtensionInterface_iid) diff --git a/src/qml/qml/qqmlfile.cpp b/src/qml/qml/qqmlfile.cpp index 7a441dd9ff..4769402855 100644 --- a/src/qml/qml/qqmlfile.cpp +++ b/src/qml/qml/qqmlfile.cpp @@ -605,7 +605,7 @@ QString QQmlFile::urlToLocalFileOrQrc(const QString& url) { if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) { if (url.length() > 4) - return QLatin1Char(':') + url.mid(4); + return QLatin1Char(':') + url.midRef(4); return QString(); } diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 5ce3942be2..69adce3da2 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -85,12 +85,11 @@ QString resolveLocalUrl(const QString &url, const QString &relative) } else if (relative.at(0) == Slash || !url.contains(Slash)) { return relative; } else { - QString base(url.left(url.lastIndexOf(Slash) + 1)); - + const QStringRef baseRef = url.leftRef(url.lastIndexOf(Slash) + 1); if (relative == QLatin1String(".")) - return base; + return baseRef.toString(); - base.append(relative); + QString base = baseRef + relative; // Remove any relative directory elements in the path int length = base.length(); @@ -483,20 +482,58 @@ QList<QQmlImports::ScriptReference> QQmlImports::resolvedScripts() const return scripts; } +static QString joinStringRefs(const QVector<QStringRef> &refs, const QChar &sep) +{ + QString str; + for (auto it = refs.cbegin(); it != refs.cend(); ++it) { + if (it != refs.cbegin()) + str += sep; + str += *it; + } + return str; +} + /*! - Form a complete path to a qmldir file, from a base URL, a module URI and version specification. + Forms complete paths to a qmldir file, from a base URL, a module URI and version specification. + + For example, QtQml.Models 2.0: + - base/QtQml/Models.2.0/qmldir + - base/QtQml.2.0/Models/qmldir + - base/QtQml/Models.2/qmldir + - base/QtQml.2/Models/qmldir + - base/QtQml/Models/qmldir */ -QString QQmlImports::completeQmldirPath(const QString &uri, const QString &base, int vmaj, int vmin, - ImportVersion version) +QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringList &basePaths, int vmaj, int vmin) { - QString url = uri; - url.replace(Dot, Slash); + const QVector<QStringRef> parts = uri.splitRef(Dot, QString::SkipEmptyParts); + + QStringList qmlDirPathsPaths; + // fully & partially versioned parts + 1 unversioned for each base path + qmlDirPathsPaths.reserve(basePaths.count() * (2 * parts.count() + 1)); + + for (int version = FullyVersioned; version <= Unversioned; ++version) { + const QString ver = versionString(vmaj, vmin, static_cast<QQmlImports::ImportVersion>(version)); + + for (const QString &path : basePaths) { + QString dir = path; + if (!dir.endsWith(Slash) && !dir.endsWith(Backslash)) + dir += Slash; + + // append to the end + qmlDirPathsPaths += dir + joinStringRefs(parts, Slash) + ver + Slash_qmldir; - QString dir = base; - if (!dir.endsWith(Slash) && !dir.endsWith(Backslash)) - dir += Slash; + if (version != Unversioned) { + // insert in the middle + for (int index = parts.count() - 2; index >= 0; --index) { + qmlDirPathsPaths += dir + joinStringRefs(parts.mid(0, index + 1), Slash) + + ver + Slash + + joinStringRefs(parts.mid(index + 1), Slash) + Slash_qmldir; + } + } + } + } - return dir + url + versionString(vmaj, vmin, version) + Slash_qmldir; + return qmlDirPathsPaths; } QString QQmlImports::versionString(int vmaj, int vmin, ImportVersion version) @@ -777,11 +814,11 @@ bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedS QString u1 = import->url; QString u2 = import2->url; if (base) { - QString b = *base; + QStringRef b(base); int dot = b.lastIndexOf(Dot); if (dot >= 0) { b = b.left(dot+1); - QString l = b.left(dot); + QStringRef l = b.left(dot); if (u1.startsWith(b)) u1 = u1.mid(b.count()); else if (u1 == l) @@ -857,7 +894,7 @@ bool QQmlImportsPrivate::populatePluginPairVector(QVector<StaticPluginPair> &res // the list the first time called to only contain QML plugins: foreach (const QStaticPlugin &plugin, QPluginLoader::staticPlugins()) { if (qobject_cast<QQmlExtensionPlugin *>(plugin.instance())) - plugins.append(plugin); + plugins.append(plugin); } } @@ -1130,32 +1167,29 @@ bool QQmlImportsPrivate::locateQmldir(const QString &uri, int vmaj, int vmin, QQ QStringList localImportPaths = database->importPathList(QQmlImportDatabase::Local); // Search local import paths for a matching version - for (int version = QQmlImports::FullyVersioned; version <= QQmlImports::Unversioned; ++version) { - foreach (const QString &path, localImportPaths) { - QString qmldirPath = QQmlImports::completeQmldirPath(uri, path, vmaj, vmin, static_cast<QQmlImports::ImportVersion>(version)); - - QString absoluteFilePath = typeLoader.absoluteFilePath(qmldirPath); - if (!absoluteFilePath.isEmpty()) { - QString url; - QString absolutePath = absoluteFilePath.left(absoluteFilePath.lastIndexOf(Slash)+1); - if (absolutePath.at(0) == Colon) - url = QLatin1String("qrc://") + absolutePath.mid(1); - else - url = QUrl::fromLocalFile(absolutePath).toString(); + const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(uri, localImportPaths, vmaj, vmin); + for (const QString &qmldirPath : qmlDirPaths) { + QString absoluteFilePath = typeLoader.absoluteFilePath(qmldirPath); + if (!absoluteFilePath.isEmpty()) { + QString url; + const QStringRef absolutePath = absoluteFilePath.leftRef(absoluteFilePath.lastIndexOf(Slash) + 1); + if (absolutePath.at(0) == Colon) + url = QLatin1String("qrc://") + absolutePath.mid(1); + else + url = QUrl::fromLocalFile(absolutePath.toString()).toString(); - QQmlImportDatabase::QmldirCache *cache = new QQmlImportDatabase::QmldirCache; - cache->versionMajor = vmaj; - cache->versionMinor = vmin; - cache->qmldirFilePath = absoluteFilePath; - cache->qmldirPathUrl = url; - cache->next = cacheHead; - database->qmldirCache.insert(uri, cache); + QQmlImportDatabase::QmldirCache *cache = new QQmlImportDatabase::QmldirCache; + cache->versionMajor = vmaj; + cache->versionMinor = vmin; + cache->qmldirFilePath = absoluteFilePath; + cache->qmldirPathUrl = url; + cache->next = cacheHead; + database->qmldirCache.insert(uri, cache); - *outQmldirFilePath = absoluteFilePath; - *outQmldirPathUrl = url; + *outQmldirFilePath = absoluteFilePath; + *outQmldirPathUrl = url; - return true; - } + return true; } } diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h index 628564ae34..0e7848730f 100644 --- a/src/qml/qml/qqmlimport_p.h +++ b/src/qml/qml/qqmlimport_p.h @@ -130,8 +130,7 @@ public: QList<CompositeSingletonReference> resolvedCompositeSingletons() const; - static QString completeQmldirPath(const QString &uri, const QString &base, int vmaj, int vmin, - QQmlImports::ImportVersion version); + static QStringList completeQmldirPaths(const QString &uri, const QStringList &basePaths, int vmaj, int vmin); static QString versionString(int vmaj, int vmin, ImportVersion version); static bool isLocal(const QString &url); diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 29fff04325..cfe1c86eba 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -1037,8 +1037,8 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo if (compiledData->isComponent(index)) { isComponent = true; QQmlComponent *component = new QQmlComponent(engine, compiledData, index, parent); - Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(QStringLiteral("<component>"), - context->url(), obj->location.line, obj->location.column)); + Q_QML_OC_PROFILE(sharedState->profiler, profiler.update( + compiledData, obj, QStringLiteral("<component>"), context->url())); QQmlComponentPrivate::get(component)->creationContext = context; instance = component; ddata = QQmlData::get(instance, /*create*/true); @@ -1048,8 +1048,8 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo installPropertyCache = !typeRef->isFullyDynamicType; QQmlType *type = typeRef->type; if (type) { - Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(type->qmlTypeName(), - context->url(), obj->location.line, obj->location.column)); + Q_QML_OC_PROFILE(sharedState->profiler, profiler.update( + compiledData, obj, type->qmlTypeName(), context->url())); instance = type->create(); if (!instance) { recordError(obj->location, tr("Unable to create object of type %1").arg(stringAt(obj->inheritedTypeNameIndex))); @@ -1071,8 +1071,9 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo sharedState->allCreatedObjects.push(instance); } else { Q_ASSERT(typeRef->component); - Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(typeRef->component->fileName(), - context->url(), obj->location.line, obj->location.column)); + Q_QML_OC_PROFILE(sharedState->profiler, profiler.update( + compiledData, obj, typeRef->component->fileName(), + context->url())); if (typeRef->component->compilationUnit->data->isSingleton()) { recordError(obj->location, tr("Composite Singleton Type %1 is not creatable").arg(stringAt(obj->inheritedTypeNameIndex))); @@ -1115,7 +1116,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo parserStatus->classBegin(); // push() the profiler state here, together with the parserStatus, as we'll pop() them // together, too. - Q_QML_OC_PROFILE(sharedState->profiler, sharedState->profiler.push(profiler)); + Q_QML_OC_PROFILE(sharedState->profiler, sharedState->profiler.push(obj)); sharedState->allParserStatusCallbacks.push(parserStatus); parserStatus->d = &sharedState->allParserStatusCallbacks.top(); } diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index 22de5e1ae9..df2ff05de1 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -58,6 +58,7 @@ #include <private/qv4functionobject_p.h> #include <QStringList> +#include <QVector> #include <private/qmetaobject_p.h> #include <private/qqmlvaluetypewrapper_p.h> #include <QtCore/qdebug.h> @@ -240,14 +241,14 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name) QQmlTypeNameCache *typeNameCache = context?context->imports:0; - QStringList path = name.split(QLatin1Char('.')); + const auto path = name.splitRef(QLatin1Char('.')); if (path.isEmpty()) return; QObject *currentObject = obj; // Everything up to the last property must be an "object type" property for (int ii = 0; ii < path.count() - 1; ++ii) { - const QString &pathName = path.at(ii); + const QStringRef &pathName = path.at(ii); if (typeNameCache) { QQmlTypeNameCache::Result r = typeNameCache->query(pathName); @@ -284,7 +285,7 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name) QQmlPropertyData local; QQmlPropertyData *property = - QQmlPropertyCache::property(engine, currentObject, pathName, context, local); + QQmlPropertyCache::property(engine, currentObject, pathName.toString(), context, local); if (!property) return; // Not a property if (property->isFunction()) @@ -324,14 +325,14 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name) } - const QString &terminal = path.last(); + const QStringRef &terminal = path.last(); if (terminal.count() >= 3 && terminal.at(0) == QLatin1Char('o') && terminal.at(1) == QLatin1Char('n') && terminal.at(2).isUpper()) { - QString signalName = terminal.mid(2); + QString signalName = terminal.mid(2).toString(); signalName[0] = signalName.at(0).toLower(); // XXX - this code treats methods as signals @@ -376,13 +377,14 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name) } // Property + const QString terminalString = terminal.toString(); QQmlPropertyData local; QQmlPropertyData *property = - QQmlPropertyCache::property(engine, currentObject, terminal, context, local); + QQmlPropertyCache::property(engine, currentObject, terminalString, context, local); if (property && !property->isFunction()) { object = currentObject; core = *property; - nameCache = terminal; + nameCache = terminalString; isNameCached = true; } } diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 15e8d62efc..c6299a1720 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -661,7 +661,7 @@ void QQmlDataBlob::notifyComplete(QQmlDataBlob *blob) Q_ASSERT(m_waitingFor.contains(blob)); Q_ASSERT(blob->status() == Error || blob->status() == Complete); QQmlCompilingProfiler prof(QQmlEnginePrivate::get(typeLoader()->engine())->profiler, - blob->url()); + blob); m_inCallback = true; @@ -1121,6 +1121,7 @@ void QQmlTypeLoader::loadThread(QQmlDataBlob *blob) } #define DATALOADER_MAXIMUM_REDIRECT_RECURSION 16 +#define TYPELOADER_MINIMUM_TRIM_THRESHOLD 64 #ifndef QT_NO_NETWORK void QQmlTypeLoader::networkReplyFinished(QNetworkReply *reply) @@ -1225,7 +1226,7 @@ void QQmlTypeLoader::setData(QQmlDataBlob *blob, QQmlFile *file) void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::Data &d) { QML_MEMORY_SCOPE_URL(blob->url()); - QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob->url()); + QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob); blob->m_inCallback = true; @@ -1245,7 +1246,7 @@ void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::Data &d) void QQmlTypeLoader::setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit) { QML_MEMORY_SCOPE_URL(blob->url()); - QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob->url()); + QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob); blob->m_inCallback = true; @@ -1398,13 +1399,10 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL // Probe for all possible locations int priority = 0; - for (int version = QQmlImports::FullyVersioned; version <= QQmlImports::Unversioned; ++version) { - foreach (const QString &path, remotePathList) { - QString qmldirUrl = QQmlImports::completeQmldirPath(importUri, path, import->majorVersion, import->minorVersion, - static_cast<QQmlImports::ImportVersion>(version)); - if (!fetchQmldir(QUrl(qmldirUrl), import, ++priority, errors)) - return false; - } + const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(importUri, remotePathList, import->majorVersion, import->minorVersion); + for (const QString &qmldirPath : qmlDirPaths) { + if (!fetchQmldir(QUrl(qmldirPath), import, ++priority, errors)) + return false; } } } @@ -1602,7 +1600,8 @@ bool QQmlTypeLoader::QmldirContent::designerSupported() const Constructs a new type loader that uses the given \a engine. */ QQmlTypeLoader::QQmlTypeLoader(QQmlEngine *engine) - : m_engine(engine), m_thread(new QQmlTypeLoaderThread(this)) + : m_engine(engine), m_thread(new QQmlTypeLoaderThread(this)), + m_typeCacheTrimThreshold(TYPELOADER_MINIMUM_TRIM_THRESHOLD) { } @@ -1639,6 +1638,10 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode) QQmlTypeData *typeData = m_typeCache.value(url); if (!typeData) { + // Trim before adding the new type, so that we don't immediately trim it away + if (m_typeCache.size() >= m_typeCacheTrimThreshold) + trimCache(); + typeData = new QQmlTypeData(url, this); // TODO: if (compiledData == 0), is it safe to omit this insertion? m_typeCache.insert(url, typeData); @@ -1943,12 +1946,22 @@ void QQmlTypeLoader::clearCache() qDeleteAll(m_importQmlDirCache); m_typeCache.clear(); + m_typeCacheTrimThreshold = TYPELOADER_MINIMUM_TRIM_THRESHOLD; m_scriptCache.clear(); m_qmldirCache.clear(); m_importDirCache.clear(); m_importQmlDirCache.clear(); } +void QQmlTypeLoader::updateTypeCacheTrimThreshold() +{ + int size = m_typeCache.size(); + if (size > m_typeCacheTrimThreshold) + m_typeCacheTrimThreshold = size * 2; + if (size < m_typeCacheTrimThreshold / 2) + m_typeCacheTrimThreshold = qMax(size * 2, TYPELOADER_MINIMUM_TRIM_THRESHOLD); +} + void QQmlTypeLoader::trimCache() { while (true) { @@ -1973,6 +1986,8 @@ void QQmlTypeLoader::trimCache() } } + updateTypeCacheTrimThreshold(); + // TODO: release any scripts which are no longer referenced by any types } diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 49a4ac716a..12ab98e425 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -374,6 +374,7 @@ private: NetworkReplies m_networkReplies; #endif TypeCache m_typeCache; + int m_typeCacheTrimThreshold; ScriptCache m_scriptCache; QmldirCache m_qmldirCache; ImportDirCache m_importDirCache; @@ -381,6 +382,7 @@ private: template<typename Loader> void doLoad(const Loader &loader, QQmlDataBlob *blob, Mode mode); + void updateTypeCacheTrimThreshold(); friend struct PlainLoader; friend struct CachedLoader; diff --git a/src/qml/qml/qqmlvme_p.h b/src/qml/qml/qqmlvme_p.h index a59d8e2aec..ac9db5c046 100644 --- a/src/qml/qml/qqmlvme_p.h +++ b/src/qml/qml/qqmlvme_p.h @@ -64,8 +64,6 @@ #include <private/qqmlengine_p.h> #include <private/qfinitestack_p.h> -#include <private/qqmlprofiler_p.h> - QT_BEGIN_NAMESPACE class QObject; diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index ac40b627d9..d4ffd2747d 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -96,9 +96,9 @@ Heap::QtObject::QtObject(QQmlEngine *qmlEngine) const QMetaObject *qtMetaObject = StaticQtMetaObject::get(); ScopedString str(scope); ScopedValue v(scope); - for (int ii = 0; ii < qtMetaObject->enumeratorCount(); ++ii) { + for (int ii = 0, eii = qtMetaObject->enumeratorCount(); ii < eii; ++ii) { QMetaEnum enumerator = qtMetaObject->enumerator(ii); - for (int jj = 0; jj < enumerator.keyCount(); ++jj) { + for (int jj = 0, ejj = enumerator.keyCount(); jj < ejj; ++jj) { o->put((str = scope.engine->newString(QString::fromUtf8(enumerator.key(jj)))), (v = QV4::Primitive::fromInt32(enumerator.value(jj)))); } } diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index 73128f6344..d8b0ef79f8 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -156,8 +156,7 @@ QV8Engine::QV8Engine(QJSEngine* qq) QV8Engine::~QV8Engine() { - for (int ii = 0; ii < m_extensionData.count(); ++ii) - delete m_extensionData[ii]; + qDeleteAll(m_extensionData); m_extensionData.clear(); #if !defined(QT_NO_XMLSTREAMREADER) && defined(QT_NO_NETWORK) diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 6e5fa516db..aee9fcd0a2 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -1040,7 +1040,7 @@ QString QQmlDelegateModelPrivate::stringValue(Compositor::Group group, int index return QString(); int from = dot+1; dot = name.indexOf(QLatin1Char('.'), from); - value = obj->property(name.mid(from, dot-from).toUtf8()); + value = obj->property(name.midRef(from, dot - from).toUtf8()); } return value.toString(); } @@ -1557,29 +1557,6 @@ bool QQmlDelegateModel::isDescendantOf(const QPersistentModelIndex& desc, const return false; } -void QQmlDelegateModel::_q_layoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint) -{ - Q_D(QQmlDelegateModel); - if (!d->m_complete) - return; - - if (hint == QAbstractItemModel::VerticalSortHint) { - d->m_storedPersistentIndexes.clear(); - if (!parents.isEmpty() && d->m_adaptorModel.rootIndex.isValid() && !isDescendantOf(d->m_adaptorModel.rootIndex, parents)) { - return; - } - - for (int i = 0; i < d->m_count; ++i) { - const QModelIndex index = d->m_adaptorModel.aim()->index(i, 0, d->m_adaptorModel.rootIndex); - d->m_storedPersistentIndexes.append(index); - } - } else if (hint == QAbstractItemModel::HorizontalSortHint) { - // Ignored - } else { - // Triggers model reset, no preparations for that are needed - } -} - void QQmlDelegateModel::_q_layoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint) { Q_D(QQmlDelegateModel); @@ -1591,19 +1568,7 @@ void QQmlDelegateModel::_q_layoutChanged(const QList<QPersistentModelIndex> &par return; } - for (int i = 0, c = d->m_storedPersistentIndexes.count(); i < c; ++i) { - const QPersistentModelIndex &index = d->m_storedPersistentIndexes.at(i); - if (i == index.row()) - continue; - - _q_itemsMoved(i, index.row(), 1); - } - - d->m_storedPersistentIndexes.clear(); - - // layoutUpdate does not necessarily have any move changes, but it can - // also mean data changes. We can't detect what exactly has changed, so - // just emit it for all items + // mark all items as changed _q_itemsChanged(0, d->m_count, QVector<int>()); } else if (hint == QAbstractItemModel::HorizontalSortHint) { diff --git a/src/qml/types/qqmldelegatemodel_p.h b/src/qml/types/qqmldelegatemodel_p.h index aea474de67..2986ec7ce5 100644 --- a/src/qml/types/qqmldelegatemodel_p.h +++ b/src/qml/types/qqmldelegatemodel_p.h @@ -146,7 +146,6 @@ private Q_SLOTS: void _q_rowsRemoved(const QModelIndex &,int,int); void _q_rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int); void _q_dataChanged(const QModelIndex&,const QModelIndex&,const QVector<int> &); - void _q_layoutAboutToBeChanged(const QList<QPersistentModelIndex>&, QAbstractItemModel::LayoutChangeHint); void _q_layoutChanged(const QList<QPersistentModelIndex>&, QAbstractItemModel::LayoutChangeHint); private: diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h index 8e2d1c1cb3..76e55f718d 100644 --- a/src/qml/types/qqmldelegatemodel_p_p.h +++ b/src/qml/types/qqmldelegatemodel_p_p.h @@ -337,8 +337,6 @@ public: }; QQmlDelegateModelGroup *m_groups[Compositor::MaximumGroupCount]; }; - - QList<QPersistentModelIndex> m_storedPersistentIndexes; }; class QQmlPartsModel : public QQmlInstanceModel, public QQmlDelegateModelGroupEmitter diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp index 15c547b5df..5fc2444b7c 100644 --- a/src/qml/util/qqmladaptormodel.cpp +++ b/src/qml/util/qqmladaptormodel.cpp @@ -470,8 +470,6 @@ public: vdm, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int))); QObject::disconnect(aim, SIGNAL(modelReset()), vdm, SLOT(_q_modelReset())); - QObject::disconnect(aim, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), - vdm, SLOT(_q_layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint))); QObject::disconnect(aim, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), vdm, SLOT(_q_layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint))); } @@ -928,8 +926,6 @@ void QQmlAdaptorModel::setModel(const QVariant &variant, QQmlDelegateModel *vdm, vdm, QQmlDelegateModel, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int))); qmlobject_connect(model, QAbstractItemModel, SIGNAL(modelReset()), vdm, QQmlDelegateModel, SLOT(_q_modelReset())); - qmlobject_connect(model, QAbstractItemModel, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), - vdm, QQmlDelegateModel, SLOT(_q_layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint))); qmlobject_connect(model, QAbstractItemModel, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), vdm, QQmlDelegateModel, SLOT(_q_layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint))); } else { diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp index 9ba93a1241..bc26a19033 100644 --- a/src/qmltest/quicktest.cpp +++ b/src/qmltest/quicktest.cpp @@ -352,7 +352,7 @@ int quick_test_main(int argc, char **argv, const char *name, const char *sourceD QTestRootObject::instance()->init(); QString path = fi.absoluteFilePath(); if (path.startsWith(QLatin1String(":/"))) - view->setSource(QUrl(QLatin1String("qrc:") + path.mid(2))); + view->setSource(QUrl(QLatin1String("qrc:") + path.midRef(2))); else view->setSource(QUrl::fromLocalFile(path)); diff --git a/src/quick/designer/qqmldesignermetaobject.cpp b/src/quick/designer/qqmldesignermetaobject.cpp index 46808f978b..0bfa72e9d4 100644 --- a/src/quick/designer/qqmldesignermetaobject.cpp +++ b/src/quick/designer/qqmldesignermetaobject.cpp @@ -140,9 +140,13 @@ void QQmlDesignerMetaObject::init(QObject *object, QQmlEngine *engine) QObjectPrivate *op = QObjectPrivate::get(object); op->metaObject = this; - //create cache - cache = m_cache = QQmlEnginePrivate::get(engine)->cache(this); - cache->addref(); + m_cache = QQmlEnginePrivate::get(engine)->cache(this); + + if (m_cache != cache) { + m_cache->addref(); + cache->release(); + cache = m_cache; + } //If our parent is not a VMEMetaObject we just se the flag to false again if (constructedMetaData(metaData)) @@ -166,17 +170,16 @@ QQmlDesignerMetaObject::QQmlDesignerMetaObject(QObject *object, QQmlEngine *engi if (ddata && ddata->propertyCache) { cache->setParent(ddata->propertyCache); cache->invalidate(engine, this); + ddata->propertyCache->release(); ddata->propertyCache = m_cache; + m_cache->addref(); } } QQmlDesignerMetaObject::~QQmlDesignerMetaObject() { - if (cache->count() > 1) // qml is crashing because the property cache is not removed from the engine - cache->release(); - else - m_type->release(); + m_type->release(); nodeInstanceMetaObjectList.remove(this); } diff --git a/src/quick/designer/qquickdesignersupport.cpp b/src/quick/designer/qquickdesignersupport.cpp index 5bb36c5192..78ed89a107 100644 --- a/src/quick/designer/qquickdesignersupport.cpp +++ b/src/quick/designer/qquickdesignersupport.cpp @@ -187,17 +187,17 @@ QTransform QQuickDesignerSupport::parentTransform(QQuickItem *referencedItem) return parentTransform; } -QString propertyNameForAnchorLine(const QQuickAnchorLine::AnchorLine &anchorLine) +QString propertyNameForAnchorLine(const QQuickAnchors::Anchor &anchorLine) { switch (anchorLine) { - case QQuickAnchorLine::Left: return QLatin1String("left"); - case QQuickAnchorLine::Right: return QLatin1String("right"); - case QQuickAnchorLine::Top: return QLatin1String("top"); - case QQuickAnchorLine::Bottom: return QLatin1String("bottom"); - case QQuickAnchorLine::HCenter: return QLatin1String("horizontalCenter"); - case QQuickAnchorLine::VCenter: return QLatin1String("verticalCenter"); - case QQuickAnchorLine::Baseline: return QLatin1String("baseline"); - case QQuickAnchorLine::Invalid: + case QQuickAnchors::LeftAnchor: return QLatin1String("left"); + case QQuickAnchors::RightAnchor: return QLatin1String("right"); + case QQuickAnchors::TopAnchor: return QLatin1String("top"); + case QQuickAnchors::BottomAnchor: return QLatin1String("bottom"); + case QQuickAnchors::HCenterAnchor: return QLatin1String("horizontalCenter"); + case QQuickAnchors::VCenterAnchor: return QLatin1String("verticalCenter"); + case QQuickAnchors::BaselineAnchor: return QLatin1String("baseline"); + case QQuickAnchors::InvalidAnchor: // fallthrough: default: return QString(); } } @@ -343,7 +343,7 @@ QPair<QString, QObject*> QQuickDesignerSupport::anchorLineTarget(QQuickItem *ite return QPair<QString, QObject*>(); QQuickAnchorLine anchorLine = metaProperty.read().value<QQuickAnchorLine>(); - if (anchorLine.anchorLine != QQuickAnchorLine::Invalid) { + if (anchorLine.anchorLine != QQuickAnchors::InvalidAnchor) { targetObject = anchorLine.item; targetName = propertyNameForAnchorLine(anchorLine.anchorLine); } diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index 56578b5f16..ced4d2a6c4 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -65,6 +65,7 @@ #include <private/qv4scopedvalue_p.h> #include <QtCore/qmath.h> +#include <QtCore/qvector.h> #include <QtCore/private/qnumeric_p.h> #include <QtCore/QRunnable> #include <QtGui/qguiapplication.h> @@ -200,7 +201,7 @@ QColor qt_color_from_string(const QV4::Value &name) return QColor(); } -static int qParseFontSizeFromToken(const QString &fontSizeToken, bool &ok) +static int qParseFontSizeFromToken(const QStringRef &fontSizeToken, bool &ok) { ok = false; float size = fontSizeToken.trimmed().toFloat(&ok); @@ -216,11 +217,11 @@ static int qParseFontSizeFromToken(const QString &fontSizeToken, bool &ok) \c true if successful. If the font size is invalid, \c false is returned and a warning is printed. */ -static bool qSetFontSizeFromToken(QFont &font, const QString &fontSizeToken) +static bool qSetFontSizeFromToken(QFont &font, const QStringRef &fontSizeToken) { - const QString trimmedToken = fontSizeToken.trimmed(); - const QString unitStr = trimmedToken.right(2); - const QString value = trimmedToken.left(trimmedToken.size() - 2); + const QStringRef trimmedToken = fontSizeToken.trimmed(); + const QStringRef unitStr = trimmedToken.right(2); + const QStringRef value = trimmedToken.left(trimmedToken.size() - 2); bool ok = false; int size = 0; if (unitStr == QLatin1String("px")) { @@ -246,7 +247,7 @@ static bool qSetFontSizeFromToken(QFont &font, const QString &fontSizeToken) each family is separated by spaces. Families with spaces in their name must be quoted. */ -static QStringList qExtractFontFamiliesFromString(const QString &fontFamiliesString) +static QStringList qExtractFontFamiliesFromString(const QStringRef &fontFamiliesString) { QStringList extractedFamilies; int quoteIndex = -1; @@ -259,7 +260,7 @@ static QStringList qExtractFontFamiliesFromString(const QString &fontFamiliesStr } else { if (ch == fontFamiliesString.at(quoteIndex)) { // Found the matching quote. +1/-1 because we don't want the quote as part of the name. - const QString family = fontFamiliesString.mid(quoteIndex + 1, index - quoteIndex - 1); + const QString family = fontFamiliesString.mid(quoteIndex + 1, index - quoteIndex - 1).toString(); extractedFamilies.push_back(family); currentFamily.clear(); quoteIndex = -1; @@ -390,16 +391,17 @@ static QFont qt_font_from_string(const QString& fontString, const QFont ¤t fontSizeEnd += 3; QFont newFont; - if (!qSetFontSizeFromToken(newFont, fontString.mid(fontSizeStart, fontSizeEnd - fontSizeStart))) + if (!qSetFontSizeFromToken(newFont, fontString.midRef(fontSizeStart, fontSizeEnd - fontSizeStart))) return currentFont; // We don't want to parse the size twice, so remove it now. QString remainingFontString = fontString; remainingFontString.remove(fontSizeStart, fontSizeEnd - fontSizeStart); + QStringRef remainingFontStringRef(&remainingFontString); // Next, we have to take any font families out, as QString::split() will ruin quoted family names. - const QString fontFamiliesString = remainingFontString.mid(fontSizeStart); - remainingFontString.chop(remainingFontString.length() - fontSizeStart); + const QStringRef fontFamiliesString = remainingFontStringRef.mid(fontSizeStart); + remainingFontStringRef.truncate(fontSizeStart); QStringList fontFamilies = qExtractFontFamiliesFromString(fontFamiliesString); if (fontFamilies.isEmpty()) { return currentFont; @@ -408,16 +410,16 @@ static QFont qt_font_from_string(const QString& fontString, const QFont ¤t return currentFont; // Now that we've removed the messy parts, we can split the font string on spaces. - const QString trimmedTokensStr = remainingFontString.trimmed(); + const QStringRef trimmedTokensStr = remainingFontStringRef.trimmed(); if (trimmedTokensStr.isEmpty()) { // No optional properties. return newFont; } - const QStringList tokens = trimmedTokensStr.split(QLatin1Char(' ')); + const auto tokens = trimmedTokensStr.split(QLatin1Char(' ')); int usedTokens = NoTokens; // Optional properties can be in any order, but font-size and font-family must be last. - for (const QString &token : tokens) { + for (const QStringRef &token : tokens) { if (token.compare(QLatin1String("normal")) == 0) { if (!(usedTokens & FontStyle) || !(usedTokens & FontVariant) || !(usedTokens & FontWeight)) { // Could be font-style, font-variant or font-weight. @@ -938,7 +940,7 @@ static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV4::ExecutionE pixelData->d()->image = QImage(w, h, QImage::Format_ARGB32); pixelData->d()->image.fill(0x00000000); } else { - Q_ASSERT(image.width() == int(w) && image.height() == int(h)); + Q_ASSERT(image.width() == qRound(w) && image.height() == qRound(h)); pixelData->d()->image = image.format() == QImage::Format_ARGB32 ? image : image.convertToFormat(QImage::Format_ARGB32); } @@ -1258,7 +1260,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_globalAlpha(QV4::CallContext *c double globalAlpha = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); - if (!qIsFinite(globalAlpha)) + if (!qt_is_finite(globalAlpha)) return QV4::Encode::undefined(); if (globalAlpha >= 0.0 && globalAlpha <= 1.0 && r->d()->context->state.globalAlpha != globalAlpha) { @@ -1542,10 +1544,10 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createLinearGradient(QV4:: qreal x1 = ctx->args()[2].toNumber(); qreal y1 = ctx->args()[3].toNumber(); - if (!qIsFinite(x0) - || !qIsFinite(y0) - || !qIsFinite(x1) - || !qIsFinite(y1)) { + if (!qt_is_finite(x0) + || !qt_is_finite(y0) + || !qt_is_finite(x1) + || !qt_is_finite(y1)) { V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createLinearGradient(): Incorrect arguments") } QQuickContext2DEngineData *ed = engineData(scope.engine); @@ -1587,12 +1589,12 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(QV4:: qreal y1 = ctx->args()[4].toNumber(); qreal r1 = ctx->args()[5].toNumber(); - if (!qIsFinite(x0) - || !qIsFinite(y0) - || !qIsFinite(x1) - || !qIsFinite(r0) - || !qIsFinite(r1) - || !qIsFinite(y1)) { + if (!qt_is_finite(x0) + || !qt_is_finite(y0) + || !qt_is_finite(x1) + || !qt_is_finite(r0) + || !qt_is_finite(r1) + || !qt_is_finite(y1)) { V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createRadialGradient(): Incorrect arguments") } @@ -1634,11 +1636,11 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(QV4: qreal x = ctx->args()[0].toNumber(); qreal y = ctx->args()[1].toNumber(); qreal angle = DEGREES(ctx->args()[2].toNumber()); - if (!qIsFinite(x) || !qIsFinite(y)) { + if (!qt_is_finite(x) || !qt_is_finite(y)) { V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createConicalGradient(): Incorrect arguments"); } - if (!qIsFinite(angle)) { + if (!qt_is_finite(angle)) { V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createConicalGradient(): Incorrect arguments"); } @@ -1889,7 +1891,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_lineWidth(QV4::CallContext *ctx qreal w = ctx->argc() ? ctx->args()[0].toNumber() : -1; - if (w > 0 && qIsFinite(w) && w != r->d()->context->state.lineWidth) { + if (w > 0 && qt_is_finite(w) && w != r->d()->context->state.lineWidth) { r->d()->context->state.lineWidth = w; r->d()->context->buffer()->setLineWidth(w); } @@ -1918,7 +1920,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_miterLimit(QV4::CallContext *ct qreal ml = ctx->argc() ? ctx->args()[0].toNumber() : -1; - if (ml > 0 && qIsFinite(ml) && ml != r->d()->context->state.miterLimit) { + if (ml > 0 && qt_is_finite(ml) && ml != r->d()->context->state.miterLimit) { r->d()->context->state.miterLimit = ml; r->d()->context->buffer()->setMiterLimit(ml); } @@ -1947,7 +1949,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_shadowBlur(QV4::CallContext *ct qreal blur = ctx->argc() ? ctx->args()[0].toNumber() : -1; - if (blur > 0 && qIsFinite(blur) && blur != r->d()->context->state.shadowBlur) { + if (blur > 0 && qt_is_finite(blur) && blur != r->d()->context->state.shadowBlur) { r->d()->context->state.shadowBlur = blur; r->d()->context->buffer()->setShadowBlur(blur); } @@ -2007,7 +2009,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_shadowOffsetX(QV4::CallContext CHECK_CONTEXT_SETTER(r) qreal offsetX = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); - if (qIsFinite(offsetX) && offsetX != r->d()->context->state.shadowOffsetX) { + if (qt_is_finite(offsetX) && offsetX != r->d()->context->state.shadowOffsetX) { r->d()->context->state.shadowOffsetX = offsetX; r->d()->context->buffer()->setShadowOffsetX(offsetX); } @@ -2035,7 +2037,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_shadowOffsetY(QV4::CallContext CHECK_CONTEXT_SETTER(r) qreal offsetY = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); - if (qIsFinite(offsetY) && offsetY != r->d()->context->state.shadowOffsetY) { + if (qt_is_finite(offsetY) && offsetY != r->d()->context->state.shadowOffsetY) { r->d()->context->state.shadowOffsetY = offsetY; r->d()->context->buffer()->setShadowOffsetY(offsetY); } @@ -2165,7 +2167,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_arc(QV4::CallContext *ctx) qreal radius = ctx->args()[2].toNumber(); - if (qIsFinite(radius) && radius < 0) + if (qt_is_finite(radius) && radius < 0) V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "Incorrect argument radius"); r->d()->context->arc(ctx->args()[0].toNumber(), @@ -2211,7 +2213,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_arcTo(QV4::CallContext *ct if (ctx->argc() >= 5) { qreal radius = ctx->args()[4].toNumber(); - if (qIsFinite(radius) && radius < 0) + if (qt_is_finite(radius) && radius < 0) V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "Incorrect argument radius"); r->d()->context->arcTo(ctx->args()[0].toNumber(), @@ -2274,7 +2276,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_bezierCurveTo(QV4::CallCon qreal x = ctx->args()[4].toNumber(); qreal y = ctx->args()[5].toNumber(); - if (!qIsFinite(cp1x) || !qIsFinite(cp1y) || !qIsFinite(cp2x) || !qIsFinite(cp2y) || !qIsFinite(x) || !qIsFinite(y)) + if (!qt_is_finite(cp1x) || !qt_is_finite(cp1y) || !qt_is_finite(cp2x) || !qt_is_finite(cp2y) || !qt_is_finite(x) || !qt_is_finite(y)) return ctx->thisObject().asReturnedValue(); r->d()->context->bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); @@ -2370,7 +2372,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_lineTo(QV4::CallContext *c qreal x = ctx->args()[0].toNumber(); qreal y = ctx->args()[1].toNumber(); - if (!qIsFinite(x) || !qIsFinite(y)) + if (!qt_is_finite(x) || !qt_is_finite(y)) return ctx->thisObject().asReturnedValue(); r->d()->context->lineTo(x, y); @@ -2394,7 +2396,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_moveTo(QV4::CallContext *c qreal x = ctx->args()[0].toNumber(); qreal y = ctx->args()[1].toNumber(); - if (!qIsFinite(x) || !qIsFinite(y)) + if (!qt_is_finite(x) || !qt_is_finite(y)) return ctx->thisObject().asReturnedValue(); r->d()->context->moveTo(x, y); } @@ -2420,7 +2422,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_quadraticCurveTo(QV4::Call qreal x = ctx->args()[2].toNumber(); qreal y = ctx->args()[3].toNumber(); - if (!qIsFinite(cpx) || !qIsFinite(cpy) || !qIsFinite(x) || !qIsFinite(y)) + if (!qt_is_finite(cpx) || !qt_is_finite(cpy) || !qt_is_finite(x) || !qt_is_finite(y)) return ctx->thisObject().asReturnedValue(); r->d()->context->quadraticCurveTo(cpx, cpy, x, y); @@ -2504,7 +2506,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_text(QV4::CallContext *ctx qreal x = ctx->args()[1].toNumber(); qreal y = ctx->args()[2].toNumber(); - if (!qIsFinite(x) || !qIsFinite(y)) + if (!qt_is_finite(x) || !qt_is_finite(y)) return ctx->thisObject().asReturnedValue(); r->d()->context->text(ctx->args()[0].toQStringNoThrow(), x, y); } @@ -2769,7 +2771,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_fillText(QV4::CallContext if (ctx->argc() >= 3) { qreal x = ctx->args()[1].toNumber(); qreal y = ctx->args()[2].toNumber(); - if (!qIsFinite(x) || !qIsFinite(y)) + if (!qt_is_finite(x) || !qt_is_finite(y)) return ctx->thisObject().asReturnedValue(); QPainterPath textPath = r->d()->context->createTextGlyphs(x, y, ctx->args()[0].toQStringNoThrow()); r->d()->context->buffer()->fill(textPath); @@ -2968,14 +2970,14 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext return ctx->thisObject().asReturnedValue(); } - if (!qIsFinite(sx) - || !qIsFinite(sy) - || !qIsFinite(sw) - || !qIsFinite(sh) - || !qIsFinite(dx) - || !qIsFinite(dy) - || !qIsFinite(dw) - || !qIsFinite(dh)) + if (!qt_is_finite(sx) + || !qt_is_finite(sy) + || !qt_is_finite(sw) + || !qt_is_finite(sh) + || !qt_is_finite(dx) + || !qt_is_finite(dy) + || !qt_is_finite(dw) + || !qt_is_finite(dh)) return ctx->thisObject().asReturnedValue(); if (sx < 0 @@ -3196,7 +3198,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createImageData(QV4::CallC qreal w = ctx->args()[0].toNumber(); qreal h = ctx->args()[1].toNumber(); - if (!qIsFinite(w) || !qIsFinite(h)) + if (!qt_is_finite(w) || !qt_is_finite(h)) V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createImageData(): invalid arguments"); if (w > 0 && h > 0) @@ -3222,7 +3224,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_getImageData(QV4::CallCont qreal y = ctx->args()[1].toNumber(); qreal w = ctx->args()[2].toNumber(); qreal h = ctx->args()[3].toNumber(); - if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h)) + if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h)) V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "getImageData(): Invalid arguments"); if (w <= 0 || h <= 0) @@ -3254,7 +3256,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(QV4::CallCont qreal dy = ctx->args()[2].toNumber(); qreal w, h, dirtyX, dirtyY, dirtyWidth, dirtyHeight; - if (!qIsFinite(dx) || !qIsFinite(dy)) + if (!qt_is_finite(dx) || !qt_is_finite(dy)) V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments"); QV4::Scoped<QQuickJSContext2DImageData> imageData(scope, arg0); @@ -3272,7 +3274,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(QV4::CallCont dirtyWidth = ctx->args()[5].toNumber(); dirtyHeight = ctx->args()[6].toNumber(); - if (!qIsFinite(dirtyX) || !qIsFinite(dirtyY) || !qIsFinite(dirtyWidth) || !qIsFinite(dirtyHeight)) + if (!qt_is_finite(dirtyX) || !qt_is_finite(dirtyY) || !qt_is_finite(dirtyWidth) || !qt_is_finite(dirtyHeight)) V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments"); @@ -3359,7 +3361,7 @@ QV4::ReturnedValue QQuickContext2DStyle::gradient_proto_addColorStop(QV4::CallCo } else { color = qt_color_from_string(ctx->args()[1]); } - if (pos < 0.0 || pos > 1.0 || !qIsFinite(pos)) { + if (pos < 0.0 || pos > 1.0 || !qt_is_finite(pos)) { V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "CanvasGradient: parameter offset out of range"); } @@ -3379,7 +3381,7 @@ void QQuickContext2D::scale(qreal x, qreal y) if (!state.invertibleCTM) return; - if (!qIsFinite(x) || !qIsFinite(y)) + if (!qt_is_finite(x) || !qt_is_finite(y)) return; QTransform newTransform = state.matrix; @@ -3400,7 +3402,7 @@ void QQuickContext2D::rotate(qreal angle) if (!state.invertibleCTM) return; - if (!qIsFinite(angle)) + if (!qt_is_finite(angle)) return; QTransform newTransform =state.matrix; @@ -3421,7 +3423,7 @@ void QQuickContext2D::shear(qreal h, qreal v) if (!state.invertibleCTM) return; - if (!qIsFinite(h) || !qIsFinite(v)) + if (!qt_is_finite(h) || !qt_is_finite(v)) return ; QTransform newTransform = state.matrix; @@ -3442,7 +3444,7 @@ void QQuickContext2D::translate(qreal x, qreal y) if (!state.invertibleCTM) return; - if (!qIsFinite(x) || !qIsFinite(y)) + if (!qt_is_finite(x) || !qt_is_finite(y)) return ; QTransform newTransform = state.matrix; @@ -3463,7 +3465,7 @@ void QQuickContext2D::transform(qreal a, qreal b, qreal c, qreal d, qreal e, qre if (!state.invertibleCTM) return; - if (!qIsFinite(a) || !qIsFinite(b) || !qIsFinite(c) || !qIsFinite(d) || !qIsFinite(e) || !qIsFinite(f)) + if (!qt_is_finite(a) || !qt_is_finite(b) || !qt_is_finite(c) || !qt_is_finite(d) || !qt_is_finite(e) || !qt_is_finite(f)) return; QTransform transform(a, b, c, d, e, f); @@ -3480,7 +3482,7 @@ void QQuickContext2D::transform(qreal a, qreal b, qreal c, qreal d, qreal e, qre void QQuickContext2D::setTransform(qreal a, qreal b, qreal c, qreal d, qreal e, qreal f) { - if (!qIsFinite(a) || !qIsFinite(b) || !qIsFinite(c) || !qIsFinite(d) || !qIsFinite(e) || !qIsFinite(f)) + if (!qt_is_finite(a) || !qt_is_finite(b) || !qt_is_finite(c) || !qt_is_finite(d) || !qt_is_finite(e) || !qt_is_finite(f)) return; QTransform ctm = state.matrix; @@ -3537,7 +3539,7 @@ void QQuickContext2D::fillRect(qreal x, qreal y, qreal w, qreal h) if (!state.invertibleCTM) return; - if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h)) + if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h)) return; buffer()->fillRect(QRectF(x, y, w, h)); @@ -3548,7 +3550,7 @@ void QQuickContext2D::strokeRect(qreal x, qreal y, qreal w, qreal h) if (!state.invertibleCTM) return; - if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h)) + if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h)) return; buffer()->strokeRect(QRectF(x, y, w, h)); @@ -3559,7 +3561,7 @@ void QQuickContext2D::clearRect(qreal x, qreal y, qreal w, qreal h) if (!state.invertibleCTM) return; - if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h)) + if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h)) return; buffer()->clearRect(QRectF(x, y, w, h)); @@ -3570,7 +3572,7 @@ void QQuickContext2D::drawText(const QString& text, qreal x, qreal y, bool fill) if (!state.invertibleCTM) return; - if (!qIsFinite(x) || !qIsFinite(y)) + if (!qt_is_finite(x) || !qt_is_finite(y)) return; QPainterPath textPath = createTextGlyphs(x, y, text); @@ -3716,7 +3718,7 @@ void QQuickContext2D::arcTo(qreal x1, qreal y1, if (!state.invertibleCTM) return; - if (!qIsFinite(x1) || !qIsFinite(y1) || !qIsFinite(x2) || !qIsFinite(y2) || !qIsFinite(radius)) + if (!qt_is_finite(x1) || !qt_is_finite(y1) || !qt_is_finite(x2) || !qt_is_finite(y2) || !qt_is_finite(radius)) return; QPointF st(x1, y1); @@ -3734,7 +3736,7 @@ void QQuickContext2D::rect(qreal x, qreal y, qreal w, qreal h) { if (!state.invertibleCTM) return; - if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h)) + if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h)) return; if (!w && !h) { @@ -3751,7 +3753,7 @@ void QQuickContext2D::roundedRect(qreal x, qreal y, if (!state.invertibleCTM) return; - if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h) || !qIsFinite(xr) || !qIsFinite(yr)) + if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h) || !qt_is_finite(xr) || !qt_is_finite(yr)) return; if (!w && !h) { @@ -3767,7 +3769,7 @@ void QQuickContext2D::ellipse(qreal x, qreal y, if (!state.invertibleCTM) return; - if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h)) + if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h)) return; if (!w && !h) { @@ -3793,7 +3795,7 @@ void QQuickContext2D::arc(qreal xc, qreal yc, qreal radius, qreal sar, qreal ear if (!state.invertibleCTM) return; - if (!qIsFinite(xc) || !qIsFinite(yc) || !qIsFinite(sar) || !qIsFinite(ear) || !qIsFinite(radius)) + if (!qt_is_finite(xc) || !qt_is_finite(yc) || !qt_is_finite(sar) || !qt_is_finite(ear) || !qt_is_finite(radius)) return; if (sar == ear) @@ -3932,13 +3934,13 @@ bool QQuickContext2D::isPointInPath(qreal x, qreal y) const if (!m_path.elementCount()) return false; - if (!qIsFinite(x) || !qIsFinite(y)) + if (!qt_is_finite(x) || !qt_is_finite(y)) return false; QPointF point(x, y); QTransform ctm = state.matrix; QPointF p = ctm.inverted().map(point); - if (!qIsFinite(p.x()) || !qIsFinite(p.y())) + if (!qt_is_finite(p.x()) || !qt_is_finite(p.y())) return false; const_cast<QQuickContext2D *>(this)->m_path.setFillRule(state.fillRule); diff --git a/src/quick/items/qquickanchors.cpp b/src/quick/items/qquickanchors.cpp index d87669df56..4cbd41106e 100644 --- a/src/quick/items/qquickanchors.cpp +++ b/src/quick/items/qquickanchors.cpp @@ -39,19 +39,48 @@ #include "qquickanchors_p_p.h" -#include "qquickitem.h" #include "qquickitem_p.h" #include <qqmlinfo.h> QT_BEGIN_NAMESPACE +static Q_ALWAYS_INLINE QQuickItem *readParentItem(const QQuickItem *item) +{ + return QQuickItemPrivate::get(item)->parentItem; +} + +static Q_ALWAYS_INLINE qreal readX(const QQuickItem *item) +{ + return QQuickItemPrivate::get(item)->x; +} + +static Q_ALWAYS_INLINE qreal readY(const QQuickItem *item) +{ + return QQuickItemPrivate::get(item)->y; +} + +static Q_ALWAYS_INLINE qreal readWidth(const QQuickItem *item) +{ + return QQuickItemPrivate::get(item)->width; +} + +static Q_ALWAYS_INLINE qreal readHeight(const QQuickItem *item) +{ + return QQuickItemPrivate::get(item)->height; +} + +static Q_ALWAYS_INLINE qreal readBaselineOffset(const QQuickItem *item) +{ + return QQuickItemPrivate::get(item)->baselineOffset; +} + //TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)? //TODO: support non-parent, non-sibling (need to find lowest common ancestor) -static inline qreal hcenter(QQuickItem const *item) +static inline qreal hcenter(const QQuickItem *item) { - qreal width = item->width(); + qreal width = readWidth(item); if (QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors) { if (!QQuickAnchorsPrivate::get(anchors)->centerAligned) return width / 2; @@ -63,9 +92,9 @@ static inline qreal hcenter(QQuickItem const *item) return width / 2; } -static inline qreal vcenter(QQuickItem const *item) +static inline qreal vcenter(const QQuickItem *item) { - qreal height = item->height(); + qreal height = readHeight(item); if (QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors) { if (!QQuickAnchorsPrivate::get(anchors)->centerAligned) return height / 2; @@ -78,30 +107,30 @@ static inline qreal vcenter(QQuickItem const *item) } //local position -static qreal position(QQuickItem const *item, QQuickAnchorLine::AnchorLine anchorLine) +static inline qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine) { qreal ret = 0.0; switch (anchorLine) { - case QQuickAnchorLine::Left: - ret = item->x(); + case QQuickAnchors::LeftAnchor: + ret = readX(item); break; - case QQuickAnchorLine::Right: - ret = item->x() + item->width(); + case QQuickAnchors::RightAnchor: + ret = readX(item) + readWidth(item); break; - case QQuickAnchorLine::Top: - ret = item->y(); + case QQuickAnchors::TopAnchor: + ret = readY(item); break; - case QQuickAnchorLine::Bottom: - ret = item->y() + item->height(); + case QQuickAnchors::BottomAnchor: + ret = readY(item) + readHeight(item); break; - case QQuickAnchorLine::HCenter: - ret = item->x() + hcenter(item); + case QQuickAnchors::HCenterAnchor: + ret = readX(item) + hcenter(item); break; - case QQuickAnchorLine::VCenter: - ret = item->y() + vcenter(item); + case QQuickAnchors::VCenterAnchor: + ret = readY(item) + vcenter(item); break; - case QQuickAnchorLine::Baseline: - ret = item->y() + item->baselineOffset(); + case QQuickAnchors::BaselineAnchor: + ret = readY(item) + readBaselineOffset(item); break; default: break; @@ -111,30 +140,30 @@ static qreal position(QQuickItem const *item, QQuickAnchorLine::AnchorLine ancho } //position when origin is 0,0 -static qreal adjustedPosition(QQuickItem *item, QQuickAnchorLine::AnchorLine anchorLine) +static inline qreal adjustedPosition(QQuickItem *item, QQuickAnchors::Anchor anchorLine) { qreal ret = 0.0; switch (anchorLine) { - case QQuickAnchorLine::Left: + case QQuickAnchors::LeftAnchor: ret = 0.0; break; - case QQuickAnchorLine::Right: - ret = item->width(); + case QQuickAnchors::RightAnchor: + ret = readWidth(item); break; - case QQuickAnchorLine::Top: + case QQuickAnchors::TopAnchor: ret = 0.0; break; - case QQuickAnchorLine::Bottom: - ret = item->height(); + case QQuickAnchors::BottomAnchor: + ret = readHeight(item); break; - case QQuickAnchorLine::HCenter: + case QQuickAnchors::HCenterAnchor: ret = hcenter(item); break; - case QQuickAnchorLine::VCenter: + case QQuickAnchors::VCenterAnchor: ret = vcenter(item); break; - case QQuickAnchorLine::Baseline: - ret = item->baselineOffset(); + case QQuickAnchors::BaselineAnchor: + ret = readBaselineOffset(item); break; default: break; @@ -154,13 +183,13 @@ QQuickAnchors::~QQuickAnchors() d->inDestructor = true; d->remDepend(d->fill); d->remDepend(d->centerIn); - d->remDepend(d->left.item); - d->remDepend(d->right.item); - d->remDepend(d->top.item); - d->remDepend(d->bottom.item); - d->remDepend(d->vCenter.item); - d->remDepend(d->hCenter.item); - d->remDepend(d->baseline.item); + d->remDepend(d->leftAnchorItem); + d->remDepend(d->rightAnchorItem); + d->remDepend(d->topAnchorItem); + d->remDepend(d->bottomAnchorItem); + d->remDepend(d->vCenterAnchorItem); + d->remDepend(d->hCenterAnchorItem); + d->remDepend(d->baselineAnchorItem); } void QQuickAnchorsPrivate::fillChanged() @@ -174,12 +203,13 @@ void QQuickAnchorsPrivate::fillChanged() qreal horizontalMargin = q->mirrored() ? rightMargin : leftMargin; - if (fill == item->parentItem()) { //child-parent + if (fill == readParentItem(item)) { //child-parent setItemPos(QPointF(horizontalMargin, topMargin)); - } else if (fill->parentItem() == item->parentItem()) { //siblings - setItemPos(QPointF(fill->x()+horizontalMargin, fill->y()+topMargin)); + } else if (readParentItem(fill) == readParentItem(item)) { //siblings + setItemPos(QPointF(readX(fill)+horizontalMargin, readY(fill) + topMargin)); } - setItemSize(QSizeF(fill->width()-leftMargin-rightMargin, fill->height()-topMargin-bottomMargin)); + setItemSize(QSizeF(readWidth(fill) - leftMargin - rightMargin, + readHeight(fill) - topMargin - bottomMargin)); --updatingFill; } else { @@ -199,12 +229,12 @@ void QQuickAnchorsPrivate::centerInChanged() ++updatingCenterIn; qreal effectiveHCenterOffset = q->mirrored() ? -hCenterOffset : hCenterOffset; - if (centerIn == item->parentItem()) { - QPointF p(hcenter(item->parentItem()) - hcenter(item) + effectiveHCenterOffset, - vcenter(item->parentItem()) - vcenter(item) + vCenterOffset); + if (centerIn == readParentItem(item)) { + QPointF p(hcenter(readParentItem(item)) - hcenter(item) + effectiveHCenterOffset, + vcenter(readParentItem(item)) - vcenter(item) + vCenterOffset); setItemPos(p); - } else if (centerIn->parentItem() == item->parentItem()) { + } else if (readParentItem(centerIn) == readParentItem(item)) { QPointF p(centerIn->x() + hcenter(centerIn) - hcenter(item) + effectiveHCenterOffset, centerIn->y() + vcenter(centerIn) - vcenter(item) + vCenterOffset); setItemPos(p); @@ -225,32 +255,32 @@ void QQuickAnchorsPrivate::clearItem(QQuickItem *item) fill = 0; if (centerIn == item) centerIn = 0; - if (left.item == item) { - left.item = 0; + if (leftAnchorItem == item) { + leftAnchorItem = 0; usedAnchors &= ~QQuickAnchors::LeftAnchor; } - if (right.item == item) { - right.item = 0; + if (rightAnchorItem == item) { + rightAnchorItem = 0; usedAnchors &= ~QQuickAnchors::RightAnchor; } - if (top.item == item) { - top.item = 0; + if (topAnchorItem == item) { + topAnchorItem = 0; usedAnchors &= ~QQuickAnchors::TopAnchor; } - if (bottom.item == item) { - bottom.item = 0; + if (bottomAnchorItem == item) { + bottomAnchorItem = 0; usedAnchors &= ~QQuickAnchors::BottomAnchor; } - if (vCenter.item == item) { - vCenter.item = 0; + if (vCenterAnchorItem == item) { + vCenterAnchorItem = 0; usedAnchors &= ~QQuickAnchors::VCenterAnchor; } - if (hCenter.item == item) { - hCenter.item = 0; + if (hCenterAnchorItem == item) { + hCenterAnchorItem = 0; usedAnchors &= ~QQuickAnchors::HCenterAnchor; } - if (baseline.item == item) { - baseline.item = 0; + if (baselineAnchorItem == item) { + baselineAnchorItem = 0; usedAnchors &= ~QQuickAnchors::BaselineAnchor; } } @@ -263,7 +293,7 @@ int QQuickAnchorsPrivate::calculateDependency(QQuickItem *controlItem) return dependency; if (fill == controlItem) { - if (controlItem == item->parentItem()) + if (controlItem == readParentItem(item)) dependency |= QQuickItemPrivate::SizeChange; else //sibling dependency |= QQuickItemPrivate::GeometryChange; @@ -271,27 +301,27 @@ int QQuickAnchorsPrivate::calculateDependency(QQuickItem *controlItem) } if (centerIn == controlItem) { - if (controlItem == item->parentItem()) + if (controlItem == readParentItem(item)) dependency |= QQuickItemPrivate::SizeChange; else //sibling dependency |= QQuickItemPrivate::GeometryChange; return dependency; //exit early } - if ((usedAnchors & QQuickAnchors::LeftAnchor && left.item == controlItem) || - (usedAnchors & QQuickAnchors::RightAnchor && right.item == controlItem) || - (usedAnchors & QQuickAnchors::HCenterAnchor && hCenter.item == controlItem)) { - if (controlItem == item->parentItem()) + if ((usedAnchors & QQuickAnchors::LeftAnchor && leftAnchorItem == controlItem) || + (usedAnchors & QQuickAnchors::RightAnchor && rightAnchorItem == controlItem) || + (usedAnchors & QQuickAnchors::HCenterAnchor && hCenterAnchorItem == controlItem)) { + if (controlItem == readParentItem(item)) dependency |= QQuickItemPrivate::WidthChange; else //sibling dependency |= QFlags<QQuickItemPrivate::GeometryChangeType>(QQuickItemPrivate::XChange | QQuickItemPrivate::WidthChange); } - if ((usedAnchors & QQuickAnchors::TopAnchor && top.item == controlItem) || - (usedAnchors & QQuickAnchors::BottomAnchor && bottom.item == controlItem) || - (usedAnchors & QQuickAnchors::VCenterAnchor && vCenter.item == controlItem) || - (usedAnchors & QQuickAnchors::BaselineAnchor && baseline.item == controlItem)) { - if (controlItem == item->parentItem()) + if ((usedAnchors & QQuickAnchors::TopAnchor && topAnchorItem == controlItem) || + (usedAnchors & QQuickAnchors::BottomAnchor && bottomAnchorItem == controlItem) || + (usedAnchors & QQuickAnchors::VCenterAnchor && vCenterAnchorItem == controlItem) || + (usedAnchors & QQuickAnchors::BaselineAnchor && baselineAnchorItem == controlItem)) { + if (controlItem == readParentItem(item)) dependency |= QQuickItemPrivate::HeightChange; else //sibling dependency |= QFlags<QQuickItemPrivate::GeometryChangeType>(QQuickItemPrivate::YChange | QQuickItemPrivate::HeightChange); @@ -422,13 +452,13 @@ void QQuickAnchorsPrivate::updateOnComplete() QQuickItem *dependencies[9]; dependencies[0] = fill; dependencies[1] = centerIn; - dependencies[2] = left.item; - dependencies[3] = right.item; - dependencies[4] = hCenter.item; - dependencies[5] = top.item; - dependencies[6] = bottom.item; - dependencies[7] = vCenter.item; - dependencies[8] = baseline.item; + dependencies[2] = leftAnchorItem; + dependencies[3] = rightAnchorItem; + dependencies[4] = hCenterAnchorItem; + dependencies[5] = topAnchorItem; + dependencies[6] = bottomAnchorItem; + dependencies[7] = vCenterAnchorItem; + dependencies[8] = baselineAnchorItem; std::sort(dependencies, dependencies + 9); @@ -447,22 +477,38 @@ void QQuickAnchorsPrivate::updateOnComplete() void QQuickAnchorsPrivate::update() { - fillChanged(); - centerInChanged(); - if (usedAnchors & QQuickAnchorLine::Horizontal_Mask) - updateHorizontalAnchors(); - if (usedAnchors & QQuickAnchorLine::Vertical_Mask) - updateVerticalAnchors(); + if (!isItemComplete()) + return; + + if (fill) { + fillChanged(); + } else if (centerIn) { + centerInChanged(); + } else { + if (usedAnchors & QQuickAnchors::Horizontal_Mask) + updateHorizontalAnchors(); + if (usedAnchors & QQuickAnchors::Vertical_Mask) + updateVerticalAnchors(); + } } void QQuickAnchorsPrivate::itemGeometryChanged(QQuickItem *, const QRectF &newG, const QRectF &oldG) { - fillChanged(); - centerInChanged(); - if ((usedAnchors & QQuickAnchorLine::Horizontal_Mask) && (newG.x() != oldG.x() || newG.width() != oldG.width())) - updateHorizontalAnchors(); - if ((usedAnchors & QQuickAnchorLine::Vertical_Mask) && (newG.y() != oldG.y() || newG.height() != oldG.height())) - updateVerticalAnchors(); + if (!isItemComplete()) + return; + + if (fill) { + fillChanged(); + } else if (centerIn) { + centerInChanged(); + } else { + if ((usedAnchors & QQuickAnchors::Horizontal_Mask) + && (newG.x() != oldG.x() || newG.width() != oldG.width())) + updateHorizontalAnchors(); + if ((usedAnchors & QQuickAnchors::Vertical_Mask) + && (newG.y() != oldG.y() || newG.height() != oldG.height())) + updateVerticalAnchors(); + } } QQuickItem *QQuickAnchors::fill() const @@ -484,7 +530,7 @@ void QQuickAnchors::setFill(QQuickItem *f) emit fillChanged(); return; } - if (f != d->item->parentItem() && f->parentItem() != d->item->parentItem()){ + if (f != readParentItem(d->item) && readParentItem(f) != readParentItem(d->item)){ qmlInfo(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling."); return; } @@ -520,7 +566,7 @@ void QQuickAnchors::setCenterIn(QQuickItem* c) emit centerInChanged(); return; } - if (c != d->item->parentItem() && c->parentItem() != d->item->parentItem()){ + if (c != readParentItem(d->item) && readParentItem(c) != readParentItem(d->item)){ qmlInfo(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling."); return; } @@ -537,29 +583,31 @@ void QQuickAnchors::resetCenterIn() setCenterIn(0); } -bool QQuickAnchorsPrivate::calcStretch(const QQuickAnchorLine &edge1, - const QQuickAnchorLine &edge2, - qreal offset1, - qreal offset2, - QQuickAnchorLine::AnchorLine line, - qreal &stretch) +bool QQuickAnchorsPrivate::calcStretch(QQuickItem *edge1Item, + QQuickAnchors::Anchor edge1Line, + QQuickItem *edge2Item, + QQuickAnchors::Anchor edge2Line, + qreal offset1, + qreal offset2, + QQuickAnchors::Anchor line, + qreal &stretch) { - bool edge1IsParent = (edge1.item == item->parentItem()); - bool edge2IsParent = (edge2.item == item->parentItem()); - bool edge1IsSibling = (edge1.item->parentItem() == item->parentItem()); - bool edge2IsSibling = (edge2.item->parentItem() == item->parentItem()); + bool edge1IsParent = (edge1Item == readParentItem(item)); + bool edge2IsParent = (edge2Item == readParentItem(item)); + bool edge1IsSibling = (readParentItem(edge1Item) == readParentItem(item)); + bool edge2IsSibling = (readParentItem(edge2Item) == readParentItem(item)); bool invalid = false; if ((edge2IsParent && edge1IsParent) || (edge2IsSibling && edge1IsSibling)) { - stretch = (position(edge2.item, edge2.anchorLine) + offset2) - - (position(edge1.item, edge1.anchorLine) + offset1); + stretch = (position(edge2Item, edge2Line) + offset2) + - (position(edge1Item, edge1Line) + offset1); } else if (edge2IsParent && edge1IsSibling) { - stretch = (position(edge2.item, edge2.anchorLine) + offset2) - - (position(item->parentItem(), line) - + position(edge1.item, edge1.anchorLine) + offset1); + stretch = (position(edge2Item, edge2Line) + offset2) + - (position(readParentItem(item), line) + + position(edge1Item, edge1Line) + offset1); } else if (edge2IsSibling && edge1IsParent) { - stretch = (position(item->parentItem(), line) + position(edge2.item, edge2.anchorLine) + offset2) - - (position(edge1.item, edge1.anchorLine) + offset1); + stretch = (position(readParentItem(item), line) + position(edge2Item, edge2Line) + offset2) + - (position(edge1Item, edge1Line) + offset1); } else invalid = true; @@ -578,52 +626,60 @@ void QQuickAnchorsPrivate::updateVerticalAnchors() bool invalid = true; qreal height = 0.0; if (usedAnchors & QQuickAnchors::BottomAnchor) { - invalid = calcStretch(top, bottom, topMargin, -bottomMargin, QQuickAnchorLine::Top, height); + invalid = calcStretch(topAnchorItem, topAnchorLine, + bottomAnchorItem, bottomAnchorLine, + topMargin, -bottomMargin, QQuickAnchors::TopAnchor, height); } else if (usedAnchors & QQuickAnchors::VCenterAnchor) { - invalid = calcStretch(top, vCenter, topMargin, vCenterOffset, QQuickAnchorLine::Top, height); + invalid = calcStretch(topAnchorItem, topAnchorLine, + vCenterAnchorItem, vCenterAnchorLine, + topMargin, vCenterOffset, QQuickAnchors::TopAnchor, height); height *= 2; } if (!invalid) setItemHeight(height); //Handle top - if (top.item == item->parentItem()) { - setItemY(adjustedPosition(top.item, top.anchorLine) + topMargin); - } else if (top.item->parentItem() == item->parentItem()) { - setItemY(position(top.item, top.anchorLine) + topMargin); + if (topAnchorItem == readParentItem(item)) { + setItemY(adjustedPosition(topAnchorItem, topAnchorLine) + topMargin); + } else if (readParentItem(topAnchorItem) == readParentItem(item)) { + setItemY(position(topAnchorItem, topAnchorLine) + topMargin); } } else if (usedAnchors & QQuickAnchors::BottomAnchor) { //Handle stretching (top + bottom case is handled above) if (usedAnchors & QQuickAnchors::VCenterAnchor) { qreal height = 0.0; - bool invalid = calcStretch(vCenter, bottom, vCenterOffset, -bottomMargin, - QQuickAnchorLine::Top, height); + bool invalid = calcStretch(vCenterAnchorItem, vCenterAnchorLine, + bottomAnchorItem, bottomAnchorLine, + vCenterOffset, -bottomMargin, QQuickAnchors::TopAnchor, + height); if (!invalid) setItemHeight(height*2); } //Handle bottom - if (bottom.item == item->parentItem()) { - setItemY(adjustedPosition(bottom.item, bottom.anchorLine) - item->height() - bottomMargin); - } else if (bottom.item->parentItem() == item->parentItem()) { - setItemY(position(bottom.item, bottom.anchorLine) - item->height() - bottomMargin); + if (bottomAnchorItem == readParentItem(item)) { + setItemY(adjustedPosition(bottomAnchorItem, bottomAnchorLine) - readHeight(item) - bottomMargin); + } else if (readParentItem(bottomAnchorItem) == readParentItem(item)) { + setItemY(position(bottomAnchorItem, bottomAnchorLine) - readHeight(item) - bottomMargin); } } else if (usedAnchors & QQuickAnchors::VCenterAnchor) { //(stetching handled above) //Handle vCenter - if (vCenter.item == item->parentItem()) { - setItemY(adjustedPosition(vCenter.item, vCenter.anchorLine) + if (vCenterAnchorItem == readParentItem(item)) { + setItemY(adjustedPosition(vCenterAnchorItem, vCenterAnchorLine) - vcenter(item) + vCenterOffset); - } else if (vCenter.item->parentItem() == item->parentItem()) { - setItemY(position(vCenter.item, vCenter.anchorLine) - vcenter(item) + vCenterOffset); + } else if (readParentItem(vCenterAnchorItem) == readParentItem(item)) { + setItemY(position(vCenterAnchorItem, vCenterAnchorLine) - vcenter(item) + vCenterOffset); } } else if (usedAnchors & QQuickAnchors::BaselineAnchor) { //Handle baseline - if (baseline.item == item->parentItem()) { - setItemY(adjustedPosition(baseline.item, baseline.anchorLine) - item->baselineOffset() + baselineOffset); - } else if (baseline.item->parentItem() == item->parentItem()) { - setItemY(position(baseline.item, baseline.anchorLine) - item->baselineOffset() + baselineOffset); + if (baselineAnchorItem == readParentItem(item)) { + setItemY(adjustedPosition(baselineAnchorItem, baselineAnchorLine) + - readBaselineOffset(item) + baselineOffset); + } else if (readParentItem(baselineAnchorItem) == readParentItem(item)) { + setItemY(position(baselineAnchorItem, baselineAnchorLine) + - readBaselineOffset(item) + baselineOffset); } } --updatingVerticalAnchor; @@ -633,12 +689,12 @@ void QQuickAnchorsPrivate::updateVerticalAnchors() } } -inline QQuickAnchorLine::AnchorLine reverseAnchorLine(QQuickAnchorLine::AnchorLine anchorLine) +static inline QQuickAnchors::Anchor reverseAnchorLine(QQuickAnchors::Anchor anchorLine) { - if (anchorLine == QQuickAnchorLine::Left) { - return QQuickAnchorLine::Right; - } else if (anchorLine == QQuickAnchorLine::Right) { - return QQuickAnchorLine::Left; + if (anchorLine == QQuickAnchors::LeftAnchor) { + return QQuickAnchors::RightAnchor; + } else if (anchorLine == QQuickAnchors::RightAnchor) { + return QQuickAnchors::LeftAnchor; } else { return anchorLine; } @@ -653,26 +709,30 @@ void QQuickAnchorsPrivate::updateHorizontalAnchors() if (updatingHorizontalAnchor < 3) { ++updatingHorizontalAnchor; qreal effectiveRightMargin, effectiveLeftMargin, effectiveHorizontalCenterOffset; - QQuickAnchorLine effectiveLeft, effectiveRight, effectiveHorizontalCenter; + QQuickItem *effectiveLeftItem, *effectiveRightItem, *effectiveHorizontalCenterItem; + QQuickAnchors::Anchor effectiveLeftLine, effectiveRightLine, effectiveHorizontalCenterLine; QQuickAnchors::Anchor effectiveLeftAnchor, effectiveRightAnchor; if (q->mirrored()) { effectiveLeftAnchor = QQuickAnchors::RightAnchor; effectiveRightAnchor = QQuickAnchors::LeftAnchor; - effectiveLeft.item = right.item; - effectiveLeft.anchorLine = reverseAnchorLine(right.anchorLine); - effectiveRight.item = left.item; - effectiveRight.anchorLine = reverseAnchorLine(left.anchorLine); - effectiveHorizontalCenter.item = hCenter.item; - effectiveHorizontalCenter.anchorLine = reverseAnchorLine(hCenter.anchorLine); + effectiveLeftItem = rightAnchorItem; + effectiveLeftLine = reverseAnchorLine(rightAnchorLine); + effectiveRightItem = leftAnchorItem; + effectiveRightLine = reverseAnchorLine(leftAnchorLine); + effectiveHorizontalCenterItem = hCenterAnchorItem; + effectiveHorizontalCenterLine = reverseAnchorLine(hCenterAnchorLine); effectiveLeftMargin = rightMargin; effectiveRightMargin = leftMargin; effectiveHorizontalCenterOffset = -hCenterOffset; } else { effectiveLeftAnchor = QQuickAnchors::LeftAnchor; effectiveRightAnchor = QQuickAnchors::RightAnchor; - effectiveLeft = left; - effectiveRight = right; - effectiveHorizontalCenter = hCenter; + effectiveLeftItem = leftAnchorItem; + effectiveLeftLine = leftAnchorLine; + effectiveRightItem = rightAnchorItem; + effectiveRightLine = rightAnchorLine; + effectiveHorizontalCenterItem = hCenterAnchorItem; + effectiveHorizontalCenterLine = hCenterAnchorLine; effectiveLeftMargin = leftMargin; effectiveRightMargin = rightMargin; effectiveHorizontalCenterOffset = hCenterOffset; @@ -683,42 +743,53 @@ void QQuickAnchorsPrivate::updateHorizontalAnchors() bool invalid = true; qreal width = 0.0; if (usedAnchors & effectiveRightAnchor) { - invalid = calcStretch(effectiveLeft, effectiveRight, effectiveLeftMargin, -effectiveRightMargin, QQuickAnchorLine::Left, width); + invalid = calcStretch(effectiveLeftItem, effectiveLeftLine, + effectiveRightItem, effectiveRightLine, + effectiveLeftMargin, -effectiveRightMargin, + QQuickAnchors::LeftAnchor, width); } else if (usedAnchors & QQuickAnchors::HCenterAnchor) { - invalid = calcStretch(effectiveLeft, effectiveHorizontalCenter, effectiveLeftMargin, effectiveHorizontalCenterOffset, QQuickAnchorLine::Left, width); + invalid = calcStretch(effectiveLeftItem, effectiveLeftLine, + effectiveHorizontalCenterItem, effectiveHorizontalCenterLine, + effectiveLeftMargin, effectiveHorizontalCenterOffset, + QQuickAnchors::LeftAnchor, width); width *= 2; } if (!invalid) setItemWidth(width); //Handle left - if (effectiveLeft.item == item->parentItem()) { - setItemX(adjustedPosition(effectiveLeft.item, effectiveLeft.anchorLine) + effectiveLeftMargin); - } else if (effectiveLeft.item->parentItem() == item->parentItem()) { - setItemX(position(effectiveLeft.item, effectiveLeft.anchorLine) + effectiveLeftMargin); + if (effectiveLeftItem == readParentItem(item)) { + setItemX(adjustedPosition(effectiveLeftItem, effectiveLeftLine) + effectiveLeftMargin); + } else if (readParentItem(effectiveLeftItem) == readParentItem(item)) { + setItemX(position(effectiveLeftItem, effectiveLeftLine) + effectiveLeftMargin); } } else if (usedAnchors & effectiveRightAnchor) { //Handle stretching (left + right case is handled in updateLeftAnchor) if (usedAnchors & QQuickAnchors::HCenterAnchor) { qreal width = 0.0; - bool invalid = calcStretch(effectiveHorizontalCenter, effectiveRight, effectiveHorizontalCenterOffset, -effectiveRightMargin, - QQuickAnchorLine::Left, width); + bool invalid = calcStretch(effectiveHorizontalCenterItem, + effectiveHorizontalCenterLine, + effectiveRightItem, effectiveRightLine, + effectiveHorizontalCenterOffset, -effectiveRightMargin, + QQuickAnchors::LeftAnchor, width); if (!invalid) setItemWidth(width*2); } //Handle right - if (effectiveRight.item == item->parentItem()) { - setItemX(adjustedPosition(effectiveRight.item, effectiveRight.anchorLine) - item->width() - effectiveRightMargin); - } else if (effectiveRight.item->parentItem() == item->parentItem()) { - setItemX(position(effectiveRight.item, effectiveRight.anchorLine) - item->width() - effectiveRightMargin); + if (effectiveRightItem == readParentItem(item)) { + setItemX(adjustedPosition(effectiveRightItem, effectiveRightLine) + - readWidth(item) - effectiveRightMargin); + } else if (readParentItem(effectiveRightItem) == readParentItem(item)) { + setItemX(position(effectiveRightItem, effectiveRightLine) + - readWidth(item) - effectiveRightMargin); } } else if (usedAnchors & QQuickAnchors::HCenterAnchor) { //Handle hCenter - if (effectiveHorizontalCenter.item == item->parentItem()) { - setItemX(adjustedPosition(effectiveHorizontalCenter.item, effectiveHorizontalCenter.anchorLine) - hcenter(item) + effectiveHorizontalCenterOffset); - } else if (effectiveHorizontalCenter.item->parentItem() == item->parentItem()) { - setItemX(position(effectiveHorizontalCenter.item, effectiveHorizontalCenter.anchorLine) - hcenter(item) + effectiveHorizontalCenterOffset); + if (effectiveHorizontalCenterItem == readParentItem(item)) { + setItemX(adjustedPosition(effectiveHorizontalCenterItem, effectiveHorizontalCenterLine) - hcenter(item) + effectiveHorizontalCenterOffset); + } else if (readParentItem(effectiveHorizontalCenterItem) == readParentItem(item)) { + setItemX(position(effectiveHorizontalCenterItem, effectiveHorizontalCenterLine) - hcenter(item) + effectiveHorizontalCenterOffset); } } --updatingHorizontalAnchor; @@ -731,13 +802,14 @@ void QQuickAnchorsPrivate::updateHorizontalAnchors() QQuickAnchorLine QQuickAnchors::top() const { Q_D(const QQuickAnchors); - return d->top; + return QQuickAnchorLine(d->topAnchorItem, d->topAnchorLine); } void QQuickAnchors::setTop(const QQuickAnchorLine &edge) { Q_D(QQuickAnchors); - if (!d->checkVAnchorValid(edge) || d->top == edge) + if (!d->checkVAnchorValid(edge) || + (d->topAnchorItem == edge.item && d->topAnchorLine == edge.anchorLine)) return; d->usedAnchors |= TopAnchor; @@ -747,10 +819,11 @@ void QQuickAnchors::setTop(const QQuickAnchorLine &edge) return; } - QQuickItem *oldTop = d->top.item; - d->top = edge; + QQuickItem *oldTop = d->topAnchorItem; + d->topAnchorItem = edge.item; + d->topAnchorLine = edge.anchorLine; d->remDepend(oldTop); - d->addDepend(d->top.item); + d->addDepend(d->topAnchorItem); emit topChanged(); d->updateVerticalAnchors(); } @@ -759,8 +832,9 @@ void QQuickAnchors::resetTop() { Q_D(QQuickAnchors); d->usedAnchors &= ~TopAnchor; - d->remDepend(d->top.item); - d->top = QQuickAnchorLine(); + d->remDepend(d->topAnchorItem); + d->topAnchorItem = Q_NULLPTR; + d->topAnchorLine = QQuickAnchors::InvalidAnchor; emit topChanged(); d->updateVerticalAnchors(); } @@ -768,13 +842,14 @@ void QQuickAnchors::resetTop() QQuickAnchorLine QQuickAnchors::bottom() const { Q_D(const QQuickAnchors); - return d->bottom; + return QQuickAnchorLine(d->bottomAnchorItem, d->bottomAnchorLine); } void QQuickAnchors::setBottom(const QQuickAnchorLine &edge) { Q_D(QQuickAnchors); - if (!d->checkVAnchorValid(edge) || d->bottom == edge) + if (!d->checkVAnchorValid(edge) || + (d->bottomAnchorItem == edge.item && d->bottomAnchorLine == edge.anchorLine)) return; d->usedAnchors |= BottomAnchor; @@ -784,10 +859,11 @@ void QQuickAnchors::setBottom(const QQuickAnchorLine &edge) return; } - QQuickItem *oldBottom = d->bottom.item; - d->bottom = edge; + QQuickItem *oldBottom = d->bottomAnchorItem; + d->bottomAnchorItem = edge.item; + d->bottomAnchorLine = edge.anchorLine; d->remDepend(oldBottom); - d->addDepend(d->bottom.item); + d->addDepend(d->bottomAnchorItem); emit bottomChanged(); d->updateVerticalAnchors(); } @@ -796,8 +872,9 @@ void QQuickAnchors::resetBottom() { Q_D(QQuickAnchors); d->usedAnchors &= ~BottomAnchor; - d->remDepend(d->bottom.item); - d->bottom = QQuickAnchorLine(); + d->remDepend(d->bottomAnchorItem); + d->bottomAnchorItem = Q_NULLPTR; + d->bottomAnchorLine = QQuickAnchors::InvalidAnchor; emit bottomChanged(); d->updateVerticalAnchors(); } @@ -805,13 +882,14 @@ void QQuickAnchors::resetBottom() QQuickAnchorLine QQuickAnchors::verticalCenter() const { Q_D(const QQuickAnchors); - return d->vCenter; + return QQuickAnchorLine(d->vCenterAnchorItem, d->vCenterAnchorLine); } void QQuickAnchors::setVerticalCenter(const QQuickAnchorLine &edge) { Q_D(QQuickAnchors); - if (!d->checkVAnchorValid(edge) || d->vCenter == edge) + if (!d->checkVAnchorValid(edge) || + (d->vCenterAnchorItem == edge.item && d->vCenterAnchorLine == edge.anchorLine)) return; d->usedAnchors |= VCenterAnchor; @@ -821,10 +899,11 @@ void QQuickAnchors::setVerticalCenter(const QQuickAnchorLine &edge) return; } - QQuickItem *oldVCenter = d->vCenter.item; - d->vCenter = edge; + QQuickItem *oldVCenter = d->vCenterAnchorItem; + d->vCenterAnchorItem = edge.item; + d->vCenterAnchorLine = edge.anchorLine; d->remDepend(oldVCenter); - d->addDepend(d->vCenter.item); + d->addDepend(d->vCenterAnchorItem); emit verticalCenterChanged(); d->updateVerticalAnchors(); } @@ -833,8 +912,9 @@ void QQuickAnchors::resetVerticalCenter() { Q_D(QQuickAnchors); d->usedAnchors &= ~VCenterAnchor; - d->remDepend(d->vCenter.item); - d->vCenter = QQuickAnchorLine(); + d->remDepend(d->vCenterAnchorItem); + d->vCenterAnchorItem = Q_NULLPTR; + d->vCenterAnchorLine = QQuickAnchors::InvalidAnchor; emit verticalCenterChanged(); d->updateVerticalAnchors(); } @@ -842,13 +922,14 @@ void QQuickAnchors::resetVerticalCenter() QQuickAnchorLine QQuickAnchors::baseline() const { Q_D(const QQuickAnchors); - return d->baseline; + return QQuickAnchorLine(d->baselineAnchorItem, d->baselineAnchorLine); } void QQuickAnchors::setBaseline(const QQuickAnchorLine &edge) { Q_D(QQuickAnchors); - if (!d->checkVAnchorValid(edge) || d->baseline == edge) + if (!d->checkVAnchorValid(edge) || + (d->baselineAnchorItem == edge.item && d->baselineAnchorLine == edge.anchorLine)) return; d->usedAnchors |= BaselineAnchor; @@ -858,10 +939,11 @@ void QQuickAnchors::setBaseline(const QQuickAnchorLine &edge) return; } - QQuickItem *oldBaseline = d->baseline.item; - d->baseline = edge; + QQuickItem *oldBaseline = d->baselineAnchorItem; + d->baselineAnchorItem = edge.item; + d->baselineAnchorLine = edge.anchorLine; d->remDepend(oldBaseline); - d->addDepend(d->baseline.item); + d->addDepend(d->baselineAnchorItem); emit baselineChanged(); d->updateVerticalAnchors(); } @@ -870,8 +952,9 @@ void QQuickAnchors::resetBaseline() { Q_D(QQuickAnchors); d->usedAnchors &= ~BaselineAnchor; - d->remDepend(d->baseline.item); - d->baseline = QQuickAnchorLine(); + d->remDepend(d->baselineAnchorItem); + d->baselineAnchorItem = Q_NULLPTR; + d->baselineAnchorLine = QQuickAnchors::InvalidAnchor; emit baselineChanged(); d->updateVerticalAnchors(); } @@ -879,13 +962,14 @@ void QQuickAnchors::resetBaseline() QQuickAnchorLine QQuickAnchors::left() const { Q_D(const QQuickAnchors); - return d->left; + return QQuickAnchorLine(d->leftAnchorItem, d->leftAnchorLine); } void QQuickAnchors::setLeft(const QQuickAnchorLine &edge) { Q_D(QQuickAnchors); - if (!d->checkHAnchorValid(edge) || d->left == edge) + if (!d->checkHAnchorValid(edge) || + (d->leftAnchorItem == edge.item && d->leftAnchorLine == edge.anchorLine)) return; d->usedAnchors |= LeftAnchor; @@ -895,10 +979,11 @@ void QQuickAnchors::setLeft(const QQuickAnchorLine &edge) return; } - QQuickItem *oldLeft = d->left.item; - d->left = edge; + QQuickItem *oldLeft = d->leftAnchorItem; + d->leftAnchorItem = edge.item; + d->leftAnchorLine = edge.anchorLine; d->remDepend(oldLeft); - d->addDepend(d->left.item); + d->addDepend(d->leftAnchorItem); emit leftChanged(); d->updateHorizontalAnchors(); } @@ -907,8 +992,9 @@ void QQuickAnchors::resetLeft() { Q_D(QQuickAnchors); d->usedAnchors &= ~LeftAnchor; - d->remDepend(d->left.item); - d->left = QQuickAnchorLine(); + d->remDepend(d->leftAnchorItem); + d->leftAnchorItem = Q_NULLPTR; + d->leftAnchorLine = QQuickAnchors::InvalidAnchor; emit leftChanged(); d->updateHorizontalAnchors(); } @@ -916,13 +1002,14 @@ void QQuickAnchors::resetLeft() QQuickAnchorLine QQuickAnchors::right() const { Q_D(const QQuickAnchors); - return d->right; + return QQuickAnchorLine(d->rightAnchorItem, d->rightAnchorLine); } void QQuickAnchors::setRight(const QQuickAnchorLine &edge) { Q_D(QQuickAnchors); - if (!d->checkHAnchorValid(edge) || d->right == edge) + if (!d->checkHAnchorValid(edge) || + (d->rightAnchorItem == edge.item && d->rightAnchorLine == edge.anchorLine)) return; d->usedAnchors |= RightAnchor; @@ -932,10 +1019,11 @@ void QQuickAnchors::setRight(const QQuickAnchorLine &edge) return; } - QQuickItem *oldRight = d->right.item; - d->right = edge; + QQuickItem *oldRight = d->rightAnchorItem; + d->rightAnchorItem = edge.item; + d->rightAnchorLine = edge.anchorLine; d->remDepend(oldRight); - d->addDepend(d->right.item); + d->addDepend(d->rightAnchorItem); emit rightChanged(); d->updateHorizontalAnchors(); } @@ -944,8 +1032,9 @@ void QQuickAnchors::resetRight() { Q_D(QQuickAnchors); d->usedAnchors &= ~RightAnchor; - d->remDepend(d->right.item); - d->right = QQuickAnchorLine(); + d->remDepend(d->rightAnchorItem); + d->rightAnchorItem = Q_NULLPTR; + d->rightAnchorLine = QQuickAnchors::InvalidAnchor; emit rightChanged(); d->updateHorizontalAnchors(); } @@ -953,13 +1042,14 @@ void QQuickAnchors::resetRight() QQuickAnchorLine QQuickAnchors::horizontalCenter() const { Q_D(const QQuickAnchors); - return d->hCenter; + return QQuickAnchorLine(d->hCenterAnchorItem, d->hCenterAnchorLine); } void QQuickAnchors::setHorizontalCenter(const QQuickAnchorLine &edge) { Q_D(QQuickAnchors); - if (!d->checkHAnchorValid(edge) || d->hCenter == edge) + if (!d->checkHAnchorValid(edge) || + (d->hCenterAnchorItem == edge.item && d->hCenterAnchorLine == edge.anchorLine)) return; d->usedAnchors |= HCenterAnchor; @@ -969,10 +1059,11 @@ void QQuickAnchors::setHorizontalCenter(const QQuickAnchorLine &edge) return; } - QQuickItem *oldHCenter = d->hCenter.item; - d->hCenter = edge; + QQuickItem *oldHCenter = d->hCenterAnchorItem; + d->hCenterAnchorItem = edge.item; + d->hCenterAnchorLine = edge.anchorLine; d->remDepend(oldHCenter); - d->addDepend(d->hCenter.item); + d->addDepend(d->hCenterAnchorItem); emit horizontalCenterChanged(); d->updateHorizontalAnchors(); } @@ -981,8 +1072,9 @@ void QQuickAnchors::resetHorizontalCenter() { Q_D(QQuickAnchors); d->usedAnchors &= ~HCenterAnchor; - d->remDepend(d->hCenter.item); - d->hCenter = QQuickAnchorLine(); + d->remDepend(d->hCenterAnchorItem); + d->hCenterAnchorItem = Q_NULLPTR; + d->hCenterAnchorLine = QQuickAnchors::InvalidAnchor; emit horizontalCenterChanged(); d->updateHorizontalAnchors(); } @@ -1230,7 +1322,7 @@ void QQuickAnchors::setBaselineOffset(qreal offset) QQuickAnchors::Anchors QQuickAnchors::usedAnchors() const { Q_D(const QQuickAnchors); - return d->usedAnchors; + return static_cast<QQuickAnchors::Anchors>(d->usedAnchors); } bool QQuickAnchorsPrivate::checkHValid() const @@ -1250,10 +1342,11 @@ bool QQuickAnchorsPrivate::checkHAnchorValid(QQuickAnchorLine anchor) const if (!anchor.item) { qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to a null item."); return false; - } else if (anchor.anchorLine & QQuickAnchorLine::Vertical_Mask) { + } else if (anchor.anchorLine & QQuickAnchors::Vertical_Mask) { qmlInfo(item) << QQuickAnchors::tr("Cannot anchor a horizontal edge to a vertical edge."); return false; - } else if (anchor.item != item->parentItem() && anchor.item->parentItem() != item->parentItem()){ + } else if (anchor.item != readParentItem(item) + && readParentItem(anchor.item) != readParentItem(item)) { qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to an item that isn't a parent or sibling."); return false; } else if (anchor.item == item) { @@ -1287,10 +1380,11 @@ bool QQuickAnchorsPrivate::checkVAnchorValid(QQuickAnchorLine anchor) const if (!anchor.item) { qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to a null item."); return false; - } else if (anchor.anchorLine & QQuickAnchorLine::Horizontal_Mask) { + } else if (anchor.anchorLine & QQuickAnchors::Horizontal_Mask) { qmlInfo(item) << QQuickAnchors::tr("Cannot anchor a vertical edge to a horizontal edge."); return false; - } else if (anchor.item != item->parentItem() && anchor.item->parentItem() != item->parentItem()){ + } else if (anchor.item != readParentItem(item) + && readParentItem(anchor.item) != readParentItem(item)) { qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to an item that isn't a parent or sibling."); return false; } else if (anchor.item == item){ diff --git a/src/quick/items/qquickanchors_p.h b/src/quick/items/qquickanchors_p.h index 0e02d80ae8..2b054e4118 100644 --- a/src/quick/items/qquickanchors_p.h +++ b/src/quick/items/qquickanchors_p.h @@ -89,7 +89,14 @@ public: QQuickAnchors(QQuickItem *item, QObject *parent=0); virtual ~QQuickAnchors(); - enum Anchor { + enum Anchor +#if !(defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && (Q_CC_GNU < 500)) + // Not specifying the enum base type will have MSVC 'interpret' it as signed instead of an unsigned bit-field. + // However, specifying the enum base type breaks GCC 4.x on OpenSUSE 13.something, where it complains that it can't store all values in a 7 bit bitfield. + : uint +#endif + { + InvalidAnchor = 0x0, LeftAnchor = 0x01, RightAnchor = 0x02, TopAnchor = 0x04, diff --git a/src/quick/items/qquickanchors_p_p.h b/src/quick/items/qquickanchors_p_p.h index 205d9a40da..da659946c0 100644 --- a/src/quick/items/qquickanchors_p_p.h +++ b/src/quick/items/qquickanchors_p_p.h @@ -60,24 +60,15 @@ QT_BEGIN_NAMESPACE class QQuickAnchorLine { public: - enum AnchorLine { - Invalid = 0x0, - Left = 0x01, - Right = 0x02, - Top = 0x04, - Bottom = 0x08, - HCenter = 0x10, - VCenter = 0x20, - Baseline = 0x40, - Horizontal_Mask = Left | Right | HCenter, - Vertical_Mask = Top | Bottom | VCenter | Baseline - }; - - QQuickAnchorLine() : item(0), anchorLine(Invalid) {} - QQuickAnchorLine(QQuickItem *i, AnchorLine l) : item(i), anchorLine(l) {} + QQuickAnchorLine() : item(0), anchorLine(QQuickAnchors::InvalidAnchor) {} + QQuickAnchorLine(QQuickItem *i, QQuickAnchors::Anchor l) : item(i), anchorLine(l) {} + QQuickAnchorLine(QQuickItem *i, uint l) + : item(i) + , anchorLine(static_cast<QQuickAnchors::Anchor>(l)) + { Q_ASSERT(l < ((QQuickAnchors::BaselineAnchor << 1) - 1)); } QQuickItem *item; - AnchorLine anchorLine; + QQuickAnchors::Anchor anchorLine; }; inline bool operator==(const QQuickAnchorLine& a, const QQuickAnchorLine& b) @@ -90,13 +81,44 @@ class QQuickAnchorsPrivate : public QObjectPrivate, public QQuickItemChangeListe Q_DECLARE_PUBLIC(QQuickAnchors) public: QQuickAnchorsPrivate(QQuickItem *i) - : componentComplete(true), updatingMe(false), inDestructor(false), centerAligned(true), - leftMarginExplicit(false), rightMarginExplicit(false), topMarginExplicit(false), - bottomMarginExplicit(false), updatingHorizontalAnchor(0), - updatingVerticalAnchor(0), updatingFill(0), updatingCenterIn(0), item(i), usedAnchors(0), fill(0), - centerIn(0), leftMargin(0), rightMargin(0), topMargin(0), bottomMargin(0), - margins(0), vCenterOffset(0), hCenterOffset(0), baselineOffset(0) - + : leftMargin(0) + , rightMargin(0) + , topMargin(0) + , bottomMargin(0) + , margins(0) + , vCenterOffset(0) + , hCenterOffset(0) + , baselineOffset(0) + , item(i) + , fill(Q_NULLPTR) + , centerIn(Q_NULLPTR) + , leftAnchorItem(Q_NULLPTR) + , rightAnchorItem(Q_NULLPTR) + , topAnchorItem(Q_NULLPTR) + , bottomAnchorItem(Q_NULLPTR) + , vCenterAnchorItem(Q_NULLPTR) + , hCenterAnchorItem(Q_NULLPTR) + , baselineAnchorItem(Q_NULLPTR) + , leftAnchorLine(QQuickAnchors::InvalidAnchor) + , leftMarginExplicit(false) + , rightAnchorLine(QQuickAnchors::InvalidAnchor) + , rightMarginExplicit(false) + , topAnchorLine(QQuickAnchors::InvalidAnchor) + , topMarginExplicit(false) + , bottomAnchorLine(QQuickAnchors::InvalidAnchor) + , bottomMarginExplicit(false) + , vCenterAnchorLine(QQuickAnchors::InvalidAnchor) + , updatingMe(false) + , hCenterAnchorLine(QQuickAnchors::InvalidAnchor) + , inDestructor(false) + , baselineAnchorLine(QQuickAnchors::InvalidAnchor) + , centerAligned(true) + , updatingFill(0) + , updatingCenterIn(0) + , updatingHorizontalAnchor(0) + , updatingVerticalAnchor(0) + , componentComplete(true) + , usedAnchors(QQuickAnchors::InvalidAnchor) { } @@ -107,19 +129,6 @@ public: void remDepend(QQuickItem *); bool isItemComplete() const; - bool componentComplete:1; - bool updatingMe:1; - bool inDestructor:1; - bool centerAligned:1; - bool leftMarginExplicit : 1; - bool rightMarginExplicit : 1; - bool topMarginExplicit : 1; - bool bottomMarginExplicit : 1; - uint updatingHorizontalAnchor:2; - uint updatingVerticalAnchor:2; - uint updatingFill:2; - uint updatingCenterIn:2; - void setItemHeight(qreal); void setItemWidth(qreal); void setItemX(qreal); @@ -139,7 +148,9 @@ public: bool checkVValid() const; bool checkHAnchorValid(QQuickAnchorLine anchor) const; bool checkVAnchorValid(QQuickAnchorLine anchor) const; - bool calcStretch(const QQuickAnchorLine &edge1, const QQuickAnchorLine &edge2, qreal offset1, qreal offset2, QQuickAnchorLine::AnchorLine line, qreal &stretch); + bool calcStretch(QQuickItem *edge1Item, QQuickAnchors::Anchor edge1Line, + QQuickItem *edge2Item, QQuickAnchors::Anchor edge2Line, + qreal offset1, qreal offset2, QQuickAnchors::Anchor line, qreal &stretch); bool isMirrored() const; void updateHorizontalAnchors(); @@ -147,20 +158,6 @@ public: void fillChanged(); void centerInChanged(); - QQuickItem *item; - QQuickAnchors::Anchors usedAnchors; - - QQuickItem *fill; - QQuickItem *centerIn; - - QQuickAnchorLine left; - QQuickAnchorLine right; - QQuickAnchorLine top; - QQuickAnchorLine bottom; - QQuickAnchorLine vCenter; - QQuickAnchorLine hCenter; - QQuickAnchorLine baseline; - qreal leftMargin; qreal rightMargin; qreal topMargin; @@ -170,6 +167,44 @@ public: qreal hCenterOffset; qreal baselineOffset; + QQuickItem *item; + + QQuickItem *fill; + QQuickItem *centerIn; + + QQuickItem *leftAnchorItem; + QQuickItem *rightAnchorItem; + QQuickItem *topAnchorItem; + QQuickItem *bottomAnchorItem; + QQuickItem *vCenterAnchorItem; + QQuickItem *hCenterAnchorItem; + QQuickItem *baselineAnchorItem; + + // The bit fields below are carefully laid out in chunks of 1 byte, so the compiler doesn't + // need to generate 2 loads (and combining shifts/ors) to create a single field. + + QQuickAnchors::Anchor leftAnchorLine : 7; + uint leftMarginExplicit : 1; + QQuickAnchors::Anchor rightAnchorLine : 7; + uint rightMarginExplicit : 1; + QQuickAnchors::Anchor topAnchorLine : 7; + uint topMarginExplicit : 1; + QQuickAnchors::Anchor bottomAnchorLine : 7; + uint bottomMarginExplicit : 1; + + QQuickAnchors::Anchor vCenterAnchorLine : 7; + uint updatingMe : 1; + QQuickAnchors::Anchor hCenterAnchorLine : 7; + uint inDestructor : 1; + QQuickAnchors::Anchor baselineAnchorLine : 7; + uint centerAligned : 1; + uint updatingFill : 2; + uint updatingCenterIn : 2; + uint updatingHorizontalAnchor : 2; + uint updatingVerticalAnchor : 2; + + uint componentComplete : 1; + uint usedAnchors : 7; // QQuickAnchors::Anchors static inline QQuickAnchorsPrivate *get(QQuickAnchors *o) { return static_cast<QQuickAnchorsPrivate *>(QObjectPrivate::get(o)); diff --git a/src/quick/items/qquickanimatedimage.cpp b/src/quick/items/qquickanimatedimage.cpp index 42033b6135..6f14bf15fe 100644 --- a/src/quick/items/qquickanimatedimage.cpp +++ b/src/quick/items/qquickanimatedimage.cpp @@ -306,8 +306,9 @@ void QQuickAnimatedImage::load() d->status = Null; emit statusChanged(d->status); - if (sourceSize() != d->oldSourceSize) { - d->oldSourceSize = sourceSize(); + d->currentSourceSize = QSize(0, 0); + if (d->currentSourceSize != d->oldSourceSize) { + d->oldSourceSize = d->currentSourceSize; emit sourceSizeChanged(); } if (isPlaying() != d->oldPlaying) @@ -383,8 +384,9 @@ void QQuickAnimatedImage::movieRequestFinished() d->status = Error; emit statusChanged(d->status); - if (sourceSize() != d->oldSourceSize) { - d->oldSourceSize = sourceSize(); + d->currentSourceSize = QSize(0, 0); + if (d->currentSourceSize != d->oldSourceSize) { + d->oldSourceSize = d->currentSourceSize; emit sourceSizeChanged(); } if (isPlaying() != d->oldPlaying) @@ -421,8 +423,14 @@ void QQuickAnimatedImage::movieRequestFinished() if (isPlaying() != d->oldPlaying) emit playingChanged(); - if (sourceSize() != d->oldSourceSize) { - d->oldSourceSize = sourceSize(); + + if (d->_movie) + d->currentSourceSize = d->_movie->currentPixmap().size(); + else + d->currentSourceSize = QSize(0, 0); + + if (d->currentSourceSize != d->oldSourceSize) { + d->oldSourceSize = d->currentSourceSize; emit sourceSizeChanged(); } } @@ -475,9 +483,7 @@ void QQuickAnimatedImage::onCacheChanged() QSize QQuickAnimatedImage::sourceSize() { Q_D(QQuickAnimatedImage); - if (!d->_movie) - return QSize(0, 0); - return QSize(d->_movie->currentPixmap().size()); + return d->currentSourceSize; } void QQuickAnimatedImage::componentComplete() diff --git a/src/quick/items/qquickanimatedimage_p_p.h b/src/quick/items/qquickanimatedimage_p_p.h index 9b284f966d..ed735d1c9c 100644 --- a/src/quick/items/qquickanimatedimage_p_p.h +++ b/src/quick/items/qquickanimatedimage_p_p.h @@ -72,6 +72,7 @@ public: #ifndef QT_NO_NETWORK , reply(0), redirectCount(0) #endif + , currentSourceSize(0, 0) { } @@ -87,6 +88,7 @@ public: int redirectCount; #endif QMap<int, QQuickPixmap *> frameMap; + QSize currentSourceSize; }; QT_END_NAMESPACE diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp index 76e13bc985..cc30199253 100644 --- a/src/quick/items/qquickdrag.cpp +++ b/src/quick/items/qquickdrag.cpp @@ -310,13 +310,14 @@ void QQuickDragAttached::setActive(bool active) else if (active) { if (d->dragType == QQuickDrag::Internal) { d->start(d->supportedActions); - } - else if (d->dragType == QQuickDrag::Automatic) { - // There are different semantics than start() since startDrag() - // may be called after an internal drag is already started. - active = true; + } else { + d->active = true; emit activeChanged(); - d->startDrag(d->supportedActions); + if (d->dragType == QQuickDrag::Automatic) { + // There are different semantics than start() since startDrag() + // may be called after an internal drag is already started. + d->startDrag(d->supportedActions); + } } } else diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp index 34b8f0ac49..c04a526bd0 100644 --- a/src/quick/items/qquickimage.cpp +++ b/src/quick/items/qquickimage.cpp @@ -714,9 +714,9 @@ QSGNode *QQuickImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) sourceRect.height() / nsHeight); if (targetRect.isEmpty() - || !qIsFinite(targetRect.width()) || !qIsFinite(targetRect.height()) + || !qt_is_finite(targetRect.width()) || !qt_is_finite(targetRect.height()) || nsrect.isEmpty() - || !qIsFinite(nsrect.width()) || !qIsFinite(nsrect.height())) { + || !qt_is_finite(nsrect.width()) || !qt_is_finite(nsrect.height())) { delete node; return 0; } diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp index 8117baa2fe..60e31631c0 100644 --- a/src/quick/items/qquickimagebase.cpp +++ b/src/quick/items/qquickimagebase.cpp @@ -225,7 +225,7 @@ void QQuickImageBase::load() // sourceSize is set. If sourceSize is not set then the provider default size // will be used, as usual. bool setDevicePixelRatio = false; - if (!d->sourcesize.isValid()) { + if (d->sourcesize.isValid()) { if (loadUrl.scheme() == QLatin1String("image")) { setDevicePixelRatio = true; } else { diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 1100b12cbc..d6fdf5795e 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -1632,7 +1632,7 @@ void QQuickItemPrivate::setLayoutMirror(bool mirror) */ /*! - \qmlproperty enumeration QtQuick::EnterKey::type + \qmlattachedproperty enumeration QtQuick::EnterKey::type Holds the type of the Enter key. @@ -2647,7 +2647,7 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) QQuickItem *scopeItem = 0; - if (hasFocus()) + if (hasFocus() || op->subFocusItem == this) scopeFocusedItem = this; else if (!isFocusScope() && d->subFocusItem) scopeFocusedItem = d->subFocusItem; @@ -3117,7 +3117,6 @@ QQuickItemPrivate::QQuickItemPrivate() , flags(0) , widthValid(false) , heightValid(false) - , baselineOffsetValid(false) , componentComplete(true) , keepMouse(false) , keepTouch(false) @@ -3192,7 +3191,7 @@ void QQuickItemPrivate::init(QQuickItem *parent) registerAccessorProperties(); - baselineOffsetValid = false; + baselineOffset = 0.0; if (parent) { q->setParentItem(parent); @@ -4168,6 +4167,23 @@ QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const if (d->extra.isAllocated() && d->extra->enterKeyAttached) v = d->extra->enterKeyAttached->type(); break; + case Qt::ImInputItemClipRectangle: + if (!(!window() ||!isVisible() || qFuzzyIsNull(opacity()))) { + QRectF rect = QRectF(0,0, width(), height()); + const QQuickItem *par = this; + while (QQuickItem *parpar = par->parentItem()) { + rect = parpar->mapRectFromItem(par, rect); + if (parpar->clip()) + rect = rect.intersected(parpar->clipRect()); + par = parpar; + } + rect = par->mapRectToScene(rect); + // once we have the rect in scene coordinates, clip to window + rect = rect.intersected(QRectF(QPoint(0,0), window()->size())); + // map it back to local coordinates + v = mapRectFromScene(rect); + } + break; default: break; } @@ -4179,43 +4195,43 @@ QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const QQuickAnchorLine QQuickItemPrivate::left() const { Q_Q(const QQuickItem); - return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::Left); + return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::LeftAnchor); } QQuickAnchorLine QQuickItemPrivate::right() const { Q_Q(const QQuickItem); - return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::Right); + return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::RightAnchor); } QQuickAnchorLine QQuickItemPrivate::horizontalCenter() const { Q_Q(const QQuickItem); - return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::HCenter); + return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::HCenterAnchor); } QQuickAnchorLine QQuickItemPrivate::top() const { Q_Q(const QQuickItem); - return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::Top); + return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::TopAnchor); } QQuickAnchorLine QQuickItemPrivate::bottom() const { Q_Q(const QQuickItem); - return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::Bottom); + return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::BottomAnchor); } QQuickAnchorLine QQuickItemPrivate::verticalCenter() const { Q_Q(const QQuickItem); - return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::VCenter); + return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::VCenterAnchor); } QQuickAnchorLine QQuickItemPrivate::baseline() const { Q_Q(const QQuickItem); - return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::Baseline); + return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::BaselineAnchor); } /*! @@ -4243,11 +4259,7 @@ QQuickAnchorLine QQuickItemPrivate::baseline() const qreal QQuickItem::baselineOffset() const { Q_D(const QQuickItem); - if (d->baselineOffsetValid) { - return d->baselineOffset; - } else { - return 0.0; - } + return d->baselineOffset; } void QQuickItem::setBaselineOffset(qreal offset) @@ -4257,7 +4269,6 @@ void QQuickItem::setBaselineOffset(qreal offset) return; d->baselineOffset = offset; - d->baselineOffsetValid = true; for (int ii = 0; ii < d->changeListeners.count(); ++ii) { const QQuickItemPrivate::ChangeListener &change = d->changeListeners.at(ii); @@ -6253,6 +6264,8 @@ QPointF QQuickItem::position() const void QQuickItem::setX(qreal v) { Q_D(QQuickItem); + if (qIsNaN(v)) + return; if (d->x == v) return; @@ -6268,6 +6281,8 @@ void QQuickItem::setX(qreal v) void QQuickItem::setY(qreal v) { Q_D(QQuickItem); + if (qIsNaN(v)) + return; if (d->y == v) return; diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index da1d430ac2..854cbd769b 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -402,7 +402,6 @@ public: quint32 flags:5; bool widthValid:1; bool heightValid:1; - bool baselineOffsetValid:1; bool componentComplete:1; bool keepMouse:1; bool keepTouch:1; @@ -411,8 +410,8 @@ public: bool antialiasing:1; bool focus:1; bool activeFocus:1; - // Bit 16 bool notifiedFocus:1; + // Bit 16 bool notifiedActiveFocus:1; bool filtersChildMouseEvents:1; bool explicitVisible:1; @@ -428,8 +427,8 @@ public: bool isAccessible:1; bool culled:1; bool hasCursor:1; - // Bit 32 bool hasCursorInChild:1; + // Bit 32 bool hasHoverInChild:1; bool activeFocusOnTab:1; bool implicitAntialiasing:1; diff --git a/src/quick/items/qquickitemgrabresult.cpp b/src/quick/items/qquickitemgrabresult.cpp index 6822e4042c..d05ecc9076 100644 --- a/src/quick/items/qquickitemgrabresult.cpp +++ b/src/quick/items/qquickitemgrabresult.cpp @@ -58,6 +58,7 @@ class QQuickItemGrabResultPrivate : public QObjectPrivate public: QQuickItemGrabResultPrivate() : cacheEntry(0) + , qmlEngine(0) , texture(0) { } diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index 6bcc3248ce..0b413b76b6 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -286,6 +286,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType<QQuickGridView, 7>(uri, 2, 7, "GridView"); qmlRegisterType<QQuickTextInput, 7>(uri, 2, 7, "TextInput"); qmlRegisterType<QQuickTextEdit, 7>(uri, 2, 7, "TextEdit"); + qmlRegisterType<QQuickPathView, 7>(uri, 2, 7, "PathView"); qmlRegisterUncreatableType<QQuickMouseEvent, 7>(uri, 2, 7, nullptr, QQuickMouseEvent::tr("MouseEvent is only available within handlers in MouseArea")); } diff --git a/src/quick/items/qquickpainteditem.cpp b/src/quick/items/qquickpainteditem.cpp index 707214e8de..75919d0791 100644 --- a/src/quick/items/qquickpainteditem.cpp +++ b/src/quick/items/qquickpainteditem.cpp @@ -663,4 +663,11 @@ QSGTextureProvider *QQuickPaintedItem::textureProvider() const return d->textureProvider; } +void QQuickPaintedItem::itemChange(ItemChange change, const ItemChangeData &value) +{ + if (change == ItemDevicePixelRatioHasChanged) + update(); + QQuickItem::itemChange(change, value); +} + QT_END_NAMESPACE diff --git a/src/quick/items/qquickpainteditem.h b/src/quick/items/qquickpainteditem.h index f9e3c91a42..e8b471ac01 100644 --- a/src/quick/items/qquickpainteditem.h +++ b/src/quick/items/qquickpainteditem.h @@ -121,6 +121,7 @@ protected: QQuickPaintedItem(QQuickPaintedItemPrivate &dd, QQuickItem *parent = Q_NULLPTR); QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE; void releaseResources() Q_DECL_OVERRIDE; + void itemChange(ItemChange, const ItemChangeData &) Q_DECL_OVERRIDE; private Q_SLOTS: void invalidateSceneGraph(); diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp index f0bbb1e732..e3d218ff01 100644 --- a/src/quick/items/qquickpathview.cpp +++ b/src/quick/items/qquickpathview.cpp @@ -105,7 +105,8 @@ QQuickPathViewPrivate::QQuickPathViewPrivate() , dragMargin(0), deceleration(100), maximumFlickVelocity(QML_FLICK_DEFAULTMAXVELOCITY) , moveOffset(this, &QQuickPathViewPrivate::setAdjustedOffset), flickDuration(0) , pathItems(-1), requestedIndex(-1), cacheSize(0), requestedZ(0) - , moveReason(Other), moveDirection(Shortest), attType(0), highlightComponent(0), highlightItem(0) + , moveReason(Other), movementDirection(QQuickPathView::Shortest), moveDirection(QQuickPathView::Shortest) + , attType(0), highlightComponent(0), highlightItem(0) , moveHighlight(this, &QQuickPathViewPrivate::setHighlightPosition) , highlightPosition(0) , highlightRangeStart(0), highlightRangeEnd(0) @@ -790,7 +791,7 @@ QQuickItem *QQuickPathView::currentItem() const void QQuickPathView::incrementCurrentIndex() { Q_D(QQuickPathView); - d->moveDirection = QQuickPathViewPrivate::Positive; + d->moveDirection = QQuickPathView::Positive; setCurrentIndex(currentIndex()+1); } @@ -804,7 +805,7 @@ void QQuickPathView::incrementCurrentIndex() void QQuickPathView::decrementCurrentIndex() { Q_D(QQuickPathView); - d->moveDirection = QQuickPathViewPrivate::Negative; + d->moveDirection = QQuickPathView::Negative; setCurrentIndex(currentIndex()-1); } @@ -1373,6 +1374,48 @@ void QQuickPathView::setSnapMode(SnapMode mode) } /*! + \qmlproperty enumeration QtQuick::PathView::movementDirection + \since 5.7 + + This property determines the direction in which items move when setting the current index. + The possible values are: + + \list + \li PathView.Shortest (default) - the items move in the direction that requires the least + movement, which could be either \c Negative or \c Positive. + \li PathView.Negative - the items move backwards towards their destination. + \li PathView.Positive - the items move forwards towards their destination. + \endlist + + For example, suppose that there are 5 items in the model, and \l currentIndex is \c 0. + If currentIndex is set to \c 2, + + \list + \li a \c Positive movement direction will result in the following order: 0, 1, 2 + \li a \c Negative movement direction will result in the following order: 0, 5, 4, 3, 2 + \li a \c Shortest movement direction will result in same order with \c Positive . + \endlist + + \note this property doesn't affect the movement of \l incrementCurrentIndex() and \l decrementCurrentIndex(). +*/ +QQuickPathView::MovementDirection QQuickPathView::movementDirection() const +{ + Q_D(const QQuickPathView); + return d->movementDirection; +} + +void QQuickPathView::setMovementDirection(QQuickPathView::MovementDirection dir) +{ + Q_D(QQuickPathView); + if (dir == d->movementDirection) + return; + d->movementDirection = dir; + if (!d->tl.isActive()) + d->moveDirection = d->movementDirection; + emit movementDirectionChanged(); +} + +/*! \qmlmethod QtQuick::PathView::positionViewAtIndex(int index, PositionMode mode) Positions the view such that the \a index is at the position specified by @@ -1910,7 +1953,7 @@ void QQuickPathView::refill() if (lcItemViewDelegateLifecycle().isDebugEnabled()) { QQuickText *text = qmlobject_cast<QQuickText*>(item); if (text) - qCDebug(lcItemViewDelegateLifecycle) << "idx" << idx << "@" << pos << ": QQuickText" << text->objectName() << text->text().left(40); + qCDebug(lcItemViewDelegateLifecycle) << "idx" << idx << "@" << pos << ": QQuickText" << text->objectName() << text->text().leftRef(40); else qCDebug(lcItemViewDelegateLifecycle) << "idx" << idx << "@" << pos << ":" << item; } @@ -2231,6 +2274,7 @@ void QQuickPathView::movementEnding() emit movingChanged(); emit movementEnded(); } + d->moveDirection = d->movementDirection; } // find the item closest to the snap position @@ -2340,7 +2384,7 @@ void QQuickPathViewPrivate::snapToIndex(int index, MovementReason reason) if (!duration) { tl.set(moveOffset, targetOffset); - } else if (moveDirection == Positive || (moveDirection == Shortest && targetOffset - offset > modelCount/2.0)) { + } else if (moveDirection == QQuickPathView::Positive || (moveDirection == QQuickPathView::Shortest && targetOffset - offset > modelCount/2.0)) { qreal distance = modelCount - targetOffset + offset; if (targetOffset > moveOffset) { tl.move(moveOffset, 0.0, QEasingCurve(QEasingCurve::InQuad), int(duration * offset / distance)); @@ -2349,7 +2393,7 @@ void QQuickPathViewPrivate::snapToIndex(int index, MovementReason reason) } else { tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), duration); } - } else if (moveDirection == Negative || targetOffset - offset <= -modelCount/2.0) { + } else if (moveDirection == QQuickPathView::Negative || targetOffset - offset <= -modelCount/2.0) { qreal distance = modelCount - offset + targetOffset; if (targetOffset < moveOffset) { tl.move(moveOffset, modelCount, QEasingCurve(targetOffset == 0 ? QEasingCurve::InOutQuad : QEasingCurve::InQuad), int(duration * (modelCount-offset) / distance)); @@ -2361,7 +2405,6 @@ void QQuickPathViewPrivate::snapToIndex(int index, MovementReason reason) } else { tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), duration); } - moveDirection = Shortest; } QQuickPathViewAttached *QQuickPathView::qmlAttachedProperties(QObject *obj) diff --git a/src/quick/items/qquickpathview_p.h b/src/quick/items/qquickpathview_p.h index 341af02013..daec965f02 100644 --- a/src/quick/items/qquickpathview_p.h +++ b/src/quick/items/qquickpathview_p.h @@ -92,6 +92,7 @@ class Q_AUTOTEST_EXPORT QQuickPathView : public QQuickItem Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged) Q_PROPERTY(int pathItemCount READ pathItemCount WRITE setPathItemCount RESET resetPathItemCount NOTIFY pathItemCountChanged) Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged) + Q_PROPERTY(MovementDirection movementDirection READ movementDirection WRITE setMovementDirection NOTIFY movementDirectionChanged REVISION 7) Q_PROPERTY(int cacheItemCount READ cacheItemCount WRITE setCacheItemCount NOTIFY cacheItemCountChanged) @@ -164,6 +165,11 @@ public: SnapMode snapMode() const; void setSnapMode(SnapMode mode); + enum MovementDirection { Shortest, Negative, Positive }; + Q_ENUM(MovementDirection) + MovementDirection movementDirection() const; + void setMovementDirection(MovementDirection dir); + enum PositionMode { Beginning, Center, End, Contain=4, SnapPosition }; // 3 == Visible in other views Q_ENUM(PositionMode) Q_INVOKABLE void positionViewAtIndex(int index, int mode); @@ -201,6 +207,7 @@ Q_SIGNALS: void highlightMoveDurationChanged(); void movementStarted(); void movementEnded(); + Q_REVISION(7) void movementDirectionChanged(); void flickStarted(); void flickEnded(); void dragStarted(); diff --git a/src/quick/items/qquickpathview_p_p.h b/src/quick/items/qquickpathview_p_p.h index 8236d9efd2..d9c4baf572 100644 --- a/src/quick/items/qquickpathview_p_p.h +++ b/src/quick/items/qquickpathview_p_p.h @@ -171,8 +171,8 @@ public: QPointer<QQmlInstanceModel> model; QVariant modelVariant; MovementReason moveReason; - enum MovementDirection { Shortest, Negative, Positive }; - MovementDirection moveDirection; + QQuickPathView::MovementDirection movementDirection; // default + QQuickPathView::MovementDirection moveDirection; // next movement QQmlOpenMetaObjectType *attType; QQmlComponent *highlightComponent; QQuickItem *highlightItem; diff --git a/src/quick/items/qquickscalegrid.cpp b/src/quick/items/qquickscalegrid.cpp index f860c08bad..d7a0f1b681 100644 --- a/src/quick/items/qquickscalegrid.cpp +++ b/src/quick/items/qquickscalegrid.cpp @@ -136,39 +136,38 @@ QQuickGridScaledImage::QQuickGridScaledImage(QIODevice *data) if (colonId <= 0) return; - QStringList list; - list.append(line.left(colonId).trimmed()); - list.append(line.mid(colonId+1).trimmed()); - - if (list[0] == QLatin1String("border.left")) - l = list[1].toInt(); - else if (list[0] == QLatin1String("border.right")) - r = list[1].toInt(); - else if (list[0] == QLatin1String("border.top")) - t = list[1].toInt(); - else if (list[0] == QLatin1String("border.bottom")) - b = list[1].toInt(); - else if (list[0] == QLatin1String("source")) - imgFile = list[1]; - else if (list[0] == QLatin1String("horizontalTileRule") || list[0] == QLatin1String("horizontalTileMode")) - _h = stringToRule(list[1]); - else if (list[0] == QLatin1String("verticalTileRule") || list[0] == QLatin1String("verticalTileMode")) - _v = stringToRule(list[1]); + const QStringRef property = line.leftRef(colonId).trimmed(); + QStringRef value = line.midRef(colonId + 1).trimmed(); + + if (property == QLatin1String("border.left")) { + l = value.toInt(); + } else if (property == QLatin1String("border.right")) { + r = value.toInt(); + } else if (property == QLatin1String("border.top")) { + t = value.toInt(); + } else if (property == QLatin1String("border.bottom")) { + b = value.toInt(); + } else if (property == QLatin1String("source")) { + if (value.startsWith(QLatin1Char('"')) && value.endsWith(QLatin1Char('"'))) + value = value.mid(1, value.size() - 2); // remove leading/trailing quotes. + imgFile = value.toString(); + } else if (property == QLatin1String("horizontalTileRule") || property == QLatin1String("horizontalTileMode")) { + _h = stringToRule(value); + } else if (property == QLatin1String("verticalTileRule") || property == QLatin1String("verticalTileMode")) { + _v = stringToRule(value); + } } if (l < 0 || r < 0 || t < 0 || b < 0 || imgFile.isEmpty()) return; _l = l; _r = r; _t = t; _b = b; - _pix = imgFile; - if (_pix.startsWith(QLatin1Char('"')) && _pix.endsWith(QLatin1Char('"'))) - _pix = _pix.mid(1, _pix.size() - 2); // remove leading/trailing quotes. } -QQuickBorderImage::TileMode QQuickGridScaledImage::stringToRule(const QString &s) +QQuickBorderImage::TileMode QQuickGridScaledImage::stringToRule(const QStringRef &s) { - QString string = s; + QStringRef string = s; if (string.startsWith(QLatin1Char('"')) && string.endsWith(QLatin1Char('"'))) string = string.mid(1, string.size() - 2); // remove leading/trailing quotes. diff --git a/src/quick/items/qquickscalegrid_p_p.h b/src/quick/items/qquickscalegrid_p_p.h index a424002dfb..7f6a31a7bd 100644 --- a/src/quick/items/qquickscalegrid_p_p.h +++ b/src/quick/items/qquickscalegrid_p_p.h @@ -116,7 +116,7 @@ public: QString pixmapUrl() const; private: - static QQuickBorderImage::TileMode stringToRule(const QString &); + static QQuickBorderImage::TileMode stringToRule(const QStringRef &); private: int _l; diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp index 41b7ea3896..d5c0cc8180 100644 --- a/src/quick/items/qquickshadereffect.cpp +++ b/src/quick/items/qquickshadereffect.cpp @@ -1041,7 +1041,6 @@ QSGNode *QQuickShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDa builder.appendSourceFile(QStringLiteral(":/qt-project.org/items/shaders/shadereffect.vert")); s.sourceCode[Key::VertexShader] = builder.source(); } - s.className = metaObject()->className(); material->setProgramSource(s); material->attributes = m_common.attributes; diff --git a/src/quick/items/qquickshadereffectnode.cpp b/src/quick/items/qquickshadereffectnode.cpp index a06fe26a9c..246a713dca 100644 --- a/src/quick/items/qquickshadereffectnode.cpp +++ b/src/quick/items/qquickshadereffectnode.cpp @@ -333,8 +333,6 @@ const char *QQuickCustomMaterialShader::fragmentShader() const bool QQuickShaderEffectMaterialKey::operator == (const QQuickShaderEffectMaterialKey &other) const { - if (className != other.className) - return false; for (int shaderType = 0; shaderType < ShaderTypeCount; ++shaderType) { if (sourceCode[shaderType] != other.sourceCode[shaderType]) return false; @@ -349,7 +347,7 @@ bool QQuickShaderEffectMaterialKey::operator != (const QQuickShaderEffectMateria uint qHash(const QQuickShaderEffectMaterialKey &key) { - uint hash = qHash((const void *)key.className); + uint hash = 1; typedef QQuickShaderEffectMaterialKey Key; for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) hash = hash * 31337 + qHash(key.sourceCode[shaderType]); diff --git a/src/quick/items/qquickshadereffectnode_p.h b/src/quick/items/qquickshadereffectnode_p.h index cc016d13a7..ff32f4e290 100644 --- a/src/quick/items/qquickshadereffectnode_p.h +++ b/src/quick/items/qquickshadereffectnode_p.h @@ -71,7 +71,6 @@ struct QQuickShaderEffectMaterialKey { }; QByteArray sourceCode[ShaderTypeCount]; - const char *className; bool operator == (const QQuickShaderEffectMaterialKey &other) const; bool operator != (const QQuickShaderEffectMaterialKey &other) const; diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h index 0b35ad5f91..40dbd51f39 100644 --- a/src/quick/items/qquicktext_p.h +++ b/src/quick/items/qquicktext_p.h @@ -254,16 +254,16 @@ Q_SIGNALS: void fontChanged(const QFont &font); void colorChanged(); void linkColorChanged(); - void styleChanged(TextStyle style); + void styleChanged(QQuickText::TextStyle style); void styleColorChanged(); - void horizontalAlignmentChanged(HAlignment alignment); - void verticalAlignmentChanged(VAlignment alignment); + void horizontalAlignmentChanged(QQuickText::HAlignment alignment); + void verticalAlignmentChanged(QQuickText::VAlignment alignment); void wrapModeChanged(); void lineCountChanged(); void truncatedChanged(); void maximumLineCountChanged(); - void textFormatChanged(TextFormat textFormat); - void elideModeChanged(TextElideMode mode); + void textFormatChanged(QQuickText::TextFormat textFormat); + void elideModeChanged(QQuickText::TextElideMode mode); void contentSizeChanged(); void lineHeightChanged(qreal lineHeight); void lineHeightModeChanged(LineHeightMode mode); diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp index 8b6cc221d5..45238e2d0c 100644 --- a/src/quick/items/qquicktextcontrol.cpp +++ b/src/quick/items/qquicktextcontrol.cpp @@ -109,6 +109,7 @@ QQuickTextControlPrivate::QQuickTextControlPrivate() overwriteMode(false), acceptRichText(true), cursorVisible(false), + cursorBlinkingEnabled(false), hasFocus(false), hadSelectionOnMousePress(false), wordSelectionEnabled(false), @@ -463,14 +464,30 @@ void QQuickTextControlPrivate::_q_updateCursorPosChanged(const QTextCursor &some void QQuickTextControlPrivate::setBlinkingCursorEnabled(bool enable) { - Q_Q(QQuickTextControl); + if (cursorBlinkingEnabled == enable) + return; + + cursorBlinkingEnabled = enable; + updateCursorFlashTime(); - if (enable && QGuiApplication::styleHints()->cursorFlashTime() > 0) - cursorBlinkTimer.start(QGuiApplication::styleHints()->cursorFlashTime() / 2, q); + if (enable) + connect(qApp->styleHints(), &QStyleHints::cursorFlashTimeChanged, this, &QQuickTextControlPrivate::updateCursorFlashTime); else - cursorBlinkTimer.stop(); + disconnect(qApp->styleHints(), &QStyleHints::cursorFlashTimeChanged, this, &QQuickTextControlPrivate::updateCursorFlashTime); +} - cursorOn = enable; +void QQuickTextControlPrivate::updateCursorFlashTime() +{ + // Note: cursorOn represents the current blinking state controlled by a timer, and + // should not be confused with cursorVisible or cursorBlinkingEnabled. However, we + // interpretate a cursorFlashTime of 0 to mean "always on, never blink". + cursorOn = true; + int flashTime = QGuiApplication::styleHints()->cursorFlashTime(); + + if (cursorBlinkingEnabled && flashTime >= 2) + cursorBlinkTimer.start(flashTime / 2, q_func()); + else + cursorBlinkTimer.stop(); repaintCursor(); } diff --git a/src/quick/items/qquicktextcontrol_p_p.h b/src/quick/items/qquicktextcontrol_p_p.h index f312fcb1ce..0f78feb5de 100644 --- a/src/quick/items/qquicktextcontrol_p_p.h +++ b/src/quick/items/qquicktextcontrol_p_p.h @@ -97,6 +97,7 @@ public: void _q_updateCursorPosChanged(const QTextCursor &someCursor); void setBlinkingCursorEnabled(bool enable); + void updateCursorFlashTime(); void extendWordwiseSelection(int suggestedNewPosition, qreal mouseXPosition); void extendBlockwiseSelection(int suggestedNewPosition); @@ -156,6 +157,7 @@ public: bool overwriteMode : 1; bool acceptRichText : 1; bool cursorVisible : 1; // used to hide the cursor in the preedit area + bool cursorBlinkingEnabled : 1; bool hasFocus : 1; bool hadSelectionOnMousePress : 1; bool wordSelectionEnabled : 1; diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index 8bb788d008..36eb5d3cde 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -1901,6 +1901,9 @@ QVariant QQuickTextEdit::inputMethodQuery(Qt::InputMethodQuery property, QVarian case Qt::ImHints: v = (int)d->effectiveInputMethodHints(); break; + case Qt::ImInputItemClipRectangle: + v = QQuickItem::inputMethodQuery(property); + break; default: if (property == Qt::ImCursorPosition && !argument.isNull()) argument = QVariant(argument.toPointF() - QPointF(d->xoff, d->yoff)); diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index f361d46424..9b7eb4ea4b 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -792,12 +792,8 @@ void QQuickTextInput::setCursorVisible(bool on) d->cursorVisible = on; if (on && isComponentComplete()) QQuickTextUtil::createCursor(d); - if (!d->cursorItem) { - d->setCursorBlinkPeriod(on ? QGuiApplication::styleHints()->cursorFlashTime() : 0); - d->updateType = QQuickTextInputPrivate::UpdatePaintNode; - polish(); - update(); - } + if (!d->cursorItem) + d->updateCursorBlinking(); emit cursorVisibleChanged(d->cursorVisible); } @@ -1858,7 +1854,7 @@ QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData node = new QQuickTextNode(this); d->textNode = node; - const bool showCursor = !isReadOnly() && d->cursorItem == 0 && d->cursorVisible && (d->m_blinkStatus || d->m_blinkPeriod == 0); + const bool showCursor = !isReadOnly() && d->cursorItem == 0 && d->cursorVisible && d->m_blinkStatus; if (!d->textLayoutDirty && oldNode != 0) { if (showCursor) @@ -1954,7 +1950,7 @@ QVariant QQuickTextInput::inputMethodQuery(Qt::InputMethodQuery property, QVaria return QVariant(d->m_text.mid(d->m_cursor)); case Qt::ImTextBeforeCursor: if (argument.isValid()) - return QVariant(d->m_text.left(d->m_cursor).right(argument.toInt())); + return QVariant(d->m_text.leftRef(d->m_cursor).right(argument.toInt()).toString()); return QVariant(d->m_text.left(d->m_cursor)); default: return QQuickItem::inputMethodQuery(property); @@ -2594,8 +2590,10 @@ void QQuickTextInputPrivate::handleFocusEvent(QFocusEvent *event) { Q_Q(QQuickTextInput); bool focus = event->gotFocus(); - if (!m_readOnly) + if (!m_readOnly) { q->setCursorVisible(focus); + setBlinkingCursorEnabled(focus); + } if (focus) { q->q_updateAlignment(); #ifndef QT_NO_IM @@ -4295,26 +4293,39 @@ bool QQuickTextInputPrivate::emitCursorPositionChanged() } -void QQuickTextInputPrivate::setCursorBlinkPeriod(int msec) +void QQuickTextInputPrivate::setBlinkingCursorEnabled(bool enable) { - Q_Q(QQuickTextInput); - if (msec == m_blinkPeriod) + if (enable == m_blinkEnabled) return; + + m_blinkEnabled = enable; + updateCursorBlinking(); + + if (enable) + connect(qApp->styleHints(), &QStyleHints::cursorFlashTimeChanged, this, &QQuickTextInputPrivate::updateCursorBlinking); + else + disconnect(qApp->styleHints(), &QStyleHints::cursorFlashTimeChanged, this, &QQuickTextInputPrivate::updateCursorBlinking); +} + +void QQuickTextInputPrivate::updateCursorBlinking() +{ + Q_Q(QQuickTextInput); + if (m_blinkTimer) { q->killTimer(m_blinkTimer); - } - if (msec) { - m_blinkTimer = q->startTimer(msec / 2); - m_blinkStatus = 1; - } else { m_blinkTimer = 0; - if (m_blinkStatus == 1) { - updateType = UpdatePaintNode; - q->polish(); - q->update(); - } } - m_blinkPeriod = msec; + + if (m_blinkEnabled && cursorVisible && !cursorItem && !m_readOnly) { + int flashTime = QGuiApplication::styleHints()->cursorFlashTime(); + if (flashTime >= 2) + m_blinkTimer = q->startTimer(flashTime / 2); + } + + m_blinkStatus = 1; + updateType = UpdatePaintNode; + q->polish(); + q->update(); } void QQuickTextInput::timerEvent(QTimerEvent *event) @@ -4351,20 +4362,8 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event) return; } - if (m_blinkPeriod > 0) { - if (m_blinkTimer) - q->killTimer(m_blinkTimer); - - m_blinkTimer = q->startTimer(m_blinkPeriod / 2); - - if (m_blinkStatus == 0) { - m_blinkStatus = 1; - - updateType = UpdatePaintNode; - q->polish(); - q->update(); - } - } + if (m_blinkEnabled) + updateCursorBlinking(); if (m_echoMode == QQuickTextInput::PasswordEchoOnEdit && !m_passwordEchoEditing diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h index d2dee2c284..d0461f551e 100644 --- a/src/quick/items/qquicktextinput_p.h +++ b/src/quick/items/qquicktextinput_p.h @@ -323,8 +323,8 @@ Q_SIGNALS: void selectionColorChanged(); void selectedTextColorChanged(); void fontChanged(const QFont &font); - void horizontalAlignmentChanged(HAlignment alignment); - void verticalAlignmentChanged(VAlignment alignment); + void horizontalAlignmentChanged(QQuickTextInput::HAlignment alignment); + void verticalAlignmentChanged(QQuickTextInput::VAlignment alignment); void wrapModeChanged(); void readOnlyChanged(bool isReadOnly); void cursorVisibleChanged(bool isCursorVisible); @@ -333,7 +333,7 @@ Q_SIGNALS: void maximumLengthChanged(int maximumLength); void validatorChanged(); void inputMaskChanged(const QString &inputMask); - void echoModeChanged(EchoMode echoMode); + void echoModeChanged(QQuickTextInput::EchoMode echoMode); void passwordCharacterChanged(); Q_REVISION(3) void passwordMaskDelayChanged(int delay); void displayTextChanged(); @@ -341,7 +341,7 @@ Q_SIGNALS: void activeFocusOnPressChanged(bool activeFocusOnPress); void autoScrollChanged(bool autoScroll); void selectByMouseChanged(bool selectByMouse); - void mouseSelectionModeChanged(SelectionMode mode); + void mouseSelectionModeChanged(QQuickTextInput::SelectionMode mode); void persistentSelectionChanged(); void canPasteChanged(); void canUndoChanged(); diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h index e6bd29bf67..93a8778c40 100644 --- a/src/quick/items/qquicktextinput_p_p.h +++ b/src/quick/items/qquicktextinput_p_p.h @@ -107,7 +107,7 @@ public: #ifndef QT_NO_IM , m_preeditCursor(0) #endif - , m_blinkPeriod(0) + , m_blinkEnabled(false) , m_blinkTimer(0) , m_maxLength(32767) , m_lastCursorPos(-1) @@ -243,7 +243,7 @@ public: #ifndef QT_NO_IM int m_preeditCursor; #endif - int m_blinkPeriod; // 0 for non-blinking cursor + bool m_blinkEnabled; int m_blinkTimer; int m_maxLength; int m_lastCursorPos; @@ -309,8 +309,9 @@ public: return !tripleClickTimer.hasExpired(QGuiApplication::styleHints()->mouseDoubleClickInterval()); } - void setNativeCursorEnabled(bool enabled) { - setCursorBlinkPeriod(enabled && cursorVisible ? QGuiApplication::styleHints()->cursorFlashTime() : 0); } + void setNativeCursorEnabled(bool) { + updateCursorBlinking(); + } int nextMaskBlank(int pos) { @@ -445,7 +446,8 @@ public: #endif void processKeyEvent(QKeyEvent* ev); - void setCursorBlinkPeriod(int msec); + void setBlinkingCursorEnabled(bool enable); + void updateCursorBlinking(); void updateLayout(); void updateBaselineOffset(); diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 454eb645fb..48e5b54016 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -99,6 +99,7 @@ void QQuickWindowPrivate::updateFocusItemTransform() QQuickItemPrivate *focusPrivate = QQuickItemPrivate::get(focus); QGuiApplication::inputMethod()->setInputItemTransform(focusPrivate->itemToWindowTransform()); QGuiApplication::inputMethod()->setInputItemRectangle(QRectF(0, 0, focusPrivate->width, focusPrivate->height)); + focus->updateInputMethod(Qt::ImInputItemClipRectangle); } #endif } @@ -257,6 +258,26 @@ void QQuickWindow::focusInEvent(QFocusEvent *ev) d->updateFocusItemTransform(); } +#ifndef QT_NO_IM +static bool transformDirtyOnItemOrAncestor(const QQuickItem *item) +{ + while (item) { + if (QQuickItemPrivate::get(item)->dirtyAttributes & ( + QQuickItemPrivate::TransformOrigin | + QQuickItemPrivate::Transform | + QQuickItemPrivate::BasicTransform | + QQuickItemPrivate::Position | + QQuickItemPrivate::Size | + QQuickItemPrivate::ParentChanged | + QQuickItemPrivate::Clip)) { + return true; + } + item = item->parentItem(); + } + return false; +} +#endif + void QQuickWindowPrivate::polishItems() { // An item can trigger polish on another item, or itself for that matter, @@ -276,7 +297,17 @@ void QQuickWindowPrivate::polishItems() if (recursionSafeguard == 0) qWarning("QQuickWindow: possible QQuickItem::polish() loop"); - updateFocusItemTransform(); +#ifndef QT_NO_IM + if (QQuickItem *focusItem = q_func()->activeFocusItem()) { + // If the current focus item, or any of its anchestors, has changed location + // inside the window, we need inform IM about it. This to ensure that overlays + // such as selection handles will be updated. + const bool isActiveFocusItem = (focusItem == QGuiApplication::focusObject()); + const bool hasImEnabled = focusItem->inputMethodQuery(Qt::ImEnabled).toBool(); + if (isActiveFocusItem && hasImEnabled && transformDirtyOnItemOrAncestor(focusItem)) + updateFocusItemTransform(); + } +#endif } /*! @@ -4024,6 +4055,12 @@ void QQuickWindow::resetOpenGLState() */ /*! + \qmlproperty Item Window::contentItem + \readonly + \brief The invisible root item of the scene. +*/ + +/*! \qmlproperty Qt::ScreenOrientation Window::contentOrientation This is a hint to the window manager in case it needs to display diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index e657307efd..d91004fbee 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -496,11 +496,6 @@ void Updater::visitGeometryNode(Node *n) if (e->batch) renderer->invalidateBatchAndOverlappingRenderOrders(e->batch); } - if (n->dirtyState & QSGNode::DirtyMaterial) { - Element *e = n->element(); - if (e->batch && e->batch->isMaterialCompatible(e) == BatchBreaksOnCompare) - renderer->invalidateBatchAndOverlappingRenderOrders(e->batch); - } } SHADOWNODE_TRAVERSE(n) visitNode(child); @@ -598,13 +593,13 @@ void Element::computeBounds() } bounds.map(*node->matrix()); - if (!qIsFinite(bounds.tl.x) || bounds.tl.x == FLT_MAX) + if (!qt_is_finite(bounds.tl.x) || bounds.tl.x == FLT_MAX) bounds.tl.x = -FLT_MAX; - if (!qIsFinite(bounds.tl.y) || bounds.tl.y == FLT_MAX) + if (!qt_is_finite(bounds.tl.y) || bounds.tl.y == FLT_MAX) bounds.tl.y = -FLT_MAX; - if (!qIsFinite(bounds.br.x) || bounds.br.x == -FLT_MAX) + if (!qt_is_finite(bounds.br.x) || bounds.br.x == -FLT_MAX) bounds.br.x = FLT_MAX; - if (!qIsFinite(bounds.br.y) || bounds.br.y == -FLT_MAX) + if (!qt_is_finite(bounds.br.y) || bounds.br.y == -FLT_MAX) bounds.br.y = FLT_MAX; Q_ASSERT(bounds.tl.x <= bounds.br.x); @@ -1240,7 +1235,10 @@ void Renderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state) if (e->isMaterialBlended != blended) { m_rebuild |= Renderer::FullRebuild; e->isMaterialBlended = blended; - } else if (!e->batch) { + } else if (e->batch) { + if (e->batch->isMaterialCompatible(e) == BatchBreaksOnCompare) + invalidateBatchAndOverlappingRenderOrders(e->batch); + } else { m_rebuild |= Renderer::BuildBatches; } } diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h index 5dbbc22870..8bf4a13af6 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h @@ -527,7 +527,7 @@ public: float lastOpacity; }; - ShaderManager(QSGRenderContext *ctx) : blitProgram(0), visualizeProgram(0), context(ctx) { } + ShaderManager(QSGRenderContext *ctx) : visualizeProgram(0), blitProgram(0), context(ctx) { } ~ShaderManager() { qDeleteAll(rewrittenShaders); qDeleteAll(stockShaders); @@ -540,11 +540,13 @@ public: Shader *prepareMaterial(QSGMaterial *material); Shader *prepareMaterialNoRewrite(QSGMaterial *material); + QOpenGLShaderProgram *visualizeProgram; + +private: QHash<QSGMaterialType *, Shader *> rewrittenShaders; QHash<QSGMaterialType *, Shader *> stockShaders; QOpenGLShaderProgram *blitProgram; - QOpenGLShaderProgram *visualizeProgram; QSGRenderContext *context; }; diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.h b/src/quick/scenegraph/qsgdefaultglyphnode_p.h index 4efeaea373..ea4c0ff787 100644 --- a/src/quick/scenegraph/qsgdefaultglyphnode_p.h +++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.h @@ -56,7 +56,6 @@ QT_BEGIN_NAMESPACE -class QGlyphs; class QSGTextMaskMaterial; class QSGDefaultGlyphNode: public QSGGlyphNode { diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp index 68dc813933..a93e7bbd30 100644 --- a/src/quick/scenegraph/util/qsgatlastexture.cpp +++ b/src/quick/scenegraph/util/qsgatlastexture.cpp @@ -127,6 +127,7 @@ Atlas::Atlas(const QSize &size) : m_allocator(size) , m_texture_id(0) , m_size(size) + , m_atlas_transient_image_threshold(0) , m_allocated(false) { @@ -176,6 +177,11 @@ Atlas::Atlas(const QSize &size) m_use_bgra_fallback = qEnvironmentVariableIsSet("QSG_ATLAS_USE_BGRA_FALLBACK"); m_debug_overlay = qEnvironmentVariableIsSet("QSG_ATLAS_OVERLAY"); + + // images smaller than this will retain their QImage. + // by default no images are retained (favoring memory) + // set to a very large value to retain all images (allowing quick removal from the atlas) + m_atlas_transient_image_threshold = qt_sg_envInt("QSG_ATLAS_TRANSIENT_IMAGE_THRESHOLD", 0); } Atlas::~Atlas() @@ -398,7 +404,10 @@ void Atlas::bind(QSGTexture::Filtering filtering) } else { upload(t); } - t->releaseImage(); + const QSize textureSize = t->textureSize(); + if (textureSize.width() > m_atlas_transient_image_threshold || + textureSize.height() > m_atlas_transient_image_threshold) + t->releaseImage(); qCDebug(QSG_LOG_TIME_TEXTURE).nospace() << "atlastexture uploaded in: " << qsg_renderer_timer.elapsed() << "ms (" << t->textureSize().width() << "x" diff --git a/src/quick/scenegraph/util/qsgatlastexture_p.h b/src/quick/scenegraph/util/qsgatlastexture_p.h index c6f1e72a4d..d6c0109c98 100644 --- a/src/quick/scenegraph/util/qsgatlastexture_p.h +++ b/src/quick/scenegraph/util/qsgatlastexture_p.h @@ -116,6 +116,8 @@ private: GLuint m_internalFormat; GLuint m_externalFormat; + int m_atlas_transient_image_threshold; + uint m_allocated : 1; uint m_use_bgra_fallback: 1; diff --git a/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp index ec1d316f78..caa296451e 100644 --- a/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp +++ b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp @@ -382,9 +382,9 @@ QString QSGShaderSourceBuilder::resolveShaderPath(const QString &path) const int idx = path.lastIndexOf(QLatin1Char('.')); QString resolvedPath; if (idx != -1) - resolvedPath = path.left(idx) - + QStringLiteral("_core") - + path.right(path.length() - idx); + resolvedPath = path.leftRef(idx) + + QLatin1String("_core") + + path.rightRef(path.length() - idx); return resolvedPath; } } diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp index adf8f600a0..741a583803 100644 --- a/src/quick/util/qquickanimation.cpp +++ b/src/quick/util/qquickanimation.cpp @@ -986,7 +986,7 @@ void QQuickScriptActionPrivate::debugAction(QDebug d, int indentLevel) const QByteArray ind(indentLevel, ' '); QString exprStr = expr.expression(); int endOfFirstLine = exprStr.indexOf('\n'); - d << "\n" << ind.constData() << exprStr.left(endOfFirstLine); + d << "\n" << ind.constData() << exprStr.leftRef(endOfFirstLine); if (endOfFirstLine != -1 && endOfFirstLine < exprStr.length()) d << "..."; } diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp index 4ad6fdd854..7692cc79f9 100644 --- a/src/quick/util/qquickglobal.cpp +++ b/src/quick/util/qquickglobal.cpp @@ -172,8 +172,8 @@ public: int index = s.indexOf(QLatin1Char(',')); bool xGood, yGood; - float xCoord = s.left(index).toFloat(&xGood); - float yCoord = s.mid(index+1).toFloat(&yGood); + float xCoord = s.leftRef(index).toFloat(&xGood); + float yCoord = s.midRef(index + 1).toFloat(&yGood); if (xGood && yGood) { if (ok) *ok = true; @@ -192,9 +192,9 @@ public: int index2 = s.indexOf(QLatin1Char(','), index+1); bool xGood, yGood, zGood; - float xCoord = s.left(index).toFloat(&xGood); - float yCoord = s.mid(index+1, index2-index-1).toFloat(&yGood); - float zCoord = s.mid(index2+1).toFloat(&zGood); + float xCoord = s.leftRef(index).toFloat(&xGood); + float yCoord = s.midRef(index + 1, index2 - index - 1).toFloat(&yGood); + float zCoord = s.midRef(index2 + 1).toFloat(&zGood); if (xGood && yGood && zGood) { if (ok) *ok = true; @@ -214,10 +214,10 @@ public: int index3 = s.indexOf(QLatin1Char(','), index2+1); bool xGood, yGood, zGood, wGood; - float xCoord = s.left(index).toFloat(&xGood); - float yCoord = s.mid(index+1, index2-index-1).toFloat(&yGood); - float zCoord = s.mid(index2+1, index3-index2-1).toFloat(&zGood); - float wCoord = s.mid(index3+1).toFloat(&wGood); + float xCoord = s.leftRef(index).toFloat(&xGood); + float yCoord = s.midRef(index + 1, index2 - index - 1).toFloat(&yGood); + float zCoord = s.midRef(index2 + 1, index3 - index2 - 1).toFloat(&zGood); + float wCoord = s.midRef(index3 + 1).toFloat(&wGood); if (xGood && yGood && zGood && wGood) { if (ok) *ok = true; @@ -257,10 +257,10 @@ public: if (s.count(QLatin1Char(',')) == 15) { float matValues[16]; bool vOK = true; - QString mutableStr = s; + QStringRef mutableStr(&s); for (int i = 0; vOK && i < 16; ++i) { int cidx = mutableStr.indexOf(QLatin1Char(',')); - matValues[i] = mutableStr.leftRef(cidx).toDouble(&vOK); + matValues[i] = mutableStr.left(cidx).toDouble(&vOK); mutableStr = mutableStr.mid(cidx + 1); } diff --git a/src/quick/util/qquickpath_p.h b/src/quick/util/qquickpath_p.h index d554e2156a..e2c99de44e 100644 --- a/src/quick/util/qquickpath_p.h +++ b/src/quick/util/qquickpath_p.h @@ -335,7 +335,7 @@ class Q_AUTOTEST_EXPORT QQuickPathPercent : public QQuickPathElement Q_OBJECT Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged) public: - QQuickPathPercent(QObject *parent=0) : QQuickPathElement(parent) {} + QQuickPathPercent(QObject *parent=0) : QQuickPathElement(parent), _value(0) {} qreal value() const; void setValue(qreal value); diff --git a/src/quick/util/qquickstategroup.cpp b/src/quick/util/qquickstategroup.cpp index da3b6fa561..200f243a1b 100644 --- a/src/quick/util/qquickstategroup.cpp +++ b/src/quick/util/qquickstategroup.cpp @@ -46,6 +46,7 @@ #include <QtCore/qstringlist.h> #include <QtCore/qdebug.h> +#include <QtCore/qvector.h> #include <private/qobject_p.h> #include <qqmlinfo.h> @@ -378,28 +379,29 @@ QQuickTransition *QQuickStateGroupPrivate::findTransition(const QString &from, c (t->fromState() == QLatin1String("*") && t->toState() == QLatin1String("*")))) break; - QStringList fromState; - QStringList toState; + const QString fromStateStr = t->fromState(); + const QString toStateStr = t->toState(); - fromState = t->fromState().split(QLatin1Char(',')); + QVector<QStringRef> fromState = fromStateStr.splitRef(QLatin1Char(',')); for (int jj = 0; jj < fromState.count(); ++jj) fromState[jj] = fromState.at(jj).trimmed(); - toState = t->toState().split(QLatin1Char(',')); + QVector<QStringRef> toState = toStateStr.splitRef(QLatin1Char(',')); for (int jj = 0; jj < toState.count(); ++jj) toState[jj] = toState.at(jj).trimmed(); if (ii == 1) qSwap(fromState, toState); int tScore = 0; - if (fromState.contains(from)) + const QString asterisk = QStringLiteral("*"); + if (fromState.contains(QStringRef(&from))) tScore += 2; - else if (fromState.contains(QLatin1String("*"))) + else if (fromState.contains(QStringRef(&asterisk))) tScore += 1; else continue; - if (toState.contains(to)) + if (toState.contains(QStringRef(&to))) tScore += 2; - else if (toState.contains(QLatin1String("*"))) + else if (toState.contains(QStringRef(&asterisk))) tScore += 1; else continue; diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index adf944c7e1..99c18f91a1 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -137,6 +137,7 @@ private slots: void functionDeclarationsInConditionals(); void arrayPop_QTBUG_35979(); + void array_unshift_QTBUG_52065(); void regexpLastMatch(); void indexedAccesses(); @@ -3045,6 +3046,20 @@ void tst_QJSEngine::arrayPop_QTBUG_35979() QCOMPARE(result.toString(), QString("1,3")); } +void tst_QJSEngine::array_unshift_QTBUG_52065() +{ + QJSEngine eng; + QJSValue result = eng.evaluate("[1, 2, 3, 4, 5, 6, 7, 8, 9]"); + QJSValue unshift = result.property(QStringLiteral("unshift")); + unshift.callWithInstance(result, QJSValueList() << QJSValue(0)); + + int len = result.property(QStringLiteral("length")).toInt(); + QCOMPARE(len, 10); + + for (int i = 0; i < len; ++i) + QCOMPARE(result.property(i).toInt(), i); +} + void tst_QJSEngine::regexpLastMatch() { QJSEngine eng; diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro index 5e798f3b48..28f04be5d7 100644 --- a/tests/auto/qml/qml.pro +++ b/tests/auto/qml/qml.pro @@ -69,7 +69,8 @@ qtHaveModule(widgets) { qjsvalue } -SUBDIRS += $$PUBLICTESTS +SUBDIRS += $$PUBLICTESTS \ + qqmlextensionplugin SUBDIRS += $$METATYPETESTS !winrt { # no QProcess on winrt !contains(QT_CONFIG, no-qml-debug): SUBDIRS += debugger diff --git a/tests/auto/qml/qqmlecmascript/data/qtbug_52340.qml b/tests/auto/qml/qqmlecmascript/data/qtbug_52340.qml new file mode 100644 index 0000000000..03f90c15c8 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/qtbug_52340.qml @@ -0,0 +1,13 @@ +import QtQml 2.0 + +QtObject { + property bool someProperty: true + function testCall() { + try { + someProperty(); // should throw + return false + } catch (e) { + return true + } + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/sequenceSort.qml b/tests/auto/qml/qqmlecmascript/data/sequenceSort.qml index b130408c18..74c7cda9a3 100644 --- a/tests/auto/qml/qqmlecmascript/data/sequenceSort.qml +++ b/tests/auto/qml/qqmlecmascript/data/sequenceSort.qml @@ -64,6 +64,16 @@ Item { var actual = msc.reals(realList); return checkResults(expected, actual, fn); } + function doIntVectorTest(intList, fn) { + var expected = createExpected(intList, fn); + var actual = msc.integerVector(intList); + return checkResults(expected, actual, fn); + } + function doRealVectorTest(realList, fn) { + var expected = createExpected(realList, fn); + var actual = msc.realVector(realList); + return checkResults(expected, actual, fn); + } function test_qtbug_25269(useCustomCompare) { return doStringTest( [ "one", "two", "three" ], null ); @@ -92,4 +102,20 @@ Item { var fn = useCustomCompare ? compareNumbers : null; return doRealTest( [ -3.4, 1, 10, 4.23, -30.1, 4.24, 4.21, -1, -1, 12, -100, 87.4, 101.3, -8.88888, 7.76, 10.10, 1.1, -1.1, -0, 11, 12.8, 0.001, -11, -0.75, 99999.99, 11.12, 32.3, 3.333333, 9.876 ], fn ); } + function test_number_vector_insertionSort(useCustomCompare) { + var fn = useCustomCompare ? compareNumbers : null; + return doIntVectorTest( [ 7, 3, 9, 1, 0, -1, 20, -11 ], fn ); + } + function test_number_vector_quickSort(useCustomCompare) { + var fn = useCustomCompare ? compareNumbers : null; + return doIntVectorTest( [ 7, 3, 37, 9, 1, 0, -1, 20, -11, -300, -87, 1, 3, -2, 100, 108, 96, 9, 99999, 12, 11, 11, 12, 11, 13, -13, 10, 10, 10, 8, 12 ], fn ); + } + function test_real_vector_insertionSort(useCustomCompare) { + var fn = useCustomCompare ? compareNumbers : null; + return doRealVectorTest( [ -3.4, 1, 10, 4.23, -30.1, 4.24, 4.21, -1, -1 ], fn ); + } + function test_real_vector_quickSort(useCustomCompare) { + var fn = useCustomCompare ? compareNumbers : null; + return doRealVectorTest( [ -3.4, 1, 10, 4.23, -30.1, 4.24, 4.21, -1, -1, 12, -100, 87.4, 101.3, -8.88888, 7.76, 10.10, 1.1, -1.1, -0, 11, 12.8, 0.001, -11, -0.75, 99999.99, 11.12, 32.3, 3.333333, 9.876 ], fn ); + } } diff --git a/tests/auto/qml/qqmlecmascript/testtypes.cpp b/tests/auto/qml/qqmlecmascript/testtypes.cpp index 2afa21ddd6..d9ddcd71a7 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.cpp +++ b/tests/auto/qml/qqmlecmascript/testtypes.cpp @@ -295,6 +295,18 @@ public: { return v; } + Q_INVOKABLE QVector<int> integerVector(QVector<int> v) const + { + return v; + } + Q_INVOKABLE QVector<qreal> realVector(QVector<qreal> v) const + { + return v; + } + Q_INVOKABLE QVector<bool> boolVector(QVector<bool> v) const + { + return v; + } }; static MyInheritedQmlObject *theSingletonObject = 0; diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h index 81b9b8d7bf..47fb2a56e7 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.h +++ b/tests/auto/qml/qqmlecmascript/testtypes.h @@ -791,6 +791,8 @@ public: Q_INVOKABLE void method_QScriptValue(QJSValue a) { invoke(14); m_actuals << qVariantFromValue(a); } Q_INVOKABLE void method_intQScriptValue(int a, QJSValue b) { invoke(15); m_actuals << a << qVariantFromValue(b); } Q_INVOKABLE void method_QByteArray(QByteArray value) { invoke(29); m_actuals << value; } + Q_INVOKABLE QJSValue method_intQJSValue(int a, QJSValue b) { invoke(30); m_actuals << a << qVariantFromValue(b); return b.call(); } + Q_INVOKABLE QJSValue method_intQJSValue(int a, int b) { m_actuals << a << b; return QJSValue();} // Should never be called. Q_INVOKABLE void method_overload(int a) { invoke(16); m_actuals << a; } Q_INVOKABLE void method_overload(int a, int b) { invoke(17); m_actuals << a << b; } diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index f71d7efe3a..2f78df1f11 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -322,6 +322,7 @@ private slots: void writeUnregisteredQObjectProperty(); void switchExpression(); void qtbug_46022(); + void qtbug_52340(); private: // static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter); @@ -2944,6 +2945,18 @@ void tst_qqmlecmascript::callQtInvokables() QCOMPARE(o->invoked(), 29); QCOMPARE(o->actuals().count(), 1); QCOMPARE(qvariant_cast<QByteArray>(o->actuals().at(0)), QByteArray("Hello")); + + o->reset(); + QV4::ScopedValue ret(scope, EVALUATE("object.method_intQJSValue(123, function() { return \"Hello world!\";})")); + QCOMPARE(o->error(), false); + QCOMPARE(o->invoked(), 30); + QVERIFY(ret->isString()); + QCOMPARE(ret->toQStringNoThrow(), QString("Hello world!")); + QCOMPARE(o->actuals().count(), 2); + QCOMPARE(o->actuals().at(0), QVariant(123)); + QJSValue callback = qvariant_cast<QJSValue>(o->actuals().at(1)); + QVERIFY(!callback.isNull()); + QVERIFY(callback.isCallable()); } // QTBUG-13047 (check that you can pass registered object types as args) @@ -7331,7 +7344,7 @@ void tst_qqmlecmascript::sequenceSort_data() QTest::newRow("qtbug_25269") << "test_qtbug_25269" << false; - const char *types[] = { "alphabet", "numbers", "reals" }; + const char *types[] = { "alphabet", "numbers", "reals", "number_vector", "real_vector" }; const char *sort[] = { "insertionSort", "quickSort" }; for (size_t t=0 ; t < sizeof(types)/sizeof(types[0]) ; ++t) { @@ -7898,6 +7911,17 @@ void tst_qqmlecmascript::qtbug_46022() QCOMPARE(obj->property("test2").toBool(), true); } +void tst_qqmlecmascript::qtbug_52340() +{ + QQmlComponent component(&engine, testFileUrl("qtbug_52340.qml")); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); + QVariant returnValue; + QVERIFY(QMetaObject::invokeMethod(object.data(), "testCall", Q_RETURN_ARG(QVariant, returnValue))); + QVERIFY(returnValue.isValid()); + QVERIFY(returnValue.toBool()); +} + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc" diff --git a/tests/auto/qml/qqmlextensionplugin/qqmlextensionplugin.pro b/tests/auto/qml/qqmlextensionplugin/qqmlextensionplugin.pro new file mode 100644 index 0000000000..af74707c4a --- /dev/null +++ b/tests/auto/qml/qqmlextensionplugin/qqmlextensionplugin.pro @@ -0,0 +1,5 @@ +CONFIG += testcase +TARGET = tst_qqmlextensionplugin +SOURCES += tst_qqmlextensionplugin.cpp +osx:CONFIG -= app_bundle +QT += qml testlib diff --git a/tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp b/tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp new file mode 100644 index 0000000000..ab5e958323 --- /dev/null +++ b/tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore> +#include <QtTest> +#include <QtQml> + +#if defined(Q_OS_WIN) +# define SUFFIX QLatin1String(".dll") +# define DEBUG_SUFFIX QLatin1String("d.dll") + +#elif defined(Q_OS_DARWIN) +# define SUFFIX QLatin1String(".dylib") +# define DEBUG_SUFFIX QLatin1String("_debug.dylib") + +# else // Unix +# define SUFFIX QLatin1String(".so") +#endif + + +class tst_qqmlextensionplugin : public QObject +{ + Q_OBJECT + + bool isDuplicate(QString file, const QList<QString> & files) { +#ifndef DEBUG_SUFFIX + Q_UNUSED(file) + Q_UNUSED(files) + return false; +#else +# ifdef QT_DEBUG + return !file.endsWith(DEBUG_SUFFIX) && files.contains(file.replace(SUFFIX, DEBUG_SUFFIX)); +# else + return file.endsWith(DEBUG_SUFFIX) && files.contains(file.replace(DEBUG_SUFFIX, SUFFIX)); +# endif +#endif + } + +public: + tst_qqmlextensionplugin() {} + +private Q_SLOTS: + void iidCheck_data(); + void iidCheck(); +}; + + +void tst_qqmlextensionplugin::iidCheck_data() +{ + QList<QString> files; + for (QDirIterator it(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath), QDirIterator::Subdirectories); it.hasNext(); ) { + QString file = it.next(); + if (file.endsWith(SUFFIX)) { + files << file; + } + } + + for (QMutableListIterator<QString> it(files); it.hasNext(); ) { + QString file = it.next(); + if (isDuplicate(file, files)) { + it.remove(); + } + } + + QTest::addColumn<QString>("filePath"); + foreach (const QString &file, files) { + QFileInfo fileInfo(file); + QTest::newRow(fileInfo.baseName().toLatin1().data()) << fileInfo.absoluteFilePath(); + } +} + + +void tst_qqmlextensionplugin::iidCheck() +{ + QFETCH(QString, filePath); + + QPluginLoader loader(filePath); + QVERIFY(loader.load()); + QVERIFY(loader.instance() != Q_NULLPTR); + + if (qobject_cast<QQmlExtensionPlugin *>(loader.instance())) { + QString iid = loader.metaData().value(QStringLiteral("IID")).toString(); + QCOMPARE(iid, QLatin1String(QQmlExtensionInterface_iid)); + } +} + + +QTEST_APPLESS_MAIN(tst_qqmlextensionplugin) +#include "tst_qqmlextensionplugin.moc" diff --git a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp index bfa7e2f13f..68739886c4 100644 --- a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp +++ b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp @@ -41,6 +41,8 @@ private slots: void importPathOrder(); void testDesignerSupported(); void uiFormatLoading(); + void completeQmldirPaths_data(); + void completeQmldirPaths(); void cleanup(); }; @@ -146,6 +148,43 @@ void tst_QQmlImport::importPathOrder() QCOMPARE(expectedImportPaths, engine.importPathList()); } +Q_DECLARE_METATYPE(QQmlImports::ImportVersion) + +void tst_QQmlImport::completeQmldirPaths_data() +{ + QTest::addColumn<QString>("uri"); + QTest::addColumn<QStringList>("basePaths"); + QTest::addColumn<int>("majorVersion"); + QTest::addColumn<int>("minorVersion"); + QTest::addColumn<QStringList>("expectedPaths"); + + QTest::newRow("QtQml") << "QtQml" << (QStringList() << "qtbase/qml/" << "path/to/qml") << 2 << 7 + << (QStringList() << "qtbase/qml/QtQml.2.7/qmldir" << "path/to/qml/QtQml.2.7/qmldir" + << "qtbase/qml/QtQml.2/qmldir" << "path/to/qml/QtQml.2/qmldir" + << "qtbase/qml/QtQml/qmldir" << "path/to/qml/QtQml/qmldir"); + + QTest::newRow("QtQml.Models") << "QtQml.Models" << QStringList("qtbase/qml/") << 2 << 2 + << (QStringList() << "qtbase/qml/QtQml/Models.2.2/qmldir" << "qtbase/qml/QtQml.2.2/Models/qmldir" + << "qtbase/qml/QtQml/Models.2/qmldir" << "qtbase/qml/QtQml.2/Models/qmldir" + << "qtbase/qml/QtQml/Models/qmldir"); + + QTest::newRow("org.qt-project.foo.bar") << "org.qt-project.foo.bar" << QStringList("qtbase/qml/") << 0 << 1 + << (QStringList() << "qtbase/qml/org/qt-project/foo/bar.0.1/qmldir" << "qtbase/qml/org/qt-project/foo.0.1/bar/qmldir" << "qtbase/qml/org/qt-project.0.1/foo/bar/qmldir" << "qtbase/qml/org.0.1/qt-project/foo/bar/qmldir" + << "qtbase/qml/org/qt-project/foo/bar.0/qmldir" << "qtbase/qml/org/qt-project/foo.0/bar/qmldir" << "qtbase/qml/org/qt-project.0/foo/bar/qmldir" << "qtbase/qml/org.0/qt-project/foo/bar/qmldir" + << "qtbase/qml/org/qt-project/foo/bar/qmldir"); +} + +void tst_QQmlImport::completeQmldirPaths() +{ + QFETCH(QString, uri); + QFETCH(QStringList, basePaths); + QFETCH(int, majorVersion); + QFETCH(int, minorVersion); + QFETCH(QStringList, expectedPaths); + + QCOMPARE(QQmlImports::completeQmldirPaths(uri, basePaths, majorVersion, minorVersion), expectedPaths); +} + QTEST_MAIN(tst_QQmlImport) #include "tst_qqmlimport.moc" diff --git a/tests/auto/qml/qqmllanguage/BLACKLIST b/tests/auto/qml/qqmllanguage/BLACKLIST deleted file mode 100644 index c1c7e56df9..0000000000 --- a/tests/auto/qml/qqmllanguage/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[importsPath] -windows diff --git a/tests/auto/qml/qqmlmoduleplugin/data/child.qml b/tests/auto/qml/qqmlmoduleplugin/data/child.qml new file mode 100644 index 0000000000..a11ae297d7 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/data/child.qml @@ -0,0 +1,3 @@ +import org.qtproject.AutoTestQmlPluginType.ChildPlugin 1.0 + +MyChildPluginType { value: 123 } diff --git a/tests/auto/qml/qqmlmoduleplugin/data/child2.qml b/tests/auto/qml/qqmlmoduleplugin/data/child2.qml new file mode 100644 index 0000000000..667164516a --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/data/child2.qml @@ -0,0 +1,3 @@ +import org.qtproject.AutoTestQmlPluginType.ChildPlugin 2.0 + +MyChildPluginType { valueOnlyIn2: 123 } diff --git a/tests/auto/qml/qqmlmoduleplugin/data/child21.qml b/tests/auto/qml/qqmlmoduleplugin/data/child21.qml new file mode 100644 index 0000000000..064d5474e0 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/data/child21.qml @@ -0,0 +1,3 @@ +import org.qtproject.AutoTestQmlPluginType.ChildPlugin 2.1 + +MyChildPluginType { valueOnlyIn2: 123 } diff --git a/tests/auto/qml/qqmlmoduleplugin/invalidFirstCommandModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/invalidFirstCommandModule/plugin.cpp index 82c3c926fd..fa9782f8c2 100644 --- a/tests/auto/qml/qqmlmoduleplugin/invalidFirstCommandModule/plugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/invalidFirstCommandModule/plugin.cpp @@ -41,7 +41,7 @@ public: class MyPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: MyPlugin() {} diff --git a/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp index bb2a344811..fe01507412 100644 --- a/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp @@ -41,7 +41,7 @@ public: class MyPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: MyPlugin() {} diff --git a/tests/auto/qml/qqmlmoduleplugin/invalidStrictModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/invalidStrictModule/plugin.cpp index bb2a344811..fe01507412 100644 --- a/tests/auto/qml/qqmlmoduleplugin/invalidStrictModule/plugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/invalidStrictModule/plugin.cpp @@ -41,7 +41,7 @@ public: class MyPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: MyPlugin() {} diff --git a/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp b/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp index 4ca5eb5402..92d30351a7 100644 --- a/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp @@ -56,7 +56,7 @@ public: class MyPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: MyPlugin() {} diff --git a/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp index f48ab16b03..5fc05b91bd 100644 --- a/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp @@ -41,7 +41,7 @@ public: class MyPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: MyPlugin() {} diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp new file mode 100644 index 0000000000..53247e7912 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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$ +** +****************************************************************************/ +#include <QStringList> +#include <QtQml/qqmlextensionplugin.h> +#include <QtQml/qqml.h> +#include <QDebug> + +class MyChildPluginType : public QObject +{ + Q_OBJECT + Q_PROPERTY(int value READ value WRITE setValue) + Q_PROPERTY(int valueOnlyIn2 READ value WRITE setValue) + +public: + MyChildPluginType(QObject *parent=0) : QObject(parent) + { + qWarning("child import2.1 worked"); + } + + int value() const { return v; } + void setValue(int i) { v = i; } + +private: + int v; +}; + + +class MyChildPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + +public: + MyChildPlugin() + { + qWarning("child plugin2.1 created"); + } + + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "org.qtproject.AutoTestQmlPluginType.ChildPlugin"); + qmlRegisterType<MyChildPluginType>(uri, 2, 1, "MyChildPluginType"); + } +}; + +#include "childplugin.moc" diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.pro b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.pro new file mode 100644 index 0000000000..7a0cd6f80f --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.pro @@ -0,0 +1,12 @@ +TEMPLATE = lib +CONFIG += childplugin +SOURCES = childplugin.cpp +QT = core qml +DESTDIR = ../../imports/org/qtproject/AutoTestQmlPluginType.2.1/ChildPlugin + +QT += core-private gui-private qml-private + +IMPORT_FILES = \ + qmldir + +include (../../../../shared/imports.pri) diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/qmldir b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/qmldir new file mode 100644 index 0000000000..c8d6488065 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/qmldir @@ -0,0 +1 @@ +plugin childplugin diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp index 2dc771fad1..6cae5254bc 100644 --- a/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp @@ -53,7 +53,7 @@ private: class MyPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: MyPlugin() diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp new file mode 100644 index 0000000000..a59347d3a9 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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$ +** +****************************************************************************/ +#include <QStringList> +#include <QtQml/qqmlextensionplugin.h> +#include <QtQml/qqml.h> +#include <QDebug> + +class MyChildPluginType : public QObject +{ + Q_OBJECT + Q_PROPERTY(int value READ value WRITE setValue) + Q_PROPERTY(int valueOnlyIn2 READ value WRITE setValue) + +public: + MyChildPluginType(QObject *parent=0) : QObject(parent) + { + qWarning("child import2 worked"); + } + + int value() const { return v; } + void setValue(int i) { v = i; } + +private: + int v; +}; + + +class MyChildPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + +public: + MyChildPlugin() + { + qWarning("child plugin2 created"); + } + + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "org.qtproject.AutoTestQmlPluginType.ChildPlugin"); + qmlRegisterType<MyChildPluginType>(uri, 2, 0, "MyChildPluginType"); + } +}; + +#include "childplugin.moc" diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.pro b/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.pro new file mode 100644 index 0000000000..c9283411f3 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.pro @@ -0,0 +1,13 @@ +TEMPLATE = lib +CONFIG += childplugin +SOURCES = childplugin.cpp +QT = core qml +DESTDIR = ../../imports/org/qtproject/AutoTestQmlPluginType.2/ChildPlugin + +QT += core-private gui-private qml-private + +IMPORT_DIR = DESTDIR +IMPORT_FILES = \ + qmldir + +include (../../../../shared/imports.pri) diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/qmldir b/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/qmldir new file mode 100644 index 0000000000..c8d6488065 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/qmldir @@ -0,0 +1 @@ +plugin childplugin diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp index 4b25181a86..49a2a747a4 100644 --- a/tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp @@ -53,7 +53,7 @@ private: class MyPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: MyPlugin() diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp new file mode 100644 index 0000000000..5f4f96f7e4 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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$ +** +****************************************************************************/ +#include <QStringList> +#include <QtQml/qqmlextensionplugin.h> +#include <QtQml/qqml.h> +#include <QDebug> + +class MyChildPluginType : public QObject +{ + Q_OBJECT + Q_PROPERTY(int value READ value WRITE setValue) + +public: + MyChildPluginType(QObject *parent=0) : QObject(parent) + { + qWarning("child import worked"); + } + + int value() const { return v; } + void setValue(int i) { v = i; } + +private: + int v; +}; + + +class MyChildPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + +public: + MyChildPlugin() + { + qWarning("child plugin created"); + } + + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "org.qtproject.AutoTestQmlPluginType.ChildPlugin"); + qmlRegisterType<MyChildPluginType>(uri, 1, 0, "MyChildPluginType"); + } +}; + +#include "childplugin.moc" diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.pro b/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.pro new file mode 100644 index 0000000000..5f5c01f77e --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.pro @@ -0,0 +1,12 @@ +TEMPLATE = lib +CONFIG += childplugin +SOURCES = childplugin.cpp +QT = core qml +DESTDIR = ../../imports/org/qtproject/AutoTestQmlPluginType/ChildPlugin + +QT += core-private gui-private qml-private + +IMPORT_FILES = \ + qmldir + +include (../../../../shared/imports.pri) diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/qmldir b/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/qmldir new file mode 100644 index 0000000000..c8d6488065 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/qmldir @@ -0,0 +1 @@ +plugin childplugin diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp index 7147769406..db51185de6 100644 --- a/tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp @@ -52,7 +52,7 @@ private: class MyPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: MyPlugin() diff --git a/tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp index 8ae091bc0f..e780d4a7fd 100644 --- a/tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp @@ -43,7 +43,7 @@ public: class MyMixedPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: MyMixedPlugin() diff --git a/tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp index 4be0ad4c66..470da6c35f 100644 --- a/tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp @@ -43,7 +43,7 @@ public: class MyMixedPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: MyMixedPlugin() diff --git a/tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp index 2c1047450a..60a0a4a3e2 100644 --- a/tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp @@ -33,7 +33,7 @@ class MyPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: void registerTypes(const char *uri) diff --git a/tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp index 4eb875be43..7669d65568 100644 --- a/tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp @@ -52,7 +52,7 @@ private: class MyPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: MyPlugin() diff --git a/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp index bace4644b3..92211ebf9d 100644 --- a/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp @@ -41,7 +41,7 @@ public: class MyPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: MyPlugin() {} diff --git a/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp index a98398ac94..3df3e9cc81 100644 --- a/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp @@ -41,7 +41,7 @@ public: class MyPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: MyPlugin() {} diff --git a/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp index df85d4a327..afdeea80f4 100644 --- a/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp @@ -40,7 +40,7 @@ public: class MyPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: MyPlugin() {} diff --git a/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro b/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro index 5c30d8cc00..889968f6cc 100644 --- a/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro +++ b/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro @@ -17,7 +17,10 @@ SUBDIRS =\ preemptedStrictModule\ invalidNamespaceModule\ invalidFirstCommandModule\ - protectedModule + protectedModule\ + plugin/childplugin\ + plugin.2/childplugin\ + plugin.2.1/childplugin tst_qqmlmoduleplugin_pro.depends += plugin SUBDIRS += tst_qqmlmoduleplugin.pro diff --git a/tests/auto/qml/qqmlmoduleplugin/strictModule.2/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/strictModule.2/plugin.cpp index 1e86c0da49..4f5176ae62 100644 --- a/tests/auto/qml/qqmlmoduleplugin/strictModule.2/plugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/strictModule.2/plugin.cpp @@ -41,7 +41,7 @@ public: class MyPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: MyPlugin() {} diff --git a/tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp index ad53ac95f3..eaa9aeb1d0 100644 --- a/tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp @@ -41,7 +41,7 @@ public: class MyPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: MyPlugin() {} diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp index 6ae1a6654f..265492b435 100644 --- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp @@ -70,6 +70,9 @@ private slots: void importStrictModule(); void importStrictModule_data(); void importProtectedModule(); + void importsChildPlugin(); + void importsChildPlugin2(); + void importsChildPlugin21(); private: QString m_importsDirectory; @@ -575,6 +578,57 @@ void tst_qqmlmoduleplugin::importProtectedModule() QVERIFY(object != 0); } +void tst_qqmlmoduleplugin::importsChildPlugin() +{ + QQmlEngine engine; + engine.addImportPath(m_importsDirectory); + QTest::ignoreMessage(QtWarningMsg, "child plugin created"); + QTest::ignoreMessage(QtWarningMsg, "child import worked"); + QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlPluginType.ChildPlugin' does not contain a module identifier directive - it cannot be protected from external registrations."); + QQmlComponent component(&engine, testFileUrl(QStringLiteral("child.qml"))); + foreach (QQmlError err, component.errors()) + qWarning() << err; + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("value").toInt(),123); + delete object; +} + +void tst_qqmlmoduleplugin::importsChildPlugin2() +{ + QQmlEngine engine; + engine.addImportPath(m_importsDirectory); + QTest::ignoreMessage(QtWarningMsg, "child plugin2 created"); + QTest::ignoreMessage(QtWarningMsg, "child import2 worked"); + QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlPluginType.ChildPlugin' does not contain a module identifier directive - it cannot be protected from external registrations."); + QQmlComponent component(&engine, testFileUrl(QStringLiteral("child2.qml"))); + foreach (QQmlError err, component.errors()) + qWarning() << err; + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("value").toInt(),123); + delete object; +} + +void tst_qqmlmoduleplugin::importsChildPlugin21() +{ + QQmlEngine engine; + engine.addImportPath(m_importsDirectory); + QTest::ignoreMessage(QtWarningMsg, "child plugin2.1 created"); + QTest::ignoreMessage(QtWarningMsg, "child import2.1 worked"); + QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlPluginType.ChildPlugin' does not contain a module identifier directive - it cannot be protected from external registrations."); + QQmlComponent component(&engine, testFileUrl(QStringLiteral("child21.qml"))); + foreach (QQmlError err, component.errors()) + qWarning() << err; + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("value").toInt(),123); + delete object; +} + QTEST_MAIN(tst_qqmlmoduleplugin) #include "tst_qqmlmoduleplugin.moc" diff --git a/tests/auto/qml/qqmltypeloader/SlowImport/plugin.h b/tests/auto/qml/qqmltypeloader/SlowImport/plugin.h index d3a3b81832..34b3920a38 100644 --- a/tests/auto/qml/qqmltypeloader/SlowImport/plugin.h +++ b/tests/auto/qml/qqmltypeloader/SlowImport/plugin.h @@ -35,7 +35,7 @@ class SlowPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: void registerTypes(const char *uri); diff --git a/tests/auto/qml/qqmltypeloader/data/trim_cache.qml b/tests/auto/qml/qqmltypeloader/data/trim_cache.qml new file mode 100644 index 0000000000..74303977dd --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/trim_cache.qml @@ -0,0 +1,8 @@ +import QtQuick 2.2 +Rectangle +{ + objectName: "dings" + width: 100 + height: 100 + color: "blue" +} diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp index 24358897f7..ef1ea3a897 100644 --- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp +++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp @@ -30,6 +30,9 @@ #include <QtQml/qqmlengine.h> #include <QtQuick/qquickview.h> #include <QtQuick/qquickitem.h> +#include <QtQml/private/qqmlengine_p.h> +#include <QtQml/private/qqmltypeloader_p.h> +#include <QtQml/private/qqmlcompiler_p.h> #include "../../shared/util.h" class tst_QQMLTypeLoader : public QQmlDataTest @@ -39,6 +42,7 @@ class tst_QQMLTypeLoader : public QQmlDataTest private slots: void testLoadComplete(); void loadComponentSynchronously(); + void trimCache(); }; void tst_QQMLTypeLoader::testLoadComplete() @@ -68,6 +72,32 @@ void tst_QQMLTypeLoader::loadComponentSynchronously() QVERIFY(o); } +void tst_QQMLTypeLoader::trimCache() +{ + QQmlEngine engine; + QQmlTypeLoader &loader = QQmlEnginePrivate::get(&engine)->typeLoader; + for (int i = 0; i < 256; ++i) { + QUrl url = testFileUrl("trim_cache.qml"); + url.setQuery(QString::number(i)); + + QQmlTypeData *data = loader.getType(url); + if (i % 5 == 0) // keep references to some of them so that they aren't trimmed + data->compiledData()->addref(); + + data->release(); + } + + for (int i = 0; i < 256; ++i) { + QUrl url = testFileUrl("trim_cache.qml"); + url.setQuery(QString::number(i)); + if (i % 5 == 0) + QVERIFY(loader.isTypeLoaded(url)); + else if (i < 128) + QVERIFY(!loader.isTypeLoaded(url)); + // The cache is free to keep the others. + } +} + QTEST_MAIN(tst_QQMLTypeLoader) #include "tst_qqmltypeloader.moc" diff --git a/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp b/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp index ab111a6cd3..77fa1292c4 100644 --- a/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp +++ b/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp @@ -39,7 +39,6 @@ #include "../shared/visualtestutil.h" Q_DECLARE_METATYPE(QQuickAnchors::Anchor) -Q_DECLARE_METATYPE(QQuickAnchorLine::AnchorLine) using namespace QQuickVisualTestUtil; @@ -351,14 +350,13 @@ void tst_qquickanchors::illegalSets_data() void tst_qquickanchors::reset() { QFETCH(QString, side); - QFETCH(QQuickAnchorLine::AnchorLine, anchorLine); - QFETCH(QQuickAnchors::Anchor, usedAnchor); + QFETCH(QQuickAnchors::Anchor, anchor); QQuickItem *baseItem = new QQuickItem; - QQuickAnchorLine anchor; - anchor.item = baseItem; - anchor.anchorLine = anchorLine; + QQuickAnchorLine anchorLine; + anchorLine.item = baseItem; + anchorLine.anchorLine = anchor; QQuickItem *item = new QQuickItem; QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); @@ -366,11 +364,11 @@ void tst_qquickanchors::reset() const QMetaObject *meta = itemPrivate->anchors()->metaObject(); QMetaProperty p = meta->property(meta->indexOfProperty(side.toUtf8().constData())); - QVERIFY(p.write(itemPrivate->anchors(), qVariantFromValue(anchor))); - QCOMPARE(itemPrivate->anchors()->usedAnchors().testFlag(usedAnchor), true); + QVERIFY(p.write(itemPrivate->anchors(), qVariantFromValue(anchorLine))); + QCOMPARE(itemPrivate->anchors()->usedAnchors().testFlag(anchor), true); QVERIFY(p.reset(itemPrivate->anchors())); - QCOMPARE(itemPrivate->anchors()->usedAnchors().testFlag(usedAnchor), false); + QCOMPARE(itemPrivate->anchors()->usedAnchors().testFlag(anchor), false); delete item; delete baseItem; @@ -379,17 +377,16 @@ void tst_qquickanchors::reset() void tst_qquickanchors::reset_data() { QTest::addColumn<QString>("side"); - QTest::addColumn<QQuickAnchorLine::AnchorLine>("anchorLine"); - QTest::addColumn<QQuickAnchors::Anchor>("usedAnchor"); + QTest::addColumn<QQuickAnchors::Anchor>("anchor"); - QTest::newRow("left") << "left" << QQuickAnchorLine::Left << QQuickAnchors::LeftAnchor; - QTest::newRow("top") << "top" << QQuickAnchorLine::Top << QQuickAnchors::TopAnchor; - QTest::newRow("right") << "right" << QQuickAnchorLine::Right << QQuickAnchors::RightAnchor; - QTest::newRow("bottom") << "bottom" << QQuickAnchorLine::Bottom << QQuickAnchors::BottomAnchor; + QTest::newRow("left") << "left" << QQuickAnchors::LeftAnchor; + QTest::newRow("top") << "top" << QQuickAnchors::TopAnchor; + QTest::newRow("right") << "right" << QQuickAnchors::RightAnchor; + QTest::newRow("bottom") << "bottom" << QQuickAnchors::BottomAnchor; - QTest::newRow("hcenter") << "horizontalCenter" << QQuickAnchorLine::HCenter << QQuickAnchors::HCenterAnchor; - QTest::newRow("vcenter") << "verticalCenter" << QQuickAnchorLine::VCenter << QQuickAnchors::VCenterAnchor; - QTest::newRow("baseline") << "baseline" << QQuickAnchorLine::Baseline << QQuickAnchors::BaselineAnchor; + QTest::newRow("hcenter") << "horizontalCenter" << QQuickAnchors::HCenterAnchor; + QTest::newRow("vcenter") << "verticalCenter" << QQuickAnchors::VCenterAnchor; + QTest::newRow("baseline") << "baseline" << QQuickAnchors::BaselineAnchor; } void tst_qquickanchors::resetConvenience() diff --git a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp index b0f0f886a0..b34f58f7c4 100644 --- a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp +++ b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp @@ -60,6 +60,7 @@ private slots: void remote_data(); void sourceSize(); void sourceSizeChanges(); + void sourceSizeChanges_intermediate(); void sourceSizeReadOnly(); void invalidSource(); void qtbug_16520(); @@ -205,16 +206,12 @@ void tst_qquickanimatedimage::mirror_notRunning() int frame = anim->currentFrame(); bool playing = anim->isPlaying(); - bool paused = anim->isPlaying(); + bool paused = anim->isPaused(); anim->setProperty("mirror", true); screenshot = window.grabWindow(); screenshot.save("screen.png"); -#if defined(Q_OS_WIN) - // QTBUG-36717 - QSKIP("This test is failing in the CI system under mysterious circumstances"); -#endif QCOMPARE(screenshot, expected); // mirroring should not change the current frame or playing status @@ -374,6 +371,28 @@ void tst_qquickanimatedimage::sourceSizeChanges() delete anim; } +void tst_qquickanimatedimage::sourceSizeChanges_intermediate() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData("import QtQuick 2.0\nAnimatedImage { readonly property int testWidth: status === AnimatedImage.Ready ? sourceSize.width : -1; source: srcImage }", QUrl::fromLocalFile("")); + QTRY_VERIFY(component.isReady()); + QQmlContext *ctxt = engine.rootContext(); + ctxt->setContextProperty("srcImage", ""); + + QScopedPointer<QQuickAnimatedImage> anim(qobject_cast<QQuickAnimatedImage*>(component.create())); + QVERIFY(anim != 0); + + ctxt->setContextProperty("srcImage", testFileUrl("hearts.gif")); + QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready); + QTRY_COMPARE(anim->property("testWidth").toInt(), anim->sourceSize().width()); + + ctxt->setContextProperty("srcImage", testFileUrl("hearts_copy.gif")); + QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready); + QTRY_COMPARE(anim->property("testWidth").toInt(), anim->sourceSize().width()); +} + + void tst_qquickanimatedimage::qtbug_16520() { TestHTTPServer server; diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml b/tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml new file mode 100644 index 0000000000..7095602ea2 --- /dev/null +++ b/tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml @@ -0,0 +1,22 @@ +import QtQuick 2.0 +import QtTest 1.1 + +CanvasTestCase { + id:testCase + name: "imagedata" + function init_data() { return testData("2d"); } + function test_rounding(row) { + var canvas = createCanvasObject(row); + var ctx = canvas.getContext('2d'); + var size = 17 + ctx.reset(); + ctx.fillStyle = Qt.rgba(0.7, 0.8, 0.9, 1.0); + ctx.fillRect(0, 0, size, size); + + var center = size / 2; + var imageData = ctx.getImageData(center, center, center, center); + comparePixel(ctx, center, center, imageData.data[0], imageData.data[1], imageData.data[2], imageData.data[3]); + + canvas.destroy(); + } +} diff --git a/tests/auto/quick/qquickcanvasitem/qquickcanvasitem.pro b/tests/auto/quick/qquickcanvasitem/qquickcanvasitem.pro index 3c41d498e5..c6d2a69f8c 100644 --- a/tests/auto/quick/qquickcanvasitem/qquickcanvasitem.pro +++ b/tests/auto/quick/qquickcanvasitem/qquickcanvasitem.pro @@ -25,6 +25,7 @@ OTHER_FILES += \ data/tst_arcto.qml \ data/tst_arc.qml \ data/tst_context.qml \ + data/tst_imagedata.qml \ data/CanvasTestCase.qml \ data/CanvasComponent.qml \ data/tst_image.qml \ diff --git a/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp b/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp index a7b5f4943e..6a919d048e 100644 --- a/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp +++ b/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp @@ -139,6 +139,8 @@ private slots: void cleanupTestCase(); void active(); + void setActive_data(); + void setActive(); void drop(); void move(); void parentChange(); @@ -374,6 +376,50 @@ void tst_QQuickDrag::active() QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0); QCOMPARE(dropTarget.moveEvents, 0); } +void tst_QQuickDrag::setActive_data() +{ + QTest::addColumn<QString>("dragType"); + + QTest::newRow("default") << ""; + QTest::newRow("internal") << "Drag.dragType: Drag.Internal"; + QTest::newRow("none") << "Drag.dragType: Drag.None"; + /* We don't test Drag.Automatic, because that causes QDrag::exec() to be + * invoked, and on some platforms tha's implemented by running a main loop + * until the drag has finished -- and at that point, the Drag.active will + * be false again. */ +} + +// QTBUG-52540 +void tst_QQuickDrag::setActive() +{ + QFETCH(QString, dragType); + + QQuickWindow window; + TestDropTarget dropTarget(window.contentItem()); + dropTarget.setSize(QSizeF(100, 100)); + QQmlComponent component(&engine); + component.setData( + "import QtQuick 2.0\n" + "Item {\n" + "property bool dragActive: Drag.active\n" + "property Item dragTarget: Drag.target\n" + + dragType.toUtf8() + "\n" + "x: 50; y: 50\n" + "width: 10; height: 10\n" + "}", QUrl()); + QScopedPointer<QObject> object(component.create()); + QQuickItem *item = qobject_cast<QQuickItem *>(object.data()); + QVERIFY(item); + item->setParentItem(&dropTarget); + + QCOMPARE(evaluate<bool>(item, "Drag.active"), false); + QCOMPARE(evaluate<bool>(item, "dragActive"), false); + + evaluate<void>(item, "Drag.active = true"); + QCOMPARE(evaluate<bool>(item, "Drag.active"), true); + QCOMPARE(evaluate<bool>(item, "dragActive"), true); +} + void tst_QQuickDrag::drop() { QQuickWindow window; diff --git a/tests/auto/quick/qquickpathview/data/movementDirection.qml b/tests/auto/quick/qquickpathview/data/movementDirection.qml new file mode 100644 index 0000000000..fce914dd68 --- /dev/null +++ b/tests/auto/quick/qquickpathview/data/movementDirection.qml @@ -0,0 +1,43 @@ +import QtQuick 2.0 + +Item { + id: root + width: 320; height: 480 + + PathView { + id: view + objectName: "view" + anchors.fill: parent + + model: ListModel { + ListElement { lColor: "red" } + ListElement { lColor: "green" } + ListElement { lColor: "yellow" } + ListElement { lColor: "blue" } + ListElement { lColor: "purple" } + ListElement { lColor: "gray" } + ListElement { lColor: "brown" } + ListElement { lColor: "thistle" } + } + + delegate: Component { + id: photoDelegate + Rectangle { + id: wrapper + objectName: "wrapper" + width: 40; height: 40; color: lColor + + Text { text: index } + } + } + + snapMode: PathView.SnapToItem + highlightMoveDuration: 1000 + path: Path { + startX: 0+20; startY: root.height/2 + PathLine { x: root.width*2; y: root.height/2 } + } + + Text { text: "Offset: " + view.offset } + } +} diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp index 51c772f540..6761313210 100644 --- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp +++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp @@ -137,6 +137,8 @@ private slots: void jsArrayChange(); void qtbug42716(); void addCustomAttribute(); + void movementDirection_data(); + void movementDirection(); }; class TestObject : public QObject @@ -2383,6 +2385,72 @@ void tst_QQuickPathView::addCustomAttribute() window->show(); } +void tst_QQuickPathView::movementDirection_data() +{ + QTest::addColumn<QQuickPathView::MovementDirection>("movementdirection"); + QTest::addColumn<int>("toidx"); + QTest::addColumn<qreal>("fromoffset"); + QTest::addColumn<qreal>("tooffset"); + + QTest::newRow("default-shortest") << QQuickPathView::Shortest << 3 << 8.0 << 5.0; + QTest::newRow("negative") << QQuickPathView::Negative << 2 << 0.0 << 6.0; + QTest::newRow("positive") << QQuickPathView::Positive << 3 << 8.0 << 5.0; + +} + +static void verify_offsets(QQuickPathView *pathview, int toidx, qreal fromoffset, qreal tooffset) +{ + pathview->setCurrentIndex(toidx); + bool started = false; + qreal first, second; + QTest::qWait(100); + first = pathview->offset(); + while (1) { + QTest::qWait(10); // highlightMoveDuration: 1000 + second = pathview->offset(); + if (!started && second != first) { // animation started + started = true; + break; + } + } + + if (tooffset > fromoffset) { + QVERIFY(fromoffset <= first); + QVERIFY(first <= second); + QVERIFY(second <= tooffset); + } else { + QVERIFY(fromoffset >= first); + QVERIFY(first >= second); + QVERIFY(second >= tooffset); + } + QTRY_COMPARE(pathview->offset(), tooffset); +} + +void tst_QQuickPathView::movementDirection() +{ + QFETCH(QQuickPathView::MovementDirection, movementdirection); + QFETCH(int, toidx); + QFETCH(qreal, fromoffset); + QFETCH(qreal, tooffset); + + QScopedPointer<QQuickView> window(createView()); + QQuickViewTestUtil::moveMouseAway(window.data()); + window->setSource(testFileUrl("movementDirection.qml")); + window->show(); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window.data())); + QCOMPARE(window.data(), qGuiApp->focusWindow()); + + QQuickPathView *pathview = window->rootObject()->findChild<QQuickPathView*>("view"); + QVERIFY(pathview != 0); + QVERIFY(pathview->offset() == 0.0); + QVERIFY(pathview->currentIndex() == 0); + pathview->setMovementDirection(movementdirection); + QVERIFY(pathview->movementDirection() == movementdirection); + + verify_offsets(pathview, toidx, fromoffset, tooffset); +} + QTEST_MAIN(tst_QQuickPathView) #include "tst_qquickpathview.moc" diff --git a/tests/auto/quick/qquickstates/tst_qquickstates.cpp b/tests/auto/quick/qquickstates/tst_qquickstates.cpp index 562d53bceb..9b152b0676 100644 --- a/tests/auto/quick/qquickstates/tst_qquickstates.cpp +++ b/tests/auto/quick/qquickstates/tst_qquickstates.cpp @@ -698,7 +698,7 @@ void tst_qquickstates::anchorChanges() rectPrivate->setState("right"); QCOMPARE(innerRect->x(), qreal(150)); QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect)); - QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickAnchorLine::Invalid); //### was reset (how do we distinguish from not set at all) + QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickAnchors::InvalidAnchor); //### was reset (how do we distinguish from not set at all) QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item); QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine); @@ -891,7 +891,7 @@ void tst_qquickstates::anchorChangesRTL() rectPrivate->setState("right"); QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(150)); QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect)); - QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickAnchorLine::Invalid); //### was reset (how do we distinguish from not set at all) + QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickAnchors::InvalidAnchor); //### was reset (how do we distinguish from not set at all) QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item); QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine); diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp index 7ea36bbafa..79d4adbb3d 100644 --- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp +++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp @@ -701,7 +701,7 @@ void tst_qquicktext::textFormat() QQuickText *text = qobject_cast<QQuickText *>(object.data()); QVERIFY(text); - QSignalSpy spy(text, SIGNAL(textFormatChanged(TextFormat))); + QSignalSpy spy(text, &QQuickText::textFormatChanged); QCOMPARE(text->textFormat(), QQuickText::AutoText); diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp index e26bf6f4e4..24cfadc2d3 100644 --- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp +++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp @@ -1390,7 +1390,7 @@ void tst_qquicktextinput::mouseSelectionMode_accessors() QQuickTextInput *input = qobject_cast<QQuickTextInput *>(object.data()); QVERIFY(input); - QSignalSpy spy(input, SIGNAL(mouseSelectionModeChanged(SelectionMode))); + QSignalSpy spy(input, &QQuickTextInput::mouseSelectionModeChanged); QCOMPARE(input->mouseSelectionMode(), QQuickTextInput::SelectCharacters); diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro index 13bd6d78e2..2e43702e7c 100644 --- a/tests/auto/quick/quick.pro +++ b/tests/auto/quick/quick.pro @@ -75,6 +75,7 @@ QUICKTESTS = \ qquickvisualdatamodel \ qquickview \ qquickcanvasitem \ + qquickdesignersupport \ qquickscreen \ touchmouse \ scenegraph diff --git a/tests/benchmarks/qml/creation/tst_creation.cpp b/tests/benchmarks/qml/creation/tst_creation.cpp index 2c8aa04a6a..fa94fd4d46 100644 --- a/tests/benchmarks/qml/creation/tst_creation.cpp +++ b/tests/benchmarks/qml/creation/tst_creation.cpp @@ -74,6 +74,9 @@ private slots: void bindings_parent_qml(); + void anchors_creation(); + void anchors_heightChange(); + private: QQmlEngine engine; }; @@ -462,6 +465,38 @@ void tst_creation::bindings_parent_qml() delete obj; } +void tst_creation::anchors_creation() +{ + QQmlComponent component(&engine); + component.setData("import QtQuick 2.0\nItem { Item { anchors.bottom: parent.bottom } }", QUrl()); + + QObject *obj = component.create(); + delete obj; + + QBENCHMARK { + QObject *obj = component.create(); + delete obj; + } +} + +void tst_creation::anchors_heightChange() +{ + QQmlComponent component(&engine); + component.setData("import QtQuick 2.0\nItem { Item { anchors.bottom: parent.bottom } }", QUrl()); + + QObject *obj = component.create(); + auto item = qobject_cast<QQuickItem *>(obj); + Q_ASSERT(item); + int height = 1; + + QBENCHMARK { + item->setHeight(height); + height += 1; + } + + delete obj; +} + QTEST_MAIN(tst_creation) #include "tst_creation.moc" diff --git a/tests/manual/highdpi/imageprovider.cpp b/tests/manual/highdpi/imageprovider.cpp index 1856a1ea9a..33a69cb87e 100644 --- a/tests/manual/highdpi/imageprovider.cpp +++ b/tests/manual/highdpi/imageprovider.cpp @@ -79,7 +79,7 @@ public: class ImageProviderExtensionPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: void registerTypes(const char *uri) { @@ -95,7 +95,4 @@ public: }; -#define QQmlExtensionInterface_iid "org.qt-project.Qt.QQmlExtensionInterface" - - #include "imageprovider.moc" diff --git a/tests/manual/qmlplugindump/tests/dumper/Dummy/dummy_plugin.h b/tests/manual/qmlplugindump/tests/dumper/Dummy/dummy_plugin.h index 739eae0f8a..86e80e6a08 100644 --- a/tests/manual/qmlplugindump/tests/dumper/Dummy/dummy_plugin.h +++ b/tests/manual/qmlplugindump/tests/dumper/Dummy/dummy_plugin.h @@ -34,7 +34,7 @@ class DummyPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: void registerTypes(const char *uri); diff --git a/tests/manual/qmlplugindump/tests/dumper/Imports/imports_plugin.h b/tests/manual/qmlplugindump/tests/dumper/Imports/imports_plugin.h index 7c136dea30..fd09584d47 100644 --- a/tests/manual/qmlplugindump/tests/dumper/Imports/imports_plugin.h +++ b/tests/manual/qmlplugindump/tests/dumper/Imports/imports_plugin.h @@ -34,7 +34,7 @@ class ImportsPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: void registerTypes(const char *uri); diff --git a/tests/manual/qmlplugindump/tests/dumper/Versions/versions_plugin.h b/tests/manual/qmlplugindump/tests/dumper/Versions/versions_plugin.h index 91e9ce4174..4ba68a8125 100644 --- a/tests/manual/qmlplugindump/tests/dumper/Versions/versions_plugin.h +++ b/tests/manual/qmlplugindump/tests/dumper/Versions/versions_plugin.h @@ -34,7 +34,7 @@ class VersionsPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: void registerTypes(const char *uri); diff --git a/tests/manual/qmltypememory/TestPlugin/plugin.cpp b/tests/manual/qmltypememory/TestPlugin/plugin.cpp index ddc5430b43..d6cbf05a55 100644 --- a/tests/manual/qmltypememory/TestPlugin/plugin.cpp +++ b/tests/manual/qmltypememory/TestPlugin/plugin.cpp @@ -50,7 +50,7 @@ class TestType : public QObject class TestPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: void registerTypes(const char *uri) diff --git a/tests/manual/scenegraph_lancelot/data/text/textedit_multiline_selected_linebreaks_and_linewraps2.qml b/tests/manual/scenegraph_lancelot/data/text/textedit_multiline_selected_linebreaks_and_linewraps2.qml new file mode 100644 index 0000000000..c16bc9cdf7 --- /dev/null +++ b/tests/manual/scenegraph_lancelot/data/text/textedit_multiline_selected_linebreaks_and_linewraps2.qml @@ -0,0 +1,22 @@ +import QtQuick 2.0 + +Item { + width: 550 + height: 480 + + TextEdit { + id: textEdit + anchors.centerIn: parent + width: 550 + textFormat: TextEdit.RichText + text: "A<br /> + This is a long message to demenostrate a text selection issue. I need to type some more text here. This is line 3<br /> + This is a long message to demenostrate a text selection issue. I need to type some more text here. This is line 4" + wrapMode: TextEdit.Wrap + + Component.onCompleted: { + textEdit.selectAll() + } + } + +} diff --git a/tools/qmlimportscanner/main.cpp b/tools/qmlimportscanner/main.cpp index dcb9709bb8..2569d78c63 100644 --- a/tools/qmlimportscanner/main.cpp +++ b/tools/qmlimportscanner/main.cpp @@ -157,24 +157,46 @@ QVariantMap pluginsForModulePath(const QString &modulePath) { // Search for a given qml import in g_qmlImportPaths. QString resolveImportPath(const QString &uri, const QString &version) { - // Create path from uri (QtQuick.Controls -> QtQuick/Controls) - QString path = uri; - path.replace(QLatin1Char('.'), QLatin1Char('/')); - // search for the most spesifc version first - QString versionedName = path + QLatin1Char('.') + version; + const QLatin1Char dot('.'); + const QLatin1Char slash('/'); + const QStringList parts = uri.split(dot, QString::SkipEmptyParts); + + QString ver = version; while (true) { - // look in all g_qmlImportPaths foreach (const QString &qmlImportPath, g_qmlImportPaths) { - QString candidatePath = QDir::cleanPath(qmlImportPath + QLatin1Char('/') + versionedName); - if (QDir(candidatePath).exists()) - return candidatePath; // import found + // Search for the most specific version first, and search + // also for the version in parent modules. For example: + // - qml/QtQml/Models.2.0 + // - qml/QtQml.2.0/Models + // - qml/QtQml/Models.2 + // - qml/QtQml.2/Models + // - qml/QtQml/Models + if (ver.isEmpty()) { + const QString candidatePath = QDir::cleanPath(qmlImportPath + slash + parts.join(slash)); + if (QDir(candidatePath).exists()) + return candidatePath; // import found + } else { + for (int index = parts.count() - 1; index >= 0; --index) { + const QString candidatePath = QDir::cleanPath(qmlImportPath + slash + + parts.mid(0, index + 1).join(slash) + + dot + ver + slash + + parts.mid(index + 1).join(slash)); + + if (QDir(candidatePath).exists()) + return candidatePath; // import found + } + } } // remove the last version digit; stop if there are none left - int lastDot = versionedName.lastIndexOf(QLatin1Char('.')); - if (lastDot == -1) + if (ver.isEmpty()) break; - versionedName = versionedName.mid(0, lastDot); + + int lastDot = ver.lastIndexOf(dot); + if (lastDot == -1) + ver.clear(); + else + ver = ver.mid(0, lastDot); } return QString(); // not found diff --git a/tools/qmlplugindump/Info.plist b/tools/qmlplugindump/Info.plist index f35846d048..e6c4914ca0 100644 --- a/tools/qmlplugindump/Info.plist +++ b/tools/qmlplugindump/Info.plist @@ -5,11 +5,11 @@ <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleSignature</key> - <string>@TYPEINFO@</string> + <string>????</string> <key>CFBundleExecutable</key> - <string>@EXECUTABLE@</string> + <string>qmlplugindump</string> <key>CFBundleIdentifier</key> - <string>com.nokia.qt.qmlplugindump</string> + <string>org.qt-project.qt.qmlplugindump</string> <key>LSUIElement</key> <string>1</string> </dict> diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp index 7870e3a9df..d0d70fd0fe 100644 --- a/tools/qmlplugindump/main.cpp +++ b/tools/qmlplugindump/main.cpp @@ -771,7 +771,7 @@ static bool readDependenciesData(QString dependenciesFile, const QByteArray &fil QString version = obj.value(QStringLiteral("version")).toString(); if (name.isEmpty() || urisToSkip.contains(name) || version.isEmpty()) continue; - if (name.endsWith(QLatin1String("Private"))) { + if (name.endsWith(QLatin1String("Private"), Qt::CaseInsensitive)) { if (verbose) std::cerr << "skipping private dependecy " << qPrintable( name ) << " " << qPrintable(version) << std::endl; |