summaryrefslogtreecommitdiffstats
path: root/examples/declarative/tutorials/contacts
diff options
context:
space:
mode:
Diffstat (limited to 'examples/declarative/tutorials/contacts')
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1/Removebutton.qml9
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1_Drawing_and_animation.qml34
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/2/RemoveButton.qml18
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/2a/RemoveButton.qml20
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/3/RemoveButton.qml39
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/4/RemoveButton.qml110
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/4a/RemoveButton.qml117
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/5/RemoveButton.qml117
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/GroupBox.qml57
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/1/ContactField.qml30
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/1/RemoveButton.qml115
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/1a/ContactField.qml33
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/1a/RemoveButton.qml115
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/1b/BlueRect.qml33
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/1b/lib/RemoveButton.qml117
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/2/ContactField.qml32
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/2/RemoveButton.qml123
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/2_Reuse.qml37
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/3/Contact.qml47
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/3/ContactField.qml61
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/3/FieldText.qml148
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/3/RemoveButton.qml119
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/4/Contact.qml50
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/4/ContactField.qml58
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/4/FieldText.qml149
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/4/RemoveButton.qml123
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/GroupBox.qml57
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/1/ContactView.qml44
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/2/ContactView.qml126
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/3/ContactView.qml139
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/3_Collections.qml29
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/GroupBox.qml57
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/lib/Button.qml57
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/lib/Contact.qml46
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/lib/ContactField.qml58
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/lib/FieldText.qml149
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/lib/RemoveButton.qml121
-rwxr-xr-xexamples/declarative/tutorials/contacts/shared/contactGenSQL.pl82
-rw-r--r--examples/declarative/tutorials/contacts/shared/contacts.sqlitebin0 -> 86016 bytes
-rw-r--r--examples/declarative/tutorials/contacts/shared/email.txt7
-rw-r--r--examples/declarative/tutorials/contacts/shared/english-f.txt143
-rw-r--r--examples/declarative/tutorials/contacts/shared/english-m.txt130
-rw-r--r--examples/declarative/tutorials/contacts/shared/english-s.txt1003
-rw-r--r--examples/declarative/tutorials/contacts/shared/pics/cancel.pngbin0 -> 1038 bytes
-rw-r--r--examples/declarative/tutorials/contacts/shared/pics/email.pngbin0 -> 977 bytes
-rw-r--r--examples/declarative/tutorials/contacts/shared/pics/new.pngbin0 -> 688 bytes
-rw-r--r--examples/declarative/tutorials/contacts/shared/pics/ok.pngbin0 -> 655 bytes
-rw-r--r--examples/declarative/tutorials/contacts/shared/pics/phone.pngbin0 -> 624 bytes
-rw-r--r--examples/declarative/tutorials/contacts/shared/pics/search.pngbin0 -> 635 bytes
-rw-r--r--examples/declarative/tutorials/contacts/shared/pics/trash.pngbin0 -> 989 bytes
50 files changed, 4159 insertions, 0 deletions
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1/Removebutton.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1/Removebutton.qml
new file mode 100644
index 0000000..bbe9f55
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1/Removebutton.qml
@@ -0,0 +1,9 @@
+//! [0]
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+}
+//! [0]
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1_Drawing_and_animation.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1_Drawing_and_animation.qml
new file mode 100644
index 0000000..cc5ebae
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1_Drawing_and_animation.qml
@@ -0,0 +1,34 @@
+Rect {
+ id: page
+ width: layout.width
+ height: layout.height
+ color: "white"
+ VerticalLayout {
+ id: layout
+ width: contents.width
+ GroupBox {
+ contents: "1/RemoveButton.qml"
+ label: "Rectangle Component"
+ }
+ GroupBox {
+ contents: "2/RemoveButton.qml"
+ label: "Closed Remove Item Button"
+ }
+ GroupBox {
+ contents: "2a/RemoveButton.qml"
+ label: "Alternative Closed Button"
+ }
+ GroupBox {
+ contents: "3/RemoveButton.qml"
+ label: "Open Remove Item Button"
+ }
+ GroupBox {
+ contents: "4/RemoveButton.qml"
+ label: "State Based Button"
+ }
+ GroupBox {
+ contents: "5/RemoveButton.qml"
+ label: "Animated Button"
+ }
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/2/RemoveButton.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/2/RemoveButton.qml
new file mode 100644
index 0000000..247e38b
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/2/RemoveButton.qml
@@ -0,0 +1,18 @@
+//! [0]
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+ Image {
+ id: trashIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/trash.png"
+ }
+}
+//! [0]
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/2a/RemoveButton.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/2a/RemoveButton.qml
new file mode 100644
index 0000000..6c6a949
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/2a/RemoveButton.qml
@@ -0,0 +1,20 @@
+//! [0]
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+ children: [
+ Image {
+ id: trashIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/trash.png"
+ }
+ ]
+}
+//! [0]
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/3/RemoveButton.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/3/RemoveButton.qml
new file mode 100644
index 0000000..3c20462
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/3/RemoveButton.qml
@@ -0,0 +1,39 @@
+//! [0]
+Rect {
+ id: removeButton
+ width: 230
+ height: 30
+ color: "red"
+ radius: 5
+ Image {
+ id: cancelIcon
+ width: 22
+ height: 22
+ anchors.right: parent.right
+ anchors.rightMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/cancel.png"
+ }
+ Image {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/ok.png"
+ }
+ 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"
+ }
+}
+//! [0]
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/4/RemoveButton.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/4/RemoveButton.qml
new file mode 100644
index 0000000..a359aaf
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/4/RemoveButton.qml
@@ -0,0 +1,110 @@
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+//! [script]
+ resources: [
+ Script {
+ function toggle() {
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ } else {
+ removeButton.state = 'opened';
+ }
+ }
+
+ }
+ ]
+//! [script]
+//! [mouse region]
+ 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() }
+ }
+ }
+//! [mouse region]
+ 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 {
+ 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() }
+ }
+ }
+ 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]
+ states: [
+ State {
+ name: "opened"
+ SetProperty {
+ target: removeButton
+ property: "width"
+ value: 230
+ }
+ 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
+ }
+ }
+ ]
+//! [states]
+}
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/4a/RemoveButton.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/4a/RemoveButton.qml
new file mode 100644
index 0000000..4db49ea
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/4a/RemoveButton.qml
@@ -0,0 +1,117 @@
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+//! [script]
+ resources: [
+ Script {
+ function toggle() {
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ } else {
+ removeButton.state = 'opened';
+ }
+ }
+
+ }
+ ]
+//! [script]
+//! [mouse region]
+ 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 {
+ id: trashMouseRegion
+ anchors.fill: parent
+ }
+ Connection {
+ sender: trashMouseRegion
+ signal: clicked()
+ script: {
+ toggle()
+ }
+ }
+ }
+//! [mouse region]
+ 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 {
+ 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() }
+ }
+ }
+ 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]
+ states: [
+ State {
+ name: "opened"
+ SetProperty {
+ target: removeButton
+ property: "width"
+ value: 230
+ }
+ 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
+ }
+ }
+ ]
+//! [states]
+}
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/5/RemoveButton.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/5/RemoveButton.qml
new file mode 100644
index 0000000..29d464b
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/5/RemoveButton.qml
@@ -0,0 +1,117 @@
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+ resources: [
+ Script {
+ function toggle() {
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ } else {
+ removeButton.state = 'opened';
+ }
+ }
+
+ }
+ ]
+ 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 {
+ 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 {
+ 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() }
+ }
+ }
+ 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: 230
+ }
+ 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
+ }
+ }
+ ]
+//! [transition]
+ transitions: [
+ Transition {
+ fromState: "*"
+ toState: "opened"
+ reversible: true
+ NumericAnimation {
+ properties: "opacity,x,width"
+ duration: 200
+ }
+ }
+ ]
+//! [transition]
+}
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/GroupBox.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/GroupBox.qml
new file mode 100644
index 0000000..edaae72
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/GroupBox.qml
@@ -0,0 +1,57 @@
+FocusRealm {
+ id: groupBox
+ width: Math.max(270, subItem.width+40)
+ height: Math.max(70, subItem.height+40)
+
+ property var contents
+ property var label
+
+ Rect {
+ id: wrapper
+ x: 5
+ y: 10
+ radius: 10
+ width: groupBox.width-20
+ height: groupBox.height-20
+ color: "white"
+ pen.color: "black"
+ Item {
+ id: subItem
+ qml: groupBox.contents
+ anchors.top: parent.top
+ anchors.topMargin: 10
+ anchors.right: parent.right
+ anchors.rightMargin: 10
+ width: qmlItem.width
+ height: qmlItem.height
+ }
+ }
+ Rect {
+ x: 20
+ y: 0
+ height: text.height
+ width: text.width+10
+ color: "white"
+ Text {
+ x: 5
+ id: text
+ text: label
+ font.bold: true
+ }
+ }
+ Rect {
+ color: "black"
+ anchors.fill: parent
+ opacity: parent.focus ? 0 : 0.3
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { parent.parent.focus=true }
+ }
+ opacity: Behaviour {
+ NumericAnimation {
+ property: "opacity"
+ duration: 250
+ }
+ }
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/1/ContactField.qml b/examples/declarative/tutorials/contacts/2_Reuse/1/ContactField.qml
new file mode 100644
index 0000000..0218c3d
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/1/ContactField.qml
@@ -0,0 +1,30 @@
+//! [load]
+Item {
+ id: contactField
+ clip: true
+ width: 230
+ height: 30
+ RemoveButton {
+ id: removeButton
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ }
+//! [load]
+ Text {
+ id: fieldText
+ width: contactField.width-80
+ anchors.right: removeButton.left
+ anchors.rightMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+ font.bold: true
+ color: "black"
+ text: 123123
+ }
+ Image {
+ source: "../../shared/pics/phone.png"
+ anchors.right: fieldText.left
+ anchors.rightMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/1/RemoveButton.qml b/examples/declarative/tutorials/contacts/2_Reuse/1/RemoveButton.qml
new file mode 100644
index 0000000..3142c45
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/1/RemoveButton.qml
@@ -0,0 +1,115 @@
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+ resources: [
+ Script {
+ function toggle() {
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ } else {
+ removeButton.state = 'opened';
+ }
+ }
+
+ }
+ ]
+ 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 {
+ 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 {
+ 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() }
+ }
+ }
+ 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: 230
+ }
+ 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/examples/declarative/tutorials/contacts/2_Reuse/1a/ContactField.qml b/examples/declarative/tutorials/contacts/2_Reuse/1a/ContactField.qml
new file mode 100644
index 0000000..62089b8
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/1a/ContactField.qml
@@ -0,0 +1,33 @@
+//! [load]
+Item {
+ id: contactField
+ clip: true
+ width: 230
+ height: 30
+ Item {
+ id: removeButton
+ qml: "RemoveButton.qml"
+ width: qmlItem.width
+ height: qmlItem.height
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ }
+//! [load]
+ Text {
+ id: fieldText
+ width: contactField.width-80
+ anchors.right: removeButton.left
+ anchors.rightMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+ font.bold: true
+ color: "black"
+ text: 123123
+ }
+ Image {
+ source: "../../shared/pics/phone.png"
+ anchors.right: fieldText.left
+ anchors.rightMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/1a/RemoveButton.qml b/examples/declarative/tutorials/contacts/2_Reuse/1a/RemoveButton.qml
new file mode 100644
index 0000000..3142c45
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/1a/RemoveButton.qml
@@ -0,0 +1,115 @@
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+ resources: [
+ Script {
+ function toggle() {
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ } else {
+ removeButton.state = 'opened';
+ }
+ }
+
+ }
+ ]
+ 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 {
+ 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 {
+ 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() }
+ }
+ }
+ 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: 230
+ }
+ 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/examples/declarative/tutorials/contacts/2_Reuse/1b/BlueRect.qml b/examples/declarative/tutorials/contacts/2_Reuse/1b/BlueRect.qml
new file mode 100644
index 0000000..92893f6
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/1b/BlueRect.qml
@@ -0,0 +1,33 @@
+//! [all]
+Rect {
+ width: 100
+ height: 100
+ color: "blue"
+ resources: [
+ Component {
+ id: redRectangle
+ Rect {
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+ }
+ }
+ ]
+ ComponentInstance {
+ component: redRectangle
+ anchors.right: parent.right
+ anchors.top: parent.top
+ }
+ ComponentInstance {
+ component: redRectangle
+ anchors.left: parent.left
+ anchors.top: parent.top
+ }
+ ComponentInstance {
+ component: redRectangle
+ anchors.left: parent.left
+ anchors.bottom: parent.bottom
+ }
+}
+//! [all]
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/1b/lib/RemoveButton.qml b/examples/declarative/tutorials/contacts/2_Reuse/1b/lib/RemoveButton.qml
new file mode 100644
index 0000000..bf6e82d
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/1b/lib/RemoveButton.qml
@@ -0,0 +1,117 @@
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+ resources: [
+ Script {
+
+ function toggle() {
+ print('removeButton.toggle()');
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ } else {
+ removeButton.state = 'opened';
+ }
+ }
+
+ }
+ ]
+ 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 {
+ 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 {
+ 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() }
+ }
+ }
+ 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: 230
+ }
+ 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/examples/declarative/tutorials/contacts/2_Reuse/2/ContactField.qml b/examples/declarative/tutorials/contacts/2_Reuse/2/ContactField.qml
new file mode 100644
index 0000000..2542c1c
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/2/ContactField.qml
@@ -0,0 +1,32 @@
+Item {
+ id: contactField
+ clip: true
+ width: 230
+ height: 30
+//! [use properties and signals]
+ RemoveButton {
+ id: removeButton
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ expandedWidth: contactField.width
+ onConfirmed: { fieldText.text='' }
+ }
+//! [use properties and signals]
+ Text {
+ id: fieldText
+ width: contactField.width-80
+ anchors.right: removeButton.left
+ anchors.rightMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+ font.bold: true
+ color: "black"
+ text: 123123
+ }
+ Image {
+ source: "../../shared/pics/phone.png"
+ anchors.right: fieldText.left
+ anchors.rightMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/2/RemoveButton.qml b/examples/declarative/tutorials/contacts/2_Reuse/2/RemoveButton.qml
new file mode 100644
index 0000000..99a521d
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/2/RemoveButton.qml
@@ -0,0 +1,123 @@
+//! [define properties and signals]
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+ property var expandedWidth: 230
+ signal confirmed
+//! [define properties and signals]
+ resources: [
+ Script {
+ function toggle() {
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ } else {
+ removeButton.state = 'opened';
+ }
+ }
+
+ }
+ ]
+ 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 {
+ 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 {
+ id: confirmIcon
+ width: 22
+ height: 22
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../shared/pics/ok.png"
+ opacity: 0
+//! [use signal]
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { toggle(); removeButton.confirmed.emit() }
+ }
+//! [use signal]
+ }
+ 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"
+//! [use width]
+ SetProperty {
+ target: removeButton
+ property: "width"
+ value: removeButton.expandedWidth
+ }
+//! [use width]
+ 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/examples/declarative/tutorials/contacts/2_Reuse/2_Reuse.qml b/examples/declarative/tutorials/contacts/2_Reuse/2_Reuse.qml
new file mode 100644
index 0000000..6ad2eb5
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/2_Reuse.qml
@@ -0,0 +1,37 @@
+Rect {
+ id: page
+ width: layout.width
+ height: layout.height
+ color: "white"
+ GridLayout {
+ id: layout
+ columns: 2
+ rows: 4
+ width: contents.width
+ GroupBox {
+ contents: "1/ContactField.qml"
+ label: "Loading: simple"
+ }
+ GroupBox {
+ contents: "1a/ContactField.qml"
+ label: "Loading: qml property"
+ }
+ GroupBox {
+ contents: "2/ContactField.qml"
+ label: "Using properties"
+ }
+ GroupBox {
+ id: prev
+ contents: "3/ContactField.qml"
+ label: "Defining signals"
+ }
+ GroupBox {
+ contents: "3/Contact.qml"
+ label: "Multiple Items"
+ }
+ GroupBox {
+ contents: "4/Contact.qml"
+ label: "Mouse Grabbing"
+ }
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/3/Contact.qml b/examples/declarative/tutorials/contacts/2_Reuse/3/Contact.qml
new file mode 100644
index 0000000..763a771
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/3/Contact.qml
@@ -0,0 +1,47 @@
+Item {
+ id: contactDetails
+ width: 230
+ height: layout.height
+
+ property var contactId: ""
+ property var label: ""
+ property var phone: ""
+ property var email: ""
+
+ onLabelChanged: { labelField.value = label }
+ onEmailChanged: { emailField.value = email }
+ onPhoneChanged: { phoneField.value = phone }
+
+ 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"
+ }
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/3/ContactField.qml b/examples/declarative/tutorials/contacts/2_Reuse/3/ContactField.qml
new file mode 100644
index 0000000..890d781
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/3/ContactField.qml
@@ -0,0 +1,61 @@
+//! [all]
+Item {
+ id: contactField
+ clip: true
+ width: 230
+ height: 30
+ property var label: "Name"
+ property var icon: "../../shared/pics/phone.png"
+ property var value: ""
+ RemoveButton {
+ id: removeButton
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ expandedWidth: contactField.width
+ onConfirmed: { 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
+ }
+ 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
+ }
+ }
+ ]
+}
+//! [all]
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/3/FieldText.qml b/examples/declarative/tutorials/contacts/2_Reuse/3/FieldText.qml
new file mode 100644
index 0000000..f6cc1e4
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/3/FieldText.qml
@@ -0,0 +1,148 @@
+//! [value change]
+Rect {
+ id: fieldText
+ height: 30
+ radius: 5
+ color: "white"
+ property var text: ""
+ onTextChanged: { reset() }
+//! [value change]
+ property var label: ""
+ signal confirmed
+ resources: [
+ Script {
+
+ function edit() {
+ fieldText.state='editing';
+ }
+ function confirm() {
+ fieldText.text = textEdit.text;
+ fieldText.state='';
+ fieldText.confirmed.emit();
+ }
+ function reset() {
+ textEdit.text = fieldText.text;
+ fieldText.state='';
+ }
+
+ }
+ ]
+ 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: 5
+ anchors.right: parent.right
+ anchors.rightMargin: 5
+ anchors.verticalCenter: parent.verticalCenter
+ color: "black"
+ font.bold: true
+ readOnly: true
+ wrap: false
+ }
+//! [behavior]
+ 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
+ }
+ }
+ }
+//! [behavior]
+ 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: 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: 39
+ }
+ SetProperty {
+ target: textEdit.anchors
+ property: "rightMargin"
+ value: 39
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: ""
+ toState: "*"
+ reversible: true
+ NumericAnimation {
+ properties: "opacity,leftMargin,rightMargin"
+ duration: 200
+ }
+ ColorAnimation {
+ duration: 150
+ }
+ }
+ ]
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/3/RemoveButton.qml b/examples/declarative/tutorials/contacts/2_Reuse/3/RemoveButton.qml
new file mode 100644
index 0000000..2f27a69
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/3/RemoveButton.qml
@@ -0,0 +1,119 @@
+//! [all]
+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 = '';
+ } else {
+ removeButton.state = 'opened';
+ }
+ }
+
+ }
+ ]
+ 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 {
+ 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 {
+ 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() }
+ }
+ }
+ 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
+ }
+ }
+ ]
+}
+//! [all]
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/4/Contact.qml b/examples/declarative/tutorials/contacts/2_Reuse/4/Contact.qml
new file mode 100644
index 0000000..bcb242f
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/4/Contact.qml
@@ -0,0 +1,50 @@
+//! [grab property]
+Item {
+ id: contactDetails
+ width: 230
+ height: layout.height
+ property var mouseGrabbed: false
+//! [grab property]
+
+ property var contactId: ""
+ property var label: ""
+ property var phone: ""
+ property var email: ""
+
+ onLabelChanged: { labelField.value = label }
+ onEmailChanged: { emailField.value = email }
+ onPhoneChanged: { phoneField.value = phone }
+
+ 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"
+ }
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/4/ContactField.qml b/examples/declarative/tutorials/contacts/2_Reuse/4/ContactField.qml
new file mode 100644
index 0000000..e9927e9
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/4/ContactField.qml
@@ -0,0 +1,58 @@
+Item {
+ id: contactField
+ clip: true
+ height: 30
+ property var label: "Name"
+ property var icon: "../../shared/pics/phone.png"
+ property var value: ""
+ RemoveButton {
+ id: removeButton
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ expandedWidth: contactField.width
+ onConfirmed: { 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
+ }
+ 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/examples/declarative/tutorials/contacts/2_Reuse/4/FieldText.qml b/examples/declarative/tutorials/contacts/2_Reuse/4/FieldText.qml
new file mode 100644
index 0000000..e969f7b
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/4/FieldText.qml
@@ -0,0 +1,149 @@
+Rect {
+ id: fieldText
+ height: 30
+ radius: 5
+ color: "white"
+ property var text: ""
+ property var label: ""
+ onTextChanged: { reset() }
+ signal confirmed
+ resources: [
+ Script {
+
+ function edit() {
+ if (!contactDetails.mouseGrabbed) {
+ fieldText.state='editing';
+ contactDetails.mouseGrabbed=true;
+ }
+ }
+ function confirm() {
+ fieldText.text = textEdit.text;
+ fieldText.state='';
+ contactDetails.mouseGrabbed=false;
+ fieldText.confirmed.emit();
+ }
+ function reset() {
+ textEdit.text = fieldText.text;
+ fieldText.state='';
+ contactDetails.mouseGrabbed=false;
+ }
+
+ }
+ ]
+ 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: 5
+ anchors.right: parent.right
+ anchors.rightMargin: 5
+ anchors.verticalCenter: parent.verticalCenter
+ color: "black"
+ 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
+ }
+ }
+ }
+ 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: 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: 39
+ }
+ SetProperty {
+ target: textEdit.anchors
+ property: "rightMargin"
+ value: 39
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: ""
+ toState: "*"
+ reversible: true
+ NumericAnimation {
+ properties: "opacity,leftMargin,rightMargin"
+ duration: 200
+ }
+ ColorAnimation {
+ duration: 150
+ }
+ }
+ ]
+}
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/4/RemoveButton.qml b/examples/declarative/tutorials/contacts/2_Reuse/4/RemoveButton.qml
new file mode 100644
index 0000000..bfe496e
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/4/RemoveButton.qml
@@ -0,0 +1,123 @@
+Rect {
+ id: removeButton
+ width: 30
+ height: 30
+ color: "red"
+ radius: 5
+ property var expandedWidth: 230
+ signal confirmed
+ resources: [
+//! [grab]
+ Script {
+ function toggle() {
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ contactDetails.mouseGrabbed=false;
+ } else {
+ if (!contactDetails.mouseGrabbed) {
+ removeButton.state = 'opened';
+ contactDetails.mouseGrabbed=true;
+ }
+ }
+ }
+
+ }
+//! [grab]
+ ]
+ 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 {
+ 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 {
+ 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() }
+ }
+ }
+ 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/examples/declarative/tutorials/contacts/2_Reuse/GroupBox.qml b/examples/declarative/tutorials/contacts/2_Reuse/GroupBox.qml
new file mode 100644
index 0000000..edaae72
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/GroupBox.qml
@@ -0,0 +1,57 @@
+FocusRealm {
+ id: groupBox
+ width: Math.max(270, subItem.width+40)
+ height: Math.max(70, subItem.height+40)
+
+ property var contents
+ property var label
+
+ Rect {
+ id: wrapper
+ x: 5
+ y: 10
+ radius: 10
+ width: groupBox.width-20
+ height: groupBox.height-20
+ color: "white"
+ pen.color: "black"
+ Item {
+ id: subItem
+ qml: groupBox.contents
+ anchors.top: parent.top
+ anchors.topMargin: 10
+ anchors.right: parent.right
+ anchors.rightMargin: 10
+ width: qmlItem.width
+ height: qmlItem.height
+ }
+ }
+ Rect {
+ x: 20
+ y: 0
+ height: text.height
+ width: text.width+10
+ color: "white"
+ Text {
+ x: 5
+ id: text
+ text: label
+ font.bold: true
+ }
+ }
+ Rect {
+ color: "black"
+ anchors.fill: parent
+ opacity: parent.focus ? 0 : 0.3
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { parent.parent.focus=true }
+ }
+ opacity: Behaviour {
+ NumericAnimation {
+ property: "opacity"
+ duration: 250
+ }
+ }
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/3_Collections/1/ContactView.qml b/examples/declarative/tutorials/contacts/3_Collections/1/ContactView.qml
new file mode 100644
index 0000000..5400544
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/1/ContactView.qml
@@ -0,0 +1,44 @@
+import "../lib"
+Item {
+ id: contacts
+ width: 240
+ height: 230
+ property var mouseGrabbed: false
+ resources: [
+//! [model]
+ SqlConnection {
+ id: contactDatabase
+ name: "qmlConnection"
+ driver: "QSQLITE"
+ databaseName: "../../shared/contacts.sqlite"
+ },
+ SqlQuery {
+ id: contactList
+ connection: contactDatabase
+ query: "SELECT recid, label, email, phone FROM contacts ORDER BY label, recid"
+ }
+//! [model]
+ ]
+//! [view]
+ ListView {
+ id: contactListView
+ anchors.fill: parent
+ clip: true
+ model: contactList
+ focus: true
+//! [delegate]
+ delegate: [
+ Text {
+ x: 45
+ y: 12
+ width: contactListView.width-45
+ height: 30
+ color: "black"
+ font.bold: true
+ text: model.label
+ }
+ ]
+//! [delegate]
+ }
+//! [view]
+}
diff --git a/examples/declarative/tutorials/contacts/3_Collections/2/ContactView.qml b/examples/declarative/tutorials/contacts/3_Collections/2/ContactView.qml
new file mode 100644
index 0000000..0a293f5
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/2/ContactView.qml
@@ -0,0 +1,126 @@
+import "../lib"
+Item {
+ id: contacts
+ width: 240
+ height: 230
+ property var mouseGrabbed: false
+ resources: [
+ SqlConnection {
+ id: contactDatabase
+ name: "qmlConnection"
+ driver: "QSQLITE"
+ databaseName: "../../shared/contacts.sqlite"
+ },
+ SqlQuery {
+ id: contactList
+ connection: contactDatabase
+ query: "SELECT recid, label, email, phone FROM contacts ORDER BY label, recid"
+ }
+ ]
+//! [button]
+ Button {
+ id: cancelEditButton
+ anchors.top: parent.top
+ anchors.topMargin: 5
+ anchors.right: parent.right
+ anchors.rightMargin: 5
+ icon: "../../shared/pics/cancel.png"
+ opacity: mouseGrabbed ? 0 : 1
+ }
+//! [button]
+ ListView {
+ id: contactListView
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: cancelEditButton.bottom
+ anchors.bottom: parent.bottom
+ clip: true
+ model: contactList
+ focus: true
+ delegate: [
+//! [components]
+ Item {
+ id: wrapper
+ x: 0
+ width: ListView.view.width
+ height: 34
+ Text {
+ id: label
+ x: 45
+ y: 12
+ width: parent.width-45
+ color: "black"
+ font.bold: true
+ text: model.label
+ }
+ MouseRegion {
+ anchors.fill: label
+ onClicked: { wrapper.state='opened'; }
+ }
+ Contact {
+ id: Details
+ anchors.fill: parent
+ contactId: model.recid
+ label: model.label
+ email: model.email
+ phone: model.phone
+ opacity: 0
+ }
+//! [components]
+//! [states]
+ 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
+ }
+ }
+ ]
+//! [states]
+//! [transitions]
+ transitions: [
+ Transition {
+ NumericAnimation {
+ duration: 500
+ properties: "yPosition,height,opacity"
+ }
+ }
+ ]
+//! [transitions]
+//! [connections]
+ Connection {
+ sender: cancelEditButton
+ signal: "clicked()"
+ script: {
+ if (wrapper.state == 'opened') {
+ wrapper.state = '';
+ }
+ }
+ }
+//! [connections]
+ }
+ ]
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/3_Collections/3/ContactView.qml b/examples/declarative/tutorials/contacts/3_Collections/3/ContactView.qml
new file mode 100644
index 0000000..7a44a3f
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/3/ContactView.qml
@@ -0,0 +1,139 @@
+import "../lib"
+Item {
+ id: contacts
+ width: 240
+ height: 230
+ property var mouseGrabbed: false
+ resources: [
+ SqlConnection {
+ id: contactDatabase
+ name: "qmlConnection"
+ driver: "QSQLITE"
+ databaseName: "../../shared/contacts.sqlite"
+ },
+ SqlQuery {
+ id: contactList
+ connection: contactDatabase
+ query: "SELECT recid, label, email, phone FROM contacts ORDER BY label, recid"
+ }
+ ]
+ Button {
+ id: cancelEditButton
+ anchors.top: parent.top
+ anchors.topMargin: 5
+ anchors.right: parent.right
+ anchors.rightMargin: 5
+ icon: "../../shared/pics/cancel.png"
+ opacity: mouseGrabbed ? 0 : 1
+ }
+ ListView {
+ id: contactListView
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: cancelEditButton.bottom
+ anchors.bottom: parent.bottom
+ clip: true
+ model: contactList
+ focus: true
+ delegate: [
+ Item {
+ id: wrapper
+ x: 0
+ width: ListView.view.width
+ height: 34
+ Text {
+ id: label
+ x: 45
+ y: 12
+ width: parent.width-45
+ color: "black"
+ font.bold: true
+ text: model.label
+ }
+//! [setting qml]
+ MouseRegion {
+ anchors.fill: label
+ onClicked: {
+ Details.qml = 'Contact.qml';
+ wrapper.state='opened';
+ }
+ }
+ Item {
+ id: Details
+ anchors.fill: parent
+ opacity: 0
+//! [setting qml]
+//! [binding]
+ 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
+ }
+//! [binding]
+ }
+ 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: cancelEditButton
+ signal: "clicked()"
+ script: {
+ if (wrapper.state == 'opened') {
+ wrapper.state = '';
+ }
+ }
+ }
+ }
+ ]
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/3_Collections/3_Collections.qml b/examples/declarative/tutorials/contacts/3_Collections/3_Collections.qml
new file mode 100644
index 0000000..7d9937c
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/3_Collections.qml
@@ -0,0 +1,29 @@
+Rect {
+ id: page
+ width: layout.width
+ height: layout.height
+ color: "white"
+ Bind {
+ id: currentItem
+ value: true
+ }
+ // relies on the current focus behavior whereby setting focus=true on a
+ // component removes focus from any previous element
+ GridLayout {
+ id: layout
+ width: contents.width
+ height: contents.height
+ GroupBox {
+ contents: "1/ContactView.qml"
+ label: "list only"
+ }
+ GroupBox {
+ contents: "2/ContactView.qml"
+ label: "dynamic delegate"
+ }
+ GroupBox {
+ contents: "3/ContactView.qml"
+ label: "delayed loading"
+ }
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/3_Collections/GroupBox.qml b/examples/declarative/tutorials/contacts/3_Collections/GroupBox.qml
new file mode 100644
index 0000000..edaae72
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/GroupBox.qml
@@ -0,0 +1,57 @@
+FocusRealm {
+ id: groupBox
+ width: Math.max(270, subItem.width+40)
+ height: Math.max(70, subItem.height+40)
+
+ property var contents
+ property var label
+
+ Rect {
+ id: wrapper
+ x: 5
+ y: 10
+ radius: 10
+ width: groupBox.width-20
+ height: groupBox.height-20
+ color: "white"
+ pen.color: "black"
+ Item {
+ id: subItem
+ qml: groupBox.contents
+ anchors.top: parent.top
+ anchors.topMargin: 10
+ anchors.right: parent.right
+ anchors.rightMargin: 10
+ width: qmlItem.width
+ height: qmlItem.height
+ }
+ }
+ Rect {
+ x: 20
+ y: 0
+ height: text.height
+ width: text.width+10
+ color: "white"
+ Text {
+ x: 5
+ id: text
+ text: label
+ font.bold: true
+ }
+ }
+ Rect {
+ color: "black"
+ anchors.fill: parent
+ opacity: parent.focus ? 0 : 0.3
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: { parent.parent.focus=true }
+ }
+ opacity: Behaviour {
+ NumericAnimation {
+ property: "opacity"
+ duration: 250
+ }
+ }
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/3_Collections/lib/Button.qml b/examples/declarative/tutorials/contacts/3_Collections/lib/Button.qml
new file mode 100644
index 0000000..d9f1236
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/lib/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/examples/declarative/tutorials/contacts/3_Collections/lib/Contact.qml b/examples/declarative/tutorials/contacts/3_Collections/lib/Contact.qml
new file mode 100644
index 0000000..6832076
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/lib/Contact.qml
@@ -0,0 +1,46 @@
+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 }
+
+ 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"
+ }
+ }
+}
diff --git a/examples/declarative/tutorials/contacts/3_Collections/lib/ContactField.qml b/examples/declarative/tutorials/contacts/3_Collections/lib/ContactField.qml
new file mode 100644
index 0000000..e9927e9
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/lib/ContactField.qml
@@ -0,0 +1,58 @@
+Item {
+ id: contactField
+ clip: true
+ height: 30
+ property var label: "Name"
+ property var icon: "../../shared/pics/phone.png"
+ property var value: ""
+ RemoveButton {
+ id: removeButton
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ expandedWidth: contactField.width
+ onConfirmed: { 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
+ }
+ 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/examples/declarative/tutorials/contacts/3_Collections/lib/FieldText.qml b/examples/declarative/tutorials/contacts/3_Collections/lib/FieldText.qml
new file mode 100644
index 0000000..427e2b0
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/lib/FieldText.qml
@@ -0,0 +1,149 @@
+Rect {
+ id: fieldText
+ height: 30
+ radius: 5
+ color: "white"
+ 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: "../../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: 5
+ anchors.right: parent.right
+ anchors.rightMargin: 5
+ anchors.verticalCenter: parent.verticalCenter
+ color: "black"
+ 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
+ }
+ }
+ }
+ 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: 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: 39
+ }
+ SetProperty {
+ target: textEdit.anchors
+ property: "rightMargin"
+ value: 39
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ fromState: ""
+ toState: "*"
+ reversible: true
+ NumericAnimation {
+ properties: "opacity,leftMargin,rightMargin"
+ duration: 200
+ }
+ ColorAnimation {
+ duration: 150
+ }
+ }
+ ]
+}
diff --git a/examples/declarative/tutorials/contacts/3_Collections/lib/RemoveButton.qml b/examples/declarative/tutorials/contacts/3_Collections/lib/RemoveButton.qml
new file mode 100644
index 0000000..c0ea79d
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/lib/RemoveButton.qml
@@ -0,0 +1,121 @@
+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: "../../shared/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: "../../shared/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: "../../shared/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/examples/declarative/tutorials/contacts/shared/contactGenSQL.pl b/examples/declarative/tutorials/contacts/shared/contactGenSQL.pl
new file mode 100755
index 0000000..2d328da
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/contactGenSQL.pl
@@ -0,0 +1,82 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+my $count = shift;
+
+open(MFIRST, "<english-m.txt") or die "Could not open male names";
+open(FFIRST, "<english-f.txt") or die "Could not open female names";
+open(SURNAME, "<english-s.txt") or die "Could not open surnames names";
+open(ISP, "<email.txt") or die "Could not open isp names";
+
+my @mnames = <MFIRST>;
+my @fnames = <FFIRST>;
+my @surnames = <SURNAME>;
+my @isps = <ISP>;
+
+print "BEGIN;\n";
+print "CREATE TABLE contacts (recid INTEGER PRIMARY KEY, label TEXT, phone TEXT, email TEXT);\n";
+print "CREATE INDEX contactSortOrder ON contacts(label, recid);\n";
+
+my $i = 0;
+while ($i < $count) {
+ $i++;
+ my $fn = randomFirstName();
+ my $sn = randomLastName();
+ my $em = randomEmail($fn, $sn);
+ my $ph = randomPhoneNumber();
+
+ $fn =~ s/'/''/g;
+ $sn =~ s/'/''/g;
+ $em =~ s/'/''/g;
+ print "INSERT INTO contacts (label, email, phone) VALUES('$fn $sn', '$em', '$ph');\n"
+}
+
+print "COMMIT;\n";
+
+
+sub randomFirstName
+{
+ my $name;
+ if (int(rand 2) == 1) {
+ $name = $mnames[int(rand @mnames)];
+ } else {
+ $name = $fnames[int(rand @fnames)];
+ }
+ chomp $name;
+ $name;
+}
+
+sub randomLastName
+{
+ my $name = $surnames[int(rand @surnames)];
+ chomp $name;
+ $name;
+}
+
+sub randomEmail
+{
+ my ($fn, $ln) = @_;
+ my $isp = $isps[int(rand @isps)];
+ chomp $isp;
+ my $path = int(rand 3);
+ my $email;
+ if ($path == 0) {
+ $email = "$fn.$ln\@$isp";
+ } elsif ($path == 1) {
+ $email = "$fn\@$isp";
+ } elsif ($path == 2) {
+ $email = "$ln\@$isp";
+ }
+}
+
+sub randomPhoneNumber
+{
+ my @digits = qw(1 2 3 4 5 6 7 8 9 0);
+ my $phonenumber;
+ for (1 .. 8) {
+ $phonenumber .= $digits[int(rand @digits)];
+ }
+ $phonenumber;
+}
diff --git a/examples/declarative/tutorials/contacts/shared/contacts.sqlite b/examples/declarative/tutorials/contacts/shared/contacts.sqlite
new file mode 100644
index 0000000..d903775
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/contacts.sqlite
Binary files differ
diff --git a/examples/declarative/tutorials/contacts/shared/email.txt b/examples/declarative/tutorials/contacts/shared/email.txt
new file mode 100644
index 0000000..de9894b
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/email.txt
@@ -0,0 +1,7 @@
+emails.com
+emails.net
+mailserver.org
+mailserver.net
+mailserver.com
+BobsMail.com
+BillMail.com
diff --git a/examples/declarative/tutorials/contacts/shared/english-f.txt b/examples/declarative/tutorials/contacts/shared/english-f.txt
new file mode 100644
index 0000000..7da5474
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/english-f.txt
@@ -0,0 +1,143 @@
+Aimee
+Aleksandra
+Alice
+Alicia
+Allison
+Alyssa
+Amy
+Andrea
+Angel
+Angela
+Ann
+Anna
+Anne
+Anne
+Marie
+Annie
+Ashley
+Barbara
+Beatrice
+Beth
+Betty
+Brenda
+Brooke
+Candace
+Cara
+Caren
+Carol
+Caroline
+Carolyn
+Carrie
+Cassandra
+Catherine
+Charlotte
+Chrissy
+Christen
+Christina
+Christine
+Christy
+Claire
+Claudia
+Courtney
+Crystal
+Cynthia
+Dana
+Danielle
+Deanne
+Deborah
+Deirdre
+Denise
+Diane
+Dianne
+Dorothy
+Eileen
+Elena
+Elizabeth
+Emily
+Erica
+Erin
+Frances
+Gina
+Giulietta
+Heather
+Helen
+Jane
+Janet
+Janice
+Jenna
+Jennifer
+Jessica
+Joanna
+Joyce
+Julia
+Juliana
+Julie
+Justine
+Kara
+Karen
+Katharine
+Katherine
+Kathleen
+Kathryn
+Katrina
+Kelly
+Kerry
+Kim
+Kimberly
+Kristen
+Kristina
+Kristine
+Laura
+Laurel
+Lauren
+Laurie
+Leah
+Linda
+Lisa
+Lori
+Marcia
+Margaret
+Maria
+Marina
+Marisa
+Martha
+Mary
+Mary
+Ann
+Maya
+Melanie
+Melissa
+Michelle
+Monica
+Nancy
+Natalie
+Nicole
+Nina
+Pamela
+Patricia
+Rachel
+Rebecca
+Renee
+Sandra
+Sara
+Sharon
+Sheri
+Shirley
+Sonia
+Stefanie
+Stephanie
+Susan
+Suzanne
+Sylvia
+Tamara
+Tara
+Tatiana
+Terri
+Theresa
+Tiffany
+Tracy
+Valerie
+Veronica
+Vicky
+Vivian
+Wendy
diff --git a/examples/declarative/tutorials/contacts/shared/english-m.txt b/examples/declarative/tutorials/contacts/shared/english-m.txt
new file mode 100644
index 0000000..3c7b13e
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/english-m.txt
@@ -0,0 +1,130 @@
+Aaron
+Adam
+Adrian
+Alan
+Alejandro
+Alex
+Allen
+Andrew
+Andy
+Anthony
+Art
+Arthur
+Barry
+Bart
+Ben
+Benjamin
+Bill
+Bobby
+Brad
+Bradley
+Brendan
+Brett
+Brian
+Bruce
+Bryan
+Carlos
+Chad
+Charles
+Chris
+Christopher
+Chuck
+Clay
+Corey
+Craig
+Dan
+Daniel
+Darren
+Dave
+David
+Dean
+Dennis
+Denny
+Derek
+Don
+Doug
+Duane
+Edward
+Eric
+Eugene
+Evan
+Frank
+Fred
+Gary
+Gene
+George
+Gordon
+Greg
+Harry
+Henry
+Hunter
+Ivan
+Jack
+James
+Jamie
+Jason
+Jay
+Jeff
+Jeffrey
+Jeremy
+Jim
+Joe
+Joel
+John
+Jonathan
+Joseph
+Justin
+Keith
+Ken
+Kevin
+Larry
+Logan
+Marc
+Mark
+Matt
+Matthew
+Michael
+Mike
+Nat
+Nathan
+Patrick
+Paul
+Perry
+Peter
+Philip
+Phillip
+Randy
+Raymond
+Ricardo
+Richard
+Rick
+Rob
+Robert
+Rod
+Roger
+Ross
+Ruben
+Russell
+Ryan
+Sam
+Scot
+Scott
+Sean
+Shaun
+Stephen
+Steve
+Steven
+Stewart
+Stuart
+Ted
+Thomas
+Tim
+Toby
+Todd
+Tom
+Troy
+Victor
+Wade
+Walter
+Wayne
+William
diff --git a/examples/declarative/tutorials/contacts/shared/english-s.txt b/examples/declarative/tutorials/contacts/shared/english-s.txt
new file mode 100644
index 0000000..1f3682d
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/english-s.txt
@@ -0,0 +1,1003 @@
+Adams
+Adamson
+Adler
+Akers
+Akin
+Aleman
+Alexander
+Allen
+Allison
+Allwood
+Anderson
+Andreou
+Anthony
+Appelbaum
+Applegate
+Arbore
+Arenson
+Armold
+Arntzen
+Askew
+Athanas
+Atkinson
+Ausman
+Austin
+Averitt
+Avila-Sakar
+Badders
+Baer
+Baggerly
+Bailliet
+Baird
+Baker
+Ball
+Ballentine
+Ballew
+Banks
+Baptist-Nguyen
+Barbee
+Barber
+Barchas
+Barcio
+Bardsley
+Barkauskas
+Barnes
+Barnett
+Barnwell
+Barrera
+Barreto
+Barroso
+Barrow
+Bart
+Barton
+Bass
+Bates
+Bavinger
+Baxter
+Bazaldua
+Becker
+Beeghly
+Belforte
+Bellamy
+Bellavance
+Beltran
+Belusar
+Bennett
+Benoit
+Bensley
+Berger
+Berggren
+Bergman
+Berry
+Bertelson
+Bess
+Beusse
+Bickford
+Bierner
+Bird
+Birdwell
+Bixby
+Blackmon
+Blackwell
+Blair
+Blankinship
+Blanton
+Block
+Blomkalns
+Bloomfield
+Blume
+Boeckenhauer
+Bolding
+Bolt
+Bolton
+Book
+Boucher
+Boudreau
+Bowman
+Boyd
+Boyes
+Boyles
+Braby
+Braden
+Bradley
+Brady
+Bragg
+Brandow
+Brantley
+Brauner
+Braunhardt
+Bray
+Bredenberg
+Bremer
+Breyer
+Bricout
+Briggs
+Brittain
+Brockman
+Brockmoller
+Broman
+Brooks
+Brown
+Brubaker
+Bruce
+Brumfield
+Brumley
+Bruning
+Buck
+Budd
+Buhler
+Buhr
+Burleson
+Burns
+Burton
+Bush
+Butterfield
+Byers
+Byon
+Byrd
+Bzostek
+Cabrera
+Caesar
+Caffey
+Caffrey
+Calhoun
+Call
+Callahan
+Campbell
+Cano
+Capri
+Carey
+Carlisle
+Carlson
+Carmichael
+Carnes
+Carr
+Carreira
+Carroll
+Carson
+Carswell
+Carter
+Cartwright
+Cason
+Cates
+Catlett
+Caudle
+Cavallaro
+Cave
+Cazamias
+Chabot
+Chance
+Chapman
+Characklis
+Cheatham
+Chen
+Chern
+Cheville
+Chong
+Christensen
+Church
+Claibourn
+Clark
+Clasen
+Claude
+Close
+Coakley
+Coffey
+Cohen
+Cole
+Collier
+Conant
+Connell
+Conte
+Conway
+Cooley
+Cooper
+Copeland
+Coram
+Corbett
+Cort
+Cortes
+Cousins
+Cowsar
+Cox
+Coyne
+Crain
+Crankshaw
+Craven
+Crawford
+Cressman
+Crestani
+Crier
+Crocker
+Cromwell
+Crouse
+Crowder
+Crowe
+Culpepper
+Cummings
+Cunningham
+Currie
+Cusey
+Cutcher
+Cyprus
+D'Ascenzo
+Dabak
+Dakoulas
+Daly
+Dana
+Danburg
+Danenhauer
+Darley
+Darrouzet
+Dartt
+Daugherty
+Davila
+Davis
+Dawkins
+Day
+DeHart
+DeMoss
+DeMuth
+DeVincentis
+Deaton
+Dees
+Degenhardt
+Deggeller
+Deigaard
+Delabroy
+Delaney
+Demir
+Denison
+Denney
+Derr
+Deuel
+Devitt
+Diamond
+Dickinson
+Dietrich
+Dilbeck
+Dobson
+Dodds
+Dodson
+Doherty
+Dooley
+Dorsey
+Dortch
+Doughty
+Dove
+Dowd
+Dowling
+Drescher
+Drucker
+Dryer
+Dryver
+Duckworth
+Dunbar
+Dunham
+Dunn
+Duston
+Dettweiler
+Dyson
+Eason
+Eaton
+Ebert
+Eckhoff
+Edelman
+Edmonds
+Eichhorn
+Eisbach
+Elders
+Elias
+Elijah
+Elizabeth
+Elliott
+Elliston
+Elms
+Emerson
+Engelberg
+Engle
+Eplett
+Epp
+Erickson
+Estades
+Etezadi
+Evans
+Ewing
+Fair
+Farfan
+Fargason
+Farhat
+Farry
+Fawcett
+Faye
+Federle
+Felcher
+Feldman
+Ferguson
+Fergusson
+Fernandez
+Ferrer
+Fine
+Fineman
+Fisher
+Flanagan
+Flathmann
+Fleming
+Fletcher
+Folk
+Fortune
+Fossati
+Foster
+Foulston
+Fowler
+Fox
+Francis
+Frantom
+Franz
+Frazer
+Fredericks
+Frey
+Freymann
+Fuentes
+Fuller
+Fundling
+Furlong
+Gainer
+Galang
+Galeazzi
+Gamse
+Gannaway
+Garcia
+Gardner
+Garneau
+Gartler
+Garverick
+Garza
+Gatt
+Gattis
+Gayman
+Geiger
+Gelder
+George
+Gerbino
+Gerbode
+Gibson
+Gifford
+Gillespie
+Gillingham
+Gilpin
+Gilyot
+Girgis
+Gjertsen
+Glantz
+Glaze
+Glenn
+Glotzbach
+Gobble
+Gockenbach
+Goff
+Goffin
+Golden
+Goldwyn
+Gomez
+Gonzalez
+Good
+Graham
+Gramm
+Granlund
+Grant
+Gray
+Grayson
+Greene
+Greenslade
+Greenwood
+Greer
+Griffin
+Grinstein
+Grisham
+Gross
+Grove
+Guthrie
+Guyton
+Haas
+Hackney
+Haddock
+Hagelstein
+Hagen
+Haggard
+Haines
+Hale
+Haley
+Hall
+Halladay
+Hamill
+Hamilton
+Hammer
+Hancock
+Hane
+Hansen
+Harding
+Harless
+Harms
+Harper
+Harrigan
+Harris
+Harrison
+Hart
+Harton
+Hartz
+Harvey
+Hastings
+Hauenstein
+Haushalter
+Haven
+Hawes
+Hawkins
+Hawley
+Haygood
+Haylock
+Hazard
+Heath
+Heidel
+Heins
+Hellums
+Hendricks
+Henry
+Henson
+Herbert
+Herman
+Hernandez
+Herrera
+Hertzmann
+Hewitt
+Hightower
+Hildebrand
+Hill
+Hindman
+Hirasaki
+Hirsh
+Hochman
+Hocker
+Hoffman
+Hoffmann
+Holder
+Holland
+Holloman
+Holstein
+Holt
+Holzer
+Honeyman
+Hood
+Hooks
+Hopper
+Horne
+House
+Houston
+Howard
+Howell
+Howley
+Huang
+Hudgings
+Huffman
+Hughes
+Humphrey
+Hunt
+Hunter
+Hurley
+Huston
+Hutchinson
+Hyatt
+Irving
+Jacobs
+Jaramillo
+Jaranson
+Jarboe
+Jarrell
+Jenkins
+Johnson
+Johnston
+Jones
+Joy
+Juette
+Julicher
+Jumper
+Kabir
+Kamberova
+Kamen
+Kamine
+Kampe
+Kane
+Kang
+Kapetanovic
+Kargatis
+Karlin
+Karlsson
+Kasbekar
+Kasper
+Kastensmidt
+Katz
+Kauffman
+Kavanagh
+Kaydos
+Kearsley
+Keleher
+Kelly
+Kelty
+Kendrick
+Key
+Kicinski
+Kiefer
+Kielt
+Kim
+Kimmel
+Kincaid
+King
+Kinney
+Kipp
+Kirby
+Kirk
+Kirkland
+Kirkpatrick
+Klamczynski
+Klein
+Kopnicky
+Kotsonis
+Koutras
+Kramer
+Kremer
+Krohn
+Kuhlken
+Kunitz
+LaLonde
+LaValle
+LaWare
+Lacy
+Lam
+Lamb
+Lampkin
+Lane
+Langston
+Lanier
+Larsen
+Lassiter
+Latchford
+Lawera
+LeBlanc
+LeGrand
+Leatherbury
+Lebron
+Ledman
+Lee
+Leinenbach
+Leslie
+Levy
+Lewis
+Lichtenstein
+Lisowski
+Liston
+Litvak
+Llano-Restrepo
+Lloyd
+Lock
+Lodge
+Logan
+Lomonaco
+Long
+Lopez
+Lopez-Bassols
+Loren
+Loughridge
+Love
+Ludtke
+Luers
+Lukes
+Luxemburg
+MacAllister
+MacLeod
+Mackey
+Maddox
+Magee
+Mallinson
+Mann
+Manning
+Manthos
+Marie
+Marrow
+Marshall
+Martin
+Martinez
+Martisek
+Massey
+Mathis
+Matt
+Maxwell
+Mayer
+Mazurek
+McAdams
+McAfee
+McAlexander
+McBride
+McCarthy
+McClure
+McCord
+McCoy
+McCrary
+McCrossin
+McDonald
+McElfresh
+McFarland
+McGarr
+McGhee
+McGoldrick
+McGrath
+McGuire
+McKinley
+McMahan
+McMahon
+McMath
+McNally
+Mcdonald
+Meade
+Meador
+Mebane
+Medrano
+Melton
+Merchant
+Merwin
+Millam
+Millard
+Miller
+Mills
+Milstead
+Minard
+Miner
+Minkoff
+Minnotte
+Minyard
+Mirza
+Mitchell
+Money
+Monk
+Montgomery
+Monton
+Moore
+Moren
+Moreno
+Morris
+Morse
+Moss
+Moyer
+Mueller
+Mull
+Mullet
+Mullins
+Munn
+Murdock
+Murphey
+Murphy
+Murray
+Murry
+Mutchler
+Myers
+Myrick
+Nassar
+Nathan
+Nazzal
+Neal
+Nederveld
+Nelson
+Nguyen
+Nichols
+Nielsen
+Nockton
+Nolan
+Noonan
+Norbury
+Nordlander
+Norris
+Norvell
+Noyes
+Nugent
+Nunn
+O'Brien
+O'Connell
+O'Neill
+O'Steen
+Ober
+Odegard
+Oliver
+Ollmann
+Olson
+Ongley
+Ordway
+Ortiz
+Ouellette
+Overcash
+Overfelt
+Overley
+Owens
+Page
+Paige
+Pardue
+Parham
+Parker
+Parks
+Patterson
+Patton
+Paul
+Payne
+Peck
+Penisson
+Percer
+Perez
+Perlioni
+Perrino
+Peterman
+Peters
+Pfeiffer
+Phelps
+Philip
+Philippe
+Phillips
+Pickett
+Pippenger
+Pistole
+Platzek
+Player
+Poddar
+Poirier
+Poklepovic
+Polk
+Polking
+Pond
+Popish
+Porter
+Pound
+Pounds
+Powell
+Powers
+Prado
+Preston
+Price
+Prichep
+Priour
+Prischmann
+Pryor
+Puckett
+Raglin
+Ralston
+Rampersad
+Ratner
+Rawles
+Ray
+Read
+Reddy
+Reed
+Reese
+Reeves
+Reichenbach
+Reifel
+Rein
+Reiten
+Reiter
+Reitmeier
+Reynolds
+Richardson
+Rider
+Rhinehart
+Ritchie
+Rittenbach
+Roberts
+Robinson
+Rodriguez
+Rogers
+Roper
+Rosemblun
+Rosen
+Rosenberg
+Rosenblatt
+Ross
+Roth
+Rowatt
+Roy
+Royston
+Rozendal
+Rubble
+Ruhlin
+Rupert
+Russell
+Ruthruff
+Ryan
+Rye
+Sabry
+Sachitano
+Sachs
+Sammartino
+Sands
+Saunders
+Savely
+Scales
+Schaefer
+Schafer
+Scheer
+Schild
+Schlitt
+Schmitz
+Schneider
+Schoenberger
+Schoppe
+Scott
+Seay
+Segura
+Selesnick
+Self
+Seligmann
+Sewall
+Shami
+Shampine
+Sharp
+Shaw
+Shefelbine
+Sheldon
+Sherrill
+Shidle
+Shifley
+Shillingsburg
+Shisler
+Shopbell
+Shupack
+Sievert
+Simpson
+Sims
+Sissman
+Smayling
+Smith
+Snyder
+Solomon
+Solon
+Soltero
+Sommers
+Sonneborn
+Sorensen
+Southworth
+Spear
+Speight
+Spencer
+Spruell
+Spudich
+Stacy
+Staebel
+Steele
+Steinhour
+Steinke
+Stepp
+Stevens
+Stewart
+Stickel
+Stine
+Stivers
+Stobb
+Stone
+Stratmann
+Stubbers
+Stuckey
+Stugart
+Sullivan
+Sultan
+Sumrall
+Sunley
+Sunshine
+Sutton
+Swaim
+Swales
+Sweed
+Swick
+Swift
+Swindell
+Swint
+Symonds
+Syzdek
+Szafranski
+Takimoto
+Talbott
+Talwar
+Tanner
+Taslimi
+Tate
+Tatum
+Taylor
+Tchainikov
+Terk
+Thacker
+Thomas
+Thompson
+Thomson
+Thornton
+Thurman
+Thurow
+Tilley
+Tolle
+Towns
+Trafton
+Tran
+Trevas
+Trevino
+Triggs
+Truchard
+Tunison
+Turner
+Twedell
+Tyler
+Tyree
+Unger
+Van
+Vanderzanden
+Vanlandingham
+Varanasi
+Varela
+Varman
+Venier
+Verspoor
+Vick
+Visinsky
+Voltz
+Wagner
+Wake
+Walcott
+Waldron
+Walker
+Wallace
+Walters
+Walton
+Ward
+Wardle
+Warnes
+Warren
+Washington
+Watson
+Watters
+Webber
+Weidenfeller
+Weien
+Weimer
+Weiner
+Weinger
+Weinheimer
+Weirich
+Welch
+Wells
+Wendt
+West
+Westmoreland
+Wex
+Whitaker
+White
+Whitley
+Wiediger
+Wilburn
+Williams
+Williamson
+Willman
+Wilson
+Winger
+Wise
+Wisur
+Witt
+Wong
+Woodbury
+Wooten
+Workman
+Wright
+Wyatt
+Yates
+Yeamans
+Yen
+York
+Yotov
+Younan
+Young
+Zeldin
+Zettner
+Ziegler
+Zitterkopf
+Zucker
diff --git a/examples/declarative/tutorials/contacts/shared/pics/cancel.png b/examples/declarative/tutorials/contacts/shared/pics/cancel.png
new file mode 100644
index 0000000..ecc9533
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/pics/cancel.png
Binary files differ
diff --git a/examples/declarative/tutorials/contacts/shared/pics/email.png b/examples/declarative/tutorials/contacts/shared/pics/email.png
new file mode 100644
index 0000000..04b3865
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/pics/email.png
Binary files differ
diff --git a/examples/declarative/tutorials/contacts/shared/pics/new.png b/examples/declarative/tutorials/contacts/shared/pics/new.png
new file mode 100644
index 0000000..c7ebac3
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/pics/new.png
Binary files differ
diff --git a/examples/declarative/tutorials/contacts/shared/pics/ok.png b/examples/declarative/tutorials/contacts/shared/pics/ok.png
new file mode 100644
index 0000000..5795f04
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/pics/ok.png
Binary files differ
diff --git a/examples/declarative/tutorials/contacts/shared/pics/phone.png b/examples/declarative/tutorials/contacts/shared/pics/phone.png
new file mode 100644
index 0000000..fc9c222
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/pics/phone.png
Binary files differ
diff --git a/examples/declarative/tutorials/contacts/shared/pics/search.png b/examples/declarative/tutorials/contacts/shared/pics/search.png
new file mode 100644
index 0000000..cc74e69
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/pics/search.png
Binary files differ
diff --git a/examples/declarative/tutorials/contacts/shared/pics/trash.png b/examples/declarative/tutorials/contacts/shared/pics/trash.png
new file mode 100644
index 0000000..2042595
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/pics/trash.png
Binary files differ