summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demos/declarative/contacts/Button.qml57
-rw-r--r--demos/declarative/contacts/Contact.qml93
-rw-r--r--demos/declarative/contacts/ContactField.qml60
-rw-r--r--demos/declarative/contacts/FieldText.qml160
-rw-r--r--demos/declarative/contacts/RemoveButton.qml120
-rw-r--r--demos/declarative/contacts/SearchBar.qml24
-rw-r--r--demos/declarative/contacts/contacts.qml266
-rw-r--r--demos/declarative/contacts/contacts.sqlitebin0 -> 86016 bytes
-rw-r--r--demos/declarative/contacts/pics/cancel.pngbin0 -> 1038 bytes
-rw-r--r--demos/declarative/contacts/pics/email.pngbin0 -> 977 bytes
-rw-r--r--demos/declarative/contacts/pics/new.pngbin0 -> 688 bytes
-rw-r--r--demos/declarative/contacts/pics/ok.pngbin0 -> 655 bytes
-rw-r--r--demos/declarative/contacts/pics/phone.pngbin0 -> 624 bytes
-rw-r--r--demos/declarative/contacts/pics/search.pngbin0 -> 635 bytes
-rw-r--r--demos/declarative/contacts/pics/trash.pngbin0 -> 989 bytes
-rw-r--r--examples/declarative/tutorials/contacts/Final/Button.qml38
-rw-r--r--examples/declarative/tutorials/contacts/Final/Contact.qml57
-rw-r--r--examples/declarative/tutorials/contacts/Final/ContactField.qml36
-rw-r--r--examples/declarative/tutorials/contacts/Final/ContactView2.qml62
-rw-r--r--examples/declarative/tutorials/contacts/Final/FieldText.qml98
-rw-r--r--examples/declarative/tutorials/contacts/Final/RemoveButton.qml80
-rw-r--r--examples/declarative/tutorials/contacts/Final/SearchBar.qml18
-rw-r--r--examples/declarative/tutorials/contacts/Final/contacts.qml148
-rw-r--r--src/declarative/canvas/qsimplecanvas.cpp11
-rw-r--r--src/declarative/canvas/qsimplecanvas.h2
-rw-r--r--src/declarative/canvas/qsimplecanvas_software.cpp5
-rw-r--r--src/declarative/canvas/qsimplecanvasitem.cpp8
-rw-r--r--src/declarative/canvas/qsimplecanvasitem.h11
-rw-r--r--src/declarative/canvas/qsimplecanvasitem_p.h25
-rw-r--r--src/declarative/debugger/debugger.pri8
-rw-r--r--src/declarative/debugger/qmldebugger.cpp183
-rw-r--r--src/declarative/debugger/qmldebugger.h15
-rw-r--r--src/declarative/debugger/qmldebuggerstatus.cpp54
-rw-r--r--src/declarative/debugger/qmldebuggerstatus.h67
-rw-r--r--src/declarative/debugger/qmlpropertyview.cpp121
-rw-r--r--src/declarative/debugger/qmlpropertyview_p.h70
-rw-r--r--src/declarative/fx/qfxkeyproxy.cpp4
-rw-r--r--src/declarative/fx/qfxtextedit.cpp24
-rw-r--r--src/declarative/fx/qfxtextedit.h3
-rw-r--r--src/declarative/qml/qmlengine.cpp36
-rw-r--r--src/declarative/qml/qmlengine_p.h11
-rw-r--r--src/declarative/qml/qmlmetaproperty.cpp12
-rw-r--r--src/declarative/qml/qmlmetaproperty.h1
43 files changed, 1381 insertions, 607 deletions
diff --git a/demos/declarative/contacts/Button.qml b/demos/declarative/contacts/Button.qml
new file mode 100644
index 0000000..d9f1236
--- /dev/null
+++ b/demos/declarative/contacts/Button.qml
@@ -0,0 +1,57 @@
+Item {
+ id: button
+ width: 30
+ height: 30
+ property var icon: ""
+ signal clicked
+ Rect {
+ id: buttonRect
+ anchors.fill: parent
+ color: "lightgreen"
+ radius: 5
+ Image {
+ id: iconImage
+ source: button.icon
+ anchors.horizontalCenter: buttonRect.horizontalCenter
+ anchors.verticalCenter: buttonRect.verticalCenter
+ }
+ MouseRegion {
+ id: buttonMouseRegion
+ anchors.fill: buttonRect
+ onClicked: { button.clicked.emit() }
+ }
+ states: [
+ State {
+ name: "pressed"
+ when: buttonMouseRegion.pressed == true
+ SetProperty {
+ target: buttonRect
+ property: "color"
+ value: "green"
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "pressed"
+ ColorAnimation {
+ duration: 200
+ }
+ },
+ Transition {
+ fromState: "pressed"
+ toState: "*"
+ ColorAnimation {
+ duration: 1000
+ }
+ }
+ ]
+ }
+ opacity: Behaviour {
+ NumericAnimation {
+ property: "opacity"
+ duration: 250
+ }
+ }
+}
diff --git a/demos/declarative/contacts/Contact.qml b/demos/declarative/contacts/Contact.qml
new file mode 100644
index 0000000..342c356
--- /dev/null
+++ b/demos/declarative/contacts/Contact.qml
@@ -0,0 +1,93 @@
+Item {
+ id: contactDetails
+ anchors.fill: parent
+
+ property var contactId: ""
+ property var label: ""
+ property var phone: ""
+ property var email: ""
+
+ onLabelChanged: { labelField.value = label }
+ onEmailChanged: { emailField.value = email }
+ onPhoneChanged: { phoneField.value = phone }
+
+ resources: [
+ SqlQuery {
+ id: updateContactQuery
+ connection: contactDatabase
+ query: "UPDATE contacts SET label = :l, email = :e, phone = :p WHERE recid = :r"
+ bindings: SqlBind {
+ name: ":r"
+ value: contactId
+ }
+ bindings: SqlBind {
+ name: ":l"
+ value: labelField.value
+ }
+ bindings: SqlBind {
+ name: ":e"
+ value: emailField.value
+ }
+ bindings: SqlBind {
+ name: ":p"
+ value: phoneField.value
+ }
+ },
+ SqlQuery {
+ id: insertContactQuery
+ connection: contactDatabase
+ query: "INSERT INTO contacts (label, email, phone) VALUES(:l, :e, :p)"
+ bindings: SqlBind {
+ name: ":l"
+ value: labelField.value
+ }
+ bindings: SqlBind {
+ name: ":e"
+ value: emailField.value
+ }
+ bindings: SqlBind {
+ name: ":p"
+ value: phoneField.value
+ }
+ }
+
+ ]
+ function update() {
+ updateContactQuery.exec();
+ }
+ function insert() {
+ insertContactQuery.exec();
+ }
+ VerticalLayout {
+ id: layout
+ anchors.fill: parent
+ spacing: 5
+ margin: 5
+ ContactField {
+ id: labelField
+ anchors.left: layout.left
+ anchors.leftMargin: 5
+ anchors.right: layout.right
+ anchors.rightMargin: 5
+ label: "Name"
+ }
+ ContactField {
+ id: phoneField
+ anchors.left: layout.left
+ anchors.leftMargin: 5
+ anchors.right: layout.right
+ anchors.rightMargin: 5
+ icon: "pics/phone.png"
+ label: "Phone"
+ }
+ ContactField {
+ id: emailField
+ anchors.left: layout.left
+ anchors.leftMargin: 5
+ anchors.right: layout.right
+ anchors.rightMargin: 5
+ icon: "pics/email.png"
+ label: "Email"
+ }
+ }
+}
diff --git a/demos/declarative/contacts/ContactField.qml b/demos/declarative/contacts/ContactField.qml
new file mode 100644
index 0000000..3ce2c1a
--- /dev/null
+++ b/demos/declarative/contacts/ContactField.qml
@@ -0,0 +1,60 @@
+Item {
+ id: contactField
+ clip: true
+ height: 30
+ property var label: "Name"
+ property var icon: "pics/phone.png"
+ property var value: ""
+ onValueChanged: { fieldText.text=field.value }
+ RemoveButton {
+ id: removeButton
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ expandedWidth: contactField.width
+ onConfirmed: { print('Clear field text'); fieldText.text='' }
+ }
+ FieldText {
+ id: fieldText
+ width: contactField.width-70
+ anchors.right: removeButton.left
+ anchors.rightMargin: 5
+ anchors.verticalCenter: parent.verticalCenter
+ label: contactField.label
+ text: contactField.value
+ onConfirmed: { contactField.value=fieldText.text }
+ }
+ Image {
+ anchors.right: fieldText.left
+ anchors.rightMargin: 5
+ anchors.verticalCenter: parent.verticalCenter
+ source: contactField.icon
+ }
+ states: [
+ State {
+ name: "editingText"
+ when: fieldText.state == 'editing'
+ SetProperty {
+ target: removeButton.anchors
+ property: "rightMargin"
+ value: -35
+ }
+ SetProperty {
+ target: fieldText
+ property: "width"
+ value: contactField.width
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: ""
+ toState: "*"
+ reversible: true
+ NumericAnimation {
+ properties: "width,rightMargin"
+ duration: 200
+ }
+ }
+ ]
+}
diff --git a/demos/declarative/contacts/FieldText.qml b/demos/declarative/contacts/FieldText.qml
new file mode 100644
index 0000000..eb18ef2
--- /dev/null
+++ b/demos/declarative/contacts/FieldText.qml
@@ -0,0 +1,160 @@
+Rect {
+ id: fieldText
+ height: 30
+ radius: 5
+ color: "black"
+ property var text: ""
+ property var label: ""
+ onTextChanged: { reset() }
+ signal confirmed
+ resources: [
+ Script {
+
+ function edit() {
+ if (!contacts.mouseGrabbed) {
+ fieldText.state='editing';
+ contacts.mouseGrabbed=true;
+ }
+ }
+ function confirm() {
+ fieldText.text = textEdit.text;
+ fieldText.state='';
+ contacts.mouseGrabbed=false;
+ fieldText.confirmed.emit();
+ }
+ function reset() {
+ textEdit.text = fieldText.text;
+ fieldText.state='';
+ contacts.mouseGrabbed=false;
+ }
+
+ }
+ ]
+ Image {
+ id: cancelIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "pics/cancel.png"
+ opacity: 0
+ }
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "pics/ok.png"
+ opacity: 0
+ }
+ TextEdit {
+ id: textEdit
+ anchors.left: parent.left
+ anchors.leftMargin: 0
+ anchors.right: parent.right
+ anchors.rightMargin: 0
+ anchors.verticalCenter: parent.verticalCenter
+ color: "white"
+ font.bold: true
+ readOnly: true
+ wrap: false
+ }
+ Text {
+ id: textLabel
+ x: 5
+ width: parent.width-10
+ anchors.verticalCenter: parent.verticalCenter
+ hAlign: "AlignHCenter"
+ color: contactDetails.state == "editing" ? "#505050" : "#AAAAAA"
+ font.italic: true
+ font.bold: true
+ text: fieldText.label
+ opacity: textEdit.text == '' ? 1 : 0
+ opacity: Behaviour {
+ NumericAnimation {
+ property: "opacity"
+ duration: 250
+ }
+ }
+ }
+ MouseRegion {
+ anchors.fill: cancelIcon
+ onClicked: { reset() }
+ }
+ MouseRegion {
+ anchors.fill: confirmIcon
+ onClicked: { confirm() }
+ }
+ MouseRegion {
+ id: editRegion
+ anchors.fill: textEdit
+ onClicked: { edit() }
+ }
+ states: [
+ State {
+ name: "editing"
+ SetProperty {
+ target: confirmIcon
+ property: "opacity"
+ value: 1
+ }
+ SetProperty {
+ target: cancelIcon
+ property: "opacity"
+ value: 1
+ }
+ SetProperty {
+ target: fieldText
+ property: "color"
+ value: "white"
+ }
+ SetProperty {
+ target: textEdit
+ property: "color"
+ value: "black"
+ }
+ SetProperty {
+ target: textEdit
+ property: "readOnly"
+ value: false
+ }
+ SetProperty {
+ target: textEdit
+ property: "focus"
+ value: true
+ }
+ SetProperty {
+ target: editRegion
+ property: "opacity"
+ value: 0
+ }
+ SetProperty {
+ target: textEdit.anchors
+ property: "leftMargin"
+ value: 34
+ }
+ SetProperty {
+ target: textEdit.anchors
+ property: "rightMargin"
+ value: 34
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: ""
+ toState: "*"
+ reversible: true
+ NumericAnimation {
+ properties: "opacity,leftMargin,rightMargin"
+ duration: 200
+ }
+ ColorAnimation {
+ duration: 150
+ }
+ }
+ ]
+}
diff --git a/demos/declarative/contacts/RemoveButton.qml b/demos/declarative/contacts/RemoveButton.qml
new file mode 100644
index 0000000..114db2e
--- /dev/null
+++ b/demos/declarative/contacts/RemoveButton.qml
@@ -0,0 +1,120 @@
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+ property var expandedWidth: 230
+ signal confirmed
+ resources: [
+ Script {
+ function toggle() {
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ contacts.mouseGrabbed=false;
+ } else {
+ if (!contacts.mouseGrabbed) {
+ removeButton.state = 'opened';
+ contacts.mouseGrabbed=true;
+ }
+ }
+ }
+ }
+ ]
+ Image {
+ id: trashIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "pics/trash.png"
+ opacity: 1
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: cancelIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "pics/cancel.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle() }
+ }
+ }
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "pics/ok.png"
+ opacity: 0
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle(); removeButton.confirmed.emit() }
+ }
+ }
+ Text {
+ id: text
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: confirmIcon.right
+ anchors.leftMargin: 4
+ anchors.right: cancelIcon.left
+ anchors.rightMargin: 4
+ font.bold: true
+ color: "white"
+ hAlign: "AlignHCenter"
+ text: "Remove"
+ opacity: 0
+ }
+ states: [
+ State {
+ name: "opened"
+ SetProperty {
+ target: removeButton
+ property: "width"
+ value: removeButton.expandedWidth
+ }
+ SetProperty {
+ target: text
+ property: "opacity"
+ value: 1
+ }
+ SetProperty {
+ target: confirmIcon
+ property: "opacity"
+ value: 1
+ }
+ SetProperty {
+ target: cancelIcon
+ property: "opacity"
+ value: 1
+ }
+ SetProperty {
+ target: trashIcon
+ property: "opacity"
+ value: 0
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "opened"
+ reversible: true
+ NumericAnimation {
+ properties: "opacity,x,width"
+ duration: 200
+ }
+ }
+ ]
+}
diff --git a/demos/declarative/contacts/SearchBar.qml b/demos/declarative/contacts/SearchBar.qml
new file mode 100644
index 0000000..3ee2665
--- /dev/null
+++ b/demos/declarative/contacts/SearchBar.qml
@@ -0,0 +1,24 @@
+Rect {
+ id: searchBar
+ color: "white"
+ property var text: searchEdit.text
+ Image {
+ id: searchIcon
+ anchors.left: parent.left
+ anchors.leftMargin: 5
+ anchors.verticalCenter: parent.verticalCenter
+ source: "pics/search.png"
+ }
+ TextEdit {
+ id: searchEdit
+ anchors.left: searchIcon.right
+ anchors.right: parent.right
+ anchors.leftMargin: 5
+ anchors.rightMargin: 5
+ anchors.verticalCenter: parent.verticalCenter
+ readOnly: false
+ wrap: false
+ focus: true
+ text: ""
+ }
+}
diff --git a/demos/declarative/contacts/contacts.qml b/demos/declarative/contacts/contacts.qml
new file mode 100644
index 0000000..ce5a2b5
--- /dev/null
+++ b/demos/declarative/contacts/contacts.qml
@@ -0,0 +1,266 @@
+Rect {
+ id: contacts
+ width: 240
+ height: 320
+ color: "black"
+ property var mode: "list"
+ property var mouseGrabbed: false
+ resources: [
+ SqlConnection {
+ id: contactDatabase
+ name: "qmlConnection"
+ driver: "QSQLITE"
+ databaseName: "contacts.sqlite"
+ },
+ SqlQuery {
+ id: contactList
+ connection: contactDatabase
+ query: "SELECT recid, label, email, phone FROM contacts WHERE lower(label) LIKE lower(:searchTerm) ORDER BY label, recid"
+ bindings: SqlBind {
+ name: ":searchTerm"
+ value: '%' + searchBar.text + '%'
+ }
+ },
+ Component {
+ id: contactDelegate
+ Item {
+ id: wrapper
+ x: 0
+ width: ListView.view.width
+ height: 34
+ Text {
+ id: label
+ x: 40
+ y: 12
+ width: parent.width-30
+ text: model.label
+ color: "white"
+ font.bold: true
+ children: [
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { Details.qml = 'Contact.qml';
+ wrapper.state='opened';
+ contacts.mode = 'edit'; }
+ }
+ ]
+ }
+ Item {
+ id: Details
+ anchors.fill: wrapper
+ opacity: 0
+ Bind {
+ target: Details.qmlItem
+ property: "contactId"
+ value: model.recid
+ }
+ Bind {
+ target: Details.qmlItem
+ property: "label"
+ value: model.label
+ }
+ Bind {
+ target: Details.qmlItem
+ property: "phone"
+ value: model.phone
+ }
+ Bind {
+ target: Details.qmlItem
+ property: "email"
+ value: model.email
+ }
+ }
+ states: [
+ State {
+ name: "opened"
+ SetProperty {
+ target: wrapper
+ property: "height"
+ value: contactListView.height
+ }
+ SetProperty {
+ target: contactListView
+ property: "yPosition"
+ value: wrapper.y
+ }
+ SetProperty {
+ target: contactListView
+ property: "locked"
+ value: 1
+ }
+ SetProperty {
+ target: label
+ property: "opacity"
+ value: 0
+ }
+ SetProperty {
+ target: Details
+ property: "opacity"
+ value: 1
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumericAnimation {
+ duration: 500
+ properties: "yPosition,height,opacity"
+ }
+ }
+ ]
+ Connection {
+ sender: confirmEditButton
+ signal: "clicked()"
+ script: {
+ if (wrapper.state == 'opened' && !contacts.mouseGrabbed) {
+ Details.qmlItem.update();
+ wrapper.state = '';
+ contacts.mode = 'list';
+ contactList.exec();
+ }
+
+ }
+ }
+ Connection {
+ sender: cancelEditButton
+ signal: "clicked()"
+ script: {
+ if (wrapper.state == 'opened' && !contacts.mouseGrabbed) {
+ wrapper.state = '';
+ contacts.mode = 'list';
+ }
+
+ }
+ }
+ }
+ }
+ ]
+ Button {
+ id: newContactButton
+ anchors.top: parent.top
+ anchors.topMargin: 5
+ anchors.right: parent.right
+ anchors.rightMargin: 5
+ icon: "pics/new.png"
+ onClicked: { print("open new contact edit"); newContactItem.label = ''; newContactItem.phone = ''; newContactItem.email = ''; contacts.mode = 'new' }
+ opacity: contacts.mode == 'list' ? 1 : 0
+ }
+ Button {
+ id: confirmEditButton
+ anchors.top: parent.top
+ anchors.topMargin: 5
+ anchors.left: parent.left
+ anchors.leftMargin: 5
+ icon: "pics/ok.png"
+ opacity: contacts.mode == 'list' || contacts.mouseGrabbed ? 0 : 1
+ }
+ Button {
+ id: cancelEditButton
+ anchors.top: parent.top
+ anchors.topMargin: 5
+ anchors.right: parent.right
+ anchors.rightMargin: 5
+ icon: "pics/cancel.png"
+ opacity: contacts.mode == 'list' || contacts.mouseGrabbed ? 0 : 1
+ }
+ ListView {
+ id: contactListView
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: cancelEditButton.bottom
+ anchors.bottom: searchBarWrapper.bottom
+ clip: true
+ model: contactList
+ delegate: contactDelegate
+ focus: false
+ }
+ Contact {
+ id: newContactItem
+ anchors.fill: contactListView
+ opacity: 0
+ }
+ Connection {
+ sender: confirmEditButton
+ signal: "clicked()"
+ script: {
+ if (contacts.mode == 'new' && contacts.mouseGrabbed != 'true') {
+ newContactItem.insert();
+ contacts.mode = 'list';
+ contactList.exec();
+ }
+ }
+ }
+ Connection {
+ sender: cancelEditButton
+ signal: "clicked()"
+ script: {
+ if (contacts.mode == 'new' && contacts.mouseGrabbed != 'true') {
+ contacts.mode = 'list';
+ }
+ }
+ }
+ FocusRealm {
+ id: searchBarWrapper
+ height: 30
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottomMargin: 0
+ focus: false
+ SearchBar {
+ id: searchBar
+ anchors.fill: parent
+ }
+ states: [
+ State {
+ name: "searchHidden"
+ when: searchBar.text == '' || contacts.mode != 'list'
+ SetProperty {
+ target: searchBarWrapper.anchors
+ property: "bottomMargin"
+ value: -30
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "*"
+ NumericAnimation {
+ property: "bottomMargin"
+ duration: 250
+ }
+ }
+ ]
+ }
+ KeyProxy {
+ focus: true
+ targets: { contacts.mode == "list" ? [searchBarWrapper, contactListView] : [contactListView]}
+ }
+ states: [
+ State {
+ name: "editNewState"
+ when: contacts.mode == 'new'
+ SetProperty {
+ target: contactListView
+ property: "opacity"
+ value: 0
+ }
+ SetProperty {
+ target: newContactItem
+ property: "opacity"
+ value: 1
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "*"
+ NumericAnimation {
+ property: "opacity"
+ duration: 500
+ }
+ }
+ ]
+}
diff --git a/demos/declarative/contacts/contacts.sqlite b/demos/declarative/contacts/contacts.sqlite
new file mode 100644
index 0000000..d33e0c7
--- /dev/null
+++ b/demos/declarative/contacts/contacts.sqlite
Binary files differ
diff --git a/demos/declarative/contacts/pics/cancel.png b/demos/declarative/contacts/pics/cancel.png
new file mode 100644
index 0000000..ecc9533
--- /dev/null
+++ b/demos/declarative/contacts/pics/cancel.png
Binary files differ
diff --git a/demos/declarative/contacts/pics/email.png b/demos/declarative/contacts/pics/email.png
new file mode 100644
index 0000000..04b3865
--- /dev/null
+++ b/demos/declarative/contacts/pics/email.png
Binary files differ
diff --git a/demos/declarative/contacts/pics/new.png b/demos/declarative/contacts/pics/new.png
new file mode 100644
index 0000000..c7ebac3
--- /dev/null
+++ b/demos/declarative/contacts/pics/new.png
Binary files differ
diff --git a/demos/declarative/contacts/pics/ok.png b/demos/declarative/contacts/pics/ok.png
new file mode 100644
index 0000000..5795f04
--- /dev/null
+++ b/demos/declarative/contacts/pics/ok.png
Binary files differ
diff --git a/demos/declarative/contacts/pics/phone.png b/demos/declarative/contacts/pics/phone.png
new file mode 100644
index 0000000..fc9c222
--- /dev/null
+++ b/demos/declarative/contacts/pics/phone.png
Binary files differ
diff --git a/demos/declarative/contacts/pics/search.png b/demos/declarative/contacts/pics/search.png
new file mode 100644
index 0000000..cc74e69
--- /dev/null
+++ b/demos/declarative/contacts/pics/search.png
Binary files differ
diff --git a/demos/declarative/contacts/pics/trash.png b/demos/declarative/contacts/pics/trash.png
new file mode 100644
index 0000000..2042595
--- /dev/null
+++ b/demos/declarative/contacts/pics/trash.png
Binary files differ
diff --git a/examples/declarative/tutorials/contacts/Final/Button.qml b/examples/declarative/tutorials/contacts/Final/Button.qml
deleted file mode 100644
index 14965b5..0000000
--- a/examples/declarative/tutorials/contacts/Final/Button.qml
+++ /dev/null
@@ -1,38 +0,0 @@
-<Item id="button" width="30" height="30">
- <properties>
- <Property name="icon"/>
- </properties>
- <signals>
- <Signal name="clicked"/>
- </signals>
- <Rect id="buttonRect"
- anchors.fill="{parent}"
- color="lightgreen"
- radius="5">
- <Image id="iconImage"
- source="{button.icon}"
- anchors.horizontalCenter="{buttonRect.horizontalCenter}"
- anchors.verticalCenter="{buttonRect.verticalCenter}"/>
- <MouseRegion id="buttonMouseRegion"
- anchors.fill="{buttonRect}"
- onClicked="button.clicked.emit()"/>
- <states>
- <State name="pressed" when="{buttonMouseRegion.pressed == true}">
- <SetProperty target="{buttonRect}" property="color" value="green"/>
- </State>
- </states>
- <transitions>
- <Transition fromState="*" toState="pressed">
- <ColorAnimation duration="200"/>
- </Transition>
- <Transition fromState="pressed" toState="*">
- <ColorAnimation duration="1000"/>
- </Transition>
- </transitions>
- </Rect>
- <opacity>
- <Behaviour>
- <NumericAnimation property="opacity" duration="250"/>
- </Behaviour>
- </opacity>
-</Item>
diff --git a/examples/declarative/tutorials/contacts/Final/Contact.qml b/examples/declarative/tutorials/contacts/Final/Contact.qml
deleted file mode 100644
index 679f4a8..0000000
--- a/examples/declarative/tutorials/contacts/Final/Contact.qml
+++ /dev/null
@@ -1,57 +0,0 @@
-<Item id="contactDetails"
- anchors.fill="{parent}">
- <properties>
- <Property name="contactid" value=""/>
- <Property name="label" onValueChanged="labelField.value = label"/>
- <Property name="phone" onValueChanged="phoneField.value = phone"/>
- <Property name="email" onValueChanged="emailField.value = email"/>
- </properties>
- <signals>
- <Signal name="update"/>
- <Signal name="insert"/>
- </signals>
- <resources>
- <SqlQuery id="updateContactQuery" connection="{contactDatabase}">
- <query>UPDATE contacts SET label = :l, email = :e, phone = :p WHERE recid = :r</query>
- <bindings>
- <SqlBind name=":r" value="{contactid}"/>
- <SqlBind name=":l" value="{labelField.value}"/>
- <SqlBind name=":e" value="{emailField.value}"/>
- <SqlBind name=":p" value="{phoneField.value}"/>
- </bindings>
- </SqlQuery>
- <SqlQuery id="insertContactQuery" connection="{contactDatabase}">
- <query>INSERT INTO contacts (label, email, phone) VALUES(:l, :e, :p)</query>
- <bindings>
- <SqlBind name=":l" value="{labelField.value}"/>
- <SqlBind name=":e" value="{emailField.value}"/>
- <SqlBind name=":p" value="{phoneField.value}"/>
- </bindings>
- </SqlQuery>
- </resources>
- <Connection sender="{contactDetails}" signal="update()">
- updateContactQuery.exec();
- </Connection>
- <Connection sender="{contactDetails}" signal="insert()">
- insertContactQuery.exec();
- </Connection>
- <VerticalLayout id="layout"
- anchors.fill="{parent}"
- spacing="5"
- margin="5">
- <ContactField id="labelField"
- anchors.left="{layout.left}" anchors.leftMargin="5"
- anchors.right="{layout.right}" anchors.rightMargin="5"
- label="Name"/>
- <ContactField id="phoneField"
- anchors.left="{layout.left}" anchors.leftMargin="5"
- anchors.right="{layout.right}" anchors.rightMargin="5"
- icon="../shared/pics/phone.png"
- label="Phone"/>
- <ContactField id="emailField"
- anchors.left="{layout.left}" anchors.leftMargin="5"
- anchors.right="{layout.right}" anchors.rightMargin="5"
- icon="../shared/pics/email.png"
- label="Email"/>
- </VerticalLayout>
-</Item>
diff --git a/examples/declarative/tutorials/contacts/Final/ContactField.qml b/examples/declarative/tutorials/contacts/Final/ContactField.qml
deleted file mode 100644
index 80ffd30..0000000
--- a/examples/declarative/tutorials/contacts/Final/ContactField.qml
+++ /dev/null
@@ -1,36 +0,0 @@
-<Item id="contactField"
- clip="true"
- height="30">
- <properties>
- <Property name="label"/>
- <Property name="icon"/>
- <Property name="value" onValueChanged="fieldText.text=field.value"/>
- </properties>
- <RemoveButton id="removeButton"
- anchors.right="{parent.right}"
- anchors.top="{parent.top}" anchors.bottom="{parent.bottom}"
- expandedWidth="{contactField.width}"
- onConfirmed="print('Clear field text'); fieldText.text=''"/>
- <FieldText id="fieldText"
- width="{contactField.width-70}"
- anchors.right="{removeButton.left}" anchors.rightMargin="5"
- anchors.verticalCenter="{parent.verticalCenter}"
- label="{contactField.label}"
- text="{contactField.value}"
- onConfirmed="contactField.value=fieldText.text"/>
- <Image
- anchors.right="{fieldText.left}" anchors.rightMargin="5"
- anchors.verticalCenter="{parent.verticalCenter}"
- source="{contactField.icon}"/>
- <states>
- <State name="editingText" when="{fieldText.state == 'editing'}">
- <SetProperty target="{removeButton.anchors}" property="rightMargin" value="-35"/>
- <SetProperty target="{fieldText}" property="width" value="{contactField.width}"/>
- </State>
- </states>
- <transitions>
- <Transition fromState='' toState="*" reversible="true">
- <NumericAnimation properties="width,rightMargin" duration="200"/>
- </Transition>
- </transitions>
-</Item>
diff --git a/examples/declarative/tutorials/contacts/Final/ContactView2.qml b/examples/declarative/tutorials/contacts/Final/ContactView2.qml
deleted file mode 100644
index da1e5db..0000000
--- a/examples/declarative/tutorials/contacts/Final/ContactView2.qml
+++ /dev/null
@@ -1,62 +0,0 @@
-<Item id="contacts">
- <resources>
- <SqlConnection id="contactDatabase" name="qmlConnection" driver="QSQLITE" databaseName="../shared/contacts.sqlite"/>
- <SqlQuery id="contactList" connection="{contactDatabase}">
- <query>SELECT recid AS contactid, label, email, phone FROM contacts ORDER BY label, recid</query>
- </SqlQuery>
- <Component id="contactDelegate">
- <Item id="wrapper"
- x="0"
- width="{ListView.view.width}" height="34">
- <Text id="label"
- x="40" y="12"
- width="{parent.width-30}"
- text="{model.label}"
- color="white"
- font.bold="true">
- </Text>
- <MouseRegion
- anchors.fill="{label}"
- onClicked="wrapper.state='opened'"/>
- <Contact id="details"
- anchors.fill="{parent}"
- contactid="{model.contactid}"
- label="{model.label}"
- email="{model.email}"
- phone="{model.phone}"
- opacity="0"/>
- <states>
- <State name='opened'>
- <SetProperty target="{wrapper}" property="height" value="{contactListView.height}"/>
- <SetProperty target="{contactListView}" property="yPosition" value="{wrapper.y}"/>
- <SetProperty target="{contactListView}" property="locked" value="1"/>
- <SetProperty target="{label}" property="opacity" value="0"/>
- <SetProperty target="{details}" property="opacity" value="1"/>
- </State>
- </states>
- <transitions>
- <Transition>
- <NumericAnimation duration="500" properties="yPosition,height,opacity"/>
- </Transition>
- </transitions>
- <Connection sender="{cancelEditButton}" signal="clicked()">
- if (wrapper.state == 'opened') {
- wrapper.state = '';
- }
- </Connection>
- </Item>
- </Component>
- </resources>
- <Button id="cancelEditButton"
- anchors.top="{parent.top}" anchors.topMargin="5"
- anchors.right="{parent.right}" anchors.rightMargin="5"
- icon="../shared/pics/cancel.png"/>
- <ListView id="contactListView"
- anchors.left="{parent.left}"
- anchors.right="{parent.right}"
- anchors.top="{cancelEditButton.bottom}"
- anchors.bottom="{parent.bottom}"
- clip="true"
- model="{contactList}"
- delegate="{contactDelegate}"/>
-</Item>
diff --git a/examples/declarative/tutorials/contacts/Final/FieldText.qml b/examples/declarative/tutorials/contacts/Final/FieldText.qml
deleted file mode 100644
index ad7669d..0000000
--- a/examples/declarative/tutorials/contacts/Final/FieldText.qml
+++ /dev/null
@@ -1,98 +0,0 @@
-<Rect id="fieldText"
- height="30"
- radius="5"
- color="black">
- <properties>
- <Property
- name="text"
- value=""
- onValueChanged="reset()"/>
- <Property
- name="label"
- value=""/>
- </properties>
- <signals>
- <Signal name="confirmed"/>
- </signals>
- <resources>
- <Script>
- function edit() {
- if (!contacts.mouseGrabbed) {
- fieldText.state='editing';
- contacts.mouseGrabbed=true;
- }
- }
- function confirm() {
- fieldText.text = textEdit.text;
- fieldText.state='';
- contacts.mouseGrabbed=false;
- fieldText.confirmed.emit();
- }
- function reset() {
- textEdit.text = fieldText.text;
- fieldText.state='';
- contacts.mouseGrabbed=false;
- }
- </Script>
- </resources>
- <Image id="cancelIcon"
- width="22" height="22"
- anchors.right="{parent.right}" anchors.rightMargin="4"
- anchors.verticalCenter="{parent.verticalCenter}"
- source="../shared/pics/cancel.png"
- opacity="0"/>
- <Image id="confirmIcon"
- width="22" height="22"
- anchors.left="{parent.left}" anchors.leftMargin="4"
- anchors.verticalCenter="{parent.verticalCenter}"
- source="../shared/pics/ok.png"
- opacity="0"/>
- <TextEdit id="textEdit"
- anchors.left="{parent.left}" anchors.leftMargin="0"
- anchors.right="{parent.right}" anchors.rightMargin="0"
- anchors.verticalCenter="{parent.verticalCenter}"
- color="white"
- font.bold="true"
- readOnly="true"
- wrap="false"
- />
- <Text id="textLabel"
- x="5" width="{parent.width-10}"
- anchors.verticalCenter="{parent.verticalCenter}"
- hAlign="AlignHCenter"
- color="#505050"
- font.italic="true"
- text="{fieldText.label}"
- opacity="{textEdit.text == '' ? 1 : 0}">
- <opacity>
- <Behaviour>
- <NumericAnimation property="opacity" duration="250"/>
- </Behaviour>
- </opacity>
- </Text>
- <MouseRegion anchors.fill="{cancelIcon}" onClicked="reset()"/>
- <MouseRegion anchors.fill="{confirmIcon}" onClicked="confirm()"/>
- <MouseRegion
- id="editRegion"
- anchors.fill="{textEdit}"
- onClicked="edit()"/>
- <states>
- <State name="editing">
- <SetProperty target="{confirmIcon}" property="opacity" value="1"/>
- <SetProperty target="{cancelIcon}" property="opacity" value="1"/>
- <SetProperty target="{fieldText}" property="color" value="white"/>
- <SetProperty target="{textEdit}" property="color" value="black"/>
- <SetProperty target="{textEdit}" property="readOnly" value="false"/>
- <SetProperty target="{textEdit}" property="focus" value="true"/>
- <SetProperty target="{editRegion}" property="opacity" value="0"/>
- <SetProperty target="{textEdit.anchors}" property="leftMargin" value="34"/>
- <SetProperty target="{textEdit.anchors}" property="rightMargin" value="34"/>
- </State>
- </states>
- <transitions>
- <Transition fromState='' toState="*" reversible="true">
- <NumericAnimation properties="opacity,leftMargin,rightMargin" duration="200"/>
- <ColorAnimation duration="150"/>
- </Transition>
- </transitions>
-</Rect>
diff --git a/examples/declarative/tutorials/contacts/Final/RemoveButton.qml b/examples/declarative/tutorials/contacts/Final/RemoveButton.qml
deleted file mode 100644
index b096bca..0000000
--- a/examples/declarative/tutorials/contacts/Final/RemoveButton.qml
+++ /dev/null
@@ -1,80 +0,0 @@
-<Rect id="removeButton"
- width="30" height="30"
- color="red"
- radius="5">
- <properties>
- <Property name="expandedWidth" value="230"/>
- </properties>
- <signals>
- <Signal name="confirmed"/>
- </signals>
- <resources>
- <Script>
- function toggle() {
- print('removeButton.toggle()');
- if (removeButton.state == 'opened') {
- removeButton.state = '';
- contacts.mouseGrabbed=false;
- } else {
- if (!contacts.mouseGrabbed) {
- removeButton.state = 'opened';
- contacts.mouseGrabbed=true;
- }
- }
- }
- </Script>
- </resources>
- <Image id="trashIcon"
- width="22" height="22"
- anchors.right="{parent.right}" anchors.rightMargin="4"
- anchors.verticalCenter="{parent.verticalCenter}"
- source="../shared/pics/trash.png"
- opacity="1">
- <MouseRegion
- anchors.fill="{parent}"
- onClicked="toggle()"/>
- </Image>
- <Image id="cancelIcon"
- width="22" height="22"
- anchors.right="{parent.right}" anchors.rightMargin="4"
- anchors.verticalCenter="{parent.verticalCenter}"
- source="../shared/pics/cancel.png"
- opacity="0">
- <MouseRegion
- anchors.fill="{parent}"
- onClicked="toggle()"/>
- </Image>
- <Image id="confirmIcon"
- width="22" height="22"
- anchors.left="{parent.left}" anchors.leftMargin="4"
- anchors.verticalCenter="{parent.verticalCenter}"
- source="../shared/pics/ok.png"
- opacity="0">
- <MouseRegion
- anchors.fill="{parent}"
- onClicked="toggle(); removeButton.confirmed.emit()"/>
- </Image>
- <Text id="text"
- anchors.verticalCenter="{parent.verticalCenter}"
- anchors.left="{confirmIcon.right}" anchors.leftMargin="4"
- anchors.right="{cancelIcon.left}" anchors.rightMargin="4"
- font.bold="true"
- color="white"
- hAlign="AlignHCenter"
- text="Remove"
- opacity="0"/>
- <states>
- <State name="opened">
- <SetProperty target="{removeButton}" property="width" value="{removeButton.expandedWidth}"/>
- <SetProperty target="{text}" property="opacity" value="1"/>
- <SetProperty target="{confirmIcon}" property="opacity" value="1"/>
- <SetProperty target="{cancelIcon}" property="opacity" value="1"/>
- <SetProperty target="{trashIcon}" property="opacity" value="0"/>
- </State>
- </states>
- <transitions>
- <Transition fromState="*" toState="opened" reversible="true">
- <NumericAnimation properties="opacity,x,width" duration="200"/>
- </Transition>
- </transitions>
-</Rect>
diff --git a/examples/declarative/tutorials/contacts/Final/SearchBar.qml b/examples/declarative/tutorials/contacts/Final/SearchBar.qml
deleted file mode 100644
index 3965e39..0000000
--- a/examples/declarative/tutorials/contacts/Final/SearchBar.qml
+++ /dev/null
@@ -1,18 +0,0 @@
-<Rect id="searchBar"
- color="white">
- <properties>
- <Property name="text" value="{searchEdit.text}"/>
- </properties>
- <Image id="searchIcon"
- anchors.left="{parent.left}" anchors.leftMargin="5"
- anchors.verticalCenter="{parent.verticalCenter}"
- source="../shared/pics/search.png"/>
- <TextEdit id="searchEdit"
- anchors.left="{searchIcon.right}" anchors.right="{parent.right}"
- anchors.leftMargin="5" anchors.rightMargin="5"
- anchors.verticalCenter="{parent.verticalCenter}"
- readOnly="false"
- wrap="false"
- focus="true"/>
-</Rect>
-
diff --git a/examples/declarative/tutorials/contacts/Final/contacts.qml b/examples/declarative/tutorials/contacts/Final/contacts.qml
deleted file mode 100644
index 8b0d6d0..0000000
--- a/examples/declarative/tutorials/contacts/Final/contacts.qml
+++ /dev/null
@@ -1,148 +0,0 @@
-<Rect id="contacts"
- width="240"
- height="320"
- color="black">
- <properties>
- <Property name="mode" value="list"/>
- <Property name="mouseGrabbed" value="false"/>
- </properties>
- <resources>
- <SqlConnection id="contactDatabase" name="qmlConnection" driver="QSQLITE" databaseName="../shared/contacts.sqlite"/>
- <SqlQuery id="contactList" connection="{contactDatabase}">
- <query>SELECT recid AS contactid, label, email, phone FROM contacts WHERE lower(label) LIKE lower(:searchTerm) ORDER BY label, recid</query>
- <bindings>
- <SqlBind name=":searchTerm" value="{searchBar.text + '%' }"/>
- </bindings>
- </SqlQuery>
- <Component id="contactDelegate">
- <Item id="wrapper"
- x="0"
- width="{ListView.view.width}"
- height="34">
- <Text id="label"
- x="40" y="12"
- width="{parent.width-30}"
- text="{model.label}"
- color="white"
- font.bold="true">
- <children>
- <MouseRegion
- anchors.fill="{parent}">
- <onClicked>
- Details.qml = 'Contact.qml';
- wrapper.state='opened';
- contacts.mode = 'edit';
- </onClicked>
- </MouseRegion>
- </children>
- </Text>
- <Item id="Details"
- anchors.fill="{wrapper}"
- opacity="0">
- <Bind target="{Details.qmlItem}" property="contactid" value="{model.contactid}"/>
- <Bind target="{Details.qmlItem}" property="label" value="{model.label}"/>
- <Bind target="{Details.qmlItem}" property="phone" value="{model.phone}"/>
- <Bind target="{Details.qmlItem}" property="email" value="{model.email}"/>
- </Item>
- <states>
- <State name='opened'>
- <SetProperty target="{wrapper}" property="height" value="{contactListView.height}"/>
- <SetProperty target="{contactListView}" property="yPosition" value="{wrapper.y}"/>
- <SetProperty target="{contactListView}" property="locked" value="1"/>
- <SetProperty target="{label}" property="opacity" value="0"/>
- <SetProperty target="{Details}" property="opacity" value="1"/>
- </State>
- </states>
- <transitions>
- <Transition>
- <NumericAnimation duration="500" properties="yPosition,height,opacity"/>
- </Transition>
- </transitions>
- <Connection sender="{cancelEditButton}" signal="clicked()">
- if (wrapper.state == 'opened' &amp;&amp; !contacts.mouseGrabbed) {
- wrapper.state = '';
- contacts.mode = 'list';
- }
- </Connection>
- <Connection sender="{confirmEditButton}" signal="clicked()">
- if (wrapper.state == 'opened' &amp;&amp; !contacts.mouseGrabbed) {
- print('confirm and close edit');
- Details.qmlItem.update.emit();
- wrapper.state = '';
- contacts.mode = 'list';
- contactList.exec();
- }
- </Connection>
- </Item>
- </Component>
- </resources>
- <Button id="newContactButton"
- anchors.top="{parent.top}" anchors.topMargin="5"
- anchors.right="{parent.right}" anchors.rightMargin="5"
- icon="../shared/pics/new.png"
- onClicked="newContactItem.label = ''; newContactItem.phone = ''; newContactItem.email = ''; contacts.mode = 'new'"
- opacity="{contacts.mode == 'list' ? 1 : 0}"/>
- <Button id="confirmEditButton"
- anchors.top="{parent.top}" anchors.topMargin="5"
- anchors.left="{parent.left}" anchors.leftMargin="5"
- icon="../shared/pics/ok.png"
- opacity="{contacts.mode == 'list' || contacts.mouseGrabbed ? 0 : 1}"/>
- <Button id="cancelEditButton"
- anchors.top="{parent.top}" anchors.topMargin="5"
- anchors.right="{parent.right}" anchors.rightMargin="5"
- icon="../shared/pics/cancel.png"
- opacity="{contacts.mode == 'list' || contacts.mouseGrabbed ? 0 : 1}"/>
- <ListView id="contactListView"
- anchors.left="{parent.left}"
- anchors.right="{parent.right}"
- anchors.top="{cancelEditButton.bottom}"
- anchors.bottom="{searchBarWrapper.bottom}"
- clip="true"
- model="{contactList}"
- delegate="{contactDelegate}"
- focus="{contacts.mode != 'list'}"/>
- <Contact id="newContactItem"
- anchors.fill="{contactListView}"
- opacity="0"/>
- <Connection sender="{confirmEditButton}" signal="clicked()">
- if (contacts.mode == 'new' &amp;&amp; contacts.mouseGrabbed != 'true') {
- newContactItem.insert.emit();
- contacts.mode = 'list';
- contactList.exec();
- }
- </Connection>
- <Connection sender="{cancelEditButton}" signal="clicked()">
- if (contacts.mode == 'new' &amp;&amp; contacts.mouseGrabbed != 'true') {
- contacts.mode = 'list';
- }
- </Connection>
- <FocusRealm id="searchBarWrapper"
- height="30"
- anchors.bottom="{parent.bottom}"
- anchors.left="{parent.left}" anchors.right="{parent.right}"
- anchors.bottomMargin="0"
- focus="{contacts.mode == 'list'}">
- <SearchBar id="searchBar" anchors.fill="{parent}"/>
- <states>
- <State name="searchHidden" when="{searchBar.text == '' || contacts.mode != 'list'}">
- <SetProperty target="{searchBarWrapper.anchors}" property="bottomMargin" value="-30"/>
- </State>
- </states>
- <transitions>
- <Transition fromState="*" toState="*">
- <NumericAnimation property="bottomMargin" duration="250"/>
- </Transition>
- </transitions>
- </FocusRealm>
- <states>
- <State name="editNewState" when="{contacts.mode == 'new'}">
- <SetProperty target="{contactListView}" property="opacity" value="0"/>
- <SetProperty target="{newContactItem}" property="opacity" value="1"/>
- </State>
- </states>
- <transitions>
- <Transition fromState="*" toState="*">
- <NumericAnimation property="opacity" duration="500"/>
- </Transition>
- </transitions>
-</Rect>
diff --git a/src/declarative/canvas/qsimplecanvas.cpp b/src/declarative/canvas/qsimplecanvas.cpp
index ce02a4c..e1dd0e8 100644
--- a/src/declarative/canvas/qsimplecanvas.cpp
+++ b/src/declarative/canvas/qsimplecanvas.cpp
@@ -60,7 +60,7 @@
QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(fullUpdate, GFX_CANVAS_FULL_UPDATE);
DEFINE_BOOL_CONFIG_OPTION(continuousUpdate, GFX_CANVAS_CONTINUOUS_UPDATE);
-DEFINE_BOOL_CONFIG_OPTION(useGraphicsView, QFX_USE_GRAPHICSVIEW);
+DEFINE_BOOL_CONFIG_OPTION(useSimpleCanvas, QFX_USE_SIMPLECANVAS);
template<class T, int s = 60>
class CircularList
@@ -556,7 +556,7 @@ QSimpleCanvas::QSimpleCanvas(CanvasMode mode, QWidget *parent)
QSimpleCanvas::QSimpleCanvas(QWidget *parent)
: QWidget(parent), d(new QSimpleCanvasPrivate(this))
{
- d->init(useGraphicsView()?SimpleCanvas:GraphicsView);
+ d->init(useSimpleCanvas()?SimpleCanvas:GraphicsView);
}
void QSimpleCanvasPrivate::init(QSimpleCanvas::CanvasMode mode)
@@ -904,6 +904,13 @@ QSimpleCanvasItem *QSimpleCanvas::activeFocusPanel() const
return d->focusPanels.top();
}
+QSimpleCanvasItem *QSimpleCanvas::focusItem(QSimpleCanvasItem *item) const
+{
+ while (item && d->focusPanelData.contains(item))
+ item = d->focusPanelData.value(item);
+ return item;
+}
+
bool QSimpleCanvas::event(QEvent *e)
{
if (e->type() == QEvent::User && d->isSimpleCanvas()) {
diff --git a/src/declarative/canvas/qsimplecanvas.h b/src/declarative/canvas/qsimplecanvas.h
index a35cbf5..20dab28 100644
--- a/src/declarative/canvas/qsimplecanvas.h
+++ b/src/declarative/canvas/qsimplecanvas.h
@@ -141,6 +141,8 @@ public:
void checkState();
QSimpleCanvasItem *focusItem() const;
+ QSimpleCanvasItem *focusItem(QSimpleCanvasItem *item) const;
+
QSimpleCanvasItem *activeFocusPanel() const;
QImage asImage() const;
diff --git a/src/declarative/canvas/qsimplecanvas_software.cpp b/src/declarative/canvas/qsimplecanvas_software.cpp
index c130a62..194024d 100644
--- a/src/declarative/canvas/qsimplecanvas_software.cpp
+++ b/src/declarative/canvas/qsimplecanvas_software.cpp
@@ -172,6 +172,11 @@ void QSimpleCanvasItemPrivate::paint(QPainter &p)
if (clip)
p.restore();
+
+ if (debuggerStatus && debuggerStatus->selected) {
+ p.setWorldTransform(data()->transformActive);
+ p.fillRect(q->boundingRect(), QColor(255, 0, 0, 80));
+ }
}
void QSimpleCanvasItemPrivate::paintChild(QPainter &p, QSimpleCanvasItem *c)
diff --git a/src/declarative/canvas/qsimplecanvasitem.cpp b/src/declarative/canvas/qsimplecanvasitem.cpp
index 62a44e4..ba33a41 100644
--- a/src/declarative/canvas/qsimplecanvasitem.cpp
+++ b/src/declarative/canvas/qsimplecanvasitem.cpp
@@ -1380,6 +1380,14 @@ QSimpleCanvasItem::operator QGraphicsItem *()
return d->graphicsItem;
}
+QSimpleCanvasItem::operator QmlDebuggerStatus *()
+{
+ Q_D(QSimpleCanvasItem);
+ if(!d->debuggerStatus)
+ d->debuggerStatus = new QSimpleCanvasItemDebuggerStatus(this);
+ return d->debuggerStatus;
+}
+
QPointF QSimpleCanvasItemPrivate::transformOrigin() const
{
Q_Q(const QSimpleCanvasItem);
diff --git a/src/declarative/canvas/qsimplecanvasitem.h b/src/declarative/canvas/qsimplecanvasitem.h
index 83f19c3..cab8492 100644
--- a/src/declarative/canvas/qsimplecanvasitem.h
+++ b/src/declarative/canvas/qsimplecanvasitem.h
@@ -42,10 +42,11 @@
#ifndef QSIMPLECANVASITEM_H
#define QSIMPLECANVASITEM_H
-#include <qfxglobal.h>
-#include <qsimplecanvas.h>
-#include <QObject>
-#include <QGraphicsItem>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qmldebuggerstatus.h>
+#include <QtDeclarative/qsimplecanvas.h>
+#include <QtCore/qobject.h>
+#include <QtGui/qgraphicsitem.h>
class QPainter;
QT_BEGIN_HEADER
@@ -70,6 +71,7 @@ class Q_DECLARATIVE_EXPORT QSimpleCanvasItem : public QObject
{
Q_OBJECT
Q_CAST_INTERFACES(QGraphicsItem)
+ Q_CAST_INTERFACES(QmlDebuggerStatus)
Q_DECLARE_PRIVATE(QSimpleCanvasItem)
Q_ENUMS(TransformOrigin)
Q_PROPERTY(TransformOrigin transformOrigin READ transformOrigin WRITE setTransformOrigin);
@@ -94,6 +96,7 @@ public:
QSimpleCanvasItem(QSimpleCanvasItem *parent=0);
virtual ~QSimpleCanvasItem();
operator QGraphicsItem *();
+ operator QmlDebuggerStatus *();
bool clip() const;
void setClip(bool);
diff --git a/src/declarative/canvas/qsimplecanvasitem_p.h b/src/declarative/canvas/qsimplecanvasitem_p.h
index 27a75bd..cfe0bba 100644
--- a/src/declarative/canvas/qsimplecanvasitem_p.h
+++ b/src/declarative/canvas/qsimplecanvasitem_p.h
@@ -110,6 +110,22 @@ public:
#endif
};
+class QSimpleCanvasItemDebuggerStatus : public QmlDebuggerStatus
+{
+public:
+ QSimpleCanvasItemDebuggerStatus(QSimpleCanvasItem *i)
+ : item(i), selected(false) {}
+
+ virtual void setSelectedState(bool state)
+ {
+ selected = state;
+ item->update();
+ }
+
+ QSimpleCanvasItem *item;
+ bool selected;
+};
+
class QSimpleCanvasFilter;
class QGraphicsQSimpleCanvasItem;
class QSimpleCanvasItemPrivate : public QObjectPrivate
@@ -117,7 +133,8 @@ class QSimpleCanvasItemPrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QSimpleCanvasItem);
public:
QSimpleCanvasItemPrivate()
- : parent(0), canvas(0), filter(0), clip(QSimpleCanvasItem::NoClip),
+ : parent(0), canvas(0), debuggerStatus(0), filter(0),
+ clip(QSimpleCanvasItem::NoClip),
origin(QSimpleCanvasItem::TopLeft), options(QSimpleCanvasItem::NoOption),
focusable(false), wantsActiveFocusPanelPendingCanvas(false),
hasBeenActiveFocusPanel(false),
@@ -127,12 +144,16 @@ public:
{
}
- virtual ~QSimpleCanvasItemPrivate() {}
+ virtual ~QSimpleCanvasItemPrivate()
+ {
+ if(debuggerStatus) delete debuggerStatus;
+ }
QSimpleCanvasItem *parent;
QSimpleCanvas *canvas;
QList<QSimpleCanvasItem *> children;
+ QSimpleCanvasItemDebuggerStatus *debuggerStatus;
QSimpleCanvasFilter *filter;
QSimpleCanvasItem::ClipType clip:3;
diff --git a/src/declarative/debugger/debugger.pri b/src/declarative/debugger/debugger.pri
index ea5219a..31a1d5b 100644
--- a/src/declarative/debugger/debugger.pri
+++ b/src/declarative/debugger/debugger.pri
@@ -1,3 +1,7 @@
-SOURCES += debugger/qmldebugger.cpp
+SOURCES += debugger/qmldebugger.cpp \
+ debugger/qmldebuggerstatus.cpp \
+ debugger/qmlpropertyview.cpp
-HEADERS += debugger/qmldebugger.h
+HEADERS += debugger/qmldebugger.h \
+ debugger/qmldebuggerstatus.h \
+ debugger/qmlpropertyview_p.h
diff --git a/src/declarative/debugger/qmldebugger.cpp b/src/declarative/debugger/qmldebugger.cpp
index 033a15f..634385b 100644
--- a/src/declarative/debugger/qmldebugger.cpp
+++ b/src/declarative/debugger/qmldebugger.cpp
@@ -43,7 +43,10 @@
#include <QtGui/qtreewidget.h>
#include <QtGui/qboxlayout.h>
#include <QtGui/qplaintextedit.h>
+#include <QTextBlock>
+#include <QtGui/qtabwidget.h>
#include <QtDeclarative/qmlbindablevalue.h>
+#include <QtDeclarative/qmldebuggerstatus.h>
#include <private/qmlboundsignal_p.h>
#include <private/qmlcontext_p.h>
#include <private/qmlengine_p.h>
@@ -52,10 +55,13 @@
#include <QtCore/qurl.h>
#include <QtGui/qsplitter.h>
#include <QtGui/qpushbutton.h>
+#include <QtGui/qtablewidget.h>
#include <QtGui/qevent.h>
+#include <private/qmlpropertyview_p.h>
QmlDebugger::QmlDebugger(QWidget *parent)
-: QWidget(parent), m_tree(0)
+: QWidget(parent), m_tree(0), m_warnings(0), m_watchers(0), m_properties(0),
+ m_text(0)
{
QHBoxLayout *layout = new QHBoxLayout;
setLayout(layout);
@@ -69,18 +75,37 @@ QmlDebugger::QmlDebugger(QWidget *parent)
splitter->addWidget(treeWid);
m_tree = new QTreeWidget(treeWid);
+ m_tree->setSelectionMode(QTreeWidget::NoSelection);
m_tree->setHeaderHidden(true);
- QObject::connect(m_tree, SIGNAL(itemPressed(QTreeWidgetItem *, int)), this, SLOT(itemPressed(QTreeWidgetItem *)));
+ QObject::connect(m_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(itemClicked(QTreeWidgetItem *)));
+ QObject::connect(m_tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(itemDoubleClicked(QTreeWidgetItem *)));
vlayout->addWidget(m_tree);
QPushButton *pb = new QPushButton("Refresh", treeWid);
QObject::connect(pb, SIGNAL(clicked()), this, SLOT(refresh()));
vlayout->addWidget(pb);
+ QTabWidget *tabs = new QTabWidget(this);
+
m_text = new QPlainTextEdit(this);
m_text->setReadOnly(true);
- splitter->addWidget(m_text);
+ tabs->addTab(m_text, "File");
+
+ m_warnings = new QTreeWidget(this);
+ m_warnings->setHeaderHidden(true);
+ tabs->addTab(m_warnings, "Warnings");
+
+ m_watchers = new QTableWidget(this);
+ m_watchers->setSelectionMode(QTableWidget::NoSelection);
+ tabs->addTab(m_watchers, "Watchers");
+
+ m_properties = new QmlPropertyView(this);
+ tabs->addTab(m_properties, "Properties");
+
+ splitter->addWidget(tabs);
splitter->setStretchFactor(1, 2);
+
+ setGeometry(0, 100, 800, 600);
}
class QmlDebuggerItem : public QTreeWidgetItem
@@ -100,34 +125,53 @@ public:
int endLine;
QUrl url;
+ QPointer<QObject> object;
QPointer<QmlBindableValue> bindableValue;
};
-void QmlDebugger::itemPressed(QTreeWidgetItem *i)
+void QmlDebugger::itemDoubleClicked(QTreeWidgetItem *i)
{
QmlDebuggerItem *item = static_cast<QmlDebuggerItem *>(i);
if(item->bindableValue) {
- QString str;
-
QmlExpressionPrivate *p = item->bindableValue->d;
- if(p->log) {
- QString str;
- QDebug d(&str);
- for(int ii = 0; ii < p->log->count(); ++ii) {
- d << p->log->at(ii).result() << "\n";
- QStringList warnings = p->log->at(ii).warnings();
- foreach(const QString &warning, warnings)
- d << " " << warning << "\n";
- }
- m_text->setPlainText(str);
+ if(m_watchedIds.contains(p->id)) {
+ m_watchedIds.remove(p->id);
+ item->setForeground(0, Qt::green);
} else {
- m_text->setPlainText("No history");
+ m_watchedIds.insert(p->id);
+ item->setForeground(0, QColor("purple"));
}
- } else if(item->url.scheme() == QLatin1String("file")) {
+ }
+}
+
+void QmlDebugger::itemClicked(QTreeWidgetItem *i)
+{
+ QmlDebuggerItem *item = static_cast<QmlDebuggerItem *>(i);
+
+ if(m_selectedItem) {
+ QmlDebuggerStatus *debug =
+ qobject_cast<QmlDebuggerStatus *>(m_selectedItem);
+ Q_ASSERT(debug);
+ debug->setSelectedState(false);
+ m_selectedItem = 0;
+ }
+
+ if(item->object) {
+ QmlDebuggerStatus *debug =
+ qobject_cast<QmlDebuggerStatus *>(item->object);
+ if(debug) {
+ debug->setSelectedState(true);
+ m_selectedItem = item->object;
+ }
+
+ m_properties->setObject(item->object);
+ }
+
+ if(item->url.scheme() == QLatin1String("file")) {
QString f = item->url.toLocalFile();
QFile file(f);
file.open(QIODevice::ReadOnly);
@@ -141,17 +185,11 @@ void QmlDebugger::itemPressed(QTreeWidgetItem *i)
QTextDocument *document = m_text->document();
QTextCharFormat format;
format.setForeground(Qt::lightGray);
- {
- QTextCursor cursor(document);
- cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
- cursor.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor, item->startLine - 1);
- cursor.setCharFormat(format);
- }
{
QTextCursor cursor(document);
cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
- cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, item->endLine);
+ cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, item->endLine);
cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
cursor.setCharFormat(format);
}
@@ -159,31 +197,89 @@ void QmlDebugger::itemPressed(QTreeWidgetItem *i)
{
QTextCursor cursor(document);
cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
- cursor.setCharFormat(QTextCharFormat());
+ cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor, item->startLine - 1);
+ cursor.setCharFormat(format);
}
{
QTextCursor cursor(document);
cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
- cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, item->startLine - 1);
+ cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, item->startLine - 1);
m_text->setTextCursor(cursor);
m_text->centerCursor();
}
+
+
}
}
}
-static bool makeItem(QObject *obj, QmlDebuggerItem *item)
+bool QmlDebugger::makeItem(QObject *obj, QmlDebuggerItem *item)
{
bool rv = true;
QString text;
+ item->object = obj;
+
if(QmlBindableValue *bv = qobject_cast<QmlBindableValue *>(obj)) {
+ QmlExpressionPrivate *p = bv->d;
+
text = bv->property().name() + ": " + bv->expression();
- item->setForeground(0, Qt::green);
+ bool watched = m_watchedIds.contains(p->id);
+ if(watched)
+ item->setForeground(0, QColor("purple"));
+ else
+ item->setForeground(0, Qt::green);
item->bindableValue = bv;
+
+ if(p->log) {
+ QTreeWidgetItem *warningItem = 0;
+
+ int column = m_watchers->columnCount();
+
+ if(watched) {
+ m_watchers->insertColumn(column);
+ QTableWidgetItem *tableheader = new QTableWidgetItem;
+ tableheader->setText(bv->expression());
+ tableheader->setToolTip(bv->expression());
+ m_watchers->setHorizontalHeaderItem(column, tableheader);
+ }
+
+ for(int ii = 0; ii < p->log->count(); ++ii) {
+ const QmlExpressionLog &log = p->log->at(ii);
+
+ QString variant; QDebug d(&variant); d << log.result();
+ if(watched) {
+ QString str = log.result().toString();
+ if(str.isEmpty())
+ str = variant;
+ m_expressions << qMakePair(log.time(), qMakePair(column, str));
+ }
+
+ if(!log.warnings().isEmpty()) {
+
+ if(!warningItem) {
+ warningItem = new QTreeWidgetItem(m_warnings);
+ warningItem->setText(0, bv->expression());
+ }
+
+ QTreeWidgetItem *entry = new QTreeWidgetItem(warningItem);
+ entry->setExpanded(true);
+
+ entry->setText(0, variant);
+
+ foreach(const QString &warning, log.warnings()) {
+ QTreeWidgetItem *w = new QTreeWidgetItem(entry);
+ w->setText(0, warning);
+ }
+ }
+
+ }
+
+ }
+
} else if(QmlBoundSignal *bs = qobject_cast<QmlBoundSignal *>(obj)) {
QMetaMethod method = obj->parent()->metaObject()->method(bs->index());
QByteArray sig = method.signature();
@@ -237,7 +333,7 @@ static bool makeItem(QObject *obj, QmlDebuggerItem *item)
return rv;
}
-static void buildTree(QObject *obj, QmlDebuggerItem *parent)
+void QmlDebugger::buildTree(QObject *obj, QmlDebuggerItem *parent)
{
QObjectList children = obj->children();
@@ -253,9 +349,20 @@ void QmlDebugger::refresh()
setDebugObject(m_object);
}
+bool operator<(const QPair<quint32, QPair<int, QString> > &lhs,
+ const QPair<quint32, QPair<int, QString> > &rhs)
+{
+ return lhs.first < rhs.first;
+}
+
void QmlDebugger::setDebugObject(QObject *obj)
{
m_tree->clear();
+ m_warnings->clear();
+ m_watchers->clear();
+ m_watchers->setColumnCount(0);
+ m_watchers->setRowCount(0);
+ m_expressions.clear();
m_object = obj;
if(!obj)
@@ -265,6 +372,20 @@ void QmlDebugger::setDebugObject(QObject *obj)
makeItem(obj, item);
buildTree(obj, item);
item->setExpanded(true);
- setGeometry(0, 100, 800, 600);
+
+ m_watchers->setRowCount(m_expressions.count());
+
+ qSort(m_expressions.begin(), m_expressions.end());
+
+ for(int ii = 0; ii < m_expressions.count(); ++ii) {
+
+ const QPair<quint32, QPair<int, QString> > &expr = m_expressions.at(ii);
+ QTableWidgetItem *item = new QTableWidgetItem;
+ item->setText(expr.second.second);
+ m_watchers->setItem(ii, expr.second.first, item);
+
+ }
+
+
}
diff --git a/src/declarative/debugger/qmldebugger.h b/src/declarative/debugger/qmldebugger.h
index 943abef..35ff92c 100644
--- a/src/declarative/debugger/qmldebugger.h
+++ b/src/declarative/debugger/qmldebugger.h
@@ -43,6 +43,7 @@
#define QMLDEBUGGER_H
#include <QtCore/qpointer.h>
+#include <QtCore/qset.h>
#include <QtGui/qwidget.h>
QT_BEGIN_HEADER
@@ -54,6 +55,9 @@ QT_MODULE(Declarative)
class QTreeWidget;
class QTreeWidgetItem;
class QPlainTextEdit;
+class QmlDebuggerItem;
+class QTableWidget;
+class QmlPropertyView;
class QmlDebugger : public QWidget
{
Q_OBJECT
@@ -66,12 +70,21 @@ public slots:
void refresh();
private slots:
- void itemPressed(QTreeWidgetItem *);
+ void itemClicked(QTreeWidgetItem *);
+ void itemDoubleClicked(QTreeWidgetItem *);
private:
+ void buildTree(QObject *obj, QmlDebuggerItem *parent);
+ bool makeItem(QObject *obj, QmlDebuggerItem *item);
QTreeWidget *m_tree;
+ QTreeWidget *m_warnings;
+ QTableWidget *m_watchers;
+ QmlPropertyView *m_properties;
QPlainTextEdit *m_text;
QPointer<QObject> m_object;
+ QList<QPair<quint32, QPair<int, QString> > > m_expressions;
+ QSet<quint32> m_watchedIds;
+ QPointer<QObject> m_selectedItem;
};
QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qmldebuggerstatus.cpp b/src/declarative/debugger/qmldebuggerstatus.cpp
new file mode 100644
index 0000000..d46a21d
--- /dev/null
+++ b/src/declarative/debugger/qmldebuggerstatus.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** 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 "qmldebuggerstatus.h"
+
+QT_BEGIN_NAMESPACE
+
+QmlDebuggerStatus::~QmlDebuggerStatus()
+{
+}
+
+void QmlDebuggerStatus::setSelectedState(bool)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qmldebuggerstatus.h b/src/declarative/debugger/qmldebuggerstatus.h
new file mode 100644
index 0000000..8c6355d
--- /dev/null
+++ b/src/declarative/debugger/qmldebuggerstatus.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QMLDEBUGGERSTATUS_P_H
+#define QMLDEBUGGERSTATUS_P_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlDebuggerStatus
+{
+public:
+ virtual ~QmlDebuggerStatus();
+
+ virtual void setSelectedState(bool);
+};
+Q_DECLARE_INTERFACE(QmlDebuggerStatus, "com.trolltech.qml.QmlDebuggerStatus");
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QLMDEBUGGERSTATUS_P_H
+
diff --git a/src/declarative/debugger/qmlpropertyview.cpp b/src/declarative/debugger/qmlpropertyview.cpp
new file mode 100644
index 0000000..2434c58
--- /dev/null
+++ b/src/declarative/debugger/qmlpropertyview.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** 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 "qmlpropertyview_p.h"
+#include <QtGui/qboxlayout.h>
+#include <QtGui/qtreewidget.h>
+#include <QtCore/qmetaobject.h>
+
+QmlPropertyView::QmlPropertyView(QWidget *parent)
+: QWidget(parent), m_tree(0)
+{
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ setLayout(layout);
+
+ m_tree = new QTreeWidget(this);
+ m_tree->setHeaderLabels(QStringList() << "Property" << "Value");
+
+ m_tree->setColumnCount(2);
+
+ layout->addWidget(m_tree);
+}
+
+class QmlPropertyViewItem : public QObject, public QTreeWidgetItem
+{
+Q_OBJECT
+public:
+ QmlPropertyViewItem(QTreeWidget *widget);
+
+ QObject *object;
+ QMetaProperty property;
+
+public slots:
+ void refresh();
+};
+
+QmlPropertyViewItem::QmlPropertyViewItem(QTreeWidget *widget)
+: QTreeWidgetItem(widget)
+{
+}
+
+void QmlPropertyViewItem::refresh()
+{
+ setText(1, property.read(object).toString());
+}
+
+void QmlPropertyView::setObject(QObject *object)
+{
+ m_object = object;
+
+ m_tree->clear();
+ if(!m_object)
+ return;
+
+ const QMetaObject *mo = object->metaObject();
+ for(int ii = 0; ii < mo->propertyCount(); ++ii) {
+ QmlPropertyViewItem *item = new QmlPropertyViewItem(m_tree);
+
+ QMetaProperty p = mo->property(ii);
+ item->object = object;
+ item->property = p;
+
+ item->setText(0, QLatin1String(p.name()));
+
+ static int refreshIdx = -1;
+ if(refreshIdx == -1)
+ refreshIdx = QmlPropertyViewItem::staticMetaObject.indexOfMethod("refresh()");
+
+ if(p.hasNotifySignal())
+ QMetaObject::connect(object, p.notifySignalIndex(),
+ item, refreshIdx);
+
+ item->refresh();
+ }
+}
+
+void QmlPropertyView::refresh()
+{
+ setObject(m_object);
+}
+
+#include "qmlpropertyview.moc"
diff --git a/src/declarative/debugger/qmlpropertyview_p.h b/src/declarative/debugger/qmlpropertyview_p.h
new file mode 100644
index 0000000..fce9941
--- /dev/null
+++ b/src/declarative/debugger/qmlpropertyview_p.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QMLPROPERTYVIEW_P_H
+#define QMLPROPERTYVIEW_P_H
+
+#include <QtGui/qwidget.h>
+#include <QtCore/qpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QTreeWidget;
+class QmlPropertyView : public QWidget
+{
+ Q_OBJECT
+public:
+ QmlPropertyView(QWidget *parent = 0);
+
+ void setObject(QObject *);
+
+public slots:
+ void refresh();
+
+private:
+ QPointer<QObject> m_object;
+ QTreeWidget *m_tree;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLPROPERTYVIEW_P_H
+
diff --git a/src/declarative/fx/qfxkeyproxy.cpp b/src/declarative/fx/qfxkeyproxy.cpp
index 6d9c6ab..1bb54ec 100644
--- a/src/declarative/fx/qfxkeyproxy.cpp
+++ b/src/declarative/fx/qfxkeyproxy.cpp
@@ -96,7 +96,7 @@ void QFxKeyProxy::keyPressEvent(QKeyEvent *e)
for (int ii = 0; ii < d->targets.count(); ++ii) {
QSimpleCanvasItem *i = d->targets.at(ii);
if (i)
- i->keyPressEvent(e);
+ canvas()->focusItem(i)->keyPressEvent(e);
if (e->isAccepted())
return;
}
@@ -107,7 +107,7 @@ void QFxKeyProxy::keyReleaseEvent(QKeyEvent *e)
for (int ii = 0; ii < d->targets.count(); ++ii) {
QSimpleCanvasItem *i = d->targets.at(ii);
if (i)
- i->keyReleaseEvent(e);
+ canvas()->focusItem(i)->keyReleaseEvent(e);
if (e->isAccepted())
return;
}
diff --git a/src/declarative/fx/qfxtextedit.cpp b/src/declarative/fx/qfxtextedit.cpp
index a1b5484..bf7a16d 100644
--- a/src/declarative/fx/qfxtextedit.cpp
+++ b/src/declarative/fx/qfxtextedit.cpp
@@ -582,25 +582,17 @@ void QFxTextEdit::keyReleaseEvent(QKeyEvent *event)
}
/*!
-\overload
-Handles the given focus \a event.
-*/
-void QFxTextEdit::focusInEvent(QFocusEvent *event)
-{
- Q_D(QFxTextEdit);
- QFxPaintedItem::focusInEvent(event);
- d->control->processEvent(event, QPointF(0, 0));
-}
-
-/*!
-\overload
-Handles the given focus \a event.
+ \overload
+ Handles changing of the focus property. Focus is applied to the control
+ even if the edit does not have active focus. This is because things
+ like KeyProxy can give the behavior of focus even when activeFocus isn't
+ true.
*/
-void QFxTextEdit::focusOutEvent(QFocusEvent *event)
+void QFxTextEdit::focusChanged(bool hasFocus)
{
Q_D(QFxTextEdit);
- QFxPaintedItem::focusOutEvent(event);
- d->control->processEvent(event, QPointF(0, 0));
+ QFocusEvent focusEvent(hasFocus ? QEvent::FocusIn : QEvent::FocusOut);
+ d->control->processEvent(&focusEvent, QPointF(0, 0));
}
static QMouseEvent *sceneMouseEventToMouseEvent(QGraphicsSceneMouseEvent *e)
diff --git a/src/declarative/fx/qfxtextedit.h b/src/declarative/fx/qfxtextedit.h
index b017635..e5e9421 100644
--- a/src/declarative/fx/qfxtextedit.h
+++ b/src/declarative/fx/qfxtextedit.h
@@ -161,8 +161,7 @@ protected:
void keyPressEvent(QKeyEvent *);
void keyReleaseEvent(QKeyEvent *);
- void focusInEvent(QFocusEvent *);
- void focusOutEvent(QFocusEvent *);
+ void focusChanged(bool);
// mouse filter?
void mousePressEvent(QGraphicsSceneMouseEvent *event);
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index be5226e..15b5879 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -139,7 +139,7 @@ QStack<QmlEngine *> *QmlEngineStack::engines()
QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e)
: rootContext(0), currentBindContext(0), currentExpression(0), q(e),
- rootComponent(0), networkAccessManager(0), typeManager(e)
+ rootComponent(0), networkAccessManager(0), typeManager(e), uniqueId(1)
{
QScriptValue proto = scriptEngine.newObject();
proto.setProperty(QLatin1String("emit"),
@@ -720,17 +720,17 @@ QmlEngine *QmlEngine::activeEngine()
QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b)
-: q(b), ctxt(0), sseData(0), proxy(0), me(0), trackChange(false), log(0)
+: q(b), ctxt(0), sseData(0), proxy(0), me(0), trackChange(false), id(0), log(0)
{
}
QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b, void *expr, QmlRefCount *rc)
-: q(b), ctxt(0), sse((const char *)expr, rc), sseData(0), proxy(0), me(0), trackChange(true), log(0)
+: q(b), ctxt(0), sse((const char *)expr, rc), sseData(0), proxy(0), me(0), trackChange(true), id(0), log(0)
{
}
QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b, const QString &expr, bool ssecompile)
-: q(b), ctxt(0), expression(expr), sseData(0), proxy(0), me(0), trackChange(true), log(0)
+: q(b), ctxt(0), expression(expr), sseData(0), proxy(0), me(0), trackChange(true), id(0), log(0)
{
if (ssecompile) {
#ifdef Q_ENABLE_PERFORMANCE_LOG
@@ -765,6 +765,8 @@ QmlExpression::QmlExpression(QmlContext *ctxt, void *expr,
: d(new QmlExpressionPrivate(this, expr, rc))
{
d->ctxt = ctxt;
+ if(ctxt && ctxt->engine())
+ d->id = ctxt->engine()->d_func()->getUniqueId();
d->me = me;
}
@@ -774,6 +776,8 @@ QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expr,
: d(new QmlExpressionPrivate(this, expr, ssecompile))
{
d->ctxt = ctxt;
+ if(ctxt && ctxt->engine())
+ d->id = ctxt->engine()->d_func()->getUniqueId();
d->me = me;
}
@@ -789,6 +793,8 @@ QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expression,
: d(new QmlExpressionPrivate(this, expression, true))
{
d->ctxt = ctxt;
+ if(ctxt && ctxt->engine())
+ d->id = ctxt->engine()->d_func()->getUniqueId();
d->me = scope;
}
@@ -810,7 +816,7 @@ QmlEngine *QmlExpression::engine() const
}
/*!
- Returns teh QmlContext this expression is associated with, or 0 if there
+ Returns the QmlContext this expression is associated with, or 0 if there
is no association or the QmlContext has been destroyed.
*/
QmlContext *QmlExpression::context() const
@@ -988,6 +994,7 @@ QVariant QmlExpression::value()
if(qmlDebugger()) {
QmlExpressionLog log;
+ log.setTime(engine()->d_func()->getUniqueId());
log.setExpression(expression());
log.setResult(rv);
@@ -997,8 +1004,8 @@ QVariant QmlExpression::value()
if (prop.hasChangedNotifier()) {
prop.connectNotifier(d->proxy, changedIndex);
- } else {
- QString warn = QLatin1String("Expression depends on property without a NOTIFY signal: ") + QLatin1String(prop.object()->metaObject()->className()) + QLatin1String(".") + prop.name();
+ } else if (prop.needsChangedNotifier()) {
+ QString warn = QLatin1String("Expression depends on property without a NOTIFY signal: [") + QLatin1String(prop.object()->metaObject()->className()) + QLatin1String("].") + prop.name();
log.addWarning(warn);
}
}
@@ -1015,6 +1022,7 @@ QVariant QmlExpression::value()
}
} else {
QmlExpressionLog log;
+ log.setTime(engine()->d_func()->getUniqueId());
log.setExpression(expression());
log.setResult(rv);
d->addLog(log);
@@ -1023,6 +1031,7 @@ QVariant QmlExpression::value()
} else {
if(qmlDebugger()) {
QmlExpressionLog log;
+ log.setTime(engine()->d_func()->getUniqueId());
log.setExpression(expression());
log.setResult(rv);
d->addLog(log);
@@ -1421,7 +1430,8 @@ QmlExpressionLog::QmlExpressionLog()
}
QmlExpressionLog::QmlExpressionLog(const QmlExpressionLog &o)
-: m_expression(o.m_expression),
+: m_time(o.m_time),
+ m_expression(o.m_expression),
m_result(o.m_result),
m_warnings(o.m_warnings)
{
@@ -1433,12 +1443,22 @@ QmlExpressionLog::~QmlExpressionLog()
QmlExpressionLog &QmlExpressionLog::operator=(const QmlExpressionLog &o)
{
+ m_time = o.m_time;
m_expression = o.m_expression;
m_result = o.m_result;
m_warnings = o.m_warnings;
return *this;
}
+void QmlExpressionLog::setTime(quint32 time)
+{
+ m_time = time;
+}
+
+quint32 QmlExpressionLog::time() const
+{
+ return m_time;
+}
QString QmlExpressionLog::expression() const
{
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index 7d5176e..63df0ba 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -114,6 +114,11 @@ public:
QmlCompositeTypeManager typeManager;
QMap<QString,QString> nameSpacePaths;
+
+ mutable quint32 uniqueId;
+ quint32 getUniqueId() const {
+ return uniqueId++;
+ }
};
@@ -201,6 +206,9 @@ public:
QmlExpressionLog &operator=(const QmlExpressionLog &);
+ void setTime(quint32);
+ quint32 time() const;
+
QString expression() const;
void setExpression(const QString &);
@@ -211,6 +219,7 @@ public:
void setResult(const QVariant &);
private:
+ quint32 m_time;
QString m_expression;
QVariant m_result;
QStringList m_warnings;
@@ -233,6 +242,8 @@ public:
QObject *me;
bool trackChange;
+ quint32 id;
+
void addLog(const QmlExpressionLog &);
QList<QmlExpressionLog> *log;
};
diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp
index 40c9b0e..59d6b38 100644
--- a/src/declarative/qml/qmlmetaproperty.cpp
+++ b/src/declarative/qml/qmlmetaproperty.cpp
@@ -988,6 +988,18 @@ bool QmlMetaProperty::hasChangedNotifier() const
}
/*!
+ Returns true if the property needs a change notifier signal for bindings
+ to remain upto date, false otherwise.
+
+ Some properties, such as attached properties or those whose value never
+ changes, do not require a change notifier.
+*/
+bool QmlMetaProperty::needsChangedNotifier() const
+{
+ return type() & Property && !(type() & Attached);
+}
+
+/*!
Connects the property's change notifier signal to the
specified \a method of the \a dest object and returns
true. Returns false if this metaproperty does not
diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h
index 4836038..68b06e5 100644
--- a/src/declarative/qml/qmlmetaproperty.h
+++ b/src/declarative/qml/qmlmetaproperty.h
@@ -89,6 +89,7 @@ public:
void emitSignal();
bool hasChangedNotifier() const;
+ bool needsChangedNotifier() const;
bool connectNotifier(QObject *dest, const char *slot) const;
bool connectNotifier(QObject *dest, int method) const;