diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2020-02-21 01:00:10 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2020-02-21 09:00:37 +0100 |
commit | f6808f89a8c17e046f53b0bb5ff36cd9e24e9772 (patch) | |
tree | 43df8901d99f1e134d7688bdf0d30d28c1679147 | |
parent | e33e250080dbbb01015daafc8a79b569806d9467 (diff) | |
parent | 5054bb49a88a8ab76f586f79b6ef62a9142e6c83 (diff) |
Merge remote-tracking branch 'origin/5.15' into dev
Conflicts:
tests/auto/quick/qquickmousearea/BLACKLIST
Change-Id: I3de2c6377d57f5f9204d2cfc688d50a7a0b4150c
35 files changed, 289 insertions, 134 deletions
diff --git a/examples/qml/tutorials/extending-qml/chapter1-basics/chapter1-basics.pro b/examples/qml/tutorials/extending-qml/chapter1-basics/chapter1-basics.pro index 294a9ad0e8..1f777d2ea8 100644 --- a/examples/qml/tutorials/extending-qml/chapter1-basics/chapter1-basics.pro +++ b/examples/qml/tutorials/extending-qml/chapter1-basics/chapter1-basics.pro @@ -1,8 +1,10 @@ QT += qml quick +#![0] CONFIG += qmltypes QML_IMPORT_NAME = Charts QML_IMPORT_MAJOR_VERSION = 1 +#![0] HEADERS += piechart.h SOURCES += piechart.cpp \ diff --git a/src/qml/debugger/qqmldebugserviceinterfaces_p.h b/src/qml/debugger/qqmldebugserviceinterfaces_p.h index 644d9d6ba9..b259e047a1 100644 --- a/src/qml/debugger/qqmldebugserviceinterfaces_p.h +++ b/src/qml/debugger/qqmldebugserviceinterfaces_p.h @@ -105,6 +105,7 @@ class QDebugMessageService {}; class QQmlEngineControlService {}; class QQmlNativeDebugService {}; class QQmlDebugTranslationService { +public: virtual QString foundElidedText(QObject *, const QString &, const QString &) {return {};} virtual void foundTranslationBinding(QQmlTranslationBinding *, QObject *, QQmlContextData *) {} }; diff --git a/src/qml/doc/snippets/qml/qml-documents/Images.qml b/src/qml/doc/snippets/qml/qml-documents/Images.qml index 80a4d95fbb..fc9fa60282 100644 --- a/src/qml/doc/snippets/qml/qml-documents/Images.qml +++ b/src/qml/doc/snippets/qml/qml-documents/Images.qml @@ -81,4 +81,4 @@ Item { } property LabeledImage selectedImage: before } -// Images.qml +//! [document] diff --git a/src/qml/doc/src/cppintegration/definetypes.qdoc b/src/qml/doc/src/cppintegration/definetypes.qdoc index f66dc44383..cbbbd9ba58 100644 --- a/src/qml/doc/src/cppintegration/definetypes.qdoc +++ b/src/qml/doc/src/cppintegration/definetypes.qdoc @@ -307,7 +307,7 @@ merged with the original target class when used from within QML. For example: The \c leftMargin property is a new property added to an existing C++ type, \l QLineEdit, without modifying its source code. -The \l {QML_EXTENDED(extended)} macro is for registering extended types. The +The QML_EXTENDED(extended) macro is for registering extended types. The argument is the name of another class to be used as extension. An extension class is a regular QObject, with a constructor that takes a QObject diff --git a/src/qml/doc/src/cppintegration/extending-tutorial.qdoc b/src/qml/doc/src/cppintegration/extending-tutorial.qdoc index d587173e5a..458768bf18 100644 --- a/src/qml/doc/src/cppintegration/extending-tutorial.qdoc +++ b/src/qml/doc/src/cppintegration/extending-tutorial.qdoc @@ -103,11 +103,22 @@ functionality of an existing QObject-based class, it could inherit from that cla Alternatively, if we want to create a visual item that doesn't need to perform drawing operations with the QPainter API, we can just subclass QQuickItem. -The \c PieChart class defines the two properties, \c name and \c color, with the Q_PROPERTY macro, -and overrides QQuickPaintedItem::paint(). The class implementation in \c piechart.cpp -simply sets and returns the \c m_name and \c m_color values as appropriate, and -implements \c paint() to draw a simple pie chart. It also turns off the -QGraphicsItem::ItemHasNoContents flag to enable painting: +The \c PieChart class defines the two properties, \c name and \c color, with the +Q_PROPERTY macro, and overrides QQuickPaintedItem::paint(). The \c PieChart +class is registered using the QML_ELEMENT macro, to allow it to be used from +QML. If you don't register the class, \c app.qml won't be able to create a +\c PieChart. + +For the registration to take effect, the \c qmltypes option is added to +\c CONFIG in the project file and a \c QML_IMPORT_NAME and +\c QML_IMPORT_MAJOR_VERSION are given: + +\snippet tutorials/extending-qml/chapter1-basics/chapter1-basics.pro 0 + +The class implementation in \c piechart.cpp simply sets and returns the +\c m_name and \c m_color values as appropriate, and implements \c paint() to +draw a simple pie chart. It also turns off the QGraphicsItem::ItemHasNoContents +flag to enable painting: \snippet tutorials/extending-qml/chapter1-basics/piechart.cpp 0 \dots 0 @@ -125,9 +136,7 @@ provided for various other \l {QML Basic Types}{basic types}; for example, a str like "640x480" can be automatically converted to a QSize value. We'll also create a C++ application that uses a QQuickView to run and -display \c app.qml. The application must register the \c PieChart type -using the qmlRegisterType() function, to allow it to be used from QML. If -you don't register the type, \c app.qml won't be able to create a \c PieChart. +display \c app.qml. Here is the application \c main.cpp: @@ -143,7 +152,7 @@ Now we can build and run the application: \image extending-tutorial-chapter1.png -\note You may see a warning \e {Expression ... depends on non-NOTIFYable properties: +\note You may see a warning \e {Expression ... depends on non-NOTIFYable properties: PieChart::name}. This happens because we add a binding to the writable \c name property, but haven't yet defined a notify signal for it. The QML engine therefore cannot update the binding if the \c name value changes. This is addressed in @@ -450,7 +459,7 @@ In this tutorial, we've shown the basic steps for creating a QML extension: \list \li Define new QML types by subclassing QObject and registering them with - qmlRegisterType() + QML_ELEMENT or QML_NAMED_ELEMENT() \li Add callable methods using \l Q_INVOKABLE or Qt slots, and connect to Qt signals with an \c onSignal syntax \li Add property bindings by defining \l{Qt's Property System}{NOTIFY} signals diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc index 63c28d7aa7..04d907f168 100644 --- a/src/qml/doc/src/qmlfunctions.qdoc +++ b/src/qml/doc/src/qmlfunctions.qdoc @@ -27,7 +27,7 @@ /*! \macro QML_ELEMENT - \related QQmlEngine + \relates QQmlEngine Declares the enclosing type or namespace to be available in QML, using its class or namespace name as the QML element name. @@ -45,10 +45,10 @@ \endcode You can use the build system to register the type in the type namespace - "com.mycompany.qmlcomponents" with major version \c 1 by specifying the + \e {com.mycompany.qmlcomponents} with major version \c 1 by specifying the following in your project file: - \code + \badcode CONFIG += qmltypes QML_IMPORT_NAME = com.mycompany.qmlcomponents QML_IMPORT_MAJOR_VERSION = 1 @@ -74,7 +74,7 @@ /*! \macro QML_NAMED_ELEMENT(name) - \related QQmlEngine + \relates QQmlEngine Declares the enclosing type or namespace to be available in QML, using \a name as the element name. Otherwise behaves the same as QML_ELEMENT. @@ -209,7 +209,7 @@ {attached property} to other types. This takes effect if the type is exposed to QML using a \l QML_ELEMENT or \l QML_NAMED_ELEMENT() macro. - \sa QML_ELEMENT, QML_NAMED_ELEMENT(), qmlAtachedPropertiesObject(), + \sa QML_ELEMENT, QML_NAMED_ELEMENT(), qmlAttachedPropertiesObject(), {Providing Attached Properties} */ @@ -234,7 +234,7 @@ \l QML_ATTACHED(), or \l QML_EXTENDED() macros in the enclosing C++ type do not apply to the enclosing type but instead to \a FOREIGN_TYPE. The enclosing type still needs to be registered with the - \l {The Meta-Object System}{meta object system} using a \l G_GADGET or + \l {The Meta-Object System}{meta object system} using a \l Q_GADGET or \l Q_OBJECT macro. This is useful for registering types that cannot be amended to add the macros, @@ -278,13 +278,14 @@ This will cause any QML which attempts to use the "Game" type to produce an error message: - \code + + \badcode fun.qml: Get back to work, slacker! Game { ^ \endcode - Using this technique, you only need a \l G_GADGET struct to customize the error + Using this technique, you only need a \l Q_GADGET struct to customize the error message, not a full-blown \l QObject. Without \l QML_UNCREATABLE(), \l QML_UNAVAILABLE still results in a more specific error message than the usual "is not a type" for completely unknown types. @@ -905,7 +906,7 @@ */ /*! - \fn int qmlRegisterSingletonInstance(const char *uri, int versionMajor, int versionMinor, const char *typeName, QObject* cppObject) + \fn template<typename T> auto qmlRegisterSingletonInstance(const char *uri, int versionMajor, int versionMinor, const char *typeName, T *cppObject) \relates QQmlEngine \since 5.14 diff --git a/src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc b/src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc index 2eaedf8f9b..a4119ff793 100644 --- a/src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc +++ b/src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc @@ -125,10 +125,11 @@ component <component name> : BaseType { Inside the file which declares the inline component, the type can be referenced simply by its name. -\snippet src/qml/doc/snippets/qml/qml-documents/Images.qml document +\snippet qml/qml-documents/Images.qml document In other files, it has to be prefixed with the name of its containing component. -\snippet src/qml/doc/snippets/qml/qml-documents/LabeledImageBox.qml document + +\snippet qml/qml-documents/LabeledImageBox.qml document \note Inline components don't share their scope with the component they are declared in. In the following example, when \c A.MyInlineComponent in file @@ -137,8 +138,8 @@ an id in B.qml. It is therefore advisable not to reference objects in an inline component which are not part of it. -\snippet src/qml/doc/snippets/qml/qml-documents/A.qml document -\snippet src/qml/doc/snippets/qml/qml-documents/B.qml document +\snippet qml/qml-documents/A.qml document +\snippet qml/qml-documents/B.qml document \note Inline components cannot be nested. diff --git a/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc b/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc index f7d71030b5..99c7fa5621 100644 --- a/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc +++ b/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc @@ -422,7 +422,7 @@ import QtQuick.tooling 1.1 // Component objects. Module { // A Component object directly corresponds to a type exported - // in a plugin with a call to qmlRegisterType. + // using the QML_ELEMENT or QML_NAMED_ELEMENT macros. Component { // The name is a unique identifier used to refer to this type. @@ -440,25 +440,34 @@ Module { attachedType: "QQuickAnimationAttached" // The list of exports determines how a type can be imported. - // Each string has the format "URI/Name version" and matches the - // arguments to qmlRegisterType. Usually types are only exported - // once, if at all. - // If the "URI/" part of the string is missing that means the - // type should be put into the package defined by the URI the - // module was imported with. - // For example if this module was imported with 'import Foo 4.8' - // the Animation object would be found in the package Foo and - // QtQuick. + // Each string has the format "URI/Name version". The URI is + // the import name given via the build system, for example as + // QML_IMPORT_NAME in qmake. The name is either the C++ class + // name or, in case of QML_NAMED_ELEMENT(), an explicitly given + // name. The version is constructed from the major version + // given via the build system, as QML_IMPORT_MAJOR_VERSION in + // qmake, and any revisions given in the class or its base + // classes by Q_REVISION(), the REVISION argument to Q_PROPERTY, + // or QML_ADDED_IN_MINOR_VERSION(). Usually types are only + // exported once, if at all. The following tells us that there + // are two variants of Animation, and that 'import QtQuick 2.0' + // will expose a different revision than imports of later + // versions. exports: [ - "Animation 4.7", - "QtQuick/Animation 1.0" + "QtQuick/Animation 2.0", + "QtQuick/Animation 2.1" ] // The meta object revisions for the exports specified in 'exports'. - // Describes with revisioned properties will be visible in an export. - // The list must have exactly the same length as the 'exports' list. - // For example the 'animations' propery described below will only be - // available through the QtQuick/Animation 1.0 export. + // Each meta object revision may add additional properties or methods, + // relative to the previous one. Those will only be visible when the + // module is imported with at least the corresponding version as + // specified in the 'exports' list. + // The exportMetaObjectRevisions list must have exactly the same + // length as the 'exports' list. For example, the 'animations' property + // described below will only be available through the QtQuick/Animation + // 2.1 export. Usually the revisions will match the versions in the + // 'exports' list. exportMetaObjectRevisions: [0, 1] Property { @@ -486,7 +495,7 @@ Module { // declarations also support the isReadonly, isPointer and isList // attributes which mean the same as for Property Method { name: "restart" } - Signal { name: "started"; revision: 2 } + Signal { name: "started"; revision: 1 } Signal { name: "runningChanged" Parameter { type: "bool" } diff --git a/src/qml/doc/src/qmllanguageref/syntax/imports.qdoc b/src/qml/doc/src/qmllanguageref/syntax/imports.qdoc index 32106d5bb8..fdba452271 100644 --- a/src/qml/doc/src/qmllanguageref/syntax/imports.qdoc +++ b/src/qml/doc/src/qmllanguageref/syntax/imports.qdoc @@ -127,15 +127,15 @@ Rectangle { In this case, the engine will emit an error and refuse to load the file. -\section4 Non-module Namespace Imports +\section4 C++ Module Imports -Types can also be registered into namespaces directly via the various -registration functions in C++ (such as qmlRegisterType()). The types which -have been registered into a namespace in this way may be imported by importing -the namespace, as if the namespace was a module identifier. +Usually, C++ types are declared using the QML_ELEMENT and QML_NAMED_ELEMENT() +macros and registered via the build system using QML_IMPORT_NAME and +QML_IMPORT_MAJOR_VERSION. The import name and version given this way form a +module that can be imported to access the types. This is most common in client applications which define their own QML object -types in C++ and register them with the QML type system manually. +types in C++. \section4 Importing into a Qualified Local Namespace diff --git a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc index 832d9a9e26..ecfef2e04f 100644 --- a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc +++ b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc @@ -684,7 +684,7 @@ Required properties play a special role in model-view-delegate code: If the delegate of a view has required properties whose names match with the role names of the view's model, then those properties will be initialized with the model's corresponding values. -For more information, visit the \l{Models and Views in QtQuick} page. +For more information, visit the \l{Models and Views in Qt Quick} page. \sa {QQmlComponent::createWithInitialProperties}, {QQmlApplicationEngine::setInitialProperties} and {QQuickView::setInitialProperties} for ways to initialize required properties from C++. diff --git a/src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc b/src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc index 5144fe219e..53984a440d 100644 --- a/src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc +++ b/src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc @@ -582,34 +582,15 @@ property is only invoked when the property is reassigned to a different object v QML objects (and certainly not JavaScript object either) and the key-value pairs in \c attributes are \e not QML properties. Rather, the \c items property holds an array of values, and \c attributes holds a set of key-value - pairs. Since they are stored as a set of values, instead of as an object, - their contents \e cannot be modified individually: - - \qml - Item { - property variant items: [1, 2, 3, "four", "five"] - property variant attributes: { 'color': 'red', 'width': 100 } - - Component.onCompleted: { - items[0] = 10 - console.log(items[0]) // This will still be '1'! - attributes.color = 'blue' - console.log(attributes.color) // This will still be 'red'! - } - } - \endqml - - Since it is not possible to individually add or remove items from a list or - object stored in a \c variant, the only way to modify its contents is to - reassign a new value. However, this is not efficient, as it causes the value - to be serialized and deserialized. + pairs. Additionally, since \c items and \c attributes are not QML objects, changing - their individual values do not trigger property change notifications. If - the above example had \c onNumberChanged or \c onAnimalChanged signal - handlers, they would not have been called. If, however, the \c items or - \c attributes properties themselves were reassigned to different values, then - such handlers would be called. + the values they contain does not trigger property change notifications. If + the above example had \c onItemsChanged or \c onAttributesChanged signal + handlers, they would not be called when assigning individual entries in + either property. If, however, the \c items or \c attributes properties + themselves were reassigned to different values, then such handlers would be + called. JavaScript programmers should also note that when a JavaScript object is copied to an array or map property, the \e contents of the object (that is, diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index a900e710c2..f1b20ce53b 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -1520,7 +1520,11 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int return retn; #endif if (typeHint != -1) { - retn = QVariant(typeHint, QMetaType::create(typeHint)); + // the QVariant constructor will create a copy, so we have manually + // destroy the value returned by QMetaType::create + auto temp = QMetaType::create(typeHint); + retn = QVariant(typeHint, temp); + QMetaType::destroy(typeHint, temp); auto retnAsIterable = retn.value<QtMetaTypePrivate::QSequentialIterableImpl>(); if (retnAsIterable._iteratorCapabilities & QtMetaTypePrivate::ContainerIsAppendable) { auto const length = a->getLength(); @@ -1533,8 +1537,8 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int if (!couldConvert) { qWarning() << QLatin1String("Could not convert array value at position %1 from %2 to %3") .arg(QString::number(i), - QMetaType::typeName(originalType), - QMetaType::typeName(retnAsIterable._metaType_id)); + QString::fromUtf8(QMetaType::typeName(originalType)), + QString::fromUtf8(QMetaType::typeName(retnAsIterable._metaType_id))); // create default constructed value asVariant = QVariant(retnAsIterable._metaType_id, nullptr); } diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 5ee27d4457..ee512a5137 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -727,6 +727,7 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt Q_ASSERT(ok); typePriv->extraData.id->url = QUrl(this->url); auto icType = QQmlType(typePriv); + typePriv->release(); return icType; }; if (containingType.isValid()) { @@ -902,6 +903,7 @@ bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, QTypeRevision int placeholderId = type_return->generatePlaceHolderICId(); icTypePriv->extraData.id->url.setFragment(QString::number(placeholderId)); auto icType = QQmlType(icTypePriv); + icTypePriv->release(); type_return->associateInlineComponent(icName, placeholderId, CompositeMetaTypeIds {}, icType); *type_return = icType; } @@ -938,6 +940,7 @@ bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, QTypeRevision int placeholderId = type_return->generatePlaceHolderICId(); icTypePriv->extraData.id->url.setFragment(QString::number(placeholderId)); auto icType = QQmlType(icTypePriv); + icTypePriv->release(); type_return->associateInlineComponent(icName, placeholderId, CompositeMetaTypeIds {}, icType); *type_return = icType; } @@ -1996,8 +1999,11 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader, static const QStringList suffixes = { # ifdef QT_DEBUG QLatin1String("d.dll"), // try a qmake-style debug build first -# endif QLatin1String(".dll") +#else + QLatin1String(".dll"), + QLatin1String("d.dll") // try a qmake-style debug build after +# endif }; #elif defined(Q_OS_DARWIN) static const QString prefix = QLatin1String("lib"); diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp index 4911cd2879..0ad013e90b 100644 --- a/src/qml/qml/qqmlincubator.cpp +++ b/src/qml/qml/qqmlincubator.cpp @@ -722,8 +722,8 @@ bool QQmlIncubatorPrivate::hadRequiredProperties() const } /*! -Stores a mapping from property names to initial values with which the incubated -component will be initialized +Stores a mapping from property names to initial values, contained in +\a initialProperties, with which the incubated component will be initialized. \sa QQmlComponent::setInitialProperties \since 5.15 diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 28dd3d4ab4..aff982012d 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -1264,7 +1264,10 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo ddata->columnNumber = obj->location.column; ddata->setImplicitDestructible(); - if (static_cast<quint32>(index) == /*root object*/0 || ddata->rootObjectInCreation) { + // inline components are root objects, but their index is != 0, so we need + // an additional check + const bool isInlineComponent = obj->flags & QV4::CompiledData::Object::IsInlineComponentRoot; + if (static_cast<quint32>(index) == /*root object*/0 || ddata->rootObjectInCreation || isInlineComponent) { if (ddata->context) { Q_ASSERT(ddata->context != context); Q_ASSERT(ddata->outerContext); diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp index e87c901c9d..047da376c6 100644 --- a/src/qml/qml/qqmltype.cpp +++ b/src/qml/qml/qqmltype.cpp @@ -941,7 +941,8 @@ int QQmlType::generatePlaceHolderICId() const void QQmlType::associateInlineComponent(const QString &name, int objectID, const CompositeMetaTypeIds &metaTypeIds, QQmlType existingType) { - auto priv = existingType.isValid() ? const_cast<QQmlTypePrivate *>(existingType.d.data()) : new QQmlTypePrivate { RegistrationType::InlineComponentType } ; + bool const reuseExistingType = existingType.isValid(); + auto priv = reuseExistingType ? const_cast<QQmlTypePrivate *>(existingType.d.data()) : new QQmlTypePrivate { RegistrationType::InlineComponentType } ; priv->setName( QString::fromUtf8(typeName()), name); auto icUrl = QUrl(sourceUrl()); icUrl.setFragment(QString::number(objectID)); @@ -953,6 +954,8 @@ void QQmlType::associateInlineComponent(const QString &name, int objectID, const d->namesToInlineComponentObjectIndex.insert(name, objectID); QQmlType icType(priv); d->objectIdToICType.insert(objectID, icType); + if (!reuseExistingType) + priv->release(); } void QQmlType::setPendingResolutionName(const QString &name) diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index d8cfd80b9b..c5218bee33 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -393,7 +393,7 @@ QQmlEngine *QQmlTypeLoader::engine() const return m_engine; } -/*! +/*! \internal Call the initializeEngine() method on \a iface. Used by QQmlImportDatabase to ensure it gets called in the correct thread. */ diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index de23e929e2..edf9657f53 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -48,6 +48,7 @@ #include "qqmlcontext_p.h" #include "qqmlbinding_p.h" #include "qqmlpropertyvalueinterceptor_p.h" +#include <qqmlinfo.h> #include <private/qqmlglobal_p.h> @@ -60,6 +61,8 @@ #include <private/qqmlpropertycachecreator_p.h> #include <private/qqmlpropertycachemethodarguments_p.h> +#include <climits> // for CHAR_BIT + QT_BEGIN_NAMESPACE class ResolvedList @@ -67,13 +70,22 @@ class ResolvedList Q_DISABLE_COPY_MOVE(ResolvedList) public: - ResolvedList(QQmlListProperty<QObject> *prop) : - m_metaObject(static_cast<QQmlVMEMetaObject *>(QObjectPrivate::get(prop->object)->metaObject)), - m_id(quintptr(prop->data)) + ResolvedList(QQmlListProperty<QObject> *prop) { + // see QQmlVMEMetaObject::metaCall for how this was constructed + auto encodedIndex = quintptr(prop->data); + constexpr quintptr usableBits = sizeof(quintptr) * CHAR_BIT; + quintptr inheritanceDepth = encodedIndex >> (usableBits / 2); + m_id = encodedIndex & ((quintptr(1) << (usableBits / 2)) - 1); + + // walk up to the correct meta object if necessary + auto mo = prop->object->metaObject(); + while (inheritanceDepth--) + mo = mo->superClass(); + m_metaObject = static_cast<QQmlVMEMetaObject *>(const_cast<QMetaObject *>(mo)); Q_ASSERT(m_metaObject); + Q_ASSERT( ::strstr(m_metaObject->property(m_metaObject->propOffset() + m_id).typeName(), "QQmlListProperty") ); Q_ASSERT(m_metaObject->object == prop->object); - Q_ASSERT(m_id <= quintptr(std::numeric_limits<int>::max() - m_metaObject->methodOffset())); // readPropertyAsList() with checks transformed into Q_ASSERT // and without allocation. @@ -747,10 +759,35 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * break; case QV4::CompiledData::BuiltinType::InvalidBuiltin: if (property.isList) { + // when reading from the list, we need to find the correct MetaObject, + // namely this. However, obejct->metaObject might point to any MetaObject + // down the inheritance hierarchy, so we need to store how far we have + // to go down + // To do this, we encode the hierarchy depth together with the id of the + // property in a single quintptr, with the first half storing the depth + // and the second half storing the property id + auto mo = object->metaObject(); + quintptr inheritanceDepth = 0u; + while (mo && mo != this) { + mo = mo->superClass(); + ++inheritanceDepth; + } + constexpr quintptr usableBits = sizeof(quintptr) * CHAR_BIT; + if (Q_UNLIKELY(inheritanceDepth >= (quintptr(1) << quintptr(usableBits / 2u) ) )) { + qmlWarning(object) << "Too many objects in inheritance hierarchy for list property"; + return -1; + } + if (Q_UNLIKELY(quintptr(id) >= (quintptr(1) << quintptr(usableBits / 2) ) )) { + qmlWarning(object) << "Too many properties in object for list property"; + return -1; + } + quintptr encodedIndex = (inheritanceDepth << (usableBits/2)) + id; + + readPropertyAsList(id); // Initializes if necessary *static_cast<QQmlListProperty<QObject> *>(a[0]) = QQmlListProperty<QObject>( - object, reinterpret_cast<void *>(quintptr(id)), + object, reinterpret_cast<void *>(quintptr(encodedIndex)), list_append, list_count, list_at, list_clear, list_replace, list_removeLast); } else { diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index d47c2604ae..f4e529f2de 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -803,7 +803,7 @@ parameter may be any of the possible format values as described for \l{QtQml::Qt::formatDateTime()}{Qt.formatDateTime()}. If \a format is not specified, \a date is formatted using -\l {QLocale::FormatType::ShortFormat}{Locale.ShortFormat} using the +\l {QLocale::FormatType}{Locale.ShortFormat} using the default locale. \sa Locale @@ -832,7 +832,7 @@ possible format values as described for \l{QtQml::Qt::formatDateTime()}{Qt.formatDateTime()}. If \a format is not specified, \a time is formatted using -\l {QLocale::FormatType::ShortFormat}{Locale.ShortFormat} using the default locale. +\l {QLocale::FormatType}{Locale.ShortFormat} using the default locale. \sa Locale */ @@ -857,13 +857,13 @@ ReturnedValue QtObject::method_formatTime(const FunctionObject *b, const Value * \qmlmethod string Qt::formatDateTime(datetime dateTime, variant format, variant localeFormatOption) Returns a string representation of \a dateTime, optionally formatted using -\a format. +\a format and \a localeFormatOption. The \a dateTime parameter may be a JavaScript \c Date object, a \l{date}{date} property, a QDate, QTime, or QDateTime value. If \a format is not provided, \a dateTime is formatted using -\l {QLocale::FormatType::ShortFormat}{Locale.ShortFormat} using the +\l {QLocale::FormatType}{Locale.ShortFormat} using the default locale. Otherwise, \a format should be either: \list @@ -874,9 +874,9 @@ default locale. Otherwise, \a format should be either: \endlist If \a format specifies a locale object, \dateTime is formatted -with \li{QLocale::toString}. In this case, localeFormatType can hold a value +with \l{QLocale::toString}. In this case, \a localeFormatOption can hold a value of type \l {QLocale::FormatType} to further tune the formatting. If none is -provided, \l {QLocale::FormatType::ShortFormat}{Locale.ShortFormat} is used. +provided, \l {QLocale::FormatType}{Locale.ShortFormat} is used. If \a format specifies a format string, it should use the following expressions to specify the date: diff --git a/src/qmlmodels/qqmladaptormodel.cpp b/src/qmlmodels/qqmladaptormodel.cpp index 33b57a0332..8c8c37d237 100644 --- a/src/qmlmodels/qqmladaptormodel.cpp +++ b/src/qmlmodels/qqmladaptormodel.cpp @@ -460,7 +460,7 @@ public: void cleanup(QQmlAdaptorModel &) const override { - const_cast<VDMAbstractItemModelDataType *>(this)->release(); + release(); } QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override diff --git a/src/quick/handlers/qquickhandlerpoint.cpp b/src/quick/handlers/qquickhandlerpoint.cpp index e6148ca072..72efdfd0f4 100644 --- a/src/quick/handlers/qquickhandlerpoint.cpp +++ b/src/quick/handlers/qquickhandlerpoint.cpp @@ -119,11 +119,13 @@ void QQuickHandlerPoint::reset(const QQuickEventPoint *point) m_rotation = tp->rotation(); m_pressure = tp->pressure(); m_ellipseDiameters = tp->ellipseDiameters(); +#if QT_CONFIG(tabletevent) } else if (event->asPointerTabletEvent()) { m_uniqueId = event->device()->uniqueId(); m_rotation = static_cast<const QQuickEventTabletPoint *>(point)->rotation(); m_pressure = static_cast<const QQuickEventTabletPoint *>(point)->pressure(); m_ellipseDiameters = QSizeF(); +#endif } else { m_uniqueId = event->device()->uniqueId(); m_rotation = 0; diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index 3c01bd2cb1..a598c13113 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -597,8 +597,10 @@ Q_GLOBAL_STATIC_WITH_ARGS(ConstructableQQuickPointerDevice, g_genericMouseDevice QQuickPointerDevice::Position | QQuickPointerDevice::Scroll | QQuickPointerDevice::Hover, 1, 3, QLatin1String("core pointer"), 0)) +#if QT_CONFIG(tabletevent) typedef QHash<qint64, QQuickPointerDevice *> PointerDeviceForDeviceIdHash; Q_GLOBAL_STATIC(PointerDeviceForDeviceIdHash, g_tabletDevices) +#endif // debugging helpers static const char *pointStateString(const QQuickEventPoint *point) @@ -658,6 +660,7 @@ QQuickPointerDevice *QQuickPointerDevice::genericMouseDevice() return g_genericMouseDevice; } +#if QT_CONFIG(tabletevent) QQuickPointerDevice *QQuickPointerDevice::tabletDevice(const QTabletEvent *event) { // QTabletEvent::uniqueId() is the same for the pointy end and the eraser end of the stylus. @@ -726,6 +729,7 @@ QQuickPointerDevice *QQuickPointerDevice::tabletDevice(const QTabletEvent *event g_tabletDevices->insert(key, device); return device; } +#endif /*! \qmltype EventPoint diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h index c37bb4e77a..b1d8b52372 100644 --- a/src/quick/items/qquickevents_p_p.h +++ b/src/quick/items/qquickevents_p_p.h @@ -769,7 +769,9 @@ public: static QQuickPointerDevice *touchDevice(const QTouchDevice *d); static QList<QQuickPointerDevice *> touchDevices(); static QQuickPointerDevice *genericMouseDevice(); +#if QT_CONFIG(tabletevent) static QQuickPointerDevice *tabletDevice(const QTabletEvent *event); +#endif QVector<QQuickPointerHandler *> &eventDeliveryTargets() { return m_eventDeliveryTargets; } diff --git a/src/quick/items/qquickpositioners.cpp b/src/quick/items/qquickpositioners.cpp index 512f59d799..65c48c583a 100644 --- a/src/quick/items/qquickpositioners.cpp +++ b/src/quick/items/qquickpositioners.cpp @@ -1609,6 +1609,7 @@ Qt::LayoutDirection QQuickGrid::effectiveLayoutDirection() const \qmlproperty enumeration QtQuick::Grid::horizontalItemAlignment \qmlproperty enumeration QtQuick::Grid::verticalItemAlignment \qmlproperty enumeration QtQuick::Grid::effectiveHorizontalItemAlignment + \since 5.1 Sets the horizontal and vertical alignment of items in the Grid. By default, the items are vertically aligned to the top. Horizontal diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index fe88960c48..4b4ecd6acc 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -2415,11 +2415,13 @@ QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QQuickPointerDevic #endif ev = new QQuickPointerTouchEvent(q, device); break; +#if QT_CONFIG(tabletevent) case QQuickPointerDevice::Stylus: case QQuickPointerDevice::Airbrush: case QQuickPointerDevice::Puck: ev = new QQuickPointerTabletEvent(q, device); break; +#endif default: break; } diff --git a/src/quick/scenegraph/compressedtexture/qsgcompressedatlastexture.cpp b/src/quick/scenegraph/compressedtexture/qsgcompressedatlastexture.cpp index b59d490250..ac21ec2ed9 100644 --- a/src/quick/scenegraph/compressedtexture/qsgcompressedatlastexture.cpp +++ b/src/quick/scenegraph/compressedtexture/qsgcompressedatlastexture.cpp @@ -151,7 +151,7 @@ Texture::~Texture() bool Texture::hasAlphaChannel() const { - return QSGCompressedTexture::formatIsOpaque(static_cast<Atlas*>(m_atlas)->format()); + return !QSGCompressedTexture::formatIsOpaque(static_cast<Atlas*>(m_atlas)->format()); } QSGTexture *Texture::removedFromAtlas() const diff --git a/tests/auto/qml/qqmllanguage/data/Action.qml b/tests/auto/qml/qqmllanguage/data/Action.qml new file mode 100644 index 0000000000..4db2bacf6e --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/Action.qml @@ -0,0 +1,21 @@ +import QtQuick 2.12 + +QtObject { + id:root + property Item parent + property Item displayComponent: null + + property list<QtObject> children + + readonly property var visibleChildren: { + var visible = []; + var child; + for (var i in children) { + child = children[i]; + if (!child.hasOwnProperty("visible") || child.visible) { + visible.push(child) + } + } + return visible; + } +} diff --git a/tests/auto/qml/qqmllanguage/data/listPropertiesChild.qml b/tests/auto/qml/qqmllanguage/data/listPropertiesChild.qml new file mode 100644 index 0000000000..b1635a9409 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/listPropertiesChild.qml @@ -0,0 +1,7 @@ +import QtQuick 2.12 + +Action +{ + id: action + property color color +} diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index d4760fa7e9..9440fcaad4 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -123,6 +123,7 @@ private slots: void dynamicProperties(); void dynamicPropertiesNested(); void listProperties(); + void listPropertiesInheritanceNoCrash(); void badListItemType(); void dynamicObjectProperties(); void dynamicSignalsAndSlots(); @@ -1492,6 +1493,16 @@ void tst_qqmllanguage::listProperties() QCOMPARE(object->property("test").toInt(), 2); } +// Tests that initializing list properties of a base class does not crash +// (QTBUG-82171) +void tst_qqmllanguage::listPropertiesInheritanceNoCrash() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("listPropertiesChild.qml")); + QScopedPointer<QObject> object(component.create()); // should not crash + QVERIFY(object != nullptr); +} + void tst_qqmllanguage::badListItemType() { QQmlComponent component(&engine, testFileUrl("badListItemType.qml")); diff --git a/tests/auto/quick/qquickmousearea/BLACKLIST b/tests/auto/quick/qquickmousearea/BLACKLIST index 1491116f59..089bb3a873 100644 --- a/tests/auto/quick/qquickmousearea/BLACKLIST +++ b/tests/auto/quick/qquickmousearea/BLACKLIST @@ -4,3 +4,7 @@ macos ci # QTBUG-78153 [nestedStopAtBounds] opensuse-leap + +# QTBUG-82282 +[pressOneAndTapAnother] +opensuse-leap diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp index bd7a33482d..e8c471e22e 100644 --- a/tools/qml/main.cpp +++ b/tools/qml/main.cpp @@ -436,7 +436,6 @@ int main(int argc, char *argv[]) app->setOrganizationDomain("qt-project.org"); QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR)); - qmlRegisterTypesAndRevisions<Config, PartialScene>("QmlRuntime.Config", 1); QQmlApplicationEngine e; QStringList files; QString confFile; diff --git a/tools/qml/qml.pro b/tools/qml/qml.pro index 5dcbb3567a..83e2e1bf80 100644 --- a/tools/qml/qml.pro +++ b/tools/qml/qml.pro @@ -5,6 +5,10 @@ qtHaveModule(widgets): QT += widgets HEADERS += conf.h SOURCES += main.cpp RESOURCES += qml.qrc +CONFIG += qmltypes + +QML_IMPORT_NAME = QmlRuntime.Config +QML_IMPORT_VERSION = 1.0 QMAKE_TARGET_DESCRIPTION = QML Runtime diff --git a/tools/qmltime/qmltime.cpp b/tools/qmltime/qmltime.cpp index b0761a54d4..ca10fdde53 100644 --- a/tools/qmltime/qmltime.cpp +++ b/tools/qmltime/qmltime.cpp @@ -25,47 +25,18 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + +#include "qmltime.h" + #include <QQmlEngine> -#include <QQmlComponent> #include <QDebug> #include <QGuiApplication> #include <QElapsedTimer> #include <QQmlContext> -#include <QQuickView> #include <QQuickItem> #include <private/qquickview_p.h> -class Timer : public QObject -{ - Q_OBJECT - Q_PROPERTY(QQmlComponent *component READ component WRITE setComponent) - -public: - Timer(); - - QQmlComponent *component() const; - void setComponent(QQmlComponent *); - - static Timer *timerInstance(); - - void run(uint); - - bool willParent() const; - void setWillParent(bool p); - -private: - void runTest(QQmlContext *, uint); - - QQmlComponent *m_component; - static Timer *m_timer; - - bool m_willparent; - QQuickView m_view; - QQuickItem *m_item; -}; -QML_DECLARE_TYPE(Timer); - Timer *Timer::m_timer = nullptr; Timer::Timer() @@ -207,8 +178,6 @@ int main(int argc, char ** argv) QGuiApplication app(argc, argv); QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR)); - qmlRegisterTypesAndRevisions<Timer>("QmlTime", 1); - uint iterations = 1024; QString filename; bool willParent = false; @@ -269,5 +238,3 @@ int main(int argc, char ** argv) return 0; } - -#include "qmltime.moc" diff --git a/tools/qmltime/qmltime.h b/tools/qmltime/qmltime.h new file mode 100644 index 0000000000..a23dc902e2 --- /dev/null +++ b/tools/qmltime/qmltime.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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$ +** +****************************************************************************/ + +#ifndef QMLTIME_H +#define QMLTIME_H + +#include <QtCore/qobject.h> +#include <QtQml/qqml.h> +#include <QtQml/qqmlcomponent.h> +#include <QtQuick/qquickview.h> + +class Timer : public QObject +{ + Q_OBJECT + Q_PROPERTY(QQmlComponent *component READ component WRITE setComponent) + QML_ELEMENT + +public: + Timer(); + + QQmlComponent *component() const; + void setComponent(QQmlComponent *); + + static Timer *timerInstance(); + + void run(uint); + + bool willParent() const; + void setWillParent(bool p); + +private: + void runTest(QQmlContext *, uint); + + QQmlComponent *m_component; + static Timer *m_timer; + + bool m_willparent; + QQuickView m_view; + QQuickItem *m_item; +}; +QML_DECLARE_TYPE(Timer); + +#endif // QMLTIME_H diff --git a/tools/qmltime/qmltime.pro b/tools/qmltime/qmltime.pro index 04a5fd5957..c915f6e8c1 100644 --- a/tools/qmltime/qmltime.pro +++ b/tools/qmltime/qmltime.pro @@ -4,5 +4,11 @@ QT += qml quick QT += quick-private macx:CONFIG -= app_bundle +CONFIG += qmltypes +QML_IMPORT_NAME = QmlTime +QML_IMPORT_VERSION = 1.0 + QMAKE_TARGET_DESCRIPTION = QML Time + SOURCES += qmltime.cpp +HEADERS += qmltime.h |