From 3b3ec6bc4114db82462eef812a47db420d4505c2 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Wed, 5 May 2010 10:19:40 +1000 Subject: Fix a crash with null objects returned from a Q_INVOKABLE Task-number: QTBUG-10412 Reviewed-by: Aaron Kennedy --- src/declarative/qml/qdeclarativeobjectscriptclass.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index 03366f0..170f440 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -775,7 +775,8 @@ QScriptDeclarativeClass::Value MetaCallArgument::toValue(QDeclarativeEngine *e) return QScriptDeclarativeClass::Value(engine, *((QString *)&data)); } else if (type == QMetaType::QObjectStar) { QObject *object = *((QObject **)&data); - QDeclarativeData::get(object, true)->setImplicitDestructible(); + if (object) + QDeclarativeData::get(object, true)->setImplicitDestructible(); QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(e); return QScriptDeclarativeClass::Value(engine, priv->objectClass->newQObject(object)); } else if (type == qMetaTypeId >()) { -- cgit v0.12 From 4982b883c31874206aaa05268852fbcee81a8a39 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Wed, 5 May 2010 11:49:20 +1000 Subject: Enable states to be activated via their 'when' clause even if unnamed. Autogenerate a name for unnamed states: "anonymousState1", etc. Task-number: QTBUG-10352 Reviewed-by: Aaron Kennedy --- src/declarative/util/qdeclarativestategroup.cpp | 10 +++++++++- .../qdeclarativestates/data/unnamedWhen.qml | 14 ++++++++++++++ .../qdeclarativestates/tst_qdeclarativestates.cpp | 20 ++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 tests/auto/declarative/qdeclarativestates/data/unnamedWhen.qml diff --git a/src/declarative/util/qdeclarativestategroup.cpp b/src/declarative/util/qdeclarativestategroup.cpp index 5b51495..9b042d7 100644 --- a/src/declarative/util/qdeclarativestategroup.cpp +++ b/src/declarative/util/qdeclarativestategroup.cpp @@ -47,6 +47,7 @@ #include #include +#include #include #include @@ -62,7 +63,7 @@ class QDeclarativeStateGroupPrivate : public QObjectPrivate public: QDeclarativeStateGroupPrivate() : nullState(0), componentComplete(true), - ignoreTrans(false), applyingState(false) {} + ignoreTrans(false), applyingState(false), unnamedCount(0) {} QString currentState; QDeclarativeState *nullState; @@ -78,6 +79,7 @@ public: bool componentComplete; bool ignoreTrans; bool applyingState; + int unnamedCount; QDeclarativeTransition *findTransition(const QString &from, const QString &to); void setCurrentStateInternal(const QString &state, bool = false); @@ -259,6 +261,12 @@ void QDeclarativeStateGroup::componentComplete() Q_D(QDeclarativeStateGroup); d->componentComplete = true; + for (int ii = 0; ii < d->states.count(); ++ii) { + QDeclarativeState *state = d->states.at(ii); + if (state->name().isEmpty()) + state->setName(QLatin1String("anonymousState") % QString::number(++d->unnamedCount)); + } + if (d->updateAutoState()) { return; } else if (!d->currentState.isEmpty()) { diff --git a/tests/auto/declarative/qdeclarativestates/data/unnamedWhen.qml b/tests/auto/declarative/qdeclarativestates/data/unnamedWhen.qml new file mode 100644 index 0000000..a70840c --- /dev/null +++ b/tests/auto/declarative/qdeclarativestates/data/unnamedWhen.qml @@ -0,0 +1,14 @@ +import Qt 4.7 + +Rectangle { + id: theRect + property bool triggerState: false + property string stateString: "" + states: State { + when: triggerState + PropertyChanges { + target: theRect + stateString: "inState" + } + } +} diff --git a/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp b/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp index d384d26..13992ad 100644 --- a/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp +++ b/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp @@ -110,6 +110,7 @@ private slots: void illegalObjectCreation(); void whenOrdering(); void urlResolution(); + void unnamedWhen(); }; void tst_qdeclarativestates::initTestCase() @@ -1049,6 +1050,25 @@ void tst_qdeclarativestates::urlResolution() QCOMPARE(image3->source(), resolved); } +void tst_qdeclarativestates::unnamedWhen() +{ + QDeclarativeEngine engine; + + QDeclarativeComponent c(&engine, SRCDIR "/data/unnamedWhen.qml"); + QDeclarativeRectangle *rect = qobject_cast(c.create()); + QVERIFY(rect != 0); + QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect); + + QCOMPARE(rectPrivate->state(), QLatin1String("")); + QCOMPARE(rect->property("stateString").toString(), QLatin1String("")); + rect->setProperty("triggerState", true); + QCOMPARE(rectPrivate->state(), QLatin1String("anonymousState1")); + QCOMPARE(rect->property("stateString").toString(), QLatin1String("inState")); + rect->setProperty("triggerState", false); + QCOMPARE(rectPrivate->state(), QLatin1String("")); + QCOMPARE(rect->property("stateString").toString(), QLatin1String("")); +} + QTEST_MAIN(tst_qdeclarativestates) #include "tst_qdeclarativestates.moc" -- cgit v0.12 From a5d15c36ae3db3caff4eeb86fd7eb5cdbb928f2d Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Wed, 5 May 2010 12:16:28 +1000 Subject: syntax update --- src/imports/gestures/qdeclarativegesturearea.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/imports/gestures/qdeclarativegesturearea.cpp b/src/imports/gestures/qdeclarativegesturearea.cpp index 615c674..19afe0c 100644 --- a/src/imports/gestures/qdeclarativegesturearea.cpp +++ b/src/imports/gestures/qdeclarativegesturearea.cpp @@ -259,7 +259,7 @@ bool QDeclarativeGestureAreaPrivate::gestureEvent(QGestureEvent *event) bool accept = true; for (Bindings::Iterator it = bindings.begin(); it != bindings.end(); ++it) { if ((gesture = event->gesture(it.key()))) { - it.value()->value(); + it.value()->evaluate(); event->setAccepted(true); // XXX only if value returns true? } } -- cgit v0.12 From 326dab74ba8df7707d1054ca5e0280c5f131c148 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 5 May 2010 12:51:02 +1000 Subject: Null objects should appear as JS null --- src/declarative/qml/qdeclarativeobjectscriptclass.cpp | 3 ++- tests/auto/declarative/qdeclarativeecmascript/data/deletedObject.qml | 4 ++-- .../declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index 170f440..8b64e0e 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -104,7 +104,8 @@ QScriptValue QDeclarativeObjectScriptClass::newQObject(QObject *object, int type QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); if (!object) - return newObject(scriptEngine, this, new ObjectData(object, type)); + return scriptEngine->nullValue(); +// return newObject(scriptEngine, this, new ObjectData(object, type)); if (QObjectPrivate::get(object)->wasDeleted) return scriptEngine->undefinedValue(); diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/deletedObject.qml b/tests/auto/declarative/qdeclarativeecmascript/data/deletedObject.qml index 72b59ae..2337e44 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/data/deletedObject.qml +++ b/tests/auto/declarative/qdeclarativeecmascript/data/deletedObject.qml @@ -19,7 +19,7 @@ QtObject { myObject.deleteOnSet = 1; - test3 = myObject.value == undefined; - test4 = obj.value == undefined; + test3 = myObject == null + test4 = obj == null } } diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index 6d39be2..8c9290f 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -1104,7 +1104,7 @@ void tst_qdeclarativeecmascript::exceptionClearsOnReeval() QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml")); QString url = component.url().toString(); - QString warning = url + ":4: TypeError: Result of expression 'objectProperty.objectProperty' [undefined] is not an object."; + QString warning = url + ":4: TypeError: Result of expression 'objectProperty' [null] is not an object."; QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); MyQmlObject *object = qobject_cast(component.create()); -- cgit v0.12 From dcee637a9f7a024803f0e5cc1bf57d878dca2ac3 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Wed, 5 May 2010 09:50:53 +1000 Subject: Doc improvements, simplify example code --- doc/src/declarative/advtutorial.qdoc | 50 +++++++++++++++---- doc/src/declarative/tutorial.qdoc | 15 +++--- .../declarative/tutorials/helloworld/tutorial1.qml | 3 +- .../declarative/tutorials/helloworld/tutorial2.qml | 3 +- .../declarative/tutorials/helloworld/tutorial3.qml | 3 +- .../tutorials/samegame/samegame1/Block.qml | 2 +- .../tutorials/samegame/samegame1/Button.qml | 17 +++++-- .../tutorials/samegame/samegame1/samegame.qml | 7 ++- .../tutorials/samegame/samegame2/Block.qml | 2 +- .../tutorials/samegame/samegame2/Button.qml | 17 +++++-- .../tutorials/samegame/samegame2/samegame.qml | 5 +- .../tutorials/samegame/samegame3/Button.qml | 17 +++++-- .../tutorials/samegame/samegame3/Dialog.qml | 33 ++++++------- .../tutorials/samegame/samegame3/samegame.js | 9 ++-- .../tutorials/samegame/samegame3/samegame.qml | 14 +++--- .../samegame/samegame4/content/Button.qml | 17 +++++-- .../samegame/samegame4/content/Dialog.qml | 57 ++++++++++++++++------ .../samegame/samegame4/content/samegame.js | 17 ++++--- .../tutorials/samegame/samegame4/samegame.qml | 38 +++++---------- 19 files changed, 208 insertions(+), 118 deletions(-) diff --git a/doc/src/declarative/advtutorial.qdoc b/doc/src/declarative/advtutorial.qdoc index 42ce246..7d2967e 100644 --- a/doc/src/declarative/advtutorial.qdoc +++ b/doc/src/declarative/advtutorial.qdoc @@ -109,12 +109,16 @@ Notice the anchors for the \c Item, \c Button and \c Text elements are set using \section2 Adding \c Button and \c Block components -The \c Button item in the code above is defined in a separate file named \c Button.qml. +The \c Button item in the code above is defined in a separate component file named \c Button.qml. To create a functional button, we use the QML elements \l Text and \l MouseArea inside a \l Rectangle. Here is the \c Button.qml code: \snippet declarative/tutorials/samegame/samegame1/Button.qml 0 +This essentially defines a rectangle that contains text and can be clicked. The \l MouseArea +has an \c onClicked() handler that is implemented to emit the \c clicked() signal of the +\c container when the area is clicked. + In Same Game, the screen is filled with small blocks when the game begins. Each block is just an item that contains an image. The block code is defined in a separate \c Block.qml file: @@ -226,14 +230,14 @@ until it is won or lost. To do this, we have added the following functions to \c samegame.js: \list -\o function \c{handleClick(x,y)} -\o function \c{floodFill(xIdx,yIdx,type)} -\o function \c{shuffleDown()} -\o function \c{victoryCheck()} -\o function \c{floodMoveCheck(xIdx, yIdx, type)} +\o \c{handleClick(x,y)} +\o \c{floodFill(xIdx,yIdx,type)} +\o \c{shuffleDown()} +\o \c{victoryCheck()} +\o \c{floodMoveCheck(xIdx, yIdx, type)} \endlist -As this is a tutorial about QML, not game design, we will only discuss \c handleClick() and \c victoryCheck() below since they interface directly with the QML elements. Note that although the game logic here is written in JavaScript, it could have been written in C++ and then exposed to JavaScript. +As this is a tutorial about QML, not game design, we will only discuss \c handleClick() and \c victoryCheck() below since they interface directly with the QML elements. Note that although the game logic here is written in JavaScript, it could have been written in C++ and then exposed to QML. \section3 Enabling mouse click interaction @@ -269,6 +273,8 @@ And this is how it is used in the main \c samegame.qml file: \snippet declarative/tutorials/samegame/samegame3/samegame.qml 2 +We give the dialog a \l {Item::z}{z} value of 100 to ensure it is displayed on top of our other components. The default \c z value for an item is 0. + \section3 A dash of color @@ -383,15 +389,41 @@ The theme change here is produced simply by replacing the block images. This can Another feature we might want to add to the game is a method of storing and retrieving high scores. -In \c samegame.qml we now pop up a dialog when the game is over and requests the player's name so it can be added to a High Scores table. The dialog is created using \c Dialog.qml: +To do this, we will show a dialog when the game is over to request the player's name and add it to a High Scores table. +This requires a few changes to \c Dialog.qml. In addition to a \c Text element, it now has a +\c TextInput child item for receiving keyboard text input: + +\snippet declarative/tutorials/samegame/samegame4/content/Dialog.qml 0 +\dots 4 +\snippet declarative/tutorials/samegame/samegame4/content/Dialog.qml 2 +\dots 4 +\snippet declarative/tutorials/samegame/samegame4/content/Dialog.qml 3 + +We'll also add a \c showWithInput() function. The text input will only be visible if this function +is called instead of \c show(). When the dialog is closed, it emits a \c closed() signal, and +other elements can retrieve the text entered by the user through an \c inputText property: + +\snippet declarative/tutorials/samegame/samegame4/content/Dialog.qml 0 +\snippet declarative/tutorials/samegame/samegame4/content/Dialog.qml 1 +\dots 4 +\snippet declarative/tutorials/samegame/samegame4/content/Dialog.qml 3 + +Now the dialog can be used in \c samegame.qml: \snippet declarative/tutorials/samegame/samegame4/samegame.qml 0 -When the dialog is closed, we call the new \c saveHighScore() function in \c samegame.js, which stores the high score locally in an SQL database and also send the score to an online database if possible. +When the dialog emits the \c closed signal, we call the new \c saveHighScore() function in \c samegame.js, which stores the high score locally in an SQL database and also send the score to an online database if possible. +The \c nameInputDialog is activated in the \c victoryCheck() function in \c samegame.js: + +\snippet declarative/tutorials/samegame/samegame4/content/samegame.js 3 +\dots 4 +\snippet declarative/tutorials/samegame/samegame4/content/samegame.js 4 \section3 Storing high scores offline +Now we need to implement the functionality to actually save the High Scores table. + Here is the \c saveHighScore() function in \c samegame.js: \snippet declarative/tutorials/samegame/samegame4/content/samegame.js 2 diff --git a/doc/src/declarative/tutorial.qdoc b/doc/src/declarative/tutorial.qdoc index 1a93d05..4cfb999 100644 --- a/doc/src/declarative/tutorial.qdoc +++ b/doc/src/declarative/tutorial.qdoc @@ -86,7 +86,7 @@ Here is the QML code for the application: \section2 Import First, we need to import the types that we need for this example. Most QML files will import the built-in QML -types (like \l{Rectangle}, \l{Image}, ...) that come with Qt with: +types (like \l{Rectangle}, \l{Image}, ...) that come with Qt, using: \snippet examples/declarative/tutorials/helloworld/tutorial1.qml 3 @@ -95,7 +95,7 @@ types (like \l{Rectangle}, \l{Image}, ...) that come with Qt with: \snippet examples/declarative/tutorials/helloworld/tutorial1.qml 1 We declare a root element of type \l{Rectangle}. It is one of the basic building blocks you can use to create an application in QML. -We give it an \c{id} to be able to refer to it later. In this case, we call it \e page. +We give it an \c{id} to be able to refer to it later. In this case, we call it "page". We also set the \c width, \c height and \c color properties. The \l{Rectangle} element contains many other properties (such as \c x and \c y), but these are left at their default values. @@ -103,15 +103,16 @@ The \l{Rectangle} element contains many other properties (such as \c x and \c y) \snippet examples/declarative/tutorials/helloworld/tutorial1.qml 2 -We add a \l Text element as a child of our root element that will display the text 'Hello world!'. +We add a \l Text element as a child of the root Rectangle element that displays the text 'Hello world!'. The \c y property is used to position the text vertically at 30 pixels from the top of its parent. -The \c font.pointSize and \c font.bold properties are related to fonts and use the \l{dot properties}{dot notation}. - The \c anchors.horizontalCenter property refers to the horizontal center of an element. In this case, we specify that our text element should be horizontally centered in the \e page element (see \l{anchor-layout}{Anchor-based Layout}). +The \c font.pointSize and \c font.bold properties are related to fonts and use the \l{dot properties}{dot notation}. + + \section2 Viewing the example To view what you have created, run the \l{Qt Declarative UI Runtime}{qml} tool (located in the \c bin directory) with your filename as the first argument. @@ -134,10 +135,10 @@ This chapter adds a color picker to change the color of the text. \image declarative-tutorial2.png Our color picker is made of six cells with different colors. -To avoid writing the same code multiple times, we first create a new \c Cell component. +To avoid writing the same code multiple times for each cell, we create a new \c Cell component. A component provides a way of defining a new type that we can re-use in other QML files. A QML component is like a black-box and interacts with the outside world through properties, signals and slots and is generally -defined in its own QML file (for more details, see \l {Defining new Components}). +defined in its own QML file. (For more details, see \l {Defining new Components}). The component's filename must always start with a capital letter. Here is the QML code for \c Cell.qml: diff --git a/examples/declarative/tutorials/helloworld/tutorial1.qml b/examples/declarative/tutorials/helloworld/tutorial1.qml index 5e27b45..04cd155 100644 --- a/examples/declarative/tutorials/helloworld/tutorial1.qml +++ b/examples/declarative/tutorials/helloworld/tutorial1.qml @@ -14,8 +14,9 @@ Rectangle { Text { id: helloText text: "Hello world!" + y: 30 + anchors.horizontalCenter: page.horizontalCenter font.pointSize: 24; font.bold: true - y: 30; anchors.horizontalCenter: page.horizontalCenter } //![2] } diff --git a/examples/declarative/tutorials/helloworld/tutorial2.qml b/examples/declarative/tutorials/helloworld/tutorial2.qml index 085efa4..66be509 100644 --- a/examples/declarative/tutorials/helloworld/tutorial2.qml +++ b/examples/declarative/tutorials/helloworld/tutorial2.qml @@ -9,8 +9,9 @@ Rectangle { Text { id: helloText text: "Hello world!" + y: 30 + anchors.horizontalCenter: page.horizontalCenter font.pointSize: 24; font.bold: true - y: 30; anchors.horizontalCenter: page.horizontalCenter } Grid { diff --git a/examples/declarative/tutorials/helloworld/tutorial3.qml b/examples/declarative/tutorials/helloworld/tutorial3.qml index 4bf4970..041d9a9 100644 --- a/examples/declarative/tutorials/helloworld/tutorial3.qml +++ b/examples/declarative/tutorials/helloworld/tutorial3.qml @@ -9,8 +9,9 @@ Rectangle { Text { id: helloText text: "Hello world!" + y: 30 + anchors.horizontalCenter: page.horizontalCenter font.pointSize: 24; font.bold: true - y: 30; anchors.horizontalCenter: page.horizontalCenter //![1] MouseArea { id: mouseArea; anchors.fill: parent } diff --git a/examples/declarative/tutorials/samegame/samegame1/Block.qml b/examples/declarative/tutorials/samegame/samegame1/Block.qml index a23654b..11fd844 100644 --- a/examples/declarative/tutorials/samegame/samegame1/Block.qml +++ b/examples/declarative/tutorials/samegame/samegame1/Block.qml @@ -7,7 +7,7 @@ Item { Image { id: img anchors.fill: parent - source: "../shared/pics/redStone.png"; + source: "../shared/pics/redStone.png" } } //![0] diff --git a/examples/declarative/tutorials/samegame/samegame1/Button.qml b/examples/declarative/tutorials/samegame/samegame1/Button.qml index e84b1ce..96a80eb 100644 --- a/examples/declarative/tutorials/samegame/samegame1/Button.qml +++ b/examples/declarative/tutorials/samegame/samegame1/Button.qml @@ -8,9 +8,9 @@ Rectangle { signal clicked - width: buttonLabel.width + 20; height: buttonLabel.height + 6 - smooth: true + width: buttonLabel.width + 20; height: buttonLabel.height + 5 border { width: 1; color: Qt.darker(activePalette.button) } + smooth: true radius: 8 // color the button with a gradient @@ -27,8 +27,17 @@ Rectangle { GradientStop { position: 1.0; color: activePalette.button } } - MouseArea { id: mouseArea; anchors.fill: parent; onClicked: container.clicked() } + MouseArea { + id: mouseArea + anchors.fill: parent + onClicked: container.clicked(); + } - Text { id: buttonLabel; text: container.text; anchors.centerIn: container; color: activePalette.buttonText } + Text { + id: buttonLabel + anchors.centerIn: container + color: activePalette.buttonText + text: container.text + } } //![0] diff --git a/examples/declarative/tutorials/samegame/samegame1/samegame.qml b/examples/declarative/tutorials/samegame/samegame1/samegame.qml index b6e01fd..f2974be 100644 --- a/examples/declarative/tutorials/samegame/samegame1/samegame.qml +++ b/examples/declarative/tutorials/samegame/samegame1/samegame.qml @@ -22,21 +22,20 @@ Rectangle { Rectangle { id: toolBar - width: parent.width; height: 32 + width: parent.width; height: 30 color: activePalette.window anchors.bottom: screen.bottom Button { - anchors { left: parent.left; leftMargin: 3; verticalCenter: parent.verticalCenter } + anchors { left: parent.left; verticalCenter: parent.verticalCenter } text: "New Game" onClicked: console.log("This doesn't do anything yet...") } Text { id: score - anchors { right: parent.right; rightMargin: 3; verticalCenter: parent.verticalCenter } + anchors { right: parent.right; verticalCenter: parent.verticalCenter } text: "Score: Who knows?" - font.bold: true } } } diff --git a/examples/declarative/tutorials/samegame/samegame2/Block.qml b/examples/declarative/tutorials/samegame/samegame2/Block.qml index 4e71e60..39da84e 100644 --- a/examples/declarative/tutorials/samegame/samegame2/Block.qml +++ b/examples/declarative/tutorials/samegame/samegame2/Block.qml @@ -6,6 +6,6 @@ Item { Image { id: img anchors.fill: parent - source: "../shared/pics/redStone.png"; + source: "../shared/pics/redStone.png" } } diff --git a/examples/declarative/tutorials/samegame/samegame2/Button.qml b/examples/declarative/tutorials/samegame/samegame2/Button.qml index 737d886..4ed856b 100644 --- a/examples/declarative/tutorials/samegame/samegame2/Button.qml +++ b/examples/declarative/tutorials/samegame/samegame2/Button.qml @@ -7,9 +7,9 @@ Rectangle { signal clicked - width: buttonLabel.width + 20; height: buttonLabel.height + 6 - smooth: true + width: buttonLabel.width + 20; height: buttonLabel.height + 5 border { width: 1; color: Qt.darker(activePalette.button) } + smooth: true radius: 8 // color the button with a gradient @@ -26,7 +26,16 @@ Rectangle { GradientStop { position: 1.0; color: activePalette.button } } - MouseArea { id: mouseArea; anchors.fill: parent; onClicked: container.clicked() } + MouseArea { + id: mouseArea + anchors.fill: parent + onClicked: container.clicked(); + } - Text { id: buttonLabel; text: container.text; anchors.centerIn: container; color: activePalette.buttonText } + Text { + id: buttonLabel + anchors.centerIn: container + color: activePalette.buttonText + text: container.text + } } diff --git a/examples/declarative/tutorials/samegame/samegame2/samegame.qml b/examples/declarative/tutorials/samegame/samegame2/samegame.qml index a7d1fba..9b4d4d5 100644 --- a/examples/declarative/tutorials/samegame/samegame2/samegame.qml +++ b/examples/declarative/tutorials/samegame/samegame2/samegame.qml @@ -30,7 +30,7 @@ Rectangle { //![1] Button { - anchors { left: parent.left; leftMargin: 3; verticalCenter: parent.verticalCenter } + anchors { left: parent.left; verticalCenter: parent.verticalCenter } text: "New Game" onClicked: SameGame.startNewGame() } @@ -38,9 +38,8 @@ Rectangle { Text { id: score - anchors { right: parent.right; rightMargin: 3; verticalCenter: parent.verticalCenter } + anchors { right: parent.right; verticalCenter: parent.verticalCenter } text: "Score: Who knows?" - font.bold: true } } } diff --git a/examples/declarative/tutorials/samegame/samegame3/Button.qml b/examples/declarative/tutorials/samegame/samegame3/Button.qml index 737d886..4ed856b 100644 --- a/examples/declarative/tutorials/samegame/samegame3/Button.qml +++ b/examples/declarative/tutorials/samegame/samegame3/Button.qml @@ -7,9 +7,9 @@ Rectangle { signal clicked - width: buttonLabel.width + 20; height: buttonLabel.height + 6 - smooth: true + width: buttonLabel.width + 20; height: buttonLabel.height + 5 border { width: 1; color: Qt.darker(activePalette.button) } + smooth: true radius: 8 // color the button with a gradient @@ -26,7 +26,16 @@ Rectangle { GradientStop { position: 1.0; color: activePalette.button } } - MouseArea { id: mouseArea; anchors.fill: parent; onClicked: container.clicked() } + MouseArea { + id: mouseArea + anchors.fill: parent + onClicked: container.clicked(); + } - Text { id: buttonLabel; text: container.text; anchors.centerIn: container; color: activePalette.buttonText } + Text { + id: buttonLabel + anchors.centerIn: container + color: activePalette.buttonText + text: container.text + } } diff --git a/examples/declarative/tutorials/samegame/samegame3/Dialog.qml b/examples/declarative/tutorials/samegame/samegame3/Dialog.qml index 15b3b2f..3efed2f 100644 --- a/examples/declarative/tutorials/samegame/samegame3/Dialog.qml +++ b/examples/declarative/tutorials/samegame/samegame3/Dialog.qml @@ -2,31 +2,30 @@ import Qt 4.7 Rectangle { - id: page + id: container - signal closed - - function forceClose() { - page.closed(); - page.opacity = 0; + function show(text) { + dialogText.text = text; + container.opacity = 1; } - function show(txt) { - dialogText.text = txt; - page.opacity = 1; + function hide() { + container.opacity = 0; } - width: dialogText.width + 20; height: dialogText.height + 20 - color: "white" - border.width: 1 + width: dialogText.width + 20 + height: dialogText.height + 20 opacity: 0 - Behavior on opacity { - NumberAnimation { duration: 1000 } + Text { + id: dialogText + anchors.centerIn: parent + text: "" } - Text { id: dialogText; anchors.centerIn: parent; text: "Hello World!" } - - MouseArea { anchors.fill: parent; onClicked: forceClose(); } + MouseArea { + anchors.fill: parent + onClicked: hide(); + } } //![0] diff --git a/examples/declarative/tutorials/samegame/samegame3/samegame.js b/examples/declarative/tutorials/samegame/samegame3/samegame.js index 4256aee..84439fc 100644 --- a/examples/declarative/tutorials/samegame/samegame3/samegame.js +++ b/examples/declarative/tutorials/samegame/samegame3/samegame.js @@ -17,7 +17,7 @@ function startNewGame() { maxIndex = maxRow * maxColumn; //Close dialogs - dialog.forceClose(); + dialog.hide(); //Initialize Board board = new Array(maxIndex); @@ -59,10 +59,9 @@ function createBlock(column, row) { return true; } -var fillFound; -//Set after a floodFill call to the number of blocks found -var floodBoard; -//Set to 1 if the floodFill reaches off that node +var fillFound; //Set after a floodFill call to the number of blocks found +var floodBoard; //Set to 1 if the floodFill reaches off that node + //![1] function handleClick(xPos, yPos) { var column = Math.floor(xPos / gameCanvas.blockSize); diff --git a/examples/declarative/tutorials/samegame/samegame3/samegame.qml b/examples/declarative/tutorials/samegame/samegame3/samegame.qml index 50f9d5d..ac93eb1 100644 --- a/examples/declarative/tutorials/samegame/samegame3/samegame.qml +++ b/examples/declarative/tutorials/samegame/samegame3/samegame.qml @@ -30,7 +30,6 @@ Rectangle { width: parent.width - (parent.width % blockSize) height: parent.height - (parent.height % blockSize) anchors.centerIn: parent - z: 20 MouseArea { anchors.fill: parent @@ -41,26 +40,29 @@ Rectangle { } //![2] - Dialog { id: dialog; anchors.centerIn: parent; z: 21 } + Dialog { + id: dialog + anchors.centerIn: parent + z: 100 + } //![2] Rectangle { id: toolBar - width: parent.width; height: 32 + width: parent.width; height: 30 color: activePalette.window anchors.bottom: screen.bottom Button { - anchors { left: parent.left; leftMargin: 3; verticalCenter: parent.verticalCenter } + anchors { left: parent.left; verticalCenter: parent.verticalCenter } text: "New Game" onClicked: SameGame.startNewGame() } Text { id: score - anchors { right: parent.right; rightMargin: 3; verticalCenter: parent.verticalCenter } + anchors { right: parent.right; verticalCenter: parent.verticalCenter } text: "Score: Who knows?" - font.bold: true } } } diff --git a/examples/declarative/tutorials/samegame/samegame4/content/Button.qml b/examples/declarative/tutorials/samegame/samegame4/content/Button.qml index 737d886..4ed856b 100644 --- a/examples/declarative/tutorials/samegame/samegame4/content/Button.qml +++ b/examples/declarative/tutorials/samegame/samegame4/content/Button.qml @@ -7,9 +7,9 @@ Rectangle { signal clicked - width: buttonLabel.width + 20; height: buttonLabel.height + 6 - smooth: true + width: buttonLabel.width + 20; height: buttonLabel.height + 5 border { width: 1; color: Qt.darker(activePalette.button) } + smooth: true radius: 8 // color the button with a gradient @@ -26,7 +26,16 @@ Rectangle { GradientStop { position: 1.0; color: activePalette.button } } - MouseArea { id: mouseArea; anchors.fill: parent; onClicked: container.clicked() } + MouseArea { + id: mouseArea + anchors.fill: parent + onClicked: container.clicked(); + } - Text { id: buttonLabel; text: container.text; anchors.centerIn: container; color: activePalette.buttonText } + Text { + id: buttonLabel + anchors.centerIn: container + color: activePalette.buttonText + text: container.text + } } diff --git a/examples/declarative/tutorials/samegame/samegame4/content/Dialog.qml b/examples/declarative/tutorials/samegame/samegame4/content/Dialog.qml index 6848534..2f45362 100644 --- a/examples/declarative/tutorials/samegame/samegame4/content/Dialog.qml +++ b/examples/declarative/tutorials/samegame/samegame4/content/Dialog.qml @@ -1,30 +1,59 @@ import Qt 4.7 +//![0] Rectangle { - id: page + id: container +//![0] +//![1] + property string inputText: textInput.text signal closed - function forceClose() { - page.closed(); - page.opacity = 0; + function show(text) { + dialogText.text = text; + container.opacity = 1; + textInput.opacity = 0; } - function show(txt) { - dialogText.text = txt; - page.opacity = 1; + function showWithInput(text) { + show(text); + textInput.opacity = 1; + textInput.text = "" } - width: dialogText.width + 20; height: dialogText.height + 20 - color: "white" - border.width: 1 + function hide() { + container.opacity = 0; + container.closed(); + } +//![1] + + width: dialogText.width + textInput.width + 20 + height: dialogText.height + 20 opacity: 0 - Behavior on opacity { - NumberAnimation { duration: 1000 } + Text { + id: dialogText + anchors { verticalCenter: parent.verticalCenter; left: parent.left; leftMargin: 10 } + text: "" + } + +//![2] + TextInput { + id: textInput + anchors { verticalCenter: parent.verticalCenter; left: dialogText.right } + width: 80 + focus: true + text: "" + + onAccepted: container.hide() // close dialog when Enter is pressed } +//![2] - Text { id: dialogText; anchors.centerIn: parent; text: "Hello World!" } + MouseArea { + anchors.fill: parent + onClicked: hide(); + } - MouseArea { anchors.fill: parent; onClicked: forceClose(); } +//![3] } +//![3] diff --git a/examples/declarative/tutorials/samegame/samegame4/content/samegame.js b/examples/declarative/tutorials/samegame/samegame4/content/samegame.js index 961cd66..06d21e6 100755 --- a/examples/declarative/tutorials/samegame/samegame4/content/samegame.js +++ b/examples/declarative/tutorials/samegame/samegame4/content/samegame.js @@ -25,8 +25,8 @@ function startNewGame() { maxIndex = maxRow * maxColumn; //Close dialogs - nameInputDialog.forceClose(); - dialog.forceClose(); + nameInputDialog.hide(); + dialog.hide(); //Initialize Board board = new Array(maxIndex); @@ -72,10 +72,9 @@ function createBlock(column, row) { return true; } -var fillFound; -//Set after a floodFill call to the number of blocks found -var floodBoard; -//Set to 1 if the floodFill reaches off that node +var fillFound; //Set after a floodFill call to the number of blocks found +var floodBoard; //Set to 1 if the floodFill reaches off that node + function handleClick(xPos, yPos) { var column = Math.floor(xPos / gameCanvas.blockSize); var row = Math.floor(yPos / gameCanvas.blockSize); @@ -157,7 +156,9 @@ function shuffleDown() { } } +//![3] function victoryCheck() { +//![3] //Award bonus points if no blocks left var deservesBonus = true; for (var column = maxColumn - 1; column >= 0; column--) @@ -166,12 +167,14 @@ function victoryCheck() { if (deservesBonus) gameCanvas.score += 500; +//![4] //Check whether game has finished if (deservesBonus || !(floodMoveCheck(0, maxRow - 1, -1))) { gameDuration = new Date() - gameDuration; - nameInputDialog.show("You won! Please enter your name: "); + nameInputDialog.showWithInput("You won! Please enter your name: "); } } +//![4] //only floods up and right, to see if it can find adjacent same-typed blocks function floodMoveCheck(column, row, type) { diff --git a/examples/declarative/tutorials/samegame/samegame4/samegame.qml b/examples/declarative/tutorials/samegame/samegame4/samegame.qml index 404af0a..feb61fd 100644 --- a/examples/declarative/tutorials/samegame/samegame4/samegame.qml +++ b/examples/declarative/tutorials/samegame/samegame4/samegame.qml @@ -25,7 +25,7 @@ Rectangle { property int score: 0 property int blockSize: 40 - z: 20; anchors.centerIn: parent + anchors.centerIn: parent width: parent.width - (parent.width % blockSize); height: parent.height - (parent.height % blockSize); @@ -35,53 +35,41 @@ Rectangle { } } - Dialog { id: dialog; anchors.centerIn: parent; z: 21 } + Dialog { + id: dialog + anchors.centerIn: parent + z: 100 + } //![0] Dialog { id: nameInputDialog - anchors.centerIn: parent - z: 22 + z: 100 - Text { - id: dialogText - opacity: 0 - text: " You won! Please enter your name:" - } - - TextInput { - id: nameInput - width: 72 - anchors { verticalCenter: parent.verticalCenter; left: dialogText.right } - focus: true - - onAccepted: { - if (nameInputDialog.opacity == 1 && nameInput.text != "") - SameGame.saveHighScore(nameInput.text); - nameInputDialog.forceClose(); - } + onClosed: { + if (nameInputDialog.inputText != "") + SameGame.saveHighScore(nameInputDialog.inputText); } } //![0] Rectangle { id: toolBar - width: parent.width; height: 32 + width: parent.width; height: 30 color: activePalette.window anchors.bottom: screen.bottom Button { - anchors { left: parent.left; leftMargin: 3; verticalCenter: parent.verticalCenter } + anchors { left: parent.left; verticalCenter: parent.verticalCenter } text: "New Game" onClicked: SameGame.startNewGame() } Text { id: score - anchors { right: parent.right; rightMargin: 3; verticalCenter: parent.verticalCenter } + anchors { right: parent.right; verticalCenter: parent.verticalCenter } text: "Score: " + gameCanvas.score - font.bold: true } } } -- cgit v0.12 From c76d98da76fd687d2953f0026b16bca3c7fcf485 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Wed, 5 May 2010 13:24:25 +1000 Subject: Allow translations without extra command-line args, and document both. --- doc/src/declarative/qmlruntime.qdoc | 17 +++++++++ tools/qml/qmlruntime.cpp | 72 +++++++++++++++++++++++-------------- tools/qml/qmlruntime.h | 6 ++++ 3 files changed, 68 insertions(+), 27 deletions(-) diff --git a/doc/src/declarative/qmlruntime.qdoc b/doc/src/declarative/qmlruntime.qdoc index a724c7d..23c5c32 100644 --- a/doc/src/declarative/qmlruntime.qdoc +++ b/doc/src/declarative/qmlruntime.qdoc @@ -112,6 +112,23 @@ When run with the \c -help option, qml shows available options. + \section2 Translations + + When the runtime loads an initial QML file, it will install a translation file from + a "i18n" subdirectory relative to that initial QML file. The actual translation file + loaded will be according to the system locale and have the form + "qml_.qm", where is a two-letter ISO 639 language, + such as "qml_fr.qm", optionally followed by an underscore and an uppercase two-letter ISO 3166 country + code, such as "qml_fr_FR.qm" or "qml_fr_CA.qm". + + Such files can be created using \l{Qt Linguist}. + + See \l{scripting.html#internationalization} for information about how to make + the JavaScript in QML files use translatable strings. + + Additionally, the QML runtime will load translation files specified on the + command line via the \c -translation option. + \section2 Dummy Data The secondary use of the qml runtime is to allow QML files to be viewed with diff --git a/tools/qml/qmlruntime.cpp b/tools/qml/qmlruntime.cpp index 008f163..da31284 100644 --- a/tools/qml/qmlruntime.cpp +++ b/tools/qml/qmlruntime.cpp @@ -66,6 +66,7 @@ #include #include #include +#include #include #include #include @@ -464,6 +465,7 @@ QDeclarativeViewer::QDeclarativeViewer(QWidget *parent, Qt::WindowFlags flags) , frame_stream(0), scaleSkin(true), mb(0) , portraitOrientation(0), landscapeOrientation(0) , m_scriptOptions(0), tester(0), useQmlFileBrowser(true) + , translator(0) { QDeclarativeViewer::registerTypes(); setWindowTitle(tr("Qt Qml Runtime")); @@ -937,6 +939,46 @@ void QDeclarativeViewer::launch(const QString& file_or_url) QMetaObject::invokeMethod(this, "open", Qt::QueuedConnection, Q_ARG(QString, file_or_url)); } +void QDeclarativeViewer::loadTranslationFile(const QString& directory) +{ + if (!translator) { + translator = new QTranslator(this); + QApplication::installTranslator(translator); + } + + translator->load(QLatin1String("qml_" )+QLocale::system().name(), directory + QLatin1String("/i18n")); +} + +void QDeclarativeViewer::loadDummyDataFiles(const QString& directory) +{ + QDir dir(directory+"/dummydata", "*.qml"); + QStringList list = dir.entryList(); + for (int i = 0; i < list.size(); ++i) { + QString qml = list.at(i); + QFile f(dir.filePath(qml)); + f.open(QIODevice::ReadOnly); + QByteArray data = f.readAll(); + QDeclarativeComponent comp(canvas->engine()); + comp.setData(data, QUrl()); + QObject *dummyData = comp.create(); + + if(comp.isError()) { + QList errors = comp.errors(); + foreach (const QDeclarativeError &error, errors) { + qWarning() << error; + } + if (tester) tester->executefailure(); + } + + if (dummyData) { + qWarning() << "Loaded dummy data:" << dir.filePath(qml); + qml.truncate(qml.length()-4); + canvas->rootContext()->setContextProperty(qml, dummyData); + dummyData->setParent(this); + } + } +} + bool QDeclarativeViewer::open(const QString& file_or_url) { currentFileOrUrl = file_or_url; @@ -966,39 +1008,15 @@ bool QDeclarativeViewer::open(const QString& file_or_url) QString fileName = url.toLocalFile(); if (!fileName.isEmpty()) { - QFileInfo fi(fileName); if (fi.exists()) { if (fi.suffix().toLower() != QLatin1String("qml")) { qWarning() << "qml cannot open non-QML file" << fileName; return false; } - QDir dir(fi.path()+"/dummydata", "*.qml"); - QStringList list = dir.entryList(); - for (int i = 0; i < list.size(); ++i) { - QString qml = list.at(i); - QFile f(dir.filePath(qml)); - f.open(QIODevice::ReadOnly); - QByteArray data = f.readAll(); - QDeclarativeComponent comp(canvas->engine()); - comp.setData(data, QUrl()); - QObject *dummyData = comp.create(); - - if(comp.isError()) { - QList errors = comp.errors(); - foreach (const QDeclarativeError &error, errors) { - qWarning() << error; - } - if (tester) tester->executefailure(); - } - - if (dummyData) { - qWarning() << "Loaded dummy data:" << dir.filePath(qml); - qml.truncate(qml.length()-4); - ctxt->setContextProperty(qml, dummyData); - dummyData->setParent(this); - } - } + QFileInfo fi(fileName); + loadTranslationFile(fi.path()); + loadDummyDataFiles(fi.path()); } else { qWarning() << "qml cannot find file:" << fileName; return false; diff --git a/tools/qml/qmlruntime.h b/tools/qml/qmlruntime.h index 2a0a07d..0b23303 100644 --- a/tools/qml/qmlruntime.h +++ b/tools/qml/qmlruntime.h @@ -59,6 +59,7 @@ class QDeclarativeTester; class QNetworkReply; class QNetworkCookieJar; class NetworkAccessManagerFactory; +class QTranslator; class QDeclarativeViewer #if defined(Q_OS_SYMBIAN) @@ -192,6 +193,11 @@ private: NetworkAccessManagerFactory *namFactory; bool useQmlFileBrowser; + + QTranslator *translator; + void loadTranslationFile(const QString& directory); + + void loadDummyDataFiles(const QString& directory); }; Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeViewer::ScriptOptions) -- cgit v0.12 From 9719866c686805d69b0026f555c97594e09c836f Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Wed, 5 May 2010 13:35:11 +1000 Subject: Example i18n. --- examples/declarative/i18n/i18n.qml | 33 ++++++++++++++++++++++++++++ examples/declarative/i18n/i18n/base.ts | 12 ++++++++++ examples/declarative/i18n/i18n/qml_en_AU.qm | Bin 0 -> 81 bytes examples/declarative/i18n/i18n/qml_en_AU.ts | 12 ++++++++++ examples/declarative/i18n/i18n/qml_fr.qm | Bin 0 -> 85 bytes examples/declarative/i18n/i18n/qml_fr.ts | 12 ++++++++++ 6 files changed, 69 insertions(+) create mode 100644 examples/declarative/i18n/i18n.qml create mode 100644 examples/declarative/i18n/i18n/base.ts create mode 100644 examples/declarative/i18n/i18n/qml_en_AU.qm create mode 100644 examples/declarative/i18n/i18n/qml_en_AU.ts create mode 100644 examples/declarative/i18n/i18n/qml_fr.qm create mode 100644 examples/declarative/i18n/i18n/qml_fr.ts diff --git a/examples/declarative/i18n/i18n.qml b/examples/declarative/i18n/i18n.qml new file mode 100644 index 0000000..3b1279a --- /dev/null +++ b/examples/declarative/i18n/i18n.qml @@ -0,0 +1,33 @@ +import Qt 4.7 + +// +// The QML runtime automatically loads a translation from the i18n subdirectory of the root +// QML file, based on the system language. +// +// The files are created/updated by running: +// +// lupdate i18n.qml -ts i18n/*.ts +// +// The .ts files can then be edited with Linguist: +// +// linguist i18n/qml_fr.ts +// +// The run-time translation files are then generaeted by running: +// +// lrelease i18n/*.ts +// +// Translations for new languages are created by copying i18n/base.ts to i18n/qml_.ts +// and editing the result with Linguist. +// + +Column { + Text { + text: "If a translation is available for the system language (eg. Franch) then the string below will translated (eg. 'Bonjour'). Otherwise is will show 'Hello'." + width: 200 + wrapMode: Text.WordWrap + } + Text { + text: qsTr("Hello") + font.pointSize: 25 + } +} diff --git a/examples/declarative/i18n/i18n/base.ts b/examples/declarative/i18n/i18n/base.ts new file mode 100644 index 0000000..82547a1 --- /dev/null +++ b/examples/declarative/i18n/i18n/base.ts @@ -0,0 +1,12 @@ + + + + + i18n + + + Hello + + + + diff --git a/examples/declarative/i18n/i18n/qml_en_AU.qm b/examples/declarative/i18n/i18n/qml_en_AU.qm new file mode 100644 index 0000000..fb8b710 Binary files /dev/null and b/examples/declarative/i18n/i18n/qml_en_AU.qm differ diff --git a/examples/declarative/i18n/i18n/qml_en_AU.ts b/examples/declarative/i18n/i18n/qml_en_AU.ts new file mode 100644 index 0000000..e991aff --- /dev/null +++ b/examples/declarative/i18n/i18n/qml_en_AU.ts @@ -0,0 +1,12 @@ + + + + + i18n + + + Hello + G'day + + + diff --git a/examples/declarative/i18n/i18n/qml_fr.qm b/examples/declarative/i18n/i18n/qml_fr.qm new file mode 100644 index 0000000..583562e Binary files /dev/null and b/examples/declarative/i18n/i18n/qml_fr.qm differ diff --git a/examples/declarative/i18n/i18n/qml_fr.ts b/examples/declarative/i18n/i18n/qml_fr.ts new file mode 100644 index 0000000..365abd9 --- /dev/null +++ b/examples/declarative/i18n/i18n/qml_fr.ts @@ -0,0 +1,12 @@ + + + + + i18n + + + Hello + Bonjour + + + -- cgit v0.12