diff options
author | Ian Walters <ian.walters@nokia.com> | 2009-05-07 01:32:36 (GMT) |
---|---|---|
committer | Ian Walters <ian.walters@nokia.com> | 2009-05-07 01:32:36 (GMT) |
commit | a6f5af838e58a9845a023493343a0b9761eb2566 (patch) | |
tree | 41c6ea0c1ee27fb20d377287dc6c24f8ea808d55 /demos | |
parent | cef84f75ec56c7ebced81faaf12d5f9bc809f4ca (diff) | |
download | Qt-a6f5af838e58a9845a023493343a0b9761eb2566.zip Qt-a6f5af838e58a9845a023493343a0b9761eb2566.tar.gz Qt-a6f5af838e58a9845a023493343a0b9761eb2566.tar.bz2 |
Move 'final' contacts application to demos.
Will finish the applicaiton in this directory to fully functional.
Missing features - removing contacts, clearing search, key only access
Known bugs -
Scroll crashes if data changes while scrolling,
VerticalLayout doesn't align horizontally correctly when in
ListView delegate.
ListView only shows one element on startup, even though query
consistently indicates 1000 items as count.
Diffstat (limited to 'demos')
-rw-r--r-- | demos/declarative/contacts/Button.qml | 57 | ||||
-rw-r--r-- | demos/declarative/contacts/Contact.qml | 93 | ||||
-rw-r--r-- | demos/declarative/contacts/ContactField.qml | 60 | ||||
-rw-r--r-- | demos/declarative/contacts/FieldText.qml | 160 | ||||
-rw-r--r-- | demos/declarative/contacts/RemoveButton.qml | 120 | ||||
-rw-r--r-- | demos/declarative/contacts/SearchBar.qml | 24 | ||||
-rw-r--r-- | demos/declarative/contacts/contacts.qml | 262 | ||||
-rw-r--r-- | demos/declarative/contacts/contacts.sqlite | bin | 0 -> 86016 bytes | |||
-rw-r--r-- | demos/declarative/contacts/pics/cancel.png | bin | 0 -> 1038 bytes | |||
-rw-r--r-- | demos/declarative/contacts/pics/email.png | bin | 0 -> 977 bytes | |||
-rw-r--r-- | demos/declarative/contacts/pics/new.png | bin | 0 -> 688 bytes | |||
-rw-r--r-- | demos/declarative/contacts/pics/ok.png | bin | 0 -> 655 bytes | |||
-rw-r--r-- | demos/declarative/contacts/pics/phone.png | bin | 0 -> 624 bytes | |||
-rw-r--r-- | demos/declarative/contacts/pics/search.png | bin | 0 -> 635 bytes | |||
-rw-r--r-- | demos/declarative/contacts/pics/trash.png | bin | 0 -> 989 bytes |
15 files changed, 776 insertions, 0 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..879c616 --- /dev/null +++ b/demos/declarative/contacts/contacts.qml @@ -0,0 +1,262 @@ +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: contacts.mode != 'list' + } + 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: 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 + } + } + ] + transitions: [ + Transition { + fromState: "*" + toState: "*" + NumericAnimation { + property: "bottomMargin" + duration: 250 + } + } + ] + } + 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 Binary files differnew file mode 100644 index 0000000..559cdf3 --- /dev/null +++ b/demos/declarative/contacts/contacts.sqlite diff --git a/demos/declarative/contacts/pics/cancel.png b/demos/declarative/contacts/pics/cancel.png Binary files differnew file mode 100644 index 0000000..ecc9533 --- /dev/null +++ b/demos/declarative/contacts/pics/cancel.png diff --git a/demos/declarative/contacts/pics/email.png b/demos/declarative/contacts/pics/email.png Binary files differnew file mode 100644 index 0000000..04b3865 --- /dev/null +++ b/demos/declarative/contacts/pics/email.png diff --git a/demos/declarative/contacts/pics/new.png b/demos/declarative/contacts/pics/new.png Binary files differnew file mode 100644 index 0000000..c7ebac3 --- /dev/null +++ b/demos/declarative/contacts/pics/new.png diff --git a/demos/declarative/contacts/pics/ok.png b/demos/declarative/contacts/pics/ok.png Binary files differnew file mode 100644 index 0000000..5795f04 --- /dev/null +++ b/demos/declarative/contacts/pics/ok.png diff --git a/demos/declarative/contacts/pics/phone.png b/demos/declarative/contacts/pics/phone.png Binary files differnew file mode 100644 index 0000000..fc9c222 --- /dev/null +++ b/demos/declarative/contacts/pics/phone.png diff --git a/demos/declarative/contacts/pics/search.png b/demos/declarative/contacts/pics/search.png Binary files differnew file mode 100644 index 0000000..cc74e69 --- /dev/null +++ b/demos/declarative/contacts/pics/search.png diff --git a/demos/declarative/contacts/pics/trash.png b/demos/declarative/contacts/pics/trash.png Binary files differnew file mode 100644 index 0000000..2042595 --- /dev/null +++ b/demos/declarative/contacts/pics/trash.png |