summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demos/declarative/phonebrowser/dummydata/PhonesModel.qml2
-rw-r--r--doc/doc.pri5
-rw-r--r--doc/src/declarative/anchor-layout.qdoc30
-rw-r--r--doc/src/declarative/animation.qdoc126
-rw-r--r--doc/src/declarative/basictypes.qdoc46
-rw-r--r--doc/src/declarative/binding.qdoc20
-rw-r--r--doc/src/declarative/components.qdoc42
-rw-r--r--doc/src/declarative/cppitem.qdoc2
-rw-r--r--doc/src/declarative/qmlreference.qdoc (renamed from doc/src/declarative/qmlfordesign.qdoc)7
-rw-r--r--doc/src/snippets/declarative/pathview/dummydata/MenuModel.qml2
-rw-r--r--examples/declarative/contacts/dummydata/contactModel.qml2
-rw-r--r--examples/declarative/easing/easing.qml2
-rw-r--r--examples/declarative/listview/dummydata/MyPetsModel.qml2
-rw-r--r--examples/declarative/listview/dummydata/Recipies.qml2
-rw-r--r--examples/declarative/minehunt/minehunt.qml6
-rw-r--r--examples/declarative/minehunt/pics/face-sad.pngbin0 -> 14844 bytes
-rw-r--r--examples/declarative/minehunt/pics/face-smile-big.pngbin0 -> 13810 bytes
-rw-r--r--examples/declarative/minehunt/pics/face-smile.pngbin0 -> 15408 bytes
-rw-r--r--examples/declarative/minehunt/pics/frown.pngbin1036 -> 0 bytes
-rw-r--r--examples/declarative/minehunt/pics/glee.pngbin1082 -> 0 bytes
-rw-r--r--examples/declarative/minehunt/pics/smile.pngbin1028 -> 0 bytes
-rw-r--r--examples/declarative/velocity/velocity.qml2
-rw-r--r--src/declarative/fx/qfxflipable.cpp4
-rw-r--r--src/declarative/fx/qfximage.cpp4
-rw-r--r--src/declarative/fx/qfxitem.cpp2
-rw-r--r--src/declarative/fx/qfxparticles.cpp18
-rw-r--r--src/declarative/fx/qfxreflectionfilter.cpp12
-rw-r--r--src/declarative/fx/qfxshadowfilter.cpp2
-rw-r--r--src/declarative/fx/qfxtransform.cpp12
-rw-r--r--src/declarative/qml/qml.pri8
-rw-r--r--src/declarative/qml/qmlcompiler.cpp297
-rw-r--r--src/declarative/qml/qmlcompiler_p.h10
-rw-r--r--src/declarative/qml/qmlcomponent.cpp41
-rw-r--r--src/declarative/qml/qmlcomponent.h5
-rw-r--r--src/declarative/qml/qmlcomponent_p.h4
-rw-r--r--src/declarative/qml/qmlcompositetypemanager.cpp23
-rw-r--r--src/declarative/qml/qmlcompositetypemanager_p.h4
-rw-r--r--src/declarative/qml/qmlcustomparser_p.h17
-rw-r--r--src/declarative/qml/qmldom.cpp25
-rw-r--r--src/declarative/qml/qmldom.h2
-rw-r--r--src/declarative/qml/qmldom_p.h2
-rw-r--r--src/declarative/qml/qmlerror.cpp227
-rw-r--r--src/declarative/qml/qmlerror.h (renamed from src/declarative/qml/qmlxmlparser_p.h)55
-rw-r--r--src/declarative/qml/qmlinstruction.cpp3
-rw-r--r--src/declarative/qml/qmlinstruction_p.h5
-rw-r--r--src/declarative/qml/qmlparser.cpp11
-rw-r--r--src/declarative/qml/qmlparser_p.h7
-rw-r--r--src/declarative/qml/qmlscriptparser.cpp119
-rw-r--r--src/declarative/qml/qmlscriptparser_p.h11
-rw-r--r--src/declarative/qml/qmlvme.cpp45
-rw-r--r--src/declarative/qml/qmlvme_p.h5
-rw-r--r--src/declarative/qml/qmlxmlparser.cpp391
-rw-r--r--src/declarative/util/qfxview.cpp79
-rw-r--r--src/declarative/util/qfxview.h3
-rw-r--r--src/declarative/util/qmllistmodel.cpp180
-rw-r--r--tools/qdoc3/helpprojectwriter.cpp3
-rw-r--r--tools/qdoc3/test/qml.qdocconf77
-rw-r--r--tools/qdoc3/tree.cpp9
-rw-r--r--tools/qmlconv/qmlconv.cpp482
-rw-r--r--tools/qmlconv/qmlconv.pro10
-rw-r--r--tools/qmlviewer/qmlviewer.cpp8
61 files changed, 809 insertions, 1711 deletions
diff --git a/demos/declarative/phonebrowser/dummydata/PhonesModel.qml b/demos/declarative/phonebrowser/dummydata/PhonesModel.qml
index eb68fdb..8d9ed97 100644
--- a/demos/declarative/phonebrowser/dummydata/PhonesModel.qml
+++ b/demos/declarative/phonebrowser/dummydata/PhonesModel.qml
@@ -1,4 +1,4 @@
-ListModel2 {
+ListModel {
id: "PhonesModel"
ListElement {
diff --git a/doc/doc.pri b/doc/doc.pri
index a4c77fe..367ef29 100644
--- a/doc/doc.pri
+++ b/doc/doc.pri
@@ -32,13 +32,14 @@ macx {
ADP_DOCS_QDOCCONF_FILE = qt-build-docs.qdocconf
}
QT_DOCUMENTATION = ($$QDOC qt-api-only.qdocconf assistant.qdocconf designer.qdocconf \
- linguist.qdocconf qmake.qdocconf) && \
+ linguist.qdocconf qmake.qdocconf qml.qdocconf) && \
(cd $$QT_BUILD_TREE && \
$$GENERATOR doc-build/html-qt/qt.qhp -o doc/qch/qt.qch && \
$$GENERATOR doc-build/html-assistant/assistant.qhp -o doc/qch/assistant.qch && \
$$GENERATOR doc-build/html-designer/designer.qhp -o doc/qch/designer.qch && \
$$GENERATOR doc-build/html-linguist/linguist.qhp -o doc/qch/linguist.qch && \
- $$GENERATOR doc-build/html-qmake/qmake.qhp -o doc/qch/qmake.qch \
+ $$GENERATOR doc-build/html-qmake/qmake.qhp -o doc/qch/qmake.qch && \
+ $$GENERATOR doc-build/html-qml/qml.qhp -o doc/qch/qml.qch \
)
win32-g++:isEmpty(QMAKE_SH) {
diff --git a/doc/src/declarative/anchor-layout.qdoc b/doc/src/declarative/anchor-layout.qdoc
index 2b1f081..9ff902ee 100644
--- a/doc/src/declarative/anchor-layout.qdoc
+++ b/doc/src/declarative/anchor-layout.qdoc
@@ -10,8 +10,8 @@ In additional to the more traditional Fx layouts GridLayout, HorizontalLayout, a
The Fx anchoring system allows you to define relationships between the anchor lines of different items. For example, you can write:
\code
-<Rect id="rect1" .../>
-<Rect id="rect2" anchors.left="{rect1.right}" .../>
+Rect { id: rect1; ... }
+Rect { id: rect2; anchors.left: rect1.right; ... }
\endcode
In this case, the left edge of \e rect2 is bound to the right edge of rect1, producing the following:
@@ -25,8 +25,8 @@ The anchoring system also allows you to specify margins and offsets. Margins spe
The following example specifies a left margin:
\code
-<Rect id="rect1" .../>
-<Rect id="rect2" anchors.left="{rect1.right}" anchors.leftMargin="5".../>
+Rect { id: rect1; ... }
+Rect { id: rect2; anchors.left: rect1.right; anchors.leftMargin: 5; ... }
\endcode
In this case, a margin of 5 pixels is reserved to the left of \e rect2, producing the following:
@@ -36,8 +36,8 @@ In this case, a margin of 5 pixels is reserved to the left of \e rect2, producin
You can specify multiple anchors. For example:
\code
-<Rect id="rect1" .../>
-<Rect id="rect2" anchors.left="{rect1.right}" anchors.top="{rect1.bottom}".../>
+Rect { id: rect1; ... }
+Rect { id: rect2; anchors.left: rect1.right; anchors.top: rect1.bottom; ... }
\endcode
\image edge3.png
@@ -45,9 +45,9 @@ You can specify multiple anchors. For example:
By specifying multiple horizontal or vertical anchors you can control the size of an item. For example:
\code
-<Rect id="rect1" x="0" .../>
-<Rect id="rect2" anchors.left="{rect1.right}" anchors.right="{rect3.left}".../>
-<Rect id="rect3" x="150" .../>
+Rect { id: rect1; x: 0; ... }
+Rect { id: rect2; anchors.left: rect1.right; anchors.right: rect3.left; ... }
+Rect { id: rect3; x: 150; ... }
\endcode
\image edge4.png
@@ -57,12 +57,12 @@ By specifying multiple horizontal or vertical anchors you can control the size o
For performance reasons, you can only anchor an item to its siblings and direct parent. For example, the following anchor would be considered invalid and would produce a warning:
\code
-<Item id="group1">
- <Rect id="rect1" .../>
-</Item>
-<Item id="group2">
- <Rect id="rect2" anchors.left="{rect1.right}".../> <!-- invalid anchor! -->
-</Item>
+Item { id: group1 }
+ Rect { id: rect1; ... }
+}
+Item id: group2">
+ Rect { id: rect2; anchors.left: rect1.right; ... } // invalid anchor!
+}
\endcode
*/
diff --git a/doc/src/declarative/animation.qdoc b/doc/src/declarative/animation.qdoc
index cd7d1b9..fb14fdc 100644
--- a/doc/src/declarative/animation.qdoc
+++ b/doc/src/declarative/animation.qdoc
@@ -29,19 +29,30 @@ The simplest form of animation is using \c &lt;NumericAnimation/&gt;
The following example creates a bouncing effect:
\code
-<Rect id="rect" width="120" height="200" color="white">
- <Image id="img" file="pics/qtlogo.png"
- x="{60-img.width/2}" y="{200-img.height}">
- <y>
- <SequentialAnimation running="true" repeat="true">
- <NumericAnimation to="{200-img.height}"
- easing="easeOutBounce(amplitude:100)"
- duration="2000" />
- <PauseAnimation duration="1000" />
- </SequentialAnimation>
- </y>
- </Image>
-</Rect>
+Rect {
+ id: rect
+ width: 120
+ height: 200
+ color: "white"
+ Image {
+ id: img
+ source: "pics/qtlogo.png"
+ x: 60-img.width/2
+ y: 200-img.height
+ y: SequentialAnimation {
+ running: true
+ repeat: true
+ NumericAnimation {
+ to: 200-img.height
+ easing: "easeOutBounce(amplitude:100)"
+ duration: 2000
+ }
+ PauseAnimation {
+ duration: 1000
+ }
+ }
+ }
+}
\endcode
\image propanim.gif
@@ -76,15 +87,28 @@ In QML:
The following example shows a simple use of states. In the default state \c myrect is positioned at 0,0. In the 'moved' state it is positioned at 50,50.
\code
-<Item>
- <Rect id="myrect" width="100" height="100"/>
- <states>
- <State name="moved">
- <SetProperty target="{myrect}" property="x" value="50"/>
- <SetProperty target="{myrect}" property="y" value="50"/>
- </State>
- </states>
-</Item>
+Item {
+ Rect {
+ id: myrect
+ width: 100
+ height: 100
+ }
+ states: [
+ State {
+ name: "moved"
+ SetProperty {
+ target: myrect
+ property: "x"
+ value: 50
+ }
+ SetProperty {
+ target: myrect
+ property: "y"
+ value: 50
+ }
+ }
+ ]
+}
\endcode
\section2 Transitions
@@ -94,34 +118,56 @@ QML transitions describe animations to perform when state changes occur.
For the previous example, a transition could describe how \c myrect moved from its initial position to its new position:
\code
-<transitions>
- <Transition>
- <NumericAnimation properties="x,y" easing="easeOutBounce" duration="200" />
- </Transition>
-</transitions>
+transitions: [
+ Transition {
+ NumericAnimation {
+ properties: "x,y"
+ easing: "easeOutBounce"
+ duration: 200
+ }
+ }
+]
\endcode
QML transitions can use selectors to determine which state changes a transition should apply to:
\code
-<Transition fromState="*" toState="Details">
-...
-</Transition>
+Transition {
+ fromState: "*"
+ toState: "Details"
+ ...
+}
\endcode
Transitions can happen in parallel, in sequence, or in any combination of the two:;
\code
-<Transition fromState="*" toState="MyState" reversible="true" >
- <SequentialAnimation>
- <ColorAnimation duration="1000" />
- <PauseAnimation duration="1000" />
- <ParallelAnimation>
- <NumericAnimation duration="1000" easing="easeOutBounce" target="{box1}" properties="x,y" />
- <NumericAnimation duration="1000" target="{box2}" properties="x,y" />
- </ParallelAnimation>
- </SequentialAnimation>
-</Transition>
+Transition {
+ fromState: "*"
+ toState: "MyState"
+ reversible: true
+ SequentialAnimation {
+ ColorAnimation {
+ duration: 1000
+ }
+ PauseAnimation {
+ duration: 1000
+ }
+ ParallelAnimation {
+ NumericAnimation {
+ duration: 1000
+ easing: "easeOutBounce"
+ target: box1
+ properties: "x,y"
+ }
+ NumericAnimation {
+ duration: 1000
+ target: box2
+ properties: "x,y"
+ }
+ }
+ }
+}
\endcode
\section1 Property Behaviors
diff --git a/doc/src/declarative/basictypes.qdoc b/doc/src/declarative/basictypes.qdoc
index 0000c37..f7eee50 100644
--- a/doc/src/declarative/basictypes.qdoc
+++ b/doc/src/declarative/basictypes.qdoc
@@ -23,7 +23,7 @@
Setting ints looks like this:
\code
- <Item width="100" height="200" />
+ Item { width: 100; height:200 }
\endcode
\target basicqmlbool
@@ -39,7 +39,7 @@
Setting bools looks like this:
\code
- <Item focusable="true" clip="false" />
+ Item { focusable: true; clip: false }
\endcode
\note Technically bool treats an empty string, "false" and "0" as false and
@@ -58,7 +58,7 @@
Setting reals looks like this:
\code
- <Item x="-10" y="100.8" />
+ Item { x: -10; y: 100.8 }
\endcode
\note In QML all reals are stored in single precision, \l {http://en.wikipedia.org/wiki/IEEE_754}{IEEE floating point} format.
@@ -76,7 +76,7 @@
Setting a string looks like this:
\code
- <Text text="Hello world!" />
+ Text { text: "Hello world!" }
\endcode
\raw HTML
@@ -101,9 +101,9 @@
Setting a color looks like this:
\code
- <Rect color="steelblue" />
- <Rect color="#FF0000" />
- <Rect color="#800000FF" />
+ Rect { color: "steelblue" }
+ Rect { color: "#FF0000" }
+ Rect { color: "#800000FF" }
\endcode
\target basicqmlpoint
@@ -118,7 +118,7 @@
Setting a point looks like this:
\code
- <Widget pos="50,50"/>
+ Widget { pos: "50,50" }
\endcode
\target basicqmlsize
@@ -133,7 +133,7 @@
Setting a size looks like this:
\code
- <Widget size="50x50"/>
+ Widget { size: "50x50" }
\endcode
\target basicqmlrectangle
@@ -148,7 +148,7 @@
Setting a rectangle looks like this:
\code
- <Widget geometry="50,50,100x100"/>
+ Widget { geometry: "50,50,100x100" }
\endcode
\target basicqmldate
@@ -163,7 +163,7 @@
Setting a date looks like this:
\code
- <DatePicker minDate="2000-01-01" maxDate="2020-12-31"/>
+ DatePicker { minDate: "2000-01-01"; maxDate: "2020-12-31" }
\endcode
\target basicqmltime
@@ -178,7 +178,7 @@
Setting a time looks like this:
\code
- <TimePicker time="14:22:15"/>
+ TimePicker { time: "14:22:15" }
\endcode
\target basicqmlfont
@@ -199,7 +199,7 @@
Setting a font looks like this:
\code
- <Text font.family="Helvetica" font.size="13" font.bold="true">
+ Text { font.family: "Helvetica"; font.size: 13; font.bold: true }
\endcode
\target basicqmlaction
@@ -220,9 +220,9 @@
Actions are used like this:
\code
- <MouseRegion onClick="{someitem.someaction.trigger()}">
- <State name="enabled" when="{someitem.someaction.enabled=='true'}">
- <Text text="{someitem.someaction.text}">
+ MouseRegion { onClicked: someitem.someaction.trigger() }
+ State { name: "enabled"; when: someitem.someaction.enabled=='true' }
+ Text { text: someitem.someaction.text }
\endcode
\target basicqmlany
@@ -252,13 +252,13 @@
For example, the \l Item class has a children list property
that can be used like this:
\code
- <Item>
- <children>
- <Item id="child1" />
- <Rect id="child2" />
- <Text id="child3" />
- </children>
- </Item>
+ Item {
+ children [
+ Item { id: child1 },
+ Rect { id: child2 },
+ Text { id: child3 }
+ ]
+ }
\endcode
\c child1, \c child2 and \c child3 will all be added to the children list
in the order in which they appear.
diff --git a/doc/src/declarative/binding.qdoc b/doc/src/declarative/binding.qdoc
index 1d4f9a1..2920d51 100644
--- a/doc/src/declarative/binding.qdoc
+++ b/doc/src/declarative/binding.qdoc
@@ -5,23 +5,23 @@
Data binding provides a declarative way of specifying the data associated with objects, as well as the relationship between data of different objects. For example, you could bind the text of a label to the value of a slider: as the value of the slider changed, the label would be automatically updated with the new value.
-Bindings are indicated in Qml through the use of brackets: \c {}. For example, the following produces two Rects of equal size (\c rect2 is bound to the size of \c rect1):
+Bindings are created in Qml when an expression is assigned to a property. For example, the following produces two Rects of equal size (\c rect2 is bound to the size of \c rect1):
\code
-<Rect id="rect1" width="100" height="100">
-<Rect id="rect2" width="{rect1.width}" height="{rect1.height}">
+Rect { id: rect1; width: 100; height: 100 }
+Rect { id: rect2; width: rect1.width; height: rect1.height }
\endcode
-There is also a special \c <Bind> element, which is typically used to bind from the UI to the underlying UI model (see \l {Passing Data Between C++ and Qml} for an example of this). The bindings above could be expressed using the \c <Bind> element as:
+There is also a special \l Bind element, which is typically used to bind from the UI to the underlying UI model (see \l {Passing Data Between C++ and Qml} for an example of this). The bindings above could be expressed using the \l Bind element as:
\code
-<Bind target="{rect2}" property="width" value="{rect1.width}"/>
-<Bind target="{rect2}" property="height" value="{rect1.height}"/>
+Bind { target: rect2; property: "width"; value: rect1.width }
+Bind { target: rect2; property: "height"; value: rect1.height }
\endcode
In addition to binding directly to a property, you can also bind to the results of expressions involving properties. For example:
\code
-<Text text="{contact.firstname + ' ' + contact.lastname}">
-<Image file="{if (contact.gender == 'female') {'pics/female.png'} else {'pics/male.png'}}">
+Text { text: contact.firstname + ' ' + contact.lastname }
+Image { source: if (contact.gender == "female") {"pics/female.png"} else {"pics/male.png"} }
\endcode
Relevant items can also be bound to the contents of a model - see \l ListView for an example of this.
@@ -101,8 +101,8 @@ view->execute();
Finally, in Qml you can make the appropriate bindings, so in \c "MyUI.qml":
\code
-<Slider value="{screen.brightness}"/>
-<Bind target="{screen}" property="brightness" value="{slider.value}" />
+Slider { value: screen.brightness }
+Bind { target: screen; property: "brightness"; value: slider.value }
\endcode
The \l QBindableMap class provides a convenient way to make data visible to the bind engine.
diff --git a/doc/src/declarative/components.qdoc b/doc/src/declarative/components.qdoc
index 9a6f2dd..db59b61 100644
--- a/doc/src/declarative/components.qdoc
+++ b/doc/src/declarative/components.qdoc
@@ -23,10 +23,18 @@ This example describes how to create a component from an existing snippet of Qml
Assume you have an existing UI with a single 'Save' button, defined as follows:
\code
-<Image file="pics/button-background.png">
- <Text text="Save" anchors.horizontalCenter="{parent.horizontalCenter}" anchors.verticalCenter="{parent.verticalCenter}"/>
- <MouseRegion anchors.fill="{parent}" onClick="saveData()"/>
-</Image>
+Image {
+ source: "pics/button-background.png"
+ Text {
+ text: "Save"
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ MouseRegion {
+ anchors.fill: parent
+ onClick: { saveData() }
+ }
+}
\endcode
For the next release, you plan to add 'Cancel' and 'Reset' buttons. Rather than copying and pasting the above markup, you can create a component:
@@ -36,12 +44,20 @@ For the next release, you plan to add 'Cancel' and 'Reset' buttons. Rather than
\o Make some minor changes to define the component's interface:
\code
-<Image file="pics/button-background.png">
- <properties><Property name="label"/></properties>
- <signals><Signal name="click"/></signals>
- <Text text="{parent.label}" anchors.horizontalCenter="{parent.horizontalCenter}" anchors.verticalCenter="{parent.verticalCenter}"/>
- <MouseRegion anchors.fill="{parent}" onClick="parent.click.emit()"/>
-</Image>
+Image {
+ property string label
+ signal clicked
+ source: "pics/button-background.png"
+ Text {
+ text: parent.label
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ MouseRegion {
+ anchors.fill: parent
+ onClick: { parent.click.emit() }
+ }
+}
\endcode
The \a label property and \a click signal that were added effectively become part of the 'public API' of the MyButton component. In a similar manner, the Text and MouseRegion elements become invisible to anyone using the component. Note that the Text element now binds in its data from \a label, and the MouseRegion emits a generic signal.
@@ -49,11 +65,11 @@ The \a label property and \a click signal that were added effectively become par
\o The component can now be used elsewhere as MyButton:
\code
-<MyButton label="Save" onClick="saveData()"/>
+MyButton { label: "Save"; onClicked: saveData() }
...
-<MyButton label="Cancel" onClick="cancelData()"/>
+MyButton { label: "Cancel"; onClicked: cancelData() }
...
-<MyButton label="Reset" onClick="resetData()"/>
+MyButton { label: "Reset"; onClicked: resetData() }
\endcode
\endlist
diff --git a/doc/src/declarative/cppitem.qdoc b/doc/src/declarative/cppitem.qdoc
index 959bc6d..534b32b 100644
--- a/doc/src/declarative/cppitem.qdoc
+++ b/doc/src/declarative/cppitem.qdoc
@@ -76,7 +76,7 @@ For example:
QML_DECLARE_TYPE(MyCircle);
QML_DEFINE_TYPE(MyCircle,Circle);
\endcode
-would make the \e MyCircle class accessable though the \c <Circle/> tag in QML.
+would make the \e MyCircle class accessable though the \c Circle type in QML.
\section1 Creating a new 'Fx' item in C++
diff --git a/doc/src/declarative/qmlfordesign.qdoc b/doc/src/declarative/qmlreference.qdoc
index 35e47df..9a63e50 100644
--- a/doc/src/declarative/qmlfordesign.qdoc
+++ b/doc/src/declarative/qmlreference.qdoc
@@ -1,11 +1,10 @@
/*!
- \page qmlfordesigners.html
- \title Qt Declarative for Designers
+ \page qmlreference.html
+ \title Qml Reference
\target qtdeclarativemainpage
- The Qt Declarative module provides a declarative framework for building
- highly dynamic and fluid applications. It is targetted at the sorts of user
+ QML is a language for building highly dynamic and fluid applications. It is targetted at the sorts of user
interface (and the sorts of hardware) in embedded devices such as phones, media
players, and set-top boxes. It is also appropriate for highly custom desktop
user-interfaces, or special elements in more traditional desktop
diff --git a/doc/src/snippets/declarative/pathview/dummydata/MenuModel.qml b/doc/src/snippets/declarative/pathview/dummydata/MenuModel.qml
index 5b973d7..44cdaf0 100644
--- a/doc/src/snippets/declarative/pathview/dummydata/MenuModel.qml
+++ b/doc/src/snippets/declarative/pathview/dummydata/MenuModel.qml
@@ -1,4 +1,4 @@
-ListModel2 {
+ListModel {
id: MenuModel
ListElement {
name: "Bill Jones"
diff --git a/examples/declarative/contacts/dummydata/contactModel.qml b/examples/declarative/contacts/dummydata/contactModel.qml
index 48b2fd9..53f6b7b 100644
--- a/examples/declarative/contacts/dummydata/contactModel.qml
+++ b/examples/declarative/contacts/dummydata/contactModel.qml
@@ -1,4 +1,4 @@
-ListModel2 {
+ListModel {
ListElement {
firstName: "Aaron"
lastName: "Kennedy"
diff --git a/examples/declarative/easing/easing.qml b/examples/declarative/easing/easing.qml
index 32c1b9b..af675d1 100644
--- a/examples/declarative/easing/easing.qml
+++ b/examples/declarative/easing/easing.qml
@@ -4,7 +4,7 @@ Rect {
height: Layout.height
color: "white"
- ListModel2 {
+ ListModel {
id: EasingTypes
ListElement { type: "easeLinear" }
ListElement { type: "easeInQuad" }
diff --git a/examples/declarative/listview/dummydata/MyPetsModel.qml b/examples/declarative/listview/dummydata/MyPetsModel.qml
index 1c96b7f..4d76ff4 100644
--- a/examples/declarative/listview/dummydata/MyPetsModel.qml
+++ b/examples/declarative/listview/dummydata/MyPetsModel.qml
@@ -1,6 +1,6 @@
// ListModel allows free form list models to be defined and populated.
// Be sure to name the file the same as the id.
-ListModel2 {
+ListModel {
id: MyListElementsModel
ListElement {
name: "Polly"
diff --git a/examples/declarative/listview/dummydata/Recipies.qml b/examples/declarative/listview/dummydata/Recipies.qml
index 8f464da..3f2ab48 100644
--- a/examples/declarative/listview/dummydata/Recipies.qml
+++ b/examples/declarative/listview/dummydata/Recipies.qml
@@ -1,4 +1,4 @@
-ListModel2 {
+ListModel {
id: Recipies
ListElement {
title: "Pancakes"
diff --git a/examples/declarative/minehunt/minehunt.qml b/examples/declarative/minehunt/minehunt.qml
index 58397b0..bf31c3d 100644
--- a/examples/declarative/minehunt/minehunt.qml
+++ b/examples/declarative/minehunt/minehunt.qml
@@ -148,9 +148,9 @@ Item {
text: numFlags
}
Image {
- x: 240
- y: 0
- source: if(isPlaying==true){'pics/smile.png'}else{if(hasWon==true){'pics/glee.png'}else{'pics/frown.png'}}
+ x: 280
+ y: 10
+ source: if(isPlaying==true){'pics/face-smile.png'}else{if(hasWon==true){'pics/face-smile-big.png'}else{'pics/face-sad.png'}}
MouseRegion {
anchors.fill: parent
onClicked: { reset() }
diff --git a/examples/declarative/minehunt/pics/face-sad.png b/examples/declarative/minehunt/pics/face-sad.png
new file mode 100644
index 0000000..cf00aaf
--- /dev/null
+++ b/examples/declarative/minehunt/pics/face-sad.png
Binary files differ
diff --git a/examples/declarative/minehunt/pics/face-smile-big.png b/examples/declarative/minehunt/pics/face-smile-big.png
new file mode 100644
index 0000000..f9c2335
--- /dev/null
+++ b/examples/declarative/minehunt/pics/face-smile-big.png
Binary files differ
diff --git a/examples/declarative/minehunt/pics/face-smile.png b/examples/declarative/minehunt/pics/face-smile.png
new file mode 100644
index 0000000..3d66d72
--- /dev/null
+++ b/examples/declarative/minehunt/pics/face-smile.png
Binary files differ
diff --git a/examples/declarative/minehunt/pics/frown.png b/examples/declarative/minehunt/pics/frown.png
deleted file mode 100644
index 52684b3..0000000
--- a/examples/declarative/minehunt/pics/frown.png
+++ /dev/null
Binary files differ
diff --git a/examples/declarative/minehunt/pics/glee.png b/examples/declarative/minehunt/pics/glee.png
deleted file mode 100644
index 59ea583..0000000
--- a/examples/declarative/minehunt/pics/glee.png
+++ /dev/null
Binary files differ
diff --git a/examples/declarative/minehunt/pics/smile.png b/examples/declarative/minehunt/pics/smile.png
deleted file mode 100644
index ccd52cd..0000000
--- a/examples/declarative/minehunt/pics/smile.png
+++ /dev/null
Binary files differ
diff --git a/examples/declarative/velocity/velocity.qml b/examples/declarative/velocity/velocity.qml
index ff95527..786f364 100644
--- a/examples/declarative/velocity/velocity.qml
+++ b/examples/declarative/velocity/velocity.qml
@@ -2,7 +2,7 @@ Rect {
color: "lightSteelBlue"
width: 800
height: 600
- ListModel2 {
+ ListModel {
id: List
ListElement {
name: "Sunday"
diff --git a/src/declarative/fx/qfxflipable.cpp b/src/declarative/fx/qfxflipable.cpp
index db390d2..24ae428 100644
--- a/src/declarative/fx/qfxflipable.cpp
+++ b/src/declarative/fx/qfxflipable.cpp
@@ -80,8 +80,8 @@ Flipable {
endX: 20
endY: 40
}
- front: Image { src: "front.png" }
- back: Image { src: "back.png" }
+ front: Image { source: "front.png" }
+ back: Image { source: "back.png" }
states: [
State {
name: "back"
diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp
index 53c6137..838da30 100644
--- a/src/declarative/fx/qfximage.cpp
+++ b/src/declarative/fx/qfximage.cpp
@@ -203,8 +203,8 @@ QFxScaleGrid *QFxImage::scaleGrid()
\qml
Item {
Image { source: "tile.png" }
- Image { x: 80; width: 100; height: 100; src: "tile.png" }
- Image { x: 190; width: 100; height: 100; tile: true; src: "tile.png" }
+ Image { x: 80; width: 100; height: 100; source: "tile.png" }
+ Image { x: 190; width: 100; height: 100; tile: true; source: "tile.png" }
}
\endqml
\image declarative-image_tile.png
diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp
index 84dc484..ecc2d65 100644
--- a/src/declarative/fx/qfxitem.cpp
+++ b/src/declarative/fx/qfxitem.cpp
@@ -448,7 +448,7 @@ QFxItem::~QFxItem()
This example scales an image about its center.
\qml
Image {
- src: "myimage.png"
+ source: "myimage.png"
transformOrigin: "Center"
scale: 4
}
diff --git a/src/declarative/fx/qfxparticles.cpp b/src/declarative/fx/qfxparticles.cpp
index 45de1a3..0ac537a 100644
--- a/src/declarative/fx/qfxparticles.cpp
+++ b/src/declarative/fx/qfxparticles.cpp
@@ -251,7 +251,7 @@ Rect {
y: 0
width: parent.width
height: 30
- src: "star.png"
+ source: "star.png"
lifeSpan: 5000
count: 50
angle: 70
@@ -543,7 +543,7 @@ Rect {
y: 0
width: parent.width
height: 30
- src: "star.png"
+ source: "star.png"
lifeSpan: 5000
count: 50
angle: 70
@@ -560,7 +560,7 @@ Rect {
x: 120
width: 1
height: 1
- src: "star.png"
+ source: "star.png"
lifeSpan: 5000
count: 200
angle: 270
@@ -698,7 +698,7 @@ void QFxParticles::setCount(int cnt)
\qml
Particles {
- src: "star.png"
+ source: "star.png"
lifeSpan: 200
lifeSpanDeviation: 100
}
@@ -735,7 +735,7 @@ void QFxParticles::setLifeSpan(int ls)
\qml
Particles {
- src: "star.png"
+ source: "star.png"
lifeSpan: 200
lifeSpanDeviation: 100
}
@@ -813,7 +813,7 @@ void QFxParticles::setFadeOutDuration(int dur)
\qml
Particles {
- src: "star.png"
+ source: "star.png"
angle: 60
angleDeviation: 90
}
@@ -848,7 +848,7 @@ void QFxParticles::setAngle(qreal angle)
\qml
Particles {
- src: "star.png"
+ source: "star.png"
angle: 60
angleDeviation: 90
}
@@ -880,7 +880,7 @@ void QFxParticles::setAngleDeviation(qreal dev)
\qml
Particles {
- src: "star.png"
+ source: "star.png"
velocity: 50
velocityDeviation: 20
}
@@ -915,7 +915,7 @@ void QFxParticles::setVelocity(qreal velocity)
\qml
Particles {
- src: "star.png"
+ source: "star.png"
velocity: 50
velocityDeviation: 20
}
diff --git a/src/declarative/fx/qfxreflectionfilter.cpp b/src/declarative/fx/qfxreflectionfilter.cpp
index a55f374..0bc01a7 100644
--- a/src/declarative/fx/qfxreflectionfilter.cpp
+++ b/src/declarative/fx/qfxreflectionfilter.cpp
@@ -72,23 +72,23 @@ public:
\qml
HorizontalLayout {
Image {
- src: "icon.png"
+ source: "icon.png"
filter: Reflection { }
}
Image {
- src: "icon.png"
+ source: "icon.png"
filter: Reflection { offset: 1 }
}
Image {
- src: "icon.png"
+ source: "icon.png"
filter: Reflection { offset: 1; alpha: 0.5 }
}
Image {
- src: "icon.png"
+ source: "icon.png"
filter: Reflection { offset: 1; alpha: 0.5; height: 50 }
}
Image {
- src: "icon.png"
+ source: "icon.png"
filter: Reflection { offset: 1; alpha: 0.5; height: 50; scale: 0.5 }
}
}
@@ -147,7 +147,7 @@ void QFxReflectionFilter::setAlpha(qreal a)
\qml
Image {
id: myImage
- src: "album.png"
+ source: "album.png"
filter: Reflection {
height: myImage.height * 0.5
}
diff --git a/src/declarative/fx/qfxshadowfilter.cpp b/src/declarative/fx/qfxshadowfilter.cpp
index 4d34f74..83c1b47 100644
--- a/src/declarative/fx/qfxshadowfilter.cpp
+++ b/src/declarative/fx/qfxshadowfilter.cpp
@@ -86,7 +86,7 @@ Rect {
}
Image {
- src: "pics/qtlogo.png"
+ source: "pics/qtlogo.png"
filter: Shadow {
yOffset: 8
xOffset: 8
diff --git a/src/declarative/fx/qfxtransform.cpp b/src/declarative/fx/qfxtransform.cpp
index 1fe02d1..71ca716 100644
--- a/src/declarative/fx/qfxtransform.cpp
+++ b/src/declarative/fx/qfxtransform.cpp
@@ -322,7 +322,7 @@ void QFxRotation3D::update()
The following example translates the image to 10, 3.
\qml
Image {
- src: "logo.png"
+ source: "logo.png"
transform: [
Translation3D {
axis.startX: 0
@@ -520,9 +520,9 @@ QMatrix4x4 QFxPerspective::transform() const
HorizontalLayout {
margin: 10
spacing: 10
- Image { src: "qt.png" }
+ Image { source: "qt.png" }
Image {
- src: "qt.png"
+ source: "qt.png"
transform: Squish {
x:0; y:0; width:60; height:60
topLeftX:0; topLeftY:0
@@ -532,7 +532,7 @@ QMatrix4x4 QFxPerspective::transform() const
}
}
Image {
- src: "qt.png"
+ source: "qt.png"
transform: Squish {
x:0; y:0; width:60; height:60
topLeftX:0; topLeftY:0
@@ -542,7 +542,7 @@ QMatrix4x4 QFxPerspective::transform() const
}
}
Image {
- src: "qt.png"
+ source: "qt.png"
transform: Squish {
x:0; y:0; width:60; height:60
topLeftX:0; topLeftY:10
@@ -552,7 +552,7 @@ QMatrix4x4 QFxPerspective::transform() const
}
}
Image {
- src: "qt.png"
+ source: "qt.png"
transform: Squish {
x:0; y:0; width:60; height:60
topLeftX:10; topLeftY:0
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
index 9067039..5198264 100644
--- a/src/declarative/qml/qml.pri
+++ b/src/declarative/qml/qml.pri
@@ -8,7 +8,6 @@ SOURCES += qml/qmlparser.cpp \
qml/qmlcontext.cpp \
qml/qmlcustomparser.cpp \
qml/qmlpropertyvaluesource.cpp \
- qml/qmlxmlparser.cpp \
qml/qmlproxymetaobject.cpp \
qml/qmlvme.cpp \
qml/qmlcompiler.cpp \
@@ -22,7 +21,8 @@ SOURCES += qml/qmlparser.cpp \
qml/qmlclassfactory.cpp \
qml/qmlparserstatus.cpp \
qml/qmlcompositetypemanager.cpp \
- qml/qmlinfo.cpp
+ qml/qmlinfo.cpp \
+ qml/qmlerror.cpp
HEADERS += qml/qmlparser_p.h \
qml/qmlinstruction_p.h \
@@ -36,7 +36,6 @@ HEADERS += qml/qmlparser_p.h \
qml/qmlcustomparser_p_p.h \
qml/qmlpropertyvaluesource.h \
qml/qmlboundsignal_p.h \
- qml/qmlxmlparser_p.h \
qml/qmlparserstatus.h \
qml/qmlproxymetaobject_p.h \
qml/qmlcompiledcomponent_p.h \
@@ -58,7 +57,8 @@ HEADERS += qml/qmlparser_p.h \
qml/qmlcontext_p.h \
qml/qmlcompositetypemanager_p.h \
qml/qmllist.h \
- qml/qmldeclarativedata_p.h
+ qml/qmldeclarativedata_p.h \
+ qml/qmlerror.h
# for qtscript debugger
QT += scripttools
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index c9bdfec..b8f3921 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -64,17 +64,6 @@
#include "qmlscriptparser_p.h"
QT_BEGIN_NAMESPACE
-/*
- New properties and signals can be added to any QObject type from QML.
- <QObject>
- <properties><Property name="myProperty" /></properties>
- <signals><Signal name="mySignal" /></signals>
- </QObject
- The special names used as magical properties (in the above case "properties"
- and "signals") are defined here.
-*/
-#define PROPERTIES_NAME "properties"
-#define SIGNALS_NAME "signals"
using namespace QmlParser;
@@ -147,7 +136,7 @@ int QmlCompiledData::indexForInt(int *data, int count)
}
QmlCompiler::QmlCompiler()
-: exceptionLine(-1), output(0)
+: exceptionLine(-1), exceptionColumn(-1), output(0)
{
}
@@ -156,14 +145,19 @@ bool QmlCompiler::isError() const
return exceptionLine != -1;
}
-qint64 QmlCompiler::errorLine() const
+QList<QmlError> QmlCompiler::errors() const
{
- return exceptionLine;
-}
+ QList<QmlError> rv;
+
+ if(isError()) {
+ QmlError error;
+ error.setDescription(exceptionDescription);
+ error.setLine(exceptionLine);
+ error.setColumn(exceptionColumn);
+ rv << error;
+ }
-QString QmlCompiler::errorDescription() const
-{
- return exceptionDescription;
+ return rv;
}
bool QmlCompiler::isValidId(const QString &val)
@@ -437,9 +431,19 @@ void QmlCompiler::reset(QmlCompiledComponent *cc, bool deleteMemory)
cc->bytecode.clear();
}
+#define COMPILE_EXCEPTION2(token, desc) \
+ { \
+ exceptionLine = token->line; \
+ exceptionColumn = token->column; \
+ QDebug d(&exceptionDescription); \
+ d << desc; \
+ return false; \
+ }
+
#define COMPILE_EXCEPTION(desc) \
{ \
exceptionLine = obj->line; \
+ exceptionColumn = obj->column; \
QDebug d(&exceptionDescription); \
d << desc; \
return false; \
@@ -532,47 +536,14 @@ bool QmlCompiler::compileObject(Object *obj, int ctxt)
ctxt = 0;
- // Only use magical "properties" and "signals" properties if the type
- // doesn't have already have them
- bool ignoreProperties = false;
- bool ignoreSignals = false;
- if (obj->metatype && obj->metatype->indexOfProperty(PROPERTIES_NAME) != -1)
- ignoreProperties = true;
- if (obj->metatype && obj->metatype->indexOfProperty(SIGNALS_NAME) != -1)
- ignoreSignals = true;
-
- Property *propertiesProperty = ignoreProperties?0:obj->getProperty(PROPERTIES_NAME, false);
- Property *signalsProperty = ignoreSignals?0:obj->getProperty(SIGNALS_NAME, false);
-
- if (propertiesProperty) {
- obj->dynamicPropertiesProperty = propertiesProperty;
- obj->properties.remove(PROPERTIES_NAME);
- }
- if (signalsProperty) {
- obj->dynamicSignalsProperty = signalsProperty;
- obj->properties.remove(SIGNALS_NAME);
- }
-
int createInstrIdx = output->bytecode.count();
- if (obj->type != -1 && output->types.at(obj->type).parser) {
- QByteArray data = obj->custom;
- int ref = output->indexForByteArray(data);
-
- QmlInstruction create;
- create.type = QmlInstruction::CreateCustomObject;
- create.line = obj->line;
- create.createCustom.type = obj->type;
- create.createCustom.data = ref;
- output->bytecode << create;
- } else {
- // Create the object
- QmlInstruction create;
- create.type = QmlInstruction::CreateObject;
- create.line = obj->line;
- create.create.data = -1;
- create.create.type = obj->type;
- output->bytecode << create;
- }
+ // Create the object
+ QmlInstruction create;
+ create.type = QmlInstruction::CreateObject;
+ create.line = obj->line;
+ create.create.data = -1;
+ create.create.type = obj->type;
+ output->bytecode << create;
COMPILE_CHECK(compileDynamicPropertiesAndSignals(obj));
@@ -599,9 +570,7 @@ bool QmlCompiler::compileObject(Object *obj, int ctxt)
QList<QmlCustomParserProperty> customProps;
foreach(Property *prop, obj->properties) {
- if (!ignoreProperties && prop->name == PROPERTIES_NAME) {
- } else if (!ignoreSignals && prop->name == SIGNALS_NAME) {
- } else if (prop->name.length() >= 3 && prop->name.startsWith("on") &&
+ if (prop->name.length() >= 3 && prop->name.startsWith("on") &&
('A' <= prop->name.at(2) && 'Z' >= prop->name.at(2))) {
if (!isCustomParser) {
COMPILE_CHECK(compileSignal(prop, obj));
@@ -1215,10 +1184,10 @@ bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop,
//### we are restricted to a rather generic message here. If we can find a way to move
// the exception into generateStoreInstruction we could potentially have better messages.
// (the problem is that both compile and run exceptions can be generated, though)
- COMPILE_EXCEPTION("Cannot assign value" << v->primitive << "to property" << obj->metaObject()->property(prop->index).name());
+ COMPILE_EXCEPTION2(v, "Cannot assign value" << v->primitive << "to property" << obj->metaObject()->property(prop->index).name());
doassign = false;
} else if (r == ReadOnly) {
- COMPILE_EXCEPTION("Cannot assign value" << v->primitive << "to the read-only property" << obj->metaObject()->property(prop->index).name());
+ COMPILE_EXCEPTION2(v, "Cannot assign value" << v->primitive << "to the read-only property" << obj->metaObject()->property(prop->index).name());
} else {
doassign = true;
}
@@ -1243,209 +1212,9 @@ bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop,
return true;
}
-bool QmlCompiler::findDynamicProperties(QmlParser::Property *prop,
- QmlParser::Object *obj)
-{
- QList<Object::DynamicProperty> definedProperties;
-
- struct TypeNameToType {
- const char *name;
- Object::DynamicProperty::Type type;
- } propTypeNameToTypes[] = {
- { "", Object::DynamicProperty::Variant },
- { "int", Object::DynamicProperty::Int },
- { "bool", Object::DynamicProperty::Bool },
- { "double", Object::DynamicProperty::Real },
- { "real", Object::DynamicProperty::Real },
- { "string", Object::DynamicProperty::String },
- { "color", Object::DynamicProperty::Color },
- { "date", Object::DynamicProperty::Date },
- { "variant", Object::DynamicProperty::Variant }
- };
- const int propTypeNameToTypesCount = sizeof(propTypeNameToTypes) /
- sizeof(propTypeNameToTypes[0]);
-
-
- if (prop->value)
- COMPILE_EXCEPTION("Invalid property specification");
-
- bool seenDefault = false;
- for (int ii = 0; ii < prop->values.count(); ++ii) {
- QmlParser::Value *val = prop->values.at(ii);
- if (!val->object)
- COMPILE_EXCEPTION("Invalid property specification");
-
- QmlParser::Object *obj = val->object;
- if (obj->type == -1 || output->types.at(obj->type).className != "Property")
- COMPILE_EXCEPTION("Use Property tag to specify properties");
-
-
- enum Seen { None = 0, Name = 0x01,
- Type = 0x02, Value = 0x04,
- ValueChanged = 0x08,
- Default = 0x10 } seen = None;
-
- Object::DynamicProperty propDef;
-
- for (QHash<QByteArray, QmlParser::Property *>::ConstIterator iter =
- obj->properties.begin();
- iter != obj->properties.end();
- ++iter) {
-
- QmlParser::Property *property = *iter;
- if (property->name == "name") {
- if (seen & Name)
- COMPILE_EXCEPTION("May only specify Property name once");
- seen = (Seen)(seen | Name);
-
- if (property->value || property->values.count() != 1 ||
- property->values.at(0)->object)
- COMPILE_EXCEPTION("Invalid Property name");
-
- propDef.name = property->values.at(0)->primitive.toLatin1();
-
- } else if (property->name == "type") {
- if (seen & Type)
- COMPILE_EXCEPTION("May only specify Property type once");
- seen = (Seen)(seen | Type);
-
- if (property->value || property->values.count() != 1 ||
- property->values.at(0)->object)
- COMPILE_EXCEPTION("Invalid Property type");
-
- QString type = property->values.at(0)->primitive.toLower();
- bool found = false;
- for (int ii = 0; !found && ii < propTypeNameToTypesCount; ++ii) {
- if (type == QLatin1String(propTypeNameToTypes[ii].name)){
- found = true;
- propDef.type = propTypeNameToTypes[ii].type;
- }
-
- }
-
- if (!found)
- COMPILE_EXCEPTION("Invalid Property type");
-
- } else if (property->name == "value") {
- if (seen & Value)
- COMPILE_EXCEPTION("May only specify Property value once");
- seen = (Seen)(seen | Value);
-
- propDef.defaultValue = property;
- } else if (property->name == "onValueChanged") {
- if (seen & ValueChanged)
- COMPILE_EXCEPTION("May only specify Property onValueChanged once");
- seen = (Seen)(seen | ValueChanged);
-
- if (property->value || property->values.count() != 1 ||
- property->values.at(0)->object)
- COMPILE_EXCEPTION("Invalid Property onValueChanged");
-
- propDef.onValueChanged = property->values.at(0)->primitive;
-
- } else if (property->name == "default") {
- if (seen & Default)
- COMPILE_EXCEPTION("May only specify Property default once");
- seen = (Seen)(seen | Default);
- if (property->value || property->values.count() != 1 ||
- property->values.at(0)->object)
- COMPILE_EXCEPTION("Invalid Property default");
-
- bool defaultValue =
- QmlStringConverters::boolFromString(property->values.at(0)->primitive);
- propDef.isDefaultProperty = defaultValue;
- if (defaultValue) {
- if (seenDefault)
- COMPILE_EXCEPTION("Only one property may be the default");
- seenDefault = true;
- }
-
- } else {
- COMPILE_EXCEPTION("Invalid Property property");
- }
-
- }
- if (obj->defaultProperty) {
- if (seen & Value)
- COMPILE_EXCEPTION("May only specify Property value once");
-
- seen = (Seen)(seen | Value);
- propDef.defaultValue = obj->defaultProperty;
- }
-
- if (!(seen & Name))
- COMPILE_EXCEPTION("Must specify Property name");
-
- definedProperties << propDef;
- }
-
- obj->dynamicProperties << definedProperties;
- return true;
-}
-
-bool QmlCompiler::findDynamicSignals(QmlParser::Property *sigs,
- QmlParser::Object *obj)
-{
- QList<Object::DynamicSignal> definedSignals;
-
- if (sigs->value)
- COMPILE_EXCEPTION("Invalid signal specification");
-
- for (int ii = 0; ii < sigs->values.count(); ++ii) {
- QmlParser::Value *val = sigs->values.at(ii);
- if (!val->object)
- COMPILE_EXCEPTION("Invalid signal specification");
-
- QmlParser::Object *obj = val->object;
- if (obj->type == -1 || output->types.at(obj->type).className != "Signal")
- COMPILE_EXCEPTION("Use Signal tag to specify signals");
-
- enum Seen { None = 0, Name = 0x01 } seen = None;
- Object::DynamicSignal sigDef;
-
- for (QHash<QByteArray, QmlParser::Property *>::ConstIterator iter =
- obj->properties.begin();
- iter != obj->properties.end();
- ++iter) {
-
- QmlParser::Property *property = *iter;
- if (property->name == "name") {
- if (seen & Name)
- COMPILE_EXCEPTION("May only specify Signal name once");
- seen = (Seen)(seen | Name);
-
- if (property->value || property->values.count() != 1 ||
- property->values.at(0)->object)
- COMPILE_EXCEPTION("Invalid Signal name");
-
- sigDef.name = property->values.at(0)->primitive.toLatin1();
-
- } else {
- COMPILE_EXCEPTION("Invalid Signal property");
- }
-
- }
-
- if (obj->defaultProperty)
- COMPILE_EXCEPTION("Invalid Signal property");
-
- if (!(seen & Name))
- COMPILE_EXCEPTION("Must specify Signal name");
-
- definedSignals << sigDef;
- }
-
- obj->dynamicSignals << definedSignals;
- return true;
-}
-
bool QmlCompiler::compileDynamicPropertiesAndSignals(QmlParser::Object *obj)
{
- if (obj->dynamicPropertiesProperty)
- findDynamicProperties(obj->dynamicPropertiesProperty, obj);
- if (obj->dynamicSignalsProperty)
- findDynamicSignals(obj->dynamicSignalsProperty, obj);
-
+ // ### FIXME - Check that there is only one default property etc.
if (obj->dynamicProperties.isEmpty() && obj->dynamicSignals.isEmpty())
return true;
diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h
index 9a0ce1c..4acdcfa 100644
--- a/src/declarative/qml/qmlcompiler_p.h
+++ b/src/declarative/qml/qmlcompiler_p.h
@@ -45,6 +45,7 @@
#include <QtCore/qbytearray.h>
#include <QtCore/qset.h>
#include <qml.h>
+#include <qmlerror.h>
#include <private/qmlinstruction_p.h>
#include <private/qmlcompositetypemanager_p.h>
class QStringList;
@@ -115,8 +116,7 @@ public:
bool compile(QmlEngine *, QmlCompositeTypeData *, QmlCompiledComponent *);
bool isError() const;
- qint64 errorLine() const;
- QString errorDescription() const;
+ QList<QmlError> errors() const;
static bool isValidId(const QString &);
static bool isBinding(const QString &);
@@ -163,11 +163,6 @@ private:
QmlParser::Value *value,
int ctxt);
- bool findDynamicProperties(QmlParser::Property *prop,
- QmlParser::Object *obj);
- bool findDynamicSignals(QmlParser::Property *sigs,
- QmlParser::Object *obj);
-
bool compileDynamicPropertiesAndSignals(QmlParser::Object *obj);
void compileBinding(const QString &, QmlParser::Property *prop,
int ctxt, const QMetaObject *, qint64);
@@ -176,6 +171,7 @@ private:
QSet<QString> ids;
qint64 exceptionLine;
+ qint64 exceptionColumn;
QString exceptionDescription;
QmlCompiledData *output;
};
diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp
index c316f03..b1beb9c 100644
--- a/src/declarative/qml/qmlcomponent.cpp
+++ b/src/declarative/qml/qmlcomponent.cpp
@@ -60,17 +60,6 @@
QT_BEGIN_NAMESPACE
class QByteArray;
-bool QmlComponentPrivate::isXml(const QByteArray &ba)
-{
- for (int i = 0; i < ba.size(); ++i) {
- char c = ba.at(i);
- if (c == ' ' || c == '\n' || c == '\r' || c == '\t')
- continue;
- return (c == '<');
- }
- return true;
-}
-
/*!
\class QmlComponent
\brief The QmlComponent class encapsulates a QML component description.
@@ -137,9 +126,7 @@ void QmlComponentPrivate::fromTypeData(QmlCompositeTypeData *data)
if (!c) {
Q_ASSERT(data->status == QmlCompositeTypeData::Error);
- errorDescription = data->errorDescription;
- qWarning().nospace() << "QmlComponent: "
- << data->errorDescription.toLatin1().constData();
+ errors = data->errors;
} else {
@@ -192,10 +179,10 @@ QmlComponent::Status QmlComponent::status() const
if (d->typeData)
return Loading;
+ else if (!d->errors.isEmpty())
+ return Error;
else if (d->engine && d->cc)
return Ready;
- else if (!d->errorDescription.isEmpty())
- return Error;
else
return Null;
}
@@ -353,13 +340,17 @@ void QmlComponent::loadUrl(const QUrl &url)
emit statusChanged(status());
}
-QString QmlComponent::errorDescription() const
+/*!
+ Return the list of errors that occured during the last compile or create
+ operation. An empty list is returned if isError() is not set.
+*/
+QList<QmlError> QmlComponent::errors() const
{
Q_D(const QmlComponent);
if (isError())
- return d->errorDescription;
+ return d->errors;
else
- return QString();
+ return QList<QmlError>();
}
/*!
@@ -448,7 +439,7 @@ QObject *QmlComponent::beginCreate(QmlContext *context)
}
if (!isReady()) {
- qWarning("QmlComponent: Cannot create un-ready component");
+ qWarning("QmlComponent: Component is not ready");
return 0;
}
@@ -466,15 +457,9 @@ QObject *QmlComponent::beginCreate(QmlContext *context)
QmlVME vme;
QObject *rv = vme.run(ctxt, d->cc, d->start, d->count);
- if (vme.isError()) {
- qWarning().nospace()
-#ifdef QML_VERBOSEERRORS_ENABLED
- << "QmlComponent: "
-#endif
- << vme.errorDescription().toLatin1().constData() << " @"
- << d->url.toString().toLatin1().constData() << ":" << vme.errorLine();
- }
+ if (vme.isError())
+ d->errors = vme.errors();
ctxt->deactivate();
diff --git a/src/declarative/qml/qmlcomponent.h b/src/declarative/qml/qmlcomponent.h
index 0493c1f..90f7467 100644
--- a/src/declarative/qml/qmlcomponent.h
+++ b/src/declarative/qml/qmlcomponent.h
@@ -46,7 +46,7 @@
#include <QtCore/qstring.h>
#include <QtDeclarative/qfxglobal.h>
#include <QtDeclarative/qml.h>
-
+#include <QtDeclarative/qmlerror.h>
QT_BEGIN_HEADER
@@ -77,7 +77,8 @@ public:
bool isReady() const;
bool isError() const;
bool isLoading() const;
- QString errorDescription() const;
+
+ QList<QmlError> errors() const;
QUrl url() const;
diff --git a/src/declarative/qml/qmlcomponent_p.h b/src/declarative/qml/qmlcomponent_p.h
index bb5f7bb..6a5345e 100644
--- a/src/declarative/qml/qmlcomponent_p.h
+++ b/src/declarative/qml/qmlcomponent_p.h
@@ -47,6 +47,7 @@
#include <QList>
#include "private/qobject_p.h"
#include "private/qmlcompositetypemanager_p.h"
+#include <qmlerror.h>
#include "qmlcomponent.h"
class QmlComponent;
class QmlEngine;
@@ -68,7 +69,7 @@ public:
void fromTypeData(QmlCompositeTypeData *data);
- QString errorDescription;
+ QList<QmlError> errors;
QUrl url;
int start;
@@ -81,7 +82,6 @@ public:
QmlEngine *engine;
void clear();
- static bool isXml(const QByteArray &);
};
#endif // QMLCOMPONENT_P_H
diff --git a/src/declarative/qml/qmlcompositetypemanager.cpp b/src/declarative/qml/qmlcompositetypemanager.cpp
index 7f2cc58..fbe40bf 100644
--- a/src/declarative/qml/qmlcompositetypemanager.cpp
+++ b/src/declarative/qml/qmlcompositetypemanager.cpp
@@ -105,10 +105,9 @@ QmlCompositeTypeData::toCompiledComponent(QmlEngine *engine)
QmlCompiler compiler;
if (!compiler.compile(engine, this, compiledComponent)) {
status = Error;
- errorDescription = compiler.errorDescription() +
- QLatin1String("@") +
- url + QLatin1String(":") +
- QString::number(compiler.errorLine());
+ errors = compiler.errors();
+ for(int ii = 0; ii < errors.count(); ++ii)
+ errors[ii].setUrl(url);
compiledComponent->release();
compiledComponent = 0;
}
@@ -188,7 +187,10 @@ void QmlCompositeTypeManager::replyFinished()
reply->url().toString();
unit->status = QmlCompositeTypeData::Error;
- unit->errorDescription = errorDescription;
+ // ### FIXME
+ QmlError error;
+ error.setDescription(errorDescription);
+ unit->errors << error;
doComplete(unit);
} else {
@@ -215,7 +217,10 @@ void QmlCompositeTypeManager::loadSource(QmlCompositeTypeData *unit)
// ### - Fill in error
errorDescription = QLatin1String("File error for URL ") + url.toString();
unit->status = QmlCompositeTypeData::Error;
- unit->errorDescription = errorDescription;
+ // ### FIXME
+ QmlError error;
+ error.setDescription(errorDescription);
+ unit->errors << error;
doComplete(unit);
}
@@ -234,7 +239,7 @@ void QmlCompositeTypeManager::setData(QmlCompositeTypeData *unit,
if (!unit->data.parse(data, url)) {
unit->status = QmlCompositeTypeData::Error;
- unit->errorDescription = unit->data.errorDescription();
+ unit->errors << unit->data.errors();
doComplete(unit);
} else {
@@ -273,7 +278,7 @@ void QmlCompositeTypeManager::checkComplete(QmlCompositeTypeData *unit)
if (u->status == QmlCompositeTypeData::Error) {
unit->status = QmlCompositeTypeData::Error;
- unit->errorDescription = u->errorDescription;
+ unit->errors = u->errors;
doComplete(unit);
return;
} else if (u->status == QmlCompositeTypeData::Waiting) {
@@ -334,7 +339,7 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
case QmlCompositeTypeData::Invalid:
case QmlCompositeTypeData::Error:
unit->status = QmlCompositeTypeData::Error;
- unit->errorDescription = urlUnit->errorDescription;
+ unit->errors = urlUnit->errors;
doComplete(unit);
return;
diff --git a/src/declarative/qml/qmlcompositetypemanager_p.h b/src/declarative/qml/qmlcompositetypemanager_p.h
index bc86fcf..e4028d5 100644
--- a/src/declarative/qml/qmlcompositetypemanager_p.h
+++ b/src/declarative/qml/qmlcompositetypemanager_p.h
@@ -45,6 +45,7 @@
#include <qglobal.h>
#include <private/qmlscriptparser_p.h>
#include <private/qmlrefcount_p.h>
+#include <qmlerror.h>
QT_BEGIN_NAMESPACE
@@ -65,7 +66,8 @@ struct QmlCompositeTypeData : public QmlRefCount
Waiting
};
Status status;
- QString errorDescription;
+
+ QList<QmlError> errors;
QString url;
QList<QmlCompositeTypeData *> dependants;
diff --git a/src/declarative/qml/qmlcustomparser_p.h b/src/declarative/qml/qmlcustomparser_p.h
index 0e6a619..e4e6089 100644
--- a/src/declarative/qml/qmlcustomparser_p.h
+++ b/src/declarative/qml/qmlcustomparser_p.h
@@ -98,26 +98,9 @@ class Q_DECLARATIVE_EXPORT QmlCustomParser
public:
virtual ~QmlCustomParser() {}
- virtual QByteArray compile(QXmlStreamReader&, bool *ok)=0;
virtual QByteArray compile(const QList<QmlCustomParserProperty> &, bool *ok);
- virtual QVariant create(const QByteArray &)=0;
virtual void setCustomData(QObject *, const QByteArray &);
-
- struct Register {
- Register(const char *name, QmlCustomParser *parser) {
- qmlRegisterCustomParser(name, parser);
- }
- };
- template<typename T>
- struct Define {
- static Register instance;
- };
};
-#define QML_DEFINE_CUSTOM_PARSER(name, parserClass) \
- template<> QmlCustomParser::Register QmlCustomParser::Define<parserClass>::instance(# name, new parserClass);
-#define QML_DEFINE_CUSTOM_PARSER_NS(namespacestring, name, parserClass) \
- template<> QmlCustomParser::Register QmlCustomParser::Define<parserClass>::instance(namespacestring "/" # name, new parserClass);
-
#define QML_DEFINE_CUSTOM_TYPE(TYPE, NAME, CUSTOMTYPE) \
template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *>::instance(qmlRegisterCustomType<TYPE>(#NAME, #TYPE, new CUSTOMTYPE));
diff --git a/src/declarative/qml/qmldom.cpp b/src/declarative/qml/qmldom.cpp
index 5380740..08755b1 100644
--- a/src/declarative/qml/qmldom.cpp
+++ b/src/declarative/qml/qmldom.cpp
@@ -70,6 +70,7 @@ QmlDomDocumentPrivate::~QmlDomDocumentPrivate()
/*!
\class QmlDomDocument
+ \internal
\brief The QmlDomDocument class represents the root of a QML document
A QML document is a self-contained snippet of QML, usually contained in a
@@ -152,7 +153,7 @@ bool QmlDomDocument::load(QmlEngine *engine, const QByteArray &data)
{
Q_UNUSED(engine);
- d->error = QString();
+ d->errors.clear();
QmlCompiledComponent component;
QmlCompiler compiler;
@@ -160,11 +161,13 @@ bool QmlDomDocument::load(QmlEngine *engine, const QByteArray &data)
QmlCompositeTypeData *td = ((QmlEnginePrivate *)QmlEnginePrivate::get(engine))->typeManager.getImmediate(data, QUrl());;
if(td->status == QmlCompositeTypeData::Error) {
- d->error = td->errorDescription;
+ d->errors = td->errors;
td->release();
return false;
} else if(td->status == QmlCompositeTypeData::Waiting) {
- d->error = QLatin1String("QmlDomDocument supports local types only");
+ QmlError error;
+ error.setDescription(QLatin1String("QmlDomDocument supports local types only"));
+ d->errors << error;
td->release();
return false;
}
@@ -172,7 +175,7 @@ bool QmlDomDocument::load(QmlEngine *engine, const QByteArray &data)
compiler.compile(engine, td, &component);
if (compiler.isError()) {
- d->error = compiler.errorDescription();
+ d->errors = compiler.errors();
td->release();
return false;
}
@@ -188,14 +191,14 @@ bool QmlDomDocument::load(QmlEngine *engine, const QByteArray &data)
/*!
- Returns the last load error. The load error will be reset after a
+ Returns the last load errors. The load errors will be reset after a
successful call to load().
\sa load()
*/
-QString QmlDomDocument::loadError() const
+QList<QmlError> QmlDomDocument::errors() const
{
- return d->error;
+ return d->errors;
}
/*!
@@ -249,6 +252,7 @@ QmlDomPropertyPrivate::~QmlDomPropertyPrivate()
/*!
\class QmlDomProperty
+ \internal
\brief The QmlDomProperty class represents one property assignment in the
QML DOM tree
@@ -450,6 +454,7 @@ QmlDomObjectPrivate::properties(QmlParser::Property *property) const
/*!
\class QmlDomObject
+ \internal
\brief The QmlDomObject class represents an object instantiation.
Each object instantiated in a QML file has a corresponding QmlDomObject
@@ -734,6 +739,7 @@ QmlDomBasicValuePrivate::~QmlDomBasicValuePrivate()
/*!
\class QmlDomValueLiteral
+ \internal
\brief The QmlDomValueLiteral class represents a literal value.
A literal value is a simple value, written inline with the QML. In the
@@ -806,6 +812,7 @@ void QmlDomValueLiteral::setLiteral(const QString &value)
/*!
\class QmlDomValueBinding
+ \internal
\brief The QmlDomValueBinding class represents a property binding.
A property binding is an ECMAScript expression assigned to a property. In
@@ -875,6 +882,7 @@ void QmlDomValueBinding::setBinding(const QString &expression)
/*!
\class QmlDomValueValueSource
+ \internal
\brief The QmlDomValueValueSource class represents a value source assignment value.
In QML, value sources are special value generating types that may be
@@ -983,6 +991,7 @@ QmlDomValuePrivate::~QmlDomValuePrivate()
/*!
\class QmlDomValue
+ \internal
\brief The QmlDomValue class represents a generic Qml value.
QmlDomValue's can be assigned to QML \l {QmlDomProperty}{properties}. In
@@ -1234,6 +1243,7 @@ QmlDomList QmlDomValue::toList() const
/*!
\class QmlDomList
+ \internal
\brief The QmlDomList class represents a list of values assigned to a QML property.
Lists of values can be assigned to properties. For example, the following
@@ -1323,6 +1333,7 @@ void QmlDomList::setValues(const QList<QmlDomValue> &values)
/*!
\class QmlDomComponent
+ \internal
\brief The QmlDomComponent class represents sub-component within a QML document.
Sub-components are QmlComponents defined within a QML document. The
diff --git a/src/declarative/qml/qmldom.h b/src/declarative/qml/qmldom.h
index 47a89d9..74ed27c 100644
--- a/src/declarative/qml/qmldom.h
+++ b/src/declarative/qml/qmldom.h
@@ -44,6 +44,7 @@
#include <QtCore/qlist.h>
#include <QtCore/qshareddata.h>
+#include <QtDeclarative/qmlerror.h>
QT_BEGIN_HEADER
@@ -71,6 +72,7 @@ public:
int version() const;
+ QList<QmlError> errors() const;
QString loadError() const;
bool load(QmlEngine *, const QByteArray &);
QByteArray save() const;
diff --git a/src/declarative/qml/qmldom_p.h b/src/declarative/qml/qmldom_p.h
index 8ea56bf..4c3ca44 100644
--- a/src/declarative/qml/qmldom_p.h
+++ b/src/declarative/qml/qmldom_p.h
@@ -57,7 +57,7 @@ public:
QmlDomDocumentPrivate(const QmlDomDocumentPrivate &);
~QmlDomDocumentPrivate();
- QString error;
+ QList<QmlError> errors;
QmlParser::Object *root;
};
diff --git a/src/declarative/qml/qmlerror.cpp b/src/declarative/qml/qmlerror.cpp
new file mode 100644
index 0000000..2ed3500
--- /dev/null
+++ b/src/declarative/qml/qmlerror.cpp
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlerror.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlError
+ \brief The QmlError class encapsulates a QML error
+*/
+class QmlErrorPrivate
+{
+public:
+ QmlErrorPrivate();
+
+ QUrl url;
+ QString description;
+ int line;
+ int column;
+};
+
+QmlErrorPrivate::QmlErrorPrivate()
+: line(-1), column(-1)
+{
+}
+
+/*!
+ Create an empty error object.
+*/
+QmlError::QmlError()
+: d(new QmlErrorPrivate)
+{
+}
+
+/*!
+ Create a copy of \a other.
+*/
+QmlError::QmlError(const QmlError &other)
+: d(new QmlErrorPrivate)
+{
+ *this = other;
+}
+
+/*!
+ Assign \a other to this error object.
+*/
+QmlError &QmlError::operator=(const QmlError &other)
+{
+ d->url = other.d->url;
+ d->description = other.d->description;
+ d->line = other.d->line;
+ d->column = other.d->column;
+ return *this;
+}
+
+/*!
+ \internal
+*/
+QmlError::~QmlError()
+{
+ delete d; d = 0;
+}
+
+/*!
+ Return the url for the file that caused this error.
+*/
+QUrl QmlError::url() const
+{
+ return d->url;
+}
+
+/*!
+ Set the \a url for the file that caused this error.
+*/
+void QmlError::setUrl(const QUrl &url)
+{
+ d->url = url;
+}
+
+/*!
+ Return the error description.
+*/
+QString QmlError::description() const
+{
+ return d->description;
+}
+
+/*!
+ Set the error \a description.
+*/
+void QmlError::setDescription(const QString &description)
+{
+ d->description = description;
+}
+
+/*!
+ Return the error line number.
+*/
+int QmlError::line() const
+{
+ return d->line;
+}
+
+/*!
+ Set the error \a line number.
+*/
+void QmlError::setLine(int line)
+{
+ d->line = line;
+}
+
+/*!
+ Return the error column number.
+*/
+int QmlError::column() const
+{
+ return d->column;
+}
+
+/*!
+ Set the error \a column number.
+*/
+void QmlError::setColumn(int column)
+{
+ d->column = column;
+}
+
+/*!
+ \relates QmlError
+ \fn QDebug operator<<(QDebug debug, const QmlError &error)
+
+ Output a human readable version of \a error to \a debug.
+*/
+
+QDebug operator<<(QDebug debug, const QmlError &error)
+{
+ QUrl url = error.url();
+
+ QString output;
+
+ output = url.toString() + QLatin1String(":") +
+ QString::number(error.line());
+
+ if(error.column() != -1)
+ output += QLatin1String(":") + QString::number(error.column());
+
+ output += QLatin1String(": ") + error.description();
+
+ debug << qPrintable(output) << "\n";
+
+ if (error.line() > 0 && error.column() > 0 &&
+ url.scheme() == QLatin1String("file")) {
+ QString file = url.toLocalFile();
+ QFile f(file);
+ if (f.open(QIODevice::ReadOnly)) {
+ QByteArray data = f.readAll();
+ QTextStream stream(data, QIODevice::ReadOnly);
+ const QString code = stream.readAll();
+ const QStringList lines = code.split(QLatin1Char('\n'));
+
+ if (lines.count() >= error.line()) {
+ const QString &line = lines.at(error.line() - 1);
+ debug << qPrintable(line) << "\n";
+
+ int column = qMax(0, error.column() - 1);
+ column = qMin(column, line.length());
+
+ QByteArray ind;
+ ind.reserve(column);
+ for (int i = 0; i < column; ++i) {
+ const QChar ch = line.at(i);
+ if (ch.isSpace())
+ ind.append(ch.unicode());
+ else
+ ind.append(' ');
+ }
+ ind.append('^');
+ debug << ind.constData();
+ }
+ }
+ }
+ return debug;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlxmlparser_p.h b/src/declarative/qml/qmlerror.h
index 9b45e28..57d2f8f 100644
--- a/src/declarative/qml/qmlxmlparser_p.h
+++ b/src/declarative/qml/qmlerror.h
@@ -39,12 +39,11 @@
**
****************************************************************************/
-#ifndef QMLXMLPARSER_P_H
-#define QMLXMLPARSER_P_H
+#ifndef QMLERROR_H
+#define QMLERROR_H
-#include <QList>
-#include <QUrl>
-#include <qml.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qstring.h>
QT_BEGIN_HEADER
@@ -52,38 +51,32 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
-namespace QmlParser {
- class Object;
-}
-
-class QByteArray;
-class QmlXmlParser
+class QDebug;
+class QmlErrorPrivate;
+class Q_DECLARATIVE_EXPORT QmlError
{
public:
- QmlXmlParser();
- ~QmlXmlParser();
-
- bool parse(const QByteArray &data, const QUrl &url=QUrl());
- QString errorDescription() const;
-
- QMap<QString,QString> nameSpacePaths() const;
- QStringList types() const;
-
- QmlParser::Object *tree() const;
- QmlParser::Object *takeTree();
-
- void clear();
-
+ QmlError();
+ QmlError(const QmlError &);
+ QmlError &operator=(const QmlError &);
+ ~QmlError();
+
+ QUrl url() const;
+ void setUrl(const QUrl &);
+ QString description() const;
+ void setDescription(const QString &);
+ int line() const;
+ void setLine(int);
+ int column() const;
+ void setColumn(int);
private:
- QMap<QString,QString> _nameSpacePaths;
- QmlParser::Object *root;
- QStringList _typeNames;
- QString _error;
+ QmlErrorPrivate *d;
};
+QDebug Q_DECLARATIVE_EXPORT operator<<(QDebug debug, const QmlError &error);
+
QT_END_NAMESPACE
QT_END_HEADER
-#endif // QMLXMLPARSER_P_H
-
+#endif // QMLERROR_H
diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp
index 82924c8..52677c2 100644
--- a/src/declarative/qml/qmlinstruction.cpp
+++ b/src/declarative/qml/qmlinstruction.cpp
@@ -58,9 +58,6 @@ void QmlCompiledComponent::dump(QmlInstruction *instr, int idx)
case QmlInstruction::CreateObject:
qWarning() << idx << "\t" << line << "\t" << "CREATE\t\t\t" << instr->create.type << "\t\t\t" << types.at(instr->create.type).className;
break;
- case QmlInstruction::CreateCustomObject:
- qWarning() << idx << "\t" << line << "\t" << "CREATE_CUSTOM\t\t" << instr->createCustom.type << "\t" << instr->createCustom.data << "\t\t" << types.at(instr->create.type).className;
- break;
case QmlInstruction::SetId:
qWarning() << idx << "\t" << line << "\t" << "SETID\t\t\t" << instr->setId.value << "\t" << instr->setId.save << "\t\t" << primitives.at(instr->setId.value);
break;
diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h
index 922fc61..462f9e4 100644
--- a/src/declarative/qml/qmlinstruction_p.h
+++ b/src/declarative/qml/qmlinstruction_p.h
@@ -63,7 +63,6 @@ public:
// top of the stack.
Init, /* init */
CreateObject, /* create */
- CreateCustomObject, /* createCustom */
SetId, /* setId */
SetDefault,
CreateComponent, /* createComponent */
@@ -180,10 +179,6 @@ public:
int data;
} storeMeta;
struct {
- int type;
- int data;
- } createCustom;
- struct {
int value;
int save;
} setId;
diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp
index ecb6f0b..d862315 100644
--- a/src/declarative/qml/qmlparser.cpp
+++ b/src/declarative/qml/qmlparser.cpp
@@ -63,8 +63,7 @@ QT_BEGIN_NAMESPACE
using namespace QmlParser;
QmlParser::Object::Object()
-: type(-1), metatype(0), extObject(0), defaultProperty(0), line(-1),
- dynamicPropertiesProperty(0), dynamicSignalsProperty(0)
+: type(-1), metatype(0), extObject(0), defaultProperty(0), line(-1), column(-1)
{
}
@@ -73,8 +72,6 @@ QmlParser::Object::~Object()
if (defaultProperty) defaultProperty->release();
foreach(Property *prop, properties)
prop->release();
- if (dynamicPropertiesProperty) dynamicPropertiesProperty->release();
- if (dynamicSignalsProperty) dynamicSignalsProperty->release();
}
const QMetaObject *Object::metaObject() const
@@ -127,12 +124,12 @@ QmlParser::Object::DynamicSignal::DynamicSignal(const DynamicSignal &o)
}
QmlParser::Property::Property()
-: type(0), index(-1), value(0), isDefault(true), line(-1)
+: type(0), index(-1), value(0), isDefault(true), line(-1), column(-1)
{
}
QmlParser::Property::Property(const QByteArray &n)
-: type(0), index(-1), value(0), name(n), isDefault(false), line(-1)
+: type(0), index(-1), value(0), name(n), isDefault(false), line(-1), column(-1)
{
}
@@ -161,7 +158,7 @@ void QmlParser::Property::addValue(Value *v)
}
QmlParser::Value::Value()
-: type(Unknown), object(0), line(-1)
+: type(Unknown), object(0), line(-1), column(-1)
{
}
diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h
index e29cdbf..aeacee8 100644
--- a/src/declarative/qml/qmlparser_p.h
+++ b/src/declarative/qml/qmlparser_p.h
@@ -103,6 +103,7 @@ namespace QmlParser
QHash<QByteArray, Property *> properties;
qint64 line;
+ qint64 column;
struct DynamicProperty {
DynamicProperty();
@@ -123,10 +124,6 @@ namespace QmlParser
QByteArray name;
};
- // The "properties" property
- Property *dynamicPropertiesProperty;
- // The "signals" property
- Property *dynamicSignalsProperty;
// The list of dynamic properties described in the "properties" property
QList<DynamicProperty> dynamicProperties;
// The list of dynamic signals described in the "signals" property
@@ -167,6 +164,7 @@ namespace QmlParser
Object *object;
qint64 line;
+ qint64 column;
};
class Property : public QmlRefCount
@@ -197,6 +195,7 @@ namespace QmlParser
bool isDefault;
qint64 line;
+ qint64 column;
};
}
diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp
index 8039b5c..81315c3 100644
--- a/src/declarative/qml/qmlscriptparser.cpp
+++ b/src/declarative/qml/qmlscriptparser.cpp
@@ -1,6 +1,5 @@
#include "qmlscriptparser_p.h"
-#include "qmlxmlparser_p.h"
#include "qmlparser_p.h"
#include "parser/javascriptengine_p.h"
@@ -65,10 +64,12 @@ protected:
Object *defineObjectBinding(int line,
AST::UiQualifiedId *propertyName,
const QString &objectType,
+ AST::SourceLocation typeLocation,
AST::UiObjectInitializer *initializer = 0);
Object *defineObjectBinding_helper(int line,
AST::UiQualifiedId *propertyName,
const QString &objectType,
+ AST::SourceLocation typeLocation,
AST::UiObjectInitializer *initializer = 0);
QString getPrimitive(const QByteArray &propertyName, AST::ExpressionNode *expr);
void defineProperty(const QString &propertyName, int line, const QString &primitive);
@@ -194,11 +195,17 @@ QString ProcessAST::asString(AST::UiQualifiedId *node) const
Object *ProcessAST::defineObjectBinding_helper(int line,
AST::UiQualifiedId *propertyName,
const QString &objectType,
+ AST::SourceLocation typeLocation,
AST::UiObjectInitializer *initializer)
{
bool isType = !objectType.isEmpty() && objectType.at(0).isUpper() && !objectType.contains(QLatin1Char('.'));
+
if (!isType) {
- qWarning() << "bad name for a class"; // ### FIXME
+ QmlError error;
+ error.setDescription("Expected type name");
+ error.setLine(typeLocation.startLine);
+ error.setColumn(typeLocation.startColumn);
+ _parser->_errors << error;
return false;
}
@@ -235,7 +242,7 @@ Object *ProcessAST::defineObjectBinding_helper(int line,
if (!_parser->scriptFile().isEmpty()) {
_stateStack.pushObject(obj);
- Object *scriptObject= defineObjectBinding(line, 0, QLatin1String("Script"));
+ Object *scriptObject= defineObjectBinding(line, 0, QLatin1String("Script"), AST::SourceLocation());
_stateStack.pushObject(scriptObject);
defineProperty(QLatin1String("src"), line, _parser->scriptFile());
_stateStack.pop(); // scriptObject
@@ -264,11 +271,12 @@ Object *ProcessAST::defineObjectBinding_helper(int line,
Object *ProcessAST::defineObjectBinding(int line,
AST::UiQualifiedId *qualifiedId,
const QString &objectType,
+ AST::SourceLocation typeLocation,
AST::UiObjectInitializer *initializer)
{
if (objectType == QLatin1String("Connection")) {
- Object *obj = defineObjectBinding_helper(line, 0, QLatin1String("Connection"));
+ Object *obj = defineObjectBinding_helper(line, 0, objectType, typeLocation);
_stateStack.pushObject(obj);
@@ -297,7 +305,7 @@ Object *ProcessAST::defineObjectBinding(int line,
return obj;
}
- return defineObjectBinding_helper(line, qualifiedId, objectType, initializer);
+ return defineObjectBinding_helper(line, qualifiedId, objectType, typeLocation, initializer);
}
void ProcessAST::defineProperty(const QString &propertyName, int line, const QString &primitive)
@@ -372,7 +380,11 @@ bool ProcessAST::visit(AST::UiPublicMember *node)
}
if(!typeFound) {
- qWarning() << "Unknown property type" << memberType; // ### FIXME
+ QmlError error;
+ error.setDescription("Expected property type");
+ error.setLine(node->typeToken.startLine);
+ error.setColumn(node->typeToken.startColumn);
+ _parser->_errors << error;
return false;
}
@@ -402,6 +414,7 @@ bool ProcessAST::visit(AST::UiObjectDefinition *node)
defineObjectBinding(node->identifierToken.startLine,
0,
node->name->asString(),
+ node->identifierToken,
node->initializer);
return false;
@@ -414,6 +427,7 @@ bool ProcessAST::visit(AST::UiObjectBinding *node)
defineObjectBinding(node->identifierToken.startLine,
node->qualifiedId,
node->name->asString(),
+ node->identifierToken,
node->initializer);
return false;
@@ -476,7 +490,8 @@ bool ProcessAST::visit(AST::UiScriptBinding *node)
Value *v = new Value;
v->primitive = primitive;
- v->line = node->colonToken.startLine;
+ v->line = node->statement->firstSourceLocation().startLine;
+ v->column = node->statement->firstSourceLocation().startColumn;
prop->addValue(v);
while (propertyCount--)
@@ -507,7 +522,11 @@ bool ProcessAST::visit(AST::UiSourceElement *node)
{
QmlParser::Object *obj = currentObject();
if (! (obj && obj->typeName == "Script")) {
- // ### warning
+ QmlError error;
+ error.setDescription("JavaScript declaration outside Script element");
+ error.setLine(node->firstSourceLocation().startLine);
+ error.setColumn(node->firstSourceLocation().startColumn);
+ _parser->_errors << error;
return false;
}
@@ -535,7 +554,7 @@ bool ProcessAST::visit(AST::UiSourceElement *node)
QmlScriptParser::QmlScriptParser()
- : root(0), _errorLine(-1)
+: root(0)
{
}
@@ -546,21 +565,6 @@ QmlScriptParser::~QmlScriptParser()
bool QmlScriptParser::parse(const QByteArray &data, const QUrl &url)
{
- if (QmlComponentPrivate::isXml(data)) {
- // parse using the XML parser.
- QmlXmlParser xmlParser;
- if (xmlParser.parse(data, url)) {
- _nameSpacePaths = xmlParser.nameSpacePaths();
- root = xmlParser.takeTree();
- _typeNames = xmlParser.types();
- return true;
- }
-
- _error = xmlParser.errorDescription();
- _errorLine = 0; // ### FIXME
- return false;
- }
-
const QString fileName = url.toString();
QTextStream stream(data, QIODevice::ReadOnly);
@@ -576,61 +580,34 @@ bool QmlScriptParser::parse(const QByteArray &data, const QUrl &url)
lexer.setCode(code, /*line = */ 1);
driver.setLexer(&lexer);
- if (! parser.parse(&driver)) {
- _error = parser.errorMessage();
- _errorLine = parser.errorLineNumber();
-
- const QStringList lines = code.split(QLatin1Char('\n'));
+ if (! parser.parse(&driver) || !_errors.isEmpty()) {
+ // Extract errors from the parser
foreach (const JavaScriptParser::DiagnosticMessage &m, parser.diagnosticMessages()) {
if (m.isWarning())
continue;
- qWarning().nospace() << qPrintable(fileName) << ":"
- << m.line << ":"
- << m.column << ": "
- << "error: "
- << qPrintable(m.message);
-
- const QString textLine = lines.at(m.line - 1);
-
- qWarning() << qPrintable(textLine);
+ QmlError error;
+ error.setUrl(url);
+ error.setDescription(m.message);
+ error.setLine(m.line);
+ error.setColumn(m.column);
+ _errors << error;
- int column = qMax(0, m.column - 1);
- column = qMin(column, textLine.length()); // paranoia check
-
- QByteArray ind;
- ind.reserve(column);
-
- for (int i = 0; i < column; ++i) {
- const QChar ch = textLine.at(i);
- if (ch.isSpace())
- ind.append(ch.unicode());
- else
- ind.append(' ');
- }
- ind.append('^');
- qWarning() << ind.constData();
}
-
- return false;
}
- ProcessAST process(this);
- process(code, parser.ast());
-
- return true;
-}
+ if (_errors.isEmpty()) {
+ ProcessAST process(this);
+ process(code, parser.ast());
-QString QmlScriptParser::errorDescription() const
-{
- return _error;
-}
+ // Set the url for process errors
+ for(int ii = 0; ii < _errors.count(); ++ii)
+ _errors[ii].setUrl(url);
+ }
-int QmlScriptParser::errorLine() const
-{
- return _errorLine;
+ return _errors.isEmpty();
}
QMap<QString,QString> QmlScriptParser::nameSpacePaths() const
@@ -648,6 +625,11 @@ Object *QmlScriptParser::tree() const
return root;
}
+QList<QmlError> QmlScriptParser::errors() const
+{
+ return _errors;
+}
+
void QmlScriptParser::clear()
{
if (root) {
@@ -656,9 +638,8 @@ void QmlScriptParser::clear()
}
_nameSpacePaths.clear();
_typeNames.clear();
- _error.clear();
+ _errors.clear();
_scriptFile.clear();
- _errorLine = 0;
}
int QmlScriptParser::findOrCreateTypeId(const QString &name)
diff --git a/src/declarative/qml/qmlscriptparser_p.h b/src/declarative/qml/qmlscriptparser_p.h
index 0d89268..4155bba 100644
--- a/src/declarative/qml/qmlscriptparser_p.h
+++ b/src/declarative/qml/qmlscriptparser_p.h
@@ -3,6 +3,7 @@
#include <QtCore/QList>
#include <QtCore/QUrl>
+#include <QtDeclarative/qmlerror.h>
#include <qml.h>
QT_BEGIN_HEADER
@@ -23,8 +24,6 @@ public:
~QmlScriptParser();
bool parse(const QByteArray &data, const QUrl &url = QUrl());
- QString errorDescription() const;
- int errorLine() const;
QMap<QString,QString> nameSpacePaths() const;
QStringList types() const;
@@ -33,6 +32,8 @@ public:
void clear();
+ QList<QmlError> errors() const;
+
// ### private:
int findOrCreateTypeId(const QString &name);
void setTree(QmlParser::Object *tree);
@@ -42,12 +43,12 @@ public:
void addNamespacePath(const QString &path);
-private:
+// ### private:
+ QList<QmlError> _errors;
+
QMap<QString,QString> _nameSpacePaths;
QmlParser::Object *root;
QStringList _typeNames;
- QString _error;
- int _errorLine;
QString _scriptFile;
};
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
index e6235e4..ad3d1d5 100644
--- a/src/declarative/qml/qmlvme.cpp
+++ b/src/declarative/qml/qmlvme.cpp
@@ -176,9 +176,14 @@ QmlVME::QmlVME()
#define VME_EXCEPTION(desc) \
{ \
- exceptionLine = instr.line; \
- QDebug d(&exceptionDescription); \
- d << desc; \
+ QString str; \
+ QDebug d(&str); \
+ d << desc; \
+ QmlError error; \
+ error.setDescription(str); \
+ error.setLine(instr.line); \
+ error.setUrl(comp->url); \
+ vmeErrors << error; \
break; \
}
@@ -224,6 +229,8 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in
QStack<QmlMetaProperty> pushedProperties;
QObject **savedObjects = 0;
+ vmeErrors.clear();
+
if (start == -1) start = 0;
if (count == -1) count = comp->bytecode.count();
@@ -270,27 +277,6 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in
}
break;
- case QmlInstruction::CreateCustomObject:
- {
-#ifdef Q_ENABLE_PERFORMANCE_LOG
- QFxCompilerTimer<QFxCompiler::InstrCreateCustomObject> cc;
-#endif
- QVariant v =
- types.at(instr.createCustom.type).parser->create(datas.at(instr.createCustom.data));
- // XXX
- QObject *o = QmlMetaType::toQObject(v);
- if (!o)
- VME_EXCEPTION("Unable to create" << types.at(instr.create.type).className);
- QmlEngine::setContextForObject(o, QmlContext::activeContext());
-
- if (!stack.isEmpty()) {
- QObject *parent = stack.top();
- o->setParent(parent);
- }
- stack.push(o);
- }
- break;
-
case QmlInstruction::SetId:
{
#ifdef Q_ENABLE_PERFORMANCE_LOG
@@ -1072,17 +1058,12 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in
bool QmlVME::isError() const
{
- return exceptionLine != -1;
-}
-
-qint64 QmlVME::errorLine() const
-{
- return exceptionLine;
+ return !vmeErrors.isEmpty();
}
-QString QmlVME::errorDescription() const
+QList<QmlError> QmlVME::errors() const
{
- return exceptionDescription;
+ return vmeErrors;
}
void QmlVME::runStoreInstruction(QStack<QObject *> &stack,
diff --git a/src/declarative/qml/qmlvme_p.h b/src/declarative/qml/qmlvme_p.h
index 2a3be06..86cd040 100644
--- a/src/declarative/qml/qmlvme_p.h
+++ b/src/declarative/qml/qmlvme_p.h
@@ -44,6 +44,7 @@
#include <QString>
#include <QStack>
+#include <qmlerror.h>
class QObject;
QT_BEGIN_NAMESPACE
@@ -60,13 +61,13 @@ public:
QObject *run(QmlContext *, QmlCompiledComponent *, int start = -1, int end = -1);
bool isError() const;
- qint64 errorLine() const;
- QString errorDescription() const;
+ QList<QmlError> errors() const;
private:
void runStoreInstruction(QStack<QObject *> &stack,
QmlInstruction &, QmlCompiledData *);
+ QList<QmlError> vmeErrors;
qint64 exceptionLine;
QString exceptionDescription;
};
diff --git a/src/declarative/qml/qmlxmlparser.cpp b/src/declarative/qml/qmlxmlparser.cpp
deleted file mode 100644
index 35d2c0e..0000000
--- a/src/declarative/qml/qmlxmlparser.cpp
+++ /dev/null
@@ -1,391 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qmlxmlparser_p.h"
-#include "qmlcustomparser_p.h"
-#include <qfxperf.h>
-#include <QXmlStreamReader>
-#include <QStack>
-#include "qmlparser_p.h"
-#include <private/qmlparser_p.h>
-#include <QtCore/qdebug.h>
-
-QT_BEGIN_NAMESPACE
-using namespace QmlParser;
-
-struct QmlXmlParserState {
- QmlXmlParserState() : object(0), property(0) {}
- QmlXmlParserState(Object *o) : object(o), property(0) {}
- QmlXmlParserState(Object *o, Property *p) : object(o), property(p) {}
-
- Object *object;
- Property *property;
-};
-
-struct QmlXmlParserStateStack : public QStack<QmlXmlParserState>
-{
- void pushObject(Object *obj)
- {
- push(QmlXmlParserState(obj));
- }
-
- void pushProperty(const QString &name, int lineNumber)
- {
- const QmlXmlParserState &state = top();
- if (state.property) {
- QmlXmlParserState s(state.property->getValue(),
- state.property->getValue()->getProperty(name.toLatin1()));
- s.property->line = lineNumber;
- push(s);
- } else {
- QmlXmlParserState s(state.object,
- state.object->getProperty(name.toLatin1()));
- s.property->line = lineNumber;
- push(s);
- }
- }
-};
-
-QmlXmlParser::~QmlXmlParser()
-{
- if (root)
- root->release();
-}
-
-QmlXmlParser::QmlXmlParser()
-: root(0)
-{
-}
-
-static QString flatXml(QXmlStreamReader& reader)
-{
- QString result;
- int depth=0;
- QStringRef ns = reader.namespaceUri();
- while (depth>=0) {
- switch (reader.tokenType()) {
- case QXmlStreamReader::StartElement:
- result += QLatin1Char('<');
- result += reader.name();
- if (reader.namespaceUri() != ns || depth==0) {
- result += QLatin1String(" xmlns=\"");
- result += reader.namespaceUri();
- result += QLatin1Char('"');
- }
- foreach(QXmlStreamAttribute attr, reader.attributes()) {
- result += QLatin1Char(' ');
- result += attr.name();
- result += QLatin1String("=\"");
- result += attr.value(); // XXX escape
- result += QLatin1Char('"');
- }
- result += QLatin1Char('>');
- ++depth;
- break;
- case QXmlStreamReader::EndElement:
- result += QLatin1String("</");
- result += reader.name();
- result += QLatin1Char('>');
- --depth;
- break;
- case QXmlStreamReader::Characters:
- result += reader.text();
- break;
- default:
- reader.raiseError(QLatin1String("Only StartElement, EndElement, and Characters permitted"));
- break;
- }
- if (depth>=0)
- reader.readNext();
- }
- return result;
-}
-
-bool QmlXmlParser::parse(const QByteArray &data, const QUrl &url)
-{
-#ifdef Q_ENABLE_PERFORMANCE_LOG
- QFxPerfTimer<QFxPerf::XmlParsing> pt;
-#endif
-
- QString fileDisplayName;
- if (url.isEmpty()) {
- fileDisplayName = QLatin1String("<unspecified file>");
- } else if (url.scheme() == QLatin1String("file")) {
- fileDisplayName = url.toLocalFile();
- } else {
- fileDisplayName = url.toString();
- }
- if (data.isEmpty()) {
- _error = QLatin1String("No Qml was specified for parsing @") + fileDisplayName;
- return false;
- }
-
- QmlXmlParserStateStack states;
-
- QXmlStreamReader reader;
- reader.addData(data);
-
- while(!reader.atEnd()) {
- switch(reader.readNext()) {
- case QXmlStreamReader::Invalid:
- case QXmlStreamReader::NoToken:
- case QXmlStreamReader::StartDocument:
- case QXmlStreamReader::EndDocument:
- break;
-
- case QXmlStreamReader::StartElement:
- {
- QString name = reader.name().toString();
- QString nameSpace = reader.namespaceUri().toString();
- int line = reader.lineNumber();
- bool isType = name.at(0).isUpper() && !name.contains(QLatin1Char('.'));
- QString qualifiedname;
- if (!nameSpace.isEmpty()) {
- qualifiedname = nameSpace;
- qualifiedname += QLatin1Char('/');
- }
- qualifiedname += name;
- QByteArray qualifiednameL1 = qualifiedname.toLatin1();
- QXmlStreamAttributes attrs = reader.attributes();
-
- if (isType) {
- // Class
- int typeId = _typeNames.indexOf(qualifiedname);
- if (typeId == -1) {
- typeId = _typeNames.count();
- _typeNames.append(qualifiedname);
- }
-
- Object *obj = new Object;
- obj->type = typeId;
- obj->typeName = qualifiednameL1;
- obj->line = line;
-
- QmlCustomParser *customparser = QmlMetaType::customParser(qualifiednameL1);
- if (customparser) {
- bool ok;
- obj->custom = customparser->compile(reader, &ok);
- if (reader.tokenType() != QXmlStreamReader::EndElement) {
- reader.raiseError(QLatin1String("Parser for ") + qualifiedname + QLatin1String(" did not end on end element"));
- ok = false;
- }
- if (!ok) {
- delete obj;
- break;
- }
- }
-
-
- if (!root) {
- root = obj;
- states.pushObject(obj);
- } else {
- const QmlXmlParserState &state = states.top();
- Value *v = new Value;
- v->object = obj;
- v->line = line;
- if (state.property)
- state.property->addValue(v);
- else
- state.object->getDefaultProperty()->addValue(v);
- states.pushObject(obj);
- }
- } else {
- // Property
- if (!root) {
- reader.raiseError(QLatin1String("Can't have a property with no object"));
- break;
- }
- QStringList str = name.split(QLatin1Char('.'));
- for (int ii = 0; ii < str.count(); ++ii) {
- QString s = str.at(ii);
- states.pushProperty(s, line);
- }
- if (!nameSpace.isEmpty()) {
- // Pass non-QML as flat text property value
- const QmlXmlParserState &state = states.top();
- Value *v = new Value;
- v->primitive = flatXml(reader);
- v->line = line;
- state.property->addValue(v);
- }
- }
-
- // (even custom parsed content gets properties set)
- foreach(QXmlStreamAttribute attr, attrs) {
- QStringList str = attr.name().toString().split(QLatin1Char('.'));
-
- for (int ii = 0; ii < str.count(); ++ii) {
- QString s = str.at(ii);
- states.pushProperty(s, line);
- }
-
- const QmlXmlParserState &state = states.top();
- Value *v = new Value;
- v->primitive = attr.value().toString();
- v->line = reader.lineNumber();
- state.property->addValue(v);
-
- for (int ii = str.count() - 1; ii >= 0; --ii)
- states.pop();
- }
- }
-
- // Custom parsers and namespaced properties move
- // the reader to the end element, so we handle that
- // BEFORE continuing.
- //
- if (reader.tokenType()!=QXmlStreamReader::EndElement)
- break;
- // ELSE fallthrough to EndElement...
- case QXmlStreamReader::EndElement:
- {
- QString name = reader.name().toString();
- Q_ASSERT(!name.isEmpty());
- if (name.at(0).isUpper() && !name.contains(QLatin1Char('.'))) {
- // Class
- states.pop();
- } else {
- // Property
- QStringList str = name.split(QLatin1Char('.'));
- for (int ii = 0; ii < str.count(); ++ii)
- states.pop();
- }
- }
- break;
- case QXmlStreamReader::Characters:
- if (!reader.isWhitespace()) {
- const QmlXmlParserState &state = states.top();
- Value *v = new Value;
- v->primitive = reader.text().toString();
- v->line = reader.lineNumber();
- if (state.property)
- state.property->addValue(v);
- else
- state.object->getDefaultProperty()->addValue(v);
- }
- break;
-
- case QXmlStreamReader::Comment:
- case QXmlStreamReader::DTD:
- case QXmlStreamReader::EntityReference:
- break;
- case QXmlStreamReader::ProcessingInstruction:
- if (reader.processingInstructionTarget() == QLatin1String("qtfx")) {
- QString str = reader.processingInstructionData().toString();
- QString token, data;
- int idx = str.indexOf(QLatin1Char(':'));
- if (-1 != idx) {
- token = str.left(idx);
- data = str.mid(idx + 1);
- } else {
- token = str;
- }
- token = token.trimmed();
- data = data.trimmed();
-
- // <?qtfx namespacepath: namespace=path>
-
- if (token == QLatin1String("namespacepath")) {
- int eq=data.indexOf(QLatin1Char('='));
- if (eq>=0) {
- _nameSpacePaths.insertMulti(data.left(eq),data.mid(eq+1));
- }
- } else {
- str = str.trimmed();
- qWarning().nospace() << "Unknown processing instruction " << str.toLatin1().constData() << " @" << fileDisplayName.toLatin1().constData() << ":" << reader.lineNumber();
- }
- }
- break;
- }
- }
-
- if (reader.hasError()) {
- if (root) {
- root->release();
- root = 0;
- }
- _error = reader.errorString() + QLatin1String(" @") + fileDisplayName +
- QLatin1String(":") + QString::number(reader.lineNumber());
- }
-
- return root != 0;
-}
-
-QMap<QString,QString> QmlXmlParser::nameSpacePaths() const
-{
- return _nameSpacePaths;
-}
-
-QStringList QmlXmlParser::types() const
-{
- return _typeNames;
-}
-
-QmlParser::Object *QmlXmlParser::tree() const
-{
- return root;
-}
-
-QmlParser::Object *QmlXmlParser::takeTree()
-{
- QmlParser::Object *r = root;
- root = 0;
- return r;
-}
-
-QString QmlXmlParser::errorDescription() const
-{
- return _error;
-}
-
-void QmlXmlParser::clear()
-{
- if (root) {
- root->release();
- root = 0;
- }
- _nameSpacePaths.clear();
- _typeNames.clear();
- _error.clear();
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/util/qfxview.cpp b/src/declarative/util/qfxview.cpp
index cac73a0..f71b87e 100644
--- a/src/declarative/util/qfxview.cpp
+++ b/src/declarative/util/qfxview.cpp
@@ -233,8 +233,6 @@ QmlContext* QFxView::rootContext()
*/
void QFxView::execute()
{
- rootContext()->activate();
-
if (d->qml.isEmpty()) {
d->component = new QmlComponent(&d->engine, d->source, this);
} else {
@@ -249,6 +247,45 @@ void QFxView::execute()
}
/*!
+ \internal
+*/
+void QFxView::printErrorLine(const QmlError &error)
+{
+ QUrl url = error.url();
+ if (error.line() > 0 && error.column() > 0 &&
+ url.scheme() == QLatin1String("file")) {
+ QString file = url.toLocalFile();
+ QFile f(file);
+ if (f.open(QIODevice::ReadOnly)) {
+ QByteArray data = f.readAll();
+ QTextStream stream(data, QIODevice::ReadOnly);
+ const QString code = stream.readAll();
+ const QStringList lines = code.split(QLatin1Char('\n'));
+
+ if (lines.count() >= error.line()) {
+ const QString &line = lines.at(error.line() - 1);
+ qWarning() << qPrintable(line);
+
+ int column = qMax(0, error.column() - 1);
+ column = qMin(column, line.length());
+
+ QByteArray ind;
+ ind.reserve(column);
+ for (int i = 0; i < column; ++i) {
+ const QChar ch = line.at(i);
+ if (ch.isSpace())
+ ind.append(ch.unicode());
+ else
+ ind.append(' ');
+ }
+ ind.append('^');
+ qWarning() << ind.constData();
+ }
+ }
+ }
+}
+
+/*!
\internal
*/
void QFxView::continueExecute()
@@ -260,8 +297,26 @@ void QFxView::continueExecute()
return;
}
+ if(d->component->isError()) {
+ QList<QmlError> errors = d->component->errors();
+ foreach (const QmlError &error, errors) {
+ qWarning() << error;
+ }
+
+ return;
+ }
+
QObject *obj = d->component->create();
- rootContext()->deactivate();
+
+ if(d->component->isError()) {
+ QList<QmlError> errors = d->component->errors();
+ foreach (const QmlError &error, errors) {
+ qWarning() << error;
+ }
+
+ return;
+ }
+
if (obj) {
if (QFxItem *item = qobject_cast<QFxItem *>(obj)) {
item->QSimpleCanvasItem::setParent(QSimpleCanvas::root());
@@ -330,7 +385,25 @@ QFxItem* QFxView::addItem(const QString &qml, QFxItem* parent)
return 0;
QmlComponent component(&d->engine, qml.toUtf8(), QUrl());
+ if(d->component->isError()) {
+ QList<QmlError> errors = d->component->errors();
+ foreach (const QmlError &error, errors) {
+ qWarning() << error;
+ }
+
+ return 0;
+ }
+
QObject *obj = component.create();
+ if(d->component->isError()) {
+ QList<QmlError> errors = d->component->errors();
+ foreach (const QmlError &error, errors) {
+ qWarning() << error;
+ }
+
+ return 0;
+ }
+
if (obj){
QFxItem *item = static_cast<QFxItem *>(obj);
if (!parent)
diff --git a/src/declarative/util/qfxview.h b/src/declarative/util/qfxview.h
index d2cacf4..f575f27 100644
--- a/src/declarative/util/qfxview.h
+++ b/src/declarative/util/qfxview.h
@@ -57,7 +57,7 @@ QT_MODULE(Declarative)
class QFxItem;
class QmlEngine;
class QmlContext;
-class Canvas;
+class QmlError;
class QFxViewPrivate;
class Q_DECLARATIVE_EXPORT QFxView : public QSimpleCanvas
@@ -84,6 +84,7 @@ public:
void dumpRoot();
+ static void printErrorLine(const QmlError &);
Q_SIGNALS:
void sceneResized(QSize size);
diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp
index 4837180..6ad0cb9 100644
--- a/src/declarative/util/qmllistmodel.cpp
+++ b/src/declarative/util/qmllistmodel.cpp
@@ -190,8 +190,6 @@ ModelObject::ModelObject(ModelNode *node)
{
}
-QML_DECLARE_TYPE(ListModel);
-QML_DEFINE_TYPE(ListModel,ListModel);
ListModel::ListModel(QObject *parent)
: QListModelInterface(parent), _rolesOk(false), _root(0)
{
@@ -304,14 +302,10 @@ int ListModel::count() const
class ListModelParser : public QmlCustomParser
{
public:
- virtual QByteArray compile(QXmlStreamReader& reader, bool *);
QByteArray compile(const QList<QmlCustomParserProperty> &, bool *ok);
- virtual QVariant create(const QByteArray &);
-
bool compileProperty(const QmlCustomParserProperty &prop, QList<ListInstruction> &instr, QByteArray &data);
void setCustomData(QObject *, const QByteArray &);
};
-QML_DEFINE_CUSTOM_PARSER(ListModel, ListModelParser);
bool ListModelParser::compileProperty(const QmlCustomParserProperty &prop, QList<ListInstruction> &instr, QByteArray &data)
{
@@ -462,13 +456,10 @@ void ListModelParser::setCustomData(QObject *obj, const QByteArray &d)
}
}
-class ListModel2 : public ListModel
-{
-Q_OBJECT
-};
-QML_DECLARE_TYPE(ListModel2);
-QML_DEFINE_CUSTOM_TYPE(ListModel2, ListModel2, ListModelParser);
+QML_DECLARE_TYPE(ListModel);
+QML_DEFINE_CUSTOM_TYPE(ListModel, ListModel, ListModelParser);
+// ### FIXME
class ListElement : public QObject
{
Q_OBJECT
@@ -512,170 +503,5 @@ ModelNode::~ModelNode()
if (modelCache) { delete modelCache; modelCache = 0; }
}
-QByteArray ListModelParser::compile(QXmlStreamReader& reader, bool *ok)
-{
- *ok = true;
-
- QByteArray data;
- QList<ListInstruction> instr;
- int depth=0;
-
- while(!reader.atEnd() && depth >= 0) {
- switch(reader.readNext()) {
- case QXmlStreamReader::StartElement:
- {
- QStringRef name = reader.name();
- bool isType = name.at(0).isUpper();
-
- if (isType) {
- ListInstruction li;
- li.type = ListInstruction::Push;
- li.dataIdx = -1;
- instr << li;
-
- for (int i = 0; i < reader.attributes().count(); ++i) {
- const QXmlStreamAttribute &attr = reader.attributes().at(i);
- QStringRef attrName = attr.name();
- QStringRef attrValue = attr.value();
-
- ListInstruction li;
- int ref = data.count();
- data.append(attrName.toString().toLatin1());
- data.append('\0');
- li.type = ListInstruction::Set;
- li.dataIdx = ref;
- instr << li;
-
- ref = data.count();
- data.append(attrValue.toString().toLatin1());
- data.append('\0');
- li.type = ListInstruction::Value;
- li.dataIdx = ref;
- instr << li;
-
- li.type = ListInstruction::Pop;
- li.dataIdx = -1;
- instr << li;
- }
- } else {
- ListInstruction li;
- int ref = data.count();
- data.append(name.toString().toLatin1());
- data.append('\0');
- li.type = ListInstruction::Set;
- li.dataIdx = ref;
- instr << li;
- }
- }
- ++depth;
- break;
- case QXmlStreamReader::EndElement:
- {
- ListInstruction li;
- li.type = ListInstruction::Pop;
- li.dataIdx = -1;
- instr << li;
- --depth;
- }
- break;
- case QXmlStreamReader::Characters:
- if (!reader.isWhitespace()) {
- int ref = data.count();
- QByteArray d = reader.text().toString().toLatin1();
- d.append('\0');
- data.append(d);
-
- ListInstruction li;
- li.type = ListInstruction::Value;
- li.dataIdx = ref;
- instr << li;
- }
- break;
-
- case QXmlStreamReader::Invalid:
- case QXmlStreamReader::NoToken:
- case QXmlStreamReader::StartDocument:
- case QXmlStreamReader::EndDocument:
- case QXmlStreamReader::Comment:
- case QXmlStreamReader::DTD:
- case QXmlStreamReader::EntityReference:
- case QXmlStreamReader::ProcessingInstruction:
- break;
- }
- }
-
- if (reader.hasError())
- *ok = true;
-
- if (!*ok)
- return QByteArray();
-
- int size = sizeof(ListModelData) +
- instr.count() * sizeof(ListInstruction) +
- data.count();
-
- QByteArray rv;
- rv.resize(size);
-
- ListModelData *lmd = (ListModelData *)rv.data();
- lmd->dataOffset = sizeof(ListModelData) +
- instr.count() * sizeof(ListInstruction);
- lmd->instrCount = instr.count();
- for (int ii = 0; ii < instr.count(); ++ii)
- lmd->instructions()[ii] = instr.at(ii);
- ::memcpy(rv.data() + lmd->dataOffset, data.constData(), data.count());
-
- return rv;
-}
-
-QVariant ListModelParser::create(const QByteArray &d)
-{
- ListModel *rv = new ListModel;
- ModelNode *root = new ModelNode;
- rv->_root = root;
- QStack<ModelNode *> nodes;
- nodes << root;
-
- const ListModelData *lmd = (const ListModelData *)d.constData();
- const char *data = ((const char *)lmd) + lmd->dataOffset;
-
- for (int ii = 0; ii < lmd->instrCount; ++ii) {
- const ListInstruction &instr = lmd->instructions()[ii];
-
- switch(instr.type) {
- case ListInstruction::Push:
- {
- ModelNode *n = nodes.top();
- ModelNode *n2 = new ModelNode;
- n->values << qVariantFromValue(n2);
- nodes.push(n2);
- }
- break;
-
- case ListInstruction::Pop:
- nodes.pop();
- break;
-
- case ListInstruction::Value:
- {
- ModelNode *n = nodes.top();
- n->values.append(QByteArray(data + instr.dataIdx));
- }
- break;
-
- case ListInstruction::Set:
- {
- ModelNode *n = nodes.top();
- ModelNode *n2 = new ModelNode;
- n->properties.insert(QLatin1String(data + instr.dataIdx), n2);
- nodes.push(n2);
- }
- break;
- }
- }
-
- return QVariant::fromValue(rv);
-}
-
QT_END_NAMESPACE
#include "qmllistmodel.moc"
diff --git a/tools/qdoc3/helpprojectwriter.cpp b/tools/qdoc3/helpprojectwriter.cpp
index 85bd898..16ee5f2 100644
--- a/tools/qdoc3/helpprojectwriter.cpp
+++ b/tools/qdoc3/helpprojectwriter.cpp
@@ -126,6 +126,9 @@ void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList
subTypeHash["module"] = Node::Module;
subTypeHash["page"] = Node::Page;
subTypeHash["externalpage"] = Node::ExternalPage;
+#ifdef QDOC_QML
+ subTypeHash["qmlclass"] = Node::QmlClass;
+#endif
QSet<Node::SubType> allSubTypes = QSet<Node::SubType>::fromList(subTypeHash.values());
diff --git a/tools/qdoc3/test/qml.qdocconf b/tools/qdoc3/test/qml.qdocconf
new file mode 100644
index 0000000..3a7d76a
--- /dev/null
+++ b/tools/qdoc3/test/qml.qdocconf
@@ -0,0 +1,77 @@
+include(compat.qdocconf)
+include(macros.qdocconf)
+include(qt-cpp-ignore.qdocconf)
+include(qt-html-templates.qdocconf)
+include(qt-defines.qdocconf)
+
+project = Qml
+description = Qml Reference Documentation
+url = http://doc.qtsoftware.com/4.6
+
+edition.Console.modules = QtCore QtDBus QtNetwork QtScript QtSql QtXml \
+ QtXmlPatterns QtTest
+edition.Desktop.modules = QtCore QtDBus QtGui QtNetwork QtOpenGL QtScript QtSql QtSvg \
+ QtWebKit QtXml QtXmlPatterns Qt3Support QtHelp \
+ QtDesigner QtAssistant QAxContainer Phonon \
+ QAxServer QtUiTools QtTest QtDBus
+edition.DesktopLight.modules = QtCore QtDBus QtGui Qt3SupportLight QtTest
+edition.DesktopLight.groups = -graphicsview-api
+
+qhp.projects = Qml
+
+qhp.Qml.file = qml.qhp
+qhp.Qml.namespace = com.trolltech.qml.460
+qhp.Qml.virtualFolder = qdoc
+qhp.Qml.indexTitle = Qml Reference
+
+# Files not referenced in any qdoc file
+# See also extraimages.HTML
+qhp.Qml.extraFiles = classic.css \
+ images/qt-logo.png
+
+qhp.Qml.filterAttributes = qt 4.6.0 qtrefdoc
+qhp.Qml.customFilters.Qt.name = Qt 4.6.0
+qhp.Qml.customFilters.Qt.filterAttributes = qt 4.6.0
+qhp.Qml.subprojects = classes
+qhp.Qml.subprojects.classes.title = Elements
+qhp.Qml.subprojects.classes.indexTitle = Qml Elements
+qhp.Qml.subprojects.classes.selectors = fake:qmlclass
+qhp.Qml.subprojects.classes.sortPages = true
+
+language = Cpp
+
+headerdirs = $QT_SOURCE_TREE/src/declarative
+sourcedirs = $QT_SOURCE_TREE/src/declarative \
+ $QT_SOURCE_TREE/doc/src/declarative
+
+sources += $QT_SOURCE_TREE/doc/src/tutorials/declarative.qdoc
+
+sources.fileextensions = "*.cpp *.qdoc"
+examples.fileextensions = "*.cpp *.h *.js *.qml"
+
+exampledirs = $QT_SOURCE_TREE/doc/src \
+ $QT_SOURCE_TREE/examples \
+ $QT_SOURCE_TREE/examples/tutorials \
+ $QT_SOURCE_TREE \
+ $QT_SOURCE_TREE/qmake/examples \
+ $QT_SOURCE_TREE/src/3rdparty/webkit/WebKit/qt/docs
+imagedirs = $QT_SOURCE_TREE/doc/src/images \
+ $QT_SOURCE_TREE/examples \
+ $QT_SOURCE_TREE/doc/src/declarative/pics
+outputdir = $QT_BUILD_TREE/doc-build/html-qml
+tagfile = $QT_BUILD_TREE/doc-build/html-qml/qt.tags
+base = file:$QT_BUILD_TREE/doc/html-qml
+
+HTML.stylesheets = classic.css
+
+HTML.postheader = "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n" \
+ "<tr>\n" \
+ "<td align=\"left\" valign=\"top\">" \
+ "<img src=\"images/qt-logo.png\" align=\"left\" border=\"0\"/>" \
+ "</td>\n" \
+ "<td width=\"1\">&nbsp;&nbsp;</td>" \
+ "<td class=\"postheader\" valign=\"center\" align=\"left\">" \
+ "<a href=\"qmlreference.html\">" \
+ "<font color=\"#004faf\">Home</font></a>" \
+ "</td>\n" \
+ "</tr></table>"
diff --git a/tools/qdoc3/tree.cpp b/tools/qdoc3/tree.cpp
index 539db51..b91de65 100644
--- a/tools/qdoc3/tree.cpp
+++ b/tools/qdoc3/tree.cpp
@@ -1901,9 +1901,14 @@ QString Tree::fullDocumentLocation(const Node *node) const
else
return "";
}
- else if (node->type() == Node::Fake)
+ else if (node->type() == Node::Fake) {
+#ifdef QDOC_QML
+ if (node->subType() == Node::QmlClass)
+ return "qml-" + node->fileBase() + ".html";
+ else
+#endif
return node->fileBase() + ".html";
- else if (node->fileBase().isEmpty())
+ } else if (node->fileBase().isEmpty())
return "";
QString parentName;
diff --git a/tools/qmlconv/qmlconv.cpp b/tools/qmlconv/qmlconv.cpp
deleted file mode 100644
index 6e89530..0000000
--- a/tools/qmlconv/qmlconv.cpp
+++ /dev/null
@@ -1,482 +0,0 @@
-#include <QtCore/QCoreApplication>
-#include <QtCore/QFile>
-#include <QtCore/QXmlStreamReader>
-#include <QtCore/QStack>
-#include <QtCore/QStringList>
-#include <QtCore/QDebug>
-
-
-static bool optionInPlace = false;
-
-class Reader
-{
- QString outString;
- QTextStream out;
- QXmlStreamReader xml;
- int depth;
- bool supressIndent;
-
- QStringList knownListProperties;
- inline QString depthString() {if (supressIndent) { supressIndent = false; return QString(); }
- return QString(depth*4, QLatin1Char(' '));}
-
-public:
- Reader(QIODevice *in)
- :xml(in) {
-
- knownListProperties << "states" << "transitions" << "children" << "resources"
- << "transform" << "notes";
- depth = 0;
- supressIndent = false;
-
- out.setString(&outString);
-
- loop();
-
- out.flush();
-
- if (! optionInPlace) {
- QTextStream print(stdout);
- print << outString;
- }
- }
-
- QString output() const
- {
- return outString;
- }
-
- void comment()
- {
- if (xml.isComment()) {
- out << depthString() << "// "
- << xml.text().toString().trimmed().replace(QRegExp("\n\\s*"),"\n"+depthString()+"// ")
- << endl;
- }
- }
-
- void emptyLoop() {
- while (!xml.atEnd()) {
- xml.readNext();
- comment();
- if (xml.tokenType() == QXmlStreamReader::EndElement)
- return;
- }
- }
-
- void loop()
- {
- while (!xml.atEnd()) {
- xml.readNext();
- if (xml.tokenType() == QXmlStreamReader::EndElement)
- return;
- else if (xml.tokenType() == QXmlStreamReader::StartElement)
- startElement();
- else if (xml.tokenType() == QXmlStreamReader::ProcessingInstruction) {
- if (xml.processingInstructionTarget() == QLatin1String("qtfx")) {
- QString data = xml.processingInstructionData().toString().trimmed();
- if (data.startsWith(QLatin1String("namespacepath:="))) {
- outString.prepend( QLatin1String("import \"") + data.mid(data.indexOf(QLatin1Char('='))+1) + QLatin1String("\"\n"));
- }
- }
- }
- comment();
- }
- }
-
- void startElement() {
-
- if (!propertyChangeSet.isEmpty()
- && xml.name() != "SetProperties"
- && xml.name() != "SetProperty") {
- clearPropertyChangeSet();
- }
-
- if (false && xml.name() == "properties")
- startDeclareProperties();
- else if (false && xml.name() == "signals")
- startDeclareSignals();
- else if (false && xml.name() == "states")
- loop(); // ignore
- else if (false && xml.name() == "transitions")
- loop(); // ignore
- else if (knownListProperties.contains(xml.name().toString()))
- startList();
- else if (false && xml.name() == "SetProperties")
- startSetProperties();
- else if (false && xml.name() == "SetProperty")
- startSetProperty();
- else if (false && xml.name() == "ParentChange")
- startParentChange();
- else if (true && xml.name() == "Connection")
- startConnection();
- else if (false && xml.name() == "Script")
- startScript();
- else if (xml.name().at(0).isLower() && xml.attributes().isEmpty())
- startObjectProperty();
- else
- startItem();
- }
-
- static void possiblyRemoveBraces(QString *s) {
- if (s->startsWith('{') && s->endsWith('}'))
- *s = s->mid(1, s->length() - 2);
- }
-
- static bool isNumber(const QString &s) {
- bool ok = true;
- s.toFloat(&ok);
- return ok;
- }
-
- static bool isSignalHandler(const QString &s) {
- return s.size() > 3
- && s.startsWith("on")
- && s.at(2).isUpper();
- }
-
- static bool isEnum(const QString &property, const QString &value) {
- return !value.contains(' ') && (property == "vAlign" || property == "hAlign"
- || property == "style");
- }
-
- static bool isIdentifier(const QString &s) {
- if (s.isEmpty())
- return false;
- if (!s.at(1).isLetter())
- return false;
- for (int i = 1; i < s.size(); ++i) {
- QChar c = s.at(i);
- if (c.isLetterOrNumber()
- || c == QLatin1Char('_')
- || c == QLatin1Char('-'))
- continue;
- return false;
- }
- return true;
- }
-
-
- void setProperty(const QString &property, const QString &value, bool newline = true) {
- QString v = value.trimmed();
- if (v.startsWith('{')) {
- possiblyRemoveBraces(&v);
- } else if (v == "true"
- || v == "false"
- || isNumber(v)
- || property == "id"
- || isEnum(property, value)
- ) {
- ;
- } else if (isSignalHandler(property)) {
- // if not a function name, create an anonymous function
- if (!isIdentifier(v)) {
- v.prepend("{ ");
- v.append(" }");
- }
- } else
-
- // if (property == "text" || property == "name" || value.contains(' ')
- // || value.contains("/") || value.startsWith('#')
- // || property == "filename" || property == "source" || property == "src"
- // || property == "title" || property == "movieTitle" || property == "movieDescription"
- // || property == "properties" || property == "fromState" || property == "toState"
- // )
- {
- v.prepend('\"');
- v.append('\"');
- }
-
-// QByteArray semiColon = ";";
-// if (v.endsWith(QLatin1Char('}')) || v.endsWith(QLatin1Char(';')))
-// semiColon.clear();
-
- if (!newline)
- out << property << ": " << v /* << semiColon.constData() */;
- else
- out << depthString() << property << ": " << v /* << semiColon.constData() */ << endl;
- }
-
-
- typedef QPair<QString,QString> StringPair;
- QList<StringPair> propertyChangeSet;
- void startItem(bool inList = false) {
-
- QString name = xml.name().toString();
-
- out << depthString() << name << " {" << endl;
- ++depth;
-
- foreach (QXmlStreamAttribute attribute, xml.attributes()) {
- setProperty(attribute.name().toString(), attribute.value().toString());
- }
-
- if (name == "Script") {
- QString text = xml.readElementText();
- if (!text.trimmed().isEmpty()) {
- out << text << endl;
- }
- } else {
- loop();
- }
-
- if (name == "State")
- clearPropertyChangeSet();
-
- --depth;
- out << depthString() << "}";
- if (!inList)
- out << endl;
- }
-
- void clearPropertyChangeSet() {
- if (propertyChangeSet.isEmpty())
- return;
-
- out << depthString() << "PropertyChangeSet" << " {" << endl;
- ++depth;
- foreach(StringPair pair, propertyChangeSet)
- setProperty(pair.first, pair.second);
- --depth;
- out << depthString() << "}" << endl;
- propertyChangeSet.clear();
- }
-
- void startObjectProperty() {
-
- QString name = xml.name().toString();
- bool hasElements = false;
- while (!xml.atEnd()) {
- xml.readNext();
- if (xml.tokenType() == QXmlStreamReader::EndElement)
- break;
- if (xml.tokenType() == QXmlStreamReader::StartElement) {
- hasElements = true;
- out << depthString() << name << ": ";
- supressIndent = true;
- startElement();
- } else if (!hasElements && xml.tokenType() == QXmlStreamReader::Characters) {
- if (!xml.text().toString().trimmed().isEmpty()) {
- setProperty(name, xml.text().toString());
- }
- }
- comment();
- }
- }
-
- void startDeclareProperty() {
- out << depthString() << "public property ";
-
- if (xml.attributes().hasAttribute("type"))
- out << "/* " << xml.attributes().value("type").toString() << " */ ";
-
- QString name = xml.attributes().value("name").toString();
-
- if (xml.attributes().hasAttribute("value"))
- setProperty(name, xml.attributes().value("value").toString(), false);
- else out << name;
-
- QMap<QString, QString> attributes;
- foreach (QXmlStreamAttribute attribute, xml.attributes()) {
- if (attribute.name() == "name" || attribute.name() == "value")
- continue;
- attributes.insert(attribute.name().toString(), attribute.value().toString());
- }
- out << endl;
- emptyLoop();
- }
-
- void startDeclareProperties() {
- while (!xml.atEnd()) {
- xml.readNext();
- if (xml.tokenType() == QXmlStreamReader::EndElement)
- return;
- if (xml.tokenType() == QXmlStreamReader::StartElement) {
- if (xml.name() == "Property")
- startDeclareProperty();
- }
- comment();
- }
- }
-
- void startDeclareSignal() {
- out << depthString() << "public signal " << xml.attributes().value("name").toString() << endl;
- emptyLoop();
- }
-
- void startDeclareSignals() {
- while (!xml.atEnd()) {
- xml.readNext();
- if (xml.tokenType() == QXmlStreamReader::EndElement)
- return;
- if (xml.tokenType() == QXmlStreamReader::StartElement) {
- if (xml.name() == "Signal")
- startDeclareSignal();
- }
- comment();
- }
- }
-
-
- void startSetProperties() {
- QString target = xml.attributes().value("target").toString();
- possiblyRemoveBraces(&target);
- foreach (QXmlStreamAttribute attribute, xml.attributes()) {
- if (attribute.name() == "target")
- continue;
- propertyChangeSet += StringPair(target + "." + attribute.name().toString(), attribute.value().toString());
- }
- emptyLoop();
- }
-
- void startSetProperty() {
- QString target = xml.attributes().value("target").toString();
- possiblyRemoveBraces(&target);
- propertyChangeSet += StringPair(target + "." + xml.attributes().value("property").toString(),
- xml.attributes().value("value").toString());
-
- emptyLoop();
- }
-
- void startParentChange() {
- QString target = xml.attributes().value("target").toString();
- possiblyRemoveBraces(&target);
-
- out << depthString() << "ParentChangeSet" << " {" << endl;
- ++depth;
- setProperty(target + ".parent", xml.attributes().value("parent").toString());
- --depth;
- out << depthString() << "}" << endl;
-
-// propertyChangeSet += StringPair(target + ".moveToParent", xml.attributes().value("parent").toString());
-
- emptyLoop();
- }
-
- void startConnection() {
- QString sender = xml.attributes().value("sender").toString();
- possiblyRemoveBraces(&sender);
- out << depthString() << "Connection {" << endl;
- ++depth;
- if (! sender.isEmpty())
- out << depthString() << "sender: " << sender << endl;
- if (xml.attributes().hasAttribute("signal"))
- out << depthString() << "signal: \"" << xml.attributes().value("signal").toString() << '"' << endl;
- if (xml.attributes().hasAttribute("script")) {
- out << depthString() << "script: { " << xml.attributes().value("script").toString() << " }" << endl;
- --depth;
- out << depthString() << "}" << endl;
- } else {
- QString text;
- while (!xml.atEnd()) {
- xml.readNext();
- if (xml.tokenType() == QXmlStreamReader::EndElement)
- break;
- else if (xml.tokenType() == QXmlStreamReader::Characters)
- text.append(xml.text());
- }
-
- out << depthString() << "script: {" << endl;
- foreach (QString line, text.split(QLatin1Char('\n'))) {
- out << depthString() << line << endl;
- }
- out << depthString() << "}" << endl;
- --depth;
- out << depthString() << "}" << endl;
- }
- emptyLoop();
- }
-
- void startScript() {
- if (xml.attributes().hasAttribute(QLatin1String("src"))) {
- /*
- QString import;
- QTextStream ts(&import);
- ts << "import \"";
- ts << xml.attributes().value(QLatin1String("src")).toString();
- ts << "\"" << endl;
- ts.flush();
- outString.prepend(import);
- */
- }
- QString text = xml.readElementText();
- if (!text.trimmed().isEmpty()) {
- out << text << endl;
- }
- if (xml.tokenType() != QXmlStreamReader::EndElement)
- emptyLoop();
- }
-
- void startList()
- {
- out << depthString() << xml.name().toString() << ": [" << endl;
- ++depth;
- bool needComma = false;
-
- while (!xml.atEnd()) {
- xml.readNext();
- if (xml.tokenType() == QXmlStreamReader::EndElement)
- break;
- if (xml.tokenType() == QXmlStreamReader::StartElement) {
- if (needComma)
- out << "," << endl;
- startItem(true);
- needComma = true;
- }
- comment();
- }
-
- out << endl;
- --depth;
- out << depthString() << "]" << endl;
- }
-
-};
-
-
-
-int main(int argc, char *argv[])
-{
- QCoreApplication a(argc, argv);
-
- QStringList args = a.arguments();
- args.removeFirst();
-
- if (!args.isEmpty() && args.first() == QLatin1String("-i")) {
- optionInPlace = true;
- args.removeFirst();
- }
-
- if (args.isEmpty() && optionInPlace) {
- qWarning() << "Usage: qmlconv [ [-i] filename ]";
- exit(1);
- }
-
- const QString fileName = args.isEmpty() ? QString("-") : args.first();
-
- QFile file(fileName);
- if (fileName == "-") {
- file.open(0,QIODevice::ReadOnly);
- } else {
- if (! file.open(QIODevice::ReadOnly)) {
- qWarning() << "qmlconv: no input file";
- exit(1);
- }
- }
-
- Reader r(&file);
- file.close();
-
- if (optionInPlace) {
- if (! file.open(QFile::WriteOnly)) {
- qWarning() << "qmlconv: cannot open file" << qPrintable(fileName);
- exit(1);
- }
-
- QTextStream out(&file);
- out << r.output();
- file.close();
- }
-
- return 0;
-}
diff --git a/tools/qmlconv/qmlconv.pro b/tools/qmlconv/qmlconv.pro
deleted file mode 100644
index 331f4ee..0000000
--- a/tools/qmlconv/qmlconv.pro
+++ /dev/null
@@ -1,10 +0,0 @@
-DESTDIR = ../../bin
-QT -= gui
-# Input
-SOURCES += qmlconv.cpp
-
-target.path=$$[QT_INSTALL_BINS]
-INSTALLS += target
-
-CONFIG += console
-macx:CONFIG -= app_bundle
diff --git a/tools/qmlviewer/qmlviewer.cpp b/tools/qmlviewer/qmlviewer.cpp
index 3c52cfe..00cb7f1 100644
--- a/tools/qmlviewer/qmlviewer.cpp
+++ b/tools/qmlviewer/qmlviewer.cpp
@@ -85,6 +85,14 @@ void QmlViewer::openQml(const QString& fileName)
QmlComponent comp(canvas->engine());
comp.setData(data, QUrl());
QObject *dummyData = comp.create();
+
+ if(comp.isError()) {
+ QList<QmlError> errors = comp.errors();
+ foreach (const QmlError &error, errors) {
+ qWarning() << error;
+ }
+ }
+
if (dummyData) {
qWarning() << "Loaded dummy data:" << dir.filePath(qml);
qml.truncate(qml.length()-4);