summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brasser <michael.brasser@nokia.com>2009-10-11 22:48:10 (GMT)
committerMichael Brasser <michael.brasser@nokia.com>2009-10-11 22:48:10 (GMT)
commit76b29d542e13184da81129ea3f7373ffd71ceedc (patch)
treec18a7af8ae2f70d6fcda5b74cd00161241596beb
parentac507b4752dcd065038130d224910a6dc64f8f37 (diff)
parent76448b41bb9c6212d2534f0597f9973c881c77bd (diff)
downloadQt-76b29d542e13184da81129ea3f7373ffd71ceedc.zip
Qt-76b29d542e13184da81129ea3f7373ffd71ceedc.tar.gz
Qt-76b29d542e13184da81129ea3f7373ffd71ceedc.tar.bz2
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
-rw-r--r--examples/declarative/gridview/gridview.qml52
-rw-r--r--examples/declarative/listview/recipes.qml228
-rw-r--r--examples/declarative/snow/ImageBatch.qml4
-rw-r--r--examples/declarative/webview/newwindows.qml33
-rw-r--r--examples/declarative/xmldata/daringfireball.qml81
-rw-r--r--examples/declarative/xmldata/yahoonews.qml146
-rw-r--r--src/declarative/qml/qmlbinding.cpp4
-rw-r--r--src/declarative/qml/qmlbinding.h3
-rw-r--r--src/declarative/qml/qmlcompiler.cpp25
-rw-r--r--src/declarative/qml/qmlcontext.cpp31
-rw-r--r--src/declarative/qml/qmlcontext_p.h5
-rw-r--r--src/declarative/qml/qmlcontextscriptclass.cpp57
-rw-r--r--src/declarative/qml/qmlcontextscriptclass_p.h6
-rw-r--r--src/declarative/qml/qmlexpression.cpp58
-rw-r--r--src/declarative/qml/qmlexpression.h4
-rw-r--r--src/declarative/qml/qmlexpression_p.h4
-rw-r--r--src/declarative/qml/qmlinstruction_p.h2
-rw-r--r--src/declarative/qml/qmlmetaproperty.cpp30
-rw-r--r--src/declarative/qml/qmlmetaproperty_p.h2
-rw-r--r--src/declarative/qml/qmlparser_p.h2
-rw-r--r--src/declarative/qml/qmlpropertycache_p.h2
-rw-r--r--src/declarative/qml/qmlvme.cpp7
-rw-r--r--tests/auto/declarative/qmlecmascript/data/scope.2.qml42
-rw-r--r--tests/auto/declarative/qmlecmascript/data/scriptErrors.js2
-rw-r--r--tests/auto/declarative/qmlecmascript/data/scriptErrors.qml10
-rw-r--r--tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp61
-rw-r--r--tests/auto/declarative/qmllanguage/data/Alias2.qml9
-rw-r--r--tests/auto/declarative/qmllanguage/data/alias.4.qml6
-rw-r--r--tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp9
29 files changed, 497 insertions, 428 deletions
diff --git a/examples/declarative/gridview/gridview.qml b/examples/declarative/gridview/gridview.qml
index 2e5110a..93931c7 100644
--- a/examples/declarative/gridview/gridview.qml
+++ b/examples/declarative/gridview/gridview.qml
@@ -4,57 +4,35 @@ Rectangle {
width: 300; height: 400; color: "white"
ListModel {
- id: AppModel
- ListElement {
- name: "Music"
- icon: "AudioPlayer_48.png"
- }
- ListElement {
- name: "Movies"
- icon: "VideoPlayer_48.png"
- }
- ListElement {
- name: "Camera"
- icon: "Camera_48.png"
- }
- ListElement {
- name: "Calendar"
- icon: "DateBook_48.png"
- }
- ListElement {
- name: "Messaging"
- icon: "EMail_48.png"
- }
- ListElement {
- name: "Todo List"
- icon: "TodoList_48.png"
- }
- ListElement {
- name: "Contacts"
- icon: "AddressBook_48.png"
- }
+ id: appModel
+ ListElement { name: "Music"; icon: "pics/AudioPlayer_48.png" }
+ ListElement { name: "Movies"; icon: "pics/VideoPlayer_48.png" }
+ ListElement { name: "Camera"; icon: "pics/Camera_48.png" }
+ ListElement { name: "Calendar"; icon: "pics/DateBook_48.png" }
+ ListElement { name: "Messaging"; icon: "pics/EMail_48.png" }
+ ListElement { name: "Todo List"; icon: "pics/TodoList_48.png" }
+ ListElement { name: "Contacts"; icon: "pics/AddressBook_48.png" }
}
Component {
- id: AppDelegate
+ id: appDelegate
Item {
width: 100; height: 100
- Image { id: Icon; y: 20; anchors.horizontalCenter: parent.horizontalCenter; source: icon }
- Text { anchors.top: Icon.bottom; anchors.horizontalCenter: parent.horizontalCenter; text: name }
+ Image { id: myIcon; y: 20; anchors.horizontalCenter: parent.horizontalCenter; source: icon }
+ Text { anchors.top: myIcon.bottom; anchors.horizontalCenter: parent.horizontalCenter; text: name }
}
}
Component {
- id: AppHighlight
- Rectangle { width: 80; height: 80; color: "#FFFF88" }
+ id: appHighlight
+ Rectangle { width: 80; height: 80; color: "lightsteelblue" }
}
GridView {
- id: List1
anchors.fill: parent
cellWidth: 100; cellHeight: 100
- model: AppModel; delegate: AppDelegate
- highlight: AppHighlight
+ model: appModel; delegate: appDelegate
+ highlight: appHighlight
focus: true
}
}
diff --git a/examples/declarative/listview/recipes.qml b/examples/declarative/listview/recipes.qml
index 4ccb344..3410f56 100644
--- a/examples/declarative/listview/recipes.qml
+++ b/examples/declarative/listview/recipes.qml
@@ -1,128 +1,136 @@
import Qt 4.6
-
import "content"
+
// This example illustrates expanding a list item to show a more detailed view
+
Rectangle {
id: page
width: 400; height: 240; color: "black"
- resources: [
- // Delegate for the recipes. This delegate has two modes:
- // 1. the list mode (default), which just shows the picture and title of the recipe.
- // 2. the details mode, which also shows the ingredients and method.
- Component {
- id: recipeDelegate
- Item {
- id: wrapper
- width: list.width
- // Create a property to contain the visibility of the details.
- // We can bind multiple element's opacity to this one property,
- // rather than having a "PropertyChanges" line for each element we
- // want to fade.
- property real detailsOpacity : 0
-
- // A simple rounded rectangle for the background
- Rectangle {
- id: background
- x: 1; y: 2; width: parent.width-2; height: parent.height-4
- color: "#FEFFEE"; border.color: "#FFBE4F"; radius: 5
- }
- // This mouse region covers the entire delegate.
- // When clicked it changes mode to 'Details'. If we are already
- // in Details mode, then no change will happen.
- MouseRegion {
- id: pageMouse
- anchors.fill: parent
- onClicked: { wrapper.state = 'Details' }
- }
- // Layout the page. Picture, title and ingredients at the top, method at the
- // bottom. Note that elements that should not be visible in the list
- // mode have their opacity set to wrapper.detailsOpacity.
- Row {
- id: topLayout
- x: 10; y: 10; height: recipePic.height; width: parent.width
- spacing: 10
- Image {
- id: recipePic
- source: picture; width: 48; height: 48
- }
- Column {
- height: recipePic.height; width: background.width-recipePic.width-20
- spacing: 5
- Text { id: name; text: title; font.bold: true; font.pointSize: 16 }
- Text {
- text: "Ingredients"; font.pointSize: 12; font.bold: true
- opacity: wrapper.detailsOpacity
- }
- Text {
- text: ingredients; wrap: true; width: parent.width
- opacity: wrapper.detailsOpacity
- }
- }
+
+ // Delegate for the recipes. This delegate has two modes:
+ // 1. the list mode (default), which just shows the picture and title of the recipe.
+ // 2. the details mode, which also shows the ingredients and method.
+ Component {
+ id: recipeDelegate
+ Item {
+ id: wrapper
+ width: list.width
+
+ // Create a property to contain the visibility of the details.
+ // We can bind multiple element's opacity to this one property,
+ // rather than having a "PropertyChanges" line for each element we
+ // want to fade.
+ property real detailsOpacity : 0
+
+ // A simple rounded rectangle for the background
+ Rectangle {
+ id: background
+ x: 1; y: 2; width: parent.width - 2; height: parent.height - 4
+ color: "#FEFFEE"; border.color: "#FFBE4F"; radius: 5
+ }
+
+ // This mouse region covers the entire delegate.
+ // When clicked it changes mode to 'Details'. If we are already
+ // in Details mode, then no change will happen.
+ MouseRegion {
+ id: pageMouse
+ anchors.fill: parent
+ onClicked: wrapper.state = 'Details';
+ }
+
+ // Layout the page. Picture, title and ingredients at the top, method at the
+ // bottom. Note that elements that should not be visible in the list
+ // mode have their opacity set to wrapper.detailsOpacity.
+ Row {
+ id: topLayout
+ x: 10; y: 10; height: recipePic.height; width: parent.width
+ spacing: 10
+
+ Image {
+ id: recipePic
+ source: picture; width: 48; height: 48
}
- Item {
- id: details
- x: 10; width: parent.width-20
- anchors.top: topLayout.bottom; anchors.topMargin: 10
- anchors.bottom: parent.bottom; anchors.bottomMargin: 10
- opacity: wrapper.detailsOpacity
+
+ Column {
+ height: recipePic.height; width: background.width-recipePic.width-20
+ spacing: 5
+ Text { id: name; text: title; font.bold: true; font.pointSize: 16 }
Text {
- id: methodTitle
- text: "Method"; font.pointSize: 12; font.bold: true
- anchors.top: parent.top
- }
- Flickable {
- id: flick
- anchors.top: methodTitle.bottom; anchors.bottom: parent.bottom
- width: parent.width; viewportHeight: methodText.height; clip: true
- Text { id: methodText; text: method; wrap: true; width: details.width }
- }
- Image {
- anchors.right: flick.right; anchors.top: flick.top
- source: "content/pics/moreUp.png"; opacity: flick.atYBeginning ? 0 : 1
+ text: "Ingredients"; font.pointSize: 12; font.bold: true
+ opacity: wrapper.detailsOpacity
}
- Image {
- anchors.right: flick.right; anchors.bottom: flick.bottom
- source: "content/pics/moreDown.png"; opacity: flick.atYEnd ? 0 : 1
+ Text {
+ text: ingredients; wrap: true; width: parent.width
+ opacity: wrapper.detailsOpacity
}
}
- // A button to close the detailed view, i.e. set the state back to default ('').
- MediaButton {
- anchors.right: background.right; anchors.rightMargin: 5
- y: 10; opacity: wrapper.detailsOpacity
- text: "Close"; onClicked: { wrapper.state = '' }
+ }
+
+ Item {
+ id: details
+ x: 10; width: parent.width-20
+ anchors.top: topLayout.bottom; anchors.topMargin: 10
+ anchors.bottom: parent.bottom; anchors.bottomMargin: 10
+ opacity: wrapper.detailsOpacity
+
+ Text {
+ id: methodTitle
+ text: "Method"; font.pointSize: 12; font.bold: true
+ anchors.top: parent.top
+ }
+ Flickable {
+ id: flick
+ anchors.top: methodTitle.bottom; anchors.bottom: parent.bottom
+ width: parent.width; viewportHeight: methodText.height; clip: true
+ Text { id: methodText; text: method; wrap: true; width: details.width }
}
- // Make the default height equal the hight of the picture, plus margin.
- height: 68
- states: [
- State {
- name: "Details"
- PropertyChanges { target: background; color: "white" }
- // Make the picture bigger
- PropertyChanges { target: recipePic; width: 128; height: 128 }
- // Make details visible
- PropertyChanges { target: wrapper; detailsOpacity: 1; x: 0 }
- // Make the detailed view fill the entire list area
- PropertyChanges { target: wrapper; height: list.height }
- // Move the list so that this item is at the top.
- PropertyChanges { target: wrapper.ListView.view; explicit: true; viewportY: wrapper.y }
- // Disallow flicking while we're in detailed view
- PropertyChanges { target: wrapper.ListView.view; interactive: false }
- }
- ]
- transitions: [
- Transition {
- // Make the state changes smooth
- ParallelAnimation {
- ColorAnimation { property: "color"; duration: 500 }
- NumberAnimation {
- duration: 300; properties: "detailsOpacity,x,viewportY,height,width"
- }
- }
+ Image {
+ anchors.right: flick.right; anchors.top: flick.top
+ source: "content/pics/moreUp.png"; opacity: flick.atYBeginning ? 0 : 1
+ }
+ Image {
+ anchors.right: flick.right; anchors.bottom: flick.bottom
+ source: "content/pics/moreDown.png"; opacity: flick.atYEnd ? 0 : 1
+ }
+ }
+
+ // A button to close the detailed view, i.e. set the state back to default ('').
+ MediaButton {
+ anchors.right: background.right; anchors.rightMargin: 5
+ y: 10; opacity: wrapper.detailsOpacity
+ text: "Close"; onClicked: wrapper.state = '';
+ }
+
+ // Make the default height equal the hight of the picture, plus margin.
+ height: 68
+
+ states: State {
+ name: "Details"
+ PropertyChanges { target: background; color: "white" }
+ // Make the picture bigger
+ PropertyChanges { target: recipePic; width: 128; height: 128 }
+ // Make details visible
+ PropertyChanges { target: wrapper; detailsOpacity: 1; x: 0 }
+ // Make the detailed view fill the entire list area
+ PropertyChanges { target: wrapper; height: list.height }
+ // Move the list so that this item is at the top.
+ PropertyChanges { target: wrapper.ListView.view; explicit: true; viewportY: wrapper.y }
+ // Disallow flicking while we're in detailed view
+ PropertyChanges { target: wrapper.ListView.view; interactive: false }
+ }
+
+ transitions: Transition {
+ // Make the state changes smooth
+ ParallelAnimation {
+ ColorAnimation { property: "color"; duration: 500 }
+ NumberAnimation {
+ duration: 300; properties: "detailsOpacity,x,viewportY,height,width"
}
- ]
+ }
}
}
- ]
+ }
+
// The actual list
ListView {
id: list
diff --git a/examples/declarative/snow/ImageBatch.qml b/examples/declarative/snow/ImageBatch.qml
index 62f986c..86e11f7 100644
--- a/examples/declarative/snow/ImageBatch.qml
+++ b/examples/declarative/snow/ImageBatch.qml
@@ -35,14 +35,14 @@ GridView {
XmlRole { name: "url"; query: "media:content/@url/string()" }
}
- Item {
+ delegate: Item {
id: root
property bool isSelected: GridView.isCurrentItem && grid.isSelected
transformOrigin: "Center"
width: grid.imageWidth; height: grid.imageHeight;
Image { id: flickrImage; source: url; fillMode: "PreserveAspectFit"; smooth: true; anchors.fill: parent;
- opacity: (status == 1)?1:0; opacity: Behavior { NumberAnimation { properties: "opacity" } } }
+ opacity: (status == Image.Ready)?1:0; /*opacity: Behavior { NumberAnimation { properties: "opacity" } }*/ }
Loading { anchors.centerIn: parent; visible: flickrImage.status!=1 }
states: State {
diff --git a/examples/declarative/webview/newwindows.qml b/examples/declarative/webview/newwindows.qml
index 59e3b3e..e2ed58f 100644
--- a/examples/declarative/webview/newwindows.qml
+++ b/examples/declarative/webview/newwindows.qml
@@ -7,22 +7,23 @@ import Qt 4.6
Row {
id: pages
- height: 200
- resources: [
- Component {
- id: webViewPage
- Rectangle {
- width: webView.width
- height: webView.height
- WebView {
- id: webView
- newWindowComponent: webViewPage
- newWindowParent: pages
- url: "newwindows.html"
- }
- }
+ height: 200; width: 500
+
+ Component {
+ id: webViewPage
+ Rectangle {
+ width: webView.width
+ height: webView.height
+ border.color: "gray"
+
+ WebView {
+ id: webView
+ newWindowComponent: webViewPage
+ newWindowParent: pages
+ url: "newwindows.html"
+ }
}
- ]
- width: 500
+ }
+
Loader { sourceComponent: webViewPage }
}
diff --git a/examples/declarative/xmldata/daringfireball.qml b/examples/declarative/xmldata/daringfireball.qml
index bea38c8..938bdd5 100644
--- a/examples/declarative/xmldata/daringfireball.qml
+++ b/examples/declarative/xmldata/daringfireball.qml
@@ -2,59 +2,44 @@ import Qt 4.6
Rectangle {
color: "white"
- width: 600
- height: 600
- resources: [
- XmlListModel {
- id: feedModel
- source: "http://daringfireball.net/index.xml"
- query: "/feed/entry"
- namespaceDeclarations: "declare default element namespace 'http://www.w3.org/2005/Atom';"
- XmlRole {
- name: "title"
- query: "title/string()"
- }
- XmlRole {
- name: "tagline"
- query: "author/name/string()"
+ width: 600; height: 600
+
+ XmlListModel {
+ id: feedModel
+ source: "http://daringfireball.net/index.xml"
+ query: "/feed/entry"
+ namespaceDeclarations: "declare default element namespace 'http://www.w3.org/2005/Atom';"
+ XmlRole { name: "title"; query: "title/string()" }
+ XmlRole { name: "tagline"; query: "author/name/string()" }
+ XmlRole { name: "content"; query: "content/string()" }
+ }
+
+ Component {
+ id: feedDelegate
+ Item {
+ height: childrenRect.height + 20
+ Text {
+ id: titleText
+ x: 10
+ text: title; font.bold: true
}
- XmlRole {
- name: "content"
- query: "content/string()"
+ Text {
+ text: 'by ' + tagline
+ anchors.left: titleText.right; anchors.leftMargin: 10
+ font.italic: true
}
- },
- Component {
- id: feedDelegate
- Item {
- height: childrenRect.height + 20
- Text {
- x: 10
- id: titleText
- text: title
- font.bold: true
- }
- Text {
- text: 'by ' + tagline
- anchors.left: titleText.right
- anchors.leftMargin: 10
- font.italic: true
- }
- Text {
- x: 10
- text: content
- anchors.top: titleText.bottom
- width: 580
- wrap: true
- onLinkActivated: { print('link clicked: ' + link) }
- }
+ Text {
+ x: 10
+ text: content
+ anchors.top: titleText.bottom
+ width: 580; wrap: true
+ onLinkActivated: { print('link clicked: ' + link) }
}
}
- ]
+ }
+
ListView {
- id: list
anchors.fill: parent
- clip: true
- model: feedModel
- delegate: feedDelegate
+ model: feedModel; delegate: feedDelegate
}
}
diff --git a/examples/declarative/xmldata/yahoonews.qml b/examples/declarative/xmldata/yahoonews.qml
index 6d43f46..7d8b8a2 100644
--- a/examples/declarative/xmldata/yahoonews.qml
+++ b/examples/declarative/xmldata/yahoonews.qml
@@ -5,100 +5,74 @@ Rectangle {
GradientStop { position: 0; color: "black" }
GradientStop { position: 1.0; color: "#AAAAAA" }
}
- width: 600
- height: 600
- resources: [
- XmlListModel {
- id: feedModel
- source: "http://rss.news.yahoo.com/rss/oceania"
- query: "/rss/channel/item"
- XmlRole {
- name: "title"
- query: "title/string()"
- }
- XmlRole {
- name: "link"
- query: "link/string()"
- }
- XmlRole {
- name: "description"
- query: "description/string()"
+ width: 600; height: 600
+
+ XmlListModel {
+ id: feedModel
+ source: "http://rss.news.yahoo.com/rss/oceania"
+ query: "/rss/channel/item"
+ XmlRole { name: "title"; query: "title/string()" }
+ XmlRole { name: "link"; query: "link/string()" }
+ XmlRole { name: "description"; query: "description/string()" }
+ }
+
+ Component {
+ id: feedDelegate
+ Item {
+ id: delegate
+ height: wrapper.height + 10
+
+ MouseRegion {
+ anchors.fill: wrapper
+ onPressed: delegate.ListView.view.currentIndex = index;
+ onClicked: if (wrapper.state == 'Details') wrapper.state = ''; else wrapper.state = 'Details';
}
- },
- Component {
- id: feedDelegate
- Item {
- id: delegate
- height: wrapper.height + 10
- MouseRegion {
- anchors.fill: wrapper
- onPressed: { delegate.ListView.view.currentIndex = index; }
- onClicked: { if (wrapper.state == 'Details') { wrapper.state = '';} else {wrapper.state = 'Details';} }
+
+ Rectangle {
+ id: wrapper
+ y: 5; height: titleText.height + 10; width: 580
+ color: "#F0F0F0"; radius: 5
+ Text {
+ id: titleText
+ x: 10; y: 5
+ text: '<a href=\'' + link + '\'>' + title + '</a>'
+ font.bold: true; font.family: "Helvetica"; font.pointSize: 14
+ onLinkActivated: { print('link clicked: ' + link) }
}
- Rectangle {
- id: wrapper
- y: 5
- height: titleText.height + 10
- width: 580
- color: "#F0F0F0"
- radius: 5
- Text {
- x: 10
- y: 5
- id: titleText
- text: '<a href=\'' + link + '\'>' + title + '</a>'
- font.bold: true
- font.family: "Helvetica"
- font.pointSize: 14
- onLinkActivated: { print('link clicked: ' + link) }
- }
- Text {
- x: 10
- id: description
- text: description
- width: 560
- wrap: true
- font.family: "Helvetica"
- anchors.top: titleText.bottom
- anchors.topMargin: 5
- opacity: 0
+
+ Text {
+ x: 10
+ id: descriptionText
+ text: description
+ width: 560
+ wrap: true
+ font.family: "Helvetica"
+ anchors.top: titleText.bottom
+ anchors.topMargin: 5
+ opacity: 0
+ }
+
+ states: State {
+ name: "Details"
+ PropertyChanges { target: wrapper; height: childrenRect.height + 10 }
+ PropertyChanges { target: descriptionText; opacity: 1 }
+ }
+
+ transitions: Transition {
+ from: "*"; to: "Details"; reversible: true
+ SequentialAnimation {
+ NumberAnimation { duration: 200; properties: "height"; easing: "easeOutQuad" }
+ NumberAnimation { duration: 200; properties: "opacity" }
}
- states: [
- State {
- name: "Details"
- PropertyChanges { target: wrapper; height: childrenRect.height + 10 }
- PropertyChanges { target: description; opacity: 1 }
- }
- ]
- transitions: [
- Transition {
- from: "*"
- to: "Details"
- reversible: true
- SequentialAnimation {
- NumberAnimation {
- duration: 200
- properties: "height"
- easing: "easeOutQuad"
- }
- NumberAnimation {
- duration: 200
- properties: "opacity"
- }
- }
- }
- ]
}
}
}
- ]
+ }
+
ListView {
id: list
- x: 10
- y: 10
- width: parent.width - 20
- height: parent.height - 20
- clip: true
+ x: 10; y: 10
+ width: parent.width - 20; height: parent.height - 20
model: feedModel
delegate: feedDelegate
}
diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp
index 907dcfa..2435c40 100644
--- a/src/declarative/qml/qmlbinding.cpp
+++ b/src/declarative/qml/qmlbinding.cpp
@@ -67,8 +67,8 @@ QmlBindingPrivate::QmlBindingPrivate()
{
}
-QmlBinding::QmlBinding(void *data, QmlRefCount *rc, QObject *obj, QmlContext *ctxt, QObject *parent)
-: QmlExpression(ctxt, data, rc, obj, *new QmlBindingPrivate)
+QmlBinding::QmlBinding(void *data, QmlRefCount *rc, QObject *obj, QmlContext *ctxt, const QUrl &url, int lineNumber, QObject *parent)
+: QmlExpression(ctxt, data, rc, obj, url, lineNumber, *new QmlBindingPrivate)
{
setParent(parent);
}
diff --git a/src/declarative/qml/qmlbinding.h b/src/declarative/qml/qmlbinding.h
index bc5a42f..6a3e92a 100644
--- a/src/declarative/qml/qmlbinding.h
+++ b/src/declarative/qml/qmlbinding.h
@@ -93,7 +93,8 @@ class Q_DECLARATIVE_EXPORT QmlBinding : public QmlExpression,
Q_OBJECT
public:
QmlBinding(const QString &, QObject *, QmlContext *, QObject *parent=0);
- QmlBinding(void *, QmlRefCount *, QObject *, QmlContext *, QObject *parent);
+ QmlBinding(void *, QmlRefCount *, QObject *, QmlContext *, const QUrl &, int,
+ QObject *parent);
~QmlBinding();
void setTarget(const QmlMetaProperty &);
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index 71f86d9..6fad513 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -833,6 +833,8 @@ void QmlCompiler::genObject(QmlParser::Object *obj)
QmlInstruction script;
script.type = QmlInstruction::StoreScript;
script.line = -1; // ###
+ script.storeScript.fileName = output->indexForString(obj->scriptBlocksFile.at(ii));
+ script.storeScript.lineNumber = obj->scriptBlocksLineNumber.at(ii);
script.storeScript.value = output->indexForString(obj->scriptBlocks.at(ii));
output->bytecode << script;
}
@@ -1054,6 +1056,8 @@ bool QmlCompiler::buildComponent(QmlParser::Object *obj,
bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script)
{
QString scriptCode;
+ QString sourceUrl;
+ int lineNumber = 1;
if (script->properties.count() == 1 &&
script->properties.begin().key() == QByteArray("source")) {
@@ -1066,8 +1070,7 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script)
source->values.at(0)->object || !source->values.at(0)->value.isString())
COMPILE_EXCEPTION(source, "Invalid Script source value");
- QString sourceUrl =
- output->url.resolved(QUrl(source->values.at(0)->value.asString())).toString();
+ sourceUrl = output->url.resolved(QUrl(source->values.at(0)->value.asString())).toString();
for (int ii = 0; ii < unit->resources.count(); ++ii) {
if (unit->resources.at(ii)->url == sourceUrl) {
@@ -1079,10 +1082,14 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script)
} else if (!script->properties.isEmpty()) {
COMPILE_EXCEPTION(*script->properties.begin(), "Properties cannot be set on Script block");
} else if (script->defaultProperty) {
+ sourceUrl = output->url.toString();
+
QmlParser::Location currentLocation;
for (int ii = 0; ii < script->defaultProperty->values.count(); ++ii) {
Value *v = script->defaultProperty->values.at(ii);
+ if (lineNumber == 1)
+ lineNumber = v->location.start.line;
if (v->object || !v->value.isString())
COMPILE_EXCEPTION(v, "Invalid Script block");
@@ -1105,8 +1112,11 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script)
}
}
- if (!scriptCode.isEmpty())
+ if (!scriptCode.isEmpty()) {
obj->scriptBlocks.append(scriptCode);
+ obj->scriptBlocksFile.append(sourceUrl);
+ obj->scriptBlocksLineNumber.append(lineNumber);
+ }
return true;
}
@@ -2272,10 +2282,13 @@ bool QmlCompiler::compileAlias(QMetaObjectBuilder &builder,
data.append((const char *)&idObject->idIndex, sizeof(idObject->idIndex));
data.append((const char *)&propIdx, sizeof(propIdx));
+ const char *typeName = aliasProperty.typeName();
+ if (aliasProperty.isEnumType())
+ typeName = "int"; // Avoid introducing a dependency on the aliased metaobject
+
builder.addSignal(prop.name + "Changed()");
QMetaPropertyBuilder propBuilder =
- builder.addProperty(prop.name, aliasProperty.typeName(),
- builder.methodCount() - 1);
+ builder.addProperty(prop.name, typeName, builder.methodCount() - 1);
propBuilder.setScriptable(true);
return true;
}
@@ -2351,7 +2364,7 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding,
store.assignBinding.value = output->indexForByteArray(ref.compiledData);
store.assignBinding.context = ref.bindingContext.stack;
store.assignBinding.owner = ref.bindingContext.owner;
- store.line = prop->location.end.line;
+ store.line = binding->location.start.line;
Q_ASSERT(ref.bindingContext.owner == 0 ||
(ref.bindingContext.owner != 0 && valueTypeProperty));
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp
index f6795aa..43a4741 100644
--- a/src/declarative/qml/qmlcontext.cpp
+++ b/src/declarative/qml/qmlcontext.cpp
@@ -61,8 +61,11 @@ QmlContextPrivate::QmlContextPrivate()
{
}
-void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject)
+void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject,
+ const QString &fileName, int lineNumber)
{
+ Q_Q(QmlContext);
+
if (!engine)
return;
@@ -70,29 +73,15 @@ void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject)
QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
QScriptContext *scriptContext = scriptEngine->pushCleanContext();
- scriptContext->pushScope(scriptValue);
+ scriptContext->pushScope(enginePriv->contextClass->newContext(q, scopeObject));
- if (scopeObject)
- scriptContext->pushScope(enginePriv->objectClass->newQObject(scopeObject));
-
QScriptValue scope = scriptEngine->newObject();
scriptContext->setActivationObject(scope);
- QScriptValue val = scriptEngine->evaluate(script);
+ QScriptValue val = scriptEngine->evaluate(script, fileName, lineNumber);
- if (scriptEngine->hasUncaughtException()) {
- if (scriptEngine->uncaughtException().isError()){
- QScriptValue exception = scriptEngine->uncaughtException();
- if (!exception.property(QLatin1String("fileName")).toString().isEmpty()){
- qWarning() << exception.property(QLatin1String("fileName")).toString()
- << scriptEngine->uncaughtExceptionLineNumber()
- << exception.toString();
-
- } else {
- qmlInfo(scopeObject) << exception.toString();
- }
- }
- }
+ if (scriptEngine->hasUncaughtException())
+ QmlExpressionPrivate::printException(scriptEngine);
scriptEngine->popContext();
@@ -139,10 +128,6 @@ void QmlContextPrivate::init()
if (parent)
parent->d_func()->childContexts.insert(q);
-
- //set scope chain
- QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
- scriptValue = QmlEnginePrivate::get(engine)->contextClass->newContext(q);
}
void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority)
diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h
index d18bfda..9a77e94 100644
--- a/src/declarative/qml/qmlcontext_p.h
+++ b/src/declarative/qml/qmlcontext_p.h
@@ -91,10 +91,9 @@ public:
QObjectList defaultObjects;
int highPriorityCount;
- QScriptValue scriptValue;
-
QList<QScriptValue> scripts;
- void addScript(const QString &script, QObject *scope);
+ void addScript(const QString &script, QObject *scope,
+ const QString &fileName = QString(), int lineNumber = 1);
QUrl url;
diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp
index 6d2c58c..939d008 100644
--- a/src/declarative/qml/qmlcontextscriptclass.cpp
+++ b/src/declarative/qml/qmlcontextscriptclass.cpp
@@ -47,8 +47,9 @@
QT_BEGIN_NAMESPACE
struct ContextData : public QScriptDeclarativeClass::Object {
- ContextData(QmlContext *c) : context(c) {}
+ ContextData(QmlContext *c, QObject *o) : context(c), scopeObject(o) {}
QGuard<QmlContext> context;
+ QGuard<QObject> scopeObject;
};
/*
@@ -57,7 +58,7 @@ struct ContextData : public QScriptDeclarativeClass::Object {
*/
QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine)
: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine),
- lastData(0), lastPropertyIndex(-1), lastDefaultObject(-1)
+ lastScopeObject(0), lastContext(0), lastData(0), lastPropertyIndex(-1), lastDefaultObject(-1)
{
}
@@ -65,11 +66,11 @@ QmlContextScriptClass::~QmlContextScriptClass()
{
}
-QScriptValue QmlContextScriptClass::newContext(QmlContext *context)
+QScriptValue QmlContextScriptClass::newContext(QmlContext *context, QObject *scopeObject)
{
QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
- return newObject(scriptEngine, this, new ContextData(context));
+ return newObject(scriptEngine, this, new ContextData(context, scopeObject));
}
QmlContext *QmlContextScriptClass::contextFromValue(const QScriptValue &v)
@@ -81,24 +82,27 @@ QmlContext *QmlContextScriptClass::contextFromValue(const QScriptValue &v)
return data->context;
}
-#include <QDebug>
QScriptClass::QueryFlags
QmlContextScriptClass::queryProperty(Object *object, const Identifier &name,
QScriptClass::QueryFlags flags)
{
Q_UNUSED(flags);
+ lastScopeObject = 0;
lastContext = 0;
lastData = 0;
lastPropertyIndex = -1;
lastDefaultObject = -1;
QmlContext *bindContext = ((ContextData *)object)->context.data();
+ QObject *scopeObject = ((ContextData *)object)->scopeObject.data();
if (!bindContext)
return 0;
while (bindContext) {
- QScriptClass::QueryFlags rv = queryProperty(bindContext, name, flags);
+ QScriptClass::QueryFlags rv =
+ queryProperty(bindContext, scopeObject, name, flags);
+ scopeObject = 0; // Only applies to the first context
if (rv) return rv;
bindContext = bindContext->parentContext();
}
@@ -107,7 +111,8 @@ QmlContextScriptClass::queryProperty(Object *object, const Identifier &name,
}
QScriptClass::QueryFlags
-QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier &name,
+QmlContextScriptClass::queryProperty(QmlContext *bindContext, QObject *scopeObject,
+ const Identifier &name,
QScriptClass::QueryFlags flags)
{
QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
@@ -129,6 +134,24 @@ QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier &
}
}
+ for (int ii = 0; ii < cp->scripts.count(); ++ii) {
+ lastFunction = QScriptDeclarativeClass::function(cp->scripts.at(ii), name);
+ if (lastFunction.isValid()) {
+ lastContext = bindContext;
+ return QScriptClass::HandlesReadAccess;
+ }
+ }
+
+ if (scopeObject) {
+ QScriptClass::QueryFlags rv =
+ ep->objectClass->queryProperty(scopeObject, name, flags, 0);
+ if (rv) {
+ lastScopeObject = scopeObject;
+ lastContext = bindContext;
+ return rv;
+ }
+ }
+
for (int ii = 0; ii < cp->defaultObjects.count(); ++ii) {
QScriptClass::QueryFlags rv =
ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags, 0);
@@ -140,13 +163,6 @@ QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier &
}
}
- for (int ii = 0; ii < cp->scripts.count(); ++ii) {
- lastFunction = QScriptDeclarativeClass::function(cp->scripts.at(ii), name);
- if (lastFunction.isValid()) {
- lastContext = bindContext;
- return QScriptClass::HandlesReadAccess;
- }
- }
return 0;
}
@@ -160,8 +176,11 @@ QScriptValue QmlContextScriptClass::property(Object *object, const Identifier &n
QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
QmlContextPrivate *cp = QmlContextPrivate::get(bindContext);
+ if (lastScopeObject) {
- if (lastData) {
+ return ep->objectClass->property(lastScopeObject, name);
+
+ } else if (lastData) {
if (lastData->type)
return ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->type);
@@ -197,7 +216,7 @@ QScriptValue QmlContextScriptClass::property(Object *object, const Identifier &n
void QmlContextScriptClass::setProperty(Object *object, const Identifier &name,
const QScriptValue &value)
{
- Q_ASSERT(lastDefaultObject != -1);
+ Q_ASSERT(lastScopeObject || lastDefaultObject != -1);
QmlContext *bindContext = lastContext;
Q_ASSERT(bindContext);
@@ -205,7 +224,11 @@ void QmlContextScriptClass::setProperty(Object *object, const Identifier &name,
QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
QmlContextPrivate *cp = QmlContextPrivate::get(bindContext);
- ep->objectClass->setProperty(cp->defaultObjects.at(lastDefaultObject), name, value);
+ if (lastScopeObject) {
+ ep->objectClass->setProperty(lastScopeObject, name, value);
+ } else {
+ ep->objectClass->setProperty(cp->defaultObjects.at(lastDefaultObject), name, value);
+ }
}
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcontextscriptclass_p.h b/src/declarative/qml/qmlcontextscriptclass_p.h
index 761a115..126c8fe 100644
--- a/src/declarative/qml/qmlcontextscriptclass_p.h
+++ b/src/declarative/qml/qmlcontextscriptclass_p.h
@@ -67,7 +67,7 @@ public:
QmlContextScriptClass(QmlEngine *);
~QmlContextScriptClass();
- QScriptValue newContext(QmlContext *);
+ QScriptValue newContext(QmlContext *, QObject * = 0);
QmlContext *contextFromValue(const QScriptValue &);
@@ -78,11 +78,13 @@ protected:
virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
private:
- QScriptClass::QueryFlags queryProperty(QmlContext *, const Identifier &,
+ QScriptClass::QueryFlags queryProperty(QmlContext *, QObject *scopeObject,
+ const Identifier &,
QScriptClass::QueryFlags flags);
QmlEngine *engine;
+ QObject *lastScopeObject;
QmlContext *lastContext;
QmlTypeNameCache::Data *lastData;
int lastPropertyIndex;
diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp
index 23e1700..0de64d9 100644
--- a/src/declarative/qml/qmlexpression.cpp
+++ b/src/declarative/qml/qmlexpression.cpp
@@ -89,8 +89,11 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, const QString &expr,
}
void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc,
- QObject *me)
+ QObject *me, const QUrl &url, int lineNumber)
{
+ data->fileName = url.toString();
+ data->line = lineNumber;
+
quint32 *exprData = (quint32 *)expr;
Q_ASSERT(*exprData == BasicScriptEngineData ||
*exprData == PreTransformedQtScriptData);
@@ -107,14 +110,12 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc,
QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
if (!dd->programs.at(progIdx)) {
- dd->programs[progIdx] = new QScriptProgram(scriptEngine->compile(data->expression));
+ dd->programs[progIdx] =
+ new QScriptProgram(scriptEngine->compile(data->expression, data->fileName, data->line));
}
- QmlContextPrivate *ctxtPriv = ctxt->d_func();
QScriptContext *scriptContext = scriptEngine->pushCleanContext();
- scriptContext->pushScope(ctxtPriv->scriptValue);
- if (me)
- scriptContext->pushScope(ep->objectClass->newQObject(me));
+ scriptContext->pushScope(ep->contextClass->newContext(ctxt, me));
data->expressionFunction = scriptEngine->evaluate(*dd->programs[progIdx]);
@@ -145,11 +146,12 @@ QmlExpression::QmlExpression()
/*! \internal */
QmlExpression::QmlExpression(QmlContext *ctxt, void *expr,
QmlRefCount *rc, QObject *me,
+ const QUrl &url, int lineNumber,
QmlExpressionPrivate &dd)
: QObject(dd, 0)
{
Q_D(QmlExpression);
- d->init(ctxt, expr, rc, me);
+ d->init(ctxt, expr, rc, me, url, lineNumber);
}
/*!
@@ -251,6 +253,28 @@ QVariant QmlExpressionPrivate::evalSSE()
return rv;
}
+void QmlExpressionPrivate::printException(QScriptEngine *scriptEngine)
+{
+ if (scriptEngine->hasUncaughtException() &&
+ scriptEngine->uncaughtException().isError()) {
+
+ QString fileName;
+ int lineNumber = scriptEngine->uncaughtExceptionLineNumber();
+
+ QScriptValue exception = scriptEngine->uncaughtException();
+ QLatin1String fileNameProp("fileName");
+
+ if (!exception.property(fileNameProp).toString().isEmpty()){
+ fileName = exception.property(fileNameProp).toString();
+ } else {
+ fileName = QLatin1String("<Unknown File>");
+ }
+
+ qWarning().nospace() << qPrintable(fileName) << ":" << lineNumber << ": "
+ << qPrintable(exception.toString());
+ }
+}
+
QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope)
{
#ifdef Q_ENABLE_PERFORMANCE_LOG
@@ -270,10 +294,7 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope)
if (!data->expressionFunctionValid) {
QScriptContext *scriptContext = scriptEngine->pushCleanContext();
- scriptContext->pushScope(ctxtPriv->scriptValue);
-
- if (data->me)
- scriptContext->pushScope(ep->objectClass->newQObject(data->me));
+ scriptContext->pushScope(ep->contextClass->newContext(data->context(), data->me));
if (data->expressionRewritten) {
data->expressionFunction = scriptEngine->evaluate(data->expression,
@@ -291,19 +312,8 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope)
QScriptValue svalue = data->expressionFunction.call();
- if (scriptEngine->hasUncaughtException()) {
- if (scriptEngine->uncaughtException().isError()){
- QScriptValue exception = scriptEngine->uncaughtException();
- QLatin1String fileNameProp("fileName");
- if (!exception.property(fileNameProp).toString().isEmpty()){
- qWarning() << exception.property(fileNameProp).toString()
- << scriptEngine->uncaughtExceptionLineNumber()
- << exception.toString();
- } else {
- qWarning() << exception.toString();
- }
- }
- }
+ if (scriptEngine->hasUncaughtException())
+ printException(scriptEngine);
if (secondaryScope)
ctxtPriv->defaultObjects.removeAt(ctxtPriv->highPriorityCount);
diff --git a/src/declarative/qml/qmlexpression.h b/src/declarative/qml/qmlexpression.h
index c295a1c..b85e0a7 100644
--- a/src/declarative/qml/qmlexpression.h
+++ b/src/declarative/qml/qmlexpression.h
@@ -89,8 +89,8 @@ Q_SIGNALS:
protected:
QmlExpression(QmlContext *, const QString &, QObject *,
QmlExpressionPrivate &dd);
- QmlExpression(QmlContext *, void *, QmlRefCount *rc, QObject *me,
- QmlExpressionPrivate &dd);
+ QmlExpression(QmlContext *, void *, QmlRefCount *rc, QObject *me, const QUrl &,
+ int, QmlExpressionPrivate &dd);
private Q_SLOTS:
void __q_notify();
diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h
index 33016e6..d9bb27b 100644
--- a/src/declarative/qml/qmlexpression_p.h
+++ b/src/declarative/qml/qmlexpression_p.h
@@ -136,7 +136,7 @@ public:
};
void init(QmlContext *, const QString &, QObject *);
- void init(QmlContext *, void *, QmlRefCount *, QObject *);
+ void init(QmlContext *, void *, QmlRefCount *, QObject *, const QUrl &, int);
QmlExpressionData *data;
@@ -150,6 +150,8 @@ public:
static QmlExpressionPrivate *get(QmlExpression *expr) {
return static_cast<QmlExpressionPrivate *>(QObjectPrivate::get(expr));
}
+
+ static void printException(QScriptEngine *);
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h
index 88dff2d..5265d42 100644
--- a/src/declarative/qml/qmlinstruction_p.h
+++ b/src/declarative/qml/qmlinstruction_p.h
@@ -246,6 +246,8 @@ public:
} storeString;
struct {
int value;
+ int fileName;
+ int lineNumber;
} storeScript;
struct {
int propertyIndex;
diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp
index 7a7e074..8643301 100644
--- a/src/declarative/qml/qmlmetaproperty.cpp
+++ b/src/declarative/qml/qmlmetaproperty.cpp
@@ -698,30 +698,6 @@ QVariant QmlMetaProperty::read() const
return QVariant();
}
-void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value)
-{
- QString expr = value.toString();
- const QObjectList &children = object->children();
-
- for (int ii = 0; ii < children.count(); ++ii) {
- QmlBoundSignal *sig = QmlBoundSignal::cast(children.at(ii));
- if (sig && sig->index() == core.coreIndex) {
- if (expr.isEmpty()) {
- sig->disconnect();
- sig->deleteLater();
- } else {
- sig->expression()->setExpression(expr);
- }
- return;
- }
- }
-
- if (!expr.isEmpty()) {
- // XXX scope
- (void *)new QmlBoundSignal(qmlContext(object), expr, object, q->method(), object);
- }
-}
-
QVariant QmlMetaPropertyPrivate::readValueProperty()
{
uint type = q->type();
@@ -1001,11 +977,7 @@ void QmlMetaProperty::write(const QVariant &value, QmlMetaProperty::WriteFlags f
if (!d->object)
return;
- if (type() & SignalProperty) {
-
- d->writeSignalProperty(value);
-
- } else if (d->core.isValid()) {
+ if (type() & Property && d->core.isValid()) {
d->writeValueProperty(value, flags);
diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h
index a856b90..b74aa2d 100644
--- a/src/declarative/qml/qmlmetaproperty_p.h
+++ b/src/declarative/qml/qmlmetaproperty_p.h
@@ -96,8 +96,6 @@ public:
int propertyType() const;
QmlMetaProperty::PropertyCategory propertyCategory() const;
- void writeSignalProperty(const QVariant &);
-
QVariant readValueProperty();
void writeValueProperty(const QVariant &, QmlMetaProperty::WriteFlags);
static bool writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object, const QVariant &value, int flags);
diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h
index e11e164..88d7d77 100644
--- a/src/declarative/qml/qmlparser_p.h
+++ b/src/declarative/qml/qmlparser_p.h
@@ -168,6 +168,8 @@ namespace QmlParser
// Script blocks that were nested under this object
QStringList scriptBlocks;
+ QStringList scriptBlocksFile;
+ QList<int> scriptBlocksLineNumber;
// The bytes to cast instances by to get to the QmlParserStatus
// interface. -1 indicates the type doesn't support this interface.
diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h
index f1b1219..91b0c53 100644
--- a/src/declarative/qml/qmlpropertycache_p.h
+++ b/src/declarative/qml/qmlpropertycache_p.h
@@ -132,7 +132,7 @@ QmlPropertyCache::Data::Data()
{
}
-bool QmlPropertyCache::Data::operator==(const QmlPropertyCache::Data::Data &other)
+bool QmlPropertyCache::Data::operator==(const QmlPropertyCache::Data &other)
{
return flags == other.flags &&
propType == other.propType &&
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
index 93c02b3..d4921b6 100644
--- a/src/declarative/qml/qmlvme.cpp
+++ b/src/declarative/qml/qmlvme.cpp
@@ -549,7 +549,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
case QmlInstruction::StoreScript:
{
QObject *target = stack.top();
- cp->addScript(primitives.at(instr.storeScript.value), target);
+ cp->addScript(primitives.at(instr.storeScript.value), target,
+ primitives.at(instr.storeScript.fileName),
+ instr.storeScript.lineNumber);
}
break;
@@ -579,12 +581,11 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
if (stack.count() == 1 && bindingSkipList.testBit(coreIndex))
break;
- QmlBinding *bind = new QmlBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, 0);
+ QmlBinding *bind = new QmlBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, comp->url, instr.line, 0);
bindValues.append(bind);
bind->m_mePtr = &bindValues.values[bindValues.count - 1];
bind->setTarget(mp);
bind->addToObject(target);
- bind->setSourceLocation(comp->url, instr.line);
}
break;
diff --git a/tests/auto/declarative/qmlecmascript/data/scope.2.qml b/tests/auto/declarative/qmlecmascript/data/scope.2.qml
new file mode 100644
index 0000000..433a22e
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/scope.2.qml
@@ -0,0 +1,42 @@
+import Qt 4.6
+
+Item {
+ property int a: 0
+ property int b: 0
+
+ Script {
+ function b() { return 11; }
+ function c() { return 33; }
+ }
+
+ Object {
+ id: a
+ property int value: 19
+ }
+
+ Object {
+ id: c
+ property int value: 24
+ }
+
+ Object {
+ id: nested
+ property int a: 1
+ property int test: a.value
+ property int test2: b()
+ property int test3: c.value
+ }
+
+
+ // id takes precedence over local, and root properties
+ property int test1: a.value
+ property alias test2: nested.test
+
+ // methods takes precedence over local, and root properties
+ property int test3: b()
+ property alias test4: nested.test2
+
+ // id takes precedence over methods
+ property int test5: c.value
+ property alias test6: nested.test3
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/scriptErrors.js b/tests/auto/declarative/qmlecmascript/data/scriptErrors.js
new file mode 100644
index 0000000..1d7b357
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/scriptErrors.js
@@ -0,0 +1,2 @@
+// Comment
+a = 10
diff --git a/tests/auto/declarative/qmlecmascript/data/scriptErrors.qml b/tests/auto/declarative/qmlecmascript/data/scriptErrors.qml
new file mode 100644
index 0000000..3fb8ff7
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/scriptErrors.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+
+Object {
+ Script { source: "scriptErrors.js" }
+ Script { function getValue() { a = 10; return 0; } }
+
+ property int x: a.value
+ property int y: getValue();
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp
index dde3bb7..5e04f7c 100644
--- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp
+++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp
@@ -61,6 +61,7 @@ private slots:
void objectToString();
void selfDeletingBinding();
void extendedObjectPropertyLookup();
+ void scriptErrors();
private:
QmlEngine engine;
@@ -537,20 +538,35 @@ void tst_qmlecmascript::nonExistantAttachedObject()
void tst_qmlecmascript::scope()
{
- QmlComponent component(&engine, TEST_FILE("scope.qml"));
- QObject *object = component.create();
- QVERIFY(object != 0);
+ {
+ QmlComponent component(&engine, TEST_FILE("scope.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test1").toInt(), 1);
+ QCOMPARE(object->property("test2").toInt(), 2);
+ QCOMPARE(object->property("test3").toString(), QString("1Test"));
+ QCOMPARE(object->property("test4").toString(), QString("2Test"));
+ QCOMPARE(object->property("test5").toInt(), 1);
+ QCOMPARE(object->property("test6").toInt(), 1);
+ QCOMPARE(object->property("test7").toInt(), 2);
+ QCOMPARE(object->property("test8").toInt(), 2);
+ QCOMPARE(object->property("test9").toInt(), 1);
+ QCOMPARE(object->property("test10").toInt(), 3);
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("scope.2.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
- QCOMPARE(object->property("test1").toInt(), 1);
- QCOMPARE(object->property("test2").toInt(), 2);
- QCOMPARE(object->property("test3").toString(), QString("1Test"));
- QCOMPARE(object->property("test4").toString(), QString("2Test"));
- QCOMPARE(object->property("test5").toInt(), 1);
- QCOMPARE(object->property("test6").toInt(), 1);
- QCOMPARE(object->property("test7").toInt(), 2);
- QCOMPARE(object->property("test8").toInt(), 2);
- QCOMPARE(object->property("test9").toInt(), 1);
- QCOMPARE(object->property("test10").toInt(), 3);
+ QCOMPARE(object->property("test1").toInt(), 19);
+ QCOMPARE(object->property("test2").toInt(), 19);
+ QCOMPARE(object->property("test3").toInt(), 11);
+ QCOMPARE(object->property("test4").toInt(), 11);
+ QCOMPARE(object->property("test5").toInt(), 24);
+ QCOMPARE(object->property("test6").toInt(), 24);
+ }
}
/*
@@ -724,6 +740,25 @@ void tst_qmlecmascript::extendedObjectPropertyLookup()
QVERIFY(object != 0);
}
+/*
+Test file/lineNumbers for binding/Script errors.
+*/
+void tst_qmlecmascript::scriptErrors()
+{
+ QmlComponent component(&engine, TEST_FILE("scriptErrors.qml"));
+ QString url = component.url().toString();
+
+ QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
+ QString warning2 = url + ":7: TypeError: Result of expression 'a' [undefined] is not an object.";
+ QString warning3 = url + ":5: Error: Invalid write to global property \"a\"";
+
+ QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
+ QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
+ QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+}
+
QTEST_MAIN(tst_qmlecmascript)
#include "tst_qmlecmascript.moc"
diff --git a/tests/auto/declarative/qmllanguage/data/Alias2.qml b/tests/auto/declarative/qmllanguage/data/Alias2.qml
new file mode 100644
index 0000000..b7e81a5
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/Alias2.qml
@@ -0,0 +1,9 @@
+import Test 1.0
+import Qt 4.6
+
+Object {
+ property var other
+ other: MyTypeObject { id: obj }
+ property alias enumAlias: obj.enumProperty;
+}
+
diff --git a/tests/auto/declarative/qmllanguage/data/alias.4.qml b/tests/auto/declarative/qmllanguage/data/alias.4.qml
new file mode 100644
index 0000000..bd6a769
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/alias.4.qml
@@ -0,0 +1,6 @@
+import Test 1.0
+
+Alias2 {
+ enumAlias: MyTypeObject.EnumVal2
+}
+
diff --git a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp
index 3825b62..135a207 100644
--- a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp
+++ b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp
@@ -612,6 +612,15 @@ void tst_qmllanguage::aliasProperties()
delete object;
}
+ // Enum aliases
+ {
+ QmlComponent component(&engine, TEST_FILE("alias.4.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("enumAlias").toInt(), 1);
+ }
}
class TestType : public QObject {