diff options
830 files changed, 15524 insertions, 4578 deletions
diff --git a/.qmake.conf b/.qmake.conf index 2f6f96de99..7f338d0c85 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,7 +1,6 @@ load(qt_build_config) CONFIG += warning_clean -DEFINES += QT_NO_LINKED_LIST DEFINES += QT_NO_JAVA_STYLE_ITERATORS MODULE_VERSION = 6.0.0 diff --git a/dist/changes-5.14.1 b/dist/changes-5.14.1 new file mode 100644 index 0000000000..f4a2ab226a --- /dev/null +++ b/dist/changes-5.14.1 @@ -0,0 +1,89 @@ +Qt 5.14.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.14.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.14 series is binary compatible with the 5.13.x series. +Applications compiled for 5.13 will continue to run with 5.14. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + +https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* QtQml * +**************************************************************************** + - [QTBUG-81109] Don't crash when iterating invalid Proxy objects + - [QTBUG-81108] Don't crash when sorting arrays with non-stringifyable entries + - [QTBUG-81105] Support printing arrays with circular references + - [QTBUG-81104] Array.includes now works even with large arrays. + - [QTBUG-81037] Fixed oob access on Array.concat. + - [QTBUG-81093] Emit QQmlEngine::warnings when load fails instead of + simply qWarning. + - [QTBUG-81055] XMLHttpRequest works correctly in a QML WorkerThread. + - [QTBUG-80963] Fixed a crash in QQmlAdaptorModel. + - [QTBUG-80609] Fixed a crash related to the use of QSequentialIterable + as a JS container type. + - [QTBUG-80511] The compiler now supports larger stack slots to avoid + crashing when passing long lists or vectors. + - [QTBUG-30467] QQmlTypeLoader no longer parses qmldir content multiple times. + It can be told to forget the qmldir contents via QQmlTypeLoader::clearCache(), + as before. + +**************************************************************************** +* QtQuick * +**************************************************************************** + + - [QTBUG-71193] Fixed two crashes and a memory leak in ItemParticle. + - [QTBUG-34779] Fixed a crash in QQuickWindow that was discovered during + fuzz testing. + - [QTBUG-80505] TableView now resets its content size to empty if the + model becomes empty. + - [QTBUG-80505][QTBUG-71374] Fixed crashes in TableView when deleting or + setting the model to null. + - [QTBUG-80534] TableView behaves better when both a delegate and an + ObjectModel or DelegateModel are declared. + - [QTBUG-67986] ObjectModel items are now re-rendered when moved between models. + - [QTBUG-78297] DelegateModel and DelegateChoice now work together better. + - [QTBUG-79163] If a MouseArea has its preventStealing flag set, + a Pointer Handler that is a child is not allowed to steal the grab. + - [QTBUG-77624] MouseArea now reacts to touch ungrab, so that it will + know the interaction has been cancelled if the user begins dragging + after the press, and a DragHandler takes over. + - [QTBUG-68232] ListView now emits currentIndexChanged (to indicate a + value of -1) if an empty model is assigned. + - [QTBUG-66163] If the populate animation runs as a result of model assignment, + the viewport should not move. + - [QTBUG-79592] PathView now continues animating to the nearest + detent, as usual, when ungrabMouse() is called. + - [QTBUG-76954] Multiple TapHandlers (again) are able to react to + multiple touchpoints simultaneously, without losing the active state + when one of the points is stationary. + - [QTBUG-64138] Particle effects can now run continuously over longer + periods of time. + - [QTBUG-80190] We no longer emit TextInput.inputMaskChanged when you are + setting the same input mask again. + - [QTBUG-80070] When an animation is set on an Item which is loaded by a + Loader, it will no longer crash when the animation is deleted. + - [QTBUG-80364] Attempting to call QSGTexture::bind() outside the direct + OpenGL rendering path now generates a warning. + - [QTBUG-80297] QRhi now follows non-integer scaling fixes for native text. + - [QTBUG-75750] MultiPointTouchArea no longer ignores Qt-synthesized mouse + events. It's now possible to use a stylus with Qt Virtual Keyboard + because MPTA will react to the synth-mouse event that occurs after the + QTabletEvent was not handled. In the case that a touch event is sent, + MPTA will accept it; so a synth-mouse event is not expected afterwards. + If Flickable has pressDelay set, and intercepts a touch press, it will + send the delayed press in the form of a mouse press, and MPTA will now + react, which is useful in case MPTA is used in an item view delegate. + But it will also receive a touch release after the synthetic delayed press, + so now it checks whether the touchpoint ID is the same as the synth-mouse + touch ID, to verify that the touch release corresponds with the synth-mouse + press that arrived earlier, and react to it. diff --git a/examples/qml/doc/src/qml-extending.qdoc b/examples/qml/doc/src/qml-extending.qdoc index 1ad3ae9a10..723e470d45 100644 --- a/examples/qml/doc/src/qml-extending.qdoc +++ b/examples/qml/doc/src/qml-extending.qdoc @@ -69,7 +69,7 @@ This example builds on: \li \l {Extending QML - Adding Types Example} \endlist -Shows how to use \l {QQmlEngine::}{qmlRegisterExtendedType()} to provide an +Shows how to use \l {QML_EXTENDED} to provide an \l {Registering Extension Objects}{extension object} to a \l QLineEdit without modifying or subclassing it. diff --git a/examples/qml/dynamicscene/dynamicscene.pro b/examples/qml/dynamicscene/dynamicscene.pro new file mode 100644 index 0000000000..29a3fa97e2 --- /dev/null +++ b/examples/qml/dynamicscene/dynamicscene.pro @@ -0,0 +1,9 @@ +TEMPLATE = app + +QT += quick qml +SOURCES += main.cpp + +RESOURCES += dynamicscene.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/qml/dynamicscene +INSTALLS += target diff --git a/examples/qml/dynamicscene/dynamicscene.qrc b/examples/qml/dynamicscene/dynamicscene.qrc new file mode 100644 index 0000000000..ac9baa4941 --- /dev/null +++ b/examples/qml/dynamicscene/dynamicscene.qrc @@ -0,0 +1,19 @@ +<RCC> + <qresource prefix="/"> + <file>dynamicscene.qml</file> + <file>content/images/face-smile.png</file> + <file>content/images/moon.png</file> + <file>content/images/NOTE</file> + <file>content/images/rabbit_brown.png</file> + <file>content/images/rabbit_bw.png</file> + <file>content/images/star.png</file> + <file>content/images/sun.png</file> + <file>content/images/tree_s.png</file> + <file>content/Button.qml</file> + <file>content/GenericSceneItem.qml</file> + <file>content/itemCreation.js</file> + <file>content/PaletteItem.qml</file> + <file>content/PerspectiveItem.qml</file> + <file>content/Sun.qml</file> + </qresource> +</RCC> diff --git a/examples/qml/dynamicscene/main.cpp b/examples/qml/dynamicscene/main.cpp new file mode 100644 index 0000000000..e28375158d --- /dev/null +++ b/examples/qml/dynamicscene/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "../../quick/shared/shared.h" +DECLARATIVE_EXAMPLE_MAIN(dynamicscene) diff --git a/examples/qml/qml-i18n/doc/src/i18n.qdoc b/examples/qml/qml-i18n/doc/src/i18n.qdoc index dbc4efa58c..48946aac9c 100644 --- a/examples/qml/qml-i18n/doc/src/i18n.qdoc +++ b/examples/qml/qml-i18n/doc/src/i18n.qdoc @@ -52,4 +52,6 @@ lrelease i18n/*.ts \endcode +\note On Android, please make sure to include the generated *.qm files as resources. + */ diff --git a/examples/qml/qml-i18n/i18n/base.ts b/examples/qml/qml-i18n/i18n/base.ts index 77c640f370..99ceeeb016 100644 --- a/examples/qml/qml-i18n/i18n/base.ts +++ b/examples/qml/qml-i18n/i18n/base.ts @@ -4,7 +4,7 @@ <context> <name>qml-i18n</name> <message> - <location filename="../qml-i18n.qml" line="66"/> + <location filename="../qml-i18n.qml" line="68"/> <source>Hello</source> <translation type="unfinished"></translation> </message> diff --git a/examples/qml/qml-i18n/i18n/qml_en_AU.ts b/examples/qml/qml-i18n/i18n/qml_en_AU.ts index 86ccfb7bf8..feb4f9e9c0 100644 --- a/examples/qml/qml-i18n/i18n/qml_en_AU.ts +++ b/examples/qml/qml-i18n/i18n/qml_en_AU.ts @@ -4,7 +4,7 @@ <context> <name>qml-i18n</name> <message> - <location filename="../qml-i18n.qml" line="66"/> + <location filename="../qml-i18n.qml" line="68"/> <source>Hello</source> <translation>G'day</translation> </message> diff --git a/examples/qml/qml-i18n/i18n/qml_fr.ts b/examples/qml/qml-i18n/i18n/qml_fr.ts index 363bebb395..c4872e63d0 100644 --- a/examples/qml/qml-i18n/i18n/qml_fr.ts +++ b/examples/qml/qml-i18n/i18n/qml_fr.ts @@ -4,7 +4,7 @@ <context> <name>qml-i18n</name> <message> - <location filename="../qml-i18n.qml" line="66"/> + <location filename="../qml-i18n.qml" line="68"/> <source>Hello</source> <translation>Bonjour</translation> </message> diff --git a/examples/qml/qml-i18n/main.cpp b/examples/qml/qml-i18n/main.cpp new file mode 100644 index 0000000000..0680dc8b41 --- /dev/null +++ b/examples/qml/qml-i18n/main.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QGuiApplication> +#include <QQmlApplicationEngine> + +int main(int argc, char *argv[]) +{ + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QGuiApplication app(argc, argv); + QQmlApplicationEngine engine; + const QUrl url(QStringLiteral("qrc:/qml-i18n.qml")); + + QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, + &app, [url](QObject *obj, const QUrl &objUrl) { + if (!obj && url == objUrl) + QCoreApplication::exit(-1); + }, Qt::QueuedConnection); + engine.load(url); + + return app.exec(); +} diff --git a/examples/qml/qml-i18n/qml-i18n.pro b/examples/qml/qml-i18n/qml-i18n.pro new file mode 100644 index 0000000000..847c741b00 --- /dev/null +++ b/examples/qml/qml-i18n/qml-i18n.pro @@ -0,0 +1,17 @@ +TEMPLATE = app + +QT += quick qml +SOURCES += main.cpp + +RESOURCES += qml-i18n.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/qml/qml-i18n +INSTALLS += target + +CONFIG += lrelease embed_translations + +TRANSLATIONS += \ + i18n/base.ts \ + i18n/qml_en.ts \ + i18n/qml_en_AU.ts \ + i18n/qml_fr.ts diff --git a/examples/qml/qml-i18n/qml-i18n.qml b/examples/qml/qml-i18n/qml-i18n.qml index 217ffb56ae..85c4c44160 100644 --- a/examples/qml/qml-i18n/qml-i18n.qml +++ b/examples/qml/qml-i18n/qml-i18n.qml @@ -48,17 +48,19 @@ ** ****************************************************************************/ -import QtQuick 2.0 +import QtQuick 2.12 +import QtQuick.Window 2.12 -Rectangle { +Window { + visible: true width: 640; height: 480 Column { anchors.fill: parent; spacing: 20 Text { - text: "If a translation is available for the system language (eg. French) then the "+ - "string below will translated (eg. 'Bonjour'). Otherwise it will show 'Hello'." + text: "If a translation is available for the system language (eg. French) then the " + + "string below will be translated (eg. 'Bonjour'). Otherwise it will show 'Hello'." width: parent.width; wrapMode: Text.WordWrap } diff --git a/examples/qml/qml-i18n/qml-i18n.qrc b/examples/qml/qml-i18n/qml-i18n.qrc new file mode 100644 index 0000000000..3a505b1665 --- /dev/null +++ b/examples/qml/qml-i18n/qml-i18n.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>qml-i18n.qml</file> + </qresource> +</RCC> diff --git a/examples/qml/qmlextensionplugins/doc/src/qmlpluginex.qdoc b/examples/qml/qmlextensionplugins/doc/src/qmlpluginex.qdoc index 9e0bbb1815..24d6991d52 100644 --- a/examples/qml/qmlextensionplugins/doc/src/qmlpluginex.qdoc +++ b/examples/qml/qmlextensionplugins/doc/src/qmlpluginex.qdoc @@ -29,7 +29,7 @@ \title QML Plugin Example \example qmlextensionplugins - \brief This example creates a C++ plugin extension by subclassing QQmlExtensionPlugin. + \brief This example creates a C++ plugin extension by subclassing QQmlEngineExtensionPlugin. \image qml-plugins-example.png diff --git a/examples/qml/qmlextensionplugins/plugin.cpp b/examples/qml/qmlextensionplugins/plugin.cpp index 99d8c5378c..ae5f35bf5f 100644 --- a/examples/qml/qmlextensionplugins/plugin.cpp +++ b/examples/qml/qmlextensionplugins/plugin.cpp @@ -48,7 +48,7 @@ ** ****************************************************************************/ -#include <QtQml/QQmlExtensionPlugin> +#include <QtQml/QQmlEngineExtensionPlugin> #include <qdebug.h> //![plugin] diff --git a/examples/qml/referenceexamples/attached/birthdayparty.cpp b/examples/qml/referenceexamples/attached/birthdayparty.cpp index da0cb800fc..888aafbc18 100644 --- a/examples/qml/referenceexamples/attached/birthdayparty.cpp +++ b/examples/qml/referenceexamples/attached/birthdayparty.cpp @@ -81,7 +81,7 @@ void BirthdayParty::setHost(Person *c) QQmlListProperty<Person> BirthdayParty::guests() { - return {this, m_guests}; + return {this, &m_guests}; } int BirthdayParty::guestCount() const diff --git a/examples/qml/referenceexamples/binding/birthdayparty.cpp b/examples/qml/referenceexamples/binding/birthdayparty.cpp index 866c1f6968..cfedf84be0 100644 --- a/examples/qml/referenceexamples/binding/birthdayparty.cpp +++ b/examples/qml/referenceexamples/binding/birthdayparty.cpp @@ -87,7 +87,7 @@ void BirthdayParty::setHost(Person *c) QQmlListProperty<Person> BirthdayParty::guests() { - return QQmlListProperty<Person>(this, m_guests); + return QQmlListProperty<Person>(this, &m_guests); } int BirthdayParty::guestCount() const diff --git a/examples/qml/referenceexamples/binding/example.qml b/examples/qml/referenceexamples/binding/example.qml index a89b4bc02e..b45ef6881b 100644 --- a/examples/qml/referenceexamples/binding/example.qml +++ b/examples/qml/referenceexamples/binding/example.qml @@ -62,7 +62,7 @@ BirthdayParty { shoe { size: 12; color: "white"; brand: "Nike"; price: 90.0 } } // ![0] - onPartyStarted: console.log("This party started rockin' at " + time); + onPartyStarted: (time) => { console.log("This party started rockin' at " + time); } Boy { diff --git a/examples/qml/referenceexamples/coercion/birthdayparty.cpp b/examples/qml/referenceexamples/coercion/birthdayparty.cpp index 1bae55076c..81db8ab1b8 100644 --- a/examples/qml/referenceexamples/coercion/birthdayparty.cpp +++ b/examples/qml/referenceexamples/coercion/birthdayparty.cpp @@ -66,7 +66,7 @@ void BirthdayParty::setHost(Person *c) QQmlListProperty<Person> BirthdayParty::guests() { - return {this, m_guests}; + return {this, &m_guests}; } int BirthdayParty::guestCount() const diff --git a/examples/qml/referenceexamples/default/birthdayparty.cpp b/examples/qml/referenceexamples/default/birthdayparty.cpp index 1bae55076c..81db8ab1b8 100644 --- a/examples/qml/referenceexamples/default/birthdayparty.cpp +++ b/examples/qml/referenceexamples/default/birthdayparty.cpp @@ -66,7 +66,7 @@ void BirthdayParty::setHost(Person *c) QQmlListProperty<Person> BirthdayParty::guests() { - return {this, m_guests}; + return {this, &m_guests}; } int BirthdayParty::guestCount() const diff --git a/examples/qml/referenceexamples/grouped/birthdayparty.cpp b/examples/qml/referenceexamples/grouped/birthdayparty.cpp index 1bae55076c..81db8ab1b8 100644 --- a/examples/qml/referenceexamples/grouped/birthdayparty.cpp +++ b/examples/qml/referenceexamples/grouped/birthdayparty.cpp @@ -66,7 +66,7 @@ void BirthdayParty::setHost(Person *c) QQmlListProperty<Person> BirthdayParty::guests() { - return {this, m_guests}; + return {this, &m_guests}; } int BirthdayParty::guestCount() const diff --git a/examples/qml/referenceexamples/methods/birthdayparty.cpp b/examples/qml/referenceexamples/methods/birthdayparty.cpp index 7e750e4f4b..4b30d31aeb 100644 --- a/examples/qml/referenceexamples/methods/birthdayparty.cpp +++ b/examples/qml/referenceexamples/methods/birthdayparty.cpp @@ -67,7 +67,7 @@ void BirthdayParty::setHost(Person *c) QQmlListProperty<Person> BirthdayParty::guests() { - return {this, m_guests}; + return {this, &m_guests}; } int BirthdayParty::guestCount() const diff --git a/examples/qml/referenceexamples/properties/birthdayparty.cpp b/examples/qml/referenceexamples/properties/birthdayparty.cpp index 9abb08dbd9..fe6abab3f5 100644 --- a/examples/qml/referenceexamples/properties/birthdayparty.cpp +++ b/examples/qml/referenceexamples/properties/birthdayparty.cpp @@ -71,7 +71,9 @@ QQmlListProperty<Person> BirthdayParty::guests() &BirthdayParty::appendGuest, &BirthdayParty::guestCount, &BirthdayParty::guest, - &BirthdayParty::clearGuests}; + &BirthdayParty::clearGuests, + &BirthdayParty::replaceGuest, + &BirthdayParty::removeLastGuest}; } void BirthdayParty::appendGuest(Person* p) { @@ -93,6 +95,16 @@ void BirthdayParty::clearGuests() { m_guests.clear(); } +void BirthdayParty::replaceGuest(int index, Person *p) +{ + m_guests[index] = p; +} + +void BirthdayParty::removeLastGuest() +{ + m_guests.removeLast(); +} + // ![0] void BirthdayParty::appendGuest(QQmlListProperty<Person>* list, Person* p) { @@ -103,6 +115,16 @@ void BirthdayParty::clearGuests(QQmlListProperty<Person>* list) { reinterpret_cast< BirthdayParty* >(list->data)->clearGuests(); } +void BirthdayParty::replaceGuest(QQmlListProperty<Person> *list, int i, Person *p) +{ + reinterpret_cast< BirthdayParty* >(list->data)->replaceGuest(i, p); +} + +void BirthdayParty::removeLastGuest(QQmlListProperty<Person> *list) +{ + reinterpret_cast< BirthdayParty* >(list->data)->removeLastGuest(); +} + Person* BirthdayParty::guest(QQmlListProperty<Person>* list, int i) { return reinterpret_cast< BirthdayParty* >(list->data)->guest(i); } diff --git a/examples/qml/referenceexamples/properties/birthdayparty.h b/examples/qml/referenceexamples/properties/birthdayparty.h index fb8b63a79d..a5704972cc 100644 --- a/examples/qml/referenceexamples/properties/birthdayparty.h +++ b/examples/qml/referenceexamples/properties/birthdayparty.h @@ -79,12 +79,16 @@ public: int guestCount() const; Person *guest(int) const; void clearGuests(); + void replaceGuest(int, Person*); + void removeLastGuest(); private: static void appendGuest(QQmlListProperty<Person>*, Person*); static int guestCount(QQmlListProperty<Person>*); static Person* guest(QQmlListProperty<Person>*, int); static void clearGuests(QQmlListProperty<Person>*); + static void replaceGuest(QQmlListProperty<Person>*, int, Person*); + static void removeLastGuest(QQmlListProperty<Person>*); Person *m_host; QVector<Person *> m_guests; diff --git a/examples/qml/referenceexamples/signal/birthdayparty.cpp b/examples/qml/referenceexamples/signal/birthdayparty.cpp index 9d34cdf146..405c8af940 100644 --- a/examples/qml/referenceexamples/signal/birthdayparty.cpp +++ b/examples/qml/referenceexamples/signal/birthdayparty.cpp @@ -82,7 +82,7 @@ void BirthdayParty::setHost(Person *c) QQmlListProperty<Person> BirthdayParty::guests() { - return {this, m_guests}; + return {this, &m_guests}; } int BirthdayParty::guestCount() const diff --git a/examples/qml/referenceexamples/signal/example.qml b/examples/qml/referenceexamples/signal/example.qml index 42d6c44939..5d80d58867 100644 --- a/examples/qml/referenceexamples/signal/example.qml +++ b/examples/qml/referenceexamples/signal/example.qml @@ -53,7 +53,7 @@ import QtQuick 2.0 // For QColor BirthdayParty { // ![0] - onPartyStarted: console.log("This party started rockin' at " + time); + onPartyStarted: (time) => { console.log("This party started rockin' at " + time); } // ![0] host: Boy { diff --git a/examples/qml/referenceexamples/valuesource/birthdayparty.cpp b/examples/qml/referenceexamples/valuesource/birthdayparty.cpp index 68d5767e8d..6a5e67aa0d 100644 --- a/examples/qml/referenceexamples/valuesource/birthdayparty.cpp +++ b/examples/qml/referenceexamples/valuesource/birthdayparty.cpp @@ -82,7 +82,7 @@ void BirthdayParty::setHost(Person *c) QQmlListProperty<Person> BirthdayParty::guests() { - return {this, m_guests}; + return {this, &m_guests}; } int BirthdayParty::guestCount() const diff --git a/examples/qml/referenceexamples/valuesource/example.qml b/examples/qml/referenceexamples/valuesource/example.qml index 0abb76261c..65d511058a 100644 --- a/examples/qml/referenceexamples/valuesource/example.qml +++ b/examples/qml/referenceexamples/valuesource/example.qml @@ -56,7 +56,7 @@ BirthdayParty { HappyBirthdaySong on announcement { name: "Bob Jones" } // ![0] - onPartyStarted: console.log("This party started rockin' at " + time); + onPartyStarted: (time) => { console.log("This party started rockin' at " + time); } host: Boy { 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/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.h b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.h index b762ce1c49..855ad7ae3a 100644 --- a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.h +++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.h @@ -61,6 +61,7 @@ class PieChart : public QQuickItem Q_PROPERTY(PieSlice* pieSlice READ pieSlice WRITE setPieSlice) //![0] Q_PROPERTY(QString name READ name WRITE setName) + Q_MOC_INCLUDE("pieslice.h") QML_ELEMENT //![1] public: diff --git a/examples/qml/tutorials/extending-qml/chapter5-listproperties/piechart.cpp b/examples/qml/tutorials/extending-qml/chapter5-listproperties/piechart.cpp index ac680bb9c9..a8e14db542 100644 --- a/examples/qml/tutorials/extending-qml/chapter5-listproperties/piechart.cpp +++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/piechart.cpp @@ -68,7 +68,8 @@ void PieChart::setName(const QString &name) //![0] QQmlListProperty<PieSlice> PieChart::slices() { - return QQmlListProperty<PieSlice>(this, nullptr, &PieChart::append_slice, nullptr, nullptr, nullptr); + return QQmlListProperty<PieSlice>(this, nullptr, &PieChart::append_slice, nullptr, + nullptr, nullptr, nullptr, nullptr); } void PieChart::append_slice(QQmlListProperty<PieSlice> *list, PieSlice *slice) 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 0b1cfcc8f1..780bb3a8f3 100644 --- a/examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.h +++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.h @@ -51,7 +51,7 @@ #define CHARTSPLUGIN_H //![0] -#include <QQmlExtensionPlugin> +#include <QQmlEngineExtensionPlugin> class ChartsPlugin : public QQmlEngineExtensionPlugin { diff --git a/examples/qml/tutorials/extending-qml/chapter6-plugins/import/piechart.cpp b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/piechart.cpp index 1c712c887a..536c0e16ae 100644 --- a/examples/qml/tutorials/extending-qml/chapter6-plugins/import/piechart.cpp +++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/piechart.cpp @@ -67,7 +67,8 @@ void PieChart::setName(const QString &name) QQmlListProperty<PieSlice> PieChart::slices() { - return QQmlListProperty<PieSlice>(this, nullptr, &PieChart::append_slice, nullptr, nullptr, nullptr); + return QQmlListProperty<PieSlice>(this, nullptr, &PieChart::append_slice, nullptr, + nullptr, nullptr, nullptr, nullptr); } void PieChart::append_slice(QQmlListProperty<PieSlice> *list, PieSlice *slice) diff --git a/examples/quick/animation/basics/property-animation.qml b/examples/quick/animation/basics/property-animation.qml index a764c395ee..8d640c9dda 100644 --- a/examples/quick/animation/basics/property-animation.qml +++ b/examples/quick/animation/basics/property-animation.qml @@ -48,6 +48,7 @@ ** ****************************************************************************/ +import QtQml 2.0 import QtQuick 2.0 Item { diff --git a/examples/quick/animation/behaviors/tvtennis.qml b/examples/quick/animation/behaviors/tvtennis.qml index 89d912777a..261f603de6 100644 --- a/examples/quick/animation/behaviors/tvtennis.qml +++ b/examples/quick/animation/behaviors/tvtennis.qml @@ -116,6 +116,13 @@ Rectangle { Rectangle { color: "#1e1b18"; x: page.width/2+50; y: 10; width: 20; height: 40 } Repeater { model: page.height / 20 - Rectangle { color: "#328930"; x: page.width/2-5; y: index * 20; width: 10; height: 10 } + Rectangle { + required property int index + color: "#328930" + x: page.width / 2 - 5 + y: index * 20 + width: 10 + height: 10 + } } } diff --git a/examples/quick/animation/behaviors/wigglytext.qml b/examples/quick/animation/behaviors/wigglytext.qml index cc2e086b51..81d4a8aef9 100644 --- a/examples/quick/animation/behaviors/wigglytext.qml +++ b/examples/quick/animation/behaviors/wigglytext.qml @@ -48,6 +48,7 @@ ** ****************************************************************************/ +import QtQml 2.0 import QtQuick 2.0 Rectangle { @@ -58,7 +59,7 @@ Rectangle { width: 320; height: 480; color: "#474747"; focus: true - Keys.onPressed: { + Keys.onPressed: (event) => { if (event.key == Qt.Key_Delete || event.key == Qt.Key_Backspace) container.remove() else if (event.text != "") { diff --git a/examples/quick/animation/pathanimation/pathanimation.qml b/examples/quick/animation/pathanimation/pathanimation.qml index b98fbebefc..ae96b32680 100644 --- a/examples/quick/animation/pathanimation/pathanimation.qml +++ b/examples/quick/animation/pathanimation/pathanimation.qml @@ -48,6 +48,7 @@ ** ****************************************************************************/ +import QtQml 2.0 import QtQuick 2.0 Rectangle { diff --git a/examples/quick/animation/pathinterpolator/pathinterpolator.qml b/examples/quick/animation/pathinterpolator/pathinterpolator.qml index 0c0d7bad46..07a82fc916 100644 --- a/examples/quick/animation/pathinterpolator/pathinterpolator.qml +++ b/examples/quick/animation/pathinterpolator/pathinterpolator.qml @@ -48,6 +48,7 @@ ** ****************************************************************************/ +import QtQml 2.0 import QtQuick 2.0 Rectangle { diff --git a/examples/quick/animation/states/states.qml b/examples/quick/animation/states/states.qml index 498fb6867c..5ff8e5318c 100644 --- a/examples/quick/animation/states/states.qml +++ b/examples/quick/animation/states/states.qml @@ -48,6 +48,7 @@ ** ****************************************************************************/ +import QtQml 2.0 import QtQuick 2.0 Rectangle { diff --git a/examples/quick/customitems/flipable/flipable.pro b/examples/quick/customitems/flipable/flipable.pro new file mode 100644 index 0000000000..ba00bf792c --- /dev/null +++ b/examples/quick/customitems/flipable/flipable.pro @@ -0,0 +1,9 @@ +TEMPLATE = app + +QT += quick qml +SOURCES += main.cpp + +RESOURCES += flipable.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/quick/customitems/flipable +INSTALLS += target diff --git a/examples/quick/customitems/flipable/flipable.qrc b/examples/quick/customitems/flipable/flipable.qrc new file mode 100644 index 0000000000..7918ccf00e --- /dev/null +++ b/examples/quick/customitems/flipable/flipable.qrc @@ -0,0 +1,9 @@ +<RCC> + <qresource prefix="/"> + <file>flipable.qml</file> + <file>content/5_heart.png</file> + <file>content/9_club.png</file> + <file>content/back.png</file> + <file>content/Card.qml</file> + </qresource> +</RCC> diff --git a/examples/quick/customitems/flipable/main.cpp b/examples/quick/customitems/flipable/main.cpp new file mode 100644 index 0000000000..a0f0d67d45 --- /dev/null +++ b/examples/quick/customitems/flipable/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "../../shared/shared.h" +DECLARATIVE_EXAMPLE_MAIN(flipable) diff --git a/examples/quick/customitems/painteditem/TextBalloonPlugin/plugin.h b/examples/quick/customitems/painteditem/TextBalloonPlugin/plugin.h index 972859f80e..4abf2cf3dc 100644 --- a/examples/quick/customitems/painteditem/TextBalloonPlugin/plugin.h +++ b/examples/quick/customitems/painteditem/TextBalloonPlugin/plugin.h @@ -48,7 +48,7 @@ ** ****************************************************************************/ -#include <QQmlExtensionPlugin> +#include <QQmlEngineExtensionPlugin> #include "../textballoon.h" diff --git a/examples/quick/customitems/scrollbar/main.cpp b/examples/quick/customitems/scrollbar/main.cpp new file mode 100644 index 0000000000..579db41efd --- /dev/null +++ b/examples/quick/customitems/scrollbar/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "../../shared/shared.h" +DECLARATIVE_EXAMPLE_MAIN(main) diff --git a/examples/quick/customitems/scrollbar/scrollbar.pro b/examples/quick/customitems/scrollbar/scrollbar.pro new file mode 100644 index 0000000000..7e6ea3c2d6 --- /dev/null +++ b/examples/quick/customitems/scrollbar/scrollbar.pro @@ -0,0 +1,9 @@ +TEMPLATE = app + +QT += quick qml +SOURCES += main.cpp + +RESOURCES += scrollbar.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/quick/customitems/scrollbar +INSTALLS += target diff --git a/examples/quick/customitems/scrollbar/scrollbar.qrc b/examples/quick/customitems/scrollbar/scrollbar.qrc new file mode 100644 index 0000000000..b1ba5f9211 --- /dev/null +++ b/examples/quick/customitems/scrollbar/scrollbar.qrc @@ -0,0 +1,7 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + <file>ScrollBar.qml</file> + <file>pics/niagara_falls.jpg</file> + </qresource> +</RCC> diff --git a/examples/quick/customitems/searchbox/main.cpp b/examples/quick/customitems/searchbox/main.cpp new file mode 100644 index 0000000000..579db41efd --- /dev/null +++ b/examples/quick/customitems/searchbox/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "../../shared/shared.h" +DECLARATIVE_EXAMPLE_MAIN(main) diff --git a/examples/quick/customitems/searchbox/searchbox.pro b/examples/quick/customitems/searchbox/searchbox.pro new file mode 100644 index 0000000000..c22fc117aa --- /dev/null +++ b/examples/quick/customitems/searchbox/searchbox.pro @@ -0,0 +1,9 @@ +TEMPLATE = app + +QT += quick qml +SOURCES += main.cpp + +RESOURCES += searchbox.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/quick/customitems/searchbox +INSTALLS += target diff --git a/examples/quick/customitems/searchbox/searchbox.qrc b/examples/quick/customitems/searchbox/searchbox.qrc new file mode 100644 index 0000000000..f7a8602c9a --- /dev/null +++ b/examples/quick/customitems/searchbox/searchbox.qrc @@ -0,0 +1,9 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + <file>SearchBox.qml</file> + <file>images/clear.png</file> + <file>images/lineedit-bg-focus.png</file> + <file>images/lineedit-bg.png</file> + </qresource> +</RCC> diff --git a/examples/quick/customitems/spinner/main.cpp b/examples/quick/customitems/spinner/main.cpp new file mode 100644 index 0000000000..579db41efd --- /dev/null +++ b/examples/quick/customitems/spinner/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "../../shared/shared.h" +DECLARATIVE_EXAMPLE_MAIN(main) diff --git a/examples/quick/customitems/spinner/spinner.pro b/examples/quick/customitems/spinner/spinner.pro new file mode 100644 index 0000000000..b5be6884d2 --- /dev/null +++ b/examples/quick/customitems/spinner/spinner.pro @@ -0,0 +1,9 @@ +TEMPLATE = app + +QT += quick qml +SOURCES += main.cpp + +RESOURCES += spinner.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/quick/customitems/spinner +INSTALLS += target diff --git a/examples/quick/customitems/spinner/spinner.qrc b/examples/quick/customitems/spinner/spinner.qrc new file mode 100644 index 0000000000..3a8e4b17fd --- /dev/null +++ b/examples/quick/customitems/spinner/spinner.qrc @@ -0,0 +1,8 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + <file>content/spinner-bg.png</file> + <file>content/spinner-select.png</file> + <file>content/Spinner.qml</file> + </qresource> +</RCC> diff --git a/examples/quick/customitems/tabwidget/main.cpp b/examples/quick/customitems/tabwidget/main.cpp new file mode 100644 index 0000000000..579db41efd --- /dev/null +++ b/examples/quick/customitems/tabwidget/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "../../shared/shared.h" +DECLARATIVE_EXAMPLE_MAIN(main) diff --git a/examples/quick/customitems/tabwidget/tabwidget.pro b/examples/quick/customitems/tabwidget/tabwidget.pro new file mode 100644 index 0000000000..b852bb4075 --- /dev/null +++ b/examples/quick/customitems/tabwidget/tabwidget.pro @@ -0,0 +1,9 @@ +TEMPLATE = app + +QT += quick qml +SOURCES += main.cpp + +RESOURCES += tabwidget.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/quick/customitems/tabwidget +INSTALLS += target diff --git a/examples/quick/customitems/tabwidget/tabwidget.qrc b/examples/quick/customitems/tabwidget/tabwidget.qrc new file mode 100644 index 0000000000..ee71f677b1 --- /dev/null +++ b/examples/quick/customitems/tabwidget/tabwidget.qrc @@ -0,0 +1,8 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + <file>TabWidget.qml</file> + <file>doc/images/qml-tabwidget-example.png</file> + <file>doc/images/tab.png</file> + </qresource> +</RCC> diff --git a/examples/quick/draganddrop/tiles/DragTile.qml b/examples/quick/draganddrop/tiles/DragTile.qml index 78fe7a483a..47f0ebed5e 100644 --- a/examples/quick/draganddrop/tiles/DragTile.qml +++ b/examples/quick/draganddrop/tiles/DragTile.qml @@ -53,7 +53,9 @@ import QtQuick 2.0 //! [0] Item { id: root - property string colorKey + + required property string colorKey + required property int modelData width: 64; height: 64 @@ -74,9 +76,9 @@ Item { anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter - color: colorKey + color: root.colorKey - Drag.keys: [ colorKey ] + Drag.keys: [ root.colorKey ] Drag.active: mouseArea.drag.active Drag.hotSpot.x: 32 Drag.hotSpot.y: 32 @@ -85,7 +87,7 @@ Item { anchors.fill: parent color: "white" font.pixelSize: 48 - text: modelData + 1 + text: root.modelData + 1 horizontalAlignment:Text.AlignHCenter verticalAlignment: Text.AlignVCenter } diff --git a/examples/quick/draganddrop/tiles/DropTile.qml b/examples/quick/draganddrop/tiles/DropTile.qml index de4c0dee44..bf7101f0f6 100644 --- a/examples/quick/draganddrop/tiles/DropTile.qml +++ b/examples/quick/draganddrop/tiles/DropTile.qml @@ -64,7 +64,7 @@ DropArea { id: dropRectangle anchors.fill: parent - color: colorKey + color: dragTarget.colorKey states: [ State { diff --git a/examples/quick/externaldraganddrop/DragAndDropTextItem.qml b/examples/quick/externaldraganddrop/DragAndDropTextItem.qml index 9858a961c9..605dc07434 100644 --- a/examples/quick/externaldraganddrop/DragAndDropTextItem.qml +++ b/examples/quick/externaldraganddrop/DragAndDropTextItem.qml @@ -71,14 +71,18 @@ Rectangle { id: dropArea anchors.fill: parent keys: ["text/plain"] - onEntered: if (!acceptDropCB.checked) { - drag.accepted = false - rejectAnimation.start() + onEntered: (drag) => { + if (!acceptDropCB.checked) { + drag.accepted = false + rejectAnimation.start() + } } - onDropped: if (drop.hasText && acceptDropCB.checked) { - if (drop.proposedAction == Qt.MoveAction || drop.proposedAction == Qt.CopyAction) { - item.display = drop.text - drop.acceptProposedAction() + onDropped: (drop) => { + if (drop.hasText && acceptDropCB.checked) { + if (drop.proposedAction == Qt.MoveAction || drop.proposedAction == Qt.CopyAction) { + item.display = drop.text + drop.acceptProposedAction() + } } } } @@ -95,7 +99,10 @@ Rectangle { Drag.hotSpot.y: 0 Drag.mimeData: { "text/plain": item.display } Drag.dragType: Drag.Automatic - Drag.onDragFinished: if (dropAction == Qt.MoveAction) item.display = "" + Drag.onDragFinished: (dropAction) => { + if (dropAction == Qt.MoveAction) + item.display = "" + } } Examples.CheckBox { id: acceptDropCB diff --git a/examples/quick/imageelements/animatedsprite.qml b/examples/quick/imageelements/animatedsprite.qml index 0c6bf5e28d..cc5226882a 100644 --- a/examples/quick/imageelements/animatedsprite.qml +++ b/examples/quick/imageelements/animatedsprite.qml @@ -73,7 +73,7 @@ Item { MouseArea { anchors.fill: parent acceptedButtons: Qt.LeftButton | Qt.RightButton - onClicked: { + onClicked: (mouse) => { if (!sprite.running) sprite.start(); if (!sprite.paused) diff --git a/examples/quick/imageelements/content/BorderImageSelector.qml b/examples/quick/imageelements/content/BorderImageSelector.qml index 93ff5136bc..d8c2101be7 100644 --- a/examples/quick/imageelements/content/BorderImageSelector.qml +++ b/examples/quick/imageelements/content/BorderImageSelector.qml @@ -93,7 +93,10 @@ Item { Repeater { model: [ "Scale", "Repeat", "Scale/Repeat", "Round" ] delegate: Text { - text: model.modelData + required property string modelData + required property int index + + text: modelData anchors.verticalCenter: parent.verticalCenter x: (index - selector.curIdx) * 80 + 140 diff --git a/examples/quick/imageelements/content/ImageCell.qml b/examples/quick/imageelements/content/ImageCell.qml index 4b147633c3..7804346bd4 100644 --- a/examples/quick/imageelements/content/ImageCell.qml +++ b/examples/quick/imageelements/content/ImageCell.qml @@ -53,8 +53,6 @@ Item { property alias mode: image.fillMode property alias caption: captionItem.text - width: parent.cellWidth; height: parent.cellHeight - Image { id: image width: parent.width; height: parent.height - captionItem.height diff --git a/examples/quick/imageelements/content/MyBorderImage.qml b/examples/quick/imageelements/content/MyBorderImage.qml index 01d26a9630..3198de3bf1 100644 --- a/examples/quick/imageelements/content/MyBorderImage.qml +++ b/examples/quick/imageelements/content/MyBorderImage.qml @@ -48,6 +48,7 @@ ** ****************************************************************************/ +import QtQml 2.0 import QtQuick 2.0 Item { diff --git a/examples/quick/imageelements/image.qml b/examples/quick/imageelements/image.qml index d414f59629..0750ea3b79 100644 --- a/examples/quick/imageelements/image.qml +++ b/examples/quick/imageelements/image.qml @@ -65,12 +65,34 @@ Rectangle { rows: 3 spacing: 30 - ImageCell { mode: Image.Stretch; caption: "Stretch" } - ImageCell { mode: Image.PreserveAspectFit; caption: "PreserveAspectFit" } - ImageCell { mode: Image.PreserveAspectCrop; caption: "PreserveAspectCrop" } + component SizedImageCell: ImageCell { + width: parent.cellWidth + height: parent.cellHeight + } - ImageCell { mode: Image.Tile; caption: "Tile" } - ImageCell { mode: Image.TileHorizontally; caption: "TileHorizontally" } - ImageCell { mode: Image.TileVertically; caption: "TileVertically" } + SizedImageCell { + mode: Image.Stretch + caption: "Stretch" + } + SizedImageCell { + mode: Image.PreserveAspectFit + caption: "PreserveAspectFit" + } + SizedImageCell { + mode: Image.PreserveAspectCrop + caption: "PreserveAspectCrop" + } + SizedImageCell { + mode: Image.Tile + caption: "Tile" + } + SizedImageCell { + mode: Image.TileHorizontally + caption: "TileHorizontally" + } + SizedImageCell { + mode: Image.TileVertically + caption: "TileVertically" + } } } diff --git a/examples/quick/keyinteraction/focus/Core/ContextMenu.qml b/examples/quick/keyinteraction/focus/Core/ContextMenu.qml index c5430aa650..31b5e1b83d 100644 --- a/examples/quick/keyinteraction/focus/Core/ContextMenu.qml +++ b/examples/quick/keyinteraction/focus/Core/ContextMenu.qml @@ -52,6 +52,7 @@ import QtQuick 2.1 FocusScope { id: container + required property Item keyRightTarget property bool open: false @@ -62,7 +63,7 @@ FocusScope { anchors.fill: parent color: "#D1DBBD" focus: true - Keys.onRightPressed: mainView.focus = true + Keys.onRightPressed: container.keyRightTarget.focus = true Text { anchors { top: parent.top; horizontalCenter: parent.horizontalCenter; margins: 30 } diff --git a/examples/quick/keyinteraction/focus/Core/GridMenu.qml b/examples/quick/keyinteraction/focus/Core/GridMenu.qml index 3f62adc792..78d6654957 100644 --- a/examples/quick/keyinteraction/focus/Core/GridMenu.qml +++ b/examples/quick/keyinteraction/focus/Core/GridMenu.qml @@ -51,12 +51,11 @@ import QtQuick 2.1 FocusScope { + id: menu property alias interactive: gridView.interactive - - onActiveFocusChanged: { - if (activeFocus) - mainView.state = "showGridViews" - } + required property Item keyUpTarget + required property Item keyDownTarget + required property Item keyLeftTarget Rectangle { anchors.fill: parent @@ -73,13 +72,15 @@ FocusScope { focus: true model: 12 - KeyNavigation.up: tabMenu - KeyNavigation.down: listMenu - KeyNavigation.left: contextMenu + KeyNavigation.up: menu.keyUpTarget + KeyNavigation.down: menu.keyDownTarget + KeyNavigation.left: menu.keyLeftTarget delegate: Item { id: container - width: GridView.view.cellWidth; height: GridView.view.cellHeight + width: GridView.view.cellWidth + height: GridView.view.cellHeight + required property int index Rectangle { id: content @@ -97,7 +98,7 @@ FocusScope { hoverEnabled: true onClicked: { - container.GridView.view.currentIndex = index + container.GridView.view.currentIndex = container.index container.forceActiveFocus() } } diff --git a/examples/quick/keyinteraction/focus/Core/ListMenu.qml b/examples/quick/keyinteraction/focus/Core/ListMenu.qml index d8e9daba78..694ae3cac6 100644 --- a/examples/quick/keyinteraction/focus/Core/ListMenu.qml +++ b/examples/quick/keyinteraction/focus/Core/ListMenu.qml @@ -48,21 +48,22 @@ ** ****************************************************************************/ +import QtQml 2.1 import QtQuick 2.1 FocusScope { + id: menu clip: true - - onActiveFocusChanged: { - if (activeFocus) - mainView.state = "showListViews" - } + required property Item keyUpTarget + required property Item keyLeftTarget ListView { id: list1 y: activeFocus ? 10 : 40; width: parent.width / 3; height: parent.height - 20 focus: true - KeyNavigation.up: gridMenu; KeyNavigation.left: contextMenu; KeyNavigation.right: list2 + KeyNavigation.up: menu.keyUpTarget + KeyNavigation.left: menu.keyLeftTarget + KeyNavigation.right: list2 model: 10; cacheBuffer: 200 delegate: ListViewDelegate {} @@ -74,7 +75,9 @@ FocusScope { ListView { id: list2 y: activeFocus ? 10 : 40; x: parseInt(parent.width / 3); width: parent.width / 3; height: parent.height - 20 - KeyNavigation.up: gridMenu; KeyNavigation.left: list1; KeyNavigation.right: list3 + KeyNavigation.up: menu.keyUpTarget + KeyNavigation.left: list1 + KeyNavigation.right: list3 model: 10; cacheBuffer: 200 delegate: ListViewDelegate {} @@ -86,7 +89,8 @@ FocusScope { ListView { id: list3 y: activeFocus ? 10 : 40; x: parseInt(2 * parent.width / 3); width: parent.width / 3; height: parent.height - 20 - KeyNavigation.up: gridMenu; KeyNavigation.left: list2 + KeyNavigation.up: menu.keyUpTarget + KeyNavigation.left: list2 model: 10; cacheBuffer: 200 delegate: ListViewDelegate {} diff --git a/examples/quick/keyinteraction/focus/Core/ListViewDelegate.qml b/examples/quick/keyinteraction/focus/Core/ListViewDelegate.qml index b1dde9ddc5..5a2957eab0 100644 --- a/examples/quick/keyinteraction/focus/Core/ListViewDelegate.qml +++ b/examples/quick/keyinteraction/focus/Core/ListViewDelegate.qml @@ -52,6 +52,8 @@ import QtQuick 2.1 Item { id: container + required property int index + width: ListView.view.width; height: 60; anchors.leftMargin: 10; anchors.rightMargin: 10 Rectangle { @@ -67,7 +69,7 @@ Item { Text { id: label anchors.centerIn: content - text: "List element " + (index + 1) + text: "List element " + (container.index + 1) color: "#193441" font.pixelSize: 14 } @@ -78,7 +80,7 @@ Item { hoverEnabled: true onClicked: { - container.ListView.view.currentIndex = index + container.ListView.view.currentIndex = container.index container.forceActiveFocus() } } diff --git a/examples/quick/keyinteraction/focus/Core/TabMenu.qml b/examples/quick/keyinteraction/focus/Core/TabMenu.qml index a40e070b2c..11b3d005c3 100644 --- a/examples/quick/keyinteraction/focus/Core/TabMenu.qml +++ b/examples/quick/keyinteraction/focus/Core/TabMenu.qml @@ -51,10 +51,9 @@ import QtQuick 2.1 FocusScope { - onActiveFocusChanged: { - if (activeFocus) - mainView.state = "showTabViews" - } + id: menu + required property Item keyUpTarget + required property Item keyDownTarget Rectangle { anchors.fill: parent @@ -76,8 +75,8 @@ FocusScope { activeFocusOnTab: true focus: true - KeyNavigation.up: listMenu - KeyNavigation.down: gridMenu + KeyNavigation.up: menu.keyUpTarget + KeyNavigation.down: menu.keyDownTarget Rectangle { id: content diff --git a/examples/quick/keyinteraction/focus/focus.qml b/examples/quick/keyinteraction/focus/focus.qml index e07df57697..9db9ab48bc 100644 --- a/examples/quick/keyinteraction/focus/focus.qml +++ b/examples/quick/keyinteraction/focus/focus.qml @@ -48,6 +48,7 @@ ** ****************************************************************************/ +import QtQml 2.1 import QtQuick 2.1 import "Core" @@ -67,20 +68,45 @@ Rectangle { id: tabMenu y: 160; width: parent.width; height: 160 + keyUpTarget: listMenu + keyDownTarget: gridMenu + focus: true activeFocusOnTab: true + + onActiveFocusChanged: { + if (activeFocus) + mainView.state = "showTabViews" + } } GridMenu { id: gridMenu y: 320; width: parent.width; height: 320 activeFocusOnTab: true + + keyUpTarget: tabMenu + keyDownTarget: listMenu + keyLeftTarget: contextMenu + + onActiveFocusChanged: { + if (activeFocus) + mainView.state = "showGridViews" + } } ListMenu { id: listMenu y: 640; width: parent.width; height: 320 activeFocusOnTab: true + + keyUpTarget: gridMenu + keyLeftTarget: contextMenu + + onActiveFocusChanged: { + if (activeFocus) + mainView.state = "showListViews" + } } Rectangle { @@ -129,7 +155,13 @@ Rectangle { } } - ContextMenu { id: contextMenu; x: -265; width: 260; height: parent.height } + ContextMenu { + keyRightTarget: mainView + id: contextMenu + x: -265 + width: 260 + height: parent.height + } states: State { name: "contextMenuOpen" diff --git a/examples/quick/localstorage/localstorage/Header.qml b/examples/quick/localstorage/localstorage/Header.qml index e9446de55e..47879500a7 100644 --- a/examples/quick/localstorage/localstorage/Header.qml +++ b/examples/quick/localstorage/localstorage/Header.qml @@ -59,6 +59,9 @@ Item { width: Screen.width / 2 height: Screen.height / 7 + required property ListView listView + required property Text statusText + function insertrec() { var rowid = parseInt(JS.dbInsert(dateInput.text, descInput.text, distInput.text), 10) if (rowid) { @@ -148,7 +151,7 @@ Item { } onEditingFinished: { if (dateInput.text == "") { - statustext.text = "Please fill in the date" + root.statusText.text = "Please fill in the date" dateInput.forceActiveFocus() } } @@ -161,10 +164,10 @@ Item { activeFocusOnTab: true onEditingFinished: { if (descInput.text.length < 8) { - statustext.text = "Enter a description of minimum 8 characters" + root.statusText.text = "Enter a description of minimum 8 characters" descInput.forceActiveFocus() } else { - statustext.text = "" + root.statusText.text = "" } } } @@ -179,7 +182,7 @@ Item { } onEditingFinished: { if (distInput.text == "") { - statustext.text = "Please fill in the distance" + root.statusText.text = "Please fill in the distance" distInput.forceActiveFocus() } } diff --git a/examples/quick/localstorage/localstorage/MyDelegate.qml b/examples/quick/localstorage/localstorage/MyDelegate.qml index 63a83bfbae..e8575d4f7a 100644 --- a/examples/quick/localstorage/localstorage/MyDelegate.qml +++ b/examples/quick/localstorage/localstorage/MyDelegate.qml @@ -54,18 +54,27 @@ import QtQuick.Layouts 1.1 import "Database.js" as JS Item { + id: delegate + width: parent.width height: rDate.implicitHeight + required property int index + required property int distance + required property string trip_desc + required property string date + + signal clicked() + Rectangle { id: baseRec anchors.fill: parent opacity: 0.8 - color: index % 2 ? "lightgrey" : "grey" + color: delegate.index % 2 ? "lightgrey" : "grey" MouseArea { anchors.fill: parent - onClicked: listView.currentIndex = index + onClicked: delegate.clicked() } GridLayout { anchors.fill:parent @@ -73,21 +82,21 @@ Item { Text { id: rDate - text: date + text: delegate.date font.pixelSize: 22 Layout.preferredWidth: parent.width / 4 color: "black" } Text { id: rDesc - text: trip_desc + text: delegate.trip_desc Layout.fillWidth: true font.pixelSize: 22 color: "black" } Text { id: rDistance - text: distance + text: delegate.distance font.pixelSize: 22 Layout.alignment: Qt.AlignRight color: "black" diff --git a/examples/quick/localstorage/localstorage/localstorage.qml b/examples/quick/localstorage/localstorage/localstorage.qml index 41f5cbd561..418aab838e 100644 --- a/examples/quick/localstorage/localstorage/localstorage.qml +++ b/examples/quick/localstorage/localstorage/localstorage.qml @@ -55,6 +55,7 @@ import QtQuick.LocalStorage 2.0 import "Database.js" as JS Window { + id: window visible: true width: Screen.width / 2 height: Screen.height / 1.8 @@ -72,19 +73,21 @@ Window { Header { id: input Layout.fillWidth: true + listView: listView + statusText: statustext } RowLayout { MyButton { text: "New" onClicked: { input.initrec_new() - creatingNewEntry = true + window.creatingNewEntry = true listView.model.setProperty(listView.currentIndex, "id", 0) } } MyButton { id: saveButton - enabled: (creatingNewEntry || editingEntry) && listView.currentIndex != -1 + enabled: (window.creatingNewEntry || window.editingEntry) && listView.currentIndex != -1 text: "Save" onClicked: { var insertedRow = false; @@ -109,8 +112,8 @@ Window { if (insertedRow) { input.initrec() - creatingNewEntry = false - editingEntry = false + window.creatingNewEntry = false + window.editingEntry = false listView.forceLayout() } } @@ -118,20 +121,20 @@ Window { MyButton { id: editButton text: "Edit" - enabled: !creatingNewEntry && !editingEntry && listView.currentIndex != -1 + enabled: !window.creatingNewEntry && !window.editingEntry && listView.currentIndex != -1 onClicked: { input.editrec(listView.model.get(listView.currentIndex).date, listView.model.get(listView.currentIndex).trip_desc, listView.model.get(listView.currentIndex).distance, listView.model.get(listView.currentIndex).id) - editingEntry = true + window.editingEntry = true } } MyButton { id: deleteButton text: "Delete" - enabled: !creatingNewEntry && listView.currentIndex != -1 + enabled: !window.creatingNewEntry && listView.currentIndex != -1 onClicked: { JS.dbDeleteRow(listView.model.get(listView.currentIndex).id) listView.model.remove(listView.currentIndex, 1) @@ -145,7 +148,7 @@ Window { MyButton { id: cancelButton text: "Cancel" - enabled: (creatingNewEntry || editingEntry) && listView.currentIndex != -1 + enabled: (window.creatingNewEntry || window.editingEntry) && listView.currentIndex != -1 onClicked: { if (listView.model.get(listView.currentIndex).id === 0) { // This entry had an id of 0, which means it was being created and hadn't @@ -153,8 +156,8 @@ Window { listView.model.remove(listView.currentIndex, 1) } listView.forceLayout() - creatingNewEntry = false - editingEntry = false + window.creatingNewEntry = false + window.editingEntry = false input.initrec() } } @@ -176,9 +179,11 @@ Window { Layout.fillWidth: true Layout.fillHeight: true model: MyModel {} - delegate: MyDelegate {} + delegate: MyDelegate { + onClicked: listView.currentIndex = index + } // Don't allow changing the currentIndex while the user is creating/editing values. - enabled: !creatingNewEntry && !editingEntry + enabled: !window.creatingNewEntry && !window.editingEntry highlight: highlightBar highlightFollowsCurrentItem: true diff --git a/examples/quick/models/abstractitemmodel/main.cpp b/examples/quick/models/abstractitemmodel/main.cpp index 515f47ec30..dd5b368c6b 100644 --- a/examples/quick/models/abstractitemmodel/main.cpp +++ b/examples/quick/models/abstractitemmodel/main.cpp @@ -68,10 +68,8 @@ int main(int argc, char ** argv) QQuickView view; view.setResizeMode(QQuickView::SizeRootObjectToView); - QQmlContext *ctxt = view.rootContext(); - ctxt->setContextProperty("myModel", &model); + view.setInitialProperties({{"model", QVariant::fromValue(&model)}}); //![0] - view.setSource(QUrl("qrc:view.qml")); view.show(); diff --git a/examples/quick/models/abstractitemmodel/view.qml b/examples/quick/models/abstractitemmodel/view.qml index f699aa40c8..2b9f87df92 100644 --- a/examples/quick/models/abstractitemmodel/view.qml +++ b/examples/quick/models/abstractitemmodel/view.qml @@ -53,8 +53,14 @@ import QtQuick 2.0 ListView { width: 200; height: 250 - model: myModel - delegate: Text { text: "Animal: " + type + ", " + size } + required model + + delegate: Text { + required property string type + required property string size + + text: "Animal: " + type + ", " + size + } } //![0] diff --git a/examples/quick/models/objectlistmodel/main.cpp b/examples/quick/models/objectlistmodel/main.cpp index 977bbfb93b..1418af90ca 100644 --- a/examples/quick/models/objectlistmodel/main.cpp +++ b/examples/quick/models/objectlistmodel/main.cpp @@ -66,18 +66,19 @@ //![0] int main(int argc, char ** argv) { + QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); - QList<QObject*> dataList; - dataList.append(new DataObject("Item 1", "red")); - dataList.append(new DataObject("Item 2", "green")); - dataList.append(new DataObject("Item 3", "blue")); - dataList.append(new DataObject("Item 4", "yellow")); + QList<QObject *> dataList = { + new DataObject("Item 1", "red"), + new DataObject("Item 2", "green"), + new DataObject("Item 3", "blue"), + new DataObject("Item 4", "yellow") + }; QQuickView view; view.setResizeMode(QQuickView::SizeRootObjectToView); - QQmlContext *ctxt = view.rootContext(); - ctxt->setContextProperty("myModel", QVariant::fromValue(dataList)); + view.setInitialProperties({{ "model", QVariant::fromValue(dataList) }}); //![0] view.setSource(QUrl("qrc:view.qml")); diff --git a/examples/quick/models/objectlistmodel/view.qml b/examples/quick/models/objectlistmodel/view.qml index d9a32aff14..ba0c905e1e 100644 --- a/examples/quick/models/objectlistmodel/view.qml +++ b/examples/quick/models/objectlistmodel/view.qml @@ -53,13 +53,15 @@ import QtQuick 2.0 //![0] ListView { width: 100; height: 100 + required model - model: myModel delegate: Rectangle { + required color + required property string name + height: 25 width: 100 - color: model.modelData.color - Text { text: name } + Text { text: parent.name } } } //![0] diff --git a/examples/quick/models/stringlistmodel/main.cpp b/examples/quick/models/stringlistmodel/main.cpp index 6b4db422a6..d9de69b3aa 100644 --- a/examples/quick/models/stringlistmodel/main.cpp +++ b/examples/quick/models/stringlistmodel/main.cpp @@ -68,15 +68,15 @@ int main(int argc, char ** argv) QGuiApplication app(argc, argv); //![0] - QStringList dataList; - dataList.append("Item 1"); - dataList.append("Item 2"); - dataList.append("Item 3"); - dataList.append("Item 4"); + QStringList dataList = { + "Item 1", + "Item 2", + "Item 3", + "Item 4" + }; QQuickView view; - QQmlContext *ctxt = view.rootContext(); - ctxt->setContextProperty("myModel", QVariant::fromValue(dataList)); + view.setInitialProperties({{ "model", QVariant::fromValue(dataList) }}); //![0] view.setSource(QUrl("qrc:view.qml")); diff --git a/examples/quick/models/stringlistmodel/view.qml b/examples/quick/models/stringlistmodel/view.qml index f74b7db1c1..e392284d0f 100644 --- a/examples/quick/models/stringlistmodel/view.qml +++ b/examples/quick/models/stringlistmodel/view.qml @@ -52,13 +52,15 @@ import QtQuick 2.0 //![0] ListView { - width: 100; height: 100 + width: 100 + height: 100 + required model - model: myModel delegate: Rectangle { + required property string modelData height: 25 width: 100 - Text { text: modelData } + Text { text: parent.modelData } } } //![0] diff --git a/examples/quick/mousearea/mousearea-wheel-example.qml b/examples/quick/mousearea/mousearea-wheel-example.qml index 44b9216285..5e8fba3ac3 100644 --- a/examples/quick/mousearea/mousearea-wheel-example.qml +++ b/examples/quick/mousearea/mousearea-wheel-example.qml @@ -63,6 +63,8 @@ Rectangle { model: ["#9ACD32", "#EEEEEE", "#FFD700", "#87CEEB"] Rectangle { + required property color modelData + property real scaleFactor: 1 height: 40 * scaleFactor diff --git a/examples/quick/mousearea/mousearea.qml b/examples/quick/mousearea/mousearea.qml index 1540d85fdd..cecbc2cfc8 100644 --- a/examples/quick/mousearea/mousearea.qml +++ b/examples/quick/mousearea/mousearea.qml @@ -76,7 +76,7 @@ Rectangle { onEntered: info.text = 'Entered' onExited: info.text = 'Exited (pressed=' + pressed + ')' - onPressed: { + onPressed: (mouse) => { if (mouse.button == Qt.LeftButton) buttonID = 'LeftButton' else if (mouse.button == Qt.RightButton) @@ -139,14 +139,14 @@ Rectangle { + ' (' + posInBox.x + ',' + posInBox.y + ' in window)' } - onReleased: { + onReleased: (mouse) => { btn.text = 'Released (isClick=' + mouse.isClick + ' wasHeld=' + mouse.wasHeld + ')' posInfo.text = '' } //! [clicks] onPressAndHold: btn.text = 'Press and hold' - onClicked: btn.text = 'Clicked (wasHeld=' + mouse.wasHeld + ')' + onClicked: (mouse) => { btn.text = 'Clicked (wasHeld=' + mouse.wasHeld + ')' } onDoubleClicked: btn.text = 'Double clicked' //! [clicks] } diff --git a/examples/quick/particles/affectors/content/customaffector.qml b/examples/quick/particles/affectors/content/customaffector.qml index 71646bcf39..6fabfb3ab2 100644 --- a/examples/quick/particles/affectors/content/customaffector.qml +++ b/examples/quick/particles/affectors/content/customaffector.qml @@ -81,7 +81,7 @@ Item { property real velocity: 1.5 width: parent.width height: parent.height - 100 - onAffectParticles: { + onAffectParticles: (particles, dt) => { /* //Linear movement if (particle.r == 0) { particle.r = Math.random() > 0.5 ? -1 : 1; @@ -117,7 +117,7 @@ Item { width: parent.width + 120 height: 100 anchors.bottom: parent.bottom - onAffectParticles: { + onAffectParticles: (particles, dt) => { for (var i=0; i<particles.length; i++) { var particle = particles[i]; var pseudoRand = (Math.floor(particle.t*1327) % 10) + 1; diff --git a/examples/quick/particles/affectors/content/groupgoal.qml b/examples/quick/particles/affectors/content/groupgoal.qml index 6472a3b450..9910531a98 100644 --- a/examples/quick/particles/affectors/content/groupgoal.qml +++ b/examples/quick/particles/affectors/content/groupgoal.qml @@ -62,7 +62,7 @@ Rectangle { Text { color: "white" anchors.right: parent.right - text: score + text: root.score } ParticleSystem { @@ -96,7 +96,7 @@ Rectangle { ParticleGroup { name: "lit" duration: 10000 - onEntered: score++; + onEntered: root.score++ TrailEmitter { id: fireballFlame group: "flame" diff --git a/examples/quick/particles/emitters/content/burstandpulse.qml b/examples/quick/particles/emitters/content/burstandpulse.qml index 8bd19ed8ed..d3c38c2360 100644 --- a/examples/quick/particles/emitters/content/burstandpulse.qml +++ b/examples/quick/particles/emitters/content/burstandpulse.qml @@ -52,6 +52,8 @@ import QtQuick 2.0 import QtQuick.Particles 2.0 Rectangle { + id: root + width: 320 height: 480 color: "black" @@ -63,12 +65,12 @@ Rectangle { repeat: true onTriggered: { //! [0] - if (lastWasPulse) { + if (root.lastWasPulse) { burstEmitter.burst(500); - lastWasPulse = false; + root.lastWasPulse = false; } else { pulseEmitter.pulse(500); - lastWasPulse = true; + root.lastWasPulse = true; } //! [0] } diff --git a/examples/quick/particles/emitters/content/customemitter.qml b/examples/quick/particles/emitters/content/customemitter.qml index aa8ca6b2f9..f6aea13d08 100644 --- a/examples/quick/particles/emitters/content/customemitter.qml +++ b/examples/quick/particles/emitters/content/customemitter.qml @@ -79,7 +79,7 @@ ParticleSystem { size: 12 anchors.centerIn: parent //! [0] - onEmitParticles: { + onEmitParticles: (particles) => { for (var i=0; i<particles.length; i++) { var particle = particles[i]; particle.startSize = Math.max(02,Math.min(492,Math.tan(particle.t/2)*24)); @@ -90,8 +90,8 @@ ParticleSystem { theta /= 6.0; theta *= 2.0*Math.PI; theta += sys.convert(sys.petalRotation);//Convert from degrees to radians - particle.initialVX = petalLength * Math.cos(theta); - particle.initialVY = petalLength * Math.sin(theta); + particle.initialVX = sys.petalLength * Math.cos(theta); + particle.initialVY = sys.petalLength * Math.sin(theta); particle.initialAX = particle.initialVX * -0.5; particle.initialAY = particle.initialVY * -0.5; } diff --git a/examples/quick/particles/imageparticle/content/sharing.qml b/examples/quick/particles/imageparticle/content/sharing.qml index 1018a8e8ba..13b0dadf85 100644 --- a/examples/quick/particles/imageparticle/content/sharing.qml +++ b/examples/quick/particles/imageparticle/content/sharing.qml @@ -56,6 +56,8 @@ import QtQuick 2.0 import QtQuick.Particles 2.0 Rectangle { + id: root + property real delegateHeight: 65 width: 200; height: 300 gradient: Gradient { @@ -65,53 +67,53 @@ Rectangle { // Define a delegate component. A component will be // instantiated for each visible item in the list. - Component { - id: petDelegate - Item { - id: wrapper - width: 200; height: delegateHeight - z: 10 - Column { - Text {color: "white"; text: name; font.pixelSize: 18 } - Text {color: "white"; text: 'Type: ' + type; font.pixelSize: 14 } - Text {color: "white"; text: 'Age: ' + age; font.pixelSize: 14 } - } - MouseArea { anchors.fill: parent; onClicked: listView.currentIndex = index; } - // indent the item if it is the current item - states: State { - name: "Current" - when: wrapper.ListView.isCurrentItem - PropertyChanges { target: wrapper; x: 20 } - } - transitions: Transition { - NumberAnimation { properties: "x"; duration: 200 } - } + component PetDelegate: Item { + id: pet + width: 200; height: root.delegateHeight + z: 10 + + required property int index + required property string name + required property string type + required property int age + + Column { + Text {color: "white"; text: pet.name; font.pixelSize: 18 } + Text {color: "white"; text: 'Type: ' + pet.type; font.pixelSize: 14 } + Text {color: "white"; text: 'Age: ' + pet.age; font.pixelSize: 14 } + } + MouseArea { anchors.fill: parent; onClicked: listView.currentIndex = pet.index; } + // indent the item if it is the current item + states: State { + name: "Current" + when: pet.ListView.isCurrentItem + PropertyChanges { target: pet; x: 20 } + } + transitions: Transition { + NumberAnimation { properties: "x"; duration: 200 } } } // Define a highlight with customized movement between items. - Component { - id: highlightBar - Rectangle { - z: 0 - width: 200; height: delegateHeight - gradient: Gradient { - GradientStop { position: 0.0; color: "#99FF99" } - GradientStop { position: 1.0; color: "#88FF88" } - } - y: listView.currentItem.y; - Behavior on y { SpringAnimation { spring: 2; damping: 0.2 } } - //! [1] - ImageParticle { - anchors.fill: parent - system: particles - source: "../../images/flower.png" - color: "red" - clip: true - alpha: 1.0 - } - //! [1] + component HighlightBar : Rectangle { + z: 0 + width: 200; height: root.delegateHeight + gradient: Gradient { + GradientStop { position: 0.0; color: "#99FF99" } + GradientStop { position: 1.0; color: "#88FF88" } + } + y: listView.currentItem.y; + Behavior on y { SpringAnimation { spring: 2; damping: 0.2 } } + //! [1] + ImageParticle { + anchors.fill: parent + system: particles + source: "../../images/flower.png" + color: "red" + clip: true + alpha: 1.0 } + //! [1] } ListView { @@ -119,12 +121,12 @@ Rectangle { width: 200; height: parent.height model: petsModel - delegate: petDelegate + delegate: PetDelegate {} focus: true // Set the highlight delegate. Note we must also set highlightFollowsCurrentItem // to false so the highlight delegate can control how the highlight is moved. - highlight: highlightBar + highlight: HighlightBar {} highlightFollowsCurrentItem: false ParticleSystem { id: particles } diff --git a/examples/quick/particles/itemparticle/particleview.qml b/examples/quick/particles/itemparticle/particleview.qml index 3b412e37e5..8eb18dc283 100644 --- a/examples/quick/particles/itemparticle/particleview.qml +++ b/examples/quick/particles/itemparticle/particleview.qml @@ -156,7 +156,7 @@ Item { interval: 800 onTriggered: { force.enabled = false; - mp.take(alertItem, true); + mp.take(root.alertItem, true); centerEmitter.burst(1); } } @@ -216,6 +216,11 @@ Item { Component { id: theDelegate Image { + required property int index + required property string title + required property string media + required property string thumbnail + id: image antialiasing: true; source: thumbnail @@ -237,7 +242,7 @@ Item { width: parent.paintedWidth + 1 height: parent.paintedHeight + 1 color: "black" - opacity: darken * (1 - depth) + opacity: image.darken * (1 - image.depth) antialiasing: true; } Text { @@ -247,7 +252,7 @@ Item { width: parent.paintedWidth - 4 horizontalAlignment: Text.AlignHCenter elide: Text.ElideRight - text: title + text: image.title color: "black" } ItemParticle.onDetached: mp.take(image); // respawns @@ -277,7 +282,7 @@ Item { } PropertyChanges { target: image - source: media + source: image.media x: 0 y: 0 width: root.width diff --git a/examples/quick/positioners/positioners-transitions.qml b/examples/quick/positioners/positioners-transitions.qml index fbaa05c81c..d4f3772c4e 100644 --- a/examples/quick/positioners/positioners-transitions.qml +++ b/examples/quick/positioners/positioners-transitions.qml @@ -48,6 +48,7 @@ ** ****************************************************************************/ +import QtQml 2.0 import QtQuick 2.0 Item { @@ -215,9 +216,9 @@ Item { opacity: page.effectiveOpacity } - Rectangle { color: "#80c342"; width:page. smallSize; height: page.smallSize } - Rectangle { color: "#14aaff"; width: smallSize; height: page.smallSize } - Rectangle { color: "#6400aa"; width: page.page.smallSize; height: page.smallSize } + Rectangle { color: "#80c342"; width: page.smallSize; height: page.smallSize } + Rectangle { color: "#14aaff"; width: page.smallSize; height: page.smallSize } + Rectangle { color: "#6400aa"; width: page.smallSize; height: page.smallSize } } Flow { diff --git a/examples/quick/quick-accessibility/content/Slider.qml b/examples/quick/quick-accessibility/content/Slider.qml index aa425797a7..241e5d804e 100644 --- a/examples/quick/quick-accessibility/content/Slider.qml +++ b/examples/quick/quick-accessibility/content/Slider.qml @@ -72,7 +72,7 @@ Rectangle { x: 1 y: 1 height: parent.height - 2 - width: ((parent.width - 2) / maximumValue) * value + width: ((parent.width - 2) / slider.maximumValue) * slider.value color: "lightgrey" Behavior on width { NumberAnimation { duration: 50 } @@ -88,8 +88,9 @@ Rectangle { MouseArea { anchors.fill: parent - onClicked: { - var pos = mouse.x / slider.width * (maximumValue - minimumValue) + minimumValue + onClicked: (mouse) => { + var pos = mouse.x / slider.width * (slider.maximumValue - slider.minimumValue) + + slider.minimumValue slider.value = pos } } diff --git a/examples/quick/righttoleft/layoutdirection/layoutdirection.qml b/examples/quick/righttoleft/layoutdirection/layoutdirection.qml index 4e3e93852c..de111ea025 100644 --- a/examples/quick/righttoleft/layoutdirection/layoutdirection.qml +++ b/examples/quick/righttoleft/layoutdirection/layoutdirection.qml @@ -84,8 +84,8 @@ Rectangle { Repeater { model: 3 Loader { - property int value: index - sourceComponent: positionerDelegate + required property int index + sourceComponent: PositionerDelegate {} } } } @@ -106,8 +106,8 @@ Rectangle { Repeater { model: 8 Loader { - property int value: index - sourceComponent: positionerDelegate + required property int index + sourceComponent: PositionerDelegate {} } } } @@ -128,8 +128,8 @@ Rectangle { Repeater { model: 8 Loader { - property int value: index - sourceComponent: positionerDelegate + required property int index + sourceComponent: PositionerDelegate {} } } } @@ -152,7 +152,7 @@ Rectangle { layoutDirection: root.direction orientation: Qt.Horizontal model: 48 - delegate: viewDelegate + delegate: ViewDelegate {} } Text { @@ -166,7 +166,7 @@ Rectangle { cellWidth: 50; cellHeight: 50 layoutDirection: root.direction model: 48 - delegate: viewDelegate + delegate: ViewDelegate {} } Rectangle { @@ -230,37 +230,36 @@ Rectangle { } } - Component { - id: positionerDelegate + component PositionerDelegate : Rectangle { + width: 40 + height: 40 + property int lightness: parent.index + 1; + color: Qt.rgba(0.8 / lightness, 0.8 / lightness, 0.8 / lightness, 1.0) + Text { + text: parent.lightness + color: "white" + font.pixelSize: 18 + anchors.centerIn: parent + } + } + + component ViewDelegate : Item { + id: delegateItem + required property int index + width: (listView.effectiveLayoutDirection == Qt.LeftToRight ? (index == 48 - 1) : (index == 0)) ? 40 : 50 Rectangle { width: 40; height: 40 - color: Qt.rgba(0.8/(parent.value+1),0.8/(parent.value+1),0.8/(parent.value+1),1.0) + color: Qt.rgba(0.5 + (48 - delegateItem.index) * Math.random() / 48, + 0.3 + delegateItem.index * Math.random() / 48, + 0.3 * Math.random(), + 1.0) Text { - text: parent.parent.value+1 + text: delegateItem.index + 1 color: "white" font.pixelSize: 18 anchors.centerIn: parent } } } - Component { - id: viewDelegate - Item { - width: (listView.effectiveLayoutDirection == Qt.LeftToRight ? (index == 48 - 1) : (index == 0)) ? 40 : 50 - Rectangle { - width: 40; height: 40 - color: Qt.rgba(0.5+(48 - index)*Math.random()/48, - 0.3+index*Math.random()/48, - 0.3*Math.random(), - 1.0) - Text { - text: index+1 - color: "white" - font.pixelSize: 18 - anchors.centerIn: parent - } - } - } - } } diff --git a/examples/quick/righttoleft/textalignment/textalignment.qml b/examples/quick/righttoleft/textalignment/textalignment.qml index c5790027f2..698917a3c0 100644 --- a/examples/quick/righttoleft/textalignment/textalignment.qml +++ b/examples/quick/righttoleft/textalignment/textalignment.qml @@ -93,18 +93,23 @@ Rectangle { width: 320 height: 320 id: editorTypeRow - model: editorType.length + model: root.editorType.length orientation: ListView.Horizontal cacheBuffer: 1000//Load the really expensive ones async if possible delegate: Item { + id: delegate + width: editorColumn.width height: editorColumn.height + + required property int index + Column { id: editorColumn spacing: 5 width: textColumn.width+10 Text { - text: root.editorType[index] + text: root.editorType[delegate.index] font.pixelSize: 16 anchors.horizontalCenter: parent.horizontalCenter } @@ -113,8 +118,8 @@ Rectangle { spacing: 5 anchors.horizontalCenter: parent.horizontalCenter Repeater { - model: textComponents.length - delegate: textComponents[index] + model: root.textComponents.length + delegate: root.textComponents[delegate.index] } } } @@ -203,9 +208,11 @@ Rectangle { Component { id: plainTextComponent Text { + required property int index + width: 180 text: root.text[index] - font.pixelSize: pxSz + font.pixelSize: root.pxSz wrapMode: Text.WordWrap horizontalAlignment: root.horizontalAlignment LayoutMirroring.enabled: root.mirror @@ -216,10 +223,10 @@ Rectangle { anchors.fill: parent } Text { - text: root.description[index] + text: root.description[parent.index] color: Qt.rgba(1,1,1,1.0) anchors.centerIn: parent - font.pixelSize: pxSz - 2 + font.pixelSize: root.pxSz - 2 Rectangle { z: -1 color: Qt.rgba(0.3, 0, 0, 0.3) @@ -228,7 +235,7 @@ Rectangle { } Text { color: "white" - text: shortText(parent.horizontalAlignment) + text: root.shortText(parent.horizontalAlignment) anchors { top: parent.top; right: parent.right; margins: 2 } } } @@ -237,9 +244,11 @@ Rectangle { Component { id: styledTextComponent Text { + required property int index + width: 180 text: root.text[index] - font.pixelSize: pxSz + font.pixelSize: root.pxSz wrapMode: Text.WordWrap horizontalAlignment: root.horizontalAlignment LayoutMirroring.enabled: root.mirror @@ -252,10 +261,10 @@ Rectangle { anchors.fill: parent } Text { - text: root.description[index] + text: root.description[parent.index] color: Qt.rgba(1,1,1,1.0) anchors.centerIn: parent - font.pixelSize: pxSz - 2 + font.pixelSize: root.pxSz - 2 Rectangle { z: -1 color: Qt.rgba(0.3, 0, 0, 0.3) @@ -264,7 +273,7 @@ Rectangle { } Text { color: "white" - text: shortText(parent.horizontalAlignment) + text: root.shortText(parent.horizontalAlignment) anchors { top: parent.top; right: parent.right; margins: 2 } } } @@ -273,9 +282,11 @@ Rectangle { Component { id: richTextComponent Text { + required property int index + width: 180 text: root.text[index] - font.pixelSize: pxSz + font.pixelSize: root.pxSz wrapMode: Text.WordWrap horizontalAlignment: root.horizontalAlignment LayoutMirroring.enabled: root.mirror @@ -286,10 +297,10 @@ Rectangle { anchors.fill: parent } Text { - text: root.description[index] + text: root.description[parent.index] color: Qt.rgba(1,1,1,1.0) anchors.centerIn: parent - font.pixelSize: pxSz - 2 + font.pixelSize: root.pxSz - 2 Rectangle { z: -1 color: Qt.rgba(0.3, 0, 0, 0.3) @@ -298,7 +309,7 @@ Rectangle { } Text { color: "white" - text: shortText(parent.horizontalAlignment) + text: root.shortText(parent.horizontalAlignment) anchors { top: parent.top; right: parent.right; margins: 2 } } } @@ -307,9 +318,11 @@ Rectangle { Component { id: italicRichTextComponent Text { + required property int index + width: 180 text: "<i>" + root.text[index] + "</i>" - font.pixelSize: pxSz + font.pixelSize: root.pxSz wrapMode: Text.WordWrap horizontalAlignment: root.horizontalAlignment LayoutMirroring.enabled: root.mirror @@ -321,10 +334,10 @@ Rectangle { anchors.fill: parent } Text { - text: root.description[index] + text: root.description[parent.index] color: Qt.rgba(1,1,1,1.0) anchors.centerIn: parent - font.pixelSize: pxSz - 2 + font.pixelSize: root.pxSz - 2 Rectangle { z: -1 color: Qt.rgba(0.3, 0, 0, 0.3) @@ -333,7 +346,7 @@ Rectangle { } Text { color: "white" - text: shortText(parent.horizontalAlignment) + text: root.shortText(parent.horizontalAlignment) anchors { top: parent.top; right: parent.right; margins: 2 } } } @@ -342,9 +355,11 @@ Rectangle { Component { id: plainTextEdit TextEdit { + required property int index + width: 180 text: root.text[index] - font.pixelSize: pxSz + font.pixelSize: root.pxSz cursorVisible: true wrapMode: TextEdit.WordWrap horizontalAlignment: root.horizontalAlignment @@ -355,10 +370,10 @@ Rectangle { anchors.fill: parent } Text { - text: root.description[index] + text: root.description[parent.index] color: Qt.rgba(1,1,1,1.0) anchors.centerIn: parent - font.pixelSize: pxSz - 2 + font.pixelSize: root.pxSz - 2 Rectangle { z: -1 color: Qt.rgba(0.3, 0, 0, 0.3) @@ -367,7 +382,7 @@ Rectangle { } Text { color: "white" - text: shortText(parent.horizontalAlignment) + text: root.shortText(parent.horizontalAlignment) anchors { top: parent.top; right: parent.right; margins: 2 } } } @@ -376,9 +391,11 @@ Rectangle { Component { id: italicTextEdit TextEdit { + required property int index + width: 180 text: "<i>" + root.text[index] + "<i>" - font.pixelSize: pxSz + font.pixelSize: root.pxSz cursorVisible: true wrapMode: TextEdit.WordWrap textFormat: TextEdit.RichText @@ -390,10 +407,10 @@ Rectangle { anchors.fill: parent } Text { - text: root.description[index] + text: root.description[parent.index] color: Qt.rgba(1,1,1,1.0) anchors.centerIn: parent - font.pixelSize: pxSz - 2 + font.pixelSize: root.pxSz - 2 Rectangle { z: -1 color: Qt.rgba(0.3, 0, 0, 0.3) @@ -402,7 +419,7 @@ Rectangle { } Text { color: "white" - text: shortText(parent.horizontalAlignment) + text: root.shortText(parent.horizontalAlignment) anchors { top: parent.top; right: parent.right; margins: 2 } } } @@ -411,13 +428,15 @@ Rectangle { Component { id: textInput Item { + id: textDelegate + required property int index width: 180 height: textInput.text.length > 20 ? 3*textInput.height : textInput.height TextInput { id: textInput width: 180 - text: root.text[index] - font.pixelSize: pxSz + text: root.text[textDelegate.index] + font.pixelSize: root.pxSz cursorVisible: true horizontalAlignment: root.horizontalAlignment LayoutMirroring.enabled: root.mirror @@ -427,10 +446,10 @@ Rectangle { anchors.fill: parent } Text { - text: root.description[index] + text: root.description[textDelegate.index] color: Qt.rgba(1,1,1,1.0) anchors.centerIn: parent - font.pixelSize: pxSz - 2 + font.pixelSize: root.pxSz - 2 Rectangle { z: -1 color: Qt.rgba(0.3, 0, 0, 0.3) @@ -439,7 +458,7 @@ Rectangle { } Text { color: "white" - text: shortText(parent.horizontalAlignment) + text: root.shortText(parent.horizontalAlignment) anchors { top: parent.top; right: parent.right; margins: 2 } } } diff --git a/examples/quick/scenegraph/customgeometry/main.cpp b/examples/quick/scenegraph/customgeometry/main.cpp index 15310d279f..0b9b2eb3f9 100644 --- a/examples/quick/scenegraph/customgeometry/main.cpp +++ b/examples/quick/scenegraph/customgeometry/main.cpp @@ -56,6 +56,7 @@ //! [1] int main(int argc, char **argv) { + QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); QQuickView view; diff --git a/examples/quick/scenegraph/metaltextureimport/main.cpp b/examples/quick/scenegraph/metaltextureimport/main.cpp index c969817e8f..4fc010e710 100644 --- a/examples/quick/scenegraph/metaltextureimport/main.cpp +++ b/examples/quick/scenegraph/metaltextureimport/main.cpp @@ -50,14 +50,10 @@ #include <QGuiApplication> #include <QtQuick/QQuickView> -#include "metaltextureimport.h" int main(int argc, char **argv) { QGuiApplication app(argc, argv); - - qmlRegisterType<CustomTextureItem>("MetalTextureImport", 1, 0, "CustomTextureItem"); - QQuickWindow::setSceneGraphBackend(QSGRendererInterface::MetalRhi); QQuickView view; diff --git a/examples/quick/scenegraph/metaltextureimport/metaltextureimport.h b/examples/quick/scenegraph/metaltextureimport/metaltextureimport.h index afc5aced97..49a29565a7 100644 --- a/examples/quick/scenegraph/metaltextureimport/metaltextureimport.h +++ b/examples/quick/scenegraph/metaltextureimport/metaltextureimport.h @@ -60,6 +60,7 @@ class CustomTextureItem : public QQuickItem { Q_OBJECT Q_PROPERTY(qreal t READ t WRITE setT NOTIFY tChanged) + QML_ELEMENT public: CustomTextureItem(); diff --git a/examples/quick/scenegraph/metaltextureimport/metaltextureimport.pro b/examples/quick/scenegraph/metaltextureimport/metaltextureimport.pro index bbdfd358d3..9e88c50dc6 100644 --- a/examples/quick/scenegraph/metaltextureimport/metaltextureimport.pro +++ b/examples/quick/scenegraph/metaltextureimport/metaltextureimport.pro @@ -1,6 +1,9 @@ !macos:!ios: error("This example requires macOS or iOS") QT += qml quick +CONFIG += qmltypes +QML_IMPORT_NAME = MetalTextureImport +QML_IMPORT_MAJOR_VERSION = 1 HEADERS += metaltextureimport.h SOURCES += metaltextureimport.mm main.cpp diff --git a/examples/quick/scenegraph/rendernode/main.qml b/examples/quick/scenegraph/rendernode/main.qml index 2c407796cf..a02fa128d5 100644 --- a/examples/quick/scenegraph/rendernode/main.qml +++ b/examples/quick/scenegraph/rendernode/main.qml @@ -66,7 +66,7 @@ Item { MouseArea { anchors.fill: parent acceptedButtons: Qt.LeftButton | Qt.RightButton - onClicked: { + onClicked: (mouse) => { if (mouse.button === Qt.LeftButton) { clipper.clip = !clipper.clip } else if (mouse.button === Qt.RightButton) { diff --git a/examples/quick/scenegraph/shared/logorenderer.h b/examples/quick/scenegraph/shared/logorenderer.h index 6e7c4b897f..03821919a9 100644 --- a/examples/quick/scenegraph/shared/logorenderer.h +++ b/examples/quick/scenegraph/shared/logorenderer.h @@ -53,8 +53,8 @@ #include <QtGui/qvector3d.h> #include <QtGui/qmatrix4x4.h> -#include <QtGui/qopenglshaderprogram.h> -#include <QtGui/qopenglfunctions.h> +#include <qopenglshaderprogram.h> +#include <qopenglfunctions.h> #include <QTime> #include <QVector> diff --git a/examples/quick/scenegraph/vulkantextureimport/main.cpp b/examples/quick/scenegraph/vulkantextureimport/main.cpp index 1c42e87043..5dc28eb8a3 100644 --- a/examples/quick/scenegraph/vulkantextureimport/main.cpp +++ b/examples/quick/scenegraph/vulkantextureimport/main.cpp @@ -50,14 +50,11 @@ #include <QGuiApplication> #include <QtQuick/QQuickView> -#include "vulkantextureimport.h" int main(int argc, char **argv) { QGuiApplication app(argc, argv); - qmlRegisterType<CustomTextureItem>("VulkanTextureImport", 1, 0, "CustomTextureItem"); - QQuickWindow::setSceneGraphBackend(QSGRendererInterface::VulkanRhi); QQuickView view; diff --git a/examples/quick/scenegraph/vulkantextureimport/vulkantextureimport.cpp b/examples/quick/scenegraph/vulkantextureimport/vulkantextureimport.cpp index a4201c1dfa..a09a05e735 100644 --- a/examples/quick/scenegraph/vulkantextureimport/vulkantextureimport.cpp +++ b/examples/quick/scenegraph/vulkantextureimport/vulkantextureimport.cpp @@ -57,6 +57,7 @@ #include <QVulkanInstance> #include <QVulkanFunctions> +#include <QFile> class CustomTextureNode : public QSGTextureProvider, public QSGSimpleTextureNode { diff --git a/examples/quick/scenegraph/vulkantextureimport/vulkantextureimport.h b/examples/quick/scenegraph/vulkantextureimport/vulkantextureimport.h index f604faf66f..b8c13b44f6 100644 --- a/examples/quick/scenegraph/vulkantextureimport/vulkantextureimport.h +++ b/examples/quick/scenegraph/vulkantextureimport/vulkantextureimport.h @@ -60,6 +60,7 @@ class CustomTextureItem : public QQuickItem { Q_OBJECT Q_PROPERTY(qreal t READ t WRITE setT NOTIFY tChanged) + QML_ELEMENT public: CustomTextureItem(); diff --git a/examples/quick/scenegraph/vulkantextureimport/vulkantextureimport.pro b/examples/quick/scenegraph/vulkantextureimport/vulkantextureimport.pro index f2f78a6ed3..11e422ecad 100644 --- a/examples/quick/scenegraph/vulkantextureimport/vulkantextureimport.pro +++ b/examples/quick/scenegraph/vulkantextureimport/vulkantextureimport.pro @@ -1,12 +1,13 @@ !qtConfig(vulkan): error("This example requires Qt built with Vulkan support") QT += qml quick +CONFIG += qmltypes +QML_IMPORT_NAME = VulkanTextureImport +QML_IMPORT_MAJOR_VERSION = 1 HEADERS += vulkantextureimport.h SOURCES += vulkantextureimport.cpp main.cpp RESOURCES += vulkantextureimport.qrc - - target.path = $$[QT_INSTALL_EXAMPLES]/quick/scenegraph/vulkantextureimport INSTALLS += target diff --git a/examples/quick/scenegraph/vulkanunderqml/main.cpp b/examples/quick/scenegraph/vulkanunderqml/main.cpp index a04497b1d6..6ed0efacdd 100644 --- a/examples/quick/scenegraph/vulkanunderqml/main.cpp +++ b/examples/quick/scenegraph/vulkanunderqml/main.cpp @@ -50,14 +50,11 @@ #include <QGuiApplication> #include <QtQuick/QQuickView> -#include "vulkansquircle.h" int main(int argc, char **argv) { QGuiApplication app(argc, argv); - qmlRegisterType<VulkanSquircle>("VulkanUnderQML", 1, 0, "VulkanSquircle"); - // This example needs Vulkan. It will not run otherwise. QQuickWindow::setSceneGraphBackend(QSGRendererInterface::VulkanRhi); diff --git a/examples/quick/scenegraph/vulkanunderqml/vulkansquircle.cpp b/examples/quick/scenegraph/vulkanunderqml/vulkansquircle.cpp index 21f46a25c1..5942b49843 100644 --- a/examples/quick/scenegraph/vulkanunderqml/vulkansquircle.cpp +++ b/examples/quick/scenegraph/vulkanunderqml/vulkansquircle.cpp @@ -54,6 +54,7 @@ #include <QVulkanInstance> #include <QVulkanFunctions> +#include <QFile> class SquircleRenderer : public QObject { diff --git a/examples/quick/scenegraph/vulkanunderqml/vulkansquircle.h b/examples/quick/scenegraph/vulkanunderqml/vulkansquircle.h index 7e65d01a15..16feeacb5b 100644 --- a/examples/quick/scenegraph/vulkanunderqml/vulkansquircle.h +++ b/examples/quick/scenegraph/vulkanunderqml/vulkansquircle.h @@ -59,6 +59,7 @@ class VulkanSquircle : public QQuickItem { Q_OBJECT Q_PROPERTY(qreal t READ t WRITE setT NOTIFY tChanged) + QML_ELEMENT public: VulkanSquircle(); diff --git a/examples/quick/scenegraph/vulkanunderqml/vulkanunderqml.pro b/examples/quick/scenegraph/vulkanunderqml/vulkanunderqml.pro index 9ea57b91c3..8f7ea5861d 100644 --- a/examples/quick/scenegraph/vulkanunderqml/vulkanunderqml.pro +++ b/examples/quick/scenegraph/vulkanunderqml/vulkanunderqml.pro @@ -1,6 +1,9 @@ !qtConfig(vulkan): error("This example requires Qt built with Vulkan support") QT += qml quick +CONFIG += qmltypes +QML_IMPORT_NAME = VulkanUnderQML +QML_IMPORT_MAJOR_VERSION = 1 HEADERS += vulkansquircle.h SOURCES += vulkansquircle.cpp main.cpp diff --git a/examples/quick/shapes/content/item18.qml b/examples/quick/shapes/content/item18.qml index 3774d19bc5..192438408d 100644 --- a/examples/quick/shapes/content/item18.qml +++ b/examples/quick/shapes/content/item18.qml @@ -65,7 +65,7 @@ Rectangle { strokeWidth: 1 fillColor: "black" - PathText { x: 0; y: 100; font.family: "Arial"; font.pixelSize: 150; text: "Qt!" } + PathText { x: 0; y: 0; font.family: "Arial"; font.pixelSize: 150; text: "Qt!" } } } } diff --git a/examples/quick/shared/FlickrRssModel.qml b/examples/quick/shared/FlickrRssModel.qml index 5f88fabcae..2fb4412ba1 100644 --- a/examples/quick/shared/FlickrRssModel.qml +++ b/examples/quick/shared/FlickrRssModel.qml @@ -72,7 +72,7 @@ ListModel { var jsonText = xhr.responseText; var objArray = JSON.parse(jsonText.replace(/\'/g,"'")) if (objArray.errors !== undefined) - console.log(lCategory, "Error fetching tweets: " + imageItems.errors[0].message) + console.log("Error fetching tweets: " + objArray.errors[0].message) else { for (var key in objArray.items) { var rssItem = objArray.items[key]; diff --git a/examples/quick/shared/LauncherList.qml b/examples/quick/shared/LauncherList.qml index f6001cc681..cb13ec4372 100644 --- a/examples/quick/shared/LauncherList.qml +++ b/examples/quick/shared/LauncherList.qml @@ -48,6 +48,9 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + +import QtQml 2.12 +import QtQml.Models 2.12 import QtQuick 2.12 Rectangle { diff --git a/examples/quick/shared/TabSet.qml b/examples/quick/shared/TabSet.qml index 9e2759c3ec..ab8476ad44 100644 --- a/examples/quick/shared/TabSet.qml +++ b/examples/quick/shared/TabSet.qml @@ -78,6 +78,7 @@ Item { Repeater { model: stack.children.length delegate: Rectangle { + required property int index width: tabWidget.width / stack.children.length height: Math.max(Screen.pixelDensity * 7, label.implicitHeight * 1.2) @@ -90,18 +91,18 @@ Item { anchors { fill: parent; leftMargin: 2; topMargin: 5; rightMargin: 1 } border { left: 7; right: 7 } source: "images/tab.png" - visible: tabWidget.current == index + visible: tabWidget.current == parent.index } Text { id: label horizontalAlignment: Qt.AlignHCenter; verticalAlignment: Qt.AlignVCenter anchors.fill: parent - text: stack.children[index].title + text: stack.children[parent.index].title elide: Text.ElideRight - font.bold: tabWidget.current == index + font.bold: tabWidget.current == parent.index } TapHandler { - onTapped: tabWidget.current = index + onTapped: tabWidget.current = parent.index } } } diff --git a/examples/quick/tableview/gameoflife/main.qml b/examples/quick/tableview/gameoflife/main.qml index 90be69b9c0..fb3195892f 100644 --- a/examples/quick/tableview/gameoflife/main.qml +++ b/examples/quick/tableview/gameoflife/main.qml @@ -48,6 +48,7 @@ ** ****************************************************************************/ +import QtQml 2.12 import QtQuick 2.12 import QtQuick.Window 2.3 import QtQuick.Controls 2.2 @@ -81,11 +82,14 @@ ApplicationWindow { implicitWidth: 15 implicitHeight: 15 - color: model.value ? "#f3f3f4" : "#b5b7bf" + required property var model + required property bool value + + color: value ? "#f3f3f4" : "#b5b7bf" MouseArea { anchors.fill: parent - onClicked: model.value = !model.value + onClicked: parent.model.value = !parent.value } } //! [tableview] diff --git a/examples/quick/tableview/pixelator/main.qml b/examples/quick/tableview/pixelator/main.qml index 38a25f439f..a5edefae90 100644 --- a/examples/quick/tableview/pixelator/main.qml +++ b/examples/quick/tableview/pixelator/main.qml @@ -65,7 +65,9 @@ Window { id: pixelDelegate Item { - readonly property real gray: model.display / 255.0 + required property real display + + readonly property real gray: display / 255.0 readonly property real size: 16 implicitWidth: size @@ -77,7 +79,7 @@ Window { id: rect anchors.centerIn: parent color: "#09102b" - radius: size - gray * size + radius: parent.size - parent.gray * parent.size implicitWidth: radius implicitHeight: radius //! [rectshape] diff --git a/examples/quick/text/fonts/availableFonts.qml b/examples/quick/text/fonts/availableFonts.qml index ea3bff22b8..41dbae0021 100644 --- a/examples/quick/text/fonts/availableFonts.qml +++ b/examples/quick/text/fonts/availableFonts.qml @@ -61,11 +61,12 @@ Rectangle { delegate: Item { height: 40; width: ListView.view.width + required property string modelData Text { anchors.centerIn: parent - text: modelData + text: parent.modelData //! [delegate] - font.family: modelData + font.family: parent.modelData //! [delegate] font.pixelSize: 20 color: "white" diff --git a/examples/quick/text/fonts/fonts.qml b/examples/quick/text/fonts/fonts.qml index f4e721b6c1..aeb17c48e2 100644 --- a/examples/quick/text/fonts/fonts.qml +++ b/examples/quick/text/fonts/fonts.qml @@ -51,6 +51,7 @@ import QtQuick 2.0 Rectangle { + id: root property string myText: "The quick brown fox jumps over the lazy dog." width: 320; height: 480 @@ -68,7 +69,7 @@ Rectangle { spacing: 15 Text { - text: myText + text: root.myText color: "lightsteelblue" width: parent.width wrapMode: Text.WordWrap @@ -78,7 +79,7 @@ Rectangle { font.pixelSize: 20 } Text { - text: myText + text: root.myText color: "lightsteelblue" width: parent.width wrapMode: Text.WordWrap @@ -86,7 +87,7 @@ Rectangle { font { family: "Times"; pixelSize: 20; capitalization: Font.AllUppercase } } Text { - text: myText + text: root.myText color: "lightsteelblue" width: parent.width horizontalAlignment: Text.AlignRight @@ -94,14 +95,14 @@ Rectangle { font { family: "Courier"; pixelSize: 20; weight: Font.Bold; capitalization: Font.AllLowercase } } Text { - text: myText + text: root.myText color: "lightsteelblue" width: parent.width wrapMode: Text.WordWrap font { family: "Courier"; pixelSize: 20; italic: true; capitalization: Font.SmallCaps } } Text { - text: myText + text: root.myText color: "lightsteelblue" width: parent.width wrapMode: Text.WordWrap @@ -109,7 +110,7 @@ Rectangle { } Text { text: { - if (webFont.status == FontLoader.Ready) myText + if (webFont.status == FontLoader.Ready) root.myText else if (webFont.status == FontLoader.Loading) "Loading..." else if (webFont.status == FontLoader.Error) "Error loading font" } diff --git a/examples/quick/text/imgtag/TextWithImage.qml b/examples/quick/text/imgtag/TextWithImage.qml index 1cb65e739d..d22e93146d 100644 --- a/examples/quick/text/imgtag/TextWithImage.qml +++ b/examples/quick/text/imgtag/TextWithImage.qml @@ -55,5 +55,5 @@ Text { font.pointSize: 14 wrapMode: Text.WordWrap textFormat: Text.StyledText - horizontalAlignment: main.hAlign + horizontalAlignment: parent.hAlign } diff --git a/examples/quick/text/imgtag/imgtag.qml b/examples/quick/text/imgtag/imgtag.qml index 1790853de2..177008940a 100644 --- a/examples/quick/text/imgtag/imgtag.qml +++ b/examples/quick/text/imgtag/imgtag.qml @@ -56,7 +56,7 @@ Rectangle { focus: true color: "#dedede" - property var hAlign: Text.AlignLeft + property int hAlign: Text.AlignLeft Flickable { anchors.fill: parent @@ -68,6 +68,7 @@ Rectangle { x: 10; y: 10 spacing: 20 width: parent.width - 20 + property int hAlign: main.hAlign TextWithImage { text: "This is a <b>happy</b> face<img src=\"images/face-smile.png\">" diff --git a/examples/quick/text/styledtext-layout.qml b/examples/quick/text/styledtext-layout.qml index 631a37b493..b399b638dc 100644 --- a/examples/quick/text/styledtext-layout.qml +++ b/examples/quick/text/styledtext-layout.qml @@ -71,12 +71,12 @@ Rectangle { text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer at ante dui <a href=\"http://www.digia.com\">www.digia.com</a>.<br/>Curabitur ante est, pulvinar quis adipiscing a, iaculis id ipsum. Nunc blandit condimentum odio vel egestas.<br><ul type=\"bullet\"><li>Coffee<ol type=\"a\"><li>Espresso<li>Cappuccino<li>Latte</ol><li>Juice<ol type=\"1\"><li>Orange</li><li>Apple</li><li>Pineapple</li><li>Tomato</li></ol></li></ul><p><font color=\"#434343\"><i>Proin consectetur <b>sapien</b> in ipsum lacinia sit amet mattis orci interdum. Quisque vitae accumsan lectus. Ut nisi turpis, sollicitudin ut dignissim id, fermentum ac est. Maecenas nec libero leo. Sed ac leo eget ipsum ultricies viverra sit amet eu orci. Praesent et tortor risus, viverra accumsan sapien. Sed faucibus eleifend lectus, sed euismod urna porta eu. Quisque vitae accumsan lectus. Ut nisi turpis, sollicitudin ut dignissim id, fermentum ac est. Maecenas nec libero leo. Sed ac leo eget ipsum ultricies viverra sit amet eu orci." //! [layout] - onLineLaidOut: { - line.width = width / 2 - (margin) + onLineLaidOut: (line) => { + line.width = width / 2 - main.margin if (line.y + line.height >= height) { - line.y -= height - margin - line.x = width / 2 + margin + line.y -= height - main.margin + line.x = width / 2 + main.activeFocusmargin } if (line.isLast) { diff --git a/examples/quick/threading/threadedlistmodel/timedisplay.qml b/examples/quick/threading/threadedlistmodel/timedisplay.qml index 5ad901c676..c4e6e7b249 100644 --- a/examples/quick/threading/threadedlistmodel/timedisplay.qml +++ b/examples/quick/threading/threadedlistmodel/timedisplay.qml @@ -59,7 +59,10 @@ Rectangle { anchors.fill: parent model: listModel delegate: Component { - Text { text: time } + Text { + required property string time + text: time + } } ListModel { id: listModel } diff --git a/examples/quick/threading/workerscript/Spinner.qml b/examples/quick/threading/workerscript/Spinner.qml index 9c70090dba..a2257f8639 100644 --- a/examples/quick/threading/workerscript/Spinner.qml +++ b/examples/quick/threading/workerscript/Spinner.qml @@ -78,6 +78,7 @@ Rectangle { clip: true model: 64 delegate: Text { + required property int index font.pixelSize: 18; color: "white"; text: index; diff --git a/examples/quick/threading/workerscript/workerscript.qml b/examples/quick/threading/workerscript/workerscript.qml index 735cc8d1f1..eb8ad43d01 100644 --- a/examples/quick/threading/workerscript/workerscript.qml +++ b/examples/quick/threading/workerscript/workerscript.qml @@ -58,7 +58,7 @@ Rectangle { id: myWorker source: "workerscript.mjs" - onMessage: { + onMessage: (messageObject) => { if (messageObject.row == rowSpinner.value && messageObject.column == columnSpinner.value){ //Not an old result if (messageObject.result == -1) resultText.text = "Column must be <= Row"; diff --git a/examples/quick/touchinteraction/flickable/content/Panel.qml b/examples/quick/touchinteraction/flickable/content/Panel.qml index 21f8fc8afd..0aae0635b2 100644 --- a/examples/quick/touchinteraction/flickable/content/Panel.qml +++ b/examples/quick/touchinteraction/flickable/content/Panel.qml @@ -50,112 +50,106 @@ import QtQuick 2.0 -Component { - Item { - property variant stickies +Item { + required property string name + required property var notes - id: page - width: ListView.view.width+40; height: ListView.view.height + property real horizontalVelocity: 0 + id: page + width: ListView.view.width+40; height: ListView.view.height - Image { - source: "cork.jpg" - width: page.ListView.view.width - height: page.ListView.view.height - fillMode: Image.PreserveAspectCrop - clip: true - } - - MouseArea { - anchors.fill: parent - onClicked: page.focus = false; - } - Text { - text: name; x: 15; y: 8; height: 40; width: 370 - font.pixelSize: 18; font.bold: true; color: "white" - style: Text.Outline; styleColor: "black" - } + Image { + source: "cork.jpg" + width: page.ListView.view.width + height: page.ListView.view.height + fillMode: Image.PreserveAspectCrop + clip: true + } - Repeater { - model: notes - Item { - id: stickyPage + MouseArea { + anchors.fill: parent + onClicked: page.focus = false; + } - property int randomX: Math.random() * (page.ListView.view.width-0.5*stickyImage.width) +100 - property int randomY: Math.random() * (page.ListView.view.height-0.5*stickyImage.height) +50 + Text { + text: page.name; x: 15; y: 8; height: 40; width: 370 + font.pixelSize: 18; font.bold: true; color: "white" + style: Text.Outline; styleColor: "black" + } - x: randomX; y: randomY + Repeater { + model: page.notes + Item { + id: stickyPage + required property string noteText - rotation: -flickable.horizontalVelocity / 100; - Behavior on rotation { - SpringAnimation { spring: 2.0; damping: 0.15 } - } + property int randomX: Math.random() * (page.ListView.view.width-0.5*stickyImage.width) +100 + property int randomY: Math.random() * (page.ListView.view.height-0.5*stickyImage.height) +50 - Item { - id: sticky - scale: 0.7 - - Image { - id: stickyImage - x: 8 + -width * 0.6 / 2; y: -20 - source: "note-yellow.png" - scale: 0.6; transformOrigin: Item.TopLeft - } + x: randomX; y: randomY - TextEdit { - id: myText - x: -104; y: 36; width: 215; height: 200 - font.pixelSize: 24 - readOnly: false - rotation: -8 - text: noteText - } + rotation: -page.horizontalVelocity / 100 + Behavior on rotation { + SpringAnimation { spring: 2.0; damping: 0.15 } + } - Item { - x: stickyImage.x; y: -20 - width: stickyImage.width * stickyImage.scale - height: stickyImage.height * stickyImage.scale - - MouseArea { - id: mouse - anchors.fill: parent - drag.target: stickyPage - drag.axis: Drag.XAndYAxis - drag.minimumY: 0 - drag.maximumY: page.height - 80 - drag.minimumX: 100 - drag.maximumX: page.width - 140 - onClicked: myText.forceActiveFocus() - } - } - } + Item { + id: sticky + scale: 0.7 Image { - x: -width / 2; y: -height * 0.5 / 2 - source: "tack.png" - scale: 0.7; transformOrigin: Item.TopLeft + id: stickyImage + x: 8 + -width * 0.6 / 2; y: -20 + source: "note-yellow.png" + scale: 0.6; transformOrigin: Item.TopLeft } - states: State { - name: "pressed" - when: mouse.pressed - PropertyChanges { target: sticky; rotation: 8; scale: 1 } - PropertyChanges { target: page; z: 8 } + TextEdit { + id: myText + x: -104; y: 36; width: 215; height: 200 + font.pixelSize: 24 + readOnly: false + rotation: -8 + text: stickyPage.noteText } - transitions: Transition { - NumberAnimation { properties: "rotation,scale"; duration: 200 } + Item { + x: stickyImage.x; y: -20 + width: stickyImage.width * stickyImage.scale + height: stickyImage.height * stickyImage.scale + + MouseArea { + id: mouse + anchors.fill: parent + drag.target: stickyPage + drag.axis: Drag.XAndYAxis + drag.minimumY: 0 + drag.maximumY: page.height - 80 + drag.minimumX: 100 + drag.maximumX: page.width - 140 + onClicked: myText.forceActiveFocus() + } } } - } - } -} - - - - - + Image { + x: -width / 2; y: -height * 0.5 / 2 + source: "tack.png" + scale: 0.7; transformOrigin: Item.TopLeft + } + states: State { + name: "pressed" + when: mouse.pressed + PropertyChanges { target: sticky; rotation: 8; scale: 1 } + PropertyChanges { target: page; z: 8 } + } + transitions: Transition { + NumberAnimation { properties: "rotation,scale"; duration: 200 } + } + } + } +} diff --git a/examples/quick/touchinteraction/flickable/corkboards.qml b/examples/quick/touchinteraction/flickable/corkboards.qml index afb5dd309c..4825053f3f 100644 --- a/examples/quick/touchinteraction/flickable/corkboards.qml +++ b/examples/quick/touchinteraction/flickable/corkboards.qml @@ -92,6 +92,8 @@ Rectangle { orientation: ListView.Horizontal snapMode: ListView.SnapOneItem model: list - delegate: Panel { } + delegate: Panel { + horizontalVelocity: flickable.horizontalVelocity + } } } diff --git a/examples/quick/touchinteraction/multipointtouch/content/AugmentedTouchPoint.qml b/examples/quick/touchinteraction/multipointtouch/content/AugmentedTouchPoint.qml index 5750ffcad1..56f287666f 100644 --- a/examples/quick/touchinteraction/multipointtouch/content/AugmentedTouchPoint.qml +++ b/examples/quick/touchinteraction/multipointtouch/content/AugmentedTouchPoint.qml @@ -66,7 +66,7 @@ TouchPoint { interval: 100 running: false repeat: false - onTriggered: child.enabled = false + onTriggered: container.child.enabled = false } property Item child: SpriteGoal { enabled: false diff --git a/examples/quick/tutorials/dynamicview/dynamicview1/dynamicview1.pro b/examples/quick/tutorials/dynamicview/dynamicview1/dynamicview1.pro new file mode 100644 index 0000000000..8ca003b6b4 --- /dev/null +++ b/examples/quick/tutorials/dynamicview/dynamicview1/dynamicview1.pro @@ -0,0 +1,9 @@ +TEMPLATE = app + +QT += quick qml +SOURCES += main.cpp + +RESOURCES += dynamicview1.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/quick/tutorials/dynamicview/dynamicview1 +INSTALLS += target diff --git a/examples/quick/tutorials/dynamicview/dynamicview1/dynamicview1.qrc b/examples/quick/tutorials/dynamicview/dynamicview1/dynamicview1.qrc new file mode 100644 index 0000000000..c89a5e3a97 --- /dev/null +++ b/examples/quick/tutorials/dynamicview/dynamicview1/dynamicview1.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/"> + <file>dynamicview.qml</file> + <file>PetsModel.qml</file> + </qresource> +</RCC> diff --git a/examples/quick/tutorials/dynamicview/dynamicview1/main.cpp b/examples/quick/tutorials/dynamicview/dynamicview1/main.cpp new file mode 100644 index 0000000000..72b8b667f5 --- /dev/null +++ b/examples/quick/tutorials/dynamicview/dynamicview1/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "../../../shared/shared.h" +DECLARATIVE_EXAMPLE_MAIN(dynamicview) diff --git a/examples/quick/tutorials/dynamicview/dynamicview2/dynamicview2.pro b/examples/quick/tutorials/dynamicview/dynamicview2/dynamicview2.pro new file mode 100644 index 0000000000..a2b058c528 --- /dev/null +++ b/examples/quick/tutorials/dynamicview/dynamicview2/dynamicview2.pro @@ -0,0 +1,9 @@ +TEMPLATE = app + +QT += quick qml +SOURCES += main.cpp + +RESOURCES += dynamicview2.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/quick/tutorials/dynamicview/dynamicview2 +INSTALLS += target diff --git a/examples/quick/tutorials/dynamicview/dynamicview2/dynamicview2.qrc b/examples/quick/tutorials/dynamicview/dynamicview2/dynamicview2.qrc new file mode 100644 index 0000000000..c89a5e3a97 --- /dev/null +++ b/examples/quick/tutorials/dynamicview/dynamicview2/dynamicview2.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/"> + <file>dynamicview.qml</file> + <file>PetsModel.qml</file> + </qresource> +</RCC> diff --git a/examples/quick/tutorials/dynamicview/dynamicview2/main.cpp b/examples/quick/tutorials/dynamicview/dynamicview2/main.cpp new file mode 100644 index 0000000000..72b8b667f5 --- /dev/null +++ b/examples/quick/tutorials/dynamicview/dynamicview2/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "../../../shared/shared.h" +DECLARATIVE_EXAMPLE_MAIN(dynamicview) diff --git a/examples/quick/tutorials/dynamicview/dynamicview3/dynamicview3.pro b/examples/quick/tutorials/dynamicview/dynamicview3/dynamicview3.pro new file mode 100644 index 0000000000..ebc753f2a7 --- /dev/null +++ b/examples/quick/tutorials/dynamicview/dynamicview3/dynamicview3.pro @@ -0,0 +1,9 @@ +TEMPLATE = app + +QT += quick qml +SOURCES += main.cpp + +RESOURCES += dynamicview3.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/quick/tutorials/dynamicview/dynamicview3 +INSTALLS += target diff --git a/examples/quick/tutorials/dynamicview/dynamicview3/dynamicview3.qrc b/examples/quick/tutorials/dynamicview/dynamicview3/dynamicview3.qrc new file mode 100644 index 0000000000..c89a5e3a97 --- /dev/null +++ b/examples/quick/tutorials/dynamicview/dynamicview3/dynamicview3.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/"> + <file>dynamicview.qml</file> + <file>PetsModel.qml</file> + </qresource> +</RCC> diff --git a/examples/quick/tutorials/dynamicview/dynamicview3/main.cpp b/examples/quick/tutorials/dynamicview/dynamicview3/main.cpp new file mode 100644 index 0000000000..72b8b667f5 --- /dev/null +++ b/examples/quick/tutorials/dynamicview/dynamicview3/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "../../../shared/shared.h" +DECLARATIVE_EXAMPLE_MAIN(dynamicview) diff --git a/examples/quick/tutorials/dynamicview/dynamicview4/dynamicview4.pro b/examples/quick/tutorials/dynamicview/dynamicview4/dynamicview4.pro new file mode 100644 index 0000000000..a5cb99f665 --- /dev/null +++ b/examples/quick/tutorials/dynamicview/dynamicview4/dynamicview4.pro @@ -0,0 +1,9 @@ +TEMPLATE = app + +QT += quick qml +SOURCES += main.cpp + +RESOURCES += dynamicview4.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/quick/tutorials/dynamicview/dynamicview4 +INSTALLS += target diff --git a/examples/quick/tutorials/dynamicview/dynamicview4/dynamicview4.qrc b/examples/quick/tutorials/dynamicview/dynamicview4/dynamicview4.qrc new file mode 100644 index 0000000000..c89a5e3a97 --- /dev/null +++ b/examples/quick/tutorials/dynamicview/dynamicview4/dynamicview4.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/"> + <file>dynamicview.qml</file> + <file>PetsModel.qml</file> + </qresource> +</RCC> diff --git a/examples/quick/tutorials/dynamicview/dynamicview4/main.cpp b/examples/quick/tutorials/dynamicview/dynamicview4/main.cpp new file mode 100644 index 0000000000..72b8b667f5 --- /dev/null +++ b/examples/quick/tutorials/dynamicview/dynamicview4/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "../../../shared/shared.h" +DECLARATIVE_EXAMPLE_MAIN(dynamicview) diff --git a/examples/quick/tutorials/samegame/samegame1/main.cpp b/examples/quick/tutorials/samegame/samegame1/main.cpp new file mode 100644 index 0000000000..7589b92906 --- /dev/null +++ b/examples/quick/tutorials/samegame/samegame1/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "../../../shared/shared.h" +DECLARATIVE_EXAMPLE_MAIN(samegame) diff --git a/examples/quick/tutorials/samegame/samegame1/samegame1.pro b/examples/quick/tutorials/samegame/samegame1/samegame1.pro new file mode 100644 index 0000000000..9f316b6868 --- /dev/null +++ b/examples/quick/tutorials/samegame/samegame1/samegame1.pro @@ -0,0 +1,11 @@ +TEMPLATE = app + +QT += quick qml +SOURCES += main.cpp + +RESOURCES += \ + samegame1.qrc \ + ../shared/pics/shared.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/quick/tutorials/samegame/samegame1 +INSTALLS += target diff --git a/examples/quick/tutorials/samegame/samegame1/samegame1.qrc b/examples/quick/tutorials/samegame/samegame1/samegame1.qrc new file mode 100644 index 0000000000..866cf899bf --- /dev/null +++ b/examples/quick/tutorials/samegame/samegame1/samegame1.qrc @@ -0,0 +1,7 @@ +<RCC> + <qresource prefix="/"> + <file>Button.qml</file> + <file>Block.qml</file> + <file>samegame.qml</file> + </qresource> +</RCC> diff --git a/examples/quick/tutorials/samegame/samegame2/main.cpp b/examples/quick/tutorials/samegame/samegame2/main.cpp new file mode 100644 index 0000000000..7589b92906 --- /dev/null +++ b/examples/quick/tutorials/samegame/samegame2/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "../../../shared/shared.h" +DECLARATIVE_EXAMPLE_MAIN(samegame) diff --git a/examples/quick/tutorials/samegame/samegame2/samegame2.pro b/examples/quick/tutorials/samegame/samegame2/samegame2.pro new file mode 100644 index 0000000000..5ede9042cc --- /dev/null +++ b/examples/quick/tutorials/samegame/samegame2/samegame2.pro @@ -0,0 +1,11 @@ +TEMPLATE = app + +QT += quick qml +SOURCES += main.cpp + +RESOURCES += \ + samegame2.qrc \ + ../shared/pics/shared.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/quick/tutorials/samegame/samegame2 +INSTALLS += target diff --git a/examples/quick/tutorials/samegame/samegame2/samegame2.qrc b/examples/quick/tutorials/samegame/samegame2/samegame2.qrc new file mode 100644 index 0000000000..0f95174d83 --- /dev/null +++ b/examples/quick/tutorials/samegame/samegame2/samegame2.qrc @@ -0,0 +1,8 @@ +<RCC> + <qresource prefix="/"> + <file>Button.qml</file> + <file>Block.qml</file> + <file>samegame.qml</file> + <file>samegame.js</file> + </qresource> +</RCC> diff --git a/examples/quick/tutorials/samegame/samegame3/main.cpp b/examples/quick/tutorials/samegame/samegame3/main.cpp new file mode 100644 index 0000000000..7589b92906 --- /dev/null +++ b/examples/quick/tutorials/samegame/samegame3/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "../../../shared/shared.h" +DECLARATIVE_EXAMPLE_MAIN(samegame) diff --git a/examples/quick/tutorials/samegame/samegame3/samegame3.pro b/examples/quick/tutorials/samegame/samegame3/samegame3.pro new file mode 100644 index 0000000000..7b99673e57 --- /dev/null +++ b/examples/quick/tutorials/samegame/samegame3/samegame3.pro @@ -0,0 +1,11 @@ +TEMPLATE = app + +QT += quick qml +SOURCES += main.cpp + +RESOURCES += \ + samegame3.qrc \ + ../shared/pics/shared.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/quick/tutorials/samegame/samegame3 +INSTALLS += target diff --git a/examples/quick/tutorials/samegame/samegame3/samegame3.qrc b/examples/quick/tutorials/samegame/samegame3/samegame3.qrc new file mode 100644 index 0000000000..0f95174d83 --- /dev/null +++ b/examples/quick/tutorials/samegame/samegame3/samegame3.qrc @@ -0,0 +1,8 @@ +<RCC> + <qresource prefix="/"> + <file>Button.qml</file> + <file>Block.qml</file> + <file>samegame.qml</file> + <file>samegame.js</file> + </qresource> +</RCC> diff --git a/examples/quick/tutorials/samegame/samegame4/main.cpp b/examples/quick/tutorials/samegame/samegame4/main.cpp new file mode 100644 index 0000000000..7589b92906 --- /dev/null +++ b/examples/quick/tutorials/samegame/samegame4/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "../../../shared/shared.h" +DECLARATIVE_EXAMPLE_MAIN(samegame) diff --git a/examples/quick/tutorials/samegame/samegame4/samegame4.pro b/examples/quick/tutorials/samegame/samegame4/samegame4.pro new file mode 100644 index 0000000000..5da0d46e19 --- /dev/null +++ b/examples/quick/tutorials/samegame/samegame4/samegame4.pro @@ -0,0 +1,11 @@ +TEMPLATE = app + +QT += quick qml +SOURCES += main.cpp + +RESOURCES += \ + samegame4.qrc \ + ../shared/pics/shared.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/quick/tutorials/samegame/samegame4 +INSTALLS += target diff --git a/examples/quick/tutorials/samegame/samegame4/samegame4.qrc b/examples/quick/tutorials/samegame/samegame4/samegame4.qrc new file mode 100644 index 0000000000..8b130721f5 --- /dev/null +++ b/examples/quick/tutorials/samegame/samegame4/samegame4.qrc @@ -0,0 +1,13 @@ +<RCC> + <qresource prefix="/"> + <file>samegame.qml</file> + <file>content/BoomBlock.qml</file> + <file>content/Button.qml</file> + <file>content/Dialog.qml</file> + <file>content/samegame.js</file> + <file>highscores/README</file> + <file>highscores/score_data.xml</file> + <file>highscores/score_style.xsl</file> + <file>highscores/scores.php</file> + </qresource> +</RCC> diff --git a/examples/quick/tutorials/samegame/shared/pics/shared.qrc b/examples/quick/tutorials/samegame/shared/pics/shared.qrc new file mode 100644 index 0000000000..8982a9face --- /dev/null +++ b/examples/quick/tutorials/samegame/shared/pics/shared.qrc @@ -0,0 +1,13 @@ +<RCC> + <qresource prefix="/shared/pics"> + <file>background.jpg</file> + <file>blueStar.png</file> + <file>blueStone.png</file> + <file>greenStar.png</file> + <file>greenStone.png</file> + <file>redStar.png</file> + <file>redStone.png</file> + <file>star.png</file> + <file>yellowStone.png</file> + </qresource> +</RCC> diff --git a/examples/quick/views/delegatemodel/dragselection.qml b/examples/quick/views/delegatemodel/dragselection.qml index 15fd2654c2..f9a0d37311 100644 --- a/examples/quick/views/delegatemodel/dragselection.qml +++ b/examples/quick/views/delegatemodel/dragselection.qml @@ -48,6 +48,7 @@ ** ****************************************************************************/ +import QtQml 2.0 import QtQuick 2.0 import QtQml.Models 2.1 @@ -64,6 +65,8 @@ Item { Package { id: packageRoot + required property var modelData + MouseArea { id: visibleContainer Package.name: "visible" @@ -130,7 +133,7 @@ Item { horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter color: "white" - text: modelData + text: packageRoot.modelData font.pixelSize: 18 } diff --git a/examples/quick/views/delegatemodel/flipable.pro b/examples/quick/views/delegatemodel/flipable.pro new file mode 100644 index 0000000000..ba00bf792c --- /dev/null +++ b/examples/quick/views/delegatemodel/flipable.pro @@ -0,0 +1,9 @@ +TEMPLATE = app + +QT += quick qml +SOURCES += main.cpp + +RESOURCES += flipable.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/quick/customitems/flipable +INSTALLS += target diff --git a/examples/quick/views/delegatemodel/flipable.qrc b/examples/quick/views/delegatemodel/flipable.qrc new file mode 100644 index 0000000000..7918ccf00e --- /dev/null +++ b/examples/quick/views/delegatemodel/flipable.qrc @@ -0,0 +1,9 @@ +<RCC> + <qresource prefix="/"> + <file>flipable.qml</file> + <file>content/5_heart.png</file> + <file>content/9_club.png</file> + <file>content/back.png</file> + <file>content/Card.qml</file> + </qresource> +</RCC> diff --git a/examples/quick/views/delegatemodel/main.cpp b/examples/quick/views/delegatemodel/main.cpp new file mode 100644 index 0000000000..a0f0d67d45 --- /dev/null +++ b/examples/quick/views/delegatemodel/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "../../shared/shared.h" +DECLARATIVE_EXAMPLE_MAIN(flipable) diff --git a/examples/quick/views/delegatemodel/slideshow.qml b/examples/quick/views/delegatemodel/slideshow.qml index b252519bbf..638c8bf10f 100644 --- a/examples/quick/views/delegatemodel/slideshow.qml +++ b/examples/quick/views/delegatemodel/slideshow.qml @@ -74,6 +74,8 @@ Rectangle { width: 76; height: 76 + required property string thumbnail + Rectangle { id: image x: 0; y: 0; width: 76; height: 76 @@ -86,7 +88,7 @@ Rectangle { anchors.leftMargin: 1 anchors.topMargin: 1 - source: thumbnail + source: delegateItem.thumbnail fillMode: Image.PreserveAspectFit } diff --git a/examples/quick/views/gridview/gridview-example.qml b/examples/quick/views/gridview/gridview-example.qml index 76a1d8dd37..4cc30d3736 100644 --- a/examples/quick/views/gridview/gridview-example.qml +++ b/examples/quick/views/gridview/gridview-example.qml @@ -74,20 +74,24 @@ Rectangle { highlight: Rectangle { width: 80; height: 80; color: "lightsteelblue" } delegate: Item { + required property string icon + required property string name + required property int index + width: 100; height: 100 Image { id: myIcon y: 20; anchors.horizontalCenter: parent.horizontalCenter - source: icon + source: parent.icon } Text { anchors { top: myIcon.bottom; horizontalCenter: parent.horizontalCenter } - text: name + text: parent.name } MouseArea { anchors.fill: parent - onClicked: parent.GridView.view.currentIndex = index + onClicked: parent.GridView.view.currentIndex = parent.index } } } diff --git a/examples/quick/views/listview/content/PressAndHoldButton.qml b/examples/quick/views/listview/content/PressAndHoldButton.qml index 527394eb4d..6d633c0264 100644 --- a/examples/quick/views/listview/content/PressAndHoldButton.qml +++ b/examples/quick/views/listview/content/PressAndHoldButton.qml @@ -72,12 +72,12 @@ Image { PropertyAction { target: container; property: "pressed"; value: true } ScriptAction { script: container.clicked() } - PauseAnimation { duration: repeatDelay } + PauseAnimation { duration: container.repeatDelay } SequentialAnimation { loops: Animation.Infinite ScriptAction { script: container.clicked() } - PauseAnimation { duration: repeatDuration } + PauseAnimation { duration: container.repeatDuration } } } diff --git a/examples/quick/views/listview/content/ToggleButton.qml b/examples/quick/views/listview/content/ToggleButton.qml index 0a2747a683..890a94570b 100644 --- a/examples/quick/views/listview/content/ToggleButton.qml +++ b/examples/quick/views/listview/content/ToggleButton.qml @@ -63,6 +63,6 @@ Rectangle { Text { id: text; anchors.centerIn: parent; font.pixelSize: 14 } MouseArea { anchors.fill: parent - onClicked: { active = !active; root.toggled() } + onClicked: { root.active = !root.active; root.toggled() } } } diff --git a/examples/quick/views/listview/displaymargin.qml b/examples/quick/views/listview/displaymargin.qml index e0024e72a9..19261caaa6 100644 --- a/examples/quick/views/listview/displaymargin.qml +++ b/examples/quick/views/listview/displaymargin.qml @@ -68,10 +68,13 @@ Item { width: parent.width height: 25 color: index % 2 ? "steelblue" : "lightsteelblue" + + required property int index + Text { anchors.centerIn: parent color: "white" - text: "Item " + (index + 1) + text: "Item " + (parent.index + 1) } } } diff --git a/examples/quick/views/listview/dynamiclist.qml b/examples/quick/views/listview/dynamiclist.qml index bfc697d094..f37aab98e2 100644 --- a/examples/quick/views/listview/dynamiclist.qml +++ b/examples/quick/views/listview/dynamiclist.qml @@ -101,6 +101,11 @@ Rectangle { width: listView.width; height: 80 clip: true + required property int index + required property string name + required property real cost + required property var attributes + Column { id: arrows anchors { @@ -109,10 +114,16 @@ Rectangle { } Image { source: "content/pics/arrow-up.png" - MouseArea { anchors.fill: parent; onClicked: fruitModel.move(index, index-1, 1) } + MouseArea { + anchors.fill: parent + onClicked: fruitModel.move(delegateItem.index, delegateItem.index - 1, 1) + } } Image { source: "content/pics/arrow-down.png" - MouseArea { anchors.fill: parent; onClicked: fruitModel.move(index, index+1, 1) } + MouseArea { + anchors.fill: parent + onClicked: fruitModel.move(delegateItem.index, delegateItem.index + 1, 1) + } } } @@ -125,7 +136,7 @@ Rectangle { Text { anchors.horizontalCenter: parent.horizontalCenter - text: name + text: delegateItem.name font.pixelSize: 15 color: "white" } @@ -133,8 +144,12 @@ Rectangle { anchors.horizontalCenter: parent.horizontalCenter spacing: 5 Repeater { - model: attributes - Text { text: description; color: "White" } + model: delegateItem.attributes + Text { + required property string description + text: description + color: "White" + } } } } @@ -154,13 +169,13 @@ Rectangle { PressAndHoldButton { anchors.verticalCenter: parent.verticalCenter source: "content/pics/plus-sign.png" - onClicked: fruitModel.setProperty(index, "cost", cost + 0.25) + onClicked: fruitModel.setProperty(delegateItem.index, "cost", delegateItem.cost + 0.25) } Text { id: costText anchors.verticalCenter: parent.verticalCenter - text: '$' + Number(cost).toFixed(2) + text: '$' + Number(delegateItem.cost).toFixed(2) font.pixelSize: 15 color: "white" font.bold: true @@ -169,12 +184,16 @@ Rectangle { PressAndHoldButton { anchors.verticalCenter: parent.verticalCenter source: "content/pics/minus-sign.png" - onClicked: fruitModel.setProperty(index, "cost", Math.max(0,cost-0.25)) + onClicked: fruitModel.setProperty(delegateItem.index, "cost", + Math.max(0, delegateItem.cost - 0.25)) } Image { source: "content/pics/list-delete.png" - MouseArea { anchors.fill:parent; onClicked: fruitModel.remove(index) } + MouseArea { + anchors.fill: parent + onClicked: fruitModel.remove(delegateItem.index) + } } } } diff --git a/examples/quick/views/listview/expandingdelegates.qml b/examples/quick/views/listview/expandingdelegates.qml index 1308e8441d..6ed1d8c341 100644 --- a/examples/quick/views/listview/expandingdelegates.qml +++ b/examples/quick/views/listview/expandingdelegates.qml @@ -67,6 +67,11 @@ Rectangle { Item { id: recipe + required property string title + required property string picture + required property string ingredients + required property string method + // Create a property to contain the visibility of the details. // We can bind multiple element's opacity to this one property, // rather than having a "PropertyChanges" line for each element we @@ -106,7 +111,7 @@ Rectangle { Image { id: recipeImage width: 50; height: 50 - source: picture + source: recipe.picture } //! [1] Column { @@ -114,7 +119,7 @@ Rectangle { spacing: 5 Text { - text: title + text: recipe.title font.bold: true; font.pointSize: 16 } @@ -125,7 +130,7 @@ Rectangle { } SmallText { - text: ingredients + text: recipe.ingredients wrapMode: Text.WordWrap width: parent.width opacity: recipe.detailsOpacity @@ -155,7 +160,12 @@ Rectangle { contentHeight: methodText.height clip: true - Text { id: methodText; text: method; wrapMode: Text.WordWrap; width: details.width } + Text { + id: methodText + text: recipe.method + wrapMode: Text.WordWrap + width: details.width + } } Image { diff --git a/examples/quick/views/listview/highlight.qml b/examples/quick/views/listview/highlight.qml index 5b03d30f25..092b4d59bd 100644 --- a/examples/quick/views/listview/highlight.qml +++ b/examples/quick/views/listview/highlight.qml @@ -58,44 +58,44 @@ import "content" Rectangle { width: 200; height: 300 - // Define a delegate component. A component will be + // Define a delegate component. The component will be // instantiated for each visible item in the list. - Component { - id: petDelegate - Item { - id: wrapper - width: 200; height: 55 - Column { - SmallText { text: 'Name: ' + name } - SmallText { text: 'Type: ' + type } - SmallText { text: 'Age: ' + age } - } - // indent the item if it is the current item - states: State { - name: "Current" - when: wrapper.ListView.isCurrentItem - PropertyChanges { target: wrapper; x: 20 } - } - transitions: Transition { - NumberAnimation { properties: "x"; duration: 200 } - } - MouseArea { - anchors.fill: parent - onClicked: wrapper.ListView.view.currentIndex = index - } + component PetDelegate: Item { + id: pet + width: 200; height: 55 + + required property int index + required property string name + required property string type + required property int age + + Column { + SmallText { text: 'Name: ' + pet.name } + SmallText { text: 'Type: ' + pet.type } + SmallText { text: 'Age: ' + pet.age } + } + // indent the item if it is the current item + states: State { + name: "Current" + when: pet.ListView.isCurrentItem + PropertyChanges { target: pet; x: 20 } + } + transitions: Transition { + NumberAnimation { properties: "x"; duration: 200 } + } + MouseArea { + anchors.fill: parent + onClicked: pet.ListView.view.currentIndex = pet.index } } //! [0] // Define a highlight with customized movement between items. - Component { - id: highlightBar - Rectangle { - width: 200; height: 50 - color: "#FFFF88" - y: listView.currentItem.y; - Behavior on y { SpringAnimation { spring: 2; damping: 0.1 } } - } + component HighlightBar : Rectangle { + width: 200; height: 50 + color: "#FFFF88" + y: listView.currentItem.y + Behavior on y { SpringAnimation { spring: 2; damping: 0.1 } } } ListView { @@ -104,12 +104,12 @@ Rectangle { x: 30 model: PetsModel {} - delegate: petDelegate + delegate: PetDelegate {} focus: true // Set the highlight delegate. Note we must also set highlightFollowsCurrentItem // to false so the highlight delegate can control how the highlight is moved. - highlight: highlightBar + highlight: HighlightBar {} highlightFollowsCurrentItem: false } //! [0] diff --git a/examples/quick/views/listview/highlightranges.qml b/examples/quick/views/listview/highlightranges.qml index 7bc9ab7fe1..dafd064332 100644 --- a/examples/quick/views/listview/highlightranges.qml +++ b/examples/quick/views/listview/highlightranges.qml @@ -62,17 +62,17 @@ Rectangle { loops: -1 running: true ScriptAction { - script: if (increasing) { - current++; - if (current >= aModel.count -1) { - current = aModel.count - 1; - increasing = !increasing; + script: if (root.increasing) { + root.current++; + if (root.current >= aModel.count -1) { + root.current = aModel.count - 1; + root.increasing = !root.increasing; } } else { - current--; - if (current <= 0) { - current = 0; - increasing = !increasing; + root.current--; + if (root.current <= 0) { + root.current = 0; + root.increasing = !root.increasing; } } } @@ -161,16 +161,22 @@ Rectangle { Item { width: 160 height: column.height + + required property int index + required property string name + required property string type + required property int age + Column { id: column - Text { text: 'Name: ' + name } - Text { text: 'Type: ' + type } - Text { text: 'Age: ' + age } + Text { text: 'Name: ' + parent.name } + Text { text: 'Type: ' + parent.type } + Text { text: 'Age: ' + parent.age } } MouseArea { anchors.fill: parent - onClicked: root.current = index + onClicked: root.current = parent.index } } } diff --git a/examples/quick/views/listview/sections.qml b/examples/quick/views/listview/sections.qml index 75b0f5c6d9..d51ed89789 100644 --- a/examples/quick/views/listview/sections.qml +++ b/examples/quick/views/listview/sections.qml @@ -87,8 +87,10 @@ Rectangle { height: childrenRect.height color: "lightsteelblue" + required property string section + Text { - text: section + text: parent.section font.bold: true font.pixelSize: 20 } @@ -101,7 +103,11 @@ Rectangle { anchors.bottom: buttonBar.top width: parent.width model: animalsModel - delegate: Text { text: name; font.pixelSize: 18 } + delegate: Text { + required property string name + text: name + font.pixelSize: 18 + } section.property: "size" section.criteria: ViewSection.FullString diff --git a/examples/quick/views/objectmodel/objectmodel.qml b/examples/quick/views/objectmodel/objectmodel.qml index 8fc2f7c386..c9e4b8a5cd 100644 --- a/examples/quick/views/objectmodel/objectmodel.qml +++ b/examples/quick/views/objectmodel/objectmodel.qml @@ -70,21 +70,21 @@ Rectangle { color: "#FFFEF0" Text { text: "Page 1"; font.bold: true; anchors.centerIn: parent } - Component.onDestruction: if (printDestruction) print("destroyed 1") + Component.onDestruction: if (root.printDestruction) print("destroyed 1") } Rectangle { width: view.width; height: view.height color: "#F0FFF7" Text { text: "Page 2"; font.bold: true; anchors.centerIn: parent } - Component.onDestruction: if (printDestruction) print("destroyed 2") + Component.onDestruction: if (root.printDestruction) print("destroyed 2") } Rectangle { width: view.width; height: view.height color: "#F4F0FF" Text { text: "Page 3"; font.bold: true; anchors.centerIn: parent } - Component.onDestruction: if (printDestruction) print("destroyed 3") + Component.onDestruction: if (root.activeFocusprintDestruction) print("destroyed 3") } } @@ -112,6 +112,8 @@ Rectangle { model: itemModel.count Rectangle { + required property int index + width: 5; height: 5 radius: 3 color: view.currentIndex == index ? "blue" : "white" @@ -119,7 +121,7 @@ Rectangle { MouseArea { width: 20; height: 20 anchors.centerIn: parent - onClicked: view.currentIndex = index + onClicked: view.currentIndex = parent.index } } } diff --git a/examples/quick/views/package/Delegate.qml b/examples/quick/views/package/Delegate.qml index 7c73f35c3d..9f4f1946d8 100644 --- a/examples/quick/views/package/Delegate.qml +++ b/examples/quick/views/package/Delegate.qml @@ -52,6 +52,12 @@ import QtQuick 2.0 //! [0] Package { + id: delegate + + required property int upTo + required property int index + required property string display + Text { id: listDelegate; width: parent.width; height: 25; text: 'Empty'; Package.name: 'list' } Text { id: gridDelegate; width: parent.width / 2; height: 50; text: 'Empty'; Package.name: 'grid' } @@ -60,8 +66,8 @@ Package { width: parent.width; height: 25 color: 'lightsteelblue' - Text { text: display; anchors.centerIn: parent } - state: root.upTo > index ? 'inGrid' : 'inList' + Text { text: delegate.display; anchors.centerIn: parent } + state: delegate.upTo > delegate.index ? 'inGrid' : 'inList' states: [ State { name: 'inList' diff --git a/examples/quick/views/package/view.qml b/examples/quick/views/package/view.qml index 311cc3be8e..632d27c724 100644 --- a/examples/quick/views/package/view.qml +++ b/examples/quick/views/package/view.qml @@ -77,7 +77,9 @@ Rectangle { //![0] DelegateModel { id: visualModel - delegate: Delegate {} + delegate: Delegate { + upTo: root.upTo + } model: myModel } diff --git a/examples/quick/window/AllScreens.qml b/examples/quick/window/AllScreens.qml index a5da380025..ac0e1cb821 100644 --- a/examples/quick/window/AllScreens.qml +++ b/examples/quick/window/AllScreens.qml @@ -69,8 +69,14 @@ Column { id: screenInfo model: Qt.application.screens Shared.Label { + required property string name + required property int virtualX + required property int virtualY + required property int width + required property int height + lineHeight: 1.5 - text: name + "\n" + virtualX + ", " + virtualY + " " + modelData.width + "x" + modelData.height + text: name + "\n" + virtualX + ", " + virtualY + " " + width + "x" + height } } } diff --git a/examples/quick/window/CurrentScreen.qml b/examples/quick/window/CurrentScreen.qml index 2703582399..563cca32a5 100644 --- a/examples/quick/window/CurrentScreen.qml +++ b/examples/quick/window/CurrentScreen.qml @@ -115,10 +115,10 @@ Item { Shared.Label { text: Screen.virtualX + ", " + Screen.virtualY } Shared.Label { text: "orientation" } - Shared.Label { text: orientationToString(Screen.orientation) + " (" + Screen.orientation + ")" } + Shared.Label { text: root.orientationToString(Screen.orientation) + " (" + Screen.orientation + ")" } Shared.Label { text: "primary orientation" } - Shared.Label { text: orientationToString(Screen.primaryOrientation) + " (" + Screen.primaryOrientation + ")" } + Shared.Label { text: root.orientationToString(Screen.primaryOrientation) + " (" + Screen.primaryOrientation + ")" } //! [screen] Shared.Label { text: "10mm rectangle" } diff --git a/examples/quick/window/Splash.qml b/examples/quick/window/Splash.qml index c3e36d9b3b..b33ad6c168 100644 --- a/examples/quick/window/Splash.qml +++ b/examples/quick/window/Splash.qml @@ -78,9 +78,9 @@ Window { } //! [timer] Timer { - interval: timeoutInterval; running: true; repeat: false + interval: splash.timeoutInterval; running: true; repeat: false onTriggered: { - visible = false + splash.visible = false splash.timeout() } } diff --git a/examples/quick/window/window.qml b/examples/quick/window/window.qml index 2ee7fb6e09..4280b6a4c0 100644 --- a/examples/quick/window/window.qml +++ b/examples/quick/window/window.qml @@ -53,65 +53,66 @@ import QtQuick.Window 2.3 import "../shared" as Shared QtObject { + id: root property real defaultSpacing: 10 property SystemPalette palette: SystemPalette { } property var controlWindow: Window { - width: col.implicitWidth + defaultSpacing * 2 - height: col.implicitHeight + defaultSpacing * 2 - color: palette.window + width: col.implicitWidth + root.defaultSpacing * 2 + height: col.implicitHeight + root.defaultSpacing * 2 + color: root.palette.window title: "Control Window" Column { id: col anchors.fill: parent - anchors.margins: defaultSpacing - spacing: defaultSpacing + anchors.margins: root.defaultSpacing + spacing: root.defaultSpacing property real cellWidth: col.width / 3 - spacing Shared.Label { text: "Control the second window:" } Grid { id: grid columns: 3 - spacing: defaultSpacing + spacing: root.defaultSpacing width: parent.width Shared.Button { id: showButton width: col.cellWidth - text: testWindow.visible ? "Hide" : "Show" - onClicked: testWindow.visible = !testWindow.visible + text: root.testWindow.visible ? "Hide" : "Show" + onClicked: root.testWindow.visible = !root.testWindow.visible } //! [windowedCheckbox] Shared.CheckBox { text: "Windowed" height: showButton.height width: col.cellWidth - Binding on checked { value: testWindow.visibility === Window.Windowed } - onClicked: testWindow.visibility = Window.Windowed + Binding on checked { value: root.testWindow.visibility === Window.Windowed } + onClicked: root.testWindow.visibility = Window.Windowed } //! [windowedCheckbox] Shared.CheckBox { height: showButton.height width: col.cellWidth text: "Full Screen" - Binding on checked { value: testWindow.visibility === Window.FullScreen } - onClicked: testWindow.visibility = Window.FullScreen + Binding on checked { value: root.testWindow.visibility === Window.FullScreen } + onClicked: root.testWindow.visibility = Window.FullScreen } Shared.Button { id: autoButton width: col.cellWidth text: "Automatic" - onClicked: testWindow.visibility = Window.AutomaticVisibility + onClicked: root.testWindow.visibility = Window.AutomaticVisibility } Shared.CheckBox { height: autoButton.height text: "Minimized" - Binding on checked { value: testWindow.visibility === Window.Minimized } - onClicked: testWindow.visibility = Window.Minimized + Binding on checked { value: root.testWindow.visibility === Window.Minimized } + onClicked: root.testWindow.visibility = Window.Minimized } Shared.CheckBox { height: autoButton.height text: "Maximized" - Binding on checked { value: testWindow.visibility === Window.Maximized } - onClicked: testWindow.visibility = Window.Maximized + Binding on checked { value: root.testWindow.visibility === Window.Maximized } + onClicked: root.testWindow.visibility = Window.Maximized } } function visibilityToString(v) { @@ -133,17 +134,17 @@ QtObject { } Shared.Label { id: visibilityLabel - text: "second window is " + (testWindow.visible ? "visible" : "invisible") + - " and has visibility " + parent.visibilityToString(testWindow.visibility) + text: "second window is " + (root.testWindow.visible ? "visible" : "invisible") + + " and has visibility " + parent.visibilityToString(root.testWindow.visibility) } Rectangle { - color: palette.text + color: root.palette.text width: parent.width height: 1 } CurrentScreen { } Rectangle { - color: palette.text + color: root.palette.text width: parent.width height: 1 } @@ -159,40 +160,40 @@ QtObject { flags: Qt.Window | Qt.WindowFullscreenButtonHint Rectangle { anchors.fill: parent - anchors.margins: defaultSpacing + anchors.margins: root.defaultSpacing Shared.Label { anchors.centerIn: parent text: "Second Window" } MouseArea { anchors.fill: parent - onClicked: testWindow.color = "#e0c31e" + onClicked: root.testWindow.color = "#e0c31e" } Shared.Button { anchors.right: parent.right anchors.top: parent.top - anchors.margins: defaultSpacing - text: testWindow.visibility === Window.FullScreen ? "exit fullscreen" : "go fullscreen" + anchors.margins: root.defaultSpacing + text: root.testWindow.visibility === Window.FullScreen ? "exit fullscreen" : "go fullscreen" width: 150 onClicked: { - if (testWindow.visibility === Window.FullScreen) - testWindow.visibility = Window.AutomaticVisibility + if (root.testWindow.visibility === Window.FullScreen) + root.testWindow.visibility = Window.AutomaticVisibility else - testWindow.visibility = Window.FullScreen + root.testWindow.visibility = Window.FullScreen } } Shared.Button { anchors.left: parent.left anchors.top: parent.top - anchors.margins: defaultSpacing + anchors.margins: root.defaultSpacing text: "X" width: 30 - onClicked: testWindow.close() + onClicked: root.testWindow.close() } } } property var splashWindow: Splash { - onTimeout: controlWindow.visible = true + onTimeout: root.controlWindow.visible = true } } diff --git a/qtdeclarative.pro b/qtdeclarative.pro index 5b94da9b69..84120bfd07 100644 --- a/qtdeclarative.pro +++ b/qtdeclarative.pro @@ -1,4 +1,9 @@ CONFIG += tests_need_tools examples_need_tools + +# Otherwise we cannot compile src/qmltyperegistrar +requires(qtConfig(commandlineparser)) +requires(qtConfig(temporaryfile)) + load(qt_parts) !python_available { diff --git a/src/imports/folderlistmodel/folderlistmodel.pro b/src/imports/folderlistmodel/folderlistmodel.pro index 8eaf9de6b9..c95a88430d 100644 --- a/src/imports/folderlistmodel/folderlistmodel.pro +++ b/src/imports/folderlistmodel/folderlistmodel.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = qmlfolderlistmodelplugin TARGETPATH = Qt/labs/folderlistmodel -IMPORT_VERSION = 2.15 +QML_IMPORT_VERSION = $$QT_VERSION QT = core-private qml-private diff --git a/src/imports/folderlistmodel/plugin.cpp b/src/imports/folderlistmodel/plugin.cpp index 28837655ef..7a38769b77 100644 --- a/src/imports/folderlistmodel/plugin.cpp +++ b/src/imports/folderlistmodel/plugin.cpp @@ -42,6 +42,8 @@ #include "qquickfolderlistmodel.h" +extern void qml_register_types_Qt_labs_folderlistmodel(); + QT_BEGIN_NAMESPACE //![class decl] @@ -51,7 +53,12 @@ class QmlFolderListModelPlugin : public QQmlExtensionPlugin Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: - QmlFolderListModelPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { } + QmlFolderListModelPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) + { + volatile auto registration = &qml_register_types_Qt_labs_folderlistmodel; + Q_UNUSED(registration); + } + void registerTypes(const char *uri) override { Q_ASSERT(QLatin1String(uri) == QLatin1String("Qt.labs.folderlistmodel")); diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.h b/src/imports/folderlistmodel/qquickfolderlistmodel.h index 5897bd2e0f..d7429efeda 100644 --- a/src/imports/folderlistmodel/qquickfolderlistmodel.h +++ b/src/imports/folderlistmodel/qquickfolderlistmodel.h @@ -67,19 +67,20 @@ class QQuickFolderListModel : public QAbstractListModel, public QQmlParserStatus Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters) Q_PROPERTY(SortField sortField READ sortField WRITE setSortField) Q_PROPERTY(bool sortReversed READ sortReversed WRITE setSortReversed) - Q_PROPERTY(bool showFiles READ showFiles WRITE setShowFiles REVISION 1) + Q_PROPERTY(bool showFiles READ showFiles WRITE setShowFiles REVISION(2, 1)) Q_PROPERTY(bool showDirs READ showDirs WRITE setShowDirs) Q_PROPERTY(bool showDirsFirst READ showDirsFirst WRITE setShowDirsFirst) Q_PROPERTY(bool showDotAndDotDot READ showDotAndDotDot WRITE setShowDotAndDotDot) - Q_PROPERTY(bool showHidden READ showHidden WRITE setShowHidden REVISION 1) + Q_PROPERTY(bool showHidden READ showHidden WRITE setShowHidden REVISION(2, 1)) Q_PROPERTY(bool showOnlyReadable READ showOnlyReadable WRITE setShowOnlyReadable) - Q_PROPERTY(bool caseSensitive READ caseSensitive WRITE setCaseSensitive REVISION 2) + Q_PROPERTY(bool caseSensitive READ caseSensitive WRITE setCaseSensitive REVISION(2, 2)) Q_PROPERTY(int count READ count NOTIFY countChanged) - Q_PROPERTY(Status status READ status NOTIFY statusChanged REVISION 11) - Q_PROPERTY(bool sortCaseSensitive READ sortCaseSensitive WRITE setSortCaseSensitive REVISION 12) + Q_PROPERTY(Status status READ status NOTIFY statusChanged REVISION(2, 11)) + Q_PROPERTY(bool sortCaseSensitive READ sortCaseSensitive WRITE setSortCaseSensitive REVISION(2, 12)) //![class props] QML_NAMED_ELEMENT(FolderListModel) + QML_ADDED_IN_VERSION(2, 0) //![abslistmodel] public: QQuickFolderListModel(QObject *parent = nullptr); @@ -163,8 +164,8 @@ public: Q_SIGNALS: void folderChanged(); void rowCountChanged() const; - Q_REVISION(1) void countChanged() const; - Q_REVISION(11) void statusChanged(); + Q_REVISION(2, 1) void countChanged() const; + Q_REVISION(2, 11) void statusChanged(); //![notifier] //![class end] diff --git a/src/imports/labsanimation/labsanimation.pro b/src/imports/labsanimation/labsanimation.pro index f64ae775c6..5fd8ff25a7 100644 --- a/src/imports/labsanimation/labsanimation.pro +++ b/src/imports/labsanimation/labsanimation.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = labsanimationplugin TARGETPATH = Qt/labs/animation -IMPORT_VERSION = 1.0 +QML_IMPORT_VERSION = $$QT_VERSION SOURCES += \ qquickboundaryrule.cpp \ diff --git a/src/imports/labsanimation/plugin.cpp b/src/imports/labsanimation/plugin.cpp index bd732a6aba..9c985f0dcf 100644 --- a/src/imports/labsanimation/plugin.cpp +++ b/src/imports/labsanimation/plugin.cpp @@ -42,6 +42,8 @@ #include "qquickboundaryrule_p.h" +extern void qml_register_types_Qt_labs_animation(); + QT_BEGIN_NAMESPACE /*! @@ -66,7 +68,11 @@ class QtLabsAnimationPlugin : public QQmlEngineExtensionPlugin Q_OBJECT Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid) public: - QtLabsAnimationPlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) { } + QtLabsAnimationPlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) + { + volatile auto registration = &qml_register_types_Qt_labs_animation; + Q_UNUSED(registration); + } }; //![class decl] diff --git a/src/imports/labsanimation/qquickboundaryrule_p.h b/src/imports/labsanimation/qquickboundaryrule_p.h index 1681558304..33cf0bb094 100644 --- a/src/imports/labsanimation/qquickboundaryrule_p.h +++ b/src/imports/labsanimation/qquickboundaryrule_p.h @@ -78,6 +78,7 @@ class QQuickBoundaryRule : public QObject, public QQmlPropertyValueInterceptor Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged) Q_PROPERTY(int returnDuration READ returnDuration WRITE setReturnDuration NOTIFY returnDurationChanged) QML_NAMED_ELEMENT(BoundaryRule) + QML_ADDED_IN_VERSION(1, 0) public: enum OvershootFilter { diff --git a/src/imports/labsmodels/labsmodels.pro b/src/imports/labsmodels/labsmodels.pro index 13468348cb..9fc52ce9cc 100644 --- a/src/imports/labsmodels/labsmodels.pro +++ b/src/imports/labsmodels/labsmodels.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = labsmodelsplugin TARGETPATH = Qt/labs/qmlmodels -IMPORT_VERSION = 1.0 +QML_IMPORT_VERSION = $$QT_VERSION QT = qml-private qmlmodels-private diff --git a/src/imports/labsmodels/plugin.cpp b/src/imports/labsmodels/plugin.cpp index feb4f3ba0a..ab5e0023a6 100644 --- a/src/imports/labsmodels/plugin.cpp +++ b/src/imports/labsmodels/plugin.cpp @@ -50,6 +50,8 @@ #include "qqmldelegatecomponent_p.h" #endif +extern void qml_register_types_Qt_labs_qmlmodels(); + QT_BEGIN_NAMESPACE /*! @@ -74,7 +76,11 @@ class QtQmlLabsModelsPlugin : public QQmlEngineExtensionPlugin Q_OBJECT Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid) public: - QtQmlLabsModelsPlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) { } + QtQmlLabsModelsPlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) + { + volatile auto registration = &qml_register_types_Qt_labs_qmlmodels; + Q_UNUSED(registration); + } }; //![class decl] diff --git a/src/imports/labsmodels/qqmldelegatecomponent.cpp b/src/imports/labsmodels/qqmldelegatecomponent.cpp index aaf3fea5da..b8eb8049b3 100644 --- a/src/imports/labsmodels/qqmldelegatecomponent.cpp +++ b/src/imports/labsmodels/qqmldelegatecomponent.cpp @@ -250,7 +250,9 @@ QQmlListProperty<QQmlDelegateChoice> QQmlDelegateChooser::choices() QQmlDelegateChooser::choices_append, QQmlDelegateChooser::choices_count, QQmlDelegateChooser::choices_at, - QQmlDelegateChooser::choices_clear); + QQmlDelegateChooser::choices_clear, + QQmlDelegateChooser::choices_replace, + QQmlDelegateChooser::choices_removeLast); } void QQmlDelegateChooser::choices_append(QQmlListProperty<QQmlDelegateChoice> *prop, QQmlDelegateChoice *choice) @@ -282,6 +284,26 @@ void QQmlDelegateChooser::choices_clear(QQmlListProperty<QQmlDelegateChoice> *pr q->delegateChanged(); } +void QQmlDelegateChooser::choices_replace(QQmlListProperty<QQmlDelegateChoice> *prop, int index, + QQmlDelegateChoice *choice) +{ + QQmlDelegateChooser *q = static_cast<QQmlDelegateChooser *>(prop->object); + disconnect(q->m_choices[index], &QQmlDelegateChoice::changed, + q, &QQmlAbstractDelegateComponent::delegateChanged); + q->m_choices[index] = choice; + connect(choice, &QQmlDelegateChoice::changed, q, + &QQmlAbstractDelegateComponent::delegateChanged); + q->delegateChanged(); +} + +void QQmlDelegateChooser::choices_removeLast(QQmlListProperty<QQmlDelegateChoice> *prop) +{ + QQmlDelegateChooser *q = static_cast<QQmlDelegateChooser *>(prop->object); + disconnect(q->m_choices.takeLast(), &QQmlDelegateChoice::changed, + q, &QQmlAbstractDelegateComponent::delegateChanged); + q->delegateChanged(); +} + QQmlComponent *QQmlDelegateChooser::delegate(QQmlAdaptorModel *adaptorModel, int row, int column) const { QVariant v; diff --git a/src/imports/labsmodels/qqmldelegatecomponent_p.h b/src/imports/labsmodels/qqmldelegatecomponent_p.h index 4c39dc0d0a..9655d1baf9 100644 --- a/src/imports/labsmodels/qqmldelegatecomponent_p.h +++ b/src/imports/labsmodels/qqmldelegatecomponent_p.h @@ -69,6 +69,8 @@ class QQmlDelegateChoice : public QObject Q_PROPERTY(QQmlComponent* delegate READ delegate WRITE setDelegate NOTIFY delegateChanged) Q_CLASSINFO("DefaultProperty", "delegate") QML_NAMED_ELEMENT(DelegateChoice) + QML_ADDED_IN_VERSION(1, 0) + public: QVariant roleValue() const; void setRoleValue(const QVariant &roleValue); @@ -106,6 +108,7 @@ class QQmlDelegateChooser : public QQmlAbstractDelegateComponent Q_PROPERTY(QQmlListProperty<QQmlDelegateChoice> choices READ choices CONSTANT) Q_CLASSINFO("DefaultProperty", "choices") QML_NAMED_ELEMENT(DelegateChooser) + QML_ADDED_IN_VERSION(1, 0) public: QString role() const { return m_role; } @@ -116,6 +119,8 @@ public: static int choices_count(QQmlListProperty<QQmlDelegateChoice> *); static QQmlDelegateChoice *choices_at(QQmlListProperty<QQmlDelegateChoice> *, int); static void choices_clear(QQmlListProperty<QQmlDelegateChoice> *); + static void choices_replace(QQmlListProperty<QQmlDelegateChoice> *, int, QQmlDelegateChoice *); + static void choices_removeLast(QQmlListProperty<QQmlDelegateChoice> *); QQmlComponent *delegate(QQmlAdaptorModel *adaptorModel, int row, int column = -1) const override; diff --git a/src/imports/labsmodels/qqmltablemodel.cpp b/src/imports/labsmodels/qqmltablemodel.cpp index b6468d760f..6ba2cecf19 100644 --- a/src/imports/labsmodels/qqmltablemodel.cpp +++ b/src/imports/labsmodels/qqmltablemodel.cpp @@ -644,7 +644,9 @@ QQmlListProperty<QQmlTableModelColumn> QQmlTableModel::columns() &QQmlTableModel::columns_append, &QQmlTableModel::columns_count, &QQmlTableModel::columns_at, - &QQmlTableModel::columns_clear); + &QQmlTableModel::columns_clear, + &QQmlTableModel::columns_replace, + &QQmlTableModel::columns_removeLast); } void QQmlTableModel::columns_append(QQmlListProperty<QQmlTableModelColumn> *property, @@ -674,6 +676,19 @@ void QQmlTableModel::columns_clear(QQmlListProperty<QQmlTableModelColumn> *prope return model->mColumns.clear(); } +void QQmlTableModel::columns_replace(QQmlListProperty<QQmlTableModelColumn> *property, int index, QQmlTableModelColumn *value) +{ + QQmlTableModel *model = static_cast<QQmlTableModel*>(property->object); + if (QQmlTableModelColumn *column = qobject_cast<QQmlTableModelColumn*>(value)) + return model->mColumns.replace(index, column); +} + +void QQmlTableModel::columns_removeLast(QQmlListProperty<QQmlTableModelColumn> *property) +{ + QQmlTableModel *model = static_cast<QQmlTableModel*>(property->object); + model->mColumns.removeLast(); +} + /*! \qmlmethod QModelIndex TableModel::index(int row, int column) diff --git a/src/imports/labsmodels/qqmltablemodel_p.h b/src/imports/labsmodels/qqmltablemodel_p.h index d6e982d19a..ae46cbe35c 100644 --- a/src/imports/labsmodels/qqmltablemodel_p.h +++ b/src/imports/labsmodels/qqmltablemodel_p.h @@ -74,6 +74,7 @@ class QQmlTableModel : public QAbstractTableModel, public QQmlParserStatus Q_INTERFACES(QQmlParserStatus) Q_CLASSINFO("DefaultProperty", "columns") QML_NAMED_ELEMENT(TableModel) + QML_ADDED_IN_VERSION(1, 0) public: QQmlTableModel(QObject *parent = nullptr); @@ -96,6 +97,8 @@ public: static int columns_count(QQmlListProperty<QQmlTableModelColumn> *property); static QQmlTableModelColumn *columns_at(QQmlListProperty<QQmlTableModelColumn> *property, int index); static void columns_clear(QQmlListProperty<QQmlTableModelColumn> *property); + static void columns_replace(QQmlListProperty<QQmlTableModelColumn> *property, int index, QQmlTableModelColumn *value); + static void columns_removeLast(QQmlListProperty<QQmlTableModelColumn> *property); QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override; diff --git a/src/imports/labsmodels/qqmltablemodelcolumn_p.h b/src/imports/labsmodels/qqmltablemodelcolumn_p.h index a18f21ab4f..2860a915cc 100644 --- a/src/imports/labsmodels/qqmltablemodelcolumn_p.h +++ b/src/imports/labsmodels/qqmltablemodelcolumn_p.h @@ -97,6 +97,7 @@ class QQmlTableModelColumn : public QObject Q_PROPERTY(QJSValue sizeHint READ sizeHint WRITE setSizeHint NOTIFY sizeHintChanged FINAL) Q_PROPERTY(QJSValue setSizeHint READ getSetSizeHint WRITE setSetSizeHint NOTIFY setSizeHintChanged FINAL) QML_NAMED_ELEMENT(TableModelColumn) + QML_ADDED_IN_VERSION(1, 0) public: QQmlTableModelColumn(QObject *parent = nullptr); diff --git a/src/imports/layouts/layouts.pro b/src/imports/layouts/layouts.pro index c52046094e..1ae269da32 100644 --- a/src/imports/layouts/layouts.pro +++ b/src/imports/layouts/layouts.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = qquicklayoutsplugin TARGETPATH = QtQuick/Layouts -IMPORT_VERSION = 1.15 +QML_IMPORT_VERSION = $$QT_VERSION QT *= qml-private quick-private gui-private core-private diff --git a/src/imports/layouts/plugin.cpp b/src/imports/layouts/plugin.cpp index c302b79164..af270c1732 100644 --- a/src/imports/layouts/plugin.cpp +++ b/src/imports/layouts/plugin.cpp @@ -42,6 +42,8 @@ #include "qquicklinearlayout_p.h" #include "qquickstacklayout_p.h" +extern void qml_register_types_QtQuick_Layouts(); + QT_BEGIN_NAMESPACE //![class decl] @@ -52,6 +54,8 @@ class QtQuickLayoutsPlugin : public QQmlEngineExtensionPlugin public: QtQuickLayoutsPlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) { + volatile auto registration = &qml_register_types_QtQuick_Layouts; + Q_UNUSED(registration); } }; //![class decl] diff --git a/src/imports/layouts/qquicklayout.cpp b/src/imports/layouts/qquicklayout.cpp index 1ca4056ba9..33c27bd928 100644 --- a/src/imports/layouts/qquicklayout.cpp +++ b/src/imports/layouts/qquicklayout.cpp @@ -700,8 +700,10 @@ QQuickItem *QQuickLayoutAttached::item() const QQuickLayout::QQuickLayout(QQuickLayoutPrivate &dd, QQuickItem *parent) - : QQuickItem(dd, parent), - m_dirty(false) + : QQuickItem(dd, parent) + , m_dirty(false) + , m_inUpdatePolish(false) + , m_polishInsideUpdatePolish(0) { } @@ -728,7 +730,9 @@ QQuickLayoutAttached *QQuickLayout::qmlAttachedProperties(QObject *object) void QQuickLayout::updatePolish() { + m_inUpdatePolish = true; rearrange(QSizeF(width(), height())); + m_inUpdatePolish = false; } void QQuickLayout::componentComplete() @@ -749,7 +753,18 @@ void QQuickLayout::invalidate(QQuickItem * /*childItem*/) if (!qobject_cast<QQuickLayout *>(parentItem())) { quickLayoutDebug() << "QQuickLayout::invalidate(), polish()"; - polish(); + + if (m_inUpdatePolish) + ++m_polishInsideUpdatePolish; + else + m_polishInsideUpdatePolish = 0; + + if (m_polishInsideUpdatePolish <= 2) + // allow at most two consecutive loops in order to respond to height-for-width + // (e.g QQuickText changes implicitHeight when its width gets changed) + polish(); + else + qWarning() << "Qt Quick Layouts: Polish loop detected. Aborting after two iterations."; } } diff --git a/src/imports/layouts/qquicklayout_p.h b/src/imports/layouts/qquicklayout_p.h index cb46c41e6c..a2594f4274 100644 --- a/src/imports/layouts/qquicklayout_p.h +++ b/src/imports/layouts/qquicklayout_p.h @@ -62,6 +62,7 @@ class QQuickLayout : public QQuickItem, public QQuickItemChangeListener { Q_OBJECT QML_NAMED_ELEMENT(Layout) + QML_ADDED_IN_VERSION(1, 0) QML_UNCREATABLE("Do not create objects of type Layout.") QML_ATTACHED(QQuickLayoutAttached) @@ -123,7 +124,9 @@ protected slots: void invalidateSenderItem(); private: - bool m_dirty; + unsigned m_dirty : 1; + unsigned m_inUpdatePolish : 1; + unsigned m_polishInsideUpdatePolish : 2; Q_DECLARE_PRIVATE(QQuickLayout) diff --git a/src/imports/layouts/qquicklinearlayout.cpp b/src/imports/layouts/qquicklinearlayout.cpp index 344ea7237c..e47eba4164 100644 --- a/src/imports/layouts/qquicklinearlayout.cpp +++ b/src/imports/layouts/qquicklinearlayout.cpp @@ -469,6 +469,16 @@ void QQuickGridLayoutBase::rearrange(const QSizeF &size) if (!isReady()) return; + const auto refCounter = qScopeGuard([&d] { + --(d->m_recurRearrangeCounter); + }); + if (d->m_recurRearrangeCounter++ == 2) { + // allow a recursive depth of two in order to respond to height-for-width + // (e.g QQuickText changes implicitHeight when its width gets changed) + qWarning() << "Qt Quick Layouts: Detected recursive rearrange. Aborting after two iterations."; + return; + } + d->m_rearranging = true; quickLayoutDebug() << objectName() << "QQuickGridLayoutBase::rearrange()" << size; Qt::LayoutDirection visualDir = effectiveLayoutDirection(); diff --git a/src/imports/layouts/qquicklinearlayout_p.h b/src/imports/layouts/qquicklinearlayout_p.h index 634e51a048..1780ba8807 100644 --- a/src/imports/layouts/qquicklinearlayout_p.h +++ b/src/imports/layouts/qquicklinearlayout_p.h @@ -56,9 +56,10 @@ class QQuickGridLayoutBase : public QQuickLayout { Q_OBJECT - Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1) + Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection + NOTIFY layoutDirectionChanged REVISION(1, 1)) QML_ANONYMOUS - QML_ADDED_IN_MINOR_VERSION(1) + QML_ADDED_IN_VERSION(1, 1) public: @@ -92,7 +93,7 @@ protected: virtual void insertLayoutItems() {} signals: - Q_REVISION(1) void layoutDirectionChanged(); + Q_REVISION(1, 1) void layoutDirectionChanged(); private: void removeGridItem(QGridLayoutItem *gridItem); @@ -106,7 +107,8 @@ class QQuickGridLayoutBasePrivate : public QQuickLayoutPrivate Q_DECLARE_PUBLIC(QQuickGridLayoutBase) public: - QQuickGridLayoutBasePrivate() : m_rearranging(false) + QQuickGridLayoutBasePrivate() : m_recurRearrangeCounter(0) + , m_rearranging(false) , m_updateAfterRearrange(false) , m_layoutDirection(Qt::LeftToRight) {} @@ -119,6 +121,7 @@ public: QQuickGridLayoutEngine engine; Qt::Orientation orientation; + unsigned m_recurRearrangeCounter : 2; unsigned m_rearranging : 1; unsigned m_updateAfterRearrange : 1; QVector<QQuickItem *> m_invalidateAfterRearrange; @@ -143,6 +146,7 @@ class QQuickGridLayout : public QQuickGridLayoutBase Q_PROPERTY(int rows READ rows WRITE setRows NOTIFY rowsChanged) Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged) QML_NAMED_ELEMENT(GridLayout) + QML_ADDED_IN_VERSION(1, 0) public: explicit QQuickGridLayout(QQuickItem *parent = 0); qreal columnSpacing() const; @@ -227,6 +231,7 @@ class QQuickRowLayout : public QQuickLinearLayout { Q_OBJECT QML_NAMED_ELEMENT(RowLayout) + QML_ADDED_IN_VERSION(1, 0) public: explicit QQuickRowLayout(QQuickItem *parent = 0) @@ -243,6 +248,7 @@ class QQuickColumnLayout : public QQuickLinearLayout { Q_OBJECT QML_NAMED_ELEMENT(ColumnLayout) + QML_ADDED_IN_VERSION(1, 0) public: explicit QQuickColumnLayout(QQuickItem *parent = 0) diff --git a/src/imports/layouts/qquickstacklayout_p.h b/src/imports/layouts/qquickstacklayout_p.h index 537d54900f..07f9e48178 100644 --- a/src/imports/layouts/qquickstacklayout_p.h +++ b/src/imports/layouts/qquickstacklayout_p.h @@ -52,7 +52,7 @@ class QQuickStackLayout : public QQuickLayout Q_PROPERTY(int count READ count NOTIFY countChanged) Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) QML_NAMED_ELEMENT(StackLayout) - QML_ADDED_IN_MINOR_VERSION(3) + QML_ADDED_IN_VERSION(1, 3) public: explicit QQuickStackLayout(QQuickItem *parent = 0); diff --git a/src/imports/localstorage/localstorage.pro b/src/imports/localstorage/localstorage.pro index d189808f49..6dff4862c7 100644 --- a/src/imports/localstorage/localstorage.pro +++ b/src/imports/localstorage/localstorage.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = qmllocalstorageplugin TARGETPATH = QtQuick/LocalStorage -IMPORT_VERSION = 2.15 +QML_IMPORT_VERSION = $$QT_VERSION QT = sql qml-private core-private diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp index ae9f37784d..e488b3d43c 100644 --- a/src/imports/localstorage/plugin.cpp +++ b/src/imports/localstorage/plugin.cpp @@ -42,6 +42,8 @@ #include <QtQml/qqmlextensionplugin.h> #include <QtQml/qqml.h> +extern void qml_register_types_QtQuick_LocalStorage(); + QT_BEGIN_NAMESPACE class QQmlLocalStoragePlugin : public QQmlEngineExtensionPlugin @@ -52,6 +54,8 @@ class QQmlLocalStoragePlugin : public QQmlEngineExtensionPlugin public: QQmlLocalStoragePlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) { + volatile auto registration = &qml_register_types_QtQuick_LocalStorage; + Q_UNUSED(registration); } }; diff --git a/src/imports/localstorage/qquicklocalstorage_p.h b/src/imports/localstorage/qquicklocalstorage_p.h index d2ebc85ce9..f90d6bad28 100644 --- a/src/imports/localstorage/qquicklocalstorage_p.h +++ b/src/imports/localstorage/qquicklocalstorage_p.h @@ -61,6 +61,7 @@ class QQuickLocalStorage : public QObject { Q_OBJECT QML_NAMED_ELEMENT(LocalStorage) + QML_ADDED_IN_VERSION(2, 0) QML_SINGLETON public: diff --git a/src/imports/models/models.pro b/src/imports/models/models.pro index ab3f4e3e15..9a22049068 100644 --- a/src/imports/models/models.pro +++ b/src/imports/models/models.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = modelsplugin TARGETPATH = QtQml/Models -IMPORT_VERSION = 2.15 +QML_IMPORT_VERSION = $$QT_VERSION SOURCES += \ plugin.cpp diff --git a/src/imports/models/plugin.cpp b/src/imports/models/plugin.cpp index 4aa9f27766..c15866cf05 100644 --- a/src/imports/models/plugin.cpp +++ b/src/imports/models/plugin.cpp @@ -37,17 +37,11 @@ ** ****************************************************************************/ -#include <QtQmlModels/private/qqmlobjectmodel_p.h> - +#include <QtQmlModels/private/qtqmlmodelsglobal_p.h> #include <QtQml/qqmlextensionplugin.h> -#include <QtQml/qqml.h> - -#include <QtCore/qloggingcategory.h> QT_BEGIN_NAMESPACE -Q_LOGGING_CATEGORY(qmlModelsPlugin, "qt.qmlModelsPlugin") - /*! \qmlmodule QtQml.Models 2.\QtMinorVersion \title Qt QML Models QML Types @@ -92,13 +86,8 @@ class QtQmlModelsPlugin : public QQmlEngineExtensionPlugin public: QtQmlModelsPlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) { - if (qmlModelsPlugin().isDebugEnabled()) { - // Superficial debug message that causes the dependency between QtQmlWorkerScript - // and the workerscript plugin to be retained. - // As qCDebug() can be a noop, retrieve the className in a separate step. - const QString className = QQmlObjectModel::staticMetaObject.className(); - qCDebug(qmlModelsPlugin) << "Loading QmlModels plugin:" << className; - } + volatile auto registration = &qml_register_types_QtQml_Models; + Q_UNUSED(registration); } }; //![class decl] diff --git a/src/imports/particles/particles.pro b/src/imports/particles/particles.pro index 50e1837544..c0f2f990b5 100644 --- a/src/imports/particles/particles.pro +++ b/src/imports/particles/particles.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = particlesplugin TARGETPATH = QtQuick/Particles -IMPORT_VERSION = 2.15 +QML_IMPORT_VERSION = $$QT_VERSION SOURCES += \ plugin.cpp diff --git a/src/imports/particles/plugin.cpp b/src/imports/particles/plugin.cpp index 4f319db9f1..6629a660af 100644 --- a/src/imports/particles/plugin.cpp +++ b/src/imports/particles/plugin.cpp @@ -50,7 +50,12 @@ class QtQuick2ParticlesPlugin : public QQmlExtensionPlugin Q_OBJECT Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: - QtQuick2ParticlesPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { } + QtQuick2ParticlesPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) + { + volatile auto registration = &qml_register_types_QtQuick_Particles; + Q_UNUSED(registration); + } + void registerTypes(const char *uri) override { Q_UNUSED(uri); diff --git a/src/imports/qtqml/plugin.cpp b/src/imports/qtqml/plugin.cpp index ec08992355..a32d86eeb1 100644 --- a/src/imports/qtqml/plugin.cpp +++ b/src/imports/qtqml/plugin.cpp @@ -37,10 +37,8 @@ ** ****************************************************************************/ +#include <QtQml/private/qtqmlglobal_p.h> #include <QtQml/qqmlextensionplugin.h> -#include <QtQml/private/qqmlengine_p.h> -#include <QtQml/private/qqmlcomponentattached_p.h> -#include <QtQml/private/qqmlbind_p.h> QT_BEGIN_NAMESPACE @@ -66,7 +64,11 @@ class QtQmlPlugin : public QQmlEngineExtensionPlugin Q_OBJECT Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid) public: - QtQmlPlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) {} + QtQmlPlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) + { + volatile auto registration = &qml_register_types_QtQml; + Q_UNUSED(registration); + } }; //![class decl] diff --git a/src/imports/qtqml/qtqml.pro b/src/imports/qtqml/qtqml.pro index 0211844b14..eac19954b6 100644 --- a/src/imports/qtqml/qtqml.pro +++ b/src/imports/qtqml/qtqml.pro @@ -1,7 +1,7 @@ TARGETPATH = QtQml CXX_MODULE = qml TARGET = qmlplugin -IMPORT_VERSION = 2.15 +QML_IMPORT_VERSION = $$QT_VERSION SOURCES += \ plugin.cpp diff --git a/src/imports/qtquick2/plugin.cpp b/src/imports/qtquick2/plugin.cpp index 98056aa551..dde0b7207a 100644 --- a/src/imports/qtquick2/plugin.cpp +++ b/src/imports/qtquick2/plugin.cpp @@ -50,7 +50,12 @@ class QtQuick2Plugin : public QQmlExtensionPlugin Q_OBJECT Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: - QtQuick2Plugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { } + QtQuick2Plugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) + { + volatile auto registration = &qml_register_types_QtQuick; + Q_UNUSED(registration); + } + void registerTypes(const char *uri) override { Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick")); @@ -59,10 +64,11 @@ public: QQmlQtQuick2Module::defineModule(); } - ~QtQuick2Plugin() override + void unregisterTypes() override { if (moduleDefined) QQmlQtQuick2Module::undefineModule(); + moduleDefined = false; } bool moduleDefined = false; diff --git a/src/imports/qtquick2/qtquick2.pro b/src/imports/qtquick2/qtquick2.pro index f89518c054..35430d0638 100644 --- a/src/imports/qtquick2/qtquick2.pro +++ b/src/imports/qtquick2/qtquick2.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = qtquick2plugin TARGETPATH = QtQuick -IMPORT_VERSION = 2.15 +QML_IMPORT_VERSION = $$QT_VERSION SOURCES += \ plugin.cpp diff --git a/src/imports/settings/plugin.cpp b/src/imports/settings/plugin.cpp index 24ff43ea6f..e8e640412b 100644 --- a/src/imports/settings/plugin.cpp +++ b/src/imports/settings/plugin.cpp @@ -42,6 +42,8 @@ #include "qqmlsettings_p.h" +extern void qml_register_types_Qt_labs_settings(); + QT_BEGIN_NAMESPACE class QmlSettingsPlugin : public QQmlEngineExtensionPlugin @@ -50,7 +52,11 @@ class QmlSettingsPlugin : public QQmlEngineExtensionPlugin Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid) public: - QmlSettingsPlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) {} + QmlSettingsPlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) + { + volatile auto registration = &qml_register_types_Qt_labs_settings; + Q_UNUSED(registration); + } }; QT_END_NAMESPACE diff --git a/src/imports/settings/qqmlsettings_p.h b/src/imports/settings/qqmlsettings_p.h index 3f1b83f541..100d0136ff 100644 --- a/src/imports/settings/qqmlsettings_p.h +++ b/src/imports/settings/qqmlsettings_p.h @@ -67,6 +67,7 @@ class QQmlSettings : public QObject, public QQmlParserStatus Q_PROPERTY(QString category READ category WRITE setCategory FINAL) Q_PROPERTY(QString fileName READ fileName WRITE setFileName FINAL) QML_NAMED_ELEMENT(Settings) + QML_ADDED_IN_VERSION(1, 0) public: explicit QQmlSettings(QObject *parent = 0); diff --git a/src/imports/settings/settings.pro b/src/imports/settings/settings.pro index d8062a2e55..6fd8b8cddd 100644 --- a/src/imports/settings/settings.pro +++ b/src/imports/settings/settings.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = qmlsettingsplugin TARGETPATH = Qt/labs/settings -IMPORT_VERSION = 1.1 +QML_IMPORT_VERSION = $$QT_VERSION QT = core qml diff --git a/src/imports/shapes/plugin.cpp b/src/imports/shapes/plugin.cpp index 3855a93fc7..48eecbd8f1 100644 --- a/src/imports/shapes/plugin.cpp +++ b/src/imports/shapes/plugin.cpp @@ -52,6 +52,8 @@ public: QmlShapesPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { + volatile auto registration = &qml_register_types_QtQuick_Shapes; + Q_UNUSED(registration); } void registerTypes(const char *uri) override diff --git a/src/imports/shapes/shapes.pro b/src/imports/shapes/shapes.pro index bb02dbf08f..b5f75343d7 100644 --- a/src/imports/shapes/shapes.pro +++ b/src/imports/shapes/shapes.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = qmlshapesplugin TARGETPATH = QtQuick/Shapes -IMPORT_VERSION = 1.15 +QML_IMPORT_VERSION = $$QT_VERSION QT = core gui-private qml quick-private quickshapes-private diff --git a/src/imports/sharedimage/plugin.cpp b/src/imports/sharedimage/plugin.cpp index 237fa64c61..d7c2ef8d17 100644 --- a/src/imports/sharedimage/plugin.cpp +++ b/src/imports/sharedimage/plugin.cpp @@ -99,6 +99,8 @@ The shared image module does not provide any directly usable QML types. */ +extern void qml_register_types_Qt_labs_sharedimage(); + QT_BEGIN_NAMESPACE class QtQuickSharedImagePlugin : public QQmlEngineExtensionPlugin @@ -106,7 +108,11 @@ class QtQuickSharedImagePlugin : public QQmlEngineExtensionPlugin Q_OBJECT Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid) public: - QtQuickSharedImagePlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) {} + QtQuickSharedImagePlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) + { + volatile auto registration = &qml_register_types_Qt_labs_sharedimage; + Q_UNUSED(registration); + } void initializeEngine(QQmlEngine *engine, const char *uri) override { diff --git a/src/imports/sharedimage/qsharedimageloader_p.h b/src/imports/sharedimage/qsharedimageloader_p.h index 4b0e989c29..ce10d0d72c 100644 --- a/src/imports/sharedimage/qsharedimageloader_p.h +++ b/src/imports/sharedimage/qsharedimageloader_p.h @@ -43,6 +43,7 @@ #include <QImage> #include <QVariant> #include <QLoggingCategory> +#include <qqml.h> QT_BEGIN_NAMESPACE @@ -55,6 +56,10 @@ class QSharedImageLoader : public QObject Q_OBJECT Q_DECLARE_PRIVATE(QSharedImageLoader) + // We need to provide some type, in order to mention the 1.0 version. + QML_ANONYMOUS + QML_ADDED_IN_VERSION(1, 0) + public: typedef QVector<QVariant> ImageParameters; diff --git a/src/imports/sharedimage/sharedimage.pro b/src/imports/sharedimage/sharedimage.pro index 8ab4f10405..cee4c3465e 100644 --- a/src/imports/sharedimage/sharedimage.pro +++ b/src/imports/sharedimage/sharedimage.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = sharedimageplugin TARGETPATH = Qt/labs/sharedimage -IMPORT_VERSION = 1.0 +QML_IMPORT_VERSION = $$QT_VERSION QT *= quick-private qml gui-private core-private diff --git a/src/imports/statemachine/childrenprivate.h b/src/imports/statemachine/childrenprivate.h index 57cda1c796..2dcecd6531 100644 --- a/src/imports/statemachine/childrenprivate.h +++ b/src/imports/statemachine/childrenprivate.h @@ -46,54 +46,142 @@ #include <QQmlInfo> #include <QQmlListProperty> -template <class T> -class ChildrenPrivate +enum class ChildrenMode { + None = 0x0, + State = 0x1, + Transition = 0x2, + StateOrTransition = State | Transition +}; + +template<typename T> +static T *parentObject(QQmlListProperty<QObject> *prop) { return static_cast<T *>(prop->object); } + +template<class T, ChildrenMode Mode> +struct ParentHandler { -public: - ChildrenPrivate() - {} + static bool unparentItem(QQmlListProperty<QObject> *prop, QObject *oldItem); + static bool parentItem(QQmlListProperty<QObject> *prop, QObject *item); +}; - static void append(QQmlListProperty<QObject> *prop, QObject *item) +template<class T> +struct ParentHandler<T, ChildrenMode::None> +{ + static bool unparentItem(QQmlListProperty<QObject> *, QObject *) { return true; } + static bool parentItem(QQmlListProperty<QObject> *, QObject *) { return true; } +}; + +template<class T> +struct ParentHandler<T, ChildrenMode::State> +{ + static bool parentItem(QQmlListProperty<QObject> *prop, QObject *item) + { + if (QAbstractState *state = qobject_cast<QAbstractState *>(item)) { + state->setParent(parentObject<T>(prop)); + return true; + } + return false; + } + + static bool unparentItem(QQmlListProperty<QObject> *, QObject *oldItem) + { + if (QAbstractState *state = qobject_cast<QAbstractState *>(oldItem)) { + state->setParent(nullptr); + return true; + } + return false; + } +}; + +template<class T> +struct ParentHandler<T, ChildrenMode::Transition> +{ + static bool parentItem(QQmlListProperty<QObject> *prop, QObject *item) { - QAbstractState *state = qobject_cast<QAbstractState*>(item); - if (state) { - item->setParent(prop->object); - } else { - QAbstractTransition *trans = qobject_cast<QAbstractTransition*>(item); - if (trans) - static_cast<T *>(prop->object)->addTransition(trans); + if (QAbstractTransition *trans = qobject_cast<QAbstractTransition *>(item)) { + parentObject<T>(prop)->addTransition(trans); + return true; } - static_cast<ChildrenPrivate<T>*>(prop->data)->children.append(item); - emit static_cast<T *>(prop->object)->childrenChanged(); + return false; } - static void appendNoTransition(QQmlListProperty<QObject> *prop, QObject *item) + static bool unparentItem(QQmlListProperty<QObject> *prop, QObject *oldItem) { - QAbstractState *state = qobject_cast<QAbstractState*>(item); - if (state) { - item->setParent(prop->object); + if (QAbstractTransition *trans = qobject_cast<QAbstractTransition *>(oldItem)) { + parentObject<T>(prop)->removeTransition(trans); + return true; } - static_cast<ChildrenPrivate<T>*>(prop->data)->children.append(item); - emit static_cast<T *>(prop->object)->childrenChanged(); + return false; + } +}; + +template<class T> +struct ParentHandler<T, ChildrenMode::StateOrTransition> +{ + static bool parentItem(QQmlListProperty<QObject> *prop, QObject *oldItem) + { + return ParentHandler<T, ChildrenMode::State>::parentItem(prop, oldItem) + || ParentHandler<T, ChildrenMode::Transition>::parentItem(prop, oldItem); + } + + static bool unparentItem(QQmlListProperty<QObject> *prop, QObject *oldItem) + { + return ParentHandler<T, ChildrenMode::State>::unparentItem(prop, oldItem) + || ParentHandler<T, ChildrenMode::Transition>::unparentItem(prop, oldItem); + } +}; + +template <class T, ChildrenMode Mode> +class ChildrenPrivate +{ +public: + static void append(QQmlListProperty<QObject> *prop, QObject *item) + { + Handler::parentItem(prop, item); + static_cast<Self *>(prop->data)->children.append(item); + emit parentObject<T>(prop)->childrenChanged(); } static int count(QQmlListProperty<QObject> *prop) { - return static_cast<ChildrenPrivate<T>*>(prop->data)->children.count(); + return static_cast<Self *>(prop->data)->children.count(); } static QObject *at(QQmlListProperty<QObject> *prop, int index) { - return static_cast<ChildrenPrivate<T>*>(prop->data)->children.at(index); + return static_cast<Self *>(prop->data)->children.at(index); } static void clear(QQmlListProperty<QObject> *prop) { - static_cast<ChildrenPrivate<T>*>(prop->data)->children.clear(); - emit static_cast<T *>(prop->object)->childrenChanged(); + auto &children = static_cast<Self *>(prop->data)->children; + for (QObject *oldItem : qAsConst(children)) + Handler::unparentItem(prop, oldItem); + + children.clear(); + emit parentObject<T>(prop)->childrenChanged(); + } + + static void replace(QQmlListProperty<QObject> *prop, int index, QObject *item) + { + auto &children = static_cast<Self *>(prop->data)->children; + + Handler::unparentItem(prop, children.at(index)); + Handler::parentItem(prop, item); + + children.replace(index, item); + emit parentObject<T>(prop)->childrenChanged(); + } + + static void removeLast(QQmlListProperty<QObject> *prop) + { + Handler::unparentItem(prop, static_cast<Self *>(prop->data)->children.takeLast()); + emit parentObject<T>(prop)->childrenChanged(); } private: + using Self = ChildrenPrivate<T, Mode>; + using Handler = ParentHandler<T, Mode>; + QList<QObject *> children; }; diff --git a/src/imports/statemachine/finalstate.cpp b/src/imports/statemachine/finalstate.cpp index 54dcc82bae..4d4c6b2cc7 100644 --- a/src/imports/statemachine/finalstate.cpp +++ b/src/imports/statemachine/finalstate.cpp @@ -50,7 +50,9 @@ FinalState::FinalState(QState *parent) QQmlListProperty<QObject> FinalState::children() { - return QQmlListProperty<QObject>(this, &m_children, m_children.appendNoTransition, m_children.count, m_children.at, m_children.clear); + return QQmlListProperty<QObject>(this, &m_children, + m_children.append, m_children.count, m_children.at, + m_children.clear, m_children.replace, m_children.removeLast); } /*! diff --git a/src/imports/statemachine/finalstate.h b/src/imports/statemachine/finalstate.h index 9cdbb51584..fef0e9c092 100644 --- a/src/imports/statemachine/finalstate.h +++ b/src/imports/statemachine/finalstate.h @@ -56,6 +56,7 @@ class FinalState : public QFinalState Q_PROPERTY(QQmlListProperty<QObject> children READ children NOTIFY childrenChanged) Q_CLASSINFO("DefaultProperty", "children") QML_ELEMENT + QML_ADDED_IN_VERSION(1, 0) public: explicit FinalState(QState *parent = 0); @@ -66,7 +67,7 @@ Q_SIGNALS: void childrenChanged(); private: - ChildrenPrivate<FinalState> m_children; + ChildrenPrivate<FinalState, ChildrenMode::State> m_children; }; QT_END_NAMESPACE diff --git a/src/imports/statemachine/plugin.cpp b/src/imports/statemachine/plugin.cpp index 4c991994f3..c370504029 100644 --- a/src/imports/statemachine/plugin.cpp +++ b/src/imports/statemachine/plugin.cpp @@ -48,6 +48,8 @@ #include <QQmlExtensionPlugin> #include <qqml.h> +extern void qml_register_types_QtQml_StateMachine(); + QT_BEGIN_NAMESPACE class QtQmlStateMachinePlugin : public QQmlEngineExtensionPlugin @@ -56,7 +58,11 @@ class QtQmlStateMachinePlugin : public QQmlEngineExtensionPlugin Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid) public: - QtQmlStateMachinePlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) { } + QtQmlStateMachinePlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) + { + volatile auto registration = &qml_register_types_QtQml_StateMachine; + Q_UNUSED(registration); + } }; QT_END_NAMESPACE diff --git a/src/imports/statemachine/signaltransition.h b/src/imports/statemachine/signaltransition.h index 748e230b3e..4d73368eb0 100644 --- a/src/imports/statemachine/signaltransition.h +++ b/src/imports/statemachine/signaltransition.h @@ -58,6 +58,7 @@ class SignalTransition : public QSignalTransition, public QQmlParserStatus Q_PROPERTY(QJSValue signal READ signal WRITE setSignal NOTIFY qmlSignalChanged) Q_PROPERTY(QQmlScriptString guard READ guard WRITE setGuard NOTIFY guardChanged) QML_ELEMENT + QML_ADDED_IN_VERSION(1, 0) public: explicit SignalTransition(QState *parent = nullptr); diff --git a/src/imports/statemachine/state.cpp b/src/imports/statemachine/state.cpp index af76087256..10530c2985 100644 --- a/src/imports/statemachine/state.cpp +++ b/src/imports/statemachine/state.cpp @@ -61,7 +61,9 @@ void State::componentComplete() QQmlListProperty<QObject> State::children() { - return QQmlListProperty<QObject>(this, &m_children, m_children.append, m_children.count, m_children.at, m_children.clear); + return QQmlListProperty<QObject>(this, &m_children, + m_children.append, m_children.count, m_children.at, + m_children.clear, m_children.replace, m_children.removeLast); } /*! diff --git a/src/imports/statemachine/state.h b/src/imports/statemachine/state.h index 4b17ea0e5f..8cb454f3cf 100644 --- a/src/imports/statemachine/state.h +++ b/src/imports/statemachine/state.h @@ -56,6 +56,7 @@ class State : public QState, public QQmlParserStatus Q_PROPERTY(QQmlListProperty<QObject> children READ children NOTIFY childrenChanged) Q_CLASSINFO("DefaultProperty", "children") QML_ELEMENT + QML_ADDED_IN_VERSION(1, 0) public: explicit State(QState *parent = 0); @@ -69,7 +70,7 @@ Q_SIGNALS: void childrenChanged(); private: - ChildrenPrivate<State> m_children; + ChildrenPrivate<State, ChildrenMode::StateOrTransition> m_children; }; QT_END_NAMESPACE diff --git a/src/imports/statemachine/statemachine.cpp b/src/imports/statemachine/statemachine.cpp index a983644018..bdad2e6bde 100644 --- a/src/imports/statemachine/statemachine.cpp +++ b/src/imports/statemachine/statemachine.cpp @@ -90,7 +90,9 @@ void StateMachine::componentComplete() QQmlListProperty<QObject> StateMachine::children() { - return QQmlListProperty<QObject>(this, &m_children, m_children.append, m_children.count, m_children.at, m_children.clear); + return QQmlListProperty<QObject>(this, &m_children, + m_children.append, m_children.count, m_children.at, + m_children.clear, m_children.replace, m_children.removeLast); } /*! diff --git a/src/imports/statemachine/statemachine.h b/src/imports/statemachine/statemachine.h index 04894477b3..85ac4cf26b 100644 --- a/src/imports/statemachine/statemachine.h +++ b/src/imports/statemachine/statemachine.h @@ -60,6 +60,7 @@ class StateMachine : public QStateMachine, public QQmlParserStatus Q_CLASSINFO("DefaultProperty", "children") QML_ELEMENT + QML_ADDED_IN_VERSION(1, 0) public: explicit StateMachine(QObject *parent = 0); @@ -82,7 +83,7 @@ Q_SIGNALS: void qmlRunningChanged(); private: - ChildrenPrivate<StateMachine> m_children; + ChildrenPrivate<StateMachine, ChildrenMode::StateOrTransition> m_children; bool m_completed; bool m_running; }; diff --git a/src/imports/statemachine/statemachine.pro b/src/imports/statemachine/statemachine.pro index b17ec6140d..cff81c2416 100644 --- a/src/imports/statemachine/statemachine.pro +++ b/src/imports/statemachine/statemachine.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = qtqmlstatemachine TARGETPATH = QtQml/StateMachine -IMPORT_VERSION = 1.15 +QML_IMPORT_VERSION = $$QT_VERSION QT = core-private qml-private diff --git a/src/imports/statemachine/statemachineforeign.h b/src/imports/statemachine/statemachineforeign.h index 363c9d0e31..7543d55fdf 100644 --- a/src/imports/statemachine/statemachineforeign.h +++ b/src/imports/statemachine/statemachineforeign.h @@ -51,6 +51,7 @@ struct QHistoryStateForeign Q_GADGET QML_FOREIGN(QHistoryState) QML_NAMED_ELEMENT(HistoryState) + QML_ADDED_IN_VERSION(1, 0) }; struct QStateForeign @@ -58,6 +59,7 @@ struct QStateForeign Q_GADGET QML_FOREIGN(QState) QML_NAMED_ELEMENT(QState) + QML_ADDED_IN_VERSION(1, 0) QML_UNCREATABLE("Don't use this, use State instead.") }; @@ -66,6 +68,7 @@ struct QAbstractStateForeign Q_GADGET QML_FOREIGN(QAbstractState) QML_NAMED_ELEMENT(QAbstractState) + QML_ADDED_IN_VERSION(1, 0) QML_UNCREATABLE("Don't use this, use State instead.") }; @@ -74,6 +77,7 @@ struct QSignalTransitionForeign Q_GADGET QML_FOREIGN(QSignalTransition) QML_NAMED_ELEMENT(QSignalTransition) + QML_ADDED_IN_VERSION(1, 0) QML_UNCREATABLE("Don't use this, use SignalTransition instead.") }; diff --git a/src/imports/statemachine/timeouttransition.h b/src/imports/statemachine/timeouttransition.h index cc3a22e0e5..3d056b5e41 100644 --- a/src/imports/statemachine/timeouttransition.h +++ b/src/imports/statemachine/timeouttransition.h @@ -53,6 +53,7 @@ class TimeoutTransition : public QSignalTransition, public QQmlParserStatus Q_PROPERTY(int timeout READ timeout WRITE setTimeout NOTIFY timeoutChanged) Q_INTERFACES(QQmlParserStatus) QML_ELEMENT + QML_ADDED_IN_VERSION(1, 0) public: TimeoutTransition(QState *parent = nullptr); diff --git a/src/imports/testlib/TestCase.qml b/src/imports/testlib/TestCase.qml index 20c5ce6418..380b7e38d7 100644 --- a/src/imports/testlib/TestCase.qml +++ b/src/imports/testlib/TestCase.qml @@ -198,7 +198,7 @@ import Qt.test.qtestroot 1.0 } \endcode - The mousePress(), mouseRelease(), mouseClick(), mouseDoubleClick(), mouseDoubleClickSequence() + The mousePress(), mouseRelease(), mouseClick(), mouseDoubleClickSequence() and mouseMove() methods can be used to simulate mouse events in a similar fashion. @@ -1331,7 +1331,7 @@ Item { If \a item is obscured by another item, or a child of \a item occupies that position, then the event will be delivered to the other item instead. - \sa mouseRelease(), mouseClick(), mouseDoubleClick(), mouseDoubleClickSequence(), mouseMove(), mouseDrag(), mouseWheel() + \sa mouseRelease(), mouseClick(), mouseDoubleClickSequence(), mouseMove(), mouseDrag(), mouseWheel() */ function mousePress(item, x, y, button, modifiers, delay) { if (!qtest_verifyItem(item, "mousePress")) @@ -1365,7 +1365,7 @@ Item { If \a item is obscured by another item, or a child of \a item occupies that position, then the event will be delivered to the other item instead. - \sa mousePress(), mouseClick(), mouseDoubleClick(), mouseDoubleClickSequence(), mouseMove(), mouseDrag(), mouseWheel() + \sa mousePress(), mouseClick(), mouseDoubleClickSequence(), mouseMove(), mouseDrag(), mouseWheel() */ function mouseRelease(item, x, y, button, modifiers, delay) { if (!qtest_verifyItem(item, "mouseRelease")) @@ -1398,7 +1398,7 @@ Item { If \a item is obscured by another item, or a child of \a item occupies that position, then the event will be delivered to the other item instead. - \sa mousePress(), mouseClick(), mouseDoubleClick(), mouseDoubleClickSequence(), mouseMove(), mouseRelease(), mouseWheel() + \sa mousePress(), mouseClick(), mouseDoubleClickSequence(), mouseMove(), mouseRelease(), mouseWheel() */ function mouseDrag(item, x, y, dx, dy, button, modifiers, delay) { if (!qtest_verifyItem(item, "mouseDrag")) @@ -1453,7 +1453,7 @@ Item { If \a item is obscured by another item, or a child of \a item occupies that position, then the event will be delivered to the other item instead. - \sa mousePress(), mouseRelease(), mouseDoubleClick(), mouseDoubleClickSequence(), mouseMove(), mouseDrag(), mouseWheel() + \sa mousePress(), mouseRelease(), mouseDoubleClickSequence(), mouseMove(), mouseDrag(), mouseWheel() */ function mouseClick(item, x, y, button, modifiers, delay) { if (!qtest_verifyItem(item, "mouseClick")) @@ -1475,6 +1475,7 @@ Item { /*! \qmlmethod TestCase::mouseDoubleClick(item, x = item.width / 2, y = item.height / 2, button = Qt.LeftButton, modifiers = Qt.NoModifier, delay = -1) + \deprecated Simulates double-clicking a mouse \a button with optional \a modifiers on an \a item. The position of the click is defined by \a x and \a y. @@ -1528,7 +1529,7 @@ Item { This QML method was introduced in Qt 5.5. - \sa mouseDoubleClick(), mousePress(), mouseRelease(), mouseClick(), mouseMove(), mouseDrag(), mouseWheel() + \sa mousePress(), mouseRelease(), mouseClick(), mouseMove(), mouseDrag(), mouseWheel() */ function mouseDoubleClickSequence(item, x, y, button, modifiers, delay) { if (!qtest_verifyItem(item, "mouseDoubleClickSequence")) @@ -1560,7 +1561,7 @@ Item { If \a item is obscured by another item, or a child of \a item occupies that position, then the event will be delivered to the other item instead. - \sa mousePress(), mouseRelease(), mouseClick(), mouseDoubleClick(), mouseDoubleClickSequence(), mouseDrag(), mouseWheel() + \sa mousePress(), mouseRelease(), mouseClick(), mouseDoubleClickSequence(), mouseDrag(), mouseWheel() */ function mouseMove(item, x, y, delay, buttons) { if (!qtest_verifyItem(item, "mouseMove")) @@ -1588,7 +1589,7 @@ Item { The \a xDelta and \a yDelta contain the wheel rotation distance in eighths of a degree. see \l QWheelEvent::angleDelta() for more details. - \sa mousePress(), mouseClick(), mouseDoubleClick(), mouseDoubleClickSequence(), mouseMove(), mouseRelease(), mouseDrag(), QWheelEvent::angleDelta() + \sa mousePress(), mouseClick(), mouseDoubleClickSequence(), mouseMove(), mouseRelease(), mouseDrag(), QWheelEvent::angleDelta() */ function mouseWheel(item, x, y, xDelta, yDelta, buttons, modifiers, delay) { if (!qtest_verifyItem(item, "mouseWheel")) diff --git a/src/qmltest/dependencies.json b/src/imports/testlib/dependencies.json index b2c4125178..b2c4125178 100644 --- a/src/qmltest/dependencies.json +++ b/src/imports/testlib/dependencies.json diff --git a/src/imports/testlib/main.cpp b/src/imports/testlib/main.cpp index 1914c02dd0..83fc150e6c 100644 --- a/src/imports/testlib/main.cpp +++ b/src/imports/testlib/main.cpp @@ -50,6 +50,8 @@ QML_DECLARE_TYPE(QuickTestResult) QML_DECLARE_TYPE(QuickTestEvent) QML_DECLARE_TYPE(QuickTestUtil) +extern void qml_register_types_QtTest(); + QT_BEGIN_NAMESPACE class QTestQmlModule : public QQmlEngineExtensionPlugin @@ -58,7 +60,11 @@ class QTestQmlModule : public QQmlEngineExtensionPlugin Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid) public: - QTestQmlModule(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) { } + QTestQmlModule(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) + { + volatile auto registration = &qml_register_types_QtTest; + Q_UNUSED(registration); + } }; QT_END_NAMESPACE diff --git a/src/imports/testlib/quicktestevent_p.h b/src/imports/testlib/quicktestevent_p.h index f452e4ff82..0bbae8434f 100644 --- a/src/imports/testlib/quicktestevent_p.h +++ b/src/imports/testlib/quicktestevent_p.h @@ -63,6 +63,7 @@ class QQuickTouchEventSequence : public QObject { Q_OBJECT QML_ANONYMOUS + QML_ADDED_IN_VERSION(1, 0) public: explicit QQuickTouchEventSequence(QuickTestEvent *testEvent, QObject *item = nullptr); @@ -83,6 +84,7 @@ class QuickTestEvent : public QObject Q_OBJECT Q_PROPERTY(int defaultMouseDelay READ defaultMouseDelay FINAL) QML_NAMED_ELEMENT(TestEvent) + QML_ADDED_IN_VERSION(1, 0) public: QuickTestEvent(QObject *parent = nullptr); ~QuickTestEvent() override; @@ -97,7 +99,7 @@ public Q_SLOTS: bool keyReleaseChar(const QString &character, int modifiers, int delay); bool keyClickChar(const QString &character, int modifiers, int delay); - Q_REVISION(2) bool keySequence(const QVariant &keySequence); + Q_REVISION(1, 2) bool keySequence(const QVariant &keySequence); bool mousePress(QObject *item, qreal x, qreal y, int button, int modifiers, int delay); diff --git a/src/imports/testlib/quicktestresultforeign_p.h b/src/imports/testlib/quicktestresultforeign_p.h index 92ff8e8a5a..e9dd12fa93 100644 --- a/src/imports/testlib/quicktestresultforeign_p.h +++ b/src/imports/testlib/quicktestresultforeign_p.h @@ -61,6 +61,7 @@ struct QuickTestResultForeign Q_GADGET QML_FOREIGN(QuickTestResult) QML_NAMED_ELEMENT(TestResult) + QML_ADDED_IN_VERSION(1, 0) }; QT_END_NAMESPACE diff --git a/src/imports/testlib/quicktestutil_p.h b/src/imports/testlib/quicktestutil_p.h index 2456bf88a7..7e90c1cd1d 100644 --- a/src/imports/testlib/quicktestutil_p.h +++ b/src/imports/testlib/quicktestutil_p.h @@ -63,6 +63,7 @@ class QuickTestUtil : public QObject Q_PROPERTY(bool printAvailableFunctions READ printAvailableFunctions NOTIFY printAvailableFunctionsChanged) Q_PROPERTY(int dragThreshold READ dragThreshold NOTIFY dragThresholdChanged) QML_NAMED_ELEMENT(TestUtil) + QML_ADDED_IN_VERSION(1, 0) public: QuickTestUtil(QObject *parent = nullptr) :QObject(parent) {} ~QuickTestUtil() override {} diff --git a/src/imports/testlib/testlib.pro b/src/imports/testlib/testlib.pro index de6453eeab..2a97213e29 100644 --- a/src/imports/testlib/testlib.pro +++ b/src/imports/testlib/testlib.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = qmltestplugin TARGETPATH = QtTest -IMPORT_VERSION = 1.15 +QML_IMPORT_VERSION = $$QT_VERSION QT += quick qmltest-private qml-private core-private testlib gui-private diff --git a/src/imports/wavefrontmesh/plugin.cpp b/src/imports/wavefrontmesh/plugin.cpp index 9bb7a45b2f..eea0db19db 100644 --- a/src/imports/wavefrontmesh/plugin.cpp +++ b/src/imports/wavefrontmesh/plugin.cpp @@ -42,6 +42,8 @@ #include "qwavefrontmesh.h" +extern void qml_register_types_Qt_labs_wavefrontmesh(); + QT_BEGIN_NAMESPACE class QmlWavefrontMeshPlugin : public QQmlEngineExtensionPlugin @@ -52,6 +54,8 @@ public: QmlWavefrontMeshPlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) { + volatile auto registration = &qml_register_types_Qt_labs_wavefrontmesh; + Q_UNUSED(registration); } }; diff --git a/src/imports/wavefrontmesh/qwavefrontmesh.cpp b/src/imports/wavefrontmesh/qwavefrontmesh.cpp index e973ef0103..1772c40c50 100644 --- a/src/imports/wavefrontmesh/qwavefrontmesh.cpp +++ b/src/imports/wavefrontmesh/qwavefrontmesh.cpp @@ -257,7 +257,7 @@ void QWavefrontMesh::readData() while (!stream.atEnd()) { stream.readLineInto(&buffer); - QVector<QStringRef> tokens = buffer.splitRef(space, QString::SkipEmptyParts); + QVector<QStringRef> tokens = buffer.splitRef(space, Qt::SkipEmptyParts); if (tokens.size() < 2) continue; @@ -316,7 +316,7 @@ void QWavefrontMesh::readData() if (tokens.size() >= 4 && tokens.size() <= 5) { { bool ok; - QVector<QStringRef> faceTokens = tokens.at(1).split(slash, QString::SkipEmptyParts); + QVector<QStringRef> faceTokens = tokens.at(1).split(slash, Qt::SkipEmptyParts); Q_ASSERT(!faceTokens.isEmpty()); p1 = faceTokens.at(0).toInt(&ok) - 1; @@ -336,7 +336,7 @@ void QWavefrontMesh::readData() { bool ok; - QVector<QStringRef> faceTokens = tokens.at(2).split(slash, QString::SkipEmptyParts); + QVector<QStringRef> faceTokens = tokens.at(2).split(slash, Qt::SkipEmptyParts); Q_ASSERT(!faceTokens.isEmpty()); p2 = faceTokens.at(0).toInt(&ok) - 1; @@ -356,7 +356,7 @@ void QWavefrontMesh::readData() { bool ok; - QVector<QStringRef> faceTokens = tokens.at(3).split(slash, QString::SkipEmptyParts); + QVector<QStringRef> faceTokens = tokens.at(3).split(slash, Qt::SkipEmptyParts); Q_ASSERT(!faceTokens.isEmpty()); p3 = faceTokens.at(0).toInt(&ok) - 1; @@ -394,7 +394,7 @@ void QWavefrontMesh::readData() if (tokens.size() == 5) { bool ok; - QVector<QStringRef> faceTokens = tokens.at(4).split(slash, QString::SkipEmptyParts); + QVector<QStringRef> faceTokens = tokens.at(4).split(slash, Qt::SkipEmptyParts); Q_ASSERT(!faceTokens.isEmpty()); int p4 = faceTokens.at(0).toInt(&ok) - 1; diff --git a/src/imports/wavefrontmesh/qwavefrontmesh.h b/src/imports/wavefrontmesh/qwavefrontmesh.h index a8a40c1a6a..67e0527e5d 100644 --- a/src/imports/wavefrontmesh/qwavefrontmesh.h +++ b/src/imports/wavefrontmesh/qwavefrontmesh.h @@ -56,6 +56,7 @@ class QWavefrontMesh : public QQuickShaderEffectMesh Q_PROPERTY(QVector3D projectionPlaneV READ projectionPlaneV WRITE setProjectionPlaneV NOTIFY projectionPlaneVChanged) Q_PROPERTY(QVector3D projectionPlaneW READ projectionPlaneW WRITE setProjectionPlaneW NOTIFY projectionPlaneWChanged) QML_NAMED_ELEMENT(WavefrontMesh) + QML_ADDED_IN_VERSION(1, 0) public: enum Error { diff --git a/src/imports/wavefrontmesh/wavefrontmesh.pro b/src/imports/wavefrontmesh/wavefrontmesh.pro index f6d93b867d..4aa06b97bf 100644 --- a/src/imports/wavefrontmesh/wavefrontmesh.pro +++ b/src/imports/wavefrontmesh/wavefrontmesh.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = qmlwavefrontmeshplugin TARGETPATH = Qt/labs/wavefrontmesh -IMPORT_VERSION = 1.15 +QML_IMPORT_VERSION = $$QT_VERSION QT = core-private qml-private quick-private diff --git a/src/imports/window/plugin.cpp b/src/imports/window/plugin.cpp index ec4f2c5d2a..5152fa02ec 100644 --- a/src/imports/window/plugin.cpp +++ b/src/imports/window/plugin.cpp @@ -41,6 +41,8 @@ #include "plugin.h" +extern void qml_register_types_QtQuick_Window(); + QT_BEGIN_NAMESPACE /*! @@ -64,7 +66,11 @@ class QtQuick2WindowPlugin : public QQmlEngineExtensionPlugin Q_OBJECT Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid) public: - QtQuick2WindowPlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) { } + QtQuick2WindowPlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) + { + volatile auto registration = &qml_register_types_QtQuick_Window; + Q_UNUSED(registration); + } }; //![class decl] diff --git a/src/imports/window/plugin.h b/src/imports/window/plugin.h index 9f58ca9ac7..625a77b12c 100644 --- a/src/imports/window/plugin.h +++ b/src/imports/window/plugin.h @@ -65,7 +65,7 @@ struct QWindowForeign Q_GADGET QML_FOREIGN(QWindow) QML_ANONYMOUS - QML_ADDED_IN_MINOR_VERSION(1) + QML_ADDED_IN_VERSION(2, 1) }; struct QQuickWindowForeign @@ -73,8 +73,8 @@ struct QQuickWindowForeign Q_GADGET QML_FOREIGN(QQuickWindow) QML_NAMED_ELEMENT(Window) - QML_ADDED_IN_MINOR_VERSION(0) - QML_REMOVED_IN_MINOR_VERSION(1) + QML_ADDED_IN_VERSION(2, 0) + QML_REMOVED_IN_VERSION(2, 1) }; struct QQuickWindowForeignAttached @@ -82,6 +82,7 @@ struct QQuickWindowForeignAttached Q_GADGET QML_FOREIGN(QQuickWindowAttached) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) }; struct QQuickScreenInfoForeign @@ -89,7 +90,7 @@ struct QQuickScreenInfoForeign Q_GADGET QML_FOREIGN(QQuickScreenInfo) QML_NAMED_ELEMENT(ScreenInfo) - QML_ADDED_IN_MINOR_VERSION(3) + QML_ADDED_IN_VERSION(2, 3) QML_UNCREATABLE("ScreenInfo can only be used via the attached property.") }; @@ -98,6 +99,7 @@ struct QQuickScreenForeignAttached Q_GADGET QML_FOREIGN(QQuickScreenAttached) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) }; struct QQuickScreenForeign @@ -105,6 +107,7 @@ struct QQuickScreenForeign Q_GADGET QML_FOREIGN(QQuickScreen) QML_NAMED_ELEMENT(Screen) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("Screen can only be used via the attached property.") }; @@ -113,7 +116,14 @@ struct QQuickWindowQmlImplForeign Q_GADGET QML_FOREIGN(QQuickWindowQmlImpl) QML_NAMED_ELEMENT(Window) - QML_ADDED_IN_MINOR_VERSION(1) + QML_ADDED_IN_VERSION(2, 1) +}; + +struct QQuickRootItemForeign +{ + Q_GADGET + QML_FOREIGN(QQuickRootItem) + QML_ANONYMOUS }; QT_END_NAMESPACE diff --git a/src/imports/window/window.pro b/src/imports/window/window.pro index 70af305937..d8f9b16df4 100644 --- a/src/imports/window/window.pro +++ b/src/imports/window/window.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = windowplugin TARGETPATH = QtQuick/Window -IMPORT_VERSION = 2.15 +QML_IMPORT_VERSION = $$QT_VERSION SOURCES += \ plugin.cpp diff --git a/src/imports/workerscript/plugin.cpp b/src/imports/workerscript/plugin.cpp index 0961979c53..1323b17ef4 100644 --- a/src/imports/workerscript/plugin.cpp +++ b/src/imports/workerscript/plugin.cpp @@ -37,17 +37,11 @@ ** ****************************************************************************/ -#include <QtQmlWorkerScript/private/qquickworkerscript_p.h> - +#include <QtQmlWorkerScript/private/qtqmlworkerscriptglobal_p.h> #include <QtQml/qqmlextensionplugin.h> -#include <QtQml/qqml.h> - -#include <QtCore/qloggingcategory.h> QT_BEGIN_NAMESPACE -Q_LOGGING_CATEGORY(workerScriptPlugin, "qt.workerScriptPlugin") - /*! \qmlmodule QtQml.WorkerScript 2.\QtMinorVersion \title Qt QML WorkerScript QML Types @@ -71,13 +65,8 @@ class QtQmlWorkerScriptPlugin : public QQmlEngineExtensionPlugin public: QtQmlWorkerScriptPlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent) { - if (workerScriptPlugin().isDebugEnabled()) { - // Superficial debug message that causes the dependency between QtQmlWorkerScript - // and the workerscript plugin to be retained. - // As qCDebug() can be a noop, retrieve the className in a separate step. - const QString className = QQuickWorkerScript::staticMetaObject.className(); - qCDebug(workerScriptPlugin) << "Loading WorkerScript plugin:" << className; - } + volatile auto registration = &qml_register_types_QtQml_WorkerScript; + Q_UNUSED(registration); } }; diff --git a/src/imports/workerscript/workerscript.pro b/src/imports/workerscript/workerscript.pro index 101442c3f3..9c6a65eb05 100644 --- a/src/imports/workerscript/workerscript.pro +++ b/src/imports/workerscript/workerscript.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = workerscriptplugin TARGETPATH = QtQml/WorkerScript -IMPORT_VERSION = 2.15 +QML_IMPORT_VERSION = $$QT_VERSION SOURCES += \ plugin.cpp diff --git a/src/particles/particles.pro b/src/particles/particles.pro index 83f6f1c83e..6a117c65fe 100644 --- a/src/particles/particles.pro +++ b/src/particles/particles.pro @@ -19,7 +19,7 @@ include(particles.pri) QMLTYPES_FILENAME = plugins.qmltypes QMLTYPES_INSTALL_DIR = $$[QT_INSTALL_QML]/QtQuick/Particles QML_IMPORT_NAME = QtQuick.Particles -IMPORT_VERSION = 2.15 +QML_IMPORT_VERSION = $$QT_VERSION CONFIG += qmltypes install_qmltypes install_metatypes load(qt_module) diff --git a/src/particles/qquickage_p.h b/src/particles/qquickage_p.h index 890c6a63c1..1730c25c28 100644 --- a/src/particles/qquickage_p.h +++ b/src/particles/qquickage_p.h @@ -60,6 +60,7 @@ class QQuickAgeAffector : public QQuickParticleAffector Q_PROPERTY(int lifeLeft READ lifeLeft WRITE setLifeLeft NOTIFY lifeLeftChanged) Q_PROPERTY(bool advancePosition READ advancePosition WRITE setAdvancePosition NOTIFY advancePositionChanged) QML_NAMED_ELEMENT(Age) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickAgeAffector(QQuickItem *parent = 0); diff --git a/src/particles/qquickangledirection_p.h b/src/particles/qquickangledirection_p.h index d0fdf5a68c..9ec9e49d1a 100644 --- a/src/particles/qquickangledirection_p.h +++ b/src/particles/qquickangledirection_p.h @@ -63,6 +63,7 @@ class QQuickAngleDirection : public QQuickDirection Q_PROPERTY(qreal angleVariation READ angleVariation WRITE setAngleVariation NOTIFY angleVariationChanged) Q_PROPERTY(qreal magnitudeVariation READ magnitudeVariation WRITE setMagnitudeVariation NOTIFY magnitudeVariationChanged) QML_NAMED_ELEMENT(AngleDirection) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickAngleDirection(QObject *parent = 0); QPointF sample(const QPointF &from) override; diff --git a/src/particles/qquickcumulativedirection_p.h b/src/particles/qquickcumulativedirection_p.h index 5160d8f09a..0a54d5dd22 100644 --- a/src/particles/qquickcumulativedirection_p.h +++ b/src/particles/qquickcumulativedirection_p.h @@ -62,6 +62,7 @@ class QQuickCumulativeDirection : public QQuickDirection Q_PROPERTY(QQmlListProperty<QQuickDirection> directions READ directions) Q_CLASSINFO("DefaultProperty", "directions") QML_NAMED_ELEMENT(CumulativeDirection) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickCumulativeDirection(QObject *parent = 0); QQmlListProperty<QQuickDirection> directions(); diff --git a/src/particles/qquickcustomaffector_p.h b/src/particles/qquickcustomaffector_p.h index 5e8671514d..4506ae9d62 100644 --- a/src/particles/qquickcustomaffector_p.h +++ b/src/particles/qquickcustomaffector_p.h @@ -68,6 +68,7 @@ class QQuickCustomAffector : public QQuickParticleAffector Q_PROPERTY(QQuickDirection *velocity READ velocity WRITE setVelocity NOTIFY velocityChanged RESET velocityReset) Q_PROPERTY(QQuickDirection *acceleration READ acceleration WRITE setAcceleration NOTIFY accelerationChanged RESET accelerationReset) QML_NAMED_ELEMENT(Affector) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickCustomAffector(QQuickItem *parent = 0); diff --git a/src/particles/qquickcustomparticle.cpp b/src/particles/qquickcustomparticle.cpp index 91fd63302a..ecb71cb913 100644 --- a/src/particles/qquickcustomparticle.cpp +++ b/src/particles/qquickcustomparticle.cpp @@ -39,7 +39,7 @@ #include "qquickcustomparticle_p.h" #include <QtCore/qrandom.h> -#include <QtGui/qopenglcontext.h> +#include <qopenglcontext.h> #include <QtQuick/private/qquickshadereffectmesh_p.h> #include <QtQuick/private/qsgshadersourcebuilder_p.h> #include <QtQml/qqmlinfo.h> diff --git a/src/particles/qquickcustomparticle_p.h b/src/particles/qquickcustomparticle_p.h index 444f7ad215..90643fe3e4 100644 --- a/src/particles/qquickcustomparticle_p.h +++ b/src/particles/qquickcustomparticle_p.h @@ -68,6 +68,7 @@ class QQuickCustomParticle : public QQuickParticlePainter Q_PROPERTY(QByteArray fragmentShader READ fragmentShader WRITE setFragmentShader NOTIFY fragmentShaderChanged) Q_PROPERTY(QByteArray vertexShader READ vertexShader WRITE setVertexShader NOTIFY vertexShaderChanged) QML_NAMED_ELEMENT(CustomParticle) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickCustomParticle(QQuickItem* parent=0); diff --git a/src/particles/qquickdirection_p.h b/src/particles/qquickdirection_p.h index 60b4d8eb1d..e671868ed2 100644 --- a/src/particles/qquickdirection_p.h +++ b/src/particles/qquickdirection_p.h @@ -61,6 +61,7 @@ class QQuickDirection : public QObject { Q_OBJECT QML_NAMED_ELEMENT(NullVector) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("Abstract type. Use one of the inheriting types instead.") public: diff --git a/src/particles/qquickellipseextruder_p.h b/src/particles/qquickellipseextruder_p.h index c92443fedf..3268923480 100644 --- a/src/particles/qquickellipseextruder_p.h +++ b/src/particles/qquickellipseextruder_p.h @@ -59,6 +59,7 @@ class QQuickEllipseExtruder : public QQuickParticleExtruder Q_OBJECT Q_PROPERTY(bool fill READ fill WRITE setFill NOTIFY fillChanged)//###Use base class? If it's still box QML_NAMED_ELEMENT(EllipseShape) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickEllipseExtruder(QObject *parent = 0); QPointF extrude(const QRectF &) override; diff --git a/src/particles/qquickfriction_p.h b/src/particles/qquickfriction_p.h index 5686bb37d5..952f47b141 100644 --- a/src/particles/qquickfriction_p.h +++ b/src/particles/qquickfriction_p.h @@ -60,6 +60,7 @@ class QQuickFrictionAffector : public QQuickParticleAffector Q_PROPERTY(qreal factor READ factor WRITE setFactor NOTIFY factorChanged) Q_PROPERTY(qreal threshold READ threshold WRITE setThreshold NOTIFY thresholdChanged) QML_NAMED_ELEMENT(Friction) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickFrictionAffector(QQuickItem *parent = 0); diff --git a/src/particles/qquickgravity_p.h b/src/particles/qquickgravity_p.h index ef7cc770b7..351cbb93b1 100644 --- a/src/particles/qquickgravity_p.h +++ b/src/particles/qquickgravity_p.h @@ -62,6 +62,7 @@ class QQuickGravityAffector : public QQuickParticleAffector Q_PROPERTY(qreal acceleration READ magnitude WRITE setAcceleration NOTIFY magnitudeChanged) Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged) QML_NAMED_ELEMENT(Gravity) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickGravityAffector(QQuickItem *parent = 0); qreal magnitude() const; diff --git a/src/particles/qquickgroupgoal_p.h b/src/particles/qquickgroupgoal_p.h index 022b244ed7..5589483aa6 100644 --- a/src/particles/qquickgroupgoal_p.h +++ b/src/particles/qquickgroupgoal_p.h @@ -62,6 +62,7 @@ class QQuickGroupGoalAffector : public QQuickParticleAffector Q_PROPERTY(QString goalState READ goalState WRITE setGoalState NOTIFY goalStateChanged) Q_PROPERTY(bool jump READ jump WRITE setJump NOTIFY jumpChanged) QML_NAMED_ELEMENT(GroupGoal) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickGroupGoalAffector(QQuickItem *parent = 0); diff --git a/src/particles/qquickimageparticle.cpp b/src/particles/qquickimageparticle.cpp index 4ce8186c7c..4d67691771 100644 --- a/src/particles/qquickimageparticle.cpp +++ b/src/particles/qquickimageparticle.cpp @@ -1,4 +1,4 @@ -/**************************************************************************** +/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ @@ -389,10 +389,10 @@ private: QSGMaterialType DeformableMaterial::m_type; -class SpriteMaterialShader : public QSGMaterialShader +class ParticleSpriteMaterialShader : public QSGMaterialShader { public: - SpriteMaterialShader() + ParticleSpriteMaterialShader() { QSGShaderSourceBuilder builder; const bool isES = QOpenGLContext::currentContext()->isOpenGLES(); @@ -478,10 +478,10 @@ public: QOpenGLFunctions* glFuncs; }; -class SpriteMaterialRhiShader : public QSGMaterialRhiShader +class ParticleSpriteMaterialRhiShader : public QSGMaterialRhiShader { public: - SpriteMaterialRhiShader() + ParticleSpriteMaterialRhiShader() { setShaderFileName(VertexStage, QStringLiteral(":/particles/shaders_ng/imageparticle_sprite.vert.qsb")); setShaderFileName(FragmentStage, QStringLiteral(":/particles/shaders_ng/imageparticle_sprite.frag.qsb")); @@ -544,9 +544,9 @@ public: SpriteMaterial() { setFlag(SupportsRhiShader, true); } QSGMaterialShader *createShader() const override { if (flags().testFlag(RhiShaderWanted)) - return new SpriteMaterialRhiShader; + return new ParticleSpriteMaterialRhiShader; else - return new SpriteMaterialShader; + return new ParticleSpriteMaterialShader; } QSGMaterialType *type() const override { return &m_type; } @@ -1143,7 +1143,9 @@ QQuickImageParticle::~QQuickImageParticle() QQmlListProperty<QQuickSprite> QQuickImageParticle::sprites() { - return QQmlListProperty<QQuickSprite>(this, &m_sprites, spriteAppend, spriteCount, spriteAt, spriteClear); + return QQmlListProperty<QQuickSprite>(this, &m_sprites, + spriteAppend, spriteCount, spriteAt, + spriteClear, spriteReplace, spriteRemoveLast); } void QQuickImageParticle::sceneGraphInvalidated() diff --git a/src/particles/qquickimageparticle_p.h b/src/particles/qquickimageparticle_p.h index fdb404861c..266054f28e 100644 --- a/src/particles/qquickimageparticle_p.h +++ b/src/particles/qquickimageparticle_p.h @@ -203,6 +203,7 @@ class QQuickImageParticle : public QQuickParticlePainter Q_PROPERTY(EntryEffect entryEffect READ entryEffect WRITE setEntryEffect NOTIFY entryEffectChanged) QML_NAMED_ELEMENT(ImageParticle) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickImageParticle(QQuickItem *parent = 0); virtual ~QQuickImageParticle(); diff --git a/src/particles/qquickitemparticle_p.h b/src/particles/qquickitemparticle_p.h index 32c9881691..fce9e95548 100644 --- a/src/particles/qquickitemparticle_p.h +++ b/src/particles/qquickitemparticle_p.h @@ -64,6 +64,7 @@ class QQuickItemParticle : public QQuickParticlePainter Q_PROPERTY(bool fade READ fade WRITE setFade NOTIFY fadeChanged) Q_PROPERTY(QQmlComponent* delegate READ delegate WRITE setDelegate NOTIFY delegateChanged) QML_NAMED_ELEMENT(ItemParticle) + QML_ADDED_IN_VERSION(2, 0) QML_ATTACHED(QQuickItemParticleAttached) public: explicit QQuickItemParticle(QQuickItem *parent = 0); diff --git a/src/particles/qquicklineextruder_p.h b/src/particles/qquicklineextruder_p.h index 76ac5aaf11..a337324c6a 100644 --- a/src/particles/qquicklineextruder_p.h +++ b/src/particles/qquicklineextruder_p.h @@ -58,6 +58,7 @@ class QQuickLineExtruder : public QQuickParticleExtruder //Default is topleft to bottom right. Flipped makes it topright to bottom left Q_PROPERTY(bool mirrored READ mirrored WRITE setMirrored NOTIFY mirroredChanged) QML_NAMED_ELEMENT(LineShape) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickLineExtruder(QObject *parent = 0); diff --git a/src/particles/qquickmaskextruder_p.h b/src/particles/qquickmaskextruder_p.h index 419d162811..0d3fa9c15a 100644 --- a/src/particles/qquickmaskextruder_p.h +++ b/src/particles/qquickmaskextruder_p.h @@ -62,6 +62,7 @@ class QQuickMaskExtruder : public QQuickParticleExtruder Q_OBJECT Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) QML_NAMED_ELEMENT(MaskShape) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickMaskExtruder(QObject *parent = 0); QPointF extrude(const QRectF &) override; diff --git a/src/particles/qquickparticleaffector_p.h b/src/particles/qquickparticleaffector_p.h index fd4887333e..22cebbead1 100644 --- a/src/particles/qquickparticleaffector_p.h +++ b/src/particles/qquickparticleaffector_p.h @@ -69,6 +69,7 @@ class Q_QUICKPARTICLES_PRIVATE_EXPORT QQuickParticleAffector : public QQuickItem Q_PROPERTY(QQuickParticleExtruder* shape READ shape WRITE setShape NOTIFY shapeChanged) QML_NAMED_ELEMENT(ParticleAffector) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("Abstract type. Use one of the inheriting types instead.") public: diff --git a/src/particles/qquickparticleemitter_p.h b/src/particles/qquickparticleemitter_p.h index b97d3f812a..8c9ca622fb 100644 --- a/src/particles/qquickparticleemitter_p.h +++ b/src/particles/qquickparticleemitter_p.h @@ -84,6 +84,7 @@ class Q_QUICKPARTICLES_PRIVATE_EXPORT QQuickParticleEmitter : public QQuickItem Q_PROPERTY(QQuickDirection *acceleration READ acceleration WRITE setAcceleration NOTIFY accelerationChanged) Q_PROPERTY(qreal velocityFromMovement READ velocityFromMovement WRITE setVelocityFromMovement NOTIFY velocityFromMovementChanged) QML_NAMED_ELEMENT(Emitter) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickParticleEmitter(QQuickItem *parent = 0); diff --git a/src/particles/qquickparticleextruder_p.h b/src/particles/qquickparticleextruder_p.h index 24f7a0a2fa..7be0ead245 100644 --- a/src/particles/qquickparticleextruder_p.h +++ b/src/particles/qquickparticleextruder_p.h @@ -63,6 +63,7 @@ class QQuickParticleExtruder : public QObject Q_OBJECT QML_NAMED_ELEMENT(ParticleExtruder) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("Abstract type. Use one of the inheriting types instead.") public: diff --git a/src/particles/qquickparticlegroup.cpp b/src/particles/qquickparticlegroup.cpp index 052fda6eff..902c23331d 100644 --- a/src/particles/qquickparticlegroup.cpp +++ b/src/particles/qquickparticlegroup.cpp @@ -106,10 +106,15 @@ void delayedRedirect(QQmlListProperty<QObject> *prop, QObject *value) QQmlListProperty<QObject> QQuickParticleGroup::particleChildren() { QQuickParticleSystem* system = qobject_cast<QQuickParticleSystem*>(parent()); - if (system) - return QQmlListProperty<QObject>(this, nullptr, &QQuickParticleSystem::statePropertyRedirect, nullptr, nullptr, nullptr); - else - return QQmlListProperty<QObject>(this, nullptr, &delayedRedirect, nullptr, nullptr, nullptr); + if (system) { + return QQmlListProperty<QObject>(this, nullptr, + &QQuickParticleSystem::statePropertyRedirect, nullptr, + nullptr, nullptr, nullptr, nullptr); + } else { + return QQmlListProperty<QObject>(this, nullptr, + &delayedRedirect, nullptr, nullptr, + nullptr, nullptr, nullptr); + } } void QQuickParticleGroup::setSystem(QQuickParticleSystem* arg) diff --git a/src/particles/qquickparticlegroup_p.h b/src/particles/qquickparticlegroup_p.h index 8d068fbe9c..9b13153a95 100644 --- a/src/particles/qquickparticlegroup_p.h +++ b/src/particles/qquickparticlegroup_p.h @@ -67,6 +67,7 @@ class QQuickParticleGroup : public QQuickStochasticState, public QQmlParserStatu Q_PROPERTY(QQmlListProperty<QObject> particleChildren READ particleChildren DESIGNABLE false)//### Hidden property for in-state system definitions - ought not to be used in actual "Sprite" states Q_CLASSINFO("DefaultProperty", "particleChildren") QML_NAMED_ELEMENT(ParticleGroup) + QML_ADDED_IN_VERSION(2, 0) Q_INTERFACES(QQmlParserStatus) public: diff --git a/src/particles/qquickparticlepainter_p.h b/src/particles/qquickparticlepainter_p.h index e3d13b8a21..5236bb6569 100644 --- a/src/particles/qquickparticlepainter_p.h +++ b/src/particles/qquickparticlepainter_p.h @@ -65,6 +65,7 @@ class QQuickParticlePainter : public QQuickItem Q_PROPERTY(QStringList groups READ groups WRITE setGroups NOTIFY groupsChanged) QML_NAMED_ELEMENT(ParticlePainter) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("Abstract type. Use one of the inheriting types instead.") public: // data diff --git a/src/particles/qquickparticlesystem_p.h b/src/particles/qquickparticlesystem_p.h index 7c0a1ffd7d..b7812c6ea5 100644 --- a/src/particles/qquickparticlesystem_p.h +++ b/src/particles/qquickparticlesystem_p.h @@ -352,6 +352,7 @@ class Q_QUICKPARTICLES_PRIVATE_EXPORT QQuickParticleSystem : public QQuickItem Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged) Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged) QML_NAMED_ELEMENT(ParticleSystem) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickParticleSystem(QQuickItem *parent = nullptr); diff --git a/src/particles/qquickpointattractor_p.h b/src/particles/qquickpointattractor_p.h index 28bbaaa84f..b3314f1a96 100644 --- a/src/particles/qquickpointattractor_p.h +++ b/src/particles/qquickpointattractor_p.h @@ -63,6 +63,7 @@ class QQuickAttractorAffector : public QQuickParticleAffector Q_PROPERTY(AffectableParameters affectedParameter READ affectedParameter WRITE setAffectedParameter NOTIFY affectedParameterChanged) Q_PROPERTY(Proportion proportionalToDistance READ proportionalToDistance WRITE setProportionalToDistance NOTIFY proportionalToDistanceChanged) QML_NAMED_ELEMENT(Attractor) + QML_ADDED_IN_VERSION(2, 0) public: enum Proportion{ diff --git a/src/particles/qquickpointdirection_p.h b/src/particles/qquickpointdirection_p.h index 9103a570c9..39109d8331 100644 --- a/src/particles/qquickpointdirection_p.h +++ b/src/particles/qquickpointdirection_p.h @@ -62,6 +62,7 @@ class QQuickPointDirection : public QQuickDirection Q_PROPERTY(qreal xVariation READ xVariation WRITE setXVariation NOTIFY xVariationChanged) Q_PROPERTY(qreal yVariation READ yVariation WRITE setYVariation NOTIFY yVariationChanged) QML_NAMED_ELEMENT(PointDirection) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickPointDirection(QObject *parent = 0); QPointF sample(const QPointF &from) override; diff --git a/src/particles/qquickrectangleextruder_p.h b/src/particles/qquickrectangleextruder_p.h index 7c0a6c2bf1..f6f39579c4 100644 --- a/src/particles/qquickrectangleextruder_p.h +++ b/src/particles/qquickrectangleextruder_p.h @@ -60,6 +60,7 @@ class QQuickRectangleExtruder : public QQuickParticleExtruder Q_OBJECT Q_PROPERTY(bool fill READ fill WRITE setFill NOTIFY fillChanged) QML_NAMED_ELEMENT(RectangleShape) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickRectangleExtruder(QObject *parent = 0); diff --git a/src/particles/qquickspritegoal_p.h b/src/particles/qquickspritegoal_p.h index d5f9bb88ae..efd9b1ab39 100644 --- a/src/particles/qquickspritegoal_p.h +++ b/src/particles/qquickspritegoal_p.h @@ -64,6 +64,7 @@ class QQuickSpriteGoalAffector : public QQuickParticleAffector Q_PROPERTY(bool jump READ jump WRITE setJump NOTIFY jumpChanged) Q_PROPERTY(bool systemStates READ systemStates WRITE setSystemStates NOTIFY systemStatesChanged) QML_NAMED_ELEMENT(SpriteGoal) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickSpriteGoalAffector(QQuickItem *parent = 0); diff --git a/src/particles/qquicktargetdirection_p.h b/src/particles/qquicktargetdirection_p.h index 232d375d8c..ea6ac24893 100644 --- a/src/particles/qquicktargetdirection_p.h +++ b/src/particles/qquicktargetdirection_p.h @@ -71,6 +71,7 @@ class QQuickTargetDirection : public QQuickDirection Q_PROPERTY(qreal magnitude READ magnitude WRITE setMagnitude NOTIFY magnitudeChanged) Q_PROPERTY(qreal magnitudeVariation READ magnitudeVariation WRITE setMagnitudeVariation NOTIFY magnitudeVariationChanged) QML_NAMED_ELEMENT(TargetDirection) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickTargetDirection(QObject *parent = 0); diff --git a/src/particles/qquicktrailemitter_p.h b/src/particles/qquicktrailemitter_p.h index 270bec52cf..bf21b66fb6 100644 --- a/src/particles/qquicktrailemitter_p.h +++ b/src/particles/qquicktrailemitter_p.h @@ -65,6 +65,7 @@ class QQuickTrailEmitter : public QQuickParticleEmitter Q_PROPERTY(qreal emitHeight READ emitterYVariation WRITE setEmitterYVariation NOTIFY emitterYVariationChanged) Q_PROPERTY(qreal emitWidth READ emitterXVariation WRITE setEmitterXVariation NOTIFY emitterXVariationChanged) QML_NAMED_ELEMENT(TrailEmitter) + QML_ADDED_IN_VERSION(2, 0) public: enum EmitSize { diff --git a/src/particles/qquickturbulence_p.h b/src/particles/qquickturbulence_p.h index 52011381e4..77239660d8 100644 --- a/src/particles/qquickturbulence_p.h +++ b/src/particles/qquickturbulence_p.h @@ -63,6 +63,7 @@ class QQuickTurbulenceAffector : public QQuickParticleAffector Q_PROPERTY(qreal strength READ strength WRITE setStrength NOTIFY strengthChanged) Q_PROPERTY(QUrl noiseSource READ noiseSource WRITE setNoiseSource NOTIFY noiseSourceChanged) QML_NAMED_ELEMENT(Turbulence) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickTurbulenceAffector(QQuickItem *parent = 0); diff --git a/src/particles/qquickwander_p.h b/src/particles/qquickwander_p.h index bf7acdacfb..174b780562 100644 --- a/src/particles/qquickwander_p.h +++ b/src/particles/qquickwander_p.h @@ -72,6 +72,7 @@ class QQuickWanderAffector : public QQuickParticleAffector Q_PROPERTY(qreal yVariance READ yVariance WRITE setYVariance NOTIFY yVarianceChanged) Q_PROPERTY(AffectableParameters affectedParameter READ affectedParameter WRITE setAffectedParameter NOTIFY affectedParameterChanged) QML_NAMED_ELEMENT(Wander) + QML_ADDED_IN_VERSION(2, 0) public: enum AffectableParameters { diff --git a/src/particles/qtquickparticlesglobal_p.h b/src/particles/qtquickparticlesglobal_p.h index d7647b3d97..927bc29050 100644 --- a/src/particles/qtquickparticlesglobal_p.h +++ b/src/particles/qtquickparticlesglobal_p.h @@ -65,4 +65,6 @@ # define Q_QUICKPARTICLES_PRIVATE_EXPORT #endif +void Q_QUICKPARTICLES_PRIVATE_EXPORT qml_register_types_QtQuick_Particles(); + #endif // QTQUICKPARTICLESGLOBAL_P_H diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp index a3d19841cf..d435e82390 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp @@ -94,9 +94,12 @@ qint64 NullDevice::writeData(const char *data, qint64 len) // (otherwise we assert in QVariant::operator<< when actually saving it) static bool isSaveable(const QVariant &value) { + const int valType = static_cast<int>(value.userType()); + if (valType >= QMetaType::User) + return false; NullDevice nullDevice; QDataStream fakeStream(&nullDevice); - return QMetaType::save(fakeStream, static_cast<int>(value.userType()), value.constData()); + return QMetaType::save(fakeStream, valType, value.constData()); } QQmlEngineDebugServiceImpl::QQmlEngineDebugServiceImpl(QObject *parent) : diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp index 61fea96e2f..333ce4b26f 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp @@ -66,7 +66,6 @@ void JavaScriptJob::run() QV4::ScopedContext ctx(scope, engine->currentStackFrame ? engine->currentContext() : engine->scriptContext()); - QObject scopeObject; QV4::CppStackFrame *frame = engine->currentStackFrame; @@ -76,9 +75,10 @@ void JavaScriptJob::run() ctx = static_cast<QV4::ExecutionContext *>(&frame->jsFrame->context); if (context >= 0) { - QQmlContext *extraContext = qmlContext(QQmlDebugService::objectForId(context)); + QObject *forId = QQmlDebugService::objectForId(context); + QQmlContext *extraContext = qmlContext(forId); if (extraContext) - ctx = QV4::QmlContext::create(ctx, QQmlContextData::get(extraContext), &scopeObject); + ctx = QV4::QmlContext::create(ctx, QQmlContextData::get(extraContext), forId); } else if (frameNr < 0) { // Use QML context if available QQmlEngine *qmlEngine = engine->qmlEngine(); if (qmlEngine) { @@ -99,7 +99,7 @@ void JavaScriptJob::run() } } if (!engine->qmlContext()) - ctx = QV4::QmlContext::create(ctx, QQmlContextData::get(qmlRootContext), &scopeObject); + ctx = QV4::QmlContext::create(ctx, QQmlContextData::get(qmlRootContext), nullptr); } } diff --git a/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp b/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp index bf73440a39..c504ea605a 100644 --- a/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp +++ b/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp @@ -183,7 +183,7 @@ QQmlNativeDebugConnector::QQmlNativeDebugConnector() : m_blockingMode(false) { const QString args = commandLineArguments(); - const auto lstjsDebugArguments = args.splitRef(QLatin1Char(','), QString::SkipEmptyParts); + const auto lstjsDebugArguments = args.splitRef(QLatin1Char(','), Qt::SkipEmptyParts); QStringList services; for (const QStringRef &strArgument : lstjsDebugArguments) { if (strArgument == QLatin1String("block")) { diff --git a/src/plugins/qmltooling/qmldbg_preview/qmldbg_preview.pro b/src/plugins/qmltooling/qmldbg_preview/qmldbg_preview.pro index 08686a43e3..e1cbc393f7 100644 --- a/src/plugins/qmltooling/qmldbg_preview/qmldbg_preview.pro +++ b/src/plugins/qmltooling/qmldbg_preview/qmldbg_preview.pro @@ -3,6 +3,7 @@ QT += core-private qml-private packetprotocol-private network quick-private gui- TARGET = qmldbg_preview SOURCES += \ + $$PWD/qqmldebugtranslationservice.cpp \ $$PWD/qqmlpreviewblacklist.cpp \ $$PWD/qqmlpreviewfileengine.cpp \ $$PWD/qqmlpreviewfileloader.cpp \ @@ -12,6 +13,7 @@ SOURCES += \ $$PWD/qqmlpreviewservicefactory.cpp HEADERS += \ + $$PWD/qqmldebugtranslationservice.h \ $$PWD/qqmlpreviewblacklist.h \ $$PWD/qqmlpreviewfileengine.h \ $$PWD/qqmlpreviewfileloader.h \ diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmldebugtranslationservice.cpp b/src/plugins/qmltooling/qmldbg_preview/qqmldebugtranslationservice.cpp new file mode 100644 index 0000000000..1561777202 --- /dev/null +++ b/src/plugins/qmltooling/qmldbg_preview/qqmldebugtranslationservice.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmldebugtranslationservice.h" + +QT_BEGIN_NAMESPACE + +QQmlDebugTranslationServiceImpl::QQmlDebugTranslationServiceImpl(QObject *parent) : + QQmlDebugTranslationService(1, parent) +{ +} + +void QQmlDebugTranslationServiceImpl::messageReceived(const QByteArray &message) +{ + Q_UNUSED(message) +} + +QString QQmlDebugTranslationServiceImpl::foundElidedText(QObject *textObject, const QString &layoutText, const QString &elideText) +{ + Q_UNUSED(textObject) + Q_UNUSED(layoutText) + return elideText; +} + +void QQmlDebugTranslationServiceImpl::foundTranslationBinding(QQmlTranslationBinding *binding, QObject *scopeObject, QQmlContextData *contextData) +{ + Q_UNUSED(binding) + Q_UNUSED(scopeObject) + Q_UNUSED(contextData) +} + +QT_END_NAMESPACE diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmldebugtranslationservice.h b/src/plugins/qmltooling/qmldbg_preview/qqmldebugtranslationservice.h new file mode 100644 index 0000000000..a337a937a5 --- /dev/null +++ b/src/plugins/qmltooling/qmldbg_preview/qqmldebugtranslationservice.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDEBUGMESSAGESERVICE_H +#define QDEBUGMESSAGESERVICE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <private/qqmldebugserviceinterfaces_p.h> + +#include <QtCore/qlogging.h> +#include <QtCore/qmutex.h> +#include <QtCore/qelapsedtimer.h> + +QT_BEGIN_NAMESPACE + +class QQmlDebugTranslationServicePrivate; + +class QQmlDebugTranslationServiceImpl : public QQmlDebugTranslationService +{ + Q_OBJECT +public: + //needs to be in sync with QQmlDebugTranslationClient in qqmldebugtranslationclient_p.h + enum Command { + ChangeLanguage, + ChangeWarningColor, + ChangeElidedTextWarningString, + SetDebugTranslationServiceLogFile, + EnableElidedTextWarning, + DisableElidedTextWarning, + TestAllLanguages + }; + QQmlDebugTranslationServiceImpl(QObject *parent = 0); + + QString foundElidedText(QObject *textObject, const QString &layoutText, const QString &elideText) override; + void foundTranslationBinding(QQmlTranslationBinding *binding, QObject *scopeObject, QQmlContextData *contextData) override; + void messageReceived(const QByteArray &message) override; +}; + +QT_END_NAMESPACE + +#endif // QDEBUGMESSAGESERVICE_H diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.json b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.json index d7e1ef1f10..5e148f8101 100644 --- a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.json +++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.json @@ -1,3 +1,3 @@ { - "Keys" : [ "QmlPreview" ] + "Keys" : [ "QmlPreview", "DebugTranslation" ] } diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservicefactory.cpp b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservicefactory.cpp index f0aa3226c8..6ff9805bbe 100644 --- a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservicefactory.cpp +++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservicefactory.cpp @@ -39,12 +39,18 @@ #include "qqmlpreviewservicefactory.h" #include "qqmlpreviewservice.h" +#include "qqmldebugtranslationservice.h" QT_BEGIN_NAMESPACE QQmlDebugService *QQmlPreviewServiceFactory::create(const QString &key) { - return key == QQmlPreviewServiceImpl::s_key ? new QQmlPreviewServiceImpl(this) : nullptr; + if (key == QQmlPreviewServiceImpl::s_key) + return new QQmlPreviewServiceImpl(this); + if (key == QQmlDebugTranslationServiceImpl::s_key) + return new QQmlDebugTranslationServiceImpl(this); + + return nullptr; } QT_END_NAMESPACE diff --git a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp index cc663cd6b3..4d68a4508b 100644 --- a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp +++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp @@ -345,7 +345,7 @@ void QQmlDebugServerImpl::parseArguments() QString fileName; QStringList services; - const auto lstjsDebugArguments = args.splitRef(QLatin1Char(','), QString::SkipEmptyParts); + const auto lstjsDebugArguments = args.splitRef(QLatin1Char(','), Qt::SkipEmptyParts); for (auto argsIt = lstjsDebugArguments.begin(), argsItEnd = lstjsDebugArguments.end(); argsIt != argsItEnd; ++argsIt) { const QStringRef &strArgument = *argsIt; if (strArgument.startsWith(QLatin1String("port:"))) { @@ -422,6 +422,11 @@ void QQmlDebugServerImpl::parseArguments() << 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 debugger console.") << '\n' + << '\n' << QQmlDebugTranslationService::s_key << "\t- " + //: Please preserve the line breaks and formatting + << tr("helps to see if a translated text\n" + "\t\t will result in an elided text\n" + "\t\t in QML elements.") << '\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/plugins/qmltooling/qmltooling.pro b/src/plugins/qmltooling/qmltooling.pro index 30097be77b..b5b6e5d7aa 100644 --- a/src/plugins/qmltooling/qmltooling.pro +++ b/src/plugins/qmltooling/qmltooling.pro @@ -36,7 +36,7 @@ qtHaveModule(quick) { qmldbg_inspector \ qmldbg_quickprofiler - qtConfig(qml-network): SUBDIRS += qmldbg_preview + qtConfig(settings):qtConfig(qml-network): SUBDIRS += qmldbg_preview qmldbg_inspector.depends = packetprotocol qmldbg_quickprofiler.depends = packetprotocol diff --git a/src/qml/common/common.pri b/src/qml/common/common.pri index bcc3ea0fa0..b333c0f6d9 100644 --- a/src/qml/common/common.pri +++ b/src/qml/common/common.pri @@ -28,6 +28,7 @@ HEADERS += \ $$PWD/qqmljsdiagnosticmessage_p.h \ $$PWD/qqmljsfixedpoolarray_p.h \ $$PWD/qqmljsmemorypool_p.h \ + $$PWD/qqmljssourcelocation_p.h \ $$PWD/qv4alloca_p.h \ $$PWD/qv4calldata_p.h \ $$PWD/qv4compileddata_p.h \ diff --git a/src/qml/common/qqmlapiversion_p.h b/src/qml/common/qqmlapiversion_p.h index 4baf37e11c..44d8e3f236 100644 --- a/src/qml/common/qqmlapiversion_p.h +++ b/src/qml/common/qqmlapiversion_p.h @@ -51,6 +51,6 @@ // We mean it. // -#define Q_QML_PRIVATE_API_VERSION 7 +#define Q_QML_PRIVATE_API_VERSION 8 #endif // QQMLAPIVERSION_P_H diff --git a/src/qml/common/qqmljsdiagnosticmessage_p.h b/src/qml/common/qqmljsdiagnosticmessage_p.h index 763332ba76..9f5380ae0c 100644 --- a/src/qml/common/qqmljsdiagnosticmessage_p.h +++ b/src/qml/common/qqmljsdiagnosticmessage_p.h @@ -58,6 +58,8 @@ // QQmlSourceLocation -> line/column change. #include <private/qqmlapiversion_p.h> +#include "qqmljssourcelocation_p.h" + QT_BEGIN_NAMESPACE namespace QQmlJS { @@ -65,8 +67,7 @@ struct DiagnosticMessage { QString message; QtMsgType type = QtCriticalMsg; - quint32 line = 0; - quint32 column = 0; + SourceLocation loc; bool isError() const { diff --git a/src/qml/parser/qqmljssourcelocation_p.h b/src/qml/common/qqmljssourcelocation_p.h index d76e701d49..7c75541eb1 100644 --- a/src/qml/parser/qqmljssourcelocation_p.h +++ b/src/qml/common/qqmljssourcelocation_p.h @@ -40,8 +40,6 @@ #ifndef QQMLJSSOURCELOCATION_P_H #define QQMLJSSOURCELOCATION_P_H -#include "qqmljsglobal_p.h" - #include <QtCore/qglobal.h> // @@ -57,7 +55,7 @@ QT_BEGIN_NAMESPACE -namespace QQmlJS { namespace AST { +namespace QQmlJS { class SourceLocation { @@ -80,7 +78,7 @@ public: quint32 startColumn; }; -} } // namespace AST +} // namespace QQmlJS QT_END_NAMESPACE diff --git a/src/qml/common/qv4compileddata_p.h b/src/qml/common/qv4compileddata_p.h index 1480df2817..7d6ef14854 100644 --- a/src/qml/common/qv4compileddata_p.h +++ b/src/qml/common/qv4compileddata_p.h @@ -57,6 +57,7 @@ #include <QtCore/qvector.h> #include <QtCore/qstringlist.h> #include <QtCore/qhash.h> +#include <QtCore/qversionnumber.h> #if QT_CONFIG(temporaryfile) #include <QtCore/qsavefile.h> @@ -76,7 +77,7 @@ QT_BEGIN_NAMESPACE // Also change the comment behind the number to describe the latest change. This has the added // benefit that if another patch changes the version too, it will result in a merge conflict, and // not get removed silently. -#define QV4_DATA_STRUCTURE_VERSION 0x28// support inline components +#define QV4_DATA_STRUCTURE_VERSION 0x30// support additional required property features class QIODevice; class QQmlTypeNameCache; @@ -671,6 +672,12 @@ struct Property }; static_assert(sizeof(Property) == 12, "Property structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); +struct RequiredPropertyExtraData { + quint32_le nameIndex; +}; + +static_assert (sizeof(RequiredPropertyExtraData) == 4, "RequiredPropertyExtraData structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); + struct Alias { enum Flags : unsigned int { IsReadOnly = 0x1, @@ -741,13 +748,16 @@ struct Object Location locationOfIdProperty; quint32_le offsetToInlineComponents; quint16_le nInlineComponents; + quint32_le offsetToRequiredPropertyExtraData; + quint16_le nRequiredPropertyExtraData; // Function[] // Property[] // Signal[] // Binding[] // InlineComponent[] +// RequiredPropertyExtraData[] - static int calculateSizeExcludingSignalsAndEnums(int nFunctions, int nProperties, int nAliases, int nEnums, int nSignals, int nBindings, int nNamedObjectsInComponent, int nInlineComponents) + static int calculateSizeExcludingSignalsAndEnums(int nFunctions, int nProperties, int nAliases, int nEnums, int nSignals, int nBindings, int nNamedObjectsInComponent, int nInlineComponents, int nRequiredPropertyExtraData) { return ( sizeof(Object) + nFunctions * sizeof(quint32) @@ -758,6 +768,7 @@ struct Object + nBindings * sizeof(Binding) + nNamedObjectsInComponent * sizeof(int) + nInlineComponents * sizeof(InlineComponent) + + nRequiredPropertyExtraData * sizeof(RequiredPropertyExtraData) + 0x7 ) & ~0x7; } @@ -811,6 +822,16 @@ struct Object return reinterpret_cast<const InlineComponent*>(reinterpret_cast<const char *>(this) + offsetToInlineComponents); } + const RequiredPropertyExtraData *requiredPropertyExtraDataAt(int idx) const + { + return requiredPropertyExtraDataTable() + idx; + } + + const RequiredPropertyExtraData *requiredPropertyExtraDataTable() const + { + return reinterpret_cast<const RequiredPropertyExtraData*>(reinterpret_cast<const char *>(this) + offsetToRequiredPropertyExtraData); + } + // --- QQmlPropertyCacheCreator interface int propertyCount() const { return nProperties; } int aliasCount() const { return nAliases; } @@ -839,10 +860,14 @@ struct Object InlineComponentIterator inlineComponentsBegin() const {return InlineComponentIterator(this, 0);} InlineComponentIterator inlineComponentsEnd() const {return InlineComponentIterator(this, nInlineComponents);} + typedef TableIterator<RequiredPropertyExtraData, Object, &Object::requiredPropertyExtraDataAt> RequiredPropertyExtraDataIterator; + RequiredPropertyExtraDataIterator requiredPropertyExtraDataBegin() const {return RequiredPropertyExtraDataIterator(this, 0); }; + RequiredPropertyExtraDataIterator requiredPropertyExtraDataEnd() const {return RequiredPropertyExtraDataIterator(this, nRequiredPropertyExtraData); }; + int namedObjectsInComponentCount() const { return nNamedObjectsInComponent; } // --- }; -static_assert(sizeof(Object) == 76, "Object structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); +static_assert(sizeof(Object) == 84, "Object structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct Import { @@ -857,14 +882,16 @@ struct Import quint32_le uriIndex; quint32_le qualifierIndex; - qint32_le majorVersion; - qint32_le minorVersion; - Location location; + QTypeRevision version; + quint16_le reserved; - Import() { type = 0; uriIndex = 0; qualifierIndex = 0; majorVersion = 0; minorVersion = 0; } + Import() + { + type = 0; uriIndex = 0; qualifierIndex = 0; version = QTypeRevision::zero(); reserved = 0; + } }; -static_assert(sizeof(Import) == 24, "Import structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); +static_assert(sizeof(Import) == 20, "Import structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct QmlUnit { diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 811f88cb73..5217e11115 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -64,6 +64,33 @@ using namespace QQmlJS; return false; \ } +void Object::simplifyRequiredProperties() { + // if a property of the current object was marked as required + // do not store that information in the ExtraData + // but rather mark the property as required + QSet<int> required; + for (auto it = this->requiredPropertyExtraDataBegin(); it != this->requiredPropertyExtraDataEnd(); ++it) + required.insert(it->nameIndex); + if (required.isEmpty()) + return; + for (auto it = this->propertiesBegin(); it != this->propertiesEnd(); ++it) { + auto requiredIt = required.find(it->nameIndex); + if (requiredIt != required.end()) { + it->isRequired = true; + required.erase(requiredIt); + } + } + QmlIR::RequiredPropertyExtraData *prev = nullptr; + auto current = this->requiredPropertyExtraDatas->first; + while (current) { + if (required.contains(current->nameIndex)) + prev = current; + else + requiredPropertyExtraDatas->unlink(prev, current); + current = current->next; + } +} + bool Parameter::init(QV4::Compiler::JSUnitGenerator *stringGenerator, const QString ¶meterName, const QString &typeName) { @@ -142,7 +169,7 @@ QV4::CompiledData::BuiltinType Parameter::stringToBuiltinType(const QString &typ return QV4::CompiledData::BuiltinType::InvalidBuiltin; } -void Object::init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, const QQmlJS::AST::SourceLocation &loc) +void Object::init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, const QQmlJS::SourceLocation &loc) { inheritedTypeNameIndex = typeNameIndex; @@ -162,10 +189,11 @@ void Object::init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, cons functions = pool->New<PoolList<Function> >(); functionsAndExpressions = pool->New<PoolList<CompiledFunctionOrExpression> >(); inlineComponents = pool->New<PoolList<InlineComponent>>(); + requiredPropertyExtraDatas = pool->New<PoolList<RequiredPropertyExtraData>>(); declarationsOverride = nullptr; } -QString IRBuilder::sanityCheckFunctionNames(Object *obj, const QSet<QString> &illegalNames, QQmlJS::AST::SourceLocation *errorLocation) +QString IRBuilder::sanityCheckFunctionNames(Object *obj, const QSet<QString> &illegalNames, QQmlJS::SourceLocation *errorLocation) { QSet<int> functionNames; for (auto functionit = obj->functionsBegin(); functionit != obj->functionsEnd(); ++functionit) { @@ -221,7 +249,7 @@ QString Object::appendSignal(Signal *signal) return QString(); // no error } -QString Object::appendProperty(Property *prop, const QString &propertyName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation) +QString Object::appendProperty(Property *prop, const QString &propertyName, bool isDefaultProperty, const QQmlJS::SourceLocation &defaultToken, QQmlJS::SourceLocation *errorLocation) { Object *target = declarationsOverride; if (!target) @@ -245,7 +273,7 @@ QString Object::appendProperty(Property *prop, const QString &propertyName, bool return QString(); // no error } -QString Object::appendAlias(Alias *alias, const QString &aliasName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation) +QString Object::appendAlias(Alias *alias, const QString &aliasName, bool isDefaultProperty, const QQmlJS::SourceLocation &defaultToken, QQmlJS::SourceLocation *errorLocation) { Object *target = declarationsOverride; if (!target) @@ -287,6 +315,11 @@ void Object::appendInlineComponent(InlineComponent *ic) inlineComponents->append(ic); } +void Object::appendRequiredPropertyExtraData(RequiredPropertyExtraData *extraData) +{ + requiredPropertyExtraDatas->append(extraData); +} + QString Object::appendBinding(Binding *b, bool isListBinding) { const bool bindingToDefaultProperty = (b->propertyNameIndex == quint32(0)); @@ -325,8 +358,8 @@ QString Object::bindingAsString(Document *doc, int scriptIndex) const QQmlJS::AST::Node *node = foe->node; if (QQmlJS::AST::ExpressionStatement *exprStmt = QQmlJS::AST::cast<QQmlJS::AST::ExpressionStatement *>(node)) node = exprStmt->expression; - QQmlJS::AST::SourceLocation start = node->firstSourceLocation(); - QQmlJS::AST::SourceLocation end = node->lastSourceLocation(); + QQmlJS::SourceLocation start = node->firstSourceLocation(); + QQmlJS::SourceLocation end = node->lastSourceLocation(); return doc->code.mid(start.offset, end.offset + end.length - start.offset); } @@ -374,11 +407,7 @@ void ScriptDirectivesCollector::importModule(const QString &uri, const QString & QV4::CompiledData::Import *import = engine->pool()->New<QV4::CompiledData::Import>(); import->type = QV4::CompiledData::Import::ImportLibrary; import->uriIndex = jsGenerator->registerString(uri); - int vmaj; - int vmin; - IRBuilder::extractVersion(QStringRef(&version), &vmaj, &vmin); - import->majorVersion = vmaj; - import->minorVersion = vmin; + import->version = IRBuilder::extractVersion(QStringRef(&version)); import->qualifierIndex = jsGenerator->registerString(module); import->location.line = lineNumber; import->location.column = column; @@ -409,7 +438,7 @@ bool IRBuilder::generateFromQml(const QString &code, const QString &url, Documen // Extract errors from the parser for (const QQmlJS::DiagnosticMessage &m : diagnosticMessages) { if (m.isWarning()) { - qWarning("%s:%d : %s", qPrintable(url), m.line, qPrintable(m.message)); + qWarning("%s:%d : %s", qPrintable(url), m.loc.startLine, qPrintable(m.message)); continue; } @@ -437,7 +466,7 @@ bool IRBuilder::generateFromQml(const QString &code, const QString &url, Documen accept(program->headers); if (program->members->next) { - QQmlJS::AST::SourceLocation loc = program->members->next->firstSourceLocation(); + QQmlJS::SourceLocation loc = program->members->next->firstSourceLocation(); recordError(loc, QCoreApplication::translate("QQmlParser", "Unexpected object definition")); return false; } @@ -452,6 +481,10 @@ bool IRBuilder::generateFromQml(const QString &code, const QString &url, Documen qSwap(_imports, output->imports); qSwap(_pragmas, output->pragmas); qSwap(_objects, output->objects); + + for (auto object: output->objects) + object->simplifyRequiredProperties(); + return errors.isEmpty(); } @@ -498,7 +531,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiObjectDefinition *node) int idx = 0; if (!defineQMLObject(&idx, node)) return false; - const QQmlJS::AST::SourceLocation nameLocation = node->qualifiedTypeNameId->identifierToken; + const QQmlJS::SourceLocation nameLocation = node->qualifiedTypeNameId->identifierToken; appendBinding(nameLocation, nameLocation, emptyStringIndex, idx); } else { int idx = 0; @@ -553,7 +586,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiScriptBinding *node) bool IRBuilder::visit(QQmlJS::AST::UiArrayBinding *node) { - const QQmlJS::AST::SourceLocation qualifiedNameLocation = node->qualifiedId->identifierToken; + const QQmlJS::SourceLocation qualifiedNameLocation = node->qualifiedId->identifierToken; Object *object = nullptr; QQmlJS::AST::UiQualifiedId *name = node->qualifiedId; if (!resolveQualifiedId(&name, &object)) @@ -618,7 +651,7 @@ void IRBuilder::accept(QQmlJS::AST::Node *node) QQmlJS::AST::Node::accept(node, this); } -bool IRBuilder::defineQMLObject(int *objectIndex, QQmlJS::AST::UiQualifiedId *qualifiedTypeNameId, const QQmlJS::AST::SourceLocation &location, QQmlJS::AST::UiObjectInitializer *initializer, Object *declarationsOverride) +bool IRBuilder::defineQMLObject(int *objectIndex, QQmlJS::AST::UiQualifiedId *qualifiedTypeNameId, const QQmlJS::SourceLocation &location, QQmlJS::AST::UiObjectInitializer *initializer, Object *declarationsOverride) { if (QQmlJS::AST::UiQualifiedId *lastName = qualifiedTypeNameId) { while (lastName->next) @@ -654,7 +687,7 @@ bool IRBuilder::defineQMLObject(int *objectIndex, QQmlJS::AST::UiQualifiedId *qu if (!errors.isEmpty()) return false; - QQmlJS::AST::SourceLocation loc; + QQmlJS::SourceLocation loc; QString error = sanityCheckFunctionNames(obj, illegalNames, &loc); if (!error.isEmpty()) { recordError(loc, error); @@ -715,16 +748,14 @@ bool IRBuilder::visit(QQmlJS::AST::UiImport *node) } if (node->version) { - import->majorVersion = node->version->majorVersion; - import->minorVersion = node->version->minorVersion; + import->version = node->version->version; } else if (import->type == QV4::CompiledData::Import::ImportLibrary) { recordError(node->importIdToken, QCoreApplication::translate("QQmlParser","Library import requires a version")); return false; } else { // For backward compatibility in how the imports are loaded we - // must otherwise initialize the major and minor version to -1. - import->majorVersion = -1; - import->minorVersion = -1; + // must otherwise initialize the major and minor version to invalid. + import->version = QTypeRevision(); } import->location.line = node->importToken.startLine; @@ -834,7 +865,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node) const QString signalName = node->name.toString(); signal->nameIndex = registerString(signalName); - QQmlJS::AST::SourceLocation loc = node->typeToken; + QQmlJS::SourceLocation loc = node->typeToken; signal->location.line = loc.startLine; signal->location.column = loc.startColumn; @@ -917,11 +948,11 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node) const QString propName = name.toString(); property->nameIndex = registerString(propName); - QQmlJS::AST::SourceLocation loc = node->firstSourceLocation(); + QQmlJS::SourceLocation loc = node->firstSourceLocation(); property->location.line = loc.startLine; property->location.column = loc.startColumn; - QQmlJS::AST::SourceLocation errorLocation; + QQmlJS::SourceLocation errorLocation; QString error; if (illegalNames.contains(propName)) @@ -962,7 +993,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiSourceElement *node) const int index = _object->functionsAndExpressions->append(foe); Function *f = New<Function>(); - QQmlJS::AST::SourceLocation loc = funDecl->identifierToken; + QQmlJS::SourceLocation loc = funDecl->identifierToken; f->location.line = loc.startLine; f->location.column = loc.startColumn; f->index = index; @@ -988,6 +1019,14 @@ bool IRBuilder::visit(QQmlJS::AST::UiSourceElement *node) return false; } +bool IRBuilder::visit(AST::UiRequired *ast) +{ + auto extraData = New<RequiredPropertyExtraData>(); + extraData->nameIndex = registerString(ast->name.toString()); + _object->appendRequiredPropertyExtraData(extraData); + return false; +} + QString IRBuilder::asString(QQmlJS::AST::UiQualifiedId *node) { QString s; @@ -1010,32 +1049,25 @@ QStringRef IRBuilder::asStringRef(QQmlJS::AST::Node *node) return textRefAt(node->firstSourceLocation(), node->lastSourceLocation()); } -void IRBuilder::extractVersion(const QStringRef &string, int *maj, int *min) +QTypeRevision IRBuilder::extractVersion(const QStringRef &string) { - *maj = -1; *min = -1; - - if (!string.isEmpty()) { - - int dot = string.indexOf(QLatin1Char('.')); + if (string.isEmpty()) + return QTypeRevision(); - if (dot < 0) { - *maj = string.toInt(); - *min = 0; - } else { - *maj = string.left(dot).toInt(); - *min = string.mid(dot + 1).toInt(); - } - } + const int dot = string.indexOf(QLatin1Char('.')); + return (dot < 0) + ? QTypeRevision::fromVersion(string.toInt(), 0) + : QTypeRevision::fromVersion(string.left(dot).toInt(), string.mid(dot + 1).toInt()); } -QStringRef IRBuilder::textRefAt(const QQmlJS::AST::SourceLocation &first, const QQmlJS::AST::SourceLocation &last) const +QStringRef IRBuilder::textRefAt(const QQmlJS::SourceLocation &first, const QQmlJS::SourceLocation &last) const { return QStringRef(&sourceCode, first.offset, last.offset + last.length - first.offset); } void IRBuilder::setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST::Statement *statement, QQmlJS::AST::Node *parentNode) { - QQmlJS::AST::SourceLocation loc = statement->firstSourceLocation(); + QQmlJS::SourceLocation loc = statement->firstSourceLocation(); binding->valueLocation.line = loc.startLine; binding->valueLocation.column = loc.startColumn; binding->type = QV4::CompiledData::Binding::Type_Invalid; @@ -1212,7 +1244,7 @@ void IRBuilder::tryGeneratingTranslationBinding(const QStringRef &base, AST::Arg void IRBuilder::appendBinding(QQmlJS::AST::UiQualifiedId *name, QQmlJS::AST::Statement *value, QQmlJS::AST::Node *parentNode) { - const QQmlJS::AST::SourceLocation qualifiedNameLocation = name->identifierToken; + const QQmlJS::SourceLocation qualifiedNameLocation = name->identifierToken; Object *object = nullptr; if (!resolveQualifiedId(&name, &object)) return; @@ -1227,7 +1259,7 @@ void IRBuilder::appendBinding(QQmlJS::AST::UiQualifiedId *name, QQmlJS::AST::Sta void IRBuilder::appendBinding(QQmlJS::AST::UiQualifiedId *name, int objectIndex, bool isOnAssignment) { - const QQmlJS::AST::SourceLocation qualifiedNameLocation = name->identifierToken; + const QQmlJS::SourceLocation qualifiedNameLocation = name->identifierToken; Object *object = nullptr; if (!resolveQualifiedId(&name, &object, isOnAssignment)) return; @@ -1236,7 +1268,7 @@ void IRBuilder::appendBinding(QQmlJS::AST::UiQualifiedId *name, int objectIndex, qSwap(_object, object); } -void IRBuilder::appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation, const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, +void IRBuilder::appendBinding(const QQmlJS::SourceLocation &qualifiedNameLocation, const QQmlJS::SourceLocation &nameLocation, quint32 propertyNameIndex, QQmlJS::AST::Statement *value, QQmlJS::AST::Node *parentNode) { Binding *binding = New<Binding>(); @@ -1252,7 +1284,7 @@ void IRBuilder::appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLo } } -void IRBuilder::appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation, const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, int objectIndex, bool isListItem, bool isOnAssignment) +void IRBuilder::appendBinding(const QQmlJS::SourceLocation &qualifiedNameLocation, const QQmlJS::SourceLocation &nameLocation, quint32 propertyNameIndex, int objectIndex, bool isListItem, bool isOnAssignment) { if (stringAt(propertyNameIndex) == QLatin1String("id")) { recordError(nameLocation, tr("Invalid component id specification")); @@ -1301,7 +1333,7 @@ bool IRBuilder::appendAlias(QQmlJS::AST::UiPublicMember *node) const QString propName = node->name.toString(); alias->nameIndex = registerString(propName); - QQmlJS::AST::SourceLocation loc = node->firstSourceLocation(); + QQmlJS::SourceLocation loc = node->firstSourceLocation(); alias->location.line = loc.startLine; alias->location.column = loc.startColumn; @@ -1310,7 +1342,7 @@ bool IRBuilder::appendAlias(QQmlJS::AST::UiPublicMember *node) if (!node->statement && !node->binding) COMPILE_EXCEPTION(loc, tr("No property alias location")); - QQmlJS::AST::SourceLocation rhsLoc; + QQmlJS::SourceLocation rhsLoc; if (node->binding) rhsLoc = node->binding->firstSourceLocation(); else if (node->statement) @@ -1345,7 +1377,7 @@ bool IRBuilder::appendAlias(QQmlJS::AST::UiPublicMember *node) propertyValue += QLatin1Char('.') + aliasReference.at(2); alias->propertyNameIndex = registerString(propertyValue); - QQmlJS::AST::SourceLocation errorLocation; + QQmlJS::SourceLocation errorLocation; QString error; if (illegalNames.contains(propName)) @@ -1371,9 +1403,9 @@ Object *IRBuilder::bindingsTarget() const return _object; } -bool IRBuilder::setId(const QQmlJS::AST::SourceLocation &idLocation, QQmlJS::AST::Statement *value) +bool IRBuilder::setId(const QQmlJS::SourceLocation &idLocation, QQmlJS::AST::Statement *value) { - QQmlJS::AST::SourceLocation loc = value->firstSourceLocation(); + QQmlJS::SourceLocation loc = value->firstSourceLocation(); QStringRef str; QQmlJS::AST::Node *node = value; @@ -1475,7 +1507,7 @@ bool IRBuilder::resolveQualifiedId(QQmlJS::AST::UiQualifiedId **nameToResolve, O binding->type = QV4::CompiledData::Binding::Type_GroupProperty; int objIndex = 0; - if (!defineQMLObject(&objIndex, nullptr, QQmlJS::AST::SourceLocation(), nullptr, nullptr)) + if (!defineQMLObject(&objIndex, nullptr, QQmlJS::SourceLocation(), nullptr, nullptr)) return false; binding->value.objectIndex = objIndex; @@ -1498,11 +1530,10 @@ bool IRBuilder::resolveQualifiedId(QQmlJS::AST::UiQualifiedId **nameToResolve, O return true; } -void IRBuilder::recordError(const QQmlJS::AST::SourceLocation &location, const QString &description) +void IRBuilder::recordError(const QQmlJS::SourceLocation &location, const QString &description) { QQmlJS::DiagnosticMessage error; - error.line = location.startLine; - error.column = location.startColumn; + error.loc = location; error.message = description; errors << error; } @@ -1590,7 +1621,7 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen uint nextOffset = objectOffset + objectOffsetTableSize; for (Object *o : qAsConst(output.objects)) { objectOffsets.insert(o, nextOffset); - nextOffset += QV4::CompiledData::Object::calculateSizeExcludingSignalsAndEnums(o->functionCount(), o->propertyCount(), o->aliasCount(), o->enumCount(), o->signalCount(), o->bindingCount(), o->namedObjectsInComponent.size(), o->inlineComponentCount()); + nextOffset += QV4::CompiledData::Object::calculateSizeExcludingSignalsAndEnums(o->functionCount(), o->propertyCount(), o->aliasCount(), o->enumCount(), o->signalCount(), o->bindingCount(), o->namedObjectsInComponent.size(), o->inlineComponentCount(), o->requiredPropertyExtraDataCount()); int signalTableSize = 0; for (const Signal *s = o->firstSignal(); s; s = s->next) @@ -1673,6 +1704,10 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen objectToWrite->offsetToInlineComponents = nextOffset; nextOffset += objectToWrite->nInlineComponents * sizeof (QV4::CompiledData::InlineComponent); + objectToWrite->nRequiredPropertyExtraData = o->requiredPropertyExtraDataCount(); + objectToWrite->offsetToRequiredPropertyExtraData = nextOffset; + nextOffset += objectToWrite->nRequiredPropertyExtraData * sizeof(QV4::CompiledData::RequiredPropertyExtraData); + quint32_le *functionsTable = reinterpret_cast<quint32_le *>(objectPtr + objectToWrite->offsetToFunctions); for (const Function *f = o->firstFunction(); f; f = f->next) *functionsTable++ = o->runtimeFunctionIndices.at(f->index); @@ -1752,6 +1787,14 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen *icToWrite = *ic; inlineComponentPtr += sizeof(QV4::CompiledData::InlineComponent); } + + char *requiredPropertyExtraDataPtr = objectPtr + objectToWrite->offsetToRequiredPropertyExtraData; + for (auto it = o->requiredPropertyExtraDataBegin(); it != o->requiredPropertyExtraDataEnd(); ++it) { + const RequiredPropertyExtraData *extraData = it.ptr; + QV4::CompiledData::RequiredPropertyExtraData *extraDataToWrite = reinterpret_cast<QV4::CompiledData::RequiredPropertyExtraData*>(requiredPropertyExtraDataPtr); + *extraDataToWrite = *extraData; + requiredPropertyExtraDataPtr += sizeof(QV4::CompiledData::RequiredPropertyExtraData); + } } if (!output.javaScriptCompilationUnit.data) { diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index d4f2eb8dd4..1f2c11f7f3 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -285,6 +285,11 @@ struct Alias : public QV4::CompiledData::Alias Alias *next; }; +struct RequiredPropertyExtraData : public QV4::CompiledData::RequiredPropertyExtraData +{ + RequiredPropertyExtraData *next; +}; + struct Function { QV4::CompiledData::Location location; @@ -341,6 +346,9 @@ public: int functionCount() const { return functions->count; } const InlineComponent *inlineComponent() const { return inlineComponents->first; } int inlineComponentCount() const { return inlineComponents->count; } + const RequiredPropertyExtraData *requiredPropertyExtraData() const {return requiredPropertyExtraDatas->first; } + int requiredPropertyExtraDataCount() const { return requiredPropertyExtraDatas->count; } + void simplifyRequiredProperties(); PoolList<Binding>::Iterator bindingsBegin() const { return bindings->begin(); } PoolList<Binding>::Iterator bindingsEnd() const { return bindings->end(); } @@ -356,19 +364,22 @@ public: PoolList<Function>::Iterator functionsEnd() const { return functions->end(); } PoolList<InlineComponent>::Iterator inlineComponentsBegin() const { return inlineComponents->begin(); } PoolList<InlineComponent>::Iterator inlineComponentsEnd() const { return inlineComponents->end(); } + PoolList<RequiredPropertyExtraData>::Iterator requiredPropertyExtraDataBegin() const {return requiredPropertyExtraDatas->begin(); } + PoolList<RequiredPropertyExtraData>::Iterator requiredPropertyExtraDataEnd() const {return requiredPropertyExtraDatas->end(); } // If set, then declarations for this object (and init bindings for these) should go into the // specified object. Used for declarations inside group properties. Object *declarationsOverride; - void init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, const QQmlJS::AST::SourceLocation &location = QQmlJS::AST::SourceLocation()); + void init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, const QQmlJS::SourceLocation &location = QQmlJS::SourceLocation()); QString appendEnum(Enum *enumeration); QString appendSignal(Signal *signal); - QString appendProperty(Property *prop, const QString &propertyName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation); - QString appendAlias(Alias *prop, const QString &aliasName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation); + QString appendProperty(Property *prop, const QString &propertyName, bool isDefaultProperty, const QQmlJS::SourceLocation &defaultToken, QQmlJS::SourceLocation *errorLocation); + QString appendAlias(Alias *prop, const QString &aliasName, bool isDefaultProperty, const QQmlJS::SourceLocation &defaultToken, QQmlJS::SourceLocation *errorLocation); void appendFunction(QmlIR::Function *f); void appendInlineComponent(InlineComponent *ic); + void appendRequiredPropertyExtraData(RequiredPropertyExtraData *extraData); QString appendBinding(Binding *b, bool isListBinding); Binding *findBinding(quint32 nameIndex) const; @@ -393,6 +404,7 @@ private: PoolList<Binding> *bindings; PoolList<Function> *functions; PoolList<InlineComponent> *inlineComponents; + PoolList<RequiredPropertyExtraData> *requiredPropertyExtraDatas; }; struct Q_QMLCOMPILER_PRIVATE_EXPORT Pragma @@ -469,27 +481,28 @@ public: bool visit(QQmlJS::AST::UiPublicMember *ast) override; bool visit(QQmlJS::AST::UiScriptBinding *ast) override; bool visit(QQmlJS::AST::UiSourceElement *ast) override; + bool visit(QQmlJS::AST::UiRequired *ast) override; void throwRecursionDepthError() override { - recordError(QQmlJS::AST::SourceLocation(), + recordError(QQmlJS::SourceLocation(), QStringLiteral("Maximum statement or expression depth exceeded")); } void accept(QQmlJS::AST::Node *node); // returns index in _objects - bool defineQMLObject(int *objectIndex, QQmlJS::AST::UiQualifiedId *qualifiedTypeNameId, const QQmlJS::AST::SourceLocation &location, QQmlJS::AST::UiObjectInitializer *initializer, Object *declarationsOverride = nullptr); + bool defineQMLObject(int *objectIndex, QQmlJS::AST::UiQualifiedId *qualifiedTypeNameId, const QQmlJS::SourceLocation &location, QQmlJS::AST::UiObjectInitializer *initializer, Object *declarationsOverride = nullptr); bool defineQMLObject(int *objectIndex, QQmlJS::AST::UiObjectDefinition *node, Object *declarationsOverride = nullptr) { return defineQMLObject(objectIndex, node->qualifiedTypeNameId, node->qualifiedTypeNameId->firstSourceLocation(), node->initializer, declarationsOverride); } static QString asString(QQmlJS::AST::UiQualifiedId *node); QStringRef asStringRef(QQmlJS::AST::Node *node); - static void extractVersion(const QStringRef &string, int *maj, int *min); - QStringRef textRefAt(const QQmlJS::AST::SourceLocation &loc) const + static QTypeRevision extractVersion(const QStringRef &string); + QStringRef textRefAt(const QQmlJS::SourceLocation &loc) const { return QStringRef(&sourceCode, loc.offset, loc.length); } - QStringRef textRefAt(const QQmlJS::AST::SourceLocation &first, - const QQmlJS::AST::SourceLocation &last) const; + QStringRef textRefAt(const QQmlJS::SourceLocation &first, + const QQmlJS::SourceLocation &last) const; void setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST::Statement *statement, QQmlJS::AST::Node *parentNode); @@ -498,24 +511,24 @@ public: void appendBinding(QQmlJS::AST::UiQualifiedId *name, QQmlJS::AST::Statement *value, QQmlJS::AST::Node *parentNode); void appendBinding(QQmlJS::AST::UiQualifiedId *name, int objectIndex, bool isOnAssignment = false); - void appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation, - const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, + void appendBinding(const QQmlJS::SourceLocation &qualifiedNameLocation, + const QQmlJS::SourceLocation &nameLocation, quint32 propertyNameIndex, QQmlJS::AST::Statement *value, QQmlJS::AST::Node *parentNode); - void appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation, - const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, + void appendBinding(const QQmlJS::SourceLocation &qualifiedNameLocation, + const QQmlJS::SourceLocation &nameLocation, quint32 propertyNameIndex, int objectIndex, bool isListItem = false, bool isOnAssignment = false); bool appendAlias(QQmlJS::AST::UiPublicMember *node); Object *bindingsTarget() const; - bool setId(const QQmlJS::AST::SourceLocation &idLocation, QQmlJS::AST::Statement *value); + bool setId(const QQmlJS::SourceLocation &idLocation, QQmlJS::AST::Statement *value); // resolves qualified name (font.pixelSize for example) and returns the last name along // with the object any right-hand-side of a binding should apply to. bool resolveQualifiedId(QQmlJS::AST::UiQualifiedId **nameToResolve, Object **object, bool onAssignment = false); - void recordError(const QQmlJS::AST::SourceLocation &location, const QString &description); + void recordError(const QQmlJS::SourceLocation &location, const QString &description); quint32 registerString(const QString &str) const { return jsGenerator->registerString(str); } template <typename _Tp> _Tp *New() { return pool->New<_Tp>(); } @@ -525,7 +538,7 @@ public: static bool isStatementNodeScript(QQmlJS::AST::Statement *statement); static bool isRedundantNullInitializerForPropertyDeclaration(Property *property, QQmlJS::AST::Statement *statement); - QString sanityCheckFunctionNames(Object *obj, const QSet<QString> &illegalNames, QQmlJS::AST::SourceLocation *errorLocation); + QString sanityCheckFunctionNames(Object *obj, const QSet<QString> &illegalNames, QQmlJS::SourceLocation *errorLocation); QList<QQmlJS::DiagnosticMessage> errors; diff --git a/src/qml/compiler/qv4bytecodegenerator.cpp b/src/qml/compiler/qv4bytecodegenerator.cpp index 7df1614ffe..f8a41edb6a 100644 --- a/src/qml/compiler/qv4bytecodegenerator.cpp +++ b/src/qml/compiler/qv4bytecodegenerator.cpp @@ -45,7 +45,7 @@ QT_USE_NAMESPACE using namespace QV4; using namespace Moth; -void BytecodeGenerator::setLocation(const QQmlJS::AST::SourceLocation &loc) +void BytecodeGenerator::setLocation(const QQmlJS::SourceLocation &loc) { currentLine = static_cast<int>(loc.startLine); } diff --git a/src/qml/compiler/qv4bytecodegenerator_p.h b/src/qml/compiler/qv4bytecodegenerator_p.h index 8c509dd9f1..1895a34a68 100644 --- a/src/qml/compiler/qv4bytecodegenerator_p.h +++ b/src/qml/compiler/qv4bytecodegenerator_p.h @@ -56,10 +56,8 @@ QT_BEGIN_NAMESPACE namespace QQmlJS { -namespace AST { class SourceLocation; } -} namespace QV4 { @@ -244,7 +242,7 @@ QT_WARNING_POP - void setLocation(const QQmlJS::AST::SourceLocation &loc); + void setLocation(const QQmlJS::SourceLocation &loc); ExceptionHandler *exceptionHandler() const { return currentExceptionHandler; diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index d61456f38d..4588690307 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -3821,8 +3821,7 @@ void Codegen::throwError(ErrorType errorType, const SourceLocation &loc, const Q _errorType = errorType; _error.message = detail; - _error.line = loc.startLine; - _error.column = loc.startColumn; + _error.loc = loc; } void Codegen::throwSyntaxError(const SourceLocation &loc, const QString &detail) @@ -4105,7 +4104,7 @@ Codegen::Reference Codegen::Reference::asLValue() const case Accumulator: Q_UNREACHABLE(); case Super: - codegen->throwSyntaxError(AST::SourceLocation(), QStringLiteral("Super lvalues not implemented.")); + codegen->throwSyntaxError(SourceLocation(), QStringLiteral("Super lvalues not implemented.")); return *this; case Member: if (!propertyBase.isStackSlot()) { diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index 82a4fc3289..255698d790 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -661,12 +661,12 @@ protected: bool visit(QQmlJS::AST::UiSourceElement *ast) override; bool throwSyntaxErrorOnEvalOrArgumentsInStrictMode(const Reference &r, - const QQmlJS::AST::SourceLocation &loc); - virtual void throwSyntaxError(const QQmlJS::AST::SourceLocation &loc, const QString &detail); - virtual void throwReferenceError(const QQmlJS::AST::SourceLocation &loc, const QString &detail); + const QQmlJS::SourceLocation &loc); + virtual void throwSyntaxError(const QQmlJS::SourceLocation &loc, const QString &detail); + virtual void throwReferenceError(const QQmlJS::SourceLocation &loc, const QString &detail); void throwRecursionDepthError() override { - throwSyntaxError(QQmlJS::AST::SourceLocation(), + throwSyntaxError(QQmlJS::SourceLocation(), QStringLiteral("Maximum statement or expression depth exceeded")); } @@ -700,7 +700,7 @@ public: Reference referenceForName( const QString &name, bool lhs, - const QQmlJS::AST::SourceLocation &accessLocation = QQmlJS::AST::SourceLocation()); + const QQmlJS::SourceLocation &accessLocation = QQmlJS::SourceLocation()); QV4::CompiledData::CompilationUnit generateCompilationUnit(bool generateUnitData = true); static QV4::CompiledData::CompilationUnit compileModule( @@ -810,7 +810,7 @@ protected: private: VolatileMemoryLocations scanVolatileMemoryLocations(QQmlJS::AST::Node *ast); void handleConstruct(const Reference &base, QQmlJS::AST::ArgumentList *args); - void throwError(ErrorType errorType, const QQmlJS::AST::SourceLocation &loc, + void throwError(ErrorType errorType, const QQmlJS::SourceLocation &loc, const QString &detail); }; diff --git a/src/qml/compiler/qv4compilercontext.cpp b/src/qml/compiler/qv4compilercontext.cpp index 88837b0feb..872fc94dc9 100644 --- a/src/qml/compiler/qv4compilercontext.cpp +++ b/src/qml/compiler/qv4compilercontext.cpp @@ -45,6 +45,7 @@ QT_USE_NAMESPACE using namespace QV4; using namespace QV4::Compiler; using namespace QQmlJS::AST; +using namespace QQmlJS; QT_BEGIN_NAMESPACE @@ -86,7 +87,7 @@ bool Context::Member::requiresTDZCheck(const SourceLocation &accessLocation, boo } bool Context::addLocalVar(const QString &name, Context::MemberType type, VariableScope scope, FunctionExpression *function, - const QQmlJS::AST::SourceLocation &endOfInitializer) + const QQmlJS::SourceLocation &endOfInitializer) { // ### can this happen? if (name.isEmpty()) @@ -122,7 +123,7 @@ bool Context::addLocalVar(const QString &name, Context::MemberType type, Variabl return true; } -Context::ResolvedName Context::resolveName(const QString &name, const QQmlJS::AST::SourceLocation &accessLocation) +Context::ResolvedName Context::resolveName(const QString &name, const QQmlJS::SourceLocation &accessLocation) { int scope = 0; Context *c = this; diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h index 8c124ac409..4a14009c35 100644 --- a/src/qml/compiler/qv4compilercontext_p.h +++ b/src/qml/compiler/qv4compilercontext_p.h @@ -183,10 +183,10 @@ struct Context { QQmlJS::AST::VariableScope scope = QQmlJS::AST::VariableScope::Var; mutable bool canEscape = false; QQmlJS::AST::FunctionExpression *function = nullptr; - QQmlJS::AST::SourceLocation endOfInitializerLocation; + QQmlJS::SourceLocation endOfInitializerLocation; bool isLexicallyScoped() const { return this->scope != QQmlJS::AST::VariableScope::Var; } - bool requiresTDZCheck(const QQmlJS::AST::SourceLocation &accessLocation, bool accessAcrossContextBoundaries) const; + bool requiresTDZCheck(const QQmlJS::SourceLocation &accessLocation, bool accessAcrossContextBoundaries) const; }; typedef QMap<QString, Member> MemberMap; @@ -227,7 +227,7 @@ struct Context { bool isWithBlock = false; bool isCatchBlock = false; QString caughtVariable; - QQmlJS::AST::SourceLocation lastBlockInitializerLocation; + QQmlJS::SourceLocation lastBlockInitializerLocation; enum UsesArgumentsObject { ArgumentsObjectUnknown, @@ -331,7 +331,7 @@ struct Context { } bool addLocalVar(const QString &name, MemberType contextType, QQmlJS::AST::VariableScope scope, QQmlJS::AST::FunctionExpression *function = nullptr, - const QQmlJS::AST::SourceLocation &endOfInitializer = QQmlJS::AST::SourceLocation()); + const QQmlJS::SourceLocation &endOfInitializer = QQmlJS::SourceLocation()); struct ResolvedName { enum Type { @@ -348,10 +348,10 @@ struct Context { bool requiresTDZCheck = false; int scope = -1; int index = -1; - QQmlJS::AST::SourceLocation endOfDeclarationLocation; + QQmlJS::SourceLocation endOfDeclarationLocation; bool isValid() const { return type != Unresolved; } }; - ResolvedName resolveName(const QString &name, const QQmlJS::AST::SourceLocation &accessLocation); + ResolvedName resolveName(const QString &name, const QQmlJS::SourceLocation &accessLocation); void emitBlockHeader(Compiler::Codegen *codegen); void emitBlockFooter(Compiler::Codegen *codegen); diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp index ab0ebf3d4b..a1ddee8234 100644 --- a/src/qml/compiler/qv4compilerscanfunctions.cpp +++ b/src/qml/compiler/qv4compilerscanfunctions.cpp @@ -55,7 +55,7 @@ using namespace QV4::Compiler; using namespace QQmlJS; using namespace QQmlJS::AST; -static CompiledData::Location location(const QQmlJS::AST::SourceLocation &astLocation) +static CompiledData::Location location(const QQmlJS::SourceLocation &astLocation) { CompiledData::Location target; target.line = astLocation.startLine; @@ -129,7 +129,7 @@ void ScanFunctions::checkDirectivePrologue(StatementList *ast) } } -void ScanFunctions::checkName(const QStringRef &name, const SourceLocation &loc) +void ScanFunctions::checkName(const QStringRef &name, const QQmlJS::SourceLocation &loc) { if (_context->isStrict) { if (name == QLatin1String("implements") @@ -330,7 +330,7 @@ bool ScanFunctions::visit(PatternElement *ast) BoundNames names; ast->boundNames(&names); - QQmlJS::AST::SourceLocation lastInitializerLocation = ast->lastSourceLocation(); + QQmlJS::SourceLocation lastInitializerLocation = ast->lastSourceLocation(); if (_context->lastBlockInitializerLocation.isValid()) lastInitializerLocation = _context->lastBlockInitializerLocation; diff --git a/src/qml/compiler/qv4compilerscanfunctions_p.h b/src/qml/compiler/qv4compilerscanfunctions_p.h index 2de80eac44..e39aa2454e 100644 --- a/src/qml/compiler/qv4compilerscanfunctions_p.h +++ b/src/qml/compiler/qv4compilerscanfunctions_p.h @@ -97,7 +97,7 @@ protected: void checkDirectivePrologue(QQmlJS::AST::StatementList *ast); - void checkName(const QStringRef &name, const QQmlJS::AST::SourceLocation &loc); + void checkName(const QStringRef &name, const QQmlJS::SourceLocation &loc); bool visit(QQmlJS::AST::Program *ast) override; void endVisit(QQmlJS::AST::Program *) override; diff --git a/src/qml/debugger/qqmldebugserviceinterfaces.cpp b/src/qml/debugger/qqmldebugserviceinterfaces.cpp index 76205c7760..3df1a21bda 100644 --- a/src/qml/debugger/qqmldebugserviceinterfaces.cpp +++ b/src/qml/debugger/qqmldebugserviceinterfaces.cpp @@ -48,6 +48,7 @@ const QString QQmlProfilerService::s_key = QStringLiteral("CanvasFrameRate"); const QString QDebugMessageService::s_key = QStringLiteral("DebugMessages"); const QString QQmlEngineControlService::s_key = QStringLiteral("EngineControl"); const QString QQmlNativeDebugService::s_key = QStringLiteral("NativeQmlDebugger"); +const QString QQmlDebugTranslationService::s_key = QStringLiteral("DebugTranslation"); QT_END_NAMESPACE diff --git a/src/qml/debugger/qqmldebugserviceinterfaces_p.h b/src/qml/debugger/qqmldebugserviceinterfaces_p.h index 01693aee24..b259e047a1 100644 --- a/src/qml/debugger/qqmldebugserviceinterfaces_p.h +++ b/src/qml/debugger/qqmldebugserviceinterfaces_p.h @@ -65,6 +65,7 @@ QT_BEGIN_NAMESPACE class QWindow; class QQuickWindow; +class QQmlTranslationBinding; #if !QT_CONFIG(qml_debug) @@ -103,6 +104,11 @@ public: class QDebugMessageService {}; class QQmlEngineControlService {}; class QQmlNativeDebugService {}; +class QQmlDebugTranslationService { +public: + virtual QString foundElidedText(QObject *, const QString &, const QString &) {return {};} + virtual void foundTranslationBinding(QQmlTranslationBinding *, QObject *, QQmlContextData *) {} +}; #else @@ -162,6 +168,22 @@ protected: QQmlBoundSignal *nextSignal(QQmlBoundSignal *prev) { return prev->m_nextSignal; } }; +class Q_QML_PRIVATE_EXPORT QQmlDebugTranslationService : public QQmlDebugService +{ + Q_OBJECT +public: + static const QString s_key; + + virtual QString foundElidedText(QObject *qQuickTextObject, const QString &layoutText, const QString &elideText) = 0; + virtual void foundTranslationBinding(QQmlTranslationBinding *binding, QObject *scopeObject, QQmlContextData *contextData) = 0; +protected: + friend class QQmlDebugConnector; + + QQmlDebugTranslationService(float version, QObject *parent = nullptr) : + QQmlDebugService(s_key, version, parent) {} + +}; + class Q_QML_PRIVATE_EXPORT QQmlInspectorService : public QQmlDebugService { Q_OBJECT diff --git a/src/qml/doc/snippets/code/backend/backend.h b/src/qml/doc/snippets/code/backend/backend.h index fa7ce9eb86..6c64236bc7 100644 --- a/src/qml/doc/snippets/code/backend/backend.h +++ b/src/qml/doc/snippets/code/backend/backend.h @@ -53,11 +53,13 @@ #include <QObject> #include <QString> +#include <qqml.h> class BackEnd : public QObject { Q_OBJECT Q_PROPERTY(QString userName READ userName WRITE setUserName NOTIFY userNameChanged) + QML_ELEMENT public: explicit BackEnd(QObject *parent = nullptr); diff --git a/src/qml/doc/snippets/code/backend/backend.pro b/src/qml/doc/snippets/code/backend/backend.pro new file mode 100644 index 0000000000..8bd2422718 --- /dev/null +++ b/src/qml/doc/snippets/code/backend/backend.pro @@ -0,0 +1,17 @@ +QT += qml + +#![registration] +CONFIG += qmltypes +QML_IMPORT_NAME = io.qt.examples.backend +QML_IMPORT_MAJOR_VERSION = 1 +#![registration] + +HEADERS += \ + backend.h + +SOURCES += \ + backend.cpp \ + main.cpp + +RESOURCES += \ + main.qml diff --git a/src/qml/doc/snippets/code/backend/main.cpp b/src/qml/doc/snippets/code/backend/main.cpp index 91a012dfda..52fcb38621 100644 --- a/src/qml/doc/snippets/code/backend/main.cpp +++ b/src/qml/doc/snippets/code/backend/main.cpp @@ -51,14 +51,10 @@ #include <QGuiApplication> #include <QQmlApplicationEngine> -#include "backend.h" - int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); - qmlRegisterType<BackEnd>("io.qt.examples.backend", 1, 0, "BackEnd"); - QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); diff --git a/src/qml/doc/snippets/qml/integrating-javascript/scarceresources/avatarExample.cpp b/src/qml/doc/snippets/qml/integrating-javascript/scarceresources/avatarExample.cpp index d74cc13d04..b41a9b4dff 100644 --- a/src/qml/doc/snippets/qml/integrating-javascript/scarceresources/avatarExample.cpp +++ b/src/qml/doc/snippets/qml/integrating-javascript/scarceresources/avatarExample.cpp @@ -51,84 +51,102 @@ #include "avatarExample.h" #include <QQmlEngine> #include <QQmlComponent> +#include <QGuiApplication> -void registerTypes() +struct Expectations { -//![0] - qmlRegisterType<AvatarExample>("Qt.example", 1, 0, "AvatarExample"); -//![0] -} + QQmlEngine engine; -void expectOne() -{ + void expectOne() + { //![1] -QQmlComponent component(&engine, "exampleOne.qml"); -QObject *object = component.create(); -// The scarce resource will have been released automatically -// by this point, after the binding expression was evaluated. -delete object; + QQmlComponent component(&engine, "qrc:/exampleOne.qml"); + QObject *object = component.create(); + // The scarce resource will have been released automatically + // by this point, after the binding expression was evaluated. + bool expectedResult = (object->property("avatarWidth").toInt() == 100); + delete object; //![1] -} + Q_ASSERT(expectedResult); + } -void expectTwo() -{ + void expectTwo() + { //![2] -QQmlComponent component(&engine, "exampleTwo.qml"); -QObject *object = component.create(); -// The scarce resource will not have been released automatically -// after the binding expression was evaluated. -// Since the scarce resource was not released explicitly prior -// to the binding expression being evaluated, we get: -bool expectedResult = (object->property("avatar").isValid() == true); -delete object; + QQmlComponent component(&engine, "qrc:/exampleTwo.qml"); + QObject *object = component.create(); + // The scarce resource will not have been released automatically + // after the binding expression was evaluated. + // Since the scarce resource was not released explicitly prior + // to the binding expression being evaluated, we get: + bool expectedResult = (object->property("avatar").isValid() == true); + delete object; //![2] -} + Q_ASSERT(expectedResult); + } -void expectThree() -{ + void expectThree() + { //![3] -QQmlComponent component(&engine, "exampleThree.qml"); -QObject *object = component.create(); -// The resource was preserved explicitly during evaluation of the -// JavaScript expression. Thus, during property assignment, the -// scarce resource was still valid, and so we get: -bool expectedResult = (object->property("avatar").isValid() == true); -// The scarce resource will not be released until all references to -// the resource are released, and the JavaScript garbage collector runs. -delete object; + QQmlComponent component(&engine, "qrc:/exampleThree.qml"); + QObject *object = component.create(); + // The resource was preserved explicitly during evaluation of the + // JavaScript expression. Thus, during property assignment, the + // scarce resource was still valid, and so we get: + bool expectedResult = (object->property("avatar").isValid() == true); + // The scarce resource will not be released until all references to + // the resource are released, and the JavaScript garbage collector runs. + delete object; //![3] -} + Q_ASSERT(expectedResult); + } -void expectFour() -{ + void expectFour() + { //![4] -QQmlComponent component(&engine, "exampleFour.qml"); -QObject *object = component.create(); -// The scarce resource was explicitly preserved by the client during -// the importAvatar() function, and so the scarce resource -// remains valid until the explicit call to releaseAvatar(). As such, -// we get the expected results: -bool expectedResultOne = (object->property("avatarOne").isValid() == true); -bool expectedResultTwo = (object->property("avatarTwo").isValid() == false); -// Because the scarce resource referenced by avatarTwo was released explicitly, -// it will no longer be consuming any system resources (beyond what a normal -// JS Object would; that small overhead will exist until the JS GC runs, as per -// any other JavaScript object). -delete object; + QQmlComponent component(&engine, "qrc:/exampleFour.qml"); + QObject *object = component.create(); + // The scarce resource was explicitly preserved by the client during + // the importAvatar() function, and so the scarce resource + // remains valid until the explicit call to releaseAvatar(). As such, + // we get the expected results: + bool expectedResultOne = (object->property("avatarOne").isValid() == true); + bool expectedResultTwo = (object->property("avatarTwo").isValid() == false); + // Because the scarce resource referenced by avatarTwo was released explicitly, + // it will no longer be consuming any system resources (beyond what a normal + // JS Object would; that small overhead will exist until the JS GC runs, as per + // any other JavaScript object). + delete object; //![4] -} + Q_ASSERT(expectedResultOne); + Q_ASSERT(expectedResultTwo); + } -void expectFive() -{ + void expectFive() + { //![5] -QQmlComponent component(&engine, "exampleFive.qml"); -QObject *object = component.create(); -// We have the expected results: -bool expectedResultOne = (object->property("avatarOne").isValid() == false); -bool expectedResultTwo = (object->property("avatarTwo").isValid() == false); -// Because although only avatarTwo was explicitly released, -// avatarOne and avatarTwo were referencing the same -// scarce resource. -delete object; + QQmlComponent component(&engine, "qrc:/exampleFive.qml"); + QObject *object = component.create(); + // We have the expected results: + bool expectedResultOne = (object->property("avatarOne").isValid() == false); + bool expectedResultTwo = (object->property("avatarTwo").isValid() == false); + // Because although only avatarTwo was explicitly released, + // avatarOne and avatarTwo were referencing the same + // scarce resource. + delete object; //![5] + Q_ASSERT(expectedResultOne); + Q_ASSERT(expectedResultTwo); + } +}; + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + Expectations expectations; + expectations.expectOne(); + expectations.expectTwo(); + expectations.expectThree(); + expectations.expectFour(); + expectations.expectFive(); } diff --git a/src/qml/doc/snippets/qml/integrating-javascript/scarceresources/avatarExample.h b/src/qml/doc/snippets/qml/integrating-javascript/scarceresources/avatarExample.h index fb9e238512..1acc3a1c2f 100644 --- a/src/qml/doc/snippets/qml/integrating-javascript/scarceresources/avatarExample.h +++ b/src/qml/doc/snippets/qml/integrating-javascript/scarceresources/avatarExample.h @@ -53,6 +53,7 @@ #include <QObject> #include <QPixmap> +#include <qqml.h> //![0] // avatarExample.h @@ -60,6 +61,8 @@ class AvatarExample : public QObject { Q_OBJECT Q_PROPERTY(QPixmap avatar READ avatar WRITE setAvatar NOTIFY avatarChanged) + QML_ELEMENT + public: AvatarExample(QObject *parent = 0) : QObject(parent), m_value(100, 100) diff --git a/src/qml/doc/snippets/qml/integrating-javascript/scarceresources/scarceresources.pro b/src/qml/doc/snippets/qml/integrating-javascript/scarceresources/scarceresources.pro new file mode 100644 index 0000000000..d88f8f574c --- /dev/null +++ b/src/qml/doc/snippets/qml/integrating-javascript/scarceresources/scarceresources.pro @@ -0,0 +1,22 @@ +QT += qml gui + +#![0] +CONFIG += qmltypes +QML_IMPORT_NAME = Qt.example +QML_IMPORT_MAJOR_VERSION = 1 +#![0] + +RESOURCES += \ + exampleFive.qml \ + exampleFour.js \ + exampleFour.qml \ + exampleOne.qml \ + exampleThree.js \ + exampleThree.qml \ + exampleTwo.qml + +HEADERS += \ + avatarExample.h + +SOURCES += \ + avatarExample.cpp diff --git a/src/qml/doc/snippets/qml/qml-documents/A.qml b/src/qml/doc/snippets/qml/qml-documents/A.qml new file mode 100644 index 0000000000..83c59dc5d7 --- /dev/null +++ b/src/qml/doc/snippets/qml/qml-documents/A.qml @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +//! [document] +// A.qml +import QtQuick 2.15 + +Item { + id: root + property string message: "From A" + component MyInlineComponent : Item { + Component.onCompleted: console.log(root.message) + } +} +//! [document] diff --git a/src/qml/doc/snippets/qml/qml-documents/B.qml b/src/qml/doc/snippets/qml/qml-documents/B.qml new file mode 100644 index 0000000000..5e603d50e0 --- /dev/null +++ b/src/qml/doc/snippets/qml/qml-documents/B.qml @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [document] +// B.qml +import QtQuick 2.15 + +Item { + A.MyInlineComponent {} +} +//! [document] diff --git a/src/qml/doc/snippets/qml/qml-documents/Images.qml b/src/qml/doc/snippets/qml/qml-documents/Images.qml new file mode 100644 index 0000000000..fc9fa60282 --- /dev/null +++ b/src/qml/doc/snippets/qml/qml-documents/Images.qml @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +//! [document] +// Images.qml +import QtQuick 2.15 + +Item { + component LabeledImage: Column { + property alias source: image.source + property alias caption: text.text + + Image { + id: image + width: 50 + height: 50 + } + Text { + id: text + font.bold: true + } + } + + Row { + LabeledImage { + id: before + source: "before.png" + caption: "Before" + } + LabeledImage { + id: after + source: "after.png" + caption: "After" + } + } + property LabeledImage selectedImage: before +} +//! [document] diff --git a/src/qml/doc/snippets/qml/qml-documents/LabeledImageBox.qml b/src/qml/doc/snippets/qml/qml-documents/LabeledImageBox.qml new file mode 100644 index 0000000000..5a259a0cc6 --- /dev/null +++ b/src/qml/doc/snippets/qml/qml-documents/LabeledImageBox.qml @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [document] +// LabeledImageBox.qml +import QtQuick 2.15 + +Rectangle { + property alias caption: image.caption + property alias source: image.source + border.width: 2 + border.color: "black" + Images.LabeledImage { + id: image + } +} +//! [document] diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc index 7c2693508c..9dfb7837e5 100644 --- a/src/qml/doc/src/cppintegration/data.qdoc +++ b/src/qml/doc/src/cppintegration/data.qdoc @@ -197,6 +197,25 @@ type or method parameter, the value can be created as a JavaScript array or object in QML, and is automatically converted to a QVariantList or QVariantMap when it is passed to C++. +Mind that QVariantList and QVariantMap properties of C++ types are stored as +values and cannot be changed in place by QML code. You can only replace the +whole map or list, but not manipulate its contents. The following code does +not work if the property \c l is a QVariantList: + +\code +MyListExposingItem { + l: [1, 2, 3] + Component.onCompleted: l[0] = 10 +} +\endcode + +The following code does work: +\code +MyListExposingItem { + l: [1, 2, 3] + Component.onCompleted: l = [10, 2, 3] +} +\endcode \section2 QDateTime to JavaScript Date @@ -284,7 +303,7 @@ In particular, QML currently supports: \li \c {std::vector<bool>} \endlist -and all registered QList, QVector, QQueue, QStack, QSet, QLinkedList, std::list, +and all registered QList, QVector, QQueue, QStack, QSet, std::list, std::vector that contain a type marked with \l Q_DECLARE_METATYPE. These sequence types are implemented directly in terms of the underlying C++ diff --git a/src/qml/doc/src/cppintegration/definetypes.qdoc b/src/qml/doc/src/cppintegration/definetypes.qdoc index 2e8102bd65..cbbbd9ba58 100644 --- a/src/qml/doc/src/cppintegration/definetypes.qdoc +++ b/src/qml/doc/src/cppintegration/definetypes.qdoc @@ -80,9 +80,17 @@ class instance can be manipulated from QML; as Types to QML} explains, the properties, methods and signals of any QObject-derived class are accessible from QML code. -To register a QObject-derived class as an instantiable QML object type, call -qmlRegisterType() to register the class as QML type into a particular type -namespace. Clients can then import that namespace in order to use the type. +To register a QObject-derived class as an instantiable QML object type, add +\c QML_ELEMENT or \c QML_NAMED_ELEMENT(<name>) to the class declaration and +\c {CONFIG += qmltypes}, a \c {QML_IMPORT_NAME}, and a +\c QML_IMPORT_MAJOR_VERSION to your project file. This will register the class +into the type namespace under the given major version, using either the class +name or an explicitly given name as QML type name. The minor version(s) will +be derived from any revisions attached to properties, methods, or signals. The +default minor version is \c 0. You can explicitly restrict the type to be +available only from specific minor versions by adding the +\c QML_ADDED_IN_MINOR_VERSION() macro to the class declaration. Clients can +import suitable versions of the namespace in order to use the type. For example, suppose there is a \c Message class with \c author and \c creationDate properties: @@ -93,17 +101,20 @@ class Message : public QObject Q_OBJECT Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged) Q_PROPERTY(QDateTime creationDate READ creationDate WRITE setCreationDate NOTIFY creationDateChanged) + QML_ELEMENT public: // ... }; \endcode -This type can be registered by calling qmlRegisterType() with an appropriate -type namespace and version number. For example, to make the type available in -the \c com.mycompany.messaging namespace with version 1.0: +This type can be registered by adding an appropriate type namespace and version +number to the project file. For example, to make the type available in the +\c com.mycompany.messaging namespace with version 1.0: \code -qmlRegisterType<Message>("com.mycompany.messaging", 1, 0, "Message"); +CONFIG += qmltypes +QML_IMPORT_NAME = com.mycompany.messaging +QML_IMPORT_MAJOR_VERSION = 1 \endcode The type can be used in an \l{qtqml-syntax-basics.html#object-declarations} @@ -135,23 +146,25 @@ not be instantiable should not be instantiable from QML \endlist -The \l {Qt QML} module provides several methods for registering non-instantiable +The \l {Qt QML} module provides several macros for registering non-instantiable types: \list -\li qmlRegisterType() (with no parameters) registers a C++ type that is not -instantiable and cannot be referred to from QML. This enables the engine to -coerce any inherited types that are instantiable from QML. -\li qmlRegisterInterface() registers an existing Qt interface type. The type is +\li QML_ANONYMOUS registers a C++ type that is not instantiable and cannot be +referred to from QML. This enables the engine to coerce any inherited types that +are instantiable from QML. +\li QML_INTERFACE registers an existing Qt interface type. The type is not instantiable from QML, and you cannot declare QML properties with it. Using C++ properties of this type from QML will do the expected interface casts, though. -\li qmlRegisterUncreatableType() registers a named C++ type that is not -instantiable but should be identifiable as a type to the QML type system. This -is useful if a type's enums or attached properties should be accessible from QML -but the type itself should not be instantiable. -\li qmlRegisterSingletonType() registers a singleton type that can be imported -from QML, as discussed below. +\li QML_UNCREATABLE(reason) combined with with QML_ELEMENT or QML_NAMED_ELEMENT +registers a named C++ type that is not instantiable but should be identifiable +as a type to the QML type system. This is useful if a type's enums or attached +properties should be accessible from QML but the type itself should not be +instantiable. The parameter should be an error message to be emitted if an +attempt at creating an instance of the type is detected. +\li QML_SINGLETON combined with QML_ELEMENT or QML_NAMED_ELEMENT registers a +singleton type that can be imported from QML, as discussed below. \endlist Note that all C++ types registered with the QML type system must be @@ -195,7 +208,7 @@ Rectangle { A QJSValue may also be exposed as a singleton type, however clients should be aware that properties of such a singleton type cannot be bound to. -See \l{qmlRegisterSingletonType()} for more information on how implement and +See \l{QML_SINGLETON} for more information on how implement and register a new singleton type, and how to use an existing singleton type. \note Enum values for registered types in QML should start with a capital. @@ -245,30 +258,20 @@ class CppType : public BaseType { Q_OBJECT Q_PROPERTY(int root READ root WRITE setRoot NOTIFY rootChanged REVISION 1) + QML_ELEMENT signals: Q_REVISION(1) void rootChanged(); }; \endcode -To register the new class revision to a particular version the following -function is used: +The revisions given this way are automatically interpreted as minor versions to +the major version given in the project file. In this case, \c root is only +available when \c MyTypes version 1.1 or higher is imported. Imports of +\c MyTypes version 1.0 remain unaffected. -\code -template<typename T, int metaObjectRevision> -int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName) -\endcode - -To register \c CppType version 1 for \c {MyTypes 1.1}: - -\code -qmlRegisterType<CppType,1>("MyTypes", 1, 1, "CppType") -\endcode - -\c root is only available when \c MyTypes version 1.1 is imported. - -For the same reason, new types introduced in later versions should use -the minor version argument of qmlRegisterType. +For the same reason, new types introduced in later versions should be tagged +with the QML_ADDED_IN_MINOR_VERSION macro. This feature of the language allows for behavioural changes to be made without breaking existing applications. Consequently QML module authors @@ -276,29 +279,10 @@ should always remember to document what changed between minor versions, and QML module users should check that their application still runs correctly before deploying an updated import statement. -You may also register the revision of a base class that your type depends -upon using the qmlRegisterRevision() function: - -\code -template<typename T, int metaObjectRevision> -int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor) - -template<typename T, int metaObjectRevision> -int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason) - -template<typename T, typename E, int metaObjectRevision> -int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason) -\endcode - -For example, if \c BaseType is changed and now has a revision 1, you can -specify that your type uses the new revision: - -\code -qmlRegisterRevision<BaseType,1>("MyTypes", 1, 1); -\endcode - -This is useful when deriving from base classes provided by other authors, -e.g. when extending classes from the Qt Quick module. +Revisions of a base class that your type depends upon are automatically +registered when registering the type itself. This is useful when deriving +from base classes provided by other authors, e.g. when extending classes from +the Qt Quick module. \note The QML engine does not support revisions for properties or signals of grouped and attached property objects. @@ -323,21 +307,8 @@ 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 {QQmlEngine::}{qmlRegisterExtendedType()} function is for registering extended types. -Note that it has two forms. - -\code -template<typename T, typename ExtendedT> -int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, const char *qmlName) - -template<typename T, typename ExtendedT> -int qmlRegisterExtendedType() -\endcode - -This functions should be used instead of the regular \c qmlRegisterType() -variations. The arguments are identical to the corresponding non-extension -registration functions, except for the ExtendedT parameter which is the type of -the extension object. +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 pointer. However, the extension class creation is delayed until the first @@ -425,8 +396,9 @@ the attributes to be made accessible to \e attachee objects. For the attached property accesses. Consequently the attachment object may not be deleted until the attachee \c object is destroyed. -\li is declared as an attaching type, by calling the QML_DECLARE_TYPEINFO() - macro with the QML_HAS_ATTACHED_PROPERTIES flag +\li is declared as an attaching type, by adding the QML_ATTACHED(attached) macro + to the class declaration. The argument is the name of the + \e{attached object type} \endlist @@ -441,6 +413,7 @@ class Message : public QObject Q_OBJECT Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged) Q_PROPERTY(QDateTime creationDate READ creationDate WRITE setCreationDate NOTIFY creationDateChanged) + QML_ELEMENT public: // ... }; @@ -472,6 +445,7 @@ class MessageBoardAttachedType : public QObject { Q_OBJECT Q_PROPERTY(bool expired READ expired WRITE setExpired NOTIFY expiredChanged) + QML_ANONYMOUS public: MessageBoardAttachedType(QObject *parent); bool expired() const; @@ -485,20 +459,21 @@ signals: Then the \e {attaching type}, \c MessageBoard, must declare a \c qmlAttachedProperties() method that returns an instance of the \e {attached object type} as implemented by MessageBoardAttachedType. -Additionally, \c Message board must be declared as an attached type -through the QML_DECLARE_TYPEINFO() macro: +Additionally, \c MessageBoard must be declared as an attaching type +via the QML_ATTACHED() macro: \code class MessageBoard : public QObject { Q_OBJECT + QML_ATTACHED(MessageBoardAttachedType) + QML_ELEMENT public: static MessageBoardAttachedType *qmlAttachedProperties(QObject *object) { return new MessageBoardAttachedType(object); } }; -QML_DECLARE_TYPEINFO(MessageBoard, QML_HAS_ATTACHED_PROPERTIES) \endcode Now, a \c Message type can access the properties and signals of the attached @@ -607,6 +582,7 @@ class RandomNumberGenerator : public QObject, public QQmlPropertyValueSource Q_OBJECT Q_INTERFACES(QQmlPropertyValueSource) Q_PROPERTY(int maxValue READ maxValue WRITE setMaxValue NOTIFY maxValueChanged); + QML_ELEMENT public: RandomNumberGenerator(QObject *parent) : QObject(parent), m_maxValue(100) @@ -690,6 +666,7 @@ class MessageBoard : public QObject Q_OBJECT Q_PROPERTY(QQmlListProperty<Message> messages READ messages) Q_CLASSINFO("DefaultProperty", "messages") + QML_ELEMENT public: QQmlListProperty<Message> messages(); @@ -766,6 +743,7 @@ class MyQmlType : public QObject, public QQmlParserStatus { Q_OBJECT Q_INTERFACES(QQmlParserStatus) + QML_ELEMENT public: virtual void componentComplete() { 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/cppintegration/topic.qdoc b/src/qml/doc/src/cppintegration/topic.qdoc index fbb654378d..bf4565a996 100644 --- a/src/qml/doc/src/cppintegration/topic.qdoc +++ b/src/qml/doc/src/cppintegration/topic.qdoc @@ -49,8 +49,16 @@ file contents with: \snippet code/backend/backend.h backend_header The \c Q_PROPERTY macro declares a property that could be accessed from QML. +The \c QML_ELEMENT macro makes the BackEnd class available in QML. -\li Replace its C++ file contents with: +\li Add the following lines to your project file: + +\snippet code/backend/backend.pro registration + +The BackEnd class is automatically registered as a type, which is accessible +from QML by importing the URL, "\c{io.qt.examples.backend 1.0}". + +\li Replace the contents of \c{backend.cpp} with: \snippet code/backend/backend.cpp backend_cpp @@ -58,14 +66,6 @@ The \c setUserName function emits the \c userNameChanged signal every time \c m_userName value changes. The signal can be handled from QML using the \c onUserNameChanged handler. -\li Include \c "backend.h" in \c main.cpp and register the class as a QML type -under a import URL as shown below: - -\snippet code/backend/main.cpp main_cpp - -The BackEnd class is registered as a type, which is accessible from QML by -importing the URL, "\c{io.qt.examples.backend 1.0}". - \li Replace the contents of \c main.qml with the following code: \snippet code/backend/main.qml main_qml diff --git a/src/qml/doc/src/javascript/expressions.qdoc b/src/qml/doc/src/javascript/expressions.qdoc index b83127389a..b27bde3cf9 100644 --- a/src/qml/doc/src/javascript/expressions.qdoc +++ b/src/qml/doc/src/javascript/expressions.qdoc @@ -147,7 +147,7 @@ Rectangle { TapHandler { id: inputHandler - onTapped: { + onTapped: { // arbitrary JavaScript expression console.log("Tapped!") } @@ -339,7 +339,7 @@ For the following examples, imagine that we have defined the following class: and that we have registered it with the QML type-system as follows: -\snippet qml/integrating-javascript/scarceresources/avatarExample.cpp 0 +\snippet qml/integrating-javascript/scarceresources/scarceresources.pro 0 The AvatarExample class has a property which is a pixmap. When the property is accessed in JavaScript scope, a copy of the resource will be created and diff --git a/src/qml/doc/src/javascript/imports.qdoc b/src/qml/doc/src/javascript/imports.qdoc index 8e26c4aadd..9227f0e604 100644 --- a/src/qml/doc/src/javascript/imports.qdoc +++ b/src/qml/doc/src/javascript/imports.qdoc @@ -154,7 +154,7 @@ var importedEnumValue = JsQtTest.MyQmlObject.EnumValue3 \endcode In particular, this may be useful in order to access functionality provided -via a singleton type; see qmlRegisterSingletonType() for more information. +via a singleton type; see QML_SINGLETON for more information. \note The .import syntax doesn't work for scripts used in the \l {WorkerScript} */ diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc index 67c0f6bb25..04d907f168 100644 --- a/src/qml/doc/src/qmlfunctions.qdoc +++ b/src/qml/doc/src/qmlfunctions.qdoc @@ -26,6 +26,274 @@ ****************************************************************************/ /*! + \macro QML_ELEMENT + \relates QQmlEngine + + Declares the enclosing type or namespace to be available in QML, using its + class or namespace name as the QML element name. + + For example, this makes the C++ class \c Slider available as a QML type + named \c Slider. + + \code + class Slider : public QObject + { + Q_OBJECT + QML_ELEMENT + ... + } + \endcode + + You can use the build system to register the type in the type namespace + \e {com.mycompany.qmlcomponents} with major version \c 1 by specifying the + following in your project file: + + \badcode + CONFIG += qmltypes + QML_IMPORT_NAME = com.mycompany.qmlcomponents + QML_IMPORT_MAJOR_VERSION = 1 + \endcode + + Once registered, the type can be used in QML by importing the + same type namespace and version number: + + \qml + import com.mycompany.qmlcomponents 1.0 + + Slider { + // ... + } + \endqml + + You can also make namespaces tagged with Q_NAMESPACE available this way, in + order to expose any enums tagged with Q_ENUM_NS they contain. + + \sa {Choosing the Correct Integration Method Between C++ and QML}, QML_NAMED_ELEMENT(), + Q_REVISION(), QML_ADDED_IN_MINOR_VERSION() +*/ + +/*! + \macro QML_NAMED_ELEMENT(name) + \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. + + \sa {Choosing the Correct Integration Method Between C++ and QML}, QML_ELEMENT +*/ + +/*! + \macro QML_ANONYMOUS + \relates QQmlEngine + + Declares the enclosing type to be available, but anonymous in QML. The type + cannot be created or used as property type, but when passed from C++, it is + recognized. + + \sa QML_ELEMENT, QML_NAMED_ELEMENT(), QML_UNCREATABLE(), QML_INTERFACE +*/ + +/*! + \macro QML_INTERFACE + \relates QQmlEngine + + This macro registers the enclosing C++ type in the QML system as an interface. + + Types registered as an interface in QML should also declare themselves as an + interface with the \l {The Meta-Object System}{meta object system}. For + example: + + \code + struct FooInterface + { + QML_INTERFACE + public: + virtual ~FooInterface(); + virtual void doSomething() = 0; + }; + + Q_DECLARE_INTERFACE(FooInterface, "org.foo.FooInterface") + \endcode + + When registered with QML in this way, they can be used as property types: + + Q_PROPERTY(FooInterface *foo READ foo WRITE setFoo) + + When you assign a \l QObject sub-class to this property, the QML engine does + the interface cast to \c FooInterface* automatically. + + Interface types are implicitly anonymous and uncreatable in QML. + + \sa QML_ELEMENT, QML_NAMED_ELEMENT(), QML_UNCREATABLE(), QML_ANONYMOUS +*/ + +/*! + \macro QML_UNCREATABLE(reason) + \relates QQmlEngine + + Declares that the enclosing type shall not be creatable from QML. This takes + effect if the type is available in QML, by having a \l QML_ELEMENT or + \l QML_NAMED_ELEMENT() macro. The \a reason will be emitted as error message if an + attempt to create the type from QML is detected. + + Some QML types are implicitly uncreatable, in particular types exposed with + \l QML_ANONYMOUS or namespaces exposed with \l QML_ELEMENT or + \l QML_NAMED_ELEMENT(). For such types, \l QML_UNCREATABLE() can be used to + provide a custom error message. + + \sa QML_ELEMENT, QML_NAMED_ELEMENT(), QML_ANONYMOUS +*/ + +/*! + \macro QML_SINGLETON + \relates QQmlEngine + + Declares the enclosing type to be a singleton in QML. This only takes effect + if the type is available in QML, by having a \l QML_ELEMENT or + \l QML_NAMED_ELEMENT() macro. By default, each QQmlEngine will try to create a + singleton instance using the type's default constructor when the type is first + accessed. If there is no default constructor the singleton is initially + inaccessible. This behavior can be overridden by calling + \l qmlRegisterSingletonType() with a specific factory function or + \l qmlRegisterSingletonInstance() with a specific instance for the same class + and the same type namespace and version. + + \sa QML_ELEMENT, QML_NAMED_ELEMENT(), qmlRegisterSingletonInstance(). +*/ + +/*! + \macro QML_ADDED_IN_MINOR_VERSION(VERSION) + \relates QQmlEngine + + Declares that the enclosing type or namespace was added in the specified minor + \a VERSION, relative to the module major version. The minor version is assumed + to be in line with any revisions given by \l Q_REVISION() macros on methods, + slots, or signals, and any REVISION tags on properties declared with + \l Q_PROPERTY(). + + \l QML_ADDED_IN_MINOR_VERSION() only takes effect if the type or namespace is + available in QML, by having a \l QML_ELEMENT, \l QML_NAMED_ELEMENT(), + \l QML_ANONYMOUS, or \l QML_INTERFACE macro. + + If the QML module the type belongs to is imported with a lower version than + the one determined this way, the QML type is invisible. + + \sa QML_ELEMENT, QML_NAMED_ELEMENT() +*/ + +/*! + \macro QML_REMOVED_IN_MINOR_VERSION(VERSION) + \relates QQmlEngine + + Declares that the enclosing type or namespace was removed in the specified + minor \a VERSION, relative to the module major version. This is primarily + useful when replacing the implementation of a QML type. If a corresponding + \l QML_ADDED_IN_MINOR_VERSION() is present on a different type or namespace of + the same QML name, then the removed type is used when importing versions of + the module lower than \a VERSION, and the added type is used when importing + versions of the module greater or equal \a VERSION. + + \l QML_REMOVED_IN_MINOR_VERSION() only takes effect if type or namespace is + available in QML, by having a \l QML_ELEMENT, \l QML_NAMED_ELEMENT(), + \l QML_ANONYMOUS, or \l QML_INTERFACE macro. + + \sa QML_ELEMENT, QML_NAMED_ELEMENT() +*/ + +/*! + \macro QML_ATTACHED(ATTACHED_TYPE) + \relates QQmlEngine + + Declares that the enclosing type attaches \a ATTACHED_TYPE as an + \l {Attached Properties and Attached Signal Handlers} + {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(), qmlAttachedPropertiesObject(), + {Providing Attached Properties} +*/ + +/*! + \macro QML_EXTENDED(EXTENDED_TYPE) + \relates QQmlEngine + + Declares that the enclosing type uses \a EXTENDED_TYPE as an extension to + provide further properties and methods in QML. 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(), {Registering Extension Objects} +*/ + +/*! + \macro QML_FOREIGN(FOREIGN_TYPE) + \relates QQmlEngine + + Declares that any \l QML_ELEMENT, \l QML_NAMED_ELEMENT(), \l QML_ANONYMOUS, + \l QML_INTERFACE, \l QML_UNCREATABLE(), \l QML_SINGLETON, + \l QML_ADDED_IN_MINOR_VERSION(), \l QML_REMOVED_IN_MINOR_VERSION(), + \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 Q_GADGET or + \l Q_OBJECT macro. + + This is useful for registering types that cannot be amended to add the macros, + for example because they belong to 3rdparty libraries. + + \sa QML_ELEMENT, QML_NAMED_ELEMENT() +*/ + +/*! + \macro QML_UNAVAILABLE + \relates QQmlEngine + + This macro declares the enclosing type to be unavailable in QML. It registers + an internal dummy type called \c QQmlTypeNotAvailable as \l QML_FOREIGN() + type, using any further QML macros you specify. + + Normally, the types exported by a module should be fixed. However, if a C++ + type is not available, you should at least "reserve" the QML type name, and + give the user of the unavailable type a meaningful error message. + + Example: + + \code + #ifdef NO_GAMES_ALLOWED + struct MinehuntGame + { + Q_GADGET + QML_NAMED_ELEMENT(Game) + QML_UNAVAILABLE + QML_UNCREATABLE("Get back to work, slacker!"); + }; + #else + class MinehuntGame : public QObject + { + Q_OBJECT + QML_NAMED_ELEMENT(Game) + // ... + }; + #endif + \endcode + + This will cause any QML which attempts to use the "Game" type to produce an + error message: + + \badcode + fun.qml: Get back to work, slacker! + Game { + ^ + \endcode + + 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. + + \sa QML_ELEMENT, QML_NAMED_ELEMENT(), QML_UNCREATABLE(), QML_FOREIGN() +*/ + +/*! \macro QML_DECLARE_TYPE() \relates QQmlEngine @@ -41,7 +309,8 @@ Current the only supported type info is \c QML_HAS_ATTACHED_PROPERTIES which declares that the \a Type supports \l {Attached Properties and Attached Signal Handlers} - {attached properties}. + {attached properties}. QML_DECLARE_TYPEINFO() is not necessary if \a Type contains the + QML_ATTACHED macro. */ /*! @@ -106,7 +375,8 @@ QML written to previous versions to continue to work, even if more advanced versions of some of its types are available. - \sa {Choosing the Correct Integration Method Between C++ and QML} + \sa QML_ELEMENT, QML_NAMED_ELEMENT(), + {Choosing the Correct Integration Method Between C++ and QML} */ /*! @@ -143,7 +413,7 @@ Returns the QML type id. - \sa qmlRegisterTypeNotAvailable(), + \sa QML_UNCREATABLE(), qmlRegisterTypeNotAvailable(), {Choosing the Correct Integration Method Between C++ and QML} */ @@ -158,7 +428,7 @@ Returns the QML type id. - \sa qmlRegisterType(), {Registering Extension Objects} + \sa QML_EXTENDED(), qmlRegisterType(), {Registering Extension Objects} */ @@ -180,7 +450,7 @@ Returns the QML type id. - \sa qmlRegisterUncreatableType() + \sa QML_EXTENDED(), QML_UNCREATABLE(), qmlRegisterUncreatableType() */ /*! @@ -220,6 +490,8 @@ \code Component.onCompleted: console.log(MyNamespace.Key2) \endcode + + \sa QML_ELEMENT, QML_NAMED_ELEMENT(), QML_UNCREATABLE() */ /*! @@ -235,6 +507,8 @@ the \a parser provided. Returns the QML type id. + + \sa QML_ELEMENT, QML_NAMED_ELEMENT(), QML_EXTENDED() */ /*! @@ -269,7 +543,7 @@ Without this, a generic "Game is not a type" message would be given. - \sa qmlRegisterUncreatableType(), + \sa QML_UNAVAILABLE, qmlRegisterUncreatableType(), {Choosing the Correct Integration Method Between C++ and QML} */ @@ -353,7 +627,7 @@ Returns the QML type id. \since 5.14 - \sa {Choosing the Correct Integration Method Between C++ and QML} + \sa QML_ANONYMOUS, {Choosing the Correct Integration Method Between C++ and QML} */ /*! @@ -397,6 +671,8 @@ the interface cast to \c FooInterface* automatically. Returns the QML type id. + + \sa QML_INTERFACE */ /*! @@ -455,7 +731,7 @@ } \endqml - \sa {Choosing the Correct Integration Method Between C++ and QML} + \sa QML_SINGLETON, {Choosing the Correct Integration Method Between C++ and QML} */ /*! @@ -477,8 +753,7 @@ Returns 0 if type \e T is not a valid attaching type, or if \a create is false and no attachment object instance has previously been created for \a attachee. - \sa {Providing Attached Properties} - + \sa QML_ATTACHED(), {Providing Attached Properties} */ /*! @@ -571,7 +846,7 @@ } \endqml - \sa {Choosing the Correct Integration Method Between C++ and QML} + \sa QML_SINGLETON, {Choosing the Correct Integration Method Between C++ and QML} */ @@ -626,10 +901,12 @@ That can be done by adding a pragma Singleton statement among the imports of the type's QML file. In addition the type must be defined in a qmldir file with a singleton keyword and the qmldir must be imported by the QML files using the singleton. + + \sa QML_SINGLETON */ /*! - \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 @@ -718,7 +995,7 @@ } \endqml - \sa qmlRegisterSingletonType + \sa QML_SINGLETON, qmlRegisterSingletonType */ /*! @@ -792,5 +1069,5 @@ Returns -1 if no matching type was found or one of the given parameters was invalid. - \sa qmlRegisterType(), qmlRegisterSingletonType() + \sa QML_ELEMENT, QML_NAMED_ELEMENT, QML_SINGLETON, qmlRegisterType(), qmlRegisterSingletonType() */ diff --git a/src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc b/src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc index 2de4eb0c18..a4119ff793 100644 --- a/src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc +++ b/src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc @@ -29,25 +29,37 @@ \title Defining Object Types through QML Documents \brief Description of how a QML document is a reusable type definition -One of the core features of QML is that it enables QML object types to be easily defined in a lightweight manner through QML documents to suit the needs of individual QML applications. The standard \l {Qt Quick} module provides various types like \l Rectangle, \l Text and \l Image for building a QML application; beyond these, you can easily define your own QML types to be reused within your application. This ability to create your own types forms the building blocks of any QML application. +One of the core features of QML is that it enables QML object types to be +easily defined in a lightweight manner through QML documents to suit the needs +of individual QML applications. The standard \l {Qt Quick} module provides +various types like \l Rectangle, \l Text and \l Image for building a QML +application; beyond these, you can easily define your own QML types to be +reused within your application. This ability to create your own types forms the +building blocks of any QML application. \section1 Defining an Object Type with a QML File \section2 Naming Custom QML Object Types -To create an object type, a QML document should be placed into a text file named as \e <TypeName>.qml where \e <TypeName> is the desired name of the type. The type name has the following requirements: +To create an object type, a QML document should be placed into a text file +named as \e <TypeName>.qml where \e <TypeName> is the desired name of the type. +The type name has the following requirements: \list \li It must be comprised of alphanumeric characters or underscores. \li It must begin with an uppercase letter. \endlist -This document is then automatically recognized by the engine as a definition of a QML type. Additionally, a type defined in this manner is automatically made available to other QML files within the same directory as the engine searches within the immediate directory when resolving QML type names. +This document is then automatically recognized by the engine as a definition of +a QML type. Additionally, a type defined in this manner is automatically made +available to other QML files within the same directory as the engine searches +within the immediate directory when resolving QML type names. \section2 Custom QML Type Definition -For example, below is a document that declares a \l Rectangle with a child \l MouseArea. The document has been saved to file named \c SquareButton.qml: +For example, below is a document that declares a \l Rectangle with a child \l +MouseArea. The document has been saved to file named \c SquareButton.qml: \qml // SquareButton.qml @@ -65,7 +77,10 @@ Rectangle { } \endqml -Since the file is named \c SquareButton.qml, \b {this can now be used as a type named \c SquareButton by any other QML file within the same directory}. For example, if there was a \c myapplication.qml file in the same directory, it could refer to the \c SquareButton type: +Since the file is named \c SquareButton.qml, \b {this can now be used as a type +named \c SquareButton by any other QML file within the same directory}. For +example, if there was a \c myapplication.qml file in the same directory, it +could refer to the \c SquareButton type: \qml // myapplication.qml @@ -76,23 +91,80 @@ SquareButton {} \image documents-definetypes-simple.png -This creates a 100 x 100 red \l Rectangle with an inner \l MouseArea, as defined in \c SquareButton.qml. When this \c myapplication.qml document is loaded by the engine, it loads the SquareButton.qml document as a component and instantiates it to create a \c SquareButton object. +This creates a 100 x 100 red \l Rectangle with an inner \l MouseArea, as +defined in \c SquareButton.qml. When this \c myapplication.qml document is +loaded by the engine, it loads the SquareButton.qml document as a component and +instantiates it to create a \c SquareButton object. + +The \c SquareButton type encapsulates the tree of QML objects declared in \c +SquareButton.qml. When the QML engine instantiates a \c SquareButton object +from this type, it is instantiating an object from the \l Rectangle tree +declared in \c SquareButton.qml. + +\note the letter case of the file name is significant on some (notably UNIX) +filesystems. It is recommended the file name case matches the case of the +desired QML type name exactly - for example, \c Box.qml and not \c BoX.qml - +regardless of the platform to which the QML type will be deployed. + +\section2 Inline Components + +Sometimes, it can be inconvenient to create a new file for a type, for +instance when reusing a small delegate in multiple views. If you don't actually +need to expose the type, but only need to create an instance, +\l{QtQml::Component}{Component} is an option. +But if you want to declare properties with the component types, or if you +want to use it in multiple files, \c Component is not an option. In that case, +you can use \e {inline components}. Inline components declare a new component +inside of a file. The syntax for that is +\code +component <component name> : BaseType { + // declare properties and bindings here +} +\endcode + +Inside the file which declares the inline component, the type can be referenced +simply by its name. + +\snippet qml/qml-documents/Images.qml document + +In other files, it has to be prefixed with the name of its containing component. + +\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 +B.qml gets created, a ReferenceError will occur, as \c root does not exist as +an id in B.qml. +It is therefore advisable not to reference objects in an inline component +which are not part of it. -The \c SquareButton type encapsulates the tree of QML objects declared in \c SquareButton.qml. When the QML engine instantiates a \c SquareButton object from this type, it is instantiating an object from the \l Rectangle tree declared in \c SquareButton.qml. +\snippet qml/qml-documents/A.qml document +\snippet qml/qml-documents/B.qml document -\note the letter case of the file name is significant on some (notably UNIX) filesystems. It is recommended the file name case matches the case of the desired QML type name exactly - for example, \c Box.qml and not \c BoX.qml - regardless of the platform to which the QML type will be deployed. +\note Inline components cannot be nested. \section2 Importing Types Defined Outside the Current Directory If \c SquareButton.qml was not in the same directory as \c myapplication.qml, -the \c SquareButton type would need to be specifically made available through an \e import statement in \c myapplication.qml. It could be imported from a relative path on the file system, or as an installed module; see \l {QML Modules}{module} for more details. +the \c SquareButton type would need to be specifically made available through +an \e import statement in \c myapplication.qml. It could be imported from a +relative path on the file system, or as an installed module; see \l {QML +Modules}{module} for more details. \section1 Accessible Attributes of Custom Types -The \b {root object} definition in a .qml file \b {defines the attributes that are available for a QML type}. All properties, signals and methods that belong to this root object - whether they are custom declared, or come from the QML type of the root object - are externally accessible and can be read and modified for objects of this type. +The \b {root object} definition in a .qml file \b {defines the attributes that +are available for a QML type}. All properties, signals and methods that belong +to this root object - whether they are custom declared, or come from the QML +type of the root object - are externally accessible and can be read and +modified for objects of this type. -For example, the root object type in the \c SquareButton.qml file above is \l Rectangle. This means any properties defined by the \l Rectangle type can be modified for a \c SquareButton object. The code below defines three \c SquareButton objects with customized values for some of the properties of the root \l Rectangle object of the \c SquareButton type: +For example, the root object type in the \c SquareButton.qml file above is \l +Rectangle. This means any properties defined by the \l Rectangle type can be +modified for a \c SquareButton object. The code below defines three \c +SquareButton objects with customized values for some of the properties of the +root \l Rectangle object of the \c SquareButton type: \qml // application.qml @@ -107,7 +179,12 @@ Column { \image documents-definetypes-attributes.png -The attributes that are accessible to objects of the custom QML type include any \l{Defining Property Attributes}{custom properties}, \l{Defining Method Attributes}{methods} and \l{Defining Signal Attributes}{signals} that have additionally been defined for an object. For example, suppose the \l Rectangle in \c SquareButton.qml had been defined as follows, with additional properties, methods and signals: +The attributes that are accessible to objects of the custom QML type include +any \l{Defining Property Attributes}{custom properties}, \l{Defining Method +Attributes}{methods} and \l{Defining Signal Attributes}{signals} that have +additionally been defined for an object. For example, suppose the \l Rectangle +in \c SquareButton.qml had been defined as follows, with additional properties, +methods and signals: \qml // SquareButton.qml @@ -136,7 +213,9 @@ Rectangle { } \endqml -Any \c SquareButton object could make use of the \c pressed property, \c buttonClicked signal and \c randomizeColor() method that have been added to the root \l Rectangle: +Any \c SquareButton object could make use of the \c pressed property, \c +buttonClicked signal and \c randomizeColor() method that have been added to the +root \l Rectangle: \qml // application.qml @@ -154,7 +233,14 @@ SquareButton { } \endqml -Note that any of the \c id values defined in \c SquareButton.qml are not accessible to \c SquareButton objects, as id values are only accessible from within the component scope in which a component is declared. The \c SquareButton object definition above cannot refer to \c mouseArea in order to refer to the \l MouseArea child, and if it had an \c id of \c root rather than \c squareButton, this would not conflict with the \c id of the same value for the root object defined in \c SquareButton.qml as the two would be declared within separate scopes. +Note that any of the \c id values defined in \c SquareButton.qml are not +accessible to \c SquareButton objects, as id values are only accessible from +within the component scope in which a component is declared. The \c +SquareButton object definition above cannot refer to \c mouseArea in order to +refer to the \l MouseArea child, and if it had an \c id of \c root rather than +\c squareButton, this would not conflict with the \c id of the same value for +the root object defined in \c SquareButton.qml as the two would be declared +within separate scopes. */ 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/modules/qqmlextensionplugin.qdocinc b/src/qml/doc/src/qmllanguageref/modules/qqmlextensionplugin.qdocinc index 05447db627..496245820a 100644 --- a/src/qml/doc/src/qmllanguageref/modules/qqmlextensionplugin.qdocinc +++ b/src/qml/doc/src/qmllanguageref/modules/qqmlextensionplugin.qdocinc @@ -1,19 +1,22 @@ -QQmlExtensionPlugin is a plugin interface that makes it possible to +\l QQmlEngineExtensionPlugin is a plugin interface that makes it possible to create QML extensions that can be loaded dynamically into QML applications. These extensions allow custom QML types to be made available to the QML engine. To write a QML extension plugin: \list 1 -\li Subclass QQmlExtensionPlugin +\li Subclass \l QQmlEngineExtensionPlugin and use the Q_PLUGIN_METADATA() macro + to register the plugin with the Qt meta object system. +\li Use the \l QML_ELEMENT and \l QML_NAMED_ELEMENT() macros to declare + QML types. +\li Write a project file for the plugin. Add: \list - \li Use the Q_PLUGIN_METADATA() macro to register the plugin with - the Qt meta object system - \li Override the \l{QQmlExtensionPlugin::}{registerTypes()} method - and call qmlRegisterType() to register the types to be exported - by the plugin + \li \c {CONFIG += qmltypes} to instruct the build system to generate + QML types. + \li \c {QML_IMPORT_NAME = <my.import.name>} to specify the import name. + \li \c {QML_IMPORT_MAJOR_VERSION = <version>} to specify the import + major version. \endlist -\li Write a project file for the plugin \li Create a \l{Module Definition qmldir Files}{qmldir file} to describe the plugin \endlist @@ -27,26 +30,18 @@ issues in the library user's code. Suppose there is a new \c TimeModel C++ class that should be made available as a new QML type. It provides the current time through \c hour and \c minute -properties. +properties. It declares a QML type called \c Time via \l QML_NAMED_ELEMENT(). \snippet qmlextensionplugins/timemodel.h 0 \dots To make this type available, we create a plugin class named \c QExampleQmlPlugin -which is a subclass of \l QQmlExtensionPlugin. It overrides the -\l{QQmlExtensionPlugin::}{registerTypes()} method in order to register the \c TimeModel -type using qmlRegisterType(). It also uses the Q_PLUGIN_METADATA() macro in the class -definition to register the plugin with the Qt meta object system using a unique -identifier for the plugin. +which is a subclass of \l QQmlEngineExtensionPlugin. It uses the +Q_PLUGIN_METADATA() macro in the class definition to register the plugin with the +Qt meta object system using a unique identifier for the plugin. \snippet qmlextensionplugins/plugin.cpp plugin -This registers the \c TimeModel class with version \c{1.0} of this plugin library, as -a QML type called \c Time. The Q_ASSERT() macro can ensure the type namespace is -imported correctly by any QML components that use this plugin. The -\l{Defining QML Types from C++} article has more information about registering C++ -types into the runtime. - \section1 Project settings for the plugin Additionally, the project file (\c .pro) defines the project as a plugin library, @@ -55,14 +50,22 @@ the plugin target name and various other details: \code TEMPLATE = lib -CONFIG += qt plugin +CONFIG += qt plugin qmltypes QT += qml -DESTDIR = imports/TimeExample -TARGET = qmlqtimeexampleplugin +QML_IMPORT_NAME = TimeExample +QML_IMPORT_MAJOR_VERSION = 1 + +DESTDIR = imports/$$QML_IMPORT_NAME +TARGET = qmlqtimeexampleplugin + SOURCES += qexampleqmlplugin.cpp \endcode +This registers the \c TimeModel class with the import \c{TimeExample 1.0}, as +a QML type called \c Time. The \l{Defining QML Types from C++} article has more +information about registering C++ types for usage in QML. + \section1 Plugin definition in the qmldir Finally, a \l{Module Definition qmldir Files}{qmldir file} is required 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 401e099ebf..ecfef2e04f 100644 --- a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc +++ b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc @@ -112,7 +112,7 @@ Alternatively, a custom property of an object type may be defined in an object declaration in a QML document with the following syntax: \code - [default] property <propertyType> <propertyName> + [default] [required] [readonly] property <propertyType> <propertyName> \endcode In this way an object declaration may \l {Defining Object Types from QML} @@ -121,10 +121,13 @@ state more easily. Property names must begin with a lower case letter and can only contain letters, numbers and underscores. \l {JavaScript Reserved Words} -{JavaScript reserved words} are not valid property names. The \c default -keyword is optional, and modifies the semantics of the property being declared. -See the upcoming section on \l {Default Properties}{default properties} for -more information about the \c default property modifier. +{JavaScript reserved words} are not valid property names. The \c default, +\c required, and \c readonly keywords are optional, and modify the semantics +of the property being declared. +See the upcoming sections on \l {Default Properties}{default properties}, +\l {Required Properties}{required properties} and, +\l {Read-Only Properties}{read-only properties} for more information +about their respective meaning. Declaring a custom property implicitly creates a value-change \l{Signal attributes}{signal} for that property, as well as an associated @@ -647,6 +650,45 @@ the \l{TabWidget Example}, which uses a default property to automatically reassign children of the TabWidget as children of an inner ListView. See also \l {Extending QML}. +\section3 Required Properties + +An object declaration may define a property as required, using the \c required +keyword. The syntax is +\code + required property <propertyType> <propertyName> +\endcode + +As the name suggests, required properties must be set when an instance of the object +is created. Violation of this rule will result in QML applications not starting if it can be +detected statically. In case of dynamically instantiated QML components (for instance via +\l {QtQml::Qt::createComponent()}{Qt.createComponent()}), violating this rule results in a +warning and a null return value. + +It's possible to make an existing property required with +\code + required <propertyName> +\endcode +The following example shows how to create a custom Rectangle component, in which the color +property always needs to be specified. +\qml +// ColorRectangle.qml +Rectangle { + required color +} +\endqml + +\note You can't assign an initial value to a required property from QML, as that would go +directly against the intended usage of required properties. + +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 Qt Quick} page. + +\sa {QQmlComponent::createWithInitialProperties}, {QQmlApplicationEngine::setInitialProperties} +and {QQuickView::setInitialProperties} for ways to initialize required properties from C++. + \section3 Read-Only Properties An object declaration may define a read-only property using the \c readonly 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/jsapi/qjsengine_p.h b/src/qml/jsapi/qjsengine_p.h index 7866a5bdda..37376a1485 100644 --- a/src/qml/jsapi/qjsengine_p.h +++ b/src/qml/jsapi/qjsengine_p.h @@ -110,8 +110,8 @@ public: QString uiLanguage; // These methods may be called from the QML loader thread - inline QQmlPropertyCache *cache(QObject *obj, int minorVersion = -1); - inline QQmlPropertyCache *cache(const QMetaObject *, int minorVersion = -1); + inline QQmlPropertyCache *cache(QObject *obj, QTypeRevision version = QTypeRevision()); + inline QQmlPropertyCache *cache(const QMetaObject *obj, QTypeRevision version = QTypeRevision()); }; QJSEnginePrivate::Locker::Locker(const QJSEngine *e) @@ -161,14 +161,14 @@ and deleted before the loader thread has a chance to use or reference it. This can't currently happen as the cache holds a reference to the QQmlPropertyCache until the QQmlEngine is destroyed. */ -QQmlPropertyCache *QJSEnginePrivate::cache(QObject *obj, int minorVersion) +QQmlPropertyCache *QJSEnginePrivate::cache(QObject *obj, QTypeRevision version) { if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted) return nullptr; Locker locker(this); const QMetaObject *mo = obj->metaObject(); - return QQmlMetaType::propertyCache(mo, minorVersion); + return QQmlMetaType::propertyCache(mo, version); } /*! @@ -180,12 +180,12 @@ exist for the lifetime of the QQmlEngine. The returned cache is not referenced, so if it is to be stored, call addref(). */ -QQmlPropertyCache *QJSEnginePrivate::cache(const QMetaObject *metaObject, int minorVersion) +QQmlPropertyCache *QJSEnginePrivate::cache(const QMetaObject *metaObject, QTypeRevision version) { Q_ASSERT(metaObject); Locker locker(this); - return QQmlMetaType::propertyCache(metaObject, minorVersion); + return QQmlMetaType::propertyCache(metaObject, version); } diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index 6c51b4cbcb..df9f117d04 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -362,7 +362,7 @@ ReturnedValue ArrayPrototype::method_toString(const FunctionObject *builtin, con ScopedString string(scope, scope.engine->newString(QStringLiteral("join"))); ScopedFunctionObject f(scope, that->get(string)); if (f) - return f->call(that, argv, argc); + return checkedResult(scope.engine, f->call(that, argv, argc)); return ObjectPrototype::method_toString(builtin, that, argv, argc); } @@ -1209,6 +1209,7 @@ ReturnedValue ArrayPrototype::method_every(const FunctionObject *b, const Value arguments[1] = Value::fromDouble(k); arguments[2] = instance; r = callback->call(that, arguments, 3); + CHECK_EXCEPTION(); ok = r->toBoolean(); } return Encode(ok); @@ -1276,6 +1277,7 @@ ReturnedValue ArrayPrototype::method_some(const FunctionObject *b, const Value * arguments[1] = Value::fromDouble(k); arguments[2] = instance; result = callback->call(that, arguments, 3); + CHECK_EXCEPTION(); if (result->toBoolean()) return Encode(true); } @@ -1345,6 +1347,7 @@ ReturnedValue ArrayPrototype::method_map(const FunctionObject *b, const Value *t arguments[1] = Value::fromDouble(k); arguments[2] = instance; mapped = callback->call(that, arguments, 3); + CHECK_EXCEPTION(); a->arraySet(k, mapped); } return a.asReturnedValue(); @@ -1380,6 +1383,7 @@ ReturnedValue ArrayPrototype::method_filter(const FunctionObject *b, const Value arguments[1] = Value::fromDouble(k); arguments[2] = instance; selected = callback->call(that, arguments, 3); + CHECK_EXCEPTION(); if (selected->toBoolean()) { a->arraySet(to, arguments[0]); ++to; @@ -1430,6 +1434,7 @@ ReturnedValue ArrayPrototype::method_reduce(const FunctionObject *b, const Value arguments[2] = Value::fromDouble(k); arguments[3] = instance; acc = callback->call(nullptr, arguments, 4); + CHECK_EXCEPTION(); } ++k; } @@ -1483,6 +1488,7 @@ ReturnedValue ArrayPrototype::method_reduceRight(const FunctionObject *b, const arguments[2] = Value::fromDouble(k - 1); arguments[3] = instance; acc = callback->call(nullptr, arguments, 4); + CHECK_EXCEPTION(); } --k; } diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index cc89947cec..bebcbd7e44 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -682,17 +682,17 @@ static inline QString ToTimeString(double t) static inline QString ToLocaleString(double t) { - return ToDateTime(t, Qt::LocalTime).toString(Qt::DefaultLocaleShortDate); + return QLocale().toString(ToDateTime(t, Qt::LocalTime), QLocale::ShortFormat); } static inline QString ToLocaleDateString(double t) { - return ToDateTime(t, Qt::LocalTime).date().toString(Qt::DefaultLocaleShortDate); + return QLocale().toString(ToDateTime(t, Qt::LocalTime).date(), QLocale::ShortFormat); } static inline QString ToLocaleTimeString(double t) { - return ToDateTime(t, Qt::LocalTime).time().toString(Qt::DefaultLocaleShortDate); + return QLocale().toString(ToDateTime(t, Qt::LocalTime).time(), QLocale::ShortFormat); } static double getLocalTZA() @@ -1561,7 +1561,7 @@ ReturnedValue DatePrototype::method_toJSON(const FunctionObject *b, const Value if (!toIso) return v4->throwTypeError(); - return toIso->call(O, nullptr, 0); + return checkedResult(v4, toIso->call(O, nullptr, 0)); } ReturnedValue DatePrototype::method_symbolToPrimitive(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc) diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 86e178d568..1efe09c59f 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -1266,20 +1266,15 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file) void ExecutionEngine::markObjects(MarkStack *markStack) { - for (int i = 0; i < NClasses; ++i) - if (classes[i]) { - classes[i]->mark(markStack); - if (markStack->top >= markStack->limit) - markStack->drain(); - } - markStack->drain(); + for (int i = 0; i < NClasses; ++i) { + if (Heap::InternalClass *c = classes[i]) + c->mark(markStack); + } identifierTable->markObjects(markStack); - for (auto compilationUnit: compilationUnits) { + for (auto compilationUnit: compilationUnits) compilationUnit->markObjects(markStack); - markStack->drain(); - } } ReturnedValue ExecutionEngine::throwError(const Value &value) @@ -1512,12 +1507,41 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int return QVariant::fromValue(QV4::JsonObject::toJsonArray(a)); } + QVariant retn; #if QT_CONFIG(qml_sequence_object) bool succeeded = false; - QVariant retn = QV4::SequencePrototype::toVariant(value, typeHint, &succeeded); + retn = QV4::SequencePrototype::toVariant(value, typeHint, &succeeded); if (succeeded) return retn; #endif + if (typeHint != -1) { + // 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(); + QV4::ScopedValue arrayValue(scope); + for (qint64 i = 0; i < length; ++i) { + arrayValue = a->get(i); + QVariant asVariant = toVariant(e, arrayValue, retnAsIterable._metaType_id, false, visitedObjects); + auto originalType = asVariant.userType(); + bool couldConvert = asVariant.convert(retnAsIterable._metaType_id); + if (!couldConvert) { + qWarning() << QLatin1String("Could not convert array value at position %1 from %2 to %3") + .arg(QString::number(i), + QString::fromUtf8(QMetaType::typeName(originalType)), + QString::fromUtf8(QMetaType::typeName(retnAsIterable._metaType_id))); + // create default constructed value + asVariant = QVariant(retnAsIterable._metaType_id, nullptr); + } + retnAsIterable.append(asVariant.constData()); + } + return retn; + } + } } if (value.isUndefined()) @@ -1886,10 +1910,10 @@ QQmlRefPointer<ExecutableCompilationUnit> ExecutionEngine::compileModule( sourceCode, sourceTimeStamp, &diagnostics); for (const QQmlJS::DiagnosticMessage &m : diagnostics) { if (m.isError()) { - throwSyntaxError(m.message, url.toString(), m.line, m.column); + throwSyntaxError(m.message, url.toString(), m.loc.startLine, m.loc.startColumn); return nullptr; } else { - qWarning() << url << ':' << m.line << ':' << m.column + qWarning() << url << ':' << m.loc.startLine << ':' << m.loc.startColumn << ": warning: " << m.message; } } @@ -2331,9 +2355,11 @@ int ExecutionEngine::registerExtension() return registrationData()->extensionCount++; } +#if QT_CONFIG(qml_network) QNetworkAccessManager *QV4::detail::getNetworkAccessManager(ExecutionEngine *engine) { return engine->qmlEngine()->networkAccessManager(); } +#endif // qml_network QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index e0025feb00..efe44a324c 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -91,6 +91,7 @@ class PageAllocation; QT_BEGIN_NAMESPACE +#if QT_CONFIG(qml_network) class QNetworkAccessManager; namespace QV4 { @@ -99,6 +100,9 @@ namespace detail { QNetworkAccessManager *getNetworkAccessManager(ExecutionEngine *engine); } } +#else +namespace QV4 { struct QObjectMethod; } +#endif // qml_network // Used to allow a QObject method take and return raw V4 handles without having to expose // 48 in the public API. @@ -355,7 +359,9 @@ public: FunctionObject *getStackFunction() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetStack_Function); } FunctionObject *thrower() const { return reinterpret_cast<FunctionObject *>(jsObjects + ThrowerObject); } +#if QT_CONFIG(qml_network) QNetworkAccessManager* (*networkAccessManager)(ExecutionEngine*) = detail::getNetworkAccessManager; +#endif enum JSStrings { String_Empty, diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp index fa4a1f1ce4..962b23fad6 100644 --- a/src/qml/jsruntime/qv4executablecompilationunit.cpp +++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp @@ -817,7 +817,7 @@ QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache(QQm if (typePropertyCache) { return typePropertyCache; } else if (type.isValid()) { - typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject(), minorVersion); + typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject(), version); return typePropertyCache; } else { Q_ASSERT(compilationUnit); diff --git a/src/qml/jsruntime/qv4executablecompilationunit_p.h b/src/qml/jsruntime/qv4executablecompilationunit_p.h index 8cad18a3dc..a748e0a762 100644 --- a/src/qml/jsruntime/qv4executablecompilationunit_p.h +++ b/src/qml/jsruntime/qv4executablecompilationunit_p.h @@ -182,8 +182,8 @@ public: CompositeMetaTypeIds typeIdsForComponent(int objectid = 0) const; - int metaTypeId = -1; - int listMetaTypeId = -1; + QMetaType metaTypeId; + QMetaType listMetaTypeId; bool isRegisteredWithEngine = false; QHash<int, InlineComponentData> inlineComponentData; @@ -326,17 +326,15 @@ private: struct ResolvedTypeReference { ResolvedTypeReference() - : majorVersion(0) - , minorVersion(0) - , isFullyDynamicType(false) + : version(QTypeRevision::zero()) + , isFullyDynamicType(false) {} QQmlType type; QQmlRefPointer<QQmlPropertyCache> typePropertyCache; QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit; - int majorVersion; - int minorVersion; + QTypeRevision version; // Types such as QQmlPropertyMap can add properties dynamically at run-time and // therefore cannot have a property cache installed when instantiated. bool isFullyDynamicType; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index dfef52583e..cdb3b8942b 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -358,7 +358,7 @@ ReturnedValue FunctionPrototype::method_apply(const QV4::FunctionObject *b, cons return v4->throwTypeError(); thisObject = argc ? argv : nullptr; if (argc < 2 || argv[1].isNullOrUndefined()) - return f->call(thisObject, argv, 0); + return checkedResult(v4, f->call(thisObject, argv, 0)); Object *arr = argv[1].objectValue(); if (!arr) @@ -398,13 +398,14 @@ ReturnedValue FunctionPrototype::method_apply(const QV4::FunctionObject *b, cons } } - return f->call(thisObject, arguments, len); + return checkedResult(v4, f->call(thisObject, arguments, len)); } ReturnedValue FunctionPrototype::method_call(const QV4::FunctionObject *b, const Value *thisObject, const Value *argv, int argc) { + QV4::ExecutionEngine *v4 = b->engine(); if (!thisObject->isFunctionObject()) - return b->engine()->throwTypeError(); + return v4->throwTypeError(); const FunctionObject *f = static_cast<const FunctionObject *>(thisObject); @@ -413,7 +414,7 @@ ReturnedValue FunctionPrototype::method_call(const QV4::FunctionObject *b, const ++argv; --argc; } - return f->call(thisObject, argv, argc); + return checkedResult(v4, f->call(thisObject, argv, argc)); } ReturnedValue FunctionPrototype::method_bind(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) @@ -713,12 +714,12 @@ void Heap::BoundFunction::init(QV4::ExecutionContext *scope, QV4::FunctionObject ReturnedValue BoundFunction::virtualCall(const FunctionObject *fo, const Value *, const Value *argv, int argc) { - const BoundFunction *f = static_cast<const BoundFunction *>(fo); - Scope scope(f->engine()); - - if (scope.hasException()) + QV4::ExecutionEngine *v4 = fo->engine(); + if (v4->hasException) return Encode::undefined(); + const BoundFunction *f = static_cast<const BoundFunction *>(fo); + Scope scope(v4); Scoped<MemberData> boundArgs(scope, f->boundArgs()); ScopedFunctionObject target(scope, f->target()); JSCallData jsCallData(scope, (boundArgs ? boundArgs->size() : 0) + argc); @@ -729,7 +730,7 @@ ReturnedValue BoundFunction::virtualCall(const FunctionObject *fo, const Value * argp += boundArgs->size(); } memcpy(argp, argv, argc*sizeof(Value)); - return target->call(jsCallData); + return checkedResult(v4, target->call(jsCallData)); } ReturnedValue BoundFunction::virtualCallAsConstructor(const FunctionObject *fo, const Value *argv, int argc, const Value *) diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index c99cad8e33..78be58c60a 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -328,6 +328,10 @@ inline bool FunctionObject::isBoundFunction() const return d()->vtable() == BoundFunction::staticVTable(); } +inline ReturnedValue checkedResult(QV4::ExecutionEngine *v4, ReturnedValue result) +{ + return v4->hasException ? QV4::Encode::undefined() : result; +} } diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp index 64ca719e29..92face6f94 100644 --- a/src/qml/jsruntime/qv4include.cpp +++ b/src/qml/jsruntime/qv4include.cpp @@ -163,7 +163,7 @@ void QV4Include::finished() QV4::Scope scope(v4); QV4::ScopedObject resultObj(scope, m_resultObject.value()); QV4::ScopedString status(scope, v4->newString(QStringLiteral("status"))); - if (m_reply->networkError() == QNetworkReply::NoError) { + if (m_reply->error() == QNetworkReply::NoError) { QByteArray data = m_reply->readAll(); QString code = QString::fromUtf8(data); diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index 936c032fad..ce759111f4 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -703,6 +703,8 @@ QString Stringify::Str(const QString &key, const Value &v) *jsCallData->thisObject = value; jsCallData->args[0] = v4->newString(key); value = toJSON->call(jsCallData); + if (v4->hasException) + return QString(); } } @@ -714,6 +716,8 @@ QString Stringify::Str(const QString &key, const Value &v) jsCallData->args[1] = value; *jsCallData->thisObject = holder; value = replacerFunction->call(jsCallData); + if (v4->hasException) + return QString(); } o = value->asReturnedValue(); diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index 0cda6b864a..d3ea50867a 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -309,7 +309,8 @@ ReturnedValue Lookup::getterAccessor(Lookup *l, ExecutionEngine *engine, const V if (!getter->isFunctionObject()) // ### catch at resolve time return Encode::undefined(); - return static_cast<const FunctionObject *>(getter)->call(&object, nullptr, 0); + return checkedResult(engine, static_cast<const FunctionObject *>(getter)->call( + &object, nullptr, 0)); } } l->getter = getterFallback; @@ -326,7 +327,8 @@ ReturnedValue Lookup::getterProtoAccessor(Lookup *l, ExecutionEngine *engine, co if (!getter->isFunctionObject()) // ### catch at resolve time return Encode::undefined(); - return static_cast<const FunctionObject *>(getter)->call(&object, nullptr, 0); + return checkedResult(engine, static_cast<const FunctionObject *>(getter)->call( + &object, nullptr, 0)); } return getterTwoClasses(l, engine, object); } @@ -346,7 +348,8 @@ ReturnedValue Lookup::getterProtoAccessorTwoClasses(Lookup *l, ExecutionEngine * if (!getter->isFunctionObject()) // ### catch at resolve time return Encode::undefined(); - return static_cast<const FunctionObject *>(getter)->call(&object, nullptr, 0); + return checkedResult(engine, static_cast<const FunctionObject *>(getter)->call( + &object, nullptr, 0)); } } l->getter = getterFallback; @@ -391,7 +394,8 @@ ReturnedValue Lookup::primitiveGetterAccessor(Lookup *l, ExecutionEngine *engine if (!getter->isFunctionObject()) // ### catch at resolve time return Encode::undefined(); - return static_cast<const FunctionObject *>(getter)->call(&object, nullptr, 0); + return checkedResult(engine, static_cast<const FunctionObject *>(getter)->call( + &object, nullptr, 0)); } } l->getter = getterGeneric; @@ -429,7 +433,8 @@ ReturnedValue Lookup::globalGetterProtoAccessor(Lookup *l, ExecutionEngine *engi if (!getter->isFunctionObject()) // ### catch at resolve time return Encode::undefined(); - return static_cast<const FunctionObject *>(getter)->call(engine->globalObject, nullptr, 0); + return checkedResult(engine, static_cast<const FunctionObject *>(getter)->call( + engine->globalObject, nullptr, 0)); } l->globalGetter = globalGetterGeneric; return globalGetterGeneric(l, engine); diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 89161433ed..b723141caa 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -105,7 +105,7 @@ ReturnedValue Object::getValueAccessor(const Value *thisObject, const Value &v, JSCallData jsCallData(scope); if (thisObject) *jsCallData->thisObject = *thisObject; - return f->call(jsCallData); + return checkedResult(scope.engine, f->call(jsCallData)); } bool Object::putValue(uint memberIndex, PropertyAttributes attrs, const Value &value) diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index 7d910a1cbc..0c8cc192fc 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -667,7 +667,7 @@ ReturnedValue ObjectPrototype::method_toLocaleString(const FunctionObject *b, co if (!f) THROW_TYPE_ERROR(); - return f->call(thisObject, argv, argc); + return checkedResult(scope.engine, f->call(thisObject, argv, argc)); } ReturnedValue ObjectPrototype::method_valueOf(const FunctionObject *b, const Value *thisObject, const Value *, int) diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp index 79c372348f..f4901e3e4d 100644 --- a/src/qml/jsruntime/qv4persistent.cpp +++ b/src/qml/jsruntime/qv4persistent.cpp @@ -240,7 +240,6 @@ void PersistentValueStorage::mark(MarkStack *markStack) if (Managed *m = p->values[i].as<Managed>()) m->mark(markStack); } - markStack->drain(); p = p->header.next; } diff --git a/src/qml/jsruntime/qv4promiseobject.cpp b/src/qml/jsruntime/qv4promiseobject.cpp index 17d218a6eb..ecaff72b22 100644 --- a/src/qml/jsruntime/qv4promiseobject.cpp +++ b/src/qml/jsruntime/qv4promiseobject.cpp @@ -618,7 +618,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this } ScopedObject nextPromise(scope, Value::fromReturnedValue(resolve->call(thisObject, nextValue, 1))); - if (!nextPromise || scope.hasException()) { + if (scope.hasException() || !nextPromise) { ScopedValue completion(scope, Runtime::IteratorClose::call(e, iteratorObject, doneValue)); if (scope.hasException()) { completion = e->exceptionValue->asReturnedValue(); @@ -764,7 +764,7 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi } ScopedObject nextPromise(scope, Value::fromReturnedValue(resolve->call(thisObject, nextValue, 1))); - if (!nextPromise || scope.hasException()) { + if (scope.hasException() || !nextPromise) { ScopedValue completion(scope, Runtime::IteratorClose::call(e, iteratorObject, doneValue)); if (scope.hasException()) { completion = e->exceptionValue->asReturnedValue(); diff --git a/src/qml/jsruntime/qv4proxy.cpp b/src/qml/jsruntime/qv4proxy.cpp index 51f96b9003..24676ffd00 100644 --- a/src/qml/jsruntime/qv4proxy.cpp +++ b/src/qml/jsruntime/qv4proxy.cpp @@ -96,6 +96,8 @@ ReturnedValue ProxyObject::virtualGet(const Managed *m, PropertyKey id, const Va cdata.args[2] = *receiver; ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); + if (scope.engine->hasException) + return Encode::undefined(); ScopedProperty targetDesc(scope); PropertyAttributes attributes = target->getOwnProperty(id, targetDesc); if (attributes != Attr_Invalid && !attributes.isConfigurable()) { @@ -136,7 +138,7 @@ bool ProxyObject::virtualPut(Managed *m, PropertyKey id, const Value &value, Val cdata.args[3] = *receiver; ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); - if (!trapResult->toBoolean()) + if (scope.engine->hasException || !trapResult->toBoolean()) return false; ScopedProperty targetDesc(scope); PropertyAttributes attributes = target->getOwnProperty(id, targetDesc); @@ -176,7 +178,7 @@ bool ProxyObject::virtualDeleteProperty(Managed *m, PropertyKey id) cdata.args[2] = o->d(); // ### fix receiver handling ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); - if (!trapResult->toBoolean()) + if (scope.engine->hasException || !trapResult->toBoolean()) return false; ScopedProperty targetDesc(scope); PropertyAttributes attributes = target->getOwnProperty(id, targetDesc); @@ -211,6 +213,8 @@ bool ProxyObject::virtualHasProperty(const Managed *m, PropertyKey id) cdata.args[1] = id.isArrayIndex() ? Value::fromUInt32(id.asArrayIndex()).toString(scope.engine) : id.asStringOrSymbol(); ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); + if (scope.engine->hasException) + return false; bool result = trapResult->toBoolean(); if (!result) { ScopedProperty targetDesc(scope); @@ -251,6 +255,8 @@ PropertyAttributes ProxyObject::virtualGetOwnProperty(const Managed *m, Property cdata.args[1] = id.isArrayIndex() ? Value::fromUInt32(id.asArrayIndex()).toString(scope.engine) : id.asStringOrSymbol(); ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); + if (scope.engine->hasException) + return Attr_Invalid; if (!trapResult->isObject() && !trapResult->isUndefined()) { scope.engine->throwTypeError(); return Attr_Invalid; @@ -323,7 +329,7 @@ bool ProxyObject::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Pro cdata.args[2] = ObjectPrototype::fromPropertyDescriptor(scope.engine, p, attrs); ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); - bool result = trapResult->toBoolean(); + bool result = !scope.engine->hasException && trapResult->toBoolean(); if (!result) return false; @@ -373,6 +379,8 @@ bool ProxyObject::virtualIsExtensible(const Managed *m) cdata.args[0] = target; ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); + if (scope.engine->hasException) + return false; bool result = trapResult->toBoolean(); if (result != target->isExtensible()) { scope.engine->throwTypeError(); @@ -404,6 +412,8 @@ bool ProxyObject::virtualPreventExtensions(Managed *m) cdata.args[0] = target; ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); + if (scope.engine->hasException) + return false; bool result = trapResult->toBoolean(); if (result && target->isExtensible()) { scope.engine->throwTypeError(); @@ -439,6 +449,8 @@ Heap::Object *ProxyObject::virtualGetPrototypeOf(const Managed *m) cdata.args[0] = target; ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); + if (scope.engine->hasException) + return nullptr; if (!trapResult->isNull() && !trapResult->isObject()) { scope.engine->throwTypeError(); return nullptr; @@ -482,7 +494,7 @@ bool ProxyObject::virtualSetPrototypeOf(Managed *m, const Object *p) cdata.args[1] = p ? p->asReturnedValue() : Encode::null(); ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); - bool result = trapResult->toBoolean(); + bool result = !scope.engine->hasException && trapResult->toBoolean(); if (!result) return false; if (!target->isExtensible()) { @@ -573,6 +585,8 @@ OwnPropertyKeyIterator *ProxyObject::virtualOwnPropertyKeys(const Object *m, Val JSCallData cdata(scope, 1, nullptr, handler); cdata.args[0] = target; ScopedObject trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); + if (scope.engine->hasException) + return nullptr; if (!trapResult) { scope.engine->throwTypeError(); return nullptr; @@ -699,7 +713,7 @@ ReturnedValue ProxyFunctionObject::virtualCall(const FunctionObject *f, const Va if (scope.hasException()) return Encode::undefined(); if (trap->isNullOrUndefined()) - return target->call(thisObject, argv, argc); + return checkedResult(scope.engine, target->call(thisObject, argv, argc)); if (!trap->isFunctionObject()) return scope.engine->throwTypeError(); diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 9613d064c4..66b79aa0e8 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -638,10 +638,11 @@ void QObjectWrapper::markWrapper(QObject *object, MarkStack *markStack) if (!ddata) return; - if (ddata->jsEngineId == markStack->engine->m_engineId) + const QV4::ExecutionEngine *engine = markStack->engine(); + if (ddata->jsEngineId == engine->m_engineId) ddata->jsWrapper.markOnce(markStack); - else if (markStack->engine->m_multiplyWrappedQObjects && ddata->hasTaintedV4Object) - markStack->engine->m_multiplyWrappedQObjects->mark(object, markStack); + else if (engine->m_multiplyWrappedQObjects && ddata->hasTaintedV4Object) + engine->m_multiplyWrappedQObjects->mark(object, markStack); } void QObjectWrapper::setProperty(ExecutionEngine *engine, int propertyIndex, const Value &value) diff --git a/src/qml/jsruntime/qv4reflect.cpp b/src/qml/jsruntime/qv4reflect.cpp index 0772770d63..2a6c61f044 100644 --- a/src/qml/jsruntime/qv4reflect.cpp +++ b/src/qml/jsruntime/qv4reflect.cpp @@ -98,7 +98,8 @@ ReturnedValue Reflect::method_apply(const FunctionObject *f, const Value *, cons if (scope.hasException()) return Encode::undefined(); - return static_cast<const FunctionObject &>(argv[0]).call(&argv[1], arguments.argv, arguments.argc); + return checkedResult(scope.engine, static_cast<const FunctionObject &>(argv[0]).call( + &argv[1], arguments.argv, arguments.argc)); } ReturnedValue Reflect::method_construct(const FunctionObject *f, const Value *, const Value *argv, int argc) diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index f1375e4ca4..a8a37cda37 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -481,6 +481,8 @@ ReturnedValue RegExpPrototype::exec(ExecutionEngine *engine, const Object *o, co ScopedFunctionObject exec(scope, o->get(key)); if (exec) { ScopedValue result(scope, exec->call(o, s, 1)); + if (scope.hasException()) + RETURN_UNDEFINED(); if (!result->isNull() && !result->isObject()) return scope.engine->throwTypeError(); return result->asReturnedValue(); @@ -737,6 +739,8 @@ ReturnedValue RegExpPrototype::method_replace(const FunctionObject *f, const Val cData->args[nCaptures + 1] = Encode(position); cData->args[nCaptures + 2] = s; ScopedValue replValue(scope, replaceFunction->call(cData)); + if (scope.hasException()) + return Encode::undefined(); replacement = replValue->toQString(); } else { replacement = RegExp::getSubstitution(matchString->toQString(), s->toQString(), position, cData.args, nCaptures, replaceValue->toQString()); diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index e47a7a0b46..5fc94b9ddd 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -390,7 +390,7 @@ QV4::ReturnedValue Runtime::Instanceof::call(ExecutionEngine *engine, const Valu return engine->throwTypeError(); ScopedValue result(scope, fHasInstance->call(&rval, &lval, 1)); - return Encode(result->toBoolean()); + return scope.hasException() ? Encode::undefined() : Encode(result->toBoolean()); } QV4::ReturnedValue Runtime::In::call(ExecutionEngine *engine, const Value &left, const Value &right) @@ -515,6 +515,8 @@ ReturnedValue RuntimeHelpers::ordinaryToPrimitive(ExecutionEngine *engine, const ScopedValue conv(scope, object->get(meth1)); if (FunctionObject *o = conv->as<FunctionObject>()) { result = o->call(object, nullptr, 0); + if (engine->hasException) + return Encode::undefined(); if (result->isPrimitive()) return result->asReturnedValue(); } @@ -525,6 +527,8 @@ ReturnedValue RuntimeHelpers::ordinaryToPrimitive(ExecutionEngine *engine, const conv = object->get(meth2); if (FunctionObject *o = conv->as<FunctionObject>()) { result = o->call(object, nullptr, 0); + if (engine->hasException) + return Encode::undefined(); if (result->isPrimitive()) return result->asReturnedValue(); } @@ -800,6 +804,8 @@ ReturnedValue Runtime::GetIterator::call(ExecutionEngine *engine, const Value &i return engine->throwTypeError(); JSCallData cData(scope, 0, nullptr, o); ScopedObject it(scope, f->call(cData)); + if (engine->hasException) + return Encode::undefined(); if (!it) return engine->throwTypeError(); return it->asReturnedValue(); @@ -1341,7 +1347,8 @@ ReturnedValue Runtime::CallGlobalLookup::call(ExecutionEngine *engine, uint inde engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]->toQString()); } - return static_cast<FunctionObject &>(function).call(&thisObject, argv, argc); + return checkedResult(engine, static_cast<FunctionObject &>(function).call( + &thisObject, argv, argc)); } ReturnedValue Runtime::CallQmlContextPropertyLookup::call(ExecutionEngine *engine, uint index, @@ -1356,7 +1363,8 @@ ReturnedValue Runtime::CallQmlContextPropertyLookup::call(ExecutionEngine *engin engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]->toQString()); } - return static_cast<FunctionObject &>(function).call(thisObject, argv, argc); + return checkedResult(engine, static_cast<FunctionObject &>(function).call( + thisObject, argv, argc)); } ReturnedValue Runtime::CallPossiblyDirectEval::call(ExecutionEngine *engine, Value *argv, int argc) @@ -1375,7 +1383,7 @@ ReturnedValue Runtime::CallPossiblyDirectEval::call(ExecutionEngine *engine, Val if (function->d() == engine->evalFunction()->d()) return static_cast<EvalFunction *>(function.getPointer())->evalCall(thisObject, argv, argc, true); - return function->call(thisObject, argv, argc); + return checkedResult(engine, function->call(thisObject, argv, argc)); } ReturnedValue Runtime::CallName::call(ExecutionEngine *engine, int nameIndex, Value *argv, int argc) @@ -1395,7 +1403,7 @@ ReturnedValue Runtime::CallName::call(ExecutionEngine *engine, int nameIndex, Va ->runtimeStrings[nameIndex]->toQString()); } - return f->call(thisObject, argv, argc); + return checkedResult(engine, f->call(thisObject, argv, argc)); } ReturnedValue Runtime::CallProperty::call(ExecutionEngine *engine, const Value &baseRef, int nameIndex, Value *argv, int argc) @@ -1437,7 +1445,7 @@ ReturnedValue Runtime::CallProperty::call(ExecutionEngine *engine, const Value & return engine->throwTypeError(error); } - return f->call(base, argv, argc); + return checkedResult(engine, f->call(base, argv, argc)); } ReturnedValue Runtime::CallPropertyLookup::call(ExecutionEngine *engine, const Value &base, uint index, Value *argv, int argc) @@ -1449,7 +1457,7 @@ ReturnedValue Runtime::CallPropertyLookup::call(ExecutionEngine *engine, const V if (!f.isFunctionObject()) return engine->throwTypeError(); - return static_cast<FunctionObject &>(f).call(&base, argv, argc); + return checkedResult(engine, static_cast<FunctionObject &>(f).call(&base, argv, argc)); } ReturnedValue Runtime::CallElement::call(ExecutionEngine *engine, const Value &baseRef, const Value &index, Value *argv, int argc) @@ -1467,7 +1475,7 @@ ReturnedValue Runtime::CallElement::call(ExecutionEngine *engine, const Value &b if (!f) return engine->throwTypeError(); - return f->call(base, argv, argc); + return checkedResult(engine, f->call(base, argv, argc)); } ReturnedValue Runtime::CallValue::call(ExecutionEngine *engine, const Value &func, Value *argv, int argc) @@ -1475,7 +1483,8 @@ ReturnedValue Runtime::CallValue::call(ExecutionEngine *engine, const Value &fun if (!func.isFunctionObject()) return engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow())); Value undef = Value::undefinedValue(); - return static_cast<const FunctionObject &>(func).call(&undef, argv, argc); + return checkedResult(engine, static_cast<const FunctionObject &>(func).call( + &undef, argv, argc)); } ReturnedValue Runtime::CallWithReceiver::call(ExecutionEngine *engine, const Value &func, @@ -1483,7 +1492,8 @@ ReturnedValue Runtime::CallWithReceiver::call(ExecutionEngine *engine, const Val { if (!func.isFunctionObject()) return engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow())); - return static_cast<const FunctionObject &>(func).call(&thisObject, argv, argc); + return checkedResult(engine, static_cast<const FunctionObject &>(func).call( + &thisObject, argv, argc)); } struct CallArgs { @@ -1537,7 +1547,8 @@ ReturnedValue Runtime::CallWithSpread::call(ExecutionEngine *engine, const Value if (engine->hasException) return Encode::undefined(); - return static_cast<const FunctionObject &>(function).call(&thisObject, arguments.argv, arguments.argc); + return checkedResult(engine, static_cast<const FunctionObject &>(function).call( + &thisObject, arguments.argv, arguments.argc)); } ReturnedValue Runtime::Construct::call(ExecutionEngine *engine, const Value &function, const Value &newTarget, Value *argv, int argc) @@ -1580,7 +1591,7 @@ ReturnedValue Runtime::TailCall::call(CppStackFrame *frame, ExecutionEngine *eng if (!frame->callerCanHandleTailCall || !fo.canBeTailCalled() || engine->debugger() || unsigned(argc) > fo.formalParameterCount()) { // Cannot tailcall, do a normal call: - return fo.call(&thisObject, argv, argc); + return checkedResult(engine, fo.call(&thisObject, argv, argc)); } memcpy(frame->jsFrame->args, argv, argc * sizeof(Value)); diff --git a/src/qml/jsruntime/qv4runtimecodegen.cpp b/src/qml/jsruntime/qv4runtimecodegen.cpp index 162d75db63..b7737982b7 100644 --- a/src/qml/jsruntime/qv4runtimecodegen.cpp +++ b/src/qml/jsruntime/qv4runtimecodegen.cpp @@ -67,7 +67,7 @@ void RuntimeCodegen::generateFromFunctionExpression(const QString &fileName, _module->rootContext = _module->functions.at(index); } -void RuntimeCodegen::throwSyntaxError(const AST::SourceLocation &loc, const QString &detail) +void RuntimeCodegen::throwSyntaxError(const SourceLocation &loc, const QString &detail) { if (hasError()) return; @@ -76,7 +76,7 @@ void RuntimeCodegen::throwSyntaxError(const AST::SourceLocation &loc, const QStr engine->throwSyntaxError(detail, _module->fileName, loc.startLine, loc.startColumn); } -void RuntimeCodegen::throwReferenceError(const AST::SourceLocation &loc, const QString &detail) +void RuntimeCodegen::throwReferenceError(const SourceLocation &loc, const QString &detail) { if (hasError()) return; diff --git a/src/qml/jsruntime/qv4runtimecodegen_p.h b/src/qml/jsruntime/qv4runtimecodegen_p.h index 71aaf1fb55..d3a30ce35d 100644 --- a/src/qml/jsruntime/qv4runtimecodegen_p.h +++ b/src/qml/jsruntime/qv4runtimecodegen_p.h @@ -69,8 +69,8 @@ public: QQmlJS::AST::FunctionExpression *ast, Compiler::Module *module); - void throwSyntaxError(const QQmlJS::AST::SourceLocation &loc, const QString &detail) override; - void throwReferenceError(const QQmlJS::AST::SourceLocation &loc, const QString &detail) override; + void throwSyntaxError(const QQmlJS::SourceLocation &loc, const QString &detail) override; + void throwReferenceError(const QQmlJS::SourceLocation &loc, const QString &detail) override; private: ExecutionEngine *engine; diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 2fab9e4b7b..2add1222ea 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -52,6 +52,7 @@ #include <private/qqmljsparser_p.h> #include <private/qqmljsast_p.h> #include <private/qqmlengine_p.h> +#include <private/qqmlsourcecoordinate_p.h> #include <private/qv4profiling_p.h> #include <qv4runtimecodegen_p.h> @@ -109,10 +110,10 @@ void Script::parse() const auto diagnosticMessages = parser.diagnosticMessages(); for (const DiagnosticMessage &m : diagnosticMessages) { if (m.isError()) { - valueScope.engine->throwSyntaxError(m.message, sourceFile, m.line, m.column); + valueScope.engine->throwSyntaxError(m.message, sourceFile, m.loc.startLine, m.loc.startColumn); return; } else { - qWarning() << sourceFile << ':' << m.line << ':' << m.column + qWarning() << sourceFile << ':' << m.loc.startLine << ':' << m.loc.startColumn << ": warning: " << m.message; } } @@ -209,8 +210,8 @@ QV4::CompiledData::CompilationUnit Script::precompile( const auto v4Error = cg.error(); QQmlError error; error.setUrl(cg.url()); - error.setLine(v4Error.line); - error.setColumn(v4Error.column); + error.setLine(qmlConvertSourceCoordinate<quint32, int>(v4Error.loc.startLine)); + error.setColumn(qmlConvertSourceCoordinate<quint32, int>(v4Error.loc.startColumn)); error.setDescription(v4Error.message); reportedErrors->append(error); } diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index 9b4a2d575e..209a1b4e76 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -591,7 +591,7 @@ ReturnedValue StringPrototype::method_match(const FunctionObject *b, const Value ScopedFunctionObject match(scope, that->get(scope.engine->symbol_match())); if (!match) return scope.engine->throwTypeError(); - return match->call(that, s, 1); + return checkedResult(scope.engine, match->call(that, s, 1)); } ReturnedValue StringPrototype::method_normalize(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc) diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp index 40a434d301..f425c6c87f 100644 --- a/src/qml/jsruntime/qv4typedarray.cpp +++ b/src/qml/jsruntime/qv4typedarray.cpp @@ -763,6 +763,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_every(const FunctionObject *b arguments[1] = Value::fromDouble(k); arguments[2] = v; r = callback->call(that, arguments, 3); + CHECK_EXCEPTION(); ok = r->toBoolean(); } return Encode(ok); @@ -862,6 +863,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_filter(const FunctionObject * arguments[1] = Value::fromDouble(k); arguments[2] = instance; selected = callback->call(that, arguments, 3); + CHECK_EXCEPTION(); if (selected->toBoolean()) { ++arguments; scope.alloc(1); @@ -1194,6 +1196,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_map(const FunctionObject *b, arguments[1] = Value::fromDouble(k); arguments[2] = instance; mapped = callback->call(that, arguments, 3); + CHECK_EXCEPTION(); a->put(k, mapped); } return a->asReturnedValue(); @@ -1243,6 +1246,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_reduce(const FunctionObject * arguments[2] = Value::fromDouble(k); arguments[3] = instance; acc = callback->call(nullptr, arguments, 4); + CHECK_EXCEPTION(); } ++k; } @@ -1298,6 +1302,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_reduceRight(const FunctionObj arguments[2] = Value::fromDouble(k - 1); arguments[3] = instance; acc = callback->call(nullptr, arguments, 4); + CHECK_EXCEPTION(); } --k; } @@ -1359,6 +1364,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_some(const FunctionObject *b, arguments[1] = Value::fromDouble(k); arguments[2] = instance; result = callback->call(that, arguments, 3); + CHECK_EXCEPTION(); if (result->toBoolean()) return Encode(true); } diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp index d29b060b9e..3449603a8a 100644 --- a/src/qml/jsruntime/qv4value.cpp +++ b/src/qml/jsruntime/qv4value.cpp @@ -250,6 +250,8 @@ bool Value::sameValue(Value other) const { if (isDouble() && other.isInteger()) return other.int_32() ? (doubleValue() == double(other.int_32())) : (doubleValue() == 0 && !std::signbit(doubleValue())); + if (isManaged()) + return other.isManaged() && cast<Managed>()->isEqualTo(other.cast<Managed>()); return false; } @@ -269,6 +271,8 @@ bool Value::sameValueZero(Value other) const { return true; } } + if (isManaged()) + return other.isManaged() && cast<Managed>()->isEqualTo(other.cast<Managed>()); return false; } diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index ae12033eb4..42e97b1d36 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -537,29 +537,8 @@ struct ValueArray { } void mark(MarkStack *markStack) { - Value *v = values; - const Value *end = v + alloc; - if (alloc > 32*1024) { - // drain from time to time to avoid overflows in the js stack - Value::HeapBasePtr *currentBase = markStack->top; - while (v < end) { - v->mark(markStack); - ++v; - if (markStack->top >= currentBase + 32*1024) { - Value::HeapBasePtr *oldBase = markStack->base; - markStack->base = currentBase; - markStack->drain(); - markStack->base = oldBase; - } - } - } else { - while (v < end) { - v->mark(markStack); - if (markStack->top >= markStack->limit) - markStack->drain(); - ++v; - } - } + for (Value *v = values, *end = values + alloc; v < end; ++v) + v->mark(markStack); } }; diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 35b2ff2749..3ed1bc48fd 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -848,16 +848,18 @@ Heap::Object *MemoryManager::allocObjectWithMemberData(const QV4::VTable *vtable static uint markStackSize = 0; MarkStack::MarkStack(ExecutionEngine *engine) - : engine(engine) + : m_engine(engine) { - base = (Heap::Base **)engine->gcStack->base(); - top = base; - limit = base + engine->maxGCStackSize()/sizeof(Heap::Base)*3/4; + m_base = (Heap::Base **)engine->gcStack->base(); + m_top = m_base; + const size_t size = engine->maxGCStackSize() / sizeof(Heap::Base); + m_hardLimit = m_base + size; + m_softLimit = m_base + size * 3 / 4; } void MarkStack::drain() { - while (top > base) { + while (m_top > m_base) { Heap::Base *h = pop(); ++markStackSize; Q_ASSERT(h); // at this point we should only have Heap::Base objects in this area on the stack. If not, weird things might happen. @@ -904,20 +906,15 @@ void MemoryManager::collectRoots(MarkStack *markStack) if (keepAlive) qobjectWrapper->mark(markStack); - - if (markStack->top >= markStack->limit) - markStack->drain(); } } void MemoryManager::mark() { markStackSize = 0; - MarkStack markStack(engine); collectRoots(&markStack); - - markStack.drain(); + // dtor of MarkStack drains } void MemoryManager::sweep(bool lastSweep, ClassDestroyStatsCallback classCountPtr) @@ -1220,8 +1217,6 @@ void MemoryManager::collectFromJSStack(MarkStack *markStack) const Q_ASSERT(m->inUse()); // Skip pointers to already freed objects, they are bogus as well m->mark(markStack); - if (markStack->top >= markStack->limit) - markStack->drain(); } ++v; } diff --git a/src/qml/memory/qv4mmdefs_p.h b/src/qml/memory/qv4mmdefs_p.h index 8a53492822..117e8f4360 100644 --- a/src/qml/memory/qv4mmdefs_p.h +++ b/src/qml/memory/qv4mmdefs_p.h @@ -53,6 +53,7 @@ #include <private/qv4global_p.h> #include <private/qv4runtimeapi_p.h> #include <QtCore/qalgorithms.h> +#include <QtCore/qmath.h> #include <qdebug.h> QT_BEGIN_NAMESPACE @@ -270,22 +271,41 @@ Q_STATIC_ASSERT(sizeof(HeapItem) == Chunk::SlotSize); Q_STATIC_ASSERT(QT_POINTER_SIZE*8 == Chunk::Bits); Q_STATIC_ASSERT((1 << Chunk::BitShift) == Chunk::Bits); -struct MarkStack { +struct Q_QML_PRIVATE_EXPORT MarkStack { MarkStack(ExecutionEngine *engine); - Heap::Base **top = nullptr; - Heap::Base **base = nullptr; - Heap::Base **limit = nullptr; - ExecutionEngine *engine; + ~MarkStack() { drain(); } + void push(Heap::Base *m) { - *top = m; - ++top; - } - Heap::Base *pop() { - --top; - return *top; + *(m_top++) = m; + + if (m_top < m_softLimit) + return; + + // If at or above soft limit, partition the remaining space into at most 64 segments and + // allow one C++ recursion of drain() per segment, plus one for the fence post. + const quintptr segmentSize = qNextPowerOfTwo(quintptr(m_hardLimit - m_softLimit) / 64u); + if (m_drainRecursion * segmentSize <= quintptr(m_top - m_softLimit)) { + ++m_drainRecursion; + drain(); + --m_drainRecursion; + } else if (m_top == m_hardLimit) { + qFatal("GC mark stack overrun. Either simplify your application or" + "increase QV4_GC_MAX_STACK_SIZE"); + } } + + ExecutionEngine *engine() const { return m_engine; } + +private: + Heap::Base *pop() { return *(--m_top); } void drain(); + Heap::Base **m_top = nullptr; + Heap::Base **m_base = nullptr; + Heap::Base **m_softLimit = nullptr; + Heap::Base **m_hardLimit = nullptr; + ExecutionEngine *m_engine = nullptr; + quintptr m_drainRecursion = 0; }; // Some helper to automate the generation of our diff --git a/src/qml/parser/parser.pri b/src/qml/parser/parser.pri index e15730f5d1..57855a82f9 100644 --- a/src/qml/parser/parser.pri +++ b/src/qml/parser/parser.pri @@ -5,9 +5,7 @@ HEADERS += \ $$PWD/qqmljsengine_p.h \ $$PWD/qqmljslexer_p.h \ $$PWD/qqmljsglobal_p.h \ - $$PWD/qqmljskeywords_p.h \ - $$PWD/qqmljsengine_p.h \ - $$PWD/qqmljssourcelocation_p.h + $$PWD/qqmljskeywords_p.h SOURCES += \ $$PWD/qqmljsast.cpp \ diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g index 397c0b51a5..ef814a57b0 100644 --- a/src/qml/parser/qqmljs.g +++ b/src/qml/parser/qqmljs.g @@ -73,7 +73,7 @@ %token T_VAR "var" T_VOID "void" T_WHILE "while" %token T_WITH "with" T_XOR "^" T_XOR_EQ "^=" %token T_NULL "null" T_TRUE "true" T_FALSE "false" -%token T_CONST "const" T_LET "let" +%token T_CONST "const" T_LET "let" T_AT "@" %token T_DEBUGGER "debugger" %token T_RESERVED_WORD "reserved word" %token T_MULTILINE_STRING_LITERAL "multiline string literal" @@ -326,6 +326,8 @@ public: AST::UiQualifiedId *UiQualifiedId; AST::UiEnumMemberList *UiEnumMemberList; AST::UiVersionSpecifier *UiVersionSpecifier; + AST::UiAnnotation *UiAnnotation; + AST::UiAnnotationList *UiAnnotationList; }; public: @@ -388,10 +390,10 @@ public: { return diagnosticMessage().message; } inline int errorLineNumber() const - { return diagnosticMessage().line; } + { return diagnosticMessage().loc.startLine; } inline int errorColumnNumber() const - { return diagnosticMessage().column; } + { return diagnosticMessage().loc.startColumn; } protected: bool parse(int startToken); @@ -407,7 +409,7 @@ protected: inline QStringRef &rawStringRef(int index) { return rawString_stack [tos + index - 1]; } - inline AST::SourceLocation &loc(int index) + inline SourceLocation &loc(int index) { return location_stack [tos + index - 1]; } AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr); @@ -415,21 +417,20 @@ protected: void pushToken(int token); int lookaheadToken(Lexer *lexer); - static DiagnosticMessage compileError(const AST::SourceLocation &location, + static DiagnosticMessage compileError(const SourceLocation &location, const QString &message, QtMsgType kind = QtCriticalMsg) { DiagnosticMessage error; - error.line = location.startLine; - error.column = location.startColumn; + error.loc = location; error.message = message; error.type = kind; return error; } - void syntaxError(const AST::SourceLocation &location, const char *message) { + void syntaxError(const SourceLocation &location, const char *message) { diagnostic_messages.append(compileError(location, QLatin1String(message))); } - void syntaxError(const AST::SourceLocation &location, const QString &message) { + void syntaxError(const SourceLocation &location, const QString &message) { diagnostic_messages.append(compileError(location, message)); } @@ -442,7 +443,7 @@ protected: int stack_size = 0; Value *sym_stack = nullptr; int *state_stack = nullptr; - AST::SourceLocation *location_stack = nullptr; + SourceLocation *location_stack = nullptr; QVector<QStringRef> string_stack; QVector<QStringRef> rawString_stack; @@ -454,7 +455,7 @@ protected: struct SavedToken { int token; double dval; - AST::SourceLocation loc; + SourceLocation loc; QStringRef spell; QStringRef raw; }; @@ -463,8 +464,8 @@ protected: double yylval = 0.; QStringRef yytokenspell; QStringRef yytokenraw; - AST::SourceLocation yylloc; - AST::SourceLocation yyprevlloc; + SourceLocation yylloc; + SourceLocation yyprevlloc; SavedToken token_buffer[TOKEN_BUFFER_SIZE]; SavedToken *first_token = nullptr; @@ -477,7 +478,7 @@ protected: CE_ParenthesizedExpression, CE_FormalParameterList }; - AST::SourceLocation coverExpressionErrorLocation; + SourceLocation coverExpressionErrorLocation; CoverExpressionType coverExpressionType = CE_Invalid; QList<DiagnosticMessage> diagnostic_messages; @@ -522,7 +523,7 @@ void Parser::reallocateStack() sym_stack = reinterpret_cast<Value*> (realloc(sym_stack, stack_size * sizeof(Value))); state_stack = reinterpret_cast<int*> (realloc(state_stack, stack_size * sizeof(int))); - location_stack = reinterpret_cast<AST::SourceLocation*> (realloc(location_stack, stack_size * sizeof(AST::SourceLocation))); + location_stack = reinterpret_cast<SourceLocation*> (realloc(location_stack, stack_size * sizeof(SourceLocation))); string_stack.resize(stack_size); rawString_stack.resize(stack_size); } @@ -542,9 +543,9 @@ Parser::~Parser() } } -static inline AST::SourceLocation location(Lexer *lexer) +static inline SourceLocation location(Lexer *lexer) { - AST::SourceLocation loc; + SourceLocation loc; loc.offset = lexer->tokenOffset(); loc.length = lexer->tokenLength(); loc.startLine = lexer->tokenStartLine(); @@ -555,7 +556,7 @@ static inline AST::SourceLocation location(Lexer *lexer) AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) { QVarLengthArray<QStringRef, 4> nameIds; - QVarLengthArray<AST::SourceLocation, 4> locations; + QVarLengthArray<SourceLocation, 4> locations; AST::ExpressionNode *it = expr; while (AST::FieldMemberExpression *m = AST::cast<AST::FieldMemberExpression *>(it)) { @@ -739,7 +740,7 @@ TopLevel: T_FEED_JS_EXPRESSION Expression; } break; ./ -TopLevel: T_FEED_UI_OBJECT_MEMBER UiObjectMember; +TopLevel: T_FEED_UI_OBJECT_MEMBER UiAnnotatedObjectMember; /. case $rule_number: { sym(1).Node = sym(2).Node; @@ -834,7 +835,15 @@ UiImport: UiImportHead Semicolon; UiVersionSpecifier: T_VERSION_NUMBER T_DOT T_VERSION_NUMBER; /. case $rule_number: { - auto version = new (pool) AST::UiVersionSpecifier(sym(1).dval, sym(3).dval); + const int major = sym(1).dval; + const int minor = sym(3).dval; + if (!QTypeRevision::isValidSegment(major) || !QTypeRevision::isValidSegment(minor)) { + diagnostic_messages.append( + compileError(loc(1), + QLatin1String("Invalid version. Version numbers must be >= 0 and < 255."))); + return false; + } + auto version = new (pool) AST::UiVersionSpecifier(major, minor); version->majorToken = loc(1); version->minorToken = loc(3); sym(1).UiVersionSpecifier = version; @@ -845,6 +854,13 @@ UiVersionSpecifier: T_VERSION_NUMBER T_DOT T_VERSION_NUMBER; UiVersionSpecifier: T_VERSION_NUMBER; /. case $rule_number: { + const int major = sym(1).dval; + if (!QTypeRevision::isValidSegment(major)) { + diagnostic_messages.append( + compileError(loc(1), + QLatin1String("Invalid major version. Version numbers must be >= 0 and < 255."))); + return false; + } auto version = new (pool) AST::UiVersionSpecifier(sym(1).dval, 0); version->majorToken = loc(1); sym(1).UiVersionSpecifier = version; @@ -913,21 +929,92 @@ Empty: ; } break; ./ -UiRootMember: UiObjectDefinition; +UiRootMember: UiAnnotatedObject; /. case $rule_number: { sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember); } break; ./ -UiObjectMemberList: UiObjectMember; +UiSimpleQualifiedId: T_IDENTIFIER; +/. + case $rule_number: { + AST::IdentifierExpression *node = new (pool) AST::IdentifierExpression(stringRef(1)); + node->identifierToken = loc(1); + sym(1).Node = node; + } break; +./ + +UiSimpleQualifiedId: UiSimpleQualifiedId T_DOT T_IDENTIFIER; +/. + case $rule_number: { + AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); + node->dotToken = loc(2); + node->identifierToken = loc(3); + sym(1).Node = node; + } break; +./ + +UiAnnotationObjectDefinition: UiSimpleQualifiedId UiObjectInitializer; +/. + case $rule_number: { + if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) { + sym(1).UiQualifiedId = qualifiedId; + } else { + sym(1).UiQualifiedId = 0; + + diagnostic_messages.append(compileError(loc(1), + QLatin1String("Expected a qualified name id"))); + + return false; + } + AST::UiAnnotation *node = new (pool) AST::UiAnnotation(sym(1).UiQualifiedId, sym(2).UiObjectInitializer); + sym(1).Node = node; + } break; +./ + +UiAnnotation: T_AT UiAnnotationObjectDefinition; +/. +case $rule_number: { + sym(1).Node = sym(2).Node; +} break; +./ + + +UiAnnotationList: UiAnnotation; +/. + case $rule_number: { + sym(1).Node = new (pool) AST::UiAnnotationList(sym(1).UiAnnotation); + } break; +./ + +UiAnnotationList: UiAnnotationList UiAnnotation; +/. + case $rule_number: { + AST::UiAnnotationList *node = new (pool) AST::UiAnnotationList(sym(1).UiAnnotationList, sym(2).UiAnnotation); + sym(1).Node = node; + } break; +./ + +UiAnnotatedObject: UiAnnotationList UiObjectDefinition; +/. + case $rule_number: { + AST::UiObjectDefinition *node = sym(2).UiObjectDefinition; + node->annotations = sym(1).UiAnnotationList->finish(); + sym(1).Node = node; + } break; +./ + +UiAnnotatedObject: UiObjectDefinition; + +UiObjectMemberList: UiAnnotatedObjectMember; /. case $rule_number: { sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember); } break; ./ -UiObjectMemberList: UiObjectMemberList UiObjectMember; +UiObjectMemberList: UiObjectMemberList UiAnnotatedObjectMember; /. case $rule_number: { AST::UiObjectMemberList *node = new (pool) AST:: UiObjectMemberList(sym(1).UiObjectMemberList, sym(2).UiObjectMember); @@ -979,6 +1066,17 @@ UiObjectDefinition: UiQualifiedId UiObjectInitializer; } break; ./ +UiAnnotatedObjectMember: UiAnnotationList UiObjectMember; +/. + case $rule_number: { + AST::UiObjectMember *node = sym(2).UiObjectMember; + node->annotations = sym(1).UiAnnotationList->finish(); + sym(1).Node = sym(2).Node; + } break; +./ + +UiAnnotatedObjectMember: UiObjectMember; + UiObjectMember: UiObjectDefinition; UiObjectMember: UiQualifiedId T_COLON ExpressionStatementLookahead T_LBRACKET UiArrayMemberList T_RBRACKET; @@ -1247,12 +1345,49 @@ UiObjectMember: T_DEFAULT UiObjectMemberListPropertyNoInitialiser; } break; ./ +UiObjectMember: T_DEFAULT T_REQUIRED UiObjectMemberPropertyNoInitialiser; +/. + case $rule_number: { + AST::UiPublicMember *node = sym(3).UiPublicMember; + node->isDefaultMember = true; + node->defaultToken = loc(1); + node->isRequired = true; + node->requiredToken = loc(2); + sym(1).Node = node; + } break; +./ + + +UiObjectMember: T_REQUIRED T_DEFAULT UiObjectMemberPropertyNoInitialiser; +/. + case $rule_number: { + AST::UiPublicMember *node = sym(3).UiPublicMember; + node->isDefaultMember = true; + node->defaultToken = loc(2); + node->isRequired = true; + node->requiredToken = loc(1); + sym(1).Node = node; + } break; +./ + OptionalSemicolon: | Semicolon; /. /* we need OptionalSemicolon because UiScriptStatement might already parse the last semicolon and then we would miss a semicolon (see tests/auto/quick/qquickvisualdatamodel/data/objectlist.qml)*/ ./ +UiRequired: T_REQUIRED QmlIdentifier Semicolon; +/. + case $rule_number: { + AST::UiRequired *node = new (pool) AST::UiRequired(stringRef(2)); + node->requiredToken = loc(1); + node->semicolonToken = loc(3); + sym(1).Node = node; + } break; +./ + +UiObjectMember: UiRequired; + UiObjectMember: T_REQUIRED UiObjectMemberPropertyNoInitialiser; /. case $rule_number: { @@ -1263,7 +1398,6 @@ UiObjectMember: T_REQUIRED UiObjectMemberPropertyNoInitialiser; } break; ./ - UiObjectMemberWithScriptStatement: T_PROPERTY UiPropertyType QmlIdentifier T_COLON UiScriptStatement OptionalSemicolon; /. case $rule_number: { @@ -2722,7 +2856,7 @@ AssignmentExpression_In: LeftHandSideExpression T_EQ AssignmentExpression_In; case $rule_number: { // need to convert the LHS to an AssignmentPattern if it was an Array/ObjectLiteral if (AST::Pattern *p = sym(1).Expression->patternCast()) { - AST::SourceLocation errorLoc; + SourceLocation errorLoc; QString errorMsg; if (!p->convertLiteralToAssignmentPattern(pool, &errorLoc, &errorMsg)) { syntaxError(errorLoc, errorMsg); @@ -3388,7 +3522,7 @@ IterationStatement: T_FOR T_LPAREN LeftHandSideExpression InOrOf Expression_In T case $rule_number: { // need to convert the LHS to an AssignmentPattern if it was an Array/ObjectLiteral if (AST::Pattern *p = sym(3).Expression->patternCast()) { - AST::SourceLocation errorLoc; + SourceLocation errorLoc; QString errorMsg; if (!p->convertLiteralToAssignmentPattern(pool, &errorLoc, &errorMsg)) { syntaxError(errorLoc, errorMsg); diff --git a/src/qml/parser/qqmljsast.cpp b/src/qml/parser/qqmljsast.cpp index aa3e8ab5e3..2a34c5a66c 100644 --- a/src/qml/parser/qqmljsast.cpp +++ b/src/qml/parser/qqmljsast.cpp @@ -167,7 +167,7 @@ UiObjectMember *UiObjectMember::uiObjectMemberCast() return this; } -void NestedExpression::accept0(Visitor *visitor) +void NestedExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -185,7 +185,7 @@ ClassExpression *NestedExpression::asClassDefinition() return expression->asClassDefinition(); } -void ThisExpression::accept0(Visitor *visitor) +void ThisExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -193,7 +193,7 @@ void ThisExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void IdentifierExpression::accept0(Visitor *visitor) +void IdentifierExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -201,7 +201,7 @@ void IdentifierExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void NullExpression::accept0(Visitor *visitor) +void NullExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -209,7 +209,7 @@ void NullExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void TrueLiteral::accept0(Visitor *visitor) +void TrueLiteral::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -217,7 +217,7 @@ void TrueLiteral::accept0(Visitor *visitor) visitor->endVisit(this); } -void FalseLiteral::accept0(Visitor *visitor) +void FalseLiteral::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -225,7 +225,7 @@ void FalseLiteral::accept0(Visitor *visitor) visitor->endVisit(this); } -void SuperLiteral::accept0(Visitor *visitor) +void SuperLiteral::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -234,7 +234,7 @@ void SuperLiteral::accept0(Visitor *visitor) } -void StringLiteral::accept0(Visitor *visitor) +void StringLiteral::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -242,7 +242,7 @@ void StringLiteral::accept0(Visitor *visitor) visitor->endVisit(this); } -void TemplateLiteral::accept0(Visitor *visitor) +void TemplateLiteral::accept0(BaseVisitor *visitor) { bool accepted = true; for (TemplateLiteral *it = this; it && accepted; it = it->next) { @@ -251,7 +251,7 @@ void TemplateLiteral::accept0(Visitor *visitor) } } -void NumericLiteral::accept0(Visitor *visitor) +void NumericLiteral::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -259,7 +259,7 @@ void NumericLiteral::accept0(Visitor *visitor) visitor->endVisit(this); } -void RegExpLiteral::accept0(Visitor *visitor) +void RegExpLiteral::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -267,7 +267,7 @@ void RegExpLiteral::accept0(Visitor *visitor) visitor->endVisit(this); } -void ArrayPattern::accept0(Visitor *visitor) +void ArrayPattern::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) accept(elements, visitor); @@ -287,7 +287,7 @@ bool ArrayPattern::isValidArrayLiteral(SourceLocation *errorLocation) const { return true; } -void ObjectPattern::accept0(Visitor *visitor) +void ObjectPattern::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(properties, visitor); @@ -462,7 +462,7 @@ bool PatternProperty::convertLiteralToAssignmentPattern(MemoryPool *pool, Source } -void Elision::accept0(Visitor *visitor) +void Elision::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { // ### @@ -471,7 +471,7 @@ void Elision::accept0(Visitor *visitor) visitor->endVisit(this); } -void IdentifierPropertyName::accept0(Visitor *visitor) +void IdentifierPropertyName::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -479,7 +479,7 @@ void IdentifierPropertyName::accept0(Visitor *visitor) visitor->endVisit(this); } -void StringLiteralPropertyName::accept0(Visitor *visitor) +void StringLiteralPropertyName::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -487,7 +487,7 @@ void StringLiteralPropertyName::accept0(Visitor *visitor) visitor->endVisit(this); } -void NumericLiteralPropertyName::accept0(Visitor *visitor) +void NumericLiteralPropertyName::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -517,7 +517,7 @@ QString NumericLiteralPropertyName::asString()const return locale.toString(id, 'g', 16); } -void ArrayMemberExpression::accept0(Visitor *visitor) +void ArrayMemberExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); @@ -527,7 +527,7 @@ void ArrayMemberExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void FieldMemberExpression::accept0(Visitor *visitor) +void FieldMemberExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); @@ -536,7 +536,7 @@ void FieldMemberExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void NewMemberExpression::accept0(Visitor *visitor) +void NewMemberExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); @@ -546,7 +546,7 @@ void NewMemberExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void NewExpression::accept0(Visitor *visitor) +void NewExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -555,7 +555,7 @@ void NewExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void CallExpression::accept0(Visitor *visitor) +void CallExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); @@ -565,7 +565,7 @@ void CallExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void ArgumentList::accept0(Visitor *visitor) +void ArgumentList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { for (ArgumentList *it = this; it; it = it->next) { @@ -576,7 +576,7 @@ void ArgumentList::accept0(Visitor *visitor) visitor->endVisit(this); } -void PostIncrementExpression::accept0(Visitor *visitor) +void PostIncrementExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); @@ -585,7 +585,7 @@ void PostIncrementExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void PostDecrementExpression::accept0(Visitor *visitor) +void PostDecrementExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); @@ -594,7 +594,7 @@ void PostDecrementExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void DeleteExpression::accept0(Visitor *visitor) +void DeleteExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -603,7 +603,7 @@ void DeleteExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void VoidExpression::accept0(Visitor *visitor) +void VoidExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -612,7 +612,7 @@ void VoidExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void TypeOfExpression::accept0(Visitor *visitor) +void TypeOfExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -621,7 +621,7 @@ void TypeOfExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void PreIncrementExpression::accept0(Visitor *visitor) +void PreIncrementExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -630,7 +630,7 @@ void PreIncrementExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void PreDecrementExpression::accept0(Visitor *visitor) +void PreDecrementExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -639,7 +639,7 @@ void PreDecrementExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void UnaryPlusExpression::accept0(Visitor *visitor) +void UnaryPlusExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -648,7 +648,7 @@ void UnaryPlusExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void UnaryMinusExpression::accept0(Visitor *visitor) +void UnaryMinusExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -657,7 +657,7 @@ void UnaryMinusExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void TildeExpression::accept0(Visitor *visitor) +void TildeExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -666,7 +666,7 @@ void TildeExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void NotExpression::accept0(Visitor *visitor) +void NotExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -675,7 +675,7 @@ void NotExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void BinaryExpression::accept0(Visitor *visitor) +void BinaryExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(left, visitor); @@ -685,7 +685,7 @@ void BinaryExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void ConditionalExpression::accept0(Visitor *visitor) +void ConditionalExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -696,7 +696,7 @@ void ConditionalExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void Expression::accept0(Visitor *visitor) +void Expression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(left, visitor); @@ -706,7 +706,7 @@ void Expression::accept0(Visitor *visitor) visitor->endVisit(this); } -void Block::accept0(Visitor *visitor) +void Block::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(statements, visitor); @@ -715,7 +715,7 @@ void Block::accept0(Visitor *visitor) visitor->endVisit(this); } -void StatementList::accept0(Visitor *visitor) +void StatementList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { for (StatementList *it = this; it; it = it->next) { @@ -726,7 +726,7 @@ void StatementList::accept0(Visitor *visitor) visitor->endVisit(this); } -void VariableStatement::accept0(Visitor *visitor) +void VariableStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(declarations, visitor); @@ -735,7 +735,7 @@ void VariableStatement::accept0(Visitor *visitor) visitor->endVisit(this); } -void VariableDeclarationList::accept0(Visitor *visitor) +void VariableDeclarationList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { for (VariableDeclarationList *it = this; it; it = it->next) { @@ -746,7 +746,7 @@ void VariableDeclarationList::accept0(Visitor *visitor) visitor->endVisit(this); } -void EmptyStatement::accept0(Visitor *visitor) +void EmptyStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -754,7 +754,7 @@ void EmptyStatement::accept0(Visitor *visitor) visitor->endVisit(this); } -void ExpressionStatement::accept0(Visitor *visitor) +void ExpressionStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -763,7 +763,7 @@ void ExpressionStatement::accept0(Visitor *visitor) visitor->endVisit(this); } -void IfStatement::accept0(Visitor *visitor) +void IfStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -774,7 +774,7 @@ void IfStatement::accept0(Visitor *visitor) visitor->endVisit(this); } -void DoWhileStatement::accept0(Visitor *visitor) +void DoWhileStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); @@ -784,7 +784,7 @@ void DoWhileStatement::accept0(Visitor *visitor) visitor->endVisit(this); } -void WhileStatement::accept0(Visitor *visitor) +void WhileStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -794,7 +794,7 @@ void WhileStatement::accept0(Visitor *visitor) visitor->endVisit(this); } -void ForStatement::accept0(Visitor *visitor) +void ForStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(initialiser, visitor); @@ -807,7 +807,7 @@ void ForStatement::accept0(Visitor *visitor) visitor->endVisit(this); } -void ForEachStatement::accept0(Visitor *visitor) +void ForEachStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(lhs, visitor); @@ -818,7 +818,7 @@ void ForEachStatement::accept0(Visitor *visitor) visitor->endVisit(this); } -void ContinueStatement::accept0(Visitor *visitor) +void ContinueStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -826,7 +826,7 @@ void ContinueStatement::accept0(Visitor *visitor) visitor->endVisit(this); } -void BreakStatement::accept0(Visitor *visitor) +void BreakStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -834,7 +834,7 @@ void BreakStatement::accept0(Visitor *visitor) visitor->endVisit(this); } -void ReturnStatement::accept0(Visitor *visitor) +void ReturnStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -843,7 +843,7 @@ void ReturnStatement::accept0(Visitor *visitor) visitor->endVisit(this); } -void YieldExpression::accept0(Visitor *visitor) +void YieldExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -853,7 +853,7 @@ void YieldExpression::accept0(Visitor *visitor) } -void WithStatement::accept0(Visitor *visitor) +void WithStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -863,7 +863,7 @@ void WithStatement::accept0(Visitor *visitor) visitor->endVisit(this); } -void SwitchStatement::accept0(Visitor *visitor) +void SwitchStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -873,7 +873,7 @@ void SwitchStatement::accept0(Visitor *visitor) visitor->endVisit(this); } -void CaseBlock::accept0(Visitor *visitor) +void CaseBlock::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(clauses, visitor); @@ -884,7 +884,7 @@ void CaseBlock::accept0(Visitor *visitor) visitor->endVisit(this); } -void CaseClauses::accept0(Visitor *visitor) +void CaseClauses::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { for (CaseClauses *it = this; it; it = it->next) { @@ -895,7 +895,7 @@ void CaseClauses::accept0(Visitor *visitor) visitor->endVisit(this); } -void CaseClause::accept0(Visitor *visitor) +void CaseClause::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -905,7 +905,7 @@ void CaseClause::accept0(Visitor *visitor) visitor->endVisit(this); } -void DefaultClause::accept0(Visitor *visitor) +void DefaultClause::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(statements, visitor); @@ -914,7 +914,7 @@ void DefaultClause::accept0(Visitor *visitor) visitor->endVisit(this); } -void LabelledStatement::accept0(Visitor *visitor) +void LabelledStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); @@ -923,7 +923,7 @@ void LabelledStatement::accept0(Visitor *visitor) visitor->endVisit(this); } -void ThrowStatement::accept0(Visitor *visitor) +void ThrowStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -932,7 +932,7 @@ void ThrowStatement::accept0(Visitor *visitor) visitor->endVisit(this); } -void TryStatement::accept0(Visitor *visitor) +void TryStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); @@ -943,7 +943,7 @@ void TryStatement::accept0(Visitor *visitor) visitor->endVisit(this); } -void Catch::accept0(Visitor *visitor) +void Catch::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(patternElement, visitor); @@ -953,7 +953,7 @@ void Catch::accept0(Visitor *visitor) visitor->endVisit(this); } -void Finally::accept0(Visitor *visitor) +void Finally::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); @@ -962,7 +962,7 @@ void Finally::accept0(Visitor *visitor) visitor->endVisit(this); } -void FunctionDeclaration::accept0(Visitor *visitor) +void FunctionDeclaration::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(formals, visitor); @@ -973,7 +973,7 @@ void FunctionDeclaration::accept0(Visitor *visitor) visitor->endVisit(this); } -void FunctionExpression::accept0(Visitor *visitor) +void FunctionExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(formals, visitor); @@ -1018,7 +1018,7 @@ BoundNames FormalParameterList::boundNames() const return names; } -void FormalParameterList::accept0(Visitor *visitor) +void FormalParameterList::accept0(BaseVisitor *visitor) { bool accepted = true; for (FormalParameterList *it = this; it && accepted; it = it->next) { @@ -1043,7 +1043,7 @@ FormalParameterList *FormalParameterList::finish(QQmlJS::MemoryPool *pool) return front; } -void Program::accept0(Visitor *visitor) +void Program::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(statements, visitor); @@ -1052,7 +1052,7 @@ void Program::accept0(Visitor *visitor) visitor->endVisit(this); } -void ImportSpecifier::accept0(Visitor *visitor) +void ImportSpecifier::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { @@ -1060,7 +1060,7 @@ void ImportSpecifier::accept0(Visitor *visitor) visitor->endVisit(this); } -void ImportsList::accept0(Visitor *visitor) +void ImportsList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { for (ImportsList *it = this; it; it = it->next) { @@ -1071,7 +1071,7 @@ void ImportsList::accept0(Visitor *visitor) visitor->endVisit(this); } -void NamedImports::accept0(Visitor *visitor) +void NamedImports::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(importsList, visitor); @@ -1080,7 +1080,7 @@ void NamedImports::accept0(Visitor *visitor) visitor->endVisit(this); } -void FromClause::accept0(Visitor *visitor) +void FromClause::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -1088,7 +1088,7 @@ void FromClause::accept0(Visitor *visitor) visitor->endVisit(this); } -void NameSpaceImport::accept0(Visitor *visitor) +void NameSpaceImport::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -1096,7 +1096,7 @@ void NameSpaceImport::accept0(Visitor *visitor) visitor->endVisit(this); } -void ImportClause::accept0(Visitor *visitor) +void ImportClause::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(nameSpaceImport, visitor); @@ -1106,7 +1106,7 @@ void ImportClause::accept0(Visitor *visitor) visitor->endVisit(this); } -void ImportDeclaration::accept0(Visitor *visitor) +void ImportDeclaration::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(importClause, visitor); @@ -1116,7 +1116,7 @@ void ImportDeclaration::accept0(Visitor *visitor) visitor->endVisit(this); } -void ExportSpecifier::accept0(Visitor *visitor) +void ExportSpecifier::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { @@ -1125,7 +1125,7 @@ void ExportSpecifier::accept0(Visitor *visitor) visitor->endVisit(this); } -void ExportsList::accept0(Visitor *visitor) +void ExportsList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { for (ExportsList *it = this; it; it = it->next) { @@ -1136,7 +1136,7 @@ void ExportsList::accept0(Visitor *visitor) visitor->endVisit(this); } -void ExportClause::accept0(Visitor *visitor) +void ExportClause::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(exportsList, visitor); @@ -1145,7 +1145,7 @@ void ExportClause::accept0(Visitor *visitor) visitor->endVisit(this); } -void ExportDeclaration::accept0(Visitor *visitor) +void ExportDeclaration::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(fromClause, visitor); @@ -1156,7 +1156,7 @@ void ExportDeclaration::accept0(Visitor *visitor) visitor->endVisit(this); } -void ESModule::accept0(Visitor *visitor) +void ESModule::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(body, visitor); @@ -1165,7 +1165,7 @@ void ESModule::accept0(Visitor *visitor) visitor->endVisit(this); } -void DebuggerStatement::accept0(Visitor *visitor) +void DebuggerStatement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -1173,7 +1173,7 @@ void DebuggerStatement::accept0(Visitor *visitor) visitor->endVisit(this); } -void UiProgram::accept0(Visitor *visitor) +void UiProgram::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(headers, visitor); @@ -1183,19 +1183,23 @@ void UiProgram::accept0(Visitor *visitor) visitor->endVisit(this); } -void UiPublicMember::accept0(Visitor *visitor) +void UiPublicMember::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { + // accept(annotations, visitor); // accept manually in visit if interested + // accept(memberType, visitor); // accept manually in visit if interested accept(statement, visitor); accept(binding, visitor); + // accept(parameters, visitor); // accept manually in visit if interested } visitor->endVisit(this); } -void UiObjectDefinition::accept0(Visitor *visitor) +void UiObjectDefinition::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { + // accept(annotations, visitor); // accept manually in visit if interested accept(qualifiedTypeNameId, visitor); accept(initializer, visitor); } @@ -1203,7 +1207,7 @@ void UiObjectDefinition::accept0(Visitor *visitor) visitor->endVisit(this); } -void UiObjectInitializer::accept0(Visitor *visitor) +void UiObjectInitializer::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(members, visitor); @@ -1212,16 +1216,18 @@ void UiObjectInitializer::accept0(Visitor *visitor) visitor->endVisit(this); } -void UiParameterList::accept0(Visitor *visitor) +void UiParameterList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { + // accept(type, visitor); // accept manually in visit if interested } visitor->endVisit(this); } -void UiObjectBinding::accept0(Visitor *visitor) +void UiObjectBinding::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { + // accept(annotations, visitor); // accept manually in visit if interested accept(qualifiedId, visitor); accept(qualifiedTypeNameId, visitor); accept(initializer, visitor); @@ -1230,9 +1236,10 @@ void UiObjectBinding::accept0(Visitor *visitor) visitor->endVisit(this); } -void UiScriptBinding::accept0(Visitor *visitor) +void UiScriptBinding::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { + // accept(annotations, visitor); // accept manually in visit if interested accept(qualifiedId, visitor); accept(statement, visitor); } @@ -1240,9 +1247,10 @@ void UiScriptBinding::accept0(Visitor *visitor) visitor->endVisit(this); } -void UiArrayBinding::accept0(Visitor *visitor) +void UiArrayBinding::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { + // accept(annotations, visitor); // accept manually in visit if interested accept(qualifiedId, visitor); accept(members, visitor); } @@ -1250,7 +1258,7 @@ void UiArrayBinding::accept0(Visitor *visitor) visitor->endVisit(this); } -void UiObjectMemberList::accept0(Visitor *visitor) +void UiObjectMemberList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { for (UiObjectMemberList *it = this; it; it = it->next) @@ -1260,7 +1268,7 @@ void UiObjectMemberList::accept0(Visitor *visitor) visitor->endVisit(this); } -void UiArrayMemberList::accept0(Visitor *visitor) +void UiArrayMemberList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { for (UiArrayMemberList *it = this; it; it = it->next) @@ -1270,15 +1278,16 @@ void UiArrayMemberList::accept0(Visitor *visitor) visitor->endVisit(this); } -void UiQualifiedId::accept0(Visitor *visitor) +void UiQualifiedId::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { + // accept(next, visitor) // accept manually in visit if interested } visitor->endVisit(this); } -void Type::accept0(Visitor *visitor) +void Type::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(typeId, visitor); @@ -1288,7 +1297,7 @@ void Type::accept0(Visitor *visitor) visitor->endVisit(this); } -void TypeArgumentList::accept0(Visitor *visitor) +void TypeArgumentList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { for (TypeArgumentList *it = this; it; it = it->next) @@ -1298,7 +1307,7 @@ void TypeArgumentList::accept0(Visitor *visitor) visitor->endVisit(this); } -void TypeAnnotation::accept0(Visitor *visitor) +void TypeAnnotation::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(type, visitor); @@ -1307,16 +1316,17 @@ void TypeAnnotation::accept0(Visitor *visitor) visitor->endVisit(this); } -void UiImport::accept0(Visitor *visitor) +void UiImport::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(importUri, visitor); + // accept(version, visitor); // accept manually in visit if interested } visitor->endVisit(this); } -void UiPragma::accept0(Visitor *visitor) +void UiPragma::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -1324,7 +1334,7 @@ void UiPragma::accept0(Visitor *visitor) visitor->endVisit(this); } -void UiHeaderItemList::accept0(Visitor *visitor) +void UiHeaderItemList::accept0(BaseVisitor *visitor) { bool accepted = true; for (UiHeaderItemList *it = this; it && accepted; it = it->next) { @@ -1337,25 +1347,27 @@ void UiHeaderItemList::accept0(Visitor *visitor) } -void UiSourceElement::accept0(Visitor *visitor) +void UiSourceElement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { + // accept(annotations, visitor); // accept manually in visit if interested accept(sourceElement, visitor); } visitor->endVisit(this); } -void UiEnumDeclaration::accept0(Visitor *visitor) +void UiEnumDeclaration::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { + // accept(annotations, visitor); // accept manually in visit if interested accept(members, visitor); } visitor->endVisit(this); } -void UiEnumMemberList::accept0(Visitor *visitor) +void UiEnumMemberList::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -1363,7 +1375,7 @@ void UiEnumMemberList::accept0(Visitor *visitor) visitor->endVisit(this); } -void TaggedTemplate::accept0(Visitor *visitor) +void TaggedTemplate::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); @@ -1373,7 +1385,7 @@ void TaggedTemplate::accept0(Visitor *visitor) visitor->endVisit(this); } -void PatternElement::accept0(Visitor *visitor) +void PatternElement::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(bindingTarget, visitor); @@ -1396,7 +1408,7 @@ void PatternElement::boundNames(BoundNames *names) } } -void PatternElementList::accept0(Visitor *visitor) +void PatternElementList::accept0(BaseVisitor *visitor) { bool accepted = true; for (PatternElementList *it = this; it && accepted; it = it->next) { @@ -1417,7 +1429,7 @@ void PatternElementList::boundNames(BoundNames *names) } } -void PatternProperty::accept0(Visitor *visitor) +void PatternProperty::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(name, visitor); @@ -1434,7 +1446,7 @@ void PatternProperty::boundNames(BoundNames *names) PatternElement::boundNames(names); } -void PatternPropertyList::accept0(Visitor *visitor) +void PatternPropertyList::accept0(BaseVisitor *visitor) { bool accepted = true; for (PatternPropertyList *it = this; it && accepted; it = it->next) { @@ -1451,7 +1463,7 @@ void PatternPropertyList::boundNames(BoundNames *names) it->property->boundNames(names); } -void ComputedPropertyName::accept0(Visitor *visitor) +void ComputedPropertyName::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); @@ -1460,7 +1472,7 @@ void ComputedPropertyName::accept0(Visitor *visitor) visitor->endVisit(this); } -void ClassExpression::accept0(Visitor *visitor) +void ClassExpression::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(heritage, visitor); @@ -1475,7 +1487,7 @@ ClassExpression *ClassExpression::asClassDefinition() return this; } -void ClassDeclaration::accept0(Visitor *visitor) +void ClassDeclaration::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { accept(heritage, visitor); @@ -1485,7 +1497,7 @@ void ClassDeclaration::accept0(Visitor *visitor) visitor->endVisit(this); } -void ClassElementList::accept0(Visitor *visitor) +void ClassElementList::accept0(BaseVisitor *visitor) { bool accepted = true; for (ClassElementList *it = this; it && accepted; it = it->next) { @@ -1514,7 +1526,7 @@ LeftHandSideExpression *LeftHandSideExpression::leftHandSideExpressionCast() return this; } -void UiVersionSpecifier::accept0(Visitor *visitor) +void UiVersionSpecifier::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { } @@ -1545,15 +1557,44 @@ void Type::toString(QString *out) const }; } -void UiInlineComponent::accept0(Visitor *visitor) +void UiInlineComponent::accept0(BaseVisitor *visitor) { if (visitor->visit(this)) { + // accept(annotations, visitor); // accept manually in visit if interested accept(component, visitor); } visitor->endVisit(this); } +void UiRequired::accept0(BaseVisitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void UiAnnotationList::accept0(BaseVisitor *visitor) +{ + if (visitor->visit(this)) { + for (UiAnnotationList *it = this; it; it = it->next) + accept(it->annotation, visitor); + } + + visitor->endVisit(this); +} + +void UiAnnotation::accept0(BaseVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(qualifiedTypeNameId, visitor); + accept(initializer, visitor); + } + + visitor->endVisit(this); +} + } } // namespace QQmlJS::AST QT_END_NAMESPACE diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h index 48a994cd33..de554a53af 100644 --- a/src/qml/parser/qqmljsast_p.h +++ b/src/qml/parser/qqmljsast_p.h @@ -57,6 +57,7 @@ #include <private/qqmljsmemorypool_p.h> #include <QtCore/qstring.h> +#include <QtCore/qversionnumber.h> QT_BEGIN_NAMESPACE @@ -258,7 +259,10 @@ public: Kind_UiHeaderItemList, Kind_UiEnumDeclaration, Kind_UiEnumMemberList, - Kind_UiVersionSpecifier + Kind_UiVersionSpecifier, + Kind_UiRequired, + Kind_UiAnnotation, + Kind_UiAnnotationList }; inline Node() {} @@ -280,9 +284,9 @@ public: bool ignoreRecursionDepth() const; - inline void accept(Visitor *visitor) + inline void accept(BaseVisitor *visitor) { - Visitor::RecursionDepthCheck recursionCheck(visitor); + BaseVisitor::RecursionDepthCheck recursionCheck(visitor); // Stack overflow is uncommon, ignoreRecursionDepth() only returns true if // QV4_CRASH_ON_STACKOVERFLOW is set, and ignoreRecursionDepth() needs to be out of line. @@ -296,19 +300,19 @@ public: } } - inline static void accept(Node *node, Visitor *visitor) + inline static void accept(Node *node, BaseVisitor *visitor) { if (node) node->accept(visitor); } // ### Remove when we can. This is part of the qmldevtools library, though. - inline static void acceptChild(Node *node, Visitor *visitor) + inline static void acceptChild(Node *node, BaseVisitor *visitor) { return accept(node, visitor); } - virtual void accept0(Visitor *visitor) = 0; + virtual void accept0(BaseVisitor *visitor) = 0; virtual SourceLocation firstSourceLocation() const = 0; virtual SourceLocation lastSourceLocation() const = 0; @@ -349,7 +353,7 @@ public: return head; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return identifierToken; } @@ -373,7 +377,7 @@ public: , typeArguments(typeArguments) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return typeId->firstSourceLocation(); } @@ -408,7 +412,7 @@ public: previous->next = this; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return typeId->firstSourceLocation(); } @@ -437,7 +441,7 @@ public: : type(type) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return colonToken; } @@ -482,7 +486,7 @@ public: : expression(expression) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return lparenToken; } @@ -507,7 +511,7 @@ public: ThisExpression() { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return thisToken; } @@ -527,7 +531,7 @@ public: IdentifierExpression(const QStringRef &n): name (n) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return identifierToken; } @@ -547,7 +551,7 @@ public: NullExpression() { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return nullToken; } @@ -566,7 +570,7 @@ public: TrueLiteral() { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return trueToken; } @@ -585,7 +589,7 @@ public: FalseLiteral() { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return falseToken; } @@ -604,7 +608,7 @@ public: SuperLiteral() { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return superToken; } @@ -625,7 +629,7 @@ public: NumericLiteral(double v): value(v) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return literalToken; } @@ -643,9 +647,12 @@ class QML_PARSER_EXPORT UiVersionSpecifier : public Node public: QQMLJS_DECLARE_AST_NODE(UiVersionSpecifier) - UiVersionSpecifier(int majorum, int minorum) : majorVersion(majorum), minorVersion(minorum) { kind = K; } + UiVersionSpecifier(int majorum, int minorum) : version(QTypeRevision::fromVersion(majorum, minorum)) + { + kind = K; + } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return majorToken; } @@ -655,8 +662,7 @@ public: } // attributes: - int majorVersion; - int minorVersion; + QTypeRevision version; SourceLocation majorToken; SourceLocation minorToken; }; @@ -669,7 +675,7 @@ public: StringLiteral(const QStringRef &v): value (v) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return literalToken; } @@ -700,7 +706,7 @@ public: return (last->expression ? last->expression->lastSourceLocation() : last->literalToken); } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; QStringRef value; QStringRef rawValue; @@ -717,7 +723,7 @@ public: RegExpLiteral(const QStringRef &p, int f): pattern (p), flags (f) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return literalToken; } @@ -752,7 +758,7 @@ public: : elements(elts) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return lbracketToken; } @@ -783,7 +789,7 @@ public: : properties(plist) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return lbraceToken; } @@ -814,7 +820,7 @@ public: previous->next = this; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return commaToken; } @@ -920,7 +926,7 @@ public: kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; virtual bool convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLocation *errorLocation, QString *errorMessage); SourceLocation firstSourceLocation() const override @@ -973,7 +979,7 @@ public: return front; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; void boundNames(BoundNames *names); @@ -1008,7 +1014,7 @@ public: : PatternElement(pattern, i), name(name) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return name->firstSourceLocation(); } @@ -1044,7 +1050,7 @@ public: previous->next = this; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; void boundNames(BoundNames *names); @@ -1065,7 +1071,7 @@ public: PatternPropertyList *next; }; -class QML_PARSER_EXPORT IdentifierPropertyName : public PropertyName +class QML_PARSER_EXPORT IdentifierPropertyName: public PropertyName { public: QQMLJS_DECLARE_AST_NODE(IdentifierPropertyName) @@ -1073,7 +1079,7 @@ public: IdentifierPropertyName(const QStringRef &n): id (n) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; QString asString() const override { return id.toString(); } @@ -1089,7 +1095,7 @@ public: StringLiteralPropertyName(const QStringRef &n): id (n) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; QString asString() const override { return id.toString(); } @@ -1105,7 +1111,7 @@ public: NumericLiteralPropertyName(double n): id (n) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; QString asString() const override; @@ -1122,7 +1128,7 @@ public: : expression(expression) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; QString asString() const override { return QString(); } @@ -1146,7 +1152,7 @@ public: base (b), expression (e) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return base->firstSourceLocation(); } @@ -1170,7 +1176,7 @@ public: base (b), name (n) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return base->firstSourceLocation(); } @@ -1194,7 +1200,7 @@ public: : base (b), templateLiteral(t) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return base->firstSourceLocation(); } @@ -1216,7 +1222,7 @@ public: base (b), arguments (a) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return newToken; } @@ -1240,7 +1246,7 @@ public: NewExpression(ExpressionNode *e): expression (e) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return newToken; } @@ -1262,7 +1268,7 @@ public: base (b), arguments (a) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return base->firstSourceLocation(); } @@ -1294,7 +1300,7 @@ public: previous->next = this; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return expression->firstSourceLocation(); } @@ -1328,7 +1334,7 @@ public: PostIncrementExpression(ExpressionNode *b): base (b) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return base->firstSourceLocation(); } @@ -1349,7 +1355,7 @@ public: PostDecrementExpression(ExpressionNode *b): base (b) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return base->firstSourceLocation(); } @@ -1370,7 +1376,7 @@ public: DeleteExpression(ExpressionNode *e): expression (e) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return deleteToken; } @@ -1391,7 +1397,7 @@ public: VoidExpression(ExpressionNode *e): expression (e) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return voidToken; } @@ -1412,7 +1418,7 @@ public: TypeOfExpression(ExpressionNode *e): expression (e) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return typeofToken; } @@ -1433,7 +1439,7 @@ public: PreIncrementExpression(ExpressionNode *e): expression (e) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return incrementToken; } @@ -1454,7 +1460,7 @@ public: PreDecrementExpression(ExpressionNode *e): expression (e) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return decrementToken; } @@ -1475,7 +1481,7 @@ public: UnaryPlusExpression(ExpressionNode *e): expression (e) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return plusToken; } @@ -1496,7 +1502,7 @@ public: UnaryMinusExpression(ExpressionNode *e): expression (e) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return minusToken; } @@ -1517,7 +1523,7 @@ public: TildeExpression(ExpressionNode *e): expression (e) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return tildeToken; } @@ -1538,7 +1544,7 @@ public: NotExpression(ExpressionNode *e): expression (e) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return notToken; } @@ -1562,7 +1568,7 @@ public: BinaryExpression *binaryExpressionCast() override; - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return left->firstSourceLocation(); } @@ -1586,7 +1592,7 @@ public: expression (e), ok (t), ko (f) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return expression->firstSourceLocation(); } @@ -1610,7 +1616,7 @@ public: Expression(ExpressionNode *l, ExpressionNode *r): left (l), right (r) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return left->firstSourceLocation(); } @@ -1632,7 +1638,7 @@ public: Block(StatementList *slist): statements (slist) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return lbraceToken; } @@ -1662,7 +1668,7 @@ public: return n; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return statement->firstSourceLocation(); } @@ -1701,7 +1707,7 @@ public: previous->next = this; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return declaration->firstSourceLocation(); } @@ -1739,7 +1745,7 @@ public: declarations (vlist) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return declarationKindToken; } @@ -1759,7 +1765,7 @@ public: EmptyStatement() { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return semicolonToken; } @@ -1779,7 +1785,7 @@ public: ExpressionStatement(ExpressionNode *e): expression (e) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return expression->firstSourceLocation(); } @@ -1801,7 +1807,7 @@ public: expression (e), ok (t), ko (f) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return ifToken; } @@ -1833,7 +1839,7 @@ public: statement (stmt), expression (e) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return doToken; } @@ -1860,7 +1866,7 @@ public: expression (e), statement (stmt) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return whileToken; } @@ -1890,7 +1896,7 @@ public: { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return forToken; } @@ -1928,7 +1934,7 @@ public: : lhs(v), expression(e), statement(stmt) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return forToken; } @@ -1959,7 +1965,7 @@ public: ContinueStatement(const QStringRef &l = QStringRef()): label (l) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return continueToken; } @@ -1982,7 +1988,7 @@ public: BreakStatement(const QStringRef &l): label (l) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return breakToken; } @@ -2005,7 +2011,7 @@ public: ReturnStatement(ExpressionNode *e): expression (e) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return returnToken; } @@ -2027,7 +2033,7 @@ public: YieldExpression(ExpressionNode *e = nullptr): expression (e) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return yieldToken; } @@ -2050,7 +2056,7 @@ public: expression (e), statement (stmt) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return withToken; } @@ -2075,7 +2081,7 @@ public: clauses (c), defaultClause (d), moreClauses (r) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return lbraceToken; } @@ -2100,7 +2106,7 @@ public: expression (e), block (b) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return switchToken; } @@ -2125,7 +2131,7 @@ public: expression (e), statements (slist) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return caseToken; } @@ -2157,7 +2163,7 @@ public: previous->next = this; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return clause->firstSourceLocation(); } @@ -2188,7 +2194,7 @@ public: statements (slist) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return defaultToken; } @@ -2211,7 +2217,7 @@ public: label (l), statement (stmt) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return identifierToken; } @@ -2234,7 +2240,7 @@ public: ThrowStatement(ExpressionNode *e): expression (e) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return throwToken; } @@ -2257,7 +2263,7 @@ public: : patternElement(p), statement(stmt) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return catchToken; } @@ -2283,7 +2289,7 @@ public: statement (stmt) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return finallyToken; } @@ -2313,7 +2319,7 @@ public: statement (stmt), catchExpression (c), finallyExpression (nullptr) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return tryToken; } @@ -2345,7 +2351,7 @@ public: typeAnnotation(typeAnnotation) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return functionToken; } @@ -2379,7 +2385,7 @@ public: FunctionExpression(n, f, b, typeAnnotation) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; }; class QML_PARSER_EXPORT FormalParameterList: public Node @@ -2450,7 +2456,7 @@ public: BoundNames boundNames() const; - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return element->firstSourceLocation(); } @@ -2476,7 +2482,7 @@ public: : name(n), heritage(heritage), elements(elements) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return classToken; } @@ -2505,7 +2511,7 @@ public: : ClassExpression(n, heritage, elements) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; }; @@ -2527,7 +2533,7 @@ public: return n; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return property->firstSourceLocation(); } @@ -2555,7 +2561,7 @@ public: : statements(statements) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return statements ? statements->firstSourceLocation() : SourceLocation(); } @@ -2584,7 +2590,7 @@ public: kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return identifier.isNull() ? importedBindingToken : identifierToken; } @@ -2629,7 +2635,7 @@ public: return head; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return importSpecifierToken; } @@ -2661,7 +2667,7 @@ public: kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return leftBraceToken; } @@ -2685,7 +2691,7 @@ public: kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; virtual SourceLocation firstSourceLocation() const override { return starToken; } @@ -2735,7 +2741,7 @@ public: kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; virtual SourceLocation firstSourceLocation() const override { return importedDefaultBinding.isNull() ? (nameSpaceImport ? nameSpaceImport->firstSourceLocation() : namedImports->firstSourceLocation()) : importedDefaultBindingToken; } @@ -2760,7 +2766,7 @@ public: kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return fromToken; } @@ -2791,7 +2797,7 @@ public: kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return importToken; } @@ -2824,7 +2830,7 @@ public: kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return identifierToken; } @@ -2869,7 +2875,7 @@ public: return head; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return exportSpecifier->firstSourceLocation(); } @@ -2897,7 +2903,7 @@ public: kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return leftBraceToken; } @@ -2941,7 +2947,7 @@ public: kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return exportToken; } @@ -2968,7 +2974,7 @@ public: kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return body ? body->firstSourceLocation() : SourceLocation(); } @@ -2988,7 +2994,7 @@ public: DebuggerStatement() { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return debuggerToken; } @@ -3014,7 +3020,7 @@ public: : importUri(uri) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return importToken; } @@ -3041,6 +3047,9 @@ public: SourceLocation lastSourceLocation() const override = 0; UiObjectMember *uiObjectMemberCast() override; + +// attributes + UiAnnotationList *annotations = nullptr; }; class QML_PARSER_EXPORT UiObjectMemberList: public Node @@ -3060,7 +3069,7 @@ public: previous->next = this; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return member->firstSourceLocation(); } @@ -3089,7 +3098,7 @@ public: : name(name) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return pragmaToken; } @@ -3103,6 +3112,28 @@ public: SourceLocation semicolonToken; }; +class QML_PARSER_EXPORT UiRequired: public Node +{ +public: + QQMLJS_DECLARE_AST_NODE(UiRequired) + + UiRequired(QStringRef name) + :name(name) + { kind = K; } + + void accept0(BaseVisitor *visitor) override; + + SourceLocation firstSourceLocation() const override + { return requiredToken; } + + SourceLocation lastSourceLocation() const override + { return semicolonToken; } + + QStringRef name; + SourceLocation requiredToken; + SourceLocation semicolonToken; +}; + class QML_PARSER_EXPORT UiHeaderItemList: public Node { public: @@ -3139,7 +3170,7 @@ public: return head; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return headerItem->firstSourceLocation(); } @@ -3161,7 +3192,7 @@ public: : headers(headers), members(members) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { @@ -3203,7 +3234,7 @@ public: previous->next = this; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return member->firstSourceLocation(); } @@ -3233,7 +3264,7 @@ public: : members(members) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return lbraceToken; } @@ -3264,7 +3295,7 @@ public: previous->next = this; } - void accept0(Visitor *) override; + void accept0(BaseVisitor *) override; SourceLocation firstSourceLocation() const override { return colonToken.isValid() ? identifierToken : propertyTypeToken; } @@ -3308,7 +3339,7 @@ public: : type(Property), memberType(memberType), name(name), statement(statement), binding(nullptr), isDefaultMember(false), isReadonlyMember(false), parameters(nullptr) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { @@ -3365,7 +3396,7 @@ public: : qualifiedTypeNameId(qualifiedTypeNameId), initializer(initializer) { kind = K; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; SourceLocation firstSourceLocation() const override { return qualifiedTypeNameId->identifierToken; } @@ -3387,17 +3418,18 @@ public: : name(inlineComponentName), component(inlineComponent) { kind = K; } - QStringRef name; - UiObjectDefinition* component; - SourceLocation componentToken; - SourceLocation lastSourceLocation() const override {return component->lastSourceLocation();} SourceLocation firstSourceLocation() const override {return componentToken;} - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; + + // attributes + QStringRef name; + UiObjectDefinition* component; + SourceLocation componentToken; }; class QML_PARSER_EXPORT UiSourceElement: public UiObjectMember @@ -3429,7 +3461,7 @@ public: return SourceLocation(); } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; // attributes @@ -3461,7 +3493,7 @@ public: SourceLocation lastSourceLocation() const override { return initializer->rbraceToken; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; // attributes @@ -3489,7 +3521,7 @@ public: SourceLocation lastSourceLocation() const override { return statement->lastSourceLocation(); } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; // attributes UiQualifiedId *qualifiedId; @@ -3514,7 +3546,7 @@ public: SourceLocation lastSourceLocation() const override { return rbracketToken; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; // attributes UiQualifiedId *qualifiedId; @@ -3558,7 +3590,7 @@ public: return last->valueToken.isValid() ? last->valueToken : last->memberToken; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; UiEnumMemberList *finish() { @@ -3592,7 +3624,7 @@ public: SourceLocation lastSourceLocation() const override { return rbraceToken; } - void accept0(Visitor *visitor) override; + void accept0(BaseVisitor *visitor) override; // attributes SourceLocation enumToken; @@ -3601,8 +3633,67 @@ public: UiEnumMemberList *members; }; -} } // namespace AST +class QML_PARSER_EXPORT UiAnnotation: public Node +{ +public: + QQMLJS_DECLARE_AST_NODE(UiAnnotation) + + UiAnnotation(UiQualifiedId *qualifiedTypeNameId, + UiObjectInitializer *initializer) + : qualifiedTypeNameId(qualifiedTypeNameId), initializer(initializer) + { kind = K; } + void accept0(BaseVisitor *visitor) override; + + SourceLocation firstSourceLocation() const override + { return qualifiedTypeNameId->identifierToken; } + + SourceLocation lastSourceLocation() const override + { return initializer->rbraceToken; } + +// attributes + UiQualifiedId *qualifiedTypeNameId; + UiObjectInitializer *initializer; +}; + +class QML_PARSER_EXPORT UiAnnotationList: public Node +{ +public: + QQMLJS_DECLARE_AST_NODE(UiAnnotationList) + + UiAnnotationList(UiAnnotation *annotation) + : next(this), annotation(annotation) + { kind = K; } + + UiAnnotationList(UiAnnotationList *previous, UiAnnotation *annotation) + : annotation(annotation) + { + kind = K; + next = previous->next; + previous->next = this; + } + + void accept0(BaseVisitor *visitor) override; + + SourceLocation firstSourceLocation() const override + { return annotation->firstSourceLocation(); } + + SourceLocation lastSourceLocation() const override + { return lastListElement(this)->annotation->lastSourceLocation(); } + + UiAnnotationList *finish() + { + UiAnnotationList *head = next; + next = nullptr; + return head; + } + +// attributes + UiAnnotationList *next; + UiAnnotation *annotation; +}; + +} } // namespace AST QT_END_NAMESPACE diff --git a/src/qml/parser/qqmljsastfwd_p.h b/src/qml/parser/qqmljsastfwd_p.h index 8a8ee2dfae..ef37e8072f 100644 --- a/src/qml/parser/qqmljsastfwd_p.h +++ b/src/qml/parser/qqmljsastfwd_p.h @@ -41,7 +41,7 @@ #define QQMLJSAST_FWD_P_H #include "qqmljsglobal_p.h" -#include "qqmljssourcelocation_p.h" +#include <private/qqmljssourcelocation_p.h> #include <QtCore/qglobal.h> @@ -60,6 +60,7 @@ QT_BEGIN_NAMESPACE namespace QQmlJS { namespace AST { +class BaseVisitor; class Visitor; class Node; class ExpressionNode; @@ -151,7 +152,6 @@ class NamedImport; class ImportClause; class FromClause; class ImportDeclaration; -class ModuleItem; class ESModule; class DebuggerStatement; class NestedExpression; @@ -183,6 +183,9 @@ class UiHeaderItemList; class UiEnumDeclaration; class UiEnumMemberList; class UiVersionSpecifier; +class UiRequired; +class UiAnnotation; +class UiAnnotationList; } // namespace AST } // namespace QQmlJS diff --git a/src/qml/parser/qqmljsastvisitor.cpp b/src/qml/parser/qqmljsastvisitor.cpp index 5ecac36423..7388eccebb 100644 --- a/src/qml/parser/qqmljsastvisitor.cpp +++ b/src/qml/parser/qqmljsastvisitor.cpp @@ -43,11 +43,13 @@ QT_BEGIN_NAMESPACE namespace QQmlJS { namespace AST { -Visitor::Visitor(quint16 parentRecursionDepth) : m_recursionDepth(parentRecursionDepth) +Visitor::Visitor(quint16 parentRecursionDepth) : BaseVisitor(parentRecursionDepth) { } -Visitor::~Visitor() +BaseVisitor::BaseVisitor(quint16 parentRecursionDepth) : m_recursionDepth(parentRecursionDepth) {} + +BaseVisitor::~BaseVisitor() { } diff --git a/src/qml/parser/qqmljsastvisitor_p.h b/src/qml/parser/qqmljsastvisitor_p.h index d6b92990ad..8fbdb97ee2 100644 --- a/src/qml/parser/qqmljsastvisitor_p.h +++ b/src/qml/parser/qqmljsastvisitor_p.h @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE namespace QQmlJS { namespace AST { -class QML_PARSER_EXPORT Visitor +class QML_PARSER_EXPORT BaseVisitor { public: class RecursionDepthCheck @@ -68,7 +68,7 @@ public: RecursionDepthCheck(RecursionDepthCheck &&) = delete; RecursionDepthCheck &operator=(RecursionDepthCheck &&) = delete; - RecursionDepthCheck(Visitor *visitor) : m_visitor(visitor) + RecursionDepthCheck(BaseVisitor *visitor) : m_visitor(visitor) { ++(m_visitor->m_recursionDepth); } @@ -84,335 +84,338 @@ public: private: static const quint16 s_recursionLimit = 4096; - Visitor *m_visitor; + BaseVisitor *m_visitor; }; - Visitor(quint16 parentRecursionDepth = 0); - virtual ~Visitor(); + BaseVisitor(quint16 parentRecursionDepth = 0); + virtual ~BaseVisitor(); - virtual bool preVisit(Node *) { return true; } - virtual void postVisit(Node *) {} + virtual bool preVisit(Node *) = 0; + virtual void postVisit(Node *) = 0; // Ui - virtual bool visit(UiProgram *) { return true; } - virtual bool visit(UiHeaderItemList *) { return true; } - virtual bool visit(UiPragma *) { return true; } - virtual bool visit(UiImport *) { return true; } - virtual bool visit(UiPublicMember *) { return true; } - virtual bool visit(UiSourceElement *) { return true; } - virtual bool visit(UiObjectDefinition *) { return true; } - virtual bool visit(UiObjectInitializer *) { return true; } - virtual bool visit(UiObjectBinding *) { return true; } - virtual bool visit(UiScriptBinding *) { return true; } - virtual bool visit(UiArrayBinding *) { return true; } - virtual bool visit(UiParameterList *) { return true; } - virtual bool visit(UiObjectMemberList *) { return true; } - virtual bool visit(UiArrayMemberList *) { return true; } - virtual bool visit(UiQualifiedId *) { return true; } - virtual bool visit(UiEnumDeclaration *) { return true; } - virtual bool visit(UiEnumMemberList *) { return true; } - virtual bool visit(UiVersionSpecifier *) { return true; } - virtual bool visit(UiInlineComponent *) { return true; } - - virtual void endVisit(UiProgram *) {} - virtual void endVisit(UiImport *) {} - virtual void endVisit(UiHeaderItemList *) {} - virtual void endVisit(UiPragma *) {} - virtual void endVisit(UiPublicMember *) {} - virtual void endVisit(UiSourceElement *) {} - virtual void endVisit(UiObjectDefinition *) {} - virtual void endVisit(UiObjectInitializer *) {} - virtual void endVisit(UiObjectBinding *) {} - virtual void endVisit(UiScriptBinding *) {} - virtual void endVisit(UiArrayBinding *) {} - virtual void endVisit(UiParameterList *) {} - virtual void endVisit(UiObjectMemberList *) {} - virtual void endVisit(UiArrayMemberList *) {} - virtual void endVisit(UiQualifiedId *) {} - virtual void endVisit(UiEnumDeclaration *) {} - virtual void endVisit(UiEnumMemberList *) { } - virtual void endVisit(UiVersionSpecifier *) {} - virtual void endVisit(UiInlineComponent *) {} + virtual bool visit(UiProgram *) = 0; + virtual bool visit(UiHeaderItemList *) = 0; + virtual bool visit(UiPragma *) = 0; + virtual bool visit(UiImport *) = 0; + virtual bool visit(UiPublicMember *) = 0; + virtual bool visit(UiSourceElement *) = 0; + virtual bool visit(UiObjectDefinition *) = 0; + virtual bool visit(UiObjectInitializer *) = 0; + virtual bool visit(UiObjectBinding *) = 0; + virtual bool visit(UiScriptBinding *) = 0; + virtual bool visit(UiArrayBinding *) = 0; + virtual bool visit(UiParameterList *) = 0; + virtual bool visit(UiObjectMemberList *) = 0; + virtual bool visit(UiArrayMemberList *) = 0; + virtual bool visit(UiQualifiedId *) = 0; + virtual bool visit(UiEnumDeclaration *) = 0; + virtual bool visit(UiEnumMemberList *) = 0; + virtual bool visit(UiVersionSpecifier *) = 0; + virtual bool visit(UiInlineComponent *) = 0; + virtual bool visit(UiAnnotation *) = 0; + virtual bool visit(UiAnnotationList *) = 0; + virtual bool visit(UiRequired *) = 0; + + virtual void endVisit(UiProgram *) = 0; + virtual void endVisit(UiImport *) = 0; + virtual void endVisit(UiHeaderItemList *) = 0; + virtual void endVisit(UiPragma *) = 0; + virtual void endVisit(UiPublicMember *) = 0; + virtual void endVisit(UiSourceElement *) = 0; + virtual void endVisit(UiObjectDefinition *) = 0; + virtual void endVisit(UiObjectInitializer *) = 0; + virtual void endVisit(UiObjectBinding *) = 0; + virtual void endVisit(UiScriptBinding *) = 0; + virtual void endVisit(UiArrayBinding *) = 0; + virtual void endVisit(UiParameterList *) = 0; + virtual void endVisit(UiObjectMemberList *) = 0; + virtual void endVisit(UiArrayMemberList *) = 0; + virtual void endVisit(UiQualifiedId *) = 0; + virtual void endVisit(UiEnumDeclaration *) = 0; + virtual void endVisit(UiEnumMemberList *) = 0; + virtual void endVisit(UiVersionSpecifier *) = 0; + virtual void endVisit(UiInlineComponent *) = 0; + virtual void endVisit(UiAnnotation *) = 0; + virtual void endVisit(UiAnnotationList *) = 0; + virtual void endVisit(UiRequired *) = 0; // QQmlJS - virtual bool visit(ThisExpression *) { return true; } - virtual void endVisit(ThisExpression *) {} - - virtual bool visit(IdentifierExpression *) { return true; } - virtual void endVisit(IdentifierExpression *) {} + virtual bool visit(ThisExpression *) = 0; + virtual void endVisit(ThisExpression *) = 0; - virtual bool visit(NullExpression *) { return true; } - virtual void endVisit(NullExpression *) {} + virtual bool visit(IdentifierExpression *) = 0; + virtual void endVisit(IdentifierExpression *) = 0; - virtual bool visit(TrueLiteral *) { return true; } - virtual void endVisit(TrueLiteral *) {} + virtual bool visit(NullExpression *) = 0; + virtual void endVisit(NullExpression *) = 0; - virtual bool visit(FalseLiteral *) { return true; } - virtual void endVisit(FalseLiteral *) {} + virtual bool visit(TrueLiteral *) = 0; + virtual void endVisit(TrueLiteral *) = 0; - virtual bool visit(SuperLiteral *) { return true; } - virtual void endVisit(SuperLiteral *) {} + virtual bool visit(FalseLiteral *) = 0; + virtual void endVisit(FalseLiteral *) = 0; - virtual bool visit(StringLiteral *) { return true; } - virtual void endVisit(StringLiteral *) {} + virtual bool visit(SuperLiteral *) = 0; + virtual void endVisit(SuperLiteral *) = 0; - virtual bool visit(TemplateLiteral *) { return true; } - virtual void endVisit(TemplateLiteral *) {} + virtual bool visit(StringLiteral *) = 0; + virtual void endVisit(StringLiteral *) = 0; - virtual bool visit(NumericLiteral *) { return true; } - virtual void endVisit(NumericLiteral *) {} + virtual bool visit(TemplateLiteral *) = 0; + virtual void endVisit(TemplateLiteral *) = 0; - virtual bool visit(RegExpLiteral *) { return true; } - virtual void endVisit(RegExpLiteral *) {} + virtual bool visit(NumericLiteral *) = 0; + virtual void endVisit(NumericLiteral *) = 0; - virtual bool visit(ArrayPattern *) { return true; } - virtual void endVisit(ArrayPattern *) {} + virtual bool visit(RegExpLiteral *) = 0; + virtual void endVisit(RegExpLiteral *) = 0; - virtual bool visit(ObjectPattern *) { return true; } - virtual void endVisit(ObjectPattern *) {} + virtual bool visit(ArrayPattern *) = 0; + virtual void endVisit(ArrayPattern *) = 0; - virtual bool visit(PatternElementList *) { return true; } - virtual void endVisit(PatternElementList *) {} + virtual bool visit(ObjectPattern *) = 0; + virtual void endVisit(ObjectPattern *) = 0; - virtual bool visit(PatternPropertyList *) { return true; } - virtual void endVisit(PatternPropertyList *) {} + virtual bool visit(PatternElementList *) = 0; + virtual void endVisit(PatternElementList *) = 0; - virtual bool visit(PatternElement *) { return true; } - virtual void endVisit(PatternElement *) {} + virtual bool visit(PatternPropertyList *) = 0; + virtual void endVisit(PatternPropertyList *) = 0; - virtual bool visit(PatternProperty *) { return true; } - virtual void endVisit(PatternProperty *) {} + virtual bool visit(PatternElement *) = 0; + virtual void endVisit(PatternElement *) = 0; - virtual bool visit(Elision *) { return true; } - virtual void endVisit(Elision *) {} + virtual bool visit(PatternProperty *) = 0; + virtual void endVisit(PatternProperty *) = 0; - virtual bool visit(NestedExpression *) { return true; } - virtual void endVisit(NestedExpression *) {} + virtual bool visit(Elision *) = 0; + virtual void endVisit(Elision *) = 0; - virtual bool visit(IdentifierPropertyName *) { return true; } - virtual void endVisit(IdentifierPropertyName *) {} + virtual bool visit(NestedExpression *) = 0; + virtual void endVisit(NestedExpression *) = 0; - virtual bool visit(StringLiteralPropertyName *) { return true; } - virtual void endVisit(StringLiteralPropertyName *) {} + virtual bool visit(IdentifierPropertyName *) = 0; + virtual void endVisit(IdentifierPropertyName *) = 0; - virtual bool visit(NumericLiteralPropertyName *) { return true; } - virtual void endVisit(NumericLiteralPropertyName *) {} + virtual bool visit(StringLiteralPropertyName *) = 0; + virtual void endVisit(StringLiteralPropertyName *) = 0; - virtual bool visit(ComputedPropertyName *) { return true; } - virtual void endVisit(ComputedPropertyName *) {} + virtual bool visit(NumericLiteralPropertyName *) = 0; + virtual void endVisit(NumericLiteralPropertyName *) = 0; - virtual bool visit(ArrayMemberExpression *) { return true; } - virtual void endVisit(ArrayMemberExpression *) {} + virtual bool visit(ComputedPropertyName *) = 0; + virtual void endVisit(ComputedPropertyName *) = 0; - virtual bool visit(FieldMemberExpression *) { return true; } - virtual void endVisit(FieldMemberExpression *) {} + virtual bool visit(ArrayMemberExpression *) = 0; + virtual void endVisit(ArrayMemberExpression *) = 0; - virtual bool visit(TaggedTemplate *) { return true; } - virtual void endVisit(TaggedTemplate *) {} + virtual bool visit(FieldMemberExpression *) = 0; + virtual void endVisit(FieldMemberExpression *) = 0; - virtual bool visit(NewMemberExpression *) { return true; } - virtual void endVisit(NewMemberExpression *) {} + virtual bool visit(TaggedTemplate *) = 0; + virtual void endVisit(TaggedTemplate *) = 0; - virtual bool visit(NewExpression *) { return true; } - virtual void endVisit(NewExpression *) {} + virtual bool visit(NewMemberExpression *) = 0; + virtual void endVisit(NewMemberExpression *) = 0; - virtual bool visit(CallExpression *) { return true; } - virtual void endVisit(CallExpression *) {} + virtual bool visit(NewExpression *) = 0; + virtual void endVisit(NewExpression *) = 0; - virtual bool visit(ArgumentList *) { return true; } - virtual void endVisit(ArgumentList *) {} + virtual bool visit(CallExpression *) = 0; + virtual void endVisit(CallExpression *) = 0; - virtual bool visit(PostIncrementExpression *) { return true; } - virtual void endVisit(PostIncrementExpression *) {} + virtual bool visit(ArgumentList *) = 0; + virtual void endVisit(ArgumentList *) = 0; - virtual bool visit(PostDecrementExpression *) { return true; } - virtual void endVisit(PostDecrementExpression *) {} + virtual bool visit(PostIncrementExpression *) = 0; + virtual void endVisit(PostIncrementExpression *) = 0; - virtual bool visit(DeleteExpression *) { return true; } - virtual void endVisit(DeleteExpression *) {} + virtual bool visit(PostDecrementExpression *) = 0; + virtual void endVisit(PostDecrementExpression *) = 0; - virtual bool visit(VoidExpression *) { return true; } - virtual void endVisit(VoidExpression *) {} + virtual bool visit(DeleteExpression *) = 0; + virtual void endVisit(DeleteExpression *) = 0; - virtual bool visit(TypeOfExpression *) { return true; } - virtual void endVisit(TypeOfExpression *) {} + virtual bool visit(VoidExpression *) = 0; + virtual void endVisit(VoidExpression *) = 0; - virtual bool visit(PreIncrementExpression *) { return true; } - virtual void endVisit(PreIncrementExpression *) {} + virtual bool visit(TypeOfExpression *) = 0; + virtual void endVisit(TypeOfExpression *) = 0; - virtual bool visit(PreDecrementExpression *) { return true; } - virtual void endVisit(PreDecrementExpression *) {} + virtual bool visit(PreIncrementExpression *) = 0; + virtual void endVisit(PreIncrementExpression *) = 0; - virtual bool visit(UnaryPlusExpression *) { return true; } - virtual void endVisit(UnaryPlusExpression *) {} + virtual bool visit(PreDecrementExpression *) = 0; + virtual void endVisit(PreDecrementExpression *) = 0; - virtual bool visit(UnaryMinusExpression *) { return true; } - virtual void endVisit(UnaryMinusExpression *) {} + virtual bool visit(UnaryPlusExpression *) = 0; + virtual void endVisit(UnaryPlusExpression *) = 0; - virtual bool visit(TildeExpression *) { return true; } - virtual void endVisit(TildeExpression *) {} + virtual bool visit(UnaryMinusExpression *) = 0; + virtual void endVisit(UnaryMinusExpression *) = 0; - virtual bool visit(NotExpression *) { return true; } - virtual void endVisit(NotExpression *) {} + virtual bool visit(TildeExpression *) = 0; + virtual void endVisit(TildeExpression *) = 0; - virtual bool visit(BinaryExpression *) { return true; } - virtual void endVisit(BinaryExpression *) {} + virtual bool visit(NotExpression *) = 0; + virtual void endVisit(NotExpression *) = 0; - virtual bool visit(ConditionalExpression *) { return true; } - virtual void endVisit(ConditionalExpression *) {} + virtual bool visit(BinaryExpression *) = 0; + virtual void endVisit(BinaryExpression *) = 0; - virtual bool visit(Expression *) { return true; } - virtual void endVisit(Expression *) {} + virtual bool visit(ConditionalExpression *) = 0; + virtual void endVisit(ConditionalExpression *) = 0; - virtual bool visit(Block *) { return true; } - virtual void endVisit(Block *) {} + virtual bool visit(Expression *) = 0; + virtual void endVisit(Expression *) = 0; - virtual bool visit(StatementList *) { return true; } - virtual void endVisit(StatementList *) {} + virtual bool visit(Block *) = 0; + virtual void endVisit(Block *) = 0; - virtual bool visit(VariableStatement *) { return true; } - virtual void endVisit(VariableStatement *) {} + virtual bool visit(StatementList *) = 0; + virtual void endVisit(StatementList *) = 0; - virtual bool visit(VariableDeclarationList *) { return true; } - virtual void endVisit(VariableDeclarationList *) {} + virtual bool visit(VariableStatement *) = 0; + virtual void endVisit(VariableStatement *) = 0; - virtual bool visit(EmptyStatement *) { return true; } - virtual void endVisit(EmptyStatement *) {} + virtual bool visit(VariableDeclarationList *) = 0; + virtual void endVisit(VariableDeclarationList *) = 0; - virtual bool visit(ExpressionStatement *) { return true; } - virtual void endVisit(ExpressionStatement *) {} + virtual bool visit(EmptyStatement *) = 0; + virtual void endVisit(EmptyStatement *) = 0; - virtual bool visit(IfStatement *) { return true; } - virtual void endVisit(IfStatement *) {} + virtual bool visit(ExpressionStatement *) = 0; + virtual void endVisit(ExpressionStatement *) = 0; - virtual bool visit(DoWhileStatement *) { return true; } - virtual void endVisit(DoWhileStatement *) {} + virtual bool visit(IfStatement *) = 0; + virtual void endVisit(IfStatement *) = 0; - virtual bool visit(WhileStatement *) { return true; } - virtual void endVisit(WhileStatement *) {} + virtual bool visit(DoWhileStatement *) = 0; + virtual void endVisit(DoWhileStatement *) = 0; - virtual bool visit(ForStatement *) { return true; } - virtual void endVisit(ForStatement *) {} + virtual bool visit(WhileStatement *) = 0; + virtual void endVisit(WhileStatement *) = 0; - virtual bool visit(ForEachStatement *) { return true; } - virtual void endVisit(ForEachStatement *) {} + virtual bool visit(ForStatement *) = 0; + virtual void endVisit(ForStatement *) = 0; - virtual bool visit(ContinueStatement *) { return true; } - virtual void endVisit(ContinueStatement *) {} + virtual bool visit(ForEachStatement *) = 0; + virtual void endVisit(ForEachStatement *) = 0; - virtual bool visit(BreakStatement *) { return true; } - virtual void endVisit(BreakStatement *) {} + virtual bool visit(ContinueStatement *) = 0; + virtual void endVisit(ContinueStatement *) = 0; - virtual bool visit(ReturnStatement *) { return true; } - virtual void endVisit(ReturnStatement *) {} + virtual bool visit(BreakStatement *) = 0; + virtual void endVisit(BreakStatement *) = 0; - virtual bool visit(YieldExpression *) { return true; } - virtual void endVisit(YieldExpression *) {} + virtual bool visit(ReturnStatement *) = 0; + virtual void endVisit(ReturnStatement *) = 0; - virtual bool visit(WithStatement *) { return true; } - virtual void endVisit(WithStatement *) {} + virtual bool visit(YieldExpression *) = 0; + virtual void endVisit(YieldExpression *) = 0; - virtual bool visit(SwitchStatement *) { return true; } - virtual void endVisit(SwitchStatement *) {} + virtual bool visit(WithStatement *) = 0; + virtual void endVisit(WithStatement *) = 0; - virtual bool visit(CaseBlock *) { return true; } - virtual void endVisit(CaseBlock *) {} + virtual bool visit(SwitchStatement *) = 0; + virtual void endVisit(SwitchStatement *) = 0; - virtual bool visit(CaseClauses *) { return true; } - virtual void endVisit(CaseClauses *) {} + virtual bool visit(CaseBlock *) = 0; + virtual void endVisit(CaseBlock *) = 0; - virtual bool visit(CaseClause *) { return true; } - virtual void endVisit(CaseClause *) {} + virtual bool visit(CaseClauses *) = 0; + virtual void endVisit(CaseClauses *) = 0; - virtual bool visit(DefaultClause *) { return true; } - virtual void endVisit(DefaultClause *) {} + virtual bool visit(CaseClause *) = 0; + virtual void endVisit(CaseClause *) = 0; - virtual bool visit(LabelledStatement *) { return true; } - virtual void endVisit(LabelledStatement *) {} + virtual bool visit(DefaultClause *) = 0; + virtual void endVisit(DefaultClause *) = 0; - virtual bool visit(ThrowStatement *) { return true; } - virtual void endVisit(ThrowStatement *) {} + virtual bool visit(LabelledStatement *) = 0; + virtual void endVisit(LabelledStatement *) = 0; - virtual bool visit(TryStatement *) { return true; } - virtual void endVisit(TryStatement *) {} + virtual bool visit(ThrowStatement *) = 0; + virtual void endVisit(ThrowStatement *) = 0; - virtual bool visit(Catch *) { return true; } - virtual void endVisit(Catch *) {} + virtual bool visit(TryStatement *) = 0; + virtual void endVisit(TryStatement *) = 0; - virtual bool visit(Finally *) { return true; } - virtual void endVisit(Finally *) {} + virtual bool visit(Catch *) = 0; + virtual void endVisit(Catch *) = 0; - virtual bool visit(FunctionDeclaration *) { return true; } - virtual void endVisit(FunctionDeclaration *) {} + virtual bool visit(Finally *) = 0; + virtual void endVisit(Finally *) = 0; - virtual bool visit(FunctionExpression *) { return true; } - virtual void endVisit(FunctionExpression *) {} + virtual bool visit(FunctionDeclaration *) = 0; + virtual void endVisit(FunctionDeclaration *) = 0; - virtual bool visit(FormalParameterList *) { return true; } - virtual void endVisit(FormalParameterList *) {} + virtual bool visit(FunctionExpression *) = 0; + virtual void endVisit(FunctionExpression *) = 0; - virtual bool visit(ClassExpression *) { return true; } - virtual void endVisit(ClassExpression *) {} + virtual bool visit(FormalParameterList *) = 0; + virtual void endVisit(FormalParameterList *) = 0; - virtual bool visit(ClassDeclaration *) { return true; } - virtual void endVisit(ClassDeclaration *) {} + virtual bool visit(ClassExpression *) = 0; + virtual void endVisit(ClassExpression *) = 0; - virtual bool visit(ClassElementList *) { return true; } - virtual void endVisit(ClassElementList *) {} + virtual bool visit(ClassDeclaration *) = 0; + virtual void endVisit(ClassDeclaration *) = 0; - virtual bool visit(Program *) { return true; } - virtual void endVisit(Program *) {} + virtual bool visit(ClassElementList *) = 0; + virtual void endVisit(ClassElementList *) = 0; - virtual bool visit(NameSpaceImport *) { return true; } - virtual void endVisit(NameSpaceImport *) {} + virtual bool visit(Program *) = 0; + virtual void endVisit(Program *) = 0; - virtual bool visit(ImportSpecifier *) { return true; } - virtual void endVisit(ImportSpecifier *) {} + virtual bool visit(NameSpaceImport *) = 0; + virtual void endVisit(NameSpaceImport *) = 0; - virtual bool visit(ImportsList *) { return true; } - virtual void endVisit(ImportsList *) {} + virtual bool visit(ImportSpecifier *) = 0; + virtual void endVisit(ImportSpecifier *) = 0; - virtual bool visit(NamedImports *) { return true; } - virtual void endVisit(NamedImports *) {} + virtual bool visit(ImportsList *) = 0; + virtual void endVisit(ImportsList *) = 0; - virtual bool visit(FromClause *) { return true; } - virtual void endVisit(FromClause *) {} + virtual bool visit(NamedImports *) = 0; + virtual void endVisit(NamedImports *) = 0; - virtual bool visit(ImportClause *) { return true; } - virtual void endVisit(ImportClause *) {} + virtual bool visit(FromClause *) = 0; + virtual void endVisit(FromClause *) = 0; - virtual bool visit(ImportDeclaration *) { return true; } - virtual void endVisit(ImportDeclaration *) {} + virtual bool visit(ImportClause *) = 0; + virtual void endVisit(ImportClause *) = 0; - virtual bool visit(ExportSpecifier *) { return true; } - virtual void endVisit(ExportSpecifier *) {} + virtual bool visit(ImportDeclaration *) = 0; + virtual void endVisit(ImportDeclaration *) = 0; - virtual bool visit(ExportsList *) { return true; } - virtual void endVisit(ExportsList *) {} + virtual bool visit(ExportSpecifier *) = 0; + virtual void endVisit(ExportSpecifier *) = 0; - virtual bool visit(ExportClause *) { return true; } - virtual void endVisit(ExportClause *) {} + virtual bool visit(ExportsList *) = 0; + virtual void endVisit(ExportsList *) = 0; - virtual bool visit(ExportDeclaration *) { return true; } - virtual void endVisit(ExportDeclaration *) {} + virtual bool visit(ExportClause *) = 0; + virtual void endVisit(ExportClause *) = 0; - virtual bool visit(ModuleItem *) { return true; } - virtual void endVisit(ModuleItem *) {} + virtual bool visit(ExportDeclaration *) = 0; + virtual void endVisit(ExportDeclaration *) = 0; - virtual bool visit(ESModule *) { return true; } - virtual void endVisit(ESModule *) {} + virtual bool visit(ESModule *) = 0; + virtual void endVisit(ESModule *) = 0; - virtual bool visit(DebuggerStatement *) { return true; } - virtual void endVisit(DebuggerStatement *) {} + virtual bool visit(DebuggerStatement *) = 0; + virtual void endVisit(DebuggerStatement *) = 0; - virtual bool visit(Type *) { return true; } - virtual void endVisit(Type *) {} + virtual bool visit(Type *) = 0; + virtual void endVisit(Type *) = 0; - virtual bool visit(TypeArgumentList *) { return true; } - virtual void endVisit(TypeArgumentList *) {} + virtual bool visit(TypeArgumentList *) = 0; + virtual void endVisit(TypeArgumentList *) = 0; - virtual bool visit(TypeAnnotation *) { return true; } - virtual void endVisit(TypeAnnotation *) {} + virtual bool visit(TypeAnnotation *) = 0; + virtual void endVisit(TypeAnnotation *) = 0; virtual void throwRecursionDepthError() = 0; @@ -423,6 +426,339 @@ protected: friend class RecursionDepthCheck; }; +class QML_PARSER_EXPORT Visitor: public BaseVisitor +{ +public: + Visitor(quint16 parentRecursionDepth = 0); + + bool preVisit(Node *) override { return true; } + void postVisit(Node *) override {} + + // Ui + bool visit(UiProgram *) override { return true; } + bool visit(UiHeaderItemList *) override { return true; } + bool visit(UiPragma *) override { return true; } + bool visit(UiImport *) override { return true; } + bool visit(UiPublicMember *) override { return true; } + bool visit(UiSourceElement *) override { return true; } + bool visit(UiObjectDefinition *) override { return true; } + bool visit(UiObjectInitializer *) override { return true; } + bool visit(UiObjectBinding *) override { return true; } + bool visit(UiScriptBinding *) override { return true; } + bool visit(UiArrayBinding *) override { return true; } + bool visit(UiParameterList *) override { return true; } + bool visit(UiObjectMemberList *) override { return true; } + bool visit(UiArrayMemberList *) override { return true; } + bool visit(UiQualifiedId *) override { return true; } + bool visit(UiEnumDeclaration *) override { return true; } + bool visit(UiEnumMemberList *) override { return true; } + bool visit(UiVersionSpecifier *) override { return true; } + bool visit(UiInlineComponent *) override { return true; } + bool visit(UiAnnotation *) override { return true; } + bool visit(UiAnnotationList *) override { return true; } + bool visit(UiRequired *) override { return true; } + + void endVisit(UiProgram *) override {} + void endVisit(UiImport *) override {} + void endVisit(UiHeaderItemList *) override {} + void endVisit(UiPragma *) override {} + void endVisit(UiPublicMember *) override {} + void endVisit(UiSourceElement *) override {} + void endVisit(UiObjectDefinition *) override {} + void endVisit(UiObjectInitializer *) override {} + void endVisit(UiObjectBinding *) override {} + void endVisit(UiScriptBinding *) override {} + void endVisit(UiArrayBinding *) override {} + void endVisit(UiParameterList *) override {} + void endVisit(UiObjectMemberList *) override {} + void endVisit(UiArrayMemberList *) override {} + void endVisit(UiQualifiedId *) override {} + void endVisit(UiEnumDeclaration *) override {} + void endVisit(UiEnumMemberList *) override {} + void endVisit(UiVersionSpecifier *) override {} + void endVisit(UiInlineComponent *) override {} + void endVisit(UiAnnotation *) override {} + void endVisit(UiAnnotationList *) override {} + void endVisit(UiRequired *) override {} + + // QQmlJS + bool visit(ThisExpression *) override { return true; } + void endVisit(ThisExpression *) override {} + + bool visit(IdentifierExpression *) override { return true; } + void endVisit(IdentifierExpression *) override {} + + bool visit(NullExpression *) override { return true; } + void endVisit(NullExpression *) override {} + + bool visit(TrueLiteral *) override { return true; } + void endVisit(TrueLiteral *) override {} + + bool visit(FalseLiteral *) override { return true; } + void endVisit(FalseLiteral *) override {} + + bool visit(SuperLiteral *) override { return true; } + void endVisit(SuperLiteral *) override {} + + bool visit(StringLiteral *) override { return true; } + void endVisit(StringLiteral *) override {} + + bool visit(TemplateLiteral *) override { return true; } + void endVisit(TemplateLiteral *) override {} + + bool visit(NumericLiteral *) override { return true; } + void endVisit(NumericLiteral *) override {} + + bool visit(RegExpLiteral *) override { return true; } + void endVisit(RegExpLiteral *) override {} + + bool visit(ArrayPattern *) override { return true; } + void endVisit(ArrayPattern *) override {} + + bool visit(ObjectPattern *) override { return true; } + void endVisit(ObjectPattern *) override {} + + bool visit(PatternElementList *) override { return true; } + void endVisit(PatternElementList *) override {} + + bool visit(PatternPropertyList *) override { return true; } + void endVisit(PatternPropertyList *) override {} + + bool visit(PatternElement *) override { return true; } + void endVisit(PatternElement *) override {} + + bool visit(PatternProperty *) override { return true; } + void endVisit(PatternProperty *) override {} + + bool visit(Elision *) override { return true; } + void endVisit(Elision *) override {} + + bool visit(NestedExpression *) override { return true; } + void endVisit(NestedExpression *) override {} + + bool visit(IdentifierPropertyName *) override { return true; } + void endVisit(IdentifierPropertyName *) override {} + + bool visit(StringLiteralPropertyName *) override { return true; } + void endVisit(StringLiteralPropertyName *) override {} + + bool visit(NumericLiteralPropertyName *) override { return true; } + void endVisit(NumericLiteralPropertyName *) override {} + + bool visit(ComputedPropertyName *) override { return true; } + void endVisit(ComputedPropertyName *) override {} + + bool visit(ArrayMemberExpression *) override { return true; } + void endVisit(ArrayMemberExpression *) override {} + + bool visit(FieldMemberExpression *) override { return true; } + void endVisit(FieldMemberExpression *) override {} + + bool visit(TaggedTemplate *) override { return true; } + void endVisit(TaggedTemplate *) override {} + + bool visit(NewMemberExpression *) override { return true; } + void endVisit(NewMemberExpression *) override {} + + bool visit(NewExpression *) override { return true; } + void endVisit(NewExpression *) override {} + + bool visit(CallExpression *) override { return true; } + void endVisit(CallExpression *) override {} + + bool visit(ArgumentList *) override { return true; } + void endVisit(ArgumentList *) override {} + + bool visit(PostIncrementExpression *) override { return true; } + void endVisit(PostIncrementExpression *) override {} + + bool visit(PostDecrementExpression *) override { return true; } + void endVisit(PostDecrementExpression *) override {} + + bool visit(DeleteExpression *) override { return true; } + void endVisit(DeleteExpression *) override {} + + bool visit(VoidExpression *) override { return true; } + void endVisit(VoidExpression *) override {} + + bool visit(TypeOfExpression *) override { return true; } + void endVisit(TypeOfExpression *) override {} + + bool visit(PreIncrementExpression *) override { return true; } + void endVisit(PreIncrementExpression *) override {} + + bool visit(PreDecrementExpression *) override { return true; } + void endVisit(PreDecrementExpression *) override {} + + bool visit(UnaryPlusExpression *) override { return true; } + void endVisit(UnaryPlusExpression *) override {} + + bool visit(UnaryMinusExpression *) override { return true; } + void endVisit(UnaryMinusExpression *) override {} + + bool visit(TildeExpression *) override { return true; } + void endVisit(TildeExpression *) override {} + + bool visit(NotExpression *) override { return true; } + void endVisit(NotExpression *) override {} + + bool visit(BinaryExpression *) override { return true; } + void endVisit(BinaryExpression *) override {} + + bool visit(ConditionalExpression *) override { return true; } + void endVisit(ConditionalExpression *) override {} + + bool visit(Expression *) override { return true; } + void endVisit(Expression *) override {} + + bool visit(Block *) override { return true; } + void endVisit(Block *) override {} + + bool visit(StatementList *) override { return true; } + void endVisit(StatementList *) override {} + + bool visit(VariableStatement *) override { return true; } + void endVisit(VariableStatement *) override {} + + bool visit(VariableDeclarationList *) override { return true; } + void endVisit(VariableDeclarationList *) override {} + + bool visit(EmptyStatement *) override { return true; } + void endVisit(EmptyStatement *) override {} + + bool visit(ExpressionStatement *) override { return true; } + void endVisit(ExpressionStatement *) override {} + + bool visit(IfStatement *) override { return true; } + void endVisit(IfStatement *) override {} + + bool visit(DoWhileStatement *) override { return true; } + void endVisit(DoWhileStatement *) override {} + + bool visit(WhileStatement *) override { return true; } + void endVisit(WhileStatement *) override {} + + bool visit(ForStatement *) override { return true; } + void endVisit(ForStatement *) override {} + + bool visit(ForEachStatement *) override { return true; } + void endVisit(ForEachStatement *) override {} + + bool visit(ContinueStatement *) override { return true; } + void endVisit(ContinueStatement *) override {} + + bool visit(BreakStatement *) override { return true; } + void endVisit(BreakStatement *) override {} + + bool visit(ReturnStatement *) override { return true; } + void endVisit(ReturnStatement *) override {} + + bool visit(YieldExpression *) override { return true; } + void endVisit(YieldExpression *) override {} + + bool visit(WithStatement *) override { return true; } + void endVisit(WithStatement *) override {} + + bool visit(SwitchStatement *) override { return true; } + void endVisit(SwitchStatement *) override {} + + bool visit(CaseBlock *) override { return true; } + void endVisit(CaseBlock *) override {} + + bool visit(CaseClauses *) override { return true; } + void endVisit(CaseClauses *) override {} + + bool visit(CaseClause *) override { return true; } + void endVisit(CaseClause *) override {} + + bool visit(DefaultClause *) override { return true; } + void endVisit(DefaultClause *) override {} + + bool visit(LabelledStatement *) override { return true; } + void endVisit(LabelledStatement *) override {} + + bool visit(ThrowStatement *) override { return true; } + void endVisit(ThrowStatement *) override {} + + bool visit(TryStatement *) override { return true; } + void endVisit(TryStatement *) override {} + + bool visit(Catch *) override { return true; } + void endVisit(Catch *) override {} + + bool visit(Finally *) override { return true; } + void endVisit(Finally *) override {} + + bool visit(FunctionDeclaration *) override { return true; } + void endVisit(FunctionDeclaration *) override {} + + bool visit(FunctionExpression *) override { return true; } + void endVisit(FunctionExpression *) override {} + + bool visit(FormalParameterList *) override { return true; } + void endVisit(FormalParameterList *) override {} + + bool visit(ClassExpression *) override { return true; } + void endVisit(ClassExpression *) override {} + + bool visit(ClassDeclaration *) override { return true; } + void endVisit(ClassDeclaration *) override {} + + bool visit(ClassElementList *) override { return true; } + void endVisit(ClassElementList *) override {} + + bool visit(Program *) override { return true; } + void endVisit(Program *) override {} + + bool visit(NameSpaceImport *) override { return true; } + void endVisit(NameSpaceImport *) override {} + + bool visit(ImportSpecifier *) override { return true; } + void endVisit(ImportSpecifier *) override {} + + bool visit(ImportsList *) override { return true; } + void endVisit(ImportsList *) override {} + + bool visit(NamedImports *) override { return true; } + void endVisit(NamedImports *) override {} + + bool visit(FromClause *) override { return true; } + void endVisit(FromClause *) override {} + + bool visit(ImportClause *) override { return true; } + void endVisit(ImportClause *) override {} + + bool visit(ImportDeclaration *) override { return true; } + void endVisit(ImportDeclaration *) override {} + + bool visit(ExportSpecifier *) override { return true; } + void endVisit(ExportSpecifier *) override {} + + bool visit(ExportsList *) override { return true; } + void endVisit(ExportsList *) override {} + + bool visit(ExportClause *) override { return true; } + void endVisit(ExportClause *) override {} + + bool visit(ExportDeclaration *) override { return true; } + void endVisit(ExportDeclaration *) override {} + + bool visit(ESModule *) override { return true; } + void endVisit(ESModule *) override {} + + bool visit(DebuggerStatement *) override { return true; } + void endVisit(DebuggerStatement *) override {} + + bool visit(Type *) override { return true; } + void endVisit(Type *) override {} + + bool visit(TypeArgumentList *) override { return true; } + void endVisit(TypeArgumentList *) override {} + + bool visit(TypeAnnotation *) override { return true; } + void endVisit(TypeAnnotation *) override {} +}; + } } // namespace AST QT_END_NAMESPACE diff --git a/src/qml/parser/qqmljsengine_p.cpp b/src/qml/parser/qqmljsengine_p.cpp index bb27f3992e..cb6b0375e6 100644 --- a/src/qml/parser/qqmljsengine_p.cpp +++ b/src/qml/parser/qqmljsengine_p.cpp @@ -123,9 +123,9 @@ void Engine::setCode(const QString &code) { _code = code; } void Engine::addComment(int pos, int len, int line, int col) -{ if (len > 0) _comments.append(QQmlJS::AST::SourceLocation(pos, len, line, col)); } +{ if (len > 0) _comments.append(QQmlJS::SourceLocation(pos, len, line, col)); } -QList<QQmlJS::AST::SourceLocation> Engine::comments() const +QList<QQmlJS::SourceLocation> Engine::comments() const { return _comments; } Lexer *Engine::lexer() const diff --git a/src/qml/parser/qqmljsengine_p.h b/src/qml/parser/qqmljsengine_p.h index 8a3e2db6a1..a34922fa1e 100644 --- a/src/qml/parser/qqmljsengine_p.h +++ b/src/qml/parser/qqmljsengine_p.h @@ -52,7 +52,7 @@ // #include "qqmljsglobal_p.h" -#include "qqmljssourcelocation_p.h" +#include <private/qqmljssourcelocation_p.h> #include <private/qqmljsmemorypool_p.h> @@ -97,7 +97,7 @@ class QML_PARSER_EXPORT Engine Lexer *_lexer; Directives *_directives; MemoryPool _pool; - QList<AST::SourceLocation> _comments; + QList<SourceLocation> _comments; QString _extraCode; QString _code; @@ -109,7 +109,7 @@ public: const QString &code() const { return _code; } void addComment(int pos, int len, int line, int col); - QList<AST::SourceLocation> comments() const; + QList<SourceLocation> comments() const; Lexer *lexer() const; void setLexer(Lexer *lexer); diff --git a/src/qml/parser/qqmljslexer.cpp b/src/qml/parser/qqmljslexer.cpp index 80d883e52f..243fc5bd30 100644 --- a/src/qml/parser/qqmljslexer.cpp +++ b/src/qml/parser/qqmljslexer.cpp @@ -719,6 +719,8 @@ again: case ')': return T_RPAREN; case '(': return T_LPAREN; + case '@': return T_AT; + case '&': if (_char == QLatin1Char('=')) { scanChar(); @@ -1478,8 +1480,8 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error) { auto setError = [error, this](QString message) { error->message = std::move(message); - error->line = tokenStartLine(); - error->column = tokenStartColumn(); + error->loc.startLine = tokenStartLine(); + error->loc.startColumn = tokenStartColumn(); }; QScopedValueRollback<bool> directivesGuard(_handlingDirectives, true); @@ -1594,8 +1596,8 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error) else setError(QCoreApplication::translate("QQmlParser", "Module import requires a qualifier")); if (tokenStartLine() != lineNumber) { - error->line = lineNumber; - error->line = column; + error->loc.startLine = lineNumber; + error->loc.startColumn = column; } return false; // expected `as' } diff --git a/src/qml/qml.pro b/src/qml/qml.pro index 5b2ac4b5cf..7bb3547ee9 100644 --- a/src/qml/qml.pro +++ b/src/qml/qml.pro @@ -71,7 +71,7 @@ MODULE_PLUGIN_TYPES = \ QMLTYPES_FILENAME = plugins.qmltypes QMLTYPES_INSTALL_DIR = $$[QT_INSTALL_QML]/QtQml QML_IMPORT_NAME = QtQml -IMPORT_VERSION = 2.15 +QML_IMPORT_VERSION = $$QT_VERSION CONFIG += qmltypes install_qmltypes install_metatypes load(qt_module) diff --git a/src/qml/qml/ftw/qqmlthread.cpp b/src/qml/qml/ftw/qqmlthread.cpp index 7d2ad354d6..0f7726ef65 100644 --- a/src/qml/qml/ftw/qqmlthread.cpp +++ b/src/qml/qml/ftw/qqmlthread.cpp @@ -188,13 +188,7 @@ void QQmlThreadPrivate::threadEvent() lock(); for (;;) { - if (m_shutdown) { - quit(); - wakeOne(); - unlock(); - - return; - } else if (!threadList.isEmpty()) { + if (!threadList.isEmpty()) { m_threadProcessing = true; QQmlThread::Message *message = threadList.first(); @@ -206,6 +200,12 @@ void QQmlThreadPrivate::threadEvent() lock(); delete threadList.takeFirst(); + } else if (m_shutdown) { + quit(); + wakeOne(); + unlock(); + + return; } else { wakeOne(); @@ -242,6 +242,7 @@ void QQmlThread::shutdown() d->lock(); Q_ASSERT(!d->m_shutdown); + d->m_shutdown = true; for (;;) { if (d->mainSync || !d->mainList.isEmpty()) { d->unlock(); @@ -254,13 +255,10 @@ void QQmlThread::shutdown() } } - d->m_shutdown = true; - if (QCoreApplication::closingDown()) { + if (QCoreApplication::closingDown()) d->quit(); - } else { + else d->triggerThreadEvent(); - d->wait(); - } d->unlock(); d->QThread::wait(); diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index a33936647f..20dd3827c5 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -46,6 +46,7 @@ #include <private/qqmlmetatypedata_p.h> #include <private/qqmltype_p_p.h> #include <private/qqmltypemodule_p_p.h> +#include <private/qqmltypenotavailable_p.h> #include <QtCore/qmutex.h> @@ -61,19 +62,20 @@ void qmlClearTypeRegistrations() // Declared in qqml.h //From qqml.h bool qmlProtectModule(const char *uri, int majVersion) { - return QQmlMetaType::protectModule(QString::fromUtf8(uri), majVersion); + return QQmlMetaType::protectModule(QString::fromUtf8(uri), + QTypeRevision::fromMajorVersion(majVersion)); } //From qqml.h void qmlRegisterModule(const char *uri, int versionMajor, int versionMinor) { - QQmlMetaType::registerModule(uri, versionMajor, versionMinor); + QQmlMetaType::registerModule(uri, QTypeRevision::fromVersion(versionMajor, versionMinor)); } //From qqml.h int qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName) { - return QQmlMetaType::typeId(uri, versionMajor, versionMinor, qmlName); + return QQmlMetaType::typeId(uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName); } // From qqmlprivate.h @@ -103,9 +105,9 @@ QObject *QQmlPrivate::RegisterSingletonFunctor::operator()(QQmlEngine *qeng, QJS return m_object; }; -static QVector<int> availableRevisions(const QMetaObject *metaObject) +static QVector<QTypeRevision> availableRevisions(const QMetaObject *metaObject) { - QVector<int> revisions; + QVector<QTypeRevision> revisions; if (!metaObject) return revisions; const int propertyOffset = metaObject->propertyOffset(); @@ -114,7 +116,7 @@ static QVector<int> availableRevisions(const QMetaObject *metaObject) propertyIndex < propertyEnd; ++propertyIndex) { const QMetaProperty property = metaObject->property(propertyIndex); if (int revision = property.revision()) - revisions.append(revision); + revisions.append(QTypeRevision::fromEncodedVersion(revision)); } const int methodOffset = metaObject->methodOffset(); const int methodCount = metaObject->methodCount(); @@ -122,7 +124,7 @@ static QVector<int> availableRevisions(const QMetaObject *metaObject) methodIndex < methodEnd; ++methodIndex) { const QMetaMethod method = metaObject->method(methodIndex); if (int revision = method.revision()) - revisions.append(revision); + revisions.append(QTypeRevision::fromEncodedVersion(revision)); } // Need to also check parent meta objects, as their revisions are inherited. @@ -132,6 +134,54 @@ static QVector<int> availableRevisions(const QMetaObject *metaObject) return revisions; } +template<typename Registration> +void assignVersions(Registration *registration, QTypeRevision revision, + QTypeRevision defaultVersion) +{ + const quint8 majorVersion = revision.hasMajorVersion() ? revision.majorVersion() + : defaultVersion.majorVersion(); + registration->version = revision.hasMinorVersion() + ? QTypeRevision::fromVersion(majorVersion, revision.minorVersion()) + : QTypeRevision::fromMajorVersion(majorVersion); + registration->revision = revision; +} + +static QVector<QTypeRevision> prepareRevisions(const QMetaObject *metaObject, QTypeRevision added) +{ + auto revisions = availableRevisions(metaObject); + revisions.append(added); + return revisions; +} + +static void uniqueRevisions(QVector<QTypeRevision> *revisions, QTypeRevision defaultVersion, + QTypeRevision added) +{ + bool revisionsHaveMajorVersions = false; + for (QTypeRevision revision : QVector<QTypeRevision>(*revisions)) { // yes, copy + // allow any minor version for each explicitly specified past major one + if (revision.hasMajorVersion()) { + revisionsHaveMajorVersions = true; + if (revision.majorVersion() < defaultVersion.majorVersion()) + revisions->append(QTypeRevision::fromVersion(revision.majorVersion(), 254)); + } + } + + if (revisionsHaveMajorVersions) { + if (!added.hasMajorVersion()) { + // If added in unspecified major version, assume default one. + revisions->append(QTypeRevision::fromVersion(defaultVersion.majorVersion(), + added.minorVersion())); + } else if (added.majorVersion() < defaultVersion.majorVersion()) { + // If added in past major version, add .0 of default version. + revisions->append(QTypeRevision::fromVersion(defaultVersion.majorVersion(), 0)); + } + } + + std::sort(revisions->begin(), revisions->end()); + const auto it = std::unique(revisions->begin(), revisions->end()); + revisions->erase(it, revisions->end()); +} + /* This method is "over generalized" to allow us to (potentially) register more types of things in the future without adding exported symbols. @@ -163,8 +213,7 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data) nullptr, noCreateReason, type.uri, - type.versionMajor, - -1, + type.version, nullptr, type.metaObject, type.attachedPropertiesFunction, @@ -175,28 +224,26 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data) type.extensionObjectCreate, type.extensionMetaObject, nullptr, - -1 + QTypeRevision() }; - const int added = intClassInfo(type.classInfoMetaObject, "QML.AddedInMinorVersion", 0); - const int removed = intClassInfo(type.classInfoMetaObject, "QML.RemovedInMinorVersion", -1); + const QTypeRevision added = revisionClassInfo( + type.classInfoMetaObject, "QML.AddedInVersion", + QTypeRevision::fromMinorVersion(0)); + const QTypeRevision removed = revisionClassInfo( + type.classInfoMetaObject, "QML.RemovedInVersion"); - auto revisions = availableRevisions(type.metaObject); - revisions.append(qMax(added, 0)); + auto revisions = prepareRevisions(type.metaObject, added); if (type.attachedPropertiesMetaObject) revisions += availableRevisions(type.attachedPropertiesMetaObject); + uniqueRevisions(&revisions, type.version, added); - std::sort(revisions.begin(), revisions.end()); - const auto it = std::unique(revisions.begin(), revisions.end()); - revisions.erase(it, revisions.end()); - - const bool typeWasRemoved = removed >= added; - for (int revision : revisions) { + for (QTypeRevision revision : revisions) { if (revision < added) continue; // When removed, we still add revisions, but anonymous ones - if (typeWasRemoved && revision >= removed) { + if (removed.isValid() && !(revision < removed)) { revisionRegistration.elementName = nullptr; revisionRegistration.create = nullptr; } else { @@ -204,11 +251,8 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data) revisionRegistration.create = creatable ? type.create : nullptr; } - // Equivalent of qmlRegisterRevision<T, revision>(...) - revisionRegistration.versionMinor = revision; - revisionRegistration.revision = revision; + assignVersions(&revisionRegistration, revision, type.version); revisionRegistration.customParser = type.customParserFactory(); - qmlregister(TypeRegistration, &revisionRegistration); } break; @@ -220,36 +264,33 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data) RegisterSingletonType revisionRegistration = { QmlCurrentSingletonTypeRegistrationVersion, type.uri, - type.versionMajor, - -1, + type.version, elementName, type.scriptApi, nullptr, type.instanceMetaObject, type.typeId, - -1, + QTypeRevision(), type.generalizedQobjectApi }; - const int added = intClassInfo(type.classInfoMetaObject, "QML.AddedInMinorVersion", 0); - const int removed = intClassInfo(type.classInfoMetaObject, "QML.RemovedInMinorVersion", -1); + const QTypeRevision added = revisionClassInfo( + type.classInfoMetaObject, "QML.AddedInVersion", + QTypeRevision::fromMinorVersion(0)); + const QTypeRevision removed = revisionClassInfo( + type.classInfoMetaObject, "QML.RemovedInVersion"); - auto revisions = availableRevisions(type.instanceMetaObject); - revisions.append(qMax(added, 0)); + auto revisions = prepareRevisions(type.instanceMetaObject, added); + uniqueRevisions(&revisions, type.version, added); - std::sort(revisions.begin(), revisions.end()); - const auto it = std::unique(revisions.begin(), revisions.end()); - revisions.erase(it, revisions.end()); - - const bool typeWasRemoved = removed >= added; - for (int revision : qAsConst(revisions)) { + for (QTypeRevision revision : qAsConst(revisions)) { if (revision < added) continue; // When removed, we still add revisions, but anonymous ones - if (typeWasRemoved && revision >= removed) { + if (removed.isValid() && !(revision < removed)) { revisionRegistration.typeName = nullptr; revisionRegistration.scriptApi = nullptr; revisionRegistration.generalizedQobjectApi = nullptr; @@ -259,10 +300,7 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data) revisionRegistration.generalizedQobjectApi = type.generalizedQobjectApi; } - // Equivalent of qmlRegisterRevision<T, revision>(...) - revisionRegistration.versionMinor = revision; - revisionRegistration.revision = revision; - + assignVersions(&revisionRegistration, revision, type.version); qmlregister(SingletonRegistration, &revisionRegistration); } break; @@ -321,4 +359,38 @@ void QQmlPrivate::qmlunregister(RegistrationType type, quintptr data) } } +namespace QQmlPrivate { + template<> + void qmlRegisterTypeAndRevisions<QQmlTypeNotAvailable, void>( + const char *uri, int versionMajor, const QMetaObject *classInfoMetaObject) + { + using T = QQmlTypeNotAvailable; + + RegisterTypeAndRevisions type = { + 0, + QMetaType::fromType<T *>(), + QMetaType::fromType<QQmlListProperty<T>>(), + 0, + nullptr, + + uri, + QTypeRevision::fromMajorVersion(versionMajor), + + &QQmlTypeNotAvailable::staticMetaObject, + classInfoMetaObject, + + attachedPropertiesFunc<T>(), + attachedPropertiesMetaObject<T>(), + + StaticCastSelector<T, QQmlParserStatus>::cast(), + StaticCastSelector<T, QQmlPropertyValueSource>::cast(), + StaticCastSelector<T, QQmlPropertyValueInterceptor>::cast(), + + nullptr, nullptr, qmlCreateCustomParser<T> + }; + + qmlregister(TypeAndRevisionsRegistration, &type); + } +} + QT_END_NAMESPACE diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index ae3893dd73..840c6aaee3 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -44,6 +44,7 @@ #include <QtCore/qbytearray.h> #include <QtCore/qmetaobject.h> +#include <QtCore/qversionnumber.h> #define QML_VERSION 0x020000 #define QML_VERSION_STR "2.0" @@ -88,10 +89,16 @@ friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor); #define QML_ADDED_IN_MINOR_VERSION(VERSION) \ - Q_CLASSINFO("QML.AddedInMinorVersion", #VERSION) + Q_CLASSINFO("QML.AddedInVersion", Q_REVISION(VERSION)) + +#define QML_ADDED_IN_VERSION(MAJOR, MINOR) \ + Q_CLASSINFO("QML.AddedInVersion", Q_REVISION(MAJOR, MINOR)) #define QML_REMOVED_IN_MINOR_VERSION(VERSION) \ - Q_CLASSINFO("QML.RemovedInMinorVersion", #VERSION) + Q_CLASSINFO("QML.RemovedInVersion", Q_REVISION(VERSION)) + +#define QML_REMOVED_IN_VERSION(MAJOR, MINOR) \ + Q_CLASSINFO("QML.RemovedInVersion", Q_REVISION(MAJOR, MINOR)) #define QML_ATTACHED(ATTACHED_TYPE) \ Q_CLASSINFO("QML.Attached", #ATTACHED_TYPE) \ @@ -113,6 +120,16 @@ template<typename T, typename... Args> \ friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor); +#define QML_INTERFACE \ + Q_CLASSINFO("QML.Element", "anonymous") \ + enum class QmlIsInterface {yes = true}; \ + template<typename, typename> friend struct QML_PRIVATE_NAMESPACE::QmlInterface; \ + template<typename T, typename... Args> \ + friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor); + +#define QML_UNAVAILABLE \ + QML_FOREIGN(QQmlTypeNotAvailable) + enum { /* TYPEINFO flags */ QML_HAS_ATTACHED_PROPERTIES = 0x01 }; @@ -139,18 +156,16 @@ QQmlCustomParser *qmlCreateCustomParser(); template<typename T> int qmlRegisterAnonymousType(const char *uri, int versionMajor) { - QML_GETTYPENAMES - QQmlPrivate::RegisterType type = { 0, - qRegisterNormalizedMetaType<T *>(pointerName.constData()), - qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), + QMetaType::fromType<T *>(), + QMetaType::fromType<QQmlListProperty<T> >(), 0, nullptr, QString(), - uri, versionMajor, 0, nullptr, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, 0), nullptr, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -162,7 +177,7 @@ int qmlRegisterAnonymousType(const char *uri, int versionMajor) nullptr, nullptr, nullptr, - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -176,23 +191,22 @@ QT_DEPRECATED_VERSION_X_5_14("Use qmlRegisterAnonymousType instead") int qmlRegi } #endif -int Q_QML_EXPORT qmlRegisterTypeNotAvailable(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& message); +int Q_QML_EXPORT qmlRegisterTypeNotAvailable(const char *uri, int versionMajor, int versionMinor, + const char *qmlName, const QString& message); template<typename T> int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason) { - QML_GETTYPENAMES - QQmlPrivate::RegisterType type = { 0, - qRegisterNormalizedMetaType<T *>(pointerName.constData()), - qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), + QMetaType::fromType<T *>(), + QMetaType::fromType<QQmlListProperty<T>>(), 0, nullptr, reason, - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -204,7 +218,7 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin nullptr, nullptr, nullptr, - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -213,18 +227,16 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin template<typename T, int metaObjectRevision> int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason) { - QML_GETTYPENAMES - QQmlPrivate::RegisterType type = { 1, - qRegisterNormalizedMetaType<T *>(pointerName.constData()), - qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), + QMetaType::fromType<T *>(), + QMetaType::fromType<QQmlListProperty<T> >(), 0, nullptr, reason, - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -236,7 +248,7 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin nullptr, nullptr, nullptr, - metaObjectRevision + QTypeRevision::fromMinorVersion(metaObjectRevision) }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -245,8 +257,6 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin template<typename T, typename E> int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason) { - QML_GETTYPENAMES - QQmlAttachedPropertiesFunc attached = QQmlPrivate::attachedPropertiesFunc<E>(); const QMetaObject * attachedMetaObject = QQmlPrivate::attachedPropertiesMetaObject<E>(); if (!attached) { @@ -257,13 +267,13 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve QQmlPrivate::RegisterType type = { 0, - qRegisterNormalizedMetaType<T *>(pointerName.constData()), - qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), + QMetaType::fromType<T *>(), + QMetaType::fromType<QQmlListProperty<T> >(), 0, nullptr, reason, - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, attached, attachedMetaObject, @@ -275,7 +285,7 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve QQmlPrivate::createParent<E>, &E::staticMetaObject, nullptr, - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -284,8 +294,6 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve template<typename T, typename E, int metaObjectRevision> int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason) { - QML_GETTYPENAMES - QQmlAttachedPropertiesFunc attached = QQmlPrivate::attachedPropertiesFunc<E>(); const QMetaObject * attachedMetaObject = QQmlPrivate::attachedPropertiesMetaObject<E>(); if (!attached) { @@ -296,13 +304,13 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve QQmlPrivate::RegisterType type = { 1, - qRegisterNormalizedMetaType<T *>(pointerName.constData()), - qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), + QMetaType::fromType<T *>(), + QMetaType::fromType<QQmlListProperty<T> >(), 0, nullptr, reason, - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, attached, attachedMetaObject, @@ -314,7 +322,7 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve QQmlPrivate::createParent<E>, &E::staticMetaObject, nullptr, - metaObjectRevision + QTypeRevision::fromMinorVersion(metaObjectRevision) }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -325,17 +333,15 @@ Q_QML_EXPORT int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaO template<typename T> int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName) { - QML_GETTYPENAMES - QQmlPrivate::RegisterType type = { 0, - qRegisterNormalizedMetaType<T *>(pointerName.constData()), - qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), + QMetaType::fromType<T *>(), + QMetaType::fromType<QQmlListProperty<T> >(), sizeof(T), QQmlPrivate::createInto<T>, QString(), - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -347,7 +353,7 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c nullptr, nullptr, nullptr, - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -356,17 +362,15 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c template<typename T, int metaObjectRevision> int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName) { - QML_GETTYPENAMES - QQmlPrivate::RegisterType type = { 1, - qRegisterNormalizedMetaType<T *>(pointerName.constData()), - qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), + QMetaType::fromType<T *>(), + QMetaType::fromType<QQmlListProperty<T> >(), sizeof(T), QQmlPrivate::createInto<T>, QString(), - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -378,7 +382,7 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c nullptr, nullptr, nullptr, - metaObjectRevision + QTypeRevision::fromMinorVersion(metaObjectRevision) }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -387,17 +391,15 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c template<typename T, int metaObjectRevision> int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor) { - QML_GETTYPENAMES - QQmlPrivate::RegisterType type = { 1, - qRegisterNormalizedMetaType<T *>(pointerName.constData()), - qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), + QMetaType::fromType<T *>(), + QMetaType::fromType<QQmlListProperty<T> >(), sizeof(T), QQmlPrivate::createInto<T>, QString(), - uri, versionMajor, versionMinor, nullptr, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), nullptr, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -409,28 +411,25 @@ int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor) nullptr, nullptr, nullptr, - metaObjectRevision + QTypeRevision::fromMinorVersion(metaObjectRevision) }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); } - template<typename T, typename E> -int qmlRegisterExtendedType() +int qmlRegisterExtendedType(const char *uri, int versionMajor) { - QML_GETTYPENAMES - QQmlPrivate::RegisterType type = { 0, - qRegisterNormalizedMetaType<T *>(pointerName.constData()), - qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), + QMetaType::fromType<T *>(), + QMetaType::fromType<QQmlListProperty<T> >(), 0, nullptr, QString(), - nullptr, 0, 0, nullptr, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, 0), nullptr, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -442,18 +441,25 @@ int qmlRegisterExtendedType() QQmlPrivate::createParent<E>, &E::staticMetaObject, nullptr, - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); } +#if QT_DEPRECATED_SINCE(5, 15) +template<typename T, typename E> +QT_DEPRECATED_VERSION_X_5_15("Use qmlRegisterExtendedType(uri, versionMajor) instead") +int qmlRegisterExtendedType() +{ + return qmlRegisterExtendedType<T, E>("", 0); +} +#endif + template<typename T, typename E> int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, const char *qmlName) { - QML_GETTYPENAMES - QQmlAttachedPropertiesFunc attached = QQmlPrivate::attachedPropertiesFunc<E>(); const QMetaObject * attachedMetaObject = QQmlPrivate::attachedPropertiesMetaObject<E>(); if (!attached) { @@ -464,12 +470,12 @@ int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, QQmlPrivate::RegisterType type = { 0, - qRegisterNormalizedMetaType<T *>(pointerName.constData()), - qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), + QMetaType::fromType<T *>(), + QMetaType::fromType<QQmlListProperty<T> >(), sizeof(T), QQmlPrivate::createInto<T>, QString(), - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, attached, attachedMetaObject, @@ -481,13 +487,15 @@ int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, QQmlPrivate::createParent<E>, &E::staticMetaObject, nullptr, - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); } +#if QT_DEPRECATED_SINCE(5, 15) template<typename T> +QT_DEPRECATED_VERSION_X_5_15("Use qmlRegisterInterface(uri, versionMajor) instead") int qmlRegisterInterface(const char *typeName) { QByteArray name(typeName); @@ -496,12 +504,31 @@ int qmlRegisterInterface(const char *typeName) QByteArray listName("QQmlListProperty<" + name + '>'); QQmlPrivate::RegisterInterface qmlInterface = { - 0, + 1, - qRegisterNormalizedMetaType<T *>(pointerName.constData()), - qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), + QMetaType::fromType<T *>(), + QMetaType::fromType<QQmlListProperty<T> >(), - qobject_interface_iid<T *>() + qobject_interface_iid<T *>(), + "", + QTypeRevision::zero() + }; + + return QQmlPrivate::qmlregister(QQmlPrivate::InterfaceRegistration, &qmlInterface); +} +#endif + +template<typename T> +int qmlRegisterInterface(const char *uri, int versionMajor) +{ + QQmlPrivate::RegisterInterface qmlInterface = { + 1, + QMetaType::fromType<T *>(), + QMetaType::fromType<QQmlListProperty<T> >(), + qobject_interface_iid<T *>(), + + uri, + QTypeRevision::fromVersion(versionMajor, 0) }; return QQmlPrivate::qmlregister(QQmlPrivate::InterfaceRegistration, &qmlInterface); @@ -511,17 +538,15 @@ template<typename T> int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, QQmlCustomParser *parser) { - QML_GETTYPENAMES - QQmlPrivate::RegisterType type = { 0, - qRegisterNormalizedMetaType<T *>(pointerName.constData()), - qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), + QMetaType::fromType<T *>(), + QMetaType::fromType<QQmlListProperty<T> >(), sizeof(T), QQmlPrivate::createInto<T>, QString(), - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -533,7 +558,7 @@ int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor, nullptr, nullptr, parser, - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -543,17 +568,15 @@ template<typename T, int metaObjectRevision> int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, QQmlCustomParser *parser) { - QML_GETTYPENAMES - QQmlPrivate::RegisterType type = { 1, - qRegisterNormalizedMetaType<T *>(pointerName.constData()), - qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), + QMetaType::fromType<T *>(), + QMetaType::fromType<QQmlListProperty<T> >(), sizeof(T), QQmlPrivate::createInto<T>, QString(), - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -565,7 +588,7 @@ int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor, nullptr, nullptr, parser, - metaObjectRevision + QTypeRevision::fromMinorVersion(metaObjectRevision) }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -575,8 +598,6 @@ template<typename T, typename E> int qmlRegisterCustomExtendedType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, QQmlCustomParser *parser) { - QML_GETTYPENAMES - QQmlAttachedPropertiesFunc attached = QQmlPrivate::attachedPropertiesFunc<E>(); const QMetaObject * attachedMetaObject = QQmlPrivate::attachedPropertiesMetaObject<E>(); if (!attached) { @@ -587,12 +608,12 @@ int qmlRegisterCustomExtendedType(const char *uri, int versionMajor, int version QQmlPrivate::RegisterType type = { 0, - qRegisterNormalizedMetaType<T *>(pointerName.constData()), - qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), + QMetaType::fromType<T *>(), + QMetaType::fromType<QQmlListProperty<T> >(), sizeof(T), QQmlPrivate::createInto<T>, QString(), - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, attached, attachedMetaObject, @@ -604,7 +625,7 @@ int qmlRegisterCustomExtendedType(const char *uri, int versionMajor, int version QQmlPrivate::createParent<E>, &E::staticMetaObject, parser, - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -667,9 +688,9 @@ inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versi QQmlPrivate::RegisterSingletonType api = { 0, - uri, versionMajor, versionMinor, typeName, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), typeName, - callback, nullptr, nullptr, 0, 0, {} + callback, nullptr, nullptr, QMetaType(), QTypeRevision::zero(), {} }; return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api); @@ -680,14 +701,13 @@ template <typename T> inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName, QObject *(*callback)(QQmlEngine *, QJSEngine *)) { - QML_GETTYPENAMES - QQmlPrivate::RegisterSingletonType api = { QmlCurrentSingletonTypeRegistrationVersion, - uri, versionMajor, versionMinor, typeName, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), typeName, + - nullptr, nullptr, &T::staticMetaObject, qRegisterNormalizedMetaType<T *>(pointerName.constData()), 0, callback + nullptr, nullptr, &T::staticMetaObject, QMetaType::fromType<T *>(), QTypeRevision::zero(), callback }; return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api); @@ -698,15 +718,13 @@ template <typename T, typename F, typename std::enable_if<std::is_convertible<F, inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName, F&& callback) { - - QML_GETTYPENAMES - QQmlPrivate::RegisterSingletonType api = { QmlCurrentSingletonTypeRegistrationVersion, - uri, versionMajor, versionMinor, typeName, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), typeName, - nullptr, nullptr, &T::staticMetaObject, qRegisterNormalizedMetaType<T *>(pointerName.constData()), 0, callback + + nullptr, nullptr, &T::staticMetaObject, QMetaType::fromType<T *>(), QTypeRevision::zero(), callback }; return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api); @@ -732,8 +750,7 @@ inline int qmlRegisterSingletonType(const QUrl &url, const char *uri, int versio QQmlPrivate::RegisterCompositeSingletonType type = { url, uri, - versionMajor, - versionMinor, + QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName }; @@ -751,19 +768,18 @@ inline int qmlRegisterType(const QUrl &url, const char *uri, int versionMajor, i QQmlPrivate::RegisterCompositeType type = { url, uri, - versionMajor, - versionMinor, + QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName }; return QQmlPrivate::qmlregister(QQmlPrivate::CompositeRegistration, &type); } -template<class T, class Resolved, class Extended, bool Singleton> +template<class T, class Resolved, class Extended, bool Singleton, bool Interface> struct QmlTypeAndRevisionsRegistration; template<class T, class Resolved, class Extended> -struct QmlTypeAndRevisionsRegistration<T, Resolved, Extended, false> { +struct QmlTypeAndRevisionsRegistration<T, Resolved, Extended, false, false> { static void registerTypeAndRevisions(const char *uri, int versionMajor) { QQmlPrivate::qmlRegisterTypeAndRevisions<Resolved, Extended>( @@ -772,7 +788,7 @@ struct QmlTypeAndRevisionsRegistration<T, Resolved, Extended, false> { }; template<class T, class Resolved> -struct QmlTypeAndRevisionsRegistration<T, Resolved, void, true> { +struct QmlTypeAndRevisionsRegistration<T, Resolved, void, true, false> { static void registerTypeAndRevisions(const char *uri, int versionMajor) { QQmlPrivate::qmlRegisterSingletonAndRevisions<Resolved>( @@ -780,6 +796,14 @@ struct QmlTypeAndRevisionsRegistration<T, Resolved, void, true> { } }; +template<class T, class Resolved> +struct QmlTypeAndRevisionsRegistration<T, Resolved, void, false, true> { + static void registerTypeAndRevisions(const char *uri, int versionMajor) + { + qmlRegisterInterface<Resolved>(uri, versionMajor); + } +}; + template<typename T = void, typename... Args> void qmlRegisterTypesAndRevisions(const char *uri, int versionMajor); @@ -789,7 +813,8 @@ void qmlRegisterTypesAndRevisions(const char *uri, int versionMajor) QmlTypeAndRevisionsRegistration< T, typename QQmlPrivate::QmlResolved<T>::Type, typename QQmlPrivate::QmlExtended<T>::Type, - QQmlPrivate::QmlSingleton<T>::Value> + QQmlPrivate::QmlSingleton<T>::Value, + QQmlPrivate::QmlInterface<T>::Value> ::registerTypeAndRevisions(uri, versionMajor); qmlRegisterTypesAndRevisions<Args...>(uri, versionMajor); } @@ -797,6 +822,38 @@ void qmlRegisterTypesAndRevisions(const char *uri, int versionMajor) template<> inline void qmlRegisterTypesAndRevisions<>(const char *, int) {} +inline void qmlRegisterNamespaceAndRevisions(const QMetaObject *metaObject, + const char *uri, int versionMajor) +{ + QQmlPrivate::RegisterTypeAndRevisions type = { + 0, + QMetaType(), + QMetaType(), + 0, + nullptr, + + uri, + QTypeRevision::fromMajorVersion(versionMajor), + + metaObject, + metaObject, + + nullptr, + nullptr, + + -1, + -1, + -1, + + nullptr, + nullptr, + + &qmlCreateCustomParser<void> + }; + + qmlregister(QQmlPrivate::TypeAndRevisionsRegistration, &type); +} + int Q_QML_EXPORT qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName); QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index e14b00af22..b9566d5862 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -43,6 +43,10 @@ #include "qqmlcontext.h" #include "qqmlinfo.h" #include "qqmldata_p.h" + +#include <private/qqmldebugserviceinterfaces_p.h> +#include <private/qqmldebugconnector_p.h> + #include <private/qqmlprofiler_p.h> #include <private/qqmlexpression_p.h> #include <private/qqmlscriptstring_p.h> @@ -392,6 +396,11 @@ QQmlBinding *QQmlBinding::createTranslationBinding(const QQmlRefPointer<QV4::Exe b->QQmlJavaScriptExpression::setContext(ctxt); b->setScopeObject(obj); + if (QQmlDebugTranslationService *service + = QQmlDebugConnector::service<QQmlDebugTranslationService>()) { + service->foundTranslationBinding(b, obj, ctxt); + } + return b; } diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 279998b5de..ede2816d5f 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -50,6 +50,7 @@ #include "qqmlincubator.h" #include "qqmlincubator_p.h" #include <private/qqmljavascriptexpression_p.h> +#include <private/qqmlsourcecoordinate_p.h> #include <private/qv4functionobject_p.h> #include <private/qv4script_p.h> @@ -1424,8 +1425,8 @@ QQmlError QQmlComponentPrivate::unsetRequiredPropertyToQQmlError(const RequiredP } error.setDescription(description); error.setUrl(unsetRequiredProperty.fileUrl); - error.setLine(unsetRequiredProperty.location.line); - error.setColumn(unsetRequiredProperty.location.column); + error.setLine(qmlConvertSourceCoordinate<quint32, int>(unsetRequiredProperty.location.line)); + error.setColumn(qmlConvertSourceCoordinate<quint32, int>(unsetRequiredProperty.location.column)); return error; } diff --git a/src/qml/qml/qqmlcomponent.h b/src/qml/qml/qqmlcomponent.h index cb5d5a787c..9a4ea711f3 100644 --- a/src/qml/qml/qqmlcomponent.h +++ b/src/qml/qml/qqmlcomponent.h @@ -71,6 +71,7 @@ class Q_QML_EXPORT QQmlComponent : public QObject Q_PROPERTY(Status status READ status NOTIFY statusChanged) Q_PROPERTY(QUrl url READ url CONSTANT) QML_NAMED_ELEMENT(Component) + QML_ADDED_IN_VERSION(2, 0) QML_ATTACHED(QQmlComponentAttached) Q_CLASSINFO("QML.Builtin", "QML") diff --git a/src/qml/qml/qqmlcomponentattached_p.h b/src/qml/qml/qqmlcomponentattached_p.h index 8ecd9da17d..eb6d35652b 100644 --- a/src/qml/qml/qqmlcomponentattached_p.h +++ b/src/qml/qml/qqmlcomponentattached_p.h @@ -66,6 +66,7 @@ class Q_QML_PRIVATE_EXPORT QQmlComponentAttached : public QObject // when registering QQmlComponent, but we cannot #include it from qqmlcomponent.h. Therefore we // force an anonymous type registration here. QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQmlComponentAttached(QObject *parent = nullptr); ~QQmlComponentAttached(); diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp index 87f7fffe41..b0df4f26dc 100644 --- a/src/qml/qml/qqmlcustomparser.cpp +++ b/src/qml/qml/qqmlcustomparser.cpp @@ -40,6 +40,7 @@ #include "qqmlcustomparser_p.h" #include <private/qv4compileddata_p.h> +#include <private/qqmlsourcecoordinate_p.h> #include <QtCore/qdebug.h> @@ -100,10 +101,10 @@ void QQmlCustomParser::clearErrors() */ void QQmlCustomParser::error(const QV4::CompiledData::Location &location, const QString &description) { - QQmlJS::DiagnosticMessage error; - error.line = location.line; - error.column = location.column; - error.message = description; + QQmlError error; + error.setLine(qmlConvertSourceCoordinate<quint32, int>(location.line)); + error.setColumn(qmlConvertSourceCoordinate<quint32, int>(location.column)); + error.setDescription(description); exceptions << error; } @@ -125,8 +126,13 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const // * <TypeName>.<EnumValue> // * <TypeName>.<ScopedEnumName>.<EnumValue> - int dot = script.indexOf('.'); - if (dot == -1 || dot == script.length()-1) + auto nextDot = [&](int dot) { + const int nextDot = script.indexOf('.', dot + 1); + return (nextDot == script.length() - 1) ? -1 : nextDot; + }; + + int dot = nextDot(-1); + if (dot == -1) return -1; QString scope = QString::fromUtf8(script.left(dot)); @@ -137,18 +143,32 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const QQmlType type; if (imports.isT1()) { - imports.asT1()->resolveType(scope, &type, nullptr, nullptr, nullptr); + QQmlImportNamespace *ns = nullptr; + if (!imports.asT1()->resolveType(scope, &type, nullptr, &ns)) + return -1; + if (!type.isValid() && ns != nullptr) { + dot = nextDot(dot); + if (dot == -1 || !imports.asT1()->resolveType(QString::fromUtf8(script.left(dot)), + &type, nullptr, nullptr)) { + return -1; + } + } } else { QQmlTypeNameCache::Result result = imports.asT2()->query(scope); - if (result.isValid()) + if (result.isValid()) { type = result.type; + } else if (result.importNamespace) { + dot = nextDot(dot); + if (dot != -1) + type = imports.asT2()->query(QString::fromUtf8(script.left(dot))).type; + } } if (!type.isValid()) return -1; - int dot2 = script.indexOf('.', dot+1); - const bool dot2Valid = dot2 != -1 && dot2 != script.length()-1; + const int dot2 = nextDot(dot); + const bool dot2Valid = (dot2 != -1); QByteArray enumValue = script.mid(dot2Valid ? dot2 + 1 : dot + 1); QByteArray scopedEnumName = (dot2Valid ? script.mid(dot + 1, dot2 - dot - 1) : QByteArray()); if (!scopedEnumName.isEmpty()) diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h index df8cbc9072..4eb709228e 100644 --- a/src/qml/qml/qqmlcustomparser_p.h +++ b/src/qml/qml/qqmlcustomparser_p.h @@ -83,7 +83,7 @@ public: virtual void verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &) = 0; virtual void applyBindings(QObject *, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &, const QList<const QV4::CompiledData::Binding *> &) = 0; - QVector<QQmlJS::DiagnosticMessage> errors() const { return exceptions; } + QVector<QQmlError> errors() const { return exceptions; } protected: void error(const QV4::CompiledData::Binding *binding, const QString& description) @@ -97,7 +97,7 @@ protected: const QMetaObject *resolveType(const QString&) const; private: - QVector<QQmlJS::DiagnosticMessage> exceptions; + QVector<QQmlError> exceptions; QQmlEnginePrivate *engine; const QQmlPropertyValidator *validator; Flags m_flags; @@ -107,11 +107,6 @@ private: }; Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlCustomParser::Flags) -#if 0 -#define QML_REGISTER_CUSTOM_TYPE(URI, VERSION_MAJ, VERSION_MIN, NAME, TYPE, CUSTOMTYPE) \ - qmlRegisterCustomType<TYPE>(#URI, VERSION_MAJ, VERSION_MIN, #NAME, #TYPE, new CUSTOMTYPE) -#endif - QT_END_NAMESPACE #endif diff --git a/src/qml/qml/qqmldatablob.cpp b/src/qml/qml/qqmldatablob.cpp index 1ab6002f0a..c29f207ae3 100644 --- a/src/qml/qml/qqmldatablob.cpp +++ b/src/qml/qml/qqmldatablob.cpp @@ -42,6 +42,7 @@ #include <private/qqmlprofiler_p.h> #include <private/qqmltypeloader_p.h> #include <private/qqmltypeloaderthread_p.h> +#include <private/qqmlsourcecoordinate_p.h> #include <QtQml/qqmlengine.h> @@ -289,7 +290,18 @@ void QQmlDataBlob::setError(const QList<QQmlError> &errors) Q_ASSERT(status() != Error); Q_ASSERT(m_errors.isEmpty()); - m_errors = errors; // Must be set before the m_data fence + // m_errors must be set before the m_data fence + m_errors.reserve(errors.count()); + for (const QQmlError &error : errors) { + if (error.url().isEmpty()) { + QQmlError mutableError = error; + mutableError.setUrl(url()); + m_errors.append(mutableError); + } else { + m_errors.append(error); + } + } + m_data.setStatus(Error); if (dumpErrors()) { @@ -306,28 +318,13 @@ void QQmlDataBlob::setError(const QList<QQmlError> &errors) void QQmlDataBlob::setError(const QQmlJS::DiagnosticMessage &error) { QQmlError e; - e.setColumn(error.column); - e.setLine(error.line); + e.setColumn(qmlConvertSourceCoordinate<quint32, int>(error.loc.startColumn)); + e.setLine(qmlConvertSourceCoordinate<quint32, int>(error.loc.startLine)); e.setDescription(error.message); e.setUrl(url()); setError(e); } -void QQmlDataBlob::setError(const QVector<QQmlJS::DiagnosticMessage> &errors) -{ - QList<QQmlError> finalErrors; - finalErrors.reserve(errors.count()); - for (const auto &error : errors) { - QQmlError e; - e.setColumn(error.column); - e.setLine(error.line); - e.setDescription(error.message); - e.setUrl(url()); - finalErrors << e; - } - setError(finalErrors); -} - void QQmlDataBlob::setError(const QString &description) { QQmlError e; diff --git a/src/qml/qml/qqmldatablob_p.h b/src/qml/qml/qqmldatablob_p.h index 0450e94c02..17db8f2dfe 100644 --- a/src/qml/qml/qqmldatablob_p.h +++ b/src/qml/qml/qqmldatablob_p.h @@ -132,7 +132,6 @@ protected: void setError(const QQmlError &); void setError(const QList<QQmlError> &errors); void setError(const QQmlJS::DiagnosticMessage &error); - void setError(const QVector<QQmlJS::DiagnosticMessage> &errors); void setError(const QString &description); void addDependency(QQmlDataBlob *); diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 5d7dddd153..725d2e7c7a 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -57,11 +57,11 @@ #include "qqmlnotifier_p.h" #include "qqmlincubator.h" #include "qqmlabstracturlinterceptor.h" +#include "qqmlsourcecoordinate_p.h" #include <private/qqmldirparser_p.h> #include <private/qqmlboundsignal_p.h> #include <private/qqmljsdiagnosticmessage_p.h> #include <QtCore/qstandardpaths.h> -#include <QtCore/qsettings.h> #include <QtCore/qmetaobject.h> #include <QDebug> #include <QtCore/qcoreapplication.h> @@ -112,13 +112,13 @@ int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject, QQmlPrivate::RegisterType type = { 0, - 0, - 0, + QMetaType(), + QMetaType(), 0, nullptr, reason, - uri, versionMajor, versionMinor, qmlName, &staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &staticMetaObject, QQmlAttachedPropertiesFunc(), nullptr, @@ -130,7 +130,7 @@ int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject, nullptr, nullptr, nullptr, - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -654,11 +654,7 @@ QQmlEnginePrivate::~QQmlEnginePrivate() for (auto iter = m_compositeTypes.cbegin(), end = m_compositeTypes.cend(); iter != end; ++iter) { iter.value()->isRegisteredWithEngine = false; - - // since unregisterInternalCompositeType() will not be called in this - // case, we have to clean up the type registration manually - QMetaType::unregisterType(iter.value()->metaTypeId); - QMetaType::unregisterType(iter.value()->listMetaTypeId); + QQmlMetaType::unregisterInternalCompositeType({iter.value()->metaTypeId, iter.value()->listMetaTypeId}); } #if QT_CONFIG(qml_debug) delete profiler; @@ -1335,12 +1331,16 @@ void QQmlEngine::setOutputWarningsToStandardError(bool enabled) \code class MySingleton : public QObject { \Q_OBJECT + + // Register as default constructed singleton. + QML_ELEMENT + QML_SINGLETON + static int typeId; // ... }; - // Register with QObject* callback - MySingleton::typeId = qmlRegisterSingletonType<MySingleton>(...); + MySingleton::typeId = qmlTypeId(...); // Retrieve as QObject* QQmlEngine engine; @@ -1357,11 +1357,10 @@ void QQmlEngine::setOutputWarningsToStandardError(bool enabled) QJSValue instance = engine.singletonInstance<QJSValue>(typeId); \endcode - It is recommended to store the QML type id during registration, e.g. as a static member - in the singleton class. Otherwise, a costly lookup via qmlTypeId() has to be performed - at run-time. + It is recommended to store the QML type id, e.g. as a static member in the + singleton class. The lookup via qmlTypeId() is costly. - \sa qmlRegisterSingletonType(), qmlTypeId() + \sa QML_SINGLETON, qmlRegisterSingletonType(), qmlTypeId() \since 5.12 */ template<> @@ -2096,15 +2095,15 @@ QList<QQmlError> QQmlEnginePrivate::qmlErrorFromDiagnostics( QList<QQmlError> errors; for (const QQmlJS::DiagnosticMessage &m : diagnosticMessages) { if (m.isWarning()) { - qWarning("%s:%d : %s", qPrintable(fileName), m.line, qPrintable(m.message)); + qWarning("%s:%d : %s", qPrintable(fileName), m.loc.startLine, qPrintable(m.message)); continue; } QQmlError error; error.setUrl(QUrl(fileName)); error.setDescription(m.message); - error.setLine(m.line); - error.setColumn(m.column); + error.setLine(qmlConvertSourceCoordinate<quint32, int>(m.loc.startLine)); + error.setColumn(qmlConvertSourceCoordinate<quint32, int>(m.loc.startColumn)); errors << error; } return errors; @@ -2244,7 +2243,7 @@ void QQmlEngine::setPluginPathList(const QStringList &paths) bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors) { Q_D(QQmlEngine); - return d->importDatabase.importDynamicPlugin(filePath, uri, QString(), -1, errors); + return d->importDatabase.importDynamicPlugin(filePath, uri, QString(), QTypeRevision(), errors); } #endif @@ -2301,17 +2300,6 @@ QString QQmlEngine::offlineStorageDatabaseFilePath(const QString &databaseName) return d->offlineStorageDatabaseDirectory() + QLatin1String(md5.result().toHex()); } -// #### Qt 6: Remove this function, it exists only for binary compatibility. -/*! - * \internal - */ -bool QQmlEngine::addNamedBundle(const QString &name, const QString &fileName) -{ - Q_UNUSED(name) - Q_UNUSED(fileName) - return false; -} - QString QQmlEnginePrivate::offlineStorageDatabaseDirectory() const { Q_Q(const QQmlEngine); @@ -2356,67 +2344,100 @@ int QQmlEnginePrivate::listType(int t) const static QQmlPropertyCache *propertyCacheForPotentialInlineComponentType(int t, const QHash<int, QV4::ExecutableCompilationUnit *>::const_iterator &iter) { - if (t != (*iter)->metaTypeId) { + if (t != (*iter)->metaTypeId.id()) { // this is an inline component, and what we have in the iterator is currently the parent compilation unit for (auto &&icDatum: (*iter)->inlineComponentData) - if (icDatum.typeIds.id == t) + if (icDatum.typeIds.id.id() == t) return (*iter)->propertyCaches.at(icDatum.objectIndex); } return (*iter)->rootPropertyCache().data(); } +/*! + * \internal + * + * Look up by type's baseMetaObject. + */ QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const { - Locker locker(this); - auto iter = m_compositeTypes.constFind(t); - if (iter != m_compositeTypes.cend()) { - return propertyCacheForPotentialInlineComponentType(t, iter); - } else { - QQmlType type = QQmlMetaType::qmlType(t); - return QQmlMetaObject(type.baseMetaObject()); - } + if (QQmlPropertyCache *composite = findPropertyCacheInCompositeTypes(t)) + return QQmlMetaObject(composite); + + QQmlType type = QQmlMetaType::qmlType(t); + return QQmlMetaObject(type.baseMetaObject()); } +/*! + * \internal + * + * Look up by type's metaObject. + */ QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const { - Locker locker(this); - auto iter = m_compositeTypes.constFind(t); - if (iter != m_compositeTypes.cend()) { - return propertyCacheForPotentialInlineComponentType(t, iter); - } else { - QQmlType type = QQmlMetaType::qmlType(t); - return QQmlMetaObject(type.metaObject()); - } + if (QQmlPropertyCache *composite = findPropertyCacheInCompositeTypes(t)) + return QQmlMetaObject(composite); + + QQmlType type = QQmlMetaType::qmlType(t); + return QQmlMetaObject(type.metaObject()); } +/*! + * \internal + * + * Look up by type's metaObject and version. + */ QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t) { - Locker locker(this); - auto iter = m_compositeTypes.constFind(t); - if (iter != m_compositeTypes.cend()) { - return propertyCacheForPotentialInlineComponentType(t, iter); - } else { - QQmlType type = QQmlMetaType::qmlType(t); - locker.unlock(); - return type.isValid() ? cache(type.metaObject()) : nullptr; - } + if (QQmlPropertyCache *composite = findPropertyCacheInCompositeTypes(t)) + return composite; + + QQmlType type = QQmlMetaType::qmlType(t); + return type.isValid() ? cache(type.metaObject(), type.version()) : nullptr; +} + +/*! + * \internal + * + * Look up by type's baseMetaObject and unspecified/any version. + * TODO: Is this correct? Passing a plain QTypeRevision() rather than QTypeRevision::zero() or + * the actual type's version seems strange. The behavior has been in place for a while. + */ +QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t) +{ + if (QQmlPropertyCache *composite = findPropertyCacheInCompositeTypes(t)) + return composite; + + QQmlType type = QQmlMetaType::qmlType(t); + return type.isValid() ? cache(type.baseMetaObject(), QTypeRevision()) : nullptr; +} + +/*! + * \internal + * + * Look up by QQmlType and version. We only fall back to lookup by metaobject if the type + * has no revisiononed attributes here. Unspecified versions are interpreted as "any". + */ +QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t, QTypeRevision version) +{ + if (QQmlPropertyCache *composite = findPropertyCacheInCompositeTypes(t)) + return composite; + + QQmlType type = QQmlMetaType::qmlType(t); + if (!type.isValid()) + return nullptr; + + return type.containsRevisionedAttributes() + ? QQmlMetaType::propertyCache(type, version) + : cache(type.metaObject(), version); } -QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t, int minorVersion) +QQmlPropertyCache *QQmlEnginePrivate::findPropertyCacheInCompositeTypes(int t) const { Locker locker(this); auto iter = m_compositeTypes.constFind(t); - if (iter != m_compositeTypes.cend()) { - return propertyCacheForPotentialInlineComponentType(t, iter); - } else { - QQmlType type = QQmlMetaType::qmlType(t); - locker.unlock(); - - if (minorVersion >= 0) - return type.isValid() ? cache(type, minorVersion) : nullptr; - else - return type.isValid() ? cache(type.baseMetaObject()) : nullptr; - } + return (iter == m_compositeTypes.constEnd()) + ? nullptr + : propertyCacheForPotentialInlineComponentType(t, iter); } void QQmlEnginePrivate::registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit) @@ -2426,10 +2447,9 @@ void QQmlEnginePrivate::registerInternalCompositeType(QV4::ExecutableCompilation Locker locker(this); // The QQmlCompiledData is not referenced here, but it is removed from this // hash in the QQmlCompiledData destructor - m_compositeTypes.insert(compilationUnit->metaTypeId, compilationUnit); - for (auto &&data: compilationUnit->inlineComponentData) { - m_compositeTypes.insert(data.typeIds.id, compilationUnit); - } + m_compositeTypes.insert(compilationUnit->metaTypeId.id(), compilationUnit); + for (auto &&data: compilationUnit->inlineComponentData) + m_compositeTypes.insert(data.typeIds.id.id(), compilationUnit); } void QQmlEnginePrivate::unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit) @@ -2437,9 +2457,9 @@ void QQmlEnginePrivate::unregisterInternalCompositeType(QV4::ExecutableCompilati compilationUnit->isRegisteredWithEngine = false; Locker locker(this); - m_compositeTypes.remove(compilationUnit->metaTypeId); + m_compositeTypes.remove(compilationUnit->metaTypeId.id()); for (auto&& icDatum: compilationUnit->inlineComponentData) - m_compositeTypes.remove(icDatum.typeIds.id); + m_compositeTypes.remove(icDatum.typeIds.id.id()); } QV4::ExecutableCompilationUnit *QQmlEnginePrivate::obtainExecutableCompilationUnit(int typeId) diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h index 31fe3a1849..a686d8a1d9 100644 --- a/src/qml/qml/qqmlengine.h +++ b/src/qml/qml/qqmlengine.h @@ -112,7 +112,9 @@ public: void setPluginPathList(const QStringList &paths); void addPluginPath(const QString& dir); - bool addNamedBundle(const QString &name, const QString &fileName); +#if QT_DEPRECATED_SINCE(6, 0) + QT_DEPRECATED bool addNamedBundle(const QString &, const QString &) { return false; } +#endif #if QT_CONFIG(library) bool importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors); diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h index 33fa800ff4..424335b61a 100644 --- a/src/qml/qml/qqmlengine_p.h +++ b/src/qml/qml/qqmlengine_p.h @@ -105,6 +105,7 @@ struct QObjectForeign { Q_GADGET QML_FOREIGN(QObject) QML_NAMED_ELEMENT(QtObject) + QML_ADDED_IN_VERSION(2, 0) Q_CLASSINFO("QML.Root", "QML") }; @@ -216,7 +217,7 @@ public: QString offlineStorageDatabaseDirectory() const; // These methods may be called from the loader thread - inline QQmlPropertyCache *cache(const QQmlType &, int); + inline QQmlPropertyCache *cache(const QQmlType &, QTypeRevision version); using QJSEnginePrivate::cache; // These methods may be called from the loader thread @@ -228,7 +229,8 @@ public: QQmlMetaObject rawMetaObjectForType(int) const; QQmlMetaObject metaObjectForType(int) const; QQmlPropertyCache *propertyCacheForType(int); - QQmlPropertyCache *rawPropertyCacheForType(int, int minorVersion = -1); + QQmlPropertyCache *rawPropertyCacheForType(int); + QQmlPropertyCache *rawPropertyCacheForType(int, QTypeRevision version); void registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit); void unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit); QV4::ExecutableCompilationUnit *obtainExecutableCompilationUnit(int typeId); @@ -268,8 +270,24 @@ public: mutable QMutex networkAccessManagerMutex; + QQmlGadgetPtrWrapper *valueTypeInstance(int typeIndex) + { + auto it = cachedValueTypeInstances.find(typeIndex); + if (it != cachedValueTypeInstances.end()) + return *it; + + if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(typeIndex)) { + QQmlGadgetPtrWrapper *instance = new QQmlGadgetPtrWrapper(valueType, q_func()); + cachedValueTypeInstances.insert(typeIndex, instance); + return instance; + } + + return nullptr; + } + private: QHash<QQmlType, QJSValue> singletonInstances; + QHash<int, QQmlGadgetPtrWrapper *> cachedValueTypeInstances; // These members must be protected by a QQmlEnginePrivate::Locker as they are required by // the threaded loader. Only access them through their respective accessor methods. @@ -282,6 +300,7 @@ private: void doDeleteInEngineThread(); void cleanupScarceResources(); + QQmlPropertyCache *findPropertyCacheInCompositeTypes(int t) const; }; /* @@ -380,15 +399,15 @@ Returns a QQmlPropertyCache for \a type with \a minorVersion. The returned cache is not referenced, so if it is to be stored, call addref(). */ -QQmlPropertyCache *QQmlEnginePrivate::cache(const QQmlType &type, int minorVersion) +QQmlPropertyCache *QQmlEnginePrivate::cache(const QQmlType &type, QTypeRevision version) { Q_ASSERT(type.isValid()); - if (minorVersion == -1 || !type.containsRevisionedAttributes()) - return cache(type.metaObject(), minorVersion); + if (!version.hasMinorVersion() || !type.containsRevisionedAttributes()) + return cache(type.metaObject(), version); Locker locker(this); - return QQmlMetaType::propertyCache(type, minorVersion); + return QQmlMetaType::propertyCache(type, version); } QV4::ExecutionEngine *QQmlEnginePrivate::getV4Engine(QQmlEngine *e) diff --git a/src/qml/qml/qqmlerror.cpp b/src/qml/qml/qqmlerror.cpp index 0b94ed3b49..da585d2126 100644 --- a/src/qml/qml/qqmlerror.cpp +++ b/src/qml/qml/qqmlerror.cpp @@ -77,12 +77,15 @@ QT_BEGIN_NAMESPACE \sa QQuickView::errors(), QQmlComponent::errors() */ -class QQmlErrorPrivate : public QQmlJS::DiagnosticMessage +class QQmlErrorPrivate { public: - QQmlErrorPrivate() { type = QtWarningMsg; } QUrl url; QPointer<QObject> object; + QString message; + QtMsgType type = QtWarningMsg; + int line = -1; + int column = -1; }; /*! @@ -185,7 +188,7 @@ void QQmlError::setDescription(const QString &description) int QQmlError::line() const { if (d) - return qmlConvertSourceCoordinate<quint32, int>(d->line); + return d->line; return -1; } @@ -196,7 +199,7 @@ void QQmlError::setLine(int line) { if (!d) d = new QQmlErrorPrivate; - d->line = qmlConvertSourceCoordinate<int, quint32>(line); + d->line = line; } /*! @@ -205,7 +208,7 @@ void QQmlError::setLine(int line) int QQmlError::column() const { if (d) - return qmlConvertSourceCoordinate<quint32, int>(d->column); + return d->column; return -1; } @@ -216,7 +219,7 @@ void QQmlError::setColumn(int column) { if (!d) d = new QQmlErrorPrivate; - d->column = qmlConvertSourceCoordinate<int, quint32>(column); + d->column = column; } /*! diff --git a/src/qml/qml/qqmlextensionplugin.cpp b/src/qml/qml/qqmlextensionplugin.cpp index 7a62c967e7..f779199b74 100644 --- a/src/qml/qml/qqmlextensionplugin.cpp +++ b/src/qml/qml/qqmlextensionplugin.cpp @@ -117,6 +117,16 @@ QUrl QQmlExtensionPlugin::baseUrl() const } /*! + \since 6.0 + + Override this method to unregister types manually registered in registerTypes. +*/ +void QQmlExtensionPlugin::unregisterTypes() +{ + +} + +/*! \internal */ diff --git a/src/qml/qml/qqmlextensionplugin.h b/src/qml/qml/qqmlextensionplugin.h index ef7ff422cd..78371106bd 100644 --- a/src/qml/qml/qqmlextensionplugin.h +++ b/src/qml/qml/qqmlextensionplugin.h @@ -64,6 +64,7 @@ public: QUrl baseUrl() const; void registerTypes(const char *uri) override = 0; + virtual void unregisterTypes(); void initializeEngine(QQmlEngine *engine, const char *uri) override; private: diff --git a/src/qml/qml/qqmlfile.cpp b/src/qml/qml/qqmlfile.cpp index ee54359d0f..465a342129 100644 --- a/src/qml/qml/qqmlfile.cpp +++ b/src/qml/qml/qqmlfile.cpp @@ -187,7 +187,7 @@ void QQmlFileNetworkReply::networkFinished() } } - if (m_reply->networkError()) { + if (m_reply->error()) { m_p->errorString = m_reply->errorString(); m_p->error = QQmlFilePrivate::Network; } else { diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 80eafdf146..47f7b40938 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -161,9 +161,17 @@ void qmlClearEnginePlugins() #if QT_CONFIG(library) for (auto &plugin : qAsConst(*plugins)) { QPluginLoader* loader = plugin.loader; - if (loader && !loader->unload()) - qWarning("Unloading %s failed: %s", qPrintable(plugin.uri), qPrintable(loader->errorString())); - delete loader; + if (loader) { + auto extensionPlugin = qobject_cast<QQmlExtensionPlugin *>(loader->instance()); + if (extensionPlugin) { + extensionPlugin->unregisterTypes(); + } +#ifndef Q_OS_MACOS + if (!loader->unload()) + qWarning("Unloading %s failed: %s", qPrintable(plugin.uri), qPrintable(loader->errorString())); + delete loader; +#endif + } } #endif plugins->clear(); @@ -213,12 +221,12 @@ public: QQmlImportNamespace *importNamespace(const QString &prefix) const; bool addLibraryImport(const QString& uri, const QString &prefix, - int vmaj, int vmin, const QString &qmldirIdentifier, const QString &qmldirUrl, bool incomplete, + QTypeRevision version, const QString &qmldirIdentifier, + const QString &qmldirUrl, bool incomplete, QQmlImportDatabase *database, QList<QQmlError> *errors); - bool addFileImport(const QString &uri, const QString &prefix, - int vmaj, int vmin, + bool addFileImport(const QString &uri, const QString &prefix, QTypeRevision version, bool isImplicitImport, bool incomplete, QQmlImportDatabase *database, QList<QQmlError> *errors); @@ -227,7 +235,7 @@ public: QQmlImportDatabase *database, QList<QQmlError> *errors); - bool resolveType(const QHashedStringRef &type, int *vmajor, int *vminor, + bool resolveType(const QHashedStringRef &type, QTypeRevision *version_return, QQmlType *type_return, QList<QQmlError> *errors, QQmlType::RegistrationType registrationType, bool *typeRecursionDetected = nullptr); @@ -247,14 +255,13 @@ public: QQmlTypeLoader *typeLoader; static QQmlImports::LocalQmldirResult locateLocalQmldir( - const QString &uri, int vmaj, int vmin, QQmlImportDatabase *database, + const QString &uri, QTypeRevision version, QQmlImportDatabase *database, QString *outQmldirFilePath, QString *outUrl); - static bool validateQmldirVersion(const QQmlTypeLoaderQmldirContent &qmldir, const QString &uri, int vmaj, int vmin, - QList<QQmlError> *errors); + static bool validateQmldirVersion(const QQmlTypeLoaderQmldirContent &qmldir, const QString &uri, + QTypeRevision version, QList<QQmlError> *errors); - bool importExtension(const QString &absoluteFilePath, const QString &uri, - int vmaj, int vmin, + bool importExtension(const QString &absoluteFilePath, const QString &uri, QTypeRevision version, QQmlImportDatabase *database, const QQmlTypeLoaderQmldirContent &qmldir, QList<QQmlError> *errors); @@ -264,10 +271,10 @@ public: QString resolvedUri(const QString &dir_arg, QQmlImportDatabase *database); - QQmlImportInstance *addImportToNamespace(QQmlImportNamespace *nameSpace, - const QString &uri, const QString &url, - int vmaj, int vmin, QV4::CompiledData::Import::ImportType type, - QList<QQmlError> *errors, bool lowPrecedence = false); + QQmlImportInstance *addImportToNamespace(QQmlImportNamespace *nameSpace, const QString &uri, + const QString &url, QTypeRevision version, + QV4::CompiledData::Import::ImportType type, + QList<QQmlError> *errors, bool lowPrecedence = false); bool populatePluginPairVector(QVector<StaticPluginPair> &result, const QString &uri, const QStringList &versionUris, const QString &qmldirPath, QList<QQmlError> *errors); @@ -344,9 +351,9 @@ void QQmlImports::populateCache(QQmlTypeNameCache *cache) const for (int ii = set.imports.count() - 1; ii >= 0; --ii) { const QQmlImportInstance *import = set.imports.at(ii); - QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->majversion); + QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->version); if (module) { - cache->m_anonymousImports.append(QQmlTypeModuleVersion(module, import->minversion)); + cache->m_anonymousImports.append(QQmlTypeModuleVersion(module, import->version)); } } @@ -360,10 +367,10 @@ void QQmlImports::populateCache(QQmlTypeNameCache *cache) const for (int ii = set.imports.count() - 1; ii >= 0; --ii) { const QQmlImportInstance *import = set.imports.at(ii); - QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->majversion); + QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->version); if (module) { QQmlImportRef &typeimport = cache->m_namedImports[set.prefix]; - typeimport.modules.append(QQmlTypeModuleVersion(module, import->minversion)); + typeimport.modules.append(QQmlTypeModuleVersion(module, import->version)); } } } @@ -395,36 +402,35 @@ void findCompositeSingletons(const QQmlImportNamespace &set, QList<QQmlImports:: const QQmlDirComponents &components = import->qmlDirComponents; - const int importMajorVersion = import->majversion; - const int importMinorVersion = import->minversion; - auto shouldSkipSingleton = [importMajorVersion, importMinorVersion](int singletonMajorVersion, int singletonMinorVersion) -> bool { - return importMajorVersion != -1 && - (singletonMajorVersion > importMajorVersion || (singletonMajorVersion == importMajorVersion && singletonMinorVersion > importMinorVersion)); + const QTypeRevision importVersion = import->version; + auto shouldSkipSingleton = [importVersion](QTypeRevision singletonVersion) -> bool { + return importVersion.hasMajorVersion() && + (singletonVersion.majorVersion() > importVersion.majorVersion() + || (singletonVersion.majorVersion() == importVersion.majorVersion() + && singletonVersion.minorVersion() > importVersion.minorVersion())); }; ConstIterator cend = components.constEnd(); for (ConstIterator cit = components.constBegin(); cit != cend; ++cit) { if (cit->singleton && excludeBaseUrl(import->url, cit->fileName, baseUrl.toString())) { - if (shouldSkipSingleton(cit->majorVersion, cit->minorVersion)) + if (shouldSkipSingleton(cit->version)) continue; QQmlImports::CompositeSingletonReference ref; ref.typeName = cit->typeName; ref.prefix = set.prefix; - ref.majorVersion = cit->majorVersion; - ref.minorVersion = cit->minorVersion; + ref.version = cit->version; resultList.append(ref); } } - if (QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->majversion)) { + if (QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->version)) { module->walkCompositeSingletons([&resultList, &set, &shouldSkipSingleton](const QQmlType &singleton) { - if (shouldSkipSingleton(singleton.majorVersion(), singleton.minorVersion())) + if (shouldSkipSingleton(singleton.version())) return; QQmlImports::CompositeSingletonReference ref; ref.typeName = singleton.elementName(); ref.prefix = set.prefix; - ref.majorVersion = singleton.majorVersion(); - ref.minorVersion = singleton.minorVersion(); + ref.version = singleton.version(); resultList.append(ref); }); } @@ -461,9 +467,9 @@ QList<QQmlImports::CompositeSingletonReference> QQmlImports::resolvedCompositeSi if (lhs.typeName != rhs.typeName) return lhs.typeName < rhs.typeName; - return lhs.majorVersion != rhs.majorVersion - ? lhs.majorVersion < rhs.majorVersion - : lhs.minorVersion < rhs.minorVersion; + return lhs.version.majorVersion() != rhs.version.majorVersion() + ? lhs.version.majorVersion() < rhs.version.majorVersion() + : lhs.version.minorVersion() < rhs.version.minorVersion(); }); return compositeSingletons; @@ -532,16 +538,17 @@ static QString joinStringRefs(const QVector<QStringRef> &refs, const QChar &sep) - base/QtQml.2/Models/qmldir - base/QtQml/Models/qmldir */ -QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringList &basePaths, int vmaj, int vmin) +QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringList &basePaths, + QTypeRevision version) { - const QVector<QStringRef> parts = uri.splitRef(Dot, QString::SkipEmptyParts); + const QVector<QStringRef> parts = uri.splitRef(Dot, Qt::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 (int versionMode = FullyVersioned; versionMode <= Unversioned; ++versionMode) { + const QString ver = versionString(version, QQmlImports::ImportVersion(versionMode)); for (const QString &path : basePaths) { QString dir = path; @@ -551,7 +558,7 @@ QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringLi // append to the end qmlDirPathsPaths += dir + joinStringRefs(parts, Slash) + ver + Slash_qmldir; - if (version != Unversioned) { + if (versionMode != Unversioned) { // insert in the middle for (int index = parts.count() - 2; index >= 0; --index) { qmlDirPathsPaths += dir + joinStringRefs(parts.mid(0, index + 1), Slash) @@ -565,14 +572,14 @@ QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringLi return qmlDirPathsPaths; } -QString QQmlImports::versionString(int vmaj, int vmin, ImportVersion version) +QString QQmlImports::versionString(QTypeRevision version, ImportVersion versionMode) { - if (version == QQmlImports::FullyVersioned) { + if (versionMode == QQmlImports::FullyVersioned) { // extension with fully encoded version number (eg. MyModule.3.2) - return QString::asprintf(".%d.%d", vmaj, vmin); - } else if (version == QQmlImports::PartiallyVersioned) { + return QString::asprintf(".%d.%d", version.majorVersion(), version.minorVersion()); + } else if (versionMode == QQmlImports::PartiallyVersioned) { // extension with encoded version major (eg. MyModule.3) - return QString::asprintf(".%d", vmaj); + return QString::asprintf(".%d", version.majorVersion()); } // else extension without version number (eg. MyModule) return QString(); } @@ -591,7 +598,7 @@ QString QQmlImports::versionString(int vmaj, int vmin, ImportVersion version) \sa addFileImport(), addLibraryImport */ bool QQmlImports::resolveType(const QHashedStringRef &type, - QQmlType *type_return, int *vmaj, int *vmin, + QQmlType *type_return, QTypeRevision *version_return, QQmlImportNamespace** ns_return, QList<QQmlError> *errors, QQmlType::RegistrationType registrationType, bool *typeRecursionDetected) const @@ -603,7 +610,7 @@ bool QQmlImports::resolveType(const QHashedStringRef &type, return true; } if (type_return) { - if (d->resolveType(type, vmaj, vmin, type_return, errors, registrationType, + if (d->resolveType(type, version_return, type_return, errors, registrationType, typeRecursionDetected)) { if (qmlImportTrace()) { #define RESOLVE_TYPE_DEBUG qDebug().nospace() << "QQmlImports(" << qPrintable(baseUrl().toString()) \ @@ -627,7 +634,9 @@ bool QQmlImports::resolveType(const QHashedStringRef &type, return false; } -bool QQmlImportInstance::setQmldirContent(const QString &resolvedUrl, const QQmlTypeLoaderQmldirContent &qmldir, QQmlImportNamespace *nameSpace, QList<QQmlError> *errors) +bool QQmlImportInstance::setQmldirContent(const QString &resolvedUrl, + const QQmlTypeLoaderQmldirContent &qmldir, + QQmlImportNamespace *nameSpace, QList<QQmlError> *errors) { Q_ASSERT(resolvedUrl.endsWith(Slash)); url = resolvedUrl; @@ -648,24 +657,27 @@ bool QQmlImportInstance::setQmldirContent(const QString &resolvedUrl, const QQml } } - qmlDirScripts = getVersionedScripts(scripts, majversion, minversion); + qmlDirScripts = getVersionedScripts(scripts, version); } return true; } -QQmlDirScripts QQmlImportInstance::getVersionedScripts(const QQmlDirScripts &qmldirscripts, int vmaj, int vmin) +QQmlDirScripts QQmlImportInstance::getVersionedScripts(const QQmlDirScripts &qmldirscripts, + QTypeRevision version) { QMap<QString, QQmlDirParser::Script> versioned; for (QList<QQmlDirParser::Script>::const_iterator sit = qmldirscripts.constBegin(); sit != qmldirscripts.constEnd(); ++sit) { // Only include scripts that match our requested version - if (((vmaj == -1) || (sit->majorVersion == vmaj)) && - ((vmin == -1) || (sit->minorVersion <= vmin))) { + if ((!version.hasMajorVersion() || (sit->version.majorVersion() == version.majorVersion())) + && (!version.hasMinorVersion() + || (sit->version.minorVersion() <= version.minorVersion()))) { // Load the highest version that matches QMap<QString, QQmlDirParser::Script>::iterator vit = versioned.find(sit->nameSpace); - if (vit == versioned.end() || (vit->minorVersion < sit->minorVersion)) { + if (vit == versioned.end() + || (vit->version.minorVersion() < sit->version.minorVersion())) { versioned.insert(sit->nameSpace, *sit); } } @@ -685,26 +697,25 @@ QQmlDirScripts QQmlImportInstance::getVersionedScripts(const QQmlDirScripts &qml If the return pointer is 0, the corresponding search is not done. */ bool QQmlImports::resolveType(QQmlImportNamespace *ns, const QHashedStringRef &type, - QQmlType *type_return, int *vmaj, int *vmin, + QQmlType *type_return, QTypeRevision *version_return, QQmlType::RegistrationType registrationType) const { - return ns->resolveType(d->typeLoader, type, vmaj, vmin, type_return, nullptr, nullptr, registrationType); + return ns->resolveType(d->typeLoader, type, version_return, type_return, nullptr, nullptr, + registrationType); } bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type, - int *vmajor, int *vminor, QQmlType *type_return, QString *base, - bool *typeRecursionDetected, + QTypeRevision *version_return, QQmlType *type_return, + QString *base, bool *typeRecursionDetected, QQmlType::RegistrationType registrationType, QQmlImport::RecursionRestriction recursionRestriction, QList<QQmlError> *errors) const { - if (majversion >= 0 && minversion >= 0) { - QQmlType t = QQmlMetaType::qmlType(type, uri, majversion, minversion); + if (version.hasMajorVersion() && version.hasMinorVersion()) { + QQmlType t = QQmlMetaType::qmlType(type, uri, version); if (t.isValid()) { - if (vmajor) - *vmajor = majversion; - if (vminor) - *vminor = minversion; + if (version_return) + *version_return = version; if (type_return) *type_return = t; return true; @@ -724,6 +735,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()) { @@ -763,14 +775,16 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt break; } - // importing version -1 means import ALL versions - if ((majversion == -1) || - (implicitlyImported && c.internal) || // allow the implicit import of internal types - (c.majorVersion == majversion && c.minorVersion <= minversion)) { + // importing invalid version means import ALL versions + if (!version.hasMajorVersion() || (implicitlyImported && c.internal) + // allow the implicit import of internal types + || (c.version.majorVersion() == version.majorVersion() + && c.version.minorVersion() <= version.minorVersion())) { // Is this better than the previous candidate? - if ((candidate == end) || - (c.majorVersion > candidate->majorVersion) || - ((c.majorVersion == candidate->majorVersion) && (c.minorVersion > candidate->minorVersion))) { + if ((candidate == end) + || (c.version.majorVersion() > candidate->version.majorVersion()) + || ((c.version.majorVersion() == candidate->version.majorVersion()) + && (c.version.minorVersion() > candidate->version.minorVersion()))) { if (base) { componentUrl = resolveLocalUrl(QString(url + c.typeName + dotqml_string), c.fileName); if (c.internal) { @@ -798,12 +812,9 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt if (!base) // ensure we have a componentUrl componentUrl = resolveLocalUrl(QString(url + candidate->typeName + dotqml_string), candidate->fileName); QQmlType returnType = QQmlMetaType::typeForUrl(componentUrl, type, isCompositeSingleton, - nullptr, candidate->majorVersion, - candidate->minorVersion); - if (vmajor) - *vmajor = candidate->majorVersion; - if (vminor) - *vminor = candidate->minorVersion; + nullptr, candidate->version); + if (version_return) + *version_return = candidate->version; if (type_return) *type_return = returnType; return returnType.isValid(); @@ -855,14 +866,14 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt return false; } -bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor, int *vminor, +bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, QTypeRevision *version_return, QQmlType *type_return, QList<QQmlError> *errors, QQmlType::RegistrationType registrationType, bool *typeRecursionDetected) { const QVector<QHashedStringRef> splitName = type.split(Dot); auto resolveTypeInNamespace = [&](QHashedStringRef unqualifiedtype, QQmlImportNamespace *nameSpace, QList<QQmlError> *errors) -> bool { - if (nameSpace->resolveType(typeLoader, unqualifiedtype, vmajor, vminor, type_return, &base, errors, + if (nameSpace->resolveType(typeLoader, unqualifiedtype, version_return, type_return, &base, errors, registrationType, typeRecursionDetected)) return true; if (nameSpace->imports.count() == 1 && !nameSpace->imports.at(0)->isLibrary && type_return && nameSpace != &unqualifiedset) { @@ -900,6 +911,7 @@ bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor, 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; } @@ -936,6 +948,7 @@ bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor, 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; } @@ -973,7 +986,7 @@ QQmlImportInstance *QQmlImportNamespace::findImport(const QString &uri) const } bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type, - int *vmajor, int *vminor, QQmlType *type_return, + QTypeRevision *version_return, QQmlType *type_return, QString *base, QList<QQmlError> *errors, QQmlType::RegistrationType registrationType, bool *typeRecursionDetected) @@ -987,13 +1000,13 @@ bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedS for (int i=0; i<imports.count(); ++i) { const QQmlImportInstance *import = imports.at(i); - if (import->resolveType(typeLoader, type, vmajor, vminor, type_return, base, + if (import->resolveType(typeLoader, type, version_return, type_return, base, typeRecursionDetected, registrationType, recursionRestriction, errors)) { if (qmlCheckTypes()) { // check for type clashes for (int j = i+1; j<imports.count(); ++j) { const QQmlImportInstance *import2 = imports.at(j); - if (import2->resolveType(typeLoader, type, vmajor, vminor, nullptr, base, + if (import2->resolveType(typeLoader, type, version_return, nullptr, base, nullptr, registrationType)) { if (errors) { QString u1 = import->url; @@ -1020,9 +1033,11 @@ bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedS error.setDescription(QQmlImportDatabase::tr("is ambiguous. Found in %1 and in %2").arg(u1).arg(u2)); } else { error.setDescription(QQmlImportDatabase::tr("is ambiguous. Found in %1 in version %2.%3 and %4.%5") - .arg(u1) - .arg(import->majversion).arg(import->minversion) - .arg(import2->majversion).arg(import2->minversion)); + .arg(u1) + .arg(import->version.majorVersion()) + .arg(import->version.minorVersion()) + .arg(import2->version.majorVersion()) + .arg(import2->version.minorVersion())); } errors->prepend(error); } @@ -1068,18 +1083,19 @@ QQmlImportNamespace *QQmlImportsPrivate::findQualifiedNamespace(const QHashedStr QtQml.Models, \a vmaj is 2, and \a vmin is 0, this method returns the following: [QtQml.Models.2.0, QtQml.2.0.Models, QtQml.Models.2, QtQml.2.Models, QtQml.Models] */ -static QStringList versionUriList(const QString &uri, int vmaj, int vmin) +static QStringList versionUriList(const QString &uri, QTypeRevision version) { QStringList result; - for (int version = QQmlImports::FullyVersioned; version <= QQmlImports::Unversioned; ++version) { + for (int mode = QQmlImports::FullyVersioned; mode <= QQmlImports::Unversioned; ++mode) { int index = uri.length(); do { QString versionUri = uri; - versionUri.insert(index, QQmlImports::versionString(vmaj, vmin, static_cast<QQmlImports::ImportVersion>(version))); + versionUri.insert(index, QQmlImports::versionString( + version, QQmlImports::ImportVersion(mode))); result += versionUri; index = uri.lastIndexOf(Dot, index - 1); - } while (index > 0 && version != QQmlImports::Unversioned); + } while (index > 0 && mode != QQmlImports::Unversioned); } return result; } @@ -1144,8 +1160,7 @@ Import an extension defined by a qmldir file. \a qmldirFilePath is a raw file path. */ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath, - const QString &uri, - int vmaj, int vmin, + const QString &uri, QTypeRevision version, QQmlImportDatabase *database, const QQmlTypeLoaderQmldirContent &qmldir, QList<QQmlError> *errors) @@ -1170,13 +1185,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath, if (qmldirPluginCount == 0) return true; - if (database->qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(qmldirFilePath)) { - if ((vmaj >= 0 && vmin >= 0) - ? !QQmlMetaType::isModule(uri, vmaj, vmin) - : !QQmlMetaType::isAnyModule(uri)) { - QQmlMetaType::qmlRegisterModuleTypes(uri, vmaj); - } - } else { + if (!database->qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(qmldirFilePath)) { // First search for listed qmldir plugins dynamically. If we cannot resolve them all, we continue // searching static plugins that has correct metadata uri. Note that since we only know the uri // for a static plugin, and not the filename, we cannot know which static plugin belongs to which @@ -1198,7 +1207,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath, QString resolvedFilePath = database->resolvePlugin(typeLoader, qmldirPath, plugin.path, plugin.name); if (!resolvedFilePath.isEmpty()) { dynamicPluginsFound++; - if (!database->importDynamicPlugin(resolvedFilePath, uri, typeNamespace, vmaj, errors)) { + if (!database->importDynamicPlugin(resolvedFilePath, uri, typeNamespace, version, errors)) { if (errors) { // XXX TODO: should we leave the import plugin error alone? // Here, we pop it off the top and coalesce it into this error's message. @@ -1223,7 +1232,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath, // versioned to unversioned, we need to compare with differnt version strings. If a module // has several plugins, they must all have the same version. Start by populating pluginPairs // with relevant plugins to cut the list short early on: - const QStringList versionUris = versionUriList(uri, vmaj, vmin); + const QStringList versionUris = versionUriList(uri, version); QVector<StaticPluginPair> pluginPairs; if (!populatePluginPairVector(pluginPairs, uri, versionUris, qmldirFilePath, errors)) return false; @@ -1235,7 +1244,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath, if (versionUri == metaTagUri.toString()) { staticPluginsFound++; QObject *instance = pair.first.instance(); - if (!database->importStaticPlugin(instance, basePath, uri, typeNamespace, vmaj, errors)) { + if (!database->importStaticPlugin(instance, basePath, uri, typeNamespace, version, errors)) { if (errors) { QQmlError poppedError = errors->takeFirst(); QQmlError error; @@ -1338,10 +1347,11 @@ and fills in outQmldirFilePath and outQmldirUrl appropriately. Otherwise return false. */ QQmlImports::LocalQmldirResult QQmlImportsPrivate::locateLocalQmldir( - const QString &uri, int vmaj, int vmin, QQmlImportDatabase *database, + const QString &uri, QTypeRevision version, QQmlImportDatabase *database, QString *outQmldirFilePath, QString *outQmldirPathUrl) { - Q_ASSERT(vmaj >= 0 && vmin >= 0); // Versions are always specified for libraries + // Versions are always specified for libraries + Q_ASSERT(version.hasMajorVersion() && version.hasMinorVersion()); // Check cache first @@ -1352,7 +1362,7 @@ QQmlImports::LocalQmldirResult QQmlImportsPrivate::locateLocalQmldir( cacheHead = *cachePtr; QQmlImportDatabase::QmldirCache *cache = cacheHead; while (cache) { - if (cache->versionMajor == vmaj && cache->versionMinor == vmin) { + if (cache->version == version) { *outQmldirFilePath = cache->qmldirFilePath; *outQmldirPathUrl = cache->qmldirPathUrl; return cache->qmldirFilePath.isEmpty() ? QQmlImports::QmldirNotFound @@ -1372,7 +1382,7 @@ QQmlImports::LocalQmldirResult QQmlImportsPrivate::locateLocalQmldir( // Search local import paths for a matching version const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths( - uri, localImportPaths, vmaj, vmin); + uri, localImportPaths, version); bool pathTurnedRemote = false; for (QString qmldirPath : qmlDirPaths) { if (interceptor) { @@ -1394,8 +1404,7 @@ QQmlImports::LocalQmldirResult QQmlImportsPrivate::locateLocalQmldir( url = QUrl::fromLocalFile(absolutePath.toString()).toString(); QQmlImportDatabase::QmldirCache *cache = new QQmlImportDatabase::QmldirCache; - cache->versionMajor = vmaj; - cache->versionMinor = vmin; + cache->version = version; cache->qmldirFilePath = absoluteFilePath; cache->qmldirPathUrl = url; cache->next = cacheHead; @@ -1409,19 +1418,19 @@ QQmlImports::LocalQmldirResult QQmlImportsPrivate::locateLocalQmldir( } QQmlImportDatabase::QmldirCache *cache = new QQmlImportDatabase::QmldirCache; - cache->versionMajor = vmaj; - cache->versionMinor = vmin; + cache->version = version; cache->next = cacheHead; database->qmldirCache.insert(uri, cache); return pathTurnedRemote ? QQmlImports::QmldirInterceptedToRemote : QQmlImports::QmldirNotFound; } -bool QQmlImportsPrivate::validateQmldirVersion(const QQmlTypeLoaderQmldirContent &qmldir, const QString &uri, int vmaj, int vmin, +bool QQmlImportsPrivate::validateQmldirVersion(const QQmlTypeLoaderQmldirContent &qmldir, + const QString &uri, QTypeRevision version, QList<QQmlError> *errors) { - int lowest_min = INT_MAX; - int highest_min = INT_MIN; + quint8 lowest_min = std::numeric_limits<quint8>::max(); + quint8 highest_min = 0; typedef QQmlDirComponents::const_iterator ConstIterator; const QQmlDirComponents &components = qmldir.components(); @@ -1429,21 +1438,20 @@ bool QQmlImportsPrivate::validateQmldirVersion(const QQmlTypeLoaderQmldirContent ConstIterator cend = components.constEnd(); for (ConstIterator cit = components.constBegin(); cit != cend; ++cit) { for (ConstIterator cit2 = components.constBegin(); cit2 != cit; ++cit2) { - if ((cit2->typeName == cit->typeName) && - (cit2->majorVersion == cit->majorVersion) && - (cit2->minorVersion == cit->minorVersion)) { + if (cit2->typeName == cit->typeName && cit2->version == cit->version) { // This entry clashes with a predecessor QQmlError error; error.setDescription(QQmlImportDatabase::tr("\"%1\" version %2.%3 is defined more than once in module \"%4\"") - .arg(cit->typeName).arg(cit->majorVersion).arg(cit->minorVersion).arg(uri)); + .arg(cit->typeName).arg(cit->version.majorVersion()) + .arg(cit->version.minorVersion()).arg(uri)); errors->prepend(error); return false; } } - if (cit->majorVersion == vmaj) { - lowest_min = qMin(lowest_min, cit->minorVersion); - highest_min = qMax(highest_min, cit->minorVersion); + if (cit->version.majorVersion() == version.majorVersion()) { + lowest_min = qMin(lowest_min, cit->version.minorVersion()); + highest_min = qMax(highest_min, cit->version.minorVersion()); } } @@ -1453,27 +1461,27 @@ bool QQmlImportsPrivate::validateQmldirVersion(const QQmlTypeLoaderQmldirContent SConstIterator send = scripts.constEnd(); for (SConstIterator sit = scripts.constBegin(); sit != send; ++sit) { for (SConstIterator sit2 = scripts.constBegin(); sit2 != sit; ++sit2) { - if ((sit2->nameSpace == sit->nameSpace) && - (sit2->majorVersion == sit->majorVersion) && - (sit2->minorVersion == sit->minorVersion)) { + if (sit2->nameSpace == sit->nameSpace && sit2->version == sit->version) { // This entry clashes with a predecessor QQmlError error; error.setDescription(QQmlImportDatabase::tr("\"%1\" version %2.%3 is defined more than once in module \"%4\"") - .arg(sit->nameSpace).arg(sit->majorVersion).arg(sit->minorVersion).arg(uri)); + .arg(sit->nameSpace).arg(sit->version.majorVersion()) + .arg(sit->version.minorVersion()).arg(uri)); errors->prepend(error); return false; } } - if (sit->majorVersion == vmaj) { - lowest_min = qMin(lowest_min, sit->minorVersion); - highest_min = qMax(highest_min, sit->minorVersion); + if (sit->version.majorVersion() == version.majorVersion()) { + lowest_min = qMin(lowest_min, sit->version.minorVersion()); + highest_min = qMax(highest_min, sit->version.minorVersion()); } } - if (lowest_min > vmin || highest_min < vmin) { + if (lowest_min > version.minorVersion() || highest_min < version.minorVersion()) { QQmlError error; - error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri).arg(vmaj).arg(vmin)); + error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed") + .arg(uri).arg(version.majorVersion()).arg(version.minorVersion())); errors->prepend(error); return false; } @@ -1500,10 +1508,9 @@ QQmlImportNamespace *QQmlImportsPrivate::importNamespace(const QString &prefix) return nameSpace; } -QQmlImportInstance *QQmlImportsPrivate::addImportToNamespace(QQmlImportNamespace *nameSpace, - const QString &uri, const QString &url, int vmaj, int vmin, - QV4::CompiledData::Import::ImportType type, - QList<QQmlError> *errors, bool lowPrecedence) +QQmlImportInstance *QQmlImportsPrivate::addImportToNamespace( + QQmlImportNamespace *nameSpace, const QString &uri, const QString &url, QTypeRevision version, + QV4::CompiledData::Import::ImportType type, QList<QQmlError> *errors, bool lowPrecedence) { Q_ASSERT(nameSpace); Q_ASSERT(errors); @@ -1514,8 +1521,7 @@ QQmlImportInstance *QQmlImportsPrivate::addImportToNamespace(QQmlImportNamespace import->uri = uri; import->url = url; import->localDirectoryPath = QQmlFile::urlToLocalFileOrQrc(url); - import->majversion = vmaj; - import->minversion = vmin; + import->version = version; import->isLibrary = (type == QV4::CompiledData::Import::ImportLibrary); if (lowPrecedence) @@ -1526,10 +1532,10 @@ QQmlImportInstance *QQmlImportsPrivate::addImportToNamespace(QQmlImportNamespace return import; } -bool QQmlImportsPrivate::addLibraryImport(const QString& uri, const QString &prefix, - int vmaj, int vmin, const QString &qmldirIdentifier, const QString &qmldirUrl, bool incomplete, - QQmlImportDatabase *database, - QList<QQmlError> *errors) +bool QQmlImportsPrivate::addLibraryImport( + const QString& uri, const QString &prefix, QTypeRevision version, + const QString &qmldirIdentifier, const QString &qmldirUrl, bool incomplete, + QQmlImportDatabase *database, QList<QQmlError> *errors) { Q_ASSERT(database); Q_ASSERT(errors); @@ -1537,7 +1543,9 @@ bool QQmlImportsPrivate::addLibraryImport(const QString& uri, const QString &pre QQmlImportNamespace *nameSpace = importNamespace(prefix); Q_ASSERT(nameSpace); - QQmlImportInstance *inserted = addImportToNamespace(nameSpace, uri, qmldirUrl, vmaj, vmin, QV4::CompiledData::Import::ImportLibrary, errors); + QQmlImportInstance *inserted = addImportToNamespace( + nameSpace, uri, qmldirUrl, version, + QV4::CompiledData::Import::ImportLibrary, errors); Q_ASSERT(inserted); if (!incomplete) { @@ -1548,7 +1556,7 @@ bool QQmlImportsPrivate::addLibraryImport(const QString& uri, const QString &pre return false; if (qmldir.hasContent()) { - if (!importExtension(qmldir.pluginLocation(), uri, vmaj, vmin, database, qmldir, errors)) + if (!importExtension(qmldir.pluginLocation(), uri, version, database, qmldir, errors)) return false; if (!inserted->setQmldirContent(qmldirUrl, qmldir, nameSpace, errors)) @@ -1557,18 +1565,22 @@ bool QQmlImportsPrivate::addLibraryImport(const QString& uri, const QString &pre } // Ensure that we are actually providing something - if ((vmaj < 0) || (vmin < 0) || !QQmlMetaType::isModule(uri, vmaj, vmin)) { + if (!version.hasMajorVersion() || !version.hasMinorVersion() + || !QQmlMetaType::isModule(uri, version)) { if (inserted->qmlDirComponents.isEmpty() && inserted->qmlDirScripts.isEmpty()) { QQmlError error; - if (QQmlMetaType::isAnyModule(uri)) - error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri).arg(vmaj).arg(vmin)); - else + if (QQmlMetaType::isAnyModule(uri)) { + error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed") + .arg(uri).arg(version.majorVersion()).arg(version.minorVersion())); + } else { error.setDescription(QQmlImportDatabase::tr("module \"%1\" is not installed").arg(uri)); + } errors->prepend(error); return false; - } else if ((vmaj >= 0) && (vmin >= 0) && qmldir.hasContent()) { + } else if (version.hasMajorVersion() && version.hasMinorVersion() + && qmldir.hasContent()) { // Verify that the qmldir content is valid for this version - if (!validateQmldirVersion(qmldir, uri, vmaj, vmin, errors)) + if (!validateQmldirVersion(qmldir, uri, version, errors)) return false; } } @@ -1577,10 +1589,9 @@ bool QQmlImportsPrivate::addLibraryImport(const QString& uri, const QString &pre return true; } -bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix, - int vmaj, int vmin, - bool isImplicitImport, bool incomplete, QQmlImportDatabase *database, - QList<QQmlError> *errors) +bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix, QTypeRevision version, + bool isImplicitImport, bool incomplete, + QQmlImportDatabase *database, QList<QQmlError> *errors) { Q_ASSERT(errors); @@ -1656,7 +1667,9 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix } } - QQmlImportInstance *inserted = addImportToNamespace(nameSpace, importUri, url, vmaj, vmin, QV4::CompiledData::Import::ImportFile, errors, isImplicitImport); + QQmlImportInstance *inserted = addImportToNamespace( + nameSpace, importUri, url, version, QV4::CompiledData::Import::ImportFile, + errors, isImplicitImport); Q_ASSERT(inserted); if (!incomplete && !qmldirIdentifier.isEmpty()) { @@ -1665,7 +1678,7 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix return false; if (qmldir.hasContent()) { - if (!importExtension(qmldir.pluginLocation(), importUri, vmaj, vmin, database, qmldir, errors)) + if (!importExtension(qmldir.pluginLocation(), importUri, version, database, qmldir, errors)) return false; if (!inserted->setQmldirContent(url, qmldir, nameSpace, errors)) @@ -1689,26 +1702,27 @@ bool QQmlImportsPrivate::updateQmldirContent(const QString &uri, const QString & return false; if (qmldir.hasContent()) { - int vmaj = import->majversion; - int vmin = import->minversion; - if (!importExtension(qmldir.pluginLocation(), uri, vmaj, vmin, database, qmldir, errors)) + QTypeRevision version = import->version; + if (!importExtension(qmldir.pluginLocation(), uri, version, database, qmldir, errors)) return false; if (import->setQmldirContent(qmldirUrl, qmldir, nameSpace, errors)) { if (import->qmlDirComponents.isEmpty() && import->qmlDirScripts.isEmpty()) { // The implicit import qmldir can be empty, and plugins have no extra versions - if (uri != QLatin1String(".") && !QQmlMetaType::isModule(uri, vmaj, vmin)) { + if (uri != QLatin1String(".") && !QQmlMetaType::isModule(uri, version)) { QQmlError error; - if (QQmlMetaType::isAnyModule(uri)) - error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri).arg(vmaj).arg(vmin)); - else + if (QQmlMetaType::isAnyModule(uri)) { + error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed") + .arg(uri).arg(version.majorVersion()).arg(version.minorVersion())); + } else { error.setDescription(QQmlImportDatabase::tr("module \"%1\" is not installed").arg(uri)); + } errors->prepend(error); return false; } - } else if ((vmaj >= 0) && (vmin >= 0)) { + } else if (version.hasMajorVersion() && version.hasMinorVersion()) { // Verify that the qmldir content is valid for this version - if (!validateQmldirVersion(qmldir, uri, vmaj, vmin, errors)) + if (!validateQmldirVersion(qmldir, uri, version, errors)) return false; } return true; @@ -1742,7 +1756,8 @@ bool QQmlImports::addImplicitImport(QQmlImportDatabase *importDb, QList<QQmlErro << ")::addImplicitImport"; bool incomplete = !isLocal(baseUrl()); - return d->addFileImport(QLatin1String("."), QString(), -1, -1, true, incomplete, importDb, errors); + return d->addFileImport(QLatin1String("."), QString(), QTypeRevision(), true, incomplete, + importDb, errors); } /*! @@ -1753,8 +1768,7 @@ bool QQmlImports::addInlineComponentImport(QQmlImportInstance *const importInsta importInstance->url = importUrl.toString(); importInstance->uri = name; importInstance->isInlineComponent = true; - importInstance->majversion = 0; - importInstance->minversion = 0; + importInstance->version = QTypeRevision::zero(); importInstance->containingType = containingType; d->unqualifiedset.imports.push_back(importInstance); return true; @@ -1782,7 +1796,7 @@ bool QQmlImports::addInlineComponentImport(QQmlImportInstance *const importInsta filled appropriately. */ bool QQmlImports::addFileImport(QQmlImportDatabase *importDb, - const QString& uri, const QString& prefix, int vmaj, int vmin, + const QString& uri, const QString& prefix, QTypeRevision version, bool incomplete, QList<QQmlError> *errors) { Q_ASSERT(importDb); @@ -1790,13 +1804,13 @@ bool QQmlImports::addFileImport(QQmlImportDatabase *importDb, if (qmlImportTrace()) qDebug().nospace() << "QQmlImports(" << qPrintable(baseUrl().toString()) << ')' << "::addFileImport: " - << uri << ' ' << vmaj << '.' << vmin << " as " << prefix; + << uri << ' ' << version << " as " << prefix; - return d->addFileImport(uri, prefix, vmaj, vmin, false, incomplete, importDb, errors); + return d->addFileImport(uri, prefix, version, false, incomplete, importDb, errors); } bool QQmlImports::addLibraryImport(QQmlImportDatabase *importDb, - const QString &uri, const QString &prefix, int vmaj, int vmin, + const QString &uri, const QString &prefix, QTypeRevision version, const QString &qmldirIdentifier, const QString& qmldirUrl, bool incomplete, QList<QQmlError> *errors) { Q_ASSERT(importDb); @@ -1804,9 +1818,9 @@ bool QQmlImports::addLibraryImport(QQmlImportDatabase *importDb, if (qmlImportTrace()) qDebug().nospace() << "QQmlImports(" << qPrintable(baseUrl().toString()) << ')' << "::addLibraryImport: " - << uri << ' ' << vmaj << '.' << vmin << " as " << prefix; + << uri << ' ' << version << " as " << prefix; - return d->addLibraryImport(uri, prefix, vmaj, vmin, qmldirIdentifier, qmldirUrl, incomplete, importDb, errors); + return d->addLibraryImport(uri, prefix, version, qmldirIdentifier, qmldirUrl, incomplete, importDb, errors); } bool QQmlImports::updateQmldirContent(QQmlImportDatabase *importDb, @@ -1824,10 +1838,10 @@ bool QQmlImports::updateQmldirContent(QQmlImportDatabase *importDb, } QQmlImports::LocalQmldirResult QQmlImports::locateLocalQmldir( - QQmlImportDatabase *importDb, const QString &uri, int vmaj, int vmin, + QQmlImportDatabase *importDb, const QString &uri, QTypeRevision version, QString *qmldirFilePath, QString *url) { - return d->locateLocalQmldir(uri, vmaj, vmin, importDb, qmldirFilePath, url); + return d->locateLocalQmldir(uri, version, importDb, qmldirFilePath, url); } bool QQmlImports::isLocal(const QString &url) @@ -1878,7 +1892,7 @@ QQmlImportDatabase::QQmlImportDatabase(QQmlEngine *e) #else QLatin1Char pathSep(':'); #endif - QStringList paths = envImportPath.split(pathSep, QString::SkipEmptyParts); + QStringList paths = envImportPath.split(pathSep, Qt::SkipEmptyParts); for (int ii = paths.count() - 1; ii >= 0; --ii) addImportPath(paths.at(ii)); } @@ -1890,7 +1904,7 @@ QQmlImportDatabase::QQmlImportDatabase(QQmlEngine *e) if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("QT_BUNDLED_LIBS_PATH"))) { const QString envImportPath = qEnvironmentVariable("QT_BUNDLED_LIBS_PATH"); QLatin1Char pathSep(':'); - QStringList paths = envImportPath.split(pathSep, QString::SkipEmptyParts); + QStringList paths = envImportPath.split(pathSep, Qt::SkipEmptyParts); for (int ii = paths.count() - 1; ii >= 0; --ii) addPluginPath(paths.at(ii)); } @@ -1993,8 +2007,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"); @@ -2133,19 +2150,21 @@ void QQmlImportDatabase::setImportPathList(const QStringList &paths) \internal */ static bool registerPluginTypes(QObject *instance, const QString &basePath, const QString &uri, - const QString &typeNamespace, int vmaj, QList<QQmlError> *errors) + const QString &typeNamespace, QTypeRevision version, + QList<QQmlError> *errors) { if (qmlImportTrace()) qDebug().nospace() << "QQmlImportDatabase::registerPluginTypes: " << uri << " from " << basePath; - if (!QQmlMetaType::registerPluginTypes(instance, basePath, uri, typeNamespace, vmaj, errors)) + if (!QQmlMetaType::registerPluginTypes(instance, basePath, uri, typeNamespace, version, errors)) return false; - if (vmaj >= 0 && !typeNamespace.isEmpty() && !QQmlMetaType::protectModule(uri, vmaj)) { + if (version.hasMajorVersion() && !typeNamespace.isEmpty() + && !QQmlMetaType::protectModule(uri, version)) { QQmlError error; error.setDescription( QString::fromLatin1("Cannot protect module %1 %2 as it was never registered") - .arg(uri).arg(vmaj)); + .arg(uri).arg(version.majorVersion())); errors->append(error); return false; } @@ -2156,8 +2175,9 @@ static bool registerPluginTypes(QObject *instance, const QString &basePath, cons /*! \internal */ -bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &basePath, - const QString &uri, const QString &typeNamespace, int vmaj, QList<QQmlError> *errors) +bool QQmlImportDatabase::importStaticPlugin( + QObject *instance, const QString &basePath, const QString &uri, + const QString &typeNamespace, QTypeRevision version, QList<QQmlError> *errors) { // Dynamic plugins are differentiated by their filepath. For static plugins we // don't have that information so we use their address as key instead. @@ -2180,7 +2200,7 @@ bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &ba plugin.loader = nullptr; plugins->insert(uniquePluginID, plugin); - if (!registerPluginTypes(instance, basePath, uri, typeNamespace, vmaj, errors)) + if (!registerPluginTypes(instance, basePath, uri, typeNamespace, version, errors)) return false; } @@ -2200,8 +2220,9 @@ bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &ba /*! \internal */ -bool QQmlImportDatabase::importDynamicPlugin(const QString &filePath, const QString &uri, - const QString &typeNamespace, int vmaj, QList<QQmlError> *errors) +bool QQmlImportDatabase::importDynamicPlugin( + const QString &filePath, const QString &uri, const QString &typeNamespace, + QTypeRevision version, QList<QQmlError> *errors) { QFileInfo fileInfo(filePath); const QString absoluteFilePath = fileInfo.absoluteFilePath(); @@ -2255,7 +2276,7 @@ bool QQmlImportDatabase::importDynamicPlugin(const QString &filePath, const QStr plugins->insert(absoluteFilePath, plugin); // Continue with shared code path for dynamic and static plugins: - if (!registerPluginTypes(instance, fileInfo.absolutePath(), uri, typeNamespace, vmaj, errors)) + if (!registerPluginTypes(instance, fileInfo.absolutePath(), uri, typeNamespace, version, errors)) return false; } } diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h index 2e994fd27f..7416bb7a4c 100644 --- a/src/qml/qml/qqmlimport_p.h +++ b/src/qml/qml/qqmlimport_p.h @@ -81,8 +81,7 @@ struct QQmlImportInstance QString url; // the base path of the import QString localDirectoryPath; // the base path of the import if it's a local file QQmlType containingType; // points to the containing type for inline components - int majversion; // the major version imported - int minversion; // the minor version imported + QTypeRevision version; // the version imported bool isLibrary; // true means that this is not a file import bool implicitlyImported = false; bool isInlineComponent = false; @@ -92,10 +91,11 @@ struct QQmlImportInstance bool setQmldirContent(const QString &resolvedUrl, const QQmlTypeLoaderQmldirContent &qmldir, QQmlImportNamespace *nameSpace, QList<QQmlError> *errors); - static QQmlDirScripts getVersionedScripts(const QQmlDirScripts &qmldirscripts, int vmaj, int vmin); + static QQmlDirScripts getVersionedScripts(const QQmlDirScripts &qmldirscripts, + QTypeRevision version); bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type, - int *vmajor, int *vminor, QQmlType* type_return, + QTypeRevision *version_return, QQmlType* type_return, QString *base = nullptr, bool *typeRecursionDetected = nullptr, QQmlType::RegistrationType = QQmlType::AnyRegistrationType, QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion, @@ -113,7 +113,7 @@ public: QQmlImportInstance *findImport(const QString &uri) const; bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type, - int *vmajor, int *vminor, QQmlType* type_return, + QTypeRevision *version_return, QQmlType* type_return, QString *base = nullptr, QList<QQmlError> *errors = nullptr, QQmlType::RegistrationType registrationType = QQmlType::AnyRegistrationType, bool *typeRecursionDeteced = nullptr); @@ -140,14 +140,14 @@ public: bool resolveType(const QHashedStringRef &type, QQmlType *type_return, - int *version_major, int *version_minor, + QTypeRevision *version_return, QQmlImportNamespace **ns_return, QList<QQmlError> *errors = nullptr, QQmlType::RegistrationType registrationType = QQmlType::AnyRegistrationType, bool *typeRecursionDetected = nullptr) const; bool resolveType(QQmlImportNamespace *, const QHashedStringRef& type, - QQmlType *type_return, int *version_major, int *version_minor, + QQmlType *type_return, QTypeRevision *version_return, QQmlType::RegistrationType registrationType = QQmlType::AnyRegistrationType) const; @@ -156,11 +156,11 @@ public: bool addInlineComponentImport(QQmlImportInstance *const importInstance, const QString &name, const QUrl importUrl, QQmlType containingType); bool addFileImport(QQmlImportDatabase *, - const QString& uri, const QString& prefix, int vmaj, int vmin, bool incomplete, - QList<QQmlError> *errors); + const QString& uri, const QString& prefix, QTypeRevision version, + bool incomplete, QList<QQmlError> *errors); bool addLibraryImport(QQmlImportDatabase *importDb, - const QString &uri, const QString &prefix, int vmaj, int vmin, + const QString &uri, const QString &prefix, QTypeRevision version, const QString &qmldirIdentifier, const QString &qmldirUrl, bool incomplete, QList<QQmlError> *errors); bool updateQmldirContent(QQmlImportDatabase *importDb, @@ -174,7 +174,7 @@ public: }; LocalQmldirResult locateLocalQmldir( - QQmlImportDatabase *, const QString &uri, int vmaj, int vmin, + QQmlImportDatabase *, const QString &uri, QTypeRevision version, QString *qmldirFilePath, QString *url); void populateCache(QQmlTypeNameCache *cache) const; @@ -192,14 +192,14 @@ public: { QString typeName; QString prefix; - int majorVersion; - int minorVersion; + QTypeRevision version; }; QList<CompositeSingletonReference> resolvedCompositeSingletons() const; - static QStringList completeQmldirPaths(const QString &uri, const QStringList &basePaths, int vmaj, int vmin); - static QString versionString(int vmaj, int vmin, ImportVersion version); + static QStringList completeQmldirPaths(const QString &uri, const QStringList &basePaths, + QTypeRevision version); + static QString versionString(QTypeRevision version, ImportVersion importVersion); static bool isLocal(const QString &url); static bool isLocal(const QUrl &url); @@ -222,7 +222,9 @@ public: ~QQmlImportDatabase(); #if QT_CONFIG(library) - bool importDynamicPlugin(const QString &filePath, const QString &uri, const QString &importNamespace, int vmaj, QList<QQmlError> *errors); + bool importDynamicPlugin(const QString &filePath, const QString &uri, + const QString &importNamespace, QTypeRevision version, + QList<QQmlError> *errors); bool removeDynamicPlugin(const QString &filePath); QStringList dynamicPlugins() const; #endif @@ -245,13 +247,13 @@ private: const QString &qmldirPath, const QString &qmldirPluginPath, const QString &baseName); bool importStaticPlugin(QObject *instance, const QString &basePath, const QString &uri, - const QString &typeNamespace, int vmaj, QList<QQmlError> *errors); + const QString &typeNamespace, QTypeRevision version, + QList<QQmlError> *errors); void clearDirCache(); void finalizePlugin(QObject *instance, const QString &path, const QString &uri); struct QmldirCache { - int versionMajor; - int versionMinor; + QTypeRevision version; QString qmldirFilePath; QString qmldirPathUrl; QmldirCache *next; 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/qqmlincubator_p.h b/src/qml/qml/qqmlincubator_p.h index aadb147bd5..a674ff274f 100644 --- a/src/qml/qml/qqmlincubator_p.h +++ b/src/qml/qml/qqmlincubator_p.h @@ -61,9 +61,7 @@ QT_BEGIN_NAMESPACE -class QQmlPropertyData; -struct RequiredPropertyInfo; -using RequiredProperties = QHash<QQmlPropertyData*, RequiredPropertyInfo>; +class RequiredProperties; class QQmlIncubator; class Q_QML_PRIVATE_EXPORT QQmlIncubatorPrivate : public QQmlEnginePrivate::Incubator diff --git a/src/qml/qml/qqmlinfo.cpp b/src/qml/qml/qqmlinfo.cpp index dd401bdb20..7204d5ccd2 100644 --- a/src/qml/qml/qqmlinfo.cpp +++ b/src/qml/qml/qqmlinfo.cpp @@ -44,6 +44,7 @@ #include "qqmlcontext_p.h" #include "qqmlmetatype_p.h" #include "qqmlengine_p.h" +#include "qqmlsourcecoordinate_p.h" #include <QCoreApplication> @@ -218,8 +219,8 @@ QQmlInfo::~QQmlInfo() QQmlData *ddata = QQmlData::get(object, false); if (ddata && ddata->outerContext) { error.setUrl(ddata->outerContext->url()); - error.setLine(ddata->lineNumber); - error.setColumn(ddata->columnNumber); + error.setLine(qmlConvertSourceCoordinate<quint16, int>(ddata->lineNumber)); + error.setColumn(qmlConvertSourceCoordinate<quint16, int>(ddata->columnNumber)); } } diff --git a/src/qml/qml/qqmlirloader.cpp b/src/qml/qml/qqmlirloader.cpp index b284e44fdf..f66094fad7 100644 --- a/src/qml/qml/qqmlirloader.cpp +++ b/src/qml/qml/qqmlirloader.cpp @@ -78,14 +78,14 @@ struct FakeExpression : public QQmlJS::AST::NullExpression : location(start, length) {} - virtual QQmlJS::AST::SourceLocation firstSourceLocation() const + virtual QQmlJS::SourceLocation firstSourceLocation() const { return location; } - virtual QQmlJS::AST::SourceLocation lastSourceLocation() const + virtual QQmlJS::SourceLocation lastSourceLocation() const { return location; } private: - QQmlJS::AST::SourceLocation location; + QQmlJS::SourceLocation location; }; QmlIR::Object *QQmlIRLoader::loadObject(const QV4::CompiledData::Object *serializedObject) diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp index 8661ebcc13..6a9ef06159 100644 --- a/src/qml/qml/qqmljavascriptexpression.cpp +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -50,6 +50,7 @@ #include <private/qqmlglobal_p.h> #include <private/qv4qobjectwrapper_p.h> #include <private/qqmlbuiltinfunctions_p.h> +#include <private/qqmlsourcecoordinate_p.h> QT_BEGIN_NAMESPACE @@ -72,8 +73,8 @@ bool QQmlDelayedError::addError(QQmlEnginePrivate *e) void QQmlDelayedError::setErrorLocation(const QQmlSourceLocation &sourceLocation) { m_error.setUrl(QUrl(sourceLocation.sourceFile)); - m_error.setLine(sourceLocation.line); - m_error.setColumn(sourceLocation.column); + m_error.setLine(qmlConvertSourceCoordinate<quint16, int>(sourceLocation.line)); + m_error.setColumn(qmlConvertSourceCoordinate<quint16, int>(sourceLocation.column)); } void QQmlDelayedError::setErrorDescription(const QString &description) diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp index 1743410776..bc227ad713 100644 --- a/src/qml/qml/qqmllocale.cpp +++ b/src/qml/qml/qqmllocale.cpp @@ -314,7 +314,7 @@ ReturnedValue QQmlDateExtension::method_fromLocaleDateString(const QV4::Function QLocale locale; QString dateString = s->toQString(); QDate date = locale.toDate(dateString); - RETURN_RESULT(engine->newDateObject(QDateTime(date))); + RETURN_RESULT(engine->newDateObject(date.startOfDay())); } } @@ -341,7 +341,7 @@ ReturnedValue QQmlDateExtension::method_fromLocaleDateString(const QV4::Function dt = r->d()->locale->toDate(dateString, enumFormat); } - RETURN_RESULT(engine->newDateObject(QDateTime(dt))); + RETURN_RESULT(engine->newDateObject(dt.startOfDay())); } ReturnedValue QQmlDateExtension::method_timeZoneUpdated(const QV4::FunctionObject *b, const QV4::Value *, const QV4::Value *, int argc) diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h index 1d6fdb12a7..d7bff5a1b7 100644 --- a/src/qml/qml/qqmllocale_p.h +++ b/src/qml/qml/qqmllocale_p.h @@ -96,7 +96,7 @@ class Q_QML_PRIVATE_EXPORT QQmlLocale Q_GADGET QML_NAMED_ELEMENT(Locale) QML_UNCREATABLE("Locale cannot be instantiated. Use Qt.locale().") - QML_ADDED_IN_MINOR_VERSION(2) + QML_ADDED_IN_VERSION(2, 2) public: ~QQmlLocale(); diff --git a/src/qml/qml/qqmlloggingcategory_p.h b/src/qml/qml/qqmlloggingcategory_p.h index c7377528b4..9cee029a9b 100644 --- a/src/qml/qml/qqmlloggingcategory_p.h +++ b/src/qml/qml/qqmlloggingcategory_p.h @@ -66,9 +66,9 @@ 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 12) + Q_PROPERTY(DefaultLogLevel defaultLogLevel READ defaultLogLevel WRITE setDefaultLogLevel REVISION(2, 12)) QML_NAMED_ELEMENT(LoggingCategory) - QML_ADDED_IN_MINOR_VERSION(8) + QML_ADDED_IN_VERSION(2, 8) public: enum DefaultLogLevel { diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 76816618ac..68b95d1cc3 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -92,8 +92,12 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, d->typeId = type.typeId; d->listId = type.listId; d->isSetup = true; - d->version_maj = 0; - d->version_min = 0; + if (type.structVersion > 0) { + d->module = QString::fromUtf8(type.uri); + d->version = type.version; + } else { + d->version = QTypeRevision::zero(); + } data->registerType(d); return d; } @@ -105,28 +109,30 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &el data->registerType(d); d->setName(QString::fromUtf8(type.uri), elementName); - d->version_maj = type.versionMajor; - d->version_min = type.versionMinor; + d->version = type.version; - if (type.qobjectApi || (type.version >= 3 && type.generalizedQobjectApi)) { - if (type.version >= 1) // static metaobject added in version 1 + if (type.qobjectApi || (type.structVersion >= 3 && type.generalizedQobjectApi)) { + if (type.structVersion >= 1) // static metaobject added in version 1 d->baseMetaObject = type.instanceMetaObject; - if (type.version >= 2) // typeId added in version 2 + if (type.structVersion >= 2) // typeId added in version 2 d->typeId = type.typeId; - if (type.version >= 2) // revisions added in version 2 + if (type.structVersion >= 2) // revisions added in version 2 d->revision = type.revision; } d->extraData.sd->singletonInstanceInfo = new QQmlType::SingletonInstanceInfo; d->extraData.sd->singletonInstanceInfo->scriptCallback = type.scriptApi; - if (type.version >= 3) { + if (type.structVersion >= 3) { d->extraData.sd->singletonInstanceInfo->qobjectCallback = type.generalizedQobjectApi; } else { d->extraData.sd->singletonInstanceInfo->qobjectCallback = type.qobjectApi; } d->extraData.sd->singletonInstanceInfo->typeName = QString::fromUtf8(type.typeName); d->extraData.sd->singletonInstanceInfo->instanceMetaObject - = ((type.qobjectApi || (type.version >= 3 && type.generalizedQobjectApi) ) && type.version >= 1) ? type.instanceMetaObject : nullptr; + = ((type.qobjectApi || (type.structVersion >= 3 && type.generalizedQobjectApi) ) + && type.structVersion >= 1) + ? type.instanceMetaObject + : nullptr; return d; } @@ -138,9 +144,8 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &el data->registerType(d); d->setName(QString::fromUtf8(type.uri), elementName); - d->version_maj = type.versionMajor; - d->version_min = type.versionMinor; - if (type.version >= 1) // revisions added in version 1 + d->version = type.version; + if (type.structVersion >= 1) // revisions added in version 1 d->revision = type.revision; d->typeId = type.typeId; d->listId = type.listId; @@ -176,8 +181,7 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &el auto *d = new QQmlTypePrivate(QQmlType::CompositeType); data->registerType(d); d->setName(QString::fromUtf8(type.uri), elementName); - d->version_maj = type.versionMajor; - d->version_min = type.versionMinor; + d->version = type.version; d->extraData.fd->url = QQmlTypeLoader::normalize(type.url); return d; @@ -190,8 +194,7 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &el data->registerType(d); d->setName(QString::fromUtf8(type.uri), elementName); - d->version_maj = type.versionMajor; - d->version_min = type.versionMinor; + d->version = type.version; d->extraData.sd->singletonInstanceInfo = new QQmlType::SingletonInstanceInfo; d->extraData.sd->singletonInstanceInfo->url = QQmlTypeLoader::normalize(type.url); @@ -267,35 +270,43 @@ void QQmlMetaType::clone(QMetaObjectBuilder &builder, const QMetaObject *mo, } } -void QQmlMetaType::qmlInsertModuleRegistration(const QString &uri, int majorVersion, - void (*registerFunction)()) +void QQmlMetaType::qmlInsertModuleRegistration(const QString &uri, void (*registerFunction)()) { - const QQmlMetaTypeData::VersionedUri versionedUri(uri, majorVersion); QQmlMetaTypeDataPtr data; - if (data->moduleTypeRegistrationFunctions.contains(versionedUri)) - qFatal("Cannot add multiple registrations for %s %d", qPrintable(uri), majorVersion); + if (data->moduleTypeRegistrationFunctions.contains(uri)) + qFatal("Cannot add multiple registrations for %s", qPrintable(uri)); else - data->moduleTypeRegistrationFunctions.insert(versionedUri, registerFunction); + data->moduleTypeRegistrationFunctions.insert(uri, registerFunction); } -void QQmlMetaType::qmlRemoveModuleRegistration(const QString &uri, int majorVersion) +void QQmlMetaType::qmlRemoveModuleRegistration(const QString &uri) { - const QQmlMetaTypeData::VersionedUri versionedUri(uri, majorVersion); QQmlMetaTypeDataPtr data; if (!data.isValid()) return; // shutdown/deletion race. Not a problem. - if (!data->moduleTypeRegistrationFunctions.contains(versionedUri)) - qFatal("Cannot remove multiple registrations for %s %d", qPrintable(uri), majorVersion); + if (!data->moduleTypeRegistrationFunctions.contains(uri)) + qFatal("Cannot remove multiple registrations for %s", qPrintable(uri)); else - data->moduleTypeRegistrationFunctions.remove(versionedUri); + data->moduleTypeRegistrationFunctions.remove(uri); +} + +bool QQmlMetaType::qmlRegisterModuleTypes(const QString &uri) +{ + QQmlMetaTypeDataPtr data; + return data->registerModuleTypes(uri); } -bool QQmlMetaType::qmlRegisterModuleTypes(const QString &uri, int majorVersion) +/*! + \internal + Method is only used to in tst_qqmlenginecleanup.cpp to test whether all + types have been removed from qmlLists after shutdown of QQmlEngine + */ +int QQmlMetaType::qmlRegisteredListTypeCount() { QQmlMetaTypeDataPtr data; - return data->registerModuleTypes(QQmlMetaTypeData::VersionedUri(uri, majorVersion)); + return data->qmlLists.count(); } void QQmlMetaType::clearTypeRegistrations() @@ -334,24 +345,19 @@ void QQmlMetaType::unregisterAutoParentFunction(const QQmlPrivate::AutoParentFun QQmlType QQmlMetaType::registerInterface(const QQmlPrivate::RegisterInterface &type) { - if (type.version > 0) + if (type.structVersion > 1) qFatal("qmlRegisterType(): Cannot mix incompatible QML versions."); QQmlMetaTypeDataPtr data; QQmlTypePrivate *priv = createQQmlType(data, type); Q_ASSERT(priv); - data->idToType.insert(priv->typeId, priv); - data->idToType.insert(priv->listId, priv); - if (!priv->elementName.isEmpty()) - data->nameToType.insert(priv->elementName, priv); - if (data->interfaces.size() <= type.typeId) - data->interfaces.resize(type.typeId + 16); - if (data->lists.size() <= type.listId) - data->lists.resize(type.listId + 16); - data->interfaces.setBit(type.typeId, true); - data->lists.setBit(type.listId, true); + data->idToType.insert(priv->typeId.id(), priv); + data->idToType.insert(priv->listId.id(), priv); + + data->interfaces.insert(type.typeId.id()); + data->lists.insert(type.listId.id()); return QQmlType(priv); } @@ -372,7 +378,7 @@ QString registrationTypeString(QQmlType::RegistrationType typeType) // NOTE: caller must hold a QMutexLocker on "data" bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *data, - const char *uri, const QString &typeName, int majorVersion) + const char *uri, const QString &typeName, QTypeRevision version) { if (!typeName.isEmpty()) { if (typeName.at(0).isLower()) { @@ -393,14 +399,14 @@ bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *da if (uri && !typeName.isEmpty()) { QString nameSpace = QString::fromUtf8(uri); - QQmlMetaTypeData::VersionedUri versionedUri; - versionedUri.uri = nameSpace; - versionedUri.majorVersion = majorVersion; + QQmlMetaTypeData::VersionedUri versionedUri(nameSpace, version); if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0)){ if (qqtm->isLocked()){ QString failure(QCoreApplication::translate("qmlRegisterType", "Cannot install %1 '%2' into protected module '%3' version '%4'")); - data->recordTypeRegFailure(failure.arg(registrationTypeString(typeType)).arg(typeName).arg(nameSpace).arg(majorVersion)); + data->recordTypeRegFailure(failure.arg(registrationTypeString(typeType)) + .arg(typeName).arg(nameSpace) + .arg(version.majorVersion())); return false; } } @@ -410,9 +416,9 @@ bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *da } // NOTE: caller must hold a QMutexLocker on "data" -QQmlTypeModule *getTypeModule(const QHashedString &uri, int majorVersion, QQmlMetaTypeData *data) +QQmlTypeModule *getTypeModule(const QHashedString &uri, QTypeRevision version, QQmlMetaTypeData *data) { - QQmlMetaTypeData::VersionedUri versionedUri(uri, majorVersion); + QQmlMetaTypeData::VersionedUri versionedUri(uri, version); QQmlTypeModule *module = data->uriToModule.value(versionedUri); if (!module) { module = new QQmlTypeModule(versionedUri.uri, versionedUri.majorVersion); @@ -432,24 +438,20 @@ void addTypeToData(QQmlTypePrivate *type, QQmlMetaTypeData *data) if (type->baseMetaObject) data->metaObjectToType.insert(type->baseMetaObject, type); - if (type->typeId) { - data->idToType.insert(type->typeId, type); - if (data->objects.size() <= type->typeId) - data->objects.resize(type->typeId + 16); - data->objects.setBit(type->typeId, true); + if (type->typeId.isValid()) { + data->idToType.insert(type->typeId.id(), type); + data->objects.insert(type->typeId.id()); } - if (type->listId) { - if (data->lists.size() <= type->listId) - data->lists.resize(type->listId + 16); - data->lists.setBit(type->listId, true); - data->idToType.insert(type->listId, type); + if (type->listId.isValid()) { + data->idToType.insert(type->listId.id(), type); + data->lists.insert(type->listId.id()); } if (!type->module.isEmpty()) { const QHashedString &mod = type->module; - QQmlTypeModule *module = getTypeModule(mod, type->version_maj, data); + QQmlTypeModule *module = getTypeModule(mod, type->version, data); Q_ASSERT(module); module->add(type); } @@ -460,14 +462,14 @@ QQmlType QQmlMetaType::registerType(const QQmlPrivate::RegisterType &type) QQmlMetaTypeDataPtr data; QString elementName = QString::fromUtf8(type.elementName); - if (!checkRegistration(QQmlType::CppType, data, type.uri, elementName, type.versionMajor)) + if (!checkRegistration(QQmlType::CppType, data, type.uri, elementName, type.version)) return QQmlType(); QQmlTypePrivate *priv = createQQmlType(data, elementName, type); addTypeToData(priv, data); - if (!type.typeId) - data->idToType.insert(priv->typeId, priv); + if (!type.typeId.isValid()) + data->idToType.insert(priv->typeId.id(), priv); return QQmlType(priv); } @@ -477,7 +479,7 @@ QQmlType QQmlMetaType::registerSingletonType(const QQmlPrivate::RegisterSingleto QQmlMetaTypeDataPtr data; QString typeName = QString::fromUtf8(type.typeName); - if (!checkRegistration(QQmlType::SingletonType, data, type.uri, typeName, type.versionMajor)) + if (!checkRegistration(QQmlType::SingletonType, data, type.uri, typeName, type.version)) return QQmlType(); QQmlTypePrivate *priv = createQQmlType(data, typeName, type); @@ -497,7 +499,7 @@ QQmlType QQmlMetaType::registerCompositeSingletonType(const QQmlPrivate::Registe if (*(type.uri) == '\0') fileImport = true; if (!checkRegistration(QQmlType::CompositeSingletonType, data, fileImport ? nullptr : type.uri, - typeName, type.versionMajor)) { + typeName, type.version)) { return QQmlType(); } @@ -519,7 +521,7 @@ QQmlType QQmlMetaType::registerCompositeType(const QQmlPrivate::RegisterComposit bool fileImport = false; if (*(type.uri) == '\0') fileImport = true; - if (!checkRegistration(QQmlType::CompositeType, data, fileImport?nullptr:type.uri, typeName, type.versionMajor)) + if (!checkRegistration(QQmlType::CompositeType, data, fileImport?nullptr:type.uri, typeName, type.version)) return QQmlType(); QQmlTypePrivate *priv = createQQmlType(data, typeName, type); @@ -531,26 +533,50 @@ QQmlType QQmlMetaType::registerCompositeType(const QQmlPrivate::RegisterComposit return QQmlType(priv); } + + +template <typename T> +struct QQmlMetaTypeInterface : QtPrivate::QMetaTypeInterface +{ + const QByteArray name; + QQmlMetaTypeInterface(const QByteArray &name) + : QMetaTypeInterface { + /*.revision=*/ 0, + /*.size=*/ sizeof(T), + /*.alignment=*/ alignof(T), + /*.flags=*/ QtPrivate::QMetaTypeTypeFlags<T>::Flags, + /*.metaObject=*/ nullptr, + /*.name=*/ name.constData(), + /*.typeId=*/ 0, + /*.ref=*/ Q_REFCOUNT_INITIALIZE_STATIC, + /*.deleteSelf=*/ [](QMetaTypeInterface *self) { + delete static_cast<QQmlMetaTypeInterface *>(self); + }, + /*.defaultCtr=*/ [](const QMetaTypeInterface *, void *addr) { new (addr) T(); }, + /*.copyCtr=*/ [](const QMetaTypeInterface *, void *addr, const void *other) { + new (addr) T(*reinterpret_cast<const T *>(other)); + }, + /*.moveCtr=*/ [](const QMetaTypeInterface *, void *addr, void *other) { + new (addr) T(std::move(*reinterpret_cast<T *>(other))); + }, + /*.dtor=*/ [](const QMetaTypeInterface *, void *addr) { + reinterpret_cast<T *>(addr)->~T(); + }, + /*.legacyRegisterOp=*/ nullptr + } + , name(name) { } +}; + CompositeMetaTypeIds QQmlMetaType::registerInternalCompositeType(const QByteArray &className) { QByteArray ptr = className + '*'; QByteArray lst = "QQmlListProperty<" + className + '>'; - int ptr_type = QMetaType::registerNormalizedType(ptr, - QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Destruct, - QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Construct, - sizeof(QObject*), - static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags), - nullptr); - int lst_type = QMetaType::registerNormalizedType(lst, - QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Destruct, - QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Construct, - sizeof(QQmlListProperty<QObject>), - static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags), - static_cast<QMetaObject*>(nullptr)); + QMetaType ptr_type(new QQmlMetaTypeInterface<QObject*>(ptr)); + QMetaType lst_type(new QQmlMetaTypeInterface<QQmlListProperty<QObject>>(lst)); QQmlMetaTypeDataPtr data; - data->qmlLists.insert(lst_type, ptr_type); + data->qmlLists.insert(lst_type.id(), ptr_type.id()); return {ptr_type, lst_type}; } @@ -558,16 +584,13 @@ CompositeMetaTypeIds QQmlMetaType::registerInternalCompositeType(const QByteArra void QQmlMetaType::unregisterInternalCompositeType(const CompositeMetaTypeIds &typeIds) { QQmlMetaTypeDataPtr data; - data->qmlLists.remove(typeIds.listId); - - QMetaType::unregisterType(typeIds.id); - QMetaType::unregisterType(typeIds.listId); + data->qmlLists.remove(typeIds.listId.id()); } int QQmlMetaType::registerUnitCacheHook( const QQmlPrivate::RegisterQmlUnitCacheHook &hookRegistration) { - if (hookRegistration.version > 0) + if (hookRegistration.structVersion > 0) qFatal("qmlRegisterType(): Cannot mix incompatible QML versions."); QQmlMetaTypeDataPtr data; @@ -575,40 +598,37 @@ int QQmlMetaType::registerUnitCacheHook( return 0; } -bool QQmlMetaType::protectModule(const QString &uri, int majVersion) +bool QQmlMetaType::protectModule(const QString &uri, QTypeRevision version) { QQmlMetaTypeDataPtr data; - QQmlMetaTypeData::VersionedUri versionedUri; - versionedUri.uri = uri; - versionedUri.majorVersion = majVersion; - - if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0)) { + if (QQmlTypeModule* qqtm = data->uriToModule.value( + QQmlMetaTypeData::VersionedUri(uri, version), nullptr)) { qqtm->lock(); return true; } return false; } -void QQmlMetaType::registerModule(const char *uri, int versionMajor, int versionMinor) +void QQmlMetaType::registerModule(const char *uri, QTypeRevision version) { QQmlMetaTypeDataPtr data; - QQmlTypeModule *module = getTypeModule(QString::fromUtf8(uri), versionMajor, data); + QQmlTypeModule *module = getTypeModule(QString::fromUtf8(uri), version, data); Q_ASSERT(module); - module->addMinorVersion(versionMinor); + module->addMinorVersion(version.minorVersion()); } -int QQmlMetaType::typeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName) +int QQmlMetaType::typeId(const char *uri, QTypeRevision version, const char *qmlName) { QQmlMetaTypeDataPtr data; - QQmlTypeModule *module = getTypeModule(QString::fromUtf8(uri), versionMajor, data); + QQmlTypeModule *module = getTypeModule(QString::fromUtf8(uri), version, data); if (!module) return -1; - QQmlType type = module->type(QHashedStringRef(QString::fromUtf8(qmlName)), versionMinor); + QQmlType type = module->type(QHashedStringRef(QString::fromUtf8(qmlName)), version); if (!type.isValid()) return -1; @@ -622,12 +642,12 @@ void QQmlMetaType::registerUndeletableType(const QQmlType &dtype) } static bool namespaceContainsRegistrations(const QQmlMetaTypeData *data, const QString &uri, - int majorVersion) + QTypeRevision version) { // Has any type previously been installed to this namespace? QHashedString nameSpace(uri); for (const QQmlType &type : data->types) { - if (type.module() == nameSpace && type.majorVersion() == majorVersion) + if (type.module() == nameSpace && type.version().majorVersion() == version.majorVersion()) return true; } @@ -654,8 +674,8 @@ public: bool QQmlMetaType::registerPluginTypes(QObject *instance, const QString &basePath, - const QString &uri, const QString &typeNamespace, int vmaj, - QList<QQmlError> *errors) + const QString &uri, const QString &typeNamespace, + QTypeRevision version, QList<QQmlError> *errors) { if (!typeNamespace.isEmpty() && typeNamespace != uri) { // This is an 'identified' module @@ -676,7 +696,7 @@ bool QQmlMetaType::registerPluginTypes(QObject *instance, const QString &basePat QQmlMetaTypeRegistrationFailureRecorder failureRecorder(data, &failures); if (!typeNamespace.isEmpty()) { // This is an 'identified' module - if (namespaceContainsRegistrations(data, typeNamespace, vmaj)) { + if (namespaceContainsRegistrations(data, typeNamespace, version)) { // Other modules have already installed to this namespace if (errors) { QQmlError error; @@ -718,7 +738,7 @@ bool QQmlMetaType::registerPluginTypes(QObject *instance, const QString &basePat iface->registerTypes(moduleId); } - data->registerModuleTypes(QQmlMetaTypeData::VersionedUri(uri, vmaj)); + data->registerModuleTypes(uri); if (!failures.isEmpty()) { if (errors) { @@ -749,7 +769,7 @@ bool QQmlMetaType::registerPluginTypes(QObject *instance, const QString &basePat QQmlType QQmlMetaType::typeForUrl(const QString &urlString, const QHashedStringRef &qualifiedType, bool isCompositeSingleton, QList<QQmlError> *errors, - int majorVersion, int minorVersion) + QTypeRevision version) { // ### unfortunate (costly) conversion const QUrl url = QQmlTypeLoader::normalize(QUrl(urlString)); @@ -794,11 +814,10 @@ QQmlType QQmlMetaType::typeForUrl(const QString &urlString, const QQmlType::RegistrationType registrationType = isCompositeSingleton ? QQmlType::CompositeSingletonType : QQmlType::CompositeType; - if (checkRegistration(registrationType, data, nullptr, typeName, majorVersion)) { + if (checkRegistration(registrationType, data, nullptr, typeName, version)) { auto *priv = new QQmlTypePrivate(registrationType); priv->setName(QString(), typeName); - priv->version_maj = majorVersion; - priv->version_min = minorVersion; + priv->version = version; if (isCompositeSingleton) { priv->extraData.sd->singletonInstanceInfo = new QQmlType::SingletonInstanceInfo; @@ -851,14 +870,12 @@ bool QQmlMetaType::isAnyModule(const QString &uri) /* Returns true if a module \a uri of this version is installed and locked; */ -bool QQmlMetaType::isLockedModule(const QString &uri, int majVersion) +bool QQmlMetaType::isLockedModule(const QString &uri, QTypeRevision version) { QQmlMetaTypeDataPtr data; - QQmlMetaTypeData::VersionedUri versionedUri; - versionedUri.uri = uri; - versionedUri.majorVersion = majVersion; - if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0)) + if (QQmlTypeModule* qqtm = data->uriToModule.value( + QQmlMetaTypeData::VersionedUri(uri, version), nullptr)) return qqtm->isLocked(); return false; } @@ -870,24 +887,24 @@ bool QQmlMetaType::isLockedModule(const QString &uri, int majVersion) So if only 4.7 and 4.9 have been registered, 4.7,4.8, and 4.9 are valid, but not 4.6 nor 4.10. */ -bool QQmlMetaType::isModule(const QString &module, int versionMajor, int versionMinor) +bool QQmlMetaType::isModule(const QString &module, QTypeRevision version) { - Q_ASSERT(versionMajor >= 0 && versionMinor >= 0); + Q_ASSERT(version.hasMajorVersion() && version.hasMinorVersion()); QQmlMetaTypeDataPtr data; // first, check Types QQmlTypeModule *tm = - data->uriToModule.value(QQmlMetaTypeData::VersionedUri(module, versionMajor)); - if (tm && tm->minimumMinorVersion() <= versionMinor && tm->maximumMinorVersion() >= versionMinor) + data->uriToModule.value(QQmlMetaTypeData::VersionedUri(module, version)); + if (tm && tm->minimumMinorVersion() <= version.minorVersion() && tm->maximumMinorVersion() >= version.minorVersion()) return true; return false; } -QQmlTypeModule *QQmlMetaType::typeModule(const QString &uri, int majorVersion) +QQmlTypeModule *QQmlMetaType::typeModule(const QString &uri, QTypeRevision version) { QQmlMetaTypeDataPtr data; - return data->uriToModule.value(QQmlMetaTypeData::VersionedUri(uri, majorVersion)); + return data->uriToModule.value(QQmlMetaTypeData::VersionedUri(uri, version)); } QList<QQmlPrivate::AutoParentFunction> QQmlMetaType::parentFunctions() @@ -912,9 +929,8 @@ bool QQmlMetaType::isQObject(int userType) { if (userType == QMetaType::QObjectStar) return true; - QQmlMetaTypeDataPtr data; - return userType >= 0 && userType < data->objects.size() && data->objects.testBit(userType); + return data->objects.contains(userType); } /* @@ -927,8 +943,8 @@ int QQmlMetaType::listType(int id) if (iter != data->qmlLists.cend()) return *iter; QQmlTypePrivate *type = data->idToType.value(id); - if (type && type->listId == id) - return type->typeId; + if (type && type->listId.id() == id) + return type->typeId.id(); else return 0; } @@ -1028,9 +1044,9 @@ QQmlMetaType::TypeCategory QQmlMetaType::typeCategory(int userType) QQmlMetaTypeDataPtr data; if (data->qmlLists.contains(userType)) return List; - else if (userType < data->objects.size() && data->objects.testBit(userType)) + else if (data->objects.contains(userType)) return Object; - else if (userType < data->lists.size() && data->lists.testBit(userType)) + else if (data->lists.contains(userType)) return List; else return Unknown; @@ -1042,7 +1058,7 @@ QQmlMetaType::TypeCategory QQmlMetaType::typeCategory(int userType) bool QQmlMetaType::isInterface(int userType) { const QQmlMetaTypeDataPtr data; - return userType >= 0 && userType < data->interfaces.size() && data->interfaces.testBit(userType); + return data->interfaces.contains(userType); } const char *QQmlMetaType::interfaceIId(int userType) @@ -1055,7 +1071,7 @@ const char *QQmlMetaType::interfaceIId(int userType) } QQmlType type(typePrivate); - if (type.isInterface() && type.typeId() == userType) + if (type.isInterface() && type.typeId().id() == userType) return type.interfaceIId(); else return nullptr; @@ -1063,10 +1079,10 @@ const char *QQmlMetaType::interfaceIId(int userType) bool QQmlMetaType::isList(int userType) { - const QQmlMetaTypeDataPtr data; + QQmlMetaTypeDataPtr data; if (data->qmlLists.contains(userType)) return true; - return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType); + return data->lists.contains(userType); } /*! @@ -1106,7 +1122,7 @@ QQmlMetaType::StringConverter QQmlMetaType::customStringConverter(int type) Returns the type (if any) of URI-qualified named \a qualifiedName and version specified by \a version_major and \a version_minor. */ -QQmlType QQmlMetaType::qmlType(const QString &qualifiedName, int version_major, int version_minor) +QQmlType QQmlMetaType::qmlType(const QString &qualifiedName, QTypeRevision version) { int slash = qualifiedName.indexOf(QLatin1Char('/')); if (slash <= 0) @@ -1115,23 +1131,23 @@ QQmlType QQmlMetaType::qmlType(const QString &qualifiedName, int version_major, QHashedStringRef module(qualifiedName.constData(), slash); QHashedStringRef name(qualifiedName.constData() + slash + 1, qualifiedName.length() - slash - 1); - return qmlType(name, module, version_major, version_minor); + return qmlType(name, module, version); } /*! Returns the type (if any) of \a name in \a module and version specified by \a version_major and \a version_minor. */ -QQmlType QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int version_major, int version_minor) +QQmlType QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStringRef &module, + QTypeRevision version) { - Q_ASSERT(version_major >= 0 && version_minor >= 0); + Q_ASSERT(version.hasMajorVersion() && version.hasMinorVersion()); const QQmlMetaTypeDataPtr data; QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.constFind(name); while (it != data->nameToType.cend() && it.key() == name) { QQmlType t(*it); - // XXX version_major<0 just a kludge for QQmlPropertyPrivate::initProperty - if (version_major < 0 || module.isEmpty() || t.availableInVersion(module, version_major,version_minor)) + if (module.isEmpty() || t.availableInVersion(module, version)) return t; ++it; } @@ -1154,15 +1170,16 @@ QQmlType QQmlMetaType::qmlType(const QMetaObject *metaObject) by \a version_major and \a version_minor in module specified by \a uri. Returns null if no type is registered. */ -QQmlType QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor) +QQmlType QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, + QTypeRevision version) { - Q_ASSERT(version_major >= 0 && version_minor >= 0); + Q_ASSERT(version.hasMajorVersion() && version.hasMinorVersion()); const QQmlMetaTypeDataPtr data; QQmlMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.constFind(metaObject); while (it != data->metaObjectToType.cend() && it.key() == metaObject) { QQmlType t(*it); - if (version_major < 0 || module.isEmpty() || t.availableInVersion(module, version_major,version_minor)) + if (module.isEmpty() || t.availableInVersion(module, version)) return t; ++it; } @@ -1181,7 +1198,7 @@ QQmlType QQmlMetaType::qmlType(int typeId, TypeIdCategory category) if (category == TypeIdCategory::MetaType) { QQmlTypePrivate *type = data->idToType.value(typeId); - if (type && type->typeId == typeId) + if (type && type->typeId.id() == typeId) return QQmlType(type); } else if (category == TypeIdCategory::QmlType) { QQmlType type = data->types.value(typeId); @@ -1212,16 +1229,16 @@ QQmlType QQmlMetaType::qmlType(const QUrl &unNormalizedUrl, bool includeNonFileI return QQmlType(); } -QQmlPropertyCache *QQmlMetaType::propertyCache(const QMetaObject *metaObject, int minorVersion) +QQmlPropertyCache *QQmlMetaType::propertyCache(const QMetaObject *metaObject, QTypeRevision version) { QQmlMetaTypeDataPtr data; // not const: the cache is created on demand - return data->propertyCache(metaObject, minorVersion); + return data->propertyCache(metaObject, version); } -QQmlPropertyCache *QQmlMetaType::propertyCache(const QQmlType &type, int minorVersion) +QQmlPropertyCache *QQmlMetaType::propertyCache(const QQmlType &type, QTypeRevision version) { QQmlMetaTypeDataPtr data; // not const: the cache is created on demand - return data->propertyCache(type, minorVersion); + return data->propertyCache(type, version); } void QQmlMetaType::unregisterType(int typeIndex) @@ -1236,7 +1253,7 @@ void QQmlMetaType::unregisterType(int typeIndex) removeQQmlTypePrivate(data->metaObjectToType, d); for (auto & module : data->uriToModule) module->remove(d); - data->clearPropertyCachesForMinorVersion(typeIndex); + data->clearPropertyCachesForVersion(typeIndex); data->types[typeIndex] = QQmlType(); data->undeletableTypes.remove(type); } @@ -1268,7 +1285,7 @@ void QQmlMetaType::freeUnusedTypesAndCaches() for (auto &module : data->uriToModule) module->remove(d); - data->clearPropertyCachesForMinorVersion(d->index); + data->clearPropertyCachesForVersion(d->index); *it = QQmlType(); } else { ++it; diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index 037cf89beb..28d647520d 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -65,11 +65,9 @@ namespace QV4 { class ExecutableCompilationUnit; } struct CompositeMetaTypeIds { - int id = -1; - int listId = -1; - CompositeMetaTypeIds() = default; - CompositeMetaTypeIds(int id, int listId) : id(id), listId(listId) {} - bool isValid() const { return id != -1 && listId != -1; } + QMetaType id; + QMetaType listId; + bool isValid() const { return id.isValid() && listId.isValid(); } }; class Q_QML_PRIVATE_EXPORT QQmlMetaType @@ -81,20 +79,20 @@ public: static QQmlType registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingletonType &type); static QQmlType registerCompositeType(const QQmlPrivate::RegisterCompositeType &type); static bool registerPluginTypes(QObject *instance, const QString &basePath, - const QString &uri, const QString &typeNamespace, int vmaj, - QList<QQmlError> *errors); + const QString &uri, const QString &typeNamespace, + QTypeRevision version, QList<QQmlError> *errors); static QQmlType typeForUrl(const QString &urlString, const QHashedStringRef& typeName, bool isCompositeSingleton, QList<QQmlError> *errors, - int majorVersion = -1, int minorVersion = -1); + QTypeRevision version = QTypeRevision()); static void unregisterType(int type); static CompositeMetaTypeIds registerInternalCompositeType(const QByteArray &className); static void unregisterInternalCompositeType(const CompositeMetaTypeIds &typeIds); - static void registerModule(const char *uri, int versionMajor, int versionMinor); - static bool protectModule(const QString &uri, int majVersion); + static void registerModule(const char *uri, QTypeRevision version); + static bool protectModule(const QString &uri, QTypeRevision version); - static int typeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName); + static int typeId(const char *uri, QTypeRevision version, const char *qmlName); static void registerUndeletableType(const QQmlType &dtype); @@ -108,15 +106,16 @@ public: QmlType }; - static QQmlType qmlType(const QString &qualifiedName, int, int); - static QQmlType qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int, int); + static QQmlType qmlType(const QString &qualifiedName, QTypeRevision version); + static QQmlType qmlType(const QHashedStringRef &name, const QHashedStringRef &module, QTypeRevision version); static QQmlType qmlType(const QMetaObject *); - static QQmlType qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor); + static QQmlType qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, QTypeRevision version); static QQmlType qmlType(int typeId, TypeIdCategory category = TypeIdCategory::MetaType); static QQmlType qmlType(const QUrl &unNormalizedUrl, bool includeNonFileImports = false); - static QQmlPropertyCache *propertyCache(const QMetaObject *metaObject, int minorVersion = -1); - static QQmlPropertyCache *propertyCache(const QQmlType &type, int minorVersion); + static QQmlPropertyCache *propertyCache(const QMetaObject *metaObject, + QTypeRevision version = QTypeRevision()); + static QQmlPropertyCache *propertyCache(const QQmlType &type, QTypeRevision version); static void freeUnusedTypesAndCaches(); @@ -150,9 +149,9 @@ public: static StringConverter customStringConverter(int); static bool isAnyModule(const QString &uri); - static bool isLockedModule(const QString &uri, int majorVersion); - static bool isModule(const QString &module, int versionMajor, int versionMinor); - static QQmlTypeModule *typeModule(const QString &uri, int majorVersion); + static bool isLockedModule(const QString &uri, QTypeRevision version); + static bool isModule(const QString &module, QTypeRevision version); + static QQmlTypeModule *typeModule(const QString &uri, QTypeRevision version); static QList<QQmlPrivate::AutoParentFunction> parentFunctions(); @@ -197,11 +196,12 @@ public: static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo, const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd); - static void qmlInsertModuleRegistration(const QString &uri, int majorVersion, - void (*registerFunction)()); - static void qmlRemoveModuleRegistration(const QString &uri, int majorVersion); + static void qmlInsertModuleRegistration(const QString &uri, void (*registerFunction)()); + static void qmlRemoveModuleRegistration(const QString &uri); - static bool qmlRegisterModuleTypes(const QString &uri, int majorVersion); + static bool qmlRegisterModuleTypes(const QString &uri); + + static int qmlRegisteredListTypeCount(); }; Q_DECLARE_TYPEINFO(QQmlMetaType, Q_MOVABLE_TYPE); diff --git a/src/qml/qml/qqmlmetatypedata.cpp b/src/qml/qml/qqmlmetatypedata.cpp index ed885eaa97..a34a0c1ae4 100644 --- a/src/qml/qml/qqmlmetatypedata.cpp +++ b/src/qml/qml/qqmlmetatypedata.cpp @@ -78,9 +78,9 @@ void QQmlMetaTypeData::registerType(QQmlTypePrivate *priv) priv->release(); } -bool QQmlMetaTypeData::registerModuleTypes(const QQmlMetaTypeData::VersionedUri &versionedUri) +bool QQmlMetaTypeData::registerModuleTypes(const QString &uri) { - auto function = moduleTypeRegistrationFunctions.constFind(versionedUri); + auto function = moduleTypeRegistrationFunctions.constFind(uri); if (function != moduleTypeRegistrationFunctions.constEnd()) { (*function)(); return true; @@ -88,28 +88,28 @@ bool QQmlMetaTypeData::registerModuleTypes(const QQmlMetaTypeData::VersionedUri return false; } -QQmlPropertyCache *QQmlMetaTypeData::propertyCacheForMinorVersion(int index, int minorVersion) const +QQmlPropertyCache *QQmlMetaTypeData::propertyCacheForVersion(int index, QTypeRevision version) const { return (index < typePropertyCaches.length()) - ? typePropertyCaches.at(index).value(minorVersion).data() + ? typePropertyCaches.at(index).value(version).data() : nullptr; } -void QQmlMetaTypeData::setPropertyCacheForMinorVersion(int index, int minorVersion, - QQmlPropertyCache *cache) +void QQmlMetaTypeData::setPropertyCacheForVersion(int index, QTypeRevision version, + QQmlPropertyCache *cache) { if (index >= typePropertyCaches.length()) typePropertyCaches.resize(index + 1); - typePropertyCaches[index][minorVersion] = cache; + typePropertyCaches[index][version] = cache; } -void QQmlMetaTypeData::clearPropertyCachesForMinorVersion(int index) +void QQmlMetaTypeData::clearPropertyCachesForVersion(int index) { if (index < typePropertyCaches.length()) typePropertyCaches[index].clear(); } -QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject, int minorVersion) +QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject, QTypeRevision version) { if (QQmlPropertyCache *rv = propertyCaches.value(metaObject)) return rv; @@ -119,29 +119,36 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject propertyCaches.insert(metaObject, rv); return rv; } - QQmlPropertyCache *super = propertyCache(metaObject->superClass(), minorVersion); - QQmlPropertyCache *rv = super->copyAndAppend(metaObject, minorVersion); + QQmlPropertyCache *super = propertyCache(metaObject->superClass(), version); + QQmlPropertyCache *rv = super->copyAndAppend(metaObject, version); propertyCaches.insert(metaObject, rv); return rv; } -QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int minorVersion) +QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, QTypeRevision version) { Q_ASSERT(type.isValid()); - if (QQmlPropertyCache *pc = propertyCacheForMinorVersion(type.index(), minorVersion)) + if (QQmlPropertyCache *pc = propertyCacheForVersion(type.index(), version)) return pc; QVector<QQmlType> types; - int maxMinorVersion = 0; + quint8 maxMinorVersion = 0; const QMetaObject *metaObject = type.metaObject(); + const QTypeRevision combinedVersion = version.hasMajorVersion() + ? version + : (version.hasMinorVersion() + ? QTypeRevision::fromVersion(type.version().majorVersion(), + version.minorVersion()) + : type.version()); + while (metaObject) { - QQmlType t = QQmlMetaType::qmlType(metaObject, type.module(), type.majorVersion(), minorVersion); + QQmlType t = QQmlMetaType::qmlType(metaObject, type.module(), combinedVersion); if (t.isValid()) { - maxMinorVersion = qMax(maxMinorVersion, t.minorVersion()); + maxMinorVersion = qMax(maxMinorVersion, t.version().minorVersion()); types << t; } else { types << QQmlType(); @@ -150,12 +157,14 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int min metaObject = metaObject->superClass(); } - if (QQmlPropertyCache *pc = propertyCacheForMinorVersion(type.index(), maxMinorVersion)) { - setPropertyCacheForMinorVersion(type.index(), minorVersion, pc); + const QTypeRevision maxVersion = QTypeRevision::fromVersion(combinedVersion.majorVersion(), + maxMinorVersion); + if (QQmlPropertyCache *pc = propertyCacheForVersion(type.index(), maxVersion)) { + setPropertyCacheForVersion(type.index(), maxVersion, pc); return pc; } - QQmlPropertyCache *raw = propertyCache(type.metaObject(), minorVersion); + QQmlPropertyCache *raw = propertyCache(type.metaObject(), combinedVersion); bool hasCopied = false; @@ -164,7 +173,7 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int min if (!currentType.isValid()) continue; - int rev = currentType.metaObjectRevision(); + QTypeRevision rev = currentType.metaObjectRevision(); int moIndex = types.count() - 1 - ii; if (raw->allowedRevision(moIndex) != rev) { @@ -222,13 +231,13 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int min } #endif - setPropertyCacheForMinorVersion(type.index(), minorVersion, raw); + setPropertyCacheForVersion(type.index(), version, raw); if (hasCopied) raw->release(); - if (minorVersion != maxMinorVersion) - setPropertyCacheForMinorVersion(type.index(), maxMinorVersion, raw); + if (version != maxVersion) + setPropertyCacheForVersion(type.index(), maxVersion, raw); return raw; } diff --git a/src/qml/qml/qqmlmetatypedata_p.h b/src/qml/qml/qqmlmetatypedata_p.h index e51d4ca1a4..322ead084a 100644 --- a/src/qml/qml/qqmlmetatypedata_p.h +++ b/src/qml/qml/qqmlmetatypedata_p.h @@ -57,7 +57,6 @@ #include <QtCore/qset.h> #include <QtCore/qvector.h> -#include <QtCore/qbitarray.h> QT_BEGIN_NAMESPACE @@ -83,29 +82,28 @@ struct QQmlMetaTypeData MetaObjects metaObjectToType; typedef QHash<int, QQmlMetaType::StringConverter> StringConverters; StringConverters stringConverters; - QVector<QHash<int, QQmlRefPointer<QQmlPropertyCache>>> typePropertyCaches; + QVector<QHash<QTypeRevision, QQmlRefPointer<QQmlPropertyCache>>> typePropertyCaches; struct VersionedUri { - VersionedUri() - : majorVersion(0) {} - VersionedUri(const QHashedString &uri, int majorVersion) - : uri(uri), majorVersion(majorVersion) {} + VersionedUri() : majorVersion(0) {} + VersionedUri(const QHashedString &uri, QTypeRevision version) + : uri(uri), majorVersion(version.majorVersion()) {} bool operator==(const VersionedUri &other) const { return other.majorVersion == majorVersion && other.uri == uri; } QHashedString uri; - int majorVersion; + quint8 majorVersion; }; typedef QHash<VersionedUri, QQmlTypeModule *> TypeModules; TypeModules uriToModule; - QHash<VersionedUri, void (*)()> moduleTypeRegistrationFunctions; - bool registerModuleTypes(const VersionedUri &versionedUri); + QHash<QString, void (*)()> moduleTypeRegistrationFunctions; + bool registerModuleTypes(const QString &uri); - QBitArray objects; - QBitArray interfaces; - QBitArray lists; + QSet<int> interfaces; + QSet<int> objects; + QSet<int> lists; QList<QQmlPrivate::AutoParentFunction> parentFunctions; QVector<QQmlPrivate::QmlUnitCacheLookupFunction> lookupCachedQmlUnit; @@ -114,12 +112,12 @@ struct QQmlMetaTypeData QHash<const QMetaObject *, QQmlPropertyCache *> propertyCaches; - QQmlPropertyCache *propertyCacheForMinorVersion(int index, int minorVersion) const; - void setPropertyCacheForMinorVersion(int index, int minorVersion, QQmlPropertyCache *cache); - void clearPropertyCachesForMinorVersion(int index); + QQmlPropertyCache *propertyCacheForVersion(int index, QTypeRevision version) const; + void setPropertyCacheForVersion(int index, QTypeRevision version, QQmlPropertyCache *cache); + void clearPropertyCachesForVersion(int index); - QQmlPropertyCache *propertyCache(const QMetaObject *metaObject, int minorVersion); - QQmlPropertyCache *propertyCache(const QQmlType &type, int minorVersion); + QQmlPropertyCache *propertyCache(const QMetaObject *metaObject, QTypeRevision version); + QQmlPropertyCache *propertyCache(const QQmlType &type, QTypeRevision version); void setTypeRegistrationFailures(QStringList *failures) { diff --git a/src/qml/qml/qqmlmoduleregistration.cpp b/src/qml/qml/qqmlmoduleregistration.cpp index b7bc3555a6..422a5c0551 100644 --- a/src/qml/qml/qqmlmoduleregistration.cpp +++ b/src/qml/qml/qqmlmoduleregistration.cpp @@ -39,27 +39,33 @@ #include <QtQml/private/qqmlmetatype_p.h> #include <QtQml/qqmlmoduleregistration.h> +#include <QtCore/qversionnumber.h> QT_BEGIN_NAMESPACE struct QQmlModuleRegistrationPrivate { const QString uri; - const int majorVersion; }; +QQmlModuleRegistration::QQmlModuleRegistration(const char *uri, void (*registerFunction)()) : + d(new QQmlModuleRegistrationPrivate { QString::fromUtf8(uri) }) +{ + QQmlMetaType::qmlInsertModuleRegistration(d->uri, registerFunction); +} + +#if QT_DEPRECATED_SINCE(6, 0) QQmlModuleRegistration::QQmlModuleRegistration( - const char *uri, int majorVersion, - void (*registerFunction)()) : - d(new QQmlModuleRegistrationPrivate { QString::fromUtf8(uri), majorVersion }) + const char *uri, int majorVersion, void (*registerFunction)()) : + QQmlModuleRegistration(uri, registerFunction) { - QQmlMetaType::qmlInsertModuleRegistration(d->uri, d->majorVersion, - registerFunction); + Q_UNUSED(majorVersion); } +#endif QQmlModuleRegistration::~QQmlModuleRegistration() { - QQmlMetaType::qmlRemoveModuleRegistration(d->uri, d->majorVersion); + QQmlMetaType::qmlRemoveModuleRegistration(d->uri); delete d; } diff --git a/src/qml/qml/qqmlmoduleregistration.h b/src/qml/qml/qqmlmoduleregistration.h index 6f553a2823..3db535faa0 100644 --- a/src/qml/qml/qqmlmoduleregistration.h +++ b/src/qml/qml/qqmlmoduleregistration.h @@ -49,9 +49,14 @@ class Q_QML_EXPORT QQmlModuleRegistration { Q_DISABLE_COPY_MOVE(QQmlModuleRegistration) public: - QQmlModuleRegistration(const char *uri, int majorVersion, void (*registerFunction)()); + QQmlModuleRegistration(const char *uri, void (*registerFunction)()); ~QQmlModuleRegistration(); +#if QT_DEPRECATED_SINCE(6, 0) + QT_DEPRECATED_X("Use registration without major version") + QQmlModuleRegistration(const char *uri, int majorVersion, void (*registerFunction)()); +#endif + private: QQmlModuleRegistrationPrivate *d = nullptr; }; diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 198ce98f2d..538a87ff5b 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -56,6 +56,7 @@ #include <private/qqmldebugconnector_p.h> #include <private/qqmldebugserviceinterfaces_p.h> #include <private/qqmlscriptdata_p.h> +#include <private/qqmlsourcecoordinate_p.h> #include <private/qjsvalue_p.h> #include <private/qv4generatorobject_p.h> @@ -173,7 +174,7 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI context = new QQmlContextData; context->isInternal = true; context->imports = compilationUnit->typeNameCache; - context->initFromTypeCompilationUnit(compilationUnit, flags & CreationFlags::NormalObject ? subComponentIndex : -1); + context->initFromTypeCompilationUnit(compilationUnit, subComponentIndex); context->setParent(parentContext); if (!sharedState->rootContext) { @@ -856,12 +857,12 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper if (stringAt(obj->inheritedTypeNameIndex).isEmpty()) { QObject *groupObject = nullptr; - QQmlValueType *valueType = nullptr; + QQmlGadgetPtrWrapper *valueType = nullptr; const QQmlPropertyData *valueTypeProperty = nullptr; QObject *bindingTarget = _bindingTarget; if (QQmlValueTypeFactory::isValueType(bindingProperty->propType())) { - valueType = QQmlValueTypeFactory::valueType(bindingProperty->propType()); + valueType = QQmlGadgetPtrWrapper::instance(engine, bindingProperty->propType()); if (!valueType) { recordError(binding->location, tr("Cannot set properties on %1 as it is null").arg(stringAt(binding->propertyNameIndex))); return false; @@ -1135,8 +1136,8 @@ void QQmlObjectCreator::recordError(const QV4::CompiledData::Location &location, { QQmlError error; error.setUrl(compilationUnit->url()); - error.setLine(location.line); - error.setColumn(location.column); + error.setLine(qmlConvertSourceCoordinate<quint32, int>(location.line)); + error.setColumn(qmlConvertSourceCoordinate<quint32, int>(location.column)); error.setDescription(description); errors << error; } @@ -1147,11 +1148,6 @@ void QQmlObjectCreator::registerObjectWithContextById(const QV4::CompiledData::O context->setIdProperty(object->id, instance); } -void QQmlObjectCreator::createQmlContext() -{ - _qmlContext->setM(QV4::QmlContext::create(v4->rootContext(), context, _scopeObject)); -} - QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isContextObject) { const QV4::CompiledData::Object *obj = compilationUnit->objectAt(index); @@ -1264,7 +1260,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); @@ -1505,15 +1504,45 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject * if (_compiledObject->flags & QV4::CompiledData::Object::HasDeferredBindings) _ddata->deferData(_compiledObjectIndex, compilationUnit, context); + QSet<QString> postHocRequired; + for (auto it = _compiledObject->requiredPropertyExtraDataBegin(); it != _compiledObject->requiredPropertyExtraDataEnd(); ++it) + postHocRequired.insert(stringAt(it->nameIndex)); + bool hadInheritedRequiredProperties = !postHocRequired.empty(); + for (int propertyIndex = 0; propertyIndex != _compiledObject->propertyCount(); ++propertyIndex) { const QV4::CompiledData::Property* property = _compiledObject->propertiesBegin() + propertyIndex; QQmlPropertyData *propertyData = _propertyCache->property(_propertyCache->propertyOffset() + propertyIndex); - if (property->isRequired) { - sharedState->hadRequiredProperties = true; - sharedState->requiredProperties.insert(propertyData, - RequiredPropertyInfo {compilationUnit->stringAt(property->nameIndex), compilationUnit->finalUrl(), property->location, {}}); - } + // only compute stringAt if there's a chance for the lookup to succeed + auto postHocIt = postHocRequired.isEmpty() ? postHocRequired.end() : postHocRequired.find(stringAt(property->nameIndex)); + if (!property->isRequired && postHocRequired.end() == postHocIt) + continue; + if (postHocIt != postHocRequired.end()) + postHocRequired.erase(postHocIt); + sharedState->hadRequiredProperties = true; + sharedState->requiredProperties.insert(propertyData, + RequiredPropertyInfo {compilationUnit->stringAt(property->nameIndex), compilationUnit->finalUrl(), property->location, {}}); + + } + + for (int i = 0; i <= _propertyCache->propertyOffset(); ++i) { + QQmlPropertyData *propertyData = _propertyCache->maybeUnresolvedProperty(i); + if (!propertyData) + continue; + if (!propertyData->isRequired() && postHocRequired.isEmpty()) + continue; + QString name = propertyData->name(_qobject); + auto postHocIt = postHocRequired.find(name); + if (!propertyData->isRequired() && postHocRequired.end() == postHocIt ) + continue; + + if (postHocIt != postHocRequired.end()) + postHocRequired.erase(postHocIt); + + sharedState->hadRequiredProperties = true; + sharedState->requiredProperties.insert(propertyData, RequiredPropertyInfo {name, compilationUnit->finalUrl(), _compiledObject->location, {}}); } + if (!postHocRequired.isEmpty() && hadInheritedRequiredProperties) + recordError({}, QLatin1String("Property %1 was marked as required but does not exist").arg(*postHocRequired.begin())); if (_compiledObject->nFunctions > 0) setupFunctions(); diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h index f8ad90be15..50ce8d5909 100644 --- a/src/qml/qml/qqmlobjectcreator_p.h +++ b/src/qml/qml/qqmlobjectcreator_p.h @@ -86,7 +86,7 @@ struct RequiredPropertyInfo QVector<AliasToRequiredInfo> aliasesToRequired; }; -using RequiredProperties = QHash<QQmlPropertyData*, RequiredPropertyInfo>; +class RequiredProperties : public QHash<QQmlPropertyData*, RequiredPropertyInfo> {}; struct QQmlObjectCreatorSharedState : public QSharedData { @@ -162,7 +162,6 @@ private: void registerObjectWithContextById(const QV4::CompiledData::Object *object, QObject *instance) const; inline QV4::QmlContext *currentQmlContext(); - Q_NEVER_INLINE void createQmlContext(); QV4::ResolvedTypeReference *resolvedType(int id) const { return compilationUnit->resolvedType(id); diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h index 9504fc37dc..8a1cbc2ddf 100644 --- a/src/qml/qml/qqmlprivate.h +++ b/src/qml/qml/qqmlprivate.h @@ -63,24 +63,11 @@ #include <QtCore/qvariant.h> #include <QtCore/qurl.h> #include <QtCore/qpointer.h> +#include <QtCore/qversionnumber.h> #include <QtCore/qmetaobject.h> #include <QtCore/qdebug.h> -#define QML_GETTYPENAMES \ - const char *className = T::staticMetaObject.className(); \ - const int nameLen = int(strlen(className)); \ - QVarLengthArray<char,48> pointerName(nameLen+2); \ - memcpy(pointerName.data(), className, size_t(nameLen)); \ - pointerName[nameLen] = '*'; \ - pointerName[nameLen+1] = '\0'; \ - const int listLen = int(strlen("QQmlListProperty<")); \ - QVarLengthArray<char,64> listName(listLen + nameLen + 2); \ - memcpy(listName.data(), "QQmlListProperty<", size_t(listLen)); \ - memcpy(listName.data()+listLen, className, size_t(nameLen)); \ - listName[listLen+nameLen] = '>'; \ - listName[listLen+nameLen+1] = '\0'; - QT_BEGIN_NAMESPACE class QQmlPropertyValueInterceptor; @@ -124,6 +111,7 @@ class QJSValue; class QJSEngine; class QQmlEngine; class QQmlCustomParser; +class QQmlTypeNotAvailable; template<class T> QQmlCustomParser *qmlCreateCustomParser() @@ -342,17 +330,16 @@ namespace QQmlPrivate typedef AutoParentResult (*AutoParentFunction)(QObject *object, QObject *parent); struct RegisterType { - int version; + int structVersion; - int typeId; - int listId; + QMetaType typeId; + QMetaType listId; int objectSize; void (*create)(void *); QString noCreationReason; const char *uri; - int versionMajor; - int versionMinor; + QTypeRevision version; const char *elementName; const QMetaObject *metaObject; @@ -368,20 +355,20 @@ namespace QQmlPrivate QQmlCustomParser *customParser; - int revision; + QTypeRevision revision; // If this is extended ensure "version" is bumped!!! }; struct RegisterTypeAndRevisions { - int version; + int structVersion; - int typeId; - int listId; + QMetaType typeId; + QMetaType listId; int objectSize; void (*create)(void *); const char *uri; - int versionMajor; + QTypeRevision version; const QMetaObject *metaObject; const QMetaObject *classInfoMetaObject; @@ -400,12 +387,15 @@ namespace QQmlPrivate }; struct RegisterInterface { - int version; + int structVersion; - int typeId; - int listId; + QMetaType typeId; + QMetaType listId; const char *iid; + + const char *uri; + QTypeRevision version; }; struct RegisterAutoParent { @@ -415,48 +405,45 @@ namespace QQmlPrivate }; struct RegisterSingletonType { - int version; + int structVersion; const char *uri; - int versionMajor; - int versionMinor; + QTypeRevision version; const char *typeName; QJSValue (*scriptApi)(QQmlEngine *, QJSEngine *); QObject *(*qobjectApi)(QQmlEngine *, QJSEngine *); const QMetaObject *instanceMetaObject; // new in version 1 - int typeId; // new in version 2 - int revision; // new in version 2 + QMetaType typeId; // new in version 2 + QTypeRevision revision; // new in version 2 std::function<QObject*(QQmlEngine *, QJSEngine *)> generalizedQobjectApi; // new in version 3 // If this is extended ensure "version" is bumped!!! }; struct RegisterSingletonTypeAndRevisions { - int version; + int structVersion; const char *uri; - int versionMajor; + QTypeRevision version; QJSValue (*scriptApi)(QQmlEngine *, QJSEngine *); const QMetaObject *instanceMetaObject; const QMetaObject *classInfoMetaObject; - int typeId; + QMetaType typeId; std::function<QObject*(QQmlEngine *, QJSEngine *)> generalizedQobjectApi; // new in version 3 }; struct RegisterCompositeType { QUrl url; const char *uri; - int versionMajor; - int versionMinor; + QTypeRevision version; const char *typeName; }; struct RegisterCompositeSingletonType { QUrl url; const char *uri; - int versionMajor; - int versionMinor; + QTypeRevision version; const char *typeName; }; @@ -468,7 +455,7 @@ namespace QQmlPrivate typedef const CachedQmlUnit *(*QmlUnitCacheLookupFunction)(const QUrl &url); struct RegisterQmlUnitCacheHook { - int version; + int structVersion; QmlUnitCacheLookupFunction lookupCachedQmlUnit; }; @@ -512,11 +499,13 @@ namespace QQmlPrivate return metaObject->classInfo(indexOfOwnClassInfo(metaObject, key)).value(); } - inline int intClassInfo(const QMetaObject *metaObject, const char *key, int defaultValue = 0) + inline QTypeRevision revisionClassInfo(const QMetaObject *metaObject, const char *key, + QTypeRevision defaultValue = QTypeRevision()) { const int index = indexOfOwnClassInfo(metaObject, key); return (index == -1) ? defaultValue - : QByteArray(metaObject->classInfo(index).value()).toInt(); + : QTypeRevision::fromEncodedVersion( + QByteArray(metaObject->classInfo(index).value()).toInt()); } inline bool boolClassInfo(const QMetaObject *metaObject, const char *key, @@ -579,24 +568,34 @@ namespace QQmlPrivate static constexpr bool Value = bool(T::QmlIsSingleton::yes); }; + template<class T, class = QmlVoidT<>> + struct QmlInterface + { + static constexpr bool Value = false; + }; + + template<class T> + struct QmlInterface<T, QmlVoidT<typename T::QmlIsInterface>> + { + static constexpr bool Value = bool(T::QmlIsInterface::yes); + }; + template<typename T> void qmlRegisterSingletonAndRevisions(const char *uri, int versionMajor, const QMetaObject *classInfoMetaObject) { - QML_GETTYPENAMES - RegisterSingletonTypeAndRevisions api = { 0, uri, - versionMajor, + QTypeRevision::fromMajorVersion(versionMajor), nullptr, &T::staticMetaObject, classInfoMetaObject, - qRegisterNormalizedMetaType<T *>(pointerName.constData()), + QMetaType::fromType<T *>(), Constructors<T>::createSingletonInstance }; @@ -607,17 +606,15 @@ namespace QQmlPrivate void qmlRegisterTypeAndRevisions(const char *uri, int versionMajor, const QMetaObject *classInfoMetaObject) { - QML_GETTYPENAMES - RegisterTypeAndRevisions type = { 0, - qRegisterNormalizedMetaType<T *>(pointerName.constData()), - qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), + QMetaType::fromType<T*>(), + QMetaType::fromType<QQmlListProperty<T>>(), int(sizeof(T)), Constructors<T>::createInto, uri, - versionMajor, + QTypeRevision::fromMajorVersion(versionMajor), &T::staticMetaObject, classInfoMetaObject, @@ -637,6 +634,11 @@ namespace QQmlPrivate qmlregister(TypeAndRevisionsRegistration, &type); } + + template<> + void Q_QML_EXPORT qmlRegisterTypeAndRevisions<QQmlTypeNotAvailable, void>( + const char *uri, int versionMajor, const QMetaObject *classInfoMetaObject); + } // namespace QQmlPrivate QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index 93020661e2..8521de6ab3 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -353,10 +353,15 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name) if (terminal.count() >= 3 && terminal.at(0) == QLatin1Char('o') && terminal.at(1) == QLatin1Char('n') && - terminal.at(2).isUpper()) { + (terminal.at(2).isUpper() || terminal.at(2) == '_')) { QString signalName = terminal.mid(2).toString(); - signalName[0] = signalName.at(0).toLower(); + int firstNon_; + int length = signalName.length(); + for (firstNon_ = 0; firstNon_ < length; ++firstNon_) + if (signalName.at(firstNon_) != '_') + break; + signalName[firstNon_] = signalName.at(firstNon_).toLower(); // XXX - this code treats methods as signals @@ -1044,13 +1049,19 @@ QVariant QQmlProperty::read(const QObject *object, const QString &name, QQmlEngi QVariant QQmlPropertyPrivate::readValueProperty() { - if (isValueType()) { - - QQmlValueType *valueType = QQmlValueTypeFactory::valueType(core.propType()); - Q_ASSERT(valueType); - valueType->read(object, core.coreIndex()); - return valueType->metaObject()->property(valueTypeData.coreIndex()).read(valueType); + auto doRead = [&](QQmlGadgetPtrWrapper *wrapper) { + wrapper->read(object, core.coreIndex()); + return wrapper->property(valueTypeData.coreIndex()).read(wrapper); + }; + if (isValueType()) { + if (QQmlGadgetPtrWrapper *wrapper = QQmlGadgetPtrWrapper::instance(engine, core.propType())) + return doRead(wrapper); + if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(core.propType())) { + QQmlGadgetPtrWrapper wrapper(valueType, nullptr); + return doRead(&wrapper); + } + return QVariant(); } else if (core.isQList()) { QQmlListProperty<QObject> prop; @@ -1183,10 +1194,22 @@ QQmlPropertyPrivate::writeValueProperty(QObject *object, bool rv = false; if (valueTypeData.isValid()) { - QQmlValueType *writeBack = QQmlValueTypeFactory::valueType(core.propType()); - writeBack->read(object, core.coreIndex()); - rv = write(writeBack, valueTypeData, value, context, flags); - writeBack->write(object, core.coreIndex(), flags); + auto doWrite = [&](QQmlGadgetPtrWrapper *wrapper) { + wrapper->read(object, core.coreIndex()); + rv = write(wrapper, valueTypeData, value, context, flags); + wrapper->write(object, core.coreIndex(), flags); + }; + + QQmlGadgetPtrWrapper *wrapper = context + ? QQmlGadgetPtrWrapper::instance(context->engine, core.propType()) + : nullptr; + if (wrapper) { + doWrite(wrapper); + } else if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(core.propType())) { + QQmlGadgetPtrWrapper wrapper(valueType, nullptr); + doWrite(&wrapper); + } + } else { rv = write(object, core, value, context, flags); } diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index c4afbbd598..09e16fdbe0 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -75,6 +75,7 @@ static QQmlPropertyData::Flags fastFlagsForProperty(const QMetaProperty &p) flags.setIsWritable(p.isWritable()); flags.setIsResettable(p.isResettable()); flags.setIsFinal(p.isFinal()); + flags.setIsRequired(p.isRequired()); if (p.isEnumType()) flags.type = QQmlPropertyData::Flags::EnumType; @@ -82,13 +83,11 @@ static QQmlPropertyData::Flags fastFlagsForProperty(const QMetaProperty &p) return flags; } -// Flags that do depend on the property's QMetaProperty::userType() and thus are slow to -// load -static void flagsForPropertyType(int propType, QQmlPropertyData::Flags &flags) +// Flags that do depend on the property's QMetaType +static void flagsForPropertyType(QMetaType metaType, QQmlPropertyData::Flags &flags) { - Q_ASSERT(propType != -1); - - if (propType == QMetaType::QObjectStar) { + int propType = metaType.id(); + if (metaType.flags() & QMetaType::PointerToQObject) { flags.type = QQmlPropertyData::Flags::QObjectDerivedType; } else if (propType == QMetaType::QVariant) { flags.type = QQmlPropertyData::Flags::QVariantType; @@ -100,8 +99,7 @@ static void flagsForPropertyType(int propType, QQmlPropertyData::Flags &flags) flags.type = QQmlPropertyData::Flags::QJSValueType; } else { QQmlMetaType::TypeCategory cat = QQmlMetaType::typeCategory(propType); - - if (cat == QQmlMetaType::Object || QMetaType::typeFlags(propType) & QMetaType::PointerToQObject) + if (cat == QQmlMetaType::Object) flags.type = QQmlPropertyData::Flags::QObjectDerivedType; else if (cat == QQmlMetaType::List) flags.type = QQmlPropertyData::Flags::QListType; @@ -120,17 +118,17 @@ QQmlPropertyData::Flags QQmlPropertyData::flagsForProperty(const QMetaProperty &p) { auto flags = fastFlagsForProperty(p); - flagsForPropertyType(p.userType(), flags); + flagsForPropertyType(p.metaType(), flags); return flags; } static void populate(QQmlPropertyData *data, const QMetaProperty &p) { - Q_ASSERT(p.revision() <= Q_INT16_MAX); + Q_ASSERT(p.revision() <= std::numeric_limits<quint16>::max()); data->setCoreIndex(p.propertyIndex()); data->setNotifyIndex(QMetaObjectPrivate::signalIndex(p.notifySignal())); data->setFlags(fastFlagsForProperty(p)); - data->setRevision(p.revision()); + data->setRevision(QTypeRevision::fromEncodedVersion(p.revision())); } void QQmlPropertyData::lazyLoad(const QMetaProperty &p) @@ -153,8 +151,9 @@ void QQmlPropertyData::lazyLoad(const QMetaProperty &p) void QQmlPropertyData::load(const QMetaProperty &p) { populate(this, p); - setPropType(p.userType()); - flagsForPropertyType(propType(), m_flags); + QMetaType type = p.metaType(); + setPropType(type.id()); + flagsForPropertyType(type, m_flags); } void QQmlPropertyData::load(const QMetaMethod &m) @@ -182,8 +181,8 @@ void QQmlPropertyData::load(const QMetaMethod &m) if (m.attributes() & QMetaMethod::Cloned) m_flags.setIsCloned(true); - Q_ASSERT(m.revision() <= Q_INT16_MAX); - setRevision(m.revision()); + Q_ASSERT(m.revision() <= std::numeric_limits<quint16>::max()); + setRevision(QTypeRevision::fromEncodedVersion(m.revision())); } void QQmlPropertyData::lazyLoad(const QMetaMethod &m) @@ -211,14 +210,14 @@ QQmlPropertyCache::QQmlPropertyCache() /*! Creates a new QQmlPropertyCache of \a metaObject. */ -QQmlPropertyCache::QQmlPropertyCache(const QMetaObject *metaObject, int metaObjectRevision) +QQmlPropertyCache::QQmlPropertyCache(const QMetaObject *metaObject, QTypeRevision metaObjectRevision) : QQmlPropertyCache() { Q_ASSERT(metaObject); update(metaObject); - if (metaObjectRevision > 0) { + if (metaObjectRevision.isValid() && metaObjectRevision != QTypeRevision::zero()) { // Set the revision of the meta object that this cache describes to be // 'metaObjectRevision'. This is useful when constructing a property cache // from a type that was created directly in C++, and not through QML. For such @@ -290,14 +289,15 @@ QQmlPropertyCache *QQmlPropertyCache::copyAndReserve(int propertyCount, int meth This is different from QMetaMethod::methodIndex(). */ void QQmlPropertyCache::appendProperty(const QString &name, QQmlPropertyData::Flags flags, - int coreIndex, int propType, int minorVersion, int notifyIndex) + int coreIndex, int propType, QTypeRevision version, + int notifyIndex) { QQmlPropertyData data; data.setPropType(propType); data.setCoreIndex(coreIndex); data.setNotifyIndex(notifyIndex); data.setFlags(flags); - data.setTypeMinorVersion(minorVersion); + data.setTypeVersion(version); QQmlPropertyData *old = findNamedProperty(name); if (old) @@ -398,6 +398,19 @@ const QMetaObject *QQmlPropertyCache::createMetaObject() return _metaObject; } +QQmlPropertyData *QQmlPropertyCache::maybeUnresolvedProperty(int index) const +{ + if (index < 0 || index >= (propertyIndexCacheStart + propertyIndexCache.count())) + return nullptr; + + QQmlPropertyData *rv = nullptr; + if (index < propertyIndexCacheStart) + return _parent->maybeUnresolvedProperty(index); + else + rv = const_cast<QQmlPropertyData *>(&propertyIndexCache.at(index - propertyIndexCacheStart)); + return rv; +} + QQmlPropertyData *QQmlPropertyCache::defaultProperty() const { return property(defaultPropertyName(), nullptr, nullptr); @@ -419,12 +432,12 @@ QQmlPropertyCache::copyAndAppend(const QMetaObject *metaObject, QQmlPropertyData::Flags methodFlags, QQmlPropertyData::Flags signalFlags) { - return copyAndAppend(metaObject, -1, propertyFlags, methodFlags, signalFlags); + return copyAndAppend(metaObject, QTypeRevision(), propertyFlags, methodFlags, signalFlags); } QQmlPropertyCache * QQmlPropertyCache::copyAndAppend(const QMetaObject *metaObject, - int typeMinorVersion, + QTypeRevision typeVersion, QQmlPropertyData::Flags propertyFlags, QQmlPropertyData::Flags methodFlags, QQmlPropertyData::Flags signalFlags) @@ -438,13 +451,13 @@ QQmlPropertyCache::copyAndAppend(const QMetaObject *metaObject, QMetaObjectPrivate::get(metaObject)->signalCount + QMetaObjectPrivate::get(metaObject)->propertyCount); - rv->append(metaObject, typeMinorVersion, propertyFlags, methodFlags, signalFlags); + rv->append(metaObject, typeVersion, propertyFlags, methodFlags, signalFlags); return rv; } void QQmlPropertyCache::append(const QMetaObject *metaObject, - int typeMinorVersion, + QTypeRevision typeVersion, QQmlPropertyData::Flags propertyFlags, QQmlPropertyData::Flags methodFlags, QQmlPropertyData::Flags signalFlags) @@ -453,7 +466,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject, bool dynamicMetaObject = isDynamicMetaObject(metaObject); - allowedRevisionCache.append(0); + allowedRevisionCache.append(QTypeRevision::zero()); int methodCount = metaObject->methodCount(); Q_ASSERT(QMetaObjectPrivate::get(metaObject)->revision >= 4); @@ -598,7 +611,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject, data->setFlags(propertyFlags); data->lazyLoad(p); - data->setTypeMinorVersion(typeMinorVersion); + data->setTypeVersion(typeVersion); data->m_flags.setIsDirect(!dynamicMetaObject); @@ -672,7 +685,7 @@ void QQmlPropertyCache::resolve(QQmlPropertyData *data) const data->setPropType(registerResult == -1 ? QMetaType::UnknownType : registerResult); } } - flagsForPropertyType(data->propType(), data->m_flags); + flagsForPropertyType(QMetaType(data->propType()), data->m_flags); } } @@ -683,7 +696,7 @@ void QQmlPropertyCache::updateRecur(const QMetaObject *metaObject) updateRecur(metaObject->superClass()); - append(metaObject, -1); + append(metaObject, QTypeRevision()); } void QQmlPropertyCache::update(const QMetaObject *metaObject) @@ -731,7 +744,7 @@ void QQmlPropertyCache::invalidate(const QMetaObject *metaObject) methodIndexCacheStart = parent()->methodIndexCache.count() + parent()->methodIndexCacheStart; signalHandlerIndexCacheStart = parent()->signalHandlerIndexCache.count() + parent()->signalHandlerIndexCacheStart; stringCache.linkAndReserve(parent()->stringCache, reserve); - append(metaObject, -1); + append(metaObject, QTypeRevision()); } else { propertyIndexCacheStart = 0; methodIndexCacheStart = 0; diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index bfd78eef88..9e6eaf9778 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -60,6 +60,7 @@ #include <private/qlinkedstringhash_p.h> #include <QtCore/qvarlengtharray.h> #include <QtCore/qvector.h> +#include <QtCore/qversionnumber.h> #include <private/qv4value_p.h> #include <private/qqmlpropertydata_p.h> @@ -80,7 +81,7 @@ class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount { public: QQmlPropertyCache(); - QQmlPropertyCache(const QMetaObject *, int metaObjectRevision = 0); + QQmlPropertyCache(const QMetaObject *, QTypeRevision metaObjectRevision = QTypeRevision::zero()); ~QQmlPropertyCache() override; void update(const QMetaObject *); @@ -92,7 +93,8 @@ public: QQmlPropertyData::Flags propertyFlags = QQmlPropertyData::Flags(), QQmlPropertyData::Flags methodFlags = QQmlPropertyData::Flags(), QQmlPropertyData::Flags signalFlags = QQmlPropertyData::Flags()); - QQmlPropertyCache *copyAndAppend(const QMetaObject *, int typeMinorVersion, + QQmlPropertyCache *copyAndAppend( + const QMetaObject *, QTypeRevision typeVersion, QQmlPropertyData::Flags propertyFlags = QQmlPropertyData::Flags(), QQmlPropertyData::Flags methodFlags = QQmlPropertyData::Flags(), QQmlPropertyData::Flags signalFlags = QQmlPropertyData::Flags()); @@ -100,7 +102,7 @@ public: QQmlPropertyCache *copyAndReserve(int propertyCount, int methodCount, int signalCount, int enumCount); void appendProperty(const QString &, QQmlPropertyData::Flags flags, int coreIndex, - int propType, int revision, int notifyIndex); + int propType, QTypeRevision revision, int notifyIndex); void appendSignal(const QString &, QQmlPropertyData::Flags, int coreIndex, const int *types = nullptr, const QList<QByteArray> &names = QList<QByteArray>()); void appendMethod(const QString &, QQmlPropertyData::Flags flags, int coreIndex, int returnType, @@ -118,6 +120,7 @@ public: } QQmlPropertyData *property(int) const; + QQmlPropertyData *maybeUnresolvedProperty(int) const; QQmlPropertyData *method(int) const; QQmlPropertyData *signal(int index) const; QQmlEnumData *qmlEnum(int) const; @@ -173,8 +176,8 @@ public: QByteArray checksum(bool *ok); - int allowedRevision(int index) const { return allowedRevisionCache[index]; } - void setAllowedRevision(int index, int allowed) { allowedRevisionCache[index] = allowed; } + QTypeRevision allowedRevision(int index) const { return allowedRevisionCache[index]; } + void setAllowedRevision(int index, QTypeRevision allowed) { allowedRevisionCache[index] = allowed; } private: friend class QQmlEnginePrivate; @@ -186,7 +189,7 @@ private: inline QQmlPropertyCache *copy(int reserve); - void append(const QMetaObject *, int typeMinorVersion, + void append(const QMetaObject *, QTypeRevision typeVersion, QQmlPropertyData::Flags propertyFlags = QQmlPropertyData::Flags(), QQmlPropertyData::Flags methodFlags = QQmlPropertyData::Flags(), QQmlPropertyData::Flags signalFlags = QQmlPropertyData::Flags()); @@ -195,7 +198,7 @@ private: typedef QVector<QQmlPropertyData> IndexCache; typedef QLinkedStringMultiHash<QPair<int, QQmlPropertyData *> > StringCache; - typedef QVector<int> AllowedRevisionCache; + typedef QVector<QTypeRevision> AllowedRevisionCache; QQmlPropertyData *findProperty(StringCache::ConstIterator it, QObject *, QQmlContextData *) const; QQmlPropertyData *findProperty(StringCache::ConstIterator it, const QQmlVMEMetaObject *, QQmlContextData *) const; @@ -351,8 +354,9 @@ QQmlPropertyCache::overrideData(QQmlPropertyData *data) const bool QQmlPropertyCache::isAllowedInRevision(QQmlPropertyData *data) const { - return (data->metaObjectOffset() == -1 && data->revision() == 0) || - (allowedRevisionCache[data->metaObjectOffset()] >= data->revision()); + return (data->metaObjectOffset() == -1 && data->revision() == QTypeRevision::zero()) + || (allowedRevisionCache[data->metaObjectOffset()].toEncodedVersion<quint16>() + >= data->revision().toEncodedVersion<quint16>()); } int QQmlPropertyCache::propertyCount() const diff --git a/src/qml/qml/qqmlpropertycachecreator.cpp b/src/qml/qml/qqmlpropertycachecreator.cpp index 36581bda4e..f132fb2d78 100644 --- a/src/qml/qml/qqmlpropertycachecreator.cpp +++ b/src/qml/qml/qqmlpropertycachecreator.cpp @@ -119,9 +119,12 @@ QQmlRefPointer<QQmlPropertyCache> QQmlBindingInstantiationContext::instantiating { if (instantiatingProperty) { if (instantiatingProperty->isQObject()) { - return enginePrivate->rawPropertyCacheForType(instantiatingProperty->propType(), instantiatingProperty->typeMinorVersion()); + // rawPropertyCacheForType assumes a given unspecified version means "any version". + // There is another overload that takes no version, which we shall not use here. + return enginePrivate->rawPropertyCacheForType(instantiatingProperty->propType(), + instantiatingProperty->typeVersion()); } else if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(instantiatingProperty->propType())) { - return enginePrivate->cache(vtmo, instantiatingProperty->typeMinorVersion()); + return enginePrivate->cache(vtmo, instantiatingProperty->typeVersion()); } } return QQmlRefPointer<QQmlPropertyCache>(); diff --git a/src/qml/qml/qqmlpropertycachecreator_p.h b/src/qml/qml/qqmlpropertycachecreator_p.h index a050a0bf0a..cadbfdd481 100644 --- a/src/qml/qml/qqmlpropertycachecreator_p.h +++ b/src/qml/qml/qqmlpropertycachecreator_p.h @@ -56,19 +56,20 @@ #include <private/qqmlpropertyresolver_p.h> #include <private/qqmltypedata_p.h> #include <private/inlinecomponentutils_p.h> +#include <private/qqmlsourcecoordinate_p.h> #include <QScopedValueRollback> #include <vector> QT_BEGIN_NAMESPACE -inline QQmlJS::DiagnosticMessage qQmlCompileError(const QV4::CompiledData::Location &location, +inline QQmlError qQmlCompileError(const QV4::CompiledData::Location &location, const QString &description) { - QQmlJS::DiagnosticMessage error; - error.line = location.line; - error.column = location.column; - error.message = description; + QQmlError error; + error.setLine(qmlConvertSourceCoordinate<quint32, int>(location.line)); + error.setColumn(qmlConvertSourceCoordinate<quint32, int>(location.column)); + error.setDescription(description); return error; } @@ -117,16 +118,16 @@ public: const ObjectContainer *objectContainer, const QQmlImports *imports, const QByteArray &typeClassName); - QQmlJS::DiagnosticMessage buildMetaObjects(); + QQmlError buildMetaObjects(); enum class VMEMetaObjectIsRequired { Maybe, Always }; protected: - QQmlJS::DiagnosticMessage buildMetaObjectRecursively(int objectIndex, const QQmlBindingInstantiationContext &context, VMEMetaObjectIsRequired isVMERequired); - QQmlRefPointer<QQmlPropertyCache> propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlJS::DiagnosticMessage *error) const; - QQmlJS::DiagnosticMessage createMetaObject(int objectIndex, const CompiledObject *obj, const QQmlRefPointer<QQmlPropertyCache> &baseTypeCache); + QQmlError buildMetaObjectRecursively(int objectIndex, const QQmlBindingInstantiationContext &context, VMEMetaObjectIsRequired isVMERequired); + QQmlRefPointer<QQmlPropertyCache> propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlError *error) const; + QQmlError createMetaObject(int objectIndex, const CompiledObject *obj, const QQmlRefPointer<QQmlPropertyCache> &baseTypeCache); int metaTypeForParameter(const QV4::CompiledData::ParameterType ¶m, QString *customTypeName = nullptr); @@ -153,12 +154,13 @@ inline QQmlPropertyCacheCreator<ObjectContainer>::QQmlPropertyCacheCreator(QQmlP , propertyCaches(propertyCaches) , pendingGroupPropertyBindings(pendingGroupPropertyBindings) , typeClassName(typeClassName) + , currentRoot(-1) { propertyCaches->resize(objectContainer->objectCount()); } template <typename ObjectContainer> -inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjects() +inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjects() { using namespace icutils; QQmlBindingInstantiationContext context; @@ -185,8 +187,8 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::buil auto nodesSorted = topoSort(nodes, adjacencyList, hasCycle); if (hasCycle) { - QQmlJS::DiagnosticMessage diag; - diag.message = QLatin1String("Inline components form a cycle!"); + QQmlError diag; + diag.setDescription(QLatin1String("Inline components form a cycle!")); return diag; } @@ -200,7 +202,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::buil QByteArray icTypeName { objectContainer->stringAt(ic.nameIndex).toUtf8() }; QScopedValueRollback<QByteArray> nameChange {typeClassName, icTypeName}; QScopedValueRollback<unsigned int> rootChange {currentRoot, ic.objectIndex}; - QQmlJS::DiagnosticMessage diag = buildMetaObjectRecursively(ic.objectIndex, context, VMEMetaObjectIsRequired::Always); + QQmlError diag = buildMetaObjectRecursively(ic.objectIndex, context, VMEMetaObjectIsRequired::Always); if (diag.isValid()) { return diag; } @@ -212,7 +214,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::buil } template <typename ObjectContainer> -inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjectRecursively(int objectIndex, const QQmlBindingInstantiationContext &context, VMEMetaObjectIsRequired isVMERequired) +inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjectRecursively(int objectIndex, const QQmlBindingInstantiationContext &context, VMEMetaObjectIsRequired isVMERequired) { auto isAddressable = [](const QUrl &url) { const QString fileName = url.fileName(); @@ -241,7 +243,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::buil auto *typeRef = objectContainer->resolvedType(obj->inheritedTypeNameIndex); Q_ASSERT(typeRef); QQmlRefPointer<QQmlPropertyCache> baseTypeCache = typeRef->createPropertyCache(QQmlEnginePrivate::get(enginePrivate)); - QQmlJS::DiagnosticMessage error = createMetaObject(context.referencingObjectIndex, obj, baseTypeCache); + QQmlError error = createMetaObject(context.referencingObjectIndex, obj, baseTypeCache); if (error.isValid()) return error; } @@ -256,7 +258,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::buil QQmlRefPointer<QQmlPropertyCache> baseTypeCache; { - QQmlJS::DiagnosticMessage error; + QQmlError error; baseTypeCache = propertyCacheForObject(obj, context, &error); if (error.isValid()) return error; @@ -264,7 +266,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::buil if (baseTypeCache) { if (needVMEMetaObject) { - QQmlJS::DiagnosticMessage error = createMetaObject(objectIndex, obj, baseTypeCache); + QQmlError error = createMetaObject(objectIndex, obj, baseTypeCache); if (error.isValid()) return error; } else { @@ -286,18 +288,18 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::buil if (!context.resolveInstantiatingProperty()) pendingGroupPropertyBindings->append(context); - QQmlJS::DiagnosticMessage error = buildMetaObjectRecursively(binding->value.objectIndex, context, VMEMetaObjectIsRequired::Maybe); + QQmlError error = buildMetaObjectRecursively(binding->value.objectIndex, context, VMEMetaObjectIsRequired::Maybe); if (error.isValid()) return error; } } - QQmlJS::DiagnosticMessage noError; + QQmlError noError; return noError; } template <typename ObjectContainer> -inline QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCacheCreator<ObjectContainer>::propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlJS::DiagnosticMessage *error) const +inline QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCacheCreator<ObjectContainer>::propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlError *error) const { if (context.instantiatingProperty) { return context.instantiatingPropertyCache(enginePrivate); @@ -343,7 +345,7 @@ inline QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCacheCreator<ObjectContaine } template <typename ObjectContainer> -inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(int objectIndex, const CompiledObject *obj, const QQmlRefPointer<QQmlPropertyCache> &baseTypeCache) +inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(int objectIndex, const CompiledObject *obj, const QQmlRefPointer<QQmlPropertyCache> &baseTypeCache) { QQmlRefPointer<QQmlPropertyCache> cache; cache.adopt(baseTypeCache->copyAndReserve(obj->propertyCount() + obj->aliasCount(), @@ -537,7 +539,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::crea pend = obj->propertiesEnd(); for ( ; p != pend; ++p, ++propertyIdx) { int propertyType = 0; - int propertTypeMinorVersion = 0; + QTypeRevision propertyTypeVersion = QTypeRevision::zero(); QQmlPropertyData::Flags propertyFlags; const QV4::CompiledData::BuiltinType type = p->builtinType(); @@ -556,7 +558,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::crea QQmlType qmltype; bool selfReference = false; - if (!imports->resolveType(stringAt(p->builtinTypeOrTypeNameIndex), &qmltype, nullptr, nullptr, nullptr, + if (!imports->resolveType(stringAt(p->builtinTypeOrTypeNameIndex), &qmltype, nullptr, nullptr, nullptr, QQmlType::AnyRegistrationType, &selfReference)) { return qQmlCompileError(p->location, QQmlPropertyCacheCreatorBase::tr("Invalid property type")); } @@ -589,16 +591,16 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::crea } if (p->isList) { - propertyType = typeIds.listId; + propertyType = typeIds.listId.id(); } else { - propertyType = typeIds.id; + propertyType = typeIds.id.id(); } } else { if (p->isList) { - propertyType = qmltype.qListTypeId(); + propertyType = qmltype.qListTypeId().id(); } else { - propertyType = qmltype.typeId(); - propertTypeMinorVersion = qmltype.minorVersion(); + propertyType = qmltype.typeId().id(); + propertyTypeVersion = qmltype.version(); } } @@ -616,12 +618,12 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::crea if (!obj->defaultPropertyIsAlias && propertyIdx == obj->indexOfDefaultPropertyOrAlias) cache->_defaultPropertyName = propertyName; cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++, - propertyType, propertTypeMinorVersion, effectiveSignalIndex); + propertyType, propertyTypeVersion, effectiveSignalIndex); effectiveSignalIndex++; } - QQmlJS::DiagnosticMessage noError; + QQmlError noError; return noError; } @@ -640,15 +642,15 @@ inline int QQmlPropertyCacheCreator<ObjectContainer>::metaTypeForParameter(const *customTypeName = typeName; QQmlType qmltype; bool selfReference = false; - if (!imports->resolveType(typeName, &qmltype, nullptr, nullptr, nullptr, nullptr, QQmlType::AnyRegistrationType, - &selfReference)) + if (!imports->resolveType(typeName, &qmltype, nullptr, nullptr, nullptr, + QQmlType::AnyRegistrationType, &selfReference)) return QMetaType::UnknownType; if (!qmltype.isComposite()) - return qmltype.typeId(); + return qmltype.typeId().id(); if (selfReference) - return objectContainer->typeIdsForComponent().id; + return objectContainer->typeIdsForComponent().id.id(); QQmlRefPointer<QQmlTypeData> tdata = enginePrivate->typeLoader.getType(qmltype.sourceUrl()); Q_ASSERT(tdata); @@ -656,7 +658,7 @@ inline int QQmlPropertyCacheCreator<ObjectContainer>::metaTypeForParameter(const auto compilationUnit = tdata->compilationUnit(); - return compilationUnit->metaTypeId; + return compilationUnit->metaTypeId.id(); } template <typename ObjectContainer> @@ -669,11 +671,11 @@ public: void appendAliasPropertiesToMetaObjects(QQmlEnginePrivate *enginePriv); - QQmlJS::DiagnosticMessage appendAliasesToPropertyCache(const CompiledObject &component, int objectIndex, QQmlEnginePrivate *enginePriv); + QQmlError appendAliasesToPropertyCache(const CompiledObject &component, int objectIndex, QQmlEnginePrivate *enginePriv); private: void appendAliasPropertiesInMetaObjectsWithinComponent(const CompiledObject &component, int firstObjectIndex, QQmlEnginePrivate *enginePriv); - QQmlJS::DiagnosticMessage propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *rev, QQmlPropertyData::Flags *propertyFlags, QQmlEnginePrivate *enginePriv); + QQmlError propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, QTypeRevision *version, QQmlPropertyData::Flags *propertyFlags, QQmlEnginePrivate *enginePriv); void collectObjectsWithAliasesRecursively(int objectIndex, QVector<int> *objectsWithAliases) const; @@ -784,8 +786,10 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::collectObjectsWithAl } template <typename ObjectContainer> -inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *minorVersion, - QQmlPropertyData::Flags *propertyFlags, QQmlEnginePrivate *enginePriv) +inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias( + const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, + QTypeRevision *version, QQmlPropertyData::Flags *propertyFlags, + QQmlEnginePrivate *enginePriv) { *type = 0; bool writable = false; @@ -817,7 +821,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>: lastAlias = targetAlias; } while (lastAlias->aliasToLocalAlias); - return propertyDataForAlias(component, *lastAlias, type, minorVersion, propertyFlags, enginePriv); + return propertyDataForAlias(component, *lastAlias, type, version, propertyFlags, enginePriv); } const int targetObjectIndex = objectForId(component, alias.targetObjectId); @@ -836,11 +840,11 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>: } if (typeRef->type.isValid()) - *type = typeRef->type.typeId(); + *type = typeRef->type.typeId().id(); else - *type = typeRef->compilationUnit->metaTypeId; + *type = typeRef->compilationUnit->metaTypeId.id(); - *minorVersion = typeRef->minorVersion; + *version = typeRef->version; propertyFlags->type = QQmlPropertyData::Flags::QObjectDerivedType; } else { @@ -895,16 +899,16 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>: propertyFlags->setIsWritable(!(alias.flags & QV4::CompiledData::Alias::IsReadOnly) && writable); propertyFlags->setIsResettable(resettable); - return QQmlJS::DiagnosticMessage(); + return QQmlError(); } template <typename ObjectContainer> -inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasesToPropertyCache( +inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasesToPropertyCache( const CompiledObject &component, int objectIndex, QQmlEnginePrivate *enginePriv) { const CompiledObject &object = *objectContainer->objectAt(objectIndex); if (!object.aliasCount()) - return QQmlJS::DiagnosticMessage(); + return QQmlError(); QQmlPropertyCache *propertyCache = propertyCaches->at(objectIndex); Q_ASSERT(propertyCache); @@ -919,9 +923,10 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>: Q_ASSERT(alias->flags & QV4::CompiledData::Alias::Resolved); int type = 0; - int minorVersion = 0; + QTypeRevision version = QTypeRevision::zero(); QQmlPropertyData::Flags propertyFlags; - QQmlJS::DiagnosticMessage error = propertyDataForAlias(component, *alias, &type, &minorVersion, &propertyFlags, enginePriv); + QQmlError error = propertyDataForAlias(component, *alias, &type, &version, + &propertyFlags, enginePriv); if (error.isValid()) return error; @@ -931,10 +936,10 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>: propertyCache->_defaultPropertyName = propertyName; propertyCache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++, - type, minorVersion, effectiveSignalIndex++); + type, version, effectiveSignalIndex++); } - return QQmlJS::DiagnosticMessage(); + return QQmlError(); } template <typename ObjectContainer> diff --git a/src/qml/qml/qqmlpropertydata_p.h b/src/qml/qml/qqmlpropertydata_p.h index 2d9091edcd..f21b502b50 100644 --- a/src/qml/qml/qqmlpropertydata_p.h +++ b/src/qml/qml/qqmlpropertydata_p.h @@ -53,6 +53,7 @@ #include <private/qobject_p.h> #include <QtCore/qglobal.h> +#include <QtCore/qversionnumber.h> QT_BEGIN_NAMESPACE @@ -109,7 +110,7 @@ public: unsigned isFinalORisV4Function : 1; // Has FINAL flag OR Function takes QQmlV4Function* args unsigned isSignalHandler : 1; // Function is a signal handler unsigned isOverload : 1; // Function is an overload of another function - unsigned isCloned : 1; // The function was marked as cloned + unsigned isRequiredORisCloned : 1; // Has REQUIRED flag OR The function was marked as cloned unsigned isConstructor : 1; // The function was marked is a constructor unsigned isDirect : 1; // Exists on a C++ QMetaObject unsigned isOverridden : 1; // Is overridden by a extension property @@ -159,6 +160,11 @@ public: isDirect = b; } + void setIsRequired(bool b) { + Q_ASSERT(type != FunctionType); + isRequiredORisCloned = b; + } + void setIsVMEFunction(bool b) { Q_ASSERT(type == FunctionType); isConstantORisVMEFunction = b; @@ -193,7 +199,7 @@ public: void setIsCloned(bool b) { Q_ASSERT(type == FunctionType); - isCloned = b; + isRequiredORisCloned = b; } void setIsConstructor(bool b) { @@ -224,6 +230,7 @@ public: bool isFinal() const { return !isFunction() && m_flags.isFinalORisV4Function; } bool isOverridden() const { return m_flags.isOverridden; } bool isDirect() const { return m_flags.isOverload; } + bool isRequired() const { return !isFunction() && m_flags.isRequiredORisCloned; } bool hasStaticMetaCallFunction() const { return staticMetaCallFunction() != nullptr; } bool isFunction() const { return m_flags.type == Flags::FunctionType; } bool isQObject() const { return m_flags.type == Flags::QObjectDerivedType; } @@ -241,11 +248,11 @@ public: bool isSignalHandler() const { return m_flags.isSignalHandler; } bool isOverload() const { return m_flags.isOverload; } void setOverload(bool onoff) { m_flags.isOverload = onoff; } - bool isCloned() const { return isFunction() && m_flags.isCloned; } + bool isCloned() const { return isFunction() && m_flags.isRequiredORisCloned; } bool isConstructor() const { return m_flags.isConstructor; } bool hasOverride() const { return overrideIndex() >= 0; } - bool hasRevision() const { return revision() != 0; } + bool hasRevision() const { return revision() != QTypeRevision::zero(); } bool isFullyResolved() const { return !m_flags.notFullyResolved; } @@ -284,12 +291,8 @@ public: m_coreIndex = qint16(idx); } - quint8 revision() const { return m_revision; } - void setRevision(quint8 rev) - { - Q_ASSERT(rev <= std::numeric_limits<quint8>::max()); - m_revision = quint8(rev); - } + QTypeRevision revision() const { return m_revision; } + void setRevision(QTypeRevision revision) { m_revision = revision; } /* If a property is a C++ type, then we store the minor * version of this type. @@ -309,12 +312,8 @@ public: * */ - quint8 typeMinorVersion() const { return m_typeMinorVersion; } - void setTypeMinorVersion(quint8 rev) - { - Q_ASSERT(rev <= std::numeric_limits<quint8>::max()); - m_typeMinorVersion = quint8(rev); - } + QTypeRevision typeVersion() const { return m_typeVersion; } + void setTypeVersion(QTypeRevision typeVersion) { m_typeVersion = typeVersion; } QQmlPropertyCacheMethodArguments *arguments() const { return m_arguments; } void setArguments(QQmlPropertyCacheMethodArguments *args) { m_arguments = args; } @@ -406,18 +405,20 @@ private: qint16 m_notifyIndex = -1; qint16 m_overrideIndex = -1; - quint8 m_revision = 0; - quint8 m_typeMinorVersion = 0; qint16 m_metaObjectOffset = -1; + quint16 m_reserved = 0; + + QTypeRevision m_revision = QTypeRevision::zero(); + QTypeRevision m_typeVersion = QTypeRevision::zero(); QQmlPropertyCacheMethodArguments *m_arguments = nullptr; StaticMetaCallFunction m_staticMetaCallFunction = nullptr; }; #if QT_POINTER_SIZE == 4 - Q_STATIC_ASSERT(sizeof(QQmlPropertyData) == 24); + Q_STATIC_ASSERT(sizeof(QQmlPropertyData) == 28); #else // QT_POINTER_SIZE == 8 - Q_STATIC_ASSERT(sizeof(QQmlPropertyData) == 32); + Q_STATIC_ASSERT(sizeof(QQmlPropertyData) == 40); #endif bool QQmlPropertyData::operator==(const QQmlPropertyData &other) const @@ -438,7 +439,7 @@ QQmlPropertyData::Flags::Flags() , isFinalORisV4Function(false) , isSignalHandler(false) , isOverload(false) - , isCloned(false) + , isRequiredORisCloned(false) , isConstructor(false) , isOverridden(false) , type(OtherType) @@ -455,7 +456,7 @@ bool QQmlPropertyData::Flags::operator==(const QQmlPropertyData::Flags &other) c isFinalORisV4Function == other.isFinalORisV4Function && isOverridden == other.isOverridden && isSignalHandler == other.isSignalHandler && - isCloned == other.isCloned && + isRequiredORisCloned == other.isRequiredORisCloned && type == other.type && isConstructor == other.isConstructor && notFullyResolved == other.notFullyResolved && diff --git a/src/qml/qml/qqmlpropertyvalidator.cpp b/src/qml/qml/qqmlpropertyvalidator.cpp index 8762dc328d..312153576a 100644 --- a/src/qml/qml/qqmlpropertyvalidator.cpp +++ b/src/qml/qml/qqmlpropertyvalidator.cpp @@ -73,7 +73,7 @@ QQmlPropertyValidator::QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, c bindingPropertyDataPerObject->resize(compilationUnit->objectCount()); } -QVector<QQmlJS::DiagnosticMessage> QQmlPropertyValidator::validate() +QVector<QQmlError> QQmlPropertyValidator::validate() { return validateObject(/*root object*/0, /*instantiatingBinding*/nullptr); } @@ -96,7 +96,7 @@ struct BindingFinder } }; -QVector<QQmlJS::DiagnosticMessage> QQmlPropertyValidator::validateObject( +QVector<QQmlError> QQmlPropertyValidator::validateObject( int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty) const { const QV4::CompiledData::Object *obj = compilationUnit->objectAt(objectIndex); @@ -104,7 +104,7 @@ QVector<QQmlJS::DiagnosticMessage> QQmlPropertyValidator::validateObject( validateObject(it->objectIndex, /* instantiatingBinding*/ nullptr); } - if (obj->flags & QV4::CompiledData::Object::IsComponent) { + if (obj->flags & QV4::CompiledData::Object::IsComponent && !(obj->flags & QV4::CompiledData::Object::IsInlineComponentRoot)) { Q_ASSERT(obj->nBindings == 1); const QV4::CompiledData::Binding *componentBinding = obj->bindingTable(); Q_ASSERT(componentBinding->type == QV4::CompiledData::Binding::Type_Object); @@ -113,7 +113,7 @@ QVector<QQmlJS::DiagnosticMessage> QQmlPropertyValidator::validateObject( QQmlPropertyCache *propertyCache = propertyCaches.at(objectIndex); if (!propertyCache) - return QVector<QQmlJS::DiagnosticMessage>(); + return QVector<QQmlError>(); QQmlCustomParser *customParser = nullptr; if (auto typeRef = resolvedType(obj->inheritedTypeNameIndex)) { @@ -192,7 +192,10 @@ QVector<QQmlJS::DiagnosticMessage> QQmlPropertyValidator::validateObject( QString typeName = stringAt(obj->inheritedTypeNameIndex); auto *objectType = resolvedType(obj->inheritedTypeNameIndex); if (objectType && objectType->type.isValid()) { - return recordError(binding->location, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(name).arg(objectType->type.module()).arg(objectType->majorVersion).arg(objectType->minorVersion)); + return recordError(binding->location, tr("\"%1.%2\" is not available in %3 %4.%5.") + .arg(typeName).arg(name).arg(objectType->type.module()) + .arg(objectType->version.majorVersion()) + .arg(objectType->version.minorVersion())); } else { return recordError(binding->location, tr("\"%1.%2\" is not available due to component versioning.").arg(typeName).arg(name)); } @@ -212,7 +215,7 @@ QVector<QQmlJS::DiagnosticMessage> QQmlPropertyValidator::validateObject( if (name.constData()->isUpper() && !binding->isAttachedProperty()) { QQmlType type; QQmlImportNamespace *typeNamespace = nullptr; - imports.resolveType(stringAt(binding->propertyNameIndex), &type, nullptr, nullptr, &typeNamespace); + imports.resolveType(stringAt(binding->propertyNameIndex), &type, nullptr, &typeNamespace); if (typeNamespace) return recordError(binding->location, tr("Invalid use of namespace")); return recordError(binding->location, tr("Invalid attached object assignment")); @@ -223,7 +226,7 @@ QVector<QQmlJS::DiagnosticMessage> QQmlPropertyValidator::validateObject( = pd && QQmlValueTypeFactory::metaObjectForMetaType(pd->propType()) && !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment); - const QVector<QQmlJS::DiagnosticMessage> subObjectValidatorErrors + const QVector<QQmlError> subObjectValidatorErrors = validateObject(binding->value.objectIndex, binding, populatingValueTypeGroupProperty); if (!subObjectValidatorErrors.isEmpty()) @@ -280,11 +283,11 @@ QVector<QQmlJS::DiagnosticMessage> QQmlPropertyValidator::validateObject( } if (binding->type < QV4::CompiledData::Binding::Type_Script) { - QQmlJS::DiagnosticMessage bindingError = validateLiteralBinding(propertyCache, pd, binding); + QQmlError bindingError = validateLiteralBinding(propertyCache, pd, binding); if (bindingError.isValid()) return recordError(bindingError); } else if (binding->type == QV4::CompiledData::Binding::Type_Object) { - QQmlJS::DiagnosticMessage bindingError = validateObjectBinding(pd, name, binding); + QQmlError bindingError = validateObjectBinding(pd, name, binding); if (bindingError.isValid()) return recordError(bindingError); } else if (binding->isGroupProperty()) { @@ -346,24 +349,24 @@ QVector<QQmlJS::DiagnosticMessage> QQmlPropertyValidator::validateObject( customParser->validator = nullptr; customParser->engine = nullptr; customParser->imports = (QQmlImports*)nullptr; - QVector<QQmlJS::DiagnosticMessage> parserErrors = customParser->errors(); + QVector<QQmlError> parserErrors = customParser->errors(); if (!parserErrors.isEmpty()) return parserErrors; } (*bindingPropertyDataPerObject)[objectIndex] = collectedBindingPropertyData; - QVector<QQmlJS::DiagnosticMessage> noError; + QVector<QQmlError> noError; return noError; } -QQmlJS::DiagnosticMessage QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) const +QQmlError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) const { if (property->isQList()) { return qQmlCompileError(binding->valueLocation, tr("Cannot assign primitives to lists")); } - QQmlJS::DiagnosticMessage noError; + QQmlError noError; if (property->isEnum()) { if (binding->flags & QV4::CompiledData::Binding::IsResolvedEnum) @@ -387,8 +390,8 @@ QQmlJS::DiagnosticMessage QQmlPropertyValidator::validateLiteralBinding(QQmlProp if (binding->type == QV4::CompiledData::Binding::Type_Null) { QQmlError warning; warning.setUrl(compilationUnit->url()); - warning.setLine(binding->valueLocation.line); - warning.setColumn(binding->valueLocation.column); + warning.setLine(qmlConvertSourceCoordinate<quint32, int>(binding->valueLocation.line)); + warning.setColumn(qmlConvertSourceCoordinate<quint32, int>(binding->valueLocation.column)); warning.setDescription(error + tr(" - Assigning null to incompatible properties in QML " "is deprecated. This will become a compile error in " "future versions of Qt.")); @@ -659,23 +662,23 @@ bool QQmlPropertyValidator::canCoerce(int to, QQmlPropertyCache *fromMo) const return false; } -QVector<QQmlJS::DiagnosticMessage> QQmlPropertyValidator::recordError(const QV4::CompiledData::Location &location, const QString &description) const +QVector<QQmlError> QQmlPropertyValidator::recordError(const QV4::CompiledData::Location &location, const QString &description) const { - QVector<QQmlJS::DiagnosticMessage> errors; + QVector<QQmlError> errors; errors.append(qQmlCompileError(location, description)); return errors; } -QVector<QQmlJS::DiagnosticMessage> QQmlPropertyValidator::recordError(const QQmlJS::DiagnosticMessage &error) const +QVector<QQmlError> QQmlPropertyValidator::recordError(const QQmlError &error) const { - QVector<QQmlJS::DiagnosticMessage> errors; + QVector<QQmlError> errors; errors.append(error); return errors; } -QQmlJS::DiagnosticMessage QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding) const +QQmlError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding) const { - QQmlJS::DiagnosticMessage noError; + QQmlError noError; if (binding->flags & QV4::CompiledData::Binding::IsOnAssignment) { Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Object); @@ -744,8 +747,8 @@ QQmlJS::DiagnosticMessage QQmlPropertyValidator::validateObjectBinding(QQmlPrope // We want to use the raw metaObject here as the raw metaobject is the // actual property type before we applied any extensions that might // effect the properties on the type, but don't effect assignability - // Using -1 for the minor version ensures that we get the raw metaObject. - QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(propType, -1); + // Not passing a version ensures that we get the raw metaObject. + QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(propType); if (propertyMetaObject) { // Will be true if the assigned type inherits propertyMetaObject diff --git a/src/qml/qml/qqmlpropertyvalidator_p.h b/src/qml/qml/qqmlpropertyvalidator_p.h index 74a1281927..281472981c 100644 --- a/src/qml/qml/qqmlpropertyvalidator_p.h +++ b/src/qml/qml/qqmlpropertyvalidator_p.h @@ -66,25 +66,24 @@ class QQmlPropertyValidator public: QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit); - QVector<QQmlJS::DiagnosticMessage> validate(); + QVector<QQmlError> validate(); private: - QVector<QQmlJS::DiagnosticMessage> validateObject( + QVector<QQmlError> validateObject( int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty = false) const; - QQmlJS::DiagnosticMessage validateLiteralBinding( + QQmlError validateLiteralBinding( QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) const; - QQmlJS::DiagnosticMessage validateObjectBinding( + QQmlError validateObjectBinding( QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding) const; bool canCoerce(int to, QQmlPropertyCache *fromMo) const; - Q_REQUIRED_RESULT QVector<QQmlJS::DiagnosticMessage> recordError( + Q_REQUIRED_RESULT QVector<QQmlError> recordError( const QV4::CompiledData::Location &location, const QString &description) const; - Q_REQUIRED_RESULT QVector<QQmlJS::DiagnosticMessage> recordError( - const QQmlJS::DiagnosticMessage &error) const; + Q_REQUIRED_RESULT QVector<QQmlError> recordError(const QQmlError &error) const; QString stringAt(int index) const { return compilationUnit->stringAt(index); } QV4::ResolvedTypeReference *resolvedType(int id) const { diff --git a/src/qml/qml/qqmlscriptblob.cpp b/src/qml/qml/qqmlscriptblob.cpp index eb103dc434..dac21f7ee7 100644 --- a/src/qml/qml/qqmlscriptblob.cpp +++ b/src/qml/qml/qqmlscriptblob.cpp @@ -41,6 +41,7 @@ #include <private/qqmlirbuilder_p.h> #include <private/qqmlscriptblob_p.h> #include <private/qqmlscriptdata_p.h> +#include <private/qqmlsourcecoordinate_p.h> #include <private/qv4runtimecodegen_p.h> #include <private/qv4script_p.h> @@ -167,8 +168,8 @@ void QQmlScriptBlob::done() QList<QQmlError> errors = script.script->errors(); QQmlError error; error.setUrl(url()); - error.setLine(script.location.line); - error.setColumn(script.location.column); + error.setLine(qmlConvertSourceCoordinate<quint32, int>(script.location.line)); + error.setColumn(qmlConvertSourceCoordinate<quint32, int>(script.location.column)); error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->urlString())); errors.prepend(error); setError(errors); diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp index 28fefca239..db22c93733 100644 --- a/src/qml/qml/qqmltype.cpp +++ b/src/qml/qml/qqmltype.cpp @@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type) - : regType(type), iid(nullptr), typeId(0), listId(0), revision(0), + : regType(type), iid(nullptr), revision(QTypeRevision::zero()), containsRevisionedAttributes(false), baseMetaObject(nullptr), index(-1), isSetup(false), isEnumFromCacheSetup(false), isEnumFromBaseSetup(false), haveSuperType(false) @@ -132,34 +132,29 @@ QHashedString QQmlType::module() const return d->module; } -int QQmlType::majorVersion() const +QTypeRevision QQmlType::version() const { if (!d) - return -1; - return d->version_maj; + return QTypeRevision(); + return d->version; } -int QQmlType::minorVersion() const +bool QQmlType::availableInVersion(QTypeRevision version) const { - if (!d) - return -1; - return d->version_min; -} - -bool QQmlType::availableInVersion(int vmajor, int vminor) const -{ - Q_ASSERT(vmajor >= 0 && vminor >= 0); + Q_ASSERT(version.hasMajorVersion() && version.hasMinorVersion()); if (!d) return false; - return vmajor == d->version_maj && vminor >= d->version_min; + return version.majorVersion() == d->version.majorVersion() + && version.minorVersion() >= d->version.minorVersion(); } -bool QQmlType::availableInVersion(const QHashedStringRef &module, int vmajor, int vminor) const +bool QQmlType::availableInVersion(const QHashedStringRef &module, QTypeRevision version) const { - Q_ASSERT(vmajor >= 0 && vminor >= 0); + Q_ASSERT(version.hasMajorVersion() && version.hasMinorVersion()); if (!d) return false; - return module == d->module && vmajor == d->version_maj && vminor >= d->version_min; + return module == d->module && version.majorVersion() == d->version.majorVersion() + && version.minorVersion() >= d->version.minorVersion(); } QQmlType QQmlTypePrivate::resolveCompositeBaseType(QQmlEnginePrivate *engine) const @@ -592,14 +587,14 @@ bool QQmlType::isQJSValueSingleton() const return d && d->regType == SingletonType && d->extraData.sd->singletonInstanceInfo->scriptCallback; } -int QQmlType::typeId() const +QMetaType QQmlType::typeId() const { - return d ? d->typeId : -1; + return d ? d->typeId : QMetaType{}; } -int QQmlType::qListTypeId() const +QMetaType QQmlType::qListTypeId() const { - return d ? d->listId : -1; + return d ? d->listId : QMetaType{}; } const QMetaObject *QQmlType::metaObject() const @@ -629,21 +624,21 @@ bool QQmlType::containsRevisionedAttributes() const return d->containsRevisionedAttributes; } -int QQmlType::metaObjectRevision() const +QTypeRevision QQmlType::metaObjectRevision() const { - return d ? d->revision : -1; + return d ? d->revision : QTypeRevision(); } QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction(QQmlEnginePrivate *engine) const { - if (const QQmlTypePrivate *base = d->attachedPropertiesBase(engine)) + if (const QQmlTypePrivate *base = d ? d->attachedPropertiesBase(engine) : nullptr) return base->extraData.cd->attachedPropertiesFunc; return nullptr; } const QMetaObject *QQmlType::attachedPropertiesType(QQmlEnginePrivate *engine) const { - if (const QQmlTypePrivate *base = d->attachedPropertiesBase(engine)) + if (const QQmlTypePrivate *base = d ? d->attachedPropertiesBase(engine) : nullptr) return base->extraData.cd->attachedPropertiesType; return nullptr; } @@ -946,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)); @@ -958,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/qqmltype_p.h b/src/qml/qml/qqmltype_p.h index 387baa74bb..2b37ec16be 100644 --- a/src/qml/qml/qqmltype_p.h +++ b/src/qml/qml/qqmltype_p.h @@ -60,6 +60,7 @@ #include <QtQml/qjsvalue.h> #include <QtCore/qobject.h> +#include <QtCore/qversionnumber.h> QT_BEGIN_NAMESPACE @@ -98,11 +99,10 @@ public: QString elementName() const; QHashedString module() const; - int majorVersion() const; - int minorVersion() const; + QTypeRevision version() const; - bool availableInVersion(int vmajor, int vminor) const; - bool availableInVersion(const QHashedStringRef &module, int vmajor, int vminor) const; + bool availableInVersion(QTypeRevision version) const; + bool availableInVersion(const QHashedStringRef &module, QTypeRevision version) const; QObject *create() const; void create(QObject **, void **, size_t) const; @@ -124,12 +124,12 @@ public: bool isQObjectSingleton() const; bool isQJSValueSingleton() const; - int typeId() const; - int qListTypeId() const; + QMetaType typeId() const; + QMetaType qListTypeId() const; const QMetaObject *metaObject() const; const QMetaObject *baseMetaObject() const; - int metaObjectRevision() const; + QTypeRevision metaObjectRevision() const; bool containsRevisionedAttributes() const; QQmlAttachedPropertiesFunc attachedPropertiesFunction(QQmlEnginePrivate *engine) const; diff --git a/src/qml/qml/qqmltype_p_p.h b/src/qml/qml/qqmltype_p_p.h index 43344827db..c94ac8c130 100644 --- a/src/qml/qml/qqmltype_p_p.h +++ b/src/qml/qml/qqmltype_p_p.h @@ -157,11 +157,10 @@ public: QHashedString module; QString name; QString elementName; - int version_maj; - int version_min; - int typeId; - int listId; - int revision; + QMetaType typeId; + QMetaType listId; + QTypeRevision version; + QTypeRevision revision; mutable bool containsRevisionedAttributes; mutable QQmlType superType; const QMetaObject *baseMetaObject; diff --git a/src/qml/qml/qqmltypecompiler.cpp b/src/qml/qml/qqmltypecompiler.cpp index 842ca697e0..5c04abf367 100644 --- a/src/qml/qml/qqmltypecompiler.cpp +++ b/src/qml/qml/qqmltypecompiler.cpp @@ -82,7 +82,7 @@ QQmlRefPointer<QV4::ExecutableCompilationUnit> QQmlTypeCompiler::compile() { QQmlPropertyCacheCreator<QQmlTypeCompiler> propertyCacheBuilder(&m_propertyCaches, &pendingGroupPropertyBindings, engine, this, imports(), typeData->typeClassName()); - QQmlJS::DiagnosticMessage error = propertyCacheBuilder.buildMetaObjects(); + QQmlError error = propertyCacheBuilder.buildMetaObjects(); if (error.isValid()) { recordError(error); return nullptr; @@ -174,8 +174,8 @@ QQmlRefPointer<QV4::ExecutableCompilationUnit> QQmlTypeCompiler::compile() void QQmlTypeCompiler::recordError(const QV4::CompiledData::Location &location, const QString &description) { QQmlError error; - error.setLine(location.line); - error.setColumn(location.column); + error.setLine(qmlConvertSourceCoordinate<quint32, int>(location.line)); + error.setColumn(qmlConvertSourceCoordinate<quint32, int>(location.column)); error.setDescription(description); error.setUrl(url()); errors << error; @@ -185,8 +185,15 @@ void QQmlTypeCompiler::recordError(const QQmlJS::DiagnosticMessage &message) { QQmlError error; error.setDescription(message.message); - error.setLine(message.line); - error.setColumn(message.column); + error.setLine(qmlConvertSourceCoordinate<quint32, int>(message.loc.startLine)); + error.setColumn(qmlConvertSourceCoordinate<quint32, int>(message.loc.startColumn)); + error.setUrl(url()); + errors << error; +} + +void QQmlTypeCompiler::recordError(const QQmlError &e) +{ + QQmlError error = e; error.setUrl(url()); errors << error; } @@ -257,7 +264,7 @@ QString QQmlTypeCompiler::bindingAsString(const QmlIR::Object *object, int scrip return object->bindingAsString(document, scriptIndex); } -void QQmlTypeCompiler::addImport(const QString &module, const QString &qualifier, int majorVersion, int minorVersion) +void QQmlTypeCompiler::addImport(const QString &module, const QString &qualifier, QTypeRevision version) { const quint32 moduleIdx = registerString(module); const quint32 qualifierIdx = registerString(qualifier); @@ -272,8 +279,7 @@ void QQmlTypeCompiler::addImport(const QString &module, const QString &qualifier auto pool = memoryPool(); QV4::CompiledData::Import *import = pool->New<QV4::CompiledData::Import>(); import->type = QV4::CompiledData::Import::ImportLibrary; - import->majorVersion = majorVersion; - import->minorVersion = minorVersion; + import->version = version; import->uriIndex = moduleIdx; import->qualifierIndex = qualifierIdx; document->imports.append(import); @@ -394,7 +400,10 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio auto *typeRef = resolvedType(obj->inheritedTypeNameIndex); const QQmlType type = typeRef ? typeRef->type : QQmlType(); if (type.isValid()) { - COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(originalPropertyName).arg(type.module()).arg(type.majorVersion()).arg(type.minorVersion())); + COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.") + .arg(typeName).arg(originalPropertyName).arg(type.module()) + .arg(type.version().majorVersion()) + .arg(type.version().minorVersion())); } else { COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available due to component versioning.").arg(typeName).arg(originalPropertyName)); } @@ -816,7 +825,12 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI if (!pd || !pd->isQObject()) continue; - QQmlPropertyCache *pc = enginePrivate->rawPropertyCacheForType(pd->propType(), pd->typeMinorVersion()); + // If the version is given, use it and look up by QQmlType. + // Otherwise, make sure we look up by metaobject. + // TODO: Is this correct? + QQmlPropertyCache *pc = pd->typeVersion().hasMinorVersion() + ? enginePrivate->rawPropertyCacheForType(pd->propType(), pd->typeVersion()) + : enginePrivate->rawPropertyCacheForType(pd->propType()); const QMetaObject *mo = pc ? pc->firstCppMetaObject() : nullptr; while (mo) { if (mo == &QQmlComponent::staticMetaObject) @@ -832,7 +846,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI Q_ASSERT(componentType.isValid()); const QString qualifier = QStringLiteral("QmlInternals"); - compiler->addImport(componentType.module(), qualifier, componentType.majorVersion(), componentType.minorVersion()); + compiler->addImport(componentType.module(), qualifier, componentType.version()); QmlIR::Object *syntheticComponent = pool->New<QmlIR::Object>(); syntheticComponent->init(pool, compiler->registerString(qualifier + QLatin1Char('.') + componentType.elementName()), compiler->registerString(QString())); @@ -842,8 +856,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI if (!containsResolvedType(syntheticComponent->inheritedTypeNameIndex)) { auto typeRef = new QV4::ResolvedTypeReference; typeRef->type = componentType; - typeRef->majorVersion = componentType.majorVersion(); - typeRef->minorVersion = componentType.minorVersion(); + typeRef->version = componentType.version(); insertResolvedType(syntheticComponent->inheritedTypeNameIndex, typeRef); } @@ -875,6 +888,10 @@ bool QQmlComponentAndAliasResolver::resolve() const int objCountWithoutSynthesizedComponents = qmlObjects->count(); for (int i = 0; i < objCountWithoutSynthesizedComponents; ++i) { QmlIR::Object *obj = qmlObjects->at(i); + if (obj->isInlineComponent) { + componentRoots.append(i); + continue; + } QQmlPropertyCache *cache = propertyCaches.at(i); if (obj->inheritedTypeNameIndex == 0 && !cache) continue; @@ -930,7 +947,7 @@ bool QQmlComponentAndAliasResolver::resolve() _objectsWithAliases.clear(); - if (!collectIdsAndAliases(rootBinding->value.objectIndex)) + if (!collectIdsAndAliases(component->isInlineComponent ? componentRoots.at(i) : rootBinding->value.objectIndex)) return false; component->namedObjectsInComponent.allocate(pool, _idToObjectIndex); @@ -1006,7 +1023,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases(int componentIndex) for (int objectIndex: qAsConst(_objectsWithAliases)) { - QQmlJS::DiagnosticMessage error; + QQmlError error; const auto result = resolveAliasesInObject(objectIndex, &error); if (error.isValid()) { @@ -1015,7 +1032,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases(int componentIndex) } if (result == AllAliasesResolved) { - QQmlJS::DiagnosticMessage error = aliasCacheCreator.appendAliasesToPropertyCache(*qmlObjects->at(componentIndex), objectIndex, enginePrivate); + QQmlError error = aliasCacheCreator.appendAliasesToPropertyCache(*qmlObjects->at(componentIndex), objectIndex, enginePrivate); if (error.isValid()) { recordError(error); return false; @@ -1046,7 +1063,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases(int componentIndex) QQmlComponentAndAliasResolver::AliasResolutionResult QQmlComponentAndAliasResolver::resolveAliasesInObject(int objectIndex, - QQmlJS::DiagnosticMessage *error) + QQmlError *error) { const QmlIR::Object * const obj = qmlObjects->at(objectIndex); if (!obj->aliasCount()) diff --git a/src/qml/qml/qqmltypecompiler_p.h b/src/qml/qml/qqmltypecompiler_p.h index 319df8673b..883fbf0d68 100644 --- a/src/qml/qml/qqmltypecompiler_p.h +++ b/src/qml/qml/qqmltypecompiler_p.h @@ -100,7 +100,8 @@ public: QList<QQmlError> compilationErrors() const { return errors; } void recordError(const QV4::CompiledData::Location &location, const QString &description); - void recordError(const QQmlJS::DiagnosticMessage &error); + void recordError(const QQmlJS::DiagnosticMessage &message); + void recordError(const QQmlError &e); int registerString(const QString &str); int registerConstant(QV4::ReturnedValue v); @@ -124,7 +125,7 @@ public: QString bindingAsString(const QmlIR::Object *object, int scriptIndex) const; - void addImport(const QString &module, const QString &qualifier, int majorVersion, int minorVersion); + void addImport(const QString &module, const QString &qualifier, QTypeRevision version); QV4::ResolvedTypeReference *resolvedType(int id) const { @@ -157,7 +158,7 @@ struct QQmlCompilePass protected: void recordError(const QV4::CompiledData::Location &location, const QString &description) const { compiler->recordError(location, description); } - void recordError(const QQmlJS::DiagnosticMessage &error) + void recordError(const QQmlError &error) { compiler->recordError(error); } QV4::ResolvedTypeReference *resolvedType(int id) const @@ -280,7 +281,7 @@ protected: AllAliasesResolved }; - AliasResolutionResult resolveAliasesInObject(int objectIndex, QQmlJS::DiagnosticMessage *error); + AliasResolutionResult resolveAliasesInObject(int objectIndex, QQmlError *error); QQmlEnginePrivate *enginePrivate; QQmlJS::MemoryPool *pool; diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp index f7abe67921..7b21edec37 100644 --- a/src/qml/qml/qqmltypedata.cpp +++ b/src/qml/qml/qqmltypedata.cpp @@ -182,8 +182,8 @@ bool QQmlTypeData::tryLoadFromDiskCache() const QV4::CompiledData::Import *import = m_compiledData->importAt(i); if (m_compiledData->stringAt(import->uriIndex) == QLatin1String(".") && import->qualifierIndex == 0 - && import->majorVersion == -1 - && import->minorVersion == -1) { + && !import->version.hasMajorVersion() + && !import->version.hasMinorVersion()) { QList<QQmlError> errors; auto pendingImport = std::make_shared<PendingImport>(this, import); if (!fetchQmldir(qmldirUrl, pendingImport, 1, &errors)) { @@ -203,8 +203,8 @@ bool QQmlTypeData::tryLoadFromDiskCache() Q_ASSERT(errors.size()); QQmlError error(errors.takeFirst()); error.setUrl(m_importCache.baseUrl()); - error.setLine(import->location.line); - error.setColumn(import->location.column); + error.setLine(qmlConvertSourceCoordinate<quint32, int>(import->location.line)); + error.setColumn(qmlConvertSourceCoordinate<quint32, int>(import->location.column)); errors.prepend(error); // put it back on the list after filling out information. setError(errors); return false; @@ -213,9 +213,9 @@ bool QQmlTypeData::tryLoadFromDiskCache() QQmlType containingType; auto containingTypeName = finalUrl().fileName().split(QLatin1Char('.')).first(); - int major = -1, minor = -1; + QTypeRevision version; QQmlImportNamespace *ns = nullptr; - m_importCache.resolveType(containingTypeName, &containingType, &major, &minor, &ns); + m_importCache.resolveType(containingTypeName, &containingType, &version, &ns); for (auto&& ic: ics) { QString const nameString = m_compiledData->stringAt(ic.nameIndex); QByteArray const name = nameString.toUtf8(); @@ -244,7 +244,7 @@ void QQmlTypeData::createTypeAndPropertyCaches( QQmlPropertyCacheCreator<QV4::ExecutableCompilationUnit> propertyCacheCreator( &m_compiledData->propertyCaches, &pendingGroupPropertyBindings, engine, m_compiledData.data(), &m_importCache, typeClassName()); - QQmlJS::DiagnosticMessage error = propertyCacheCreator.buildMetaObjects(); + QQmlError error = propertyCacheCreator.buildMetaObjects(); if (error.isValid()) { setError(error); return; @@ -325,8 +325,8 @@ void QQmlTypeData::done() QList<QQmlError> errors = script.script->errors(); QQmlError error; error.setUrl(url()); - error.setLine(script.location.line); - error.setColumn(script.location.column); + error.setLine(qmlConvertSourceCoordinate<quint32, int>(script.location.line)); + error.setColumn(qmlConvertSourceCoordinate<quint32, int>(script.location.column)); error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->urlString())); errors.prepend(error); setError(errors); @@ -349,8 +349,8 @@ void QQmlTypeData::done() QList<QQmlError> errors = type.typeData ? type.typeData->errors() : QList<QQmlError>{}; QQmlError error; error.setUrl(url()); - error.setLine(type.location.line); - error.setColumn(type.location.column); + error.setLine(qmlConvertSourceCoordinate<quint32, int>(type.location.line)); + error.setColumn(qmlConvertSourceCoordinate<quint32, int>(type.location.column)); error.setDescription(QQmlTypeLoader::tr("Type %1 has no inline component type called %2").arg(typeName.leftRef(lastDot), type.type.pendingResolutionName())); errors.prepend(error); setError(errors); @@ -365,8 +365,8 @@ void QQmlTypeData::done() QList<QQmlError> errors = type.typeData->errors(); QQmlError error; error.setUrl(url()); - error.setLine(type.location.line); - error.setColumn(type.location.column); + error.setLine(qmlConvertSourceCoordinate<quint32, int>(type.location.line)); + error.setColumn(qmlConvertSourceCoordinate<quint32, int>(type.location.column)); error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName)); errors.prepend(error); setError(errors); @@ -384,8 +384,8 @@ void QQmlTypeData::done() QList<QQmlError> errors = type.typeData->errors(); QQmlError error; error.setUrl(url()); - error.setLine(type.location.line); - error.setColumn(type.location.column); + error.setLine(qmlConvertSourceCoordinate<quint32, int>(type.location.line)); + error.setColumn(qmlConvertSourceCoordinate<quint32, int>(type.location.column)); error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName)); errors.prepend(error); setError(errors); @@ -414,7 +414,7 @@ void QQmlTypeData::done() QV4::ResolvedTypeReferenceMap resolvedTypeCache; QQmlRefPointer<QQmlTypeNameCache> typeNameCache; { - QQmlJS::DiagnosticMessage error = buildTypeResolutionCaches(&typeNameCache, &resolvedTypeCache); + QQmlError error = buildTypeResolutionCaches(&typeNameCache, &resolvedTypeCache); if (error.isValid()) { setError(error); qDeleteAll(resolvedTypeCache); @@ -461,7 +461,7 @@ void QQmlTypeData::done() { // Sanity check property bindings QQmlPropertyValidator validator(enginePrivate, m_importCache, m_compiledData); - QVector<QQmlJS::DiagnosticMessage> errors = validator.validate(); + QVector<QQmlError> errors = validator.validate(); if (!errors.isEmpty()) { setError(errors); return; @@ -625,8 +625,8 @@ bool QQmlTypeData::loadFromSource() for (const QQmlJS::DiagnosticMessage &msg : qAsConst(compiler.errors)) { QQmlError e; e.setUrl(url()); - e.setLine(msg.line); - e.setColumn(msg.column); + e.setLine(qmlConvertSourceCoordinate<quint32, int>(msg.loc.startLine)); + e.setColumn(qmlConvertSourceCoordinate<quint32, int>(msg.loc.startColumn)); e.setDescription(msg.message); errors << e; } @@ -651,9 +651,9 @@ void QQmlTypeData::continueLoadFromIR() { QQmlType containingType; auto containingTypeName = finalUrl().fileName().split(QLatin1Char('.')).first(); - int major = -1, minor = -1; + QTypeRevision version; QQmlImportNamespace *ns = nullptr; - m_importCache.resolveType(containingTypeName, &containingType, &major, &minor, &ns); + m_importCache.resolveType(containingTypeName, &containingType, &version, &ns); for (auto const& object: m_document->objects) { for (auto it = object->inlineComponentsBegin(); it != object->inlineComponentsEnd(); ++it) { QString const nameString = m_document->stringAt(it->nameIndex); @@ -679,8 +679,7 @@ void QQmlTypeData::continueLoadFromIR() // This qmldir is for the implicit import auto implicitImport = std::make_shared<PendingImport>(); implicitImport->uri = QLatin1String("."); - implicitImport->majorVersion = -1; - implicitImport->minorVersion = -1; + implicitImport->version = QTypeRevision(); QList<QQmlError> errors; if (!fetchQmldir(qmldirUrl, implicitImport, 1, &errors)) { @@ -697,8 +696,8 @@ void QQmlTypeData::continueLoadFromIR() Q_ASSERT(errors.size()); QQmlError error(errors.takeFirst()); error.setUrl(m_importCache.baseUrl()); - error.setLine(import->location.line); - error.setColumn(import->location.column); + error.setLine(qmlConvertSourceCoordinate<quint32, int>(import->location.line)); + error.setColumn(qmlConvertSourceCoordinate<quint32, int>(import->location.column)); errors.prepend(error); // put it back on the list after filling out information. setError(errors); return; @@ -724,8 +723,8 @@ void QQmlTypeData::allDependenciesDone() QQmlError error; error.setDescription(QQmlTypeLoader::tr("module \"%1\" is not installed").arg(import->uri)); error.setUrl(m_importCache.baseUrl()); - error.setLine(import->location.line); - error.setColumn(import->location.column); + error.setLine(qmlConvertSourceCoordinate<quint32, int>(import->location.line)); + error.setColumn(qmlConvertSourceCoordinate<quint32, int>(import->location.column)); errors.prepend(error); } } @@ -824,17 +823,15 @@ void QQmlTypeData::resolveTypes() typeName = csRef.typeName; } - int majorVersion = csRef.majorVersion > -1 ? csRef.majorVersion : -1; - int minorVersion = csRef.minorVersion > -1 ? csRef.minorVersion : -1; - - if (!resolveType(typeName, majorVersion, minorVersion, ref, -1, -1, true, - QQmlType::CompositeSingletonType)) + QTypeRevision version = csRef.version; + if (!resolveType(typeName, version, ref, -1, -1, true, QQmlType::CompositeSingletonType)) return; if (ref.type.isCompositeSingleton()) { ref.typeData = typeLoader()->getType(ref.type.sourceUrl()); - if (ref.typeData->status() == QQmlDataBlob::ResolvingDependencies || m_waitingOnMe.contains(ref.typeData.data())) { - // TODO: give an error message? If so, we should record and show the path of the cycle. + if (ref.typeData->isWaiting() || m_waitingOnMe.contains(ref.typeData.data())) { + qWarning() << "Cyclic dependency detected between" << ref.typeData->urlString() + << "and" << urlString(); continue; } addDependency(ref.typeData.data()); @@ -851,14 +848,13 @@ void QQmlTypeData::resolveTypes() const bool reportErrors = unresolvedRef->errorWhenNotFound; - int majorVersion = -1; - int minorVersion = -1; + QTypeRevision version; const QString name = stringAt(unresolvedRef.key()); bool *selfReferenceDetection = unresolvedRef->needsCreation ? nullptr : &ref.selfReference; - if (!resolveType(name, majorVersion, minorVersion, ref, unresolvedRef->location.line, + if (!resolveType(name, version, ref, unresolvedRef->location.line, unresolvedRef->location.column, reportErrors, QQmlType::AnyRegistrationType, selfReferenceDetection) && reportErrors) return; @@ -878,8 +874,7 @@ void QQmlTypeData::resolveTypes() } } } - ref.majorVersion = majorVersion; - ref.minorVersion = minorVersion; + ref.version = version; ref.location.line = unresolvedRef->location.line; ref.location.column = unresolvedRef->location.column; @@ -893,7 +888,7 @@ void QQmlTypeData::resolveTypes() loadImplicitImport(); } -QQmlJS::DiagnosticMessage QQmlTypeData::buildTypeResolutionCaches( +QQmlError QQmlTypeData::buildTypeResolutionCaches( QQmlRefPointer<QQmlTypeNameCache> *typeNameCache, QV4::ResolvedTypeReferenceMap *resolvedTypeCache ) const @@ -939,7 +934,8 @@ QQmlJS::DiagnosticMessage QQmlTypeData::buildTypeResolutionCaches( ref->type = qmlType; if (qmlType.isValid()) { // this is required for inline components in singletons - auto typeID = qmlType.lookupInlineComponentById(qmlType.inlineComponendId()).typeId(); + auto type = qmlType.lookupInlineComponentById(qmlType.inlineComponendId()).typeId(); + auto typeID = type.isValid() ? type.id() : -1; auto exUnit = engine->obtainExecutableCompilationUnit(typeID); if (exUnit) { ref->compilationUnit = exUnit; @@ -962,21 +958,18 @@ QQmlJS::DiagnosticMessage QQmlTypeData::buildTypeResolutionCaches( return qQmlCompileError(resolvedType->location, reason); } - if (ref->type.containsRevisionedAttributes()) { - ref->typePropertyCache = engine->cache(ref->type, - resolvedType->minorVersion); - } + if (ref->type.containsRevisionedAttributes()) + ref->typePropertyCache = engine->cache(ref->type, resolvedType->version); } - ref->majorVersion = resolvedType->majorVersion; - ref->minorVersion = resolvedType->minorVersion; + ref->version = resolvedType->version; ref->doDynamicTypeCheck(); resolvedTypeCache->insert(resolvedType.key(), ref.take()); } - QQmlJS::DiagnosticMessage noError; + QQmlError noError; return noError; } -bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int &minorVersion, +bool QQmlTypeData::resolveType(const QString &typeName, QTypeRevision &version, TypeReference &ref, int lineNumber, int columnNumber, bool reportErrors, QQmlType::RegistrationType registrationType, bool *typeRecursionDetected) @@ -984,7 +977,7 @@ bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int & QQmlImportNamespace *typeNamespace = nullptr; QList<QQmlError> errors; - bool typeFound = m_importCache.resolveType(typeName, &ref.type, &majorVersion, &minorVersion, + bool typeFound = m_importCache.resolveType(typeName, &ref.type, &version, &typeNamespace, &errors, registrationType, typeRecursionDetected); if (!typeNamespace && !typeFound && !m_implicitImportLoaded) { @@ -992,7 +985,7 @@ bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int & if (loadImplicitImport()) { // Try again to find the type errors.clear(); - typeFound = m_importCache.resolveType(typeName, &ref.type, &majorVersion, &minorVersion, + typeFound = m_importCache.resolveType(typeName, &ref.type, &version, &typeNamespace, &errors, registrationType, typeRecursionDetected); } else { diff --git a/src/qml/qml/qqmltypedata_p.h b/src/qml/qml/qqmltypedata_p.h index d894090b36..c3b0faa5b4 100644 --- a/src/qml/qml/qqmltypedata_p.h +++ b/src/qml/qml/qqmltypedata_p.h @@ -62,12 +62,11 @@ class Q_AUTOTEST_EXPORT QQmlTypeData : public QQmlTypeLoader::Blob public: struct TypeReference { - TypeReference() : majorVersion(0), minorVersion(0), needsCreation(true) {} + TypeReference() : version(QTypeRevision::zero()), needsCreation(true) {} QV4::CompiledData::Location location; QQmlType type; - int majorVersion; - int minorVersion; + QTypeRevision version; QQmlRefPointer<QQmlTypeData> typeData; bool selfReference = false; QString prefix; // used by CompositeSingleton types @@ -125,7 +124,7 @@ private: void restoreIR(QV4::CompiledData::CompilationUnit &&unit); void continueLoadFromIR(); void resolveTypes(); - QQmlJS::DiagnosticMessage buildTypeResolutionCaches( + QQmlError buildTypeResolutionCaches( QQmlRefPointer<QQmlTypeNameCache> *typeNameCache, QV4::ResolvedTypeReferenceMap *resolvedTypeCache ) const; @@ -134,7 +133,7 @@ private: const QV4::CompiledData::DependentTypesHasher &dependencyHasher); void createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache, const QV4::ResolvedTypeReferenceMap &resolvedTypeCache); - bool resolveType(const QString &typeName, int &majorVersion, int &minorVersion, + bool resolveType(const QString &typeName, QTypeRevision &version, TypeReference &ref, int lineNumber = -1, int columnNumber = -1, bool reportErrors = true, QQmlType::RegistrationType registrationType = QQmlType::AnyRegistrationType, diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index e9a38945fa..75dc9d15a5 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -45,6 +45,7 @@ #include <private/qqmltypedata_p.h> #include <private/qqmltypeloaderqmldircontent_p.h> #include <private/qqmltypeloaderthread_p.h> +#include <private/qqmlsourcecoordinate_p.h> #include <QtQml/qqmlabstracturlinterceptor.h> #include <QtQml/qqmlengine.h> @@ -357,8 +358,8 @@ void QQmlTypeLoader::networkReplyFinished(QNetworkReply *reply) } } - if (reply->networkError()) { - blob->networkError(reply->networkError()); + if (reply->error()) { + blob->networkError(reply->error()); } else { QByteArray data = reply->readAll(); setData(blob, data); @@ -393,7 +394,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. */ @@ -487,8 +488,7 @@ QQmlTypeLoader::Blob::PendingImport::PendingImport(QQmlTypeLoader::Blob *blob, c type = static_cast<QV4::CompiledData::Import::ImportType>(quint32(import->type)); uri = blob->stringAt(import->uriIndex); qualifier = blob->stringAt(import->qualifierIndex); - majorVersion = import->majorVersion; - minorVersion = import->minorVersion; + version = import->version; location = import->location; } @@ -578,12 +578,13 @@ bool QQmlTypeLoader::Blob::addImport(QQmlTypeLoader::Blob::PendingImportPtr impo QString qmldirUrl; const QQmlImports::LocalQmldirResult qmldirResult = m_importCache.locateLocalQmldir( - importDatabase, import->uri, import->majorVersion, import->minorVersion, + importDatabase, import->uri, import->version, &qmldirFilePath, &qmldirUrl); if (qmldirResult == QQmlImports::QmldirFound) { // This is a local library import - if (!m_importCache.addLibraryImport(importDatabase, import->uri, import->qualifier, import->majorVersion, - import->minorVersion, qmldirFilePath, qmldirUrl, false, errors)) + if (!m_importCache.addLibraryImport( + importDatabase, import->uri, import->qualifier, + import->version, qmldirFilePath, qmldirUrl, false, errors)) return false; if (!loadImportDependencies(import, qmldirFilePath, errors)) @@ -602,49 +603,59 @@ bool QQmlTypeLoader::Blob::addImport(QQmlTypeLoader::Blob::PendingImportPtr impo scriptImported(blob, import->location, script.nameSpace, import->qualifier); } } + } else if ( + // Major version of module already registered: + // We believe that the registration is complete. + QQmlMetaType::typeModule(import->uri, import->version) + + // Otherwise, try to register further module types. + || (qmldirResult != QQmlImports::QmldirInterceptedToRemote + && QQmlMetaType::qmlRegisterModuleTypes(import->uri)) + + // Otherwise, there is no way to register any further types. + // Try with any module of that name. + || QQmlMetaType::isAnyModule(import->uri)) { + + if (!m_importCache.addLibraryImport( + importDatabase, import->uri, import->qualifier, import->version, + QString(), QString(), false, errors)) { + return false; + } } else { - // Is this a module? - if (QQmlMetaType::isAnyModule(import->uri) - || (qmldirResult != QQmlImports::QmldirInterceptedToRemote - && QQmlMetaType::qmlRegisterModuleTypes(import->uri, - import->majorVersion))) { - if (!m_importCache.addLibraryImport(importDatabase, import->uri, import->qualifier, import->majorVersion, - import->minorVersion, QString(), QString(), false, errors)) + // We haven't yet resolved this import + m_unresolvedImports << import; + + QQmlAbstractUrlInterceptor *interceptor = typeLoader()->engine()->urlInterceptor(); + + // Query any network import paths for this library. + // Interceptor might redirect local paths. + QStringList remotePathList = importDatabase->importPathList( + interceptor ? QQmlImportDatabase::LocalOrRemote + : QQmlImportDatabase::Remote); + if (!remotePathList.isEmpty()) { + // Add this library and request the possible locations for it + if (!m_importCache.addLibraryImport( + importDatabase, import->uri, import->qualifier, import->version, + QString(), QString(), true, errors)) return false; - } else { - // We haven't yet resolved this import - m_unresolvedImports << import; - - QQmlAbstractUrlInterceptor *interceptor = typeLoader()->engine()->urlInterceptor(); - - // Query any network import paths for this library. - // Interceptor might redirect local paths. - QStringList remotePathList = importDatabase->importPathList( - interceptor ? QQmlImportDatabase::LocalOrRemote - : QQmlImportDatabase::Remote); - if (!remotePathList.isEmpty()) { - // Add this library and request the possible locations for it - if (!m_importCache.addLibraryImport(importDatabase, import->uri, import->qualifier, import->majorVersion, - import->minorVersion, QString(), QString(), true, errors)) - return false; - // Probe for all possible locations - int priority = 0; - const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(import->uri, remotePathList, import->majorVersion, import->minorVersion); - for (const QString &qmldirPath : qmlDirPaths) { - if (interceptor) { - QUrl url = interceptor->intercept( - QQmlImports::urlFromLocalFileOrQrcOrUrl(qmldirPath), - QQmlAbstractUrlInterceptor::QmldirFile); - if (!QQmlFile::isLocalFile(url) - && !fetchQmldir(url, import, ++priority, errors)) { - return false; - } - } else if (!fetchQmldir(QUrl(qmldirPath), import, ++priority, errors)) { + // Probe for all possible locations + int priority = 0; + const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths( + import->uri, remotePathList, import->version); + for (const QString &qmldirPath : qmlDirPaths) { + if (interceptor) { + QUrl url = interceptor->intercept( + QQmlImports::urlFromLocalFileOrQrcOrUrl(qmldirPath), + QQmlAbstractUrlInterceptor::QmldirFile); + if (!QQmlFile::isLocalFile(url) + && !fetchQmldir(url, import, ++priority, errors)) { return false; } - + } else if (!fetchQmldir(QUrl(qmldirPath), import, ++priority, errors)) { + return false; } + } } } @@ -663,8 +674,8 @@ bool QQmlTypeLoader::Blob::addImport(QQmlTypeLoader::Blob::PendingImportPtr impo incomplete = true; } - if (!m_importCache.addFileImport(importDatabase, import->uri, import->qualifier, import->majorVersion, - import->minorVersion, incomplete, errors)) + if (!m_importCache.addFileImport(importDatabase, import->uri, import->qualifier, + import->version, incomplete, errors)) return false; if (incomplete) { @@ -688,8 +699,8 @@ void QQmlTypeLoader::Blob::dependencyComplete(QQmlDataBlob *blob) Q_ASSERT(errors.size()); QQmlError error(errors.takeFirst()); error.setUrl(m_importCache.baseUrl()); - error.setLine(import->location.line); - error.setColumn(import->location.column); + error.setLine(qmlConvertSourceCoordinate<quint32, int>(import->location.line)); + error.setColumn(qmlConvertSourceCoordinate<quint32, int>(import->location.column)); errors.prepend(error); // put it back on the list after filling out information. setError(errors); } @@ -703,8 +714,7 @@ bool QQmlTypeLoader::Blob::loadImportDependencies(PendingImportPtr currentImport auto dependencyImport = std::make_shared<PendingImport>(); dependencyImport->uri = implicitImports; dependencyImport->qualifier = currentImport->qualifier; - dependencyImport->majorVersion = currentImport->majorVersion; - dependencyImport->minorVersion = currentImport->minorVersion; + dependencyImport->version = currentImport->version; if (!addImport(dependencyImport, errors)) return false; } diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index adecf61896..a1ba2967e3 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -97,8 +97,7 @@ public: QString uri; QString qualifier; - int majorVersion = -1; - int minorVersion = -1; + QTypeRevision version; QV4::CompiledData::Location location; diff --git a/src/qml/qml/qqmltypeloaderqmldircontent.cpp b/src/qml/qml/qqmltypeloaderqmldircontent.cpp index 860971d296..714ea79e67 100644 --- a/src/qml/qml/qqmltypeloaderqmldircontent.cpp +++ b/src/qml/qml/qqmltypeloaderqmldircontent.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include <private/qqmltypeloaderqmldircontent_p.h> +#include <private/qqmlsourcecoordinate_p.h> #include <QtQml/qqmlerror.h> QT_BEGIN_NAMESPACE @@ -59,8 +60,8 @@ QList<QQmlError> QQmlTypeLoaderQmldirContent::errors(const QString &uri) const for (const auto &parseError : parseErrors) { QQmlError error; error.setUrl(url); - error.setLine(parseError.line); - error.setColumn(parseError.column); + error.setLine(qmlConvertSourceCoordinate<quint32, int>(parseError.loc.startLine)); + error.setColumn(qmlConvertSourceCoordinate<quint32, int>(parseError.loc.startColumn)); error.setDescription(parseError.message); errors.append(error); } @@ -83,8 +84,8 @@ void QQmlTypeLoaderQmldirContent::setContent(const QString &location, const QStr void QQmlTypeLoaderQmldirContent::setError(const QQmlError &error) { QQmlJS::DiagnosticMessage parseError; - parseError.line = error.line(); - parseError.column = error.column(); + parseError.loc.startLine = error.line(); + parseError.loc.startColumn = error.column(); parseError.message = error.description(); m_parser.setError(parseError); } diff --git a/src/qml/qml/qqmltypemodule.cpp b/src/qml/qml/qqmltypemodule.cpp index 9d6f269030..e6bf796d74 100644 --- a/src/qml/qml/qqmltypemodule.cpp +++ b/src/qml/qml/qqmltypemodule.cpp @@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE -QQmlTypeModule::QQmlTypeModule(const QString &module, int majorVersion) +QQmlTypeModule::QQmlTypeModule(const QString &module, quint8 majorVersion) : d(new QQmlTypeModulePrivate(module, majorVersion)) { } @@ -61,23 +61,23 @@ QString QQmlTypeModule::module() const return d->module; } -int QQmlTypeModule::majorVersion() const +quint8 QQmlTypeModule::majorVersion() const { // No need to lock. d->majorVersion is const return d->majorVersion; } -int QQmlTypeModule::minimumMinorVersion() const +quint8 QQmlTypeModule::minimumMinorVersion() const { return d->minMinorVersion.loadRelaxed(); } -int QQmlTypeModule::maximumMinorVersion() const +quint8 QQmlTypeModule::maximumMinorVersion() const { return d->maxMinorVersion.loadRelaxed(); } -void QQmlTypeModule::addMinorVersion(int version) +void QQmlTypeModule::addMinorVersion(quint8 version) { for (int oldVersion = d->minMinorVersion.loadRelaxed(); oldVersion > version && !d->minMinorVersion.testAndSetOrdered(oldVersion, version); @@ -93,16 +93,16 @@ void QQmlTypeModule::addMinorVersion(int version) void QQmlTypeModule::add(QQmlTypePrivate *type) { QMutexLocker lock(&d->mutex); - addMinorVersion(type->version_min); + addMinorVersion(type->version.minorVersion()); QList<QQmlTypePrivate *> &list = d->typeHash[type->elementName]; for (int ii = 0; ii < list.count(); ++ii) { QQmlTypePrivate *in_list = list.at(ii); Q_ASSERT(in_list); - if (in_list->version_min < type->version_min) { + if (in_list->version.minorVersion() < type->version.minorVersion()) { list.insert(ii, type); return; - } else if (in_list->version_min == type->version_min) { + } else if (in_list->version.minorVersion() == type->version.minorVersion()) { list[ii] = type; return; } @@ -137,26 +137,26 @@ void QQmlTypeModule::lock() d->locked.storeRelaxed(1); } -QQmlType QQmlTypeModule::type(const QHashedStringRef &name, int minor) const +QQmlType QQmlTypeModule::type(const QHashedStringRef &name, QTypeRevision version) const { QMutexLocker lock(&d->mutex); QList<QQmlTypePrivate *> *types = d->typeHash.value(name); if (types) { for (int ii = 0; ii < types->count(); ++ii) - if (types->at(ii)->version_min <= minor) + if (types->at(ii)->version.minorVersion() <= version.minorVersion()) return QQmlType(types->at(ii)); } return QQmlType(); } -QQmlType QQmlTypeModule::type(const QV4::String *name, int minor) const +QQmlType QQmlTypeModule::type(const QV4::String *name, QTypeRevision version) const { QMutexLocker lock(&d->mutex); QList<QQmlTypePrivate *> *types = d->typeHash.value(name); if (types) { for (int ii = 0; ii < types->count(); ++ii) - if (types->at(ii)->version_min <= minor) + if (types->at(ii)->version.minorVersion() <= version.minorVersion()) return QQmlType(types->at(ii)); } diff --git a/src/qml/qml/qqmltypemodule_p.h b/src/qml/qml/qqmltypemodule_p.h index b84a91b5db..d3149567a3 100644 --- a/src/qml/qml/qqmltypemodule_p.h +++ b/src/qml/qml/qqmltypemodule_p.h @@ -53,6 +53,7 @@ #include <QtQml/qtqmlglobal.h> #include <QtCore/qstring.h> +#include <QtCore/qversionnumber.h> #include <functional> @@ -72,7 +73,7 @@ class QQmlTypeModulePrivate; class QQmlTypeModule { public: - QQmlTypeModule(const QString &uri = QString(), int majorVersion = 0); + QQmlTypeModule(const QString &uri = QString(), quint8 majorVersion = 0); ~QQmlTypeModule(); void add(QQmlTypePrivate *); @@ -82,14 +83,14 @@ public: void lock(); QString module() const; - int majorVersion() const; + quint8 majorVersion() const; - void addMinorVersion(int minorVersion); - int minimumMinorVersion() const; - int maximumMinorVersion() const; + void addMinorVersion(quint8 minorVersion); + quint8 minimumMinorVersion() const; + quint8 maximumMinorVersion() const; - QQmlType type(const QHashedStringRef &, int) const; - QQmlType type(const QV4::String *, int) const; + QQmlType type(const QHashedStringRef &, QTypeRevision version) const; + QQmlType type(const QV4::String *, QTypeRevision version) const; void walkCompositeSingletons(const std::function<void(const QQmlType &)> &callback) const; diff --git a/src/qml/qml/qqmltypemodule_p_p.h b/src/qml/qml/qqmltypemodule_p_p.h index b1dab1c4a0..5d4d2e458a 100644 --- a/src/qml/qml/qqmltypemodule_p_p.h +++ b/src/qml/qml/qqmltypemodule_p_p.h @@ -62,15 +62,15 @@ QT_BEGIN_NAMESPACE class QQmlTypeModulePrivate { public: - QQmlTypeModulePrivate(QString module, int majorVersion) : + QQmlTypeModulePrivate(QString module, quint8 majorVersion) : module(std::move(module)), majorVersion(majorVersion) {} const QString module; - const int majorVersion = 0; + const quint8 majorVersion = 0; // Can only ever decrease - QAtomicInt minMinorVersion = std::numeric_limits<int>::max(); + QAtomicInt minMinorVersion = std::numeric_limits<quint8>::max(); // Can only ever increase QAtomicInt maxMinorVersion = 0; diff --git a/src/qml/qml/qqmltypemoduleversion.cpp b/src/qml/qml/qqmltypemoduleversion.cpp index bbbfa1a7b6..207b77770a 100644 --- a/src/qml/qml/qqmltypemoduleversion.cpp +++ b/src/qml/qml/qqmltypemoduleversion.cpp @@ -49,11 +49,11 @@ QQmlTypeModuleVersion::QQmlTypeModuleVersion() { } -QQmlTypeModuleVersion::QQmlTypeModuleVersion(QQmlTypeModule *module, int minor) - : m_module(module), m_minor(minor) +QQmlTypeModuleVersion::QQmlTypeModuleVersion(QQmlTypeModule *module, QTypeRevision version) + : m_module(module), m_minor(version.minorVersion()) { Q_ASSERT(m_module); - Q_ASSERT(m_minor >= 0); + Q_ASSERT(QTypeRevision::isValidSegment(m_minor)); } QQmlTypeModuleVersion::QQmlTypeModuleVersion(const QQmlTypeModuleVersion &o) @@ -68,28 +68,18 @@ QQmlTypeModuleVersion &QQmlTypeModuleVersion::operator=(const QQmlTypeModuleVers return *this; } -QQmlTypeModule *QQmlTypeModuleVersion::module() const -{ - return m_module; -} - -int QQmlTypeModuleVersion::minorVersion() const -{ - return m_minor; -} - QQmlType QQmlTypeModuleVersion::type(const QHashedStringRef &name) const { if (!m_module) return QQmlType(); - return m_module->type(name, m_minor); + return m_module->type(name, QTypeRevision::fromMinorVersion(m_minor)); } QQmlType QQmlTypeModuleVersion::type(const QV4::String *name) const { if (!m_module) return QQmlType(); - return m_module->type(name, m_minor); + return m_module->type(name, QTypeRevision::fromMinorVersion(m_minor)); } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmltypemoduleversion_p.h b/src/qml/qml/qqmltypemoduleversion_p.h index 20f4709ecb..b7e94ef27b 100644 --- a/src/qml/qml/qqmltypemoduleversion_p.h +++ b/src/qml/qml/qqmltypemoduleversion_p.h @@ -52,6 +52,7 @@ // #include <QtQml/qtqmlglobal.h> +#include <QtCore/qversionnumber.h> QT_BEGIN_NAMESPACE @@ -67,19 +68,16 @@ class QQmlTypeModuleVersion { public: QQmlTypeModuleVersion(); - QQmlTypeModuleVersion(QQmlTypeModule *, int); + QQmlTypeModuleVersion(QQmlTypeModule *, QTypeRevision); QQmlTypeModuleVersion(const QQmlTypeModuleVersion &); QQmlTypeModuleVersion &operator=(const QQmlTypeModuleVersion &); - QQmlTypeModule *module() const; - int minorVersion() const; - QQmlType type(const QHashedStringRef &) const; QQmlType type(const QV4::String *) const; private: QQmlTypeModule *m_module; - int m_minor; + quint8 m_minor; }; QT_END_NAMESPACE diff --git a/src/qml/qml/qqmltypenamecache.cpp b/src/qml/qml/qqmltypenamecache.cpp index 1015403226..45333668e3 100644 --- a/src/qml/qml/qqmltypenamecache.cpp +++ b/src/qml/qml/qqmltypenamecache.cpp @@ -101,7 +101,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedStringRef &name) QQmlImportNamespace *typeNamespace = nullptr; QList<QQmlError> errors; QQmlType t; - bool typeFound = m_imports.resolveType(name, &t, nullptr, nullptr, &typeNamespace, &errors); + bool typeFound = m_imports.resolveType(name, &t, nullptr, &typeNamespace, &errors); if (typeFound) { return Result(t); } @@ -129,7 +129,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedStringRef &name, QQmlImportNamespace *typeNamespace = nullptr; QList<QQmlError> errors; QQmlType t; - bool typeFound = m_imports.resolveType(qualifiedTypeName, &t, nullptr, nullptr, &typeNamespace, &errors); + bool typeFound = m_imports.resolveType(qualifiedTypeName, &t, nullptr, &typeNamespace, &errors); if (typeFound) { return Result(t); } @@ -155,7 +155,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name, QQml QList<QQmlError> errors; QQmlType t; bool typeRecursionDetected = false; - bool typeFound = m_imports.resolveType(typeName, &t, nullptr, nullptr, &typeNamespace, &errors, + bool typeFound = m_imports.resolveType(typeName, &t, nullptr, &typeNamespace, &errors, QQmlType::AnyRegistrationType, recursionRestriction == QQmlImport::AllowRecursion ? &typeRecursionDetected : nullptr); if (typeFound) { @@ -191,7 +191,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name, cons QQmlImportNamespace *typeNamespace = nullptr; QList<QQmlError> errors; QQmlType t; - bool typeFound = m_imports.resolveType(qualifiedTypeName, &t, nullptr, nullptr, &typeNamespace, &errors); + bool typeFound = m_imports.resolveType(qualifiedTypeName, &t, nullptr, &typeNamespace, &errors); if (typeFound) { return Result(t); } diff --git a/src/qml/qml/qqmltypenotavailable.cpp b/src/qml/qml/qqmltypenotavailable.cpp index ffa4472e4b..0e95d6062c 100644 --- a/src/qml/qml/qqmltypenotavailable.cpp +++ b/src/qml/qml/qqmltypenotavailable.cpp @@ -46,8 +46,6 @@ int qmlRegisterTypeNotAvailable(const char *uri, int versionMajor, int versionMi return qmlRegisterUncreatableType<QQmlTypeNotAvailable>(uri,versionMajor,versionMinor,qmlName,message); } -QQmlTypeNotAvailable::QQmlTypeNotAvailable() { } - QT_END_NAMESPACE #include "moc_qqmltypenotavailable_p.cpp" diff --git a/src/qml/qml/qqmltypenotavailable_p.h b/src/qml/qml/qqmltypenotavailable_p.h index 8db5876b10..dbd37ace2a 100644 --- a/src/qml/qml/qqmltypenotavailable_p.h +++ b/src/qml/qml/qqmltypenotavailable_p.h @@ -55,14 +55,11 @@ QT_BEGIN_NAMESPACE - class QQmlTypeNotAvailable : public QObject { Q_OBJECT QML_NAMED_ELEMENT(TypeNotAvailable) + QML_ADDED_IN_VERSION(2, 15) QML_UNCREATABLE("Type not available.") - -public: - QQmlTypeNotAvailable(); }; QT_END_NAMESPACE diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index fa5d36503d..7bcc5e9900 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -407,9 +407,9 @@ ReturnedValue QQmlTypeWrapper::virtualInstanceOf(const Object *typeObject, const if (!wrapperObject) return engine->throwTypeError(); - const int myTypeId = typeWrapper->d()->type().typeId(); + const QMetaType myTypeId = typeWrapper->d()->type().typeId(); QQmlMetaObject myQmlType; - if (myTypeId == 0) { + if (!myTypeId.isValid()) { // we're a composite type; a composite type cannot be equal to a // non-composite object instance (Rectangle{} is never an instance of // CustomRectangle) @@ -420,9 +420,9 @@ ReturnedValue QQmlTypeWrapper::virtualInstanceOf(const Object *typeObject, const QQmlRefPointer<QQmlTypeData> td = qenginepriv->typeLoader.getType(typeWrapper->d()->type().sourceUrl()); ExecutableCompilationUnit *cu = td->compilationUnit(); - myQmlType = qenginepriv->metaObjectForType(cu->metaTypeId); + myQmlType = qenginepriv->metaObjectForType(cu->metaTypeId.id()); } else { - myQmlType = qenginepriv->metaObjectForType(myTypeId); + myQmlType = qenginepriv->metaObjectForType(myTypeId.id()); } const QMetaObject *theirType = wrapperObject->metaObject(); diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp index 4beb6a4d07..254f1015e2 100644 --- a/src/qml/qml/qqmlvaluetype.cpp +++ b/src/qml/qml/qqmlvaluetype.cpp @@ -42,11 +42,11 @@ #include <QtCore/qmutex.h> #include <private/qqmlglobal_p.h> #include <QtCore/qdebug.h> +#include <private/qqmlengine_p.h> #include <private/qmetaobjectbuilder_p.h> #if QT_CONFIG(qml_itemmodel) #include <private/qqmlmodelindexvaluetype_p.h> #endif -#include <private/qmetatype_p.h> Q_DECLARE_METATYPE(QQmlProperty) @@ -221,61 +221,82 @@ void QQmlValueTypeFactory::registerValueTypes(const char *uri, int versionMajor, #endif } -QQmlValueType::QQmlValueType() : - _metaObject(nullptr), - gadgetPtr(nullptr), - metaType(QMetaType::UnknownType) +QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject) + : metaType(typeId) { + QMetaObjectBuilder builder(gadgetMetaObject); + dynamicMetaObject = builder.toMetaObject(); + *static_cast<QMetaObject*>(this) = *dynamicMetaObject; } -QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject) - : gadgetPtr(QMetaType::create(typeId)) - , metaType(typeId) +QQmlValueType::~QQmlValueType() { - QObjectPrivate *op = QObjectPrivate::get(this); - Q_ASSERT(!op->metaObject); - op->metaObject = this; + ::free(dynamicMetaObject); +} - QMetaObjectBuilder builder(gadgetMetaObject); - _metaObject = builder.toMetaObject(); +QQmlGadgetPtrWrapper *QQmlGadgetPtrWrapper::instance(QQmlEngine *engine, int index) +{ + return engine ? QQmlEnginePrivate::get(engine)->valueTypeInstance(index) : nullptr; +} - *static_cast<QMetaObject*>(this) = *_metaObject; +QQmlGadgetPtrWrapper::QQmlGadgetPtrWrapper(QQmlValueType *valueType, QObject *parent) + : QObject(parent), m_gadgetPtr(valueType->create()) +{ + QObjectPrivate *d = QObjectPrivate::get(this); + Q_ASSERT(!d->metaObject); + d->metaObject = valueType; } -QQmlValueType::~QQmlValueType() +QQmlGadgetPtrWrapper::~QQmlGadgetPtrWrapper() { - QObjectPrivate *op = QObjectPrivate::get(this); - Q_ASSERT(op->metaObject == nullptr || op->metaObject == this); - op->metaObject = nullptr; - ::free(const_cast<QMetaObject *>(_metaObject)); - metaType.destroy(gadgetPtr); + QObjectPrivate *d = QObjectPrivate::get(this); + static_cast<const QQmlValueType *>(d->metaObject)->destroy(m_gadgetPtr); + d->metaObject = nullptr; } -void QQmlValueType::read(QObject *obj, int idx) +void QQmlGadgetPtrWrapper::read(QObject *obj, int idx) { - void *a[] = { gadgetPtr, nullptr }; + Q_ASSERT(m_gadgetPtr); + void *a[] = { m_gadgetPtr, nullptr }; QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QQmlValueType::write(QObject *obj, int idx, QQmlPropertyData::WriteFlags flags) +void QQmlGadgetPtrWrapper::write(QObject *obj, int idx, QQmlPropertyData::WriteFlags flags) { - Q_ASSERT(gadgetPtr); + Q_ASSERT(m_gadgetPtr); int status = -1; - void *a[] = { gadgetPtr, nullptr, &status, &flags }; + void *a[] = { m_gadgetPtr, nullptr, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } -QVariant QQmlValueType::value() +QVariant QQmlGadgetPtrWrapper::value() +{ + Q_ASSERT(m_gadgetPtr); + return QVariant(metaTypeId(), m_gadgetPtr); +} + +void QQmlGadgetPtrWrapper::setValue(const QVariant &value) +{ + Q_ASSERT(m_gadgetPtr); + Q_ASSERT(metaTypeId() == value.userType()); + const QQmlValueType *type = valueType(); + type->destruct(m_gadgetPtr); + type->construct(m_gadgetPtr, value.constData()); +} + +int QQmlGadgetPtrWrapper::metaCall(QMetaObject::Call type, int id, void **argv) { - Q_ASSERT(gadgetPtr); - return QVariant(metaType.id(), gadgetPtr); + Q_ASSERT(m_gadgetPtr); + const QMetaObject *metaObject = valueType(); + QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(type, &metaObject, &id); + metaObject->d.static_metacall(static_cast<QObject *>(m_gadgetPtr), type, id, argv); + return id; } -void QQmlValueType::setValue(const QVariant &value) +const QQmlValueType *QQmlGadgetPtrWrapper::valueType() const { - Q_ASSERT(metaType.id() == value.userType()); - metaType.destruct(gadgetPtr); - metaType.construct(gadgetPtr, value.constData()); + const QObjectPrivate *d = QObjectPrivate::get(this); + return static_cast<const QQmlValueType *>(d->metaObject); } QAbstractDynamicMetaObject *QQmlValueType::toDynamicMetaObject(QObject *) @@ -287,12 +308,9 @@ void QQmlValueType::objectDestroyed(QObject *) { } -int QQmlValueType::metaCall(QObject *, QMetaObject::Call type, int _id, void **argv) +int QQmlValueType::metaCall(QObject *object, QMetaObject::Call type, int _id, void **argv) { - const QMetaObject *mo = _metaObject; - QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(type, &mo, &_id); - mo->d.static_metacall(reinterpret_cast<QObject*>(gadgetPtr), type, _id, argv); - return _id; + return static_cast<QQmlGadgetPtrWrapper *>(object)->metaCall(type, _id, argv); } QString QQmlPointFValueType::toString() const diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h index ff664adbe7..0b38c746d6 100644 --- a/src/qml/qml/qqmlvaluetype_p.h +++ b/src/qml/qml/qqmlvaluetype_p.h @@ -54,7 +54,9 @@ #include "qqml.h" #include "qqmlproperty.h" #include "qqmlproperty_p.h" + #include <private/qqmlnullablevalue_p.h> +#include <private/qmetatype_p.h> #include <QtCore/qobject.h> #include <QtCore/qrect.h> @@ -65,16 +67,20 @@ QT_BEGIN_NAMESPACE -class Q_QML_PRIVATE_EXPORT QQmlValueType : public QObject, public QAbstractDynamicMetaObject +class Q_QML_PRIVATE_EXPORT QQmlValueType : public QAbstractDynamicMetaObject { public: - QQmlValueType(); + QQmlValueType() : metaType(QMetaType::UnknownType) {} QQmlValueType(int userType, const QMetaObject *metaObject); - ~QQmlValueType() override; - void read(QObject *, int); - void write(QObject *, int, QQmlPropertyData::WriteFlags flags); - QVariant value(); - void setValue(const QVariant &); + ~QQmlValueType(); + + void *create() const { return metaType.create(); } + void destroy(void *gadgetPtr) const { metaType.destroy(gadgetPtr); } + + void construct(void *gadgetPtr, const void *copy) const { metaType.construct(gadgetPtr, copy); } + void destruct(void *gadgetPtr) const { metaType.destruct(gadgetPtr); } + + int metaTypeId() const { return metaType.id(); } // ---- dynamic meta object data interface QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) override; @@ -82,12 +88,33 @@ public: int metaCall(QObject *obj, QMetaObject::Call type, int _id, void **argv) override; // ---- -private: - const QMetaObject *_metaObject; - void *gadgetPtr; - public: QMetaType metaType; + QMetaObject *dynamicMetaObject = nullptr; +}; + +class Q_QML_PRIVATE_EXPORT QQmlGadgetPtrWrapper : public QObject +{ + Q_OBJECT +public: + static QQmlGadgetPtrWrapper *instance(QQmlEngine *engine, int index); + + QQmlGadgetPtrWrapper(QQmlValueType *valueType, QObject *parent); + ~QQmlGadgetPtrWrapper(); + + void read(QObject *obj, int idx); + void write(QObject *obj, int idx, QQmlPropertyData::WriteFlags flags); + QVariant value(); + void setValue(const QVariant &value); + + int metaTypeId() const { return valueType()->metaTypeId(); } + int metaCall(QMetaObject::Call type, int id, void **argv); + QMetaProperty property(int index) { return valueType()->property(index); } + +private: + const QQmlValueType *valueType() const; + + void *m_gadgetPtr = nullptr; }; class Q_QML_PRIVATE_EXPORT QQmlValueTypeFactory @@ -219,6 +246,7 @@ struct QQmlEasingValueType QEasingCurve v; Q_GADGET QML_NAMED_ELEMENT(Easing) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("Use the Type enum.") Q_PROPERTY(QQmlEasingValueType::Type type READ type WRITE setType FINAL) @@ -282,18 +310,14 @@ public: template<typename T> int qmlRegisterValueTypeEnums(const char *uri, int versionMajor, int versionMinor, const char *qmlName) { - QByteArray name(T::staticMetaObject.className()); - - QByteArray pointerName(name + '*'); - QQmlPrivate::RegisterType type = { 0, - qRegisterNormalizedMetaType<T *>(pointerName.constData()), 0, 0, nullptr, + QMetaType::fromType<T*>(), QMetaType(), 0, nullptr, QString(), - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, nullptr, nullptr, @@ -302,7 +326,7 @@ int qmlRegisterValueTypeEnums(const char *uri, int versionMajor, int versionMino nullptr, nullptr, nullptr, - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index ecb86e2f10..aa9f4bc1bd 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. @@ -136,6 +148,20 @@ static void list_clear(QQmlListProperty<QObject> *prop) resolved.activateSignal(); } +static void list_replace(QQmlListProperty<QObject> *prop, int index, QObject *o) +{ + const ResolvedList resolved(prop); + resolved.list()->replace(index, o); + resolved.activateSignal(); +} + +static void list_removeLast(QQmlListProperty<QObject> *prop) +{ + const ResolvedList resolved(prop); + resolved.list()->removeLast(); + resolved.activateSignal(); +} + QQmlVMEVariantQObjectPtr::QQmlVMEVariantQObjectPtr() : QQmlGuard<QObject>(nullptr), m_target(nullptr), m_index(-1) { @@ -289,11 +315,13 @@ bool QQmlInterceptorMetaObject::intercept(QMetaObject::Call c, int id, void **a) continue; const int valueIndex = vi->m_propertyIndex.valueTypeIndex(); - int type = QQmlData::get(object)->propertyCache->property(id)->propType(); + const QQmlData *data = QQmlData::get(object); + const int type = data->propertyCache->property(id)->propType(); if (type != QMetaType::UnknownType) { if (valueIndex != -1) { - QQmlValueType *valueType = QQmlValueTypeFactory::valueType(type); + QQmlGadgetPtrWrapper *valueType = QQmlGadgetPtrWrapper::instance( + data->context->engine, type); Q_ASSERT(valueType); // @@ -327,7 +355,7 @@ bool QQmlInterceptorMetaObject::intercept(QMetaObject::Call c, int id, void **a) // (7) Issue the interceptor call with the new component value. // - QMetaProperty valueProp = valueType->metaObject()->property(valueIndex); + QMetaProperty valueProp = valueType->property(valueIndex); QVariant newValue(type, a[0]); valueType->read(object, id); @@ -731,11 +759,37 @@ 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)), - list_append, list_count, list_at, list_clear); + object, reinterpret_cast<void *>(quintptr(encodedIndex)), + list_append, list_count, list_at, + list_clear, list_replace, list_removeLast); } else { *reinterpret_cast<QObject **>(a[0]) = readPropertyAsQObject(id); } @@ -879,9 +933,9 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * return -1; const QQmlPropertyData *pd = targetDData->propertyCache->property(coreIndex); // Value type property or deep alias - QQmlValueType *valueType = QQmlValueTypeFactory::valueType(pd->propType()); + QQmlGadgetPtrWrapper *valueType = QQmlGadgetPtrWrapper::instance( + ctxt->engine, pd->propType()); if (valueType) { - valueType->read(target, coreIndex); int rv = QMetaObject::metacall(valueType, c, valueTypePropertyIndex, a); @@ -1184,7 +1238,7 @@ void QQmlVMEMetaObject::ensureQObjectWrapper() void QQmlVMEMetaObject::mark(QV4::MarkStack *markStack) { - if (engine != markStack->engine) + if (engine != markStack->engine()) return; propertyAndMethodStorage.markOnce(markStack); diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index c820499703..61070113cc 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -1203,25 +1203,15 @@ void QQmlXMLHttpRequest::requestFromUrl(const QUrl &url) if (m_method == QLatin1String("PUT")) { if (!xhrFileWrite()) { - if (qEnvironmentVariableIsSet("QML_XHR_ALLOW_FILE_WRITE")) { - qWarning("XMLHttpRequest: Tried to use PUT on a local file despite being disabled."); - return; - } else { - qWarning("XMLHttpRequest: Using PUT on a local file is dangerous " - "and will be disabled by default in a future Qt version." - "Set QML_XHR_ALLOW_FILE_WRITE to 1 if you wish to continue using this feature."); - } + qWarning("XMLHttpRequest: Using PUT on a local file is disabled by default.\n" + "Set QML_XHR_ALLOW_FILE_WRITE to 1 to enable this feature."); + return; } } else if (m_method == QLatin1String("GET")) { if (!xhrFileRead()) { - if (qEnvironmentVariableIsSet("QML_XHR_ALLOW_FILE_READ")) { - qWarning("XMLHttpRequest: Tried to use GET on a local file despite being disabled."); - return; - } else { - qWarning("XMLHttpRequest: Using GET on a local file is dangerous " - "and will be disabled by default in a future Qt version." - "Set QML_XHR_ALLOW_FILE_READ to 1 if you wish to continue using this feature."); - } + qWarning("XMLHttpRequest: Using GET on a local file is disabled by default.\n" + "Set QML_XHR_ALLOW_FILE_READ to 1 to enable this feature."); + return; } } else { qWarning("XMLHttpRequest: Unsupported method used on a local file"); @@ -1291,7 +1281,7 @@ void QQmlXMLHttpRequest::requestFromUrl(const QUrl &url) if (m_network->bytesAvailable() > 0) readyRead(); - QNetworkReply::NetworkError networkError = m_network->networkError(); + QNetworkReply::NetworkError networkError = m_network->error(); if (networkError != QNetworkReply::NoError) { error(networkError); } else { diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 02032142ee..4e5ab9b899 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -722,70 +722,114 @@ ReturnedValue QtObject::method_tint(const FunctionObject *b, const Value *, cons return scope.engine->fromVariant(QQml_colorProvider()->tint(v1, v2)); } +namespace { +template <typename T> +QString formatDateTimeObjectUsingDateFormat(T formatThis, Qt::DateFormat format) { + switch (format) { + case Qt::TextDate: + case Qt::ISODate: + case Qt::RFC2822Date: + case Qt::ISODateWithMs: + return formatThis.toString(format); + default: // ### Qt 6: remove once qtbase has removed the rest of the enum ! + break; + } + // Q_UNREACHABLE(); // ### Qt 6: restore once the default is gone + return QString(); +} + +template <typename T> +ReturnedValue formatDateTimeObject(const T &formatThis, const QV4::Scope &scope, const QString &functionName, int argc, const Value *argv) { + + QString formatted; + if (argc >= 2) { + QV4::ScopedString s(scope, argv[1]); + if (s) { + if (argc == 3) + scope.engine->throwError(QLatin1String("%1(): Stay argument, third argument can only be used if second argument is a locale").arg(functionName)); + QString format = s->toQString(); + formatted = formatThis.toString(format); + } else if (argv[1].isNumber()) { + if (argc == 3) + scope.engine->throwError(QLatin1String("%1(): Stay argument, third argument can only be used if second argument is a locale").arg(functionName)); + quint32 intFormat = argv[1].asDouble(); + Qt::DateFormat format = Qt::DateFormat(intFormat); + formatted = formatDateTimeObjectUsingDateFormat(formatThis, format); + } else { + QLocale::FormatType formatOptions = QLocale::ShortFormat; + if (argc == 3) { + if (argv[2].isNumber()) + formatOptions = QLocale::FormatType(quint32(argv[2].asDouble())); + else + scope.engine->throwError(QLatin1String("%1(): Third argument must be a Locale format option").arg(functionName)); + } + auto enginePriv = QQmlEnginePrivate::get(scope.engine->qmlEngine()); + auto localeMetaTypeId = qMetaTypeId<QLocale>(); + QVariant locale = enginePriv->v4engine()->toVariant(argv[1], localeMetaTypeId); + if (!locale.canConvert(localeMetaTypeId)) + scope.engine->throwError(QLatin1String("%1(): Bad second argument (must be either string, number or locale)").arg(functionName)); + formatted = locale.value<QLocale>().toString(formatThis, formatOptions); + } + } else { + formatted = QLocale().toString(formatThis, QLocale::ShortFormat); + } + + return Encode(scope.engine->newString(formatted)); +} + +} + /*! -\qmlmethod string Qt::formatDate(datetime date, variant format) +\qmlmethod string Qt::formatDate(datetime date, variant format, variant localeFormatOption) -Returns a string representation of \a date, optionally formatted according -to \a format. +Returns a string representation of \a date, optionally formatted using \a format. The \a date parameter may be a JavaScript \c Date object, a \l{date}{date} -property, a QDate, or QDateTime value. The \a format parameter may be any of -the possible format values as described for +property, a QDate, or QDateTime value. The \a format and \a localeFormatOption +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 {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. +\l {QLocale::FormatType}{Locale.ShortFormat} using the +default locale. \sa Locale */ ReturnedValue QtObject::method_formatDate(const FunctionObject *b, const Value *, const Value *argv, int argc) { QV4::Scope scope(b); - if (argc < 1 || argc > 2) - THROW_GENERIC_ERROR("Qt.formatDate(): Invalid arguments"); + if (argc < 1) + THROW_GENERIC_ERROR("Qt.formatDate(): Missing argument"); + if (argc > 3) + THROW_GENERIC_ERROR("Qt.formatDate(): Stray arguments; formatDate takes at most 3 arguments."); - Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate; QDate date = scope.engine->toVariant(argv[0], -1).toDateTime().date(); - QString formattedDate; - if (argc == 2) { - QV4::ScopedString s(scope, argv[1]); - if (s) { - QString format = s->toQString(); - formattedDate = date.toString(format); - } else if (argv[1].isNumber()) { - quint32 intFormat = argv[1].asDouble(); - Qt::DateFormat format = Qt::DateFormat(intFormat); - formattedDate = date.toString(format); - } else { - THROW_GENERIC_ERROR("Qt.formatDate(): Invalid date format"); - } - } else { - formattedDate = date.toString(enumFormat); - } - - return Encode(scope.engine->newString(formattedDate)); + return formatDateTimeObject(date, scope, QLatin1String("Qt.formatDate"), argc, argv); } /*! -\qmlmethod string Qt::formatTime(datetime time, variant format) +\qmlmethod string Qt::formatTime(datetime time, variant format, variant localeFormatOption) -Returns a string representation of \a time, optionally formatted according to -\a format. +Returns a string representation of \a time, optionally formatted using +\a format, and, if provided, \a localeFormatOption. The \a time parameter may be a JavaScript \c Date object, a QTime, or QDateTime -value. The \a format parameter may be any of the possible format values as -described for \l{QtQml::Qt::formatDateTime()}{Qt.formatDateTime()}. +value. The \a format and \a localeFormatOption 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 time is formatted using -\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. +\l {QLocale::FormatType}{Locale.ShortFormat} using the default locale. \sa Locale */ ReturnedValue QtObject::method_formatTime(const FunctionObject *b, const Value *, const Value *argv, int argc) { QV4::Scope scope(b); - if (argc < 1 || argc > 2) - THROW_GENERIC_ERROR("Qt.formatTime(): Invalid arguments"); + if (argc < 1) + THROW_GENERIC_ERROR("Qt.formatTime(): Missing argument"); + if (argc > 3) + THROW_GENERIC_ERROR("Qt.formatTime(): Stray arguments; formatTime takes at most 3 arguments."); QVariant argVariant = scope.engine->toVariant(argv[0], -1); QTime time; @@ -793,47 +837,34 @@ ReturnedValue QtObject::method_formatTime(const FunctionObject *b, const Value * time = argVariant.toDateTime().time(); else // if (argVariant.type() == QVariant::Time), or invalid. time = argVariant.toTime(); - - Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate; - QString formattedTime; - if (argc == 2) { - QV4::ScopedString s(scope, argv[1]); - if (s) { - QString format = s->toQString(); - formattedTime = time.toString(format); - } else if (argv[1].isNumber()) { - quint32 intFormat = argv[1].asDouble(); - Qt::DateFormat format = Qt::DateFormat(intFormat); - formattedTime = time.toString(format); - } else { - THROW_GENERIC_ERROR("Qt.formatTime(): Invalid time format"); - } - } else { - formattedTime = time.toString(enumFormat); - } - - return Encode(scope.engine->newString(formattedTime)); + return formatDateTimeObject(time, scope, QLatin1String("Qt.formatTime"), argc, argv); } /*! -\qmlmethod string Qt::formatDateTime(datetime dateTime, variant format) +\qmlmethod string Qt::formatDateTime(datetime dateTime, variant format, variant localeFormatOption) -Returns a string representation of \a dateTime, optionally formatted according to -\a format. +Returns a string representation of \a dateTime, optionally formatted using +\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 {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. Otherwise, -\a format should be either: +\l {QLocale::FormatType}{Locale.ShortFormat} using the +default locale. Otherwise, \a format should be either: \list \li One of the Qt::DateFormat enumeration values, such as - \c Qt.DefaultLocaleShortDate or \c Qt.ISODate + \c Qt.RFC2822Date or \c Qt.ISODate. \li A string that specifies the format of the returned string, as detailed below. +\li A \c locale object. \endlist +If \a format specifies a locale object, \dateTime is formatted +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}{Locale.ShortFormat} is used. + If \a format specifies a format string, it should use the following expressions to specify the date: @@ -910,29 +941,13 @@ with the \a format values below to produce the following results: ReturnedValue QtObject::method_formatDateTime(const FunctionObject *b, const Value *, const Value *argv, int argc) { QV4::Scope scope(b); - if (argc < 1 || argc > 2) - THROW_GENERIC_ERROR("Qt.formatDateTime(): Invalid arguments"); + if (argc < 1) + THROW_GENERIC_ERROR("Qt.formatDateTime(): Missing argument"); + if (argc > 3) + THROW_GENERIC_ERROR("Qt.formatDateTime(): Stray arguments; formatDate takes at most 3 arguments."); - Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate; QDateTime dt = scope.engine->toVariant(argv[0], -1).toDateTime(); - QString formattedDt; - if (argc == 2) { - QV4::ScopedString s(scope, argv[1]); - if (s) { - QString format = s->toQString(); - formattedDt = dt.toString(format); - } else if (argv[1].isNumber()) { - quint32 intFormat = argv[1].asDouble(); - Qt::DateFormat format = Qt::DateFormat(intFormat); - formattedDt = dt.toString(format); - } else { - THROW_GENERIC_ERROR("Qt.formatDateTime(): Invalid datetime format"); - } - } else { - formattedDt = dt.toString(enumFormat); - } - - return Encode(scope.engine->newString(formattedDt)); + return formatDateTimeObject(dt, scope, QLatin1String("Qt.formatDateTime"), argc, argv); } /*! diff --git a/src/qml/qmldirparser/qqmldirparser.cpp b/src/qml/qmldirparser/qqmldirparser.cpp index 36b47a3302..161d902854 100644 --- a/src/qml/qmldirparser/qqmldirparser.cpp +++ b/src/qml/qmldirparser/qqmldirparser.cpp @@ -60,17 +60,17 @@ static int parseInt(const QStringRef &str, bool *ok) return number; } -static bool parseVersion(const QString &str, int *major, int *minor) +static QTypeRevision parseVersion(const QString &str) { const int dotIndex = str.indexOf(QLatin1Char('.')); if (dotIndex != -1 && str.indexOf(QLatin1Char('.'), dotIndex + 1) == -1) { bool ok = false; - *major = parseInt(QStringRef(&str, 0, dotIndex), &ok); - if (ok) - *minor = parseInt(QStringRef(&str, dotIndex + 1, str.length() - dotIndex - 1), &ok); - return ok; + const int major = parseInt(QStringRef(&str, 0, dotIndex), &ok); + if (!ok) return QTypeRevision(); + const int minor = parseInt(QStringRef(&str, dotIndex + 1, str.length() - dotIndex - 1), &ok); + return ok ? QTypeRevision::fromVersion(major, minor) : QTypeRevision(); } - return false; + return QTypeRevision(); } void QQmlDirParser::clear() @@ -203,7 +203,7 @@ bool QQmlDirParser::parse(const QString &source) QStringLiteral("internal types require 2 arguments, but %1 were provided").arg(sectionCount - 1)); continue; } - Component entry(sections[1], sections[2], -1, -1); + Component entry(sections[1], sections[2], QTypeRevision()); entry.internal = true; _components.insert(entry.typeName, entry); } else if (sections[0] == QLatin1String("singleton")) { @@ -214,16 +214,16 @@ bool QQmlDirParser::parse(const QString &source) } else if (sectionCount == 3) { // handle qmldir directory listing case where singleton is defined in the following pattern: // singleton TestSingletonType TestSingletonType.qml - Component entry(sections[1], sections[2], -1, -1); + Component entry(sections[1], sections[2], QTypeRevision()); entry.singleton = true; _components.insert(entry.typeName, entry); } else { // handle qmldir module listing case where singleton is defined in the following pattern: // singleton TestSingletonType 2.0 TestSingletonType20.qml - int major, minor; - if (parseVersion(sections[2], &major, &minor)) { + const QTypeRevision version = parseVersion(sections[2]); + if (version.isValid()) { const QString &fileName = sections[3]; - Component entry(sections[1], fileName, major, minor); + Component entry(sections[1], fileName, version); entry.singleton = true; _components.insert(entry.typeName, entry); } else { @@ -253,9 +253,9 @@ bool QQmlDirParser::parse(const QString &source) continue; } - int major, minor; - if (parseVersion(sections[2], &major, &minor)) { - Component entry(sections[1], QString(), major, minor); + const QTypeRevision version = parseVersion(sections[2]); + if (version.isValid()) { + Component entry(sections[1], QString(), version); entry.internal = true; _dependencies.insert(entry.typeName, entry); } else { @@ -270,19 +270,19 @@ bool QQmlDirParser::parse(const QString &source) _imports << sections[1]; } else if (sectionCount == 2) { // No version specified (should only be used for relative qmldir files) - const Component entry(sections[0], sections[1], -1, -1); + const Component entry(sections[0], sections[1], QTypeRevision()); _components.insert(entry.typeName, entry); } else if (sectionCount == 3) { - int major, minor; - if (parseVersion(sections[1], &major, &minor)) { + const QTypeRevision version = parseVersion(sections[1]); + if (version.isValid()) { const QString &fileName = sections[2]; if (fileName.endsWith(QLatin1String(".js")) || fileName.endsWith(QLatin1String(".mjs"))) { // A 'js' extension indicates a namespaced script import - const Script entry(sections[0], fileName, major, minor); + const Script entry(sections[0], fileName, version); _scripts.append(entry); } else { - const Component entry(sections[0], fileName, major, minor); + const Component entry(sections[0], fileName, version); _components.insert(entry.typeName, entry); } } else { @@ -302,8 +302,8 @@ bool QQmlDirParser::parse(const QString &source) void QQmlDirParser::reportError(quint16 line, quint16 column, const QString &description) { QQmlJS::DiagnosticMessage error; - error.line = line; - error.column = column; + error.loc.startLine = line; + error.loc.startColumn = column; error.message = description; _errors.append(error); } @@ -319,7 +319,7 @@ bool QQmlDirParser::hasError() const void QQmlDirParser::setError(const QQmlJS::DiagnosticMessage &e) { _errors.clear(); - reportError(e.line, e.column, e.message); + reportError(e.loc.startLine, e.loc.startColumn, e.message); } QList<QQmlJS::DiagnosticMessage> QQmlDirParser::errors(const QString &uri) const @@ -387,15 +387,17 @@ QString QQmlDirParser::className() const QDebug &operator<< (QDebug &debug, const QQmlDirParser::Component &component) { - const QString output = QStringLiteral("{%1 %2.%3}"). - arg(component.typeName).arg(component.majorVersion).arg(component.minorVersion); + const QString output = QStringLiteral("{%1 %2.%3}") + .arg(component.typeName).arg(component.version.majorVersion()) + .arg(component.version.minorVersion()); return debug << qPrintable(output); } QDebug &operator<< (QDebug &debug, const QQmlDirParser::Script &script) { - const QString output = QStringLiteral("{%1 %2.%3}"). - arg(script.nameSpace).arg(script.majorVersion).arg(script.minorVersion); + const QString output = QStringLiteral("{%1 %2.%3}") + .arg(script.nameSpace).arg(script.version.majorVersion()) + .arg(script.version.minorVersion()); return debug << qPrintable(output); } diff --git a/src/qml/qmldirparser/qqmldirparser_p.h b/src/qml/qmldirparser/qqmldirparser_p.h index 3696a1aa12..ccdac8f484 100644 --- a/src/qml/qmldirparser/qqmldirparser_p.h +++ b/src/qml/qmldirparser/qqmldirparser_p.h @@ -54,6 +54,7 @@ #include <QtCore/QUrl> #include <QtCore/QHash> #include <QtCore/QDebug> +#include <QtCore/QTypeRevision> #include <private/qtqmlcompilerglobal_p.h> #include <private/qqmljsengine_p.h> #include <private/qqmljsdiagnosticmessage_p.h> @@ -101,8 +102,8 @@ public: { Component() = default; - Component(const QString &typeName, const QString &fileName, int majorVersion, int minorVersion) - : typeName(typeName), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion), + Component(const QString &typeName, const QString &fileName, QTypeRevision version) + : typeName(typeName), fileName(fileName), version(version), internal(false), singleton(false) { checkNonRelative("Component", typeName, fileName); @@ -110,8 +111,7 @@ public: QString typeName; QString fileName; - int majorVersion = 0; - int minorVersion = 0; + QTypeRevision version = QTypeRevision::zero(); bool internal = false; bool singleton = false; }; @@ -120,16 +120,15 @@ public: { Script() = default; - Script(const QString &nameSpace, const QString &fileName, int majorVersion, int minorVersion) - : nameSpace(nameSpace), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion) + Script(const QString &nameSpace, const QString &fileName, QTypeRevision version) + : nameSpace(nameSpace), fileName(fileName), version(version) { checkNonRelative("Script", nameSpace, fileName); } QString nameSpace; QString fileName; - int majorVersion = 0; - int minorVersion = 0; + QTypeRevision version = QTypeRevision::zero(); }; QMultiHash<QString,Component> components() const; diff --git a/src/qml/qtqmlglobal_p.h b/src/qml/qtqmlglobal_p.h index 9ca0cf2abe..a729729b67 100644 --- a/src/qml/qtqmlglobal_p.h +++ b/src/qml/qtqmlglobal_p.h @@ -60,6 +60,8 @@ #define Q_QML_PRIVATE_EXPORT Q_QML_EXPORT +void Q_QML_PRIVATE_EXPORT qml_register_types_QtQml(); + #if !defined(QT_QMLDEVTOOLS_LIB) && !defined(QT_BUILD_QMLDEVTOOLS_LIB) # define Q_QML_AUTOTEST_EXPORT Q_AUTOTEST_EXPORT #else diff --git a/src/qml/types/qqmlbind_p.h b/src/qml/types/qqmlbind_p.h index c709224c23..052af0d167 100644 --- a/src/qml/types/qqmlbind_p.h +++ b/src/qml/types/qqmlbind_p.h @@ -77,11 +77,12 @@ private: Q_PROPERTY(QString property READ property WRITE setProperty) Q_PROPERTY(QJSValue value READ value WRITE setValue) Q_PROPERTY(bool when READ when WRITE setWhen) - Q_PROPERTY(bool delayed READ delayed WRITE setDelayed REVISION 8) + Q_PROPERTY(bool delayed READ delayed WRITE setDelayed REVISION(2, 8)) Q_PROPERTY(RestorationMode restoreMode READ restoreMode WRITE setRestoreMode - NOTIFY restoreModeChanged REVISION 14) + NOTIFY restoreModeChanged REVISION(2, 14)) Q_ENUM(RestorationMode) QML_NAMED_ELEMENT(Binding) + QML_ADDED_IN_VERSION(2, 0) public: QQmlBind(QObject *parent=nullptr); diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp index 1e801641e5..4c44bba43e 100644 --- a/src/qml/types/qqmlconnections.cpp +++ b/src/qml/types/qqmlconnections.cpp @@ -238,7 +238,8 @@ void QQmlConnectionsParser::verifyBindings(const QQmlRefPointer<QV4::ExecutableC const QV4::CompiledData::Binding *binding = props.at(ii); const QString &propName = compilationUnit->stringAt(binding->propertyNameIndex); - if (!propName.startsWith(QLatin1String("on")) || (propName.length() < 3 || !propName.at(2).isUpper())) { + const bool thirdCharacterIsValid = (propName.length() >= 2) && (propName.at(2).isUpper() || propName.at(2) == '_'); + if (!propName.startsWith(QLatin1String("on")) || !thirdCharacterIsValid) { error(props.at(ii), QQmlConnections::tr("Cannot assign to non-existent property \"%1\"").arg(propName)); return; } diff --git a/src/qml/types/qqmlconnections_p.h b/src/qml/types/qqmlconnections_p.h index 7bf688cf75..8ed874d9fc 100644 --- a/src/qml/types/qqmlconnections_p.h +++ b/src/qml/types/qqmlconnections_p.h @@ -69,9 +69,10 @@ class Q_AUTOTEST_EXPORT QQmlConnections : public QObject, public QQmlParserStatu Q_INTERFACES(QQmlParserStatus) Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged) - Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged REVISION 3) + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged REVISION(2, 3)) Q_PROPERTY(bool ignoreUnknownSignals READ ignoreUnknownSignals WRITE setIgnoreUnknownSignals) QML_NAMED_ELEMENT(Connections) + QML_ADDED_IN_VERSION(2, 0) public: QQmlConnections(QObject *parent=nullptr); @@ -88,7 +89,7 @@ public: Q_SIGNALS: void targetChanged(); - Q_REVISION(3) void enabledChanged(); + Q_REVISION(2, 3) void enabledChanged(); private: void connectSignals(); diff --git a/src/qml/types/qqmltimer_p.h b/src/qml/types/qqmltimer_p.h index 0cd93e4659..a8236977c4 100644 --- a/src/qml/types/qqmltimer_p.h +++ b/src/qml/types/qqmltimer_p.h @@ -73,6 +73,7 @@ class Q_QML_PRIVATE_EXPORT QQmlTimer : public QObject, public QQmlParserStatus Q_PROPERTY(bool triggeredOnStart READ triggeredOnStart WRITE setTriggeredOnStart NOTIFY triggeredOnStartChanged) Q_PROPERTY(QObject *parent READ parent CONSTANT) QML_NAMED_ELEMENT(Timer) + QML_ADDED_IN_VERSION(2, 0) public: QQmlTimer(QObject *parent=nullptr); diff --git a/src/qmldebug/qmldebug.pro b/src/qmldebug/qmldebug.pro index 94d300b765..ac3f3bf3bf 100644 --- a/src/qmldebug/qmldebug.pro +++ b/src/qmldebug/qmldebug.pro @@ -1,5 +1,5 @@ TARGET = QtQmlDebug -QT = core-private network packetprotocol-private +QT = core-private qml-private network packetprotocol-private CONFIG += static internal_module load(qt_module) @@ -8,6 +8,7 @@ SOURCES += \ qqmldebugclient.cpp \ qqmldebugconnection.cpp \ qqmldebugmessageclient.cpp \ + qqmldebugtranslationclient.cpp \ qqmlenginecontrolclient.cpp \ qqmlenginedebugclient.cpp \ qqmlinspectorclient.cpp \ @@ -24,6 +25,7 @@ HEADERS += \ qqmldebugclient_p_p.h \ qqmldebugconnection_p.h \ qqmldebugmessageclient_p.h \ + qqmldebugtranslationclient_p.h \ qqmlenginedebugclient_p.h \ qqmlenginedebugclient_p_p.h \ qqmlenginecontrolclient_p.h \ diff --git a/src/qmldebug/qqmldebugtranslationclient.cpp b/src/qmldebug/qqmldebugtranslationclient.cpp new file mode 100644 index 0000000000..1fd0748fa0 --- /dev/null +++ b/src/qmldebug/qqmldebugtranslationclient.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmldebugtranslationclient_p.h" +#include "qqmldebugconnection_p.h" + +#include <QUrl> +#include <QDataStream> + +#include <QDebug> +#include <QtPacketProtocol/private/qpacket_p.h> + +QT_BEGIN_NAMESPACE + +/*! + \class QQmlDebugTranslationClient + \internal + + \brief Client for the debug translation service + + The QQmlDebugTranslationClient can test if translated texts will fit. + */ + +QQmlDebugTranslationClient::QQmlDebugTranslationClient(QQmlDebugConnection *client) + : QQmlDebugClient(QLatin1String("DebugTranslation"), client) +{ +} + +void QQmlDebugTranslationClient::messageReceived(const QByteArray &data) +{ + Q_UNUSED(data); +} + +void QQmlDebugTranslationClient::triggerLanguage(const QUrl &url, const QString &locale) +{ + Q_UNUSED(url) + Q_UNUSED(locale) +} + +QT_END_NAMESPACE diff --git a/src/qmldebug/qqmldebugtranslationclient_p.h b/src/qmldebug/qqmldebugtranslationclient_p.h new file mode 100644 index 0000000000..3163759d9e --- /dev/null +++ b/src/qmldebug/qqmldebugtranslationclient_p.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QQMLDEBUGTRANSLATIONCLIENT_P_H +#define QQMLDEBUGTRANSLATIONCLIENT_P_H + +#include "qqmldebugclient_p.h" + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +class QQmlDebugTranslationClient : public QQmlDebugClient +{ + Q_OBJECT + +public: + //needs to be in sync with QQmlDebugTranslationServiceImpl in qqmldebugtranslationservice.h + enum Command { + ChangeLanguage, + ChangeWarningColor, + ChangeElidedTextWarningString, + SetDebugTranslationServiceLogFile, + EnableElidedTextWarning, + DisableElidedTextWarning, + TestAllLanguages + }; + + explicit QQmlDebugTranslationClient(QQmlDebugConnection *client); + + virtual void messageReceived(const QByteArray &) override; + void triggerLanguage(const QUrl &url, const QString &locale); +}; + +QT_END_NAMESPACE + +#endif // QQMLDEBUGTRANSLATIONCLIENT_P_H diff --git a/src/imports/models/dependencies.json b/src/qmlmodels/dependencies.json index 0d4f101c7a..0d4f101c7a 100644 --- a/src/imports/models/dependencies.json +++ b/src/qmlmodels/dependencies.json diff --git a/src/qmlmodels/qmlmodels.pro b/src/qmlmodels/qmlmodels.pro index d3a7495599..34380ee14e 100644 --- a/src/qmlmodels/qmlmodels.pro +++ b/src/qmlmodels/qmlmodels.pro @@ -66,7 +66,7 @@ qtConfig(qml-delegate-model) { QMLTYPES_FILENAME = plugins.qmltypes QMLTYPES_INSTALL_DIR = $$[QT_INSTALL_QML]/QtQml/Models QML_IMPORT_NAME = QtQml.Models -IMPORT_VERSION = 2.15 +QML_IMPORT_VERSION = $$QT_VERSION CONFIG += qmltypes install_qmltypes install_metatypes load(qt_module) diff --git a/src/qmlmodels/qqmlabstractdelegatecomponent_p.h b/src/qmlmodels/qqmlabstractdelegatecomponent_p.h index 07cae6b092..853a7e8af8 100644 --- a/src/qmlmodels/qqmlabstractdelegatecomponent_p.h +++ b/src/qmlmodels/qqmlabstractdelegatecomponent_p.h @@ -65,6 +65,7 @@ class Q_QMLMODELS_PRIVATE_EXPORT QQmlAbstractDelegateComponent : public QQmlComp { Q_OBJECT QML_NAMED_ELEMENT(AbstractDelegateComponent) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("Cannot create instance of abstract class AbstractDelegateComponent.") public: diff --git a/src/qmlmodels/qqmladaptormodel.cpp b/src/qmlmodels/qqmladaptormodel.cpp index fbb85327a7..8c8c37d237 100644 --- a/src/qmlmodels/qqmladaptormodel.cpp +++ b/src/qmlmodels/qqmladaptormodel.cpp @@ -93,7 +93,7 @@ class QQmlDMCachedModelData : public QQmlDelegateModelItem { public: QQmlDMCachedModelData( - QQmlDelegateModelItemMetaType *metaType, + const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType, VDMModelDelegateDataType *dataType, int index, int row, int column); @@ -255,7 +255,9 @@ public: bool hasModelData; }; -QQmlDMCachedModelData::QQmlDMCachedModelData(QQmlDelegateModelItemMetaType *metaType, VDMModelDelegateDataType *dataType, int index, int row, int column) +QQmlDMCachedModelData::QQmlDMCachedModelData( + const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType, + VDMModelDelegateDataType *dataType, int index, int row, int column) : QQmlDelegateModelItem(metaType, dataType, index, row, column) , type(dataType) { @@ -390,7 +392,7 @@ class QQmlDMAbstractItemModelData : public QQmlDMCachedModelData public: QQmlDMAbstractItemModelData( - QQmlDelegateModelItemMetaType *metaType, + const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType, VDMModelDelegateDataType *dataType, int index, int row, int column) : QQmlDMCachedModelData(metaType, dataType, index, row, column) @@ -458,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 @@ -512,7 +514,7 @@ public: QQmlDelegateModelItem *createItem( QQmlAdaptorModel &model, - QQmlDelegateModelItemMetaType *metaType, + const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType, int index, int row, int column) const override { VDMAbstractItemModelDataType *dataType = const_cast<VDMAbstractItemModelDataType *>(this); @@ -560,7 +562,7 @@ class QQmlDMListAccessorData : public QQmlDelegateModelItem Q_OBJECT Q_PROPERTY(QVariant modelData READ modelData WRITE setModelData NOTIFY modelDataChanged) public: - QQmlDMListAccessorData(QQmlDelegateModelItemMetaType *metaType, + QQmlDMListAccessorData(const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType, QQmlAdaptorModel::Accessors *accessor, int index, int row, int column, const QVariant &value) : QQmlDelegateModelItem(metaType, accessor, index, row, column) @@ -676,7 +678,7 @@ public: QQmlDelegateModelItem *createItem( QQmlAdaptorModel &model, - QQmlDelegateModelItemMetaType *metaType, + const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType, int index, int row, int column) const override { VDMListDelegateDataType *dataType = const_cast<VDMListDelegateDataType *>(this); @@ -719,7 +721,7 @@ class QQmlDMObjectData : public QQmlDelegateModelItem, public QQmlAdaptorModelPr Q_INTERFACES(QQmlAdaptorModelProxyInterface) public: QQmlDMObjectData( - QQmlDelegateModelItemMetaType *metaType, + const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType, VDMObjectDelegateDataType *dataType, int index, int row, int column, QObject *object); @@ -790,7 +792,7 @@ public: QQmlDelegateModelItem *createItem( QQmlAdaptorModel &model, - QQmlDelegateModelItemMetaType *metaType, + const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType, int index, int row, int column) const override { VDMObjectDelegateDataType *dataType = const_cast<VDMObjectDelegateDataType *>(this); @@ -930,7 +932,7 @@ public: VDMObjectDelegateDataType *m_type; }; -QQmlDMObjectData::QQmlDMObjectData(QQmlDelegateModelItemMetaType *metaType, +QQmlDMObjectData::QQmlDMObjectData(const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType, VDMObjectDelegateDataType *dataType, int index, int row, int column, QObject *object) @@ -975,6 +977,9 @@ void QQmlAdaptorModel::setModel(const QVariant &variant, QObject *parent, QQmlEn } else if (list.type() == QQmlListAccessor::ListProperty) { setObject(static_cast<const QQmlListReference *>(variant.constData())->object(), parent); accessors = new VDMObjectDelegateDataType; + } else if (list.type() == QQmlListAccessor::ObjectList) { + setObject(nullptr, parent); + accessors = new VDMObjectDelegateDataType; } else if (list.type() != QQmlListAccessor::Invalid && list.type() != QQmlListAccessor::Instance) { // Null QObject setObject(nullptr, parent); @@ -1030,9 +1035,9 @@ int QQmlAdaptorModel::indexAt(int row, int column) const return column * rowCount() + row; } -void QQmlAdaptorModel::useImportVersion(int minorVersion) +void QQmlAdaptorModel::useImportVersion(QTypeRevision revision) { - modelItemRevision = minorVersion; + modelItemRevision = revision; } void QQmlAdaptorModel::objectDestroyed(QObject *) diff --git a/src/qmlmodels/qqmladaptormodel_p.h b/src/qmlmodels/qqmladaptormodel_p.h index a4549127af..2c90ffc1d1 100644 --- a/src/qmlmodels/qqmladaptormodel_p.h +++ b/src/qmlmodels/qqmladaptormodel_p.h @@ -87,7 +87,7 @@ public: virtual QQmlDelegateModelItem *createItem( QQmlAdaptorModel &, - QQmlDelegateModelItemMetaType *, + const QQmlRefPointer<QQmlDelegateModelItemMetaType> &, int, int, int) const { return nullptr; } virtual bool notify( @@ -115,7 +115,7 @@ public: QPersistentModelIndex rootIndex; QQmlListAccessor list; - int modelItemRevision = 0; + QTypeRevision modelItemRevision = QTypeRevision::zero(); QQmlAdaptorModel(); ~QQmlAdaptorModel(); @@ -132,7 +132,7 @@ public: int columnAt(int index) const; int indexAt(int row, int column) const; - void useImportVersion(int minorVersion); + void useImportVersion(QTypeRevision revision); inline bool adaptsAim() const { return qobject_cast<QAbstractItemModel *>(object()); } inline QAbstractItemModel *aim() { return static_cast<QAbstractItemModel *>(object()); } @@ -140,10 +140,16 @@ public: inline QVariant value(int index, const QString &role) const { return accessors->value(*this, index, role); } - inline QQmlDelegateModelItem *createItem(QQmlDelegateModelItemMetaType *metaType, int index) { - return accessors->createItem(*this, metaType, index, rowAt(index), columnAt(index)); } + inline QQmlDelegateModelItem *createItem( + const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType, int index) + { + return accessors->createItem(*this, metaType, index, rowAt(index), columnAt(index)); + } inline bool hasProxyObject() const { - return list.type() == QQmlListAccessor::Instance || list.type() == QQmlListAccessor::ListProperty; } + return list.type() == QQmlListAccessor::Instance + || list.type() == QQmlListAccessor::ListProperty + || list.type() == QQmlListAccessor::ObjectList; + } inline bool notify( const QList<QQmlDelegateModelItem *> &items, diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp index 3a3903965c..3a05bf1689 100644 --- a/src/qmlmodels/qqmldelegatemodel.cpp +++ b/src/qmlmodels/qqmldelegatemodel.cpp @@ -731,7 +731,7 @@ QQmlListProperty<QQmlDelegateModelGroup> QQmlDelegateModel::groups() QQmlDelegateModelPrivate::group_append, QQmlDelegateModelPrivate::group_count, QQmlDelegateModelPrivate::group_at, - nullptr); + nullptr, nullptr, nullptr); } /*! @@ -1211,11 +1211,13 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, QQ } Compositor::iterator it = m_compositor.find(group, index); + const auto flags = it->flags; + const auto modelIndex = it.modelIndex(); QQmlDelegateModelItem *cacheItem = it->inCache() ? m_cache.at(it.cacheIndex) : 0; if (!cacheItem || !cacheItem->delegate) { - QQmlComponent *delegate = resolveDelegate(it.modelIndex()); + QQmlComponent *delegate = resolveDelegate(modelIndex); if (!delegate) return nullptr; @@ -1226,17 +1228,17 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, QQ // all related properties, and return the object (which // has already been incubated, otherwise it wouldn't be in the pool). addCacheItem(cacheItem, it); - reuseItem(cacheItem, index, it->flags); + reuseItem(cacheItem, index, flags); cacheItem->referenceObject(); return cacheItem->object; } // Since we could't find an available item in the pool, we create a new one - cacheItem = m_adaptorModel.createItem(m_cacheMetaType, it.modelIndex()); + cacheItem = m_adaptorModel.createItem(m_cacheMetaType, modelIndex); if (!cacheItem) return nullptr; - cacheItem->groups = it->flags; + cacheItem->groups = flags; addCacheItem(cacheItem, it); } @@ -2267,9 +2269,10 @@ void QV4::Heap::QQmlDelegateModelItemObject::destroy() } -QQmlDelegateModelItem::QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *metaType, - QQmlAdaptorModel::Accessors *accessor, - int modelIndex, int row, int column) +QQmlDelegateModelItem::QQmlDelegateModelItem( + const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType, + QQmlAdaptorModel::Accessors *accessor, + int modelIndex, int row, int column) : v4(metaType->v4Engine) , metaType(metaType) , contextData(nullptr) @@ -2285,8 +2288,6 @@ QQmlDelegateModelItem::QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *meta , row(row) , column(column) { - metaType->addref(); - if (accessor->propertyCache) { // The property cache in the accessor is common for all the model // items in the model it wraps. It describes available model roles, @@ -2315,9 +2316,6 @@ QQmlDelegateModelItem::~QQmlDelegateModelItem() else delete incubationTask; } - - metaType->release(); - } void QQmlDelegateModelItem::Dispose() diff --git a/src/qmlmodels/qqmldelegatemodel_p.h b/src/qmlmodels/qqmldelegatemodel_p.h index adb5f7008b..f4578e130e 100644 --- a/src/qmlmodels/qqmldelegatemodel_p.h +++ b/src/qmlmodels/qqmldelegatemodel_p.h @@ -86,7 +86,7 @@ class Q_QMLMODELS_PRIVATE_EXPORT QQmlDelegateModel : public QQmlInstanceModel, p Q_PROPERTY(QVariant rootIndex READ rootIndex WRITE setRootIndex NOTIFY rootIndexChanged) Q_CLASSINFO("DefaultProperty", "delegate") QML_NAMED_ELEMENT(DelegateModel) - QML_ADDED_IN_MINOR_VERSION(1) + QML_ADDED_IN_VERSION(2, 1) QML_ATTACHED(QQmlDelegateModelAttached) Q_INTERFACES(QQmlParserStatus) @@ -144,8 +144,6 @@ Q_SIGNALS: void defaultGroupsChanged(); void rootIndexChanged(); void delegateChanged(); - void itemPooled(int index, QObject *object); - void itemReused(int index, QObject *object); private Q_SLOTS: void _q_itemsChanged(int index, int count, const QVector<int> &roles); @@ -174,7 +172,7 @@ class Q_QMLMODELS_PRIVATE_EXPORT QQmlDelegateModelGroup : public QObject Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) Q_PROPERTY(bool includeByDefault READ defaultInclude WRITE setDefaultInclude NOTIFY defaultIncludeChanged) QML_NAMED_ELEMENT(DelegateModelGroup) - QML_ADDED_IN_MINOR_VERSION(1) + QML_ADDED_IN_VERSION(2, 1) public: QQmlDelegateModelGroup(QObject *parent = nullptr); QQmlDelegateModelGroup(const QString &name, QQmlDelegateModel *model, int compositorType, QObject *parent = nullptr); diff --git a/src/qmlmodels/qqmldelegatemodel_p_p.h b/src/qmlmodels/qqmldelegatemodel_p_p.h index a1c4555d01..8684439508 100644 --- a/src/qmlmodels/qqmldelegatemodel_p_p.h +++ b/src/qmlmodels/qqmldelegatemodel_p_p.h @@ -100,11 +100,11 @@ class QQmlDelegateModelItem : public QObject { Q_OBJECT Q_PROPERTY(int index READ modelIndex NOTIFY modelIndexChanged) - Q_PROPERTY(int row READ modelRow NOTIFY rowChanged REVISION 12) - Q_PROPERTY(int column READ modelColumn NOTIFY columnChanged REVISION 12) + Q_PROPERTY(int row READ modelRow NOTIFY rowChanged REVISION(2, 12)) + Q_PROPERTY(int column READ modelColumn NOTIFY columnChanged REVISION(2, 12)) Q_PROPERTY(QObject *model READ modelObject CONSTANT) public: - QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *metaType, + QQmlDelegateModelItem(const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType, QQmlAdaptorModel::Accessors *accessor, int modelIndex, int row, int column); ~QQmlDelegateModelItem(); @@ -148,7 +148,7 @@ public: static QV4::ReturnedValue get_index(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &arg); QV4::ExecutionEngine *v4; - QQmlDelegateModelItemMetaType * const metaType; + QQmlRefPointer<QQmlDelegateModelItemMetaType> const metaType; QQmlContextDataRef contextData; QPointer<QObject> object; QPointer<QQmlDelegateModelAttached> attached; @@ -162,8 +162,8 @@ public: Q_SIGNALS: void modelIndexChanged(); - Q_REVISION(12) void rowChanged(); - Q_REVISION(12) void columnChanged(); + Q_REVISION(2, 12) void rowChanged(); + Q_REVISION(2, 12) void columnChanged(); protected: void objectDestroyed(QObject *); diff --git a/src/qmlmodels/qqmlinstantiator_p.h b/src/qmlmodels/qqmlinstantiator_p.h index 9f6d816d18..fec5c3888a 100644 --- a/src/qmlmodels/qqmlinstantiator_p.h +++ b/src/qmlmodels/qqmlinstantiator_p.h @@ -73,7 +73,7 @@ class Q_QMLMODELS_PRIVATE_EXPORT QQmlInstantiator : public QObject, public QQmlP Q_PROPERTY(QObject *object READ object NOTIFY objectChanged) Q_CLASSINFO("DefaultProperty", "delegate") QML_NAMED_ELEMENT(Instantiator) - QML_ADDED_IN_MINOR_VERSION(1) + QML_ADDED_IN_VERSION(2, 1) public: QQmlInstantiator(QObject *parent = nullptr); diff --git a/src/qmlmodels/qqmllistaccessor.cpp b/src/qmlmodels/qqmllistaccessor.cpp index c450c616e7..69427df184 100644 --- a/src/qmlmodels/qqmllistaccessor.cpp +++ b/src/qmlmodels/qqmllistaccessor.cpp @@ -80,6 +80,8 @@ void QQmlListAccessor::setList(const QVariant &v, QQmlEngine *engine) m_type = StringList; } else if (d.userType() == QMetaType::QVariantList) { m_type = VariantList; + } else if (d.userType() == qMetaTypeId<QList<QObject *>>()) { + m_type = ObjectList; } else if (d.canConvert(QMetaType::Int)) { // Here we have to check for an upper limit, because down the line code might (well, will) // allocate memory depending on the number of elements. The upper limit cannot be INT_MAX: @@ -120,6 +122,8 @@ int QQmlListAccessor::count() const return qvariant_cast<QStringList>(d).count(); case VariantList: return qvariant_cast<QVariantList>(d).count(); + case ObjectList: + return qvariant_cast<QList<QObject *>>(d).count(); case ListProperty: return ((const QQmlListReference *)d.constData())->count(); case Instance: @@ -140,6 +144,8 @@ QVariant QQmlListAccessor::at(int idx) const return QVariant::fromValue(qvariant_cast<QStringList>(d).at(idx)); case VariantList: return qvariant_cast<QVariantList>(d).at(idx); + case ObjectList: + return QVariant::fromValue(qvariant_cast<QList<QObject *>>(d).at(idx)); case ListProperty: return QVariant::fromValue(((const QQmlListReference *)d.constData())->at(idx)); case Instance: diff --git a/src/qmlmodels/qqmllistaccessor_p.h b/src/qmlmodels/qqmllistaccessor_p.h index bcd079adef..a57e4173e3 100644 --- a/src/qmlmodels/qqmllistaccessor_p.h +++ b/src/qmlmodels/qqmllistaccessor_p.h @@ -70,7 +70,7 @@ public: int count() const; QVariant at(int) const; - enum Type { Invalid, StringList, VariantList, ListProperty, Instance, Integer }; + enum Type { Invalid, StringList, VariantList, ObjectList, ListProperty, Instance, Integer }; Type type() const { return m_type; } private: diff --git a/src/qmlmodels/qqmllistmodel.cpp b/src/qmlmodels/qqmllistmodel.cpp index 2c05b04429..e58fc19178 100644 --- a/src/qmlmodels/qqmllistmodel.cpp +++ b/src/qmlmodels/qqmllistmodel.cpp @@ -2786,10 +2786,12 @@ bool QQmlListModelParser::applyProperty( QV4::ScopedContext context(scope, QV4::QmlContext::create(v4->rootContext(), QQmlContextData::get(qmlContext(model->m_modelCache)), nullptr)); QV4::ScopedFunctionObject function(scope, QV4::FunctionObject::createScriptFunction(context, compilationUnit->runtimeFunctions[id])); - QV4::ReturnedValue result = function->call(v4->globalObject, nullptr, 0); - QJSValue v; - QJSValuePrivate::setValue(&v, v4, result); + QV4::ScopedValue result(scope, function->call(v4->globalObject, nullptr, 0)); + if (v4->hasException) + v4->catchException(); + else + QJSValuePrivate::setValue(&v, v4, result->asReturnedValue()); value.setValue<QJSValue>(v); } else { QByteArray script = scriptStr.toUtf8(); diff --git a/src/qmlmodels/qqmllistmodel_p.h b/src/qmlmodels/qqmllistmodel_p.h index dc5063eb97..bf4279cd05 100644 --- a/src/qmlmodels/qqmllistmodel_p.h +++ b/src/qmlmodels/qqmllistmodel_p.h @@ -82,8 +82,9 @@ class Q_QMLMODELS_PRIVATE_EXPORT QQmlListModel : public QAbstractListModel Q_OBJECT Q_PROPERTY(int count READ count NOTIFY countChanged) Q_PROPERTY(bool dynamicRoles READ dynamicRoles WRITE setDynamicRoles) - Q_PROPERTY(QObject *agent READ agent CONSTANT REVISION(14)) + Q_PROPERTY(QObject *agent READ agent CONSTANT REVISION(2, 14)) QML_NAMED_ELEMENT(ListModel) + QML_ADDED_IN_VERSION(2, 0) public: QQmlListModel(QObject *parent=nullptr); @@ -174,6 +175,7 @@ class QQmlListElement : public QObject { Q_OBJECT QML_NAMED_ELEMENT(ListElement) + QML_ADDED_IN_VERSION(2, 0) }; class QQmlListModelParser : public QQmlCustomParser diff --git a/src/qmlmodels/qqmllistmodelworkeragent_p.h b/src/qmlmodels/qqmllistmodelworkeragent_p.h index f65909dcec..1700ff755f 100644 --- a/src/qmlmodels/qqmllistmodelworkeragent_p.h +++ b/src/qmlmodels/qqmllistmodelworkeragent_p.h @@ -73,6 +73,7 @@ class QQmlListModelWorkerAgent : public QObject Q_PROPERTY(int count READ count) Q_PROPERTY(QV4::ExecutionEngine *engine READ engine WRITE setEngine NOTIFY engineChanged) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQmlListModelWorkerAgent(QQmlListModel *); diff --git a/src/qmlmodels/qqmlmodelsmodule_p.h b/src/qmlmodels/qqmlmodelsmodule_p.h index e3e43f3922..70268f53f2 100644 --- a/src/qmlmodels/qqmlmodelsmodule_p.h +++ b/src/qmlmodels/qqmlmodelsmodule_p.h @@ -67,7 +67,7 @@ struct QItemSelectionModelForeign Q_GADGET QML_FOREIGN(QItemSelectionModel) QML_NAMED_ELEMENT(ItemSelectionModel) - QML_ADDED_IN_MINOR_VERSION(2) + QML_ADDED_IN_VERSION(2, 2) }; #endif diff --git a/src/qmlmodels/qqmlobjectmodel.cpp b/src/qmlmodels/qqmlobjectmodel.cpp index 85e64cc2f9..dac868a0a2 100644 --- a/src/qmlmodels/qqmlobjectmodel.cpp +++ b/src/qmlmodels/qqmlobjectmodel.cpp @@ -91,6 +91,15 @@ public: static_cast<QQmlObjectModelPrivate *>(prop->data)->clear(); } + static void children_replace(QQmlListProperty<QObject> *prop, int index, QObject *item) { + static_cast<QQmlObjectModelPrivate *>(prop->data)->replace(index, item); + } + + static void children_removeLast(QQmlListProperty<QObject> *prop) { + auto data = static_cast<QQmlObjectModelPrivate *>(prop->data); + data->remove(data->children.count() - 1, 1); + } + void insert(int index, QObject *item) { Q_Q(QQmlObjectModel); children.insert(index, Item(item)); @@ -105,6 +114,18 @@ public: emit q->childrenChanged(); } + void replace(int index, QObject *item) { + Q_Q(QQmlObjectModel); + auto *attached = QQmlObjectModelAttached::properties(children.at(index).item); + attached->setIndex(-1); + children.replace(index, Item(item)); + QQmlObjectModelAttached::properties(children.at(index).item)->setIndex(index); + QQmlChangeSet changeSet; + changeSet.change(index, 1); + emit q->modelUpdated(changeSet, false); + emit q->childrenChanged(); + } + void move(int from, int to, int n) { Q_Q(QQmlObjectModel); if (from > to) { @@ -229,12 +250,13 @@ QQmlObjectModel::QQmlObjectModel(QObject *parent) QQmlListProperty<QObject> QQmlObjectModel::children() { Q_D(QQmlObjectModel); - return QQmlListProperty<QObject>(this, - d, - d->children_append, - d->children_count, - d->children_at, - d->children_clear); + return QQmlListProperty<QObject>(this, d, + QQmlObjectModelPrivate::children_append, + QQmlObjectModelPrivate::children_count, + QQmlObjectModelPrivate::children_at, + QQmlObjectModelPrivate::children_clear, + QQmlObjectModelPrivate::children_replace, + QQmlObjectModelPrivate::children_removeLast); } /*! diff --git a/src/qmlmodels/qqmlobjectmodel_p.h b/src/qmlmodels/qqmlobjectmodel_p.h index 6c68e55012..761e9c73ec 100644 --- a/src/qmlmodels/qqmlobjectmodel_p.h +++ b/src/qmlmodels/qqmlobjectmodel_p.h @@ -70,6 +70,7 @@ class Q_QMLMODELS_PRIVATE_EXPORT QQmlInstanceModel : public QObject Q_PROPERTY(int count READ count NOTIFY countChanged) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: enum ReusableFlag { @@ -104,6 +105,8 @@ Q_SIGNALS: void createdItem(int index, QObject *object); void initItem(int index, QObject *object); void destroyingItem(QObject *object); + Q_REVISION(2, 15) void itemPooled(int index, QObject *object); + Q_REVISION(2, 15) void itemReused(int index, QObject *object); protected: QQmlInstanceModel(QObjectPrivate &dd, QObject *parent = nullptr) @@ -123,7 +126,7 @@ class Q_QMLMODELS_PRIVATE_EXPORT QQmlObjectModel : public QQmlInstanceModel Q_PROPERTY(QQmlListProperty<QObject> children READ children NOTIFY childrenChanged DESIGNABLE false) Q_CLASSINFO("DefaultProperty", "children") QML_NAMED_ELEMENT(ObjectModel) - QML_ADDED_IN_MINOR_VERSION(1) + QML_ADDED_IN_VERSION(2, 1) QML_ATTACHED(QQmlObjectModelAttached) public: @@ -144,14 +147,14 @@ public: static QQmlObjectModelAttached *qmlAttachedProperties(QObject *obj); - Q_REVISION(3) Q_INVOKABLE QObject *get(int index) const; - Q_REVISION(3) Q_INVOKABLE void append(QObject *object); - Q_REVISION(3) Q_INVOKABLE void insert(int index, QObject *object); - Q_REVISION(3) Q_INVOKABLE void move(int from, int to, int n = 1); - Q_REVISION(3) Q_INVOKABLE void remove(int index, int n = 1); + Q_REVISION(2, 3) Q_INVOKABLE QObject *get(int index) const; + Q_REVISION(2, 3) Q_INVOKABLE void append(QObject *object); + Q_REVISION(2, 3) Q_INVOKABLE void insert(int index, QObject *object); + Q_REVISION(2, 3) Q_INVOKABLE void move(int from, int to, int n = 1); + Q_REVISION(2, 3) Q_INVOKABLE void remove(int index, int n = 1); public Q_SLOTS: - Q_REVISION(3) void clear(); + Q_REVISION(2, 3) void clear(); Q_SIGNALS: void childrenChanged(); diff --git a/src/qmlmodels/qqmltableinstancemodel.cpp b/src/qmlmodels/qqmltableinstancemodel.cpp index b4d1e61e31..8c034356f3 100644 --- a/src/qmlmodels/qqmltableinstancemodel.cpp +++ b/src/qmlmodels/qqmltableinstancemodel.cpp @@ -78,13 +78,14 @@ void QQmlTableInstanceModel::deleteModelItemLater(QQmlDelegateModelItem *modelIt QQmlTableInstanceModel::QQmlTableInstanceModel(QQmlContext *qmlContext, QObject *parent) : QQmlInstanceModel(*(new QObjectPrivate()), parent) , m_qmlContext(qmlContext) - , m_metaType(new QQmlDelegateModelItemMetaType(m_qmlContext->engine()->handle(), nullptr, QStringList())) + , m_metaType(new QQmlDelegateModelItemMetaType(m_qmlContext->engine()->handle(), nullptr, QStringList()), + QQmlRefPointer<QQmlDelegateModelItemMetaType>::Adopt) { } -void QQmlTableInstanceModel::useImportVersion(int minorVersion) +void QQmlTableInstanceModel::useImportVersion(QTypeRevision version) { - m_adaptorModel.useImportVersion(minorVersion); + m_adaptorModel.useImportVersion(version); } QQmlTableInstanceModel::~QQmlTableInstanceModel() @@ -149,7 +150,7 @@ QQmlDelegateModelItem *QQmlTableInstanceModel::resolveModelItem(int index) } // Create a new item from scratch - modelItem = m_adaptorModel.createItem(m_metaType, index); + modelItem = m_adaptorModel.createItem(m_metaType.data(), index); if (modelItem) { modelItem->delegate = delegate; m_modelItems.insert(index, modelItem); @@ -242,6 +243,25 @@ void QQmlTableInstanceModel::destroyModelItem(QQmlDelegateModelItem *modelItem) delete modelItem; } +void QQmlTableInstanceModel::dispose(QObject *object) +{ + Q_ASSERT(object); + auto modelItem = qvariant_cast<QQmlDelegateModelItem *>(object->property(kModelItemTag)); + Q_ASSERT(modelItem); + + modelItem->releaseObject(); + + // The item is not referenced by anyone + Q_ASSERT(!modelItem->isObjectReferenced()); + Q_ASSERT(!modelItem->isReferenced()); + + m_modelItems.remove(modelItem->index); + + emit destroyingItem(object); + delete object; + delete modelItem; +} + void QQmlTableInstanceModel::cancel(int index) { auto modelItem = m_modelItems.value(index); diff --git a/src/qmlmodels/qqmltableinstancemodel_p.h b/src/qmlmodels/qqmltableinstancemodel_p.h index d924455918..57b9b26e43 100644 --- a/src/qmlmodels/qqmltableinstancemodel_p.h +++ b/src/qmlmodels/qqmltableinstancemodel_p.h @@ -89,7 +89,7 @@ public: QQmlTableInstanceModel(QQmlContext *qmlContext, QObject *parent = nullptr); ~QQmlTableInstanceModel() override; - void useImportVersion(int minorVersion); + void useImportVersion(QTypeRevision version); int count() const override { return m_adaptorModel.count(); } int rows() const { return m_adaptorModel.rowCount(); } @@ -110,6 +110,7 @@ public: QObject *object(int index, QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested) override; ReleaseFlags release(QObject *object, ReusableFlag reusable = NotReusable) override; + void dispose(QObject *object); void cancel(int) override; void drainReusableItemsPool(int maxPoolTime) override; @@ -122,10 +123,6 @@ public: void setWatchedRoles(const QList<QByteArray> &) override { Q_UNREACHABLE(); } int indexOf(QObject *, QObject *) const override { Q_UNREACHABLE(); return 0; } -Q_SIGNALS: - void itemPooled(int index, QObject *object); - void itemReused(int index, QObject *object); - private: QQmlComponent *resolveDelegate(int index); @@ -133,7 +130,7 @@ private: QQmlAbstractDelegateComponent *m_delegateChooser = nullptr; QQmlComponent *m_delegate = nullptr; QPointer<QQmlContext> m_qmlContext; - QQmlDelegateModelItemMetaType *m_metaType; + QQmlRefPointer<QQmlDelegateModelItemMetaType> m_metaType; QHash<int, QQmlDelegateModelItem *> m_modelItems; QQmlReusableDelegateModelItemsPool m_reusableItemsPool; diff --git a/src/qmlmodels/qquickpackage.cpp b/src/qmlmodels/qquickpackage.cpp index 567381e5ab..42e7d0e09f 100644 --- a/src/qmlmodels/qquickpackage.cpp +++ b/src/qmlmodels/qquickpackage.cpp @@ -115,6 +115,14 @@ public: QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data); return list->count(); } + static void data_replace(QQmlListProperty<QObject> *prop, int index, QObject *o) { + QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data); + list->replace(index, DataGuard(o, list)); + } + static void data_removeLast(QQmlListProperty<QObject> *prop) { + QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data); + list->removeLast(); + } }; QHash<QObject *, QQuickPackageAttached *> QQuickPackageAttached::attached; @@ -152,10 +160,13 @@ QQuickPackage::~QQuickPackage() QQmlListProperty<QObject> QQuickPackage::data() { Q_D(QQuickPackage); - return QQmlListProperty<QObject>(this, &d->dataList, QQuickPackagePrivate::data_append, - QQuickPackagePrivate::data_count, - QQuickPackagePrivate::data_at, - QQuickPackagePrivate::data_clear); + return QQmlListProperty<QObject>(this, &d->dataList, + QQuickPackagePrivate::data_append, + QQuickPackagePrivate::data_count, + QQuickPackagePrivate::data_at, + QQuickPackagePrivate::data_clear, + QQuickPackagePrivate::data_replace, + QQuickPackagePrivate::data_removeLast); } bool QQuickPackage::hasPart(const QString &name) diff --git a/src/qmlmodels/qquickpackage_p.h b/src/qmlmodels/qquickpackage_p.h index 801b8d8409..f40ffe552a 100644 --- a/src/qmlmodels/qquickpackage_p.h +++ b/src/qmlmodels/qquickpackage_p.h @@ -67,6 +67,7 @@ class Q_AUTOTEST_EXPORT QQuickPackage : public QObject Q_CLASSINFO("DefaultProperty", "data") QML_NAMED_ELEMENT(Package) + QML_ADDED_IN_VERSION(2, 0) QML_ATTACHED(QQuickPackageAttached) Q_PROPERTY(QQmlListProperty<QObject> data READ data) diff --git a/src/qmlmodels/qtqmlmodelsglobal_p.h b/src/qmlmodels/qtqmlmodelsglobal_p.h index 145112c9c1..1a1157138d 100644 --- a/src/qmlmodels/qtqmlmodelsglobal_p.h +++ b/src/qmlmodels/qtqmlmodelsglobal_p.h @@ -58,4 +58,6 @@ #define Q_QMLMODELS_PRIVATE_EXPORT Q_QMLMODELS_EXPORT #define Q_QMLMODELS_AUTOTEST_EXPORT Q_AUTOTEST_EXPORT +void Q_QMLMODELS_PRIVATE_EXPORT qml_register_types_QtQml_Models(); + #endif // QTQMLMODELSGLOBAL_P_H diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp index 470b3c0f7a..96a5c20f22 100644 --- a/src/qmltest/quicktest.cpp +++ b/src/qmltest/quicktest.cpp @@ -52,7 +52,7 @@ #include <QtQml/qqmlpropertymap.h> #include <QtQuick/private/qquickitem_p.h> #include <QtQuick/qquickitem.h> -#include <QtGui/qopengl.h> +#include <qopengl.h> #include <QtCore/qurl.h> #include <QtCore/qfileinfo.h> #include <QtCore/qdir.h> diff --git a/src/qmltest/quicktestresult_p.h b/src/qmltest/quicktestresult_p.h index 81b9d78830..7ebfb21186 100644 --- a/src/qmltest/quicktestresult_p.h +++ b/src/qmltest/quicktestresult_p.h @@ -158,10 +158,10 @@ public Q_SLOTS: QObject *grabImage(QQuickItem *item); - Q_REVISION(1) QObject *findChild(QObject *parent, const QString &objectName); + Q_REVISION(1, 1) QObject *findChild(QObject *parent, const QString &objectName); - Q_REVISION(13) bool isPolishScheduled(QQuickItem *item) const; - Q_REVISION(13) bool waitForItemPolished(QQuickItem *item, int timeout); + Q_REVISION(1, 13) bool isPolishScheduled(QQuickItem *item) const; + Q_REVISION(1, 13) bool waitForItemPolished(QQuickItem *item, int timeout); public: // Helper functions for the C++ main() shell. diff --git a/src/qmltyperegistrar/qmltyperegistrar.cpp b/src/qmltyperegistrar/qmltyperegistrar.cpp index 4738e28314..33f1ebbbd5 100644 --- a/src/qmltyperegistrar/qmltyperegistrar.cpp +++ b/src/qmltyperegistrar/qmltyperegistrar.cpp @@ -47,14 +47,32 @@ struct ScopedPointerFileCloser static inline void cleanup(FILE *handle) { if (handle) fclose(handle); } }; -static bool acceptClassForQmlTypeRegistration(const QJsonObject &classDef) +enum RegistrationMode { + NoRegistration, + ObjectRegistration, + GadgetRegistration, + NamespaceRegistration +}; + +static RegistrationMode qmlTypeRegistrationMode(const QJsonObject &classDef) { const QJsonArray classInfos = classDef[QLatin1String("classInfos")].toArray(); for (const QJsonValue &info: classInfos) { - if (info[QLatin1String("name")].toString() == QLatin1String("QML.Element")) - return true; + const QString name = info[QLatin1String("name")].toString(); + if (name == QLatin1String("QML.Element")) { + if (classDef[QLatin1String("object")].toBool()) + return ObjectRegistration; + if (classDef[QLatin1String("gadget")].toBool()) + return GadgetRegistration; + if (classDef[QLatin1String("namespace")].toBool()) + return NamespaceRegistration; + qWarning() << "Not registering classInfo which is neither an object, " + "nor a gadget, nor a namespace:" + << name; + break; + } } - return false; + return NoRegistration; } static bool argumentsFromCommandLineAndFile(QStringList &allArguments, const QStringList &arguments) @@ -317,7 +335,10 @@ int main(int argc, char **argv) const QJsonArray classes = metaObject[QLatin1String("classes")].toArray(); for (const auto &cls : classes) { QJsonObject classDef = cls.toObject(); - if (acceptClassForQmlTypeRegistration(classDef)) { + switch (qmlTypeRegistrationMode(classDef)) { + case NamespaceRegistration: + case GadgetRegistration: + case ObjectRegistration: { const QString include = metaObject[QLatin1String("inputFile")].toString(); const bool declaredInHeader = include.endsWith(QLatin1String(".h")); if (declaredInHeader) { @@ -329,9 +350,13 @@ int main(int argc, char **argv) qPrintable(classDef.value(QLatin1String("qualifiedClassName")) .toString())); } + types.append(classDef); - } else { + break; + } + case NoRegistration: foreignTypes.append(classDef); + break; } } }; @@ -393,16 +418,22 @@ int main(int argc, char **argv) continue; const QString className = classDef[QLatin1String("qualifiedClassName")].toString(); - fprintf(output, "\n qmlRegisterTypesAndRevisions<%s>(\"%s\", %s);", qPrintable(className), - qPrintable(module), qPrintable(majorVersion)); + + if (classDef.value(QLatin1String("namespace")).toBool()) { + fprintf(output, "\n qmlRegisterNamespaceAndRevisions(&%s::staticMetaObject, \"%s\", %s);", + qPrintable(className), qPrintable(module), qPrintable(majorVersion)); + } else { + fprintf(output, "\n qmlRegisterTypesAndRevisions<%s>(\"%s\", %s);", + qPrintable(className), qPrintable(module), qPrintable(majorVersion)); + } } fprintf(output, "\n qmlRegisterModule(\"%s\", %s, %s);", qPrintable(module), qPrintable(majorVersion), qPrintable(parser.value(minorVersionOption))); fprintf(output, "\n}\n"); - fprintf(output, "\nstatic const QQmlModuleRegistration registration(\"%s\", %s, %s);\n", - qPrintable(module), qPrintable(majorVersion), qPrintable(functionName)); + fprintf(output, "\nstatic const QQmlModuleRegistration registration(\"%s\", %s);\n", + qPrintable(module), qPrintable(functionName)); if (!parser.isSet(pluginTypesOption)) return EXIT_SUCCESS; @@ -447,7 +478,7 @@ int main(int argc, char **argv) creator.setOwnTypes(std::move(types)); creator.setForeignTypes(std::move(foreignTypes)); creator.setModule(module); - creator.setMajorVersion(parser.value(majorVersionOption).toInt()); + creator.setVersion(QTypeRevision::fromVersion(parser.value(majorVersionOption).toInt(), 0)); creator.generate(parser.value(pluginTypesOption), parser.value(dependenciesOption)); return EXIT_SUCCESS; diff --git a/src/qmltyperegistrar/qmltypesclassdescription.cpp b/src/qmltyperegistrar/qmltypesclassdescription.cpp index 15a8113ac8..e21abd97bc 100644 --- a/src/qmltyperegistrar/qmltypesclassdescription.cpp +++ b/src/qmltyperegistrar/qmltypesclassdescription.cpp @@ -27,18 +27,19 @@ ****************************************************************************/ #include "qmltypesclassdescription.h" +#include "qmltypescreator.h" #include <QtCore/qjsonarray.h> static void collectExtraVersions(const QJsonObject *component, const QString &key, - QList<int> &extraVersions) + QList<QTypeRevision> &extraVersions) { const QJsonArray &items = component->value(key).toArray(); for (const QJsonValue &item : items) { const QJsonObject obj = item.toObject(); const auto revision = obj.find(QLatin1String("revision")); if (revision != obj.end()) { - const int extraVersion = revision.value().toInt(); + const auto extraVersion = QTypeRevision::fromEncodedVersion(revision.value().toInt()); if (!extraVersions.contains(extraVersion)) extraVersions.append(extraVersion); } @@ -60,7 +61,7 @@ const QJsonObject *QmlTypesClassDescription::findType(const QVector<QJsonObject> void QmlTypesClassDescription::collect(const QJsonObject *classDef, const QVector<QJsonObject> &types, const QVector<QJsonObject> &foreign, - bool topLevel) + CollectMode mode, QTypeRevision defaultRevision) { const auto classInfos = classDef->value(QLatin1String("classInfos")).toArray(); for (const QJsonValue &classInfo : classInfos) { @@ -69,18 +70,19 @@ void QmlTypesClassDescription::collect(const QJsonObject *classDef, const QString value = obj[QLatin1String("value")].toString(); if (name == QLatin1String("DefaultProperty")) { - if (defaultProp.isEmpty()) + if (mode != AttachedType && defaultProp.isEmpty()) defaultProp = value; - } else if (name == QLatin1String("QML.AddedInMinorVersion")) { - if (topLevel) { - addedInRevision = value.toInt(); - revisions.append(value.toInt()); + } else if (name == QLatin1String("QML.AddedInVersion")) { + const QTypeRevision revision = QTypeRevision::fromEncodedVersion(value.toInt()); + if (mode == TopLevel) { + addedInRevision = revision; + revisions.append(revision); } else if (!elementName.isEmpty()) { - revisions.append(value.toInt()); + revisions.append(revision); } } - if (!topLevel) + if (mode != TopLevel) continue; // These only apply to the original class @@ -89,32 +91,28 @@ void QmlTypesClassDescription::collect(const QJsonObject *classDef, elementName = classDef->value(QLatin1String("className")).toString(); else if (value != QLatin1String("anonymous")) elementName = value; - } else if (name == QLatin1String("QML.RemovedInMinorVersion")) { - removedInRevision = value.toInt(); + } else if (name == QLatin1String("QML.RemovedInVersion")) { + removedInRevision = QTypeRevision::fromEncodedVersion(value.toInt()); } else if (name == QLatin1String("QML.Creatable")) { isCreatable = (value != QLatin1String("false")); } else if (name == QLatin1String("QML.Attached")) { - attachedType = value; - if (const QJsonObject *other = findType(types, attachedType)) - collect(other, types, foreign, false); - else if (const QJsonObject *other = findType(foreign, attachedType)) - collect(other, types, foreign, false); + collectAttached(value, types, foreign, defaultRevision); } else if (name == QLatin1String("QML.Singleton")) { if (value == QLatin1String("true")) isSingleton = true; } else if (name == QLatin1String("QML.Foreign")) { if (const QJsonObject *other = findType(foreign, value)) { classDef = other; - if (defaultProp.isEmpty()) { - // Foreign type can have a default property - const auto classInfos = classDef->value(QLatin1String("classInfos")).toArray(); - for (const QJsonValue &classInfo : classInfos) { - QJsonObject obj = classInfo.toObject(); - if (obj[QLatin1String("name")].toString() == QLatin1String("DefaultProperty")) { - defaultProp = obj[QLatin1String("value")].toString(); - break; - } - } + // Foreign type can have a default property or an attached types + const auto classInfos = classDef->value(QLatin1String("classInfos")).toArray(); + for (const QJsonValue &classInfo : classInfos) { + const QJsonObject obj = classInfo.toObject(); + const QString foreignName = obj[QLatin1String("name")].toString(); + const QString foreignValue = obj[QLatin1String("value")].toString(); + if (defaultProp.isEmpty() && foreignName == QLatin1String("DefaultProperty")) + defaultProp = foreignValue; + else if (foreignName == QLatin1String("QML.Attached")) + collectAttached(foreignValue, types, foreign, defaultRevision); } } } else if (name == QLatin1String("QML.Root")) { @@ -125,7 +123,7 @@ void QmlTypesClassDescription::collect(const QJsonObject *classDef, } } - if (!elementName.isEmpty()) { + if (mode == AttachedType || !elementName.isEmpty()) { collectExtraVersions(classDef, QString::fromLatin1("properties"), revisions); collectExtraVersions(classDef, QString::fromLatin1("slots"), revisions); collectExtraVersions(classDef, QString::fromLatin1("methods"), revisions); @@ -137,19 +135,22 @@ void QmlTypesClassDescription::collect(const QJsonObject *classDef, const QJsonObject superObject = supers.first().toObject(); if (superObject[QLatin1String("access")].toString() == QLatin1String("public")) { const QString superName = superObject[QLatin1String("name")].toString(); - if (topLevel && superClass.isEmpty()) + if (mode == TopLevel && superClass.isEmpty()) superClass = superName; + const CollectMode superMode = (mode == TopLevel) ? SuperClass : AttachedType; if (const QJsonObject *other = findType(types, superName)) - collect(other, types, foreign, false); + collect(other, types, foreign, superMode, defaultRevision); else if (const QJsonObject *other = findType(foreign, superName)) - collect(other, types, foreign, false); + collect(other, types, foreign, superMode, defaultRevision); } } - if (addedInRevision == -1) { - revisions.append(0); - addedInRevision = 0; + if (!addedInRevision.isValid()) { + revisions.append(defaultRevision); + addedInRevision = defaultRevision; + } else if (addedInRevision < defaultRevision) { + revisions.append(defaultRevision); } std::sort(revisions.begin(), revisions.end()); @@ -157,4 +158,19 @@ void QmlTypesClassDescription::collect(const QJsonObject *classDef, revisions.erase(end, revisions.end()); resolvedClass = classDef; + + // If it's not a QObject, it's not creatable + isCreatable = isCreatable && classDef->value(QLatin1String("object")).toBool(); +} + +void QmlTypesClassDescription::collectAttached(const QString &attached, + const QVector<QJsonObject> &types, + const QVector<QJsonObject> &foreign, + QTypeRevision defaultRevision) +{ + attachedType = attached; + if (const QJsonObject *other = findType(types, attachedType)) + collect(other, types, foreign, AttachedType, defaultRevision); + else if (const QJsonObject *other = findType(foreign, attachedType)) + collect(other, types, foreign, AttachedType, defaultRevision); } diff --git a/src/qmltyperegistrar/qmltypesclassdescription.h b/src/qmltyperegistrar/qmltypesclassdescription.h index 8f3a6ea124..e4ae37a84e 100644 --- a/src/qmltyperegistrar/qmltypesclassdescription.h +++ b/src/qmltyperegistrar/qmltypesclassdescription.h @@ -33,6 +33,7 @@ #include <QtCore/qjsonobject.h> #include <QtCore/qvector.h> #include <QtCore/qset.h> +#include <QtCore/qversionnumber.h> struct QmlTypesClassDescription { @@ -41,16 +42,25 @@ struct QmlTypesClassDescription QString defaultProp; QString superClass; QString attachedType; - QList<int> revisions; - int addedInRevision = -1; - int removedInRevision = -1; + QList<QTypeRevision> revisions; + QTypeRevision addedInRevision; + QTypeRevision removedInRevision; bool isCreatable = true; bool isSingleton = false; bool isRootClass = false; bool isBuiltin = false; + enum CollectMode { + TopLevel, + SuperClass, + AttachedType + }; + void collect(const QJsonObject *classDef, const QVector<QJsonObject> &types, - const QVector<QJsonObject> &foreign, bool topLevel); + const QVector<QJsonObject> &foreign, CollectMode mode, + QTypeRevision defaultRevision); + void collectAttached(const QString &attached, const QVector<QJsonObject> &types, + const QVector<QJsonObject> &foreign, QTypeRevision defaultRevision); static const QJsonObject *findType(const QVector<QJsonObject> &types, const QString &name); }; diff --git a/src/qmltyperegistrar/qmltypescreator.cpp b/src/qmltyperegistrar/qmltypescreator.cpp index 911120027e..3569bbe253 100644 --- a/src/qmltyperegistrar/qmltypescreator.cpp +++ b/src/qmltyperegistrar/qmltypescreator.cpp @@ -35,6 +35,7 @@ #include <QtCore/qsavefile.h> #include <QtCore/qfile.h> #include <QtCore/qjsondocument.h> +#include <QtCore/qversionnumber.h> static QString enquote(const QString &string) { @@ -62,24 +63,24 @@ void QmlTypesCreator::writeClassProperties(const QmlTypesClassDescription &colle QStringList exports; QStringList metaObjects; + if (collector.isBuiltin) { + exports.append(enquote(QString::fromLatin1("QML/%1 1.0").arg(collector.elementName))); + metaObjects.append(QString::number(QTypeRevision::fromVersion(1, 0).toEncodedVersion<quint16>())); + } + for (auto it = collector.revisions.begin(), end = collector.revisions.end(); it != end; ++it) { - const int revision = *it; + const QTypeRevision revision = *it; if (revision < collector.addedInRevision) continue; - if (collector.removedInRevision > collector.addedInRevision - && revision >= collector.removedInRevision) { + if (collector.removedInRevision.isValid() && !(revision < collector.removedInRevision)) break; - } - - if (collector.isBuiltin) { - exports.append(enquote(QString::fromLatin1("QML/%1 1.0").arg(collector.elementName))); - metaObjects.append(QLatin1String("0")); - } exports.append(enquote(QString::fromLatin1("%1/%2 %3.%4") - .arg(m_module).arg(collector.elementName) - .arg(m_majorVersion).arg(revision))); - metaObjects.append(QString::number(revision)); + .arg(m_module).arg(collector.elementName) + .arg(revision.hasMajorVersion() ? revision.majorVersion() + : m_version.majorVersion()) + .arg(revision.minorVersion()))); + metaObjects.append(QString::number(revision.toEncodedVersion<quint16>())); } m_qml.writeArrayBinding(QLatin1String("exports"), exports); @@ -245,7 +246,8 @@ void QmlTypesCreator::writeComponents() m_qml.writeStartObject(componentElement); QmlTypesClassDescription collector; - collector.collect(&component, m_ownTypes, m_foreignTypes, true); + collector.collect(&component, m_ownTypes, m_foreignTypes, + QmlTypesClassDescription::TopLevel, m_version); writeClassProperties(collector); diff --git a/src/qmltyperegistrar/qmltypescreator.h b/src/qmltyperegistrar/qmltypescreator.h index 9207a64b7e..808c189323 100644 --- a/src/qmltyperegistrar/qmltypescreator.h +++ b/src/qmltyperegistrar/qmltypescreator.h @@ -45,7 +45,7 @@ public: void setOwnTypes(QVector<QJsonObject> ownTypes) { m_ownTypes = std::move(ownTypes); } void setForeignTypes(QVector<QJsonObject> foreignTypes) { m_foreignTypes = std::move(foreignTypes); } void setModule(QString module) { m_module = std::move(module); } - void setMajorVersion(int majorVersion) { m_majorVersion = majorVersion; } + void setVersion(QTypeRevision version) { m_version = version; } private: void writeClassProperties(const QmlTypesClassDescription &collector); @@ -62,7 +62,7 @@ private: QVector<QJsonObject> m_ownTypes; QVector<QJsonObject> m_foreignTypes; QString m_module; - int m_majorVersion = 0; + QTypeRevision m_version = QTypeRevision::zero(); }; #endif // QMLTYPESCREATOR_H diff --git a/src/imports/workerscript/dependencies.json b/src/qmlworkerscript/dependencies.json index 0d4f101c7a..0d4f101c7a 100644 --- a/src/imports/workerscript/dependencies.json +++ b/src/qmlworkerscript/dependencies.json diff --git a/src/qmlworkerscript/qmlworkerscript.pro b/src/qmlworkerscript/qmlworkerscript.pro index a8ec68d423..82b61ab12e 100644 --- a/src/qmlworkerscript/qmlworkerscript.pro +++ b/src/qmlworkerscript/qmlworkerscript.pro @@ -20,7 +20,7 @@ include(../3rdparty/masm/masm-defs.pri) QMLTYPES_FILENAME = plugins.qmltypes QMLTYPES_INSTALL_DIR = $$[QT_INSTALL_QML]/QtQml/WorkerScript QML_IMPORT_NAME = QtQml.WorkerScript -IMPORT_VERSION = 2.15 +QML_IMPORT_VERSION = $$QT_VERSION CONFIG += qmltypes install_qmltypes install_metatypes load(qt_module) diff --git a/src/qmlworkerscript/qquickworkerscript.cpp b/src/qmlworkerscript/qquickworkerscript.cpp index 4a79027234..0bdbbabadc 100644 --- a/src/qmlworkerscript/qquickworkerscript.cpp +++ b/src/qmlworkerscript/qquickworkerscript.cpp @@ -130,7 +130,9 @@ struct WorkerScript : public QV4::ExecutionEngine { QQuickWorkerScriptEnginePrivate *p = nullptr; QUrl source; QQuickWorkerScript *owner = nullptr; +#if QT_CONFIG(qml_network) QScopedPointer<QNetworkAccessManager> scriptLocalNAM; +#endif int id = -1; }; @@ -390,6 +392,7 @@ WorkerScript::WorkerScript(int id, QQuickWorkerScriptEnginePrivate *parent) QV4::ScopedValue sendMessage(scope, QV4::FunctionObject::createBuiltinFunction(this, name, QQuickWorkerScriptEnginePrivate::method_sendMessage, 1)); api->put(QV4::ScopedString(scope, scope.engine->newString(QStringLiteral("sendMessage"))), sendMessage); globalObject->put(QV4::ScopedString(scope, scope.engine->newString(QStringLiteral("WorkerScript"))), api); +#if QT_CONFIG(qml_network) networkAccessManager = [](QV4::ExecutionEngine *engine){ auto *workerScript = static_cast<WorkerScript *>(engine); if (workerScript->scriptLocalNAM) @@ -400,6 +403,7 @@ WorkerScript::WorkerScript(int id, QQuickWorkerScriptEnginePrivate *parent) workerScript->scriptLocalNAM.reset(new QNetworkAccessManager(workerScript->p)); return workerScript->scriptLocalNAM.get(); }; +#endif // qml_network } int QQuickWorkerScriptEngine::registerWorkerScript(QQuickWorkerScript *owner) diff --git a/src/qmlworkerscript/qquickworkerscript_p.h b/src/qmlworkerscript/qquickworkerscript_p.h index 03581089e0..d1ea34422a 100644 --- a/src/qmlworkerscript/qquickworkerscript_p.h +++ b/src/qmlworkerscript/qquickworkerscript_p.h @@ -84,13 +84,14 @@ private: }; class QQmlV4Function; -class Q_QMLWORKERSCRIPT_PRIVATE_EXPORT QQuickWorkerScript : public QObject, public QQmlParserStatus +class Q_AUTOTEST_EXPORT QQuickWorkerScript : public QObject, public QQmlParserStatus { Q_OBJECT Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) - Q_PROPERTY(bool ready READ ready NOTIFY readyChanged) + Q_PROPERTY(bool ready READ ready NOTIFY readyChanged REVISION(2, 15)) QML_NAMED_ELEMENT(WorkerScript); + QML_ADDED_IN_VERSION(2, 0) Q_INTERFACES(QQmlParserStatus) public: @@ -107,7 +108,7 @@ public Q_SLOTS: Q_SIGNALS: void sourceChanged(); - void readyChanged(); + Q_REVISION(2, 15) void readyChanged(); void message(const QJSValue &messageObject); protected: diff --git a/src/qmlworkerscript/qtqmlworkerscriptglobal_p.h b/src/qmlworkerscript/qtqmlworkerscriptglobal_p.h index 34236cd79e..c75d5f3129 100644 --- a/src/qmlworkerscript/qtqmlworkerscriptglobal_p.h +++ b/src/qmlworkerscript/qtqmlworkerscriptglobal_p.h @@ -57,4 +57,6 @@ #define Q_QMLWORKERSCRIPT_PRIVATE_EXPORT Q_QMLWORKERSCRIPT_EXPORT #define Q_QMLWORKERSCRIPT_AUTOTEST_EXPORT Q_AUTOTEST_EXPORT +void Q_QMLWORKERSCRIPT_PRIVATE_EXPORT qml_register_types_QtQml_WorkerScript(); + #endif // QTQMLWORKERSCRIPTGLOBAL_P_H diff --git a/src/quick/accessible/qaccessiblequickview.cpp b/src/quick/accessible/qaccessiblequickview.cpp index 41a02fc09c..b23b0316f5 100644 --- a/src/quick/accessible/qaccessiblequickview.cpp +++ b/src/quick/accessible/qaccessiblequickview.cpp @@ -84,8 +84,12 @@ QAccessibleInterface *QAccessibleQuickWindow::child(int index) const QAccessibleInterface *QAccessibleQuickWindow::focusChild() const { QObject *focusObject = window()->focusObject(); - if (focusObject) - return QAccessible::queryAccessibleInterface(focusObject); + if (focusObject) { + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(focusObject); + if (!iface || iface == this || !iface->focusChild()) + return iface; + return iface->focusChild(); + } return nullptr; } diff --git a/src/quick/designer/qquickdesignersupportitems.cpp b/src/quick/designer/qquickdesignersupportitems.cpp index ed5fdf3a4a..4fd9158f4a 100644 --- a/src/quick/designer/qquickdesignersupportitems.cpp +++ b/src/quick/designer/qquickdesignersupportitems.cpp @@ -210,14 +210,14 @@ static bool isCrashingType(const QQmlType &type) return false; } -QObject *QQuickDesignerSupportItems::createPrimitive(const QString &typeName, int majorNumber, int minorNumber, QQmlContext *context) +QObject *QQuickDesignerSupportItems::createPrimitive(const QString &typeName, QTypeRevision version, QQmlContext *context) { ComponentCompleteDisabler disableComponentComplete; Q_UNUSED(disableComponentComplete) QObject *object = nullptr; - QQmlType type = QQmlMetaType::qmlType(typeName, majorNumber, minorNumber); + QQmlType type = QQmlMetaType::qmlType(typeName, version); if (isCrashingType(type)) { object = new QObject; @@ -242,7 +242,8 @@ QObject *QQuickDesignerSupportItems::createPrimitive(const QString &typeName, in if (!object) { qWarning() << "QuickDesigner: Cannot create an object of type" - << QString::fromLatin1("%1 %2,%3").arg(typeName).arg(majorNumber).arg(minorNumber) + << QString::fromLatin1("%1 %2,%3").arg(typeName) + .arg(version.majorVersion()).arg(version.minorVersion()) << "- type isn't known to declarative meta type system"; } diff --git a/src/quick/designer/qquickdesignersupportitems_p.h b/src/quick/designer/qquickdesignersupportitems_p.h index 8c5a44d9fe..93b4c529fa 100644 --- a/src/quick/designer/qquickdesignersupportitems_p.h +++ b/src/quick/designer/qquickdesignersupportitems_p.h @@ -58,6 +58,7 @@ #include <QVariant> #include <QList> #include <QByteArray> +#include <QTypeRevision> #include <QQmlContext> #include <QQmlListReference> @@ -66,7 +67,7 @@ QT_BEGIN_NAMESPACE class Q_QUICK_EXPORT QQuickDesignerSupportItems { public: - static QObject *createPrimitive(const QString &typeName, int majorNumber, int minorNumber, QQmlContext *context); + static QObject *createPrimitive(const QString &typeName, QTypeRevision version, QQmlContext *context); static QObject *createComponent(const QUrl &componentUrl, QQmlContext *context); static void tweakObjects(QObject *object); static bool objectWasDeleted(QObject *object); diff --git a/src/quick/designer/qquickdesignersupportproperties.cpp b/src/quick/designer/qquickdesignersupportproperties.cpp index c746f55daa..335795acf1 100644 --- a/src/quick/designer/qquickdesignersupportproperties.cpp +++ b/src/quick/designer/qquickdesignersupportproperties.cpp @@ -155,8 +155,8 @@ QQuickDesignerSupport::PropertyNameList QQuickDesignerSupportProperties::propert baseName + QQuickDesignerSupport::PropertyName(metaProperty.name()) + '.', inspectedObjects)); } - } else if (QQmlValueTypeFactory::valueType(metaProperty.userType())) { - QQmlValueType *valueType = QQmlValueTypeFactory::valueType(metaProperty.userType()); + } else if (QQmlGadgetPtrWrapper *valueType + = QQmlGadgetPtrWrapper::instance(qmlEngine(object), metaProperty.userType())) { valueType->setValue(metaProperty.read(object)); propertyNameList.append(propertyNameListForWritableProperties(valueType, baseName + QQuickDesignerSupport::PropertyName(metaProperty.name()) @@ -223,8 +223,8 @@ QQuickDesignerSupport::PropertyNameList QQuickDesignerSupportProperties::allProp + QQuickDesignerSupport::PropertyName(metaProperty.name()) + '.', inspectedObjects)); } - } else if (QQmlValueTypeFactory::valueType(metaProperty.userType())) { - QQmlValueType *valueType = QQmlValueTypeFactory::valueType(metaProperty.userType()); + } else if (QQmlGadgetPtrWrapper *valueType + = QQmlGadgetPtrWrapper::instance(qmlEngine(object), metaProperty.userType())) { valueType->setValue(metaProperty.read(object)); propertyNameList.append(baseName + QQuickDesignerSupport::PropertyName(metaProperty.name())); propertyNameList.append(allPropertyNames(valueType, diff --git a/src/quick/doc/snippets/qml/qml-data-models/listmodel-listview-required.qml b/src/quick/doc/snippets/qml/qml-data-models/listmodel-listview-required.qml new file mode 100644 index 0000000000..e9a668ed8f --- /dev/null +++ b/src/quick/doc/snippets/qml/qml-data-models/listmodel-listview-required.qml @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [document] +import QtQuick 2.0 + +Item { + width: 200 + height: 250 + + ListModel { + id: myModel + ListElement { type: "Dog"; age: 8; noise: "meow" } + ListElement { type: "Cat"; age: 5; noise: "woof" } + } + + component MyDelegate : Text { + required property string type + required property int age + text: type + ", " + age + // WRONG: Component.onCompleted: () => console.log(noise) + // The above line would cause a ReferenceError + // as there is no required property noise, + // and the presence of the required properties prevents + // noise from being injected into the scope + } + + ListView { + anchors.fill: parent + model: myModel + delegate: MyDelegate {} + } +} +//! [document] diff --git a/src/quick/doc/snippets/qml/tableview/cpp-tablemodel.cpp b/src/quick/doc/snippets/qml/tableview/cpp-tablemodel.cpp index ea9f76f131..a8a37f80af 100644 --- a/src/quick/doc/snippets/qml/tableview/cpp-tablemodel.cpp +++ b/src/quick/doc/snippets/qml/tableview/cpp-tablemodel.cpp @@ -48,56 +48,19 @@ ** ****************************************************************************/ -//![0] +#include "cpp-tablemodel.h" #include <QGuiApplication> -#include <QQmlApplicationEngine> -#include <QAbstractTableModel> - -class TableModel : public QAbstractTableModel -{ - Q_OBJECT - -public: - - int rowCount(const QModelIndex & = QModelIndex()) const override - { - return 200; - } - - int columnCount(const QModelIndex & = QModelIndex()) const override - { - return 200; - } - - QVariant data(const QModelIndex &index, int role) const override - { - switch (role) { - case Qt::DisplayRole: - return QString("%1, %2").arg(index.column()).arg(index.row()); - default: - break; - } - - return QVariant(); - } - - QHash<int, QByteArray> roleNames() const override - { - return { {Qt::DisplayRole, "display"} }; - } -}; +#include <QQuickView> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); - qmlRegisterType<TableModel>("TableModel", 0, 1, "TableModel"); - - QQmlApplicationEngine engine; - engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + QQuickView view; + view.setSource(QStringLiteral("qrc:/cpp-tablemodel.qml")); + view.show(); return app.exec(); } -#include "main.moc" //![0] diff --git a/src/quick/doc/snippets/qml/tableview/cpp-tablemodel.h b/src/quick/doc/snippets/qml/tableview/cpp-tablemodel.h new file mode 100644 index 0000000000..4a3c46b573 --- /dev/null +++ b/src/quick/doc/snippets/qml/tableview/cpp-tablemodel.h @@ -0,0 +1,94 @@ +/**************************************************************************** + ** + ** Copyright (C) 2020 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the documentation of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:BSD$ + ** 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. + ** + ** BSD License Usage + ** Alternatively, you may use this file under the terms of the BSD license + ** as follows: + ** + ** "Redistribution and use in source and binary forms, with or without + ** modification, are permitted provided that the following conditions are + ** met: + ** * Redistributions of source code must retain the above copyright + ** notice, this list of conditions and the following disclaimer. + ** * Redistributions in binary form must reproduce the above copyright + ** notice, this list of conditions and the following disclaimer in + ** the documentation and/or other materials provided with the + ** distribution. + ** * Neither the name of The Qt Company Ltd nor the names of its + ** contributors may be used to endorse or promote products derived + ** from this software without specific prior written permission. + ** + ** + ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +#ifndef CPPTABLEMODEL_H +#define CPPTABLEMODEL_H + +//![0] +#include <qqml.h> +#include <QAbstractTableModel> + +class TableModel : public QAbstractTableModel +{ + Q_OBJECT + QML_ELEMENT + QML_ADDED_IN_MINOR_VERSION(1) + +public: + int rowCount(const QModelIndex & = QModelIndex()) const override + { + return 200; + } + + int columnCount(const QModelIndex & = QModelIndex()) const override + { + return 200; + } + + QVariant data(const QModelIndex &index, int role) const override + { + switch (role) { + case Qt::DisplayRole: + return QString("%1, %2").arg(index.column()).arg(index.row()); + default: + break; + } + + return QVariant(); + } + + QHash<int, QByteArray> roleNames() const override + { + return { {Qt::DisplayRole, "display"} }; + } +}; +//![0] + +#endif // CPPTABLEMODEL_H diff --git a/src/quick/doc/snippets/qml/tableview/tableview.pro b/src/quick/doc/snippets/qml/tableview/tableview.pro new file mode 100644 index 0000000000..0821f1b5d3 --- /dev/null +++ b/src/quick/doc/snippets/qml/tableview/tableview.pro @@ -0,0 +1,20 @@ +TEMPLATE = app + +QT += qml quick + +CONFIG += qmltypes +QML_IMPORT_NAME = TableModel +QML_IMPORT_MAJOR_VERSION = 0 + +SOURCES += \ + cpp-tablemodel.cpp + +HEADERS += \ + cpp-tablemodel.h + +RESOURCES += \ + cpp-tablemodel.qml \ + qml-tablemodel.qml \ + reusabledelegate.qml \ + tableviewwithheader.qml \ + tableviewwithprovider.qml diff --git a/src/quick/doc/snippets/qml/xmlrole.xml b/src/quick/doc/snippets/qml/xmlrole.xml deleted file mode 100644 index 70280e067d..0000000000 --- a/src/quick/doc/snippets/qml/xmlrole.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> -<catalog> - <book type="Online" wanted="true"> - <title>Qt 5 Cadaques</title> - <year>2014</year> - <author>Juergen Bocklage-Ryannel</author> - <author>Johan Thelin</author> - </book> - <book type="Hardcover"> - <title>C++ GUI Programming with Qt 4</title> - <year>2006</year> - <author>Jasmin Blanchette</author> - <author>Mark Summerfield</author> - </book> - <book type="Paperback"> - <title>Programming with Qt</title> - <year>2002</year> - <author>Matthias Kalle Dalheimer</author> - </book> - </catalog> diff --git a/src/quick/doc/src/concepts/modelviewsdata/modelview.qdoc b/src/quick/doc/src/concepts/modelviewsdata/modelview.qdoc index 04dbf1cf20..555f730c9e 100644 --- a/src/quick/doc/src/concepts/modelviewsdata/modelview.qdoc +++ b/src/quick/doc/src/concepts/modelviewsdata/modelview.qdoc @@ -164,6 +164,16 @@ To visualize data, bind the view's \c model property to a model and the \snippet qml/qml-data-models/listmodel-listview.qml document + To get finer control over which roles are accessible, and to make delegates + more self-contained and usable outside of views, + \li{Required Properties}{required properties} can be used. If a delegate + contains required properties, the named roles are not provided. Instead, + the QML engine will check if the name of a required property matches that of + a model role. If so, that property will be bound to the corresponding value + from the model. + + \snippet qml/qml-data-models/listmodel-listview-required.qml document + If there is a naming clash between the model's properties and the delegate's properties, the roles can be accessed with the qualified \e model name instead. For example, if a \l Text type had \e type or \e age properties, @@ -186,6 +196,10 @@ To visualize data, bind the view's \c model property to a model and the modelData role is also provided for models that have only one role. In this case the \e modelData role contains the same data as the named role. + \note \e model, \e index, and \e modelData roles are not accessible + if the delegate contains required properties, unless it has also required + properties with matching names. + QML provides several types of data models among the built-in set of QML types. In addition, models can be created with Qt C++ and then made available to \l{QQmlEngine} for use by @@ -417,6 +431,12 @@ ListView { \note The \c edit role is equal to \l Qt::EditRole. See \l{QAbstractItemModel::}{roleNames}() for the built-in role names. However, real life models would usually register custom roles. +\node If a model role is bound to a \li{Required Property}{required property}, assigning to +that property will not modify the model. It will instead break the binding to the model (just +like assigning to any other property breaks existing bindings). If you want to use +required properties and change the model data, make model also a required property and assign to +\e model.propertyName. + For more information, visit the \l{qtquick-modelviewsdata-cppmodels.html#changing-model-data}{Using C++ Models with Qt Quick Views} article. diff --git a/src/quick/doc/src/qmltypereference.qdoc b/src/quick/doc/src/qmltypereference.qdoc index 418475f100..528444cad3 100644 --- a/src/quick/doc/src/qmltypereference.qdoc +++ b/src/quick/doc/src/qmltypereference.qdoc @@ -179,6 +179,7 @@ available when you import \c QtQuick. \li \l bool \c font.kerning \li \l bool \c font.preferShaping \li \l enumeration \c font.hintingPreference + \li \l string \c font.styleName \endlist Example: diff --git a/src/quick/handlers/qquickdragaxis_p.h b/src/quick/handlers/qquickdragaxis_p.h index ef74902122..b3db1be620 100644 --- a/src/quick/handlers/qquickdragaxis_p.h +++ b/src/quick/handlers/qquickdragaxis_p.h @@ -63,7 +63,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickDragAxis : public QObject Q_PROPERTY(qreal maximum READ maximum WRITE setMaximum NOTIFY maximumChanged) Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) QML_NAMED_ELEMENT(DragAxis) - QML_ADDED_IN_MINOR_VERSION(12) + QML_ADDED_IN_VERSION(2, 12) QML_UNCREATABLE("DragAxis is only available as a grouped property of DragHandler.") public: diff --git a/src/quick/handlers/qquickdraghandler_p.h b/src/quick/handlers/qquickdraghandler_p.h index 22d51c78ec..1315f79114 100644 --- a/src/quick/handlers/qquickdraghandler_p.h +++ b/src/quick/handlers/qquickdraghandler_p.h @@ -62,9 +62,9 @@ class Q_QUICK_PRIVATE_EXPORT QQuickDragHandler : public QQuickMultiPointHandler Q_PROPERTY(QQuickDragAxis * xAxis READ xAxis CONSTANT) Q_PROPERTY(QQuickDragAxis * yAxis READ yAxis CONSTANT) Q_PROPERTY(QVector2D translation READ translation NOTIFY translationChanged) - Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged REVISION 14) + Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged REVISION(2, 14)) QML_NAMED_ELEMENT(DragHandler) - QML_ADDED_IN_MINOR_VERSION(12) + QML_ADDED_IN_VERSION(2, 12) public: enum SnapMode { @@ -91,7 +91,7 @@ public: Q_SIGNALS: void translationChanged(); - Q_REVISION(14) void snapModeChanged(); + Q_REVISION(2, 14) void snapModeChanged(); protected: void onActiveChanged() override; diff --git a/src/quick/handlers/qquickhandlerpoint.cpp b/src/quick/handlers/qquickhandlerpoint.cpp index f3d92cf200..72efdfd0f4 100644 --- a/src/quick/handlers/qquickhandlerpoint.cpp +++ b/src/quick/handlers/qquickhandlerpoint.cpp @@ -119,8 +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()) { - // TODO + 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/handlers/qquickhoverhandler.cpp b/src/quick/handlers/qquickhoverhandler.cpp index 79cb288af8..b12d85784a 100644 --- a/src/quick/handlers/qquickhoverhandler.cpp +++ b/src/quick/handlers/qquickhoverhandler.cpp @@ -64,6 +64,9 @@ Q_LOGGING_CATEGORY(lcHoverHandler, "qt.quick.handler.hover") properties can be used to narrow the behavior to detect hovering of specific kinds of devices or while holding a modifier key. + The \l cursorShape property allows changing the cursor whenever + \l hovered changes to \c true. + \sa MouseArea, PointHandler */ @@ -90,11 +93,22 @@ bool QQuickHoverHandler::wantsPointerEvent(QQuickPointerEvent *event) { QQuickEventPoint *point = event->point(0); if (QQuickPointerDeviceHandler::wantsPointerEvent(event) && wantsEventPoint(point) && parentContains(point)) { - // assume this is a mouse event, so there's only one point + // assume this is a mouse or tablet event, so there's only one point setPointId(point->pointId()); return true; } - setHovered(false); + + // Some hover events come from QQuickWindow::tabletEvent(). In between, + // some hover events come from QQWindowPrivate::flushFrameSynchronousEvents(), + // but those look like mouse events. If a particular HoverHandler instance + // is filtering for tablet events only (e.g. by setting + // acceptedDevices:PointerDevice.Stylus), those events should not cause + // the hovered property to transition to false prematurely. + // If a QQuickPointerTabletEvent caused the hovered property to become true, + // then only another QQuickPointerTabletEvent can make it become false. + if (!(m_hoveredTablet && event->asPointerMouseEvent())) + setHovered(false); + return false; } @@ -104,6 +118,8 @@ void QQuickHoverHandler::handleEventPoint(QQuickEventPoint *point) if (point->state() == QQuickEventPoint::Released && point->pointerEvent()->device()->pointerType() == QQuickPointerDevice::Finger) hovered = false; + else if (point->pointerEvent()->asPointerTabletEvent()) + m_hoveredTablet = true; setHovered(hovered); setPassiveGrab(point); } @@ -121,8 +137,58 @@ void QQuickHoverHandler::setHovered(bool hovered) if (m_hovered != hovered) { qCDebug(lcHoverHandler) << objectName() << "hovered" << m_hovered << "->" << hovered; m_hovered = hovered; + if (!hovered) + m_hoveredTablet = false; emit hoveredChanged(); } } +/*! + \since 5.15 + \qmlproperty Qt::CursorShape QtQuick::HoverHandler::cursorShape + This property holds the cursor shape that will appear whenever + \l hovered is \c true and no other handler is overriding it. + + The available cursor shapes are: + \list + \li Qt.ArrowCursor + \li Qt.UpArrowCursor + \li Qt.CrossCursor + \li Qt.WaitCursor + \li Qt.IBeamCursor + \li Qt.SizeVerCursor + \li Qt.SizeHorCursor + \li Qt.SizeBDiagCursor + \li Qt.SizeFDiagCursor + \li Qt.SizeAllCursor + \li Qt.BlankCursor + \li Qt.SplitVCursor + \li Qt.SplitHCursor + \li Qt.PointingHandCursor + \li Qt.ForbiddenCursor + \li Qt.WhatsThisCursor + \li Qt.BusyCursor + \li Qt.OpenHandCursor + \li Qt.ClosedHandCursor + \li Qt.DragCopyCursor + \li Qt.DragMoveCursor + \li Qt.DragLinkCursor + \endlist + + The default value of this property is not set, which allows any active + handler on the same \l parentItem to determine the cursor shape. + This property can be reset to the initial condition by setting it to + \c undefined. + + If any handler with defined \c cursorShape is + \l {PointerHandler::active}{active}, that cursor will appear. + Else if the HoverHandler has a defined \c cursorShape, that cursor will appear. + Otherwise, the \l {QQuickItem::cursor()}{cursor} of \l parentItem will appear. + + \note When this property has not been set, or has been set to \c undefined, + if you read the value it will return \c Qt.ArrowCursor. + + \sa Qt::CursorShape, QQuickItem::cursor() +*/ + QT_END_NAMESPACE diff --git a/src/quick/handlers/qquickhoverhandler_p.h b/src/quick/handlers/qquickhoverhandler_p.h index e4786bfa53..4b9d0a9f39 100644 --- a/src/quick/handlers/qquickhoverhandler_p.h +++ b/src/quick/handlers/qquickhoverhandler_p.h @@ -63,7 +63,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickHoverHandler : public QQuickSinglePointHandle Q_OBJECT Q_PROPERTY(bool hovered READ isHovered NOTIFY hoveredChanged) QML_NAMED_ELEMENT(HoverHandler) - QML_ADDED_IN_MINOR_VERSION(12) + QML_ADDED_IN_VERSION(2, 12) public: explicit QQuickHoverHandler(QQuickItem *parent = nullptr); @@ -84,6 +84,7 @@ private: private: bool m_hovered = false; + bool m_hoveredTablet = false; }; QT_END_NAMESPACE diff --git a/src/quick/handlers/qquickpinchhandler.cpp b/src/quick/handlers/qquickpinchhandler.cpp index 5b30d08557..8413b8b721 100644 --- a/src/quick/handlers/qquickpinchhandler.cpp +++ b/src/quick/handlers/qquickpinchhandler.cpp @@ -153,49 +153,6 @@ void QQuickPinchHandler::setMaximumRotation(qreal maximumRotation) emit maximumRotationChanged(); } -#if QT_DEPRECATED_SINCE(5, 12) -void QQuickPinchHandler::warnAboutMinMaxDeprecated() const -{ - qmlWarning(this) << "min and max constraints are now part of the xAxis and yAxis properties"; -} - -void QQuickPinchHandler::setMinimumX(qreal minX) -{ - warnAboutMinMaxDeprecated(); - if (qFuzzyCompare(m_minimumX, minX)) - return; - m_minimumX = minX; - emit minimumXChanged(); -} - -void QQuickPinchHandler::setMaximumX(qreal maxX) -{ - warnAboutMinMaxDeprecated(); - if (qFuzzyCompare(m_maximumX, maxX)) - return; - m_maximumX = maxX; - emit maximumXChanged(); -} - -void QQuickPinchHandler::setMinimumY(qreal minY) -{ - warnAboutMinMaxDeprecated(); - if (qFuzzyCompare(m_minimumY, minY)) - return; - m_minimumY = minY; - emit minimumYChanged(); -} - -void QQuickPinchHandler::setMaximumY(qreal maxY) -{ - warnAboutMinMaxDeprecated(); - if (qFuzzyCompare(m_maximumY, maxY)) - return; - m_maximumY = maxY; - emit maximumYChanged(); -} -#endif - bool QQuickPinchHandler::wantsPointerEvent(QQuickPointerEvent *event) { if (!QQuickMultiPointHandler::wantsPointerEvent(event)) diff --git a/src/quick/handlers/qquickpinchhandler_p.h b/src/quick/handlers/qquickpinchhandler_p.h index 708c836acf..b4e9fa0336 100644 --- a/src/quick/handlers/qquickpinchhandler_p.h +++ b/src/quick/handlers/qquickpinchhandler_p.h @@ -70,16 +70,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPinchHandler : public QQuickMultiPointHandler Q_PROPERTY(qreal activeScale READ activeScale NOTIFY updated) Q_PROPERTY(qreal rotation READ rotation NOTIFY updated) Q_PROPERTY(QVector2D translation READ translation NOTIFY updated) -#if QT_DEPRECATED_SINCE(5, 12) - Q_PROPERTY(qreal minimumX READ minimumX WRITE setMinimumX NOTIFY minimumXChanged) // ### Qt 6: remove - Q_PROPERTY(qreal maximumX READ maximumX WRITE setMaximumX NOTIFY maximumXChanged) // ### Qt 6: remove - Q_PROPERTY(qreal minimumY READ minimumY WRITE setMinimumY NOTIFY minimumYChanged) // ### Qt 6: remove - Q_PROPERTY(qreal maximumY READ maximumY WRITE setMaximumY NOTIFY maximumYChanged) // ### Qt 6: remove -#endif Q_PROPERTY(QQuickDragAxis * xAxis READ xAxis CONSTANT) Q_PROPERTY(QQuickDragAxis * yAxis READ yAxis CONSTANT) QML_NAMED_ELEMENT(PinchHandler) - QML_ADDED_IN_MINOR_VERSION(12) + QML_ADDED_IN_VERSION(2, 12) public: explicit QQuickPinchHandler(QQuickItem *parent = nullptr); @@ -101,18 +95,6 @@ public: qreal activeScale() const { return m_activeScale; } qreal rotation() const { return m_activeRotation; } -#if QT_DEPRECATED_SINCE(5, 12) - void warnAboutMinMaxDeprecated() const; - qreal minimumX() const { warnAboutMinMaxDeprecated(); return m_minimumX; } - void setMinimumX(qreal minX); - qreal maximumX() const { warnAboutMinMaxDeprecated(); return m_maximumX; } - void setMaximumX(qreal maxX); - qreal minimumY() const { warnAboutMinMaxDeprecated(); return m_minimumY; } - void setMinimumY(qreal minY); - qreal maximumY() const { warnAboutMinMaxDeprecated(); return m_maximumY; } - void setMaximumY(qreal maxY); -#endif - QQuickDragAxis *xAxis() { return &m_xAxis; } QQuickDragAxis *yAxis() { return &m_yAxis; } @@ -121,10 +103,6 @@ signals: void maximumScaleChanged(); void minimumRotationChanged(); void maximumRotationChanged(); - void minimumXChanged(); - void maximumXChanged(); - void minimumYChanged(); - void maximumYChanged(); void updated(); protected: @@ -145,10 +123,6 @@ private: qreal m_minimumRotation = -qInf(); qreal m_maximumRotation = qInf(); - qreal m_minimumX = -qInf(); - qreal m_maximumX = qInf(); - qreal m_minimumY = -qInf(); - qreal m_maximumY = qInf(); QQuickDragAxis m_xAxis; QQuickDragAxis m_yAxis; diff --git a/src/quick/handlers/qquickpointerhandler.cpp b/src/quick/handlers/qquickpointerhandler.cpp index c498c96454..adb753e000 100644 --- a/src/quick/handlers/qquickpointerhandler.cpp +++ b/src/quick/handlers/qquickpointerhandler.cpp @@ -51,7 +51,6 @@ Q_LOGGING_CATEGORY(lcPointerHandlerActive, "qt.quick.handler.active") \qmltype PointerHandler \qmlabstract \since 5.10 - \preliminary \instantiates QQuickPointerHandler \inqmlmodule QtQuick \brief Abstract handler for pointer events. @@ -154,6 +153,87 @@ void QQuickPointerHandler::resetDragThreshold() } /*! + \since 5.15 + \qmlproperty Qt::CursorShape PointerHandler::cursorShape + This property holds the cursor shape that will appear whenever the mouse is + hovering over the \l parentItem while \l active is \c true. + + The available cursor shapes are: + \list + \li Qt.ArrowCursor + \li Qt.UpArrowCursor + \li Qt.CrossCursor + \li Qt.WaitCursor + \li Qt.IBeamCursor + \li Qt.SizeVerCursor + \li Qt.SizeHorCursor + \li Qt.SizeBDiagCursor + \li Qt.SizeFDiagCursor + \li Qt.SizeAllCursor + \li Qt.BlankCursor + \li Qt.SplitVCursor + \li Qt.SplitHCursor + \li Qt.PointingHandCursor + \li Qt.ForbiddenCursor + \li Qt.WhatsThisCursor + \li Qt.BusyCursor + \li Qt.OpenHandCursor + \li Qt.ClosedHandCursor + \li Qt.DragCopyCursor + \li Qt.DragMoveCursor + \li Qt.DragLinkCursor + \endlist + + The default value is not set, which allows the \l {QQuickItem::cursor()}{cursor} + of \l parentItem to appear. This property can be reset to the same initial + condition by setting it to undefined. + + \note When this property has not been set, or has been set to \c undefined, + if you read the value it will return \c Qt.ArrowCursor. + + \sa Qt::CursorShape, QQuickItem::cursor(), HoverHandler::cursorShape +*/ +#if QT_CONFIG(cursor) +Qt::CursorShape QQuickPointerHandler::cursorShape() const +{ + Q_D(const QQuickPointerHandler); + return d->cursorShape; +} + +void QQuickPointerHandler::setCursorShape(Qt::CursorShape shape) +{ + Q_D(QQuickPointerHandler); + if (d->cursorSet && shape == d->cursorShape) + return; + d->cursorShape = shape; + d->cursorSet = true; + QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(parentItem()); + itemPriv->hasCursorHandler = true; + itemPriv->setHasCursorInChild(true); + emit cursorShapeChanged(); +} + +void QQuickPointerHandler::resetCursorShape() +{ + Q_D(QQuickPointerHandler); + if (!d->cursorSet) + return; + d->cursorShape = Qt::ArrowCursor; + d->cursorSet = false; + QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(parentItem()); + itemPriv->hasCursorHandler = false; + itemPriv->setHasCursorInChild(itemPriv->hasCursor); + emit cursorShapeChanged(); +} + +bool QQuickPointerHandler::isCursorShapeExplicitlySet() const +{ + Q_D(const QQuickPointerHandler); + return d->cursorSet; +} +#endif + +/*! Notification that the grab has changed in some way which is relevant to this handler. The \a grabber (subject) will be the Input Handler whose state is changing, or null if the state change regards an Item. @@ -597,11 +677,13 @@ QQuickPointerHandlerPrivate::QQuickPointerHandlerPrivate() : grabPermissions(QQuickPointerHandler::CanTakeOverFromItems | QQuickPointerHandler::CanTakeOverFromHandlersOfDifferentType | QQuickPointerHandler::ApprovesTakeOverByAnything) + , cursorShape(Qt::ArrowCursor) , enabled(true) , active(false) , targetExplicitlySet(false) , hadKeepMouseGrab(false) , hadKeepTouchGrab(false) + , cursorSet(false) { } diff --git a/src/quick/handlers/qquickpointerhandler_p.h b/src/quick/handlers/qquickpointerhandler_p.h index 34ae9ce2c2..3e7876b3d9 100644 --- a/src/quick/handlers/qquickpointerhandler_p.h +++ b/src/quick/handlers/qquickpointerhandler_p.h @@ -71,11 +71,14 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointerHandler : public QObject, public QQmlP Q_PROPERTY(QQuickItem * parent READ parentItem CONSTANT) Q_PROPERTY(GrabPermissions grabPermissions READ grabPermissions WRITE setGrabPermissions NOTIFY grabPermissionChanged) Q_PROPERTY(qreal margin READ margin WRITE setMargin NOTIFY marginChanged) - Q_PROPERTY(int dragThreshold READ dragThreshold WRITE setDragThreshold RESET resetDragThreshold NOTIFY dragThresholdChanged REVISION 15) + Q_PROPERTY(int dragThreshold READ dragThreshold WRITE setDragThreshold RESET resetDragThreshold NOTIFY dragThresholdChanged REVISION(2, 15)) +#if QT_CONFIG(cursor) + Q_PROPERTY(Qt::CursorShape cursorShape READ cursorShape WRITE setCursorShape RESET resetCursorShape NOTIFY cursorShapeChanged REVISION(2, 15)) +#endif QML_NAMED_ELEMENT(PointerHandler) QML_UNCREATABLE("PointerHandler is an abstract base class.") - QML_ADDED_IN_MINOR_VERSION(12) + QML_ADDED_IN_VERSION(2, 12) public: explicit QQuickPointerHandler(QQuickItem *parent = nullptr); @@ -119,15 +122,25 @@ public: void setDragThreshold(int t); void resetDragThreshold(); +#if QT_CONFIG(cursor) + Qt::CursorShape cursorShape() const; + void setCursorShape(Qt::CursorShape shape); + void resetCursorShape(); + bool isCursorShapeExplicitlySet() const; +#endif + Q_SIGNALS: void enabledChanged(); void activeChanged(); void targetChanged(); void marginChanged(); - Q_REVISION(15) void dragThresholdChanged(); + Q_REVISION(2, 15) void dragThresholdChanged(); void grabChanged(QQuickEventPoint::GrabTransition transition, QQuickEventPoint *point); void grabPermissionChanged(); void canceled(QQuickEventPoint *point); +#if QT_CONFIG(cursor) + Q_REVISION(2, 15) void cursorShapeChanged(); +#endif protected: QQuickPointerHandler(QQuickPointerHandlerPrivate &dd, QQuickItem *parent); diff --git a/src/quick/handlers/qquickpointerhandler_p_p.h b/src/quick/handlers/qquickpointerhandler_p_p.h index 5727b1ef55..db053fb6b4 100644 --- a/src/quick/handlers/qquickpointerhandler_p_p.h +++ b/src/quick/handlers/qquickpointerhandler_p_p.h @@ -79,11 +79,13 @@ public: qreal m_margin = 0; qint16 dragThreshold = -1; // -1 means use the platform default uint8_t grabPermissions : 8; + Qt::CursorShape cursorShape : 6; bool enabled : 1; bool active : 1; bool targetExplicitlySet : 1; bool hadKeepMouseGrab : 1; // some handlers override target()->setKeepMouseGrab(); this remembers previous state bool hadKeepTouchGrab : 1; // some handlers override target()->setKeepTouchGrab(); this remembers previous state + bool cursorSet : 1; }; QT_END_NAMESPACE diff --git a/src/quick/handlers/qquickpointhandler_p.h b/src/quick/handlers/qquickpointhandler_p.h index 42677540a7..cedbc1c539 100644 --- a/src/quick/handlers/qquickpointhandler_p.h +++ b/src/quick/handlers/qquickpointhandler_p.h @@ -60,7 +60,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointHandler : public QQuickSinglePointHandle Q_OBJECT Q_PROPERTY(QVector2D translation READ translation NOTIFY translationChanged) QML_NAMED_ELEMENT(PointHandler) - QML_ADDED_IN_MINOR_VERSION(12) + QML_ADDED_IN_VERSION(2, 12) public: explicit QQuickPointHandler(QQuickItem *parent = nullptr); diff --git a/src/quick/handlers/qquicktaphandler_p.h b/src/quick/handlers/qquicktaphandler_p.h index 07454bccb8..d5c16b071f 100644 --- a/src/quick/handlers/qquicktaphandler_p.h +++ b/src/quick/handlers/qquicktaphandler_p.h @@ -68,7 +68,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTapHandler : public QQuickSinglePointHandler Q_PROPERTY(GesturePolicy gesturePolicy READ gesturePolicy WRITE setGesturePolicy NOTIFY gesturePolicyChanged) QML_NAMED_ELEMENT(TapHandler) - QML_ADDED_IN_MINOR_VERSION(12) + QML_ADDED_IN_VERSION(2, 12) public: enum GesturePolicy { diff --git a/src/quick/handlers/qquickwheelhandler_p.h b/src/quick/handlers/qquickwheelhandler_p.h index 26b052c5b3..021cd23679 100644 --- a/src/quick/handlers/qquickwheelhandler_p.h +++ b/src/quick/handlers/qquickwheelhandler_p.h @@ -73,7 +73,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickWheelHandler : public QQuickSinglePointHandle Q_PROPERTY(bool targetTransformAroundCursor READ isTargetTransformAroundCursor WRITE setTargetTransformAroundCursor NOTIFY targetTransformAroundCursorChanged) QML_NAMED_ELEMENT(WheelHandler) - QML_ADDED_IN_MINOR_VERSION(14) + QML_ADDED_IN_VERSION(2, 14) public: explicit QQuickWheelHandler(QQuickItem *parent = nullptr); diff --git a/src/quick/items/context2d/qquickcanvasitem_p.h b/src/quick/items/context2d/qquickcanvasitem_p.h index 6575caf806..48663c2dad 100644 --- a/src/quick/items/context2d/qquickcanvasitem_p.h +++ b/src/quick/items/context2d/qquickcanvasitem_p.h @@ -100,6 +100,7 @@ class QQuickCanvasItem : public QQuickItem Q_PROPERTY(RenderTarget renderTarget READ renderTarget WRITE setRenderTarget NOTIFY renderTargetChanged) Q_PROPERTY(RenderStrategy renderStrategy READ renderStrategy WRITE setRenderStrategy NOTIFY renderStrategyChanged) QML_NAMED_ELEMENT(Canvas) + QML_ADDED_IN_VERSION(2, 0) public: enum RenderTarget { diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index 54cda72a36..8361be7277 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -74,12 +74,12 @@ #include <QtCore/private/qnumeric_p.h> #include <QtCore/QRunnable> #include <QtGui/qguiapplication.h> -#include <QtGui/qopenglframebufferobject.h> #include <private/qguiapplication_p.h> #include <qpa/qplatformintegration.h> #if QT_CONFIG(opengl) -# include <private/qsgdefaultrendercontext_p.h> +#include <qopenglframebufferobject.h> +#include <private/qsgdefaultrendercontext_p.h> #endif #include <cmath> diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h index b7254d6686..8a71c492a3 100644 --- a/src/quick/items/qquickaccessibleattached_p.h +++ b/src/quick/items/qquickaccessibleattached_p.h @@ -91,6 +91,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickAccessibleAttached : public QObject Q_PROPERTY(bool ignored READ ignored WRITE setIgnored NOTIFY ignoredChanged FINAL) QML_NAMED_ELEMENT(Accessible) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("Accessible is only available via attached properties.") QML_ATTACHED(QQuickAccessibleAttached) diff --git a/src/quick/items/qquickanchors_p.h b/src/quick/items/qquickanchors_p.h index e0276549e9..d243f6070f 100644 --- a/src/quick/items/qquickanchors_p.h +++ b/src/quick/items/qquickanchors_p.h @@ -85,6 +85,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickAnchors : public QObject Q_PROPERTY(QQuickItem *centerIn READ centerIn WRITE setCenterIn RESET resetCenterIn NOTIFY centerInChanged) Q_PROPERTY(bool alignWhenCentered READ alignWhenCentered WRITE setAlignWhenCentered NOTIFY centerAlignedChanged) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQuickAnchors(QQuickItem *item, QObject *parent=nullptr); diff --git a/src/quick/items/qquickanimatedimage.cpp b/src/quick/items/qquickanimatedimage.cpp index 18d492cd68..192ed289e2 100644 --- a/src/quick/items/qquickanimatedimage.cpp +++ b/src/quick/items/qquickanimatedimage.cpp @@ -67,7 +67,7 @@ QQuickPixmap* QQuickAnimatedImagePrivate::infoForCurrentFrame(QQmlEngine *engine .arg(current)); } if (!requestedUrl.isEmpty()) { - if (QQuickPixmap::isCached(requestedUrl, QSize(), 0, QQuickImageProviderOptions())) + if (QQuickPixmap::isCached(requestedUrl, QRect(), QSize(), 0, QQuickImageProviderOptions())) pixmap = new QQuickPixmap(engine, requestedUrl); else pixmap = new QQuickPixmap(requestedUrl, movie->currentImage()); diff --git a/src/quick/items/qquickanimatedimage_p.h b/src/quick/items/qquickanimatedimage_p.h index 7f2199fd2a..6f7a7e45d5 100644 --- a/src/quick/items/qquickanimatedimage_p.h +++ b/src/quick/items/qquickanimatedimage_p.h @@ -70,11 +70,12 @@ class Q_AUTOTEST_EXPORT QQuickAnimatedImage : public QQuickImage Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged) Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY frameChanged) Q_PROPERTY(int frameCount READ frameCount NOTIFY frameCountChanged) - Q_PROPERTY(qreal speed READ speed WRITE setSpeed NOTIFY speedChanged REVISION 11) + Q_PROPERTY(qreal speed READ speed WRITE setSpeed NOTIFY speedChanged REVISION(2, 11)) // read-only for AnimatedImage Q_PROPERTY(QSize sourceSize READ sourceSize NOTIFY sourceSizeChanged) QML_NAMED_ELEMENT(AnimatedImage) + QML_ADDED_IN_VERSION(2, 0) public: QQuickAnimatedImage(QQuickItem *parent=nullptr); @@ -104,7 +105,7 @@ Q_SIGNALS: void frameChanged(); void currentFrameChanged(); void frameCountChanged(); - Q_REVISION(11) void speedChanged(); + Q_REVISION(2, 11) void speedChanged(); private Q_SLOTS: void movieUpdate(); diff --git a/src/quick/items/qquickanimatedsprite_p.h b/src/quick/items/qquickanimatedsprite_p.h index c28b6ce3af..77147add16 100644 --- a/src/quick/items/qquickanimatedsprite_p.h +++ b/src/quick/items/qquickanimatedsprite_p.h @@ -92,8 +92,9 @@ class Q_AUTOTEST_EXPORT QQuickAnimatedSprite : public QQuickItem Q_PROPERTY(int loops READ loops WRITE setLoops NOTIFY loopsChanged) Q_PROPERTY(bool paused READ paused WRITE setPaused NOTIFY pausedChanged) Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY currentFrameChanged) - Q_PROPERTY(FinishBehavior finishBehavior READ finishBehavior WRITE setFinishBehavior NOTIFY finishBehaviorChanged REVISION 15) + Q_PROPERTY(FinishBehavior finishBehavior READ finishBehavior WRITE setFinishBehavior NOTIFY finishBehaviorChanged REVISION(2, 15)) QML_NAMED_ELEMENT(AnimatedSprite) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickAnimatedSprite(QQuickItem *parent = nullptr); @@ -124,6 +125,7 @@ public: bool paused() const; int currentFrame() const; FinishBehavior finishBehavior() const; + void setFinishBehavior(FinishBehavior arg); Q_SIGNALS: @@ -143,9 +145,9 @@ Q_SIGNALS: void frameDurationChanged(int arg); void loopsChanged(int arg); void currentFrameChanged(int arg); - Q_REVISION(15) void finishBehaviorChanged(FinishBehavior arg); + Q_REVISION(2, 15) void finishBehaviorChanged(FinishBehavior arg); - Q_REVISION(12) void finished(); + Q_REVISION(2, 12) void finished(); public Q_SLOTS: void start(); @@ -172,7 +174,6 @@ public Q_SLOTS: void resetFrameDuration(); void setLoops(int arg); void setCurrentFrame(int arg); - void setFinishBehavior(FinishBehavior arg); private Q_SLOTS: void createEngine(); diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp index 32407a474f..3679df37d1 100644 --- a/src/quick/items/qquickborderimage.cpp +++ b/src/quick/items/qquickborderimage.cpp @@ -478,7 +478,7 @@ void QQuickBorderImage::sciRequestFinished() } d->redirectCount=0; - if (d->sciReply->networkError() != QNetworkReply::NoError) { + if (d->sciReply->error() != QNetworkReply::NoError) { d->status = Error; d->sciReply->deleteLater(); d->sciReply = nullptr; diff --git a/src/quick/items/qquickborderimage_p.h b/src/quick/items/qquickborderimage_p.h index 515edb33da..48922147ba 100644 --- a/src/quick/items/qquickborderimage_p.h +++ b/src/quick/items/qquickborderimage_p.h @@ -68,6 +68,7 @@ class Q_AUTOTEST_EXPORT QQuickBorderImage : public QQuickImageBase // read-only for BorderImage Q_PROPERTY(QSize sourceSize READ sourceSize NOTIFY sourceSizeChanged) QML_NAMED_ELEMENT(BorderImage) + QML_ADDED_IN_VERSION(2, 0) public: QQuickBorderImage(QQuickItem *parent=nullptr); diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp index 737b7ffe24..117daef924 100644 --- a/src/quick/items/qquickdrag.cpp +++ b/src/quick/items/qquickdrag.cpp @@ -61,6 +61,7 @@ class QQuickDragAttachedPrivate : public QObjectPrivate, public QQuickItemChange { Q_DECLARE_PUBLIC(QQuickDragAttached) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: static QQuickDragAttachedPrivate *get(QQuickDragAttached *attached) { diff --git a/src/quick/items/qquickdrag_p.h b/src/quick/items/qquickdrag_p.h index 9dbaac18f9..36b0a2bfd1 100644 --- a/src/quick/items/qquickdrag_p.h +++ b/src/quick/items/qquickdrag_p.h @@ -173,6 +173,7 @@ class Q_AUTOTEST_EXPORT QQuickDrag : public QObject //### consider drag and drop QML_NAMED_ELEMENT(Drag) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("Drag is only available via attached properties.") QML_ATTACHED(QQuickDragAttached) @@ -260,6 +261,7 @@ class QQuickDragAttached : public QObject Q_PROPERTY(QQuickDrag::DragType dragType READ dragType WRITE setDragType NOTIFY dragTypeChanged) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQuickDragAttached(QObject *parent); diff --git a/src/quick/items/qquickdroparea_p.h b/src/quick/items/qquickdroparea_p.h index ee2deaa97a..b1d3d78a37 100644 --- a/src/quick/items/qquickdroparea_p.h +++ b/src/quick/items/qquickdroparea_p.h @@ -81,6 +81,7 @@ class QQuickDropEvent : public QObject Q_PROPERTY(QList<QUrl> urls READ urls) Q_PROPERTY(QStringList formats READ formats) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQuickDropEvent(QQuickDropAreaPrivate *d, QDropEvent *event) : d(d), event(event) {} @@ -127,6 +128,7 @@ class QQuickDropAreaDrag : public QObject Q_PROPERTY(qreal y READ y NOTIFY positionChanged) Q_PROPERTY(QObject *source READ source NOTIFY sourceChanged) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQuickDropAreaDrag(QQuickDropAreaPrivate *d, QObject *parent = 0); ~QQuickDropAreaDrag(); @@ -154,6 +156,7 @@ class Q_AUTOTEST_EXPORT QQuickDropArea : public QQuickItem Q_PROPERTY(QStringList keys READ keys WRITE setKeys NOTIFY keysChanged) Q_PROPERTY(QQuickDropAreaDrag *drag READ drag CONSTANT) QML_NAMED_ELEMENT(DropArea) + QML_ADDED_IN_VERSION(2, 0) public: QQuickDropArea(QQuickItem *parent=0); diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index 03280e4c1f..804c3a081e 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,15 +660,76 @@ QQuickPointerDevice *QQuickPointerDevice::genericMouseDevice() return g_genericMouseDevice; } -QQuickPointerDevice *QQuickPointerDevice::tabletDevice(qint64 id) +#if QT_CONFIG(tabletevent) +QQuickPointerDevice *QQuickPointerDevice::tabletDevice(const QTabletEvent *event) { - auto it = g_tabletDevices->find(id); + // QTabletEvent::uniqueId() is the same for the pointy end and the eraser end of the stylus. + // We need to make those unique. QTabletEvent::PointerType only needs 2 bits' worth of storage. + // The key into g_tabletDevices just needs to be unique; we don't need to extract uniqueId + // back out of it, because QQuickPointerDevice stores that separately anyway. + // So the shift-and-add can be thought of as a sort of hash function, even though + // most of the time the result will be recognizable because the uniqueId MSBs are often 0. + qint64 key = event->uniqueId() + (qint64(event->pointerType()) << 60); + auto it = g_tabletDevices->find(key); if (it != g_tabletDevices->end()) return it.value(); - // ### Figure out how to populate the tablet devices - return nullptr; + DeviceType type = UnknownDevice; + int buttonCount = 0; + Capabilities caps = Position | Pressure | Hover; + // TODO Qt 6: we can't know for sure about XTilt or YTilt until we have a + // QTabletDevice populated with capabilities provided by QPA plugins + + switch (event->deviceType()) { + case QTabletEvent::Stylus: + type = QQuickPointerDevice::Stylus; + buttonCount = 3; + break; + case QTabletEvent::RotationStylus: + type = QQuickPointerDevice::Stylus; + caps |= QQuickPointerDevice::Rotation; + buttonCount = 1; + break; + case QTabletEvent::Airbrush: + type = QQuickPointerDevice::Airbrush; + buttonCount = 2; + break; + case QTabletEvent::Puck: + type = QQuickPointerDevice::Puck; + buttonCount = 3; + break; + case QTabletEvent::FourDMouse: + type = QQuickPointerDevice::Mouse; + caps |= QQuickPointerDevice::Rotation; + buttonCount = 3; + break; + default: + type = QQuickPointerDevice::UnknownDevice; + break; + } + + PointerType ptype = GenericPointer; + switch (event->pointerType()) { + case QTabletEvent::Pen: + ptype = Pen; + break; + case QTabletEvent::Eraser: + ptype = Eraser; + break; + case QTabletEvent::Cursor: + ptype = Cursor; + break; + case QTabletEvent::UnknownPointer: + break; + } + + QQuickPointerDevice *device = new QQuickPointerDevice(type, ptype, caps, 1, buttonCount, + QLatin1String("tablet tool ") + QString::number(event->uniqueId()), event->uniqueId()); + + g_tabletDevices->insert(key, device); + return device; } +#endif /*! \qmltype EventPoint @@ -1284,6 +1347,12 @@ QVector2D QQuickEventPoint::estimatedVelocity() const QQuickPointerEvent::~QQuickPointerEvent() {} +QQuickPointerMouseEvent::QQuickPointerMouseEvent(QObject *parent, QQuickPointerDevice *device) + : QQuickSinglePointEvent(parent, device) +{ + m_point = new QQuickEventPoint(this); +} + QQuickPointerEvent *QQuickPointerMouseEvent::reset(QEvent *event) { auto ev = static_cast<QMouseEvent*>(event); @@ -1398,6 +1467,12 @@ void QQuickPointerTouchEvent::localize(QQuickItem *target) } #if QT_CONFIG(gestures) +QQuickPointerNativeGestureEvent::QQuickPointerNativeGestureEvent(QObject *parent, QQuickPointerDevice *device) + : QQuickSinglePointEvent(parent, device) +{ + m_point = new QQuickEventPoint(this); +} + QQuickPointerEvent *QQuickPointerNativeGestureEvent::reset(QEvent *event) { auto ev = static_cast<QNativeGestureEvent*>(event); @@ -1560,6 +1635,12 @@ QQuickEventPoint *QQuickSinglePointEvent::point(int i) const \note Many platforms provide no such information. On such platforms, \c inverted always returns false. */ +QQuickPointerScrollEvent::QQuickPointerScrollEvent(QObject *parent, QQuickPointerDevice *device) + : QQuickSinglePointEvent(parent, device) +{ + m_point = new QQuickEventPoint(this); +} + QQuickPointerEvent *QQuickPointerScrollEvent::reset(QEvent *event) { m_event = static_cast<QInputEvent*>(event); @@ -1626,6 +1707,8 @@ bool QQuickSinglePointEvent::allPointsGrabbed() const QMouseEvent *QQuickPointerMouseEvent::asMouseEvent(const QPointF &localPos) const { + if (!m_event) + return nullptr; auto event = static_cast<QMouseEvent *>(m_event); event->setLocalPos(localPos); return event; @@ -1830,6 +1913,81 @@ QMouseEvent *QQuickPointerTouchEvent::syntheticMouseEvent(int pointID, QQuickIte return &m_synthMouseEvent; } +#if QT_CONFIG(tabletevent) +QQuickPointerTabletEvent::QQuickPointerTabletEvent(QObject *parent, QQuickPointerDevice *device) + : QQuickSinglePointEvent(parent, device) +{ + m_point = new QQuickEventTabletPoint(this); +} + +QQuickPointerEvent *QQuickPointerTabletEvent::reset(QEvent *event) +{ + auto ev = static_cast<QTabletEvent*>(event); + m_event = ev; + if (!event) + return this; + + Q_ASSERT(m_device == QQuickPointerDevice::tabletDevice(ev)); + m_device->eventDeliveryTargets().clear(); + m_button = ev->button(); + m_pressedButtons = ev->buttons(); + static_cast<QQuickEventTabletPoint *>(m_point)->reset(ev); + return this; +} + +QQuickEventTabletPoint::QQuickEventTabletPoint(QQuickPointerTabletEvent *parent) + : QQuickEventPoint(parent) +{ +} + +void QQuickEventTabletPoint::reset(const QTabletEvent *ev) +{ + Qt::TouchPointState state = Qt::TouchPointStationary; + switch (ev->type()) { + case QEvent::TabletPress: + state = Qt::TouchPointPressed; + clearPassiveGrabbers(); + break; + case QEvent::TabletRelease: + state = Qt::TouchPointReleased; + break; + case QEvent::TabletMove: + state = Qt::TouchPointMoved; + break; + default: + break; + } + QQuickEventPoint::reset(state, ev->posF(), 1, ev->timestamp()); + m_rotation = ev->rotation(); + m_pressure = ev->pressure(); + m_tangentialPressure = ev->tangentialPressure(); + m_tilt = QVector2D(ev->xTilt(), ev->yTilt()); +} + +bool QQuickPointerTabletEvent::isPressEvent() const +{ + auto me = static_cast<QTabletEvent *>(m_event); + return me->type() == QEvent::TabletPress; +} + +bool QQuickPointerTabletEvent::isUpdateEvent() const +{ + auto me = static_cast<QTabletEvent *>(m_event); + return me->type() == QEvent::TabletMove; +} + +bool QQuickPointerTabletEvent::isReleaseEvent() const +{ + auto me = static_cast<QTabletEvent *>(m_event); + return me->type() == QEvent::TabletRelease; +} + +QTabletEvent *QQuickPointerTabletEvent::asTabletEvent() const +{ + return static_cast<QTabletEvent *>(m_event); +} +#endif // QT_CONFIG(tabletevent) + #if QT_CONFIG(gestures) bool QQuickPointerNativeGestureEvent::isPressEvent() const { diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h index 4615ce43d2..b1d8b52372 100644 --- a/src/quick/items/qquickevents_p_p.h +++ b/src/quick/items/qquickevents_p_p.h @@ -56,12 +56,14 @@ #include <QtCore/qobject.h> #include <QtCore/qpointer.h> -#include <QtGui/qvector2d.h> #include <QtGui/qevent.h> +#include <QtGui/qtouchdevice.h> +#include <QtGui/qvector2d.h> +#include <QtQuick/qquickitem.h> + #if QT_CONFIG(shortcut) # include <QtGui/qkeysequence.h> #endif -#include <QtQuick/qquickitem.h> QT_BEGIN_NAMESPACE @@ -87,6 +89,7 @@ class QQuickKeyEvent : public QObject Q_PROPERTY(quint32 nativeScanCode READ nativeScanCode CONSTANT) Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQuickKeyEvent() @@ -117,7 +120,7 @@ public: void setAccepted(bool accepted) { event.setAccepted(accepted); } #if QT_CONFIG(shortcut) - Q_REVISION(2) Q_INVOKABLE bool matches(QKeySequence::StandardKey key) const { return event.matches(key); } + Q_REVISION(2, 2) Q_INVOKABLE bool matches(QKeySequence::StandardKey key) const { return event.matches(key); } #endif private: @@ -133,12 +136,13 @@ class Q_QUICK_PRIVATE_EXPORT QQuickMouseEvent : public QObject Q_PROPERTY(int button READ button CONSTANT) Q_PROPERTY(int buttons READ buttons CONSTANT) Q_PROPERTY(int modifiers READ modifiers CONSTANT) - Q_PROPERTY(int source READ source CONSTANT REVISION 7) + Q_PROPERTY(int source READ source CONSTANT REVISION(2, 7)) Q_PROPERTY(bool wasHeld READ wasHeld CONSTANT) Q_PROPERTY(bool isClick READ isClick CONSTANT) Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted) - Q_PROPERTY(int flags READ flags CONSTANT REVISION 11) + Q_PROPERTY(int flags READ flags CONSTANT REVISION(2, 11)) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQuickMouseEvent() @@ -205,6 +209,7 @@ class QQuickWheelEvent : public QObject Q_PROPERTY(bool inverted READ inverted CONSTANT) Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQuickWheelEvent() @@ -250,6 +255,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickCloseEvent : public QObject Q_OBJECT Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQuickCloseEvent() {} @@ -278,7 +284,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickEventPoint : public QObject QML_NAMED_ELEMENT(EventPoint) QML_UNCREATABLE("EventPoint is only available as a member of PointerEvent.") - QML_ADDED_IN_MINOR_VERSION(12) + QML_ADDED_IN_VERSION(2, 12) public: enum State { @@ -373,7 +379,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickEventTouchPoint : public QQuickEventPoint QML_NAMED_ELEMENT(EventTouchPoint) QML_UNCREATABLE("EventTouchPoint is only available as a member of PointerEvent.") - QML_ADDED_IN_MINOR_VERSION(12) + QML_ADDED_IN_VERSION(2, 12) public: QQuickEventTouchPoint(QQuickPointerTouchEvent *parent); @@ -406,7 +412,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointerEvent : public QObject QML_NAMED_ELEMENT(PointerEvent) QML_UNCREATABLE("PointerEvent is only available as a parameter of several signals in PointerHandler") - QML_ADDED_IN_MINOR_VERSION(12) + QML_ADDED_IN_VERSION(2, 12) public: QQuickPointerEvent(QObject *parent = nullptr, QQuickPointerDevice *device = nullptr) @@ -476,8 +482,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickSinglePointEvent : public QQuickPointerEvent { Q_OBJECT public: - QQuickSinglePointEvent(QObject *parent = nullptr, QQuickPointerDevice *device = nullptr) - : QQuickPointerEvent(parent, device), m_point(new QQuickEventPoint(this)) { } + QQuickSinglePointEvent(QObject *parent, QQuickPointerDevice *device) + : QQuickPointerEvent(parent, device) { } void localize(QQuickItem *target) override; int pointCount() const override { return 1; } @@ -491,7 +497,7 @@ public: bool hasExclusiveGrabber(const QQuickPointerHandler *handler) const override; protected: - QQuickEventPoint *m_point; + QQuickEventPoint *m_point = nullptr; Q_DISABLE_COPY(QQuickSinglePointEvent) }; @@ -502,11 +508,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointerMouseEvent : public QQuickSinglePointE QML_NAMED_ELEMENT(PointerMouseEvent) QML_UNCREATABLE("PointerMouseEvent is only available as a parameter of several signals in PointerHandler") - QML_ADDED_IN_MINOR_VERSION(12) + QML_ADDED_IN_VERSION(2, 12) public: - QQuickPointerMouseEvent(QObject *parent = nullptr, QQuickPointerDevice *device = nullptr) - : QQuickSinglePointEvent(parent, device) { } + QQuickPointerMouseEvent(QObject *parent, QQuickPointerDevice *device); QQuickPointerEvent *reset(QEvent *) override; bool isPressEvent() const override; @@ -527,7 +532,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointerTouchEvent : public QQuickPointerEvent QML_NAMED_ELEMENT(PointerTouchEvent) QML_UNCREATABLE("PointerTouchEvent is only available as a parameter of several signals in PointerHandler") - QML_ADDED_IN_MINOR_VERSION(12) + QML_ADDED_IN_VERSION(2, 12) public: QQuickPointerTouchEvent(QObject *parent = nullptr, QQuickPointerDevice *device = nullptr) @@ -568,6 +573,60 @@ private: Q_DISABLE_COPY(QQuickPointerTouchEvent) }; +#if QT_CONFIG(tabletevent) +class Q_QUICK_PRIVATE_EXPORT QQuickEventTabletPoint : public QQuickEventPoint +{ + Q_OBJECT + Q_PROPERTY(qreal rotation READ rotation) + Q_PROPERTY(qreal pressure READ pressure) + Q_PROPERTY(qreal tangentialPressure READ tangentialPressure) + Q_PROPERTY(QVector2D tilt READ tilt) + + QML_NAMED_ELEMENT(EventTabletPoint) + QML_UNCREATABLE("EventTouchPoint is only available as a member of PointerEvent.") + QML_ADDED_IN_VERSION(2, 15) + +public: + QQuickEventTabletPoint(QQuickPointerTabletEvent *parent); + + void reset(const QTabletEvent *e); + + qreal rotation() const { return m_rotation; } + qreal pressure() const { return m_pressure; } + qreal tangentialPressure() const { return m_tangentialPressure; } + QVector2D tilt() const { return m_tilt; } + +private: + qreal m_rotation; + qreal m_pressure; + qreal m_tangentialPressure; + QVector2D m_tilt; + + friend class QQuickPointerTouchEvent; + + Q_DISABLE_COPY(QQuickEventTabletPoint) +}; + +class Q_QUICK_PRIVATE_EXPORT QQuickPointerTabletEvent : public QQuickSinglePointEvent +{ + Q_OBJECT +public: + QQuickPointerTabletEvent(QObject *parent, QQuickPointerDevice *device); + + QQuickPointerEvent *reset(QEvent *) override; + bool isPressEvent() const override; + bool isUpdateEvent() const override; + bool isReleaseEvent() const override; + QQuickPointerTabletEvent *asPointerTabletEvent() override { return this; } + const QQuickPointerTabletEvent *asPointerTabletEvent() const override { return this; } + const QQuickEventTabletPoint *tabletPoint() const { return static_cast<QQuickEventTabletPoint *>(m_point); } + + QTabletEvent *asTabletEvent() const; + + Q_DISABLE_COPY(QQuickPointerTabletEvent) +}; +#endif // QT_CONFIG(tabletevent) + #if QT_CONFIG(gestures) class Q_QUICK_PRIVATE_EXPORT QQuickPointerNativeGestureEvent : public QQuickSinglePointEvent { @@ -576,8 +635,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointerNativeGestureEvent : public QQuickSing Q_PROPERTY(qreal value READ value CONSTANT) public: - QQuickPointerNativeGestureEvent(QObject *parent = nullptr, QQuickPointerDevice *device = nullptr) - : QQuickSinglePointEvent(parent, device) { } + QQuickPointerNativeGestureEvent(QObject *parent, QQuickPointerDevice *device); QQuickPointerEvent *reset(QEvent *) override; bool isPressEvent() const override; @@ -603,11 +661,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointerScrollEvent : public QQuickSinglePoint QML_NAMED_ELEMENT(PointerScrollEvent) QML_UNCREATABLE("PointerScrollEvent is only available via the WheelHandler::wheel signal.") - QML_ADDED_IN_MINOR_VERSION(14) + QML_ADDED_IN_VERSION(2, 14) public: - QQuickPointerScrollEvent(QObject *parent = nullptr, QQuickPointerDevice *device = nullptr) - : QQuickSinglePointEvent(parent, device) { } + QQuickPointerScrollEvent(QObject *parent, QQuickPointerDevice *device); QQuickPointerEvent *reset(QEvent *) override; void localize(QQuickItem *target) override; @@ -656,7 +713,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointerDevice : public QObject QML_NAMED_ELEMENT(PointerDevice) QML_UNCREATABLE("PointerDevice is only available as a property of PointerEvent.") - QML_ADDED_IN_MINOR_VERSION(12) + QML_ADDED_IN_VERSION(2, 12) public: enum DeviceType : qint16 { @@ -712,7 +769,9 @@ public: static QQuickPointerDevice *touchDevice(const QTouchDevice *d); static QList<QQuickPointerDevice *> touchDevices(); static QQuickPointerDevice *genericMouseDevice(); - static QQuickPointerDevice *tabletDevice(qint64); +#if QT_CONFIG(tabletevent) + static QQuickPointerDevice *tabletDevice(const QTabletEvent *event); +#endif QVector<QQuickPointerHandler *> &eventDeliveryTargets() { return m_eventDeliveryTargets; } diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index 8ade5b7e37..27c57e147a 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -128,8 +128,13 @@ void QQuickFlickableVisibleArea::updateVisible() // Vertical const qreal viewheight = flickable->height(); const qreal maxyextent = -flickable->maxYExtent() + flickable->minYExtent(); - qreal pagePos = (-p->vData.move.value() + flickable->minYExtent()) / (maxyextent + viewheight); - qreal pageSize = viewheight / (maxyextent + viewheight); + const qreal maxYBounds = maxyextent + viewheight; + qreal pagePos = 0; + qreal pageSize = 0; + if (!qFuzzyIsNull(maxYBounds)) { + pagePos = (-p->vData.move.value() + flickable->minYExtent()) / maxYBounds; + pageSize = viewheight / maxYBounds; + } if (pageSize != m_heightRatio) { m_heightRatio = pageSize; @@ -143,8 +148,14 @@ void QQuickFlickableVisibleArea::updateVisible() // Horizontal const qreal viewwidth = flickable->width(); const qreal maxxextent = -flickable->maxXExtent() + flickable->minXExtent(); - pagePos = (-p->hData.move.value() + flickable->minXExtent()) / (maxxextent + viewwidth); - pageSize = viewwidth / (maxxextent + viewwidth); + const qreal maxXBounds = maxxextent + viewwidth; + if (!qFuzzyIsNull(maxXBounds)) { + pagePos = (-p->hData.move.value() + flickable->minXExtent()) / maxXBounds; + pageSize = viewwidth / maxXBounds; + } else { + pagePos = 0; + pageSize = 0; + } if (pageSize != m_widthRatio) { m_widthRatio = pageSize; diff --git a/src/quick/items/qquickflickable_p.h b/src/quick/items/qquickflickable_p.h index 2d8d4a5e9a..fe74425d57 100644 --- a/src/quick/items/qquickflickable_p.h +++ b/src/quick/items/qquickflickable_p.h @@ -80,7 +80,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickFlickable : public QQuickItem Q_PROPERTY(qreal verticalVelocity READ verticalVelocity NOTIFY verticalVelocityChanged) Q_PROPERTY(BoundsBehavior boundsBehavior READ boundsBehavior WRITE setBoundsBehavior NOTIFY boundsBehaviorChanged) - Q_PROPERTY(BoundsMovement boundsMovement READ boundsMovement WRITE setBoundsMovement NOTIFY boundsMovementChanged REVISION 10) + Q_PROPERTY(BoundsMovement boundsMovement READ boundsMovement WRITE setBoundsMovement NOTIFY boundsMovementChanged REVISION(2, 10)) Q_PROPERTY(QQuickTransition *rebound READ rebound WRITE setRebound NOTIFY reboundChanged) Q_PROPERTY(qreal maximumFlickVelocity READ maximumFlickVelocity WRITE setMaximumFlickVelocity NOTIFY maximumFlickVelocityChanged) Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY flickDecelerationChanged) @@ -106,15 +106,16 @@ class Q_QUICK_PRIVATE_EXPORT QQuickFlickable : public QQuickItem Q_PROPERTY(QQuickFlickableVisibleArea *visibleArea READ visibleArea CONSTANT) Q_PROPERTY(bool pixelAligned READ pixelAligned WRITE setPixelAligned NOTIFY pixelAlignedChanged) - Q_PROPERTY(bool synchronousDrag READ synchronousDrag WRITE setSynchronousDrag NOTIFY synchronousDragChanged REVISION 12) + Q_PROPERTY(bool synchronousDrag READ synchronousDrag WRITE setSynchronousDrag NOTIFY synchronousDragChanged REVISION(2, 12)) - Q_PROPERTY(qreal horizontalOvershoot READ horizontalOvershoot NOTIFY horizontalOvershootChanged REVISION 9) - Q_PROPERTY(qreal verticalOvershoot READ verticalOvershoot NOTIFY verticalOvershootChanged REVISION 9) + Q_PROPERTY(qreal horizontalOvershoot READ horizontalOvershoot NOTIFY horizontalOvershootChanged REVISION(2, 9)) + Q_PROPERTY(qreal verticalOvershoot READ verticalOvershoot NOTIFY verticalOvershootChanged REVISION(2, 9)) Q_PROPERTY(QQmlListProperty<QObject> flickableData READ flickableData) Q_PROPERTY(QQmlListProperty<QQuickItem> flickableChildren READ flickableChildren) Q_CLASSINFO("DefaultProperty", "flickableData") QML_NAMED_ELEMENT(Flickable) + QML_ADDED_IN_VERSION(2, 0) public: QQuickFlickable(QQuickItem *parent=nullptr); @@ -252,7 +253,7 @@ Q_SIGNALS: void flickableDirectionChanged(); void interactiveChanged(); void boundsBehaviorChanged(); - Q_REVISION(10) void boundsMovementChanged(); + Q_REVISION(2, 10) void boundsMovementChanged(); void reboundChanged(); void maximumFlickVelocityChanged(); void flickDecelerationChanged(); @@ -264,11 +265,11 @@ Q_SIGNALS: void dragStarted(); void dragEnded(); void pixelAlignedChanged(); - Q_REVISION(12) void synchronousDragChanged(); - Q_REVISION(9) void horizontalOvershootChanged(); - Q_REVISION(9) void verticalOvershootChanged(); + Q_REVISION(2, 12) void synchronousDragChanged(); + Q_REVISION(2, 9) void horizontalOvershootChanged(); + Q_REVISION(2, 9) void verticalOvershootChanged(); - // The next four signals should be marked as Q_REVISION(12). See QTBUG-71243 + // The next four signals should be marked as Q_REVISION(2, 12). See QTBUG-71243 void atXEndChanged(); void atYEndChanged(); void atXBeginningChanged(); diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h index 1ff55dae90..0d7f27492a 100644 --- a/src/quick/items/qquickflickable_p_p.h +++ b/src/quick/items/qquickflickable_p_p.h @@ -73,7 +73,7 @@ class QQuickFlickableVisibleArea; class QQuickTransition; class QQuickFlickableReboundTransition; -class Q_AUTOTEST_EXPORT QQuickFlickablePrivate : public QQuickItemPrivate, public QQuickItemChangeListener +class Q_QUICK_PRIVATE_EXPORT QQuickFlickablePrivate : public QQuickItemPrivate, public QQuickItemChangeListener { Q_DECLARE_PUBLIC(QQuickFlickable) @@ -285,6 +285,7 @@ class QQuickFlickableVisibleArea : public QObject Q_PROPERTY(qreal widthRatio READ widthRatio NOTIFY widthRatioChanged) Q_PROPERTY(qreal heightRatio READ heightRatio NOTIFY heightRatioChanged) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQuickFlickableVisibleArea(QQuickFlickable *parent=nullptr); diff --git a/src/quick/items/qquickflipable_p.h b/src/quick/items/qquickflipable_p.h index 42c632a33c..8d6716ec53 100644 --- a/src/quick/items/qquickflipable_p.h +++ b/src/quick/items/qquickflipable_p.h @@ -72,6 +72,7 @@ class Q_AUTOTEST_EXPORT QQuickFlipable : public QQuickItem Q_PROPERTY(QQuickItem *back READ back WRITE setBack NOTIFY backChanged) Q_PROPERTY(Side side READ side NOTIFY sideChanged) QML_NAMED_ELEMENT(Flipable) + QML_ADDED_IN_VERSION(2, 0) //### flipAxis //### flipRotation public: diff --git a/src/quick/items/qquickfocusscope_p.h b/src/quick/items/qquickfocusscope_p.h index c32fa93cd9..d3e9197fc7 100644 --- a/src/quick/items/qquickfocusscope_p.h +++ b/src/quick/items/qquickfocusscope_p.h @@ -59,6 +59,7 @@ class Q_AUTOTEST_EXPORT QQuickFocusScope : public QQuickItem { Q_OBJECT QML_NAMED_ELEMENT(FocusScope) + QML_ADDED_IN_VERSION(2, 0) public: QQuickFocusScope(QQuickItem *parent=nullptr); virtual ~QQuickFocusScope(); diff --git a/src/quick/items/qquickgraphicsinfo.cpp b/src/quick/items/qquickgraphicsinfo.cpp index adf620b256..0e711afcf2 100644 --- a/src/quick/items/qquickgraphicsinfo.cpp +++ b/src/quick/items/qquickgraphicsinfo.cpp @@ -40,7 +40,7 @@ #include "qquickgraphicsinfo_p.h" #include "qquickwindow.h" #include "qquickitem.h" -#include <QtGui/qopenglcontext.h> +#include <qopenglcontext.h> QT_BEGIN_NAMESPACE diff --git a/src/quick/items/qquickgraphicsinfo_p.h b/src/quick/items/qquickgraphicsinfo_p.h index aa7d15f72d..c55a35ed5e 100644 --- a/src/quick/items/qquickgraphicsinfo_p.h +++ b/src/quick/items/qquickgraphicsinfo_p.h @@ -76,7 +76,7 @@ class QQuickGraphicsInfo : public QObject Q_PROPERTY(RenderableType renderableType READ renderableType NOTIFY renderableTypeChanged FINAL) QML_NAMED_ELEMENT(GraphicsInfo) - QML_ADDED_IN_MINOR_VERSION(8) + QML_ADDED_IN_VERSION(2, 8) QML_UNCREATABLE("GraphicsInfo is only available via attached properties.") QML_ATTACHED(QQuickGraphicsInfo) diff --git a/src/quick/items/qquickgridview_p.h b/src/quick/items/qquickgridview_p.h index 9072e5f269..7187eb7816 100644 --- a/src/quick/items/qquickgridview_p.h +++ b/src/quick/items/qquickgridview_p.h @@ -74,6 +74,7 @@ class Q_AUTOTEST_EXPORT QQuickGridView : public QQuickItemView Q_CLASSINFO("DefaultProperty", "data") QML_NAMED_ELEMENT(GridView) + QML_ADDED_IN_VERSION(2, 0) QML_ATTACHED(QQuickGridViewAttached) public: diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp index fccacdcce8..1882ec8997 100644 --- a/src/quick/items/qquickimage.cpp +++ b/src/quick/items/qquickimage.cpp @@ -427,10 +427,10 @@ qreal QQuickImage::paintedHeight() const /*! \qmlproperty QSize QtQuick::Image::sourceSize - This property holds the actual width and height of the loaded image. + This property holds the scaled width and height of the full-frame image. Unlike the \l {Item::}{width} and \l {Item::}{height} properties, which scale - the painting of the image, this property sets the actual number of pixels + the painting of the image, this property sets the maximum number of pixels stored for the loaded image so that large images do not use more memory than necessary. For example, this ensures the image in memory is no larger than 1024x1024 pixels, regardless of the Image's \l {Item::}{width} and @@ -455,7 +455,7 @@ qreal QQuickImage::paintedHeight() const other dimension is set in proportion to preserve the source image's aspect ratio. (The \l fillMode is independent of this.) - If both the sourceSize.width and sourceSize.height are set the image will be scaled + If both the sourceSize.width and sourceSize.height are set, the image will be scaled down to fit within the specified size (unless PreserveAspectCrop or PreserveAspectFit are used, then it will be scaled to match the optimal size for cropping/fitting), maintaining the image's aspect ratio. The actual @@ -470,6 +470,9 @@ qreal QQuickImage::paintedHeight() const be no greater than this property specifies. For some formats (currently only JPEG), the whole image will never actually be loaded into memory. + If the \l sourceClipRect property is also set, \c sourceSize determines the scale, + but it will be clipped to the size of the clip rectangle. + sourceSize can be cleared to the natural size of the image by setting sourceSize to \c undefined. @@ -478,6 +481,51 @@ qreal QQuickImage::paintedHeight() const */ /*! + \qmlproperty rect QtQuick::Image::sourceClipRect + \since 5.15 + + This property, if set, holds the rectangular region of the source image to + be loaded. + + The \c sourceClipRect works together with the \l sourceSize property to + conserve system resources when only a portion of an image needs to be + loaded. + + \code + Rectangle { + width: ... + height: ... + + Image { + anchors.fill: parent + source: "reallyBigImage.svg" + sourceSize.width: 1024 + sourceSize.height: 1024 + sourceClipRect: Qt.rect(100, 100, 512, 512) + } + } + \endcode + + In the above example, we conceptually scale the SVG graphic to 1024x1024 + first, and then cut out a region of interest that is 512x512 pixels from a + location 100 pixels from the top and left edges. Thus \c sourceSize + determines the scale, but the actual output image is 512x512 pixels. + + Some image formats are able to conserve CPU time by rendering only the + specified region. Others will need to load the entire image first and then + clip it to the specified region. + + This property can be cleared to reload the entire image by setting + \c sourceClipRect to \c undefined. + + \note \e {Changing this property dynamically causes the image source to be reloaded, + potentially even from the network, if it is not in the disk cache.} + + \note Sub-pixel clipping is not supported: the given rectangle will be + passed to \l QImageReader::setScaledClipRect(). +*/ + +/*! \qmlproperty url QtQuick::Image::source Image can handle any image format supported by Qt, loaded from any URL scheme supported by Qt. diff --git a/src/quick/items/qquickimage_p.h b/src/quick/items/qquickimage_p.h index f7e652cdcc..1119f20e45 100644 --- a/src/quick/items/qquickimage_p.h +++ b/src/quick/items/qquickimage_p.h @@ -66,9 +66,11 @@ class Q_QUICK_PRIVATE_EXPORT QQuickImage : public QQuickImageBase Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedGeometryChanged) Q_PROPERTY(HAlignment horizontalAlignment READ horizontalAlignment WRITE setHorizontalAlignment NOTIFY horizontalAlignmentChanged) Q_PROPERTY(VAlignment verticalAlignment READ verticalAlignment WRITE setVerticalAlignment NOTIFY verticalAlignmentChanged) - Q_PROPERTY(bool mipmap READ mipmap WRITE setMipmap NOTIFY mipmapChanged REVISION 3) - Q_PROPERTY(bool autoTransform READ autoTransform WRITE setAutoTransform NOTIFY autoTransformChanged REVISION 5) + Q_PROPERTY(bool mipmap READ mipmap WRITE setMipmap NOTIFY mipmapChanged REVISION(2, 3)) + Q_PROPERTY(bool autoTransform READ autoTransform WRITE setAutoTransform NOTIFY autoTransformChanged REVISION(2, 5)) + Q_PROPERTY(QRectF sourceClipRect READ sourceClipRect WRITE setSourceClipRect RESET resetSourceClipRect NOTIFY sourceClipRectChanged REVISION(2, 15)) QML_NAMED_ELEMENT(Image) + QML_ADDED_IN_VERSION(2, 0) public: QQuickImage(QQuickItem *parent=nullptr); @@ -113,8 +115,8 @@ Q_SIGNALS: void paintedGeometryChanged(); void horizontalAlignmentChanged(HAlignment alignment); void verticalAlignmentChanged(VAlignment alignment); - Q_REVISION(3) void mipmapChanged(bool); - Q_REVISION(5) void autoTransformChanged(); + Q_REVISION(2, 3) void mipmapChanged(bool); + Q_REVISION(2, 5) void autoTransformChanged(); private Q_SLOTS: void invalidateSceneGraph(); diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp index 55b29d7a70..8849c2005c 100644 --- a/src/quick/items/qquickimagebase.cpp +++ b/src/quick/items/qquickimagebase.cpp @@ -167,6 +167,29 @@ void QQuickImageBase::resetSourceSize() setSourceSize(QSize()); } +QRectF QQuickImageBase::sourceClipRect() const +{ + Q_D(const QQuickImageBase); + return d->sourceClipRect; +} + +void QQuickImageBase::setSourceClipRect(const QRectF &r) +{ + Q_D(QQuickImageBase); + if (d->sourceClipRect == r) + return; + + d->sourceClipRect = r; + emit sourceClipRectChanged(); + if (isComponentComplete()) + load(); +} + +void QQuickImageBase::resetSourceClipRect() +{ + setSourceClipRect(QRect()); +} + bool QQuickImageBase::cache() const { Q_D(const QQuickImageBase); @@ -295,6 +318,7 @@ void QQuickImageBase::loadPixmap(const QUrl &url, LoadPixmapOptions loadOptions) d->pix.load(qmlEngine(this), loadUrl, + d->sourceClipRect.toRect(), (loadOptions & HandleDPR) ? d->sourcesize * d->devicePixelRatio : QSize(), options, (loadOptions & UseProviderOptions) ? d->providerOptions : QQuickImageProviderOptions(), @@ -372,6 +396,10 @@ void QQuickImageBase::requestFinished() d->frameCount = d->pix.frameCount(); emit frameCountChanged(); } + if (d->colorSpace != d->pix.colorSpace()) { + d->colorSpace = d->pix.colorSpace(); + emit colorSpaceChanged(); + } update(); } @@ -464,6 +492,22 @@ void QQuickImageBase::setAutoTransform(bool transform) emitAutoTransformBaseChanged(); } +QColorSpace QQuickImageBase::colorSpace() const +{ + Q_D(const QQuickImageBase); + return d->colorSpace; +} + +void QQuickImageBase::setColorSpace(const QColorSpace &colorSpace) +{ + Q_D(QQuickImageBase); + if (d->colorSpace == colorSpace) + return; + d->colorSpace = colorSpace; + d->providerOptions.setTargetColorSpace(colorSpace); + emit colorSpaceChanged(); +} + QT_END_NAMESPACE #include "moc_qquickimagebase_p.cpp" diff --git a/src/quick/items/qquickimagebase_p.h b/src/quick/items/qquickimagebase_p.h index 9308230bfa..9265792be1 100644 --- a/src/quick/items/qquickimagebase_p.h +++ b/src/quick/items/qquickimagebase_p.h @@ -53,6 +53,7 @@ #include "qquickimplicitsizeitem_p.h" #include <private/qtquickglobal_p.h> +#include <QtGui/qcolorspace.h> QT_BEGIN_NAMESPACE @@ -68,11 +69,12 @@ class Q_QUICK_PRIVATE_EXPORT QQuickImageBase : public QQuickImplicitSizeItem Q_PROPERTY(bool cache READ cache WRITE setCache NOTIFY cacheChanged) Q_PROPERTY(QSize sourceSize READ sourceSize WRITE setSourceSize RESET resetSourceSize NOTIFY sourceSizeChanged) Q_PROPERTY(bool mirror READ mirror WRITE setMirror NOTIFY mirrorChanged) - Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY currentFrameChanged REVISION 14) - Q_PROPERTY(int frameCount READ frameCount NOTIFY frameCountChanged REVISION 14) + Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY currentFrameChanged REVISION(2, 14)) + Q_PROPERTY(int frameCount READ frameCount NOTIFY frameCountChanged REVISION(2, 14)) + Q_PROPERTY(QColorSpace colorSpace READ colorSpace WRITE setColorSpace NOTIFY colorSpaceChanged REVISION(2, 15)) QML_NAMED_ELEMENT(ImageBase); - QML_ADDED_IN_MINOR_VERSION(14) + QML_ADDED_IN_VERSION(2, 14) QML_UNCREATABLE("ImageBase is an abstract base class.") public: @@ -107,6 +109,10 @@ public: QSize sourceSize() const; void resetSourceSize(); + QRectF sourceClipRect() const; + void setSourceClipRect(const QRectF &r); + void resetSourceClipRect(); + virtual void setMirror(bool mirror); bool mirror() const; @@ -118,6 +124,9 @@ public: virtual void setAutoTransform(bool transform); bool autoTransform() const; + QColorSpace colorSpace() const; + virtual void setColorSpace(const QColorSpace &colorSpace); + static void resolve2xLocalFile(const QUrl &url, qreal targetDevicePixelRatio, QUrl *sourceUrl, qreal *sourceDevicePixelRatio); // Use a virtual rather than a signal->signal to avoid the huge @@ -132,8 +141,10 @@ Q_SIGNALS: void asynchronousChanged(); void cacheChanged(); void mirrorChanged(); - Q_REVISION(14) void currentFrameChanged(); - Q_REVISION(14) void frameCountChanged(); + Q_REVISION(2, 14) void currentFrameChanged(); + Q_REVISION(2, 14) void frameCountChanged(); + Q_REVISION(2, 15) void sourceClipRectChanged(); + Q_REVISION(2, 15) void colorSpaceChanged(); protected: void loadEmptyUrl(); diff --git a/src/quick/items/qquickimagebase_p_p.h b/src/quick/items/qquickimagebase_p_p.h index 88e18ba32e..ebb7568caf 100644 --- a/src/quick/items/qquickimagebase_p_p.h +++ b/src/quick/items/qquickimagebase_p_p.h @@ -86,7 +86,9 @@ public: QSize sourcesize; QSize oldSourceSize; qreal devicePixelRatio; + QRectF sourceClipRect; QQuickImageProviderOptions providerOptions; + QColorSpace colorSpace; int currentFrame; int frameCount; bool async : 1; diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 03cdeb5bef..4d9e3de859 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -2569,6 +2569,7 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo bool skip = false; QQuickItem *startItem = item; + QQuickItem *originalStartItem = startItem; // Protect from endless loop: // If we start on an invisible item we will not find it again. // If there is no other item which can become the focus item, we have a forever loop, @@ -2644,7 +2645,12 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo } } from = last; - if (current == startItem && from == firstFromItem) { + // if [from] item is equal to [firstFromItem], means we have traversed one path and + // jump back to parent of the chain, and then we have to check whether we have + // traversed all of the chain (by compare the [current] item with [startItem]) + // Since the [startItem] might be promoted to its parent if it is invisible, + // we still have to check [current] item with original start item + if ((current == startItem || current == originalStartItem) && from == firstFromItem) { // wrapped around, avoid endless loops if (item == contentItem) { qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return contentItem"; @@ -3244,6 +3250,7 @@ QQuickItemPrivate::QQuickItemPrivate() #else , touchEnabled(false) #endif + , hasCursorHandler(false) , dirtyAttributes(0) , nextDirtyItem(nullptr) , prevDirtyItem(nullptr) @@ -7472,14 +7479,14 @@ void QQuickItem::setAcceptTouchEvents(bool enabled) d->touchEnabled = enabled; } -void QQuickItemPrivate::setHasCursorInChild(bool hasCursor) +void QQuickItemPrivate::setHasCursorInChild(bool hc) { #if QT_CONFIG(cursor) Q_Q(QQuickItem); // if we're asked to turn it off (because of an unsetcursor call, or a node // removal) then we should make sure it's really ok to turn it off. - if (!hasCursor && subtreeCursorEnabled) { + if (!hc && subtreeCursorEnabled) { if (hasCursor) return; // nope! sorry, I have a cursor myself for (QQuickItem *otherChild : qAsConst(childItems)) { @@ -7489,14 +7496,14 @@ void QQuickItemPrivate::setHasCursorInChild(bool hasCursor) } } - subtreeCursorEnabled = hasCursor; + subtreeCursorEnabled = hc; QQuickItem *parent = q->parentItem(); if (parent) { QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(parent); - parentPrivate->setHasCursorInChild(hasCursor); + parentPrivate->setHasCursorInChild(hc); } #else - Q_UNUSED(hasCursor); + Q_UNUSED(hc); #endif } @@ -7573,17 +7580,20 @@ void QQuickItem::setCursor(const QCursor &cursor) } } + QPointF updateCursorPos; if (!d->hasCursor) { - d->setHasCursorInChild(true); d->hasCursor = true; if (d->window) { QWindow *renderWindow = QQuickRenderControl::renderWindowFor(d->window); QWindow *window = renderWindow ? renderWindow : d->window; QPointF pos = window->mapFromGlobal(QGuiApplicationPrivate::lastCursorPosition.toPoint()); if (contains(mapFromScene(pos))) - QQuickWindowPrivate::get(d->window)->updateCursor(pos); + updateCursorPos = pos; } } + d->setHasCursorInChild(d->hasCursor || d->hasCursorHandler); + if (!updateCursorPos.isNull()) + QQuickWindowPrivate::get(d->window)->updateCursor(updateCursorPos); } /*! @@ -7597,8 +7607,8 @@ void QQuickItem::unsetCursor() Q_D(QQuickItem); if (!d->hasCursor) return; - d->setHasCursorInChild(false); d->hasCursor = false; + d->setHasCursorInChild(d->hasCursorHandler); if (d->extra.isAllocated()) d->extra->cursor = QCursor(); @@ -7611,6 +7621,64 @@ void QQuickItem::unsetCursor() } } +/*! + \internal + Returns the cursor that should actually be shown, allowing the given + \handler to override the Item cursor if it is active or hovered. + + \sa cursor(), setCursor(), QtQuick::PointerHandler::cursor +*/ +QCursor QQuickItemPrivate::effectiveCursor(const QQuickPointerHandler *handler) const +{ + Q_Q(const QQuickItem); + if (!handler) + return q->cursor(); + bool hoverCursorSet = false; + QCursor hoverCursor; + bool activeCursorSet = false; + QCursor activeCursor; + if (const QQuickHoverHandler *hoverHandler = qobject_cast<const QQuickHoverHandler *>(handler)) { + hoverCursorSet = hoverHandler->isCursorShapeExplicitlySet(); + hoverCursor = hoverHandler->cursorShape(); + } else if (handler->active()) { + activeCursorSet = handler->isCursorShapeExplicitlySet(); + activeCursor = handler->cursorShape(); + } + if (activeCursorSet) + return activeCursor; + if (hoverCursorSet) + return hoverCursor; + return q->cursor(); +} + +/*! + \internal + Returns the Pointer Handler that is currently attempting to set the cursor shape, + or null if there is no such handler. + + \sa QtQuick::PointerHandler::cursor +*/ +QQuickPointerHandler *QQuickItemPrivate::effectiveCursorHandler() const +{ + if (!hasPointerHandlers()) + return nullptr; + QQuickPointerHandler *retHoverHandler = nullptr; + for (QQuickPointerHandler *h : extra->pointerHandlers) { + if (!h->isCursorShapeExplicitlySet()) + continue; + QQuickHoverHandler *hoverHandler = qmlobject_cast<QQuickHoverHandler *>(h); + // For now, we don't expect multiple hover handlers in one Item, so we choose the first one found; + // but a future use case could be to have different cursors for different tablet stylus devices. + // In that case, this function needs more information: which device did the event come from. + // TODO Qt 6: add QPointerDevice* as argument to this function? (it doesn't exist yet in Qt 5) + if (!retHoverHandler && hoverHandler) + retHoverHandler = hoverHandler; + if (!hoverHandler && h->active()) + return h; + } + return retHoverHandler; +} + #endif /*! @@ -8192,6 +8260,10 @@ bool QQuickItem::event(QEvent *ev) ev->ignore(); break; #endif // gestures + case QEvent::LanguageChange: + for (QQuickItem *item : d->childItems) + QCoreApplication::sendEvent(item, ev); + break; default: return QObject::event(ev); } diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h index 8c04ced11b..ca0c2f4764 100644 --- a/src/quick/items/qquickitem.h +++ b/src/quick/items/qquickitem.h @@ -59,6 +59,7 @@ class Q_QUICK_EXPORT QQuickTransform : public QObject { Q_OBJECT QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickTransform(QObject *parent = nullptr); ~QQuickTransform() override; @@ -133,7 +134,7 @@ class Q_QUICK_EXPORT QQuickItem : public QObject, public QQmlParserStatus Q_PROPERTY(bool focus READ hasFocus WRITE setFocus NOTIFY focusChanged FINAL) Q_PROPERTY(bool activeFocus READ hasActiveFocus NOTIFY activeFocusChanged FINAL) - Q_PROPERTY(bool activeFocusOnTab READ activeFocusOnTab WRITE setActiveFocusOnTab NOTIFY activeFocusOnTabChanged FINAL REVISION 1) + Q_PROPERTY(bool activeFocusOnTab READ activeFocusOnTab WRITE setActiveFocusOnTab NOTIFY activeFocusOnTabChanged FINAL REVISION(2, 1)) Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged) Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged) @@ -145,13 +146,14 @@ class Q_QUICK_EXPORT QQuickItem : public QObject, public QQmlParserStatus Q_PROPERTY(bool antialiasing READ antialiasing WRITE setAntialiasing NOTIFY antialiasingChanged RESET resetAntialiasing) Q_PROPERTY(qreal implicitWidth READ implicitWidth WRITE setImplicitWidth NOTIFY implicitWidthChanged) Q_PROPERTY(qreal implicitHeight READ implicitHeight WRITE setImplicitHeight NOTIFY implicitHeightChanged) - Q_PROPERTY(QObject *containmentMask READ containmentMask WRITE setContainmentMask NOTIFY containmentMaskChanged REVISION 11) + Q_PROPERTY(QObject *containmentMask READ containmentMask WRITE setContainmentMask NOTIFY containmentMaskChanged REVISION(2, 11)) Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickItemLayer *layer READ layer DESIGNABLE false CONSTANT FINAL) Q_CLASSINFO("DefaultProperty", "data") Q_CLASSINFO("qt_QmlJSWrapperFactoryMethod", "_q_createJSWrapper(QV4::ExecutionEngine*)") QML_NAMED_ELEMENT(Item) + QML_ADDED_IN_VERSION(2, 0) public: enum Flag { @@ -320,7 +322,7 @@ public: void setKeepTouchGrab(bool); // implemented in qquickitemgrabresult.cpp - Q_REVISION(4) Q_INVOKABLE bool grabToImage(const QJSValue &callback, const QSize &targetSize = QSize()); + Q_REVISION(2, 4) Q_INVOKABLE bool grabToImage(const QJSValue &callback, const QSize &targetSize = QSize()); QSharedPointer<QQuickItemGrabResult> grabToImage(const QSize &targetSize = QSize()); Q_INVOKABLE virtual bool contains(const QPointF &point) const; @@ -343,11 +345,11 @@ public: Q_INVOKABLE void mapFromItem(QQmlV4Function*) const; Q_INVOKABLE void mapToItem(QQmlV4Function*) const; - Q_REVISION(7) Q_INVOKABLE void mapFromGlobal(QQmlV4Function*) const; - Q_REVISION(7) Q_INVOKABLE void mapToGlobal(QQmlV4Function*) const; + Q_REVISION(2, 7) Q_INVOKABLE void mapFromGlobal(QQmlV4Function*) const; + Q_REVISION(2, 7) Q_INVOKABLE void mapToGlobal(QQmlV4Function*) const; Q_INVOKABLE void forceActiveFocus(); Q_INVOKABLE void forceActiveFocus(Qt::FocusReason reason); - Q_REVISION(1) Q_INVOKABLE QQuickItem *nextItemInFocusChain(bool forward = true); + Q_REVISION(2, 1) Q_INVOKABLE QQuickItem *nextItemInFocusChain(bool forward = true); Q_INVOKABLE QQuickItem *childAt(qreal x, qreal y) const; #if QT_CONFIG(im) @@ -373,13 +375,13 @@ Q_SIGNALS: void stateChanged(const QString &); void focusChanged(bool); void activeFocusChanged(bool); - Q_REVISION(1) void activeFocusOnTabChanged(bool); + Q_REVISION(2, 1) void activeFocusOnTabChanged(bool); void parentChanged(QQuickItem *); void transformOriginChanged(TransformOrigin); void smoothChanged(bool); void antialiasingChanged(bool); void clipChanged(bool); - Q_REVISION(1) void windowChanged(QQuickWindow* window); + Q_REVISION(2, 1) void windowChanged(QQuickWindow* window); void childrenChanged(); void opacityChanged(); @@ -396,7 +398,7 @@ Q_SIGNALS: void zChanged(); void implicitWidthChanged(); void implicitHeightChanged(); - Q_REVISION(11) void containmentMaskChanged(); + Q_REVISION(2, 11) void containmentMaskChanged(); protected: bool event(QEvent *) override; diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 3c0517cb3b..a8958dfd59 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -153,6 +153,7 @@ class QQuickItemLayer : public QObject, public QQuickItemChangeListener Q_PROPERTY(QQuickShaderEffectSource::TextureMirroring textureMirroring READ textureMirroring WRITE setTextureMirroring NOTIFY textureMirroringChanged) Q_PROPERTY(int samples READ samples WRITE setSamples NOTIFY samplesChanged) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQuickItemLayer(QQuickItem *item); @@ -471,6 +472,7 @@ public: bool isTabFence:1; bool replayingPressEvent:1; bool touchEnabled:1; + bool hasCursorHandler:1; enum DirtyType { TransformOrigin = 0x00000001, @@ -651,6 +653,10 @@ public: void setHasCursorInChild(bool hasCursor); void setHasHoverInChild(bool hasHover); +#if QT_CONFIG(cursor) + QCursor effectiveCursor(const QQuickPointerHandler *handler) const; + QQuickPointerHandler *effectiveCursorHandler() const; +#endif virtual void updatePolish() { } }; @@ -717,6 +723,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickKeyNavigationAttached : public QObject, publi Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged) QML_NAMED_ELEMENT(KeyNavigation) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("KeyNavigation is only available via attached properties.") QML_ATTACHED(QQuickKeyNavigationAttached) @@ -766,6 +773,7 @@ class QQuickLayoutMirroringAttached : public QObject Q_PROPERTY(bool childrenInherit READ childrenInherit WRITE setChildrenInherit NOTIFY childrenInheritChanged) QML_NAMED_ELEMENT(LayoutMirroring) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("LayoutMirroring is only available via attached properties.") QML_ATTACHED(QQuickLayoutMirroringAttached) @@ -795,7 +803,7 @@ class QQuickEnterKeyAttached : public QObject QML_NAMED_ELEMENT(EnterKey) QML_UNCREATABLE("EnterKey is only available via attached properties") - QML_ADDED_IN_MINOR_VERSION(6) + QML_ADDED_IN_VERSION(2, 6) QML_ATTACHED(QQuickEnterKeyAttached) public: @@ -844,6 +852,7 @@ class QQuickKeysAttached : public QObject, public QQuickItemKeyFilter Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged) QML_NAMED_ELEMENT(Keys) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("Keys is only available via attached properties") QML_ATTACHED(QQuickKeysAttached) diff --git a/src/quick/items/qquickitemanimation_p.h b/src/quick/items/qquickitemanimation_p.h index 28c18c874d..ee4df1b6ca 100644 --- a/src/quick/items/qquickitemanimation_p.h +++ b/src/quick/items/qquickitemanimation_p.h @@ -67,6 +67,7 @@ class Q_AUTOTEST_EXPORT QQuickParentAnimation : public QQuickAnimationGroup Q_PROPERTY(QQuickItem *newParent READ newParent WRITE setNewParent NOTIFY newParentChanged) Q_PROPERTY(QQuickItem *via READ via WRITE setVia NOTIFY viaChanged) QML_NAMED_ELEMENT(ParentAnimation) + QML_ADDED_IN_VERSION(2, 0) public: QQuickParentAnimation(QObject *parent=nullptr); @@ -102,6 +103,7 @@ class Q_AUTOTEST_EXPORT QQuickAnchorAnimation : public QQuickAbstractAnimation Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged) Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged) QML_NAMED_ELEMENT(AnchorAnimation) + QML_ADDED_IN_VERSION(2, 0) public: QQuickAnchorAnimation(QObject *parent=nullptr); @@ -146,6 +148,7 @@ class Q_AUTOTEST_EXPORT QQuickPathAnimation : public QQuickAbstractAnimation Q_PROPERTY(int orientationExitDuration READ orientationExitDuration WRITE setOrientationExitDuration NOTIFY orientationExitDurationChanged) Q_PROPERTY(qreal endRotation READ endRotation WRITE setEndRotation NOTIFY endRotationChanged) QML_NAMED_ELEMENT(PathAnimation) + QML_ADDED_IN_VERSION(2, 0) public: QQuickPathAnimation(QObject *parent=nullptr); diff --git a/src/quick/items/qquickitemgrabresult.cpp b/src/quick/items/qquickitemgrabresult.cpp index f298803c7f..00e84536e9 100644 --- a/src/quick/items/qquickitemgrabresult.cpp +++ b/src/quick/items/qquickitemgrabresult.cpp @@ -195,6 +195,7 @@ bool QQuickItemGrabResult::saveToFile(const QString &fileName) const } #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +#if QT_DEPRECATED_SINCE(5, 15) /*! * \overload * \internal @@ -203,6 +204,7 @@ bool QQuickItemGrabResult::saveToFile(const QString &fileName) { return qAsConst(*this).saveToFile(fileName); } +#endif #endif // < Qt 6 QUrl QQuickItemGrabResult::url() const diff --git a/src/quick/items/qquickitemgrabresult.h b/src/quick/items/qquickitemgrabresult.h index c92a8c52f4..96d18b907b 100644 --- a/src/quick/items/qquickitemgrabresult.h +++ b/src/quick/items/qquickitemgrabresult.h @@ -62,13 +62,17 @@ class Q_QUICK_EXPORT QQuickItemGrabResult : public QObject Q_PROPERTY(QImage image READ image CONSTANT) Q_PROPERTY(QUrl url READ url CONSTANT) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QImage image() const; QUrl url() const; #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - Q_INVOKABLE bool saveToFile(const QString &fileName); // ### Qt 6: remove +#if QT_DEPRECATED_SINCE(5, 15) + QT_DEPRECATED_X("This overload is deprecated. Use the const member function instead") + Q_INVOKABLE bool saveToFile(const QString &fileName); +#endif #endif Q_INVOKABLE bool saveToFile(const QString &fileName) const; diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index bd6b9d741e..125518e51b 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -183,13 +183,6 @@ static void qt_quickitems_defineModule() qRegisterMetaType<QQuickAnchorLine>("QQuickAnchorLine"); qRegisterMetaType<QPointingDeviceUniqueId>("QPointingDeviceUniqueId"); qRegisterMetaType<QQuickHandlerPoint>(); - -#if !QT_CONFIG(quick_animatedimage) - qmlRegisterTypeNotAvailable( - "QtQuick", 2, 15, "AnimatedImage", - QCoreApplication::translate("QQuickAnimatedImage", - "Qt was built without support for QMovie")); -#endif } static void initResources() diff --git a/src/quick/items/qquickitemsmodule_p.h b/src/quick/items/qquickitemsmodule_p.h index 6ceb0d56e6..f7081f6ece 100644 --- a/src/quick/items/qquickitemsmodule_p.h +++ b/src/quick/items/qquickitemsmodule_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <private/qtquickglobal_p.h> #include <QtGui/qevent.h> #include <qqml.h> @@ -67,10 +68,21 @@ struct QPointingDeviceUniqueIdForeign Q_GADGET QML_FOREIGN(QPointingDeviceUniqueId) QML_NAMED_ELEMENT(PointingDeviceUniqueId) - QML_ADDED_IN_MINOR_VERSION(9) + QML_ADDED_IN_VERSION(2, 9) QML_UNCREATABLE("PointingDeviceUniqueId is only available via read-only properties.") }; +#if !QT_CONFIG(quick_animatedimage) +struct QQuickAnimatedImageNotAvailable +{ + Q_GADGET + QML_UNAVAILABLE + QML_NAMED_ELEMENT(AnimatedImage) + QML_ADDED_IN_VERSION(2, 0) + QML_UNCREATABLE("Qt was built without support for QMovie.") +}; +#endif + QT_END_NAMESPACE #endif // QQUICKITEMSMODULE_P_H diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index 0d30606ef7..7fb392233e 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -197,8 +197,10 @@ void QQuickItemView::setModel(const QVariant &m) disconnect(d->model, SIGNAL(initItem(int,QObject*)), this, SLOT(initItem(int,QObject*))); disconnect(d->model, SIGNAL(createdItem(int,QObject*)), this, SLOT(createdItem(int,QObject*))); disconnect(d->model, SIGNAL(destroyingItem(QObject*)), this, SLOT(destroyingItem(QObject*))); - disconnect(d->model, SIGNAL(itemPooled(int, QObject *)), this, SLOT(onItemPooled(int, QObject *))); - disconnect(d->model, SIGNAL(itemReused(int, QObject *)), this, SLOT(onItemReused(int, QObject *))); + if (QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel*>(d->model)) { + disconnect(delegateModel, SIGNAL(itemPooled(int, QObject *)), this, SLOT(onItemPooled(int, QObject *))); + disconnect(delegateModel, SIGNAL(itemReused(int, QObject *)), this, SLOT(onItemReused(int, QObject *))); + } } QQmlInstanceModel *oldModel = d->model; @@ -234,8 +236,10 @@ void QQuickItemView::setModel(const QVariant &m) connect(d->model, SIGNAL(createdItem(int,QObject*)), this, SLOT(createdItem(int,QObject*))); connect(d->model, SIGNAL(initItem(int,QObject*)), this, SLOT(initItem(int,QObject*))); connect(d->model, SIGNAL(destroyingItem(QObject*)), this, SLOT(destroyingItem(QObject*))); - connect(d->model, SIGNAL(itemPooled(int, QObject *)), this, SLOT(onItemPooled(int, QObject *))); - connect(d->model, SIGNAL(itemReused(int, QObject *)), this, SLOT(onItemReused(int, QObject *))); + if (QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel*>(d->model)) { + connect(delegateModel, SIGNAL(itemPooled(int, QObject *)), this, SLOT(onItemPooled(int, QObject *))); + connect(delegateModel, SIGNAL(itemReused(int, QObject *)), this, SLOT(onItemReused(int, QObject *))); + } if (isComponentComplete()) { d->updateSectionCriteria(); d->refill(); diff --git a/src/quick/items/qquickitemview_p.h b/src/quick/items/qquickitemview_p.h index 521580d292..d8d5678ad0 100644 --- a/src/quick/items/qquickitemview_p.h +++ b/src/quick/items/qquickitemview_p.h @@ -79,10 +79,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickItemView : public QQuickFlickable Q_PROPERTY(QQuickItem *currentItem READ currentItem NOTIFY currentItemChanged) Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled NOTIFY keyNavigationWrapsChanged) - Q_PROPERTY(bool keyNavigationEnabled READ isKeyNavigationEnabled WRITE setKeyNavigationEnabled NOTIFY keyNavigationEnabledChanged REVISION 7) + Q_PROPERTY(bool keyNavigationEnabled READ isKeyNavigationEnabled WRITE setKeyNavigationEnabled NOTIFY keyNavigationEnabledChanged REVISION(2, 7)) Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged) - Q_PROPERTY(int displayMarginBeginning READ displayMarginBeginning WRITE setDisplayMarginBeginning NOTIFY displayMarginBeginningChanged REVISION 3) - Q_PROPERTY(int displayMarginEnd READ displayMarginEnd WRITE setDisplayMarginEnd NOTIFY displayMarginEndChanged REVISION 3) + Q_PROPERTY(int displayMarginBeginning READ displayMarginBeginning WRITE setDisplayMarginBeginning NOTIFY displayMarginBeginningChanged REVISION(2, 3)) + Q_PROPERTY(int displayMarginEnd READ displayMarginEnd WRITE setDisplayMarginEnd NOTIFY displayMarginEndChanged REVISION(2, 3)) Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged) Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged) @@ -110,11 +110,11 @@ class Q_QUICK_PRIVATE_EXPORT QQuickItemView : public QQuickFlickable Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged RESET resetPreferredHighlightEnd) Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged) - Q_PROPERTY(bool reuseItems READ reuseItems WRITE setReuseItems NOTIFY reuseItemsChanged REVISION 15) + Q_PROPERTY(bool reuseItems READ reuseItems WRITE setReuseItems NOTIFY reuseItemsChanged REVISION(2, 15)) QML_NAMED_ELEMENT(ItemView) QML_UNCREATABLE("ItemView is an abstract base class.") - QML_ADDED_IN_MINOR_VERSION(1) + QML_ADDED_IN_VERSION(2, 1) public: // this holds all layout enum values so they can be referred to by other enums @@ -237,10 +237,10 @@ public: Q_INVOKABLE void positionViewAtIndex(int index, int mode); Q_INVOKABLE int indexAt(qreal x, qreal y) const; Q_INVOKABLE QQuickItem *itemAt(qreal x, qreal y) const; - Q_REVISION(13) Q_INVOKABLE QQuickItem *itemAtIndex(int index) const; + Q_REVISION(2, 13) Q_INVOKABLE QQuickItem *itemAtIndex(int index) const; Q_INVOKABLE void positionViewAtBeginning(); Q_INVOKABLE void positionViewAtEnd(); - Q_REVISION(1) Q_INVOKABLE void forceLayout(); + Q_REVISION(2, 1) Q_INVOKABLE void forceLayout(); void setContentX(qreal pos) override; void setContentY(qreal pos) override; @@ -255,7 +255,7 @@ Q_SIGNALS: void currentItemChanged(); void keyNavigationWrapsChanged(); - Q_REVISION(7) void keyNavigationEnabledChanged(); + Q_REVISION(2, 7) void keyNavigationEnabledChanged(); void cacheBufferChanged(); void displayMarginBeginningChanged(); void displayMarginEndChanged(); @@ -286,7 +286,7 @@ Q_SIGNALS: void preferredHighlightEndChanged(); void highlightMoveDurationChanged(); - Q_REVISION(15) void reuseItemsChanged(); + Q_REVISION(2, 15) void reuseItemsChanged(); protected: void updatePolish() override; @@ -303,8 +303,8 @@ protected Q_SLOTS: virtual void initItem(int index, QObject *item); void modelUpdated(const QQmlChangeSet &changeSet, bool reset); void destroyingItem(QObject *item); - void onItemPooled(int modelIndex, QObject *object); - void onItemReused(int modelIndex, QObject *object); + Q_REVISION(2, 15) void onItemPooled(int modelIndex, QObject *object); + Q_REVISION(2, 15) void onItemReused(int modelIndex, QObject *object); void animStopped(); void trackedPositionChanged(); diff --git a/src/quick/items/qquickitemviewtransition_p.h b/src/quick/items/qquickitemviewtransition_p.h index 5f4e74171e..43858db688 100644 --- a/src/quick/items/qquickitemviewtransition_p.h +++ b/src/quick/items/qquickitemviewtransition_p.h @@ -195,6 +195,7 @@ class QQuickViewTransitionAttached : public QObject Q_PROPERTY(QQmlListProperty<QObject> targetItems READ targetItems NOTIFY targetItemsChanged) QML_NAMED_ELEMENT(ViewTransition) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("ViewTransition is only available via attached properties.") QML_ATTACHED(QQuickViewTransitionAttached) diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index badd2efe29..b91e705ad0 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -141,6 +141,8 @@ public: QQuickItemViewAttached *getAttachedObject(const QObject *object) const override; + void fixupHeader(); + void fixupHeaderCompleted(); QQuickListView::Orientation orient; qreal visiblePos; qreal averageSize; @@ -169,6 +171,12 @@ public: QString nextSection; qreal overshootDist; + + qreal desiredViewportPosition; + qreal fixupHeaderPosition; + bool headerNeedsSeparateFixup : 1; + bool desiredHeaderVisible : 1; + bool correctFlick : 1; bool inFlickCorrection : 1; @@ -182,7 +190,9 @@ public: , highlightPosAnimator(nullptr), highlightWidthAnimator(nullptr), highlightHeightAnimator(nullptr) , highlightMoveVelocity(400), highlightResizeVelocity(400), highlightResizeDuration(-1) , sectionCriteria(nullptr), currentSectionItem(nullptr), nextSectionItem(nullptr) - , overshootDist(0.0), correctFlick(false), inFlickCorrection(false) + , overshootDist(0.0), desiredViewportPosition(0.0), fixupHeaderPosition(0.0) + , headerNeedsSeparateFixup(false), desiredHeaderVisible(false) + , correctFlick(false), inFlickCorrection(false) { highlightMoveDuration = -1; //override default value set in base class } @@ -1402,6 +1412,31 @@ void QQuickListViewPrivate::updateFooter() emit q->footerItemChanged(); } +void QQuickListViewPrivate::fixupHeaderCompleted() +{ + headerNeedsSeparateFixup = false; + QObjectPrivate::disconnect(&timeline, &QQuickTimeLine::updated, this, &QQuickListViewPrivate::fixupHeader); +} + +void QQuickListViewPrivate::fixupHeader() +{ + FxListItemSG *listItem = static_cast<FxListItemSG*>(header); + const bool fixingUp = (orient == QQuickListView::Vertical ? vData : hData).fixingUp; + if (fixingUp && headerPositioning == QQuickListView::PullBackHeader && visibleItems.count()) { + int fixupDura = timeline.duration(); + if (fixupDura < 0) + fixupDura = fixupDuration/2; + const int t = timeline.time(); + + const qreal progress = qreal(t)/fixupDura; + const qreal ultimateHeaderPosition = desiredHeaderVisible ? desiredViewportPosition : desiredViewportPosition - headerSize(); + const qreal headerPosition = fixupHeaderPosition * (1 - progress) + ultimateHeaderPosition * progress; + const qreal viewPos = isContentFlowReversed() ? -position() - size() : position(); + const qreal clampedPos = qBound(originPosition() - headerSize(), headerPosition, lastPosition() - size()); + listItem->setPosition(qBound(viewPos - headerSize(), clampedPos, viewPos)); + } +} + void QQuickListViewPrivate::updateHeader() { Q_Q(QQuickListView); @@ -1419,9 +1454,14 @@ void QQuickListViewPrivate::updateHeader() if (headerPositioning == QQuickListView::OverlayHeader) { listItem->setPosition(isContentFlowReversed() ? -position() - size() : position()); } else if (visibleItems.count()) { + const bool fixingUp = (orient == QQuickListView::Vertical ? vData : hData).fixingUp; if (headerPositioning == QQuickListView::PullBackHeader) { - qreal viewPos = isContentFlowReversed() ? -position() - size() : position(); - qreal clampedPos = qBound(originPosition() - headerSize(), listItem->position(), lastPosition() - headerSize() - size()); + qreal headerPosition = listItem->position(); + const qreal viewPos = isContentFlowReversed() ? -position() - size() : position(); + // Make sure the header is not shown if we absolutely do not have any plans to show it + if (fixingUp && !headerNeedsSeparateFixup) + headerPosition = viewPos - headerSize(); + qreal clampedPos = qBound(originPosition() - headerSize(), headerPosition, lastPosition() - size()); listItem->setPosition(qBound(viewPos - headerSize(), clampedPos, viewPos)); } else { qreal startPos = originPosition(); @@ -1539,13 +1579,46 @@ void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte bias = -bias; tempPosition -= bias; } - FxViewItem *topItem = snapItemAt(tempPosition+highlightRangeStart); + + qreal snapOffset = 0; + qreal overlayHeaderOffset = 0; + bool isHeaderWithinBounds = false; + if (header) { + qreal visiblePartOfHeader = header->position() + header->size() - tempPosition; + isHeaderWithinBounds = visiblePartOfHeader > 0; + switch (headerPositioning) { + case QQuickListView::OverlayHeader: + snapOffset = header->size(); + overlayHeaderOffset = header->size(); + break; + case QQuickListView::InlineHeader: + if (isHeaderWithinBounds && tempPosition < originPosition()) + // For the inline header, we want to snap to the first item + // if we're more than halfway down the inline header. + // So if we look for an item halfway down of the header + snapOffset = header->size() / 2; + break; + case QQuickListView::PullBackHeader: + desiredHeaderVisible = visiblePartOfHeader > header->size()/2; + if (qFuzzyCompare(header->position(), tempPosition)) { + // header was pulled down; make sure it remains visible and snap items to bottom of header + snapOffset = header->size(); + } else if (desiredHeaderVisible) { + // More than 50% of the header is shown. Show it fully. + // Scroll the view so the next item snaps to the header. + snapOffset = header->size(); + overlayHeaderOffset = header->size(); + } + break; + } + } + FxViewItem *topItem = snapItemAt(tempPosition + snapOffset + highlightRangeStart); if (strictHighlightRange && currentItem && (!topItem || (topItem->index != currentIndex && fixupMode == Immediate))) { // StrictlyEnforceRange always keeps an item in range updateHighlight(); topItem = currentItem; } - FxViewItem *bottomItem = snapItemAt(tempPosition+highlightRangeEnd); + FxViewItem *bottomItem = snapItemAt(tempPosition + snapOffset + highlightRangeEnd); if (strictHighlightRange && currentItem && (!bottomItem || (bottomItem->index != currentIndex && fixupMode == Immediate))) { // StrictlyEnforceRange always keeps an item in range updateHighlight(); @@ -1553,27 +1626,92 @@ void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte } qreal pos; bool isInBounds = -position() > maxExtent && -position() <= minExtent; - if (topItem && (isInBounds || strictHighlightRange)) { - if (topItem->index == 0 && header && tempPosition+highlightRangeStart < header->position()+header->size()/2 && !strictHighlightRange) { - pos = isContentFlowReversed() ? - header->position() + highlightRangeStart - size() : header->position() - highlightRangeStart; + + if (header && !topItem && isInBounds) { + // We are trying to pull back further than needed + switch (headerPositioning) { + case QQuickListView::OverlayHeader: + pos = startPosition() - overlayHeaderOffset; + break; + case QQuickListView::InlineHeader: + pos = isContentFlowReversed() ? header->size() - size() : header->position(); + break; + case QQuickListView::PullBackHeader: + pos = isContentFlowReversed() ? -size() : startPosition(); + break; + } + } else if (topItem && (isInBounds || strictHighlightRange)) { + if (topItem->index == 0 && header && !hasStickyHeader() && tempPosition+highlightRangeStart < header->position()+header->size()/2 && !strictHighlightRange) { + pos = isContentFlowReversed() ? -header->position() + highlightRangeStart - size() : (header->position() - highlightRangeStart + header->size()); } else { - if (isContentFlowReversed()) - pos = qMax(qMin(-static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size(), -maxExtent), -minExtent); - else - pos = qMax(qMin(static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart, -maxExtent), -minExtent); + if (header && headerPositioning == QQuickListView::PullBackHeader) { + // We pulled down the header. If it isn't pulled all way down, we need to snap + // the header. + if (qFuzzyCompare(tempPosition, header->position())) { + // It is pulled all way down. Scroll-snap the content, but not the header. + if (isContentFlowReversed()) + pos = -static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size() + snapOffset; + else + pos = static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart - snapOffset; + } else { + // Header is not pulled all way down, make it completely visible or hide it. + // Depends on how much of the header is visible. + if (desiredHeaderVisible) { + // More than half of the header is visible - show it. + // Scroll so that the topItem is aligned to a fully visible header + if (isContentFlowReversed()) + pos = -static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size() + headerSize(); + else + pos = static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart - headerSize(); + } else { + // Less than half is visible - hide the header. Scroll so + // that the topItem is aligned to the top of the view + if (isContentFlowReversed()) + pos = -static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size(); + else + pos = static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart; + } + } + + headerNeedsSeparateFixup = isHeaderWithinBounds || desiredHeaderVisible; + if (headerNeedsSeparateFixup) { + // We need to animate the header independently if it starts visible or should end as visible, + // since the header should not necessarily follow the content. + // Store the desired viewport position. + // Also store the header position so we know where to animate the header from (fixupHeaderPosition). + // We deduce the desired header position from the desiredViewportPosition variable. + pos = qBound(-minExtent, pos, -maxExtent); + desiredViewportPosition = isContentFlowReversed() ? -pos - size() : pos; + + FxListItemSG *headerItem = static_cast<FxListItemSG*>(header); + fixupHeaderPosition = headerItem->position(); + + // follow the same fixup timeline + QObjectPrivate::connect(&timeline, &QQuickTimeLine::updated, this, &QQuickListViewPrivate::fixupHeader); + QObjectPrivate::connect(&timeline, &QQuickTimeLine::completed, this, &QQuickListViewPrivate::fixupHeaderCompleted); + } + } else if (isContentFlowReversed()) { + pos = -static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size() + overlayHeaderOffset; + } else { + pos = static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart - overlayHeaderOffset; + } } } else if (bottomItem && isInBounds) { if (isContentFlowReversed()) - pos = qMax(qMin(-static_cast<FxListItemSG*>(bottomItem)->itemPosition() + highlightRangeEnd - size(), -maxExtent), -minExtent); + pos = -static_cast<FxListItemSG*>(bottomItem)->itemPosition() + highlightRangeEnd - size() + overlayHeaderOffset; else - pos = qMax(qMin(static_cast<FxListItemSG*>(bottomItem)->itemPosition() - highlightRangeEnd, -maxExtent), -minExtent); + pos = static_cast<FxListItemSG*>(bottomItem)->itemPosition() - highlightRangeEnd - overlayHeaderOffset; } else { QQuickItemViewPrivate::fixup(data, minExtent, maxExtent); return; } + pos = qBound(-minExtent, pos, -maxExtent); qreal dist = qAbs(data.move + pos); - if (dist > 0) { + if (dist >= 0) { + // Even if dist == 0 we still start the timeline, because we use the same timeline for + // moving the header. And we might need to move the header while the content does not + // need moving timeline.reset(data.move); if (fixupMode != Immediate) { timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); diff --git a/src/quick/items/qquicklistview_p.h b/src/quick/items/qquicklistview_p.h index be21b93155..5e3dbac3a7 100644 --- a/src/quick/items/qquicklistview_p.h +++ b/src/quick/items/qquicklistview_p.h @@ -71,6 +71,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickViewSection : public QObject Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged) Q_PROPERTY(int labelPositioning READ labelPositioning WRITE setLabelPositioning NOTIFY labelPositioningChanged) QML_NAMED_ELEMENT(ViewSection) + QML_ADDED_IN_VERSION(2, 0) public: QQuickViewSection(QQuickListView *parent=nullptr); @@ -127,11 +128,12 @@ class Q_QUICK_PRIVATE_EXPORT QQuickListView : public QQuickItemView Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged) - Q_PROPERTY(HeaderPositioning headerPositioning READ headerPositioning WRITE setHeaderPositioning NOTIFY headerPositioningChanged REVISION 4) - Q_PROPERTY(FooterPositioning footerPositioning READ footerPositioning WRITE setFooterPositioning NOTIFY footerPositioningChanged REVISION 4) + Q_PROPERTY(HeaderPositioning headerPositioning READ headerPositioning WRITE setHeaderPositioning NOTIFY headerPositioningChanged REVISION(2, 4)) + Q_PROPERTY(FooterPositioning footerPositioning READ footerPositioning WRITE setFooterPositioning NOTIFY footerPositioningChanged REVISION(2, 4)) Q_CLASSINFO("DefaultProperty", "data") QML_NAMED_ELEMENT(ListView) + QML_ADDED_IN_VERSION(2, 0) QML_ATTACHED(QQuickListViewAttached) public: @@ -193,8 +195,8 @@ Q_SIGNALS: void highlightResizeVelocityChanged(); void highlightResizeDurationChanged(); void snapModeChanged(); - Q_REVISION(4) void headerPositioningChanged(); - Q_REVISION(4) void footerPositioningChanged(); + Q_REVISION(2, 4) void headerPositioningChanged(); + Q_REVISION(2, 4) void footerPositioningChanged(); protected: void viewportMoved(Qt::Orientations orient) override; diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp index 8722a45373..1fb71272b1 100644 --- a/src/quick/items/qquickloader.cpp +++ b/src/quick/items/qquickloader.cpp @@ -56,7 +56,7 @@ static const QQuickItemPrivate::ChangeTypes watchedChanges QQuickLoaderPrivate::QQuickLoaderPrivate() : item(nullptr), object(nullptr), itemContext(nullptr), incubator(nullptr), updatingSize(false), - active(true), loadingFromSource(false), asynchronous(false) + active(true), loadingFromSource(false), asynchronous(false), status(computeStatus()) { } @@ -379,7 +379,7 @@ void QQuickLoader::setActive(bool newVal) d->object = nullptr; emit itemChanged(); } - emit statusChanged(); + d->updateStatus(); } emit activeChanged(); } @@ -432,7 +432,7 @@ void QQuickLoader::loadFromSource() Q_D(QQuickLoader); if (d->source.isEmpty()) { emit sourceChanged(); - emit statusChanged(); + d->updateStatus(); emit progressChanged(); emit itemChanged(); return; @@ -503,7 +503,7 @@ void QQuickLoader::loadFromSourceComponent() Q_D(QQuickLoader); if (!d->component) { emit sourceComponentChanged(); - emit statusChanged(); + d->updateStatus(); emit progressChanged(); emit itemChanged(); return; @@ -619,7 +619,7 @@ void QQuickLoaderPrivate::load() q, SLOT(_q_sourceLoaded())); QObject::connect(component, SIGNAL(progressChanged(qreal)), q, SIGNAL(progressChanged())); - emit q->statusChanged(); + updateStatus(); emit q->progressChanged(); if (loadingFromSource) emit q->sourceChanged(); @@ -707,7 +707,7 @@ void QQuickLoaderPrivate::incubatorStateChanged(QQmlIncubator::Status status) emit q->sourceChanged(); else emit q->sourceComponentChanged(); - emit q->statusChanged(); + updateStatus(); emit q->progressChanged(); if (status == QQmlIncubator::Ready) emit q->loaded(); @@ -724,7 +724,7 @@ void QQuickLoaderPrivate::_q_sourceLoaded() emit q->sourceChanged(); else emit q->sourceComponentChanged(); - emit q->statusChanged(); + updateStatus(); emit q->progressChanged(); emit q->itemChanged(); //Like clearing source, emit itemChanged even if previous item was also null disposeInitialPropertyValues(); // cleanup @@ -742,7 +742,7 @@ void QQuickLoaderPrivate::_q_sourceLoaded() component->create(*incubator, itemContext); if (incubator && incubator->status() == QQmlIncubator::Loading) - emit q->statusChanged(); + updateStatus(); } /*! @@ -789,37 +789,7 @@ QQuickLoader::Status QQuickLoader::status() const { Q_D(const QQuickLoader); - if (!d->active) - return Null; - - if (d->component) { - switch (d->component->status()) { - case QQmlComponent::Loading: - return Loading; - case QQmlComponent::Error: - return Error; - case QQmlComponent::Null: - return Null; - default: - break; - } - } - - if (d->incubator) { - switch (d->incubator->status()) { - case QQmlIncubator::Loading: - return Loading; - case QQmlIncubator::Error: - return Error; - default: - break; - } - } - - if (d->object) - return Ready; - - return d->source.isEmpty() ? Null : Error; + return static_cast<Status>(d->status); } void QQuickLoader::componentComplete() @@ -1020,6 +990,51 @@ QV4::ReturnedValue QQuickLoaderPrivate::extractInitialPropertyValues(QQmlV4Funct return valuemap->asReturnedValue(); } +QQuickLoader::Status QQuickLoaderPrivate::computeStatus() const +{ + if (!active) + return QQuickLoader::Status::Null; + + if (component) { + switch (component->status()) { + case QQmlComponent::Loading: + return QQuickLoader::Status::Loading; + case QQmlComponent::Error: + return QQuickLoader::Status::Error; + case QQmlComponent::Null: + return QQuickLoader::Status::Null; + default: + break; + } + } + + if (incubator) { + switch (incubator->status()) { + case QQmlIncubator::Loading: + return QQuickLoader::Status::Loading; + case QQmlIncubator::Error: + return QQuickLoader::Status::Error; + default: + break; + } + } + + if (object) + return QQuickLoader::Status::Ready; + + return source.isEmpty() ? QQuickLoader::Status::Null : QQuickLoader::Status::Error; +} + +void QQuickLoaderPrivate::updateStatus() +{ + Q_Q(QQuickLoader); + auto newStatus = computeStatus(); + if (status != newStatus) { + status = newStatus; + emit q->statusChanged(); + } +} + #include <moc_qquickloader_p.cpp> QT_END_NAMESPACE diff --git a/src/quick/items/qquickloader_p.h b/src/quick/items/qquickloader_p.h index 2d560fb856..8f061d3139 100644 --- a/src/quick/items/qquickloader_p.h +++ b/src/quick/items/qquickloader_p.h @@ -68,6 +68,7 @@ class Q_AUTOTEST_EXPORT QQuickLoader : public QQuickImplicitSizeItem Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged) Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged) QML_NAMED_ELEMENT(Loader) + QML_ADDED_IN_VERSION(2, 0) public: QQuickLoader(QQuickItem *parent = nullptr); diff --git a/src/quick/items/qquickloader_p_p.h b/src/quick/items/qquickloader_p_p.h index 349b5c6c06..39d50280c5 100644 --- a/src/quick/items/qquickloader_p_p.h +++ b/src/quick/items/qquickloader_p_p.h @@ -96,6 +96,8 @@ public: void disposeInitialPropertyValues(); static QUrl resolveSourceUrl(QQmlV4Function *args); QV4::ReturnedValue extractInitialPropertyValues(QQmlV4Function *args, QObject *loader, bool *error); + QQuickLoader::Status computeStatus() const; + void updateStatus(); qreal getImplicitWidth() const override; qreal getImplicitHeight() const override; @@ -112,6 +114,11 @@ public: bool active : 1; bool loadingFromSource : 1; bool asynchronous : 1; + // We need to use char instead of QQuickLoader::Status + // as otherwise the size of the class would increase + // on 32-bit systems, as sizeof(Status) == sizeof(int) + // and sizeof(int) > remaining padding on 32 bit + char status; void _q_sourceLoaded(); void _q_updateSize(bool loaderGeometryChanged = true); diff --git a/src/quick/items/qquickmousearea_p.h b/src/quick/items/qquickmousearea_p.h index 806cc41369..02ad56fd79 100644 --- a/src/quick/items/qquickmousearea_p.h +++ b/src/quick/items/qquickmousearea_p.h @@ -71,7 +71,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickMouseArea : public QQuickItem Q_PROPERTY(bool containsMouse READ hovered NOTIFY hoveredChanged) Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) - Q_PROPERTY(bool scrollGestureEnabled READ isScrollGestureEnabled WRITE setScrollGestureEnabled NOTIFY scrollGestureEnabledChanged REVISION 5) + Q_PROPERTY(bool scrollGestureEnabled READ isScrollGestureEnabled WRITE setScrollGestureEnabled NOTIFY scrollGestureEnabledChanged REVISION(2, 5)) Q_PROPERTY(Qt::MouseButtons pressedButtons READ pressedButtons NOTIFY pressedButtonsChanged) Q_PROPERTY(Qt::MouseButtons acceptedButtons READ acceptedButtons WRITE setAcceptedButtons NOTIFY acceptedButtonsChanged) Q_PROPERTY(bool hoverEnabled READ hoverEnabled WRITE setHoverEnabled NOTIFY hoverEnabledChanged) @@ -83,9 +83,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickMouseArea : public QQuickItem #if QT_CONFIG(cursor) Q_PROPERTY(Qt::CursorShape cursorShape READ cursorShape WRITE setCursorShape RESET unsetCursor NOTIFY cursorShapeChanged) #endif - Q_PROPERTY(bool containsPress READ containsPress NOTIFY containsPressChanged REVISION 4) - Q_PROPERTY(int pressAndHoldInterval READ pressAndHoldInterval WRITE setPressAndHoldInterval NOTIFY pressAndHoldIntervalChanged RESET resetPressAndHoldInterval REVISION 9) + Q_PROPERTY(bool containsPress READ containsPress NOTIFY containsPressChanged REVISION(2, 4)) + Q_PROPERTY(int pressAndHoldInterval READ pressAndHoldInterval WRITE setPressAndHoldInterval NOTIFY pressAndHoldIntervalChanged RESET resetPressAndHoldInterval REVISION(2, 9)) QML_NAMED_ELEMENT(MouseArea) + QML_ADDED_IN_VERSION(2, 0) public: QQuickMouseArea(QQuickItem *parent=nullptr); @@ -135,7 +136,7 @@ Q_SIGNALS: void hoveredChanged(); void pressedChanged(); void enabledChanged(); - Q_REVISION(5) void scrollGestureEnabledChanged(); + Q_REVISION(2, 5) void scrollGestureEnabledChanged(); void pressedButtonsChanged(); void acceptedButtonsChanged(); void hoverEnabledChanged(); @@ -157,8 +158,8 @@ Q_SIGNALS: void entered(); void exited(); void canceled(); - Q_REVISION(4) void containsPressChanged(); - Q_REVISION(9) void pressAndHoldIntervalChanged(); + Q_REVISION(2, 4) void containsPressChanged(); + Q_REVISION(2, 9) void pressAndHoldIntervalChanged(); protected: void setHovered(bool); diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp index 9a371207ce..3a807d3c66 100644 --- a/src/quick/items/qquickmultipointtoucharea.cpp +++ b/src/quick/items/qquickmultipointtoucharea.cpp @@ -88,20 +88,18 @@ void QQuickTouchPoint::setPointId(int id) These properties hold the current position of the touch point. */ -void QQuickTouchPoint::setX(qreal x) +void QQuickTouchPoint::setPosition(QPointF p) { - if (_x == x) + bool xch = (_x != p.x()); + bool ych = (_y != p.y()); + if (!xch && !ych) return; - _x = x; - emit xChanged(); -} - -void QQuickTouchPoint::setY(qreal y) -{ - if (_y == y) - return; - _y = y; - emit yChanged(); + _x = p.x(); + _y = p.y(); + if (xch) + emit xChanged(); + if (ych) + emit yChanged(); } /*! @@ -798,8 +796,7 @@ void QQuickMultiPointTouchArea::updateTouchPoint(QQuickTouchPoint *dtp, const QT //TODO: if !qmlDefined, could bypass setters. // also, should only emit signals after all values have been set dtp->setUniqueId(p->uniqueId()); - dtp->setX(p->pos().x()); - dtp->setY(p->pos().y()); + dtp->setPosition(p->pos()); dtp->setEllipseDiameters(p->ellipseDiameters()); dtp->setPressure(p->pressure()); dtp->setRotation(p->rotation()); @@ -817,8 +814,7 @@ void QQuickMultiPointTouchArea::updateTouchPoint(QQuickTouchPoint *dtp, const QM { dtp->setPreviousX(dtp->x()); dtp->setPreviousY(dtp->y()); - dtp->setX(e->localPos().x()); - dtp->setY(e->localPos().y()); + dtp->setPosition(e->localPos()); if (e->type() == QEvent::MouseButtonPress) { dtp->setStartX(e->localPos().x()); dtp->setStartY(e->localPos().y()); diff --git a/src/quick/items/qquickmultipointtoucharea_p.h b/src/quick/items/qquickmultipointtoucharea_p.h index 363e62593b..d37cc6df7e 100644 --- a/src/quick/items/qquickmultipointtoucharea_p.h +++ b/src/quick/items/qquickmultipointtoucharea_p.h @@ -67,13 +67,13 @@ class Q_AUTOTEST_EXPORT QQuickTouchPoint : public QObject { Q_OBJECT Q_PROPERTY(int pointId READ pointId NOTIFY pointIdChanged) - Q_PROPERTY(QPointingDeviceUniqueId uniqueId READ uniqueId NOTIFY uniqueIdChanged REVISION 9) + Q_PROPERTY(QPointingDeviceUniqueId uniqueId READ uniqueId NOTIFY uniqueIdChanged REVISION(2, 9)) Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged) Q_PROPERTY(qreal x READ x NOTIFY xChanged) Q_PROPERTY(qreal y READ y NOTIFY yChanged) - Q_PROPERTY(QSizeF ellipseDiameters READ ellipseDiameters NOTIFY ellipseDiametersChanged REVISION 9) + Q_PROPERTY(QSizeF ellipseDiameters READ ellipseDiameters NOTIFY ellipseDiametersChanged REVISION(2, 9)) Q_PROPERTY(qreal pressure READ pressure NOTIFY pressureChanged) - Q_PROPERTY(qreal rotation READ rotation NOTIFY rotationChanged REVISION 9) + Q_PROPERTY(qreal rotation READ rotation NOTIFY rotationChanged REVISION(2, 9)) Q_PROPERTY(QVector2D velocity READ velocity NOTIFY velocityChanged) Q_PROPERTY(QRectF area READ area NOTIFY areaChanged) @@ -84,6 +84,7 @@ class Q_AUTOTEST_EXPORT QQuickTouchPoint : public QObject Q_PROPERTY(qreal sceneX READ sceneX NOTIFY sceneXChanged) Q_PROPERTY(qreal sceneY READ sceneY NOTIFY sceneYChanged) QML_NAMED_ELEMENT(TouchPoint) + QML_ADDED_IN_VERSION(2, 0) public: QQuickTouchPoint(bool qmlDefined = true) @@ -97,10 +98,8 @@ public: void setUniqueId(const QPointingDeviceUniqueId &id); qreal x() const { return _x; } - void setX(qreal x); - qreal y() const { return _y; } - void setY(qreal y); + void setPosition(QPointF pos); QSizeF ellipseDiameters() const { return _ellipseDiameters; } void setEllipseDiameters(const QSizeF &d); @@ -146,12 +145,12 @@ public: Q_SIGNALS: void pressedChanged(); void pointIdChanged(); - Q_REVISION(9) void uniqueIdChanged(); + Q_REVISION(2, 9) void uniqueIdChanged(); void xChanged(); void yChanged(); - Q_REVISION(9) void ellipseDiametersChanged(); + Q_REVISION(2, 9) void ellipseDiametersChanged(); void pressureChanged(); - Q_REVISION(9) void rotationChanged(); + Q_REVISION(2, 9) void rotationChanged(); void velocityChanged(); void areaChanged(); void startXChanged(); @@ -189,6 +188,7 @@ class QQuickGrabGestureEvent : public QObject Q_PROPERTY(QQmlListProperty<QObject> touchPoints READ touchPoints CONSTANT) Q_PROPERTY(qreal dragThreshold READ dragThreshold CONSTANT) QML_NAMED_ELEMENT(GestureEvent) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("GestureEvent is only available in the context of handling the gestureStarted signal from MultiPointTouchArea.") public: @@ -218,6 +218,7 @@ class Q_AUTOTEST_EXPORT QQuickMultiPointTouchArea : public QQuickItem Q_PROPERTY(int maximumTouchPoints READ maximumTouchPoints WRITE setMaximumTouchPoints NOTIFY maximumTouchPointsChanged) Q_PROPERTY(bool mouseEnabled READ mouseEnabled WRITE setMouseEnabled NOTIFY mouseEnabledChanged) QML_NAMED_ELEMENT(MultiPointTouchArea) + QML_ADDED_IN_VERSION(2, 0) public: QQuickMultiPointTouchArea(QQuickItem *parent=nullptr); diff --git a/src/quick/items/qquickopenglinfo_p.h b/src/quick/items/qquickopenglinfo_p.h index b733d205e3..e0c2572b8d 100644 --- a/src/quick/items/qquickopenglinfo_p.h +++ b/src/quick/items/qquickopenglinfo_p.h @@ -72,7 +72,7 @@ class QQuickOpenGLInfo : public QObject QML_NAMED_ELEMENT(OpenGLInfo) QML_UNCREATABLE("OpenGLInfo is only available via attached properties.") - QML_ADDED_IN_MINOR_VERSION(4) + QML_ADDED_IN_VERSION(2, 4) QML_ATTACHED(QQuickOpenGLInfo) public: diff --git a/src/quick/items/qquickopenglshadereffect.cpp b/src/quick/items/qquickopenglshadereffect.cpp index e217fdb5d0..280cdbf831 100644 --- a/src/quick/items/qquickopenglshadereffect.cpp +++ b/src/quick/items/qquickopenglshadereffect.cpp @@ -52,8 +52,9 @@ #include "qquickshadereffectmesh_p.h" #include <QtQml/qqmlfile.h> -#include <QtCore/qsignalmapper.h> +#include <QtCore/qfile.h> #include <QtCore/qfileselector.h> +#include <QtCore/qsignalmapper.h> QT_BEGIN_NAMESPACE diff --git a/src/quick/items/qquickopenglshadereffectnode.cpp b/src/quick/items/qquickopenglshadereffectnode.cpp index 5721f116e8..71cfe96462 100644 --- a/src/quick/items/qquickopenglshadereffectnode.cpp +++ b/src/quick/items/qquickopenglshadereffectnode.cpp @@ -45,7 +45,7 @@ #include <QtQuick/private/qsgshadersourcebuilder_p.h> #include <QtQuick/private/qsgtexture_p.h> #include <QtCore/qmutex.h> -#include <QtGui/qopenglfunctions.h> +#include <qopenglfunctions.h> #ifndef GL_TEXTURE_EXTERNAL_OES #define GL_TEXTURE_EXTERNAL_OES 0x8D65 diff --git a/src/quick/items/qquickpainteditem.cpp b/src/quick/items/qquickpainteditem.cpp index df5ec0c3f2..1eb852f6bf 100644 --- a/src/quick/items/qquickpainteditem.cpp +++ b/src/quick/items/qquickpainteditem.cpp @@ -44,6 +44,9 @@ #include <QtQuick/private/qsgcontext_p.h> #include <private/qsgadaptationlayer_p.h> #include <qsgtextureprovider.h> +#if QT_CONFIG(opengl) +#include <QOpenGLContext> +#endif // QT_CONFIG(opengl) #include <qmath.h> diff --git a/src/quick/items/qquickpainteditem.h b/src/quick/items/qquickpainteditem.h index 4821a409be..a6a78f6166 100644 --- a/src/quick/items/qquickpainteditem.h +++ b/src/quick/items/qquickpainteditem.h @@ -57,6 +57,7 @@ class Q_QUICK_EXPORT QQuickPaintedItem : public QQuickItem Q_PROPERTY(QSize textureSize READ textureSize WRITE setTextureSize NOTIFY textureSizeChanged) QML_NAMED_ELEMENT(PaintedItem) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("Cannot create instance of abstract class PaintedItem.") public: diff --git a/src/quick/items/qquickpathview_p.h b/src/quick/items/qquickpathview_p.h index c12358e4f6..0c5a6578c3 100644 --- a/src/quick/items/qquickpathview_p.h +++ b/src/quick/items/qquickpathview_p.h @@ -97,10 +97,11 @@ class Q_QUICK_PRIVATE_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(MovementDirection movementDirection READ movementDirection WRITE setMovementDirection NOTIFY movementDirectionChanged REVISION(2, 7)) Q_PROPERTY(int cacheItemCount READ cacheItemCount WRITE setCacheItemCount NOTIFY cacheItemCountChanged) QML_NAMED_ELEMENT(PathView) + QML_ADDED_IN_VERSION(2, 0) QML_ATTACHED(QQuickPathViewAttached) public: @@ -182,7 +183,7 @@ public: Q_INVOKABLE void positionViewAtIndex(int index, int mode); Q_INVOKABLE int indexAt(qreal x, qreal y) const; Q_INVOKABLE QQuickItem *itemAt(qreal x, qreal y) const; - Q_REVISION(13) Q_INVOKABLE QQuickItem *itemAtIndex(int index) const; + Q_REVISION(2, 13) Q_INVOKABLE QQuickItem *itemAtIndex(int index) const; static QQuickPathViewAttached *qmlAttachedProperties(QObject *); @@ -215,7 +216,7 @@ Q_SIGNALS: void highlightMoveDurationChanged(); void movementStarted(); void movementEnded(); - Q_REVISION(7) void movementDirectionChanged(); + Q_REVISION(2, 7) void movementDirectionChanged(); void flickStarted(); void flickEnded(); void dragStarted(); diff --git a/src/quick/items/qquickpincharea_p.h b/src/quick/items/qquickpincharea_p.h index d7f814cc8a..27f895612a 100644 --- a/src/quick/items/qquickpincharea_p.h +++ b/src/quick/items/qquickpincharea_p.h @@ -71,6 +71,7 @@ class Q_AUTOTEST_EXPORT QQuickPinch : public QObject Q_PROPERTY(qreal maximumY READ ymax WRITE setYmax NOTIFY maximumYChanged) Q_PROPERTY(bool active READ active NOTIFY activeChanged) QML_NAMED_ELEMENT(Pinch) + QML_ADDED_IN_VERSION(2, 0) public: QQuickPinch(); @@ -212,6 +213,7 @@ class Q_AUTOTEST_EXPORT QQuickPinchEvent : public QObject Q_PROPERTY(int pointCount READ pointCount) Q_PROPERTY(bool accepted READ accepted WRITE setAccepted) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQuickPinchEvent(QPointF c, qreal s, qreal a, qreal r) @@ -271,6 +273,7 @@ class Q_AUTOTEST_EXPORT QQuickPinchArea : public QQuickItem Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) Q_PROPERTY(QQuickPinch *pinch READ pinch CONSTANT) QML_NAMED_ELEMENT(PinchArea) + QML_ADDED_IN_VERSION(2, 0) public: QQuickPinchArea(QQuickItem *parent=nullptr); @@ -286,7 +289,7 @@ Q_SIGNALS: void pinchStarted(QQuickPinchEvent *pinch); void pinchUpdated(QQuickPinchEvent *pinch); void pinchFinished(QQuickPinchEvent *pinch); - Q_REVISION(5) void smartZoom(QQuickPinchEvent *pinch); + Q_REVISION(2, 5) void smartZoom(QQuickPinchEvent *pinch); protected: bool childMouseEventFilter(QQuickItem *i, QEvent *e) override; 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/qquickpositioners_p.h b/src/quick/items/qquickpositioners_p.h index b924cb9c12..2c3aa674c6 100644 --- a/src/quick/items/qquickpositioners_p.h +++ b/src/quick/items/qquickpositioners_p.h @@ -107,13 +107,14 @@ class Q_QUICK_PRIVATE_EXPORT QQuickBasePositioner : public QQuickImplicitSizeIte Q_PROPERTY(QQuickTransition *move READ move WRITE setMove NOTIFY moveChanged) Q_PROPERTY(QQuickTransition *add READ add WRITE setAdd NOTIFY addChanged) - Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6) - Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6) - Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION 6) - Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION 6) - Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6) + Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION(2, 6)) + Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION(2, 6)) + Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION(2, 6)) + Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION(2, 6)) + Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION(2, 6)) QML_NAMED_ELEMENT(Positioner) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("Positioner is an abstract type that is only available as an attached property.") QML_ATTACHED(QQuickPositionerAttached) @@ -159,7 +160,7 @@ public: void setBottomPadding(qreal padding); void resetBottomPadding(); - Q_REVISION(9) Q_INVOKABLE void forceLayout(); + Q_REVISION(2, 9) Q_INVOKABLE void forceLayout(); protected: QQuickBasePositioner(QQuickBasePositionerPrivate &dd, PositionerType at, QQuickItem *parent); @@ -173,12 +174,12 @@ Q_SIGNALS: void populateChanged(); void moveChanged(); void addChanged(); - Q_REVISION(6) void paddingChanged(); - Q_REVISION(6) void topPaddingChanged(); - Q_REVISION(6) void leftPaddingChanged(); - Q_REVISION(6) void rightPaddingChanged(); - Q_REVISION(6) void bottomPaddingChanged(); - Q_REVISION(9) void positioningComplete(); + Q_REVISION(2, 6) void paddingChanged(); + Q_REVISION(2, 6) void topPaddingChanged(); + Q_REVISION(2, 6) void leftPaddingChanged(); + Q_REVISION(2, 6) void rightPaddingChanged(); + Q_REVISION(2, 6) void bottomPaddingChanged(); + Q_REVISION(2, 9) void positioningComplete(); protected Q_SLOTS: void prePositioning(); @@ -236,6 +237,7 @@ class Q_AUTOTEST_EXPORT QQuickColumn : public QQuickBasePositioner { Q_OBJECT QML_NAMED_ELEMENT(Column) + QML_ADDED_IN_VERSION(2, 0) public: QQuickColumn(QQuickItem *parent=nullptr); @@ -253,6 +255,7 @@ class Q_AUTOTEST_EXPORT QQuickRow: public QQuickBasePositioner Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged) Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged) QML_NAMED_ELEMENT(Row) + QML_ADDED_IN_VERSION(2, 0) public: QQuickRow(QQuickItem *parent=nullptr); @@ -284,10 +287,11 @@ class Q_AUTOTEST_EXPORT QQuickGrid : public QQuickBasePositioner Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged) Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged) Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged) - Q_PROPERTY(HAlignment horizontalItemAlignment READ hItemAlign WRITE setHItemAlign NOTIFY horizontalAlignmentChanged REVISION 1) - Q_PROPERTY(HAlignment effectiveHorizontalItemAlignment READ effectiveHAlign NOTIFY effectiveHorizontalAlignmentChanged REVISION 1) - Q_PROPERTY(VAlignment verticalItemAlignment READ vItemAlign WRITE setVItemAlign NOTIFY verticalAlignmentChanged REVISION 1) + Q_PROPERTY(HAlignment horizontalItemAlignment READ hItemAlign WRITE setHItemAlign NOTIFY horizontalAlignmentChanged REVISION(2, 1)) + Q_PROPERTY(HAlignment effectiveHorizontalItemAlignment READ effectiveHAlign NOTIFY effectiveHorizontalAlignmentChanged REVISION(2, 1)) + Q_PROPERTY(VAlignment verticalItemAlignment READ vItemAlign WRITE setVItemAlign NOTIFY verticalAlignmentChanged REVISION(2, 1)) QML_NAMED_ELEMENT(Grid) + QML_ADDED_IN_VERSION(2, 0) public: QQuickGrid(QQuickItem *parent=nullptr); @@ -339,9 +343,9 @@ Q_SIGNALS: void effectiveLayoutDirectionChanged(); void rowSpacingChanged(); void columnSpacingChanged(); - Q_REVISION(1) void horizontalAlignmentChanged(HAlignment alignment); - Q_REVISION(1) void effectiveHorizontalAlignmentChanged(HAlignment alignment); - Q_REVISION(1) void verticalAlignmentChanged(VAlignment alignment); + Q_REVISION(2, 1) void horizontalAlignmentChanged(HAlignment alignment); + Q_REVISION(2, 1) void effectiveHorizontalAlignmentChanged(HAlignment alignment); + Q_REVISION(2, 1) void verticalAlignmentChanged(VAlignment alignment); protected: void doPositioning(QSizeF *contentSize) override; @@ -369,6 +373,7 @@ class Q_AUTOTEST_EXPORT QQuickFlow: public QQuickBasePositioner Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged) Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged) QML_NAMED_ELEMENT(Flow) + QML_ADDED_IN_VERSION(2, 0) public: QQuickFlow(QQuickItem *parent=nullptr); diff --git a/src/quick/items/qquickrectangle_p.h b/src/quick/items/qquickrectangle_p.h index 934300b63b..c4f03de770 100644 --- a/src/quick/items/qquickrectangle_p.h +++ b/src/quick/items/qquickrectangle_p.h @@ -67,6 +67,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPen : public QObject Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY penChanged) Q_PROPERTY(bool pixelAligned READ pixelAligned WRITE setPixelAligned NOTIFY penChanged) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQuickPen(QObject *parent=nullptr); @@ -98,6 +99,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickGradientStop : public QObject Q_PROPERTY(qreal position READ position WRITE setPosition) Q_PROPERTY(QColor color READ color WRITE setColor) QML_NAMED_ELEMENT(GradientStop) + QML_ADDED_IN_VERSION(2, 0) public: QQuickGradientStop(QObject *parent=nullptr); @@ -121,9 +123,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickGradient : public QObject Q_OBJECT Q_PROPERTY(QQmlListProperty<QQuickGradientStop> stops READ stops) - Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged REVISION 12) + Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged REVISION(2, 12)) Q_CLASSINFO("DefaultProperty", "stops") QML_NAMED_ELEMENT(Gradient) + QML_ADDED_IN_VERSION(2, 0) Q_ENUMS(QGradient::Preset) public: @@ -165,6 +168,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickRectangle : public QQuickItem Q_PROPERTY(QQuickPen * border READ border CONSTANT) Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged) QML_NAMED_ELEMENT(Rectangle) + QML_ADDED_IN_VERSION(2, 0) public: QQuickRectangle(QQuickItem *parent=nullptr); diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp index 9f9777f199..08d04d3b11 100644 --- a/src/quick/items/qquickrendercontrol.cpp +++ b/src/quick/items/qquickrendercontrol.cpp @@ -45,7 +45,7 @@ #include <QtQuick/private/qquickanimatorcontroller_p.h> #if QT_CONFIG(opengl) -# include <QtGui/QOpenGLContext> +# include <QOpenGLContext> # include <QtQuick/private/qsgdefaultrendercontext_p.h> #if QT_CONFIG(quick_shadereffect) # include <QtQuick/private/qquickopenglshadereffectnode_p.h> diff --git a/src/quick/items/qquickrepeater_p.h b/src/quick/items/qquickrepeater_p.h index 20984fa23e..652651efb9 100644 --- a/src/quick/items/qquickrepeater_p.h +++ b/src/quick/items/qquickrepeater_p.h @@ -71,6 +71,7 @@ class Q_AUTOTEST_EXPORT QQuickRepeater : public QQuickItem Q_PROPERTY(int count READ count NOTIFY countChanged) Q_CLASSINFO("DefaultProperty", "delegate") QML_NAMED_ELEMENT(Repeater) + QML_ADDED_IN_VERSION(2, 0) public: QQuickRepeater(QQuickItem *parent=nullptr); diff --git a/src/quick/items/qquickscalegrid_p_p.h b/src/quick/items/qquickscalegrid_p_p.h index 56b0ee86ab..1eb6c05ef1 100644 --- a/src/quick/items/qquickscalegrid_p_p.h +++ b/src/quick/items/qquickscalegrid_p_p.h @@ -70,6 +70,7 @@ class Q_AUTOTEST_EXPORT QQuickScaleGrid : public QObject Q_PROPERTY(int right READ right WRITE setRight NOTIFY rightBorderChanged) Q_PROPERTY(int bottom READ bottom WRITE setBottom NOTIFY bottomBorderChanged) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQuickScaleGrid(QObject *parent=nullptr); diff --git a/src/quick/items/qquickscreen_p.h b/src/quick/items/qquickscreen_p.h index b4266d78c7..dc1c820309 100644 --- a/src/quick/items/qquickscreen_p.h +++ b/src/quick/items/qquickscreen_p.h @@ -68,9 +68,9 @@ class Q_QUICK_PRIVATE_EXPORT QQuickScreenInfo : public QObject { Q_OBJECT Q_PROPERTY(QString name READ name NOTIFY nameChanged) - Q_PROPERTY(QString manufacturer READ manufacturer NOTIFY manufacturerChanged REVISION 10) - Q_PROPERTY(QString model READ model NOTIFY modelChanged REVISION 10) - Q_PROPERTY(QString serialNumber READ serialNumber NOTIFY serialNumberChanged REVISION 10) + Q_PROPERTY(QString manufacturer READ manufacturer NOTIFY manufacturerChanged REVISION(2, 10)) + Q_PROPERTY(QString model READ model NOTIFY modelChanged REVISION(2, 10)) + Q_PROPERTY(QString serialNumber READ serialNumber NOTIFY serialNumberChanged REVISION(2, 10)) Q_PROPERTY(int width READ width NOTIFY widthChanged) Q_PROPERTY(int height READ height NOTIFY heightChanged) Q_PROPERTY(int desktopAvailableWidth READ desktopAvailableWidth NOTIFY desktopGeometryChanged) @@ -83,8 +83,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickScreenInfo : public QObject // TODO Qt 6 Remove this orientation -> incomplete device orientation -> better use OrientationSensor Q_PROPERTY(Qt::ScreenOrientation orientation READ orientation NOTIFY orientationChanged) - Q_PROPERTY(int virtualX READ virtualX NOTIFY virtualXChanged REVISION 3) - Q_PROPERTY(int virtualY READ virtualY NOTIFY virtualYChanged REVISION 3) + Q_PROPERTY(int virtualX READ virtualX NOTIFY virtualXChanged REVISION(2, 3)) + Q_PROPERTY(int virtualY READ virtualY NOTIFY virtualYChanged REVISION(2, 3)) public: QQuickScreenInfo(QObject *parent = nullptr, QScreen *wrappedScreen = nullptr); @@ -110,9 +110,9 @@ public: Q_SIGNALS: void nameChanged(); - Q_REVISION(10) void manufacturerChanged(); - Q_REVISION(10) void modelChanged(); - Q_REVISION(10) void serialNumberChanged(); + Q_REVISION(2, 10) void manufacturerChanged(); + Q_REVISION(2, 10) void modelChanged(); + Q_REVISION(2, 10) void serialNumberChanged(); void widthChanged(); void heightChanged(); void desktopGeometryChanged(); @@ -121,8 +121,8 @@ Q_SIGNALS: void devicePixelRatioChanged(); void primaryOrientationChanged(); void orientationChanged(); - Q_REVISION(3) void virtualXChanged(); - Q_REVISION(3) void virtualYChanged(); + Q_REVISION(2, 3) void virtualXChanged(); + Q_REVISION(2, 3) void virtualYChanged(); protected: QPointer<QScreen> m_screen; diff --git a/src/quick/items/qquickshadereffect_p.h b/src/quick/items/qquickshadereffect_p.h index c14907092c..16eb252add 100644 --- a/src/quick/items/qquickshadereffect_p.h +++ b/src/quick/items/qquickshadereffect_p.h @@ -74,8 +74,9 @@ class Q_QUICK_PRIVATE_EXPORT QQuickShaderEffect : public QQuickItem Q_PROPERTY(CullMode cullMode READ cullMode WRITE setCullMode NOTIFY cullModeChanged) Q_PROPERTY(QString log READ log NOTIFY logChanged) Q_PROPERTY(Status status READ status NOTIFY statusChanged) - Q_PROPERTY(bool supportsAtlasTextures READ supportsAtlasTextures WRITE setSupportsAtlasTextures NOTIFY supportsAtlasTexturesChanged REVISION 4) + Q_PROPERTY(bool supportsAtlasTextures READ supportsAtlasTextures WRITE setSupportsAtlasTextures NOTIFY supportsAtlasTexturesChanged REVISION(2, 4)) QML_NAMED_ELEMENT(ShaderEffect) + QML_ADDED_IN_VERSION(2, 0) public: enum CullMode { diff --git a/src/quick/items/qquickshadereffectmesh_p.h b/src/quick/items/qquickshadereffectmesh_p.h index 710d37c275..4cd885a740 100644 --- a/src/quick/items/qquickshadereffectmesh_p.h +++ b/src/quick/items/qquickshadereffectmesh_p.h @@ -78,6 +78,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickShaderEffectMesh : public QObject Q_OBJECT QML_NAMED_ELEMENT(ShaderEffectMesh) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("Cannot create instance of abstract class ShaderEffectMesh.") public: @@ -102,6 +103,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickGridMesh : public QQuickShaderEffectMesh Q_OBJECT Q_PROPERTY(QSize resolution READ resolution WRITE setResolution NOTIFY resolutionChanged) QML_NAMED_ELEMENT(GridMesh) + QML_ADDED_IN_VERSION(2, 0) public: QQuickGridMesh(QObject *parent = nullptr); bool validateAttributes(const QVector<QByteArray> &attributes, int *posIndex) override; @@ -131,7 +133,7 @@ class QQuickBorderImageMesh : public QQuickShaderEffectMesh Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode NOTIFY verticalTileModeChanged) QML_NAMED_ELEMENT(BorderImageMesh) - QML_ADDED_IN_MINOR_VERSION(8) + QML_ADDED_IN_VERSION(2, 8) public: QQuickBorderImageMesh(QObject *parent = nullptr); diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp index f9f3e5cfa3..b298ed74da 100644 --- a/src/quick/items/qquickshadereffectsource.cpp +++ b/src/quick/items/qquickshadereffectsource.cpp @@ -161,10 +161,6 @@ public: \l sourceItem while still handling input. For this, you can use the \l hideSource property. - \note If \l sourceItem is a \l Rectangle with border, by default half the - border width falls outside the texture. To get the whole border, you can - extend the \l sourceRect. - \note The ShaderEffectSource relies on FBO multisampling support to antialias edges. If the underlying hardware does not support this, which is the case for most embedded graphics chips, edges rendered diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h index c0a1ccab78..fe419e5959 100644 --- a/src/quick/items/qquickshadereffectsource_p.h +++ b/src/quick/items/qquickshadereffectsource_p.h @@ -87,9 +87,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickShaderEffectSource : public QQuickItem, publi Q_PROPERTY(bool hideSource READ hideSource WRITE setHideSource NOTIFY hideSourceChanged) Q_PROPERTY(bool mipmap READ mipmap WRITE setMipmap NOTIFY mipmapChanged) Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged) - Q_PROPERTY(TextureMirroring textureMirroring READ textureMirroring WRITE setTextureMirroring NOTIFY textureMirroringChanged REVISION 6) - Q_PROPERTY(int samples READ samples WRITE setSamples NOTIFY samplesChanged REVISION 9) + Q_PROPERTY(TextureMirroring textureMirroring READ textureMirroring WRITE setTextureMirroring NOTIFY textureMirroringChanged REVISION(2, 6)) + Q_PROPERTY(int samples READ samples WRITE setSamples NOTIFY samplesChanged REVISION(2, 9)) QML_NAMED_ELEMENT(ShaderEffectSource) + QML_ADDED_IN_VERSION(2, 0) public: enum WrapMode { diff --git a/src/quick/items/qquicksprite_p.h b/src/quick/items/qquicksprite_p.h index 98e5b82db8..328dc74f47 100644 --- a/src/quick/items/qquicksprite_p.h +++ b/src/quick/items/qquicksprite_p.h @@ -87,6 +87,7 @@ class Q_QUICK_EXPORT QQuickSprite : public QQuickStochasticState Q_PROPERTY(int frameDuration READ frameDuration WRITE setFrameDuration NOTIFY frameDurationChanged RESET resetFrameDuration) Q_PROPERTY(int frameDurationVariation READ frameDurationVariation WRITE setFrameDurationVariation NOTIFY frameDurationVariationChanged) QML_NAMED_ELEMENT(Sprite) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickSprite(QObject *parent = nullptr); diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp index 8c52703938..3e4ed8707b 100644 --- a/src/quick/items/qquickspriteengine.cpp +++ b/src/quick/items/qquickspriteengine.cpp @@ -45,7 +45,7 @@ #include <QPainter> #include <QRandomGenerator> #include <QSet> -#include <QtGui/qopengl.h> +#include <qopengl.h> #include <QOpenGLFunctions> QT_BEGIN_NAMESPACE diff --git a/src/quick/items/qquickspriteengine_p.h b/src/quick/items/qquickspriteengine_p.h index d76055c831..5ad33389de 100644 --- a/src/quick/items/qquickspriteengine_p.h +++ b/src/quick/items/qquickspriteengine_p.h @@ -330,6 +330,18 @@ inline int spriteCount(QQmlListProperty<QQuickSprite> *p) return reinterpret_cast<QList<QQuickSprite *> *>(p->data)->count(); } +inline void spriteReplace(QQmlListProperty<QQuickSprite> *p, int idx, QQuickSprite *s) +{ + reinterpret_cast<QList<QQuickSprite *> *>(p->data)->replace(idx, s); + p->object->metaObject()->invokeMethod(p->object, "createEngine"); +} + +inline void spriteRemoveLast(QQmlListProperty<QQuickSprite> *p) +{ + reinterpret_cast<QList<QQuickSprite *> *>(p->data)->removeLast(); + p->object->metaObject()->invokeMethod(p->object, "createEngine"); +} + QT_END_NAMESPACE #endif // QQUICKSPRITEENGINE_P_H diff --git a/src/quick/items/qquickspritesequence.cpp b/src/quick/items/qquickspritesequence.cpp index eb4b5335e7..c29938a1bb 100644 --- a/src/quick/items/qquickspritesequence.cpp +++ b/src/quick/items/qquickspritesequence.cpp @@ -162,7 +162,9 @@ void QQuickSpriteSequence::setInterpolate(bool arg) QQmlListProperty<QQuickSprite> QQuickSpriteSequence::sprites() { Q_D(QQuickSpriteSequence); - return QQmlListProperty<QQuickSprite>(this, &d->m_sprites, spriteAppend, spriteCount, spriteAt, spriteClear); + return QQmlListProperty<QQuickSprite>(this, &d->m_sprites, + spriteAppend, spriteCount, spriteAt, + spriteClear, spriteReplace, spriteRemoveLast); } bool QQuickSpriteSequence::running() const diff --git a/src/quick/items/qquickspritesequence_p.h b/src/quick/items/qquickspritesequence_p.h index 8361f7832a..39b536daae 100644 --- a/src/quick/items/qquickspritesequence_p.h +++ b/src/quick/items/qquickspritesequence_p.h @@ -75,6 +75,7 @@ class Q_AUTOTEST_EXPORT QQuickSpriteSequence : public QQuickItem Q_PROPERTY(QQmlListProperty<QQuickSprite> sprites READ sprites) Q_CLASSINFO("DefaultProperty", "sprites") QML_NAMED_ELEMENT(SpriteSequence) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickSpriteSequence(QQuickItem *parent = nullptr); diff --git a/src/quick/items/qquickstateoperations_p.h b/src/quick/items/qquickstateoperations_p.h index d451dc6f77..5ba5400367 100644 --- a/src/quick/items/qquickstateoperations_p.h +++ b/src/quick/items/qquickstateoperations_p.h @@ -75,6 +75,7 @@ class Q_AUTOTEST_EXPORT QQuickParentChange : public QQuickStateOperation, public Q_PROPERTY(QQmlScriptString scale READ scale WRITE setScale) Q_PROPERTY(QQmlScriptString rotation READ rotation WRITE setRotation) QML_NAMED_ELEMENT(ParentChange) + QML_ADDED_IN_VERSION(2, 0) public: QQuickParentChange(QObject *parent=nullptr); ~QQuickParentChange(); @@ -138,6 +139,7 @@ class Q_AUTOTEST_EXPORT QQuickAnchorSet : public QObject Q_PROPERTY(QQmlScriptString verticalCenter READ verticalCenter WRITE setVerticalCenter RESET resetVerticalCenter) Q_PROPERTY(QQmlScriptString baseline READ baseline WRITE setBaseline RESET resetBaseline) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQuickAnchorSet(QObject *parent=nullptr); @@ -188,6 +190,7 @@ class Q_AUTOTEST_EXPORT QQuickAnchorChanges : public QQuickStateOperation, publi Q_PROPERTY(QQuickItem *target READ object WRITE setObject) Q_PROPERTY(QQuickAnchorSet *anchors READ anchors CONSTANT) QML_NAMED_ELEMENT(AnchorChanges) + QML_ADDED_IN_VERSION(2, 0) public: QQuickAnchorChanges(QObject *parent=nullptr); diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp index 66e89f0a09..9b1704421c 100644 --- a/src/quick/items/qquicktableview.cpp +++ b/src/quick/items/qquicktableview.cpp @@ -82,7 +82,7 @@ The following example shows how to create a model from C++ with multiple columns: - \snippet qml/tableview/cpp-tablemodel.cpp 0 + \snippet qml/tableview/cpp-tablemodel.h 0 And then how to use it from QML: @@ -441,7 +441,16 @@ QQuickTableViewPrivate::QQuickTableViewPrivate() QQuickTableViewPrivate::~QQuickTableViewPrivate() { - releaseLoadedItems(QQmlTableInstanceModel::NotReusable); + for (auto *fxTableItem : loadedItems) { + if (auto item = fxTableItem->item) { + if (fxTableItem->ownItem) + delete item; + else if (tableModel) + tableModel->dispose(item); + } + delete fxTableItem; + } + if (tableModel) delete tableModel; } @@ -2121,15 +2130,17 @@ void QQuickTableViewPrivate::fixup(QQuickFlickablePrivate::AxisData &data, qreal QQuickFlickablePrivate::fixup(data, minExtent, maxExtent); } -int QQuickTableViewPrivate::resolveImportVersion() +QTypeRevision QQuickTableViewPrivate::resolveImportVersion() { const auto data = QQmlData::get(q_func()); if (!data || !data->propertyCache) - return 0; + return QTypeRevision::zero(); const auto cppMetaObject = data->propertyCache->firstCppMetaObject(); const auto qmlTypeView = QQmlMetaType::qmlType(cppMetaObject); - return qmlTypeView.minorVersion(); + + // TODO: did we rather want qmlTypeView.revision() here? + return qmlTypeView.metaObjectRevision(); } void QQuickTableViewPrivate::createWrapperModel() @@ -2350,14 +2361,11 @@ void QQuickTableViewPrivate::connectToModel() QObjectPrivate::connect(model, &QQmlInstanceModel::createdItem, this, &QQuickTableViewPrivate::itemCreatedCallback); QObjectPrivate::connect(model, &QQmlInstanceModel::initItem, this, &QQuickTableViewPrivate::initItemCallback); + QObjectPrivate::connect(model, &QQmlTableInstanceModel::itemPooled, this, &QQuickTableViewPrivate::itemPooledCallback); + QObjectPrivate::connect(model, &QQmlTableInstanceModel::itemReused, this, &QQuickTableViewPrivate::itemReusedCallback); - if (tableModel) { - const auto tm = tableModel.data(); - QObjectPrivate::connect(tm, &QQmlTableInstanceModel::itemPooled, this, &QQuickTableViewPrivate::itemPooledCallback); - QObjectPrivate::connect(tm, &QQmlTableInstanceModel::itemReused, this, &QQuickTableViewPrivate::itemReusedCallback); - // Connect atYEndChanged to a function that fetches data if more is available - QObjectPrivate::connect(q, &QQuickTableView::atYEndChanged, this, &QQuickTableViewPrivate::fetchMoreData); - } + // Connect atYEndChanged to a function that fetches data if more is available + QObjectPrivate::connect(q, &QQuickTableView::atYEndChanged, this, &QQuickTableViewPrivate::fetchMoreData); if (auto const aim = model->abstractItemModel()) { // When the model exposes a QAIM, we connect to it directly. This means that if the current model is @@ -2385,13 +2393,10 @@ void QQuickTableViewPrivate::disconnectFromModel() QObjectPrivate::disconnect(model, &QQmlInstanceModel::createdItem, this, &QQuickTableViewPrivate::itemCreatedCallback); QObjectPrivate::disconnect(model, &QQmlInstanceModel::initItem, this, &QQuickTableViewPrivate::initItemCallback); + QObjectPrivate::disconnect(model, &QQmlTableInstanceModel::itemPooled, this, &QQuickTableViewPrivate::itemPooledCallback); + QObjectPrivate::disconnect(model, &QQmlTableInstanceModel::itemReused, this, &QQuickTableViewPrivate::itemReusedCallback); - if (tableModel) { - const auto tm = tableModel.data(); - QObjectPrivate::disconnect(tm, &QQmlTableInstanceModel::itemPooled, this, &QQuickTableViewPrivate::itemPooledCallback); - QObjectPrivate::disconnect(tm, &QQmlTableInstanceModel::itemReused, this, &QQuickTableViewPrivate::itemReusedCallback); - QObjectPrivate::disconnect(q, &QQuickTableView::atYEndChanged, this, &QQuickTableViewPrivate::fetchMoreData); - } + QObjectPrivate::disconnect(q, &QQuickTableView::atYEndChanged, this, &QQuickTableViewPrivate::fetchMoreData); if (auto const aim = model->abstractItemModel()) { disconnect(aim, &QAbstractItemModel::rowsMoved, this, &QQuickTableViewPrivate::rowsMovedCallback); diff --git a/src/quick/items/qquicktableview_p.h b/src/quick/items/qquicktableview_p.h index d549aaddf7..c71e74bfdc 100644 --- a/src/quick/items/qquicktableview_p.h +++ b/src/quick/items/qquicktableview_p.h @@ -79,11 +79,11 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTableView : public QQuickFlickable Q_PROPERTY(bool reuseItems READ reuseItems WRITE setReuseItems NOTIFY reuseItemsChanged) Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth NOTIFY contentWidthChanged) Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight NOTIFY contentHeightChanged) - Q_PROPERTY(QQuickTableView *syncView READ syncView WRITE setSyncView NOTIFY syncViewChanged REVISION 14) - Q_PROPERTY(Qt::Orientations syncDirection READ syncDirection WRITE setSyncDirection NOTIFY syncDirectionChanged REVISION 14) + Q_PROPERTY(QQuickTableView *syncView READ syncView WRITE setSyncView NOTIFY syncViewChanged REVISION(2, 14)) + Q_PROPERTY(Qt::Orientations syncDirection READ syncDirection WRITE setSyncDirection NOTIFY syncDirectionChanged REVISION(2, 14)) QML_NAMED_ELEMENT(TableView) - QML_ADDED_IN_MINOR_VERSION(12) + QML_ADDED_IN_VERSION(2, 12) QML_ATTACHED(QQuickTableViewAttached) public: @@ -136,8 +136,8 @@ Q_SIGNALS: void modelChanged(); void delegateChanged(); void reuseItemsChanged(); - Q_REVISION(14) void syncViewChanged(); - Q_REVISION(14) void syncDirectionChanged(); + Q_REVISION(2, 14) void syncViewChanged(); + Q_REVISION(2, 14) void syncDirectionChanged(); protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; diff --git a/src/quick/items/qquicktableview_p_p.h b/src/quick/items/qquicktableview_p_p.h index c629ae0a5d..a3cc39419f 100644 --- a/src/quick/items/qquicktableview_p_p.h +++ b/src/quick/items/qquicktableview_p_p.h @@ -91,7 +91,7 @@ private: Q_DECLARE_PRIVATE(QQuickTableSectionSizeProvider) }; -class Q_QML_AUTOTEST_EXPORT QQuickTableViewPrivate : public QQuickFlickablePrivate +class Q_QUICK_PRIVATE_EXPORT QQuickTableViewPrivate : public QQuickFlickablePrivate { Q_DECLARE_PUBLIC(QQuickTableView) @@ -395,7 +395,7 @@ public: void scheduleRebuildTable(QQuickTableViewPrivate::RebuildOptions options); - int resolveImportVersion(); + QTypeRevision resolveImportVersion(); void createWrapperModel(); void initItemCallback(int modelIndex, QObject *item); diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index 2a6337cdb3..c8f3f113dd 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -40,6 +40,9 @@ #include "qquicktext_p.h" #include "qquicktext_p_p.h" +#include <private/qqmldebugserviceinterfaces_p.h> +#include <private/qqmldebugconnector_p.h> + #include <QtQuick/private/qsgcontext_p.h> #include <private/qqmlglobal_p.h> #include <private/qsgadaptationlayer_p.h> @@ -1146,6 +1149,10 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline) elideLayout->setFont(layout.font()); elideLayout->setTextOption(layout.textOption()); + if (QQmlDebugTranslationService *service + = QQmlDebugConnector::service<QQmlDebugTranslationService>()) { + elideText = service->foundElidedText(q, layoutText, elideText); + } elideLayout->setText(elideText); elideLayout->beginLayout(); @@ -1212,7 +1219,7 @@ void QQuickTextPrivate::setLineGeometry(QTextLine &line, qreal lineWidth, qreal if (!image->pix) { QUrl url = q->baseUrl().resolved(image->url); - image->pix = new QQuickPixmap(qmlEngine(q), url, image->size); + image->pix = new QQuickPixmap(qmlEngine(q), url, QRect(), image->size); if (image->pix->isLoading()) { image->pix->connectFinished(q, SLOT(imageDownloadFinished())); if (!extra.isAllocated() || !extra->nbActiveDownloads) @@ -2642,6 +2649,12 @@ void QQuickText::setLineHeightMode(LineHeightMode mode) If the text does not fit within the item bounds with the minimum font size the text will be elided as per the \l elide property. + + If the \l textFormat property is set to \l Text.RichText, this will have no effect at all as the + property will be ignored completely. If \l textFormat is set to \l Text.StyledText, then the + property will be respected provided there is no font size tags inside the text. If there are + font size tags, the property will still respect those. This can cause it to not fully comply with + the fontSizeMode setting. */ QQuickText::FontSizeMode QQuickText::fontSizeMode() const @@ -2961,6 +2974,8 @@ void QQuickText::setRenderType(QQuickText::RenderType renderType) d->updateLayout(); } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +#if QT_DEPRECATED_SINCE(5, 15) /*! \qmlmethod QtQuick::Text::doLayout() \deprecated @@ -2972,6 +2987,8 @@ void QQuickText::doLayout() forceLayout(); } +#endif +#endif /*! \qmlmethod QtQuick::Text::forceLayout() \since 5.9 diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h index d310db508e..6c04f63ca9 100644 --- a/src/quick/items/qquicktext_p.h +++ b/src/quick/items/qquicktext_p.h @@ -90,17 +90,18 @@ class Q_QUICK_PRIVATE_EXPORT QQuickText : public QQuickImplicitSizeItem Q_PROPERTY(int minimumPointSize READ minimumPointSize WRITE setMinimumPointSize NOTIFY minimumPointSizeChanged) Q_PROPERTY(FontSizeMode fontSizeMode READ fontSizeMode WRITE setFontSizeMode NOTIFY fontSizeModeChanged) Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged) - Q_PROPERTY(QString hoveredLink READ hoveredLink NOTIFY linkHovered REVISION 2) + Q_PROPERTY(QString hoveredLink READ hoveredLink NOTIFY linkHovered REVISION(2, 2)) - Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6) - Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6) - Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION 6) - Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION 6) - Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6) + Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION(2, 6)) + Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION(2, 6)) + Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION(2, 6)) + Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION(2, 6)) + Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION(2, 6)) - Q_PROPERTY(QJSValue fontInfo READ fontInfo NOTIFY fontInfoChanged REVISION 9) - Q_PROPERTY(QSizeF advance READ advance NOTIFY contentSizeChanged REVISION 10) + Q_PROPERTY(QJSValue fontInfo READ fontInfo NOTIFY fontInfoChanged REVISION(2, 9)) + Q_PROPERTY(QSizeF advance READ advance NOTIFY contentSizeChanged REVISION(2, 10)) QML_NAMED_ELEMENT(Text) + QML_ADDED_IN_VERSION(2, 0) public: QQuickText(QQuickItem *parent=nullptr); @@ -223,15 +224,20 @@ public: QRectF boundingRect() const override; QRectF clipRect() const override; - Q_INVOKABLE void doLayout(); // ### Qt 6: remove - Q_REVISION(9) Q_INVOKABLE void forceLayout(); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +#if QT_DEPRECATED_SINCE(5, 15) + QT_DEPRECATED_X("Use forceLayout() instead") + Q_INVOKABLE void doLayout(); +#endif +#endif + Q_REVISION(2, 9) Q_INVOKABLE void forceLayout(); RenderType renderType() const; void setRenderType(RenderType renderType); QString hoveredLink() const; - Q_REVISION(3) Q_INVOKABLE QString linkAt(qreal x, qreal y) const; + Q_REVISION(2, 3) Q_INVOKABLE QString linkAt(qreal x, qreal y) const; qreal padding() const; void setPadding(qreal padding); @@ -259,7 +265,7 @@ public: Q_SIGNALS: void textChanged(const QString &text); void linkActivated(const QString &link); - Q_REVISION(2) void linkHovered(const QString &link); + Q_REVISION(2, 2) void linkHovered(const QString &link); void fontChanged(const QFont &font); void colorChanged(); void linkColorChanged(); @@ -274,7 +280,7 @@ Q_SIGNALS: void textFormatChanged(QQuickText::TextFormat textFormat); void elideModeChanged(QQuickText::TextElideMode mode); void contentSizeChanged(); - // The next two signals should be marked as Q_REVISION(12). See QTBUG-71247 + // The next two signals should be marked as Q_REVISION(2, 12). See QTBUG-71247 void contentWidthChanged(qreal contentWidth); void contentHeightChanged(qreal contentHeight); @@ -287,12 +293,12 @@ Q_SIGNALS: void lineLaidOut(QQuickTextLine *line); void baseUrlChanged(); void renderTypeChanged(); - Q_REVISION(6) void paddingChanged(); - Q_REVISION(6) void topPaddingChanged(); - Q_REVISION(6) void leftPaddingChanged(); - Q_REVISION(6) void rightPaddingChanged(); - Q_REVISION(6) void bottomPaddingChanged(); - Q_REVISION(9) void fontInfoChanged(); + Q_REVISION(2, 6) void paddingChanged(); + Q_REVISION(2, 6) void topPaddingChanged(); + Q_REVISION(2, 6) void leftPaddingChanged(); + Q_REVISION(2, 6) void rightPaddingChanged(); + Q_REVISION(2, 6) void bottomPaddingChanged(); + Q_REVISION(2, 9) void fontInfoChanged(); protected: QQuickText(QQuickTextPrivate &dd, QQuickItem *parent = nullptr); @@ -330,9 +336,10 @@ class QQuickTextLine : public QObject Q_PROPERTY(qreal height READ height WRITE setHeight) Q_PROPERTY(qreal x READ x WRITE setX) Q_PROPERTY(qreal y READ y WRITE setY) - Q_PROPERTY(qreal implicitWidth READ implicitWidth) - Q_PROPERTY(bool isLast READ isLast) + Q_PROPERTY(qreal implicitWidth READ implicitWidth REVISION(2, 15)) + Q_PROPERTY(bool isLast READ isLast REVISION(2, 15)) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQuickTextLine(); diff --git a/src/quick/items/qquicktextdocument.h b/src/quick/items/qquicktextdocument.h index bf9162755c..aadc4ca8c0 100644 --- a/src/quick/items/qquicktextdocument.h +++ b/src/quick/items/qquicktextdocument.h @@ -50,6 +50,7 @@ class Q_QUICK_EXPORT QQuickTextDocument : public QObject { Q_OBJECT QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQuickTextDocument(QQuickItem *parent); diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h index 227d8cbf51..37610ed7e6 100644 --- a/src/quick/items/qquicktextedit_p.h +++ b/src/quick/items/qquicktextedit_p.h @@ -94,7 +94,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem Q_PROPERTY(bool persistentSelection READ persistentSelection WRITE setPersistentSelection NOTIFY persistentSelectionChanged) Q_PROPERTY(qreal textMargin READ textMargin WRITE setTextMargin NOTIFY textMarginChanged) Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints NOTIFY inputMethodHintsChanged) - Q_PROPERTY(bool selectByKeyboard READ selectByKeyboard WRITE setSelectByKeyboard NOTIFY selectByKeyboardChanged REVISION 1) + Q_PROPERTY(bool selectByKeyboard READ selectByKeyboard WRITE setSelectByKeyboard NOTIFY selectByKeyboardChanged REVISION(2, 1)) Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged) Q_PROPERTY(SelectionMode mouseSelectionMode READ mouseSelectionMode WRITE setMouseSelectionMode NOTIFY mouseSelectionModeChanged) Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged) @@ -103,16 +103,17 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged) Q_PROPERTY(QUrl baseUrl READ baseUrl WRITE setBaseUrl RESET resetBaseUrl NOTIFY baseUrlChanged) Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged) - Q_PROPERTY(QQuickTextDocument *textDocument READ textDocument CONSTANT FINAL REVISION 1) - Q_PROPERTY(QString hoveredLink READ hoveredLink NOTIFY linkHovered REVISION 2) - Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6) - Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6) - Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION 6) - Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION 6) - Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6) - Q_PROPERTY(QString preeditText READ preeditText NOTIFY preeditTextChanged REVISION 7) - Q_PROPERTY(qreal tabStopDistance READ tabStopDistance WRITE setTabStopDistance NOTIFY tabStopDistanceChanged REVISION 10) + Q_PROPERTY(QQuickTextDocument *textDocument READ textDocument CONSTANT FINAL REVISION(2, 1)) + Q_PROPERTY(QString hoveredLink READ hoveredLink NOTIFY linkHovered REVISION(2, 2)) + Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION(2, 6)) + Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION(2, 6)) + Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION(2, 6)) + Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION(2, 6)) + Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION(2, 6)) + Q_PROPERTY(QString preeditText READ preeditText NOTIFY preeditTextChanged REVISION(2, 7)) + Q_PROPERTY(qreal tabStopDistance READ tabStopDistance WRITE setTabStopDistance NOTIFY tabStopDistanceChanged REVISION(2, 10)) QML_NAMED_ELEMENT(TextEdit) + QML_ADDED_IN_VERSION(2, 0) public: QQuickTextEdit(QQuickItem *parent=nullptr); @@ -162,7 +163,7 @@ public: QString text() const; void setText(const QString &); - Q_REVISION(7) QString preeditText() const; + Q_REVISION(2, 7) QString preeditText() const; TextFormat textFormat() const; void setTextFormat(TextFormat format); @@ -247,7 +248,7 @@ public: #if QT_CONFIG(im) QVariant inputMethodQuery(Qt::InputMethodQuery property) const override; - Q_REVISION(4) Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery query, QVariant argument) const; + Q_REVISION(2, 4) Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery query, QVariant argument) const; #endif qreal contentWidth() const; @@ -277,7 +278,7 @@ public: QString hoveredLink() const; - Q_REVISION(3) Q_INVOKABLE QString linkAt(qreal x, qreal y) const; + Q_REVISION(2, 3) Q_INVOKABLE QString linkAt(qreal x, qreal y) const; qreal padding() const; void setPadding(qreal padding); @@ -304,7 +305,7 @@ public: Q_SIGNALS: void textChanged(); - Q_REVISION(7) void preeditTextChanged(); + Q_REVISION(2, 7) void preeditTextChanged(); void contentSizeChanged(); void cursorPositionChanged(); void cursorRectangleChanged(); @@ -327,11 +328,11 @@ Q_SIGNALS: void activeFocusOnPressChanged(bool activeFocusOnPressed); void persistentSelectionChanged(bool isPersistentSelection); void textMarginChanged(qreal textMargin); - Q_REVISION(1) void selectByKeyboardChanged(bool selectByKeyboard); + Q_REVISION(2, 1) void selectByKeyboardChanged(bool selectByKeyboard); void selectByMouseChanged(bool selectByMouse); void mouseSelectionModeChanged(QQuickTextEdit::SelectionMode mode); void linkActivated(const QString &link); - Q_REVISION(2) void linkHovered(const QString &link); + Q_REVISION(2, 2) void linkHovered(const QString &link); void canPasteChanged(); void canUndoChanged(); void canRedoChanged(); @@ -340,13 +341,13 @@ Q_SIGNALS: void baseUrlChanged(); void inputMethodHintsChanged(); void renderTypeChanged(); - Q_REVISION(6) void editingFinished(); - Q_REVISION(6) void paddingChanged(); - Q_REVISION(6) void topPaddingChanged(); - Q_REVISION(6) void leftPaddingChanged(); - Q_REVISION(6) void rightPaddingChanged(); - Q_REVISION(6) void bottomPaddingChanged(); - Q_REVISION(10) void tabStopDistanceChanged(qreal distance); + Q_REVISION(2, 6) void editingFinished(); + Q_REVISION(2, 6) void paddingChanged(); + Q_REVISION(2, 6) void topPaddingChanged(); + Q_REVISION(2, 6) void leftPaddingChanged(); + Q_REVISION(2, 6) void rightPaddingChanged(); + Q_REVISION(2, 6) void bottomPaddingChanged(); + Q_REVISION(2, 10) void tabStopDistanceChanged(qreal distance); public Q_SLOTS: void selectAll(); @@ -363,8 +364,8 @@ public Q_SLOTS: void redo(); void insert(int position, const QString &text); void remove(int start, int end); - Q_REVISION(2) void append(const QString &text); - Q_REVISION(7) void clear(); + Q_REVISION(2, 2) void append(const QString &text); + Q_REVISION(2, 7) void clear(); private Q_SLOTS: void q_textChanged(); diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index 1f6f24e419..b204cb3417 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -4694,6 +4694,18 @@ void QQuickTextInput::clear() These properties hold the padding around the content. This space is reserved in addition to the contentWidth and contentHeight. + + The individual padding properties assume the value of the \c padding + property unless they are set explicitly. For example, if \c padding is + set to \c 4 and \c leftPadding to \c 8, \c 8 will be used as the left + padding. + + \note If an explicit width or height is given to a TextInput, care must be + taken to ensure it is large enough to accommodate the relevant padding + values. For example: if \c topPadding and \c bottomPadding are set to + \c 10, but the height of the TextInput is only set to \c 20, the text will + not have enough vertical space in which to be rendered, and will appear + clipped. */ qreal QQuickTextInput::padding() const { diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h index 9f7b82b168..234ebc2a0a 100644 --- a/src/quick/items/qquicktextinput_p.h +++ b/src/quick/items/qquicktextinput_p.h @@ -93,9 +93,9 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextInput : public QQuickImplicitSizeItem Q_PROPERTY(EchoMode echoMode READ echoMode WRITE setEchoMode NOTIFY echoModeChanged) Q_PROPERTY(bool activeFocusOnPress READ focusOnPress WRITE setFocusOnPress NOTIFY activeFocusOnPressChanged) Q_PROPERTY(QString passwordCharacter READ passwordCharacter WRITE setPasswordCharacter NOTIFY passwordCharacterChanged) - Q_PROPERTY(int passwordMaskDelay READ passwordMaskDelay WRITE setPasswordMaskDelay RESET resetPasswordMaskDelay NOTIFY passwordMaskDelayChanged REVISION 4) + Q_PROPERTY(int passwordMaskDelay READ passwordMaskDelay WRITE setPasswordMaskDelay RESET resetPasswordMaskDelay NOTIFY passwordMaskDelayChanged REVISION(2, 4)) Q_PROPERTY(QString displayText READ displayText NOTIFY displayTextChanged) - Q_PROPERTY(QString preeditText READ preeditText NOTIFY preeditTextChanged REVISION 7) + Q_PROPERTY(QString preeditText READ preeditText NOTIFY preeditTextChanged REVISION(2, 7)) Q_PROPERTY(bool autoScroll READ autoScroll WRITE setAutoScroll NOTIFY autoScrollChanged) Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged) Q_PROPERTY(SelectionMode mouseSelectionMode READ mouseSelectionMode WRITE setMouseSelectionMode NOTIFY mouseSelectionModeChanged) @@ -108,12 +108,13 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextInput : public QQuickImplicitSizeItem Q_PROPERTY(qreal contentHeight READ contentHeight NOTIFY contentSizeChanged) Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged) - Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6) - Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6) - Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION 6) - Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION 6) - Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6) + Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION(2, 6)) + Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION(2, 6)) + Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION(2, 6)) + Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION(2, 6)) + Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION(2, 6)) QML_NAMED_ELEMENT(TextInput) + QML_ADDED_IN_VERSION(2, 0) public: QQuickTextInput(QQuickItem * parent=nullptr); @@ -242,7 +243,7 @@ public: void resetPasswordMaskDelay(); QString displayText() const; - Q_REVISION(7) QString preeditText() const; + Q_REVISION(2, 7) QString preeditText() const; QQmlComponent* cursorDelegate() const; void setCursorDelegate(QQmlComponent*); @@ -269,7 +270,7 @@ public: #if QT_CONFIG(im) QVariant inputMethodQuery(Qt::InputMethodQuery property) const override; - Q_REVISION(4) Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery query, const QVariant &argument) const; + Q_REVISION(2, 4) Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery query, const QVariant &argument) const; #endif QRectF boundingRect() const override; @@ -319,8 +320,8 @@ Q_SIGNALS: void selectedTextChanged(); void accepted(); void acceptableInputChanged(); - Q_REVISION(2) void editingFinished(); - Q_REVISION(9) void textEdited(); + Q_REVISION(2, 2) void editingFinished(); + Q_REVISION(2, 9) void textEdited(); void colorChanged(); void selectionColorChanged(); void selectedTextColorChanged(); @@ -337,9 +338,9 @@ Q_SIGNALS: void inputMaskChanged(const QString &inputMask); void echoModeChanged(QQuickTextInput::EchoMode echoMode); void passwordCharacterChanged(); - Q_REVISION(4) void passwordMaskDelayChanged(int delay); + Q_REVISION(2, 4) void passwordMaskDelayChanged(int delay); void displayTextChanged(); - Q_REVISION(7) void preeditTextChanged(); + Q_REVISION(2, 7) void preeditTextChanged(); void activeFocusOnPressChanged(bool activeFocusOnPress); void autoScrollChanged(bool autoScroll); void selectByMouseChanged(bool selectByMouse); @@ -353,11 +354,11 @@ Q_SIGNALS: void contentSizeChanged(); void inputMethodHintsChanged(); void renderTypeChanged(); - Q_REVISION(6) void paddingChanged(); - Q_REVISION(6) void topPaddingChanged(); - Q_REVISION(6) void leftPaddingChanged(); - Q_REVISION(6) void rightPaddingChanged(); - Q_REVISION(6) void bottomPaddingChanged(); + Q_REVISION(2, 6) void paddingChanged(); + Q_REVISION(2, 6) void topPaddingChanged(); + Q_REVISION(2, 6) void leftPaddingChanged(); + Q_REVISION(2, 6) void rightPaddingChanged(); + Q_REVISION(2, 6) void bottomPaddingChanged(); private: void invalidateFontCaches(); @@ -400,8 +401,8 @@ public Q_SLOTS: void redo(); void insert(int position, const QString &text); void remove(int start, int end); - Q_REVISION(4) void ensureVisible(int position); - Q_REVISION(7) void clear(); + Q_REVISION(2, 4) void ensureVisible(int position); + Q_REVISION(2, 7) void clear(); private Q_SLOTS: void selectionChanged(); diff --git a/src/quick/items/qquicktranslate_p.h b/src/quick/items/qquicktranslate_p.h index aeda6ca589..9832989e73 100644 --- a/src/quick/items/qquicktranslate_p.h +++ b/src/quick/items/qquicktranslate_p.h @@ -65,6 +65,7 @@ class Q_AUTOTEST_EXPORT QQuickTranslate : public QQuickTransform Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged) Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged) QML_NAMED_ELEMENT(Translate) + QML_ADDED_IN_VERSION(2, 0) public: QQuickTranslate(QObject *parent = nullptr); @@ -97,6 +98,7 @@ class Q_AUTOTEST_EXPORT QQuickScale : public QQuickTransform Q_PROPERTY(qreal yScale READ yScale WRITE setYScale NOTIFY yScaleChanged) Q_PROPERTY(qreal zScale READ zScale WRITE setZScale NOTIFY zScaleChanged) QML_NAMED_ELEMENT(Scale) + QML_ADDED_IN_VERSION(2, 0) public: QQuickScale(QObject *parent = nullptr); ~QQuickScale(); @@ -135,6 +137,7 @@ class Q_AUTOTEST_EXPORT QQuickRotation : public QQuickTransform Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged) Q_PROPERTY(QVector3D axis READ axis WRITE setAxis NOTIFY axisChanged) QML_NAMED_ELEMENT(Rotation) + QML_ADDED_IN_VERSION(2, 0) public: QQuickRotation(QObject *parent = nullptr); ~QQuickRotation(); @@ -167,7 +170,7 @@ class Q_AUTOTEST_EXPORT QQuickMatrix4x4 : public QQuickTransform Q_PROPERTY(QMatrix4x4 matrix READ matrix WRITE setMatrix NOTIFY matrixChanged) QML_NAMED_ELEMENT(Matrix4x4) - QML_ADDED_IN_MINOR_VERSION(3) + QML_ADDED_IN_VERSION(2, 3) public: QQuickMatrix4x4(QObject *parent = nullptr); ~QQuickMatrix4x4(); diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 2eee98a738..39f238e4ed 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -78,8 +78,11 @@ #include <private/qqmldebugserviceinterfaces_p.h> #include <private/qqmldebugconnector_p.h> #if QT_CONFIG(opengl) -# include <private/qopenglvertexarrayobject_p.h> -# include <private/qsgdefaultrendercontext_p.h> +#include <private/qopenglvertexarrayobject_p.h> +#include <private/qsgdefaultrendercontext_p.h> +#include <private/qopengl_p.h> +#include <QOpenGLContext> +#include <QOpenGLFramebufferObject> #endif #ifndef QT_NO_DEBUG_STREAM #include <private/qdebug_p.h> @@ -93,6 +96,7 @@ Q_LOGGING_CATEGORY(DBG_TOUCH, "qt.quick.touch") Q_LOGGING_CATEGORY(DBG_TOUCH_TARGET, "qt.quick.touch.target") Q_LOGGING_CATEGORY(DBG_MOUSE, "qt.quick.mouse") Q_LOGGING_CATEGORY(DBG_MOUSE_TARGET, "qt.quick.mouse.target") +Q_LOGGING_CATEGORY(lcTablet, "qt.quick.tablet") Q_LOGGING_CATEGORY(lcWheelTarget, "qt.quick.wheel.target") Q_LOGGING_CATEGORY(lcGestureTarget, "qt.quick.gesture.target") Q_LOGGING_CATEGORY(DBG_HOVER_TRACE, "qt.quick.hover.trace") @@ -547,7 +551,7 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size, const QSize &surfa else context->endNextFrame(renderer); - if (renderer->hasCustomRenderModeWithContinuousUpdate()) { + if (renderer && renderer->hasCustomRenderModeWithContinuousUpdate()) { // For the overdraw visualizer. This update is not urgent so avoid a // direct update() call, this is only here to keep the overdraw // visualization box rotating even when the scene is static. @@ -560,6 +564,7 @@ QQuickWindowPrivate::QQuickWindowPrivate() , activeFocusItem(nullptr) #if QT_CONFIG(cursor) , cursorItem(nullptr) + , cursorHandler(nullptr) #endif #if QT_CONFIG(quick_draganddrop) , dragGrabber(nullptr) @@ -681,10 +686,13 @@ void QQuickWindow::handleApplicationStateChanged(Qt::ApplicationState state) QQmlListProperty<QObject> QQuickWindowPrivate::data() { - return QQmlListProperty<QObject>(q_func(), nullptr, QQuickWindowPrivate::data_append, - QQuickWindowPrivate::data_count, - QQuickWindowPrivate::data_at, - QQuickWindowPrivate::data_clear); + return QQmlListProperty<QObject>(q_func(), nullptr, + QQuickWindowPrivate::data_append, + QQuickWindowPrivate::data_count, + QQuickWindowPrivate::data_at, + QQuickWindowPrivate::data_clear, + QQuickWindowPrivate::data_replace, + QQuickWindowPrivate::data_removeLast); } static QMouseEvent *touchToMouseEvent(QEvent::Type type, const QTouchEvent::TouchPoint &p, QTouchEvent *event, QQuickItem *item, bool transformNeeded = true) @@ -1762,6 +1770,10 @@ bool QQuickWindow::event(QEvent *e) if (d->activeFocusItem) QCoreApplication::sendEvent(d->activeFocusItem, e); return true; + case QEvent::LanguageChange: + if (d->contentItem) + QCoreApplication::sendEvent(d->contentItem, e); + break; default: break; } @@ -2118,6 +2130,17 @@ void QQuickWindow::wheelEvent(QWheelEvent *event) } #endif // wheelevent +#if QT_CONFIG(tabletevent) +/*! \reimp */ +void QQuickWindow::tabletEvent(QTabletEvent *event) +{ + Q_D(QQuickWindow); + qCDebug(lcTablet) << event; + // TODO Qt 6: make sure TabletEnterProximity and TabletLeaveProximity are delivered here + d->deliverPointerEvent(d->pointerEventInstance(event)); +} +#endif // tabletevent + bool QQuickWindowPrivate::deliverTouchCancelEvent(QTouchEvent *event) { qCDebug(DBG_TOUCH) << event; @@ -2396,8 +2419,14 @@ 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: - // TODO tablet event types break; } pointerEventInstances << ev; @@ -2428,7 +2457,15 @@ QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QEvent *event) con case QEvent::TouchCancel: dev = QQuickPointerDevice::touchDevice(static_cast<QTouchEvent *>(event)->device()); break; - // TODO tablet event types +#if QT_CONFIG(tabletevent) + case QEvent::TabletPress: + case QEvent::TabletMove: + case QEvent::TabletRelease: + case QEvent::TabletEnterProximity: + case QEvent::TabletLeaveProximity: + dev = QQuickPointerDevice::tabletDevice(static_cast<QTabletEvent *>(event)); + break; +#endif #if QT_CONFIG(gestures) case QEvent::NativeGesture: dev = QQuickPointerDevice::touchDevice(static_cast<QNativeGestureEvent *>(event)->device()); @@ -2463,6 +2500,11 @@ void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event) deliverTouchEvent(event->asPointerTouchEvent()); } else { deliverSinglePointEventUntilAccepted(event); + // If any handler got interested in the tablet event, we don't want to receive a synth-mouse event from QtGui + // TODO Qt 6: QTabletEvent will be accepted by default, like other events + if (event->asPointerTabletEvent() && + (!event->point(0)->passiveGrabbers().isEmpty() || event->point(0)->exclusiveGrabber())) + event->setAccepted(true); } event->reset(nullptr); @@ -2967,26 +3009,27 @@ void QQuickWindowPrivate::updateCursor(const QPointF &scenePos) { Q_Q(QQuickWindow); - QQuickItem *oldCursorItem = cursorItem; - cursorItem = findCursorItem(contentItem, scenePos); + auto cursorItemAndHandler = findCursorItemAndHandler(contentItem, scenePos); - if (cursorItem != oldCursorItem) { + if (cursorItem != cursorItemAndHandler.first || cursorHandler != cursorItemAndHandler.second) { QWindow *renderWindow = QQuickRenderControl::renderWindowFor(q); QWindow *window = renderWindow ? renderWindow : q; + cursorItem = cursorItemAndHandler.first; + cursorHandler = cursorItemAndHandler.second; if (cursorItem) - window->setCursor(cursorItem->cursor()); + window->setCursor(QQuickItemPrivate::get(cursorItem)->effectiveCursor(cursorHandler)); else window->unsetCursor(); } } -QQuickItem *QQuickWindowPrivate::findCursorItem(QQuickItem *item, const QPointF &scenePos) +QPair<QQuickItem*, QQuickPointerHandler*> QQuickWindowPrivate::findCursorItemAndHandler(QQuickItem *item, const QPointF &scenePos) const { QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) { QPointF p = item->mapFromScene(scenePos); if (!item->contains(p)) - return nullptr; + return {nullptr, nullptr}; } if (itemPrivate->subtreeCursorEnabled) { @@ -2995,17 +3038,24 @@ QQuickItem *QQuickWindowPrivate::findCursorItem(QQuickItem *item, const QPointF QQuickItem *child = children.at(ii); if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled) continue; - if (QQuickItem *cursorItem = findCursorItem(child, scenePos)) - return cursorItem; + auto ret = findCursorItemAndHandler(child, scenePos); + if (ret.first) + return ret; + } + if (itemPrivate->hasCursor || itemPrivate->hasCursorHandler) { + QPointF p = item->mapFromScene(scenePos); + if (!item->contains(p)) + return {nullptr, nullptr}; + if (itemPrivate->hasCursorHandler) { + if (auto handler = itemPrivate->effectiveCursorHandler()) + return {item, handler}; + } + if (itemPrivate->hasCursor) + return {item, nullptr}; } } - if (itemPrivate->hasCursor) { - QPointF p = item->mapFromScene(scenePos); - if (item->contains(p)) - return item; - } - return nullptr; + return {nullptr, nullptr}; } #endif @@ -3248,6 +3298,20 @@ void QQuickWindowPrivate::data_clear(QQmlListProperty<QObject> *property) itemProperty.clear(&itemProperty); } +void QQuickWindowPrivate::data_replace(QQmlListProperty<QObject> *property, int i, QObject *o) +{ + QQuickWindow *win = static_cast<QQuickWindow*>(property->object); + QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data(); + itemProperty.replace(&itemProperty, i, o); +} + +void QQuickWindowPrivate::data_removeLast(QQmlListProperty<QObject> *property) +{ + QQuickWindow *win = static_cast<QQuickWindow*>(property->object); + QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data(); + itemProperty.removeLast(&itemProperty); +} + bool QQuickWindowPrivate::isRenderable() const { Q_Q(const QQuickWindow); @@ -4377,7 +4441,7 @@ QQmlIncubationController *QQuickWindow::incubationController() const OpenGL context is actually created. QQuickWindow::openglContext() will still return 0 for this window - until after the QQuickWindow::sceneGraphInitialize() has been + until after the QQuickWindow::sceneGraphInitialized() has been emitted. \note @@ -4513,7 +4577,7 @@ QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image, CreateText } - +#if QT_DEPRECATED_SINCE(5, 15) /*! Creates a new QSGTexture object from an existing OpenGL texture \a id and \a size. @@ -4535,6 +4599,8 @@ QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image, CreateText \note This function has no effect when running on the RHI graphics abstraction. Use createTextureFromNativeObject() instead. + \obsolete + \sa sceneGraphInitialized(), QSGTexture */ QSGTexture *QQuickWindow::createTextureFromId(uint id, const QSize &size, CreateTextureOptions options) const @@ -4561,6 +4627,7 @@ QSGTexture *QQuickWindow::createTextureFromId(uint id, const QSize &size, Create #endif return nullptr; } +#endif /*! \enum QQuickWindow::NativeObjectType diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h index 56d50cec2a..bba8c014c8 100644 --- a/src/quick/items/qquickwindow.h +++ b/src/quick/items/qquickwindow.h @@ -43,7 +43,7 @@ #include <QtQuick/qtquickglobal.h> #include <QtQuick/qsgrendererinterface.h> #include <QtCore/qmetatype.h> -#include <QtGui/qopengl.h> +#include <qopengl.h> #include <QtGui/qwindow.h> #include <QtGui/qevent.h> #include <QtQml/qqml.h> @@ -74,7 +74,7 @@ class Q_QUICK_EXPORT QQuickWindow : public QWindow Q_PRIVATE_PROPERTY(QQuickWindow::d_func(), QQmlListProperty<QObject> data READ data DESIGNABLE false) Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) Q_PROPERTY(QQuickItem* contentItem READ contentItem CONSTANT) - Q_PROPERTY(QQuickItem* activeFocusItem READ activeFocusItem NOTIFY activeFocusItemChanged REVISION 1) + Q_PROPERTY(QQuickItem* activeFocusItem READ activeFocusItem NOTIFY activeFocusItemChanged REVISION(2, 1)) Q_CLASSINFO("DefaultProperty", "data") Q_DECLARE_PRIVATE(QQuickWindow) public: @@ -157,7 +157,12 @@ public: // Scene graph specific functions QSGTexture *createTextureFromImage(const QImage &image) const; QSGTexture *createTextureFromImage(const QImage &image, CreateTextureOptions options) const; + +#if QT_DEPRECATED_SINCE(5, 15) + QT_DEPRECATED_X("Use createTextureFromNativeObject() instead") QSGTexture *createTextureFromId(uint id, const QSize &size, CreateTextureOptions options = CreateTextureOption()) const; +#endif + QSGTexture *createTextureFromNativeObject(NativeObjectType type, const void *nativeObjectPtr, int nativeLayout, @@ -201,23 +206,23 @@ public: Q_SIGNALS: void frameSwapped(); - Q_REVISION(2) void openglContextCreated(QOpenGLContext *context); + Q_REVISION(2, 2) void openglContextCreated(QOpenGLContext *context); void sceneGraphInitialized(); void sceneGraphInvalidated(); void beforeSynchronizing(); - Q_REVISION(2) void afterSynchronizing(); + Q_REVISION(2, 2) void afterSynchronizing(); void beforeRendering(); void afterRendering(); - Q_REVISION(2) void afterAnimating(); - Q_REVISION(2) void sceneGraphAboutToStop(); + Q_REVISION(2, 2) void afterAnimating(); + Q_REVISION(2, 2) void sceneGraphAboutToStop(); - Q_REVISION(1) void closing(QQuickCloseEvent *close); + Q_REVISION(2, 1) void closing(QQuickCloseEvent *close); void colorChanged(const QColor &); - Q_REVISION(1) void activeFocusItemChanged(); - Q_REVISION(2) void sceneGraphError(QQuickWindow::SceneGraphError error, const QString &message); + Q_REVISION(2, 1) void activeFocusItemChanged(); + Q_REVISION(2, 2) void sceneGraphError(QQuickWindow::SceneGraphError error, const QString &message); - Q_REVISION(14) void beforeRenderPassRecording(); - Q_REVISION(14) void afterRenderPassRecording(); + Q_REVISION(2, 14) void beforeRenderPassRecording(); + Q_REVISION(2, 14) void afterRenderPassRecording(); public Q_SLOTS: void update(); @@ -247,6 +252,9 @@ protected: #if QT_CONFIG(wheelevent) void wheelEvent(QWheelEvent *) override; #endif +#if QT_CONFIG(tabletevent) + void tabletEvent(QTabletEvent *) override; +#endif private Q_SLOTS: void maybeUpdate(); diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index ef10ba3fe8..8e4ecbc178 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -62,9 +62,6 @@ #include <QtCore/qwaitcondition.h> #include <QtCore/qrunnable.h> #include <private/qwindow_p.h> -#include <private/qopengl_p.h> -#include <qopenglcontext.h> -#include <QtGui/qopenglframebufferobject.h> #include <QtGui/qevent.h> #include <QtGui/qstylehints.h> #include <QtGui/qguiapplication.h> @@ -88,7 +85,7 @@ class QRhiRenderBuffer; class QRhiRenderPassDescriptor; //Make it easy to identify and customize the root item if needed -class QQuickRootItem : public QQuickItem +class Q_QUICK_PRIVATE_EXPORT QQuickRootItem : public QQuickItem { Q_OBJECT public: @@ -134,6 +131,7 @@ public: // Keeps track of the item currently receiving mouse events #if QT_CONFIG(cursor) QQuickItem *cursorItem; + QQuickPointerHandler *cursorHandler; #endif #if QT_CONFIG(quick_draganddrop) QQuickDragGrabber *dragGrabber; @@ -197,7 +195,7 @@ public: #endif #if QT_CONFIG(cursor) void updateCursor(const QPointF &scenePos); - QQuickItem *findCursorItem(QQuickItem *item, const QPointF &scenePos); + QPair<QQuickItem*, QQuickPointerHandler*> findCursorItemAndHandler(QQuickItem *item, const QPointF &scenePos) const; #endif QList<QQuickItem*> hoverItems; @@ -298,6 +296,8 @@ public: static int data_count(QQmlListProperty<QObject> *); static QObject *data_at(QQmlListProperty<QObject> *, int); static void data_clear(QQmlListProperty<QObject> *); + static void data_replace(QQmlListProperty<QObject> *, int, QObject *); + static void data_removeLast(QQmlListProperty<QObject> *); static void contextCreationFailureMessage(const QSurfaceFormat &format, QString *translatedMessage, diff --git a/src/quick/items/qquickwindowmodule_p.h b/src/quick/items/qquickwindowmodule_p.h index d0bf5c29b3..2f05b987d1 100644 --- a/src/quick/items/qquickwindowmodule_p.h +++ b/src/quick/items/qquickwindowmodule_p.h @@ -67,7 +67,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickWindowQmlImpl : public QQuickWindow, public Q Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged) Q_PROPERTY(Visibility visibility READ visibility WRITE setVisibility NOTIFY visibilityChanged) - Q_PROPERTY(QObject *screen READ screen WRITE setScreen NOTIFY screenChanged REVISION 3) + Q_PROPERTY(QObject *screen READ screen WRITE setScreen NOTIFY screenChanged REVISION(2, 3)) QML_ATTACHED(QQuickWindowAttached) public: @@ -84,7 +84,7 @@ public: Q_SIGNALS: void visibleChanged(bool arg); void visibilityChanged(QWindow::Visibility visibility); - Q_REVISION(3) void screenChanged(); + Q_REVISION(2, 3) void screenChanged(); protected: void classBegin() override; diff --git a/src/quick/qtquickglobal_p.h b/src/quick/qtquickglobal_p.h index f6376a6d17..80e59563c7 100644 --- a/src/quick/qtquickglobal_p.h +++ b/src/quick/qtquickglobal_p.h @@ -61,6 +61,8 @@ #define Q_QUICK_PRIVATE_EXPORT Q_QUICK_EXPORT +void Q_QUICK_PRIVATE_EXPORT qml_register_types_QtQuick(); + QT_BEGIN_NAMESPACE void QQuick_initializeProviders(); diff --git a/src/quick/quick.pro b/src/quick/quick.pro index 6db2ae884e..77517a45e0 100644 --- a/src/quick/quick.pro +++ b/src/quick/quick.pro @@ -3,8 +3,10 @@ TARGET = QtQuick QT = core-private gui-private qml-private qmlmodels-private qtConfig(qml-network): \ QT_PRIVATE += network -qtConfig(opengl): \ +qtConfig(opengl) { QT_PRIVATE += opengl-private + QT += opengl +} TRACEPOINT_PROVIDER = $$PWD/qtquick.tracepoints CONFIG += qt_tracepoints @@ -23,13 +25,10 @@ exists("qqml_enable_gcov") { QMAKE_DOCS = $$PWD/doc/qtquick.qdocconf -ANDROID_LIB_DEPENDENCIES = \ - lib/libQt5QuickParticles.so MODULE_PLUGIN_TYPES += \ scenegraph ANDROID_BUNDLED_FILES += \ - qml \ - lib/libQt5QuickParticles.so + qml include(util/util.pri) include(scenegraph/scenegraph.pri) @@ -56,5 +55,5 @@ load(qt_module) QMLTYPES_FILENAME = plugins.qmltypes QMLTYPES_INSTALL_DIR = $$[QT_INSTALL_QML]/QtQuick QML_IMPORT_NAME = QtQuick -IMPORT_VERSION = 2.15 +QML_IMPORT_VERSION = $$QT_VERSION CONFIG += qmltypes install_qmltypes install_metatypes diff --git a/src/quick/scenegraph/compressedtexture/qsgcompressedatlastexture.cpp b/src/quick/scenegraph/compressedtexture/qsgcompressedatlastexture.cpp index b59d490250..45d7a65555 100644 --- a/src/quick/scenegraph/compressedtexture/qsgcompressedatlastexture.cpp +++ b/src/quick/scenegraph/compressedtexture/qsgcompressedatlastexture.cpp @@ -136,12 +136,12 @@ Texture::Texture(Atlas *atlas, const QRect &textureRect, const QByteArray &data, { float w = atlas->size().width(); float h = atlas->size().height(); - QRect nopad = atlasSubRect(); + const QRect &r = atlasSubRect(); // offset by half-pixel to prevent bleeding when scaling - m_texture_coords_rect = QRectF((nopad.x() + .5) / w, - (nopad.y() + .5) / h, - (nopad.width() - 1.) / w, - (nopad.height() - 1.) / h); + m_texture_coords_rect = QRectF((r.x() + .5) / w, + (r.y() + .5) / h, + (size.width() - 1.) / w, + (size.height() - 1.) / h); } Texture::~Texture() @@ -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/src/quick/scenegraph/compressedtexture/qsgcompressedatlastexture_p.h b/src/quick/scenegraph/compressedtexture/qsgcompressedatlastexture_p.h index 78051778f5..aec7dbf976 100644 --- a/src/quick/scenegraph/compressedtexture/qsgcompressedatlastexture_p.h +++ b/src/quick/scenegraph/compressedtexture/qsgcompressedatlastexture_p.h @@ -53,7 +53,7 @@ #include <QtCore/QSize> -#include <QtGui/qopengl.h> +#include <qopengl.h> #include <QtQuick/QSGTexture> #include <QtQuick/private/qsgareaallocator_p.h> diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index 5310e76dae..f9e6ba03a8 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -138,6 +138,7 @@ struct QMatrix4x4_Accessor static bool isScale(const QMatrix4x4 &m) { return ((const QMatrix4x4_Accessor &) m).flagBits <= 0x2; } static bool is2DSafe(const QMatrix4x4 &m) { return ((const QMatrix4x4_Accessor &) m).flagBits < 0x8; } }; +Q_STATIC_ASSERT(sizeof(QMatrix4x4_Accessor) == sizeof(QMatrix4x4)); const float OPAQUE_LIMIT = 0.999f; @@ -480,8 +481,6 @@ Updater::Updater(Renderer *r) m_roots.add(0); m_combined_matrix_stack.add(&m_identityMatrix); m_rootMatrices.add(m_identityMatrix); - - Q_ASSERT(sizeof(QMatrix4x4_Accessor) == sizeof(QMatrix4x4)); } void Updater::updateStates(QSGNode *n) diff --git a/src/quick/scenegraph/coreapi/qsggeometry.h b/src/quick/scenegraph/coreapi/qsggeometry.h index d17915a842..9c60876597 100644 --- a/src/quick/scenegraph/coreapi/qsggeometry.h +++ b/src/quick/scenegraph/coreapi/qsggeometry.h @@ -41,7 +41,7 @@ #define QSGGEOMETRY_H #include <QtQuick/qtquickglobal.h> -#include <QtGui/qopengl.h> +#include <qopengl.h> #include <QtCore/QRectF> QT_BEGIN_NAMESPACE diff --git a/src/quick/scenegraph/coreapi/qsgmaterialshader.cpp b/src/quick/scenegraph/coreapi/qsgmaterialshader.cpp index d614f9be4c..9049dd5826 100644 --- a/src/quick/scenegraph/coreapi/qsgmaterialshader.cpp +++ b/src/quick/scenegraph/coreapi/qsgmaterialshader.cpp @@ -44,8 +44,8 @@ # include <private/qsgshadersourcebuilder_p.h> # include <private/qsgdefaultcontext_p.h> # include <private/qsgdefaultrendercontext_p.h> -# include <QtGui/QOpenGLFunctions> -# include <QtGui/QOpenGLContext> +# include <QOpenGLFunctions> +# include <QOpenGLContext> #endif QT_BEGIN_NAMESPACE diff --git a/src/quick/scenegraph/coreapi/qsgmaterialshader.h b/src/quick/scenegraph/coreapi/qsgmaterialshader.h index d7ee23384f..6783b3f890 100644 --- a/src/quick/scenegraph/coreapi/qsgmaterialshader.h +++ b/src/quick/scenegraph/coreapi/qsgmaterialshader.h @@ -42,7 +42,7 @@ #include <QtQuick/qtquickglobal.h> #if QT_CONFIG(opengl) -# include <QtGui/qopenglshaderprogram.h> +# include <qopenglshaderprogram.h> #endif #include <QtGui/QMatrix4x4> #include <QtCore/QRect> diff --git a/src/quick/scenegraph/coreapi/qsgrenderer.cpp b/src/quick/scenegraph/coreapi/qsgrenderer.cpp index 90090e1cc0..cd16014d41 100644 --- a/src/quick/scenegraph/coreapi/qsgrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgrenderer.cpp @@ -40,9 +40,9 @@ #include "qsgrenderer_p.h" #include "qsgnodeupdater_p.h" #if QT_CONFIG(opengl) -# include <QtGui/QOpenGLFramebufferObject> -# include <QtGui/QOpenGLContext> -# include <QtGui/QOpenGLFunctions> +# include <QOpenGLFramebufferObject> +# include <QOpenGLContext> +# include <QOpenGLFunctions> #endif #include <private/qquickprofiler_p.h> #include <qtquick_tracepoints_p.h> diff --git a/src/quick/scenegraph/coreapi/qsgtexture.cpp b/src/quick/scenegraph/coreapi/qsgtexture.cpp index 715633fdba..486fe50190 100644 --- a/src/quick/scenegraph/coreapi/qsgtexture.cpp +++ b/src/quick/scenegraph/coreapi/qsgtexture.cpp @@ -39,8 +39,8 @@ #include "qsgtexture_p.h" #if QT_CONFIG(opengl) -# include <QtGui/qopenglcontext.h> -# include <QtGui/qopenglfunctions.h> +# include <qopenglcontext.h> +# include <qopenglfunctions.h> #endif #include <private/qqmlglobal_p.h> #include <private/qsgmaterialshader_p.h> diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp index eab0369be7..e0d9d5db68 100644 --- a/src/quick/scenegraph/qsgadaptationlayer.cpp +++ b/src/quick/scenegraph/qsgadaptationlayer.cpp @@ -329,7 +329,7 @@ void QSGDistanceFieldGlyphCache::updateRhiTexture(QRhiTexture *oldTex, QRhiTextu } #if defined(QSG_DISTANCEFIELD_CACHE_DEBUG) -#include <QtGui/qopenglfunctions.h> +#include <qopenglfunctions.h> void QSGDistanceFieldGlyphCache::saveTexture(GLuint textureId, int width, int height) const { diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.h b/src/quick/scenegraph/qsgdefaultglyphnode_p.h index 4cff2d3d24..f70d51d1ee 100644 --- a/src/quick/scenegraph/qsgdefaultglyphnode_p.h +++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.h @@ -53,7 +53,6 @@ #include <private/qsgadaptationlayer_p.h> #include <private/qsgbasicglyphnode_p.h> -#include <qlinkedlist.h> QT_BEGIN_NAMESPACE diff --git a/src/quick/scenegraph/qsgdefaultinternalimagenode.cpp b/src/quick/scenegraph/qsgdefaultinternalimagenode.cpp index 500d4e6e95..167d2b01dd 100644 --- a/src/quick/scenegraph/qsgdefaultinternalimagenode.cpp +++ b/src/quick/scenegraph/qsgdefaultinternalimagenode.cpp @@ -41,7 +41,7 @@ #include <private/qsgdefaultrendercontext_p.h> #include <private/qsgmaterialshader_p.h> #include <private/qsgtexturematerial_p.h> -#include <QtGui/qopenglfunctions.h> +#include <qopenglfunctions.h> #include <QtCore/qmath.h> #include <QtGui/private/qrhi_p.h> diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp index e8e9f76d04..a25daa6070 100644 --- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp +++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp @@ -39,7 +39,7 @@ #include "qsgdistancefieldglyphnode_p_p.h" #include "qsgrhidistancefieldglyphcache_p.h" -#include <QtGui/qopenglfunctions.h> +#include <qopenglfunctions.h> #include <QtGui/qsurface.h> #include <QtGui/qwindow.h> #include <qmath.h> diff --git a/src/quick/scenegraph/qsgopengldistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgopengldistancefieldglyphcache.cpp index fc8ec25053..2f9b1e4ce6 100644 --- a/src/quick/scenegraph/qsgopengldistancefieldglyphcache.cpp +++ b/src/quick/scenegraph/qsgopengldistancefieldglyphcache.cpp @@ -54,7 +54,7 @@ #if !defined(QT_OPENGL_ES_2) -#include <QtGui/qopenglfunctions_3_2_core.h> +#include <qopenglfunctions_3_2_core.h> #endif QT_BEGIN_NAMESPACE diff --git a/src/quick/scenegraph/qsgopengldistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgopengldistancefieldglyphcache_p.h index e78e735b6f..2e7b5baae2 100644 --- a/src/quick/scenegraph/qsgopengldistancefieldglyphcache_p.h +++ b/src/quick/scenegraph/qsgopengldistancefieldglyphcache_p.h @@ -52,7 +52,7 @@ // #include "qsgadaptationlayer_p.h" -#include <QtGui/qopenglfunctions.h> +#include <qopenglfunctions.h> #include <qopenglshaderprogram.h> #include <qopenglbuffer.h> #include <qopenglvertexarrayobject.h> diff --git a/src/quick/scenegraph/qsgrhisupport.cpp b/src/quick/scenegraph/qsgrhisupport.cpp index 9194d3e730..cf30cb3f9a 100644 --- a/src/quick/scenegraph/qsgrhisupport.cpp +++ b/src/quick/scenegraph/qsgrhisupport.cpp @@ -157,6 +157,8 @@ void QSGRhiSupport::applySettings() } else if (rhiBackend == QByteArrayLiteral("null")) { m_rhiBackend = QRhi::Null; } else { + if (!rhiBackend.isEmpty()) + qWarning("Unknown key \"%s\" for QSG_RHI_BACKEND, falling back to default backend.", qPrintable(rhiBackend)); #if defined(Q_OS_WIN) m_rhiBackend = QRhi::D3D11; #elif defined(Q_OS_MACOS) || defined(Q_OS_IOS) diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index 4777f46f0a..9b288029b4 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -660,6 +660,11 @@ void QSGRenderThread::sync(bool inExpose, bool inGrab) qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- window has bad size, sync aborted"); } + // Two special cases: For grabs we do not care about blocking the gui + // (main) thread. When this is from an expose, we will keep locked until + // the frame is rendered (submitted), so in that case waking happens later + // in syncAndRender(). Otherwise, wake now and let the main thread go on + // while we render. if (!inExpose && !inGrab) { qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- sync complete, waking Gui"); waitCondition.wakeOne(); @@ -756,13 +761,11 @@ void QSGRenderThread::syncAndRender(QImage *grabImage) QCoreApplication::postEvent(window, new QEvent(QEvent::Type(QQuickWindowPrivate::FullUpdateRequest))); // Before returning we need to ensure the same wake up logic that // would have happened if beginFrame() had suceeded. - if (exposeRequested) { + if (syncRequested && !grabRequested) { + // Lock like sync() would do. Note that exposeRequested always includes syncRequested. qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- bailing out due to failed beginFrame, wake Gui"); - waitCondition.wakeOne(); - mutex.unlock(); - } else if (syncRequested && !grabRequested) { - qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- bailing out due to failed beginFrame, wake Gui like sync would do"); mutex.lock(); + // Go ahead with waking because we will return right after this. waitCondition.wakeOne(); mutex.unlock(); } @@ -885,7 +888,8 @@ void QSGRenderThread::syncAndRender(QImage *grabImage) // has started rendering with a bad window, causing makeCurrent to // fail or if the window has a bad size. if (exposeRequested) { - qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- wake Gui after initial expose"); + // With expose sync() did not wake gui, do it now. + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- wake Gui after expose"); waitCondition.wakeOne(); mutex.unlock(); } diff --git a/src/quick/scenegraph/util/qsgengine.cpp b/src/quick/scenegraph/util/qsgengine.cpp index 4880d98871..13c97e8615 100644 --- a/src/quick/scenegraph/util/qsgengine.cpp +++ b/src/quick/scenegraph/util/qsgengine.cpp @@ -45,7 +45,7 @@ #include <private/qsgplaintexture_p.h> #if QT_CONFIG(opengl) -# include <QtGui/QOpenGLContext> +# include <QOpenGLContext> # include <private/qsgdefaultrendercontext_p.h> #endif diff --git a/src/quick/scenegraph/util/qsgopenglatlastexture_p.h b/src/quick/scenegraph/util/qsgopenglatlastexture_p.h index f8dd7cdf02..379c4c7fff 100644 --- a/src/quick/scenegraph/util/qsgopenglatlastexture_p.h +++ b/src/quick/scenegraph/util/qsgopenglatlastexture_p.h @@ -53,7 +53,7 @@ #include <QtCore/QSize> -#include <QtGui/qopengl.h> +#include <qopengl.h> #include <QtQuick/QSGTexture> #include <QtQuick/private/qsgplaintexture_p.h> diff --git a/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp index 93fc213f2e..77fded6c21 100644 --- a/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp +++ b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp @@ -39,8 +39,8 @@ #include "qsgshadersourcebuilder_p.h" -#include <QtGui/qopenglcontext.h> -#include <QtGui/qopenglshaderprogram.h> +#include <qopenglcontext.h> +#include <qopenglshaderprogram.h> #include <QtCore/qdebug.h> #include <QtCore/qfile.h> diff --git a/src/quick/scenegraph/util/qsgtexturematerial.cpp b/src/quick/scenegraph/util/qsgtexturematerial.cpp index 67b8748119..b4ac0c4d1d 100644 --- a/src/quick/scenegraph/util/qsgtexturematerial.cpp +++ b/src/quick/scenegraph/util/qsgtexturematerial.cpp @@ -40,8 +40,8 @@ #include "qsgtexturematerial_p.h" #include <private/qsgtexture_p.h> #if QT_CONFIG(opengl) -# include <QtGui/qopenglshaderprogram.h> -# include <QtGui/qopenglfunctions.h> +# include <qopenglshaderprogram.h> +# include <qopenglfunctions.h> #endif #include <QtGui/private/qrhi_p.h> diff --git a/src/quick/util/qquickanimation_p.h b/src/quick/util/qquickanimation_p.h index 7bad9d50c4..b86533eb3f 100644 --- a/src/quick/util/qquickanimation_p.h +++ b/src/quick/util/qquickanimation_p.h @@ -81,6 +81,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickAbstractAnimation : public QObject, public QQ Q_CLASSINFO("DefaultMethod", "start()") QML_NAMED_ELEMENT(Animation) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("Animation is an abstract class") public: @@ -129,7 +130,7 @@ Q_SIGNALS: void pausedChanged(bool); void alwaysRunToEndChanged(bool); void loopCountChanged(int); - Q_REVISION(12) void finished(); + Q_REVISION(2, 12) void finished(); public Q_SLOTS: void restart(); @@ -169,6 +170,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPauseAnimation : public QQuickAbstractAnimati Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged) QML_NAMED_ELEMENT(PauseAnimation) + QML_ADDED_IN_VERSION(2, 0) public: QQuickPauseAnimation(QObject *parent=nullptr); @@ -196,6 +198,7 @@ class QQuickScriptAction : public QQuickAbstractAnimation Q_PROPERTY(QQmlScriptString script READ script WRITE setScript) Q_PROPERTY(QString scriptName READ stateChangeScriptName WRITE setStateChangeScriptName) QML_NAMED_ELEMENT(ScriptAction) + QML_ADDED_IN_VERSION(2, 0) public: QQuickScriptAction(QObject *parent=nullptr); @@ -227,6 +230,7 @@ class QQuickPropertyAction : public QQuickAbstractAnimation Q_PROPERTY(QQmlListProperty<QObject> exclude READ exclude) Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged) QML_NAMED_ELEMENT(PropertyAction) + QML_ADDED_IN_VERSION(2, 0) public: QQuickPropertyAction(QObject *parent=nullptr); @@ -276,6 +280,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPropertyAnimation : public QQuickAbstractAnim Q_PROPERTY(QQmlListProperty<QObject> targets READ targets) Q_PROPERTY(QQmlListProperty<QObject> exclude READ exclude) QML_NAMED_ELEMENT(PropertyAnimation) + QML_ADDED_IN_VERSION(2, 0) public: QQuickPropertyAnimation(QObject *parent=nullptr); @@ -332,6 +337,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickColorAnimation : public QQuickPropertyAnimati Q_PROPERTY(QColor from READ from WRITE setFrom) Q_PROPERTY(QColor to READ to WRITE setTo) QML_NAMED_ELEMENT(ColorAnimation) + QML_ADDED_IN_VERSION(2, 0) public: QQuickColorAnimation(QObject *parent=nullptr); @@ -352,6 +358,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickNumberAnimation : public QQuickPropertyAnimat Q_PROPERTY(qreal from READ from WRITE setFrom NOTIFY fromChanged) Q_PROPERTY(qreal to READ to WRITE setTo NOTIFY toChanged) QML_NAMED_ELEMENT(NumberAnimation) + QML_ADDED_IN_VERSION(2, 0) public: QQuickNumberAnimation(QObject *parent=nullptr); @@ -378,6 +385,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickVector3dAnimation : public QQuickPropertyAnim Q_PROPERTY(QVector3D from READ from WRITE setFrom NOTIFY fromChanged) Q_PROPERTY(QVector3D to READ to WRITE setTo NOTIFY toChanged) QML_NAMED_ELEMENT(Vector3dAnimation) + QML_ADDED_IN_VERSION(2, 0) public: QQuickVector3dAnimation(QObject *parent=nullptr); @@ -400,6 +408,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickRotationAnimation : public QQuickPropertyAnim Q_PROPERTY(qreal to READ to WRITE setTo NOTIFY toChanged) Q_PROPERTY(RotationDirection direction READ direction WRITE setDirection NOTIFY directionChanged) QML_NAMED_ELEMENT(RotationAnimation) + QML_ADDED_IN_VERSION(2, 0) public: QQuickRotationAnimation(QObject *parent=nullptr); @@ -445,6 +454,7 @@ class QQuickSequentialAnimation : public QQuickAnimationGroup Q_OBJECT Q_DECLARE_PRIVATE(QQuickAnimationGroup) QML_NAMED_ELEMENT(SequentialAnimation) + QML_ADDED_IN_VERSION(2, 0) public: QQuickSequentialAnimation(QObject *parent=nullptr); @@ -463,6 +473,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickParallelAnimation : public QQuickAnimationGro Q_OBJECT Q_DECLARE_PRIVATE(QQuickAnimationGroup) QML_NAMED_ELEMENT(ParallelAnimation) + QML_ADDED_IN_VERSION(2, 0) public: QQuickParallelAnimation(QObject *parent=nullptr); diff --git a/src/quick/util/qquickanimationcontroller_p.h b/src/quick/util/qquickanimationcontroller_p.h index da6df6038a..de308735ef 100644 --- a/src/quick/util/qquickanimationcontroller_p.h +++ b/src/quick/util/qquickanimationcontroller_p.h @@ -65,6 +65,7 @@ class Q_AUTOTEST_EXPORT QQuickAnimationController : public QObject, public QQmlP Q_DECLARE_PRIVATE(QQuickAnimationController) Q_CLASSINFO("DefaultProperty", "animation") QML_NAMED_ELEMENT(AnimationController) + QML_ADDED_IN_VERSION(2, 0) Q_PROPERTY(qreal progress READ progress WRITE setProgress NOTIFY progressChanged) Q_PROPERTY(QQuickAbstractAnimation *animation READ animation WRITE setAnimation NOTIFY animationChanged) diff --git a/src/quick/util/qquickanimator_p.h b/src/quick/util/qquickanimator_p.h index 9f7aaafcb0..0bcf4c40a4 100644 --- a/src/quick/util/qquickanimator_p.h +++ b/src/quick/util/qquickanimator_p.h @@ -70,7 +70,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickAnimator : public QQuickAbstractAnimation Q_PROPERTY(qreal from READ from WRITE setFrom NOTIFY fromChanged) QML_NAMED_ELEMENT(Animator) - QML_ADDED_IN_MINOR_VERSION(2) + QML_ADDED_IN_VERSION(2, 2) QML_UNCREATABLE("Animator is an abstract class") public: @@ -114,7 +114,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickScaleAnimator : public QQuickAnimator { Q_OBJECT QML_NAMED_ELEMENT(ScaleAnimator) - QML_ADDED_IN_MINOR_VERSION(2) + QML_ADDED_IN_VERSION(2, 2) public: QQuickScaleAnimator(QObject *parent = nullptr); protected: @@ -126,7 +126,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickXAnimator : public QQuickAnimator { Q_OBJECT QML_NAMED_ELEMENT(XAnimator) - QML_ADDED_IN_MINOR_VERSION(2) + QML_ADDED_IN_VERSION(2, 2) public: QQuickXAnimator(QObject *parent = nullptr); protected: @@ -138,7 +138,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickYAnimator : public QQuickAnimator { Q_OBJECT QML_NAMED_ELEMENT(YAnimator) - QML_ADDED_IN_MINOR_VERSION(2) + QML_ADDED_IN_VERSION(2, 2) public: QQuickYAnimator(QObject *parent = nullptr); protected: @@ -150,7 +150,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickOpacityAnimator : public QQuickAnimator { Q_OBJECT QML_NAMED_ELEMENT(OpacityAnimator) - QML_ADDED_IN_MINOR_VERSION(2) + QML_ADDED_IN_VERSION(2, 2) public: QQuickOpacityAnimator(QObject *parent = nullptr); protected: @@ -165,7 +165,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickRotationAnimator : public QQuickAnimator Q_DECLARE_PRIVATE(QQuickRotationAnimator) Q_PROPERTY(RotationDirection direction READ direction WRITE setDirection NOTIFY directionChanged) QML_NAMED_ELEMENT(RotationAnimator) - QML_ADDED_IN_MINOR_VERSION(2) + QML_ADDED_IN_VERSION(2, 2) public: enum RotationDirection { Numerical, Shortest, Clockwise, Counterclockwise }; @@ -192,7 +192,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickUniformAnimator : public QQuickAnimator Q_DECLARE_PRIVATE(QQuickUniformAnimator) Q_PROPERTY(QString uniform READ uniform WRITE setUniform NOTIFY uniformChanged) QML_NAMED_ELEMENT(UniformAnimator) - QML_ADDED_IN_MINOR_VERSION(2) + QML_ADDED_IN_VERSION(2, 2) public: QQuickUniformAnimator(QObject *parent = nullptr); diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp index 0112a4b337..7b6b8bc878 100644 --- a/src/quick/util/qquickanimatorjob.cpp +++ b/src/quick/util/qquickanimatorjob.cpp @@ -48,6 +48,7 @@ # include <private/qquickopenglshadereffectnode_p.h> # include <private/qquickopenglshadereffect_p.h> # include <private/qquickshadereffect_p.h> +# include <QOpenGLContext> #endif #include <private/qanimationgroupjob_p.h> diff --git a/src/quick/util/qquickapplication_p.h b/src/quick/util/qquickapplication_p.h index b0eb6fa604..a740067bf3 100644 --- a/src/quick/util/qquickapplication_p.h +++ b/src/quick/util/qquickapplication_p.h @@ -72,6 +72,7 @@ class Q_AUTOTEST_EXPORT QQuickApplication : public QQmlApplication Q_PROPERTY(QQmlListProperty<QQuickScreenInfo> screens READ screens NOTIFY screensChanged) QML_NAMED_ELEMENT(Application) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("Application is an abstract class.") public: diff --git a/src/quick/util/qquickbehavior.cpp b/src/quick/util/qquickbehavior.cpp index eee8562a2a..ceda5589b2 100644 --- a/src/quick/util/qquickbehavior.cpp +++ b/src/quick/util/qquickbehavior.cpp @@ -185,6 +185,80 @@ QVariant QQuickBehavior::targetValue() const return d->targetValue; } +/*! + \readonly + \qmlpropertygroup QtQuick::Behavior::targetProperty + \qmlproperty string QtQuick::Behavior::targetProperty.name + \qmlproperty Object QtQuick::Behavior::targetProperty.object + + \table + \header + \li Property + \li Description + \row + \li name + \li This property holds the name of the property being controlled by this Behavior. + \row + \li object + \li This property holds the object of the property being controlled by this Behavior. + \endtable + + This property can be used to define custom behaviors based on the name or the object of + the property being controlled. + + The following example defines a Behavior fading out and fading in its target object + when the property it controls changes: + \qml + // FadeBehavior.qml + import QtQuick 2.15 + + Behavior { + id: root + property Item fadeTarget: targetProperty.object + SequentialAnimation { + NumberAnimation { + target: root.fadeTarget + property: "opacity" + to: 0 + easing.type: Easing.InQuad + } + PropertyAction { } // actually change the controlled property between the 2 other animations + NumberAnimation { + target: root.fadeTarget + property: "opacity" + to: 1 + easing.type: Easing.OutQuad + } + } + } + \endqml + + This can be used to animate a text when it changes: + \qml + import QtQuick 2.15 + + Text { + id: root + property int counter + text: counter + FadeBehavior on text {} + Timer { + running: true + repeat: true + interval: 1000 + onTriggered: ++root.counter + } + } + \endqml + + \since QtQuick 2.15 +*/ +QQmlProperty QQuickBehavior::targetProperty() const +{ + Q_D(const QQuickBehavior); + return d->property; +} + void QQuickBehavior::write(const QVariant &value) { Q_D(QQuickBehavior); @@ -265,6 +339,8 @@ void QQuickBehavior::setTarget(const QQmlProperty &property) if (finalizedIdx < 0) finalizedIdx = metaObject()->indexOfSlot("componentFinalized()"); engPriv->registerFinalizeCallback(this, finalizedIdx); + + Q_EMIT targetPropertyChanged(); } void QQuickBehavior::componentFinalized() diff --git a/src/quick/util/qquickbehavior_p.h b/src/quick/util/qquickbehavior_p.h index fa9cf6d6bc..1ce687ac44 100644 --- a/src/quick/util/qquickbehavior_p.h +++ b/src/quick/util/qquickbehavior_p.h @@ -69,9 +69,11 @@ class Q_QUICK_PRIVATE_EXPORT QQuickBehavior : public QObject, public QQmlPropert Q_CLASSINFO("DefaultProperty", "animation") Q_PROPERTY(QQuickAbstractAnimation *animation READ animation WRITE setAnimation) Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) - Q_PROPERTY(QVariant targetValue READ targetValue NOTIFY targetValueChanged REVISION 13) + Q_PROPERTY(QVariant targetValue READ targetValue NOTIFY targetValueChanged REVISION(2, 13)) + Q_PROPERTY(QQmlProperty targetProperty READ targetProperty NOTIFY targetPropertyChanged REVISION(2, 15)) Q_CLASSINFO("DeferredPropertyNames", "animation") QML_NAMED_ELEMENT(Behavior) + QML_ADDED_IN_VERSION(2, 0) public: QQuickBehavior(QObject *parent=nullptr); @@ -88,9 +90,12 @@ public: QVariant targetValue() const; + QQmlProperty targetProperty() const; + Q_SIGNALS: void enabledChanged(); void targetValueChanged(); + void targetPropertyChanged(); private Q_SLOTS: void componentFinalized(); diff --git a/src/quick/util/qquickfontloader.cpp b/src/quick/util/qquickfontloader.cpp index addf8b0c18..63aba04c34 100644 --- a/src/quick/util/qquickfontloader.cpp +++ b/src/quick/util/qquickfontloader.cpp @@ -121,7 +121,7 @@ void QQuickFontObject::replyFinished() } redirectCount = 0; - if (!reply->networkError()) { + if (!reply->error()) { id = QFontDatabase::addApplicationFontFromData(reply->readAll()); if (id != -1) emit fontDownloaded(QFontDatabase::applicationFontFamilies(id).at(0), QQuickFontLoader::Ready); diff --git a/src/quick/util/qquickfontloader_p.h b/src/quick/util/qquickfontloader_p.h index c0247cee3a..8d831dac4d 100644 --- a/src/quick/util/qquickfontloader_p.h +++ b/src/quick/util/qquickfontloader_p.h @@ -68,6 +68,7 @@ class Q_AUTOTEST_EXPORT QQuickFontLoader : public QObject Q_PROPERTY(QString name READ name NOTIFY nameChanged) Q_PROPERTY(Status status READ status NOTIFY statusChanged) QML_NAMED_ELEMENT(FontLoader) + QML_ADDED_IN_VERSION(2, 0) public: enum Status { Null = 0, Ready, Loading, Error }; diff --git a/src/quick/util/qquickfontmetrics_p.h b/src/quick/util/qquickfontmetrics_p.h index ee6d679649..59f4aa8355 100644 --- a/src/quick/util/qquickfontmetrics_p.h +++ b/src/quick/util/qquickfontmetrics_p.h @@ -80,7 +80,7 @@ class Q_AUTOTEST_EXPORT QQuickFontMetrics : public QObject Q_PROPERTY(qreal strikeOutPosition READ strikeOutPosition NOTIFY fontChanged) Q_PROPERTY(qreal lineWidth READ lineWidth NOTIFY fontChanged) QML_NAMED_ELEMENT(FontMetrics) - QML_ADDED_IN_MINOR_VERSION(4) + QML_ADDED_IN_VERSION(2, 4) public: explicit QQuickFontMetrics(QObject *parent = nullptr); ~QQuickFontMetrics(); diff --git a/src/quick/util/qquickforeignutils_p.h b/src/quick/util/qquickforeignutils_p.h index 7e51bc4f82..9802420780 100644 --- a/src/quick/util/qquickforeignutils_p.h +++ b/src/quick/util/qquickforeignutils_p.h @@ -73,6 +73,7 @@ struct QValidatorForeign Q_GADGET QML_FOREIGN(QValidator) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) }; struct QRegExpValidatorForeign @@ -80,6 +81,7 @@ struct QRegExpValidatorForeign Q_GADGET QML_FOREIGN(QRegExpValidator) QML_NAMED_ELEMENT(RegExpValidator) + QML_ADDED_IN_VERSION(2, 0) }; #if QT_CONFIG(regularexpression) @@ -88,7 +90,7 @@ struct QRegularExpressionValidatorForeign Q_GADGET QML_FOREIGN(QRegularExpressionValidator) QML_NAMED_ELEMENT(RegularExpressionValidator) - QML_ADDED_IN_MINOR_VERSION(14) + QML_ADDED_IN_VERSION(2, 14) }; #endif // QT_CONFIG(regularexpression) @@ -100,6 +102,7 @@ struct QInputMethodForeign Q_GADGET QML_FOREIGN(QInputMethod) QML_NAMED_ELEMENT(InputMethod) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("InputMethod is an abstract class.") }; #endif // QT_CONFIG(im) @@ -110,7 +113,7 @@ struct QKeySequenceForeign Q_GADGET QML_FOREIGN(QKeySequence) QML_NAMED_ELEMENT(StandardKey) - QML_ADDED_IN_MINOR_VERSION(2) + QML_ADDED_IN_VERSION(2, 2) QML_UNCREATABLE("Cannot create an instance of StandardKey.") }; #endif // QT_CONFIG(shortcut) diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp index 85bc78dee8..3ea2f88712 100644 --- a/src/quick/util/qquickglobal.cpp +++ b/src/quick/util/qquickglobal.cpp @@ -273,6 +273,52 @@ public: return QMatrix4x4(); } + static QColorSpace colorSpaceFromObject(const QV4::Value &object, QV4::ExecutionEngine *v4, bool *ok) + { + if (ok) + *ok = false; + QColorSpace retn; + QV4::Scope scope(v4); + QV4::ScopedObject obj(scope, object); + if (!obj) { + if (ok) + *ok = false; + return retn; + } + + QV4::ScopedString s(scope); + + QV4::ScopedValue vName(scope, obj->get((s = v4->newString(QStringLiteral("namedColorSpace"))))); + if (vName->isInt32()) { + if (ok) + *ok = true; + return QColorSpace((QColorSpace::NamedColorSpace)vName->toInt32()); + } + + QV4::ScopedValue vPri(scope, obj->get((s = v4->newString(QStringLiteral("primaries"))))); + QV4::ScopedValue vTra(scope, obj->get((s = v4->newString(QStringLiteral("transferFunction"))))); + if (!vPri->isInt32() || !vTra->isInt32()) { + if (ok) + *ok = false; + return retn; + } + + QColorSpace::Primaries pri = static_cast<QColorSpace::Primaries>(vPri->integerValue()); + QColorSpace::TransferFunction tra = static_cast<QColorSpace::TransferFunction>(vTra->integerValue()); + float gamma = 0.0f; + if (tra == QColorSpace::TransferFunction::Gamma) { + QV4::ScopedValue vGam(scope, obj->get((s = v4->newString(QStringLiteral("gamma"))))); + if (!vGam->isNumber()) { + if (ok) + *ok = false; + return retn; + } + gamma = vGam->toNumber(); + } + if (ok) *ok = true; + return QColorSpace(pri, tra, gamma); + } + static QFont fontFromObject(const QV4::Value &object, QV4::ExecutionEngine *v4, bool *ok) { if (ok) @@ -402,6 +448,8 @@ public: switch (type) { case QMetaType::QColor: return &QQuickColorValueType::staticMetaObject; + case QMetaType::QColorSpace: + return &QQuickColorSpaceValueType::staticMetaObject; case QMetaType::QFont: return &QQuickFontValueType::staticMetaObject; case QMetaType::QVector2D: @@ -427,6 +475,9 @@ public: case QMetaType::QColor: dst.setValue<QColor>(QColor()); return true; + case QMetaType::QColorSpace: + dst.setValue<QColorSpace>(QColorSpace()); + return true; case QMetaType::QFont: dst.setValue<QFont>(QFont()); return true; @@ -647,6 +698,9 @@ public: #endif bool ok = false; switch (type) { + case QMetaType::QColorSpace: + *v = QVariant::fromValue(colorSpaceFromObject(object, v4, &ok)); + break; case QMetaType::QFont: *v = QVariant::fromValue(fontFromObject(object, v4, &ok)); break; @@ -669,6 +723,8 @@ public: switch (type) { case QMetaType::QColor: return typedEqual<QColor>(lhs, rhs); + case QMetaType::QColorSpace: + return typedEqual<QColorSpace>(lhs, rhs); case QMetaType::QFont: return typedEqual<QFont>(lhs, rhs); case QMetaType::QVector2D: @@ -732,6 +788,8 @@ public: switch (dstType) { case QMetaType::QColor: return typedRead<QColor>(src, dstType, dst); + case QMetaType::QColorSpace: + return typedRead<QColorSpace>(src, dstType, dst); case QMetaType::QFont: return typedRead<QFont>(src, dstType, dst); case QMetaType::QVector2D: @@ -766,6 +824,8 @@ public: switch (type) { case QMetaType::QColor: return typedWrite<QColor>(src, dst); + case QMetaType::QColorSpace: + return typedWrite<QColorSpace>(src, dst); case QMetaType::QFont: return typedWrite<QFont>(src, dst); case QMetaType::QVector2D: diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp index db82b2d807..80873e2ad5 100644 --- a/src/quick/util/qquickimageprovider.cpp +++ b/src/quick/util/qquickimageprovider.cpp @@ -43,6 +43,7 @@ #include "qquickpixmapcache_p.h" #include <QtQuick/private/qsgcontext_p.h> #include <private/qqmlglobal_p.h> +#include <QtGui/qcolorspace.h> QT_BEGIN_NAMESPACE @@ -510,6 +511,7 @@ public: { } + QColorSpace targetColorSpace; QQuickImageProviderOptions::AutoTransform autoTransform = QQuickImageProviderOptions::UsePluginDefaultTransform; bool preserveAspectRatioCrop = false; bool preserveAspectRatioFit = false; @@ -558,7 +560,8 @@ bool QQuickImageProviderOptions::operator==(const QQuickImageProviderOptions &ot { return d->autoTransform == other.d->autoTransform && d->preserveAspectRatioCrop == other.d->preserveAspectRatioCrop && - d->preserveAspectRatioFit == other.d->preserveAspectRatioFit; + d->preserveAspectRatioFit == other.d->preserveAspectRatioFit && + d->targetColorSpace == other.d->targetColorSpace; } /*! @@ -602,6 +605,19 @@ void QQuickImageProviderOptions::setPreserveAspectRatioFit(bool preserveAspectRa d->preserveAspectRatioFit = preserveAspectRatioFit; } +/*! + Returns the color space the image provider should return the image in. +*/ +QColorSpace QQuickImageProviderOptions::targetColorSpace() const +{ + return d->targetColorSpace; +} + +void QQuickImageProviderOptions::setTargetColorSpace(const QColorSpace &colorSpace) +{ + d->targetColorSpace = colorSpace; +} + QQuickImageProviderWithOptions::QQuickImageProviderWithOptions(ImageType type, Flags flags) : QQuickAsyncImageProvider() { diff --git a/src/quick/util/qquickpath.cpp b/src/quick/util/qquickpath.cpp index 375d0265e8..74ee52b1d3 100644 --- a/src/quick/util/qquickpath.cpp +++ b/src/quick/util/qquickpath.cpp @@ -2827,11 +2827,11 @@ void QQuickPathText::updatePath() const if (!_path.isEmpty()) return; - _path.addText(_x, _y, _font, _text); + _path.addText(0.0, 0.0, _font, _text); // Account for distance from baseline to top, since addText() takes baseline position QRectF brect = _path.boundingRect(); - _path.translate(0.0, -brect.y()); + _path.translate(_x, _y - brect.y()); } void QQuickPathText::addToPath(QPainterPath &path) diff --git a/src/quick/util/qquickpath_p.h b/src/quick/util/qquickpath_p.h index 159c46d13c..8660537587 100644 --- a/src/quick/util/qquickpath_p.h +++ b/src/quick/util/qquickpath_p.h @@ -79,6 +79,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathElement : public QObject { Q_OBJECT QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQuickPathElement(QObject *parent=nullptr) : QObject(parent) {} Q_SIGNALS: @@ -92,6 +93,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathAttribute : public QQuickPathElement Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged) QML_NAMED_ELEMENT(PathAttribute) + QML_ADDED_IN_VERSION(2, 0) public: QQuickPathAttribute(QObject *parent=nullptr) : QQuickPathElement(parent) {} @@ -120,6 +122,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickCurve : public QQuickPathElement Q_PROPERTY(qreal relativeX READ relativeX WRITE setRelativeX NOTIFY relativeXChanged) Q_PROPERTY(qreal relativeY READ relativeY WRITE setRelativeY NOTIFY relativeYChanged) QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQuickCurve(QObject *parent=nullptr) : QQuickPathElement(parent) {} @@ -158,6 +161,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathLine : public QQuickCurve { Q_OBJECT QML_NAMED_ELEMENT(PathLine) + QML_ADDED_IN_VERSION(2, 0) public: QQuickPathLine(QObject *parent=nullptr) : QQuickCurve(parent) {} @@ -168,7 +172,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathMove : public QQuickCurve { Q_OBJECT QML_NAMED_ELEMENT(PathMove) - QML_ADDED_IN_MINOR_VERSION(9) + QML_ADDED_IN_VERSION(2, 9) public: QQuickPathMove(QObject *parent=nullptr) : QQuickCurve(parent) {} @@ -185,6 +189,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathQuad : public QQuickCurve Q_PROPERTY(qreal relativeControlY READ relativeControlY WRITE setRelativeControlY NOTIFY relativeControlYChanged) QML_NAMED_ELEMENT(PathQuad) + QML_ADDED_IN_VERSION(2, 0) public: QQuickPathQuad(QObject *parent=nullptr) : QQuickCurve(parent) {} @@ -230,6 +235,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathCubic : public QQuickCurve Q_PROPERTY(qreal relativeControl2X READ relativeControl2X WRITE setRelativeControl2X NOTIFY relativeControl2XChanged) Q_PROPERTY(qreal relativeControl2Y READ relativeControl2Y WRITE setRelativeControl2Y NOTIFY relativeControl2YChanged) QML_NAMED_ELEMENT(PathCubic) + QML_ADDED_IN_VERSION(2, 0) public: QQuickPathCubic(QObject *parent=nullptr) : QQuickCurve(parent) {} @@ -288,6 +294,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathCatmullRomCurve : public QQuickCurve { Q_OBJECT QML_NAMED_ELEMENT(PathCurve) + QML_ADDED_IN_VERSION(2, 0) public: QQuickPathCatmullRomCurve(QObject *parent=nullptr) : QQuickCurve(parent) {} @@ -301,8 +308,9 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathArc : public QQuickCurve Q_PROPERTY(qreal radiusY READ radiusY WRITE setRadiusY NOTIFY radiusYChanged) Q_PROPERTY(bool useLargeArc READ useLargeArc WRITE setUseLargeArc NOTIFY useLargeArcChanged) Q_PROPERTY(ArcDirection direction READ direction WRITE setDirection NOTIFY directionChanged) - Q_PROPERTY(qreal xAxisRotation READ xAxisRotation WRITE setXAxisRotation NOTIFY xAxisRotationChanged REVISION 9) + Q_PROPERTY(qreal xAxisRotation READ xAxisRotation WRITE setXAxisRotation NOTIFY xAxisRotationChanged REVISION(2, 9)) QML_NAMED_ELEMENT(PathArc) + QML_ADDED_IN_VERSION(2, 0) public: QQuickPathArc(QObject *parent=nullptr) @@ -333,7 +341,7 @@ Q_SIGNALS: void radiusYChanged(); void useLargeArcChanged(); void directionChanged(); - Q_REVISION(9) void xAxisRotationChanged(); + Q_REVISION(2, 9) void xAxisRotationChanged(); private: qreal _radiusX = 0; @@ -355,7 +363,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathAngleArc : public QQuickCurve Q_PROPERTY(bool moveToStart READ moveToStart WRITE setMoveToStart NOTIFY moveToStartChanged) QML_NAMED_ELEMENT(PathAngleArc) - QML_ADDED_IN_MINOR_VERSION(11) + QML_ADDED_IN_VERSION(2, 11) public: QQuickPathAngleArc(QObject *parent=nullptr) @@ -408,6 +416,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathSvg : public QQuickCurve Q_OBJECT Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged) QML_NAMED_ELEMENT(PathSvg) + QML_ADDED_IN_VERSION(2, 0) public: QQuickPathSvg(QObject *parent=nullptr) : QQuickCurve(parent) {} @@ -428,6 +437,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathPercent : public QQuickPathElement Q_OBJECT Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged) QML_NAMED_ELEMENT(PathPercent) + QML_ADDED_IN_VERSION(2, 0) public: QQuickPathPercent(QObject *parent=nullptr) : QQuickPathElement(parent) {} @@ -447,7 +457,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathPolyline : public QQuickCurve Q_PROPERTY(QPointF start READ start NOTIFY startChanged) Q_PROPERTY(QVariant path READ path WRITE setPath NOTIFY pathChanged) QML_NAMED_ELEMENT(PathPolyline) - QML_ADDED_IN_MINOR_VERSION(14) + QML_ADDED_IN_VERSION(2, 14) public: QQuickPathPolyline(QObject *parent=nullptr); @@ -471,7 +481,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathMultiline : public QQuickCurve Q_PROPERTY(QPointF start READ start NOTIFY startChanged) Q_PROPERTY(QVariant paths READ paths WRITE setPaths NOTIFY pathsChanged) QML_NAMED_ELEMENT(PathMultiline) - QML_ADDED_IN_MINOR_VERSION(14) + QML_ADDED_IN_VERSION(2, 14) public: QQuickPathMultiline(QObject *parent=nullptr); @@ -512,9 +522,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPath : public QObject, public QQmlParserStatu Q_PROPERTY(qreal startX READ startX WRITE setStartX NOTIFY startXChanged) Q_PROPERTY(qreal startY READ startY WRITE setStartY NOTIFY startYChanged) Q_PROPERTY(bool closed READ isClosed NOTIFY changed) - Q_PROPERTY(QSizeF scale READ scale WRITE setScale NOTIFY scaleChanged REVISION 14) + Q_PROPERTY(QSizeF scale READ scale WRITE setScale NOTIFY scaleChanged REVISION(2, 14)) Q_CLASSINFO("DefaultProperty", "pathElements") QML_NAMED_ELEMENT(Path) + QML_ADDED_IN_VERSION(2, 0) Q_INTERFACES(QQmlParserStatus) public: QQuickPath(QObject *parent=nullptr); @@ -535,7 +546,7 @@ public: QPainterPath path() const; QStringList attributes() const; qreal attributeAt(const QString &, qreal) const; - Q_REVISION(14) Q_INVOKABLE QPointF pointAtPercent(qreal t) const; + Q_REVISION(2, 14) Q_INVOKABLE QPointF pointAtPercent(qreal t) const; QPointF sequentialPointAt(qreal p, qreal *angle = nullptr) const; void invalidateSequentialHistory() const; @@ -546,7 +557,7 @@ Q_SIGNALS: void changed(); void startXChanged(); void startYChanged(); - Q_REVISION(14) void scaleChanged(); + Q_REVISION(2, 14) void scaleChanged(); protected: QQuickPath(QQuickPathPrivate &dd, QObject *parent = nullptr); @@ -609,7 +620,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathText : public QQuickPathElement Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged) QML_NAMED_ELEMENT(PathText) - QML_ADDED_IN_MINOR_VERSION(15) + QML_ADDED_IN_VERSION(2, 15) public: QQuickPathText(QObject *parent=nullptr) : QQuickPathElement(parent) { diff --git a/src/quick/util/qquickpathinterpolator_p.h b/src/quick/util/qquickpathinterpolator_p.h index 440ea06841..70fb0935e8 100644 --- a/src/quick/util/qquickpathinterpolator_p.h +++ b/src/quick/util/qquickpathinterpolator_p.h @@ -70,6 +70,7 @@ class Q_AUTOTEST_EXPORT QQuickPathInterpolator : public QObject Q_PROPERTY(qreal y READ y NOTIFY yChanged) Q_PROPERTY(qreal angle READ angle NOTIFY angleChanged) QML_NAMED_ELEMENT(PathInterpolator) + QML_ADDED_IN_VERSION(2, 0) public: explicit QQuickPathInterpolator(QObject *parent = nullptr); diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp index d47719389b..d96ebe70b2 100644 --- a/src/quick/util/qquickpixmapcache.cpp +++ b/src/quick/util/qquickpixmapcache.cpp @@ -86,6 +86,8 @@ QT_BEGIN_NAMESPACE const QLatin1String QQuickPixmap::itemGrabberScheme = QLatin1String("itemgrabber"); +Q_LOGGING_CATEGORY(lcImg, "qt.quick.image") + #ifndef QT_NO_DEBUG static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty("QML_LEAK_CHECK"); #endif @@ -137,6 +139,7 @@ public: QQuickPixmapData *data; QQmlEngine *engineForReader; // always access reader inside readerMutex + QRect requestRegion; QSize requestSize; QUrl url; @@ -240,9 +243,10 @@ public: class QQuickPixmapData { public: - QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QSize &s, const QQuickImageProviderOptions &po, const QString &e) + QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QRect &r, const QSize &rs, + const QQuickImageProviderOptions &po, const QString &e) : refCount(1), frameCount(1), frame(0), inCache(false), pixmapStatus(QQuickPixmap::Error), - url(u), errorString(e), requestSize(s), + url(u), errorString(e), requestRegion(r), requestSize(rs), providerOptions(po), appliedTransform(QQuickImageProviderOptions::UsePluginDefaultTransform), textureFactory(nullptr), reply(nullptr), prevUnreferenced(nullptr), prevUnreferencedPtr(nullptr), nextUnreferenced(nullptr) @@ -250,9 +254,10 @@ public: declarativePixmaps.insert(pixmap); } - QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QSize &r, const QQuickImageProviderOptions &po, QQuickImageProviderOptions::AutoTransform aTransform, int frame=0, int frameCount=1) + QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QRect &r, const QSize &s, const QQuickImageProviderOptions &po, + QQuickImageProviderOptions::AutoTransform aTransform, int frame=0, int frameCount=1) : refCount(1), frameCount(frameCount), frame(frame), inCache(false), pixmapStatus(QQuickPixmap::Loading), - url(u), requestSize(r), + url(u), requestRegion(r), requestSize(s), providerOptions(po), appliedTransform(aTransform), textureFactory(nullptr), reply(nullptr), prevUnreferenced(nullptr), prevUnreferencedPtr(nullptr), nextUnreferenced(nullptr) @@ -261,9 +266,10 @@ public: } QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, QQuickTextureFactory *texture, - const QSize &s, const QSize &r, const QQuickImageProviderOptions &po, QQuickImageProviderOptions::AutoTransform aTransform, int frame=0, int frameCount=1) + const QSize &s, const QRect &r, const QSize &rs, const QQuickImageProviderOptions &po, + QQuickImageProviderOptions::AutoTransform aTransform, int frame=0, int frameCount=1) : refCount(1), frameCount(frameCount), frame(frame), inCache(false), pixmapStatus(QQuickPixmap::Ready), - url(u), implicitSize(s), requestSize(r), + url(u), implicitSize(s), requestRegion(r), requestSize(rs), providerOptions(po), appliedTransform(aTransform), textureFactory(texture), reply(nullptr), prevUnreferenced(nullptr), prevUnreferencedPtr(nullptr), nextUnreferenced(nullptr) @@ -308,9 +314,11 @@ public: QUrl url; QString errorString; QSize implicitSize; + QRect requestRegion; QSize requestSize; QQuickImageProviderOptions providerOptions; QQuickImageProviderOptions::AutoTransform appliedTransform; + QColorSpace targetColorSpace; QQuickTextureFactory *textureFactory; @@ -399,7 +407,7 @@ static void maybeRemoveAlpha(QImage *image) } static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize, int *frameCount, - const QSize &requestSize, const QQuickImageProviderOptions &providerOptions, + const QRect &requestRegion, const QSize &requestSize, const QQuickImageProviderOptions &providerOptions, QQuickImageProviderOptions::AutoTransform *appliedTransform = nullptr, int frame = 0) { QImageReader imgio(dev); @@ -417,14 +425,25 @@ static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *e QSize scSize = QQuickImageProviderWithOptions::loadSize(imgio.size(), requestSize, imgio.format(), providerOptions); if (scSize.isValid()) imgio.setScaledSize(scSize); + if (!requestRegion.isNull()) + imgio.setScaledClipRect(requestRegion); + const QSize originalSize = imgio.size(); + qCDebug(lcImg) << url << "frame" << frame << "of" << imgio.imageCount() + << "requestRegion" << requestRegion << "QImageReader size" << originalSize << "-> scSize" << scSize; if (impsize) - *impsize = imgio.size(); + *impsize = originalSize; if (imgio.read(image)) { maybeRemoveAlpha(image); if (impsize && impsize->width() < 0) *impsize = image->size(); + if (providerOptions.targetColorSpace().isValid()) { + if (image->colorSpace().isValid()) + image->convertToColorSpace(providerOptions.targetColorSpace()); + else + image->setColorSpace(providerOptions.targetColorSpace()); + } return true; } else { if (errorString) @@ -559,7 +578,7 @@ void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply) QQuickPixmapReply::ReadError error = QQuickPixmapReply::NoError; QString errorString; QSize readSize; - if (reply->networkError()) { + if (reply->error()) { error = QQuickPixmapReply::Loading; errorString = reply->errorString(); } else { @@ -568,7 +587,8 @@ void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply) buff.open(QIODevice::ReadOnly); int frameCount; int const frame = job->data ? job->data->frame : 0; - if (!readImage(reply->url(), &buff, &image, &errorString, &readSize, &frameCount, job->requestSize, job->providerOptions, nullptr, frame)) + if (!readImage(reply->url(), &buff, &image, &errorString, &readSize, &frameCount, + job->requestRegion, job->requestSize, job->providerOptions, nullptr, frame)) error = QQuickPixmapReply::Decoding; else if (job->data) job->data->frameCount = frameCount; @@ -884,7 +904,8 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u } else { int frameCount; int const frame = runningJob->data ? runningJob->data->frame : 0; - if ( !readImage(url, &f, &image, &errorStr, &readSize, &frameCount, runningJob->requestSize, runningJob->providerOptions, nullptr, frame)) { + if (!readImage(url, &f, &image, &errorStr, &readSize, &frameCount, runningJob->requestRegion, runningJob->requestSize, + runningJob->providerOptions, nullptr, frame)) { errorCode = QQuickPixmapReply::Loading; if (f.fileName() != localFile) errorStr += QString::fromLatin1(" (%1)").arg(f.fileName()); @@ -997,6 +1018,7 @@ class QQuickPixmapKey { public: const QUrl *url; + const QRect *region; const QSize *size; int frame; QQuickImageProviderOptions options; @@ -1004,12 +1026,20 @@ public: inline bool operator==(const QQuickPixmapKey &lhs, const QQuickPixmapKey &rhs) { - return *lhs.size == *rhs.size && *lhs.url == *rhs.url && lhs.options == rhs.options && lhs.frame == rhs.frame; + return *lhs.url == *rhs.url && + *lhs.region == *rhs.region && + *lhs.size == *rhs.size && + lhs.frame == rhs.frame && + lhs.options == rhs.options; } inline uint qHash(const QQuickPixmapKey &key) { - return qHash(*key.url) ^ (key.size->width()*7) ^ (key.size->height()*17) ^ (key.frame*23) ^ (key.options.autoTransform() * 0x5c5c5c5c); + return qHash(*key.url) ^ (key.size->width()*7) ^ (key.size->height()*17) ^ (key.frame*23) ^ + (key.region->x()*29) ^ (key.region->y()*31) ^ (key.options.autoTransform() * 0x5c5c5c5c); + // key.region.width() and height() are not included, because the hash function should be simple, + // and they are more likely to be held constant for some batches of images + // (e.g. tiles, or repeatedly cropping to the same viewport at different positions). } class QQuickPixmapStore : public QObject @@ -1176,7 +1206,8 @@ void QQuickPixmap::purgeCache() } QQuickPixmapReply::QQuickPixmapReply(QQuickPixmapData *d) -: data(d), engineForReader(nullptr), requestSize(d->requestSize), url(d->url), loading(false), providerOptions(d->providerOptions), redirectCount(0) + : data(d), engineForReader(nullptr), requestRegion(d->requestRegion), requestSize(d->requestSize), + url(d->url), loading(false), providerOptions(d->providerOptions), redirectCount(0) { if (finishedIndex == -1) { finishedIndex = QMetaMethod::fromSignal(&QQuickPixmapReply::finished).methodIndex(); @@ -1271,7 +1302,7 @@ void QQuickPixmapData::release() void QQuickPixmapData::addToCache() { if (!inCache) { - QQuickPixmapKey key = { &url, &requestSize, frame, providerOptions }; + QQuickPixmapKey key = { &url, &requestRegion, &requestSize, frame, providerOptions }; pixmapStore()->m_cache.insert(key, this); inCache = true; PIXMAP_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapCacheCountChanged>( @@ -1282,7 +1313,7 @@ void QQuickPixmapData::addToCache() void QQuickPixmapData::removeFromCache() { if (inCache) { - QQuickPixmapKey key = { &url, &requestSize, frame, providerOptions }; + QQuickPixmapKey key = { &url, &requestRegion, &requestSize, frame, providerOptions }; pixmapStore()->m_cache.remove(key); inCache = false; PIXMAP_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapCacheCountChanged>( @@ -1290,7 +1321,9 @@ void QQuickPixmapData::removeFromCache() } } -static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, QQmlEngine *engine, const QUrl &url, const QSize &requestSize, const QQuickImageProviderOptions &providerOptions, int frame, bool *ok) +static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, QQmlEngine *engine, const QUrl &url, + const QRect &requestRegion, const QSize &requestSize, + const QQuickImageProviderOptions &providerOptions, int frame, bool *ok) { if (url.scheme() == QLatin1String("image")) { QSize readSize; @@ -1305,7 +1338,7 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q switch (imageType) { case QQuickImageProvider::Invalid: - return new QQuickPixmapData(declarativePixmap, url, requestSize, providerOptions, + return new QQuickPixmapData(declarativePixmap, url, requestRegion, requestSize, providerOptions, QQuickPixmap::tr("Invalid image provider: %1").arg(url.toString())); case QQuickImageProvider::Texture: { @@ -1313,7 +1346,8 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q : provider->requestTexture(imageId(url), &readSize, requestSize); if (texture) { *ok = true; - return new QQuickPixmapData(declarativePixmap, url, texture, readSize, requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform, frame); + return new QQuickPixmapData(declarativePixmap, url, texture, readSize, requestRegion, requestSize, + providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform, frame); } break; } @@ -1324,7 +1358,9 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q : provider->requestImage(imageId(url), &readSize, requestSize); if (!image.isNull()) { *ok = true; - return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform, frame); + return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), + readSize, requestRegion, requestSize, providerOptions, + QQuickImageProviderOptions::UsePluginDefaultTransform, frame); } break; } @@ -1334,7 +1370,9 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q : provider->requestPixmap(imageId(url), &readSize, requestSize); if (!pixmap.isNull()) { *ok = true; - return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(pixmap.toImage()), readSize, requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform, frame); + return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(pixmap.toImage()), + readSize, requestRegion, requestSize, providerOptions, + QQuickImageProviderOptions::UsePluginDefaultTransform, frame); } break; } @@ -1346,7 +1384,7 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q } // provider has bad image type, or provider returned null image - return new QQuickPixmapData(declarativePixmap, url, requestSize, providerOptions, + return new QQuickPixmapData(declarativePixmap, url, requestRegion, requestSize, providerOptions, QQuickPixmap::tr("Failed to get image from provider: %1").arg(url.toString())); } @@ -1364,7 +1402,8 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q QQuickTextureFactory *factory = texReader.read(); if (factory) { *ok = true; - return new QQuickPixmapData(declarativePixmap, url, factory, factory->textureSize(), requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform, frame); + return new QQuickPixmapData(declarativePixmap, url, factory, factory->textureSize(), requestRegion, requestSize, + providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform, frame); } else { errorString = QQuickPixmap::tr("Error decoding: %1").arg(url.toString()); if (f.fileName() != localFile) @@ -1374,9 +1413,10 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q QImage image; QQuickImageProviderOptions::AutoTransform appliedTransform = providerOptions.autoTransform(); int frameCount; - if (readImage(url, &f, &image, &errorString, &readSize, &frameCount, requestSize, providerOptions, &appliedTransform, frame)) { + if (readImage(url, &f, &image, &errorString, &readSize, &frameCount, requestRegion, requestSize, providerOptions, &appliedTransform, frame)) { *ok = true; - return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestSize, providerOptions, appliedTransform, frame, frameCount); + return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestRegion, requestSize, + providerOptions, appliedTransform, frame, frameCount); } else if (f.fileName() != localFile) { errorString += QString::fromLatin1(" (%1)").arg(f.fileName()); } @@ -1384,12 +1424,13 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q } else { errorString = QQuickPixmap::tr("Cannot open: %1").arg(url.toString()); } - return new QQuickPixmapData(declarativePixmap, url, requestSize, providerOptions, errorString); + return new QQuickPixmapData(declarativePixmap, url, requestRegion, requestSize, providerOptions, errorString); } struct QQuickPixmapNull { QUrl url; + QRect region; QSize size; }; Q_GLOBAL_STATIC(QQuickPixmapNull, nullPixmap); @@ -1405,15 +1446,16 @@ QQuickPixmap::QQuickPixmap(QQmlEngine *engine, const QUrl &url) load(engine, url); } -QQuickPixmap::QQuickPixmap(QQmlEngine *engine, const QUrl &url, const QSize &size) +QQuickPixmap::QQuickPixmap(QQmlEngine *engine, const QUrl &url, const QRect ®ion, const QSize &size) : d(nullptr) { - load(engine, url, size); + load(engine, url, region, size); } QQuickPixmap::QQuickPixmap(const QUrl &url, const QImage &image) { - d = new QQuickPixmapData(this, url, new QQuickDefaultTextureFactory(image), image.size(), QSize(), QQuickImageProviderOptions(), QQuickImageProviderOptions::UsePluginDefaultTransform); + d = new QQuickPixmapData(this, url, new QQuickDefaultTextureFactory(image), image.size(), QRect(), QSize(), + QQuickImageProviderOptions(), QQuickImageProviderOptions::UsePluginDefaultTransform); d->addToCache(); } @@ -1486,6 +1528,14 @@ const QSize &QQuickPixmap::requestSize() const return nullPixmap()->size; } +const QRect &QQuickPixmap::requestRegion() const +{ + if (d) + return d->requestRegion; + else + return nullPixmap()->region; +} + QQuickImageProviderOptions::AutoTransform QQuickPixmap::autoTransform() const { if (d) @@ -1561,25 +1611,26 @@ QRect QQuickPixmap::rect() const void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url) { - load(engine, url, QSize(), QQuickPixmap::Cache); + load(engine, url, QRect(), QSize(), QQuickPixmap::Cache); } void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, QQuickPixmap::Options options) { - load(engine, url, QSize(), options); + load(engine, url, QRect(), QSize(), options); } -void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &size) +void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QRect &requestRegion, const QSize &requestSize) { - load(engine, url, size, QQuickPixmap::Cache); + load(engine, url, requestRegion, requestSize, QQuickPixmap::Cache); } -void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &requestSize, QQuickPixmap::Options options) +void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QRect &requestRegion, const QSize &requestSize, QQuickPixmap::Options options) { - load(engine, url, requestSize, options, QQuickImageProviderOptions()); + load(engine, url, requestRegion, requestSize, options, QQuickImageProviderOptions()); } -void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &requestSize, QQuickPixmap::Options options, const QQuickImageProviderOptions &providerOptions, int frame, int frameCount) +void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QRect &requestRegion, const QSize &requestSize, + QQuickPixmap::Options options, const QQuickImageProviderOptions &providerOptions, int frame, int frameCount) { if (d) { d->declarativePixmaps.remove(this); @@ -1587,7 +1638,7 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &reques d = nullptr; } - QQuickPixmapKey key = { &url, &requestSize, frame, providerOptions }; + QQuickPixmapKey key = { &url, &requestRegion, &requestSize, frame, providerOptions }; QQuickPixmapStore *store = pixmapStore(); QHash<QQuickPixmapKey, QQuickPixmapData *>::Iterator iter = store->m_cache.end(); @@ -1596,10 +1647,11 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &reques // cached version. Unless it's an itemgrabber url, since the cache is used to pass // the result between QQuickItemGrabResult and QQuickImage. if (url.scheme() == itemGrabberScheme) { - QSize dummy; - if (requestSize != dummy) + QRect dummyRegion; + QSize dummySize; + if (requestSize != dummySize) qWarning() << "Ignoring sourceSize request for image url that came from grabToImage. Use the targetSize parameter of the grabToImage() function instead."; - const QQuickPixmapKey grabberKey = { &url, &dummy, 0, QQuickImageProviderOptions() }; + const QQuickPixmapKey grabberKey = { &url, &dummyRegion, &dummySize, 0, QQuickImageProviderOptions() }; iter = store->m_cache.find(grabberKey); } else if (options & QQuickPixmap::Cache) iter = store->m_cache.find(key); @@ -1621,7 +1673,7 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &reques if (!(options & QQuickPixmap::Asynchronous)) { bool ok = false; PIXMAP_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingStarted>(url)); - d = createPixmapDataSync(this, engine, url, requestSize, providerOptions, frame, &ok); + d = createPixmapDataSync(this, engine, url, requestRegion, requestSize, providerOptions, frame, &ok); if (ok) { PIXMAP_PROFILE(pixmapLoadingFinished(url, QSize(width(), height()))); if (options & QQuickPixmap::Cache) @@ -1638,7 +1690,8 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &reques return; - d = new QQuickPixmapData(this, url, requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform, frame, frameCount); + d = new QQuickPixmapData(this, url, requestRegion, requestSize, providerOptions, + QQuickImageProviderOptions::UsePluginDefaultTransform, frame, frameCount); if (options & QQuickPixmap::Cache) d->addToCache(); @@ -1672,9 +1725,10 @@ void QQuickPixmap::clear(QObject *obj) } } -bool QQuickPixmap::isCached(const QUrl &url, const QSize &requestSize, const int frame, const QQuickImageProviderOptions &options) +bool QQuickPixmap::isCached(const QUrl &url, const QRect &requestRegion, const QSize &requestSize, + const int frame, const QQuickImageProviderOptions &options) { - QQuickPixmapKey key = { &url, &requestSize, frame, options }; + QQuickPixmapKey key = { &url, &requestRegion, &requestSize, frame, options }; QQuickPixmapStore *store = pixmapStore(); return store->m_cache.contains(key); @@ -1720,6 +1774,13 @@ bool QQuickPixmap::connectDownloadProgress(QObject *object, int method) return QMetaObject::connect(d->reply, QQuickPixmapReply::downloadProgressIndex, object, method); } +QColorSpace QQuickPixmap::colorSpace() const +{ + if (!d || !d->textureFactory) + return QColorSpace(); + return d->textureFactory->image().colorSpace(); +} + QT_END_NAMESPACE #include <qquickpixmapcache.moc> diff --git a/src/quick/util/qquickpixmapcache_p.h b/src/quick/util/qquickpixmapcache_p.h index c4f4d1a101..87724d6210 100644 --- a/src/quick/util/qquickpixmapcache_p.h +++ b/src/quick/util/qquickpixmapcache_p.h @@ -117,6 +117,9 @@ public: bool preserveAspectRatioFit() const; void setPreserveAspectRatioFit(bool preserveAspectRatioFit); + QColorSpace targetColorSpace() const; + void setTargetColorSpace(const QColorSpace &colorSpace); + private: QSharedDataPointer<QQuickImageProviderOptionsPrivate> d; }; @@ -127,7 +130,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPixmap public: QQuickPixmap(); QQuickPixmap(QQmlEngine *, const QUrl &); - QQuickPixmap(QQmlEngine *, const QUrl &, const QSize &); + QQuickPixmap(QQmlEngine *, const QUrl &, const QRect ®ion, const QSize &); QQuickPixmap(const QUrl &, const QImage &image); ~QQuickPixmap(); @@ -148,6 +151,7 @@ public: QString error() const; const QUrl &url() const; const QSize &implicitSize() const; + const QRect &requestRegion() const; const QSize &requestSize() const; QQuickImageProviderOptions::AutoTransform autoTransform() const; int frameCount() const; @@ -155,6 +159,8 @@ public: void setImage(const QImage &); void setPixmap(const QQuickPixmap &other); + QColorSpace colorSpace() const; + QQuickTextureFactory *textureFactory() const; QRect rect() const; @@ -163,9 +169,10 @@ public: void load(QQmlEngine *, const QUrl &); void load(QQmlEngine *, const QUrl &, QQuickPixmap::Options options); - void load(QQmlEngine *, const QUrl &, const QSize &); - void load(QQmlEngine *, const QUrl &, const QSize &, QQuickPixmap::Options options); - void load(QQmlEngine *, const QUrl &, const QSize &, QQuickPixmap::Options options, const QQuickImageProviderOptions &providerOptions, int frame = 0, int frameCount = 1); + void load(QQmlEngine *, const QUrl &, const QRect &requestRegion, const QSize &requestSize); + void load(QQmlEngine *, const QUrl &, const QRect &requestRegion, const QSize &requestSize, QQuickPixmap::Options options); + void load(QQmlEngine *, const QUrl &, const QRect &requestRegion, const QSize &requestSize, + QQuickPixmap::Options options, const QQuickImageProviderOptions &providerOptions, int frame = 0, int frameCount = 1); void clear(); void clear(QObject *); @@ -176,7 +183,8 @@ public: bool connectDownloadProgress(QObject *, int); static void purgeCache(); - static bool isCached(const QUrl &url, const QSize &requestSize, const int frame, const QQuickImageProviderOptions &options); + static bool isCached(const QUrl &url, const QRect &requestRegion, const QSize &requestSize, + const int frame, const QQuickImageProviderOptions &options); static const QLatin1String itemGrabberScheme; diff --git a/src/quick/util/qquickpropertychanges_p.h b/src/quick/util/qquickpropertychanges_p.h index 27a00420af..ff48de96c6 100644 --- a/src/quick/util/qquickpropertychanges_p.h +++ b/src/quick/util/qquickpropertychanges_p.h @@ -66,6 +66,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPropertyChanges : public QQuickStateOperation Q_PROPERTY(bool restoreEntryValues READ restoreEntryValues WRITE setRestoreEntryValues) Q_PROPERTY(bool explicit READ isExplicit WRITE setIsExplicit) QML_NAMED_ELEMENT(PropertyChanges) + QML_ADDED_IN_VERSION(2, 0) public: QQuickPropertyChanges(); diff --git a/src/quick/util/qquickshortcut_p.h b/src/quick/util/qquickshortcut_p.h index 0e66a38e75..67dab928b7 100644 --- a/src/quick/util/qquickshortcut_p.h +++ b/src/quick/util/qquickshortcut_p.h @@ -67,14 +67,14 @@ class QQuickShortcut : public QObject, public QQmlParserStatus Q_OBJECT Q_INTERFACES(QQmlParserStatus) Q_PROPERTY(QVariant sequence READ sequence WRITE setSequence NOTIFY sequenceChanged FINAL) - Q_PROPERTY(QVariantList sequences READ sequences WRITE setSequences NOTIFY sequencesChanged FINAL REVISION 9) - Q_PROPERTY(QString nativeText READ nativeText NOTIFY sequenceChanged FINAL REVISION 6) - Q_PROPERTY(QString portableText READ portableText NOTIFY sequenceChanged FINAL REVISION 6) + Q_PROPERTY(QVariantList sequences READ sequences WRITE setSequences NOTIFY sequencesChanged FINAL REVISION(2, 9)) + Q_PROPERTY(QString nativeText READ nativeText NOTIFY sequenceChanged FINAL REVISION(2, 6)) + Q_PROPERTY(QString portableText READ portableText NOTIFY sequenceChanged FINAL REVISION(2, 6)) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged FINAL) Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat NOTIFY autoRepeatChanged FINAL) Q_PROPERTY(Qt::ShortcutContext context READ context WRITE setContext NOTIFY contextChanged FINAL) QML_NAMED_ELEMENT(Shortcut) - QML_ADDED_IN_MINOR_VERSION(5) + QML_ADDED_IN_VERSION(2, 5) public: explicit QQuickShortcut(QObject *parent = nullptr); @@ -100,7 +100,7 @@ public: Q_SIGNALS: void sequenceChanged(); - Q_REVISION(9) void sequencesChanged(); + Q_REVISION(2, 9) void sequencesChanged(); void enabledChanged(); void autoRepeatChanged(); void contextChanged(); diff --git a/src/quick/util/qquicksmoothedanimation_p.h b/src/quick/util/qquicksmoothedanimation_p.h index d7e637446d..4a53a4406f 100644 --- a/src/quick/util/qquicksmoothedanimation_p.h +++ b/src/quick/util/qquicksmoothedanimation_p.h @@ -69,6 +69,7 @@ class Q_AUTOTEST_EXPORT QQuickSmoothedAnimation : public QQuickNumberAnimation Q_PROPERTY(ReversingMode reversingMode READ reversingMode WRITE setReversingMode NOTIFY reversingModeChanged) Q_PROPERTY(qreal maximumEasingTime READ maximumEasingTime WRITE setMaximumEasingTime NOTIFY maximumEasingTimeChanged) QML_NAMED_ELEMENT(SmoothedAnimation) + QML_ADDED_IN_VERSION(2, 0) public: enum ReversingMode { Eased, Immediate, Sync }; diff --git a/src/quick/util/qquickspringanimation_p.h b/src/quick/util/qquickspringanimation_p.h index 771b746622..c09806e0ec 100644 --- a/src/quick/util/qquickspringanimation_p.h +++ b/src/quick/util/qquickspringanimation_p.h @@ -72,6 +72,7 @@ class Q_AUTOTEST_EXPORT QQuickSpringAnimation : public QQuickNumberAnimation Q_PROPERTY(qreal modulus READ modulus WRITE setModulus NOTIFY modulusChanged) Q_PROPERTY(qreal mass READ mass WRITE setMass NOTIFY massChanged) QML_NAMED_ELEMENT(SpringAnimation) + QML_ADDED_IN_VERSION(2, 0) public: QQuickSpringAnimation(QObject *parent=nullptr); diff --git a/src/quick/util/qquickstate.cpp b/src/quick/util/qquickstate.cpp index c106528f45..71ab1f4d62 100644 --- a/src/quick/util/qquickstate.cpp +++ b/src/quick/util/qquickstate.cpp @@ -267,9 +267,13 @@ void QQuickState::setExtends(const QString &extends) QQmlListProperty<QQuickStateOperation> QQuickState::changes() { Q_D(QQuickState); - return QQmlListProperty<QQuickStateOperation>(this, &d->operations, QQuickStatePrivate::operations_append, - QQuickStatePrivate::operations_count, QQuickStatePrivate::operations_at, - QQuickStatePrivate::operations_clear); + return QQmlListProperty<QQuickStateOperation>(this, &d->operations, + QQuickStatePrivate::operations_append, + QQuickStatePrivate::operations_count, + QQuickStatePrivate::operations_at, + QQuickStatePrivate::operations_clear, + QQuickStatePrivate::operations_replace, + QQuickStatePrivate::operations_removeLast); } int QQuickState::operationCount() const diff --git a/src/quick/util/qquickstate_p.h b/src/quick/util/qquickstate_p.h index af49bb1c2f..ee9aa92bbd 100644 --- a/src/quick/util/qquickstate_p.h +++ b/src/quick/util/qquickstate_p.h @@ -126,6 +126,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickStateOperation : public QObject { Q_OBJECT QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQuickStateOperation(QObject *parent = nullptr) : QObject(parent) {} @@ -159,6 +160,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickState : public QObject Q_CLASSINFO("DefaultProperty", "changes") Q_CLASSINFO("DeferredPropertyNames", "changes") QML_NAMED_ELEMENT(State) + QML_ADDED_IN_VERSION(2, 0) public: QQuickState(QObject *parent=nullptr); diff --git a/src/quick/util/qquickstate_p_p.h b/src/quick/util/qquickstate_p_p.h index 2fa5321165..ae4ed291b5 100644 --- a/src/quick/util/qquickstate_p_p.h +++ b/src/quick/util/qquickstate_p_p.h @@ -244,6 +244,23 @@ public: QList<OperationGuard> *list = static_cast<QList<OperationGuard> *>(prop->data); return list->at(index); } + static void operations_replace(QQmlListProperty<QQuickStateOperation> *prop, int index, + QQuickStateOperation *op) { + QList<OperationGuard> *list = static_cast<QList<OperationGuard> *>(prop->data); + auto &guard = list->at(index); + if (guard.object() == op) { + op->setState(qobject_cast<QQuickState*>(prop->object)); + } else { + list->at(index)->setState(nullptr); + op->setState(qobject_cast<QQuickState*>(prop->object)); + list->replace(index, OperationGuard(op, list)); + } + } + static void operations_removeLast(QQmlListProperty<QQuickStateOperation> *prop) { + QList<OperationGuard> *list = static_cast<QList<OperationGuard> *>(prop->data); + list->last()->setState(nullptr); + list->removeLast(); + } QQuickTransitionManager transitionManager; diff --git a/src/quick/util/qquickstatechangescript_p.h b/src/quick/util/qquickstatechangescript_p.h index 931baaca4e..62f4910606 100644 --- a/src/quick/util/qquickstatechangescript_p.h +++ b/src/quick/util/qquickstatechangescript_p.h @@ -65,6 +65,7 @@ class Q_AUTOTEST_EXPORT QQuickStateChangeScript : public QQuickStateOperation, p Q_PROPERTY(QQmlScriptString script READ script WRITE setScript) Q_PROPERTY(QString name READ name WRITE setName) QML_NAMED_ELEMENT(StateChangeScript) + QML_ADDED_IN_VERSION(2, 0) public: QQuickStateChangeScript(QObject *parent=nullptr); diff --git a/src/quick/util/qquickstategroup.cpp b/src/quick/util/qquickstategroup.cpp index 46e7d62fc1..2109aafc10 100644 --- a/src/quick/util/qquickstategroup.cpp +++ b/src/quick/util/qquickstategroup.cpp @@ -70,6 +70,8 @@ public: static int count_state(QQmlListProperty<QQuickState> *list); static QQuickState *at_state(QQmlListProperty<QQuickState> *list, int index); static void clear_states(QQmlListProperty<QQuickState> *list); + static void replace_states(QQmlListProperty<QQuickState> *list, int index, QQuickState *state); + static void removeLast_states(QQmlListProperty<QQuickState> *list); static void append_transition(QQmlListProperty<QQuickTransition> *list, QQuickTransition *state); static int count_transitions(QQmlListProperty<QQuickTransition> *list); @@ -163,10 +165,13 @@ QList<QQuickState *> QQuickStateGroup::states() const QQmlListProperty<QQuickState> QQuickStateGroup::statesProperty() { Q_D(QQuickStateGroup); - return QQmlListProperty<QQuickState>(this, &d->states, &QQuickStateGroupPrivate::append_state, - &QQuickStateGroupPrivate::count_state, - &QQuickStateGroupPrivate::at_state, - &QQuickStateGroupPrivate::clear_states); + return QQmlListProperty<QQuickState>(this, &d->states, + &QQuickStateGroupPrivate::append_state, + &QQuickStateGroupPrivate::count_state, + &QQuickStateGroupPrivate::at_state, + &QQuickStateGroupPrivate::clear_states, + &QQuickStateGroupPrivate::replace_states, + &QQuickStateGroupPrivate::removeLast_states); } void QQuickStateGroupPrivate::append_state(QQmlListProperty<QQuickState> *list, QQuickState *state) @@ -201,6 +206,29 @@ void QQuickStateGroupPrivate::clear_states(QQmlListProperty<QQuickState> *list) _this->d_func()->states.clear(); } +void QQuickStateGroupPrivate::replace_states(QQmlListProperty<QQuickState> *list, int index, QQuickState *state) +{ + auto *self = qobject_cast<QQuickStateGroup *>(list->object); + auto *d = self->d_func(); + auto *oldState = d->states.at(index); + if (oldState != state) { + oldState->setStateGroup(nullptr); + state->setStateGroup(self); + d->states.replace(index, state); + if (d->currentState == oldState->name()) + d->setCurrentStateInternal(state->name(), true); + } +} + +void QQuickStateGroupPrivate::removeLast_states(QQmlListProperty<QQuickState> *list) +{ + auto *d = qobject_cast<QQuickStateGroup *>(list->object)->d_func(); + if (d->currentState == d->states.last()->name()) + d->setCurrentStateInternal(d->states.length() > 1 ? d->states.first()->name() : QString(), true); + d->states.last()->setStateGroup(nullptr); + d->states.removeLast(); +} + /*! \qmlproperty list<Transition> QtQuick::StateGroup::transitions This property holds a list of transitions defined by the state group. diff --git a/src/quick/util/qquickstategroup_p.h b/src/quick/util/qquickstategroup_p.h index 11a0c5f442..c3d66fd824 100644 --- a/src/quick/util/qquickstategroup_p.h +++ b/src/quick/util/qquickstategroup_p.h @@ -66,6 +66,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickStateGroup : public QObject, public QQmlParse Q_PROPERTY(QQmlListProperty<QQuickState> states READ statesProperty DESIGNABLE false) Q_PROPERTY(QQmlListProperty<QQuickTransition> transitions READ transitionsProperty DESIGNABLE false) QML_NAMED_ELEMENT(StateGroup) + QML_ADDED_IN_VERSION(2, 0) public: QQuickStateGroup(QObject * = nullptr); diff --git a/src/quick/util/qquickstyledtext.cpp b/src/quick/util/qquickstyledtext.cpp index 08d06c66ab..660852ba83 100644 --- a/src/quick/util/qquickstyledtext.cpp +++ b/src/quick/util/qquickstyledtext.cpp @@ -706,7 +706,7 @@ void QQuickStyledTextPrivate::parseImageAttributes(const QChar *&ch, const QStri // to avoid a relayout later on. QUrl url = baseUrl.resolved(image->url); if (url.isLocalFile()) { - image->pix = new QQuickPixmap(context->engine(), url, image->size); + image->pix = new QQuickPixmap(context->engine(), url, QRect(), image->size); if (image->pix && image->pix->isReady()) { image->size = image->pix->implicitSize(); } else { diff --git a/src/quick/util/qquicksystempalette_p.h b/src/quick/util/qquicksystempalette_p.h index c6d9fc2604..43d7277bea 100644 --- a/src/quick/util/qquicksystempalette_p.h +++ b/src/quick/util/qquicksystempalette_p.h @@ -80,6 +80,7 @@ class Q_AUTOTEST_EXPORT QQuickSystemPalette : public QObject Q_PROPERTY(QColor highlight READ highlight NOTIFY paletteChanged) Q_PROPERTY(QColor highlightedText READ highlightedText NOTIFY paletteChanged) QML_NAMED_ELEMENT(SystemPalette) + QML_ADDED_IN_VERSION(2, 0) public: QQuickSystemPalette(QObject *parent=nullptr); diff --git a/src/quick/util/qquicktextmetrics_p.h b/src/quick/util/qquicktextmetrics_p.h index a1d64e3d0a..33c64073c2 100644 --- a/src/quick/util/qquicktextmetrics_p.h +++ b/src/quick/util/qquicktextmetrics_p.h @@ -75,7 +75,7 @@ class Q_AUTOTEST_EXPORT QQuickTextMetrics : public QObject Q_PROPERTY(Qt::TextElideMode elide READ elide WRITE setElide NOTIFY elideChanged FINAL) Q_PROPERTY(qreal elideWidth READ elideWidth WRITE setElideWidth NOTIFY elideWidthChanged FINAL) QML_NAMED_ELEMENT(TextMetrics) - QML_ADDED_IN_MINOR_VERSION(4) + QML_ADDED_IN_VERSION(2, 4) public: explicit QQuickTextMetrics(QObject *parent = 0); diff --git a/src/quick/util/qquicktimeline_p_p.h b/src/quick/util/qquicktimeline_p_p.h index abb5369b7b..fc5bd15ed1 100644 --- a/src/quick/util/qquicktimeline_p_p.h +++ b/src/quick/util/qquicktimeline_p_p.h @@ -52,6 +52,7 @@ // #include <QtCore/QObject> +#include <private/qtquickglobal_p.h> #include "private/qabstractanimationjob_p.h" QT_BEGIN_NAMESPACE @@ -61,7 +62,7 @@ class QQuickTimeLineValue; class QQuickTimeLineCallback; struct QQuickTimeLinePrivate; class QQuickTimeLineObject; -class Q_AUTOTEST_EXPORT QQuickTimeLine : public QObject, QAbstractAnimationJob +class Q_QUICK_PRIVATE_EXPORT QQuickTimeLine : public QObject, QAbstractAnimationJob { Q_OBJECT public: diff --git a/src/quick/util/qquicktransition_p.h b/src/quick/util/qquicktransition_p.h index 6e45143126..bfb7d75821 100644 --- a/src/quick/util/qquicktransition_p.h +++ b/src/quick/util/qquicktransition_p.h @@ -104,6 +104,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTransition : public QObject Q_CLASSINFO("DefaultProperty", "animations") Q_CLASSINFO("DeferredPropertyNames", "animations") QML_NAMED_ELEMENT(Transition) + QML_ADDED_IN_VERSION(2, 0) public: QQuickTransition(QObject *parent=nullptr); diff --git a/src/quick/util/qquickvalidator_p.h b/src/quick/util/qquickvalidator_p.h index a0dc2cd5ba..029737e10b 100644 --- a/src/quick/util/qquickvalidator_p.h +++ b/src/quick/util/qquickvalidator_p.h @@ -62,6 +62,7 @@ class Q_AUTOTEST_EXPORT QQuickIntValidator : public QIntValidator Q_OBJECT Q_PROPERTY(QString locale READ localeName WRITE setLocaleName RESET resetLocaleName NOTIFY localeNameChanged) QML_NAMED_ELEMENT(IntValidator) + QML_ADDED_IN_VERSION(2, 0) public: QQuickIntValidator(QObject *parent = nullptr); @@ -78,6 +79,7 @@ class Q_AUTOTEST_EXPORT QQuickDoubleValidator : public QDoubleValidator Q_OBJECT Q_PROPERTY(QString locale READ localeName WRITE setLocaleName RESET resetLocaleName NOTIFY localeNameChanged) QML_NAMED_ELEMENT(DoubleValidator) + QML_ADDED_IN_VERSION(2, 0) public: QQuickDoubleValidator(QObject *parent = nullptr); diff --git a/src/quick/util/qquickvaluetypes.cpp b/src/quick/util/qquickvaluetypes.cpp index f9cd28cb24..517ed5da38 100644 --- a/src/quick/util/qquickvaluetypes.cpp +++ b/src/quick/util/qquickvaluetypes.cpp @@ -41,6 +41,7 @@ #include <qtquickglobal.h> #include <private/qqmlvaluetype_p.h> +#include <private/qcolorspace_p.h> #include <private/qfont_p.h> @@ -784,6 +785,47 @@ void QQuickFontValueType::setPreferShaping(bool enable) v.setStyleStrategy(static_cast<QFont::StyleStrategy>(v.styleStrategy() | QFont::PreferNoShaping)); } +QQuickColorSpaceValueType::NamedColorSpace QQuickColorSpaceValueType::namedColorSpace() const noexcept +{ + if (const auto *p = QColorSpacePrivate::get(v)) + return (QQuickColorSpaceValueType::NamedColorSpace)p->namedColorSpace; + return QQuickColorSpaceValueType::Unknown; +} +void QQuickColorSpaceValueType::setNamedColorSpace(QQuickColorSpaceValueType::NamedColorSpace namedColorSpace) +{ + v = { (QColorSpace::NamedColorSpace)namedColorSpace }; +} + +QQuickColorSpaceValueType::Primaries QQuickColorSpaceValueType::primaries() const noexcept +{ + return (QQuickColorSpaceValueType::Primaries)v.primaries(); +} + +void QQuickColorSpaceValueType::setPrimaries(QQuickColorSpaceValueType::Primaries primariesId) +{ + v.setPrimaries((QColorSpace::Primaries)primariesId); +} + +QQuickColorSpaceValueType::TransferFunction QQuickColorSpaceValueType::transferFunction() const noexcept +{ + return (QQuickColorSpaceValueType::TransferFunction)v.transferFunction(); +} + +void QQuickColorSpaceValueType::setTransferFunction(QQuickColorSpaceValueType::TransferFunction transferFunction) +{ + v.setTransferFunction((QColorSpace::TransferFunction)transferFunction, v.gamma()); +} + +float QQuickColorSpaceValueType::gamma() const noexcept +{ + return v.gamma(); +} + +void QQuickColorSpaceValueType::setGamma(float gamma) +{ + v.setTransferFunction(v.transferFunction(), gamma); +} + QT_END_NAMESPACE #include "moc_qquickvaluetypes_p.cpp" diff --git a/src/quick/util/qquickvaluetypes_p.h b/src/quick/util/qquickvaluetypes_p.h index 91a5ea83e5..ccd9eefe47 100644 --- a/src/quick/util/qquickvaluetypes_p.h +++ b/src/quick/util/qquickvaluetypes_p.h @@ -56,6 +56,7 @@ #include <private/qqmlvaluetype_p.h> #include <QtGui/QColor> +#include <QtGui/QColorSpace> #include <QtGui/QVector2D> #include <QtGui/QVector3D> #include <QtGui/QVector4D> @@ -329,6 +330,7 @@ class QQuickFontValueType Q_PROPERTY(bool preferShaping READ preferShaping WRITE setPreferShaping FINAL) QML_NAMED_ELEMENT(Font) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("Element is not creatable.") public: @@ -408,6 +410,58 @@ public: void setPreferShaping(bool b); }; +class QQuickColorSpaceValueType +{ + QColorSpace v; + Q_GADGET + + Q_PROPERTY(NamedColorSpace namedColorSpace READ namedColorSpace WRITE setNamedColorSpace FINAL) + Q_PROPERTY(Primaries primaries READ primaries WRITE setPrimaries FINAL) + Q_PROPERTY(TransferFunction transferFunction READ transferFunction WRITE setTransferFunction FINAL) + Q_PROPERTY(float gamma READ gamma WRITE setGamma FINAL) + + QML_NAMED_ELEMENT(ColorSpace) + QML_ADDED_IN_VERSION(2, 15) + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + +public: + enum NamedColorSpace { + Unknown = 0, + SRgb, + SRgbLinear, + AdobeRgb, + DisplayP3, + ProPhotoRgb + }; + Q_ENUM(NamedColorSpace) + + enum class Primaries { + Custom = 0, + SRgb, + AdobeRgb, + DciP3D65, + ProPhotoRgb + }; + Q_ENUM(Primaries) + enum class TransferFunction { + Custom = 0, + Linear, + Gamma, + SRgb, + ProPhotoRgb + }; + Q_ENUM(TransferFunction) + + NamedColorSpace namedColorSpace() const noexcept; + void setNamedColorSpace(NamedColorSpace namedColorSpace); + Primaries primaries() const noexcept; + void setPrimaries(Primaries primariesId); + TransferFunction transferFunction() const noexcept; + void setTransferFunction(TransferFunction transferFunction); + float gamma() const noexcept; + void setGamma(float gamma); +}; + QT_END_NAMESPACE #endif // QQUICKVALUETYPES_P_H diff --git a/src/quickshapes/qquickshape_p.h b/src/quickshapes/qquickshape_p.h index f86f2b03d6..ca72c628c5 100644 --- a/src/quickshapes/qquickshape_p.h +++ b/src/quickshapes/qquickshape_p.h @@ -76,6 +76,7 @@ class Q_QUICKSHAPES_PRIVATE_EXPORT QQuickShapeGradient : public QQuickGradient Q_CLASSINFO("DefaultProperty", "stops") QML_NAMED_ELEMENT(ShapeGradient) + QML_ADDED_IN_VERSION(1, 0) QML_UNCREATABLE("ShapeGradient is an abstract base class."); public: @@ -107,6 +108,7 @@ class Q_QUICKSHAPES_PRIVATE_EXPORT QQuickShapeLinearGradient : public QQuickShap Q_PROPERTY(qreal y2 READ y2 WRITE setY2 NOTIFY y2Changed) Q_CLASSINFO("DefaultProperty", "stops") QML_NAMED_ELEMENT(LinearGradient) + QML_ADDED_IN_VERSION(1, 0) public: QQuickShapeLinearGradient(QObject *parent = nullptr); @@ -142,6 +144,7 @@ class Q_QUICKSHAPES_PRIVATE_EXPORT QQuickShapeRadialGradient : public QQuickShap Q_PROPERTY(qreal focalRadius READ focalRadius WRITE setFocalRadius NOTIFY focalRadiusChanged) Q_CLASSINFO("DefaultProperty", "stops") QML_NAMED_ELEMENT(RadialGradient) + QML_ADDED_IN_VERSION(1, 0) public: QQuickShapeRadialGradient(QObject *parent = nullptr); @@ -187,6 +190,7 @@ class Q_QUICKSHAPES_PRIVATE_EXPORT QQuickShapeConicalGradient : public QQuickSha Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged) Q_CLASSINFO("DefaultProperty", "stops") QML_NAMED_ELEMENT(ConicalGradient) + QML_ADDED_IN_VERSION(1, 0) public: QQuickShapeConicalGradient(QObject *parent = nullptr); @@ -225,8 +229,9 @@ class Q_QUICKSHAPES_PRIVATE_EXPORT QQuickShapePath : public QQuickPath Q_PROPERTY(qreal dashOffset READ dashOffset WRITE setDashOffset NOTIFY dashOffsetChanged) Q_PROPERTY(QVector<qreal> dashPattern READ dashPattern WRITE setDashPattern NOTIFY dashPatternChanged) Q_PROPERTY(QQuickShapeGradient *fillGradient READ fillGradient WRITE setFillGradient RESET resetFillGradient) - Q_PROPERTY(QSizeF scale READ scale WRITE setScale NOTIFY scaleChanged REVISION 14) + Q_PROPERTY(QSizeF scale READ scale WRITE setScale NOTIFY scaleChanged REVISION(1, 14)) QML_NAMED_ELEMENT(ShapePath) + QML_ADDED_IN_VERSION(1, 0) public: enum FillRule { @@ -318,10 +323,11 @@ class Q_QUICKSHAPES_PRIVATE_EXPORT QQuickShape : public QQuickItem Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged) Q_PROPERTY(bool vendorExtensionsEnabled READ vendorExtensionsEnabled WRITE setVendorExtensionsEnabled NOTIFY vendorExtensionsEnabledChanged) Q_PROPERTY(Status status READ status NOTIFY statusChanged) - Q_PROPERTY(ContainsMode containsMode READ containsMode WRITE setContainsMode NOTIFY containsModeChanged REVISION 11) + Q_PROPERTY(ContainsMode containsMode READ containsMode WRITE setContainsMode NOTIFY containsModeChanged REVISION(1, 11)) Q_PROPERTY(QQmlListProperty<QObject> data READ data) Q_CLASSINFO("DefaultProperty", "data") QML_NAMED_ELEMENT(Shape) + QML_ADDED_IN_VERSION(1, 0) public: enum RendererType { @@ -377,7 +383,7 @@ Q_SIGNALS: void asynchronousChanged(); void vendorExtensionsEnabledChanged(); void statusChanged(); - Q_REVISION(11) void containsModeChanged(); + Q_REVISION(1, 11) void containsModeChanged(); private: Q_DISABLE_COPY(QQuickShape) diff --git a/src/quickshapes/qquickshapesglobal_p.h b/src/quickshapes/qquickshapesglobal_p.h index 2f559b45a0..40f6cfbdcf 100644 --- a/src/quickshapes/qquickshapesglobal_p.h +++ b/src/quickshapes/qquickshapesglobal_p.h @@ -59,5 +59,6 @@ QT_BEGIN_NAMESPACE QT_END_NAMESPACE +void Q_QUICKSHAPES_PRIVATE_EXPORT qml_register_types_QtQuick_Shapes(); #endif // QQUICKSHAPESGLOBAL_P_H diff --git a/src/quickshapes/quickshapes.pro b/src/quickshapes/quickshapes.pro index 7c71aa4f4a..7b77391d92 100644 --- a/src/quickshapes/quickshapes.pro +++ b/src/quickshapes/quickshapes.pro @@ -35,5 +35,5 @@ load(qt_module) QMLTYPES_FILENAME = plugins.qmltypes QMLTYPES_INSTALL_DIR = $$[QT_INSTALL_QML]/QtQuick/Shapes QML_IMPORT_NAME = QtQuick.Shapes -IMPORT_VERSION = 1.15 +QML_IMPORT_VERSION = $$QT_VERSION CONFIG += qmltypes install_qmltypes install_metatypes diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp index dbb103973c..db7ae22767 100644 --- a/src/quickwidgets/qquickwidget.cpp +++ b/src/quickwidgets/qquickwidget.cpp @@ -59,9 +59,11 @@ #include <QtGui/qpa/qplatformintegration.h> #if QT_CONFIG(opengl) +#include <private/qopenglcontext_p.h> +#include <private/qopenglextensions_p.h> +#include <QOpenGLFramebufferObject> #include <QOpenGLContext> #include <QOpenGLFunctions> -#include <private/qopenglextensions_p.h> #endif #include <QtGui/QPainter> diff --git a/src/src.pro b/src/src.pro index 2855102eff..c9de88e942 100644 --- a/src/src.pro +++ b/src/src.pro @@ -4,9 +4,6 @@ include($$OUT_PWD/qml/qtqml-config.pri) include($$OUT_PWD/quick/qtquick-config.pri) QT_FOR_CONFIG += qml qml-private quick-private -# Otherwise we cannot compile qmltyperegistrar -requires(qtConfig(commandlineparser)) - # We need qmltyperegistrar for all type registrations, even in qml SUBDIRS += \ qmltyperegistrar \ diff --git a/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp b/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp index a8bcadbc84..8c4c461813 100644 --- a/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp +++ b/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp @@ -432,8 +432,7 @@ void tst_QParallelAnimationGroupJob::deleteChildrenWithRunningGroup() QCOMPARE(group.state(), QAnimationGroupJob::Running); QCOMPARE(anim1->state(), QAnimationGroupJob::Running); - QTest::qWait(80); - QVERIFY(group.currentLoopTime() > 0); + QTRY_VERIFY(group.currentLoopTime() > 0); delete anim1; QVERIFY(!group.firstChild()); diff --git a/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp b/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp index 8f6b6a2ab7..1d644bf9b5 100644 --- a/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp +++ b/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp @@ -32,8 +32,8 @@ #include <QtQml/private/qsequentialanimationgroupjob_p.h> #include <QtQml/private/qparallelanimationgroupjob_p.h> -#ifdef Q_OS_WIN -static const char winTimerError[] = "On windows, consistent timing is not working properly due to bad timer resolution"; +#if defined(Q_OS_WIN) || defined(Q_OS_MACOS) +static const char timerError[] = "On some platforms, consistent timing is not working properly due to bad timer resolution"; #endif class TestablePauseAnimation : public QPauseAnimationJob @@ -144,7 +144,7 @@ void tst_QPauseAnimationJob::noTimerUpdates() #ifdef Q_OS_WIN if (animation.state() != QAbstractAnimationJob::Stopped) - QEXPECT_FAIL("", winTimerError, Abort); + QEXPECT_FAIL("", timerError, Abort); #endif QCOMPARE(animation.state(), QAbstractAnimationJob::Stopped); @@ -152,7 +152,7 @@ void tst_QPauseAnimationJob::noTimerUpdates() #ifdef Q_OS_WIN if (animation.m_updateCurrentTimeCount != expectedLoopCount) - QEXPECT_FAIL("", winTimerError, Abort); + QEXPECT_FAIL("", timerError, Abort); #endif QCOMPARE(animation.m_updateCurrentTimeCount, expectedLoopCount); } @@ -173,25 +173,25 @@ void tst_QPauseAnimationJob::multiplePauseAnimations() #ifdef Q_OS_WIN if (animation.state() != QAbstractAnimationJob::Stopped) - QEXPECT_FAIL("", winTimerError, Abort); + QEXPECT_FAIL("", timerError, Abort); #endif QCOMPARE(animation.state(), QAbstractAnimationJob::Stopped); #ifdef Q_OS_WIN if (animation2.state() != QAbstractAnimationJob::Running) - QEXPECT_FAIL("", winTimerError, Abort); + QEXPECT_FAIL("", timerError, Abort); #endif QCOMPARE(animation2.state(), QAbstractAnimationJob::Running); #ifdef Q_OS_WIN if (animation.m_updateCurrentTimeCount != 2) - QEXPECT_FAIL("", winTimerError, Abort); + QEXPECT_FAIL("", timerError, Abort); #endif QCOMPARE(animation.m_updateCurrentTimeCount, 2); #ifdef Q_OS_WIN if (animation2.m_updateCurrentTimeCount != 2) - QEXPECT_FAIL("", winTimerError, Abort); + QEXPECT_FAIL("", timerError, Abort); #endif QCOMPARE(animation2.m_updateCurrentTimeCount, 2); @@ -388,7 +388,7 @@ void tst_QPauseAnimationJob::multipleSequentialGroups() #ifdef Q_OS_WIN if (group.state() != QAbstractAnimationJob::Stopped) - QEXPECT_FAIL("", winTimerError, Abort); + QEXPECT_FAIL("", timerError, Abort); QCOMPARE(group.state(), QAbstractAnimationJob::Stopped); #else QTRY_COMPARE(group.state(), QAbstractAnimationJob::Stopped); @@ -396,31 +396,31 @@ void tst_QPauseAnimationJob::multipleSequentialGroups() #ifdef Q_OS_WIN if (subgroup1.state() != QAbstractAnimationJob::Stopped) - QEXPECT_FAIL("", winTimerError, Abort); + QEXPECT_FAIL("", timerError, Abort); #endif QCOMPARE(subgroup1.state(), QAbstractAnimationJob::Stopped); #ifdef Q_OS_WIN if (subgroup2.state() != QAbstractAnimationJob::Stopped) - QEXPECT_FAIL("", winTimerError, Abort); + QEXPECT_FAIL("", timerError, Abort); #endif QCOMPARE(subgroup2.state(), QAbstractAnimationJob::Stopped); #ifdef Q_OS_WIN if (subgroup3.state() != QAbstractAnimationJob::Stopped) - QEXPECT_FAIL("", winTimerError, Abort); + QEXPECT_FAIL("", timerError, Abort); #endif QCOMPARE(subgroup3.state(), QAbstractAnimationJob::Stopped); #ifdef Q_OS_WIN if (subgroup4.state() != QAbstractAnimationJob::Stopped) - QEXPECT_FAIL("", winTimerError, Abort); + QEXPECT_FAIL("", timerError, Abort); #endif QCOMPARE(subgroup4.state(), QAbstractAnimationJob::Stopped); -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) || defined(Q_OS_MACOS) if (pause5.m_updateCurrentTimeCount != 4) - QEXPECT_FAIL("", winTimerError, Abort); + QEXPECT_FAIL("", timerError, Abort); #endif QCOMPARE(pause5.m_updateCurrentTimeCount, 4); } diff --git a/tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp b/tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp index 57b0905a8a..add19273d9 100644 --- a/tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp +++ b/tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp @@ -1332,6 +1332,8 @@ void tst_QSequentialAnimationGroupJob::stopUncontrolledAnimations() void tst_QSequentialAnimationGroupJob::finishWithUncontrolledAnimation() { + const int targetDuration = 300; + //1st case: //first we test a group with one uncontrolled animation QSequentialAnimationGroupJob group; @@ -1346,7 +1348,7 @@ void tst_QSequentialAnimationGroupJob::finishWithUncontrolledAnimation() QCOMPARE(group.currentLoopTime(), 0); QCOMPARE(notTimeDriven.currentLoopTime(), 0); - QTest::qWait(300); //wait for the end of notTimeDriven + QTest::qWait(targetDuration); //wait for the end of notTimeDriven QTRY_COMPARE(notTimeDriven.state(), QAnimationGroupJob::Stopped); const int actualDuration = notTimeDriven.currentLoopTime(); QCOMPARE(group.state(), QAnimationGroupJob::Stopped); @@ -1361,10 +1363,15 @@ void tst_QSequentialAnimationGroupJob::finishWithUncontrolledAnimation() StateChangeListener animStateChangedSpy; anim.addAnimationChangeListener(&animStateChangedSpy, QAbstractAnimationJob::StateChange); - group.setCurrentTime(300); + group.setCurrentTime(targetDuration); QCOMPARE(group.state(), QAnimationGroupJob::Stopped); - QCOMPARE(notTimeDriven.currentLoopTime(), actualDuration); - QCOMPARE(group.currentAnimation(), static_cast<QAbstractAnimationJob*>(&anim)); + if (actualDuration > targetDuration) { + QCOMPARE(notTimeDriven.currentLoopTime(), targetDuration); + QCOMPARE(group.currentAnimation(), ¬TimeDriven); + } else { + QCOMPARE(notTimeDriven.currentLoopTime(), actualDuration); + QCOMPARE(group.currentAnimation(), &anim); + } //3rd case: //now let's add a perfectly defined animation at the end @@ -1377,13 +1384,13 @@ void tst_QSequentialAnimationGroupJob::finishWithUncontrolledAnimation() QCOMPARE(animStateChangedSpy.count(), 0); - QTest::qWait(300); //wait for the end of notTimeDriven + QTest::qWait(targetDuration); //wait for the end of notTimeDriven QTRY_COMPARE(notTimeDriven.state(), QAnimationGroupJob::Stopped); QCOMPARE(group.state(), QAnimationGroupJob::Running); QCOMPARE(anim.state(), QAnimationGroupJob::Running); QCOMPARE(group.currentAnimation(), static_cast<QAbstractAnimationJob*>(&anim)); QCOMPARE(animStateChangedSpy.count(), 1); - QTest::qWait(300); //wait for the end of anim + QTest::qWait(targetDuration); //wait for the end of anim QTRY_COMPARE(anim.state(), QAnimationGroupJob::Stopped); QCOMPARE(anim.currentLoopTime(), anim.duration()); diff --git a/tests/auto/qml/debugger/debugger.pro b/tests/auto/qml/debugger/debugger.pro index 5c328fbfcc..890e722aa3 100644 --- a/tests/auto/qml/debugger/debugger.pro +++ b/tests/auto/qml/debugger/debugger.pro @@ -4,6 +4,7 @@ SUBDIRS += qqmldebugjsserver PUBLICTESTS += \ qdebugmessageservice \ + qqmldebugtranslationservice \ qqmlenginedebugservice \ qqmldebugjs \ qqmlinspector \ diff --git a/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp b/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp index 1c1f785560..ec7ee15d34 100644 --- a/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp +++ b/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp @@ -135,7 +135,7 @@ QList<QQmlDebugClient *> tst_QDebugMessageService::createClients() void tst_QDebugMessageService::retrieveDebugOutput() { - QCOMPARE(QQmlDebugTest::connect(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml", + QCOMPARE(QQmlDebugTest::connectTo(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml", QString(), testFile(QMLFILE), true), ConnectSuccess); QTRY_VERIFY(m_client->logBuffer.size() >= 2); diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml b/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml index deba24cf91..a7231df48b 100644 --- a/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml +++ b/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml @@ -36,5 +36,9 @@ Item { } id: root property int a: 10 + + Item { + property int b: 11 + } } diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp index 5b6c43bc0c..91470e0651 100644 --- a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp +++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp @@ -180,7 +180,7 @@ QQmlDebugTest::ConnectResult tst_QQmlDebugJS::init(bool qmlscene, const QString const QString executable = qmlscene ? QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene" : debugJsServerPath("qqmldebugjs"); - return QQmlDebugTest::connect( + return QQmlDebugTest::connectTo( executable, restrictServices ? QStringLiteral("V8Debugger") : QString(), testFile(qmlFile), blockMode); } @@ -896,6 +896,16 @@ void tst_QQmlDebugJS::evaluateInContext() QVERIFY(waitForClientSignal(SIGNAL(result()))); QTRY_COMPARE(responseBody(m_client).value("value").toInt(), 20); + + auto childObjects = object.children; + QVERIFY(childObjects.count() > 0); // QQmlComponentAttached is also in there + QCOMPARE(childObjects[0].className, QString::fromLatin1("Item")); + + // "b" accessible in context of surrounding (child) object + m_client->evaluate(QLatin1String("b"), -1, childObjects[0].debugId); + QVERIFY(waitForClientSignal(SIGNAL(result()))); + + QTRY_COMPARE(responseBody(m_client).value("value").toInt(), 11); } void tst_QQmlDebugJS::getScripts() diff --git a/tests/auto/qml/debugger/qqmldebugtranslationservice/data/test.qml b/tests/auto/qml/debugger/qqmldebugtranslationservice/data/test.qml new file mode 100644 index 0000000000..234496577a --- /dev/null +++ b/tests/auto/qml/debugger/qqmldebugtranslationservice/data/test.qml @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Controls 2.12 + +Item { + width: 360 + height: 360 + + Text { + text: qsTr("hello") + width: parent.width / 10 + elide: Text.ElideRight + } +} diff --git a/tests/auto/qml/debugger/qqmldebugtranslationservice/qqmldebugtranslationservice.pro b/tests/auto/qml/debugger/qqmldebugtranslationservice/qqmldebugtranslationservice.pro new file mode 100644 index 0000000000..32e60e306d --- /dev/null +++ b/tests/auto/qml/debugger/qqmldebugtranslationservice/qqmldebugtranslationservice.pro @@ -0,0 +1,12 @@ +CONFIG += testcase +TARGET = tst_qdebugtranslationservice +QT += network testlib gui-private core-private qmldebug-private +macos:CONFIG -= app_bundle + +SOURCES += tst_qqmldebugtranslationservice.cpp + +include(../shared/debugutil.pri) + +TESTDATA = data/* + +OTHER_FILES += data/test.qml diff --git a/tests/auto/qml/debugger/qqmldebugtranslationservice/tst_qqmldebugtranslationservice.cpp b/tests/auto/qml/debugger/qqmldebugtranslationservice/tst_qqmldebugtranslationservice.cpp new file mode 100644 index 0000000000..01ee805dee --- /dev/null +++ b/tests/auto/qml/debugger/qqmldebugtranslationservice/tst_qqmldebugtranslationservice.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +//QQmlDebugTest +#include <debugutil_p.h> +#include <qqmldebugprocess_p.h> + +#include <private/qqmldebugclient_p.h> +#include <private/qqmldebugtranslationclient_p.h> +#include <private/qqmldebugconnection_p.h> +#include <private/qpacket_p.h> + +#include <QtCore/qstring.h> +#include <QtCore/qlibraryinfo.h> +#include <QtTest/qtest.h> + +const char *QMLFILE = "test.qml"; + +class tst_QQmlDebugTranslationService : public QQmlDebugTest +{ + Q_OBJECT + +private slots: + void pluginConnection(); + +private: + QList<QQmlDebugClient *> createClients() override; + QPointer<QQmlDebugTranslationClient> m_client; +}; + +QList<QQmlDebugClient *> tst_QQmlDebugTranslationService::createClients() +{ + m_client = new QQmlDebugTranslationClient(m_connection); + + QObject::connect(m_client, &QQmlDebugClient::stateChanged, m_client, [this](QQmlDebugClient::State newState) { + QCOMPARE(newState, m_client->state()); + }); + + return {m_client}; +} + +void tst_QQmlDebugTranslationService::pluginConnection() +{ + auto executable = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml"; + auto services = "DebugTranslation"; + auto extraArgs = testFile(QMLFILE); + auto block = true; + + auto result = QQmlDebugTest::connectTo(executable, services, extraArgs, block); + QCOMPARE(result, ConnectSuccess); +} + +QTEST_MAIN(tst_QQmlDebugTranslationService) + +#include "tst_qqmldebugtranslationservice.moc" diff --git a/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp b/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp index a8c43b1c75..c8915fb840 100644 --- a/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp +++ b/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp @@ -66,7 +66,7 @@ class tst_QQmlEngineControl : public QQmlDebugTest Q_OBJECT private: - ConnectResult connect(const QString &testFile, bool restrictServices); + ConnectResult connectTo(const QString &testFile, bool restrictServices); QList<QQmlDebugClient *> createClients() override; void engine_data(); @@ -79,10 +79,10 @@ private slots: void stopEngine(); }; -QQmlDebugTest::ConnectResult tst_QQmlEngineControl::connect(const QString &file, +QQmlDebugTest::ConnectResult tst_QQmlEngineControl::connectTo(const QString &file, bool restrictServices) { - return QQmlDebugTest::connect(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene", + return QQmlDebugTest::connectTo(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene", restrictServices ? QStringLiteral("EngineControl") : QString(), testFile(file), true); } @@ -109,7 +109,7 @@ void tst_QQmlEngineControl::startEngine_data() void tst_QQmlEngineControl::startEngine() { QFETCH(bool, restrictMode); - QCOMPARE(connect("test.qml", restrictMode), ConnectSuccess); + QCOMPARE(connectTo("test.qml", restrictMode), ConnectSuccess); QTRY_VERIFY(!m_client->blockedEngines().empty()); m_client->releaseEngine(m_client->blockedEngines().last()); @@ -130,7 +130,7 @@ void tst_QQmlEngineControl::stopEngine() { QFETCH(bool, restrictMode); - QCOMPARE(connect("exit.qml", restrictMode), ConnectSuccess); + QCOMPARE(connectTo("exit.qml", restrictMode), ConnectSuccess); QTRY_VERIFY(!m_client->blockedEngines().empty()); m_client->releaseEngine(m_client->blockedEngines().last()); diff --git a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp index 980e2be1f1..9830f1a9bd 100644 --- a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp +++ b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp @@ -87,7 +87,7 @@ QQmlEngineDebugObjectReference tst_QQmlEngineDebugInspectorIntegration::findRoot QQmlDebugTest::ConnectResult tst_QQmlEngineDebugInspectorIntegration::init(bool restrictServices) { - return QQmlDebugTest::connect( + return QQmlDebugTest::connectTo( QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml", restrictServices ? QStringLiteral("QmlDebugger,QmlInspector") : QString(), testFile("qtquick2.qml"), true); diff --git a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp index 6685558bb5..b5f45f1eeb 100644 --- a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp +++ b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp @@ -64,7 +64,7 @@ private slots: QQmlDebugTest::ConnectResult tst_QQmlInspector::startQmlProcess(const QString &qmlFile, bool restrictServices) { - return QQmlDebugTest::connect(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml", + return QQmlDebugTest::connectTo(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml", restrictServices ? QStringLiteral("QmlInspector") : QString(), testFile(qmlFile), true); } diff --git a/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp b/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp index 15eb4012ac..bfec776614 100644 --- a/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp +++ b/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp @@ -74,7 +74,7 @@ private slots: QQmlDebugTest::ConnectResult tst_QQmlPreview::startQmlProcess(const QString &qmlFile) { - return QQmlDebugTest::connect(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml", + return QQmlDebugTest::connectTo(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml", QStringLiteral("QmlPreview"), testFile(qmlFile), true); } diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp index 085eb7b87a..c2a774b42d 100644 --- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp +++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp @@ -201,7 +201,7 @@ private: CheckType = CheckMessageType | CheckDetailType | CheckLine | CheckColumn | CheckFileEndsWith }; - ConnectResult connect(bool block, const QString &file, bool recordFromStart = true, + ConnectResult connectTo(bool block, const QString &file, bool recordFromStart = true, uint flushInterval = 0, bool restrictServices = true, const QString &executable = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene"); @@ -246,7 +246,7 @@ private: #define VERIFY(type, position, expected, checks, numbers) \ QVERIFY(verify(type, position, expected, checks, numbers)) -QQmlDebugTest::ConnectResult tst_QQmlProfilerService::connect( +QQmlDebugTest::ConnectResult tst_QQmlProfilerService::connectTo( bool block, const QString &file, bool recordFromStart, uint flushInterval, bool restrictServices, const QString &executable) { @@ -255,7 +255,7 @@ QQmlDebugTest::ConnectResult tst_QQmlProfilerService::connect( m_isComplete = false; // ### Still using qmlscene due to QTBUG-33377 - return QQmlDebugTest::connect( + return QQmlDebugTest::connectTo( executable, restrictServices ? "CanvasFrameRate,EngineControl,DebugMessages" : QString(), testFile(file), block); @@ -542,7 +542,7 @@ void tst_QQmlProfilerService::connect() QFETCH(bool, restrictMode); QFETCH(bool, traceEnabled); - QCOMPARE(connect(blockMode, "test.qml", traceEnabled, 0, restrictMode), ConnectSuccess); + QCOMPARE(connectTo(blockMode, "test.qml", traceEnabled, 0, restrictMode), ConnectSuccess); if (!traceEnabled) m_client->client->setRecording(true); @@ -556,7 +556,7 @@ void tst_QQmlProfilerService::connect() void tst_QQmlProfilerService::pixmapCacheData() { - QCOMPARE(connect(true, "pixmapCacheTest.qml"), ConnectSuccess); + QCOMPARE(connectTo(true, "pixmapCacheTest.qml"), ConnectSuccess); // Don't wait for readyReadStandardOutput before the loop. It may have already arrived. while (m_process->output().indexOf(QLatin1String("image loaded")) == -1 && @@ -594,7 +594,7 @@ void tst_QQmlProfilerService::pixmapCacheData() void tst_QQmlProfilerService::scenegraphData() { - QCOMPARE(connect(true, "scenegraphTest.qml"), ConnectSuccess); + QCOMPARE(connectTo(true, "scenegraphTest.qml"), ConnectSuccess); while (!m_process->output().contains(QLatin1String("tick"))) QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput()))); @@ -654,7 +654,7 @@ void tst_QQmlProfilerService::scenegraphData() void tst_QQmlProfilerService::profileOnExit() { - QCOMPARE(connect(true, "exit.qml"), ConnectSuccess); + QCOMPARE(connectTo(true, "exit.qml"), ConnectSuccess); checkProcessTerminated(); checkTraceReceived(); @@ -663,7 +663,7 @@ void tst_QQmlProfilerService::profileOnExit() void tst_QQmlProfilerService::controlFromJS() { - QCOMPARE(connect(true, "controlFromJS.qml", false), ConnectSuccess); + QCOMPARE(connectTo(true, "controlFromJS.qml", false), ConnectSuccess); QTRY_VERIFY(m_client->numLoadedEventTypes() > 0); m_client->client->setRecording(false); @@ -673,7 +673,7 @@ void tst_QQmlProfilerService::controlFromJS() void tst_QQmlProfilerService::signalSourceLocation() { - QCOMPARE(connect(true, "signalSourceLocation.qml"), ConnectSuccess); + QCOMPARE(connectTo(true, "signalSourceLocation.qml"), ConnectSuccess); while (!(m_process->output().contains(QLatin1String("500")))) QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput()))); @@ -694,7 +694,7 @@ void tst_QQmlProfilerService::signalSourceLocation() void tst_QQmlProfilerService::javascript() { - QCOMPARE(connect(true, "javascript.qml"), ConnectSuccess); + QCOMPARE(connectTo(true, "javascript.qml"), ConnectSuccess); while (!(m_process->output().contains(QLatin1String("done")))) QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput()))); @@ -722,7 +722,7 @@ void tst_QQmlProfilerService::javascript() void tst_QQmlProfilerService::flushInterval() { - QCOMPARE(connect(true, "timer.qml", true, 1), ConnectSuccess); + QCOMPARE(connectTo(true, "timer.qml", true, 1), ConnectSuccess); // Make sure we get multiple messages QTRY_VERIFY(m_client->qmlMessages.length() > 0); @@ -736,7 +736,7 @@ void tst_QQmlProfilerService::flushInterval() void tst_QQmlProfilerService::translationBinding() { - QCOMPARE(connect(true, "qstr.qml"), ConnectSuccess); + QCOMPARE(connectTo(true, "qstr.qml"), ConnectSuccess); checkProcessTerminated(); checkTraceReceived(); @@ -752,7 +752,7 @@ void tst_QQmlProfilerService::translationBinding() void tst_QQmlProfilerService::memory() { - QCOMPARE(connect(true, "memory.qml"), ConnectSuccess); + QCOMPARE(connectTo(true, "memory.qml"), ConnectSuccess); checkProcessTerminated(); checkTraceReceived(); @@ -781,7 +781,7 @@ static bool hasCompileEvents(const QVector<QQmlProfilerEventType> &types) void tst_QQmlProfilerService::compile() { // Flush interval so that we actually get the events before we stop recording. - connect(true, "test.qml", true, 100); + connectTo(true, "test.qml", true, 100); QVERIFY(m_client); @@ -820,7 +820,7 @@ void tst_QQmlProfilerService::compile() void tst_QQmlProfilerService::multiEngine() { - QCOMPARE(connect(true, "quit.qml", true, 0, false, debugJsServerPath("qqmlprofilerservice")), + QCOMPARE(connectTo(true, "quit.qml", true, 0, false, debugJsServerPath("qqmlprofilerservice")), ConnectSuccess); QSignalSpy spy(m_client->client, SIGNAL(complete(qint64))); @@ -837,7 +837,7 @@ void tst_QQmlProfilerService::multiEngine() void tst_QQmlProfilerService::batchOverflow() { // The trace client checks that the events are received in order. - QCOMPARE(connect(true, "batchOverflow.qml"), ConnectSuccess); + QCOMPARE(connectTo(true, "batchOverflow.qml"), ConnectSuccess); checkProcessTerminated(); checkTraceReceived(); checkJsHeap(); diff --git a/tests/auto/qml/debugger/shared/debugutil.cpp b/tests/auto/qml/debugger/shared/debugutil.cpp index 68446b53a4..3787f34bc2 100644 --- a/tests/auto/qml/debugger/shared/debugutil.cpp +++ b/tests/auto/qml/debugger/shared/debugutil.cpp @@ -120,7 +120,7 @@ void QQmlDebugTestClient::messageReceived(const QByteArray &ba) emit serverMessage(ba); } -QQmlDebugTest::ConnectResult QQmlDebugTest::connect( +QQmlDebugTest::ConnectResult QQmlDebugTest::connectTo( const QString &executable, const QString &services, const QString &extraArgs, bool block) { diff --git a/tests/auto/qml/debugger/shared/debugutil_p.h b/tests/auto/qml/debugger/shared/debugutil_p.h index 1c32590305..190909dc44 100644 --- a/tests/auto/qml/debugger/shared/debugutil_p.h +++ b/tests/auto/qml/debugger/shared/debugutil_p.h @@ -53,7 +53,6 @@ public: static QString clientStateString(const QQmlDebugClient *client); static QString connectionStateString(const QQmlDebugConnection *connection); -protected: enum ConnectResult { ConnectSuccess, ProcessFailed, @@ -64,7 +63,9 @@ protected: RestrictFailed }; - ConnectResult connect(const QString &executable, const QString &services, + Q_ENUM(ConnectResult) +protected: + ConnectResult connectTo(const QString &executable, const QString &services, const QString &extraArgs, bool block); virtual QQmlDebugProcess *createProcess(const QString &executable); diff --git a/tests/auto/qml/ecmascripttests/BLACKLIST b/tests/auto/qml/ecmascripttests/BLACKLIST deleted file mode 100644 index 1ed255e9e2..0000000000 --- a/tests/auto/qml/ecmascripttests/BLACKLIST +++ /dev/null @@ -1,4 +0,0 @@ -[runInterpreted] -macos ci -[runJitted] -macos diff --git a/tests/auto/qml/ecmascripttests/qjstest/qjstest.pro b/tests/auto/qml/ecmascripttests/qjstest/qjstest.pro index 6dec5f8f23..adead821e4 100644 --- a/tests/auto/qml/ecmascripttests/qjstest/qjstest.pro +++ b/tests/auto/qml/ecmascripttests/qjstest/qjstest.pro @@ -3,6 +3,8 @@ TARGET = qjstest QT += qml-private INCLUDEPATH += . +CONFIG += c++14 + DEFINES += QT_DEPRECATED_WARNINGS HEADERS += test262runner.h diff --git a/tests/auto/qml/ecmascripttests/testcase.pro b/tests/auto/qml/ecmascripttests/testcase.pro index 5bf7ecd696..9405095050 100644 --- a/tests/auto/qml/ecmascripttests/testcase.pro +++ b/tests/auto/qml/ecmascripttests/testcase.pro @@ -6,6 +6,8 @@ SOURCES += tst_ecmascripttests.cpp qjstest/test262runner.cpp HEADERS += qjstest/test262runner.h DEFINES += SRCDIR=\\\"$$PWD\\\" +CONFIG += c++14 + # The ES test suite takes approximately 5 mins to run, on a fairly # vanilla developer machine, so the default watchdog timer kills the # test some of the time. Fix by raising time-out to 400s when diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index 7b59087a72..aeb0303899 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -3342,7 +3342,7 @@ void tst_QJSEngine::dateRoundtripJSQtJS() #ifdef Q_OS_WIN QSKIP("This test fails on Windows due to a bug in QDateTime."); #endif - qint64 secs = QDateTime(QDate(2009, 1, 1)).toUTC().toSecsSinceEpoch(); + qint64 secs = QDate(2009, 1, 1).startOfDay(Qt::UTC).toSecsSinceEpoch(); QJSEngine eng; for (int i = 0; i < 8000; ++i) { QJSValue jsDate = eng.evaluate(QString::fromLatin1("new Date(%0)").arg(secs * 1000.0)); @@ -3359,7 +3359,7 @@ void tst_QJSEngine::dateRoundtripQtJSQt() #ifdef Q_OS_WIN QSKIP("This test fails on Windows due to a bug in QDateTime."); #endif - QDateTime qtDate = QDateTime(QDate(2009, 1, 1)); + QDateTime qtDate = QDate(2009, 1, 1).startOfDay(); QJSEngine eng; for (int i = 0; i < 8000; ++i) { QJSValue jsDate = eng.toScriptValue(qtDate); @@ -3375,7 +3375,7 @@ void tst_QJSEngine::dateConversionJSQt() #ifdef Q_OS_WIN QSKIP("This test fails on Windows due to a bug in QDateTime."); #endif - qint64 secs = QDateTime(QDate(2009, 1, 1)).toUTC().toSecsSinceEpoch(); + qint64 secs = QDate(2009, 1, 1).startOfDay(Qt::UTC).toSecsSinceEpoch(); QJSEngine eng; for (int i = 0; i < 8000; ++i) { QJSValue jsDate = eng.evaluate(QString::fromLatin1("new Date(%0)").arg(secs * 1000.0)); @@ -3391,7 +3391,7 @@ void tst_QJSEngine::dateConversionJSQt() void tst_QJSEngine::dateConversionQtJS() { - QDateTime qtDate = QDateTime(QDate(2009, 1, 1)); + QDateTime qtDate = QDate(2009, 1, 1).startOfDay(); QJSEngine eng; for (int i = 0; i < 8000; ++i) { QJSValue jsDate = eng.toScriptValue(qtDate); diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp index d6e85f973f..0d0bd2ae7e 100644 --- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp +++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp @@ -1067,7 +1067,7 @@ void tst_QJSValue::toVariant() } { - QDateTime dateTime = QDateTime(QDate(1980, 10, 4)); + QDateTime dateTime = QDate(1980, 10, 4).startOfDay(); QJSValue dateObject = eng.toScriptValue(dateTime); QVariant var = dateObject.toVariant(); QCOMPARE(var, QVariant(dateTime)); @@ -1128,6 +1128,10 @@ void tst_QJSValue::toVariant() // array { + auto handler = qInstallMessageHandler([](QtMsgType type, const QMessageLogContext &, const QString &) { + if (type == QtMsgType::QtWarningMsg) + QFAIL("Converting QJSValue to QVariant should not cause error messages"); + }); QVariantList listIn; listIn << 123 << "hello"; QJSValue array = eng.toScriptValue(listIn); @@ -1145,8 +1149,9 @@ void tst_QJSValue::toVariant() QCOMPARE(array2.property("length").toInt(), array.property("length").toInt()); for (int i = 0; i < array.property("length").toInt(); ++i) QVERIFY(array2.property(i).strictlyEquals(array.property(i))); - } + qInstallMessageHandler(handler); + } } void tst_QJSValue::toQObject_nonQObject_data() @@ -1217,7 +1222,7 @@ void tst_QJSValue::toDateTime() QDateTime dt = eng.evaluate("new Date(0)").toDateTime(); QVERIFY(dt.isValid()); QCOMPARE(dt.timeSpec(), Qt::LocalTime); - QCOMPARE(dt.toUTC(), QDateTime(QDate(1970, 1, 1), QTime(0, 0, 0), Qt::UTC)); + QCOMPARE(dt.toUTC(), QDate(1970, 1, 1).startOfDay(Qt::UTC)); QVERIFY(!eng.evaluate("[]").toDateTime().isValid()); QVERIFY(!eng.evaluate("{}").toDateTime().isValid()); @@ -2140,8 +2145,8 @@ void tst_QJSValue::equals() QCOMPARE(str2.equals(QJSValue(321)), false); QCOMPARE(str2.equals(QJSValue()), false); - QJSValue date1 = eng.toScriptValue(QDateTime(QDate(2000, 1, 1))); - QJSValue date2 = eng.toScriptValue(QDateTime(QDate(1999, 1, 1))); + QJSValue date1 = eng.toScriptValue(QDate(2000, 1, 1).startOfDay()); + QJSValue date2 = eng.toScriptValue(QDate(1999, 1, 1).startOfDay()); QCOMPARE(date1.equals(date2), false); QCOMPARE(date1.equals(date1), true); QCOMPARE(date2.equals(date2), true); @@ -2273,8 +2278,8 @@ void tst_QJSValue::strictlyEquals() QCOMPARE(str2.strictlyEquals(QJSValue(321)), false); QVERIFY(!str2.strictlyEquals(QJSValue())); - QJSValue date1 = eng.toScriptValue(QDateTime(QDate(2000, 1, 1))); - QJSValue date2 = eng.toScriptValue(QDateTime(QDate(1999, 1, 1))); + QJSValue date1 = eng.toScriptValue(QDate(2000, 1, 1).startOfDay()); + QJSValue date2 = eng.toScriptValue(QDate(1999, 1, 1).startOfDay()); QCOMPARE(date1.strictlyEquals(date2), false); QCOMPARE(date1.strictlyEquals(date1), true); QCOMPARE(date2.strictlyEquals(date2), true); diff --git a/tests/auto/qml/qmlformat/data/Annotations.formatted.nosort.qml b/tests/auto/qml/qmlformat/data/Annotations.formatted.nosort.qml new file mode 100644 index 0000000000..a05c2125dc --- /dev/null +++ b/tests/auto/qml/qmlformat/data/Annotations.formatted.nosort.qml @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Charts module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** 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$ +** +****************************************************************************/ + +//![2] +import QtQuick 2.0 +//![2] +import QtCharts 2.0 + +@Pippo { + atg1: 3 +} +@Annotation2 { +} +Item { + //![1] + + @AnnotateMore { + property int x: 5 + } + @AnnotateALot { + } + + property variant othersSlice: 0 + @Annotate { + } + + anchors.fill: parent + @SuperComplete { + binding: late + } + Component.onCompleted: { + // You can also manipulate slices dynamically, like append a slice or set a slice exploded + othersSlice = pieSeries.append("Others", 52); + pieSeries.find("Volkswagen").exploded = true; + } + //![1] + ChartView { + id: chart + + title: "Top-5 car brand shares in Finland" + anchors.fill: parent + legend.alignment: Qt.AlignBottom + antialiasing: true + + @ExtraAnnotation { + signal pippo() + } + PieSeries { + id: pieSeries + + PieSlice { + label: "Volkswagen" + value: 13.5 + } + + PieSlice { + label: "Toyota" + value: 10.9 + } + + PieSlice { + label: "Ford" + value: 8.6 + } + + PieSlice { + label: "Skoda" + value: 8.2 + } + + PieSlice { + label: "Volvo" + value: 6.8 + } + + } + + } + +} diff --git a/tests/auto/qml/qmlformat/data/Annotations.formatted.qml b/tests/auto/qml/qmlformat/data/Annotations.formatted.qml new file mode 100644 index 0000000000..a142d4cb74 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/Annotations.formatted.qml @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Charts module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** 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$ +** +****************************************************************************/ + +//![2] +import QtCharts 2.0 +//![2] +import QtQuick 2.0 + +@Pippo { + atg1: 3 +} +@Annotation2 { +} +Item { + //![1] + + @AnnotateMore { + property int x: 5 + } + @AnnotateALot { + } + + property variant othersSlice: 0 + @Annotate { + } + + anchors.fill: parent + @SuperComplete { + binding: late + } + Component.onCompleted: { + // You can also manipulate slices dynamically, like append a slice or set a slice exploded + othersSlice = pieSeries.append("Others", 52); + pieSeries.find("Volkswagen").exploded = true; + } + //![1] + ChartView { + id: chart + + title: "Top-5 car brand shares in Finland" + anchors.fill: parent + legend.alignment: Qt.AlignBottom + antialiasing: true + + @ExtraAnnotation { + signal pippo() + } + PieSeries { + id: pieSeries + + PieSlice { + label: "Volkswagen" + value: 13.5 + } + + PieSlice { + label: "Toyota" + value: 10.9 + } + + PieSlice { + label: "Ford" + value: 8.6 + } + + PieSlice { + label: "Skoda" + value: 8.2 + } + + PieSlice { + label: "Volvo" + value: 6.8 + } + + } + + } + +} diff --git a/tests/auto/qml/qmlformat/data/Annotations.qml b/tests/auto/qml/qmlformat/data/Annotations.qml new file mode 100644 index 0000000000..2d3d7d2cfd --- /dev/null +++ b/tests/auto/qml/qmlformat/data/Annotations.qml @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Charts module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** 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$ +** +****************************************************************************/ + +//![2] +import QtQuick 2.0 +//![2] +import QtCharts 2.0 + +@Pippo{ atg1:3 } +@Annotation2{} +Item { + @Annotate{} + anchors.fill: parent + @AnnotateMore{ + property int x: 5 + } + @AnnotateALot{} + property variant othersSlice: 0 + + //![1] + ChartView { + id: chart + title: "Top-5 car brand shares in Finland" + anchors.fill: parent + legend.alignment: Qt.AlignBottom + antialiasing: true + +@ExtraAnnotation{ + signal pippo +} + PieSeries { + id: pieSeries + PieSlice { label: "Volkswagen"; value: 13.5 } + PieSlice { label: "Toyota"; value: 10.9 } + PieSlice { label: "Ford"; value: 8.6 } + PieSlice { label: "Skoda"; value: 8.2 } + PieSlice { label: "Volvo"; value: 6.8 } + } + } + +@SuperComplete{ +binding: late +} + Component.onCompleted: { + // You can also manipulate slices dynamically, like append a slice or set a slice exploded + othersSlice = pieSeries.append("Others", 52.0); + pieSeries.find("Volkswagen").exploded = true; + } + //![1] +} diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted.nosort.qml b/tests/auto/qml/qmlformat/data/Example1.formatted.nosort.qml index 080cec438e..34d58cf571 100644 --- a/tests/auto/qml/qmlformat/data/Example1.formatted.nosort.qml +++ b/tests/auto/qml/qmlformat/data/Example1.formatted.nosort.qml @@ -91,11 +91,11 @@ Item { x = 100; break; } - if (x == 50) + if (x == 50) console.log("true"); - else if (x == 50) + else if (x == 50) console.log("other thing"); - else + else console.log("false"); if (x == 50) { @@ -132,6 +132,7 @@ Item { Rectangle { } ] + Text { required property string batman @@ -143,6 +144,7 @@ Item { // This comment is related to the property animation PropertyAnimation on x { id: foo + x: 3 y: x + 3 } diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted.qml b/tests/auto/qml/qmlformat/data/Example1.formatted.qml index 4b65b9add6..b06734eb0b 100644 --- a/tests/auto/qml/qmlformat/data/Example1.formatted.qml +++ b/tests/auto/qml/qmlformat/data/Example1.formatted.qml @@ -91,11 +91,11 @@ Item { x = 100; break; } - if (x == 50) + if (x == 50) console.log("true"); - else if (x == 50) + else if (x == 50) console.log("other thing"); - else + else console.log("false"); if (x == 50) { @@ -132,6 +132,7 @@ Item { Rectangle { } ] + Text { required property string batman @@ -143,6 +144,7 @@ Item { // This comment is related to the property animation PropertyAnimation on x { id: foo + x: 3 y: x + 3 } diff --git a/tests/auto/qml/qmlformat/data/largeBindings.formatted.qml b/tests/auto/qml/qmlformat/data/largeBindings.formatted.qml new file mode 100644 index 0000000000..d8e4ffb087 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/largeBindings.formatted.qml @@ -0,0 +1,9 @@ +QtObject { + small1: 3 + small2: foo + // THIS NEEDS TO BE LAST + largeBinding: { + var x = 300; + console.log(x); + } +} diff --git a/tests/auto/qml/qmlformat/data/largeBindings.qml b/tests/auto/qml/qmlformat/data/largeBindings.qml new file mode 100644 index 0000000000..a2249f6815 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/largeBindings.qml @@ -0,0 +1,11 @@ +QtObject +{ + // THIS NEEDS TO BE LAST + largeBinding: { + var x = 300; + console.log(x); + } + + small1: 3 + small2: foo +} diff --git a/tests/auto/qml/qmlformat/data/readOnlyProps.formatted.qml b/tests/auto/qml/qmlformat/data/readOnlyProps.formatted.qml new file mode 100644 index 0000000000..6e7cc31dcf --- /dev/null +++ b/tests/auto/qml/qmlformat/data/readOnlyProps.formatted.qml @@ -0,0 +1,29 @@ +import QtQuick 2.0 + +QtObject { + // Testing UiObjectBinding + readonly property Item + item: Item { + id: test + + signal foo() + } + // End comment + + // Testing UiArrayBinding + readonly property list<Item> array: [ + Item { + id: test1 + + signal foo() + }, + Item { + id: test2 + + signal bar() + } + ] + // Testing UiScriptBinding + readonly property int script: Math.sin(Math.PI) + property bool normalProperty: true +} diff --git a/tests/auto/qml/qmlformat/data/readOnlyProps.qml b/tests/auto/qml/qmlformat/data/readOnlyProps.qml new file mode 100644 index 0000000000..8a32dd131e --- /dev/null +++ b/tests/auto/qml/qmlformat/data/readOnlyProps.qml @@ -0,0 +1,15 @@ +import QtQuick 2.0 + +QtObject { + // Testing UiObjectBinding + readonly property Item item: Item { id: test; signal foo() } + // End comment + + // Testing UiArrayBinding + readonly property list<Item> array: [ Item { id: test1; signal foo() }, Item { id: test2; signal bar() } ] + + // Testing UiScriptBinding + readonly property int script: Math.sin(Math.PI) + + property bool normalProperty: true +} diff --git a/tests/auto/qml/qmlformat/data/statesAndTransitions.formatted.qml b/tests/auto/qml/qmlformat/data/statesAndTransitions.formatted.qml new file mode 100644 index 0000000000..bd063ac498 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/statesAndTransitions.formatted.qml @@ -0,0 +1,16 @@ +QtObject { + id: foo + + // This needs to be *before* states and transitions after formatting + Item { + } + + states: [ + State { + } + ] + transitions: [ + Transition { + } + ] +} diff --git a/tests/auto/qml/qmlformat/data/statesAndTransitions.qml b/tests/auto/qml/qmlformat/data/statesAndTransitions.qml new file mode 100644 index 0000000000..648bdce6b9 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/statesAndTransitions.qml @@ -0,0 +1,10 @@ +QtObject { + id: foo + + states: [ State {} ] + transitions: [ Transition {} ] + + // This needs to be *before* states and transitions after formatting + Item {} + +} diff --git a/tests/auto/qml/qmlformat/tst_qmlformat.cpp b/tests/auto/qml/qmlformat/tst_qmlformat.cpp index 95c8e88f21..21d5ae46a9 100644 --- a/tests/auto/qml/qmlformat/tst_qmlformat.cpp +++ b/tests/auto/qml/qmlformat/tst_qmlformat.cpp @@ -41,7 +41,12 @@ private Q_SLOTS: void testFormat(); void testFormatNoSort(); + void testAnnotations(); + void testAnnotationsNoSort(); + void testReadOnlyProps(); + void testStatesAndTransitions(); + void testLargeBindings(); #if !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled void testExample(); @@ -112,7 +117,6 @@ void TestQmlformat::initTestCase() m_invalidFiles << "tests/auto/qml/qqmllanguage/data/fuzzed.2.qml"; m_invalidFiles << "tests/auto/qml/qqmllanguage/data/fuzzed.3.qml"; m_invalidFiles << "tests/auto/qml/qqmllanguage/data/requiredProperties.2.qml"; - m_invalidFiles << "tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml"; m_invalidFiles << "tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_And.qml"; m_invalidFiles << "tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_And.qml"; m_invalidFiles << "tests/auto/qml/qqmllanguage/data/nullishCoalescing_LHS_Or.qml"; @@ -120,6 +124,11 @@ void TestQmlformat::initTestCase() m_invalidFiles << "tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_Or.qml"; m_invalidFiles << "tests/auto/qml/qqmllanguage/data/typeAnnotations.2.qml"; m_invalidFiles << "tests/auto/qml/qqmlparser/data/disallowedtypeannotations/qmlnestedfunction.qml"; + + // These files rely on exact formatting + m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/incrDecrSemicolon1.qml"; + m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/incrDecrSemicolon_error1.qml"; + m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/incrDecrSemicolon2.qml"; } QStringList TestQmlformat::findFiles(const QDir &d) @@ -178,6 +187,31 @@ void TestQmlformat::testFormatNoSort() QCOMPARE(runQmlformat(testFile("Example1.qml"), false, true), readTestFile("Example1.formatted.nosort.qml")); } +void TestQmlformat::testAnnotations() +{ + QCOMPARE(runQmlformat(testFile("Annotations.qml"), true, true), readTestFile("Annotations.formatted.qml")); +} + +void TestQmlformat::testAnnotationsNoSort() +{ + QCOMPARE(runQmlformat(testFile("Annotations.qml"), false, true), readTestFile("Annotations.formatted.nosort.qml")); +} + +void TestQmlformat::testReadOnlyProps() +{ + QCOMPARE(runQmlformat(testFile("readOnlyProps.qml"), false, true), readTestFile("readOnlyProps.formatted.qml")); +} + +void TestQmlformat::testStatesAndTransitions() +{ + QCOMPARE(runQmlformat(testFile("statesAndTransitions.qml"), false, true), readTestFile("statesAndTransitions.formatted.qml")); +} + +void TestQmlformat::testLargeBindings() +{ + QCOMPARE(runQmlformat(testFile("largeBindings.qml"), false, true), readTestFile("largeBindings.formatted.qml")); +} + #if !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled void TestQmlformat::testExample_data() { diff --git a/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugins.qmltypes b/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugins.qmltypes index d84eb0011a..5c5ae73ca5 100644 --- a/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugins.qmltypes +++ b/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugins.qmltypes @@ -27,9 +27,9 @@ Module { "dumper.ExtendedType/Type 1.0", "dumper.ExtendedType/Type 1.1" ] - exportMetaObjectRevisions: [0, 101] + exportMetaObjectRevisions: [0, 257] Property { name: "baseProperty"; type: "int" } - Property { name: "extendedProperty"; revision: 101; type: "int" } - Property { name: "data"; revision: 101; type: "QObject"; isList: true; isReadonly: true } + Property { name: "extendedProperty"; revision: 257; type: "int" } + Property { name: "data"; revision: 257; type: "QObject"; isList: true; isReadonly: true } } } diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Versions/plugins.qmltypes b/tests/auto/qml/qmlplugindump/data/dumper/Versions/plugins.qmltypes index 3a33590139..ce003fc535 100644 --- a/tests/auto/qml/qmlplugindump/data/dumper/Versions/plugins.qmltypes +++ b/tests/auto/qml/qmlplugindump/data/dumper/Versions/plugins.qmltypes @@ -15,9 +15,9 @@ Module { "dumper.Versions/Versions 1.0", "dumper.Versions/Versions 1.1" ] - exportMetaObjectRevisions: [0, 1] + exportMetaObjectRevisions: [0, 65281] Property { name: "foo"; type: "int" } - Property { name: "bar"; revision: 1; type: "int" } - Property { name: "baz"; revision: 2; type: "int" } + Property { name: "bar"; revision: 65281; type: "int" } + Property { name: "baz"; revision: 65282; type: "int" } } } diff --git a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp index b019ff4535..f636e527c3 100644 --- a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp +++ b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp @@ -325,7 +325,8 @@ void tst_qqmlapplicationengine::failureToLoadTriggersWarningSignal() auto url = testFileUrl("invalid.qml"); qRegisterMetaType<QList<QQmlError>>(); QTest::ignoreMessage(QtMsgType::QtWarningMsg, "QQmlApplicationEngine failed to load component"); - QTest::ignoreMessage(QtMsgType::QtWarningMsg, QRegularExpression(url.toString() + QLatin1Char('*'))); + QTest::ignoreMessage(QtMsgType::QtWarningMsg, + QRegularExpression(QRegularExpression::escape(url.toString()) + QLatin1Char('*'))); QQmlApplicationEngine test; QSignalSpy warningObserver(&test, &QQmlApplicationEngine::warnings); test.load(url); diff --git a/tests/auto/qml/qqmlcomponent/data/RequiredDefault.qml b/tests/auto/qml/qqmlcomponent/data/RequiredDefault.qml new file mode 100644 index 0000000000..7e8f225a52 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/RequiredDefault.qml @@ -0,0 +1,5 @@ +import QtQuick 2.15 + +Item { + required default property Text requiredDefault +} diff --git a/tests/auto/qml/qqmlcomponent/data/requiredDefault.1.qml b/tests/auto/qml/qqmlcomponent/data/requiredDefault.1.qml new file mode 100644 index 0000000000..68dff22f33 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredDefault.1.qml @@ -0,0 +1,5 @@ +import QtQuick 2.15 + +RequiredDefault { + Text {text: "Hello, world!"} +} diff --git a/tests/auto/qml/qqmlcomponent/data/requiredDefault.2.qml b/tests/auto/qml/qqmlcomponent/data/requiredDefault.2.qml new file mode 100644 index 0000000000..a6c4e8ea3f --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredDefault.2.qml @@ -0,0 +1,3 @@ +import QtQuick 2.15 + +RequiredDefault { } diff --git a/tests/auto/qml/qqmlcomponent/data/requiredDefault.3.qml b/tests/auto/qml/qqmlcomponent/data/requiredDefault.3.qml new file mode 100644 index 0000000000..19b3271858 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredDefault.3.qml @@ -0,0 +1,6 @@ +import QtQuick 2.15 +import qt.test 1.0 + +RequiredDefaultCpp { + Text {text: "Hello, world!"} +} diff --git a/tests/auto/qml/qqmlcomponent/data/requiredDefault.4.qml b/tests/auto/qml/qqmlcomponent/data/requiredDefault.4.qml new file mode 100644 index 0000000000..acd56db328 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredDefault.4.qml @@ -0,0 +1,4 @@ +import QtQuick 2.15 +import qt.test 1.0 + +RequiredDefaultCpp { } diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp index 2acc62ca28..43cbd93396 100644 --- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp +++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp @@ -671,8 +671,20 @@ void tst_qqmlcomponent::setDataNoEngineNoSegfault() QVERIFY(!c); } +class RequiredDefaultCpp : public QObject +{ + Q_OBJECT +public: + Q_PROPERTY(QQuickItem *defaultProperty MEMBER m_defaultProperty NOTIFY defaultPropertyChanged REQUIRED) + Q_SIGNAL void defaultPropertyChanged(); + Q_CLASSINFO("DefaultProperty", "defaultProperty") +private: + QQuickItem *m_defaultProperty = nullptr; +}; + void tst_qqmlcomponent::testRequiredProperties_data() { + qmlRegisterType<RequiredDefaultCpp>("qt.test", 1, 0, "RequiredDefaultCpp"); QTest::addColumn<QUrl>("testFile"); QTest::addColumn<bool>("shouldSucceed"); QTest::addColumn<QString>("errorMsg"); @@ -687,6 +699,10 @@ void tst_qqmlcomponent::testRequiredProperties_data() QTest::addRow("setLater") << testFileUrl("requiredSetLater.qml") << true << ""; QTest::addRow("setViaAliasToSubcomponent") << testFileUrl("setViaAliasToSubcomponent.qml") << true << ""; QTest::addRow("aliasToSubcomponentNotSet") << testFileUrl("aliasToSubcomponentNotSet.qml") << false << "It can be set via the alias property i_alias"; + QTest::addRow("required default set") << testFileUrl("requiredDefault.1.qml") << true << ""; + QTest::addRow("required default not set") << testFileUrl("requiredDefault.2.qml") << false << "Required property requiredDefault was not initialized"; + QTest::addRow("required default set (C++)") << testFileUrl("requiredDefault.3.qml") << true << ""; + QTest::addRow("required default not set (C++)") << testFileUrl("requiredDefault.4.qml") << false << "Required property defaultProperty was not initialized"; } diff --git a/tests/auto/qml/qqmlconnections/data/underscore.qml b/tests/auto/qml/qqmlconnections/data/underscore.qml new file mode 100644 index 0000000000..0f73dc8f17 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/underscore.qml @@ -0,0 +1,14 @@ +import QtQuick 2.12 + +Item { + id: item + property bool success: false + property bool sanityCheck: false + property int __underscore_property: 0 + on__Underscore_propertyChanged: item.sanityCheck = true + + Connections { + target: item + on__Underscore_propertyChanged: item.success = true + } +} diff --git a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp index 07af519a3d..f144002875 100644 --- a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp +++ b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp @@ -77,6 +77,8 @@ private slots: void noAcceleratedGlobalLookup_data() { prefixes(); } void noAcceleratedGlobalLookup(); + void bindToPropertyWithUnderscoreChangeHandler(); + private: QQmlEngine engine; void prefixes(); @@ -474,6 +476,19 @@ void tst_qqmlconnections::noAcceleratedGlobalLookup() QCOMPARE(val.toInt(), int(Proxy::EnumValue)); } +void tst_qqmlconnections::bindToPropertyWithUnderscoreChangeHandler() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("underscore.qml")); + QScopedPointer<QObject> root {component.create()}; + QVERIFY(root); + QQmlProperty underscoreProperty(root.get(), "__underscore_property"); + QVERIFY(underscoreProperty.isValid()); + underscoreProperty.write(42); + QVERIFY(root->property("sanityCheck").toBool()); + QVERIFY(root->property("success").toBool()); +} + QTEST_MAIN(tst_qqmlconnections) #include "tst_qqmlconnections.moc" diff --git a/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp b/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp index bc4ba9437c..627347df06 100644 --- a/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp +++ b/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp @@ -63,10 +63,10 @@ namespace { for (const QQmlJS::DiagnosticMessage &e : errors) { QString errorString = QLatin1String("qmldir"); - if (e.line > 0) { - errorString += QLatin1Char(':') + QString::number(e.line); - if (e.column > 0) - errorString += QLatin1Char(':') + QString::number(e.column); + if (e.loc.startLine > 0) { + errorString += QLatin1Char(':') + QString::number(e.loc.startLine); + if (e.loc.startColumn > 0) + errorString += QLatin1Char(':') + QString::number(e.loc.startColumn); } errorString += QLatin1String(": ") + e.message; @@ -94,7 +94,8 @@ namespace { QString toString(const QQmlDirParser::Component &c) { return c.typeName + QLatin1Char('|') + c.fileName + QLatin1Char('|') - + QString::number(c.majorVersion) + QLatin1Char('|') + QString::number(c.minorVersion) + + QString::number(c.version.majorVersion()) + QLatin1Char('|') + + QString::number(c.version.minorVersion()) + QLatin1Char('|') + (c.internal ? "true" : "false"); } @@ -112,7 +113,8 @@ namespace { QString toString(const QQmlDirParser::Script &s) { return s.nameSpace + QLatin1Char('|') + s.fileName + QLatin1Char('|') - + QString::number(s.majorVersion) + '|' + QString::number(s.minorVersion); + + QString::number(s.version.majorVersion()) + '|' + + QString::number(s.version.minorVersion()); } QStringList toStringList(const QList<QQmlDirParser::Script> &scripts) @@ -248,7 +250,7 @@ void tst_qqmldirparser::parse_data() << "unversioned-component/qmldir" << QStringList() << QStringList() - << (QStringList() << "foo|bar|-1|-1|false") + << (QStringList() << "foo|bar|255|255|false") << QStringList() << QStringList() << false; diff --git a/tests/auto/qml/qqmlecmascript/data/sequenceConversion.write.error.qml b/tests/auto/qml/qqmlecmascript/data/sequenceConversion.write.error.qml index 75beafd1ee..c2c8c1b52b 100644 --- a/tests/auto/qml/qqmlecmascript/data/sequenceConversion.write.error.qml +++ b/tests/auto/qml/qqmlecmascript/data/sequenceConversion.write.error.qml @@ -12,7 +12,7 @@ Item { function performTest() { // we have NOT registered QList<QPoint> as a type - var pointList = [ Qt.point(7,7), Qt.point(8,8), Qt.point(9,9) ]; + var pointList = [ Qt.point(7,7), "hello world", Qt.point(8,8), Qt.point(9,9) ]; msco.pointListProperty = pointList; // error. } } diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index a05933d071..a136235f90 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -74,6 +74,7 @@ public: private slots: void initTestCase(); + void arrayIncludesValueType(); void assignBasicTypes(); void assignDate_data(); void assignDate(); @@ -414,6 +415,36 @@ void tst_qqmlecmascript::initTestCase() registerTypes(); } +void tst_qqmlecmascript::arrayIncludesValueType() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + // It is vital that QtQuick is imported below else we get a warning about + // QQml_colorProvider and tst_qqmlecmascript::signalParameterTypes fails due + // to some static variable being initialized with the wrong value + component.setData(R"( + import QtQuick 2.15 + import QtQml 2.15 + QtObject { + id: root + property color r: Qt.rgba(1, 0, 0) + property color g: Qt.rgba(0, 1, 0) + property color b: Qt.rgba(0, 0, 1) + property var colors: [r, g, b] + property bool success: false + + Component.onCompleted: { + root.success = root.colors.includes(root.g) + } + } + )", QUrl("testData")); + QScopedPointer<QObject> o(component.create()); + QVERIFY(o); + auto success = o->property("success"); + QVERIFY(success.isValid()); + QVERIFY(success.toBool()); +} + void tst_qqmlecmascript::assignBasicTypes() { QQmlEngine engine; @@ -5740,9 +5771,7 @@ void tst_qqmlecmascript::sequenceConversionRead() QVERIFY(seq != nullptr); // we haven't registered QList<NonRegisteredType> as a sequence type. - QString warningOne = QLatin1String("QMetaProperty::read: Unable to handle unregistered datatype 'QVector<NonRegisteredType>' for property 'MySequenceConversionObject::typeListProperty'"); - QString warningTwo = qmlFile.toString() + QLatin1String(":18: TypeError: Cannot read property 'length' of undefined"); - QTest::ignoreMessage(QtWarningMsg, warningOne.toLatin1().constData()); + QString warningTwo = qmlFile.toString() + QLatin1String(":18: Error: Cannot assign [undefined] to int"); QTest::ignoreMessage(QtWarningMsg, warningTwo.toLatin1().constData()); QMetaObject::invokeMethod(object, "performTest"); @@ -5750,10 +5779,6 @@ void tst_qqmlecmascript::sequenceConversionRead() // QList<NonRegisteredType> has not been registered as a sequence type. QCOMPARE(object->property("pointListLength").toInt(), 0); QVERIFY(!object->property("pointList").isValid()); - QTest::ignoreMessage(QtWarningMsg, "QMetaProperty::read: Unable to handle unregistered datatype 'QVector<NonRegisteredType>' for property 'MySequenceConversionObject::typeListProperty'"); - QQmlProperty seqProp(seq, "typeListProperty", &engine); - QVERIFY(!seqProp.read().isValid()); // not a valid/known sequence type - delete object; } } @@ -5792,13 +5817,12 @@ void tst_qqmlecmascript::sequenceConversionWrite() MySequenceConversionObject *seq = object->findChild<MySequenceConversionObject*>("msco"); QVERIFY(seq != nullptr); - // we haven't registered QList<QPoint> as a sequence type, so writing shouldn't work. - QString warningOne = qmlFile.toString() + QLatin1String(":16: Error: Cannot assign QJSValue to QVector<QPoint>"); - QTest::ignoreMessage(QtWarningMsg, warningOne.toLatin1().constData()); - + // Behavior change in 5.14: due to added auto-magical conversions, it is possible to assign to + // QList<QPoint>, even though it is not a registered sequence type + QTest::ignoreMessage(QtMsgType::QtWarningMsg, QRegularExpression("Could not convert array value at position 1 from QString to QPoint")); QMetaObject::invokeMethod(object, "performTest"); - QList<QPoint> pointList; pointList << QPoint(1, 2) << QPoint(3, 4) << QPoint(5, 6); // original values, shouldn't have changed + QList<QPoint> pointList; pointList << QPoint(7, 7) << QPoint(0,0) << QPoint(8, 8) << QPoint(9, 9); // original values, shouldn't have changed QCOMPARE(seq->pointListProperty(), pointList); delete object; @@ -7274,7 +7298,7 @@ void tst_qqmlecmascript::forInLoop() QMetaObject::invokeMethod(object, "listProperty"); - QStringList r = object->property("listResult").toString().split("|", QString::SkipEmptyParts); + QStringList r = object->property("listResult").toString().split("|", Qt::SkipEmptyParts); QCOMPARE(r.size(), 3); QCOMPARE(r[0],QLatin1String("0=obj1")); QCOMPARE(r[1],QLatin1String("1=obj2")); diff --git a/tests/auto/qml/qqmlengine/data/qtqmlModule.10.qml b/tests/auto/qml/qqmlengine/data/qtqmlModule.10.qml new file mode 100644 index 0000000000..3fc0cc217d --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/qtqmlModule.10.qml @@ -0,0 +1,4 @@ +import QtQml 6.50 + +QtObject { +} diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp index ab4c083b65..0081243a88 100644 --- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp +++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp @@ -687,9 +687,9 @@ void tst_qqmlengine::qtqmlModule_data() << QString(testFileUrl("qtqmlModule.3.qml").toString() + QLatin1String(":1 module \"QtQml\" version 1.0 is not installed\n")) << QStringList(); - QTest::newRow("import QtQml of incorrect version (2.50)") + QTest::newRow("import QtQml of old version (2.50)") << testFileUrl("qtqmlModule.4.qml") - << QString(testFileUrl("qtqmlModule.4.qml").toString() + QLatin1String(":1 module \"QtQml\" version 2.50 is not installed\n")) + << QString() << QStringList(); QTest::newRow("QtQml 2.0 module provides Component, QtObject, Connections, Binding and Timer") @@ -716,6 +716,11 @@ void tst_qqmlengine::qtqmlModule_data() << testFileUrl("qtqmlModule.9.qml") << QString(testFileUrl("qtqmlModule.9.qml").toString() + QLatin1String(":4 Item is not a type\n")) << QStringList(); + + QTest::newRow("import QtQml of incorrect version (6.50)") + << testFileUrl("qtqmlModule.10.qml") + << QString(testFileUrl("qtqmlModule.10.qml").toString() + QLatin1String(":1 module \"QtQml\" version 6.50 is not installed\n")) + << QStringList(); } // Test that the engine registers the QtQml module @@ -997,6 +1002,11 @@ public: SomeQObjectClass() : QObject(nullptr){} }; +class Dayfly : public QObject +{ + Q_OBJECT +}; + void tst_qqmlengine::singletonInstance() { QQmlEngine engine; @@ -1115,7 +1125,7 @@ void tst_qqmlengine::singletonInstance() { // deleted object - auto dayfly = new QObject{}; + auto dayfly = new Dayfly{}; auto id = qmlRegisterSingletonInstance("Vanity", 1, 0, "Dayfly", dayfly); delete dayfly; QTest::ignoreMessage(QtMsgType::QtWarningMsg, "<Unknown File>: The registered singleton has already been deleted. Ensure that it outlives the engine."); diff --git a/tests/auto/qml/qqmlenginecleanup/data/MyItem.qml b/tests/auto/qml/qqmlenginecleanup/data/MyItem.qml new file mode 100644 index 0000000000..4bb8dfb486 --- /dev/null +++ b/tests/auto/qml/qqmlenginecleanup/data/MyItem.qml @@ -0,0 +1,2 @@ +import QtQuick 2.12 +Item {} diff --git a/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp b/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp index 690db30838..26b2b839ea 100644 --- a/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp +++ b/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp @@ -45,6 +45,7 @@ private slots: void test_qmlClearTypeRegistrations(); void test_valueTypeProviderModule(); // QTBUG-43004 void test_customModuleCleanup(); + void test_qmlListCleared(); }; // A wrapper around QQmlComponent to ensure the temporary reference counts @@ -77,7 +78,8 @@ void tst_qqmlenginecleanup::test_qmlClearTypeRegistrations() QUrl testFile = testFileUrl("types.qml"); const auto qmlTypeForTestType = []() { - return QQmlMetaType::qmlType(QStringLiteral("TestTypeCpp"), QStringLiteral("Test"), 2, 0); + return QQmlMetaType::qmlType(QStringLiteral("TestTypeCpp"), QStringLiteral("Test"), + QTypeRevision::fromVersion(2, 0)); }; QVERIFY(!qmlTypeForTestType().isValid()); @@ -186,6 +188,18 @@ void tst_qqmlenginecleanup::test_customModuleCleanup() } } +void tst_qqmlenginecleanup::test_qmlListCleared() +{ + { + QQmlEngine engine; + auto url = testFileUrl("MyItem.qml"); + QQmlComponent comp(&engine, url); + QScopedPointer<QObject> item {comp.create()}; + QCOMPARE(QQmlMetaType::qmlRegisteredListTypeCount(), 1); + } + QCOMPARE(QQmlMetaType::qmlRegisteredListTypeCount(), 0); +} + QTEST_MAIN(tst_qqmlenginecleanup) #include "tst_qqmlenginecleanup.moc" diff --git a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp index 9c865b3f73..6e95ddfdea 100644 --- a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp +++ b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp @@ -190,7 +190,9 @@ void tst_QQmlImport::completeQmldirPaths() QFETCH(int, minorVersion); QFETCH(QStringList, expectedPaths); - QCOMPARE(QQmlImports::completeQmldirPaths(uri, basePaths, majorVersion, minorVersion), expectedPaths); + QCOMPARE(QQmlImports::completeQmldirPaths( + uri, basePaths, QTypeRevision::fromVersion(majorVersion, minorVersion)), + expectedPaths); } class QmldirUrlInterceptor : public QQmlAbstractUrlInterceptor { 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/NonRequiredBase.qml b/tests/auto/qml/qqmllanguage/data/NonRequiredBase.qml new file mode 100644 index 0000000000..60d45c2b1e --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/NonRequiredBase.qml @@ -0,0 +1,5 @@ +import QtQuick 2.15 + +Item { + property int i +} diff --git a/tests/auto/qml/qqmllanguage/data/RequiredBase.qml b/tests/auto/qml/qqmllanguage/data/RequiredBase.qml new file mode 100644 index 0000000000..4effdbf1c7 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/RequiredBase.qml @@ -0,0 +1,3 @@ +NonRequiredBase { + required i +} diff --git a/tests/auto/qml/qqmllanguage/data/SimpleItem.qml b/tests/auto/qml/qqmllanguage/data/SimpleItem.qml new file mode 100644 index 0000000000..c7bce2bc78 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/SimpleItem.qml @@ -0,0 +1,5 @@ +import QtQuick 2.15 + +Item { + property int i: 42 +} diff --git a/tests/auto/qml/qqmllanguage/data/arrayToContainer.qml b/tests/auto/qml/qqmllanguage/data/arrayToContainer.qml new file mode 100644 index 0000000000..ee400eb41f --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/arrayToContainer.qml @@ -0,0 +1,7 @@ +import QtQml 2.14 +import qt.test 1.0 + +TestItem { + property var vector + positions: vector +} diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredProperty.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredProperty.qml new file mode 100644 index 0000000000..76673f6409 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/cppRequiredProperty.qml @@ -0,0 +1,4 @@ +import QtQuick 2.15 +import example.org 1.0 + +MyClass {test: 42} diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParent.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParent.qml new file mode 100644 index 0000000000..d4c059581c --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParent.qml @@ -0,0 +1,4 @@ +import QtQuick 2.15 +import example.org 1.0 + +Child2 {test: test2; test2: 18} diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParentNotSet.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParentNotSet.qml new file mode 100644 index 0000000000..082e22dc3f --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParentNotSet.qml @@ -0,0 +1,4 @@ +import QtQuick 2.15 +import example.org 1.0 + +Child2 { test: 13 } diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParent.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParent.qml new file mode 100644 index 0000000000..6602684542 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParent.qml @@ -0,0 +1,4 @@ +import QtQuick 2.15 +import example.org 1.0 + +Child {test: 42} diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParentNotSet.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParentNotSet.qml new file mode 100644 index 0000000000..5971b0c263 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParentNotSet.qml @@ -0,0 +1,4 @@ +import QtQuick 2.15 +import example.org 1.0 + +Child {} diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyNotSet.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyNotSet.qml new file mode 100644 index 0000000000..dab48a3d71 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyNotSet.qml @@ -0,0 +1,4 @@ +import QtQuick 2.15 +import example.org 1.0 + +MyClass {} diff --git a/tests/auto/qml/qqmllanguage/data/cppstaticnamespace.2.qml b/tests/auto/qml/qqmllanguage/data/cppstaticnamespace.2.qml new file mode 100644 index 0000000000..3b37c29b18 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/cppstaticnamespace.2.qml @@ -0,0 +1,5 @@ +import StaticTest 1.0 + +MyStaticSecondNamespacedType { + list: [ MyStaticNamespacedType {} ] +} diff --git a/tests/auto/qml/qqmllanguage/data/cppstaticnamespace.qml b/tests/auto/qml/qqmllanguage/data/cppstaticnamespace.qml new file mode 100644 index 0000000000..2778baadb9 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/cppstaticnamespace.qml @@ -0,0 +1,6 @@ +import StaticTest 1.0 + +MyStaticNamespacedType { + myEnum: MyStaticNamespace.Key5 + property int intProperty: MyStaticNamespace.MyOtherNSEnum.OtherKey2 +} diff --git a/tests/auto/qml/qqmllanguage/data/inlineComponentWithAlias.qml b/tests/auto/qml/qqmllanguage/data/inlineComponentWithAlias.qml new file mode 100644 index 0000000000..ab125e9323 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/inlineComponentWithAlias.qml @@ -0,0 +1,17 @@ +import QtQuick 2.15 + +Item { + id: root + component IC: SimpleItem { + width: i + Rectangle { + id: rect + color: "lime" + } + property alias color: rect.color + } + width: 200 + IC { + objectName: "icInstance" + } +} diff --git a/tests/auto/qml/qqmllanguage/data/inlineComponentWithId.qml b/tests/auto/qml/qqmllanguage/data/inlineComponentWithId.qml new file mode 100644 index 0000000000..c4093bad2f --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/inlineComponentWithId.qml @@ -0,0 +1,14 @@ +import QtQuick 2.15 + +Item { + id: root + component IC: SimpleItem { + id: root + width: root.i + property color color: "red" + } + width: 200 + IC { + objectName: "icInstance" + } +} 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/data/requiredProperties.3.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml index 534322215f..2585cf361e 100644 --- a/tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml +++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml @@ -1,4 +1,6 @@ -import QtQuick 2.13 +import QtQuick 2.15 + Item { - default required property int test // cannot have required default property + property int i; + required i; } diff --git a/tests/auto/qml/qqmllanguage/data/requiredProperties.4.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.4.qml new file mode 100644 index 0000000000..1126f845c9 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.4.qml @@ -0,0 +1,5 @@ +import QtQuick 2.15 + +Item { + required objectName +} diff --git a/tests/auto/qml/qqmllanguage/data/requiredProperties.5.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.5.qml new file mode 100644 index 0000000000..c2d155b123 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.5.qml @@ -0,0 +1 @@ +RequiredBase {} diff --git a/tests/auto/qml/qqmllanguage/data/requiredProperties.6.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.6.qml new file mode 100644 index 0000000000..e8802aef20 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.6.qml @@ -0,0 +1,3 @@ +RequiredBase { + i: 42 +} diff --git a/tests/auto/qml/qqmllanguage/data/requiredProperties.7.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.7.qml new file mode 100644 index 0000000000..40987f5c56 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.7.qml @@ -0,0 +1,5 @@ +import QtQuick 2.15 + +Item { + required blub +} diff --git a/tests/auto/qml/qqmllanguage/qqmllanguage.pro b/tests/auto/qml/qqmllanguage/qqmllanguage.pro index 724a27320c..6c54525544 100644 --- a/tests/auto/qml/qqmllanguage/qqmllanguage.pro +++ b/tests/auto/qml/qqmllanguage/qqmllanguage.pro @@ -1,4 +1,7 @@ -CONFIG += testcase +CONFIG += testcase qmltypes +QML_IMPORT_NAME = StaticTest +QML_IMPORT_VERSION = 1.0 + TARGET = tst_qqmllanguage macx:CONFIG -= app_bundle diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h index 39502372e6..8852bf7af9 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.h +++ b/tests/auto/qml/qqmllanguage/testtypes.h @@ -750,6 +750,47 @@ private: bool m_ownRWObj; }; +namespace MyStaticNamespace { + Q_NAMESPACE + QML_ELEMENT + + enum MyNSEnum { + Key1 = 1, + Key2, + Key5 = 5 + }; + Q_ENUM_NS(MyNSEnum); + + enum class MyOtherNSEnum { + OtherKey1 = 1, + OtherKey2 + }; + Q_ENUM_NS(MyOtherNSEnum); + + + class MyNamespacedType : public QObject + { + Q_OBJECT + Q_PROPERTY(MyStaticNamespace::MyNSEnum myEnum MEMBER m_myEnum) + QML_NAMED_ELEMENT(MyStaticNamespacedType) + MyStaticNamespace::MyNSEnum m_myEnum = MyNSEnum::Key1; + }; + + class MySecondNamespacedType : public QObject + { + Q_OBJECT + Q_PROPERTY(QQmlListProperty<MyStaticNamespace::MyNamespacedType> list READ list) + QML_NAMED_ELEMENT(MyStaticSecondNamespacedType) + public: + QQmlListProperty<MyNamespacedType> list() + { + return QQmlListProperty<MyNamespacedType>(this, &m_list); + } + + private: + QList<MyNamespacedType *> m_list; + }; +} namespace MyNamespace { Q_NAMESPACE @@ -1440,17 +1481,22 @@ public: int base() const { return 43; } }; +class Local : public QObject +{ + Q_OBJECT +}; + class Foreign { Q_GADGET - QML_FOREIGN(QObject) + QML_FOREIGN(Local) QML_NAMED_ELEMENT(Foreign) }; class ForeignExtended { Q_GADGET - QML_FOREIGN(QObject) + QML_FOREIGN(Local) QML_NAMED_ELEMENT(ForeignExtended) QML_EXTENDED(Extension) }; diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 4d2f773dbf..c6076410b2 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(); @@ -133,6 +134,8 @@ private slots: void autoComponentCreationInGroupProperty(); void propertyValueSource(); void requiredProperty(); + void requiredPropertyFromCpp_data(); + void requiredPropertyFromCpp(); void attachedProperties(); void dynamicObjects(); void customVariantTypes(); @@ -321,6 +324,10 @@ private slots: void listContainingDeletedObject(); void overrideSingleton(); + void revisionedPropertyOfAttachedObjectProperty(); + + void arrayToContainer(); + void qualifiedScopeInCustomParser(); private: QQmlEngine engine; @@ -1486,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")); @@ -1674,8 +1691,103 @@ void tst_qqmllanguage::requiredProperty() QVERIFY(!component.errors().empty()); } { + QQmlComponent component(&engine, testFileUrl("requiredProperties.4.qml")); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!component.errors().empty()); + QVERIFY(component.errorString().contains("Required property objectName was not initialized")); + } + { QQmlComponent component(&engine, testFileUrl("requiredProperties.3.qml")); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!component.errors().empty()); + QVERIFY(component.errorString().contains("Required property i was not initialized")); + } + { + QQmlComponent component(&engine, testFileUrl("requiredProperties.5.qml")); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!component.errors().empty()); + QVERIFY(component.errorString().contains("Required property i was not initialized")); + } + { + QQmlComponent component(&engine, testFileUrl("requiredProperties.6.qml")); + VERIFY_ERRORS(0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(object); + } + { + QQmlComponent component(&engine, testFileUrl("requiredProperties.7.qml")); + QScopedPointer<QObject> object(component.create()); QVERIFY(!component.errors().empty()); + QVERIFY(component.errorString().contains("Property blub was marked as required but does not exist")); + } +} + +class MyClassWithRequiredProperty : public QObject +{ +public: + Q_OBJECT + Q_PROPERTY(int test MEMBER m_test REQUIRED NOTIFY testChanged) + Q_SIGNAL void testChanged(); +private: + int m_test; +}; + +class ChildClassWithoutOwnRequired : public MyClassWithRequiredProperty +{ +public: + Q_OBJECT + Q_PROPERTY(int test2 MEMBER m_test2 NOTIFY test2Changed) + Q_SIGNAL void test2Changed(); +private: + int m_test2; +}; + +class ChildClassWithOwnRequired : public MyClassWithRequiredProperty +{ +public: + Q_OBJECT + Q_PROPERTY(int test2 MEMBER m_test2 REQUIRED NOTIFY test2Changed) + Q_SIGNAL void test2Changed(); +private: + int m_test2; +}; + +void tst_qqmllanguage::requiredPropertyFromCpp_data() +{ + qmlRegisterType<MyClassWithRequiredProperty>("example.org", 1, 0, "MyClass"); + qmlRegisterType<ChildClassWithoutOwnRequired>("example.org", 1, 0, "Child"); + qmlRegisterType<ChildClassWithOwnRequired>("example.org", 1, 0, "Child2"); + + + QTest::addColumn<QUrl>("setFile"); + QTest::addColumn<QUrl>("notSetFile"); + QTest::addColumn<QString>("errorMessage"); + QTest::addColumn<int>("expectedValue"); + + QTest::addRow("direct") << testFileUrl("cppRequiredProperty.qml") << testFileUrl("cppRequiredPropertyNotSet.qml") << QString(":4 Required property test was not initialized\n") << 42; + QTest::addRow("in parent") << testFileUrl("cppRequiredPropertyInParent.qml") << testFileUrl("cppRequiredPropertyInParentNotSet.qml") << QString(":4 Required property test was not initialized\n") << 42; + QTest::addRow("in child and parent") << testFileUrl("cppRequiredPropertyInChildAndParent.qml") << testFileUrl("cppRequiredPropertyInChildAndParentNotSet.qml") << QString(":4 Required property test2 was not initialized\n") << 18; +} + +void tst_qqmllanguage::requiredPropertyFromCpp() +{ + QQmlEngine engine; + QFETCH(QUrl, setFile); + QFETCH(QUrl, notSetFile); + QFETCH(QString, errorMessage); + QFETCH(int, expectedValue); + { + QQmlComponent comp(&engine, notSetFile); + QScopedPointer<QObject> o { comp.create() }; + QVERIFY(o.isNull()); + QVERIFY(comp.isError()); + QCOMPARE(comp.errorString(), notSetFile.toString() + errorMessage); + } + { + QQmlComponent comp(&engine, setFile); + QScopedPointer<QObject> o { comp.create() }; + QVERIFY(!o.isNull()); + QCOMPARE(o->property("test").toInt(), expectedValue); } } @@ -1747,21 +1859,30 @@ void tst_qqmllanguage::valueTypes() void tst_qqmllanguage::cppnamespace() { - { - QQmlComponent component(&engine, testFileUrl("cppnamespace.qml")); + QScopedPointer<QObject> object; + + auto create = [&](const char *file) { + QQmlComponent component(&engine, testFileUrl(file)); VERIFY_ERRORS(0); - QScopedPointer<QObject> object(component.create()); + object.reset(component.create()); QVERIFY(object != nullptr); + }; - QCOMPARE(object->property("intProperty").toInt(), (int)MyNamespace::MyOtherNSEnum::OtherKey2); - } + auto createAndCheck = [&](const char *file) { + create(file); + return !QTest::currentTestFailed(); + }; - { - QQmlComponent component(&engine, testFileUrl("cppnamespace.2.qml")); - VERIFY_ERRORS(0); - QScopedPointer<QObject> object(component.create()); - QVERIFY(object != nullptr); - } + QVERIFY(createAndCheck("cppnamespace.qml")); + QCOMPARE(object->property("intProperty").toInt(), + (int)MyNamespace::MyOtherNSEnum::OtherKey2); + + QVERIFY(createAndCheck("cppstaticnamespace.qml")); + QCOMPARE(object->property("intProperty").toInt(), + (int)MyStaticNamespace::MyOtherNSEnum::OtherKey2); + + QVERIFY(createAndCheck("cppnamespace.2.qml")); + QVERIFY(createAndCheck("cppstaticnamespace.2.qml")); } void tst_qqmllanguage::aliasProperties() @@ -5318,7 +5439,7 @@ void tst_qqmllanguage::selfReference() const QMetaObject *metaObject = o->metaObject(); QMetaProperty selfProperty = metaObject->property(metaObject->indexOfProperty("self")); - QCOMPARE(selfProperty.userType(), compilationUnit->metaTypeId); + QCOMPARE(selfProperty.userType(), compilationUnit->metaTypeId.id()); QByteArray typeName = selfProperty.typeName(); QVERIFY(typeName.endsWith('*')); @@ -5327,7 +5448,7 @@ void tst_qqmllanguage::selfReference() QMetaMethod selfFunction = metaObject->method(metaObject->indexOfMethod("returnSelf()")); QVERIFY(selfFunction.isValid()); - QCOMPARE(selfFunction.returnType(), compilationUnit->metaTypeId); + QCOMPARE(selfFunction.returnType(), compilationUnit->metaTypeId.id()); QMetaMethod selfSignal; @@ -5341,7 +5462,7 @@ void tst_qqmllanguage::selfReference() QVERIFY(selfSignal.isValid()); QCOMPARE(selfSignal.parameterCount(), 1); - QCOMPARE(selfSignal.parameterType(0), compilationUnit->metaTypeId); + QCOMPARE(selfSignal.parameterType(0), compilationUnit->metaTypeId.id()); } void tst_qqmllanguage::selfReferencingSingleton() @@ -5418,6 +5539,85 @@ void tst_qqmllanguage::overrideSingleton() check("uncreatable", "UncreatableSingleton"); } +class AttachedObject; +class InnerObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool revisionedProperty READ revisionedProperty WRITE setRevisionedProperty + NOTIFY revisionedPropertyChanged REVISION 2) + +public: + InnerObject(QObject *parent = nullptr) : QObject(parent) {} + + bool revisionedProperty() const { return m_revisionedProperty; } + void setRevisionedProperty(bool revisionedProperty) + { + if (revisionedProperty != m_revisionedProperty) { + m_revisionedProperty = revisionedProperty; + emit revisionedPropertyChanged(); + } + } + + static AttachedObject *qmlAttachedProperties(QObject *object); + +signals: + Q_REVISION(2) void revisionedPropertyChanged(); + +private: + bool m_revisionedProperty = false; +}; + +class AttachedObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(InnerObject *attached READ attached CONSTANT) + +public: + explicit AttachedObject(QObject *parent = nullptr) : + QObject(parent), + m_attached(new InnerObject(this)) + {} + + InnerObject *attached() const { return m_attached; } + +private: + InnerObject *m_attached; +}; + +class OuterObject : public QObject +{ + Q_OBJECT +public: + explicit OuterObject(QObject *parent = nullptr) : QObject(parent) {} +}; + +AttachedObject *InnerObject::qmlAttachedProperties(QObject *object) +{ + return new AttachedObject(object); +} + +QML_DECLARE_TYPE(InnerObject) +QML_DECLARE_TYPEINFO(InnerObject, QML_HAS_ATTACHED_PROPERTIES) + +void tst_qqmllanguage::revisionedPropertyOfAttachedObjectProperty() +{ + qmlRegisterAnonymousType<AttachedObject>("foo", 2); + qmlRegisterType<InnerObject>("foo", 2, 0, "InnerObject"); + qmlRegisterType<InnerObject, 2>("foo", 2, 2, "InnerObject"); + qmlRegisterType<OuterObject>("foo", 2, 2, "OuterObject"); + + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData("import foo 2.2\n" + "OuterObject {\n" + " InnerObject.attached.revisionedProperty: true\n" + "}", QUrl()); + + QVERIFY(component.isReady()); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); +} + void tst_qqmllanguage::inlineComponent() { QFETCH(QUrl, componentUrl); @@ -5450,6 +5650,9 @@ void tst_qqmllanguage::inlineComponent_data() QTest::newRow("Non-toplevel IC is found") << testFileUrl("inlineComponentUser5.qml") << QColorConstants::Svg::red << 24; QTest::newRow("Resolved in correct order") << testFileUrl("inlineComponentOrder.qml") << QColorConstants::Blue << 200; + + QTest::newRow("ID resolves correctly") << testFileUrl("inlineComponentWithId.qml") << QColorConstants::Svg::red << 42; + QTest::newRow("Alias resolves correctly") << testFileUrl("inlineComponentWithAlias.qml") << QColorConstants::Svg::lime << 42; } void tst_qqmllanguage::inlineComponentReferenceCycle_data() @@ -5540,6 +5743,60 @@ void tst_qqmllanguage::nonExistingInlineComponent() QCOMPARE(error.column(), column); } +class TestItem : public QObject +{ + Q_OBJECT + Q_PROPERTY( QVector<QPointF> positions MEMBER m_points ) + +public: + TestItem() = default; + QVector< QPointF > m_points; +}; + + +Q_DECLARE_METATYPE(QVector<QPointF>); +void tst_qqmllanguage::arrayToContainer() +{ + QQmlEngine engine; + qmlRegisterType<TestItem>("qt.test", 1, 0, "TestItem"); + QVector<QPointF> points { QPointF (2.0, 3.0) }; + engine.rootContext()->setContextProperty("test", QVariant::fromValue(points)); + QQmlComponent component(&engine, testFileUrl("arrayToContainer.qml")); + VERIFY_ERRORS(0); + QScopedPointer<TestItem> root(qobject_cast<TestItem *>(component.createWithInitialProperties( {{"vector", QVariant::fromValue(points)}} ))); + QVERIFY(root); + QCOMPARE(root->m_points.at(0), QPointF (2.0, 3.0) ); +} + +class EnumTester : public QObject +{ + Q_OBJECT +public: + enum Types + { + FIRST = 0, + SECOND, + THIRD + }; + Q_ENUM(Types) +}; + +void tst_qqmllanguage::qualifiedScopeInCustomParser() +{ + qmlRegisterUncreatableType<EnumTester>("scoped.custom.test", 1, 0, "EnumTester", + "Object only creatable in C++"); + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData("import QtQml.Models 2.12\n" + "import scoped.custom.test 1.0 as BACKEND\n" + "ListModel {\n" + " ListElement { text: \"a\"; type: BACKEND.EnumTester.FIRST }\n" + "}\n", QUrl()); + QVERIFY(component.isReady()); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); +} + QTEST_MAIN(tst_qqmllanguage) #include "tst_qqmllanguage.moc" diff --git a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp index ea157a7d15..b21d2a908d 100644 --- a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp +++ b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp @@ -112,9 +112,9 @@ void tst_QQmlMetaObject::property_data() QTest::newRow("date") << "property.date.qml" << QByteArray("QDateTime") << int(QMetaType::QDateTime) << false // default - << QVariant(QDateTime(QDate(2012, 2, 7))) + << QVariant(QDate(2012, 2, 7).startOfDay()) << true // writable - << QVariant(QDateTime(QDate(2010, 7, 2))); + << QVariant(QDate(2010, 7, 2).startOfDay()); QTest::newRow("variant") << "property.variant.qml" << QByteArray("QVariant") << int(QMetaType::QVariant) << true // default diff --git a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp index 296d1b14e0..b69b466947 100644 --- a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp +++ b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp @@ -217,13 +217,14 @@ void tst_qqmlmetatype::qmlPropertyValueInterceptorCast() void tst_qqmlmetatype::qmlType() { - QQmlType type = QQmlMetaType::qmlType(QString("ParserStatusTestType"), QString("Test"), 1, 0); + QQmlType type = QQmlMetaType::qmlType(QString("ParserStatusTestType"), QString("Test"), + QTypeRevision::fromVersion(1, 0)); QVERIFY(type.isValid()); QVERIFY(type.module() == QLatin1String("Test")); QVERIFY(type.elementName() == QLatin1String("ParserStatusTestType")); QCOMPARE(type.qmlTypeName(), QLatin1String("Test/ParserStatusTestType")); - type = QQmlMetaType::qmlType("Test/ParserStatusTestType", 1, 0); + type = QQmlMetaType::qmlType("Test/ParserStatusTestType", QTypeRevision::fromVersion(1, 0)); QVERIFY(type.isValid()); QVERIFY(type.module() == QLatin1String("Test")); QVERIFY(type.elementName() == QLatin1String("ParserStatusTestType")); @@ -282,19 +283,22 @@ void tst_qqmlmetatype::defaultObject() void tst_qqmlmetatype::registrationType() { - QQmlType type = QQmlMetaType::qmlType(QString("TestType"), QString("Test"), 1, 0); + QQmlType type = QQmlMetaType::qmlType(QString("TestType"), QString("Test"), + QTypeRevision::fromVersion(1, 0)); QVERIFY(type.isValid()); QVERIFY(!type.isInterface()); QVERIFY(!type.isSingleton()); QVERIFY(!type.isComposite()); - type = QQmlMetaType::qmlType(QString("TestTypeSingleton"), QString("Test"), 1, 0); + type = QQmlMetaType::qmlType(QString("TestTypeSingleton"), QString("Test"), + QTypeRevision::fromVersion(1, 0)); QVERIFY(type.isValid()); QVERIFY(!type.isInterface()); QVERIFY(type.isSingleton()); QVERIFY(!type.isComposite()); - type = QQmlMetaType::qmlType(QString("TestTypeComposite"), QString("Test"), 1, 0); + type = QQmlMetaType::qmlType(QString("TestTypeComposite"), QString("Test"), + QTypeRevision::fromVersion(1, 0)); QVERIFY(type.isValid()); QVERIFY(!type.isInterface()); QVERIFY(!type.isSingleton()); @@ -310,7 +314,8 @@ void tst_qqmlmetatype::compositeType() QScopedPointer<QObject> obj(c.create()); QVERIFY(obj); - QQmlType type = QQmlMetaType::qmlType(QString("ImplicitType"), QString(""), 1, 0); + QQmlType type = QQmlMetaType::qmlType(QString("ImplicitType"), QString(""), + QTypeRevision::fromVersion(1, 0)); QVERIFY(type.isValid()); QVERIFY(type.module().isEmpty()); QCOMPARE(type.elementName(), QLatin1String("ImplicitType")); @@ -380,70 +385,76 @@ void tst_qqmlmetatype::unregisterCustomType() int controllerId = 0; { QQmlEngine engine; - QQmlType type = QQmlMetaType::qmlType(QString("Controller"), QString("mytypes"), 1, 0); - QVERIFY(!type.isValid()); + QQmlType type = QQmlMetaType::qmlType(QString("Controller"), QString("mytypes"), + QTypeRevision::fromVersion(1, 0)); + QVERIFY2(!type.isValid(), "Type is not valid yet"); controllerId = qmlRegisterType<Controller1>("mytypes", 1, 0, "Controller"); - type = QQmlMetaType::qmlType(QString("Controller"), QString("mytypes"), 1, 0); - QVERIFY(type.isValid()); - QVERIFY(!type.isInterface()); - QVERIFY(!type.isSingleton()); - QVERIFY(!type.isComposite()); + type = QQmlMetaType::qmlType(QString("Controller"), QString("mytypes"), + QTypeRevision::fromVersion(1, 0)); + QVERIFY2(type.isValid(), "Type is valid now"); + QVERIFY2(!type.isInterface(), "Type is not an interface"); + QVERIFY2(!type.isSingleton(), "Type is not a singleton"); + QVERIFY2(!type.isComposite(), "Types is not a composite type"); QQmlComponent c(&engine, testFileUrl("testUnregisterCustomType.qml")); QScopedPointer<QObject> obj(c.create()); - QVERIFY(obj); + QVERIFY2(obj, "obj is not null"); QObject *controller = obj->findChild<QObject *>("controller"); - QVERIFY(qobject_cast<Controller1 *>(controller)); + QVERIFY2(qobject_cast<Controller1 *>(controller), "child 'controller' could be found and is a Controller1*"); QVariant stringVal = controller->property("string"); QCOMPARE(stringVal.userType(), QVariant::String); QCOMPARE(stringVal.toString(), QStringLiteral("Controller #1")); QVariant enumVal = controller->property("enumVal"); - QCOMPARE(enumVal.userType(), QVariant::Int); + QVERIFY2(QMetaType(enumVal.userType()).flags() & QMetaType::IsEnumeration, "enumVal's type is enumeratoion"); QCOMPARE(enumVal.toInt(), 1); } QQmlMetaType::unregisterType(controllerId); { QQmlEngine engine; - QQmlType type = QQmlMetaType::qmlType(QString("Controller"), QString("mytypes"), 1, 0); - QVERIFY(!type.isValid()); + QQmlType type = QQmlMetaType::qmlType(QString("Controller"), QString("mytypes"), + QTypeRevision::fromVersion(1, 0)); + QVERIFY2(!type.isValid(), "Type is not valid anymore"); controllerId = qmlRegisterType<Controller2>("mytypes", 1, 0, "Controller"); - type = QQmlMetaType::qmlType(QString("Controller"), QString("mytypes"), 1, 0); - QVERIFY(type.isValid()); - QVERIFY(!type.isInterface()); - QVERIFY(!type.isSingleton()); - QVERIFY(!type.isComposite()); + type = QQmlMetaType::qmlType(QString("Controller"), QString("mytypes"), + QTypeRevision::fromVersion(1, 0)); + QVERIFY2(type.isValid(), "Type is valid again"); + QVERIFY2(!type.isInterface(), "Type is not an interface"); + QVERIFY2(!type.isSingleton(), "Type is not a singleton"); + QVERIFY2(!type.isComposite(), "Type is not a composite"); QQmlComponent c(&engine, testFileUrl("testUnregisterCustomType.qml")); QScopedPointer<QObject> obj(c.create()); - QVERIFY(obj); + QVERIFY2(obj, "obj is not null"); QObject *controller = obj->findChild<QObject *>("controller"); - QVERIFY(qobject_cast<Controller2 *>(controller)); + QVERIFY2(qobject_cast<Controller2 *>(controller), "child 'controller' could be found and is a Controller2*"); QVariant stringVal = controller->property("string"); QCOMPARE(stringVal.userType(), QVariant::String); QCOMPARE(stringVal.toString(), QStringLiteral("Controller #2")); QVariant enumVal = controller->property("enumVal"); - QCOMPARE(enumVal.userType(), QVariant::Int); + QVERIFY2(QMetaType(enumVal.userType()).flags() & QMetaType::IsEnumeration, "enumVal's type is enumeratoion"); QCOMPARE(enumVal.toInt(), 111); } QQmlMetaType::unregisterType(controllerId); { QQmlEngine engine; - QQmlType type = QQmlMetaType::qmlType(QString("Controller"), QString("mytypes"), 1, 0); - QVERIFY(!type.isValid()); + QQmlType type = QQmlMetaType::qmlType(QString("Controller"), QString("mytypes"), + QTypeRevision::fromVersion(1, 0)); + QVERIFY2(!type.isValid(), "Type is not valid anymore"); controllerId = qmlRegisterType<Controller1>("mytypes", 1, 0, "Controller"); - type = QQmlMetaType::qmlType(QString("Controller"), QString("mytypes"), 1, 0); - QVERIFY(type.isValid()); - QVERIFY(!type.isInterface()); - QVERIFY(!type.isSingleton()); - QVERIFY(!type.isComposite()); + type = QQmlMetaType::qmlType(QString("Controller"), QString("mytypes"), + QTypeRevision::fromVersion(1, 0)); + QVERIFY2(type.isValid(), "Type is valid again"); + QVERIFY2(!type.isInterface(), "Type is not an interface"); + QVERIFY2(!type.isSingleton(), "Type is not a singleton"); + QVERIFY2(!type.isComposite(), "Type is not a composite"); QQmlComponent c(&engine, testFileUrl("testUnregisterCustomType.qml")); QScopedPointer<QObject> obj(c.create()); - QVERIFY(obj); + QVERIFY2(obj, "obj is not null"); QObject *controller = obj->findChild<QObject *>("controller"); - QVERIFY(qobject_cast<Controller1 *>(controller)); + QVERIFY2(qobject_cast<Controller1 *>(controller), "child 'controller' could be found and is a Controller1*"); QVariant stringVal = controller->property("string"); QCOMPARE(stringVal.userType(), QVariant::String); QCOMPARE(stringVal.toString(), QStringLiteral("Controller #1")); QVariant enumVal = controller->property("enumVal"); - QCOMPARE(enumVal.userType(), QVariant::Int); + QVERIFY2(QMetaType(enumVal.userType()).flags() & QMetaType::IsEnumeration, "enumVal's type is enumeratoion"); QCOMPARE(enumVal.toInt(), 1); } } @@ -480,7 +491,8 @@ void tst_qqmlmetatype::unregisterCustomSingletonType() { QQmlEngine engine; staticProviderId = qmlRegisterSingletonType<StaticProvider1>("mytypes", 1, 0, "StaticProvider", createStaticProvider1); - QQmlType type = QQmlMetaType::qmlType(QString("StaticProvider"), QString("mytypes"), 1, 0); + QQmlType type = QQmlMetaType::qmlType(QString("StaticProvider"), QString("mytypes"), + QTypeRevision::fromVersion(1, 0)); QVERIFY(type.isValid()); QVERIFY(!type.isInterface()); QVERIFY(type.isSingleton()); @@ -496,7 +508,8 @@ void tst_qqmlmetatype::unregisterCustomSingletonType() { QQmlEngine engine; staticProviderId = qmlRegisterSingletonType<StaticProvider2>("mytypes", 1, 0, "StaticProvider", createStaticProvider2); - QQmlType type = QQmlMetaType::qmlType(QString("StaticProvider"), QString("mytypes"), 1, 0); + QQmlType type = QQmlMetaType::qmlType(QString("StaticProvider"), QString("mytypes"), + QTypeRevision::fromVersion(1, 0)); QVERIFY(type.isValid()); QVERIFY(!type.isInterface()); QVERIFY(type.isSingleton()); @@ -512,7 +525,8 @@ void tst_qqmlmetatype::unregisterCustomSingletonType() { QQmlEngine engine; staticProviderId = qmlRegisterSingletonType<StaticProvider1>("mytypes", 1, 0, "StaticProvider", createStaticProvider1); - QQmlType type = QQmlMetaType::qmlType(QString("StaticProvider"), QString("mytypes"), 1, 0); + QQmlType type = QQmlMetaType::qmlType(QString("StaticProvider"), QString("mytypes"), + QTypeRevision::fromVersion(1, 0)); QVERIFY(type.isValid()); QVERIFY(!type.isInterface()); QVERIFY(type.isSingleton()); @@ -548,7 +562,8 @@ void tst_qqmlmetatype::unregisterAttachedProperties() QQmlComponent c(&e); c.setData("import QtQuick 2.2\n Item { }", dummy); - const QQmlType attachedType = QQmlMetaType::qmlType("QtQuick/KeyNavigation", 2, 2); + const QQmlType attachedType = QQmlMetaType::qmlType("QtQuick/KeyNavigation", + QTypeRevision::fromVersion(2, 2)); QCOMPARE(attachedType.attachedPropertiesType(QQmlEnginePrivate::get(&e)), attachedType.metaObject()); @@ -568,7 +583,8 @@ void tst_qqmlmetatype::unregisterAttachedProperties() "import QtQuick 2.2 \n" "Item { KeyNavigation.up: null }", dummy); - const QQmlType attachedType = QQmlMetaType::qmlType("QtQuick/KeyNavigation", 2, 2); + const QQmlType attachedType = QQmlMetaType::qmlType("QtQuick/KeyNavigation", + QTypeRevision::fromVersion(2, 2)); QCOMPARE(attachedType.attachedPropertiesType(QQmlEnginePrivate::get(&e)), attachedType.metaObject()); diff --git a/tests/auto/qml/qqmlparser/data/annotations/View1.qml b/tests/auto/qml/qqmlparser/data/annotations/View1.qml new file mode 100644 index 0000000000..2d3d7d2cfd --- /dev/null +++ b/tests/auto/qml/qqmlparser/data/annotations/View1.qml @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Charts module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** 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$ +** +****************************************************************************/ + +//![2] +import QtQuick 2.0 +//![2] +import QtCharts 2.0 + +@Pippo{ atg1:3 } +@Annotation2{} +Item { + @Annotate{} + anchors.fill: parent + @AnnotateMore{ + property int x: 5 + } + @AnnotateALot{} + property variant othersSlice: 0 + + //![1] + ChartView { + id: chart + title: "Top-5 car brand shares in Finland" + anchors.fill: parent + legend.alignment: Qt.AlignBottom + antialiasing: true + +@ExtraAnnotation{ + signal pippo +} + PieSeries { + id: pieSeries + PieSlice { label: "Volkswagen"; value: 13.5 } + PieSlice { label: "Toyota"; value: 10.9 } + PieSlice { label: "Ford"; value: 8.6 } + PieSlice { label: "Skoda"; value: 8.2 } + PieSlice { label: "Volvo"; value: 6.8 } + } + } + +@SuperComplete{ +binding: late +} + Component.onCompleted: { + // You can also manipulate slices dynamically, like append a slice or set a slice exploded + othersSlice = pieSeries.append("Others", 52.0); + pieSeries.find("Volkswagen").exploded = true; + } + //![1] +} diff --git a/tests/auto/qml/qqmlparser/data/noannotations/View1.qml b/tests/auto/qml/qqmlparser/data/noannotations/View1.qml new file mode 100644 index 0000000000..945bce3a44 --- /dev/null +++ b/tests/auto/qml/qqmlparser/data/noannotations/View1.qml @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Charts module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** 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$ +** +****************************************************************************/ + +//![2] +import QtQuick 2.0 +//![2] +import QtCharts 2.0 + + + +Item { + + anchors.fill: parent + + + + + property variant othersSlice: 0 + + //![1] + ChartView { + id: chart + title: "Top-5 car brand shares in Finland" + anchors.fill: parent + legend.alignment: Qt.AlignBottom + antialiasing: true + + + + + PieSeries { + id: pieSeries + PieSlice { label: "Volkswagen"; value: 13.5 } + PieSlice { label: "Toyota"; value: 10.9 } + PieSlice { label: "Ford"; value: 8.6 } + PieSlice { label: "Skoda"; value: 8.2 } + PieSlice { label: "Volvo"; value: 6.8 } + } + } + + + + + Component.onCompleted: { + // You can also manipulate slices dynamically, like append a slice or set a slice exploded + othersSlice = pieSeries.append("Others", 52.0); + pieSeries.find("Volkswagen").exploded = true; + } + //![1] +} diff --git a/tests/auto/qml/qqmlparser/qqmlparser.pro b/tests/auto/qml/qqmlparser/qqmlparser.pro index d8e4b0dd06..7f117b3157 100644 --- a/tests/auto/qml/qqmlparser/qqmlparser.pro +++ b/tests/auto/qml/qqmlparser/qqmlparser.pro @@ -11,3 +11,4 @@ cross_compile: DEFINES += QTEST_CROSS_COMPILED TESTDATA = data/* include (../../shared/util.pri) +include (../../shared/astdump.pri) diff --git a/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp b/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp index 76b56bd303..8483bd1f95 100644 --- a/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp +++ b/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp @@ -33,10 +33,12 @@ #include <private/qqmljsast_p.h> #include "../../shared/util.h" +#include "../../shared/qqmljsastdumper.h" #include <qtest.h> #include <QDir> #include <QDebug> +#include <QRegularExpression> #include <cstdlib> class tst_qqmlparser : public QQmlDataTest @@ -65,6 +67,10 @@ private slots: void semicolonPartOfExpressionStatement(); void typeAssertion_data(); void typeAssertion(); + void annotations_data(); + void annotations(); + void invalidImportVersion_data(); + void invalidImportVersion(); private: QStringList excludedDirs; @@ -521,6 +527,108 @@ void tst_qqmlparser::typeAssertion() QVERIFY(parser.parse()); } +void tst_qqmlparser::annotations_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<QString>("refFile"); + + QString tests = dataDirectory() + "/annotations/"; + QString compare = dataDirectory() + "/noannotations/"; + + QStringList files; + files << findFiles(QDir(tests)); + + QStringList refFiles; + refFiles << findFiles(QDir(compare)); + + for (const QString &file: qAsConst(files)) { + auto fileNameStart = file.lastIndexOf(QDir::separator()); + QStringRef fileName(&file, fileNameStart, file.length()-fileNameStart); + auto ref=std::find_if(refFiles.constBegin(),refFiles.constEnd(), [fileName](const QString &s){ return s.endsWith(fileName); }); + if (ref != refFiles.constEnd()) + QTest::newRow(qPrintable(file)) << file << *ref; + else + QTest::newRow(qPrintable(file)) << file << QString(); + } +} + +void tst_qqmlparser::annotations() +{ + using namespace QQmlJS; + + QFETCH(QString, file); + QFETCH(QString, refFile); + + QString code; + QString refCode; + + QFile f(file); + if (f.open(QFile::ReadOnly)) + code = QString::fromUtf8(f.readAll()); + QFile refF(refFile); + if (!refFile.isEmpty() && refF.open(QFile::ReadOnly)) + refCode = QString::fromUtf8(refF.readAll()); + + const bool qmlMode = true; + + Engine engine; + Lexer lexer(&engine); + lexer.setCode(code, 1, qmlMode); + Parser parser(&engine); + QVERIFY(parser.parse()); + + if (!refCode.isEmpty()) { + Engine engine2; + Lexer lexer2(&engine2); + lexer2.setCode(refCode, 1, qmlMode); + Parser parser2(&engine2); + QVERIFY(parser2.parse()); + + QCOMPARE(AstDumper::diff(parser.ast(), parser2.rootNode(), 3, DumperOptions::NoAnnotations | DumperOptions::NoLocations), QString()); + } +} + +void tst_qqmlparser::invalidImportVersion_data() +{ + QTest::addColumn<QString>("expression"); + + const QStringList segments = { + "0", "255", "500", "3030303030303030303030303" + }; + + for (const QString &major : segments) { + if (major != "0") { + QTest::addRow("%s", qPrintable(major)) + << QString::fromLatin1("import Foo %1").arg(major); + } + + for (const QString &minor : segments) { + if (major == "0" && minor == "0") + continue; + + QTest::addRow("%s.%s", qPrintable(major), qPrintable(minor)) + << QString::fromLatin1("import Foo %1.%2").arg(major).arg(minor); + } + } + + +} + +void tst_qqmlparser::invalidImportVersion() +{ + QFETCH(QString, expression); + + QQmlJS::Engine engine; + QQmlJS::Lexer lexer(&engine); + lexer.setCode(expression, 1); + QQmlJS::Parser parser(&engine); + QVERIFY(!parser.parse()); + + QRegularExpression regexp( + "^Invalid (major )?version. Version numbers must be >= 0 and < 255\\.$"); + QVERIFY(regexp.match(parser.errorMessage()).hasMatch()); +} + QTEST_MAIN(tst_qqmlparser) #include "tst_qqmlparser.moc" diff --git a/tests/auto/qml/qqmlproperty/data/interfaceBinding2.qml b/tests/auto/qml/qqmlproperty/data/interfaceBinding2.qml new file mode 100644 index 0000000000..e7c5dc7344 --- /dev/null +++ b/tests/auto/qml/qqmlproperty/data/interfaceBinding2.qml @@ -0,0 +1,27 @@ +import QtQuick 2.12 +import io.qt.bugreports 2.0 +Item { + InterfaceConsumer2 { + objectName: "a1" + i: A2 { + property int i: 42 + } + } + + InterfaceConsumer2 { + objectName: "a2" + property A2 a: A2 { + property int i: 43 + } + i: a + } + + InterfaceConsumer2 { + objectName: "a3" + property A2 a: A2 { + id : aa + property int i: 44 + } + i: aa + } +} diff --git a/tests/auto/qml/qqmlproperty/interfaces.h b/tests/auto/qml/qqmlproperty/interfaces.h new file mode 100644 index 0000000000..2c06c5f594 --- /dev/null +++ b/tests/auto/qml/qqmlproperty/interfaces.h @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** 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 INTERFACES_H +#define INTERFACES_H + +#include <QtQml/qqml.h> + +struct Interface { +}; + +QT_BEGIN_NAMESPACE +#define MyInterface_iid "io.qt.bugreports.Interface" +Q_DECLARE_INTERFACE(Interface, MyInterface_iid); +QT_END_NAMESPACE + +class A : public QObject, Interface { + Q_OBJECT + Q_INTERFACES(Interface) +}; + +class B : public QObject, Interface { + Q_OBJECT + Q_INTERFACES(Interface) +}; + +class C : public QObject { + Q_OBJECT +}; + +struct Interface2 +{ + Q_GADGET + QML_INTERFACE +}; + +QT_BEGIN_NAMESPACE +#define MyInterface2_iid "io.qt.bugreports.Interface2" +Q_DECLARE_INTERFACE(Interface2, MyInterface2_iid); +QT_END_NAMESPACE + +class A2 : public QObject, Interface2 { + Q_OBJECT + QML_ELEMENT + Q_INTERFACES(Interface2) +}; + +class B2 : public QObject, Interface2 { + Q_OBJECT + QML_ELEMENT + Q_INTERFACES(Interface2) +}; + +class C2 : public QObject { + Q_OBJECT + QML_ELEMENT +}; + +class InterfaceConsumer : public QObject { + Q_OBJECT + Q_PROPERTY(Interface *i READ interface WRITE setInterface NOTIFY interfaceChanged) + Q_PROPERTY(int testValue READ testValue NOTIFY testValueChanged) + +public: + + Interface* interface() const + { + return m_interface; + } + void setInterface(Interface* interface) + { + QObject* object = reinterpret_cast<QObject*>(interface); + m_testValue = object->property("i").toInt(); + emit testValueChanged(); + if (m_interface == interface) + return; + + m_interface = interface; + emit interfaceChanged(); + } + + int testValue() { + return m_testValue; + } + +signals: + void interfaceChanged(); + void testValueChanged(); + +private: + Interface* m_interface = nullptr; + int m_testValue = 0; +}; + + +class InterfaceConsumer2 : public QObject +{ + Q_OBJECT + + Q_PROPERTY(Interface2 *i READ interface WRITE setInterface NOTIFY interfaceChanged) + Q_PROPERTY(int testValue READ testValue NOTIFY testValueChanged) + + QML_ELEMENT + +public: + + Interface2* interface() const + { + return m_interface; + } + void setInterface(Interface2* interface2) + { + QObject* object = reinterpret_cast<QObject*>(interface2); + m_testValue = object->property("i").toInt(); + emit testValueChanged(); + if (m_interface == interface2) + return; + + m_interface = interface2; + emit interfaceChanged(); + } + + int testValue() { + return m_testValue; + } + +signals: + void interfaceChanged(); + void testValueChanged(); + +private: + Interface2 *m_interface = nullptr; + int m_testValue = 0; +}; + +#endif // INTERFACES_H diff --git a/tests/auto/qml/qqmlproperty/qqmlproperty.pro b/tests/auto/qml/qqmlproperty/qqmlproperty.pro index b1bcf1f17d..4d42975369 100644 --- a/tests/auto/qml/qqmlproperty/qqmlproperty.pro +++ b/tests/auto/qml/qqmlproperty/qqmlproperty.pro @@ -1,7 +1,10 @@ -CONFIG += testcase +CONFIG += testcase qmltypes TARGET = tst_qqmlproperty macx:CONFIG -= app_bundle +QML_IMPORT_NAME = io.qt.bugreports +QML_IMPORT_VERSION = 2.0 + SOURCES += tst_qqmlproperty.cpp include (../../shared/util.pri) @@ -9,3 +12,6 @@ include (../../shared/util.pri) TESTDATA = data/* QT += core-private gui-private qml-private testlib + +HEADERS += \ + interfaces.h diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp index f039ccc110..8a96fc52c5 100644 --- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp +++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp @@ -25,6 +25,8 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + +#include "interfaces.h" #include <qtest.h> #include <QtQml/qqmlengine.h> #include <QtQml/qqmlcomponent.h> @@ -160,6 +162,8 @@ private slots: void bindingToAlias(); void nestedQQmlPropertyMap(); + + void underscorePropertyChangeHandler(); private: QQmlEngine engine; }; @@ -1224,10 +1228,10 @@ void tst_qqmlproperty::read() } { QQmlComponent component(&engine, testFileUrl("readSynthesizedObject.qml")); - QObject *object = component.create(); + QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); - QQmlProperty p(object, "test", &engine); + QQmlProperty p(object.data(), "test", &engine); QCOMPARE(p.propertyTypeCategory(), QQmlProperty::Object); QVERIFY(p.propertyType() != QMetaType::QObjectStar); @@ -1239,10 +1243,10 @@ void tst_qqmlproperty::read() } { // static QQmlComponent component(&engine, testFileUrl("readSynthesizedObject.qml")); - QObject *object = component.create(); + QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); - QVariant v = QQmlProperty::read(object, "test", &engine); + QVariant v = QQmlProperty::read(object.data(), "test", &engine); QCOMPARE(v.userType(), int(QMetaType::QObjectStar)); QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10); QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19); @@ -1252,41 +1256,38 @@ void tst_qqmlproperty::read() { QQmlComponent component(&engine); component.setData("import Test 1.0\nMyContainer { }", QUrl()); - QObject *object = component.create(); + QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); - QQmlProperty p(object, "MyContainer.foo", qmlContext(object)); + QQmlProperty p(object.data(), "MyContainer.foo", qmlContext(object.data())); QCOMPARE(p.read(), QVariant(13)); - delete object; } { QQmlComponent component(&engine); component.setData("import Test 1.0\nMyContainer { MyContainer.foo: 10 }", QUrl()); - QObject *object = component.create(); + QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); - QQmlProperty p(object, "MyContainer.foo", qmlContext(object)); + QQmlProperty p(object.data(), "MyContainer.foo", qmlContext(object.data())); QCOMPARE(p.read(), QVariant(10)); - delete object; } { QQmlComponent component(&engine); component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl()); - QObject *object = component.create(); + QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); - QQmlProperty p(object, "Foo.MyContainer.foo", qmlContext(object)); + QQmlProperty p(object.data(), "Foo.MyContainer.foo", qmlContext(object.data())); QCOMPARE(p.read(), QVariant(10)); - delete object; } { // static QQmlComponent component(&engine); component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl()); - QObject *object = component.create(); + QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); - QCOMPARE(QQmlProperty::read(object, "Foo.MyContainer.foo", qmlContext(object)), QVariant(10)); - delete object; + QCOMPARE(QQmlProperty::read(object.data(), "Foo.MyContainer.foo", + qmlContext(object.data())), QVariant(10)); } } @@ -1447,11 +1448,12 @@ void tst_qqmlproperty::write() { // QChar -> QString QQmlComponent component(&engine); component.setData("import Test 1.0\nPropertyObject { stringProperty: constQChar }", QUrl()); - PropertyObject *obj = qobject_cast<PropertyObject*>(component.create()); - QVERIFY(obj != nullptr); - if (obj) { - QQmlProperty stringProperty(obj, "stringProperty"); - QCOMPARE(stringProperty.read(), QVariant(QString(obj->constQChar()))); + QScopedPointer<QObject> object(component.create()); + PropertyObject *propertyObject = qobject_cast<PropertyObject*>(object.data()); + QVERIFY(propertyObject != nullptr); + if (propertyObject) { + QQmlProperty stringProperty(propertyObject, "stringProperty"); + QCOMPARE(stringProperty.read(), QVariant(QString(propertyObject->constQChar()))); } } @@ -1628,29 +1630,32 @@ void tst_qqmlproperty::writeObjectToList() { QQmlComponent containerComponent(&engine); containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl()); - MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create()); + QScopedPointer<QObject> object(containerComponent.create()); + MyContainer *container = qobject_cast<MyContainer*>(object.data()); QVERIFY(container != nullptr); QQmlListReference list(container, "children"); QCOMPARE(list.count(), 1); - MyQmlObject *object = new MyQmlObject; + QScopedPointer<MyQmlObject> childObject(new MyQmlObject); QQmlProperty prop(container, "children"); - prop.write(QVariant::fromValue(object)); + prop.write(QVariant::fromValue(childObject.data())); QCOMPARE(list.count(), 1); - QCOMPARE(list.at(0), qobject_cast<QObject*>(object)); + QCOMPARE(list.at(0), qobject_cast<QObject*>(childObject.data())); } void tst_qqmlproperty::writeListToList() { QQmlComponent containerComponent(&engine); containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl()); - MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create()); + QScopedPointer<QObject> object(containerComponent.create()); + MyContainer *container = qobject_cast<MyContainer*>(object.data()); QVERIFY(container != nullptr); QQmlListReference list(container, "children"); QCOMPARE(list.count(), 1); QList<QObject*> objList; - objList << new MyQmlObject() << new MyQmlObject() << new MyQmlObject() << new MyQmlObject(); + objList << new MyQmlObject(this) << new MyQmlObject(this) + << new MyQmlObject(this) << new MyQmlObject(this); QQmlProperty prop(container, "children"); prop.write(QVariant::fromValue(objList)); QCOMPARE(list.count(), 4); @@ -1828,10 +1833,11 @@ void tst_qqmlproperty::crashOnValueProperty() QQmlComponent component(engine); component.setData("import Test 1.0\nPropertyObject { wrectProperty.x: 10 }", QUrl()); - PropertyObject *obj = qobject_cast<PropertyObject*>(component.create()); - QVERIFY(obj != nullptr); + QScopedPointer<QObject> object(component.create()); + PropertyObject *propertyObject = qobject_cast<PropertyObject*>(object.data()); + QVERIFY(propertyObject != nullptr); - QQmlProperty p(obj, "wrectProperty.x", qmlContext(obj)); + QQmlProperty p(propertyObject, "wrectProperty.x", qmlContext(propertyObject)); QCOMPARE(p.name(), QString("wrectProperty.x")); QCOMPARE(p.read(), QVariant(10)); @@ -2088,74 +2094,20 @@ void tst_qqmlproperty::nullPropertyBinding() QMetaObject::invokeMethod(root.get(), "tog"); } -struct Interface { -}; - -QT_BEGIN_NAMESPACE -#define MyInterface_iid "io.qt.bugreports.Interface" -Q_DECLARE_INTERFACE(Interface, MyInterface_iid); -QT_END_NAMESPACE - -class A : public QObject, Interface { - Q_OBJECT - Q_INTERFACES(Interface) -}; - -class B : public QObject, Interface { - Q_OBJECT - Q_INTERFACES(Interface) -}; - -class C : public QObject { - Q_OBJECT -}; - -class InterfaceConsumer : public QObject { - Q_OBJECT - Q_PROPERTY(Interface* i READ interface WRITE setInterface NOTIFY interfaceChanged) - Q_PROPERTY(int testValue READ testValue NOTIFY testValueChanged) - - -public: - - Interface* interface() const - { - return m_interface; - } - void setInterface(Interface* interface) - { - QObject* object = reinterpret_cast<QObject*>(interface); - m_testValue = object->property("i").toInt(); - emit testValueChanged(); - if (m_interface == interface) - return; - - m_interface = interface; - emit interfaceChanged(); - } - - int testValue() { - return m_testValue; - } - -signals: - void interfaceChanged(); - void testValueChanged(); - -private: - Interface* m_interface = nullptr; - int m_testValue = 0; -}; void tst_qqmlproperty::interfaceBinding() { - - qmlRegisterInterface<Interface>("Interface"); - qmlRegisterType<A>("io.qt.bugreports", 1, 0, "A"); - qmlRegisterType<B>("io.qt.bugreports", 1, 0, "B"); - qmlRegisterType<C>("io.qt.bugreports", 1, 0, "C"); - qmlRegisterType<InterfaceConsumer>("io.qt.bugreports", 1, 0, "InterfaceConsumer"); - - const QUrl url = testFileUrl("interfaceBinding.qml"); + qmlRegisterInterface<Interface>("Interface"); + qmlRegisterType<A>("io.qt.bugreports", 1, 0, "A"); + qmlRegisterType<B>("io.qt.bugreports", 1, 0, "B"); + qmlRegisterType<C>("io.qt.bugreports", 1, 0, "C"); + qmlRegisterType<InterfaceConsumer>("io.qt.bugreports", 1, 0, "InterfaceConsumer"); + + const QVector<QUrl> urls = { + testFileUrl("interfaceBinding.qml"), + testFileUrl("interfaceBinding2.qml") + }; + + for (const QUrl &url : urls) { QQmlEngine engine; QQmlComponent component(&engine, url); QScopedPointer<QObject> root(component.create()); @@ -2163,6 +2115,7 @@ void tst_qqmlproperty::interfaceBinding() QCOMPARE(root->findChild<QObject*>("a1")->property("testValue").toInt(), 42); QCOMPARE(root->findChild<QObject*>("a2")->property("testValue").toInt(), 43); QCOMPARE(root->findChild<QObject*>("a3")->property("testValue").toInt(), 44); + } } void tst_qqmlproperty::floatToStringPrecision_data() @@ -2239,6 +2192,24 @@ void tst_qqmlproperty::nestedQQmlPropertyMap() QCOMPARE(success.read().toString(), QLatin1String("success")); } +void tst_qqmlproperty::underscorePropertyChangeHandler() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData(R"( + import QtQuick 2.12 + + Item { + property int __withUnderScore + } + )", QUrl::fromLocalFile(".")); + QScopedPointer<QObject> root { component.create() }; + QVERIFY(root); + QQmlProperty changeHandler(root.get(), "on__WithUnderScoreChanged"); + QVERIFY(changeHandler.isValid()); + QVERIFY(changeHandler.isSignalProperty()); +} + QTEST_MAIN(tst_qqmlproperty) #include "tst_qqmlproperty.moc" diff --git a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp index c79fdc57b4..2e040eec18 100644 --- a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp +++ b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp @@ -167,8 +167,9 @@ void tst_qqmlpropertycache::revisionedProperties() QQmlRefPointer<QQmlPropertyCache> cacheWithoutVersion(new QQmlPropertyCache(metaObject), QQmlRefPointer<QQmlPropertyCache>::Adopt); - QQmlRefPointer<QQmlPropertyCache> cacheWithVersion(new QQmlPropertyCache(metaObject, 1), - QQmlRefPointer<QQmlPropertyCache>::Adopt); + QQmlRefPointer<QQmlPropertyCache> cacheWithVersion( + new QQmlPropertyCache(metaObject, QTypeRevision::fromMinorVersion(1)), + QQmlRefPointer<QQmlPropertyCache>::Adopt); QQmlPropertyData *data; QVERIFY((data = cacheProperty(cacheWithoutVersion, "propertyE"))); diff --git a/tests/auto/qml/qqmlqt/data/formatting.qml b/tests/auto/qml/qqmlqt/data/formatting.qml index f2d1e1b5c8..14af9ba88b 100644 --- a/tests/auto/qml/qqmlqt/data/formatting.qml +++ b/tests/auto/qml/qqmlqt/data/formatting.qml @@ -1,4 +1,4 @@ -import QtQuick 2.0 +import QtQuick 2.15 QtObject { property date dateFromString: "2008-12-24" @@ -8,7 +8,7 @@ QtObject { var v = eval(prop) return [ Qt.formatDate(v), - Qt.formatDate(v, Qt.DefaultLocaleLongDate), + Qt.formatDate(v, Qt.locale(), Locale.LongFormat), Qt.formatDate(v, "ddd MMMM d yy") ] } @@ -17,7 +17,7 @@ QtObject { var v = eval(prop) return [ Qt.formatTime(v), - Qt.formatTime(v, Qt.DefaultLocaleLongDate), + Qt.formatTime(v, Qt.locale(), Locale.LongFormat), Qt.formatTime(v, "H:m:s a"), Qt.formatTime(v, "hh:mm:ss.zzz") ] @@ -27,7 +27,7 @@ QtObject { var v = eval(prop) return [ Qt.formatDateTime(v), - Qt.formatDateTime(v, Qt.DefaultLocaleLongDate), + Qt.formatDateTime(v, Qt.locale(), Locale.LongFormat), Qt.formatDateTime(v, "M/d/yy H:m:s a") ] } diff --git a/tests/auto/qml/qqmlqt/data/formattingLocale.qml b/tests/auto/qml/qqmlqt/data/formattingLocale.qml new file mode 100644 index 0000000000..9da349b101 --- /dev/null +++ b/tests/auto/qml/qqmlqt/data/formattingLocale.qml @@ -0,0 +1,12 @@ +import QtQml 2.15 + +QtObject { + required property var myDateTime + required property var myDate + property var myTime + + property string dateTimeString: Qt.formatDateTime(myDateTime, Qt.locale("de_DE"), Locale.NarrowFormat) + property string dateString: Qt.formatDate(myDate, Qt.locale("de_DE")) + + function invalidUsage() { Qt.formatTime(myTime, null, "hello") } +} diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp index 8fa18c9860..60ee2a4d1c 100644 --- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp +++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp @@ -91,6 +91,7 @@ private slots: void dateTimeFormatting_data(); void dateTimeFormattingVariants(); void dateTimeFormattingVariants_data(); + void dateTimeFormattingWithLocale(); void isQtObject(); void btoa(); void atob(); @@ -738,12 +739,12 @@ void tst_qqmlqt::dateTimeFormatting() QQmlComponent component(&eng, testFileUrl("formatting.qml")); QStringList warnings; - warnings << component.url().toString() + ":37: Error: Qt.formatDate(): Invalid date format" - << component.url().toString() + ":36: Error: Qt.formatDate(): Invalid arguments" - << component.url().toString() + ":40: Error: Qt.formatTime(): Invalid time format" - << component.url().toString() + ":39: Error: Qt.formatTime(): Invalid arguments" - << component.url().toString() + ":43: Error: Qt.formatDateTime(): Invalid datetime format" - << component.url().toString() + ":42: Error: Qt.formatDateTime(): Invalid arguments"; + warnings << component.url().toString() + ":37: Error: Qt.formatDate(): Bad second argument (must be either string, number or locale)" + << component.url().toString() + ":36: Error: Qt.formatDate(): Missing argument" + << component.url().toString() + ":40: Error: Qt.formatTime(): Bad second argument (must be either string, number or locale)" + << component.url().toString() + ":39: Error: Qt.formatTime(): Missing argument" + << component.url().toString() + ":43: Error: Qt.formatDateTime(): Bad second argument (must be either string, number or locale)" + << component.url().toString() + ":42: Error: Qt.formatDateTime(): Missing argument"; foreach (const QString &warning, warnings) QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); @@ -784,23 +785,23 @@ void tst_qqmlqt::dateTimeFormatting_data() QTest::newRow("formatDate") << "formatDate" << (QStringList() << "dateFromString" << "jsdate" << "qdate" << "qdatetime") - << (QStringList() << date.toString(Qt::DefaultLocaleShortDate) - << date.toString(Qt::DefaultLocaleLongDate) + << (QStringList() << QLocale().toString(date, QLocale::ShortFormat) + << QLocale().toString(date, QLocale::LongFormat) << date.toString("ddd MMMM d yy")); QTest::newRow("formatTime") << "formatTime" << (QStringList() << "jsdate" << "qtime" << "qdatetime") - << (QStringList() << time.toString(Qt::DefaultLocaleShortDate) - << time.toString(Qt::DefaultLocaleLongDate) + << (QStringList() << QLocale().toString(time, QLocale::ShortFormat) + << QLocale().toString(time, QLocale::LongFormat) << time.toString("H:m:s a") << time.toString("hh:mm:ss.zzz")); QTest::newRow("formatDateTime") << "formatDateTime" << (QStringList() << "jsdate" << "qdatetime") - << (QStringList() << dateTime.toString(Qt::DefaultLocaleShortDate) - << dateTime.toString(Qt::DefaultLocaleLongDate) + << (QStringList() << QLocale().toString(dateTime, QLocale::ShortFormat) + << QLocale().toString(dateTime, QLocale::LongFormat) << dateTime.toString("M/d/yy H:m:s a")); } @@ -814,12 +815,12 @@ void tst_qqmlqt::dateTimeFormattingVariants() QQmlComponent component(&eng, testFileUrl("formatting.qml")); QStringList warnings; - warnings << component.url().toString() + ":37: Error: Qt.formatDate(): Invalid date format" - << component.url().toString() + ":36: Error: Qt.formatDate(): Invalid arguments" - << component.url().toString() + ":40: Error: Qt.formatTime(): Invalid time format" - << component.url().toString() + ":39: Error: Qt.formatTime(): Invalid arguments" - << component.url().toString() + ":43: Error: Qt.formatDateTime(): Invalid datetime format" - << component.url().toString() + ":42: Error: Qt.formatDateTime(): Invalid arguments"; + warnings << component.url().toString() + ":37: Error: Qt.formatDate(): Bad second argument (must be either string, number or locale)" + << component.url().toString() + ":36: Error: Qt.formatDate(): Missing argument" + << component.url().toString() + ":40: Error: Qt.formatTime(): Bad second argument (must be either string, number or locale)" + << component.url().toString() + ":39: Error: Qt.formatTime(): Missing argument" + << component.url().toString() + ":43: Error: Qt.formatDateTime(): Bad second argument (must be either string, number or locale)" + << component.url().toString() + ":42: Error: Qt.formatDateTime(): Missing argument"; foreach (const QString &warning, warnings) QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); @@ -848,38 +849,145 @@ void tst_qqmlqt::dateTimeFormattingVariants_data() QTime time(11, 16, 39, 755); temporary = QDateTime(QDate(1970,1,1), time); - QTest::newRow("formatTime, qtime") << "formatTime" << QVariant::fromValue(time) << (QStringList() << temporary.time().toString(Qt::DefaultLocaleShortDate) << temporary.time().toString(Qt::DefaultLocaleLongDate) << temporary.time().toString("H:m:s a") << temporary.time().toString("hh:mm:ss.zzz")); + QTest::newRow("formatTime, qtime") + << "formatTime" << QVariant::fromValue(time) + << (QStringList() + << QLocale().toString(temporary.time(), QLocale::ShortFormat) + << QLocale().toString(temporary.time(), QLocale::LongFormat) + << temporary.time().toString("H:m:s a") + << temporary.time().toString("hh:mm:ss.zzz")); QDate date(2011,5,31); // V4 reads the date in UTC but DateObject::toQDateTime() gives it back in local time: temporary = QDateTime(date, QTime(0, 0, 0), Qt::UTC).toLocalTime(); - QTest::newRow("formatDate, qdate") << "formatDate" << QVariant::fromValue(date) << (QStringList() << temporary.date().toString(Qt::DefaultLocaleShortDate) << temporary.date().toString(Qt::DefaultLocaleLongDate) << temporary.date().toString("ddd MMMM d yy")); - QTest::newRow("formatDateTime, qdate") << "formatDateTime" << QVariant::fromValue(date) << (QStringList() << temporary.toString(Qt::DefaultLocaleShortDate) << temporary.toString(Qt::DefaultLocaleLongDate) << temporary.toString("M/d/yy H:m:s a")); - QTest::newRow("formatTime, qdate") << "formatTime" << QVariant::fromValue(date) << (QStringList() << temporary.time().toString(Qt::DefaultLocaleShortDate) << temporary.time().toString(Qt::DefaultLocaleLongDate) << temporary.time().toString("H:m:s a") << temporary.time().toString("hh:mm:ss.zzz")); + QTest::newRow("formatDate, qdate") + << "formatDate" << QVariant::fromValue(date) + << (QStringList() + << QLocale().toString(temporary.date(), QLocale::ShortFormat) + << QLocale().toString(temporary.date(), QLocale::LongFormat) + << temporary.date().toString("ddd MMMM d yy")); + QTest::newRow("formatDateTime, qdate") + << "formatDateTime" << QVariant::fromValue(date) + << (QStringList() + << QLocale().toString(temporary, QLocale::ShortFormat) + << QLocale().toString(temporary, QLocale::LongFormat) + << temporary.toString("M/d/yy H:m:s a")); + QTest::newRow("formatTime, qdate") + << "formatTime" << QVariant::fromValue(date) + << (QStringList() + << QLocale().toString(temporary.time(), QLocale::ShortFormat) + << QLocale().toString(temporary.time(), QLocale::LongFormat) + << temporary + .time().toString("H:m:s a") << temporary.time().toString("hh:mm:ss.zzz")); QDateTime dateTime(date, time); temporary = dateTime; - QTest::newRow("formatDate, qdatetime") << "formatDate" << QVariant::fromValue(dateTime) << (QStringList() << temporary.date().toString(Qt::DefaultLocaleShortDate) << temporary.date().toString(Qt::DefaultLocaleLongDate) << temporary.date().toString("ddd MMMM d yy")); - QTest::newRow("formatDateTime, qdatetime") << "formatDateTime" << QVariant::fromValue(dateTime) << (QStringList() << temporary.toString(Qt::DefaultLocaleShortDate) << temporary.toString(Qt::DefaultLocaleLongDate) << temporary.toString("M/d/yy H:m:s a")); - QTest::newRow("formatTime, qdatetime") << "formatTime" << QVariant::fromValue(dateTime) << (QStringList() << temporary.time().toString(Qt::DefaultLocaleShortDate) << temporary.time().toString(Qt::DefaultLocaleLongDate) << temporary.time().toString("H:m:s a") << temporary.time().toString("hh:mm:ss.zzz")); + QTest::newRow("formatDate, qdatetime") + << "formatDate" << QVariant::fromValue(dateTime) + << (QStringList() + << QLocale().toString(temporary.date(), QLocale::ShortFormat) + << QLocale().toString(temporary.date(), QLocale::LongFormat) + << temporary.date().toString("ddd MMMM d yy")); + QTest::newRow("formatDateTime, qdatetime") + << "formatDateTime" << QVariant::fromValue(dateTime) + << (QStringList() + << QLocale().toString(temporary, QLocale::ShortFormat) + << QLocale().toString(temporary, QLocale::LongFormat) + << temporary.toString("M/d/yy H:m:s a")); + QTest::newRow("formatTime, qdatetime") + << "formatTime" << QVariant::fromValue(dateTime) + << (QStringList() + << QLocale().toString(temporary.time(), QLocale::ShortFormat) + << QLocale().toString(temporary.time(), QLocale::LongFormat) + << temporary.time().toString("H:m:s a") + << temporary.time().toString("hh:mm:ss.zzz")); QString string(QLatin1String("2011/05/31 11:16:39.755")); temporary = QDateTime::fromString(string, "yyyy/MM/dd HH:mm:ss.zzz"); - QTest::newRow("formatDate, qstring") << "formatDate" << QVariant::fromValue(string) << (QStringList() << temporary.date().toString(Qt::DefaultLocaleShortDate) << temporary.date().toString(Qt::DefaultLocaleLongDate) << temporary.date().toString("ddd MMMM d yy")); - QTest::newRow("formatDateTime, qstring") << "formatDateTime" << QVariant::fromValue(string) << (QStringList() << temporary.toString(Qt::DefaultLocaleShortDate) << temporary.toString(Qt::DefaultLocaleLongDate) << temporary.toString("M/d/yy H:m:s a")); - QTest::newRow("formatTime, qstring") << "formatTime" << QVariant::fromValue(string) << (QStringList() << temporary.time().toString(Qt::DefaultLocaleShortDate) << temporary.time().toString(Qt::DefaultLocaleLongDate) << temporary.time().toString("H:m:s a") << temporary.time().toString("hh:mm:ss.zzz")); + QTest::newRow("formatDate, qstring") + << "formatDate" << QVariant::fromValue(string) + << (QStringList() + << QLocale().toString(temporary.date(), QLocale::ShortFormat) + << QLocale().toString(temporary.date(), QLocale::LongFormat) + << temporary.date().toString("ddd MMMM d yy")); + QTest::newRow("formatDateTime, qstring") + << "formatDateTime" << QVariant::fromValue(string) + << (QStringList() + << QLocale().toString(temporary, QLocale::ShortFormat) + << QLocale().toString(temporary, QLocale::LongFormat) + << temporary.toString("M/d/yy H:m:s a")); + QTest::newRow("formatTime, qstring") + << "formatTime" << QVariant::fromValue(string) + << (QStringList() + << QLocale().toString(temporary.time(), QLocale::ShortFormat) + << QLocale().toString(temporary.time(), QLocale::LongFormat) + << temporary.time().toString("H:m:s a") + << temporary.time().toString("hh:mm:ss.zzz")); QColor color(Qt::red); temporary = QVariant::fromValue(color).toDateTime(); - QTest::newRow("formatDate, qcolor") << "formatDate" << QVariant::fromValue(color) << (QStringList() << temporary.date().toString(Qt::DefaultLocaleShortDate) << temporary.date().toString(Qt::DefaultLocaleLongDate) << temporary.date().toString("ddd MMMM d yy")); - QTest::newRow("formatDateTime, qcolor") << "formatDateTime" << QVariant::fromValue(color) << (QStringList() << temporary.toString(Qt::DefaultLocaleShortDate) << temporary.toString(Qt::DefaultLocaleLongDate) << temporary.toString("M/d/yy H:m:s a")); - QTest::newRow("formatTime, qcolor") << "formatTime" << QVariant::fromValue(color) << (QStringList() << temporary.time().toString(Qt::DefaultLocaleShortDate) << temporary.time().toString(Qt::DefaultLocaleLongDate) << temporary.time().toString("H:m:s a") << temporary.time().toString("hh:mm:ss.zzz")); + QTest::newRow("formatDate, qcolor") + << "formatDate" << QVariant::fromValue(color) + << (QStringList() + << QLocale().toString(temporary.date(), QLocale::ShortFormat) + << QLocale().toString(temporary.date(), QLocale::LongFormat) + << temporary.date().toString("ddd MMMM d yy")); + QTest::newRow("formatDateTime, qcolor") + << "formatDateTime" << QVariant::fromValue(color) + << (QStringList() + << QLocale().toString(temporary, QLocale::ShortFormat) + << QLocale().toString(temporary, QLocale::LongFormat) + << temporary.toString("M/d/yy H:m:s a")); + QTest::newRow("formatTime, qcolor") + << "formatTime" << QVariant::fromValue(color) + << (QStringList() + << QLocale().toString(temporary.time(), QLocale::ShortFormat) + << QLocale().toString(temporary.time(), QLocale::LongFormat) + << temporary.time().toString("H:m:s a") + << temporary.time().toString("hh:mm:ss.zzz")); int integer(4); temporary = QVariant::fromValue(integer).toDateTime(); - QTest::newRow("formatDate, int") << "formatDate" << QVariant::fromValue(integer) << (QStringList() << temporary.date().toString(Qt::DefaultLocaleShortDate) << temporary.date().toString(Qt::DefaultLocaleLongDate) << temporary.date().toString("ddd MMMM d yy")); - QTest::newRow("formatDateTime, int") << "formatDateTime" << QVariant::fromValue(integer) << (QStringList() << temporary.toString(Qt::DefaultLocaleShortDate) << temporary.toString(Qt::DefaultLocaleLongDate) << temporary.toString("M/d/yy H:m:s a")); - QTest::newRow("formatTime, int") << "formatTime" << QVariant::fromValue(integer) << (QStringList() << temporary.time().toString(Qt::DefaultLocaleShortDate) << temporary.time().toString(Qt::DefaultLocaleLongDate) << temporary.time().toString("H:m:s a") << temporary.time().toString("hh:mm:ss.zzz")); + QTest::newRow("formatDate, int") + << "formatDate" << QVariant::fromValue(integer) + << (QStringList() + << QLocale().toString(temporary.date(), QLocale::ShortFormat) + << QLocale().toString(temporary.date(), QLocale::LongFormat) + << temporary.date().toString("ddd MMMM d yy")); + QTest::newRow("formatDateTime, int") + << "formatDateTime" << QVariant::fromValue(integer) + << (QStringList() + << QLocale().toString(temporary, QLocale::ShortFormat) + << QLocale().toString(temporary, QLocale::LongFormat) + << temporary.toString("M/d/yy H:m:s a")); + QTest::newRow("formatTime, int") + << "formatTime" << QVariant::fromValue(integer) + << (QStringList() + << QLocale().toString(temporary.time(), QLocale::ShortFormat) + << QLocale().toString(temporary.time(), QLocale::LongFormat) + << temporary.time().toString("H:m:s a") + << temporary.time().toString("hh:mm:ss.zzz")); +} + +void tst_qqmlqt::dateTimeFormattingWithLocale() +{ + QQmlEngine engine; + auto url = testFileUrl("formattingLocale.qml"); + QQmlComponent comp(&engine, url); + QDateTime dateTime = QDateTime::fromString("M1d1y9800:01:02", + "'M'M'd'd'y'yyhh:mm:ss"); + QDate date(1995, 5, 17); + QScopedPointer<QObject> o(comp.createWithInitialProperties({ {"myDateTime", dateTime}, {"myDate", date} })); + QVERIFY(!o.isNull()); + + auto dateTimeString = o->property("dateTimeString").toString(); + QCOMPARE(dateTimeString, QLocale("de_DE").toString(dateTime, QLocale::NarrowFormat)); + auto dateString = o->property("dateString").toString(); + QCOMPARE(dateString, QLocale("de_DE").toString(date, QLocale::ShortFormat)); + + QString warningMsg = url.toString() + QLatin1String(":11: Error: Qt.formatTime(): Third argument must be a Locale format option"); + QTest::ignoreMessage(QtMsgType::QtWarningMsg, warningMsg.toUtf8().constData()); + QMetaObject::invokeMethod(o.get(), "invalidUsage"); } void tst_qqmlqt::isQtObject() diff --git a/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp b/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp index 4e42d02514..0168663cf2 100644 --- a/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp +++ b/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp @@ -311,7 +311,7 @@ void tst_qqmltimer::restart() { QQmlEngine engine; QQmlComponent component(&engine); - component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 500; repeat: true; running: true }"), QUrl::fromLocalFile("")); + component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 1000; repeat: true; running: true }"), QUrl::fromLocalFile("")); QQmlTimer *timer = qobject_cast<QQmlTimer*>(component.create()); QVERIFY(timer != nullptr); @@ -319,14 +319,16 @@ void tst_qqmltimer::restart() connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); QCOMPARE(helper.count, 0); - consistentWait(600); + consistentWait(1200); QCOMPARE(helper.count, 1); - consistentWait(300); + consistentWait(500); + QCOMPARE(helper.count, 1); timer->restart(); + QCOMPARE(helper.count, 1); - consistentWait(700); + consistentWait(1400); QCOMPARE(helper.count, 2); QVERIFY(timer->isRunning()); diff --git a/tests/auto/qml/qqmlvaluetypes/testtypes.h b/tests/auto/qml/qqmlvaluetypes/testtypes.h index e11d831236..78797f06b1 100644 --- a/tests/auto/qml/qqmlvaluetypes/testtypes.h +++ b/tests/auto/qml/qqmlvaluetypes/testtypes.h @@ -48,6 +48,8 @@ #include <private/qqmlproperty_p.h> #include <private/qqmlpropertyvalueinterceptor_p.h> +Q_DECLARE_METATYPE(QQmlProperty) + class MyTypeObject : public QObject { Q_OBJECT diff --git a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp index ae794e76a9..2c08c33fc8 100644 --- a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp +++ b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp @@ -1133,15 +1133,16 @@ void tst_qqmlxmlhttprequest::sendFileRequest() #if QT_CONFIG(process) void tst_qqmlxmlhttprequest::sendFileRequestNotSet() { if (qEnvironmentVariableIsSet("TEST_CUSTOM_PERMISSIONS")) { - // Test with no settings - // Should just result in warnings in Qt 5 - doFileRequest([](QObject* object, QTemporaryFile &writeFile) { - QTRY_COMPARE(object->property("readResult").toString(), testString); + // Test with no settings, neither reading nor writing should work + doFileRequest([](QObject *object, QTemporaryFile &writeFile) { + QTest::qWait(1000); - QTRY_VERIFY(object->property("writeDone").toBool()); + // Verify that the read has not yielded any value + QVERIFY(object->property("readResult").isNull()); + // Check that the file stays empty QVERIFY(writeFile.open()); - QCOMPARE(QString::fromUtf8(writeFile.readAll()), testString); + QCOMPARE(QString::fromUtf8(writeFile.readAll()), ""); writeFile.close(); }); return; @@ -1161,22 +1162,25 @@ void tst_qqmlxmlhttprequest::sendFileRequestNotSet() { // Check exit code QCOMPARE(child.exitCode(), 0); - // Check if all warnings were printed + // Check if all errors were printed QString output = QString::fromUtf8(child.readAllStandardOutput()); + // Due to differences in line endings on Windows, check for the error lines individually + const QStringList readingError = { + QLatin1String("XMLHttpRequest: Using GET on a local file is disabled by default."), + QLatin1String("Set QML_XHR_ALLOW_FILE_READ to 1 to enable this feature.") + }; - const QString readingWarning = QLatin1String( - "XMLHttpRequest: Using GET on a local file is dangerous " - "and will be disabled by default in a future Qt version." - "Set QML_XHR_ALLOW_FILE_READ to 1 if you wish to continue using this feature."); + const QStringList writingError = { + QLatin1String("XMLHttpRequest: Using PUT on a local file is disabled by default."), + QLatin1String("Set QML_XHR_ALLOW_FILE_WRITE to 1 to enable this feature.") + }; - const QString writingWarning = QLatin1String( - "XMLHttpRequest: Using PUT on a local file is dangerous " - "and will be disabled by default in a future Qt version." - "Set QML_XHR_ALLOW_FILE_WRITE to 1 if you wish to continue using this feature."); + for (const auto &readingErrorLine : readingError) + QVERIFY(output.contains(readingErrorLine)); - QVERIFY(output.contains(readingWarning)); - QVERIFY(output.contains(writingWarning)); + for (const auto &writingErrorLine : writingError) + QVERIFY(output.contains(writingErrorLine)); } #endif diff --git a/tests/auto/qml/qquickworkerscript/data/BaseWorker.qml b/tests/auto/qml/qquickworkerscript/data/BaseWorker.qml index 59af114379..1d3420e186 100644 --- a/tests/auto/qml/qquickworkerscript/data/BaseWorker.qml +++ b/tests/auto/qml/qquickworkerscript/data/BaseWorker.qml @@ -1,4 +1,5 @@ import QtQuick 2.0 +import QtQml.WorkerScript 2.15 WorkerScript { id: worker diff --git a/tests/auto/quick/drawingmodes/tst_drawingmodes.cpp b/tests/auto/quick/drawingmodes/tst_drawingmodes.cpp index 9bcc21c77d..39f4c3c70a 100644 --- a/tests/auto/quick/drawingmodes/tst_drawingmodes.cpp +++ b/tests/auto/quick/drawingmodes/tst_drawingmodes.cpp @@ -34,7 +34,7 @@ #include <QtQuick/qsggeometry.h> #include <QtQuick/qsgflatcolormaterial.h> #include <QtGui/qscreen.h> -#include <QtGui/qopenglcontext.h> +#include <qopenglcontext.h> #include "../../shared/util.h" diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml index 7b3601bea0..81fa20f3bb 100644 --- a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml +++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the manual tests of the Qt Toolkit. @@ -26,7 +26,7 @@ ** ****************************************************************************/ -import QtQuick 2.12 +import QtQuick 2.15 Item { id: root @@ -47,6 +47,7 @@ Item { DragHandler { id: dragHandler objectName: "DragHandler " + (index + 1) + cursorShape: Qt.ClosedHandCursor } Text { diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp index 65c5ac9ef4..47cfd27817 100644 --- a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp @@ -249,8 +249,11 @@ void tst_DragHandler::mouseDrag() QPointF ballCenter = ball->clipRect().center(); QPointF scenePressPos = ball->mapToScene(ballCenter); QPoint p1 = scenePressPos.toPoint(); - QTest::mousePress(window, static_cast<Qt::MouseButton>(int(dragButton)), Qt::NoModifier, p1); + QTest::mousePress(window, static_cast<Qt::MouseButton>(int(dragButton)), Qt::NoModifier, p1, 500); QVERIFY(!dragHandler->active()); +#if QT_CONFIG(cursor) + QCOMPARE(window->cursor().shape(), Qt::ArrowCursor); +#endif if (shouldDrag) { QCOMPARE(dragHandler->centroid().position(), ballCenter); QCOMPARE(dragHandler->centroid().pressPosition(), ballCenter); @@ -265,6 +268,9 @@ void tst_DragHandler::mouseDrag() QTRY_VERIFY(dragHandler->centroid().velocity().x() > 0); QCOMPARE(centroidChangedSpy.count(), 2); QVERIFY(!dragHandler->active()); +#if QT_CONFIG(cursor) + QCOMPARE(window->cursor().shape(), Qt::ArrowCursor); +#endif } p1 += QPoint(1, 0); QTest::mouseMove(window, p1); @@ -292,6 +298,9 @@ void tst_DragHandler::mouseDrag() QCOMPARE(dragHandler->translation().y(), 0.0); QVERIFY(dragHandler->centroid().velocity().x() > 0); QCOMPARE(centroidChangedSpy.count(), 4); +#if QT_CONFIG(cursor) + QCOMPARE(window->cursor().shape(), Qt::ClosedHandCursor); +#endif } QTest::mouseRelease(window, static_cast<Qt::MouseButton>(int(dragButton)), Qt::NoModifier, p1); QTRY_VERIFY(!dragHandler->active()); @@ -300,6 +309,10 @@ void tst_DragHandler::mouseDrag() QCOMPARE(ball->mapToScene(ballCenter).toPoint(), p1); QCOMPARE(translationChangedSpy.count(), shouldDrag ? 1 : 0); QCOMPARE(centroidChangedSpy.count(), shouldDrag ? 5 : 0); +#if QT_CONFIG(cursor) + QTest::mouseMove(window, p1 + QPoint(1, 0)); // TODO after fixing QTBUG-53987, don't send mouseMove + QCOMPARE(window->cursor().shape(), Qt::ArrowCursor); +#endif } void tst_DragHandler::mouseDragThreshold_data() diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/BLACKLIST b/tests/auto/quick/pointerhandlers/qquickhoverhandler/BLACKLIST new file mode 100644 index 0000000000..9bb35c4770 --- /dev/null +++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/BLACKLIST @@ -0,0 +1,3 @@ +[movingItemWithHoverHandler] +macos # Can't move cursor (QTBUG-76312) + diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml index 011dc4e75f..38a19c57c5 100644 --- a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml +++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** 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. @@ -26,7 +26,7 @@ ** ****************************************************************************/ -import QtQuick 2.12 +import QtQuick 2.15 Rectangle { id: root @@ -52,6 +52,7 @@ Rectangle { id: buttonMA objectName: "buttonMA" hoverEnabled: true + cursorShape: Qt.UpArrowCursor anchors.fill: parent onClicked: console.log("clicked MA") } @@ -74,9 +75,12 @@ Rectangle { id: buttonHH objectName: "buttonHH" acceptedDevices: PointerDevice.AllDevices + cursorShape: tapHandler.pressed ? Qt.BusyCursor : Qt.PointingHandCursor } - TapHandler { } + TapHandler { + id: tapHandler + } Text { anchors.centerIn: parent @@ -127,6 +131,7 @@ Rectangle { HoverHandler { id: topSidebarHH objectName: "topSidebarHH" + cursorShape: Qt.OpenHandCursor } Loader { @@ -152,6 +157,7 @@ Rectangle { id: bottomSidebarMA objectName: "bottomSidebarMA" hoverEnabled: true + cursorShape: Qt.ClosedHandCursor anchors.fill: parent } diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp b/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp index 575139f851..61f2752dd2 100644 --- a/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp @@ -104,30 +104,45 @@ void tst_HoverHandler::hoverHandlerAndUnderlyingHoverHandler() QCOMPARE(sidebarHoveredSpy.count(), 0); QCOMPARE(buttonHH->isHovered(), false); QCOMPARE(buttonHoveredSpy.count(), 0); +#if QT_CONFIG(cursor) + QCOMPARE(window->cursor().shape(), Qt::ArrowCursor); +#endif QTest::mouseMove(window, rightOfButton); QCOMPARE(topSidebarHH->isHovered(), true); QCOMPARE(sidebarHoveredSpy.count(), 1); QCOMPARE(buttonHH->isHovered(), false); QCOMPARE(buttonHoveredSpy.count(), 0); +#if QT_CONFIG(cursor) + QCOMPARE(window->cursor().shape(), Qt::OpenHandCursor); +#endif QTest::mouseMove(window, buttonCenter); QCOMPARE(topSidebarHH->isHovered(), true); QCOMPARE(sidebarHoveredSpy.count(), 1); QCOMPARE(buttonHH->isHovered(), true); QCOMPARE(buttonHoveredSpy.count(), 1); +#if QT_CONFIG(cursor) + QCOMPARE(window->cursor().shape(), Qt::PointingHandCursor); +#endif QTest::mouseMove(window, rightOfButton); QCOMPARE(topSidebarHH->isHovered(), true); QCOMPARE(sidebarHoveredSpy.count(), 1); QCOMPARE(buttonHH->isHovered(), false); QCOMPARE(buttonHoveredSpy.count(), 2); +#if QT_CONFIG(cursor) + QCOMPARE(window->cursor().shape(), Qt::OpenHandCursor); +#endif QTest::mouseMove(window, outOfSidebar); QCOMPARE(topSidebarHH->isHovered(), false); QCOMPARE(sidebarHoveredSpy.count(), 2); QCOMPARE(buttonHH->isHovered(), false); QCOMPARE(buttonHoveredSpy.count(), 2); +#if QT_CONFIG(cursor) + QCOMPARE(window->cursor().shape(), Qt::ArrowCursor); +#endif } void tst_HoverHandler::mouseAreaAndUnderlyingHoverHandler() @@ -153,30 +168,45 @@ void tst_HoverHandler::mouseAreaAndUnderlyingHoverHandler() QCOMPARE(sidebarHoveredSpy.count(), 0); QCOMPARE(buttonMA->hovered(), false); QCOMPARE(buttonHoveredSpy.count(), 0); +#if QT_CONFIG(cursor) + QCOMPARE(window->cursor().shape(), Qt::ArrowCursor); +#endif QTest::mouseMove(window, rightOfButton); QCOMPARE(topSidebarHH->isHovered(), true); QCOMPARE(sidebarHoveredSpy.count(), 1); QCOMPARE(buttonMA->hovered(), false); QCOMPARE(buttonHoveredSpy.count(), 0); +#if QT_CONFIG(cursor) + QCOMPARE(window->cursor().shape(), Qt::OpenHandCursor); +#endif QTest::mouseMove(window, buttonCenter); QCOMPARE(topSidebarHH->isHovered(), true); QCOMPARE(sidebarHoveredSpy.count(), 1); QCOMPARE(buttonMA->hovered(), true); QCOMPARE(buttonHoveredSpy.count(), 1); +#if QT_CONFIG(cursor) + QCOMPARE(window->cursor().shape(), Qt::UpArrowCursor); +#endif QTest::mouseMove(window, rightOfButton); QCOMPARE(topSidebarHH->isHovered(), true); QCOMPARE(sidebarHoveredSpy.count(), 1); QCOMPARE(buttonMA->hovered(), false); QCOMPARE(buttonHoveredSpy.count(), 2); +#if QT_CONFIG(cursor) + QCOMPARE(window->cursor().shape(), Qt::OpenHandCursor); +#endif QTest::mouseMove(window, outOfSidebar); QCOMPARE(topSidebarHH->isHovered(), false); QCOMPARE(sidebarHoveredSpy.count(), 2); QCOMPARE(buttonMA->hovered(), false); QCOMPARE(buttonHoveredSpy.count(), 2); +#if QT_CONFIG(cursor) + QCOMPARE(window->cursor().shape(), Qt::ArrowCursor); +#endif } void tst_HoverHandler::hoverHandlerAndUnderlyingMouseArea() @@ -204,30 +234,45 @@ void tst_HoverHandler::hoverHandlerAndUnderlyingMouseArea() QCOMPARE(sidebarHoveredSpy.count(), 0); QCOMPARE(buttonHH->isHovered(), false); QCOMPARE(buttonHoveredSpy.count(), 0); +#if QT_CONFIG(cursor) + QCOMPARE(window->cursor().shape(), Qt::ArrowCursor); +#endif QTest::mouseMove(window, rightOfButton); QCOMPARE(bottomSidebarMA->hovered(), true); QCOMPARE(sidebarHoveredSpy.count(), 1); QCOMPARE(buttonHH->isHovered(), false); QCOMPARE(buttonHoveredSpy.count(), 0); +#if QT_CONFIG(cursor) + QCOMPARE(window->cursor().shape(), Qt::ClosedHandCursor); +#endif QTest::mouseMove(window, buttonCenter); QCOMPARE(bottomSidebarMA->hovered(), false); QCOMPARE(sidebarHoveredSpy.count(), 2); QCOMPARE(buttonHH->isHovered(), true); QCOMPARE(buttonHoveredSpy.count(), 1); +#if QT_CONFIG(cursor) + QCOMPARE(window->cursor().shape(), Qt::PointingHandCursor); +#endif QTest::mouseMove(window, rightOfButton); QCOMPARE(bottomSidebarMA->hovered(), true); QCOMPARE(sidebarHoveredSpy.count(), 3); QCOMPARE(buttonHH->isHovered(), false); QCOMPARE(buttonHoveredSpy.count(), 2); +#if QT_CONFIG(cursor) + QCOMPARE(window->cursor().shape(), Qt::ClosedHandCursor); +#endif QTest::mouseMove(window, outOfSidebar); QCOMPARE(bottomSidebarMA->hovered(), false); QCOMPARE(sidebarHoveredSpy.count(), 4); QCOMPARE(buttonHH->isHovered(), false); QCOMPARE(buttonHoveredSpy.count(), 2); +#if QT_CONFIG(cursor) + QCOMPARE(window->cursor().shape(), Qt::ArrowCursor); +#endif } void tst_HoverHandler::movingItemWithHoverHandler() @@ -255,6 +300,7 @@ void tst_HoverHandler::movingItemWithHoverHandler() QVERIFY(QTest::qWaitForWindowExposed(window)); QTRY_COMPARE(paddleHH->isHovered(), true); + // TODO check the cursor shape after fixing QTBUG-53987 paddle->setX(100); QTRY_COMPARE(paddleHH->isHovered(), false); diff --git a/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp index d0b3bc3d36..ca6463f365 100644 --- a/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp @@ -55,6 +55,7 @@ private slots: void initTestCase(); void singleTouch(); + void tabletStylus(); void simultaneousMultiTouch(); void pressedMultipleButtons_data(); void pressedMultipleButtons(); @@ -136,6 +137,65 @@ void tst_PointHandler::singleTouch() QCOMPARE(translationSpy.count(), 3); } +void tst_PointHandler::tabletStylus() +{ + qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTabletEvents, false); + QScopedPointer<QQuickView> windowPtr; + createView(windowPtr, "pointTracker.qml"); + QQuickView * window = windowPtr.data(); + QQuickPointHandler *handler = window->rootObject()->findChild<QQuickPointHandler *>("pointHandler"); + QVERIFY(handler); + handler->setAcceptedDevices(QQuickPointerDevice::Stylus); + + QSignalSpy activeSpy(handler, SIGNAL(activeChanged())); + QSignalSpy pointSpy(handler, SIGNAL(pointChanged())); + QSignalSpy translationSpy(handler, SIGNAL(translationChanged())); + + QPoint point(100,100); + const qint64 stylusId = 1234567890; + + QWindowSystemInterface::handleTabletEvent(window, point, window->mapToGlobal(point), + QTabletEvent::Stylus, QTabletEvent::Pen, Qt::LeftButton, 0.5, 25, 35, 0.6, 12.3, 3, stylusId, Qt::NoModifier); + QTRY_COMPARE(handler->active(), true); + QCOMPARE(activeSpy.count(), 1); + QCOMPARE(pointSpy.count(), 1); + QCOMPARE(handler->point().position().toPoint(), point); + QCOMPARE(handler->point().scenePosition().toPoint(), point); + QCOMPARE(handler->point().pressedButtons(), Qt::LeftButton); + QCOMPARE(handler->point().pressure(), 0.5); + QCOMPARE(handler->point().rotation(), 12.3); + QCOMPARE(handler->point().uniqueId().numericId(), stylusId); + QCOMPARE(handler->translation(), QVector2D()); + QCOMPARE(translationSpy.count(), 1); + + point += QPoint(10, 10); + QWindowSystemInterface::handleTabletEvent(window, point, window->mapToGlobal(point), + QTabletEvent::Stylus, QTabletEvent::Pen, Qt::LeftButton, 0.45, 23, 33, 0.57, 15.6, 3.4, stylusId, Qt::NoModifier); + QTRY_COMPARE(pointSpy.count(), 2); + QCOMPARE(handler->active(), true); + QCOMPARE(activeSpy.count(), 1); + QCOMPARE(handler->point().position().toPoint(), point); + QCOMPARE(handler->point().scenePosition().toPoint(), point); + QCOMPARE(handler->point().pressPosition().toPoint(), QPoint(100, 100)); + QCOMPARE(handler->point().scenePressPosition().toPoint(), QPoint(100, 100)); + QCOMPARE(handler->point().pressedButtons(), Qt::LeftButton); + QCOMPARE(handler->point().pressure(), 0.45); + QCOMPARE(handler->point().rotation(), 15.6); + QCOMPARE(handler->point().uniqueId().numericId(), stylusId); + QVERIFY(handler->point().velocity().x() > 0); + QVERIFY(handler->point().velocity().y() > 0); + QCOMPARE(handler->translation(), QVector2D(10, 10)); + QCOMPARE(translationSpy.count(), 2); + + QWindowSystemInterface::handleTabletEvent(window, point, window->mapToGlobal(point), + QTabletEvent::Stylus, QTabletEvent::Pen, Qt::NoButton, 0, 0, 0, 0, 0, 0, stylusId, Qt::NoModifier); + QTRY_COMPARE(handler->active(), false); + QCOMPARE(activeSpy.count(), 2); + QCOMPARE(pointSpy.count(), 3); + QCOMPARE(handler->translation(), QVector2D()); + QCOMPARE(translationSpy.count(), 3); +} + void tst_PointHandler::simultaneousMultiTouch() { QScopedPointer<QQuickView> windowPtr; diff --git a/tests/auto/quick/pointerhandlers/qquickwheelhandler/BLACKLIST b/tests/auto/quick/pointerhandlers/qquickwheelhandler/BLACKLIST new file mode 100644 index 0000000000..2949d3371f --- /dev/null +++ b/tests/auto/quick/pointerhandlers/qquickwheelhandler/BLACKLIST @@ -0,0 +1,3 @@ +# QTBUG-81993 +[singleHandler] +macos ci diff --git a/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp b/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp index 9f616c56e2..47d6008c28 100644 --- a/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp +++ b/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp @@ -34,8 +34,8 @@ #include <private/qquickitem_p.h> #include <QtCore/qscopedpointer.h> #include <QtGui/qpainter.h> -#include <QtGui/qopenglcontext.h> -#include <QtGui/qopenglfunctions.h> +#include <qopenglcontext.h> +#include <qopenglfunctions.h> #include <QtGui/qoffscreensurface.h> #include <QtQml/qqmlproperty.h> diff --git a/tests/auto/quick/qquickanimations/BLACKLIST b/tests/auto/quick/qquickanimations/BLACKLIST new file mode 100644 index 0000000000..a1b8557128 --- /dev/null +++ b/tests/auto/quick/qquickanimations/BLACKLIST @@ -0,0 +1,2 @@ +[simplePath] +macos ci diff --git a/tests/auto/quick/qquickbehaviors/data/targetProperty.qml b/tests/auto/quick/qquickbehaviors/data/targetProperty.qml new file mode 100644 index 0000000000..18abd46010 --- /dev/null +++ b/tests/auto/quick/qquickbehaviors/data/targetProperty.qml @@ -0,0 +1,16 @@ +import QtQuick 2.15 + +Item { + readonly property QtObject xBehaviorObject: xBehavior.targetProperty.object + readonly property string xBehaviorName: xBehavior.targetProperty.name + readonly property QtObject emptyBehaviorObject: emptyBehavior.targetProperty.object + readonly property string emptyBehaviorName: emptyBehavior.targetProperty.name + Behavior on x { + id: xBehavior + objectName: "xBehavior" + } + Behavior { + id: emptyBehavior + objectName: "emptyBehavior" + } +} diff --git a/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp b/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp index 64e32dcdfd..3b46019f64 100644 --- a/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp +++ b/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp @@ -75,6 +75,7 @@ private slots: void innerBehaviorOverwritten(); void oneWay(); void safeToDelete(); + void targetProperty(); }; void tst_qquickbehaviors::simpleBehavior() @@ -656,6 +657,27 @@ void tst_qquickbehaviors::safeToDelete() QVERIFY(c.create()); } +Q_DECLARE_METATYPE(QQmlProperty) +void tst_qquickbehaviors::targetProperty() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("targetProperty.qml")); + QScopedPointer<QQuickItem> item(qobject_cast<QQuickItem*>(c.create())); + QVERIFY2(!item.isNull(), qPrintable(c.errorString())); + + QQuickBehavior* xBehavior = + qobject_cast<QQuickBehavior*>(item->findChild<QQuickBehavior*>("xBehavior")); + QCOMPARE(xBehavior->property("targetProperty").value<QQmlProperty>(), QQmlProperty(item.data(), "x")); + QCOMPARE(item->property("xBehaviorObject").value<QObject*>(), item.data()); + QCOMPARE(item->property("xBehaviorName").toString(), "x"); + + QQuickBehavior* emptyBehavior = + qobject_cast<QQuickBehavior*>(item->findChild<QQuickBehavior*>("emptyBehavior")); + QCOMPARE(emptyBehavior->property("targetProperty").value<QQmlProperty>().isValid(), false); + QCOMPARE(item->property("emptyBehaviorObject").value<QObject*>(), nullptr); + QCOMPARE(item->property("emptyBehaviorName").toString(), ""); +} + QTEST_MAIN(tst_qquickbehaviors) diff --git a/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp b/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp index b44977bd5a..062a8b5c9a 100644 --- a/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp +++ b/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp @@ -76,7 +76,10 @@ void tst_qquickdesignersupport::customData() QVERIFY(rootItem); - QScopedPointer<QObject> newItemScopedPointer(QQuickDesignerSupportItems::createPrimitive(QLatin1String("QtQuick/Item"), 2, 6, view->rootContext())); + QScopedPointer<QObject> newItemScopedPointer(QQuickDesignerSupportItems::createPrimitive( + QLatin1String("QtQuick/Item"), + QTypeRevision::fromVersion(2, 6), + view->rootContext())); QObject *newItem = newItemScopedPointer.data(); QVERIFY(newItem); diff --git a/tests/auto/quick/qquickflickable/data/visibleAreaBinding.qml b/tests/auto/quick/qquickflickable/data/visibleAreaBinding.qml new file mode 100644 index 0000000000..6f7bc89793 --- /dev/null +++ b/tests/auto/quick/qquickflickable/data/visibleAreaBinding.qml @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick 2.14 + +Flickable { + id: flickable + // Deliberately has no size set. + + Text { + text: flickable.visibleArea.xPosition + } +} diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index 5364530ca8..f3659290eb 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -205,6 +205,7 @@ private slots: void overshoot_reentrant(); void synchronousDrag_data(); void synchronousDrag(); + void visibleAreaBinding(); private: void flickWithTouch(QQuickWindow *window, const QPoint &from, const QPoint &to); @@ -2540,6 +2541,16 @@ void tst_qquickflickable::synchronousDrag() QTest::touchEvent(window, touchDevice).release(0, p5, window); } +// QTBUG-81098: tests that a binding to visibleArea doesn't result +// in a division-by-zero exception (when exceptions are enabled). +void tst_qquickflickable::visibleAreaBinding() +{ + QScopedPointer<QQuickView> window(new QQuickView); + window->setSource(testFileUrl("visibleAreaBinding.qml")); + QTRY_COMPARE(window->status(), QQuickView::Ready); + // Shouldn't crash. +} + QTEST_MAIN(tst_qquickflickable) #include "tst_qquickflickable.moc" diff --git a/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp b/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp index 6aff66d61e..2327270b0f 100644 --- a/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp +++ b/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp @@ -30,9 +30,9 @@ #include <QtQuick/qquickitem.h> #include <QtQuick/qquickview.h> -#include <QtGui/qopenglcontext.h> -#include <QtGui/qopenglframebufferobject.h> -#include <QtGui/qopenglfunctions.h> +#include <qopenglcontext.h> +#include <qopenglframebufferobject.h> +#include <qopenglfunctions.h> #include <QtQuick/QQuickFramebufferObject> diff --git a/tests/auto/quick/qquickgraphicsinfo/tst_qquickgraphicsinfo.cpp b/tests/auto/quick/qquickgraphicsinfo/tst_qquickgraphicsinfo.cpp index 4da6da6043..aff081c4a8 100644 --- a/tests/auto/quick/qquickgraphicsinfo/tst_qquickgraphicsinfo.cpp +++ b/tests/auto/quick/qquickgraphicsinfo/tst_qquickgraphicsinfo.cpp @@ -36,7 +36,7 @@ #include "../../shared/util.h" #if QT_CONFIG(opengl) -#include <QtGui/qopenglcontext.h> +#include <qopenglcontext.h> #include <QtGui/qsurfaceformat.h> #endif diff --git a/tests/auto/quick/qquickimage/data/ProPhoto.jpg b/tests/auto/quick/qquickimage/data/ProPhoto.jpg Binary files differnew file mode 100644 index 0000000000..481d35ca8e --- /dev/null +++ b/tests/auto/quick/qquickimage/data/ProPhoto.jpg diff --git a/tests/auto/quick/qquickimage/data/image.qml b/tests/auto/quick/qquickimage/data/image.qml new file mode 100644 index 0000000000..09a577cc6f --- /dev/null +++ b/tests/auto/quick/qquickimage/data/image.qml @@ -0,0 +1,5 @@ +import QtQuick 2.15 + +Image { + source: "heart.png" +} diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp index abc7cd86bd..f0b44743b9 100644 --- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp +++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp @@ -51,6 +51,7 @@ #include "../../shared/testhttpserver.h" #include "../shared/visualtestutil.h" +// #define DEBUG_WRITE_OUTPUT using namespace QQuickVisualTestUtil; @@ -89,6 +90,8 @@ private slots: void imageCrash_QTBUG_32513(); void sourceSize_data(); void sourceSize(); + void sourceClipRect_data(); + void sourceClipRect(); void progressAndStatusChanges(); void sourceSizeChanges(); void correctStatus(); @@ -99,6 +102,7 @@ private slots: void urlInterceptor(); void multiFrame_data(); void multiFrame(); + void colorSpace(); private: QQmlEngine engine; @@ -879,6 +883,72 @@ void tst_qquickimage::sourceSizeChanges() delete img; } +void tst_qquickimage::sourceClipRect_data() +{ + QTest::addColumn<QRectF>("sourceClipRect"); + QTest::addColumn<QSize>("sourceSize"); + QTest::addColumn<QList<QPoint>>("redPixelLocations"); + QTest::addColumn<QList<QPoint>>("bluePixelLocations"); + + QTest::newRow("unclipped") << QRectF() << QSize() + << (QList<QPoint>() << QPoint(80, 80) << QPoint(150, 256)) + << (QList<QPoint>() << QPoint(28, 28) << QPoint(215, 215)); + QTest::newRow("upperLeft") << QRectF(10, 10, 100, 100) << QSize() + << (QList<QPoint>() << QPoint(99, 99)) + << (QList<QPoint>() << QPoint(100, 100) << QPoint(28, 28)); + QTest::newRow("lowerRight") << QRectF(200, 200, 20, 20) << QSize() + << (QList<QPoint>() << QPoint(0, 0)) + << (QList<QPoint>() << QPoint(14, 14)); + QTest::newRow("miniMiddle") << QRectF(20, 20, 60, 60) << QSize(100, 100) + << (QList<QPoint>() << QPoint(59, 0) << QPoint(6, 12) << QPoint(42, 42)) + << (QList<QPoint>() << QPoint(54, 54) << QPoint(15, 59)); +} + +void tst_qquickimage::sourceClipRect() +{ + QFETCH(QRectF, sourceClipRect); + QFETCH(QSize, sourceSize); + QFETCH(QList<QPoint>, redPixelLocations); + QFETCH(QList<QPoint>, bluePixelLocations); + + QScopedPointer<QQuickView> window(new QQuickView(nullptr)); + + window->setColor(Qt::blue); + window->setSource(testFileUrl("image.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + + QQuickImage *image = qobject_cast<QQuickImage*>(window->rootObject()); + QVERIFY(image); + + image->setSourceSize(sourceSize); + QCOMPARE(image->implicitWidth(), sourceSize.isValid() ? sourceSize.width() : 300); + QCOMPARE(image->implicitHeight(), sourceSize.isValid() ? sourceSize.height() : 300); + image->setSourceClipRect(sourceClipRect); + QCOMPARE(image->implicitWidth(), sourceClipRect.isNull() ? 300 : sourceClipRect.width()); + QCOMPARE(image->implicitHeight(), sourceClipRect.isNull() ? 300 : sourceClipRect.height()); + + if ((QGuiApplication::platformName() == QLatin1String("offscreen")) + || (QGuiApplication::platformName() == QLatin1String("minimal"))) + QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms"); + QImage contents = window->grabWindow(); + if (contents.width() < sourceClipRect.width()) + QSKIP("Skipping due to grabWindow not functional"); +#ifdef DEBUG_WRITE_OUTPUT + contents.save("/tmp/sourceClipRect_" + QLatin1String(QTest::currentDataTag()) + ".png"); +#endif + for (auto p : redPixelLocations) { + QRgb color = contents.pixel(p); + QVERIFY(qRed(color) > 0xc0); + QVERIFY(qBlue(color) < 0x0f); + } + for (auto p : bluePixelLocations){ + QRgb color = contents.pixel(p); + QVERIFY(qBlue(color) > 0xc0); + QVERIFY(qRed(color) < 0x0f); + } +} + void tst_qquickimage::progressAndStatusChanges() { TestHTTPServer server; @@ -1190,6 +1260,34 @@ void tst_qquickimage::multiFrame() QVERIFY(qBlue(color) < 0xc0); } +void tst_qquickimage::colorSpace() +{ + QString componentStr1 = "import QtQuick 2.15\n" + "Image { source: srcImage; }"; + QQmlComponent component1(&engine); + component1.setData(componentStr1.toLatin1(), QUrl::fromLocalFile("")); + engine.rootContext()->setContextProperty("srcImage", testFileUrl("ProPhoto.jpg")); + + QScopedPointer<QQuickImage> object1 { qobject_cast<QQuickImage*>(component1.create())}; + QVERIFY(object1); + QTRY_COMPARE(object1->status(), QQuickImageBase::Ready); + QCOMPARE(object1->colorSpace(), QColorSpace(QColorSpace::ProPhotoRgb)); + + QString componentStr2 = "import QtQuick 2.15\n" + "Image {\n" + " source: srcImage;\n" + " colorSpace.namedColorSpace: ColorSpace.SRgb;\n" + "}"; + + QQmlComponent component2(&engine); + component2.setData(componentStr2.toLatin1(), QUrl::fromLocalFile("")); + + QScopedPointer<QQuickImage> object2 { qobject_cast<QQuickImage*>(component2.create())}; + QVERIFY(object2); + QTRY_COMPARE(object2->status(), QQuickImageBase::Ready); + QCOMPARE(object2->colorSpace(), QColorSpace(QColorSpace::SRgb)); +} + QTEST_MAIN(tst_qquickimage) #include "tst_qquickimage.moc" diff --git a/tests/auto/quick/qquickitem/data/hellotr_la.qm b/tests/auto/quick/qquickitem/data/hellotr_la.qm Binary files differnew file mode 100644 index 0000000000..25c0aad583 --- /dev/null +++ b/tests/auto/quick/qquickitem/data/hellotr_la.qm diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp index 8aab13e095..137162099f 100644 --- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp @@ -34,12 +34,16 @@ #include "private/qquickfocusscope_p.h" #include "private/qquickitem_p.h" #include <qpa/qwindowsysteminterface.h> +#ifdef Q_OS_WIN +#include <QOpenGLContext> +#endif #include <QDebug> #include <QTimer> #include <QQmlEngine> #include "../../shared/util.h" #include "../shared/viewtestutil.h" #include <QSignalSpy> +#include <QTranslator> #ifdef TEST_QTBUG_60123 #include <QWidget> @@ -70,6 +74,7 @@ public: ulong timestamp; QPoint lastWheelEventPos; QPoint lastWheelEventGlobalPos; + int languageChangeEventCount = 0; protected: virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; } virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; } @@ -86,6 +91,12 @@ protected: lastWheelEventPos = event->position().toPoint(); lastWheelEventGlobalPos = event->globalPosition().toPoint(); } + bool event(QEvent *e) override + { + if (e->type() == QEvent::LanguageChange) + languageChangeEventCount++; + return QQuickItem::event(e); + } }; class TestWindow: public QQuickWindow @@ -198,6 +209,7 @@ private slots: #endif void setParentCalledInOnWindowChanged(); + void receivesLanguageChangeEvent(); private: @@ -2155,6 +2167,32 @@ void tst_qquickitem::setParentCalledInOnWindowChanged() QVERIFY(ensureFocus(&view)); // should not crash } +void tst_qquickitem::receivesLanguageChangeEvent() +{ + QQuickWindow window; + window.setFramePosition(QPoint(100, 100)); + window.resize(200, 200); + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + + QScopedPointer<TestItem> child1(new TestItem); + child1->setObjectName(QStringLiteral("child1")); + child1->setSize(QSizeF(200, 100)); + child1->setParentItem(window.contentItem()); + + QScopedPointer<TestItem> child2(new TestItem); + child2->setObjectName(QStringLiteral("child2")); + child2->setSize(QSizeF(50, 50)); + child2->setParentItem(child1.data()); + + QTranslator t; + QVERIFY(t.load("hellotr_la.qm", dataDirectory())); + QVERIFY(QCoreApplication::installTranslator(&t)); + + QTRY_COMPARE(child1->languageChangeEventCount, 1); + QCOMPARE(child2->languageChangeEventCount, 1); +} + QTEST_MAIN(tst_qquickitem) #include "tst_qquickitem.moc" diff --git a/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop2.qml b/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop2.qml new file mode 100644 index 0000000000..042f408753 --- /dev/null +++ b/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop2.qml @@ -0,0 +1,12 @@ +import QtQuick 2.14 + +Item { + width: 400 + height: 200 + Item { + objectName: "hiddenChild" + focus: true + activeFocusOnTab: true + visible: false + } +} diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp index a1b4a70217..45ecbfde11 100644 --- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp @@ -64,6 +64,7 @@ private slots: void activeFocusOnTab8(); void activeFocusOnTab9(); void activeFocusOnTab10(); + void activeFocusOnTab_infiniteLoop_data(); void activeFocusOnTab_infiniteLoop(); void nextItemInFocusChain(); @@ -1027,12 +1028,20 @@ void tst_QQuickItem::activeFocusOnTab10() delete window; } +void tst_QQuickItem::activeFocusOnTab_infiniteLoop_data() +{ + QTest::addColumn<QUrl>("source"); + QTest::newRow("infiniteLoop") << testFileUrl("activeFocusOnTab_infiniteLoop.qml"); // QTBUG-68271 + QTest::newRow("infiniteLoop2") << testFileUrl("activeFocusOnTab_infiniteLoop2.qml");// QTBUG-81510 +} + void tst_QQuickItem::activeFocusOnTab_infiniteLoop() { - // see QTBUG-68271 + QFETCH(QUrl, source); + // create a window where the currently focused item is not visible QScopedPointer<QQuickView>window(new QQuickView()); - window->setSource(testFileUrl("activeFocusOnTab_infiniteLoop.qml")); + window->setSource(source); window->show(); auto *hiddenChild = findItem<QQuickItem>(window->rootObject(), "hiddenChild"); QVERIFY(hiddenChild); @@ -1041,6 +1050,8 @@ void tst_QQuickItem::activeFocusOnTab_infiniteLoop() auto *item = hiddenChild->nextItemInFocusChain(); // focus is moved to the root object since there is no other candidate QCOMPARE(item, window->rootObject()); + item = hiddenChild->nextItemInFocusChain(false); + QCOMPARE(item, window->rootObject()); } void tst_QQuickItem::nextItemInFocusChain() diff --git a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp index 2f90632841..b45aa5d61c 100644 --- a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp +++ b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp @@ -31,8 +31,8 @@ #include <QtQuick/qquickitem.h> #include <QtQuick/qquickview.h> #include <QtQuick/qsgrendererinterface.h> -#include <QtGui/qopenglcontext.h> -#include <QtGui/qopenglfunctions.h> +#include <qopenglcontext.h> +#include <qopenglfunctions.h> #include "../../shared/util.h" diff --git a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml index 07af6a77ac..0732884c97 100644 --- a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml +++ b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml @@ -1100,5 +1100,36 @@ Item { waitForRendering(rootRect.layout) compare(rootRect.item1.width, 100) } + +//--------------------------- + Component { + id: rowlayoutWithTextItems_Component + RowLayout { + Text { + Layout.fillWidth: true + text: "OneWord" + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + } + Text { + Layout.fillWidth: true + text: "OneWord" + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + } + } + } + + // QTBUG-73683 + function test_rowlayoutWithTextItems() { + var layout = createTemporaryObject(rowlayoutWithTextItems_Component, container) + waitForRendering(layout) + for (var i = 0; i < 3; i++) { + ignoreWarning(/Qt Quick Layouts: Detected recursive rearrange. Aborting after two iterations./) + } + ignoreWarning(/Qt Quick Layouts: Polish loop detected. Aborting after two iterations./) + layout.width = layout.width - 2 // set the size to be smaller than its "minimum size" + waitForRendering(layout) // do not exit before all warnings have been received + + // DO NOT CRASH due to stack overflow (or loop endlessly due to updatePolish()/polish() loop) + } } } diff --git a/tests/auto/quick/qquicklistview/data/headerSnapToItem.qml b/tests/auto/quick/qquicklistview/data/headerSnapToItem.qml new file mode 100644 index 0000000000..1e5a811630 --- /dev/null +++ b/tests/auto/quick/qquicklistview/data/headerSnapToItem.qml @@ -0,0 +1,67 @@ +import QtQuick 2.12 + +Rectangle { + + width: 240 + height: 320 + color: "#ffffff" + + Component { + id: myDelegate + Rectangle { + id: wrapper + objectName: "wrapper" + width: list.orientation == ListView.Vertical ? 240 : 20 + height: list.orientation == ListView.Vertical ? 20 : 240 + border.width: 1 + border.color: "black" + Text { + text: index + ":" + (list.orientation == ListView.Vertical ? parent.y : parent.x).toFixed(0) + } + color: ListView.isCurrentItem ? "lightsteelblue" : "white" + } + } + + ListView { + id: list + objectName: "list" + focus: true + width: 240 + height: 200 + clip: true + snapMode: ListView.SnapToItem + headerPositioning: ListView.OverlayHeader + model: 30 + delegate: myDelegate + orientation: ListView.Vertical + verticalLayoutDirection: ListView.BottomToTop + + header: Rectangle { + width: list.orientation == Qt.Vertical ? 240 : 30 + height: list.orientation == Qt.Vertical ? 30 : 240 + objectName: "header"; + color: "green" + z: 11 + Text { + anchors.centerIn: parent + text: "header " + (list.orientation == ListView.Vertical ? parent.y : parent.x).toFixed(1) + } + } + } + + Rectangle { + color: "red" + opacity: 0.5 + width: txt.implicitWidth + 50 + height: txt.implicitHeight + anchors.bottom: parent.bottom + anchors.right: parent.right + + Text { + id: txt + anchors.centerIn: parent + text: "header position: " + (list.orientation == ListView.Vertical ? list.headerItem.y : list.headerItem.x).toFixed(1) + + "\ncontent position: " + (list.orientation == ListView.Vertical ? list.contentY : list.contentX).toFixed(1) + } + } +} diff --git a/tests/auto/quick/qquicklistview/data/requiredObjectListModel.qml b/tests/auto/quick/qquicklistview/data/requiredObjectListModel.qml new file mode 100644 index 0000000000..f6380ed5aa --- /dev/null +++ b/tests/auto/quick/qquicklistview/data/requiredObjectListModel.qml @@ -0,0 +1,15 @@ +import QtQuick 2.0 + +ListView { + width: 100 + height: 100 + required model + + delegate: Rectangle { + required color + required property string name + + height: 25 + width: 100 + } +} diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index 9a8dfee9d2..49b68a8473 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -30,6 +30,7 @@ #include <QtCore/QStringListModel> #include <QtCore/QSortFilterProxyModel> #include <QtGui/QStandardItemModel> +#include <QtGui/QStyleHints> #include <QtQuick/qquickview.h> #include <QtQuickTest/QtQuickTest> #include <QtQml/qqmlengine.h> @@ -40,6 +41,7 @@ #include <QtQuick/private/qquicklistview_p.h> #include <QtQuick/private/qquickmousearea_p.h> #include <QtQuick/private/qquicktext_p.h> +#include <QtQuick/private/qquickrectangle_p.h> #include <QtQmlModels/private/qqmlobjectmodel_p.h> #include <QtQmlModels/private/qqmllistmodel_p.h> #include <QtQmlModels/private/qqmldelegatemodel_p.h> @@ -185,6 +187,8 @@ private slots: void creationContext(); void snapToItem_data(); void snapToItem(); + void headerSnapToItem_data(); + void headerSnapToItem(); void snapToItemWithSpacing_QTBUG_59852(); void snapOneItemResize_QTBUG_43555(); void snapOneItem_data(); @@ -291,6 +295,8 @@ private slots: void moveObjectModelItemToAnotherObjectModel(); void changeModelAndDestroyTheOldOne(); + void requiredObjectListModel(); + private: template <class T> void items(const QUrl &source); template <class T> void changed(const QUrl &source); @@ -5412,6 +5418,604 @@ void tst_QQuickListView::snapToItemWithSpacing_QTBUG_59852() releaseView(window); } +static void drag_helper(QWindow *window, QPoint *startPos, const QPoint &delta) +{ + QPoint pos = *startPos; + int dragDistance = delta.manhattanLength(); + Q_ASSERT(qAbs(delta.x()) >= 1 || qAbs(delta.y()) >= 1); + + const int stepSize = 8; + QPoint unitVector(0, 0); + if (delta.x()) + unitVector.setX(qBound(-1, delta.x(), 1)); + if (delta.y()) + unitVector.setY(qBound(-1, delta.y(), 1)); + QPoint dragStepSize = unitVector * stepSize; + int nDragSteps = qAbs(dragDistance/stepSize); + + for (int i = 0 ; i < nDragSteps; ++i) { + QTest::mouseMove(window, pos); + pos += dragStepSize; + } + // Move to the final position + pos = *startPos + delta; + QTest::mouseMove(window, pos); + *startPos = pos; +} + +static void dragtwice(QWindow *window, QPoint *startPos, const QPoint &delta1, const QPoint &delta2) +{ + const int dragThreshold = QGuiApplication::styleHints()->startDragDistance(); + QPoint &pos = *startPos; + QPoint unitVector(0, 0); + if (delta1.x()) + unitVector.setX(qBound(-1, delta1.x(), 1)); + if (delta1.y()) + unitVector.setY(qBound(-1, delta1.y(), 1)); + + // go just beyond the drag theshold + drag_helper(window, &pos, unitVector * (dragThreshold + 1)); + drag_helper(window, &pos, unitVector); + + // next drag will actually scroll the listview + if (delta1.manhattanLength() >= 1) + drag_helper(window, &pos, delta1); + if (delta2.manhattanLength() >= 1) + drag_helper(window, &pos, delta2); +} + +struct MyListView : public QQuickListView{ + qreal contentPosition() const + { + return (orientation() == QQuickListView::Horizontal ? contentX(): contentY()); + } + + qreal headerPosition() const + { + return (orientation() == QQuickListView::Horizontal ? headerItem()->x() : headerItem()->y()); + } +}; + +void tst_QQuickListView::headerSnapToItem() +{ + QFETCH(QQuickItemView::LayoutDirection, layoutDirection); + QFETCH(QQuickListView::HeaderPositioning, headerPositioning); + QFETCH(int, firstDragDistance); + QFETCH(int, secondDragDistance); + QFETCH(int, expectedContentPosition); + QFETCH(int, expectedHeaderPosition); + + QQuickView *window = getView(); + window->setSource(testFileUrl("headerSnapToItem.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + MyListView *listview = static_cast<MyListView *>(findItem<QQuickListView>(window->rootObject(), "list")); + QVERIFY(listview != nullptr); + + const bool horizontal = layoutDirection < QQuickItemView::VerticalTopToBottom; + listview->setOrientation(horizontal ? QQuickListView::Horizontal : QQuickListView::Vertical); + + if (horizontal) + listview->setLayoutDirection(static_cast<Qt::LayoutDirection>(layoutDirection)); + else + listview->setVerticalLayoutDirection(static_cast<QQuickItemView::VerticalLayoutDirection>(layoutDirection)); + + listview->setHeaderPositioning(headerPositioning); + QVERIFY(QQuickTest::qWaitForItemPolished(listview)); + + QQuickItem *contentItem = listview->contentItem(); + QVERIFY(contentItem != nullptr); + QQuickItem *header = findItem<QQuickItem>(contentItem, "header"); + QVERIFY(header != nullptr); + QCOMPARE(header, listview->headerItem()); + + QPoint startPos = (QPointF(listview->width(), listview->height())/2).toPoint(); + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, startPos, 200); + + QPoint firstDragDelta(0, firstDragDistance); + QPoint secondDragDelta = QPoint(0, secondDragDistance); + if (horizontal) { + firstDragDelta = firstDragDelta.transposed(); + secondDragDelta = secondDragDelta.transposed(); + } + + dragtwice(window, &startPos, firstDragDelta, secondDragDelta); + + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, startPos, 200); // Wait 200 ms before we release to avoid trigger a flick + + // wait for the "fixup" animation to finish + QTest::qWaitFor([&]() + { return !listview->isMoving();} + ); + + QCOMPARE(listview->contentPosition(), expectedContentPosition); + QCOMPARE(listview->headerPosition(), expectedHeaderPosition); +} + +void tst_QQuickListView::headerSnapToItem_data() +{ + QTest::addColumn<QQuickItemView::LayoutDirection>("layoutDirection"); + QTest::addColumn<QQuickListView::HeaderPositioning>("headerPositioning"); + QTest::addColumn<int>("firstDragDistance"); + QTest::addColumn<int>("secondDragDistance"); + QTest::addColumn<int>("expectedContentPosition"); + QTest::addColumn<int>("expectedHeaderPosition"); + + // -------------------- + // InlineHeader TopToBottom + QTest::newRow("InlineHeader TopToBottom -10") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -10 << 0 + << -30 << -30; + + QTest::newRow("InlineHeader TopToBottom -14") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -14 << 0 + << -30 << -30; + + QTest::newRow("InlineHeader TopToBottom -16") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -16 << 0 + << 0 << -30; + + QTest::newRow("InlineHeader TopToBottom -30") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -30 << 0 + << 0 << -30; + + QTest::newRow("InlineHeader TopToBottom -39") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -39 << 0 + << 0 << -30; + + QTest::newRow("InlineHeader TopToBottom -41") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -41 << 0 + << 20 << -30; + + QTest::newRow("InlineHeader TopToBottom -65+10") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -65 << 10 + << 20 << -30; + + // -------------------- + // InlineHeader BottomToTop + QTest::newRow("InlineHeader BottomToTop +10") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 10 << 0 + << -170 << 0; + + QTest::newRow("InlineHeader BottomToTop +14") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 14 << 0 + << -170 << 0; + + QTest::newRow("InlineHeader BottomToTop +16") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 16 << 0 + << -200 << 0; + + QTest::newRow("InlineHeader BottomToTop +30") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 30 << 0 + << -200 << 0; + + QTest::newRow("InlineHeader BottomToTop +39") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 39 << 0 + << -200 << 0; + + QTest::newRow("InlineHeader BottomToTop +41") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 41 << 0 + << -220 << 0; + + QTest::newRow("InlineHeader BottomToTop +65-10") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 65 << -10 + << -220 << 0; + + // -------------------- + // InlineHeader LeftToRight + QTest::newRow("InlineHeader LeftToRight -10") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -10 << 0 + << -30 << -30; + + QTest::newRow("InlineHeader LeftToRight -14") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -14 << 0 + << -30 << -30; + + QTest::newRow("InlineHeader LeftToRight -16") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -16 << 0 + << 0 << -30; + + QTest::newRow("InlineHeader LeftToRight -30") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -30 << 0 + << 0 << -30; + + QTest::newRow("InlineHeader LeftToRight -39") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -39 << 0 + << 0 << -30; + + QTest::newRow("InlineHeader LeftToRight -41") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -41 << 0 + << 20 << -30; + + QTest::newRow("InlineHeader LeftToRight -65+10") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -65 << 10 + << 20 << -30; + + // -------------------- + // InlineHeader RightToLeft + QTest::newRow("InlineHeader RightToLeft +10") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 10 << 0 + << -210 << 0; + + QTest::newRow("InlineHeader RightToLeft +14") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 14 << 0 + << -210 << 0; + + QTest::newRow("InlineHeader RightToLeft +16") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 16 << 0 + << -240 << 0; + + QTest::newRow("InlineHeader RightToLeft +30") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 30 << 0 + << -240 << 0; + + QTest::newRow("InlineHeader RightToLeft +39") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 39 << 0 + << -240 << 0; + + QTest::newRow("InlineHeader RightToLeft +41") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 41 << 0 + << -260 << 0; + + QTest::newRow("InlineHeader RightToLeft +65-10") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 65 << -10 + << -260 << 0; + + // -------------------- + // OverlayHeader TopToBottom + QTest::newRow("OverlayHeader TopToBottom +9") << QQuickItemView::VerticalTopToBottom + << QQuickListView::OverlayHeader + << 9 << 0 + << -30 << -30; + + QTest::newRow("OverlayHeader TopToBottom -9") << QQuickItemView::VerticalTopToBottom + << QQuickListView::OverlayHeader + << -9 << 0 + << -30 << -30; + + QTest::newRow("OverlayHeader TopToBottom -11") << QQuickItemView::VerticalTopToBottom + << QQuickListView::OverlayHeader + << -11 << 0 + << -10 << -10; + + QTest::newRow("OverlayHeader TopToBottom -29") << QQuickItemView::VerticalTopToBottom + << QQuickListView::OverlayHeader + << -29 << 0 + << -10 << -10; + + QTest::newRow("OverlayHeader TopToBottom -31") << QQuickItemView::VerticalTopToBottom + << QQuickListView::OverlayHeader + << -31 << 0 + << 10 << 10; + + // -------------------- + // OverlayHeader BottomToTop + QTest::newRow("OverlayHeader BottomToTop -9") << QQuickItemView::VerticalBottomToTop + << QQuickListView::OverlayHeader + << -9 << 0 + << -170 << 0; + + QTest::newRow("OverlayHeader BottomToTop +9") << QQuickItemView::VerticalBottomToTop + << QQuickListView::OverlayHeader + << 9 << 0 + << -170 << 0; + + QTest::newRow("OverlayHeader BottomToTop +11") << QQuickItemView::VerticalBottomToTop + << QQuickListView::OverlayHeader + << 11 << 0 + << -190 << -20; + + QTest::newRow("OverlayHeader BottomToTop +29") << QQuickItemView::VerticalBottomToTop + << QQuickListView::OverlayHeader + << 29 << 0 + << -190 << -20; + + QTest::newRow("OverlayHeader BottomToTop +31") << QQuickItemView::VerticalBottomToTop + << QQuickListView::OverlayHeader + << 31 << 0 + << -210 << -40; + + // -------------------- + // OverlayHeader LeftToRight + QTest::newRow("OverlayHeader LeftToRight +9") << QQuickItemView::LeftToRight + << QQuickListView::OverlayHeader + << 9 << 0 + << -30 << -30; + + QTest::newRow("OverlayHeader LeftToRight -9") << QQuickItemView::LeftToRight + << QQuickListView::OverlayHeader + << -9 << 0 + << -30 << -30; + + QTest::newRow("OverlayHeader LeftToRight -11") << QQuickItemView::LeftToRight + << QQuickListView::OverlayHeader + << -11 << 0 + << -10 << -10; + + QTest::newRow("OverlayHeader LeftToRight -29") << QQuickItemView::LeftToRight + << QQuickListView::OverlayHeader + << -29 << 0 + << -10 << -10; + + QTest::newRow("OverlayHeader LeftToRight -31") << QQuickItemView::LeftToRight + << QQuickListView::OverlayHeader + << -31 << 0 + << 10 << 10; + + // -------------------- + // OverlayHeader RightToLeft + QTest::newRow("OverlayHeader RightToLeft -9") << QQuickItemView::RightToLeft + << QQuickListView::OverlayHeader + << -9 << 0 + << -210 << 0; + + QTest::newRow("OverlayHeader RightToLeft +9") << QQuickItemView::RightToLeft + << QQuickListView::OverlayHeader + << 9 << 0 + << -210 << 0; + + QTest::newRow("OverlayHeader RightToLeft +11") << QQuickItemView::RightToLeft + << QQuickListView::OverlayHeader + << 11 << 0 + << -230 << -20; + + QTest::newRow("OverlayHeader RightToLeft +29") << QQuickItemView::RightToLeft + << QQuickListView::OverlayHeader + << 29 << 0 + << -230 << -20; + + QTest::newRow("OverlayHeader RightToLeft +31") << QQuickItemView::RightToLeft + << QQuickListView::OverlayHeader + << 31 << 0 + << -250 << -40; + + // -------------------- + // PullbackHeader TopToBottom + QTest::newRow("PullbackHeader TopToBottom -2") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -2 << 0 + << -30 << -30; + + QTest::newRow("PullbackHeader TopToBottom -10") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -10 << 0 + << -30 << -30; + + QTest::newRow("PullbackHeader TopToBottom -11") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -11 << 0 + << -10 << -10; + + QTest::newRow("PullbackHeader TopToBottom -14") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -14 << 0 + << -10 << -10; + + QTest::newRow("PullbackHeader TopToBottom -16") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -16 << 0 + << 0 << -30; + + QTest::newRow("PullbackHeader TopToBottom -20") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -20 << 0 + << 0 << -30; + + QTest::newRow("PullbackHeader TopToBottom -65+10") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -65 << 10 + << 20 << -10; + + QTest::newRow("PullbackHeader TopToBottom -65+20") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -65 << 20 + << 10 << 10; + + // Should move header even if contentY doesn't move (its aligned with top) + QTest::newRow("PullbackHeader TopToBottom -55+5") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -55 << 5 + << 20 << -10; + + // Should move header even if contentY doesn't move (it's aligned with header) + QTest::newRow("PullbackHeader TopToBottom -76+16") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -76 << 16 + << 30 << 30; + + // -------------------- + // PullbackHeader BottomToTop + QTest::newRow("PullbackHeader BottomToTop +2") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +2 << 0 + << -170 << 0; + + QTest::newRow("PullbackHeader BottomToTop +9") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +9 << 0 + << -170 << 0; + + QTest::newRow("PullbackHeader BottomToTop +11") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +11 << 0 + << -190 << -20; + + QTest::newRow("PullbackHeader BottomToTop +14") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +14 << 0 + << -190 << -20; + + QTest::newRow("PullbackHeader BottomToTop +16") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +16 << 0 + << -200 << 0; + + QTest::newRow("PullbackHeader BottomToTop +20") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +20 << 0 + << -200 << 0; + + QTest::newRow("PullbackHeader BottomToTop +65-10") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +65 << -10 + << -220 << -20; + + QTest::newRow("PullbackHeader BottomToTop +65-20") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +65 << -20 + << -210 << -40; + + // Should move header even if contentY doesn't move (it's aligned with top) + QTest::newRow("PullbackHeader BottomToTop +55-5") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << 55 << -5 + << -220 << -20; + + // Should move header even if contentY doesn't move (it's aligned with header) + QTest::newRow("PullbackHeader BottomToTop +76-16") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << 76 << -16 + << -230 << -60; + + // -------------------- + // PullbackHeader LeftToRight + QTest::newRow("PullbackHeader LeftToRight -2") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -2 << 0 + << -30 << -30; + + QTest::newRow("PullbackHeader LeftToRight -10") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -10 << 0 + << -30 << -30; + + QTest::newRow("PullbackHeader LeftToRight -11") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -11 << 0 + << -10 << -10; + + QTest::newRow("PullbackHeader LeftToRight -14") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -14 << 0 + << -10 << -10; + + QTest::newRow("PullbackHeader LeftToRight -16") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -16 << 0 + << 0 << -30; + + QTest::newRow("PullbackHeader LeftToRight -20") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -20 << 0 + << 0 << -30; + + QTest::newRow("PullbackHeader LeftToRight -65+10") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -65 << 10 + << 20 << -10; + + QTest::newRow("PullbackHeader LeftToRight -65+20") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -65 << 20 + << 10 << 10; + + // Should move header even if contentX doesn't move (its aligned with top) + QTest::newRow("PullbackHeader LeftToRight -55+5") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -55 << 5 + << 20 << -10; + + // Should move header even if contentX doesn't move (it's aligned with header) + QTest::newRow("PullbackHeader LeftToRight -76+16") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -76 << 16 + << 30 << 30; + + // -------------------- + // PullbackHeader RightToLeft + QTest::newRow("PullbackHeader RightToLeft +2") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +2 << 0 + << -210 << 0; + + QTest::newRow("PullbackHeader RightToLeft +9") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +9 << 0 + << -210 << 0; + + QTest::newRow("PullbackHeader RightToLeft +11") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +11 << 0 + << -230 << -20; + + QTest::newRow("PullbackHeader RightToLeft +14") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +14 << 0 + << -230 << -20; + + QTest::newRow("PullbackHeader RightToLeft +16") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +16 << 0 + << -240 << 0; + + QTest::newRow("PullbackHeader RightToLeft +20") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +20 << 0 + << -240 << 0; + + QTest::newRow("PullbackHeader RightToLeft +65-10") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +65 << -10 + << -260 << -20; + + QTest::newRow("PullbackHeader RightToLeft +65-20") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +65 << -20 + << -250 << -40; + + // Should move header even if contentX doesn't move (it's aligned with top) + QTest::newRow("PullbackHeader RightToLeft +55-5") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << 55 << -5 + << -260 << -20; + + // Should move header even if contentX doesn't move (it's aligned with header) + QTest::newRow("PullbackHeader RightToLeft +76-16") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << 76 << -16 + << -270 << -60; + +} + void tst_QQuickListView::snapOneItemResize_QTBUG_43555() { QScopedPointer<QQuickView> window(createView()); @@ -9263,6 +9867,7 @@ void tst_QQuickListView::reuse_checkThatItemsAreReused() window->resize(640, 480); window->show(); QVERIFY(QTest::qWaitForWindowExposed(window.data())); + QVERIFY(window->rootObject() != nullptr); QQuickListView *listView = findItem<QQuickListView>(window->rootObject(), "list"); QTRY_VERIFY(listView != nullptr); @@ -9431,6 +10036,60 @@ void tst_QQuickListView::changeModelAndDestroyTheOldOne() // QTBUG-80203 // no crash } +class DataObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString name READ name CONSTANT) + Q_PROPERTY(QString color READ color CONSTANT) + +public: + DataObject(QObject *parent = nullptr) : QObject(parent) {} + DataObject(const QString &name, const QString &color, QObject *parent = nullptr) + : QObject(parent), m_name(name), m_color(color) {} + + QString name() const { return m_name; } + QString color() const { return m_color; } + +private: + QString m_name; + QString m_color; +}; + +void tst_QQuickListView::requiredObjectListModel() +{ + QList<QObject *> dataList = { + new DataObject("Item 1", "red", this), + new DataObject("Item 2", "green", this), + new DataObject("Item 3", "blue", this), + new DataObject("Item 4", "yellow", this) + }; + + const auto deleter = qScopeGuard([&](){ qDeleteAll(dataList); }); + Q_UNUSED(deleter); + + QQuickView view; + view.setInitialProperties({{ "model", QVariant::fromValue(dataList) }}); + view.setSource(testFileUrl("requiredObjectListModel.qml")); + view.show(); + + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + const auto *root = qobject_cast<QQuickListView *>(view.rootObject()); + QVERIFY(root); + + QCOMPARE(root->count(), dataList.count()); + + for (int i = 0, end = dataList.count(); i != end; ++i) { + const auto *rect = qobject_cast<QQuickRectangle *>(root->itemAtIndex(i)); + QVERIFY(rect); + const auto *data = qobject_cast<DataObject *>(dataList.at(i)); + QVERIFY(data); + + QCOMPARE(rect->color(), QColor(data->color())); + QCOMPARE(rect->property("name").toString(), data->name()); + } +} + QTEST_MAIN(tst_QQuickListView) #include "tst_qquicklistview.moc" diff --git a/tests/auto/quick/qquickloader/data/statusChanged.qml b/tests/auto/quick/qquickloader/data/statusChanged.qml new file mode 100644 index 0000000000..fe46bc7b24 --- /dev/null +++ b/tests/auto/quick/qquickloader/data/statusChanged.qml @@ -0,0 +1,16 @@ +import QtQuick 2.12 +import QtQuick.Window 2.12 + +Window { + id: root + property int statusChangedCounter: 0 + property alias status: loader.status + visible: true; width: 640; height: 480 + Loader { + id: loader + anchors.fill: parent + asynchronous: true + source: "./RedRect.qml" + onStatusChanged: root.statusChangedCounter++ + } +} diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp index e05b7ae9ce..91d0bcab2e 100644 --- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp +++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp @@ -39,6 +39,7 @@ #include "testhttpserver.h" #include "../../shared/util.h" #include "../shared/geometrytestutil.h" +#include <QQmlApplicationEngine> Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests") @@ -128,6 +129,7 @@ private slots: void rootContext(); void sourceURLKeepComponent(); + void statusChangeOnlyEmittedOnce(); }; Q_DECLARE_METATYPE(QList<QQmlError>) @@ -1456,6 +1458,18 @@ void tst_QQuickLoader::sourceURLKeepComponent() } +// QTBUG-82002 +void tst_QQuickLoader::statusChangeOnlyEmittedOnce() +{ + QQmlApplicationEngine engine; + auto url = testFileUrl("statusChanged.qml"); + engine.load(url); + auto root = engine.rootObjects().at(0); + QVERIFY(root); + QTRY_COMPARE(QQuickLoader::Status(root->property("status").toInt()), QQuickLoader::Ready); + QCOMPARE(root->property("statusChangedCounter").toInt(), 2); // 1xLoading + 1xReady*/ +} + QTEST_MAIN(tst_QQuickLoader) #include "tst_qquickloader.moc" diff --git a/tests/auto/quick/qquickmousearea/BLACKLIST b/tests/auto/quick/qquickmousearea/BLACKLIST new file mode 100644 index 0000000000..089bb3a873 --- /dev/null +++ b/tests/auto/quick/qquickmousearea/BLACKLIST @@ -0,0 +1,10 @@ +[pressAndHold] +macos ci + +# QTBUG-78153 +[nestedStopAtBounds] +opensuse-leap + +# QTBUG-82282 +[pressOneAndTapAnother] +opensuse-leap diff --git a/tests/auto/quick/qquickopenglinfo/tst_qquickopenglinfo.cpp b/tests/auto/quick/qquickopenglinfo/tst_qquickopenglinfo.cpp index 3bf61e8f17..a4cbaa453d 100644 --- a/tests/auto/quick/qquickopenglinfo/tst_qquickopenglinfo.cpp +++ b/tests/auto/quick/qquickopenglinfo/tst_qquickopenglinfo.cpp @@ -32,7 +32,7 @@ #include <QtQuick/qquickitem.h> #include <QtQuick/qquickview.h> -#include <QtGui/qopenglcontext.h> +#include <qopenglcontext.h> #include <QtGui/qsurfaceformat.h> #include "../../shared/util.h" diff --git a/tests/auto/quick/qquicktextedit/BLACKLIST b/tests/auto/quick/qquicktextedit/BLACKLIST index 36c7f0042f..b8147a0ef9 100644 --- a/tests/auto/quick/qquicktextedit/BLACKLIST +++ b/tests/auto/quick/qquicktextedit/BLACKLIST @@ -4,3 +4,7 @@ opensuse-leap # QTBUG-78846 [mouseSelectionMode] opensuse-leap + +# QTBUG-82052 +[linkHover] +macos ci diff --git a/tests/auto/quick/qquicktextinput/BLACKLIST b/tests/auto/quick/qquicktextinput/BLACKLIST index ada7c57c75..6cd24de9a9 100644 --- a/tests/auto/quick/qquicktextinput/BLACKLIST +++ b/tests/auto/quick/qquicktextinput/BLACKLIST @@ -1,3 +1,7 @@ # QTBUG-78162 [mouseSelectionMode] opensuse-leap + +# QTBUG-82058 +[setInputMask] +macos ci diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp index 5b6b11c746..0bf83c267a 100644 --- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp +++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp @@ -1797,22 +1797,26 @@ void tst_qquickwindow::cursor() window.resize(320, 290); QQuickItem parentItem; + parentItem.setObjectName("parentItem"); parentItem.setPosition(QPointF(0, 0)); parentItem.setSize(QSizeF(180, 180)); parentItem.setParentItem(window.contentItem()); QQuickItem childItem; + childItem.setObjectName("childItem"); childItem.setPosition(QPointF(60, 90)); childItem.setSize(QSizeF(120, 120)); childItem.setParentItem(&parentItem); QQuickItem clippingItem; + clippingItem.setObjectName("clippingItem"); clippingItem.setPosition(QPointF(120, 120)); clippingItem.setSize(QSizeF(180, 180)); clippingItem.setClip(true); clippingItem.setParentItem(window.contentItem()); QQuickItem clippedItem; + clippedItem.setObjectName("clippedItem"); clippedItem.setPosition(QPointF(-30, -30)); clippedItem.setSize(QSizeF(120, 120)); clippedItem.setParentItem(&clippingItem); @@ -2856,7 +2860,7 @@ void tst_qquickwindow::pointerEventTypeAndPointCount() QList<QTouchEvent::TouchPoint>() << QTouchEvent::TouchPoint(1)); - QQuickPointerMouseEvent pme; + QQuickPointerMouseEvent pme(nullptr, QQuickPointerDevice::genericMouseDevice()); pme.reset(&me); QCOMPARE(pme.asMouseEvent(localPosition), &me); QVERIFY(pme.asPointerMouseEvent()); @@ -2868,7 +2872,7 @@ void tst_qquickwindow::pointerEventTypeAndPointCount() QCOMPARE(pme.asMouseEvent(localPosition)->localPos(), localPosition); QCOMPARE(pme.asMouseEvent(localPosition)->screenPos(), screenPosition); - QQuickPointerTouchEvent pte; + QQuickPointerTouchEvent pte(nullptr, QQuickPointerDevice::touchDevice(touchDevice)); pte.reset(&te); QCOMPARE(pte.asTouchEvent(), &te); QVERIFY(!pte.asPointerMouseEvent()); diff --git a/tests/auto/quick/rendernode/tst_rendernode.cpp b/tests/auto/quick/rendernode/tst_rendernode.cpp index e75e9e30b9..961531db6d 100644 --- a/tests/auto/quick/rendernode/tst_rendernode.cpp +++ b/tests/auto/quick/rendernode/tst_rendernode.cpp @@ -30,8 +30,8 @@ #include <QtQuick/qquickitem.h> #include <QtQuick/qquickview.h> -#include <QtGui/qopenglcontext.h> -#include <QtGui/qopenglfunctions.h> +#include <qopenglcontext.h> +#include <qopenglfunctions.h> #include <QtGui/qscreen.h> #include <private/qsgrendernode_p.h> diff --git a/tests/auto/quickwidgets/qquickwidget/BLACKLIST b/tests/auto/quickwidgets/qquickwidget/BLACKLIST index 18ea65bb72..095e9ee484 100644 --- a/tests/auto/quickwidgets/qquickwidget/BLACKLIST +++ b/tests/auto/quickwidgets/qquickwidget/BLACKLIST @@ -1,3 +1,5 @@ [tabKey] opensuse-42.3 opensuse-leap +[enterLeave] +macos diff --git a/tests/auto/shared/astdump.pri b/tests/auto/shared/astdump.pri new file mode 100644 index 0000000000..365b12fc51 --- /dev/null +++ b/tests/auto/shared/astdump.pri @@ -0,0 +1,7 @@ + +INCLUDEPATH += $$PWD +HEADERS += \ + $$PWD/qqmljsastdumper.h + +SOURCES += \ + $$PWD/qqmljsastdumper.cpp diff --git a/tests/auto/shared/qqmljsastdumper.cpp b/tests/auto/shared/qqmljsastdumper.cpp new file mode 100644 index 0000000000..1292be8d5b --- /dev/null +++ b/tests/auto/shared/qqmljsastdumper.cpp @@ -0,0 +1,1081 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +**/ +#include "qqmljsastdumper.h" +#include <private/qqmljsast_p.h> +#include <QtCore/QDebug> +#include <QtCore/QString> +#include <QtCore/QTextStream> + +QT_BEGIN_NAMESPACE + +namespace QQmlJS { +using namespace AST; +/*! +\internal +\enum QQmlJS::DumperOptions + +This enum type specifies the options for the AstDumper. +The values can be combined with the '|' operator, and checked using the '&' operator. + +\value None + Default dumping options +\value NoLocations + Does not dump SourceLocations, allowing one to compare equivalent AST + generated by code formatted differently +\value NoAnnotations + Does not dump annotations +\value DumpNode + Does dump a <Node></Node> in preVisit/postVisit +*/ + +/*! +\internal +\class QQmlJS::AstDumper +\brief Dumps or compares AST in an xml like format, mostly for testing/debugging + +Initialize it with a lambda that dumps a string, and configure it with .setX methods. +If \l{indent} is set to a non zero value the xml is indented by that amount, and +\l{baseIndent} is the initial indent. +If \l{emitNode} is true the node tag is emitted in the preVisit/postVisit. +If \l{emitLocation} is true the SourceLocations are emitted. +If \l{emitAnnotations} is true annotations are emitted + +The implementation has unnecessary roundtrips to QString, but it is supposed to be used +for debugging purposes... + +Probably you will not use the visitor at all but rather the static method diff or +the qDebug() and ostream operator << that use the visitor... + +\fn AstDumper::diff(AST::Node *n1, AST::Node *n2, int nContext, DumperOptions opt, int indent) + +\brief compares the two AST::Node n1 and n2 and returns a string describing their first difference + +If there are no differences the empty string is returned, so .isEmpty() can be use to check +for no differences. +\l{nContext} decides how much context is printed out. + +*/ + + +QDebug operator<<(QDebug d, AST::Node *n) { + QDebug noQuote = d.noquote().nospace(); + AstDumper visitor([&noQuote](const QString &s){ noQuote << s; }); + Node::accept(n, &visitor); + return d; +} + + +std::ostream &operator<<(std::ostream &stream, AST::Node *n) { + AstDumper visitor([&stream](const QString &s){ stream << s.toStdString(); }); + Node::accept(n, &visitor); + return stream; +} + +bool operator & (DumperOptions lhs, DumperOptions rhs) { + return bool(static_cast<int>(lhs) & static_cast<int>(rhs)); +} + +DumperOptions operator | (DumperOptions lhs, DumperOptions rhs) { + return DumperOptions(static_cast<int>(lhs) | static_cast<int>(rhs)); +} + +QString AstDumper::diff(AST::Node *n1, AST::Node *n2, int nContext, DumperOptions opt, int indent) { + QString s1, s2; + QTextStream d1(&s1), d2(&s2); + AstDumper visitor1=AstDumper([&d1](const QString &s){ d1 << s; }, opt, indent); + AstDumper visitor2=AstDumper([&d2](const QString &s){ d2 << s; }, opt, indent); + Node::accept(n1, &visitor1); + Node::accept(n2, &visitor2); + d1.seek(0); + d2.seek(0); + std::vector<QString> preLines(nContext); + int nLine = 0; + bool same = true; + QString l1, l2; + while (same && !d1.atEnd() && !d2.atEnd()) { + l1=d1.readLine(); + l2=d2.readLine(); + if (l1 == l2) + preLines[nLine++ % nContext] = l1; + else + same = false; + } + QString res; + QTextStream ss(&res); + if (!same || !d1.atEnd() || !d2.atEnd()) { + for (int iline = qMin(nLine, nContext); iline > 0; --iline) { + ss << QLatin1String(" ") << preLines[(nLine - iline) % nContext] << QLatin1String("\n"); + } + int iline = 0; + if (!same) { + ss << QLatin1String("-") << l1 << QLatin1String("\n"); + ++iline; + } + if (same && nContext == 0) + nContext = 1; + for (;iline < nContext && !d1.atEnd(); iline ++) { + l1 = d1.readLine(); + ss << QLatin1String("-") << l1 << QLatin1String("\n"); + } + iline = 0; + if (!same) { + ss << QLatin1String("+") << l2 << QLatin1String("\n"); + ++iline; + } + for (;iline < nContext && !d2.atEnd(); iline ++) { + l2 = d2.readLine(); + ss << QLatin1String("+") << l2 << QLatin1String("\n"); + } + } + return res; +} + +QString AstDumper::printNode(Node *n, DumperOptions opt, int indent, int baseIndent) +{ + QString res; + QTextStream d(&res); + AstDumper visitor=AstDumper([&d](const QString &s){ d << s; }, opt, indent, baseIndent); + Node::accept(n, &visitor); + return res; +} + +AstDumper::AstDumper(const std::function<void(const QString &)> &dumper, DumperOptions options, int indent, int baseIndent): + dumper(dumper), options(options), indent(indent), baseIndent(baseIndent) {} + +void AstDumper::start(const QString &str) { + dumper(QString::fromLatin1(" ").repeated(baseIndent)); + dumper(QLatin1String("<")); + dumper(str); + dumper(QLatin1String(">\n")); + baseIndent += indent; +} + +void AstDumper::start(const char *str) { + start(QLatin1String(str)); +} + +void AstDumper::stop(const QString &str) { + baseIndent -= indent; + dumper(QString::fromLatin1(" ").repeated(baseIndent)); + dumper(QLatin1String("</")); + dumper(str); + dumper(QLatin1String(">\n")); +} + +void AstDumper::stop(const char *str) { + stop(QLatin1String(str)); +} + +QString AstDumper::qs(const QString &s) { + QString res(s); + return QLatin1String("\"") + res + .replace(QLatin1String("\\"), QLatin1String("\\\\")) + .replace(QLatin1String("\""), QLatin1String("\\\"")) + QLatin1String("\""); +} + +QString AstDumper::qs(const char *s) { + return qs(QLatin1String(s)); +} + +QString AstDumper::qs(const QStringRef &s) { + return qs(s.toString()); +} + +QString AstDumper::loc(const SourceLocation &s) { + if (noLocations() || !s.isValid()) + return QLatin1String("\"\""); + else { + return QLatin1String("\"off:%1 len:%2 l:%3 c:%4\"").arg(QString::number(s.offset), QString::number(s.length), QString::number(s.startLine), QString::number(s.startColumn)); + } +} + +QString AstDumper::boolStr(bool v) { return (v ? qs("true"): qs("false")); } + +bool AstDumper::preVisit(Node *) { if (dumpNode()) start("Node"); return true; } + +void AstDumper::postVisit(Node *) { if (dumpNode()) stop("Node"); } + +bool AstDumper::visit(UiProgram *) { start("UiProgram"); return true; } + +bool AstDumper::visit(UiHeaderItemList *) { start("UiHeaderItemList"); return true; } + +bool AstDumper::visit(UiPragma *el) { + start(QLatin1String("UiPragma name=%1 pragmaToken=%2 semicolonToken=%3") + .arg(qs(el->name), loc(el->pragmaToken), loc(el->semicolonToken))); + return true; +} + +bool AstDumper::visit(UiImport *el) +{ + start(QLatin1String("UiImport fileName=%1 importId=%2 importToken=%3 fileNameToken=%4 asToken=%5 importIdToken=%6 semicolonToken=%7") + .arg(qs(el->fileName), qs(el->importId), loc(el->importToken), loc(el->fileNameToken), loc(el->asToken), loc(el->importIdToken), loc(el->semicolonToken))); + return true; +} + +bool AstDumper::visit(UiPublicMember *el) { + QString typeStr = ((el->type == UiPublicMember::Signal) ? QLatin1String("Signal") : + (el->type == UiPublicMember::Property) ? QLatin1String("Property") : QLatin1String("Unexpected(%1)").arg(el->type)); + start(QLatin1String("UiPublicMember type=%1 typeModifier=%2 name=%3 isDefaultMember=%4 isReadonlyMember=%5 isRequired=%6 " + "defaultToken=%7 readonlyToken=%8 propertyToken=%9 requiredToken=%10 typeModifierToken=%11 typeToken=%12 " + "identifierToken=%13 colonToken=%14 semicolonToken=%15") + .arg(qs(typeStr), qs(el->typeModifier), qs(el->name), + el->isDefaultMember, el->isReadonlyMember, el->isRequired, + loc(el->defaultToken), loc(el->readonlyToken), loc(el->propertyToken), + loc(el->requiredToken), loc(el->typeModifierToken), loc(el->typeToken), + loc(el->identifierToken), loc(el->colonToken), loc(el->semicolonToken) + )); + if (!noAnnotations()) // put annotations inside the node they refer to + Node::accept(el->annotations, this); + Node::accept(el->memberType, this); + return true; +} + +bool AstDumper::visit(AST::UiSourceElement *el) { + start(QLatin1String("UiSourceElement")); + if (!noAnnotations()) // put annotations inside the node they refer to + Node::accept(el->annotations, this); + return true; +} + +bool AstDumper::visit(AST::UiObjectDefinition *el) { + start("UiObjectDefinition"); + if (!noAnnotations()) // put annotations inside the node they refer to + Node::accept(el->annotations, this); + return true; +} + +bool AstDumper::visit(AST::UiObjectInitializer *el) { + start(QLatin1String("UiObjectInitializer lbraceToken=%1 rbraceToken=%2") + .arg(loc(el->lbraceToken), loc(el->rbraceToken))); + return true; +} + +bool AstDumper::visit(AST::UiObjectBinding *el) { + start(QLatin1String("UiObjectBinding colonToken=%1 hasOnToken=%2") + .arg(loc(el->colonToken), boolStr(el->hasOnToken))); + if (!noAnnotations()) // put annotations inside the node they refer to + Node::accept(el->annotations, this); + return true; +} + +bool AstDumper::visit(AST::UiScriptBinding *el) { + start(QLatin1String("UiScriptBinding colonToken=%1") + .arg(loc(el->colonToken))); + if (!noAnnotations()) // put annotations inside the node they refer to + Node::accept(el->annotations, this); + return true; +} + +bool AstDumper::visit(AST::UiArrayBinding *el) { + start(QLatin1String("UiArrayBinding colonToken=%1 lbracketToken=%2 rbracketToken=%3") + .arg(loc(el->colonToken), loc(el->lbracketToken), loc(el->rbracketToken))); + if (!noAnnotations()) // put annotations inside the node they refer to + Node::accept(el->annotations, this); + return true; +} + +bool AstDumper::visit(AST::UiParameterList *el) { + start(QLatin1String("UiArrayBinding name=%1 commaToken=%2 propertyTypeToken=%3 identifierToken=%4 colonToken=%5") + .arg(qs(el->name), loc(el->commaToken), loc(el->propertyTypeToken), loc(el->identifierToken), loc(el->colonToken))); + Node::accept(el->type, this); + return true; +} + +bool AstDumper::visit(AST::UiObjectMemberList *) { start("UiObjectMemberList"); return true; } + +bool AstDumper::visit(AST::UiArrayMemberList *el) { + start(QLatin1String("UiArrayMemberList commaToken=%1") + .arg(loc(el->commaToken))); + return true; +} + +bool AstDumper::visit(AST::UiQualifiedId *el) { + start(QLatin1String("UiQualifiedId name=%1 identifierToken=%2") + .arg(qs(el->name), loc(el->identifierToken))); + Node::accept(el->next, this); + return true; +} + +bool AstDumper::visit(AST::UiEnumDeclaration *el) { + start(QLatin1String("UiEnumDeclaration enumToken=%1 rbraceToken=%2 name=%3") + .arg(loc(el->enumToken), loc(el->rbraceToken), qs(el->name))); + if (!noAnnotations()) // put annotations inside the node they refer to + Node::accept(el->annotations, this); + return true; +} + +bool AstDumper::visit(AST::UiEnumMemberList *el) { + start(QLatin1String("UiEnumMemberList member=%1 value=%2 memberToken=%3 valueToken=%4") + .arg(qs(el->member), qs(QString::number(el->value)), loc(el->memberToken), loc(el->valueToken))); + return true; +} + +bool AstDumper::visit(AST::UiVersionSpecifier *el) { + start(QLatin1String("UiVersionSpecifier majorVersion=%1 minorVersion=%2 majorToken=%3 minorToken=%4") + .arg(qs(QString::number(el->version.majorVersion())), + qs(QString::number(el->version.minorVersion())), + loc(el->majorToken), loc(el->minorToken))); + return true; +} + +bool AstDumper::visit(AST::UiInlineComponent *el) { + start(QLatin1String("UiInlineComponent name=%1 componentToken=%2") + .arg(qs(el->name), loc(el->componentToken))); + if (!noAnnotations()) // put annotations inside the node they refer to + Node::accept(el->annotations, this); + return true; +} + +bool AstDumper::visit(UiRequired *el) +{ + start(QLatin1String("UiRequired name=%1 requiredToken=%2 semicolonToken=%3") + .arg(qs(el->name), loc(el->requiredToken), loc(el->semicolonToken))); + return true; +} + +bool AstDumper::visit(UiAnnotation *) +{ + start(QLatin1String("UiAnnotation")); + return true; +} + +bool AstDumper::visit(UiAnnotationList *) +{ + start(QLatin1String("UiAnnotationList")); + return true; +} + +void AstDumper::endVisit(AST::UiProgram *) { stop("UiProgram"); } + +void AstDumper::endVisit(AST::UiImport *el) { + Node::accept(el->version, this); + stop("UiImport"); +} + +void AstDumper::endVisit(AST::UiHeaderItemList *) { stop("UiHeaderItemList"); } + +void AstDumper::endVisit(AST::UiPragma *) { stop("UiPragma"); } + +void AstDumper::endVisit(AST::UiPublicMember *el) { + Node::accept(el->parameters, this); + stop("UiPublicMember"); +} + +void AstDumper::endVisit(AST::UiSourceElement *) { stop("UiSourceElement"); } +void AstDumper::endVisit(AST::UiObjectDefinition *) { stop("UiObjectDefinition"); } +void AstDumper::endVisit(AST::UiObjectInitializer *) { stop("UiObjectInitializer"); } +void AstDumper::endVisit(AST::UiObjectBinding *) { stop("UiObjectBinding"); } +void AstDumper::endVisit(AST::UiScriptBinding *) { stop("UiScriptBinding"); } +void AstDumper::endVisit(AST::UiArrayBinding *) { stop("UiArrayBinding"); } +void AstDumper::endVisit(AST::UiParameterList *el) { + stop("UiParameterList"); + Node::accept(el->next, this); // put other args at the same level as this one... +} +void AstDumper::endVisit(AST::UiObjectMemberList *) { stop("UiObjectMemberList"); } +void AstDumper::endVisit(AST::UiArrayMemberList *) { stop("UiArrayMemberList"); } +void AstDumper::endVisit(AST::UiQualifiedId *) { stop("UiQualifiedId"); } +void AstDumper::endVisit(AST::UiEnumDeclaration *) { stop("UiEnumDeclaration"); } +void AstDumper::endVisit(AST::UiEnumMemberList *el) { + stop("UiEnumMemberList"); + Node::accept(el->next, this); // put other enum members at the same level as this one... +} +void AstDumper::endVisit(AST::UiVersionSpecifier *) { stop("UiVersionSpecifier"); } +void AstDumper::endVisit(AST::UiInlineComponent *) { stop("UiInlineComponent"); } +void AstDumper::endVisit(UiRequired *) { stop("UiRequired"); } +void AstDumper::endVisit(UiAnnotation *) { stop("UiAnnotation"); } +void AstDumper::endVisit(UiAnnotationList *) { stop("UiAnnotationList"); } + +// QQmlJS +bool AstDumper::visit(AST::ThisExpression *el) { + start(QLatin1String("ThisExpression thisToken=%1") + .arg(loc(el->thisToken))); + return true; +} +void AstDumper::endVisit(AST::ThisExpression *) { stop("ThisExpression"); } + +bool AstDumper::visit(AST::IdentifierExpression *el) { + start(QLatin1String("IdentifierExpression name=%1 identiferToken=%2") + .arg(qs(el->name), loc(el->identifierToken))); + return true; +} +void AstDumper::endVisit(AST::IdentifierExpression *) { stop("IdentifierExpression"); } + +bool AstDumper::visit(AST::NullExpression *el) { + start(QLatin1String("NullExpression nullToken=%1") + .arg(loc(el->nullToken))); + return true; +} +void AstDumper::endVisit(AST::NullExpression *) { stop("NullExpression"); } + +bool AstDumper::visit(AST::TrueLiteral *el) { + start(QLatin1String("TrueLiteral trueToken=%1") + .arg(loc(el->trueToken))); + return true; +} +void AstDumper::endVisit(AST::TrueLiteral *) { stop("TrueLiteral"); } + +bool AstDumper::visit(AST::FalseLiteral *el) { + start(QLatin1String("FalseLiteral falseToken=%1") + .arg(loc(el->falseToken))); + return true; +} +void AstDumper::endVisit(AST::FalseLiteral *) { stop("FalseLiteral"); } + +bool AstDumper::visit(AST::SuperLiteral *el) { + start(QLatin1String("SuperLiteral superToken=%1") + .arg(loc(el->superToken))); + return true; +} +void AstDumper::endVisit(AST::SuperLiteral *) { stop("SuperLiteral"); } + +bool AstDumper::visit(AST::StringLiteral *el) { + start(QLatin1String("StringLiteral value=%1 literalToken=%2") + .arg(qs(el->value), loc(el->literalToken))); + return true; +} +void AstDumper::endVisit(AST::StringLiteral *) { stop("StringLiteral"); } + +bool AstDumper::visit(AST::TemplateLiteral *el) { + start(QLatin1String("TemplateLiteral value=%1 rawValue=%2 literalToken=%3") + .arg(qs(el->value), qs(el->rawValue), loc(el->literalToken))); + Node::accept(el->expression, this); + return true; +} +void AstDumper::endVisit(AST::TemplateLiteral *) { stop("TemplateLiteral"); } + +bool AstDumper::visit(AST::NumericLiteral *el) { + start(QLatin1String("NumericLiteral value=%1 literalToken=%2") + .arg(qs(QString::number(el->value)), loc(el->literalToken))); + return true; +} +void AstDumper::endVisit(AST::NumericLiteral *) { stop("NumericLiteral"); } + +bool AstDumper::visit(AST::RegExpLiteral *el) { + start(QLatin1String("RegExpLiteral pattern=%1 flags=%2 literalToken=%3") + .arg(qs(el->pattern), qs(QString::number(el->flags, 16)), loc(el->literalToken))); + return true; +} +void AstDumper::endVisit(AST::RegExpLiteral *) { stop("RegExpLiteral"); } + +bool AstDumper::visit(AST::ArrayPattern *el) { + start(QLatin1String("ArrayPattern lbracketToken=%1, commaToken=%2, rbracketToken=%3 parseMode=%4") + .arg(loc(el->lbracketToken),loc(el->commaToken),loc(el->rbracketToken), qs(QString::number(el->parseMode, 16)))); + return true; +} +void AstDumper::endVisit(AST::ArrayPattern *) { stop("ArrayPattern"); } + +bool AstDumper::visit(AST::ObjectPattern *el) { + start(QLatin1String("ObjectPattern lbraceToken=%1 rbraceToken=%2 parseMode=%3") + .arg(loc(el->lbraceToken), loc(el->rbraceToken), qs(QString::number(el->parseMode, 16)))); + return true; +} +void AstDumper::endVisit(AST::ObjectPattern *) { stop("ObjectPattern"); } + +bool AstDumper::visit(AST::PatternElementList *) { start("PatternElementList"); return true; } +void AstDumper::endVisit(AST::PatternElementList *) { stop("PatternElementList"); } + +bool AstDumper::visit(AST::PatternPropertyList *) { start("PatternPropertyList"); return true; } +void AstDumper::endVisit(AST::PatternPropertyList *) { stop("PatternPropertyList"); } + +bool AstDumper::visit(AST::PatternElement *el) { + start(QLatin1String("PatternElement identifierToken=%1 bindingIdentifier=%2 type=%3 scope=%4 isForDeclaration=%5") + .arg(loc(el->identifierToken), qs(el->bindingIdentifier), qs(QString::number(el->type, 16)), + qs(QString::number(static_cast<int>(el->scope), 16)), boolStr(el->isForDeclaration))); + return true; +} +void AstDumper::endVisit(AST::PatternElement *) { stop("PatternElement"); } + +bool AstDumper::visit(AST::PatternProperty *el) { + start(QLatin1String("PatternProperty identifierToken=%1 bindingIdentifier=%2 type=%3 scope=%4 isForDeclaration=%5 colonToken=%6") + .arg(loc(el->identifierToken), qs(el->bindingIdentifier), qs(QString::number(el->type, 16)), + qs(QString::number(static_cast<int>(el->scope), 16)), boolStr(el->isForDeclaration), loc(el->colonToken))); + return true; +} +void AstDumper::endVisit(AST::PatternProperty *) { stop("PatternProperty"); } + +bool AstDumper::visit(AST::Elision *el) { + start(QLatin1String("Elision commaToken=%1") + .arg(loc(el->commaToken))); + return true; +} +void AstDumper::endVisit(AST::Elision *el) { + stop("Elision"); + Node::accept(el->next, this); // emit other elisions at the same level +} + +bool AstDumper::visit(AST::NestedExpression *el) { + start(QLatin1String("NestedExpression lparenToken=%1 rparenToken=%2") + .arg(loc(el->lparenToken), loc(el->rparenToken))); + return true; +} +void AstDumper::endVisit(AST::NestedExpression *) { stop("NestedExpression"); } + +bool AstDumper::visit(AST::IdentifierPropertyName *el) { + start(QLatin1String("IdentifierPropertyName id=%1 propertyNameToken=%2") + .arg(qs(el->id), loc(el->propertyNameToken))); + return true; +} +void AstDumper::endVisit(AST::IdentifierPropertyName *) { stop("IdentifierPropertyName"); } + +bool AstDumper::visit(AST::StringLiteralPropertyName *el) { + start(QLatin1String("StringLiteralPropertyName id=%1 propertyNameToken=%2") + .arg(qs(el->id), loc(el->propertyNameToken))); + return true; +} +void AstDumper::endVisit(AST::StringLiteralPropertyName *) { stop("StringLiteralPropertyName"); } + +bool AstDumper::visit(AST::NumericLiteralPropertyName *el) { + start(QLatin1String("NumericLiteralPropertyName id=%1 propertyNameToken=%2") + .arg(qs(QString::number(el->id)),loc(el->propertyNameToken))); + return true; +} +void AstDumper::endVisit(AST::NumericLiteralPropertyName *) { stop("NumericLiteralPropertyName"); } + +bool AstDumper::visit(AST::ComputedPropertyName *) { + start(QLatin1String("ComputedPropertyName")); + return true; +} +void AstDumper::endVisit(AST::ComputedPropertyName *) { stop("ComputedPropertyName"); } + +bool AstDumper::visit(AST::ArrayMemberExpression *el) { + start(QLatin1String("ArrayMemberExpression lbraketToken=%1 rbraketToken=%2") + .arg(loc(el->lbracketToken), loc(el->rbracketToken))); + return true; +} +void AstDumper::endVisit(AST::ArrayMemberExpression *) { stop("ArrayMemberExpression"); } + +bool AstDumper::visit(AST::FieldMemberExpression *el) { + start(QLatin1String("FieldMemberExpression name=%1 dotToken=%2 identifierToken=%3") + .arg(qs(el->name), loc(el->dotToken), loc(el->identifierToken))); + return true; +} +void AstDumper::endVisit(AST::FieldMemberExpression *) { stop("FieldMemberExpression"); } + +bool AstDumper::visit(AST::TaggedTemplate *) { + start(QLatin1String("TaggedTemplate")); + return true; +} +void AstDumper::endVisit(AST::TaggedTemplate *) { stop("TaggedTemplate"); } + +bool AstDumper::visit(AST::NewMemberExpression *el) { + start(QLatin1String("NewMemberExpression newToken=%1 lparenToken=%2 rparenToken=%3") + .arg(loc(el->newToken), loc(el->lparenToken), loc(el->rparenToken))); + return true; +} +void AstDumper::endVisit(AST::NewMemberExpression *) { stop("NewMemberExpression"); } + +bool AstDumper::visit(AST::NewExpression *el) { + start(QLatin1String("NewExpression newToken=%1") + .arg(loc(el->newToken))); + return true; +} +void AstDumper::endVisit(AST::NewExpression *) { stop("NewExpression"); } + +bool AstDumper::visit(AST::CallExpression *el) { + start(QLatin1String("CallExpression lparenToken=%1 rparenToken=%2") + .arg(loc(el->lparenToken), loc(el->rparenToken))); + return true; +} +void AstDumper::endVisit(AST::CallExpression *) { stop("CallExpression"); } + +bool AstDumper::visit(AST::ArgumentList *el) { + start(QLatin1String("ArgumentList commaToken=%1 isSpreadElement=%2") + .arg(loc(el->commaToken), boolStr(el->isSpreadElement))); + return true; +} +void AstDumper::endVisit(AST::ArgumentList *) { stop("ArgumentList"); } + +bool AstDumper::visit(AST::PostIncrementExpression *el) { + start(QLatin1String("PostIncrementExpression incrementToken=%1") + .arg(loc(el->incrementToken))); + return true; +} +void AstDumper::endVisit(AST::PostIncrementExpression *) { stop("PostIncrementExpression"); } + +bool AstDumper::visit(AST::PostDecrementExpression *el) { + start(QLatin1String("PostDecrementExpression decrementToken=%1") + .arg(loc(el->decrementToken))); + return true; +} +void AstDumper::endVisit(AST::PostDecrementExpression *) { stop("PostDecrementExpression"); } + +bool AstDumper::visit(AST::DeleteExpression *el) { + start(QLatin1String("DeleteExpression deleteToken=%1") + .arg(loc(el->deleteToken))); + return true; +} +void AstDumper::endVisit(AST::DeleteExpression *) { stop("DeleteExpression"); } + +bool AstDumper::visit(AST::VoidExpression *el) { + start(QLatin1String("VoidExpression voidToken=%1") + .arg(loc(el->voidToken))); + return true; +} +void AstDumper::endVisit(AST::VoidExpression *) { stop("VoidExpression"); } + +bool AstDumper::visit(AST::TypeOfExpression *el) { + start(QLatin1String("TypeOfExpression typeofToken=%1") + .arg(loc(el->typeofToken))); + return true; +} +void AstDumper::endVisit(AST::TypeOfExpression *) { stop("TypeOfExpression"); } + +bool AstDumper::visit(AST::PreIncrementExpression *el) { + start(QLatin1String("PreIncrementExpression incrementToken=%1") + .arg(loc(el->incrementToken))); + return true; +} +void AstDumper::endVisit(AST::PreIncrementExpression *) { stop("PreIncrementExpression"); } + +bool AstDumper::visit(AST::PreDecrementExpression *el) { + start(QLatin1String("PreDecrementExpression decrementToken=%1") + .arg(loc(el->decrementToken))); + return true; +} +void AstDumper::endVisit(AST::PreDecrementExpression *) { stop("PreDecrementExpression"); } + +bool AstDumper::visit(AST::UnaryPlusExpression *el) { + start(QLatin1String("UnaryPlusExpression plusToken=%1") + .arg(loc(el->plusToken))); + return true; +} +void AstDumper::endVisit(AST::UnaryPlusExpression *) { stop("UnaryPlusExpression"); } + +bool AstDumper::visit(AST::UnaryMinusExpression *el) { + start(QLatin1String("UnaryMinusExpression minusToken=%1") + .arg(loc(el->minusToken))); + return true; +} +void AstDumper::endVisit(AST::UnaryMinusExpression *) { stop("UnaryMinusExpression"); } + +bool AstDumper::visit(AST::TildeExpression *el) { + start(QLatin1String("TildeExpression tildeToken=%1") + .arg(loc(el->tildeToken))); + return true; +} +void AstDumper::endVisit(AST::TildeExpression *) { stop("TildeExpression"); } + +bool AstDumper::visit(AST::NotExpression *el) { + start(QLatin1String("NotExpression notToken=%1") + .arg(loc(el->notToken))); + return true; +} +void AstDumper::endVisit(AST::NotExpression *) { stop("NotExpression"); } + +bool AstDumper::visit(AST::BinaryExpression *el) { + start(QLatin1String("BinaryExpression op=%1 operatorToken=%2") + .arg(qs(QString::number(el->op,16)), loc(el->operatorToken))); + return true; +} +void AstDumper::endVisit(AST::BinaryExpression *) { stop("BinaryExpression"); } + +bool AstDumper::visit(AST::ConditionalExpression *el) { + start(QLatin1String("ConditionalExpression questionToken=%1 colonToken=%2") + .arg(loc(el->questionToken), loc(el->colonToken))); + return true; +} +void AstDumper::endVisit(AST::ConditionalExpression *) { stop("ConditionalExpression"); } + +bool AstDumper::visit(AST::Expression *el) { + start(QLatin1String("Expression commaToken=%1") + .arg(loc(el->commaToken))); + return true; +} +void AstDumper::endVisit(AST::Expression *) { stop("Expression"); } + +bool AstDumper::visit(AST::Block *el) { + start(QLatin1String("Block lbraceToken=%1 rbraceToken=%2") + .arg(loc(el->lbraceToken), loc(el->rbraceToken))); + return true; +} +void AstDumper::endVisit(AST::Block *) { stop("Block"); } + +bool AstDumper::visit(AST::StatementList *) { + start(QLatin1String("StatementList")); + return true; +} +void AstDumper::endVisit(AST::StatementList *) { stop("StatementList"); } + +bool AstDumper::visit(AST::VariableStatement *el) { + start(QLatin1String("VariableStatement declarationKindToken=%1") + .arg(loc(el->declarationKindToken))); + return true; +} +void AstDumper::endVisit(AST::VariableStatement *) { stop("VariableStatement"); } + +bool AstDumper::visit(AST::VariableDeclarationList *el) { + start(QLatin1String("VariableDeclarationList commaToken=%1") + .arg(loc(el->commaToken))); + return true; +} +void AstDumper::endVisit(AST::VariableDeclarationList *) { stop("VariableDeclarationList"); } + +bool AstDumper::visit(AST::EmptyStatement *el) { + start(QLatin1String("EmptyStatement semicolonToken=%1") + .arg(loc(el->semicolonToken))); + return true; +} +void AstDumper::endVisit(AST::EmptyStatement *) { stop("EmptyStatement"); } + +bool AstDumper::visit(AST::ExpressionStatement *el) { + start(QLatin1String("ExpressionStatement semicolonToken=%1") + .arg(loc(el->semicolonToken))); + return true; +} +void AstDumper::endVisit(AST::ExpressionStatement *) { stop("ExpressionStatement"); } + +bool AstDumper::visit(AST::IfStatement *el) { + start(QLatin1String("IfStatement ifToken=%1 lparenToken=%2 rparenToken=%3 elseToken=%4") + .arg(loc(el->ifToken), loc(el->lparenToken), loc(el->rparenToken), loc(el->elseToken))); + return true; +} +void AstDumper::endVisit(AST::IfStatement *) { stop("IfStatement"); } + +bool AstDumper::visit(AST::DoWhileStatement *el) { + start(QLatin1String("DoWhileStatement doToken=%1 whileToken=%2 lparenToken=%3 rparenToken=%4 semicolonToken=%5") + .arg(loc(el->doToken), loc(el->whileToken), loc(el->lparenToken), loc(el->rparenToken), loc(el->semicolonToken))); + return true; +} +void AstDumper::endVisit(AST::DoWhileStatement *) { stop("DoWhileStatement"); } + +bool AstDumper::visit(AST::WhileStatement *el) { + start(QLatin1String("WhileStatement whileToken=%1 lparenToken=%2 rparenToken=%3") + .arg(loc(el->whileToken), loc(el->lparenToken), loc(el->rparenToken))); + return true; +} +void AstDumper::endVisit(AST::WhileStatement *) { stop("WhileStatement"); } + +bool AstDumper::visit(AST::ForStatement *el) { + start(QLatin1String("ForStatement forToken=%1 lparenToken=%2 firstSemicolonToken=%3 secondSemicolonToken=%4 rparenToken=%5") + .arg(loc(el->forToken), loc(el->lparenToken), loc(el->firstSemicolonToken), loc(el->secondSemicolonToken), loc(el->rparenToken))); + return true; +} +void AstDumper::endVisit(AST::ForStatement *) { stop("ForStatement"); } + +bool AstDumper::visit(AST::ForEachStatement *el) { + start(QLatin1String("ForEachStatement forToken=%1 lparenToken=%2 inOfToken=%3 rparenToken=%4 type=%5") + .arg(loc(el->forToken), loc(el->lparenToken), loc(el->inOfToken), loc(el->rparenToken), qs(QString::number(static_cast<int>(el->type), 16)))); + return true; +} +void AstDumper::endVisit(AST::ForEachStatement *) { stop("ForEachStatement"); } + +bool AstDumper::visit(AST::ContinueStatement *el) { + start(QLatin1String("ContinueStatement label=%1 continueToken=%2 identifierToken=%3 semicolonToken=%4") + .arg(qs(el->label), loc(el->continueToken), loc(el->identifierToken), loc(el->semicolonToken))); + return true; +} +void AstDumper::endVisit(AST::ContinueStatement *) { stop("ContinueStatement"); } + +bool AstDumper::visit(AST::BreakStatement *el) { + start(QLatin1String("BreakStatement label=%1 breakToken=%2 identifierToken=%3 semicolonToken=%4") + .arg(qs(el->label), loc(el->breakToken), loc(el->identifierToken), loc(el->semicolonToken))); + return true; +} +void AstDumper::endVisit(AST::BreakStatement *) { stop("BreakStatement"); } + +bool AstDumper::visit(AST::ReturnStatement *el) { + start(QLatin1String("ReturnStatement returnToken=%1 semicolonToken=%2") + .arg(loc(el->returnToken), loc(el->semicolonToken))); + return true; +} +void AstDumper::endVisit(AST::ReturnStatement *) { stop("ReturnStatement"); } + +bool AstDumper::visit(AST::YieldExpression *el) { + start(QLatin1String("YieldExpression isYieldStar=%1 yieldToken=%2") + .arg(boolStr(el->isYieldStar), loc(el->yieldToken))); + return true; +} +void AstDumper::endVisit(AST::YieldExpression *) { stop("YieldExpression"); } + +bool AstDumper::visit(AST::WithStatement *el) { + start(QLatin1String("WithStatement withToken=%1 lparenToken=%2 rparenToken=%3") + .arg(loc(el->withToken), loc(el->lparenToken), loc(el->rparenToken))); + return true; +} +void AstDumper::endVisit(AST::WithStatement *) { stop("WithStatement"); } + +bool AstDumper::visit(AST::SwitchStatement *el) { + start(QLatin1String("SwitchStatement switchToken=%1 lparenToken=%2 rparenToken=%3") + .arg(loc(el->switchToken), loc(el->lparenToken), loc(el->rparenToken))); + return true; +} +void AstDumper::endVisit(AST::SwitchStatement *) { stop("SwitchStatement"); } + +bool AstDumper::visit(AST::CaseBlock *el) { + start(QLatin1String("CaseBlock lbraceToken=%1 rbraceToken=%2") + .arg(loc(el->lbraceToken), loc(el->rbraceToken))); + return true; +} +void AstDumper::endVisit(AST::CaseBlock *) { stop("CaseBlock"); } + +bool AstDumper::visit(AST::CaseClauses *) { + start(QLatin1String("CaseClauses")); + return true; +} +void AstDumper::endVisit(AST::CaseClauses *) { stop("CaseClauses"); } + +bool AstDumper::visit(AST::CaseClause *el) { + start(QLatin1String("CaseClause caseToken=%1 colonToken=%2") + .arg(loc(el->caseToken), loc(el->colonToken))); + return true; +} +void AstDumper::endVisit(AST::CaseClause *) { stop("CaseClause"); } + +bool AstDumper::visit(AST::DefaultClause *el) { + start(QLatin1String("DefaultClause defaultToken=%1 colonToken=%2") + .arg(loc(el->defaultToken), loc(el->colonToken))); + return true; +} +void AstDumper::endVisit(AST::DefaultClause *) { stop("DefaultClause"); } + +bool AstDumper::visit(AST::LabelledStatement *el) { + start(QLatin1String("LabelledStatement label=%1 identifierToken=%2 colonToken=%3") + .arg(qs(el->label), loc(el->identifierToken), loc(el->colonToken))); + return true; +} +void AstDumper::endVisit(AST::LabelledStatement *) { stop("LabelledStatement"); } + +bool AstDumper::visit(AST::ThrowStatement *el) { + start(QLatin1String("ThrowStatement throwToken=%1 semicolonToken=%2") + .arg(loc(el->throwToken), loc(el->semicolonToken))); + return true; +} +void AstDumper::endVisit(AST::ThrowStatement *) { stop("ThrowStatement"); } + +bool AstDumper::visit(AST::TryStatement *el) { + start(QLatin1String("TryStatement tryToken=%1") + .arg(loc(el->tryToken))); + return true; +} +void AstDumper::endVisit(AST::TryStatement *) { stop("TryStatement"); } + +bool AstDumper::visit(AST::Catch *el) { + start(QLatin1String("Catch catchToken=%1 lparenToken=%2 identifierToken=%3 rparenToken=%4") + .arg(loc(el->catchToken), loc(el->lparenToken), loc(el->identifierToken), loc(el->rparenToken))); + return true; +} +void AstDumper::endVisit(AST::Catch *) { stop("Catch"); } + +bool AstDumper::visit(AST::Finally *el) { + start(QLatin1String("Finally finallyToken=%1") + .arg(loc(el->finallyToken))); + return true; +} +void AstDumper::endVisit(AST::Finally *) { stop("Finally"); } + +bool AstDumper::visit(AST::FunctionDeclaration *el) { + start(QLatin1String("FunctionDeclaration name=%1 isArrowFunction=%2 isGenerator=%3 functionToken=%4 " + "identifierToken=%5 lparenToken=%6 rparenToken=%7 lbraceToken=%8 rbraceToken=%9") + .arg(qs(el->name), boolStr(el->isArrowFunction), boolStr(el->isGenerator), loc(el->functionToken), + loc(el->identifierToken), loc(el->lparenToken), loc(el->rparenToken), loc(el->lbraceToken), + loc(el->rbraceToken))); + return true; +} +void AstDumper::endVisit(AST::FunctionDeclaration *) { stop("FunctionDeclaration"); } + +bool AstDumper::visit(AST::FunctionExpression *el) { + start(QLatin1String("FunctionExpression name=%1 isArrowFunction=%2 isGenerator=%3 functionToken=%4 " + "identifierToken=%5 lparenToken=%6 rparenToken=%7 lbraceToken=%8 rbraceToken=%9") + .arg(qs(el->name), boolStr(el->isArrowFunction), boolStr(el->isGenerator), loc(el->functionToken), + loc(el->identifierToken), loc(el->lparenToken), loc(el->rparenToken), loc(el->lbraceToken), + loc(el->rbraceToken))); + return true; +} +void AstDumper::endVisit(AST::FunctionExpression *) { stop("FunctionExpression"); } + +bool AstDumper::visit(AST::FormalParameterList *) { + start(QLatin1String("FormalParameterList")); + return true; +} +void AstDumper::endVisit(AST::FormalParameterList *) { stop("FormalParameterList"); } + +bool AstDumper::visit(AST::ClassExpression *el) { + start(QLatin1String("ClassExpression name=%1 classToken=%2 identifierToken=%3 lbraceToken=%4 rbraceToken=%5") + .arg(qs(el->name), loc(el->classToken), loc(el->identifierToken), loc(el->lbraceToken), loc(el->rbraceToken))); + return true; +} +void AstDumper::endVisit(AST::ClassExpression *) { stop("ClassExpression"); } + +bool AstDumper::visit(AST::ClassDeclaration *el) { + start(QLatin1String("ClassDeclaration name=%1 classToken=%2 identifierToken=%3 lbraceToken=%4 rbraceToken=%5") + .arg(qs(el->name), loc(el->classToken), loc(el->identifierToken), loc(el->lbraceToken), loc(el->rbraceToken))); + return true; +} +void AstDumper::endVisit(AST::ClassDeclaration *) { stop("ClassDeclaration"); } + +bool AstDumper::visit(AST::ClassElementList *el) { + start(QLatin1String("ClassElementList isStatic=%1") + .arg(boolStr(el->isStatic))); + return true; +} +void AstDumper::endVisit(AST::ClassElementList *) { stop("ClassElementList"); } + +bool AstDumper::visit(AST::Program *) { + start(QLatin1String("Program")); + return true; +} +void AstDumper::endVisit(AST::Program *) { stop("Program"); } + +bool AstDumper::visit(AST::NameSpaceImport *el) { + start(QLatin1String("NameSpaceImport starToken=%1 importedBindingToken=%2 importedBinding=%3") + .arg(loc(el->starToken), loc(el->importedBindingToken), qs(el->importedBinding))); + return true; +} +void AstDumper::endVisit(AST::NameSpaceImport *) { stop("NameSpaceImport"); } + +bool AstDumper::visit(AST::ImportSpecifier *el) { + start(QLatin1String("ImportSpecifier identifierToken=%1 importedBindingToken=%2 identifier=%3 importedBinding=%4") + .arg(loc(el->identifierToken), loc(el->importedBindingToken), qs(el->identifier), qs(el->importedBinding))); + return true; +} +void AstDumper::endVisit(AST::ImportSpecifier *) { stop("ImportSpecifier"); } + +bool AstDumper::visit(AST::ImportsList *el) { + start(QLatin1String("ImportsList importSpecifierToken=%1") + .arg(loc(el->importSpecifierToken))); + return true; +} +void AstDumper::endVisit(AST::ImportsList *) { stop("ImportsList"); } + +bool AstDumper::visit(AST::NamedImports *el) { + start(QLatin1String("NamedImports leftBraceToken=%1 rightBraceToken=%2") + .arg(loc(el->leftBraceToken), loc(el->rightBraceToken))); + return true; +} +void AstDumper::endVisit(AST::NamedImports *) { stop("NamedImports"); } + +bool AstDumper::visit(AST::FromClause *el) { + start(QLatin1String("FromClause fromToken=%1 moduleSpecifierToken=%2 moduleSpecifier=%3") + .arg(loc(el->fromToken), loc(el->moduleSpecifierToken), qs(el->moduleSpecifier))); + return true; +} +void AstDumper::endVisit(AST::FromClause *) { stop("FromClause"); } + +bool AstDumper::visit(AST::ImportClause *el) { + start(QLatin1String("ImportClause importedDefaultBindingToken=%1 importedDefaultBinding=%2") + .arg(loc(el->importedDefaultBindingToken), qs(el->importedDefaultBinding))); + return true; +} +void AstDumper::endVisit(AST::ImportClause *) { stop("ImportClause"); } + +bool AstDumper::visit(AST::ImportDeclaration *el) { + start(QLatin1String("ImportDeclaration importToken=%1 moduleSpecifierToken=%2 moduleSpecifier=%3") + .arg(loc(el->importToken), loc(el->moduleSpecifierToken), qs(el->moduleSpecifier))); + return true; +} +void AstDumper::endVisit(AST::ImportDeclaration *) { stop("ImportDeclaration"); } + +bool AstDumper::visit(AST::ExportSpecifier *el) { + start(QLatin1String("ExportSpecifier identifierToken=%1 exportedIdentifierToken=%2 identifier=%3 exportedIdentifier=%4") + .arg(loc(el->identifierToken), loc(el->exportedIdentifierToken), qs(el->identifier), qs(el->exportedIdentifier))); + return true; +} +void AstDumper::endVisit(AST::ExportSpecifier *) { stop("ExportSpecifier"); } + +bool AstDumper::visit(AST::ExportsList *) { + start(QLatin1String("ExportsList")); + return true; +} +void AstDumper::endVisit(AST::ExportsList *) { stop("ExportsList"); } + +bool AstDumper::visit(AST::ExportClause *el) { + start(QLatin1String("ExportClause leftBraceToken=%1 rightBraceToken=%2") + .arg(loc(el->leftBraceToken), loc(el->rightBraceToken))); + return true; +} +void AstDumper::endVisit(AST::ExportClause *) { stop("ExportClause"); } + +bool AstDumper::visit(AST::ExportDeclaration *el) { + start(QLatin1String("ExportDeclaration exportToken=%1 exportAll=%2 exportDefault=%3") + .arg(loc(el->exportToken), boolStr(el->exportAll), boolStr(el->exportDefault))); + return true; +} +void AstDumper::endVisit(AST::ExportDeclaration *) { stop("ExportDeclaration"); } + +bool AstDumper::visit(AST::ESModule *) { + start(QLatin1String("ESModule")); + return true; +} +void AstDumper::endVisit(AST::ESModule *) { stop("ESModule"); } + +bool AstDumper::visit(AST::DebuggerStatement *el) { + start(QLatin1String("DebuggerStatement debuggerToken=%1 semicolonToken=%2") + .arg(loc(el->debuggerToken), loc(el->semicolonToken))); + return true; +} +void AstDumper::endVisit(AST::DebuggerStatement *) { stop("DebuggerStatement"); } + +bool AstDumper::visit(AST::Type *) { + start(QLatin1String("Type")); + return true; +} +void AstDumper::endVisit(AST::Type *) { stop("Type"); } + +bool AstDumper::visit(AST::TypeArgumentList *) { + start(QLatin1String("TypeArgumentList")); + return true; +} +void AstDumper::endVisit(AST::TypeArgumentList *) { stop("TypeArgumentList"); } + +bool AstDumper::visit(AST::TypeAnnotation *el) { + start(QLatin1String("TypeAnnotation colonToken=%1") + .arg(loc(el->colonToken))); + return true; +} +void AstDumper::endVisit(AST::TypeAnnotation *) { stop("TypeAnnotation"); } + +void AstDumper::throwRecursionDepthError() +{ + qDebug() << "Maximum statement or expression depth exceeded in AstDumper"; +} + +bool AstDumper::dumpNode() { + return options & DumperOptions::DumpNode; +} + +bool AstDumper::noLocations() { + return options & DumperOptions::NoLocations; +} + +bool AstDumper::noAnnotations() { + return options & DumperOptions::NoAnnotations; +} + +} // end namespace QQmlJS + +QT_END_NAMESPACE diff --git a/tests/auto/shared/qqmljsastdumper.h b/tests/auto/shared/qqmljsastdumper.h new file mode 100644 index 0000000000..5e46e516f0 --- /dev/null +++ b/tests/auto/shared/qqmljsastdumper.h @@ -0,0 +1,446 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +**/ +#ifndef ASTDUMPER_H +#define ASTDUMPER_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <private/qqmljsglobal_p.h> +#include <private/qqmljsastvisitor_p.h> +#include <QtCore/QString> +#include <functional> +#include <ostream> + +QT_BEGIN_NAMESPACE +class QDebug; + +namespace QQmlJS { + +enum class DumperOptions { + None=0, + NoLocations=0x1, + NoAnnotations=0x2, + DumpNode=0x4 +}; +bool operator & (DumperOptions lhs, DumperOptions rhs); +DumperOptions operator | (DumperOptions lhs, DumperOptions rhs); + +// no export, currently just a supporting file... +class AstDumper: public AST::BaseVisitor +{ +public: + static QString printNode2(AST::Node *); + + static QString diff(AST::Node *n1, AST::Node *n2, int nContext=3, DumperOptions opt=DumperOptions::None, int indent=0); + static QString printNode(AST::Node *n, DumperOptions opt=DumperOptions::None, int indent=1, int baseIndent=0); + + AstDumper(const std::function <void (const QString &)> &dumper, DumperOptions options=DumperOptions::None, + int indent=1, int baseIndent=0); + + void start(const QString &str); + void start(const char *str); + void stop(const QString &str); + void stop(const char *str); + + QString qs(const QString &s); + QString qs(const char *s); + QString qs(const QStringRef &s); + + QString loc(const SourceLocation &s); + + QString boolStr(bool v); + + bool preVisit(AST::Node *el) override; + void postVisit(AST::Node *el) override; + + // Ui + bool visit(AST::UiProgram *el) override; + bool visit(AST::UiHeaderItemList *) override; + bool visit(AST::UiPragma *el) override; + bool visit(AST::UiImport *el) override; + bool visit(AST::UiPublicMember *el) override; + bool visit(AST::UiSourceElement *) override; + bool visit(AST::UiObjectDefinition *) override; + bool visit(AST::UiObjectInitializer *) override; + bool visit(AST::UiObjectBinding *) override; + bool visit(AST::UiScriptBinding *) override; + bool visit(AST::UiArrayBinding *) override; + bool visit(AST::UiParameterList *) override; + bool visit(AST::UiObjectMemberList *) override; + bool visit(AST::UiArrayMemberList *) override; + bool visit(AST::UiQualifiedId *) override; + bool visit(AST::UiEnumDeclaration *) override; + bool visit(AST::UiEnumMemberList *) override; + bool visit(AST::UiVersionSpecifier *) override; + bool visit(AST::UiInlineComponent *) override; + bool visit(AST::UiRequired *) override; + bool visit(AST::UiAnnotation *) override; + bool visit(AST::UiAnnotationList *) override; + + void endVisit(AST::UiProgram *) override; + void endVisit(AST::UiImport *) override; + void endVisit(AST::UiHeaderItemList *) override; + void endVisit(AST::UiPragma *) override; + void endVisit(AST::UiPublicMember *) override; + void endVisit(AST::UiSourceElement *) override; + void endVisit(AST::UiObjectDefinition *) override; + void endVisit(AST::UiObjectInitializer *) override; + void endVisit(AST::UiObjectBinding *) override; + void endVisit(AST::UiScriptBinding *) override; + void endVisit(AST::UiArrayBinding *) override; + void endVisit(AST::UiParameterList *) override; + void endVisit(AST::UiObjectMemberList *) override; + void endVisit(AST::UiArrayMemberList *) override; + void endVisit(AST::UiQualifiedId *) override; + void endVisit(AST::UiEnumDeclaration *) override; + void endVisit(AST::UiEnumMemberList *) override; + void endVisit(AST::UiVersionSpecifier *) override; + void endVisit(AST::UiInlineComponent *) override; + void endVisit(AST::UiRequired *) override; + void endVisit(AST::UiAnnotation *) override; + void endVisit(AST::UiAnnotationList *) override; + + // QQmlJS + bool visit(AST::ThisExpression *) override; + void endVisit(AST::ThisExpression *) override; + + bool visit(AST::IdentifierExpression *) override; + void endVisit(AST::IdentifierExpression *) override; + + bool visit(AST::NullExpression *) override; + void endVisit(AST::NullExpression *) override; + + bool visit(AST::TrueLiteral *) override; + void endVisit(AST::TrueLiteral *) override; + + bool visit(AST::FalseLiteral *) override; + void endVisit(AST::FalseLiteral *) override; + + bool visit(AST::SuperLiteral *) override; + void endVisit(AST::SuperLiteral *) override; + + bool visit(AST::StringLiteral *) override; + void endVisit(AST::StringLiteral *) override; + + bool visit(AST::TemplateLiteral *) override; + void endVisit(AST::TemplateLiteral *) override; + + bool visit(AST::NumericLiteral *) override; + void endVisit(AST::NumericLiteral *) override; + + bool visit(AST::RegExpLiteral *) override; + void endVisit(AST::RegExpLiteral *) override; + + bool visit(AST::ArrayPattern *) override; + void endVisit(AST::ArrayPattern *) override; + + bool visit(AST::ObjectPattern *) override; + void endVisit(AST::ObjectPattern *) override; + + bool visit(AST::PatternElementList *) override; + void endVisit(AST::PatternElementList *) override; + + bool visit(AST::PatternPropertyList *) override; + void endVisit(AST::PatternPropertyList *) override; + + bool visit(AST::PatternElement *) override; + void endVisit(AST::PatternElement *) override; + + bool visit(AST::PatternProperty *) override; + void endVisit(AST::PatternProperty *) override; + + bool visit(AST::Elision *) override; + void endVisit(AST::Elision *) override; + + bool visit(AST::NestedExpression *) override; + void endVisit(AST::NestedExpression *) override; + + bool visit(AST::IdentifierPropertyName *) override; + void endVisit(AST::IdentifierPropertyName *) override; + + bool visit(AST::StringLiteralPropertyName *) override; + void endVisit(AST::StringLiteralPropertyName *) override; + + bool visit(AST::NumericLiteralPropertyName *) override; + void endVisit(AST::NumericLiteralPropertyName *) override; + + bool visit(AST::ComputedPropertyName *) override; + void endVisit(AST::ComputedPropertyName *) override; + + bool visit(AST::ArrayMemberExpression *) override; + void endVisit(AST::ArrayMemberExpression *) override; + + bool visit(AST::FieldMemberExpression *) override; + void endVisit(AST::FieldMemberExpression *) override; + + bool visit(AST::TaggedTemplate *) override; + void endVisit(AST::TaggedTemplate *) override; + + bool visit(AST::NewMemberExpression *) override; + void endVisit(AST::NewMemberExpression *) override; + + bool visit(AST::NewExpression *) override; + void endVisit(AST::NewExpression *) override; + + bool visit(AST::CallExpression *) override; + void endVisit(AST::CallExpression *) override; + + bool visit(AST::ArgumentList *) override; + void endVisit(AST::ArgumentList *) override; + + bool visit(AST::PostIncrementExpression *) override; + void endVisit(AST::PostIncrementExpression *) override; + + bool visit(AST::PostDecrementExpression *) override; + void endVisit(AST::PostDecrementExpression *) override; + + bool visit(AST::DeleteExpression *) override; + void endVisit(AST::DeleteExpression *) override; + + bool visit(AST::VoidExpression *) override; + void endVisit(AST::VoidExpression *) override; + + bool visit(AST::TypeOfExpression *) override; + void endVisit(AST::TypeOfExpression *) override; + + bool visit(AST::PreIncrementExpression *) override; + void endVisit(AST::PreIncrementExpression *) override; + + bool visit(AST::PreDecrementExpression *) override; + void endVisit(AST::PreDecrementExpression *) override; + + bool visit(AST::UnaryPlusExpression *) override; + void endVisit(AST::UnaryPlusExpression *) override; + + bool visit(AST::UnaryMinusExpression *) override; + void endVisit(AST::UnaryMinusExpression *) override; + + bool visit(AST::TildeExpression *) override; + void endVisit(AST::TildeExpression *) override; + + bool visit(AST::NotExpression *) override; + void endVisit(AST::NotExpression *) override; + + bool visit(AST::BinaryExpression *) override; + void endVisit(AST::BinaryExpression *) override; + + bool visit(AST::ConditionalExpression *) override; + void endVisit(AST::ConditionalExpression *) override; + + bool visit(AST::Expression *) override; + void endVisit(AST::Expression *) override; + + bool visit(AST::Block *) override; + void endVisit(AST::Block *) override; + + bool visit(AST::StatementList *) override; + void endVisit(AST::StatementList *) override; + + bool visit(AST::VariableStatement *) override; + void endVisit(AST::VariableStatement *) override; + + bool visit(AST::VariableDeclarationList *) override; + void endVisit(AST::VariableDeclarationList *) override; + + bool visit(AST::EmptyStatement *) override; + void endVisit(AST::EmptyStatement *) override; + + bool visit(AST::ExpressionStatement *) override; + void endVisit(AST::ExpressionStatement *) override; + + bool visit(AST::IfStatement *) override; + void endVisit(AST::IfStatement *) override; + + bool visit(AST::DoWhileStatement *) override; + void endVisit(AST::DoWhileStatement *) override; + + bool visit(AST::WhileStatement *) override; + void endVisit(AST::WhileStatement *) override; + + bool visit(AST::ForStatement *) override; + void endVisit(AST::ForStatement *) override; + + bool visit(AST::ForEachStatement *) override; + void endVisit(AST::ForEachStatement *) override; + + bool visit(AST::ContinueStatement *) override; + void endVisit(AST::ContinueStatement *) override; + + bool visit(AST::BreakStatement *) override; + void endVisit(AST::BreakStatement *) override; + + bool visit(AST::ReturnStatement *) override; + void endVisit(AST::ReturnStatement *) override; + + bool visit(AST::YieldExpression *) override; + void endVisit(AST::YieldExpression *) override; + + bool visit(AST::WithStatement *) override; + void endVisit(AST::WithStatement *) override; + + bool visit(AST::SwitchStatement *) override; + void endVisit(AST::SwitchStatement *) override; + + bool visit(AST::CaseBlock *) override; + void endVisit(AST::CaseBlock *) override; + + bool visit(AST::CaseClauses *) override; + void endVisit(AST::CaseClauses *) override; + + bool visit(AST::CaseClause *) override; + void endVisit(AST::CaseClause *) override; + + bool visit(AST::DefaultClause *) override; + void endVisit(AST::DefaultClause *) override; + + bool visit(AST::LabelledStatement *) override; + void endVisit(AST::LabelledStatement *) override; + + bool visit(AST::ThrowStatement *) override; + void endVisit(AST::ThrowStatement *) override; + + bool visit(AST::TryStatement *) override; + void endVisit(AST::TryStatement *) override; + + bool visit(AST::Catch *) override; + void endVisit(AST::Catch *) override; + + bool visit(AST::Finally *) override; + void endVisit(AST::Finally *) override; + + bool visit(AST::FunctionDeclaration *) override; + void endVisit(AST::FunctionDeclaration *) override; + + bool visit(AST::FunctionExpression *) override; + void endVisit(AST::FunctionExpression *) override; + + bool visit(AST::FormalParameterList *) override; + void endVisit(AST::FormalParameterList *) override; + + bool visit(AST::ClassExpression *) override; + void endVisit(AST::ClassExpression *) override; + + bool visit(AST::ClassDeclaration *) override; + void endVisit(AST::ClassDeclaration *) override; + + bool visit(AST::ClassElementList *) override; + void endVisit(AST::ClassElementList *) override; + + bool visit(AST::Program *) override; + void endVisit(AST::Program *) override; + + bool visit(AST::NameSpaceImport *) override; + void endVisit(AST::NameSpaceImport *) override; + + bool visit(AST::ImportSpecifier *) override; + void endVisit(AST::ImportSpecifier *) override; + + bool visit(AST::ImportsList *) override; + void endVisit(AST::ImportsList *) override; + + bool visit(AST::NamedImports *) override; + void endVisit(AST::NamedImports *) override; + + bool visit(AST::FromClause *) override; + void endVisit(AST::FromClause *) override; + + bool visit(AST::ImportClause *) override; + void endVisit(AST::ImportClause *) override; + + bool visit(AST::ImportDeclaration *) override; + void endVisit(AST::ImportDeclaration *) override; + + bool visit(AST::ExportSpecifier *) override; + void endVisit(AST::ExportSpecifier *) override; + + bool visit(AST::ExportsList *) override; + void endVisit(AST::ExportsList *) override; + + bool visit(AST::ExportClause *) override; + void endVisit(AST::ExportClause *) override; + + bool visit(AST::ExportDeclaration *) override; + void endVisit(AST::ExportDeclaration *) override; + + bool visit(AST::ESModule *) override; + void endVisit(AST::ESModule *) override; + + bool visit(AST::DebuggerStatement *) override; + void endVisit(AST::DebuggerStatement *) override; + + bool visit(AST::Type *) override; + void endVisit(AST::Type *) override; + + bool visit(AST::TypeArgumentList *) override; + void endVisit(AST::TypeArgumentList *) override; + + bool visit(AST::TypeAnnotation *) override; + void endVisit(AST::TypeAnnotation *) override; + + void throwRecursionDepthError() override; + +private: + // attributes + std::function <void (const QString &)> dumper; + DumperOptions options = DumperOptions::None; + int indent = 0; + int baseIndent = 0; + bool dumpNode(); + bool noLocations(); + bool noAnnotations(); +}; + +QDebug operator<<(QDebug d, AST::Node *n); + +std::ostream &operator<<(std::ostream &stream, AST::Node *n); + +} // namespace AST + +QT_END_NAMESPACE + +#endif // ASTDUMPER_H diff --git a/tests/benchmarks/qml/creation/tst_creation.cpp b/tests/benchmarks/qml/creation/tst_creation.cpp index ed2e52f869..2044360b3d 100644 --- a/tests/benchmarks/qml/creation/tst_creation.cpp +++ b/tests/benchmarks/qml/creation/tst_creation.cpp @@ -196,7 +196,7 @@ void tst_creation::qobject_10tree_cpp() void tst_creation::qobject_qmltype() { - QQmlType t = QQmlMetaType::qmlType("QtQuick/QtObject", 2, 0); + QQmlType t = QQmlMetaType::qmlType("QtQuick/QtObject", QTypeRevision::fromVersion(2, 0)); QBENCHMARK { QObject *obj = t.create(); diff --git a/tests/benchmarks/qml/painting/painting.pro b/tests/benchmarks/qml/painting/painting.pro index 633be76e30..9948df511a 100644 --- a/tests/benchmarks/qml/painting/painting.pro +++ b/tests/benchmarks/qml/painting/painting.pro @@ -1,7 +1,7 @@ requires(qtHaveModule(opengl)) requires(qtHaveModule(widgets)) -QT += opengl widgets +QT += opengl widgets openglwidgets CONFIG += console macx:CONFIG -= app_bundle diff --git a/tests/manual/pointer/main.qml b/tests/manual/pointer/main.qml index d382d8b23d..83e1d3b2ba 100644 --- a/tests/manual/pointer/main.qml +++ b/tests/manual/pointer/main.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the manual tests of the Qt Toolkit. @@ -57,6 +57,7 @@ Window { addExample("multibuttons", "TapHandler: gesturePolicy (99 red balloons)", Qt.resolvedUrl("multibuttons.qml")) addExample("flickable with Handlers", "Flickable with buttons, sliders etc. implemented in various ways", Qt.resolvedUrl("flickableWithHandlers.qml")) addExample("tap and drag", "Flickable with all possible combinations of TapHandler and DragHandler children", Qt.resolvedUrl("pointerDrag.qml")) + addExample("tablet canvas", "PointHandler and HoverHandler with a tablet: detect the stylus, and draw", Qt.resolvedUrl("tabletCanvasDrawing.qml")) } } Item { diff --git a/tests/manual/pointer/qml.qrc b/tests/manual/pointer/qml.qrc index 95bece180a..20956fcbac 100644 --- a/tests/manual/pointer/qml.qrc +++ b/tests/manual/pointer/qml.qrc @@ -13,6 +13,7 @@ <file>pointerDrag.qml</file> <file>singlePointHandlerProperties.qml</file> <file>sidebar.qml</file> + <file>tabletCanvasDrawing.qml</file> <file>tapHandler.qml</file> <file>content/CheckBox.qml</file> <file>content/FakeFlickable.qml</file> @@ -30,6 +31,10 @@ <file>content/TouchpointFeedbackSprite.qml</file> <file>resources/arrowhead.png</file> <file>resources/balloon.png</file> + <file>resources/cursor-airbrush.png</file> + <file>resources/cursor-eraser.png</file> + <file>resources/cursor-felt-marker.png</file> + <file>resources/cursor-pencil.png</file> <file>resources/fighter.png</file> <file>resources/fingersprite.png</file> <file>resources/grabbing-location.svg</file> diff --git a/tests/manual/pointer/resources/cursor-airbrush.png b/tests/manual/pointer/resources/cursor-airbrush.png Binary files differnew file mode 100644 index 0000000000..bea756ed6f --- /dev/null +++ b/tests/manual/pointer/resources/cursor-airbrush.png diff --git a/tests/manual/pointer/resources/cursor-eraser.png b/tests/manual/pointer/resources/cursor-eraser.png Binary files differnew file mode 100644 index 0000000000..e5488a89f2 --- /dev/null +++ b/tests/manual/pointer/resources/cursor-eraser.png diff --git a/tests/manual/pointer/resources/cursor-felt-marker.png b/tests/manual/pointer/resources/cursor-felt-marker.png Binary files differnew file mode 100644 index 0000000000..132f09aa39 --- /dev/null +++ b/tests/manual/pointer/resources/cursor-felt-marker.png diff --git a/tests/manual/pointer/resources/cursor-pencil.png b/tests/manual/pointer/resources/cursor-pencil.png Binary files differnew file mode 100644 index 0000000000..cc2f447d02 --- /dev/null +++ b/tests/manual/pointer/resources/cursor-pencil.png diff --git a/tests/manual/pointer/sidebar.qml b/tests/manual/pointer/sidebar.qml index 827dbd1980..b7370a4fb7 100644 --- a/tests/manual/pointer/sidebar.qml +++ b/tests/manual/pointer/sidebar.qml @@ -26,7 +26,7 @@ ** ****************************************************************************/ -import QtQuick 2.12 +import QtQuick 2.15 import "content" Rectangle { @@ -53,6 +53,7 @@ Rectangle { id: buttonMA objectName: "buttonMA" hoverEnabled: true + cursorShape: Qt.UpArrowCursor anchors.fill: parent onClicked: console.log("clicked MA") } @@ -75,9 +76,11 @@ Rectangle { id: buttonHH objectName: "buttonHH" acceptedDevices: PointerDevice.AllDevices + cursorShape: tapHandler.pressed ? Qt.BusyCursor : Qt.PointingHandCursor } TapHandler { + id: tapHandler onTapped: tapFlash.start() } @@ -148,6 +151,7 @@ Rectangle { HoverHandler { id: topSidebarHH objectName: "topSidebarHH" + cursorShape: Qt.OpenHandCursor } Loader { @@ -173,6 +177,7 @@ Rectangle { id: bottomSidebarMA objectName: "bottomSidebarMA" hoverEnabled: true + cursorShape: Qt.ClosedHandCursor anchors.fill: parent } diff --git a/tests/manual/pointer/tabletCanvasDrawing.qml b/tests/manual/pointer/tabletCanvasDrawing.qml new file mode 100644 index 0000000000..c340dee5f4 --- /dev/null +++ b/tests/manual/pointer/tabletCanvasDrawing.qml @@ -0,0 +1,242 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import "content" + +Rectangle { + width: 1024 + height: 1024 + color: "#444" + + ColumnLayout { + x: -15; width: 80 + height: parent.height + Slider { + id: hueSlider + width: 80; height: 200 + Layout.fillHeight: true + label: "hue" + Rectangle { + color: "beige" + width: 30 + height: 25 + anchors.bottom: parent.bottom + anchors.bottomMargin: 2 + anchors.horizontalCenter: parent.horizontalCenter + Rectangle { + border.color: "white" + color: canvas.drawingColor + anchors.fill: parent + } + } + } + Slider { + id: saturationSlider + width: 80; height: 200 + Layout.fillHeight: true + label: "sat" + } + Slider { + id: lightnessSlider + width: 80; height: 200 + Layout.fillHeight: true + label: "light" + } + } + + ColumnLayout { + x: parent.width - 65; width: 80 + height: parent.height + Slider { + id: widthSlider + width: 80; height: 200 + Layout.fillHeight: true + label: "width" + } + Slider { + id: alphaSlider + width: 80; height: 200 + Layout.fillHeight: true + label: "alpha" + } + } + + Rectangle { + id: rect + width: 640 + height: 480 + color: "beige" + anchors { + fill: parent + margins: 10 + leftMargin: 50 + rightMargin: 50 + } + + Canvas { + id: canvas + anchors.fill: parent + antialiasing: true + renderTarget: Canvas.FramebufferObject + property color drawingColor: Qt.hsla(hueSlider.value / 100.0, + saturationSlider.value / 100.0, + lightnessSlider.value / 100.0, + alphaSlider.value / 100.0) + property var points: [] + property var pressures: [] + property var pointerType: PointerDevice.Pen + onPaint: { + if (points.length < 2) + return + var ctx = canvas.getContext('2d'); + ctx.save() + ctx.strokeStyle = pointerType === PointerDevice.Pen ? drawingColor : "beige" + ctx.lineCap = "round" + if (pressures.length === points.length) { + for (var i = 1; i < points.length; i++) { + ctx.lineWidth = pressures[i] * widthSlider.value + ctx.beginPath() + ctx.moveTo(points[i - 1].x, points[i - 1].y) + ctx.lineTo(points[i].x, points[i].y) + ctx.stroke() + } + points = points.slice(points.length - 2, 1) + pressures = pressures.slice(pressures.length - 2, 1) + } else { + ctx.beginPath() + ctx.moveTo(points[0].x, points[0].y) + for (var i = 1; i < points.length; i++) + ctx.lineTo(points[i].x, points[i].y) + ctx.lineWidth = widthSlider + ctx.stroke() + points = points.slice(points.length - 2, 1) + pressures = [] + } + ctx.restore() + } + } + + PointHandler { + acceptedPointerTypes: PointerDevice.Pen + onActiveChanged: + if (active) { + canvas.pointerType = PointerDevice.Pen + } else { + canvas.points = [] + canvas.pressures = [] + } + onPointChanged: + if (active) { + canvas.points.push(point.position) + canvas.pressures.push(point.pressure) + canvas.requestPaint() + } + } + + PointHandler { + acceptedPointerTypes: PointerDevice.Eraser + onActiveChanged: + if (active) { + canvas.pointerType = PointerDevice.Eraser + } else { + canvas.points = [] + canvas.pressures = [] + } + onPointChanged: + if (active) { + canvas.points.push(point.position) + canvas.pressures.push(point.pressure) + canvas.requestPaint() + } + } + + HoverHandler { + id: stylusHandler + acceptedDevices: PointerDevice.Stylus + acceptedPointerTypes: PointerDevice.Pen + target: Image { + parent: rect + source: stylusHandler.point.rotation === 0 ? + "resources/cursor-pencil.png" : "resources/cursor-felt-marker.png" + visible: stylusHandler.hovered + rotation: stylusHandler.point.rotation + x: stylusHandler.point.position.x + y: stylusHandler.point.position.y + } + } + + HoverHandler { + id: airbrushHandler + acceptedDevices: PointerDevice.Airbrush + acceptedPointerTypes: PointerDevice.Pen + target: Image { + parent: rect + source: "resources/cursor-airbrush.png" + visible: airbrushHandler.hovered + x: airbrushHandler.point.position.x + y: airbrushHandler.point.position.y + } + } + + HoverHandler { + id: eraserHandler + acceptedPointerTypes: PointerDevice.Eraser + target: Image { + parent: rect + source: "resources/cursor-eraser.png" + visible: eraserHandler.hovered + x: eraserHandler.point.position.x + y: eraserHandler.point.position.y - 32 + } + } + } +} diff --git a/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/attributes.qml b/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/attributes.qml deleted file mode 100644 index 17d9aadf95..0000000000 --- a/tests/manual/scenegraph_lancelot/data/shaders/gridmesh/attributes.qml +++ /dev/null @@ -1,65 +0,0 @@ -import QtQuick 2.0 - -Rectangle { - width: 320 - height: 480 - - Text { - id: text - font.pixelSize: 80 - text: "Shaderz!" - } - - ShaderEffectSource { - id: source - sourceItem: text - hideSource: true - smooth: true - } - Column { - ShaderEffect { - width: 320 - height: 160 - property variant source: source - vertexShader: " - uniform highp mat4 qt_Matrix; - attribute highp vec4 qt_Vertex; - attribute highp vec2 qt_MultiTexCoord0; - varying highp vec2 qt_TexCoord0; - void main() { - gl_Position = qt_Matrix * qt_Vertex; - qt_TexCoord0 = qt_MultiTexCoord0; - }" - } - ShaderEffect { - width: 320 - height: 160 - property variant source: source - vertexShader: " - attribute highp vec2 qt_MultiTexCoord0; - uniform highp mat4 qt_Matrix; - attribute highp vec4 qt_Vertex; - varying highp vec2 qt_TexCoord0; - void main() { - gl_Position = qt_Matrix * qt_Vertex; - qt_TexCoord0 = qt_MultiTexCoord0; - }" - } - ShaderEffect { - width: 320 - height: 160 - property variant source: source - vertexShader: " - attribute highp vec2 qt_MultiTexCoord0; - uniform highp mat4 qt_Matrix; - attribute highp vec4 qt_Vertex; - varying highp vec2 qt_TexCoord0; - uniform highp float width; - uniform highp float height; - void main() { - gl_Position = qt_Matrix * qt_Vertex; - qt_TexCoord0 = qt_Vertex.xy / vec2(width, height); - }" - } - } -} diff --git a/tests/manual/scenegraph_lancelot/data/shaders/source/switch_3.qml b/tests/manual/scenegraph_lancelot/data/shaders/source/switch_3.qml index 0d3c1fc4ee..c02dfba9e2 100644 --- a/tests/manual/scenegraph_lancelot/data/shaders/source/switch_3.qml +++ b/tests/manual/scenegraph_lancelot/data/shaders/source/switch_3.qml @@ -47,14 +47,7 @@ Item { property variant source: source - fragmentShader: " - uniform lowp sampler2D source; - varying highp vec2 qt_TexCoord0; - uniform lowp float qt_Opacity; - void main() { - gl_FragColor = vec4(qt_TexCoord0.x, qt_TexCoord0.y, 1, 1) * texture2D(source, qt_TexCoord0).a; - } - " + fragmentShader: "qrc:shaders/gradient.frag" } diff --git a/tests/manual/scenegraph_lancelot/data/shape/shape_text.qml b/tests/manual/scenegraph_lancelot/data/shape/shape_text.qml new file mode 100644 index 0000000000..37367054b5 --- /dev/null +++ b/tests/manual/scenegraph_lancelot/data/shape/shape_text.qml @@ -0,0 +1,91 @@ +import QtQuick 2.15 +import QtQuick.Shapes 1.0 + +Item { + width: 320 + height: 480 + + Column { + Item { + width: 200 + height: 160 + + Shape { + anchors.fill: parent + vendorExtensionsEnabled: false + + ShapePath { + fillColor: "transparent" + strokeColor: "blue" + strokeStyle: ShapePath.DashLine + strokeWidth: 4 + + PathText { + x: 96 + y: 10 + font.pixelSize: 120 + text: "Qt" + } + } + } + } + + Item { + width: 200 + height: 160 + + Rectangle { + anchors.fill: parent + color: "blue" + } + + Shape { + anchors.fill: parent + vendorExtensionsEnabled: false + + ShapePath { + fillColor: "red" + strokeColor: "blue" + strokeStyle: ShapePath.DashLine + capStyle: ShapePath.RoundCap + strokeWidth: 8 + + PathText { + x: 96; y: 10 + font.pixelSize: 150 + text: "Qt" + } + } + } + } + + Item { + width: 200 + height: 160 + + Shape { + anchors.fill: parent + vendorExtensionsEnabled: false + + ShapePath { + fillGradient: LinearGradient { + x1: 0; x2: 200; y1: 0; y2: 160 + spread: ShapeGradient.PadSpread + GradientStop { position: 0.0; color: "red"; } + GradientStop { position: 1.0; color: "green"; } + } + strokeColor: "blue" + strokeStyle: ShapePath.DashLine + joinStyle: ShapePath.RoundJoin + strokeWidth: 4 + + PathText { + x: 96; y: 10 + font.pixelSize: 150 + text: "Qt" + } + } + } + } + } +} diff --git a/tests/manual/tableview/imagetiling/imageTiling.qml b/tests/manual/tableview/imagetiling/imageTiling.qml new file mode 100644 index 0000000000..5c9cdb9888 --- /dev/null +++ b/tests/manual/tableview/imagetiling/imageTiling.qml @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.15 +import Qt.labs.qmlmodels 1.0 + +TableView { + id: root + width: 1024 + height: 200 + property int tileSize: 1024 / 8 + rowSpacing: 1; columnSpacing: 1 + model: TableModel { + TableModelColumn {} + TableModelColumn {} + TableModelColumn {} + TableModelColumn {} + TableModelColumn {} + TableModelColumn {} + TableModelColumn {} + TableModelColumn {} + columns: [0, 1, 2, 3, 4, 5, 6, 7] + rows: [0, 1, 2, 3] + } + delegate: Image { + id: image +// source: "map.png" // unscaled because png doesn't support QImageIOHandler::ScaledClipRect +// source: "map.svgz" // tiles offset incorrectly: see QTBUG-81044 + source: "map.pdf" // ok if the qtpdf plugin is installed + fillMode: Image.Pad + sourceSize.width: 1024 + sourceClipRect: Qt.rect(model.column * tileSize, model.row * tileSize, tileSize, tileSize) + cache: true + asynchronous: true + Text { + text: image.sourceClipRect.width + "x" + image.sourceClipRect.height + + " " + image.sourceClipRect.x + "," + image.sourceClipRect.y + + "\nfrom " + image.sourceSize.toString() + // inconsistency: if we don't set sourceSize, it ends up being sourceClipRect.size + "\nimplicit " + image.implicitWidth + "x" + image.implicitHeight + } + } + columnWidthProvider: function (c) { return tileSize } // workaround for QTBUG-81045 + rowHeightProvider: function (r) { return tileSize } +} diff --git a/tests/manual/tableview/imagetiling/map.pdf b/tests/manual/tableview/imagetiling/map.pdf Binary files differnew file mode 100644 index 0000000000..31e7b5225e --- /dev/null +++ b/tests/manual/tableview/imagetiling/map.pdf diff --git a/tests/manual/tableview/imagetiling/map.png b/tests/manual/tableview/imagetiling/map.png Binary files differnew file mode 100644 index 0000000000..23a8342818 --- /dev/null +++ b/tests/manual/tableview/imagetiling/map.png diff --git a/tests/manual/tableview/imagetiling/map.svgz b/tests/manual/tableview/imagetiling/map.svgz Binary files differnew file mode 100644 index 0000000000..64d509c106 --- /dev/null +++ b/tests/manual/tableview/imagetiling/map.svgz diff --git a/tools/qml/conf.h b/tools/qml/conf.h index 4ad45428ed..84167c9134 100644 --- a/tools/qml/conf.h +++ b/tools/qml/conf.h @@ -40,6 +40,7 @@ class PartialScene : public QObject Q_PROPERTY(QUrl container READ container WRITE setContainer NOTIFY containerChanged) Q_PROPERTY(QString itemType READ itemType WRITE setItemType NOTIFY itemTypeChanged) QML_ELEMENT + QML_ADDED_IN_VERSION(1, 0) public: PartialScene(QObject *parent = 0) : QObject(parent) {} @@ -75,6 +76,7 @@ class Config : public QObject Q_PROPERTY(QQmlListProperty<PartialScene> sceneCompleters READ sceneCompleters) Q_CLASSINFO("DefaultProperty", "sceneCompleters") QML_NAMED_ELEMENT(Configuration) + QML_ADDED_IN_VERSION(1, 0) public: Config (QObject* parent=0) : QObject(parent) {} diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp index 618dab6690..e8c471e22e 100644 --- a/tools/qml/main.cpp +++ b/tools/qml/main.cpp @@ -37,6 +37,7 @@ #include <QFileOpenEvent> #include <QOpenGLContext> #include <QOpenGLFunctions> +#include <QSurfaceFormat> #ifdef QT_WIDGETS_LIB #include <QApplication> #endif // QT_WIDGETS_LIB @@ -59,6 +60,7 @@ #include <QLibraryInfo> #include <qqml.h> #include <qqmldebug.h> +#include <qqmlfileselector.h> #include <private/qmemory_p.h> #include <private/qtqmlglobal_p.h> @@ -434,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; @@ -511,6 +512,9 @@ int main(int argc, char *argv[]) "Backend is one of: default, vulkan, metal, d3d11, gl"), QStringLiteral("backend")); parser.addOption(rhiOption); + QCommandLineOption selectorOption(QStringLiteral("S"), QCoreApplication::translate("main", + "Add selector to the list of QQmlFileSelectors."), QStringLiteral("selector")); + parser.addOption(selectorOption); // Positional arguments parser.addPositionalArgument("files", @@ -550,6 +554,26 @@ int main(int argc, char *argv[]) #endif for (const QString &importPath : parser.values(importOption)) e.addImportPath(importPath); + + QStringList customSelectors; + for (const QString &selector : parser.values(selectorOption)) + customSelectors.append(selector); + if (!customSelectors.isEmpty()) { + QQmlFileSelector *selector = QQmlFileSelector::get(&e); + selector->setExtraSelectors(customSelectors); + } + +#if defined(QT_GUI_LIB) && QT_CONFIG(opengl) + if (qEnvironmentVariableIsSet("QSG_CORE_PROFILE") || qEnvironmentVariableIsSet("QML_CORE_PROFILE")) { + QSurfaceFormat surfaceFormat; + surfaceFormat.setStencilBufferSize(8); + surfaceFormat.setDepthBufferSize(24); + surfaceFormat.setVersion(4, 1); + surfaceFormat.setProfile(QSurfaceFormat::CoreProfile); + QSurfaceFormat::setDefaultFormat(surfaceFormat); + } +#endif + files << parser.values(qmlFileOption); if (parser.isSet(configOption)) confFile = parser.value(configOption); 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/qmlcachegen/generateloader.cpp b/tools/qmlcachegen/generateloader.cpp index 71286137eb..a8ec527299 100644 --- a/tools/qmlcachegen/generateloader.cpp +++ b/tools/qmlcachegen/generateloader.cpp @@ -155,7 +155,7 @@ bool generateLoader(const QStringList &compiledFiles, const QString &outputFileN } stream << " QQmlPrivate::RegisterQmlUnitCacheHook registration;\n"; - stream << " registration.version = 0;\n"; + stream << " registration.structVersion = 0;\n"; stream << " registration.lookupCachedQmlUnit = &lookupCachedUnit;\n"; stream << " QQmlPrivate::qmlregister(QQmlPrivate::QmlUnitCacheHookRegistration, ®istration);\n"; diff --git a/tools/qmlcachegen/qmlcachegen.cpp b/tools/qmlcachegen/qmlcachegen.cpp index d1b28c41f5..174cd547f6 100644 --- a/tools/qmlcachegen/qmlcachegen.cpp +++ b/tools/qmlcachegen/qmlcachegen.cpp @@ -84,9 +84,9 @@ Error Error::augment(const QString &contextErrorMessage) const QString diagnosticErrorMessage(const QString &fileName, const QQmlJS::DiagnosticMessage &m) { QString message; - message = fileName + QLatin1Char(':') + QString::number(m.line) + QLatin1Char(':'); - if (m.column > 0) - message += QString::number(m.column) + QLatin1Char(':'); + message = fileName + QLatin1Char(':') + QString::number(m.loc.startLine) + QLatin1Char(':'); + if (m.loc.startColumn > 0) + message += QString::number(m.loc.startColumn) + QLatin1Char(':'); if (m.isError()) message += QLatin1String(" error: "); diff --git a/tools/qmlcachegen/qtquickcompiler.prf b/tools/qmlcachegen/qtquickcompiler.prf index 8aac3b9e07..7353dfb17a 100644 --- a/tools/qmlcachegen/qtquickcompiler.prf +++ b/tools/qmlcachegen/qtquickcompiler.prf @@ -29,6 +29,7 @@ defineReplace(qmlCacheResourceFileOutputName) { # Flatten RESOURCES that may contain individual files or objects load(resources_functions) qtFlattenResources() +qtEnsurePluginResourcesCpp() NEWRESOURCES = QMLCACHE_RESOURCE_FILES = diff --git a/tools/qmleasing/splineeditor.cpp b/tools/qmleasing/splineeditor.cpp index 69850dc7a1..3657fe3f27 100644 --- a/tools/qmleasing/splineeditor.cpp +++ b/tools/qmleasing/splineeditor.cpp @@ -674,7 +674,7 @@ void SplineEditor::setEasingCurve(const QString &code) return; if (code.startsWith(QLatin1Char('[')) && code.endsWith(QLatin1Char(']'))) { const QStringRef cleanCode(&code, 1, code.size() - 2); - const auto stringList = cleanCode.split(QLatin1Char(','), QString::SkipEmptyParts); + const auto stringList = cleanCode.split(QLatin1Char(','), Qt::SkipEmptyParts); if (stringList.count() >= 6 && (stringList.count() % 6 == 0)) { QVector<qreal> realList; realList.reserve(stringList.count()); diff --git a/tools/qmlformat/commentastvisitor.cpp b/tools/qmlformat/commentastvisitor.cpp index 8264a6099e..4dd241ff93 100644 --- a/tools/qmlformat/commentastvisitor.cpp +++ b/tools/qmlformat/commentastvisitor.cpp @@ -268,3 +268,9 @@ bool CommentAstVisitor::visit(UiImport *node) attachComment(node); return true; } + +bool CommentAstVisitor::visit(UiPragma *node) +{ + attachComment(node); + return true; +} diff --git a/tools/qmlformat/commentastvisitor.h b/tools/qmlformat/commentastvisitor.h index 369784a5ba..d3de0a9b9d 100644 --- a/tools/qmlformat/commentastvisitor.h +++ b/tools/qmlformat/commentastvisitor.h @@ -38,6 +38,7 @@ #include <QVector> using namespace QQmlJS::AST; +using namespace QQmlJS; struct Comment { @@ -108,6 +109,7 @@ public: void endVisit(StatementList *node) override; bool visit(UiImport *node) override; + bool visit(UiPragma *node) override; bool visit(UiPublicMember *node) override; bool visit(FunctionDeclaration *node) override; private: diff --git a/tools/qmlformat/dumpastvisitor.cpp b/tools/qmlformat/dumpastvisitor.cpp index 20ebef8927..75712975cc 100644 --- a/tools/qmlformat/dumpastvisitor.cpp +++ b/tools/qmlformat/dumpastvisitor.cpp @@ -35,10 +35,29 @@ DumpAstVisitor::DumpAstVisitor(Node *rootNode, CommentAstVisitor *comment): m_co // Add all completely orphaned comments m_result += getOrphanedComments(nullptr); + m_scope_properties.push(ScopeProperties {}); + rootNode->accept(this); // We need to get rid of one new-line so our output doesn't append an empty line m_result.chop(1); + + // Remove trailing whitespace + QStringList lines = m_result.split("\n"); + for (QString& line : lines) { + while (line.endsWith(" ")) + line.chop(1); + } + + m_result = lines.join("\n"); +} + +bool DumpAstVisitor::preVisit(Node *el) +{ + UiObjectMember *m = el->uiObjectMemberCast(); + if (m != 0) + Node::accept(m->annotations, this); + return true; } static QString parseUiQualifiedId(UiQualifiedId *id) @@ -185,7 +204,7 @@ QString DumpAstVisitor::parseUiParameterList(UiParameterList *list) { QString result = ""; for (auto *item = list; item != nullptr; item = item->next) - result += item->type->name + " " + item->name + (item->next != nullptr ? ", " : ""); + result += parseUiQualifiedId(item->type) + " " + item->name + (item->next != nullptr ? ", " : ""); return result; } @@ -218,20 +237,28 @@ QString DumpAstVisitor::parsePatternElement(PatternElement *element, bool scope) result += element->bindingIdentifier.toString(); + if (element->typeAnnotation != nullptr) + result += ": " + parseType(element->typeAnnotation->type); + if (!expr.isEmpty()) result += " = "+expr; return result; } default: + m_error = true; return "pe_unknown"; } } QString escapeString(QString string) { - // Escape \r, \n and \t - string = string.replace("\r", "\\r").replace("\n", "\\n").replace("\t", "\\t"); + // Handle escape sequences + string = string.replace("\r", "\\r").replace("\n", "\\n").replace("\t", "\\t") + .replace("\b","\\b").replace("\v", "\\v").replace("\f", "\\f"); + + // Escape backslash + string = string.replace("\\", "\\\\"); // Escape " string = string.replace("\"", "\\\""); @@ -261,7 +288,14 @@ QString DumpAstVisitor::parseFormalParameterList(FormalParameterList *list) QString DumpAstVisitor::parsePatternProperty(PatternProperty *property) { - return escapeString(property->name->asString())+": "+parsePatternElement(property, false); + switch (property->type) { + case PatternElement::Getter: + return "get "+parseFunctionExpression(cast<FunctionExpression *>(property->initializer), true); + case PatternElement::Setter: + return "set "+parseFunctionExpression(cast<FunctionExpression *>(property->initializer), true); + default: + return escapeString(property->name->asString())+": "+parsePatternElement(property, false); + } } QString DumpAstVisitor::parsePatternPropertyList(PatternPropertyList *list) @@ -275,6 +309,61 @@ QString DumpAstVisitor::parsePatternPropertyList(PatternPropertyList *list) return result; } +QString DumpAstVisitor::parseFunctionExpression(FunctionExpression *functExpr, bool omitFunction) +{ + m_indentLevel++; + QString result; + + if (!functExpr->isArrowFunction) { + result += omitFunction ? "" : "function"; + + if (functExpr->isGenerator) + result += "*"; + + if (!functExpr->name.isEmpty()) + result += (omitFunction ? "" : " ") + functExpr->name; + + result += "("+parseFormalParameterList(functExpr->formals)+")"; + + if (functExpr->typeAnnotation != nullptr) + result += " : " + parseType(functExpr->typeAnnotation->type); + + result += " {\n" + parseStatementList(functExpr->body); + } else { + result += "("+parseFormalParameterList(functExpr->formals)+")"; + + if (functExpr->typeAnnotation != nullptr) + result += " : " + parseType(functExpr->typeAnnotation->type); + + result += " => {\n" + parseStatementList(functExpr->body); + } + + m_indentLevel--; + + result += formatLine("}", false); + + return result; + +} + +QString DumpAstVisitor::parseType(Type *type) { + QString result = parseUiQualifiedId(type->typeId); + + if (type->typeArguments != nullptr) { + TypeArgumentList *list = cast<TypeArgumentList *>(type->typeArguments); + + result += "<"; + + for (auto *item = list; item != nullptr; item = item->next) { + result += parseType(item->typeId) + (item->next != nullptr ? ", " : ""); + } + + result += ">"; + } + + return result; +} + QString DumpAstVisitor::parseExpression(ExpressionNode *expression) { if (expression == nullptr) @@ -288,7 +377,15 @@ QString DumpAstVisitor::parseExpression(ExpressionNode *expression) return cast<IdentifierExpression*>(expression)->name.toString(); case Node::Kind_FieldMemberExpression: { auto *fieldMemberExpr = cast<FieldMemberExpression *>(expression); - return parseExpression(fieldMemberExpr->base) + "." + fieldMemberExpr->name.toString(); + QString result = parseExpression(fieldMemberExpr->base); + + // If we're operating on a numeric literal, always put it in braces + if (fieldMemberExpr->base->kind == Node::Kind_NumericLiteral) + result = "(" + result + ")"; + + result += "." + fieldMemberExpr->name.toString(); + + return result; } case Node::Kind_ArrayMemberExpression: { auto *arrayMemberExpr = cast<ArrayMemberExpression *>(expression); @@ -304,31 +401,7 @@ QString DumpAstVisitor::parseExpression(ExpressionNode *expression) case Node::Kind_FunctionExpression: { auto *functExpr = cast<FunctionExpression *>(expression); - - m_indentLevel++; - QString result; - - if (!functExpr->isArrowFunction) { - result += "function"; - - if (functExpr->isGenerator) - result += "*"; - - if (!functExpr->name.isEmpty()) - result += " " + functExpr->name; - - result += "("+parseFormalParameterList(functExpr->formals)+") {\n" - + parseStatementList(functExpr->body); - } else { - result += "("+parseFormalParameterList(functExpr->formals)+") => {\n"; - result += parseStatementList(functExpr->body); - } - - m_indentLevel--; - - result += formatLine("}", false); - - return result; + return parseFunctionExpression(functExpr); } case Node::Kind_NullExpression: return "null"; @@ -419,8 +492,7 @@ QString DumpAstVisitor::parseExpression(ExpressionNode *expression) } case Node::Kind_Type: { auto* type = reinterpret_cast<Type*>(expression); - - return parseUiQualifiedId(type->typeId); + return parseType(type); } case Node::Kind_RegExpLiteral: { auto* regexpLiteral = cast<RegExpLiteral*>(expression); @@ -610,10 +682,14 @@ QString DumpAstVisitor::parseStatement(Statement *statement, bool blockHasNext, result += "; "; result += parseExpression(forStatement->condition) + "; "; - result += parseExpression(forStatement->expression)+") "; + result += parseExpression(forStatement->expression)+")"; - result += parseStatement(forStatement->statement); + const QString statement = parseStatement(forStatement->statement); + if (!statement.isEmpty()) + result += " "+statement; + else + result += ";"; return result; } @@ -639,9 +715,16 @@ QString DumpAstVisitor::parseStatement(Statement *statement, bool blockHasNext, break; } - result += parseExpression(forEachStatement->expression) + ") "; + result += parseExpression(forEachStatement->expression) + ")"; + + const QString statement = parseStatement(forEachStatement->statement); + + if (!statement.isEmpty()) + result += " "+statement; + else + result += ";"; + - result += parseStatement(forEachStatement->statement); return result; } @@ -652,9 +735,14 @@ QString DumpAstVisitor::parseStatement(Statement *statement, bool blockHasNext, auto statement = parseStatement(whileStatement->statement, false, true); - return "while ("+parseExpression(whileStatement->expression) + ")" - + (m_blockNeededBraces ? " " : "") - + statement; + QString result = "while ("+parseExpression(whileStatement->expression) + ")"; + + if (!statement.isEmpty()) + result += (m_blockNeededBraces ? " " : "") + statement; + else + result += ";"; + + return result; } case Node::Kind_DoWhileStatement: { auto *doWhileStatement = cast<DoWhileStatement *>(statement); @@ -762,31 +850,32 @@ bool DumpAstVisitor::visit(UiPublicMember *node) { switch (node->type) { case UiPublicMember::Signal: - if (m_firstSignal) { - if (m_firstOfAll) - m_firstOfAll = false; + if (scope().m_firstSignal) { + if (scope().m_firstOfAll) + scope().m_firstOfAll = false; else addNewLine(); - m_firstSignal = false; + scope().m_firstSignal = false; } addLine("signal "+node->name.toString()+"("+parseUiParameterList(node->parameters) + ")" + commentBackInline); break; case UiPublicMember::Property: { - if (m_firstProperty) { - if (m_firstOfAll) - m_firstOfAll = false; + if (scope().m_firstProperty) { + if (scope().m_firstOfAll) + scope().m_firstOfAll = false; else addNewLine(); - m_firstProperty = false; + scope().m_firstProperty = false; } const bool is_required = node->requiredToken.isValid(); const bool is_default = node->defaultToken.isValid(); const bool is_readonly = node->readonlyToken.isValid(); + const bool has_type_modifier = node->typeModifierToken.isValid(); QString prefix = ""; QString statement = parseStatement(node->statement); @@ -803,8 +892,20 @@ bool DumpAstVisitor::visit(UiPublicMember *node) { if (is_readonly) prefix += "readonly "; - addLine(prefix + "property " + node->memberType->name + " " - + node->name+statement + commentBackInline); + QString member_type = parseUiQualifiedId(node->memberType); + + if (has_type_modifier) + member_type = node->typeModifier + "<" + member_type + ">"; + + if (is_readonly && statement.isEmpty() + && scope().m_bindings.contains(node->name.toString())) { + m_result += formatLine(prefix + "property " + member_type + " ", false); + + scope().m_pendingBinding = true; + } else { + addLine(prefix + "property " + member_type + " " + + node->name+statement + commentBackInline); + } break; } } @@ -845,26 +946,70 @@ void DumpAstVisitor::addLine(QString line) { m_result += formatLine(line); } +QHash<QString, UiObjectMember*> findBindings(UiObjectMemberList *list) { + QHash<QString, UiObjectMember*> bindings; + + // This relies on RestructureASTVisitor having run beforehand + + for (auto *item = list; item != nullptr; item = item->next) { + switch (item->member->kind) { + case Node::Kind_UiPublicMember: { + UiPublicMember *member = cast<UiPublicMember *>(item->member); + + if (member->type != UiPublicMember::Property) + continue; + + bindings[member->name.toString()] = nullptr; + + break; + } + case Node::Kind_UiObjectBinding: { + UiObjectBinding *binding = cast<UiObjectBinding *>(item->member); + + const QString name = parseUiQualifiedId(binding->qualifiedId); + + if (bindings.contains(name)) + bindings[name] = binding; + + break; + } + case Node::Kind_UiArrayBinding: { + UiArrayBinding *binding = cast<UiArrayBinding *>(item->member); + + const QString name = parseUiQualifiedId(binding->qualifiedId); + + if (bindings.contains(name)) + bindings[name] = binding; + + break; + } + case Node::Kind_UiScriptBinding: + // We can ignore UiScriptBindings since those are actually properly attached to the property + break; + } + } + + return bindings; +} + bool DumpAstVisitor::visit(UiObjectDefinition *node) { - if (m_firstObject) { - if (m_firstOfAll) - m_firstOfAll = false; + if (scope().m_firstObject) { + if (scope().m_firstOfAll) + scope().m_firstOfAll = false; else addNewLine(); - m_firstObject = false; + scope().m_firstObject = false; } addLine(getComment(node, Comment::Location::Front)); - addLine(node->qualifiedTypeNameId->name+" {"); + addLine(parseUiQualifiedId(node->qualifiedTypeNameId) + " {"); m_indentLevel++; - m_firstProperty = true; - m_firstSignal = true; - m_firstBinding = true; - m_firstObject = true; - m_firstOfAll = true; + ScopeProperties props; + props.m_bindings = findBindings(node->initializer->members); + m_scope_properties.push(props); m_result += getOrphanedComments(node); @@ -873,9 +1018,14 @@ bool DumpAstVisitor::visit(UiObjectDefinition *node) { void DumpAstVisitor::endVisit(UiObjectDefinition *node) { m_indentLevel--; - addLine(m_inArrayBinding && m_lastInArrayBinding != node ? "}," : "}"); + + m_scope_properties.pop(); + + bool need_comma = scope().m_inArrayBinding && scope().m_lastInArrayBinding != node; + + addLine(need_comma ? "}," : "}"); addLine(getComment(node, Comment::Location::Back)); - if (!m_inArrayBinding) + if (!scope().m_inArrayBinding) addNewLine(); } @@ -920,49 +1070,64 @@ bool DumpAstVisitor::visit(UiEnumMemberList *node) { } bool DumpAstVisitor::visit(UiScriptBinding *node) { - if (m_firstBinding) { - if (m_firstOfAll) - m_firstOfAll = false; + if (scope().m_firstBinding) { + if (scope().m_firstOfAll) + scope().m_firstOfAll = false; else addNewLine(); if (parseUiQualifiedId(node->qualifiedId) != "id") - m_firstBinding = false; + scope().m_firstBinding = false; } addLine(getComment(node, Comment::Location::Front)); - addLine(parseUiQualifiedId(node->qualifiedId)+ ": " + parseStatement(node->statement) - + getComment(node, Comment::Location::Back_Inline)); + + QString statement = parseStatement(node->statement); + + QString result = parseUiQualifiedId(node->qualifiedId) + ":"; + + if (!statement.isEmpty()) + result += " "+statement; + else + result += ";"; + + result += getComment(node, Comment::Location::Back_Inline); + + addLine(result); + return true; } bool DumpAstVisitor::visit(UiArrayBinding *node) { - if (m_firstBinding) { - if (m_firstOfAll) - m_firstOfAll = false; + if (!scope().m_pendingBinding && scope().m_firstBinding) { + if (scope().m_firstOfAll) + scope().m_firstOfAll = false; else addNewLine(); - m_firstBinding = false; + scope().m_firstBinding = false; } - addLine(getComment(node, Comment::Location::Front)); - addLine(parseUiQualifiedId(node->qualifiedId)+ ": ["); + if (scope().m_pendingBinding) { + m_result += parseUiQualifiedId(node->qualifiedId)+ ": [\n"; + scope().m_pendingBinding = false; + } else { + addLine(getComment(node, Comment::Location::Front)); + addLine(parseUiQualifiedId(node->qualifiedId)+ ": ["); + } m_indentLevel++; - m_inArrayBinding = true; - m_firstOfAll = true; - m_firstObject = true; - m_firstSignal = true; - m_firstBinding = true; - m_firstProperty = true; + ScopeProperties props; + props.m_inArrayBinding = true; for (auto *item = node->members; item != nullptr; item = item->next) { if (item->next == nullptr) - m_lastInArrayBinding = item->member; + props.m_lastInArrayBinding = item->member; } + m_scope_properties.push(props); + m_result += getOrphanedComments(node); return true; @@ -970,8 +1135,7 @@ bool DumpAstVisitor::visit(UiArrayBinding *node) { void DumpAstVisitor::endVisit(UiArrayBinding *) { m_indentLevel--; - m_inArrayBinding = false; - m_lastInArrayBinding = nullptr; + m_scope_properties.pop(); addLine("]"); } @@ -986,7 +1150,12 @@ bool DumpAstVisitor::visit(FunctionDeclaration *node) { if (node->isGenerator) head += "*"; - head += " "+node->name+"("+parseFormalParameterList(node->formals)+") {"; + head += " "+node->name+"("+parseFormalParameterList(node->formals)+")"; + + if (node->typeAnnotation != nullptr) + head += " : " + parseType(node->typeAnnotation->type); + + head += " {"; addLine(head); m_indentLevel++; @@ -1000,27 +1169,37 @@ bool DumpAstVisitor::visit(FunctionDeclaration *node) { } bool DumpAstVisitor::visit(UiObjectBinding *node) { - if (m_firstObject) { - if (m_firstOfAll) - m_firstOfAll = false; + if (!scope().m_pendingBinding && scope().m_firstObject) { + if (scope().m_firstOfAll) + scope().m_firstOfAll = false; else addNewLine(); - m_firstObject = false; + scope().m_firstObject = false; } QString name = parseUiQualifiedId(node->qualifiedTypeNameId); QString result = name; + ScopeProperties props; + props.m_bindings = findBindings(node->initializer->members); + m_scope_properties.push(props); + if (node->hasOnToken) result += " on "+parseUiQualifiedId(node->qualifiedId); else result.prepend(parseUiQualifiedId(node->qualifiedId) + ": "); - addNewLine(); - addLine(getComment(node, Comment::Location::Front)); - addLine(result+" {"); + if (scope().m_pendingBinding) { + m_result += result + " {\n"; + + scope().m_pendingBinding = false; + } else { + addNewLine(); + addLine(getComment(node, Comment::Location::Front)); + addLine(result + " {"); + } m_indentLevel++; @@ -1029,6 +1208,8 @@ bool DumpAstVisitor::visit(UiObjectBinding *node) { void DumpAstVisitor::endVisit(UiObjectBinding *node) { m_indentLevel--; + m_scope_properties.pop(); + addLine("}"); addLine(getComment(node, Comment::Location::Back)); @@ -1036,6 +1217,8 @@ void DumpAstVisitor::endVisit(UiObjectBinding *node) { } bool DumpAstVisitor::visit(UiImport *node) { + scope().m_firstOfAll = false; + addLine(getComment(node, Comment::Location::Front)); QString result = "import "; @@ -1046,8 +1229,8 @@ bool DumpAstVisitor::visit(UiImport *node) { result += parseUiQualifiedId(node->importUri); if (node->version) { - result += " " + QString::number(node->version->majorVersion) + "." - + QString::number(node->version->minorVersion); + result += " " + QString::number(node->version->version.majorVersion()) + "." + + QString::number(node->version->version.minorVersion()); } if (node->asToken.isValid()) { @@ -1060,3 +1243,49 @@ bool DumpAstVisitor::visit(UiImport *node) { return true; } + +bool DumpAstVisitor::visit(UiPragma *node) { + scope().m_firstOfAll = false; + + addLine(getComment(node, Comment::Location::Front)); + QString result = "pragma "+ node->name; + result += getComment(node, Comment::Location::Back_Inline); + + addLine(result); + + return true; +} + +bool DumpAstVisitor::visit(UiAnnotation *node) +{ + if (scope().m_firstObject) { + if (scope().m_firstOfAll) + scope().m_firstOfAll = false; + else + addNewLine(); + + scope().m_firstObject = false; + } + + addLine(getComment(node, Comment::Location::Front)); + addLine(QLatin1String("@") + parseUiQualifiedId(node->qualifiedTypeNameId) + " {"); + + m_indentLevel++; + + ScopeProperties props; + props.m_bindings = findBindings(node->initializer->members); + m_scope_properties.push(props); + + m_result += getOrphanedComments(node); + + return true; +} + +void DumpAstVisitor::endVisit(UiAnnotation *node) { + m_indentLevel--; + + m_scope_properties.pop(); + + addLine("}"); + addLine(getComment(node, Comment::Location::Back)); +} diff --git a/tools/qmlformat/dumpastvisitor.h b/tools/qmlformat/dumpastvisitor.h index 2001f4366e..faf067d400 100644 --- a/tools/qmlformat/dumpastvisitor.h +++ b/tools/qmlformat/dumpastvisitor.h @@ -32,9 +32,13 @@ #include <QtQml/private/qqmljsastvisitor_p.h> #include <QtQml/private/qqmljsast_p.h> +#include <QHash> +#include <QStack> + #include "commentastvisitor.h" using namespace QQmlJS::AST; +using namespace QQmlJS; class DumpAstVisitor : protected Visitor { @@ -43,6 +47,8 @@ public: QString toString() const { return m_result; } + bool preVisit(Node *) override; + bool visit(UiScriptBinding *node) override; bool visit(UiArrayBinding *node) override; @@ -62,11 +68,28 @@ public: bool visit(UiEnumMemberList *node) override; bool visit(UiPublicMember *node) override; bool visit(UiImport *node) override; + bool visit(UiPragma *node) override; + + bool visit(UiAnnotation *node) override; + void endVisit(UiAnnotation *node) override; void throwRecursionDepthError() override {} bool error() const { return m_error; } private: + struct ScopeProperties { + bool m_firstOfAll = true; + bool m_firstSignal = true; + bool m_firstProperty = true; + bool m_firstBinding = true; + bool m_firstObject = true; + bool m_inArrayBinding = false; + bool m_pendingBinding = false; + + UiObjectMember* m_lastInArrayBinding = nullptr; + QHash<QString, UiObjectMember*> m_bindings; + }; + QString generateIndent() const; QString formatLine(QString line, bool newline = true) const; @@ -106,19 +129,19 @@ private: QString parseFormalParameterList(FormalParameterList *list); + QString parseType(Type *type); + + QString parseFunctionExpression(FunctionExpression *expression, bool omitFunction = false); + + ScopeProperties& scope() { return m_scope_properties.top(); } + int m_indentLevel = 0; bool m_error = false; bool m_blockNeededBraces = false; - bool m_inArrayBinding = false; - bool m_firstOfAll = false; - bool m_firstSignal = false; - bool m_firstProperty = false; - bool m_firstBinding = false; - bool m_firstObject = true; + QStack<ScopeProperties> m_scope_properties; - UiObjectMember* m_lastInArrayBinding = nullptr; QString m_result = ""; CommentAstVisitor *m_comment; }; diff --git a/tools/qmlformat/main.cpp b/tools/qmlformat/main.cpp index 036fbe9748..da58ffd5d0 100644 --- a/tools/qmlformat/main.cpp +++ b/tools/qmlformat/main.cpp @@ -67,7 +67,7 @@ bool parseFile(const QString& filename, bool inplace, bool verbose, bool sortImp const auto diagnosticMessages = parser.diagnosticMessages(); for (const QQmlJS::DiagnosticMessage &m : diagnosticMessages) { qWarning().noquote() << QString::fromLatin1("%1:%2 : %3") - .arg(filename).arg(m.line).arg(m.message); + .arg(filename).arg(m.loc.startLine).arg(m.message); } qWarning().noquote() << "Failed to parse" << filename; @@ -101,11 +101,29 @@ bool parseFile(const QString& filename, bool inplace, bool verbose, bool sortImp DumpAstVisitor dump(parser.rootNode(), &comment); - if (dump.error()) { + QString dumpCode = dump.toString(); + + lexer.setCode(dumpCode, 1, true); + + bool dumpSuccess = parser.parse(); + + if (!dumpSuccess) { + if (verbose) { + const auto diagnosticMessages = parser.diagnosticMessages(); + for (const QQmlJS::DiagnosticMessage &m : diagnosticMessages) { + qWarning().noquote() << QString::fromLatin1("<formatted>:%2 : %3") + .arg(m.loc.startLine).arg(m.message); + } + } + + qWarning().noquote() << "Failed to parse formatted code."; + } + + if (dump.error() || !dumpSuccess) { if (force) { qWarning().noquote() << "An error has occurred. The output may not be reliable."; } else { - qWarning().noquote() << "Am error has occurred. Aborting."; + qWarning().noquote() << "An error has occurred. Aborting."; return false; } } @@ -120,10 +138,10 @@ bool parseFile(const QString& filename, bool inplace, bool verbose, bool sortImp return false; } - file.write(dump.toString().toUtf8()); + file.write(dumpCode.toUtf8()); file.close(); } else { - QTextStream(stdout) << dump.toString(); + QTextStream(stdout) << dumpCode; } return true; diff --git a/tools/qmlformat/restructureastvisitor.cpp b/tools/qmlformat/restructureastvisitor.cpp index f9ac2a20c2..7cce0e8034 100644 --- a/tools/qmlformat/restructureastvisitor.cpp +++ b/tools/qmlformat/restructureastvisitor.cpp @@ -110,6 +110,11 @@ void RestructureAstVisitor::endVisit(UiObjectMemberList *node) { QList<UiObjectMember*> correctOrder; + QList<UiScriptBinding*> largeScriptBinding; + + UiObjectMember *states = nullptr; + UiObjectMember *transitions = nullptr; + auto enumDeclarations = findKind<UiEnumDeclaration>(node); auto scriptBindings = findKind<UiScriptBinding>(node); auto arrayBindings = findKind<UiArrayBinding>(node); @@ -117,11 +122,47 @@ void RestructureAstVisitor::endVisit(UiObjectMemberList *node) auto sourceElements = findKind<UiSourceElement>(node); auto objectDefinitions = findKind<UiObjectDefinition>(node); + // Look for transitions and states + for (auto *binding : findKind<UiObjectBinding>(node)) { + const QString name = parseUiQualifiedId(binding->qualifiedId); + + if (name == "transitions") + transitions = binding; + else if (name == "states") + states = binding; + } + + for (auto it = arrayBindings.begin(); it != arrayBindings.end();) { + const QString name = parseUiQualifiedId((*it)->qualifiedId); + + if (name == "transitions") { + transitions = *it; + it = arrayBindings.erase(it); + } else if (name == "states") { + states = *it; + it = arrayBindings.erase(it); + } else { + it++; + } + } + + // Find large script bindings + for (auto it = scriptBindings.begin(); it != scriptBindings.end();) { + // A binding is considered large if it uses a block + if ((*it)->statement->kind != Node::Kind_Block) { + it++; + continue; + } + + largeScriptBinding.push_back(*it); + it = scriptBindings.erase(it); + } + // This structure is based on https://doc.qt.io/qt-5/qml-codingconventions.html // 1st id for (auto *binding : scriptBindings) { - if (binding->qualifiedId->name == "id") { + if (parseUiQualifiedId(binding->qualifiedId) == "id") { correctOrder.append(binding); scriptBindings.removeOne(binding); @@ -154,9 +195,14 @@ void RestructureAstVisitor::endVisit(UiObjectMemberList *node) correctOrder.append(source); // 6th properties + // small script bindings... for (auto *binding : scriptBindings) correctOrder.append(binding); + // ...then large ones + for (auto *binding : largeScriptBinding) + correctOrder.append(binding); + for (auto *binding : arrayBindings) correctOrder.append(binding); @@ -170,6 +216,13 @@ void RestructureAstVisitor::endVisit(UiObjectMemberList *node) correctOrder.append(item->member); } + // 9th states and transitions + if (states != nullptr) + correctOrder.append(states); + + if (transitions != nullptr) + correctOrder.append(transitions); + // Rebuild member list from correctOrder for (auto *item = node; item != nullptr; item = item->next) { item->member = correctOrder.front(); diff --git a/tools/qmlimportscanner/main.cpp b/tools/qmlimportscanner/main.cpp index b563d7df95..f9f3cd90cf 100644 --- a/tools/qmlimportscanner/main.cpp +++ b/tools/qmlimportscanner/main.cpp @@ -123,7 +123,11 @@ QVariantList findImportsInAst(QQmlJS::AST::UiHeaderItemList *headerItemList, con if (!name.isEmpty()) import[nameLiteral()] = name; import[typeLiteral()] = moduleLiteral(); - auto versionString = importNode->version ? QString::number(importNode->version->majorVersion) + QLatin1Char('.') + QString::number(importNode->version->minorVersion) : QString(); + auto versionString = importNode->version + ? QString::number(importNode->version->version.majorVersion()) + + QLatin1Char('.') + + QString::number(importNode->version->version.minorVersion()) + : QString(); import[versionLiteral()] = versionString; } @@ -179,7 +183,7 @@ QPair<QString, QString> resolveImportPath(const QString &uri, const QString &ver { const QLatin1Char dot('.'); const QLatin1Char slash('/'); - const QStringList parts = uri.split(dot, QString::SkipEmptyParts); + const QStringList parts = uri.split(dot, Qt::SkipEmptyParts); QString ver = version; while (true) { @@ -277,7 +281,7 @@ QVariantList findQmlImportsInQmlCode(const QString &filePath, const QString &cod const auto diagnosticMessages = parser.diagnosticMessages(); for (const QQmlJS::DiagnosticMessage &m : diagnosticMessages) { std::cerr << QDir::toNativeSeparators(filePath).toStdString() << ':' - << m.line << ':' << m.message.toStdString() << std::endl; + << m.loc.startLine << ':' << m.message.toStdString() << std::endl; } return QVariantList(); } diff --git a/tools/qmlimportscanner/qmlimportscanner.pro b/tools/qmlimportscanner/qmlimportscanner.pro index d69f1a3b0b..33089a5c48 100644 --- a/tools/qmlimportscanner/qmlimportscanner.pro +++ b/tools/qmlimportscanner/qmlimportscanner.pro @@ -14,9 +14,9 @@ contains(CMAKE_BIN_DIR, "^\\.\\./.*") { CMAKE_BIN_DIR_IS_ABSOLUTE = True } -CMAKE_QML_DIR = $$cmakeRelativePath($$[QT_INSTALL_QML/get], $$[QT_INSTALL_PREFIX]) +CMAKE_QML_DIR = $$cmakeRelativePath($$[QT_INSTALL_QML], $$[QT_INSTALL_PREFIX]) contains(CMAKE_QML_DIR, "^\\.\\./.*") { - CMAKE_QML_DIR = $$[QT_INSTALL_QML/get]/ + CMAKE_QML_DIR = $$[QT_INSTALL_QML]/ CMAKE_QML_DIR_IS_ABSOLUTE = True } load(qt_build_paths) diff --git a/tools/qmllint/componentversion.cpp b/tools/qmllint/componentversion.cpp index e5047b8302..95403ec15f 100644 --- a/tools/qmllint/componentversion.cpp +++ b/tools/qmllint/componentversion.cpp @@ -41,21 +41,21 @@ ComponentVersion::ComponentVersion(const QString &versionString) const int maybeMinor = versionString.midRef(dotIdx + 1).toInt(&ok); if (!ok) return; - m_major = maybeMajor; - m_minor = maybeMinor; + m_version = QTypeRevision::fromVersion(maybeMajor, maybeMinor); } bool operator<(const ComponentVersion &lhs, const ComponentVersion &rhs) { - return lhs.majorVersion() < rhs.majorVersion() - || (lhs.majorVersion() == rhs.majorVersion() && lhs.minorVersion() < rhs.minorVersion()); + return lhs.version().majorVersion() < rhs.version().majorVersion() + || (lhs.version().majorVersion() == rhs.version().majorVersion() + && lhs.version().minorVersion() < rhs.version().minorVersion()); } bool operator<=(const ComponentVersion &lhs, const ComponentVersion &rhs) { - return lhs.majorVersion() < rhs.majorVersion() - || (lhs.majorVersion() == rhs.majorVersion() - && lhs.minorVersion() <= rhs.minorVersion()); + return lhs.version().majorVersion() < rhs.version().majorVersion() + || (lhs.version().majorVersion() == rhs.version().majorVersion() + && lhs.version().minorVersion() <= rhs.version().minorVersion()); } bool operator>(const ComponentVersion &lhs, const ComponentVersion &rhs) @@ -70,8 +70,8 @@ bool operator>=(const ComponentVersion &lhs, const ComponentVersion &rhs) bool operator==(const ComponentVersion &lhs, const ComponentVersion &rhs) { - return lhs.majorVersion() == rhs.majorVersion() - && lhs.minorVersion() == rhs.minorVersion(); + return lhs.version().majorVersion() == rhs.version().majorVersion() + && lhs.version().minorVersion() == rhs.version().minorVersion(); } bool operator!=(const ComponentVersion &lhs, const ComponentVersion &rhs) diff --git a/tools/qmllint/componentversion.h b/tools/qmllint/componentversion.h index 9c4604b9a3..bbb039fc40 100644 --- a/tools/qmllint/componentversion.h +++ b/tools/qmllint/componentversion.h @@ -40,24 +40,20 @@ // We mean it. #include <QtCore/qglobal.h> +#include <QtCore/qversionnumber.h> class ComponentVersion { public: - static const int NoVersion = -1; - ComponentVersion() = default; - ComponentVersion(int major, int minor) : m_major(major), m_minor(minor) {} + ComponentVersion(QTypeRevision version) : m_version(version) {} explicit ComponentVersion(const QString &versionString); - int majorVersion() const { return m_major; } - int minorVersion() const { return m_minor; } - - bool isValid() const { return m_major >= 0 && m_minor >= 0; } + QTypeRevision version() const { return m_version; } + bool isValid() const { return m_version.hasMajorVersion() && m_version.hasMinorVersion(); } private: - int m_major = NoVersion; - int m_minor = NoVersion; + QTypeRevision m_version; }; bool operator<(const ComponentVersion &lhs, const ComponentVersion &rhs); diff --git a/tools/qmllint/findunqualified.cpp b/tools/qmllint/findunqualified.cpp index 807110c3c1..6155ea4637 100644 --- a/tools/qmllint/findunqualified.cpp +++ b/tools/qmllint/findunqualified.cpp @@ -92,8 +92,7 @@ void FindUnqualifiedIDVisitor::parseHeaders(QQmlJS::AST::UiHeaderItemList *heade if (import->asToken.isValid()) { prefix += import->importId + QLatin1Char('.'); } - importHelper(path, prefix, import->version->majorVersion, - import->version->minorVersion); + importHelper(path, prefix, import->version->version); } } header = header->next; @@ -119,26 +118,27 @@ ScopeTree *FindUnqualifiedIDVisitor::parseProgram(QQmlJS::AST::Program *program, enum ImportVersion { FullyVersioned, PartiallyVersioned, Unversioned, BasePath }; -QStringList completeImportPaths(const QString &uri, const QString &basePath, int vmaj, int vmin) +QStringList completeImportPaths(const QString &uri, const QString &basePath, QTypeRevision version) { static const QLatin1Char Slash('/'); static const QLatin1Char Backslash('\\'); - const QVector<QStringRef> parts = uri.splitRef(QLatin1Char('.'), QString::SkipEmptyParts); + const QVector<QStringRef> parts = uri.splitRef(QLatin1Char('.'), Qt::SkipEmptyParts); QStringList qmlDirPathsPaths; // fully & partially versioned parts + 1 unversioned for each base path qmlDirPathsPaths.reserve(2 * parts.count() + 1); - auto versionString = [](int vmaj, int vmin, ImportVersion version) + auto versionString = [](QTypeRevision version, ImportVersion mode) { - if (version == FullyVersioned) { + if (mode == FullyVersioned) { // extension with fully encoded version number (eg. MyModule.3.2) - return QString::fromLatin1(".%1.%2").arg(vmaj).arg(vmin); + return QString::fromLatin1(".%1.%2").arg(version.majorVersion()) + .arg(version.minorVersion()); } - if (version == PartiallyVersioned) { + if (mode == PartiallyVersioned) { // extension with encoded version major (eg. MyModule.3) - return QString::fromLatin1(".%1").arg(vmaj); + return QString::fromLatin1(".%1").arg(version.majorVersion()); } // else extension without version number (eg. MyModule) return QString(); @@ -153,24 +153,24 @@ QStringList completeImportPaths(const QString &uri, const QString &basePath, int return str; }; - const ImportVersion initial = (vmin >= 0) + const ImportVersion initial = (version.hasMinorVersion()) ? FullyVersioned - : (vmaj >= 0 ? PartiallyVersioned : Unversioned); - for (int version = initial; version <= BasePath; ++version) { - const QString ver = versionString(vmaj, vmin, static_cast<ImportVersion>(version)); + : (version.hasMajorVersion() ? PartiallyVersioned : Unversioned); + for (int mode = initial; mode <= BasePath; ++mode) { + const QString ver = versionString(version, ImportVersion(mode)); QString dir = basePath; if (!dir.endsWith(Slash) && !dir.endsWith(Backslash)) dir += Slash; - if (version == BasePath) { + if (mode == BasePath) { qmlDirPathsPaths += dir; } else { // append to the end qmlDirPathsPaths += dir + joinStringRefs(parts, Slash) + ver; } - if (version < Unversioned) { + if (mode < Unversioned) { // insert in the middle for (int index = parts.count() - 2; index >= 0; --index) { qmlDirPathsPaths += dir + joinStringRefs(parts.mid(0, index + 1), Slash) @@ -222,7 +222,7 @@ FindUnqualifiedIDVisitor::Import FindUnqualifiedIDVisitor::readQmldir(const QStr (*mo)->addExport( it.key(), reader.typeNamespace(), - ComponentVersion(it->majorVersion, it->minorVersion)); + ComponentVersion(it->version)); } for (auto it = qmlComponents.begin(), end = qmlComponents.end(); it != end; ++it) result.objects.insert( it.key(), ScopeTree::ConstPtr(it.value())); @@ -240,11 +240,11 @@ void FindUnqualifiedIDVisitor::processImport(const QString &prefix, const FindUn auto const &id = split.at(0); if (split.length() > 1) { const auto version = split.at(1).split('.'); - importHelper(id, QString(), - version.at(0).toInt(), - version.length() > 1 ? version.at(1).toInt() : -1); + importHelper(id, QString(), QTypeRevision::fromVersion( + version.at(0).toInt(), + version.length() > 1 ? version.at(1).toInt() : -1)); } else { - importHelper(id, QString(), -1, -1); + importHelper(id, QString(), QTypeRevision()); } @@ -267,7 +267,7 @@ void FindUnqualifiedIDVisitor::processImport(const QString &prefix, const FindUn } void FindUnqualifiedIDVisitor::importHelper(const QString &module, const QString &prefix, - int major, int minor) + QTypeRevision version) { const QString id = QString(module).replace(QLatin1Char('/'), QLatin1Char('.')); QPair<QString, QString> importId { id, prefix }; @@ -276,7 +276,7 @@ void FindUnqualifiedIDVisitor::importHelper(const QString &module, const QString m_alreadySeenImports.insert(importId); for (const QString &qmltypeDir : m_qmltypeDirs) { - auto qmltypesPaths = completeImportPaths(id, qmltypeDir, major, minor); + auto qmltypesPaths = completeImportPaths(id, qmltypeDir, version); for (auto const &qmltypesPath : qmltypesPaths) { if (QFile::exists(qmltypesPath + SlashQmldir)) { @@ -764,7 +764,7 @@ bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::UiImport *import) } path.chop(1); - importHelper(path, prefix, import->version->majorVersion, import->version->minorVersion); + importHelper(path, prefix, import->version->version); } return true; } diff --git a/tools/qmllint/findunqualified.h b/tools/qmllint/findunqualified.h index 6668b53b08..1c351e4fd9 100644 --- a/tools/qmllint/findunqualified.h +++ b/tools/qmllint/findunqualified.h @@ -91,7 +91,7 @@ private: void enterEnvironment(ScopeType type, const QString &name); void leaveEnvironment(); void importHelper(const QString &module, const QString &prefix = QString(), - int major = -1, int minor = -1); + QTypeRevision version = QTypeRevision()); void readQmltypes(const QString &filename, Import &result); Import readQmldir(const QString &dirname); diff --git a/tools/qmllint/main.cpp b/tools/qmllint/main.cpp index 0a0e669e94..fa601986b2 100644 --- a/tools/qmllint/main.cpp +++ b/tools/qmllint/main.cpp @@ -78,7 +78,7 @@ static bool lint_file(const QString &filename, const bool silent, const bool war const auto diagnosticMessages = parser.diagnosticMessages(); for (const QQmlJS::DiagnosticMessage &m : diagnosticMessages) { qWarning().noquote() << QString::fromLatin1("%1:%2 : %3") - .arg(filename).arg(m.line).arg(m.message); + .arg(filename).arg(m.loc.startLine).arg(m.message); } } diff --git a/tools/qmllint/scopetree.cpp b/tools/qmllint/scopetree.cpp index 2ca3ed9a67..e7e0113f35 100644 --- a/tools/qmllint/scopetree.cpp +++ b/tools/qmllint/scopetree.cpp @@ -62,7 +62,7 @@ void ScopeTree::insertJSIdentifier(const QString &id, QQmlJS::AST::VariableScope } void ScopeTree::insertSignalIdentifier(const QString &id, const MetaMethod &method, - const QQmlJS::AST::SourceLocation &loc, + const QQmlJS::SourceLocation &loc, bool hasMultilineHandlerBody) { Q_ASSERT(m_scopeType == ScopeType::QMLScope); @@ -77,7 +77,7 @@ void ScopeTree::insertPropertyIdentifier(const MetaProperty &property) } void ScopeTree::addUnmatchedSignalHandler(const QString &handler, - const QQmlJS::AST::SourceLocation &location) + const QQmlJS::SourceLocation &location) { m_unmatchedSignalHandlers.append(qMakePair(handler, location)); } @@ -87,13 +87,13 @@ bool ScopeTree::isIdInCurrentScope(const QString &id) const return isIdInCurrentQMlScopes(id) || isIdInCurrentJSScopes(id); } -void ScopeTree::addIdToAccessed(const QString &id, const QQmlJS::AST::SourceLocation &location) { +void ScopeTree::addIdToAccessed(const QString &id, const QQmlJS::SourceLocation &location) { m_currentFieldMember = new FieldMemberList {id, QString(), location, {}}; m_accessedIdentifiers.push_back(std::unique_ptr<FieldMemberList>(m_currentFieldMember)); } void ScopeTree::accessMember(const QString &name, const QString &parentType, - const QQmlJS::AST::SourceLocation &location) + const QQmlJS::SourceLocation &location) { Q_ASSERT(m_currentFieldMember); auto *fieldMember = new FieldMemberList {name, parentType, location, {}}; @@ -115,7 +115,7 @@ bool ScopeTree::isVisualRootScope() const class IssueLocationWithContext { public: - IssueLocationWithContext(const QString &code, const QQmlJS::AST::SourceLocation &location) { + IssueLocationWithContext(const QString &code, const QQmlJS::SourceLocation &location) { int before = std::max(0,code.lastIndexOf('\n', location.offset)); m_beforeText = code.midRef(before + 1, int(location.offset - (before + 1))); m_issueText = code.midRef(location.offset, location.length); @@ -440,7 +440,7 @@ const ScopeTree *ScopeTree::currentQMLScope() const } void ScopeTree::printContext(ColorOutput &colorOut, const QString &code, - const QQmlJS::AST::SourceLocation &location) const + const QQmlJS::SourceLocation &location) const { IssueLocationWithContext issueLocationWithContext {code, location}; colorOut.write(issueLocationWithContext.beforeText().toString(), Normal); diff --git a/tools/qmllint/scopetree.h b/tools/qmllint/scopetree.h index f5d1155a49..63f4310bf8 100644 --- a/tools/qmllint/scopetree.h +++ b/tools/qmllint/scopetree.h @@ -68,7 +68,7 @@ enum class ScopeType struct MethodUsage { MetaMethod method; - QQmlJS::AST::SourceLocation loc; + QQmlJS::SourceLocation loc; bool hasMultilineHandlerBody; }; @@ -112,16 +112,16 @@ public: void insertJSIdentifier(const QString &id, QQmlJS::AST::VariableScope scope); void insertSignalIdentifier(const QString &id, const MetaMethod &method, - const QQmlJS::AST::SourceLocation &loc, bool hasMultilineHandlerBody); + const QQmlJS::SourceLocation &loc, bool hasMultilineHandlerBody); // inserts property as qml identifier as well as the corresponding void insertPropertyIdentifier(const MetaProperty &prop); void addUnmatchedSignalHandler(const QString &handler, - const QQmlJS::AST::SourceLocation &location); + const QQmlJS::SourceLocation &location); bool isIdInCurrentScope(const QString &id) const; - void addIdToAccessed(const QString &id, const QQmlJS::AST::SourceLocation &location); + void addIdToAccessed(const QString &id, const QQmlJS::SourceLocation &location); void accessMember(const QString &name, const QString &parentType, - const QQmlJS::AST::SourceLocation &location); + const QQmlJS::SourceLocation &location); void resetMemberScope(); bool isVisualRootScope() const; @@ -174,7 +174,7 @@ private: { QString m_name; QString m_parentType; - QQmlJS::AST::SourceLocation m_location; + QQmlJS::SourceLocation m_location; std::unique_ptr<FieldMemberList> m_child; }; @@ -188,7 +188,7 @@ private: std::vector<std::unique_ptr<FieldMemberList>> m_accessedIdentifiers; FieldMemberList *m_currentFieldMember = nullptr; - QVector<QPair<QString, QQmlJS::AST::SourceLocation>> m_unmatchedSignalHandlers; + QVector<QPair<QString, QQmlJS::SourceLocation>> m_unmatchedSignalHandlers; QVector<ScopeTree::Ptr> m_childScopes; ScopeTree *m_parentScope; @@ -211,7 +211,7 @@ private: bool isIdInjectedFromSignal(const QString &id) const; const ScopeTree *currentQMLScope() const; void printContext(ColorOutput &colorOut, const QString &code, - const QQmlJS::AST::SourceLocation &location) const; + const QQmlJS::SourceLocation &location) const; bool checkMemberAccess( const QString &code, FieldMemberList *members, diff --git a/tools/qmllint/typedescriptionreader.cpp b/tools/qmllint/typedescriptionreader.cpp index 3dc87ffc8d..8734f349d5 100644 --- a/tools/qmllint/typedescriptionreader.cpp +++ b/tools/qmllint/typedescriptionreader.cpp @@ -102,7 +102,7 @@ void TypeDescriptionReader::readDocument(UiProgram *ast) return; } - if (import->version->majorVersion != 1) { + if (import->version->version.majorVersion() != 1) { addError(import->version->firstSourceLocation(), tr("Major version different from 1 not supported.")); return; diff --git a/tools/qmllint/typedescriptionreader.h b/tools/qmllint/typedescriptionreader.h index 5fcbe3abc9..48c33bee3c 100644 --- a/tools/qmllint/typedescriptionreader.h +++ b/tools/qmllint/typedescriptionreader.h @@ -90,8 +90,8 @@ private: void readMetaObjectRevisions(QQmlJS::AST::UiScriptBinding *ast, const ScopeTree::Ptr &scope); void readEnumValues(QQmlJS::AST::UiScriptBinding *ast, MetaEnum *metaEnum); - void addError(const QQmlJS::AST::SourceLocation &loc, const QString &message); - void addWarning(const QQmlJS::AST::SourceLocation &loc, const QString &message); + void addError(const QQmlJS::SourceLocation &loc, const QString &message); + void addWarning(const QQmlJS::SourceLocation &loc, const QString &message); QString m_fileName; QString m_source; diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp index 947b5dff27..3efa4dc605 100644 --- a/tools/qmlplugindump/main.cpp +++ b/tools/qmlplugindump/main.cpp @@ -103,15 +103,15 @@ static QString enquote(const QString &string) struct QmlVersionInfo { QString pluginImportUri; - int majorVersion; - int minorVersion; + QTypeRevision version; bool strict; }; static bool matchingImportUri(const QQmlType &ty, const QmlVersionInfo& versionInfo) { if (versionInfo.strict) { return (versionInfo.pluginImportUri == ty.module() - && (ty.majorVersion() == versionInfo.majorVersion || ty.majorVersion() == -1)) + && (ty.version().majorVersion() == versionInfo.version.majorVersion() + || !ty.version().hasMajorVersion())) || ty.module().isEmpty(); } return ty.module().isEmpty() @@ -335,23 +335,23 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine, } class KnownAttributes { - QHash<QByteArray, int> m_properties; - QHash<QByteArray, QHash<int, int> > m_methods; + QHash<QByteArray, QTypeRevision> m_properties; + QHash<QByteArray, QHash<int, QTypeRevision> > m_methods; public: - bool knownMethod(const QByteArray &name, int nArgs, int revision) + bool knownMethod(const QByteArray &name, int nArgs, QTypeRevision revision) { if (m_methods.contains(name)) { - QHash<int, int> overloads = m_methods.value(name); - if (overloads.contains(nArgs) && overloads.value(nArgs) <= revision) + QHash<int, QTypeRevision> overloads = m_methods.value(name); + if (overloads.contains(nArgs) && overloads.value(nArgs).toEncodedVersion<quint16>() <= revision.toEncodedVersion<quint16>()) return true; } m_methods[name][nArgs] = revision; return false; } - bool knownProperty(const QByteArray &name, int revision) + bool knownProperty(const QByteArray &name, QTypeRevision revision) { - if (m_properties.contains(name) && m_properties.value(name) <= revision) + if (m_properties.contains(name) && m_properties.value(name).toEncodedVersion<quint16>() <= revision.toEncodedVersion<quint16>()) return true; m_properties[name] = revision; return false; @@ -375,13 +375,14 @@ public: { const QString module = type.module().isEmpty() ? versionInfo.pluginImportUri : type.module(); - const int majorVersion = type.majorVersion() >= 0 ? type.majorVersion() - : versionInfo.majorVersion; - const int minorVersion = type.minorVersion() >= 0 ? type.minorVersion() - : versionInfo.minorVersion; + QTypeRevision version = QTypeRevision::fromVersion( + type.version().hasMajorVersion() ? type.version().majorVersion() + : versionInfo.version.majorVersion(), + type.version().hasMinorVersion() ? type.version().minorVersion() + : versionInfo.version.minorVersion()); const QString versionedElement = type.elementName() - + QString::fromLatin1(" %1.%2").arg(majorVersion).arg(minorVersion); + + QString::fromLatin1(" %1.%2").arg(version.majorVersion()).arg(version.minorVersion()); return enquote((module == relocatableModuleUri) ? versionedElement @@ -390,7 +391,7 @@ public: void writeMetaContent(const QMetaObject *meta, KnownAttributes *knownAttributes = nullptr) { - QSet<QString> implicitSignals = dumpMetaProperties(meta, 0, knownAttributes); + QSet<QString> implicitSignals = dumpMetaProperties(meta, QTypeRevision::zero(), knownAttributes); if (meta == &QObject::staticMetaObject) { // for QObject, hide deleteLater() and onDestroyed @@ -405,17 +406,17 @@ public: } // and add toString(), destroy() and destroy(int) - if (!knownAttributes || !knownAttributes->knownMethod(QByteArray("toString"), 0, 0)) { + if (!knownAttributes || !knownAttributes->knownMethod(QByteArray("toString"), 0, QTypeRevision::zero())) { qml->writeStartObject(QLatin1String("Method")); qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("toString"))); qml->writeEndObject(); } - if (!knownAttributes || !knownAttributes->knownMethod(QByteArray("destroy"), 0, 0)) { + if (!knownAttributes || !knownAttributes->knownMethod(QByteArray("destroy"), 0, QTypeRevision::zero())) { qml->writeStartObject(QLatin1String("Method")); qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("destroy"))); qml->writeEndObject(); } - if (!knownAttributes || !knownAttributes->knownMethod(QByteArray("destroy"), 1, 0)) { + if (!knownAttributes || !knownAttributes->knownMethod(QByteArray("destroy"), 1, QTypeRevision::zero())) { qml->writeStartObject(QLatin1String("Method")); qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("destroy"))); qml->writeStartObject(QLatin1String("Parameter")); @@ -498,7 +499,12 @@ public: qml->writeScriptBinding(QLatin1String("name"), exportString); qml->writeArrayBinding(QLatin1String("exports"), QStringList() << exportString); - qml->writeArrayBinding(QLatin1String("exportMetaObjectRevisions"), QStringList() << QString::number(compositeType.minorVersion())); + + // TODO: shouldn't this be metaObjectRevision().value<quint16>() + // rather than version().minorVersion() + qml->writeArrayBinding(QLatin1String("exportMetaObjectRevisions"), QStringList() + << QString::number(compositeType.version().minorVersion())); + qml->writeBooleanBinding(QLatin1String("isComposite"), true); if (compositeType.isSingleton()) { @@ -537,10 +543,10 @@ public: struct QmlTypeInfo { QmlTypeInfo() {} - QmlTypeInfo(const QString &exportString, int revision, const QMetaObject *extendedObject, QByteArray attachedTypeId) + QmlTypeInfo(const QString &exportString, QTypeRevision revision, const QMetaObject *extendedObject, QByteArray attachedTypeId) : exportString(exportString), revision(revision), extendedObject(extendedObject), attachedTypeId(attachedTypeId) {} QString exportString; - int revision = 0; + QTypeRevision revision = QTypeRevision::zero(); const QMetaObject *extendedObject = nullptr; QByteArray attachedTypeId; }; @@ -563,11 +569,11 @@ public: if (attachedType != meta) attachedTypeId = convertToId(attachedType); } - const QString exportString = getExportString(type, { QString(), -1, -1, false }); - int metaObjectRevision = type.metaObjectRevision(); + const QString exportString = getExportString(type, { QString(), QTypeRevision(), false }); + QTypeRevision metaObjectRevision = type.metaObjectRevision(); if (extendedObject) { // emulate custom metaobjectrevision out of import - metaObjectRevision = type.majorVersion() * 100 + type.minorVersion(); + metaObjectRevision = type.version(); } QmlTypeInfo info = { exportString, metaObjectRevision, extendedObject, attachedTypeId }; @@ -576,7 +582,7 @@ public: // sort to ensure stable output std::sort(typeInfo.begin(), typeInfo.end(), [](const QmlTypeInfo &i1, const QmlTypeInfo &i2) { - return i1.revision < i2.revision; + return i1.revision.toEncodedVersion<quint16>() < i2.revision.toEncodedVersion<quint16>(); }); // determine default property @@ -600,7 +606,7 @@ public: if (!typeInfo.isEmpty()) { QMap<QString, QString> exports; // sort exports for (const QmlTypeInfo &iter : typeInfo) - exports.insert(iter.exportString, QString::number(iter.revision)); + exports.insert(iter.exportString, QString::number(iter.revision.toEncodedVersion<quint16>())); QStringList exportStrings = exports.keys(); QStringList metaObjectRevisions = exports.values(); @@ -681,22 +687,27 @@ private: qml->writeScriptBinding(QLatin1String("isPointer"), QLatin1String("true")); } - void dump(const QMetaProperty &prop, int metaRevision = -1, KnownAttributes *knownAttributes = nullptr) + void dump(const QMetaProperty &prop, QTypeRevision metaRevision = QTypeRevision(), + KnownAttributes *knownAttributes = nullptr) { - int revision = metaRevision ? metaRevision : prop.revision(); + // TODO: should that not be metaRevision.isValid() rather than comparing to zero()? + QTypeRevision revision = (metaRevision == QTypeRevision::zero()) + ? QTypeRevision::fromEncodedVersion(prop.revision()) + : metaRevision; QByteArray propName = prop.name(); if (knownAttributes && knownAttributes->knownProperty(propName, revision)) return; qml->writeStartObject("Property"); qml->writeScriptBinding(QLatin1String("name"), enquote(QString::fromUtf8(prop.name()))); - if (revision) - qml->writeScriptBinding(QLatin1String("revision"), QString::number(revision)); + if (revision != QTypeRevision::zero()) + qml->writeScriptBinding(QLatin1String("revision"), QString::number(revision.toEncodedVersion<quint16>())); writeTypeProperties(prop.typeName(), prop.isWritable()); qml->writeEndObject(); } - QSet<QString> dumpMetaProperties(const QMetaObject *meta, int metaRevision = -1, KnownAttributes *knownAttributes = nullptr) + QSet<QString> dumpMetaProperties(const QMetaObject *meta, QTypeRevision metaRevision = QTypeRevision(), + KnownAttributes *knownAttributes = nullptr) { QSet<QString> implicitSignals; for (int index = meta->propertyOffset(); index < meta->propertyCount(); ++index) { @@ -704,7 +715,7 @@ private: dump(property, metaRevision, knownAttributes); if (knownAttributes) knownAttributes->knownMethod(QByteArray(property.name()).append("Changed"), - 0, property.revision()); + 0, QTypeRevision::fromEncodedVersion(property.revision())); implicitSignals.insert(QString("%1Changed").arg(QString::fromUtf8(property.name()))); } return implicitSignals; @@ -732,7 +743,7 @@ private: return; } - int revision = meth.revision(); + QTypeRevision revision = QTypeRevision::fromEncodedVersion(meth.revision()); if (knownAttributes && knownAttributes->knownMethod(name, meth.parameterNames().size(), revision)) return; if (meth.methodType() == QMetaMethod::Signal) @@ -742,8 +753,8 @@ private: qml->writeScriptBinding(QLatin1String("name"), enquote(name)); - if (revision) - qml->writeScriptBinding(QLatin1String("revision"), QString::number(revision)); + if (revision != QTypeRevision::zero()) + qml->writeScriptBinding(QLatin1String("revision"), QString::number(revision.toEncodedVersion<quint16>())); if (typeName != QLatin1String("void")) qml->writeScriptBinding(QLatin1String("type"), enquote(typeName)); @@ -1001,9 +1012,9 @@ static bool operator<(const QQmlType &a, const QQmlType &b) { return a.qmlTypeName() < b.qmlTypeName() || (a.qmlTypeName() == b.qmlTypeName() - && ((a.majorVersion() < b.majorVersion()) - || (a.majorVersion() == b.majorVersion() - && a.minorVersion() < b.minorVersion()))); + && ((a.version().majorVersion() < b.version().majorVersion()) + || (a.version().majorVersion() == b.version().majorVersion() + && a.version().minorVersion() < b.version().minorVersion()))); } QT_END_NAMESPACE @@ -1243,11 +1254,13 @@ int main(int argc, char *argv[]) // composite types we want to dump information of QMap<QString, QList<QQmlType>> compositeTypes; - int majorVersion = qtQmlMajorVersion, minorVersion = qtQmlMinorVersion; + QTypeRevision version = QTypeRevision::fromVersion(qtQmlMajorVersion, qtQmlMinorVersion); QmlVersionInfo info; if (action == Builtins) { QMap<QString, QList<QQmlType>> defaultCompositeTypes; - QSet<const QMetaObject *> builtins = collectReachableMetaObjects(&engine, uncreatableMetas, singletonMetas, defaultCompositeTypes, {QLatin1String("Qt"), majorVersion, minorVersion, strict}); + QSet<const QMetaObject *> builtins = collectReachableMetaObjects( + &engine, uncreatableMetas, singletonMetas, defaultCompositeTypes, + {QLatin1String("Qt"), version, strict}); Q_ASSERT(builtins.size() == 1); metas.insert(*builtins.begin()); } else { @@ -1256,12 +1269,13 @@ int main(int argc, char *argv[]) if (!ok) qCritical("Invalid version number"); else { - majorVersion = versionSplitted.at(0).toInt(&ok); + const int majorVersion = versionSplitted.at(0).toInt(&ok); if (!ok) qCritical("Invalid major version"); - minorVersion = versionSplitted.at(1).toInt(&ok); + const int minorVersion = versionSplitted.at(1).toInt(&ok); if (!ok) qCritical("Invalid minor version"); + version = QTypeRevision::fromVersion(majorVersion, minorVersion); } QList<QQmlType> defaultTypes = QQmlMetaType::qmlTypes(); // find a valid QtQuick import @@ -1273,9 +1287,9 @@ int main(int argc, char *argv[]) } else { QString module = qtObjectType.qmlTypeName(); module = module.mid(0, module.lastIndexOf(QLatin1Char('/'))); - importCode = QString("import %1 %2.%3").arg(module, - QString::number(qtObjectType.majorVersion()), - QString::number(qtObjectType.minorVersion())).toUtf8(); + importCode = QString("import %1 %2.%3").arg( + module, QString::number(qtObjectType.version().majorVersion()), + QString::number(qtObjectType.version().minorVersion())).toUtf8(); } // avoid importing dependencies? for (const QString &moduleToImport : qAsConst(dependencies)) { @@ -1307,7 +1321,7 @@ int main(int argc, char *argv[]) return EXIT_IMPORTERROR; } } - info = {pluginImportUri, majorVersion, minorVersion, strict}; + info = {pluginImportUri, version, strict}; QSet<const QMetaObject *> candidates = collectReachableMetaObjects(&engine, uncreatableMetas, singletonMetas, compositeTypes, info, defaultTypes); for (auto it = compositeTypes.begin(), end = compositeTypes.end(); it != end; ++it) { diff --git a/tools/qmlprofiler/qmlprofilerapplication.cpp b/tools/qmlprofiler/qmlprofilerapplication.cpp index 7b010546c3..7c92f428ae 100644 --- a/tools/qmlprofiler/qmlprofilerapplication.cpp +++ b/tools/qmlprofiler/qmlprofilerapplication.cpp @@ -354,7 +354,7 @@ bool QmlProfilerApplication::checkOutputFile(PendingRequest pending) void QmlProfilerApplication::userCommand(const QString &command) { - auto args = command.splitRef(QChar::Space, QString::SkipEmptyParts); + auto args = command.splitRef(QChar::Space, Qt::SkipEmptyParts); if (args.isEmpty()) { prompt(); return; diff --git a/tools/qmlscene/main.cpp b/tools/qmlscene/main.cpp index 28370cb522..b0635a7e87 100644 --- a/tools/qmlscene/main.cpp +++ b/tools/qmlscene/main.cpp @@ -500,7 +500,8 @@ int main(int argc, char ** argv) } } - if (qEnvironmentVariableIsSet("QMLSCENE_CORE_PROFILE")) + if (qEnvironmentVariableIsSet("QMLSCENE_CORE_PROFILE") + || qEnvironmentVariableIsSet("QSG_CORE_PROFILE")) options.coreProfile = true; // Set default surface format before creating the window diff --git a/tools/qmltestrunner/main.cpp b/tools/qmltestrunner/main.cpp index 687d6fbb01..2463757282 100644 --- a/tools/qmltestrunner/main.cpp +++ b/tools/qmltestrunner/main.cpp @@ -28,9 +28,6 @@ #include <QtQuickTest/quicktest.h> #include <QtCore/qstring.h> -#ifdef QT_OPENGL_LIB -#include <QtOpenGL/qgl.h> -#endif int main(int argc, char **argv) { 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 diff --git a/tools/tools.pro b/tools/tools.pro index d16f78071c..07eaa0be70 100644 --- a/tools/tools.pro +++ b/tools/tools.pro @@ -7,11 +7,11 @@ qtConfig(qml-devtools) { qmlimportscanner \ qmlformat - qtConfig(commandlineparser):qtConfig(xmlstreamwriter): SUBDIRS += qmlcachegen + qtConfig(xmlstreamwriter): SUBDIRS += qmlcachegen } qtConfig(thread):!android|android_app:!wasm:!rtems { - qtConfig(commandlineparser): SUBDIRS += qml + SUBDIRS += qml qtConfig(qml-profiler): SUBDIRS += qmlprofiler qtConfig(qml-preview): SUBDIRS += qmlpreview |