diff options
author | Antti Piira <apiira@blackberry.com> | 2013-08-22 12:08:37 -0700 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-21 01:20:55 +0200 |
commit | 200a869441562d62e7fc0867599097e0599f0411 (patch) | |
tree | 982dc3c5a9c22bdea24a21054dd2b434fcea1147 /tests/auto | |
parent | b365471f0abc79f08bf0d852aea3be0a601c6901 (diff) |
Add Singleton support for QML
This introduces Singleton support for QML (Composite Singleton). For
now, the Singleton support is only availabe for QML types in modules
or (remote and local) directories with qmldir file. However, in the
future this support may be expanded to arbitrary QML file imports
without by leaving out the qmldir requirement.
You define a QML type as a Singleton with the following two steps:
1. By adding a pragma Singleton to a type's QML file:
pragma Singleton
The pragma and import statements can be mixed and their order does
not matter. Singleton is the only supported pragma for now. Others
will generate errors.
2. By specifying a qmldir file for the directory of your imported
type and prepending the type with "singleton" keyword as follows:
singleton TestTypeSingleton TestTypeSingleton.qml
Alternatively you may specify a qmldir file for a module and specify
your type as a singleton as follows:
singleton TestTypeSingleton 1.0 TestTypeSingleton.qml
Composite Singletons may be included in a module and may be used with
a local namespace qualifier when imported with:
"import xxx as NameSpace"
A singleton instance is created at first use and stored into the
QmlEngine (one instance per engine) and eventually released by the
engine's destructor.
CompositeSingletonType has a dual nature and will return true to both
isComposite() and isSingleton() calls. In most cases its enough to
check for just isComposite() or isSingleton(). However, there is a
isCompositeSingleton() available as well.
I used "qlalr --no-debug --no-lines --qt qqmljs.g" to generate the
qqmljsparser and qqmljsgrammar files from qqmljs.g.
Unit tests are included.
Change-Id: I91b303612c5e132143b325b9a8f982e9355bc90e
Reviewed-by: Alan Alpert (Personal) <416365416c@gmail.com>
Diffstat (limited to 'tests/auto')
45 files changed, 721 insertions, 8 deletions
diff --git a/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp b/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp index 634a6e5df1..b37c6a14dc 100644 --- a/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp +++ b/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp @@ -157,8 +157,7 @@ void tst_qqmldirparser::parse_data() QTest::newRow("four-sections") << "four-sections/qmldir" - << (QStringList() << "qmldir:1:12: unexpected token" - << "qmldir:1: invalid qmldir directive contains too many tokens") + << (QStringList() << "qmldir:1: a component declaration requires two or three arguments, but 4 were provided") << QStringList() << QStringList() << QStringList(); @@ -200,8 +199,7 @@ void tst_qqmldirparser::parse_data() QTest::newRow("excessive-plugin") << "excessive-plugin/qmldir" - << (QStringList() << "qmldir:1:15: unexpected token" - << "qmldir:1: invalid qmldir directive contains too many tokens") + << (QStringList() << "qmldir:1: plugin directive requires one or two arguments, but 3 were provided") << QStringList() << QStringList() << QStringList(); diff --git a/tests/auto/qml/qqmllanguage/data/singleton/SingletonType.qml b/tests/auto/qml/qqmllanguage/data/singleton/SingletonType.qml new file mode 100644 index 0000000000..a2f1a4eeb7 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singleton/SingletonType.qml @@ -0,0 +1,18 @@ +import QtQuick 2.0 +pragma Singleton + +Item { + id: singletonId + + property int testProp1: 125 + property int testProp2: 25 + property int testProp3: -55 + + width: 25; height: 25 + + Rectangle { + id: rectangle + border.color: "white" + anchors.fill: parent + } +}
\ No newline at end of file diff --git a/tests/auto/qml/qqmllanguage/data/singleton/js/jspragma.js b/tests/auto/qml/qqmllanguage/data/singleton/js/jspragma.js new file mode 100644 index 0000000000..b652689a48 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singleton/js/jspragma.js @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2013 BlackBerry Limited. All rights reserved. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Digia Plc and its Subsidiary(-ies) 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$ +** +****************************************************************************/ + +.pragma library + +var value = 333 diff --git a/tests/auto/qml/qqmllanguage/data/singleton/module/org/qtproject/SingletonTest/NonSingletonType.qml b/tests/auto/qml/qqmllanguage/data/singleton/module/org/qtproject/SingletonTest/NonSingletonType.qml new file mode 100644 index 0000000000..9a3b7abbd6 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singleton/module/org/qtproject/SingletonTest/NonSingletonType.qml @@ -0,0 +1,17 @@ +import QtQuick 2.0 + +Item { + id: singletonId + + property int testProp1: 125 + property int testProp2: 25 + property int testProp3: -55 + + width: 25; height: 25 + + Rectangle { + id: rectangle + border.color: "white" + anchors.fill: parent + } +}
\ No newline at end of file diff --git a/tests/auto/qml/qqmllanguage/data/singleton/module/org/qtproject/SingletonTest/NonSingletonType25.qml b/tests/auto/qml/qqmllanguage/data/singleton/module/org/qtproject/SingletonTest/NonSingletonType25.qml new file mode 100644 index 0000000000..ca4d87faf7 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singleton/module/org/qtproject/SingletonTest/NonSingletonType25.qml @@ -0,0 +1,17 @@ +import QtQuick 2.0 + +Item { + id: singletonId + + property int testProp1: 225 + property int testProp2: 125 + property int testProp3: 55 + + width: 25; height: 25 + + Rectangle { + id: rectangle + border.color: "white" + anchors.fill: parent + } +}
\ No newline at end of file diff --git a/tests/auto/qml/qqmllanguage/data/singleton/module/org/qtproject/SingletonTest/SingletonType.qml b/tests/auto/qml/qqmllanguage/data/singleton/module/org/qtproject/SingletonTest/SingletonType.qml new file mode 100644 index 0000000000..a2f1a4eeb7 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singleton/module/org/qtproject/SingletonTest/SingletonType.qml @@ -0,0 +1,18 @@ +import QtQuick 2.0 +pragma Singleton + +Item { + id: singletonId + + property int testProp1: 125 + property int testProp2: 25 + property int testProp3: -55 + + width: 25; height: 25 + + Rectangle { + id: rectangle + border.color: "white" + anchors.fill: parent + } +}
\ No newline at end of file diff --git a/tests/auto/qml/qqmllanguage/data/singleton/module/org/qtproject/SingletonTest/SingletonType22.qml b/tests/auto/qml/qqmllanguage/data/singleton/module/org/qtproject/SingletonTest/SingletonType22.qml new file mode 100644 index 0000000000..2ca61b0fcc --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singleton/module/org/qtproject/SingletonTest/SingletonType22.qml @@ -0,0 +1,18 @@ +pragma Singleton +import QtQuick 2.0 + +Item { + id: singletonId + + property int testProp1: 225 + property int testProp2: 125 + property int testProp3: 55 + + width: 25; height: 25 + + Rectangle { + id: rectangle + border.color: "white" + anchors.fill: parent + } +}
\ No newline at end of file diff --git a/tests/auto/qml/qqmllanguage/data/singleton/module/org/qtproject/SingletonTest/qmldir b/tests/auto/qml/qqmllanguage/data/singleton/module/org/qtproject/SingletonTest/qmldir new file mode 100644 index 0000000000..91fc8f9139 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singleton/module/org/qtproject/SingletonTest/qmldir @@ -0,0 +1,5 @@ +module org.qtproject.SingletonTest +singleton SingletonType 1.0 SingletonType.qml +singleton SingletonType 2.2 SingletonType22.qml +NonSingletonType 1.0 NonSingletonType.qml +NonSingletonType 2.5 NonSingletonType25.qml diff --git a/tests/auto/qml/qqmllanguage/data/singleton/qmldir b/tests/auto/qml/qqmllanguage/data/singleton/qmldir new file mode 100644 index 0000000000..533fb6999a --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singleton/qmldir @@ -0,0 +1,3 @@ +singleton SingletonType SingletonType.qml + + diff --git a/tests/auto/qml/qqmllanguage/data/singleton/qmldir-error/SType2.qml b/tests/auto/qml/qqmllanguage/data/singleton/qmldir-error/SType2.qml new file mode 100644 index 0000000000..43450afcec --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singleton/qmldir-error/SType2.qml @@ -0,0 +1,18 @@ +import QtQuick 2.0 +pragma Singleton + +Item { + id: singletonId + + property int testProp1: 125 + property int testProp2: 25 + property int testProp3: -55 + + width: 25; height: 25 + + Rectangle { + id: rectangle + border.color: "white" + anchors.fill: parent + } +} diff --git a/tests/auto/qml/qqmllanguage/data/singleton/qmldir-error/qmldir b/tests/auto/qml/qqmllanguage/data/singleton/qmldir-error/qmldir new file mode 100644 index 0000000000..0f499f9dce --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singleton/qmldir-error/qmldir @@ -0,0 +1 @@ +singleton SType2 diff --git a/tests/auto/qml/qqmllanguage/data/singleton/qualified/SingletonType.qml b/tests/auto/qml/qqmllanguage/data/singleton/qualified/SingletonType.qml new file mode 100644 index 0000000000..9a3b7abbd6 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singleton/qualified/SingletonType.qml @@ -0,0 +1,17 @@ +import QtQuick 2.0 + +Item { + id: singletonId + + property int testProp1: 125 + property int testProp2: 25 + property int testProp3: -55 + + width: 25; height: 25 + + Rectangle { + id: rectangle + border.color: "white" + anchors.fill: parent + } +}
\ No newline at end of file diff --git a/tests/auto/qml/qqmllanguage/data/singleton/registeredComposite/CompositeType.qml b/tests/auto/qml/qqmllanguage/data/singleton/registeredComposite/CompositeType.qml new file mode 100644 index 0000000000..5c86c21ffb --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singleton/registeredComposite/CompositeType.qml @@ -0,0 +1,19 @@ +import QtQuick 2.0 +pragma Singleton + +Item { + id: singletonId + + property int testProp1: 325 + property int testProp2: 225 + property int testProp3: 155 + + width: 25; height: 25 + + Rectangle { + id: rectangle + border.color: "white" + anchors.fill: parent + } +} + diff --git a/tests/auto/qml/qqmllanguage/data/singleton/remote/RemoteSingletonType2.qml b/tests/auto/qml/qqmllanguage/data/singleton/remote/RemoteSingletonType2.qml new file mode 100644 index 0000000000..41d619a275 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singleton/remote/RemoteSingletonType2.qml @@ -0,0 +1,18 @@ +import QtQuick 2.0 +pragma Singleton + +Item { + id: singletonId + + property int testProp1: 525 + property int testProp2: 425 + property int testProp3: 355 + + width: 25; height: 25 + + Rectangle { + id: rectangle + border.color: "white" + anchors.fill: parent + } +} diff --git a/tests/auto/qml/qqmllanguage/data/singleton/remote/qmldir b/tests/auto/qml/qqmllanguage/data/singleton/remote/qmldir new file mode 100644 index 0000000000..c73782b825 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singleton/remote/qmldir @@ -0,0 +1 @@ +singleton RemoteSingletonType2 RemoteSingletonType2.qml
\ No newline at end of file diff --git a/tests/auto/qml/qqmllanguage/data/singleton/subdir/ErrorSingletonType.qml b/tests/auto/qml/qqmllanguage/data/singleton/subdir/ErrorSingletonType.qml new file mode 100644 index 0000000000..9a3b7abbd6 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singleton/subdir/ErrorSingletonType.qml @@ -0,0 +1,17 @@ +import QtQuick 2.0 + +Item { + id: singletonId + + property int testProp1: 125 + property int testProp2: 25 + property int testProp3: -55 + + width: 25; height: 25 + + Rectangle { + id: rectangle + border.color: "white" + anchors.fill: parent + } +}
\ No newline at end of file diff --git a/tests/auto/qml/qqmllanguage/data/singleton/subdir/qmldir b/tests/auto/qml/qqmllanguage/data/singleton/subdir/qmldir new file mode 100644 index 0000000000..eb702eccaf --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singleton/subdir/qmldir @@ -0,0 +1,3 @@ +singleton ErrorSingletonType ErrorSingletonType.qml + + diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest1.qml b/tests/auto/qml/qqmllanguage/data/singletonTest1.qml new file mode 100644 index 0000000000..2eb80df53c --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest1.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 +import "singleton" + +Item { + property int value1: SingletonType.testProp1; + property string value2: "Test value: " + SingletonType.testProp3; +} diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest10.error.txt b/tests/auto/qml/qqmllanguage/data/singletonTest10.error.txt new file mode 100644 index 0000000000..32d2ed857e --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest10.error.txt @@ -0,0 +1 @@ +4:1:Composite Singleton Type SingletonType is not creatable. diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest10.qml b/tests/auto/qml/qqmllanguage/data/singletonTest10.qml new file mode 100644 index 0000000000..292536c628 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest10.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 +import "singleton" + +Item { + property SingletonType test +} diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest11.qml b/tests/auto/qml/qqmllanguage/data/singletonTest11.qml new file mode 100644 index 0000000000..4248731314 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest11.qml @@ -0,0 +1,17 @@ +import QtQuick 2.0 +import "singleton" + +Item { + id: test + + property int value1: SingletonType.testProp1; + property string value2: "Test value: " + SingletonType.testProp3; + + signal customSignal(SingletonType type) + + onCustomSignal: { + type.testProp1 = 99 + } + + Component.onCompleted: test.customSignal(SingletonType) +} diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest12.error.txt b/tests/auto/qml/qqmllanguage/data/singletonTest12.error.txt new file mode 100644 index 0000000000..716cf5709a --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest12.error.txt @@ -0,0 +1,2 @@ +5:5:Type RegisteredCompositeType unavailable +2:1:pragma Singleton used with a non composite singleton type CompositeSingletonTest/RegisteredCompositeType diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest12.qml b/tests/auto/qml/qqmllanguage/data/singletonTest12.qml new file mode 100644 index 0000000000..06015c33d2 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest12.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 +import CompositeSingletonTest 1.0 + +Item { + RegisteredCompositeType { } +} diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest13.error.txt b/tests/auto/qml/qqmllanguage/data/singletonTest13.error.txt new file mode 100644 index 0000000000..bc9cc61d57 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest13.error.txt @@ -0,0 +1,2 @@ +-1:-1:Type ErrorSingletonType unavailable +-1:-1:qmldir defines type as singleton, but no pragma Singleton found in type ErrorSingletonType. diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest13.qml b/tests/auto/qml/qqmllanguage/data/singletonTest13.qml new file mode 100644 index 0000000000..04c0471ad6 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest13.qml @@ -0,0 +1,8 @@ +import QtQuick 2.0 +import "singleton/subdir" + +Item { + property int value1: ErrorSingletonType.testProp1; + property string value2: "Test value: " + ErrorSingletonType.testProp3; + property variant singletonInstance: ErrorSingletonType; +} diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest14.error.txt b/tests/auto/qml/qqmllanguage/data/singletonTest14.error.txt new file mode 100644 index 0000000000..c2463d2899 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest14.error.txt @@ -0,0 +1 @@ +2:1:singleton types require 2 or 3 arguments, but 1 were provided diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest14.qml b/tests/auto/qml/qqmllanguage/data/singletonTest14.qml new file mode 100644 index 0000000000..7fad45be5d --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest14.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 +import "singleton/qmldir-error" + +Item { + property int value1: SType2.testProp1; + property string value2: "Test value: " + SType2.testProp3; +}
\ No newline at end of file diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest15.qml b/tests/auto/qml/qqmllanguage/data/singletonTest15.qml new file mode 100644 index 0000000000..183d52d259 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest15.qml @@ -0,0 +1,8 @@ +import QtQuick 2.0 +import "http://127.0.0.1:14447/singleton/remote" + +Item { + property int value1: RemoteSingletonType2.testProp1; + property string value2: "Test value: " + RemoteSingletonType2.testProp3; + property variant singletonInstance: RemoteSingletonType2; +} diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest16.qml b/tests/auto/qml/qqmllanguage/data/singletonTest16.qml new file mode 100644 index 0000000000..ea8b3a2eba --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest16.qml @@ -0,0 +1,10 @@ +import QtQuick 2.0 +import "singleton" +import "singleton/js/jspragma.js" as JsPragmaTest + +Item { + id: test + + property int value1: SingletonType.testProp1; + property string value2: "Test value: " + JsPragmaTest.value; +} diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest2.qml b/tests/auto/qml/qqmllanguage/data/singletonTest2.qml new file mode 100644 index 0000000000..b22d8e6c9a --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest2.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 +import "singleton" + +Item { + property variant singleton1: SingletonType; +} diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest3.qml b/tests/auto/qml/qqmllanguage/data/singletonTest3.qml new file mode 100644 index 0000000000..f984a12c89 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest3.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 +import "singleton" + +Item { + property QtObject singleton2: SingletonType; +} diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest4.error.txt b/tests/auto/qml/qqmllanguage/data/singletonTest4.error.txt new file mode 100644 index 0000000000..77c26df310 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest4.error.txt @@ -0,0 +1 @@ +2:1:No matching type found, pragma Singleton files cannot be used by QQmlComponent. diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest4.qml b/tests/auto/qml/qqmllanguage/data/singletonTest4.qml new file mode 100644 index 0000000000..c0aca77e0f --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest4.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 +pragma Singleton + +Item { + +} diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest5.qml b/tests/auto/qml/qqmllanguage/data/singletonTest5.qml new file mode 100644 index 0000000000..b673f24023 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest5.qml @@ -0,0 +1,8 @@ +import QtQuick 2.0 +import "singleton" as TestNameSpace + +Item { + property int value1: TestNameSpace.SingletonType.testProp1; + property string value2: "Test value: " + TestNameSpace.SingletonType.testProp3; + property variant singletonInstance: TestNameSpace.SingletonType; +} diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest5a.qml b/tests/auto/qml/qqmllanguage/data/singletonTest5a.qml new file mode 100644 index 0000000000..634bdeb8e3 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest5a.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 +import "singleton" + +Item { + property variant singletonInstance: SingletonType; +} diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest6.qml b/tests/auto/qml/qqmllanguage/data/singletonTest6.qml new file mode 100644 index 0000000000..0c5c65cc7a --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest6.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 +import org.qtproject.SingletonTest 1.0 + +Item { + property int value1: SingletonType.testProp1; + property string value2: "Test value: " + SingletonType.testProp3; + property variant singletonInstance: SingletonType; + + NonSingletonType { id: nonSingleton } + + property int value3: nonSingleton.testProp1; + property string value4: "Test value: " + nonSingleton.testProp3; +} + diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest6a.qml b/tests/auto/qml/qqmllanguage/data/singletonTest6a.qml new file mode 100644 index 0000000000..cf57bcc594 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest6a.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 +import org.qtproject.SingletonTest 1.0 + +Item { + property variant singletonInstance: SingletonType; +} + diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest7.qml b/tests/auto/qml/qqmllanguage/data/singletonTest7.qml new file mode 100644 index 0000000000..f1d8418ac8 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest7.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 +import org.qtproject.SingletonTest 2.5 + +Item { + property int value1: SingletonType.testProp1; + property string value2: "Test value: " + SingletonType.testProp3; + property variant singletonInstance: SingletonType; + + NonSingletonType { id: nonSingleton } + + property int value3: nonSingleton.testProp1; + property string value4: "Test value: " + nonSingleton.testProp3; +} + diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest7a.qml b/tests/auto/qml/qqmllanguage/data/singletonTest7a.qml new file mode 100644 index 0000000000..8f8a7ff249 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest7a.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 +import org.qtproject.SingletonTest 2.5 + +Item { + property variant singletonInstance: SingletonType; +} + diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest8.qml b/tests/auto/qml/qqmllanguage/data/singletonTest8.qml new file mode 100644 index 0000000000..d55c16045b --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest8.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 +import org.qtproject.SingletonTest 2.5 as TestNameSpace + +Item { + property int value1: TestNameSpace.SingletonType.testProp1; + property string value2: "Test value: " + TestNameSpace.SingletonType.testProp3; + property variant singletonInstance: TestNameSpace.SingletonType; + + TestNameSpace.NonSingletonType { id: nonSingleton } + + property int value3: nonSingleton.testProp1; + property string value4: "Test value: " + nonSingleton.testProp3; +} + diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest8a.qml b/tests/auto/qml/qqmllanguage/data/singletonTest8a.qml new file mode 100644 index 0000000000..8f8a7ff249 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest8a.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 +import org.qtproject.SingletonTest 2.5 + +Item { + property variant singletonInstance: SingletonType; +} + diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest9.error.txt b/tests/auto/qml/qqmllanguage/data/singletonTest9.error.txt new file mode 100644 index 0000000000..7481e47ae2 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest9.error.txt @@ -0,0 +1 @@ +5:5:Composite Singleton Type SingletonType is not creatable. diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest9.qml b/tests/auto/qml/qqmllanguage/data/singletonTest9.qml new file mode 100644 index 0000000000..142e798809 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/singletonTest9.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 +import "singleton" + +Item { + SingletonType {} +} diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index dae19dee57..65afdb06d2 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -193,6 +193,23 @@ private slots: void deepProperty(); + void compositeSingletonProperties(); + void compositeSingletonSameEngine(); + void compositeSingletonDifferentEngine(); + void compositeSingletonNonTypeError(); + void compositeSingletonQualifiedNamespace(); + void compositeSingletonModule(); + void compositeSingletonModuleVersioned(); + void compositeSingletonModuleQualified(); + void compositeSingletonInstantiateError(); + void compositeSingletonDynamicPropertyError(); + void compositeSingletonDynamicSignal(); + void compositeSingletonQmlRegisterTypeError(); + void compositeSingletonQmldirNoPragmaError(); + void compositeSingletonQmlDirError(); + void compositeSingletonRemote(); + void compositeSingletonJavaScriptPragma(); + private: QQmlEngine engine; QStringList defaultImportPathList; @@ -210,6 +227,9 @@ private: || userType == (int) QVariant::UInt || userType == (int) QVariant::Double; } + + void getSingletonInstance(QQmlEngine& engine, const char* fileName, const char* propertyName, QObject** result /* out */); + void getSingletonInstance(QObject* o, const char* propertyName, QObject** result /* out */); }; #define DETERMINE_ERRORS(errorfile,expected,actual)\ @@ -1893,6 +1913,7 @@ void tst_qqmllanguage::reservedWords_data() QTest::newRow("if") << QByteArray("if"); QTest::newRow("implements") << QByteArray("implements"); QTest::newRow("import") << QByteArray("import"); + QTest::newRow("pragma") << QByteArray("pragma"); QTest::newRow("in") << QByteArray("in"); QTest::newRow("instanceof") << QByteArray("instanceof"); QTest::newRow("int") << QByteArray("int"); @@ -3194,6 +3215,291 @@ void tst_qqmllanguage::implicitImportsLast() engine.setImportPathList(defaultImportPathList); } +void tst_qqmllanguage::getSingletonInstance(QQmlEngine& engine, const char* fileName, const char* propertyName, QObject** result /* out */) +{ + QVERIFY(fileName != 0); + QVERIFY(propertyName != 0); + + if (!fileName || !propertyName) + return; + + QQmlComponent component(&engine, testFile(fileName)); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + getSingletonInstance(object, propertyName, result); +} + +void tst_qqmllanguage::getSingletonInstance(QObject* o, const char* propertyName, QObject** result /* out */) +{ + QVERIFY(o != 0); + QVERIFY(propertyName != 0); + + if (!o || !propertyName) + return; + + QVariant variant = o->property(propertyName); + QVERIFY(variant.userType() == qMetaTypeId<QObject *>()); + + QObject *singleton = NULL; + if (variant.canConvert<QObject*>()) + singleton = variant.value<QObject*>(); + + QVERIFY(singleton != 0); + *result = singleton; +} + +void verifyCompositeSingletonPropertyValues(QObject* o, const char* n1, int v1, const char* n2, int v2) +{ + QCOMPARE(o->property(n1).userType(), (int)QMetaType::Int); + QCOMPARE(o->property(n1), QVariant(v1)); + + QCOMPARE(o->property(n2).userType(), (int)QVariant::String); + QString numStr; + QCOMPARE(o->property(n2), QVariant(QString(QLatin1String("Test value: ")).append(numStr.setNum(v2)))); +} + +// Reads values from a composite singleton type +void tst_qqmllanguage::compositeSingletonProperties() +{ + QQmlComponent component(&engine, testFile("singletonTest1.qml")); + VERIFY_ERRORS(0); + QObject *o = component.create(); + QVERIFY(o != 0); + + verifyCompositeSingletonPropertyValues(o, "value1", 125, "value2", -55); +} + +// Checks that the addresses of the composite singletons used in the same +// engine are the same. +void tst_qqmllanguage::compositeSingletonSameEngine() +{ + QObject* s1 = NULL; + getSingletonInstance(engine, "singletonTest2.qml", "singleton1", &s1); + QVERIFY(s1 != 0); + s1->setProperty("testProp2", QVariant(13)); + + QObject* s2 = NULL; + getSingletonInstance(engine, "singletonTest3.qml", "singleton2", &s2); + QVERIFY(s2 != 0); + QCOMPARE(s2->property("testProp2"), QVariant(13)); + + QVERIFY(s1 == s2); +} + +// Checks that the addresses of the composite singletons used in different +// engines are different. +void tst_qqmllanguage::compositeSingletonDifferentEngine() +{ + QQmlEngine e2; + + QObject* s1 = NULL; + getSingletonInstance(engine, "singletonTest2.qml", "singleton1", &s1); + QVERIFY(s1 != 0); + s1->setProperty("testProp2", QVariant(13)); + + QObject* s2 = NULL; + getSingletonInstance(e2, "singletonTest3.qml", "singleton2", &s2); + QVERIFY(s2 != 0); + QCOMPARE(s2->property("testProp2"), QVariant(25)); + + QVERIFY(s1 != s2); +} + +// pragma Singleton in a non-type qml file fails +void tst_qqmllanguage::compositeSingletonNonTypeError() +{ + QQmlComponent component(&engine, testFile("singletonTest4.qml")); + VERIFY_ERRORS("singletonTest4.error.txt"); +} + +// Loads the singleton using a namespace qualifier +void tst_qqmllanguage::compositeSingletonQualifiedNamespace() +{ + QQmlComponent component(&engine, testFile("singletonTest5.qml")); + VERIFY_ERRORS(0); + QObject *o = component.create(); + QVERIFY(o != 0); + + verifyCompositeSingletonPropertyValues(o, "value1", 125, "value2", -55); + + // lets verify that the singleton instance we are using is the same + // when loaded through another file (without namespace!) + QObject *s1 = NULL; + getSingletonInstance(o, "singletonInstance", &s1); + QVERIFY(s1 != 0); + + QObject* s2 = NULL; + getSingletonInstance(engine, "singletonTest5a.qml", "singletonInstance", &s2); + QVERIFY(s2 != 0); + + QVERIFY(s1 == s2); +} + +// Loads a singleton from a module +void tst_qqmllanguage::compositeSingletonModule() +{ + engine.addImportPath(testFile("singleton/module")); + + QQmlComponent component(&engine, testFile("singletonTest6.qml")); + VERIFY_ERRORS(0); + QObject *o = component.create(); + QVERIFY(o != 0); + + verifyCompositeSingletonPropertyValues(o, "value1", 125, "value2", -55); + verifyCompositeSingletonPropertyValues(o, "value3", 125, "value4", -55); + + // lets verify that the singleton instance we are using is the same + // when loaded through another file + QObject *s1 = NULL; + getSingletonInstance(o, "singletonInstance", &s1); + QVERIFY(s1 != 0); + + QObject* s2 = NULL; + getSingletonInstance(engine, "singletonTest6a.qml", "singletonInstance", &s2); + QVERIFY(s2 != 0); + + QVERIFY(s1 == s2); +} + +// Loads a singleton from a module with a higher version +void tst_qqmllanguage::compositeSingletonModuleVersioned() +{ + engine.addImportPath(testFile("singleton/module")); + + QQmlComponent component(&engine, testFile("singletonTest7.qml")); + VERIFY_ERRORS(0); + QObject *o = component.create(); + QVERIFY(o != 0); + + verifyCompositeSingletonPropertyValues(o, "value1", 225, "value2", 55); + verifyCompositeSingletonPropertyValues(o, "value3", 225, "value4", 55); + + // lets verify that the singleton instance we are using is the same + // when loaded through another file + QObject *s1 = NULL; + getSingletonInstance(o, "singletonInstance", &s1); + QVERIFY(s1 != 0); + + QObject* s2 = NULL; + getSingletonInstance(engine, "singletonTest7a.qml", "singletonInstance", &s2); + QVERIFY(s2 != 0); + + QVERIFY(s1 == s2); +} + +// Loads a singleton from a module with a qualified namespace +void tst_qqmllanguage::compositeSingletonModuleQualified() +{ + engine.addImportPath(testFile("singleton/module")); + + QQmlComponent component(&engine, testFile("singletonTest8.qml")); + VERIFY_ERRORS(0); + QObject *o = component.create(); + QVERIFY(o != 0); + + verifyCompositeSingletonPropertyValues(o, "value1", 225, "value2", 55); + verifyCompositeSingletonPropertyValues(o, "value3", 225, "value4", 55); + + // lets verify that the singleton instance we are using is the same + // when loaded through another file + QObject *s1 = NULL; + getSingletonInstance(o, "singletonInstance", &s1); + QVERIFY(s1 != 0); + + QObject* s2 = NULL; + getSingletonInstance(engine, "singletonTest8a.qml", "singletonInstance", &s2); + QVERIFY(s2 != 0); + + QVERIFY(s1 == s2); +} + +// Tries to instantiate a type with a pragma Singleton and fails +void tst_qqmllanguage::compositeSingletonInstantiateError() +{ + QQmlComponent component(&engine, testFile("singletonTest9.qml")); + VERIFY_ERRORS("singletonTest9.error.txt"); +} + +// Having a composite singleton type as dynamic property type fails +// (like C++ singleton) +void tst_qqmllanguage::compositeSingletonDynamicPropertyError() +{ + QQmlComponent component(&engine, testFile("singletonTest10.qml")); + VERIFY_ERRORS("singletonTest10.error.txt"); +} + +// Having a composite singleton type as dynamic signal parameter succeeds +// (like C++ singleton) +void tst_qqmllanguage::compositeSingletonDynamicSignal() +{ + QQmlComponent component(&engine, testFile("singletonTest11.qml")); + VERIFY_ERRORS(0); + QObject *o = component.create(); + QVERIFY(o != 0); + + verifyCompositeSingletonPropertyValues(o, "value1", 99, "value2", -55); +} + +// Use qmlRegisterType to register a qml composite type with pragma Singleton defined in it. +// This will fail as qmlRegisterType will only instantiate CompositeTypes. +void tst_qqmllanguage::compositeSingletonQmlRegisterTypeError() +{ + qmlRegisterType(testFileUrl("singleton/registeredComposite/CompositeType.qml"), + "CompositeSingletonTest", 1, 0, "RegisteredCompositeType"); + QQmlComponent component(&engine, testFile("singletonTest12.qml")); + VERIFY_ERRORS("singletonTest12.error.txt"); +} + +// Qmldir defines a type as a singleton, but the qml file does not have a pragma Singleton. +void tst_qqmllanguage::compositeSingletonQmldirNoPragmaError() +{ + QQmlComponent component(&engine, testFile("singletonTest13.qml")); + VERIFY_ERRORS("singletonTest13.error.txt"); +} + +// Invalid singleton definition in the qmldir file results in an error +void tst_qqmllanguage::compositeSingletonQmlDirError() +{ + QQmlComponent component(&engine, testFile("singletonTest14.qml")); + VERIFY_ERRORS("singletonTest14.error.txt"); +} + +// Load a remote composite singleton type via qmldir that defines the type as a singleton +void tst_qqmllanguage::compositeSingletonRemote() +{ + TestHTTPServer server(14447); + server.serveDirectory(dataDirectory()); + + QQmlComponent component(&engine, testFile("singletonTest15.qml")); + + while (component.isLoading()) + QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents, 50); + + VERIFY_ERRORS(0); + QObject *o = component.create(); + QVERIFY(o != 0); + + verifyCompositeSingletonPropertyValues(o, "value1", 525, "value2", 355); +} + +// Load a composite singleton type and a javascript file that has .pragma library +// in it. This will make sure that the javascript .pragma does not get mixed with +// the pragma Singleton changes. +void tst_qqmllanguage::compositeSingletonJavaScriptPragma() +{ + QQmlComponent component(&engine, testFile("singletonTest16.qml")); + VERIFY_ERRORS(0); + QObject *o = component.create(); + QVERIFY(o != 0); + + // The value1 that is read from the SingletonType was changed from 125 to 99 + // in compositeSingletonDynamicSignal() above. As the type is a singleton and + // the engine has not been destroyed, we just retrieve the old instance and + // the value is still 99. + verifyCompositeSingletonPropertyValues(o, "value1", 99, "value2", 333); +} QTEST_MAIN(tst_qqmllanguage) diff --git a/tests/auto/qml/qqmlmoduleplugin/data/implicit2/implicitQmldir.2.errors.txt b/tests/auto/qml/qqmlmoduleplugin/data/implicit2/implicitQmldir.2.errors.txt index 08492af787..ee68ebdfe0 100644 --- a/tests/auto/qml/qqmlmoduleplugin/data/implicit2/implicitQmldir.2.errors.txt +++ b/tests/auto/qml/qqmlmoduleplugin/data/implicit2/implicitQmldir.2.errors.txt @@ -1,4 +1,2 @@ -1:12:unexpected token -1:-1:invalid qmldir directive contains too many tokens -2:17:unexpected token -2:-1:invalid qmldir directive contains too many tokens +1:-1:a component declaration requires two or three arguments, but 4 were provided +2:-1:internal types require 2 arguments, but 3 were provided |