diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2019-09-05 11:08:59 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2019-09-05 11:08:59 +0200 |
commit | 2746518c76e02c642ff29faf568de4de90216e58 (patch) | |
tree | 822a6d979c13b6450c221b2a45ccfb6674bcb8e4 /src/qml/qml | |
parent | 9e32b23a1514f367921b4a9ee25bc864a008463c (diff) | |
parent | bdf0a46c289298f7378796d62ae5fb283e08657d (diff) |
Merge remote-tracking branch 'origin/dev' into wip/qt6
Conflicts:
.qmake.conf
src/qml/qml/qqmlengine.cpp
src/qmlmodels/qqmlmodelsmodule.cpp
Change-Id: Id60420f8250a9c97fcfe56d4eea19b62c6870404
Diffstat (limited to 'src/qml/qml')
-rw-r--r-- | src/qml/qml/qml.pri | 2 | ||||
-rw-r--r-- | src/qml/qml/qqml.h | 10 | ||||
-rw-r--r-- | src/qml/qml/qqmlapplicationengine.cpp | 18 | ||||
-rw-r--r-- | src/qml/qml/qqmlapplicationengine.h | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmlapplicationengine_p.h | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 74 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent_p.h | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 24 | ||||
-rw-r--r-- | src/qml/qml/qqmlimport.cpp | 10 | ||||
-rw-r--r-- | src/qml/qml/qqmlloggingcategory_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertyvalidator.cpp | 18 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetype.cpp | 7 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetype_p.h | 4 |
14 files changed, 142 insertions, 34 deletions
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri index 08591b5237..2e9c6f3de6 100644 --- a/src/qml/qml/qml.pri +++ b/src/qml/qml/qml.pri @@ -186,5 +186,7 @@ qtConfig(qml-network) { $$PWD/qqmltypeloadernetworkreplyproxy.cpp } +android: DEFINES += LIBS_SUFFIX='\\"_$${QT_ARCH}.so\\"' + include(ftw/ftw.pri) include(v8/v8.pri) diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index bfd1c88b28..a93b012c70 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -102,7 +102,7 @@ class QQmlPropertyValueInterceptor; void Q_QML_EXPORT qmlClearTypeRegistrations(); template<typename T> -int qmlRegisterType() +int qmlRegisterAnonymousType(const char *uri, int versionMajor=1) { QML_GETTYPENAMES @@ -115,7 +115,7 @@ int qmlRegisterType() nullptr, QString(), - nullptr, 0, 0, nullptr, &T::staticMetaObject, + uri, versionMajor, 0, nullptr, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -133,6 +133,12 @@ int qmlRegisterType() return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); } +template<typename T> +QT_DEPRECATED_VERSION_X_5_14("Use qmlRegisterAnonymousType instead") int qmlRegisterType() +{ + return qmlRegisterAnonymousType<T>(""); +} + int Q_QML_EXPORT qmlRegisterTypeNotAvailable(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& message); template<typename T> diff --git a/src/qml/qml/qqmlapplicationengine.cpp b/src/qml/qml/qqmlapplicationengine.cpp index e93cfcadb9..d04a89b514 100644 --- a/src/qml/qml/qqmlapplicationengine.cpp +++ b/src/qml/qml/qqmlapplicationengine.cpp @@ -131,7 +131,7 @@ void QQmlApplicationEnginePrivate::finishLoad(QQmlComponent *c) q->objectCreated(nullptr, c->url()); break; case QQmlComponent::Ready: { - auto newObj = c->create(); + auto newObj = initialProperties.empty() ? c->create() : c->createWithInitialProperties(initialProperties); objects << newObj; QObject::connect(newObj, &QObject::destroyed, q, [&](QObject *obj) { objects.removeAll(obj); }); q->objectCreated(objects.constLast(), c->url()); @@ -279,6 +279,22 @@ void QQmlApplicationEngine::load(const QString &filePath) } /*! + Sets the initial properties with which the QML component gets initialized after + it gets loaded. + + + \sa QQmlComponent::setInitialProperties + \sa QQmlApplicationEngine::load + \sa QQmlApplicationEngine::loadData + \since 5.14 +*/ +void QQmlApplicationEngine::setInitialProperties(const QVariantMap &initialProperties) +{ + Q_D(QQmlApplicationEngine); + d->initialProperties = initialProperties; +} + +/*! Loads the QML given in \a data. The object tree defined by \a data is instantiated immediately. diff --git a/src/qml/qml/qqmlapplicationengine.h b/src/qml/qml/qqmlapplicationengine.h index bb5d6b5d68..2b4de91154 100644 --- a/src/qml/qml/qqmlapplicationengine.h +++ b/src/qml/qml/qqmlapplicationengine.h @@ -66,6 +66,7 @@ public: public Q_SLOTS: void load(const QUrl &url); void load(const QString &filePath); + void setInitialProperties(const QVariantMap &initialProperties); void loadData(const QByteArray &data, const QUrl &url = QUrl()); Q_SIGNALS: diff --git a/src/qml/qml/qqmlapplicationengine_p.h b/src/qml/qml/qqmlapplicationengine_p.h index 7a341847bd..1279e400e8 100644 --- a/src/qml/qml/qqmlapplicationengine_p.h +++ b/src/qml/qml/qqmlapplicationengine_p.h @@ -73,6 +73,7 @@ public: void loadTranslations(const QUrl &rootFile); void finishLoad(QQmlComponent *component); QList<QObject *> objects; + QVariantMap initialProperties; }; QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index fefe2bc685..ed8c41a582 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -350,6 +350,32 @@ void QQmlComponentPrivate::clear() compilationUnit = nullptr; } +QObject *QQmlComponentPrivate::doBeginCreate(QQmlComponent *q, QQmlContext *context) +{ + if (!engine) { + // ###Qt6: In Qt 6, it should be impossible for users to create a QQmlComponent without an engine, and we can remove this check + qWarning("QQmlComponent: Must provide an engine before calling create"); + return nullptr; + } + if (!context) + context = engine->rootContext(); + return q->beginCreate(context); +} + +bool QQmlComponentPrivate::setInitialProperty(QObject *component, const QString& name, const QVariant &value) +{ + QQmlProperty prop(component, name); + auto privProp = QQmlPropertyPrivate::get(prop); + if (!prop.isValid() || !privProp->writeValueProperty(value, nullptr)) { + QQmlError error{}; + error.setUrl(url); + error.setDescription(QLatin1String("Could not set property %1").arg(name)); + state.errors.push_back(error); + return false; + } else + return true; +} + /*! \internal */ @@ -780,18 +806,28 @@ QObject *QQmlComponent::create(QQmlContext *context) { Q_D(QQmlComponent); - if (!d->engine) { - // ###Qt6: In Qt 6, it should be impossible for users to create a QQmlComponent without an engine, and we can remove this check - qWarning("QQmlComponent: Must provide an engine before calling create"); - return nullptr; - } + QObject *rv = d->doBeginCreate(this, context); + if (rv) + completeCreate(); + return rv; +} - if (!context) - context = d->engine->rootContext(); +/*! + Create an object instance of this component, and initialize its toplevel properties according to initalPropertyValues. - QObject *rv = beginCreate(context); - if (rv) + + \sa QQmlComponent::create + \since 5.14 +*/ +QObject *QQmlComponent::createWithInitialProperties(const QVariantMap& initialProperties, QQmlContext *context) +{ + Q_D(QQmlComponent); + + QObject *rv = d->doBeginCreate(this, context); + if (rv) { + setInitialProperties(rv, initialProperties); completeCreate(); + } return rv; } @@ -1067,6 +1103,26 @@ void QQmlComponent::create(QQmlIncubator &incubator, QQmlContext *context, enginePriv->incubate(incubator, forContextData); } +/*! + Set toplevel properties of the component. + + + This method provides advanced control over component instance creation. + In general, programmers should use + \l QQmlComponent::createWithInitialProperties to create a component. + + Use this method after beginCreate and before completeCreate has been called. + If a provided property does not exist, a warning is issued. + + \since 5.14 +*/ +void QQmlComponent::setInitialProperties(QObject *component, const QVariantMap &properties) +{ + Q_D(QQmlComponent); + for (auto it = properties.constBegin(); it != properties.constEnd(); ++it) + d->setInitialProperty(component, it.key(), it.value()); +} + /* This is essentially a copy of QQmlComponent::create(); except it takes the QQmlContextData arguments instead of QQmlContext which means we don't have to construct the rather weighty diff --git a/src/qml/qml/qqmlcomponent.h b/src/qml/qml/qqmlcomponent.h index 39b6d4526f..f259c99b08 100644 --- a/src/qml/qml/qqmlcomponent.h +++ b/src/qml/qml/qqmlcomponent.h @@ -100,6 +100,8 @@ public: QUrl url() const; virtual QObject *create(QQmlContext *context = nullptr); + QObject *createWithInitialProperties(const QVariantMap& initialProperties, QQmlContext *context = nullptr); + void setInitialProperties(QObject *component, const QVariantMap &properties); virtual QObject *beginCreate(QQmlContext *); virtual void completeCreate(); diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h index 9a967501c9..2170646b89 100644 --- a/src/qml/qml/qqmlcomponent_p.h +++ b/src/qml/qml/qqmlcomponent_p.h @@ -143,6 +143,9 @@ public: static QQmlComponentPrivate *get(QQmlComponent *c) { return static_cast<QQmlComponentPrivate *>(QObjectPrivate::get(c)); } + + QObject *doBeginCreate(QQmlComponent *q, QQmlContext *context); + bool setInitialProperty(QObject *component, const QString &name, const QVariant& value); }; QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 8bf660d2ec..5fb5d73341 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -206,14 +206,18 @@ void QQmlEnginePrivate::defineModule() qmlRegisterType<QQmlBind>(uri, 2, 0, "Binding"); qmlRegisterType<QQmlBind, 8>(uri, 2, 8, "Binding"); // Only available in >= 2.8 qmlRegisterType<QQmlBind, 14>(uri, 2, 14, "Binding"); + + // TODO: We won't need Connections to be a custom type anymore once we can drop the + // automatic signal handler inference from undeclared properties. qmlRegisterCustomType<QQmlConnections>(uri, 2, 0, "Connections", new QQmlConnectionsParser); - qmlRegisterCustomType<QQmlConnections, 1>(uri, 2, 3, "Connections", new QQmlConnectionsParser); // Only available in QtQml >= 2.3 + qmlRegisterCustomType<QQmlConnections, 3>(uri, 2, 3, "Connections", new QQmlConnectionsParser); // Only available in QtQml >= 2.3 + #if QT_CONFIG(qml_animation) qmlRegisterType<QQmlTimer>(uri, 2, 0, "Timer"); #endif qmlRegisterType<QQmlLoggingCategory>(uri, 2, 8, "LoggingCategory"); // Only available in >= 2.8 - qmlRegisterType<QQmlLoggingCategory, 1>(uri, 2, 12, "LoggingCategory"); // Only available in >= 2.12 + qmlRegisterType<QQmlLoggingCategory, 12>(uri, 2, 12, "LoggingCategory"); // Only available in >= 2.12 #if QT_CONFIG(qml_locale) qmlRegisterUncreatableType<QQmlLocale>(uri, 2, 2, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()")); @@ -796,11 +800,12 @@ void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int in QMetaMethod m = QMetaObjectPrivate::signal(object->metaObject(), index); QList<QByteArray> parameterTypes = m.parameterTypes(); - int *types = (int *)malloc((parameterTypes.count() + 1) * sizeof(int)); - void **args = (void **) malloc((parameterTypes.count() + 1) *sizeof(void *)); + QScopedPointer<QMetaCallEvent> ev(new QMetaCallEvent(m.methodIndex(), 0, nullptr, + object, index, + parameterTypes.count() + 1)); - types[0] = 0; // return type - args[0] = nullptr; // return value + void **args = ev->args(); + int *types = ev->types(); for (int ii = 0; ii < parameterTypes.count(); ++ii) { const QByteArray &typeName = parameterTypes.at(ii); @@ -813,21 +818,16 @@ void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int in qWarning("QObject::connect: Cannot queue arguments of type '%s'\n" "(Make sure '%s' is registered using qRegisterMetaType().)", typeName.constData(), typeName.constData()); - free(types); - free(args); return; } args[ii + 1] = QMetaType::create(types[ii + 1], a[ii + 1]); } - QMetaCallEvent *ev = new QMetaCallEvent(m.methodIndex(), 0, nullptr, object, index, - parameterTypes.count() + 1, types, args); - QQmlThreadNotifierProxyObject *mpo = new QQmlThreadNotifierProxyObject; mpo->target = object; mpo->moveToThread(QObjectPrivate::get(object)->threadData->thread.loadAcquire()); - QCoreApplication::postEvent(mpo, ev); + QCoreApplication::postEvent(mpo, ev.take()); } else { QQmlNotifierEndpoint *ep = ddata->notify(index); diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 7c9c0da01a..31a7004407 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -1852,9 +1852,15 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader, QLatin1String(".so"), QLatin1String(".bundle") }; -# else // Unix +#else // Unix static const QString prefix = QLatin1String("lib"); - static const QStringList suffixes = { QLatin1String(".so") }; + static const QStringList suffixes = { +# if defined(Q_OS_ANDROID) + QStringLiteral(LIBS_SUFFIX), +# endif + QLatin1String(".so") + + }; #endif return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName, suffixes, prefix); diff --git a/src/qml/qml/qqmlloggingcategory_p.h b/src/qml/qml/qqmlloggingcategory_p.h index ece06e04b4..ee5d9af2e7 100644 --- a/src/qml/qml/qqmlloggingcategory_p.h +++ b/src/qml/qml/qqmlloggingcategory_p.h @@ -65,7 +65,7 @@ class QQmlLoggingCategory : public QObject, public QQmlParserStatus Q_INTERFACES(QQmlParserStatus) Q_PROPERTY(QString name READ name WRITE setName) - Q_PROPERTY(DefaultLogLevel defaultLogLevel READ defaultLogLevel WRITE setDefaultLogLevel REVISION 1) + Q_PROPERTY(DefaultLogLevel defaultLogLevel READ defaultLogLevel WRITE setDefaultLogLevel REVISION 12) public: enum DefaultLogLevel { diff --git a/src/qml/qml/qqmlpropertyvalidator.cpp b/src/qml/qml/qqmlpropertyvalidator.cpp index 71964aca64..7dbcbe986b 100644 --- a/src/qml/qml/qqmlpropertyvalidator.cpp +++ b/src/qml/qml/qqmlpropertyvalidator.cpp @@ -711,21 +711,25 @@ QQmlJS::DiagnosticMessage QQmlPropertyValidator::validateObjectBinding(QQmlPrope // Using -1 for the minor version ensures that we get the raw metaObject. QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(property->propType(), -1); - // Will be true if the assigned type inherits propertyMetaObject - bool isAssignable = false; - // Determine isAssignable value if (propertyMetaObject) { + // Will be true if the assigned type inherits propertyMetaObject + // Determine isAssignable value + bool isAssignable = false; QQmlPropertyCache *c = propertyCaches.at(binding->value.objectIndex); while (c && !isAssignable) { isAssignable |= c == propertyMetaObject; c = c->parent(); } - } - if (!isAssignable) { - return qQmlCompileError(binding->valueLocation, tr("Cannot assign object of type \"%1\" to property of type \"%2\" as the former is neither the same as the latter nor a sub-class of it.") - .arg(stringAt(compilationUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex)).arg(QLatin1String(QMetaType::typeName(property->propType())))); + if (!isAssignable) { + return qQmlCompileError(binding->valueLocation, tr("Cannot assign object of type \"%1\" to property of type \"%2\" as the former is neither the same as the latter nor a sub-class of it.") + .arg(stringAt(compilationUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex)).arg(QLatin1String(QMetaType::typeName(property->propType())))); + } + } else { + return qQmlCompileError(binding->valueLocation, tr("Cannot assign to property of unknown type \"%1\".") + .arg(QLatin1String(QMetaType::typeName(property->propType())))); } + } return noError; } diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp index 88f7b69dc2..2225191a9d 100644 --- a/src/qml/qml/qqmlvaluetype.cpp +++ b/src/qml/qml/qqmlvaluetype.cpp @@ -122,8 +122,10 @@ const QMetaObject *QQmlValueTypeFactoryImpl::metaObjectForMetaType(int t) return &QQmlRectValueType::staticMetaObject; case QVariant::RectF: return &QQmlRectFValueType::staticMetaObject; +#if QT_CONFIG(easingcurve) case QVariant::EasingCurve: return &QQmlEasingValueType::staticMetaObject; +#endif #if QT_CONFIG(qml_itemmodel) case QVariant::ModelIndex: return &QQmlModelIndexValueType::staticMetaObject; @@ -201,7 +203,9 @@ const QMetaObject *QQmlValueTypeFactory::metaObjectForMetaType(int type) void QQmlValueTypeFactory::registerValueTypes(const char *uri, int versionMajor, int versionMinor) { +#if QT_CONFIG(easingcurve) qmlRegisterValueTypeEnums<QQmlEasingValueType>(uri, versionMajor, versionMinor, "Easing"); +#endif } QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject) @@ -489,6 +493,7 @@ int QQmlRectValueType::bottom() const return v.bottom(); } +#if QT_CONFIG(easingcurve) QQmlEasingValueType::Type QQmlEasingValueType::type() const { return (QQmlEasingValueType::Type)v.type(); @@ -572,6 +577,8 @@ QVariantList QQmlEasingValueType::bezierCurve() const rv << QVariant(point.x()) << QVariant(point.y()); return rv; } +#endif // easingcurve + QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h index 89f1b71d61..75150b3f32 100644 --- a/src/qml/qml/qqmlvaluetype_p.h +++ b/src/qml/qml/qqmlvaluetype_p.h @@ -58,7 +58,9 @@ #include <QtCore/qobject.h> #include <QtCore/qrect.h> +#if QT_CONFIG(easingcurve) #include <QtCore/qeasingcurve.h> +#endif #include <QtCore/qvariant.h> QT_BEGIN_NAMESPACE @@ -210,6 +212,7 @@ public: int bottom() const; }; +#if QT_CONFIG(easingcurve) struct QQmlEasingValueType { QEasingCurve v; @@ -260,6 +263,7 @@ public: void setBezierCurve(const QVariantList &); QVariantList bezierCurve() const; }; +#endif template<typename T> int qmlRegisterValueTypeEnums(const char *uri, int versionMajor, int versionMinor, const char *qmlName) |