summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/src/declarative/qml-intro.qdoc7
-rw-r--r--doc/src/declarative/qmlruntime.qdoc12
-rw-r--r--doc/src/snippets/declarative/qml-intro/basic-syntax.qml48
-rw-r--r--doc/src/snippets/declarative/qml-intro/sequential-animation3.qml2
-rw-r--r--src/declarative/graphicsitems/qdeclarativeflickable.cpp1
-rw-r--r--src/declarative/qml/parser/qdeclarativejslexer.cpp8
-rw-r--r--src/declarative/qml/qdeclarativeobjectscriptclass.cpp2
-rw-r--r--src/declarative/qml/qdeclarativevmemetaobject.cpp14
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/data/in.qml7
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp11
-rw-r--r--tests/auto/declarative/qdeclarativelanguage/data/variantNotify.qml13
-rw-r--r--tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp16
-rw-r--r--tests/auto/linguist/lupdate/testdata/good/parseqml/main.qml97
-rw-r--r--tests/auto/linguist/lupdate/testdata/good/parseqml/project.pro3
-rw-r--r--tests/auto/linguist/lupdate/testdata/good/parseqml/project.ts.result195
-rw-r--r--tools/linguist/lupdate/qdeclarative.cpp159
16 files changed, 531 insertions, 64 deletions
diff --git a/doc/src/declarative/qml-intro.qdoc b/doc/src/declarative/qml-intro.qdoc
index 63d6825..9130be0 100644
--- a/doc/src/declarative/qml-intro.qdoc
+++ b/doc/src/declarative/qml-intro.qdoc
@@ -58,7 +58,12 @@ would be a property.
The basic syntax of an \l{QML Elements}{element} is
-\snippet doc/src/snippets/declarative/qml-intro/basic-syntax.qml basic syntax
+\code
+SomeElement {
+ id: myObject
+ ... some other things here ...
+}
+\endcode
Here we are defining a new object. We specify its 'type' first as SomeElement.
Then within matching braces { ... } we specify the various parts of our
diff --git a/doc/src/declarative/qmlruntime.qdoc b/doc/src/declarative/qmlruntime.qdoc
index d44e774..9a84237 100644
--- a/doc/src/declarative/qmlruntime.qdoc
+++ b/doc/src/declarative/qmlruntime.qdoc
@@ -104,20 +104,22 @@ can be constructed directly instead. In this case, \c application.qml is
loaded as a QDeclarativeComponent instance rather than placed into a view:
\code
- #include <QCoreApplication>
+ #include <QApplication>
#include <QDeclarativeEngine>
+ #include <QDeclarativeContext>
+ #include <QDeclarativeComponent>
int main(int argc, char *argv[])
{
- QCoreApplication app(argc, argv);
+ QApplication app(argc, argv);
QDeclarativeEngine engine;
- QDeclarativeContext *windowContext = new QDeclarativeContext(engine.rootContext());
+ QDeclarativeContext *objectContext = new QDeclarativeContext(engine.rootContext());
QDeclarativeComponent component(&engine, "application.qml");
- QObject *window = component.create(windowContext);
+ QObject *object = component.create(objectContext);
- // ... delete window and windowContext when necessary
+ // ... delete object and objectContext when necessary
return app.exec();
}
diff --git a/doc/src/snippets/declarative/qml-intro/basic-syntax.qml b/doc/src/snippets/declarative/qml-intro/basic-syntax.qml
deleted file mode 100644
index 686a927..0000000
--- a/doc/src/snippets/declarative/qml-intro/basic-syntax.qml
+++ /dev/null
@@ -1,48 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module 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 Nokia Corporation 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$
-**
-****************************************************************************/
-
-// Note: this file is not intended to be run.
-
-//! [basic syntax]
-SomeElement {
- id: myObject
- ... some other things here ...
-}
-//! [basic syntax]
diff --git a/doc/src/snippets/declarative/qml-intro/sequential-animation3.qml b/doc/src/snippets/declarative/qml-intro/sequential-animation3.qml
index f83a966..6926f8a 100644
--- a/doc/src/snippets/declarative/qml-intro/sequential-animation3.qml
+++ b/doc/src/snippets/declarative/qml-intro/sequential-animation3.qml
@@ -39,6 +39,8 @@
****************************************************************************/
//! [document]
+import Qt 4.7
+
Rectangle {
id: mainRec
width: 600
diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp
index 63a2a77..b302393 100644
--- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp
@@ -1258,6 +1258,7 @@ bool QDeclarativeFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event)
if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease) {
d->clearDelayedPress();
d->stealMouse = false;
+ d->pressed = false;
}
return false;
}
diff --git a/src/declarative/qml/parser/qdeclarativejslexer.cpp b/src/declarative/qml/parser/qdeclarativejslexer.cpp
index cd08658..1eb42e4 100644
--- a/src/declarative/qml/parser/qdeclarativejslexer.cpp
+++ b/src/declarative/qml/parser/qdeclarativejslexer.cpp
@@ -677,9 +677,9 @@ int Lexer::lex()
setDone(Other);
} else
state = Start;
- if (driver) driver->addComment(startpos, tokenLength(), startlineno, startcolumn);
+ if (driver) driver->addComment(startpos+2, tokenLength()-2, startlineno, startcolumn+2);
} else if (current == 0) {
- if (driver) driver->addComment(startpos, tokenLength(), startlineno, startcolumn);
+ if (driver) driver->addComment(startpos+2, tokenLength()-2, startlineno, startcolumn+2);
setDone(Eof);
}
@@ -689,14 +689,14 @@ int Lexer::lex()
setDone(Bad);
err = UnclosedComment;
errmsg = QCoreApplication::translate("QDeclarativeParser", "Unclosed comment at end of file");
- if (driver) driver->addComment(startpos, tokenLength(), startlineno, startcolumn);
+ if (driver) driver->addComment(startpos+2, tokenLength()-2, startlineno, startcolumn+2);
} else if (isLineTerminator()) {
shiftWindowsLineBreak();
yylineno++;
} else if (current == '*' && next1 == '/') {
state = Start;
shift(1);
- if (driver) driver->addComment(startpos, tokenLength(), startlineno, startcolumn);
+ if (driver) driver->addComment(startpos+2, tokenLength()-3, startlineno, startcolumn+2);
}
break;
diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
index 3af892d..f439151 100644
--- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
+++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
@@ -192,7 +192,7 @@ QDeclarativeObjectScriptClass::queryProperty(QObject *obj, const Identifier &nam
if (!(hints & ImplicitObject)) {
local.coreIndex = -1;
lastData = &local;
- return QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess;
+ return QScriptClass::HandlesWriteAccess;
}
return 0;
diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp
index 689ed92..3e32006 100644
--- a/src/declarative/qml/qdeclarativevmemetaobject.cpp
+++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp
@@ -707,11 +707,19 @@ void QDeclarativeVMEMetaObject::writeVarProperty(int id, const QScriptValue &val
void QDeclarativeVMEMetaObject::writeVarProperty(int id, const QVariant &value)
{
- if (value.userType() == QMetaType::QObjectStar)
+ bool needActivate = false;
+ if (value.userType() == QMetaType::QObjectStar) {
+ QObject *o = qvariant_cast<QObject *>(value);
+ needActivate = (data[id].dataType() != QMetaType::QObjectStar || data[id].asQObject() != o);
data[id].setValue(qvariant_cast<QObject *>(value));
- else
+ } else {
+ needActivate = (data[id].dataType() != qMetaTypeId<QVariant>() ||
+ data[id].asQVariant().userType() != value.userType() ||
+ data[id].asQVariant() != value);
data[id].setValue(value);
- activate(object, methodOffset + id, 0);
+ }
+ if (needActivate)
+ activate(object, methodOffset + id, 0);
}
void QDeclarativeVMEMetaObject::listChanged(int id)
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/in.qml b/tests/auto/declarative/qdeclarativeecmascript/data/in.qml
new file mode 100644
index 0000000..0b5b0ba
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeecmascript/data/in.qml
@@ -0,0 +1,7 @@
+import Qt 4.7
+
+Item {
+ id: root
+ property bool test1: "x" in root
+ property bool test2: !("foo" in root)
+}
diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
index 496cc05..76ca964 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
+++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
@@ -159,6 +159,7 @@ private slots:
void qtbug_11600();
void nonscriptable();
void deleteLater();
+ void in();
void include();
@@ -2553,6 +2554,16 @@ void tst_qdeclarativeecmascript::deleteLater()
delete o;
}
+void tst_qdeclarativeecmascript::in()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
+ QObject *o = component.create();
+ QVERIFY(o != 0);
+ QCOMPARE(o->property("test1").toBool(), true);
+ QCOMPARE(o->property("test2").toBool(), true);
+ delete o;
+}
+
QTEST_MAIN(tst_qdeclarativeecmascript)
#include "tst_qdeclarativeecmascript.moc"
diff --git a/tests/auto/declarative/qdeclarativelanguage/data/variantNotify.qml b/tests/auto/declarative/qdeclarativelanguage/data/variantNotify.qml
new file mode 100644
index 0000000..e7aaf16
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativelanguage/data/variantNotify.qml
@@ -0,0 +1,13 @@
+import Qt 4.7
+
+QtObject {
+ property int notifyCount: 0
+
+ property variant foo
+ onFooChanged: notifyCount++
+
+ Component.onCompleted: {
+ foo = 1;
+ foo = 1;
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp
index fc78663..dc00e16 100644
--- a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp
+++ b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp
@@ -142,8 +142,8 @@ private slots:
void importsOrder();
void qmlAttachedPropertiesObjectMethod();
-
void customOnProperty();
+ void variantNotify();
// regression tests for crashes
void crash1();
@@ -1685,6 +1685,20 @@ void tst_qdeclarativelanguage::customOnProperty()
delete object;
}
+// QTBUG-12601
+void tst_qdeclarativelanguage::variantNotify()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("variantNotify.qml"));
+
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("notifyCount").toInt(), 1);
+
+ delete object;
+}
+
void tst_qdeclarativelanguage::initTestCase()
{
registerTypes();
diff --git a/tests/auto/linguist/lupdate/testdata/good/parseqml/main.qml b/tests/auto/linguist/lupdate/testdata/good/parseqml/main.qml
new file mode 100644
index 0000000..172bd65
--- /dev/null
+++ b/tests/auto/linguist/lupdate/testdata/good/parseqml/main.qml
@@ -0,0 +1,97 @@
+import Qt 4.7
+
+QtObject {
+ function translate() {
+ qsTr("One");
+ qsTranslate("FooContext", "Two");
+
+ var greeting_strings = [
+ QT_TR_NOOP("Hello"),
+ QT_TRANSLATE_NOOP("FooContext", "Goodbye")
+ ];
+
+ qsTr("One", "not the same one");
+
+ //: My first comment.
+ qsTr("See comment");
+
+ //: My second comment.
+ qsTranslate("BarContext", "See other comment");
+
+ //: My third comment
+ //: spans two lines.
+ qsTr("The comment explains it all");
+
+ //: My fourth comment
+ //: spans a whopping
+ //: three lines.
+ qsTranslate("BazContext", "It should be clear by now");
+
+ /*: C-style comment. */
+ qsTr("I love C++");
+
+ /*: Another C-style comment. */
+ qsTranslate("FooContext", "I really love C++");
+
+ /*: C-style comment, followed by */
+ /*: another one. */
+ qsTr("Qt is the best");
+
+ /*: Another C-style comment, followed by */
+ /*: yet another one. */
+ qsTranslate("BarContext", "Qt is the very best");
+
+ // This comment doesn't have any effect.
+ qsTr("The comment had no effect");
+
+ // This comment doesn't have any effect either.
+ qsTranslate("BazContext", "The comment had no effect, really");
+
+ /* This C-style comment doesn't have any effect. */
+ qsTr("No comment to your comment");
+
+ /* This C-style comment doesn't have any effect either. */
+ qsTranslate("FooContext", "I refuse to comment on that");
+
+ //= id_foo
+ qsTr("This string has an identifier");
+
+ //= id_bar
+ qsTranslate("BarContext", "This string also has an identifier");
+
+ //~ loc-blank False
+ qsTr("This string has meta-data");
+
+ //~ loc-layout_id foo_dialog
+ qsTranslate("BazContext", "This string also has meta-data");
+
+ // This comment is to be ignored.
+ //: This is a comment for the translator.
+ //= id_baz
+ //~ foo 123
+ //~ magic-stuff This means something special.
+ qsTr("This string has a lot of information");
+
+ // This comment is also to be ignored.
+ //: This is another comment for the translator.
+ //= id_babar
+ //~ foo-bar Important stuff
+ //~ needle-in-haystack Found
+ //~ overflow True
+ qsTranslate("FooContext", "This string has even more information");
+
+ qsTr("This string has disambiguation", "Disambiguation");
+
+ qsTranslate("BarContext", "This string also has disambiguation", "Another disambiguation");
+
+ qsTr("This string contains plurals", "", 10);
+
+ qsTrId("qtn_foo_bar");
+
+ var more_greeting_strings = [ QT_TRID_NOOP("qtn_needle"), QT_TRID_NOOP("qtn_haystack") ];
+
+ //: qsTrId() with comment, meta-data and plurals.
+ //~ well-tested True
+ qsTrId("qtn_bar_baz", 10);
+ }
+}
diff --git a/tests/auto/linguist/lupdate/testdata/good/parseqml/project.pro b/tests/auto/linguist/lupdate/testdata/good/parseqml/project.pro
new file mode 100644
index 0000000..1040e22
--- /dev/null
+++ b/tests/auto/linguist/lupdate/testdata/good/parseqml/project.pro
@@ -0,0 +1,3 @@
+SOURCES += main.qml
+
+TRANSLATIONS = project.ts
diff --git a/tests/auto/linguist/lupdate/testdata/good/parseqml/project.ts.result b/tests/auto/linguist/lupdate/testdata/good/parseqml/project.ts.result
new file mode 100644
index 0000000..7dac8cb
--- /dev/null
+++ b/tests/auto/linguist/lupdate/testdata/good/parseqml/project.ts.result
@@ -0,0 +1,195 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0">
+<context>
+ <name></name>
+ <message id="qtn_foo_bar">
+ <location filename="main.qml" line="89"/>
+ <source></source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message id="qtn_needle">
+ <location filename="main.qml" line="91"/>
+ <source></source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message id="qtn_haystack">
+ <location filename="main.qml" line="91"/>
+ <source></source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message id="qtn_bar_baz" numerus="yes">
+ <location filename="main.qml" line="95"/>
+ <source></source>
+ <extracomment>qsTrId() with comment, meta-data and plurals.</extracomment>
+ <translation type="unfinished">
+ <numerusform></numerusform>
+ </translation>
+ <extra-well-tested>True</extra-well-tested>
+ </message>
+</context>
+<context>
+ <name>BarContext</name>
+ <message>
+ <location filename="main.qml" line="19"/>
+ <source>See other comment</source>
+ <extracomment>My second comment.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.qml" line="42"/>
+ <source>Qt is the very best</source>
+ <extracomment>Another C-style comment, followed by yet another one.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message id="id_bar">
+ <location filename="main.qml" line="60"/>
+ <source>This string also has an identifier</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.qml" line="85"/>
+ <source>This string also has disambiguation</source>
+ <comment>Another disambiguation</comment>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>BazContext</name>
+ <message>
+ <location filename="main.qml" line="28"/>
+ <source>It should be clear by now</source>
+ <extracomment>My fourth comment spans a whopping three lines.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.qml" line="48"/>
+ <source>The comment had no effect, really</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.qml" line="66"/>
+ <source>This string also has meta-data</source>
+ <translation type="unfinished"></translation>
+ <extra-loc-layout_id>foo_dialog</extra-loc-layout_id>
+ </message>
+</context>
+<context>
+ <name>FooContext</name>
+ <message>
+ <location filename="main.qml" line="6"/>
+ <source>Two</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.qml" line="10"/>
+ <source>Goodbye</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.qml" line="34"/>
+ <source>I really love C++</source>
+ <extracomment>Another C-style comment.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.qml" line="54"/>
+ <source>I refuse to comment on that</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message id="id_babar">
+ <location filename="main.qml" line="81"/>
+ <source>This string has even more information</source>
+ <extracomment>This is another comment for the translator.</extracomment>
+ <translation type="unfinished"></translation>
+ <extra-needle-in-haystack>Found</extra-needle-in-haystack>
+ <extra-overflow>True</extra-overflow>
+ <extra-foo-bar>Important stuff</extra-foo-bar>
+ </message>
+</context>
+<context>
+ <name>main</name>
+ <message>
+ <location filename="main.qml" line="5"/>
+ <source>One</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.qml" line="9"/>
+ <source>Hello</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.qml" line="13"/>
+ <source>One</source>
+ <comment>not the same one</comment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.qml" line="16"/>
+ <source>See comment</source>
+ <extracomment>My first comment.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.qml" line="23"/>
+ <source>The comment explains it all</source>
+ <extracomment>My third comment spans two lines.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.qml" line="31"/>
+ <source>I love C++</source>
+ <extracomment>C-style comment.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.qml" line="38"/>
+ <source>Qt is the best</source>
+ <extracomment>C-style comment, followed by another one.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.qml" line="45"/>
+ <source>The comment had no effect</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.qml" line="51"/>
+ <source>No comment to your comment</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message id="id_foo">
+ <location filename="main.qml" line="57"/>
+ <source>This string has an identifier</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="main.qml" line="63"/>
+ <source>This string has meta-data</source>
+ <translation type="unfinished"></translation>
+ <extra-loc-blank>False</extra-loc-blank>
+ </message>
+ <message id="id_baz">
+ <location filename="main.qml" line="73"/>
+ <source>This string has a lot of information</source>
+ <extracomment>This is a comment for the translator.</extracomment>
+ <translation type="unfinished"></translation>
+ <extra-foo>123</extra-foo>
+ <extra-magic-stuff>This means something special.</extra-magic-stuff>
+ </message>
+ <message>
+ <location filename="main.qml" line="83"/>
+ <source>This string has disambiguation</source>
+ <comment>Disambiguation</comment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message numerus="yes">
+ <location filename="main.qml" line="87"/>
+ <source>This string contains plurals</source>
+ <translation type="unfinished">
+ <numerusform></numerusform>
+ </translation>
+ </message>
+</context>
+</TS>
diff --git a/tools/linguist/lupdate/qdeclarative.cpp b/tools/linguist/lupdate/qdeclarative.cpp
index ffcbf20..01b9a1d 100644
--- a/tools/linguist/lupdate/qdeclarative.cpp
+++ b/tools/linguist/lupdate/qdeclarative.cpp
@@ -71,6 +71,20 @@ class LU {
using namespace QDeclarativeJS;
+class Comment
+{
+public:
+ Comment() : lastLine(-1) {}
+ QString extracomment;
+ QString msgid;
+ TranslatorMessage::ExtraData extra;
+ QString sourcetext;
+ int lastLine;
+
+ bool isValid() const
+ { return !extracomment.isEmpty() || !msgid.isEmpty() || !sourcetext.isEmpty() || !extra.isEmpty(); }
+};
+
class FindTrCalls: protected AST::Visitor
{
public:
@@ -82,6 +96,8 @@ public:
accept(node);
}
+ QList<Comment> comments;
+
protected:
using AST::Visitor::visit;
using AST::Visitor::endVisit;
@@ -118,10 +134,23 @@ protected:
plural = true;
}
+ QString id;
+ QString extracomment;
+ TranslatorMessage::ExtraData extra;
+ Comment scomment = findComment(node->firstSourceLocation().startLine);
+ if (scomment.isValid()) {
+ extracomment = scomment.extracomment;
+ extra = scomment.extra;
+ id = scomment.msgid;
+ }
+
TranslatorMessage msg(m_component, source,
comment, QString(), m_fileName,
node->firstSourceLocation().startLine, QStringList(),
TranslatorMessage::Unfinished, plural);
+ msg.setExtraComment(extracomment.simplified());
+ msg.setId(id);
+ msg.setExtras(extra);
m_translator->extend(msg);
}
} else if (idExpr->name->asString() == QLatin1String("qsTranslate") ||
@@ -144,6 +173,17 @@ protected:
}
if (!literal && m_bSource.isEmpty())
return;
+
+ QString id;
+ QString extracomment;
+ TranslatorMessage::ExtraData extra;
+ Comment scomment = findComment(node->firstSourceLocation().startLine);
+ if (scomment.isValid()) {
+ extracomment = scomment.extracomment;
+ extra = scomment.extra;
+ id = scomment.msgid;
+ }
+
source = literal ? literal->value->asString() : m_bSource;
AST::ArgumentList *commentNode = sourceNode->next;
if (commentNode && AST::cast<AST::StringLiteral *>(commentNode->expression)) {
@@ -159,15 +199,48 @@ protected:
comment, QString(), m_fileName,
node->firstSourceLocation().startLine, QStringList(),
TranslatorMessage::Unfinished, plural);
+ msg.setExtraComment(extracomment.simplified());
+ msg.setId(id);
+ msg.setExtras(extra);
m_translator->extend(msg);
}
+ } else if (idExpr->name->asString() == QLatin1String("qsTrId") ||
+ idExpr->name->asString() == QLatin1String("QT_TRID_NOOP")) {
+ if (!node->arguments)
+ return;
+ AST::StringLiteral *literal = AST::cast<AST::StringLiteral *>(node->arguments->expression);
+ if (literal) {
+
+ QString extracomment;
+ QString sourcetext;
+ TranslatorMessage::ExtraData extra;
+ Comment comment = findComment(node->firstSourceLocation().startLine);
+ if (comment.isValid()) {
+ extracomment = comment.extracomment;
+ sourcetext = comment.sourcetext;
+ extra = comment.extra;
+ }
+
+ const QString id = literal->value->asString();
+ bool plural = node->arguments->next;
+
+ TranslatorMessage msg(QString(), QString(),
+ QString(), QString(), m_fileName,
+ node->firstSourceLocation().startLine, QStringList(),
+ TranslatorMessage::Unfinished, plural);
+ msg.setExtraComment(extracomment.simplified());
+ msg.setId(id);
+ msg.setExtras(extra);
+ m_translator->extend(msg);
+ }
}
}
}
private:
- bool createString(AST::BinaryExpression *b) {
+ bool createString(AST::BinaryExpression *b)
+ {
if (!b || b->op != 0)
return false;
AST::BinaryExpression *l = AST::cast<AST::BinaryExpression *>(b->left);
@@ -191,6 +264,23 @@ private:
return true;
}
+ Comment findComment(int loc)
+ {
+ if (comments.isEmpty())
+ return Comment();
+
+ int i = 0;
+ int commentLoc = comments.at(i).lastLine;
+ while (commentLoc <= loc) {
+ if (commentLoc == loc)
+ return comments.at(i);
+ if (i == comments.count()-1)
+ break;
+ commentLoc = comments.at(++i).lastLine;
+ }
+ return Comment();
+ }
+
Translator *m_translator;
QString m_fileName;
QString m_component;
@@ -240,6 +330,54 @@ QString createErrorString(const QString &filename, const QString &code, Parser &
return errorString;
}
+bool processComment(const QChar *chars, int length, Comment &comment)
+{
+ // Try to match the logic of the QtScript parser.
+ if (!length)
+ return comment.isValid();
+ if (*chars == QLatin1Char(':') && chars[1].isSpace()) {
+ comment.extracomment += QString(chars+1, length-1);
+ } else if (*chars == QLatin1Char('=') && chars[1].isSpace()) {
+ comment.msgid = QString(chars+2, length-2).simplified();
+ } else if (*chars == QLatin1Char('~') && chars[1].isSpace()) {
+ QString text = QString(chars+2, length-2).trimmed();
+ int k = text.indexOf(QLatin1Char(' '));
+ if (k > -1)
+ comment.extra.insert(text.left(k), text.mid(k + 1).trimmed());
+ } else if (*chars == QLatin1Char('%') && chars[1].isSpace()) {
+ comment.sourcetext.reserve(comment.sourcetext.length() + length-2);
+ ushort *ptr = (ushort *)comment.sourcetext.data() + comment.sourcetext.length();
+ int p = 2, c;
+ forever {
+ if (p >= length)
+ break;
+ c = chars[p++].unicode();
+ if (isspace(c))
+ continue;
+ if (c != '"')
+ break;
+ forever {
+ if (p >= length)
+ break;
+ c = chars[p++].unicode();
+ if (c == '"')
+ break;
+ if (c == '\\') {
+ if (p >= length)
+ break;
+ c = chars[p++].unicode();
+ if (c == '\n')
+ break;
+ *ptr++ = '\\';
+ }
+ *ptr++ = c;
+ }
+ }
+ comment.sourcetext.resize(ptr - (ushort *)comment.sourcetext.data());
+ }
+ return comment.isValid();
+}
+
bool loadQml(Translator &translator, const QString &filename, ConversionData &cd)
{
cd.m_sourceFileName = filename;
@@ -263,6 +401,25 @@ bool loadQml(Translator &translator, const QString &filename, ConversionData &cd
if (parser.parse()) {
FindTrCalls trCalls;
+
+ // build up a list of comments that contain translation information.
+ for (int i = 0; i < driver.comments().size(); ++i) {
+ AST::SourceLocation loc = driver.comments().at(i);
+ QString commentStr = code.mid(loc.offset, loc.length);
+
+ if (trCalls.comments.isEmpty() || trCalls.comments.last().lastLine != int(loc.startLine)) {
+ Comment comment;
+ comment.lastLine = loc.startLine+1;
+ if (processComment(commentStr.constData(), commentStr.length(), comment))
+ trCalls.comments.append(comment);
+ } else {
+ Comment &lastComment = trCalls.comments.last();
+ lastComment.lastLine += 1;
+ processComment(commentStr.constData(), commentStr.length(), lastComment);
+ }
+ }
+
+ //find all tr calls in the code
trCalls(&translator, filename, parser.ast());
} else {
QString error = createErrorString(filename, code, parser);