diff options
Diffstat (limited to 'demos')
67 files changed, 2568 insertions, 0 deletions
diff --git a/demos/declarative/calculator/CalcButton.qml b/demos/declarative/calculator/CalcButton.qml new file mode 100644 index 0000000..8203710 --- /dev/null +++ b/demos/declarative/calculator/CalcButton.qml @@ -0,0 +1,60 @@ +Item { + property string operation + property bool toggable : false + property bool toggled : false + + id: Button; width: 50; height: 30 + + Script { + function buttonClicked(operation) { + if (Button.toggable == true) { + if (Button.toggled == true) { + Button.toggled = false; + Button.state = 'Toggled'; + } else { + Button.toggled = true; + Button.state = ''; + } + } + else + doOp(operation); + } + } + + Image { + id: Image + source: "pics/button.sci" + width: Button.width; height: Button.height + } + + Image { + id: ImagePressed + source: "pics/button-pressed.sci" + width: Button.width; height: Button.height + opacity: 0 + } + + Text { + anchors.centeredIn: Image + text: Button.operation + color: "white" + font.bold: true + } + + MouseRegion { + id: MouseRegion + anchors.fill: Button + onClicked: { buttonClicked(Button.operation) } + } + + states: [ + State { + name: "Pressed"; when: MouseRegion.pressed == true + SetProperties { target: ImagePressed; opacity: 1 } + }, + State { + name: "Toggled"; when: Button.toggled == true + SetProperties { target: ImagePressed; opacity: 1 } + } + ] +} diff --git a/demos/declarative/calculator/calculator.js b/demos/declarative/calculator/calculator.js new file mode 100644 index 0000000..774b232 --- /dev/null +++ b/demos/declarative/calculator/calculator.js @@ -0,0 +1,87 @@ + +var curVal = 0; +var memory = 0; +var lastOp = ""; +var timer = 0; + +function disabled(op) { + if (op == "." && CurNum.text.toString().search(/\./) != -1) { + return true; + } else if (op == "Sqrt" && CurNum.text.toString().search(/-/) != -1) { + return true; + } else { + return false; + } +} + +function doOp(op) { + if (disabled(op)) { + return; + } + + if (op.toString().length==1 && ((op >= "0" && op <= "9") || op==".") ) { + if (CurNum.text.toString().length >= 14) + return; // No arbitrary length numbers + if (lastOp.toString().length == 1 && ((lastOp >= "0" && lastOp <= "9") || lastOp==".") ) { + CurNum.text = CurNum.text + op.toString(); + } else { + CurNum.text = op; + } + lastOp = op; + return; + } + lastOp = op; + + // Pending operations + if (CurrentOperation.text == "+") { + CurNum.text = Number(CurNum.text.valueOf()) + Number(curVal.valueOf()); + } else if (CurrentOperation.text == "-") { + CurNum.text = Number(curVal) - Number(CurNum.text.valueOf()); + } else if (CurrentOperation.text == "x") { + CurNum.text = Number(curVal) * Number(CurNum.text.valueOf()); + } else if (CurrentOperation.text == "/") { + CurNum.text = Number(Number(curVal) / Number(CurNum.text.valueOf())).toString(); + } else if (CurrentOperation.text == "=") { + } + + if (op == "+" || op == "-" || op == "x" || op == "/") { + CurrentOperation.text = op; + curVal = CurNum.text.valueOf(); + return; + } + curVal = 0; + CurrentOperation.text = ""; + + // Immediate operations + if (op == "1/x") { // reciprocal + CurNum.text = (1 / CurNum.text.valueOf()).toString(); + } else if (op == "^2") { // squared + CurNum.text = (CurNum.text.valueOf() * CurNum.text.valueOf()).toString(); + } else if (op == "Abs") { + CurNum.text = (Math.abs(CurNum.text.valueOf())).toString(); + } else if (op == "Int") { + CurNum.text = (Math.floor(CurNum.text.valueOf())).toString(); + } else if (op == "+/-") { // plus/minus + CurNum.text = (CurNum.text.valueOf() * -1).toString(); + } else if (op == "Sqrt") { // square root + CurNum.text = (Math.sqrt(CurNum.text.valueOf())).toString(); + } else if (op == "MC") { // memory clear + memory = 0; + } else if (op == "M+") { // memory increment + memory += CurNum.text.valueOf(); + } else if (op == "MR") { // memory recall + CurNum.text = memory.toString(); + } else if (op == "MS") { // memory set + memory = CurNum.text.valueOf(); + } else if (op == "Bksp") { + CurNum.text = CurNum.text.toString().slice(0, -1); + } else if (op == "C") { + CurNum.text = "0"; + } else if (op == "AC") { + curVal = 0; + memory = 0; + lastOp = ""; + CurNum.text ="0"; + } +} + diff --git a/demos/declarative/calculator/calculator.qml b/demos/declarative/calculator/calculator.qml new file mode 100644 index 0000000..145435b --- /dev/null +++ b/demos/declarative/calculator/calculator.qml @@ -0,0 +1,127 @@ +Rect { + id: MainWindow; + width: 320; height: 270; color: "black" + + Script { source: "calculator.js" } + + VerticalLayout { + spacing: 2; margin: 2 + + Rect { + id: Container + width: 316; height: 60; z: 2 + pen.color: "white"; color: "#343434" + + Text { + id: CurNum + font.bold: true; font.size: 16 + color: "white" + anchors.right: Container.right + anchors.rightMargin: 5 + anchors.verticalCenter: Container.verticalCenter + } + + Text { + id: CurrentOperation + color: "white" + font.bold: true; font.size: 16 + anchors.left: Container.left + anchors.leftMargin: 5 + anchors.verticalCenter: Container.verticalCenter + } + } + + Item { + width: 320; height: 30 + + CalcButton { + id: AdvancedCheckBox + x: 55; width: 206 + operation: "Advanced Mode" + toggable: true + } + } + + Item { + width: 320 + + Item { + id: BasicButtons + x: 55; width: 160; height: 160 + + CalcButton { operation: "Bksp"; id: Bksp; width: 67; opacity: 0 } + CalcButton { operation: "C"; id: C; width: 76 } + CalcButton { operation: "AC"; id: AC; x: 78; width: 76 } + + GridLayout { + id: NumKeypad; y: 32; spacing: 2; columns: 3 + + CalcButton { operation: 7 } + CalcButton { operation: 8 } + CalcButton { operation: 9 } + CalcButton { operation: 4 } + CalcButton { operation: 5 } + CalcButton { operation: 6 } + CalcButton { operation: 1 } + CalcButton { operation: 2 } + CalcButton { operation: 3 } + } + + HorizontalLayout { + y: 128; spacing: 2 + + CalcButton { operation: 0; width: 50 } + CalcButton { operation: "."; x: 77; width: 50 } + CalcButton { operation: "="; id: Equals; x: 77; width: 102 } + } + + VerticalLayout { + id: SimpleOperations + x: 156; y: 0; spacing: 2 + + CalcButton { operation: "x" } + CalcButton { operation: "/" } + CalcButton { operation: "-" } + CalcButton { operation: "+" } + } + } + + GridLayout { + id: AdvancedButtons + x: 350; spacing: 2; columns: 2; opacity: 0 + + CalcButton { operation: "Abs" } + CalcButton { operation: "Int" } + CalcButton { operation: "MC" } + CalcButton { operation: "Sqrt" } + CalcButton { operation: "MR" } + CalcButton { operation: "^2" } + CalcButton { operation: "MS" } + CalcButton { operation: "1/x" } + CalcButton { operation: "M+" } + CalcButton { operation: "+/-" } + } + + } + } + + states: [ + State { + name: "Advanced"; when: AdvancedCheckBox.toggled == true + SetProperties { target: BasicButtons; x: 0 } + SetProperties { target: SimpleOperations; y: 32 } + SetProperties { target: Bksp; opacity: 1 } + SetProperties { target: C; x: 69; width: 67 } + SetProperties { target: AC; x: 138; width: 67 } + SetProperties { target: Equals; width: 50 } + SetProperties { target: AdvancedButtons; x: 210; opacity: 1 } + } + ] + + transitions: [ + Transition { + NumericAnimation { properties: "x,y,width"; easing: "easeOutBounce"; duration: 500 } + NumericAnimation { properties: "opacity"; easing: "easeInOutQuad"; duration: 500 } + } + ] +} diff --git a/demos/declarative/calculator/pics/button-pressed.png b/demos/declarative/calculator/pics/button-pressed.png Binary files differnew file mode 100644 index 0000000..1a24cee --- /dev/null +++ b/demos/declarative/calculator/pics/button-pressed.png diff --git a/demos/declarative/calculator/pics/button-pressed.sci b/demos/declarative/calculator/pics/button-pressed.sci new file mode 100644 index 0000000..f3bc860 --- /dev/null +++ b/demos/declarative/calculator/pics/button-pressed.sci @@ -0,0 +1,5 @@ +gridLeft: 5 +gridTop: 5 +gridBottom: 5 +gridRight: 5 +imageFile: button-pressed.png diff --git a/demos/declarative/calculator/pics/button.png b/demos/declarative/calculator/pics/button.png Binary files differnew file mode 100644 index 0000000..88c8bf8 --- /dev/null +++ b/demos/declarative/calculator/pics/button.png diff --git a/demos/declarative/calculator/pics/button.sci b/demos/declarative/calculator/pics/button.sci new file mode 100644 index 0000000..b1c7929 --- /dev/null +++ b/demos/declarative/calculator/pics/button.sci @@ -0,0 +1,5 @@ +gridLeft: 5 +gridTop: 5 +gridBottom: 5 +gridRight: 5 +imageFile: button.png diff --git a/demos/declarative/calculator/pics/clear.png b/demos/declarative/calculator/pics/clear.png Binary files differnew file mode 100644 index 0000000..fb07a27c --- /dev/null +++ b/demos/declarative/calculator/pics/clear.png 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..50c9d1c --- /dev/null +++ b/demos/declarative/contacts/Contact.qml @@ -0,0 +1,113 @@ +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 + }, + SqlBind { + name: ":l" + value: labelField.value + }, + SqlBind { + name: ":e" + value: emailField.value + }, + 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 + }, + SqlBind { + name: ":e" + value: emailField.value + }, + SqlBind { + name: ":p" + value: phoneField.value + } + ] + }, + SqlQuery { + id: removeContactQuery + connection: contactDatabase + query: "DELETE FROM contacts WHERE recid = :r" + bindings: SqlBind { + name: ":r" + value: contactId + } + } + ] + function refresh() { + labelField.value = label; + emailField.value = email; + phoneField.value = phone; + } + function update() { + updateContactQuery.exec(); + } + function insert() { + insertContactQuery.exec(); + } + function remove() { + removeContactQuery.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..003e723 --- /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: "" + property var value: "" + onValueChanged: { fieldText.text = contactField.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..59e3fcb --- /dev/null +++ b/demos/declarative/contacts/RemoveButton.qml @@ -0,0 +1,126 @@ +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 + } + opacity: Behaviour { + NumericAnimation { + property: "opacity" + duration: 250 + } + } + 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..b38e02e --- /dev/null +++ b/demos/declarative/contacts/contacts.qml @@ -0,0 +1,293 @@ +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'; + } + + } + } + Connection { + sender: removeContactButton + signal: "confirmed()" + script: { + if (wrapper.state == 'opened' && !contacts.mouseGrabbed) { + Details.qmlItem.remove(); + wrapper.state = ''; + contacts.mode = 'list'; + contactList.exec(); + } + + } + } + } + } + ] + Button { + id: newContactButton + anchors.top: parent.top + anchors.topMargin: 5 + anchors.right: parent.right + anchors.rightMargin: 5 + icon: "pics/new.png" + onClicked: { newContactItem.refresh(); 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 + } + RemoveButton { + id: removeContactButton + anchors.top: parent.top + anchors.topMargin: 5 + anchors.horizontalCenter: parent.horizontalCenter + opacity: (contacts.mode == 'edit' && (!contacts.mouseGrabbed || removeContactButton.state =='opened')) ? 1 : 0 + } + ListView { + id: contactListView + anchors.left: parent.left + anchors.right: parent.right + anchors.top: cancelEditButton.bottom + anchors.bottom: searchBarWrapper.bottom + clip: true + model: contactList + delegate: contactDelegate + focus: false + } + FocusRealm { + id: newContactWrapper + anchors.fill: contactListView + opacity: 0 + focus: contacts.mode == 'new' + Contact { + id: newContactItem + anchors.fill: parent + } + } + Connection { + sender: confirmEditButton + signal: "clicked()" + script: { + if (contacts.mode == 'new' && contacts.mouseGrabbed != 'true') { + newContactItem.insert(); + contacts.mode = 'list'; + contactList.exec(); + } + } + } + Connection { + sender: cancelEditButton + signal: "clicked()" + script: { + if (contacts.mode == 'new' && contacts.mouseGrabbed != 'true') { + contacts.mode = 'list'; + } + } + } + FocusRealm { + id: searchBarWrapper + height: 30 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.bottomMargin: 0 + focus: false + SearchBar { + id: searchBar + anchors.fill: parent + } + states: [ + State { + name: "searchHidden" + when: searchBar.text == '' || contacts.mode != 'list' + SetProperty { + target: searchBarWrapper.anchors + property: "bottomMargin" + value: -30 + } + } + ] + transitions: [ + Transition { + fromState: "*" + toState: "*" + NumericAnimation { + property: "bottomMargin" + duration: 250 + } + } + ] + } + KeyProxy { + focus: contacts.mode != 'new' + targets: { contacts.mode == "list" ? [searchBarWrapper, contactListView] : [contactListView]} + } + states: [ + State { + name: "editNewState" + when: contacts.mode == 'new' + SetProperty { + target: contactListView + property: "opacity" + value: 0 + } + SetProperty { + target: newContactWrapper + 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..d33e0c7 --- /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 diff --git a/demos/declarative/flickr/content/ImageDetails.qml b/demos/declarative/flickr/content/ImageDetails.qml new file mode 100644 index 0000000..ccc91cb --- /dev/null +++ b/demos/declarative/flickr/content/ImageDetails.qml @@ -0,0 +1,141 @@ +Flipable { + id: Container + + property var frontContainer: ContainerFront + property string photoTitle: "" + property string photoDescription: "" + property string photoTags: "" + property int photoWidth + property int photoHeight + property string photoType + property string photoAuthor + property string photoDate + property string photoUrl + property int rating: 2 + property var prevScale: 1.0 + + signal closed + + axis: Axis { startX: Container.width / 2; endX: Container.width / 2; endY: 1 } + + front: Item { + id: ContainerFront; anchors.fill: Container + + Rect { + anchors.fill: parent + color: "black"; opacity: 0.4 + pen.color: "white"; pen.width: 2 + } + + MediaButton { + id: BackButton; x: 630; y: 370; text: "Back" + onClicked: { Container.closed.emit() } + } + + MediaButton { + id: MoreButton; x: 530; y: 370; text: "View..." + onClicked: { Container.state='Back' } + } + + Text { id: TitleText; style: "Raised"; styleColor: "black"; color: "white"; elide: "ElideRight" + x: 220; y: 30; width: parent.width - 240; text: Container.photoTitle; font.size: 22 } + + LikeOMeter { x: 40; y: 250; rating: Container.rating } + + Flickable { id: Flickable; x: 220; width: 480; height: 210; y: 130; clip: true + viewportWidth: 480; viewportHeight: DescriptionText.height + + WebView { id: DescriptionText; width: parent.width + html: "<style TYPE=\"text/css\">body {color: white;} a:link {color: cyan; text-decoration: underline; }</style>" + Container.photoDescription } + } + + Text { id: Size; color: "white"; width: 300; x: 40; y: 300 + text: "<b>Size:</b> " + Container.photoWidth + 'x' + Container.photoHeight } + Text { id: Type; color: "white"; width: 300; x: 40; anchors.top: Size.bottom + text: "<b>Type:</b> " + Container.photoType } + + Text { id: Author; color: "white"; width: 300; x: 220; y: 80 + text: "<b>Author:</b> " + Container.photoAuthor } + Text { id: Date; color: "white"; width: 300; x: 220; anchors.top: Author.bottom + text: "<b>Published:</b> " + Container.photoDate } + Text { id: TagsLabel; color: "white"; x: 220; anchors.top: Date.bottom; + text: Container.photoTags == "" ? "" : "<b>Tags:</b> " } + Text { id: Tags; color: "white"; width: parent.width-x-20; + anchors.left: TagsLabel.right; anchors.top: Date.bottom; + elide: "ElideRight"; text: Container.photoTags } + + ScrollBar { id: ScrollBar; x: 720; y: Flickable.y; width: 7; height: Flickable.height; opacity: 0; + flickableArea: Flickable; clip: true } + } + + back: Item { + anchors.fill: Container + + Rect { anchors.fill: parent; color: "black"; opacity: 0.4; pen.color: "white"; pen.width: 2 } + + Progress { anchors.centeredIn: parent; width: 200; height: 18; progress: BigImage.progress; visible: BigImage.status } + Flickable { + id: Flick; width: Container.width - 10; height: Container.height - 10 + x: 5; y: 5; clip: true; + viewportWidth: ImageContainer.width; viewportHeight: ImageContainer.height + + Item { + id: ImageContainer + width: Math.max(BigImage.width * BigImage.scale, Flick.width); + height: Math.max(BigImage.height * BigImage.scale, Flick.height); + + Image { + id: BigImage; source: Container.photoUrl; scale: Slider.value + // Center image if it is smaller than the flickable area. + x: ImageContainer.width > width*scale ? (ImageContainer.width - width*scale) / 2 : 0 + y: ImageContainer.height > height*scale ? (ImageContainer.height - height*scale) / 2 : 0 + onStatusChanged : { + // Default scale shows the entire image. + if (status == 0 && width != 0) { + Slider.minimum = Math.min(Flick.width / width, Flick.height / height); + prevScale = Math.min(Slider.minimum, 1); + Slider.value = prevScale; + } + } + } + } + } + + MediaButton { + id: BackButton2; x: 630; y: 370; text: "Back"; onClicked: { Container.state = '' } + } + Text { + text: "Image Unavailable" + visible: BigImage.status == 'Error' + anchors.centeredIn: parent; color: "white"; font.bold: true + } + + Slider { + id: Slider; x: 25; y: 374; visible: { BigImage.status == 0 && maximum > minimum } + onValueChanged: { + if (BigImage.width * value > Flick.width) { + var xoff = (Flick.width/2 + Flick.xPosition) * value / prevScale; + Flick.xPosition = xoff - Flick.width/2; + } + if (BigImage.height * value > Flick.height) { + var yoff = (Flick.height/2 + Flick.yPosition) * value / prevScale; + Flick.yPosition = yoff - Flick.height/2; + } + prevScale = value; + } + } + } + + states: [ + State { + name: "Back" + SetProperty { target: Container; property: "rotation"; value: 180 } + } + ] + + transitions: [ + Transition { + NumericAnimation { easing: "easeInOutQuad"; properties: "rotation"; duration: 500 } + } + ] +} diff --git a/demos/declarative/flickr/content/LikeOMeter.qml b/demos/declarative/flickr/content/LikeOMeter.qml new file mode 100644 index 0000000..61317ae --- /dev/null +++ b/demos/declarative/flickr/content/LikeOMeter.qml @@ -0,0 +1,33 @@ +Item { + id: Container + + property int rating: 2 + + HorizontalLayout { + Star { + rating: 0 + onClicked: { Container.rating = rating } + on: Container.rating >= 0 + } + Star { + rating: 1 + onClicked: { Container.rating = rating } + on: Container.rating >= 1 + } + Star { + rating: 2 + onClicked: { Container.rating = rating } + on: Container.rating >= 2 + } + Star { + rating: 3 + onClicked: { Container.rating = rating } + on: Container.rating >= 3 + } + Star { + rating: 4 + onClicked: { Container.rating = rating } + on: Container.rating >= 4 + } + } +} diff --git a/demos/declarative/flickr/content/Loading.qml b/demos/declarative/flickr/content/Loading.qml new file mode 100644 index 0000000..7488a66 --- /dev/null +++ b/demos/declarative/flickr/content/Loading.qml @@ -0,0 +1,6 @@ +Image { + id: Loading; source: "pics/loading.png"; transformOrigin: "Center" + rotation: NumericAnimation { + id: "RotationAnimation"; from: 0; to: 360; running: Loading.visible == true; repeat: true; duration: 900 + } +} diff --git a/demos/declarative/flickr/content/MediaButton.qml b/demos/declarative/flickr/content/MediaButton.qml new file mode 100644 index 0000000..6392a13 --- /dev/null +++ b/demos/declarative/flickr/content/MediaButton.qml @@ -0,0 +1,39 @@ +Item { + id: Container + + signal clicked + + property string text + + Image { + id: Image + source: "pics/button.png" + } + Image { + id: Pressed + source: "pics/button-pressed.png" + opacity: 0 + } + MouseRegion { + id: MouseRegion + anchors.fill: Image + onClicked: { Container.clicked.emit(); } + } + Text { + font.bold: true + color: "white" + anchors.centeredIn: Image + text: Container.text + } + width: Image.width + states: [ + State { + name: "Pressed" + when: MouseRegion.pressed == true + SetProperties { + target: Pressed + opacity: 1 + } + } + ] +} diff --git a/demos/declarative/flickr/content/MediaLineEdit.qml b/demos/declarative/flickr/content/MediaLineEdit.qml new file mode 100644 index 0000000..691bb5b --- /dev/null +++ b/demos/declarative/flickr/content/MediaLineEdit.qml @@ -0,0 +1,109 @@ +Item { + id: Container + + property string label + property string text + + width: Math.max(94,Label.width + Editor.width + 20) + height: Image.height + + states: [ + State { + name: "Edit" + SetProperties { + target: Label + text: Container.label + ": " + } + SetProperty { + target: Label + property: "x" + binding: 10 + } + SetProperties { + target: Editor + cursorVisible: true + width: 100 + } + SetProperties { + target: Proxy + focus: true + } + RunScript { + script:"Editor.selectAll()" + } + }, + State { + // When returning to default state, typed text is propagated + RunScript { + script: "Container.text = Editor.text" + } + } + ] + transitions: [ + Transition { + NumericAnimation { properties: "x,width"; duration: 500; easing: "easeInOutQuad" } + } + ] + + + Image { + id: Image + source: "pics/button.sci" + anchors.left: Container.left + anchors.right: Container.right + } + + Image { + id: Pressed + source: "pics/button-pressed.sci" + opacity: 0 + anchors.left: Container.left + anchors.right: Container.right + } + + MouseRegion { + id: MouseRegion + anchors.fill: Image + onClicked: { Container.state = Container.state=="Edit" ? "" : "Edit" } + states: [ + State { + when: MouseRegion.pressed == true + SetProperties { + target: Pressed + opacity: 1 + } + } + ] + } + + Text { + id: Label + font.bold: true + color: "white" + anchors.verticalCenter: Container.verticalCenter + x: (Container.width - width)/2 + text: Container.label + "..." + } + + TextEdit { + id: Editor + font.bold: true + color: "white" + highlightColor: "green" + width: 0 + clip: true + anchors.left: Label.right + anchors.verticalCenter: Container.verticalCenter + } + KeyProxy { + id: Proxy + anchors.left: Container.left + anchors.fill: Container + focusable: true + targets: [(ReturnKey), (Editor)] + } + KeyActions { + id: ReturnKey + return: "Container.state = ''" + } +} diff --git a/demos/declarative/flickr/content/Progress.qml b/demos/declarative/flickr/content/Progress.qml new file mode 100644 index 0000000..743c45e --- /dev/null +++ b/demos/declarative/flickr/content/Progress.qml @@ -0,0 +1,33 @@ +Item { + id: Progress; + + property var progress: 0 + + Rect { + id: Container; anchors.fill: parent + pen.color: "white"; pen.width: 0; radius: height/2 - 2 + gradient: Gradient { + GradientStop { position: 0; color: "#66343434" } + GradientStop { position: 1.0; color: "#66000000" } + } + } + + Rect { + id: Fill + y: 2; height: parent.height-4; + x: 2; width: Math.max(parent.width * progress - 4, 0); + opacity: width < 1 ? 0 : 1 + gradient: Gradient { + GradientStop { position: 0; color: "lightsteelblue" } + GradientStop { position: 1.0; color: "steelblue" } + } + radius: height/2 - 2 + } + + Text { + text: Math.round(progress * 100) + "%" + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + color: "white"; font.bold: true + } +} diff --git a/demos/declarative/flickr/content/ScrollBar.qml b/demos/declarative/flickr/content/ScrollBar.qml new file mode 100644 index 0000000..2c4ff54 --- /dev/null +++ b/demos/declarative/flickr/content/ScrollBar.qml @@ -0,0 +1,38 @@ +Item { + id: Container + + property var flickableArea + + Rect { + radius: 5 + color: "black" + opacity: 0.3 + pen.color: "white" + pen.width: 2 + x: 0 + y: flickableArea.pageYPosition * Container.height + width: parent.width + height: flickableArea.pageHeight * Container.height + } + states: [ + State { + name: "show" + when: flickableArea.moving + SetProperties { + target: Container + opacity: 1 + } + } + ] + transitions: [ + Transition { + fromState: "*" + toState: "*" + NumericAnimation { + target: Container + properties: "opacity" + duration: 400 + } + } + ] +} diff --git a/demos/declarative/flickr/content/Slider.qml b/demos/declarative/flickr/content/Slider.qml new file mode 100644 index 0000000..931dfe3 --- /dev/null +++ b/demos/declarative/flickr/content/Slider.qml @@ -0,0 +1,34 @@ +Item { + id: Slider; width: 400; height: 16 + + // value is read/write. + property real value + onValueChanged: { Handle.x = 2 + (value - minimum) * Slider.xMax / (maximum - minimum); } + property real maximum: 1 + property real minimum: 1 + property int xMax: Slider.width - Handle.width - 4 + + Rect { + id: Container; anchors.fill: parent + pen.color: "white"; pen.width: 0; radius: 8 + gradient: Gradient { + GradientStop { position: 0.0; color: "#66343434" } + GradientStop { position: 1.0; color: "#66000000" } + } + } + + Rect { + id: Handle + x: Slider.width / 2 - Handle.width / 2; y: 2; width: 30; height: Slider.height-4; radius: 6 + gradient: Gradient { + GradientStop { position: 0.0; color: "lightgray" } + GradientStop { position: 1.0; color: "gray" } + } + + MouseRegion { + anchors.fill: parent; drag.target: parent + drag.axis: "x"; drag.xmin: 2; drag.xmax: Slider.xMax+2 + onPositionChanged: { value = (maximum - minimum) * (Handle.x-2) / Slider.xMax + minimum; } + } + } +} diff --git a/demos/declarative/flickr/content/Star.qml b/demos/declarative/flickr/content/Star.qml new file mode 100644 index 0000000..22fc138 --- /dev/null +++ b/demos/declarative/flickr/content/Star.qml @@ -0,0 +1,44 @@ +Item { + id: Container + width: 24 + height: 24 + + property string rating + property string on + + signal clicked + + Image { + id: Image + source: "pics/ghns_star.png" + x: 6 + y: 7 + opacity: 0.4 + scale: 0.5 + } + MouseRegion { + anchors.fill: Container + onClicked: { Container.clicked.emit() } + } + states: [ + State { + name: "on" + when: Container.on == true + SetProperties { + target: Image + opacity: 1 + scale: 1 + x: 1 + y: 0 + } + } + ] + transitions: [ + Transition { + NumericAnimation { + properties: "opacity,scale,x,y" + easing: "easeOutBounce" + } + } + ] +} diff --git a/demos/declarative/flickr/content/pics/background.png b/demos/declarative/flickr/content/pics/background.png Binary files differnew file mode 100644 index 0000000..5b37072 --- /dev/null +++ b/demos/declarative/flickr/content/pics/background.png diff --git a/demos/declarative/flickr/content/pics/button-pressed.png b/demos/declarative/flickr/content/pics/button-pressed.png Binary files differnew file mode 100644 index 0000000..e434d32 --- /dev/null +++ b/demos/declarative/flickr/content/pics/button-pressed.png diff --git a/demos/declarative/flickr/content/pics/button-pressed.sci b/demos/declarative/flickr/content/pics/button-pressed.sci new file mode 100644 index 0000000..d3b16e2 --- /dev/null +++ b/demos/declarative/flickr/content/pics/button-pressed.sci @@ -0,0 +1,5 @@ +gridLeft: 8 +gridTop: 4 +gridBottom: 4 +gridRight: 8 +imageFile: button.png diff --git a/demos/declarative/flickr/content/pics/button.png b/demos/declarative/flickr/content/pics/button.png Binary files differnew file mode 100644 index 0000000..56a63ce --- /dev/null +++ b/demos/declarative/flickr/content/pics/button.png diff --git a/demos/declarative/flickr/content/pics/button.sci b/demos/declarative/flickr/content/pics/button.sci new file mode 100644 index 0000000..d3b16e2 --- /dev/null +++ b/demos/declarative/flickr/content/pics/button.sci @@ -0,0 +1,5 @@ +gridLeft: 8 +gridTop: 4 +gridBottom: 4 +gridRight: 8 +imageFile: button.png diff --git a/demos/declarative/flickr/content/pics/ghns_star.png b/demos/declarative/flickr/content/pics/ghns_star.png Binary files differnew file mode 100644 index 0000000..4ad43cc --- /dev/null +++ b/demos/declarative/flickr/content/pics/ghns_star.png diff --git a/demos/declarative/flickr/content/pics/loading.png b/demos/declarative/flickr/content/pics/loading.png Binary files differnew file mode 100644 index 0000000..47a1589 --- /dev/null +++ b/demos/declarative/flickr/content/pics/loading.png diff --git a/demos/declarative/flickr/content/pics/reflection.png b/demos/declarative/flickr/content/pics/reflection.png Binary files differnew file mode 100644 index 0000000..c143a48 --- /dev/null +++ b/demos/declarative/flickr/content/pics/reflection.png diff --git a/demos/declarative/flickr/content/pics/shadow-bottom.png b/demos/declarative/flickr/content/pics/shadow-bottom.png Binary files differnew file mode 100644 index 0000000..523f6e7 --- /dev/null +++ b/demos/declarative/flickr/content/pics/shadow-bottom.png diff --git a/demos/declarative/flickr/content/pics/shadow-corner.png b/demos/declarative/flickr/content/pics/shadow-corner.png Binary files differnew file mode 100644 index 0000000..ef8c856 --- /dev/null +++ b/demos/declarative/flickr/content/pics/shadow-corner.png diff --git a/demos/declarative/flickr/content/pics/shadow-right-screen.png b/demos/declarative/flickr/content/pics/shadow-right-screen.png Binary files differnew file mode 100644 index 0000000..9856c4f --- /dev/null +++ b/demos/declarative/flickr/content/pics/shadow-right-screen.png diff --git a/demos/declarative/flickr/content/pics/shadow-right.png b/demos/declarative/flickr/content/pics/shadow-right.png Binary files differnew file mode 100644 index 0000000..f534a35 --- /dev/null +++ b/demos/declarative/flickr/content/pics/shadow-right.png diff --git a/demos/declarative/flickr/flickr.qml b/demos/declarative/flickr/flickr.qml new file mode 100644 index 0000000..da77d93 --- /dev/null +++ b/demos/declarative/flickr/flickr.qml @@ -0,0 +1,208 @@ +import "content" + +Item { + id: MainWindow; width: 800; height: 450 + + property bool showPathView : false + + resources: [ + XmlListModel { + id: FeedModel + property string tags : TagsEdit.text + source: "http://api.flickr.com/services/feeds/photos_public.gne?"+(tags ? "tags="+tags+"&" : "")+"format=rss2" + query: "doc($src)/rss/channel/item" + namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";" + + Role { name: "title"; query: "title/string()" } + Role { name: "imagePath"; query: "media:thumbnail/@url/string()" } + Role { name: "url"; query: "media:content/@url/string()" } + Role { name: "description"; query: "description/string()"; isCData: true } + Role { name: "tags"; query: "media:category/string()" } + Role { name: "photoWidth"; query: "media:content/@width/string()" } + Role { name: "photoHeight"; query: "media:content/@height/string()" } + Role { name: "photoType"; query: "media:content/@type/string()" } + Role { name: "photoAuthor"; query: "author/string()" } + Role { name: "photoDate"; query: "pubDate/string()" } + }, + + Component { + id: PhotoDelegate + Item { + id: Wrapper; width: 85; height: 85 + scale: Wrapper.PathView.scale; z: Wrapper.PathView.z + + transform: [ + Rotation3D { id: Rotation; axis.startX: 30; axis.endX: 30; axis.endY: 60; angle: Wrapper.PathView.angle } + ] + + Connection { + sender: ImageDetails; signal: "closed()" + script: { + if (Wrapper.state == 'Details') { + Wrapper.state = ''; + ImageDetails.photoUrl = ""; + } + } + } + + Script { + function photoClicked() { + ImageDetails.photoTitle = title; + ImageDetails.photoDescription = description; + ImageDetails.photoTags = tags; + ImageDetails.photoWidth = photoWidth; + ImageDetails.photoHeight = photoHeight; + ImageDetails.photoType = photoType; + ImageDetails.photoAuthor = photoAuthor; + ImageDetails.photoDate = photoDate; + ImageDetails.photoUrl = url; + ImageDetails.rating = 0; + Wrapper.state = "Details"; + } + } + + Rect { + id: WhiteRect; anchors.fill: parent; color: "white"; radius: 5 + + Loading { x: 26; y: 26; visible: Thumb.status } + Image { id: Thumb; source: imagePath; x: 5; y: 5 } + + Item { + id: Shadows + Image { source: "content/pics/shadow-right.png"; x: WhiteRect.width; height: WhiteRect.height } + Image { source: "content/pics/shadow-bottom.png"; y: WhiteRect.height; width: WhiteRect.width } + Image { id: Corner; source: "content/pics/shadow-corner.png"; x: WhiteRect.width; y: WhiteRect.height } + } + } + + MouseRegion { anchors.fill: Wrapper; onClicked: { photoClicked() } } + + states: [ + State { + name: "Details" + SetProperties { target: ImageDetails; z: 2 } + ParentChange { target: Wrapper; parent: ImageDetails.frontContainer } + SetProperties { target: Wrapper; x: 45; y: 35; scale: 1; z: 1000 } + SetProperties { target: Rotation; angle: 0 } + SetProperties { target: Shadows; opacity: 0 } + SetProperties { target: ImageDetails; y: 20 } + SetProperties { target: PhotoGridView; y: "-480" } + SetProperties { target: PhotoPathView; y: "-480" } + SetProperties { target: ViewModeButton; opacity: 0 } + SetProperties { target: TagsEdit; opacity: 0 } + SetProperties { target: FetchButton; opacity: 0 } + SetProperties { target: CategoryText; y: "-50" } + } + ] + + transitions: [ + Transition { + fromState: "*"; toState: "Details" + ParentChangeAction { } + NumericAnimation { properties: "x,y,scale,opacity,angle"; duration: 500; easing: "easeInOutQuad" } + }, + Transition { + fromState: "Details"; toState: "*" + SequentialAnimation { + ParentChangeAction { } + NumericAnimation { properties: "x,y,scale,opacity,angle"; duration: 500; easing: "easeInOutQuad" } + SetPropertyAction { filter: Wrapper; properties: "z" } + } + } + ] + + } + } + ] + + Item { + id: Background + + anchors.fill: parent + + Image { source: "content/pics/background.png"; opaque: true; anchors.fill: parent } + + Loading { anchors.centeredIn: parent; visible: FeedModel.status != 0 } + + GridView { + id: PhotoGridView; model: FeedModel; delegate: PhotoDelegate; cacheBuffer: 100 + cellWidth: 105; cellHeight: 105; x:32; y: 80; width: 800; height: 330; z: 1 + } + + PathView { + id: PhotoPathView; model: FeedModel; delegate: PhotoDelegate + y: -380; width: 800; height: 330; pathItemCount: 10; z: 1 + path: Path { + startX: -50; startY: 40; + + PathAttribute { name: "scale"; value: 1 } + PathAttribute { name: "angle"; value: -45 } + + PathCubic { + x: 400; y: 220 + control1X: 140; control1Y: 40 + control2X: 210; control2Y: 220 + } + + PathAttribute { name: "scale"; value: 1.2 } + PathAttribute { name: "z"; value: 1 } + PathAttribute { name: "angle"; value: 0 } + + PathCubic { + x: 850; y: 40 + control2X: 660; control2Y: 40 + control1X: 590; control1Y: 220 + } + + PathAttribute { name: "scale"; value: 1 } + PathAttribute { name: "angle"; value: 45 } + } + + } + + ImageDetails { id: ImageDetails; width: 750; x: 25; y: 500; height: 410 } + + MediaButton { + id: ViewModeButton; x: 680; y: 410; text: "View Mode" + onClicked: { if (MainWindow.showPathView == true) MainWindow.showPathView = false; else MainWindow.showPathView = true } + } + + MediaButton { + id: FetchButton + text: "Update" + anchors.right: ViewModeButton.left; anchors.rightMargin: 5 + anchors.top: ViewModeButton.top + onClicked: { FeedModel.reload(); } + } + + MediaLineEdit { + id: TagsEdit; + label: "Tags" + anchors.right: FetchButton.left; anchors.rightMargin: 5 + anchors.top: ViewModeButton.top + } + + states: [ + State { + name: "PathView" + when: MainWindow.showPathView == true + SetProperties { target: PhotoPathView; y: 80 } + SetProperties { target: PhotoGridView; y: -380 } + } + ] + + transitions: [ + Transition { + fromState: "*"; toState: "*" + NumericAnimation { properties: "y"; duration: 1000; easing: "easeOutBounce(amplitude:0.5)" } + } + ] + } + + Text { + id: CategoryText; anchors.horizontalCenter: parent.horizontalCenter; y: 15; + text: "Flickr - " + + (FeedModel.tags=="" ? "Uploads from everyone" : "Recent Uploads tagged " + FeedModel.tags) + font.size: 20; font.bold: true; color: "white"; style: "Raised"; styleColor: "black" + } +} diff --git a/demos/declarative/flickr/flickr2.qml b/demos/declarative/flickr/flickr2.qml new file mode 100644 index 0000000..52f8675 --- /dev/null +++ b/demos/declarative/flickr/flickr2.qml @@ -0,0 +1,263 @@ +import "content" + +Item { + id: MainWindow; width: 800; height: 450 + + property bool showPathView : false + + VisualModel { + id: MyVisualModel + model: + XmlListModel { + id: FeedModel + property string tags : TagsEdit.text + source: "http://api.flickr.com/services/feeds/photos_public.gne?"+(tags ? "tags="+tags+"&" : "")+"format=rss2" + query: "doc($src)/rss/channel/item" + namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";" + + Role { name: "title"; query: "title/string()" } + Role { name: "imagePath"; query: "media:thumbnail/@url/string()" } + Role { name: "url"; query: "media:content/@url/string()" } + Role { name: "description"; query: "description/string()"; isCData: true } + Role { name: "tags"; query: "media:category/string()" } + Role { name: "photoWidth"; query: "media:content/@width/string()" } + Role { name: "photoHeight"; query: "media:content/@height/string()" } + Role { name: "photoType"; query: "media:content/@type/string()" } + Role { name: "photoAuthor"; query: "author/string()" } + Role { name: "photoDate"; query: "pubDate/string()" } + } + + delegate: Package { + Item { + id: Wrapper; width: 85; height: 85; scale: {1.0} + z: PathViewPackage.PathView.z + property real angle: 0 * 0 + + transform: [ + Rotation3D { + id: Rotation; axis.startX: 30; axis.endX: 30; axis.endY: 60 + angle: Wrapper.angle + } + ] + + Connection { + sender: Background.imageDetails; signal: "closed()" + script: { if (Wrapper.state == 'Details') Wrapper.state = '' } + } + + Script { + function photoClicked() { + Background.imageDetails.photoTitle = title; + Background.imageDetails.flickableArea.yPosition = 0; + Background.imageDetails.photoDescription = description; + Background.imageDetails.photoTags = tags; + Background.imageDetails.photoWidth = photoWidth; + Background.imageDetails.photoHeight = photoHeight; + Background.imageDetails.photoType = photoType; + Background.imageDetails.photoAuthor = photoAuthor; + Background.imageDetails.photoDate = photoDate; + Background.imageDetails.photoUrl = url; + Background.imageDetails.rating = 0; + Wrapper.state = "Details"; + } + } + + Rect { + id: WhiteRect; anchors.fill: parent; color: "white"; radius: 5 + + Loading { x: 26; y: 26; visible: Thumb.status } + Image { id: Thumb; source: imagePath; x: 5; y: 5 } + + Item { + id: Shadows + Image { source: "content/pics/shadow-right.png"; x: WhiteRect.width; height: WhiteRect.height } + Image { source: "content/pics/shadow-bottom.png"; y: WhiteRect.height; width: WhiteRect.width } + Image { id: Corner; source: "content/pics/shadow-corner.png"; x: WhiteRect.width; y: WhiteRect.height } + } + } + + MouseRegion { anchors.fill: Wrapper; onClicked: { photoClicked() } } + + states: [ + State { + name: "Details" + SetProperties { target: Background.imageDetails; z: 2 } + ParentChange { target: Wrapper; parent: Background.imageDetails.frontContainer } + SetProperties { target: Wrapper; x: 45; y: 35; scale: 1; z: 1000 } + SetProperties { target: Rotation; angle: 0 } + SetProperties { target: Shadows; opacity: 0 } + SetProperties { target: Background.imageDetails; y: 20 } + SetProperties { target: PhotoGridView; y: "-480" } + SetProperties { target: PhotoPathView; y: "-480" } + SetProperties { target: ViewModeButton; opacity: 0 } + SetProperties { target: TagsEdit; opacity: 0 } + SetProperties { target: FetchButton; opacity: 0 } + SetProperties { target: CategoryText; y: "-50" } + } + ] + + transitions: [ + Transition { + fromState: "*"; toState: "Details" + ParentChangeAction { } + NumericAnimation { properties: "x,y,scale,opacity,angle"; duration: 500; easing: "easeInOutQuad" } + }, + Transition { + fromState: "Details"; toState: "*" + SequentialAnimation { + ParentChangeAction { } + NumericAnimation { properties: "x,y,scale,opacity,angle"; duration: 500; easing: "easeInOutQuad" } + SetPropertyAction { filter: Wrapper; properties: "z" } + } + } + ] + } + + Item { + Package.name: "pathView" + id: PathViewPackage; width: 85; height: 85 + } + + Item { + Package.name: "gridView" + id: GridViewPackage; width: 85; height: 85 + } + + Item { + id: MyItem + state: MainWindow.showPathView ? "pathView" : "gridView" + states: [ + State { + name: "gridView" + SetProperty { target: Wrapper; property: "moveToParent"; value: GridViewPackage } + }, + State { + name: "pathView" + SetProperty { target: Wrapper; property: "scale"; value: PathViewPackage.PathView.scale } + SetProperty { target: Wrapper; property: "scale"; binding: "PathViewPackage.PathView.scale" } + SetProperty { target: Wrapper; property: "angle"; value: PathViewPackage.PathView.angle } + SetProperty { target: Wrapper; property: "angle"; binding: "PathViewPackage.PathView.angle" } + SetProperty { target: Wrapper; property: "moveToParent"; value: PathViewPackage } + } + ] + transitions: [ + Transition { + toState: "pathView" + SequentialAnimation { + SetPropertyAction { target: Wrapper; property: "moveToParent" } + ParallelAnimation { + NumericAnimation { + target: Wrapper + properties: "x,y" + to: 0 + easing: "easeOutQuad" + duration: 350 + } + NumericAnimation { target: Wrapper; properties: "scale,angle"; duration: 350 } + } + } + }, + Transition { + toState: "gridView" + SequentialAnimation { + PauseAnimation { duration: Math.floor(index/7)*100 } + SetPropertyAction { target: Wrapper; property: "moveToParent" } + ParallelAnimation { + NumericAnimation { + target: Wrapper + properties: "x,y" + to: 0 + easing: "easeOutQuad" + duration: 250 + } + NumericAnimation { target: Wrapper; properties: "scale,angle"; duration: 250 } + } + } + } + ] + } + } + } + + + Item { + id: Background + property var imageDetails: ImageDetails + + Image { source: "content/pics/background.png"; opaque: true } + + GridView { + id: PhotoGridView; model: MyVisualModel.parts.gridView + cellWidth: 105; cellHeight: 105; x:32; y: 80; width: 800; height: 330; z: 1 + cacheBuffer: 100 + } + + PathView { + id: PhotoPathView; model: MyVisualModel.parts.pathView + y: 80; width: 800; height: 330; z: 1 + pathItemCount: 10; snapPosition: 0.001 + path: Path { + startX: -150; startY: 40; + + PathAttribute { name: "scale"; value: 0.9 } + PathAttribute { name: "angle"; value: -45 } + PathPercent { value: 0 } + PathLine { x: -50; y: 40 } + + PathPercent { value: 0.001 } + + PathCubic { + x: 400; y: 220 + control1X: 140; control1Y: 40 + control2X: 210; control2Y: 220 + } + + PathAttribute { name: "scale"; value: 1.2 } + PathAttribute { name: "z"; value: 1 } + PathAttribute { name: "angle"; value: 0 } + + PathCubic { + x: 850; y: 40 + control2X: 660; control2Y: 40 + control1X: 590; control1Y: 220 + } + + PathPercent { value: 0.999 } + PathLine { x: 950; y: 40 } + PathPercent { value: 1.0 } + PathAttribute { name: "scale"; value: 0.9 } + PathAttribute { name: "angle"; value: 45 } + } + } + + ImageDetails { id: ImageDetails; width: 750; x: 25; y: 500; height: 410 } + + MediaButton { + id: ViewModeButton; x: 680; y: 410; text: "View Mode" + onClicked: { if (MainWindow.showPathView == true) MainWindow.showPathView = false; else MainWindow.showPathView = true } + } + + MediaButton { + id: FetchButton + text: "Update" + anchors.right: ViewModeButton.left; anchors.rightMargin: 5 + anchors.top: ViewModeButton.top + onClicked: { FeedModel.reload(); } + } + + MediaLineEdit { + id: TagsEdit; + label: "Tags" + anchors.right: FetchButton.left; anchors.rightMargin: 5 + anchors.top: ViewModeButton.top + } + + } + + Text { + id: CategoryText; anchors.horizontalCenter: parent.horizontalCenter; y: 15; + text: "Flickr - " + + (FeedModel.tags=="" ? "Uploads from everyone" : "Recent Uploads tagged " + FeedModel.tags) + font.size: 16; font.bold: true; color: "white"; style: "Raised"; styleColor: "black" + } +} diff --git a/demos/declarative/webbrowser/README b/demos/declarative/webbrowser/README new file mode 100644 index 0000000..7bfd41f --- /dev/null +++ b/demos/declarative/webbrowser/README @@ -0,0 +1,6 @@ +For good performance, be sure to use disk cache for remote content: + + duiviewer -cache webbrowser.qml + +Otherwise everything always re-loads over the network. + diff --git a/demos/declarative/webbrowser/content/RectSoftShadow.qml b/demos/declarative/webbrowser/content/RectSoftShadow.qml new file mode 100644 index 0000000..1734433 --- /dev/null +++ b/demos/declarative/webbrowser/content/RectSoftShadow.qml @@ -0,0 +1,30 @@ +Item { + Image { + source: "pics/softshadow-left.sci" + x: -16 + y: -16 + width: 16 + height: parent.height+32 + } + Image { + source: "pics/softshadow-right.sci" + x: parent.width + y: -16 + width: 16 + height: parent.height+32 + } + Image { + source: "pics/softshadow-top.png" + x: 0 + y: -16 + width: parent.width + height: 16 + } + Image { + source: "pics/softshadow-bottom.png" + x: 0 + y: parent.height + width: WebView.width*WebView.scale + height: 16 + } +} diff --git a/demos/declarative/webbrowser/content/pics/addressbar-filled.png b/demos/declarative/webbrowser/content/pics/addressbar-filled.png Binary files differnew file mode 100644 index 0000000..d8452ec --- /dev/null +++ b/demos/declarative/webbrowser/content/pics/addressbar-filled.png diff --git a/demos/declarative/webbrowser/content/pics/addressbar-filled.sci b/demos/declarative/webbrowser/content/pics/addressbar-filled.sci new file mode 100644 index 0000000..464dbf5 --- /dev/null +++ b/demos/declarative/webbrowser/content/pics/addressbar-filled.sci @@ -0,0 +1,6 @@ +gridLeft: 7 +gridTop: 7 +gridBottom: 7 +gridRight: 7 +imageFile: addressbar-filled.png + diff --git a/demos/declarative/webbrowser/content/pics/addressbar.png b/demos/declarative/webbrowser/content/pics/addressbar.png Binary files differnew file mode 100644 index 0000000..3278f58 --- /dev/null +++ b/demos/declarative/webbrowser/content/pics/addressbar.png diff --git a/demos/declarative/webbrowser/content/pics/addressbar.sci b/demos/declarative/webbrowser/content/pics/addressbar.sci new file mode 100644 index 0000000..23a2a19 --- /dev/null +++ b/demos/declarative/webbrowser/content/pics/addressbar.sci @@ -0,0 +1,6 @@ +gridLeft: 7 +gridTop: 7 +gridBottom: 7 +gridRight: 7 +imageFile: addressbar.png + diff --git a/demos/declarative/webbrowser/content/pics/back-disabled.png b/demos/declarative/webbrowser/content/pics/back-disabled.png Binary files differnew file mode 100644 index 0000000..91b9e76 --- /dev/null +++ b/demos/declarative/webbrowser/content/pics/back-disabled.png diff --git a/demos/declarative/webbrowser/content/pics/back.png b/demos/declarative/webbrowser/content/pics/back.png Binary files differnew file mode 100644 index 0000000..9988dd3 --- /dev/null +++ b/demos/declarative/webbrowser/content/pics/back.png diff --git a/demos/declarative/webbrowser/content/pics/footer.png b/demos/declarative/webbrowser/content/pics/footer.png Binary files differnew file mode 100644 index 0000000..8391a93 --- /dev/null +++ b/demos/declarative/webbrowser/content/pics/footer.png diff --git a/demos/declarative/webbrowser/content/pics/footer.sci b/demos/declarative/webbrowser/content/pics/footer.sci new file mode 100644 index 0000000..be1d086 --- /dev/null +++ b/demos/declarative/webbrowser/content/pics/footer.sci @@ -0,0 +1,6 @@ +gridLeft: 5 +gridTop: 0 +gridBottom: 0 +gridRight: 5 +imageFile: footer.png + diff --git a/demos/declarative/webbrowser/content/pics/forward-disabled.png b/demos/declarative/webbrowser/content/pics/forward-disabled.png Binary files differnew file mode 100644 index 0000000..cb87f4f --- /dev/null +++ b/demos/declarative/webbrowser/content/pics/forward-disabled.png diff --git a/demos/declarative/webbrowser/content/pics/forward.png b/demos/declarative/webbrowser/content/pics/forward.png Binary files differnew file mode 100644 index 0000000..83870ee --- /dev/null +++ b/demos/declarative/webbrowser/content/pics/forward.png diff --git a/demos/declarative/webbrowser/content/pics/header.png b/demos/declarative/webbrowser/content/pics/header.png Binary files differnew file mode 100644 index 0000000..26588c3 --- /dev/null +++ b/demos/declarative/webbrowser/content/pics/header.png diff --git a/demos/declarative/webbrowser/content/pics/reload.png b/demos/declarative/webbrowser/content/pics/reload.png Binary files differnew file mode 100644 index 0000000..45b5535 --- /dev/null +++ b/demos/declarative/webbrowser/content/pics/reload.png diff --git a/demos/declarative/webbrowser/content/pics/softshadow-bottom.png b/demos/declarative/webbrowser/content/pics/softshadow-bottom.png Binary files differnew file mode 100644 index 0000000..85b0b44 --- /dev/null +++ b/demos/declarative/webbrowser/content/pics/softshadow-bottom.png diff --git a/demos/declarative/webbrowser/content/pics/softshadow-left.png b/demos/declarative/webbrowser/content/pics/softshadow-left.png Binary files differnew file mode 100644 index 0000000..02926d1 --- /dev/null +++ b/demos/declarative/webbrowser/content/pics/softshadow-left.png diff --git a/demos/declarative/webbrowser/content/pics/softshadow-left.sci b/demos/declarative/webbrowser/content/pics/softshadow-left.sci new file mode 100644 index 0000000..82e38f8 --- /dev/null +++ b/demos/declarative/webbrowser/content/pics/softshadow-left.sci @@ -0,0 +1,5 @@ +gridLeft: 0 +gridTop: 16 +gridBottom: 16 +gridRight: 0 +imageFile: softshadow-left.png diff --git a/demos/declarative/webbrowser/content/pics/softshadow-right.png b/demos/declarative/webbrowser/content/pics/softshadow-right.png Binary files differnew file mode 100644 index 0000000..e459f4f --- /dev/null +++ b/demos/declarative/webbrowser/content/pics/softshadow-right.png diff --git a/demos/declarative/webbrowser/content/pics/softshadow-right.sci b/demos/declarative/webbrowser/content/pics/softshadow-right.sci new file mode 100644 index 0000000..e9494ed --- /dev/null +++ b/demos/declarative/webbrowser/content/pics/softshadow-right.sci @@ -0,0 +1,5 @@ +gridLeft: 0 +gridTop: 16 +gridBottom: 16 +gridRight: 0 +imageFile: softshadow-right.png diff --git a/demos/declarative/webbrowser/content/pics/softshadow-top.png b/demos/declarative/webbrowser/content/pics/softshadow-top.png Binary files differnew file mode 100644 index 0000000..9a9e232 --- /dev/null +++ b/demos/declarative/webbrowser/content/pics/softshadow-top.png diff --git a/demos/declarative/webbrowser/webbrowser.qml b/demos/declarative/webbrowser/webbrowser.qml new file mode 100644 index 0000000..a38d032 --- /dev/null +++ b/demos/declarative/webbrowser/webbrowser.qml @@ -0,0 +1,429 @@ +import "content" + +Item { + id: WebBrowser + + property var url : "http://www.qtsoftware.com" + + width: 640 + height: 480 + state: "Normal" + + Script { + function zoomOut() { + WebBrowser.state = "ZoomedOut"; + } + function toggleZoom() { + if(WebBrowser.state == "ZoomedOut") { + Flick.centerX = WebView.mouseX; + Flick.centerY = WebView.mouseY; + WebBrowser.state = "Normal"; + } else { + zoomOut(); + } + } + } + + Item { + id: WebPanel + anchors.fill: parent + clip: true + Rect { + color: "#555555" + anchors.fill: parent + } + Image { + source: "content/pics/softshadow-bottom.png" + width: WebPanel.width + height: 16 + } + Image { + source: "content/pics/softshadow-top.png" + width: WebPanel.width + height: 16 + anchors.bottom: Footer.top + } + RectSoftShadow { + x: -Flick.xPosition + y: -Flick.yPosition + width: WebView.width*WebView.scale + height: Flick.y+WebView.height*WebView.scale + } + Item { + id: HeaderSpace + width: parent.width + height: 60 + z: 1 + + Image { + id: Header + source: "content/pics/header.png" + width: parent.width + height: 64 + state: "Normal" + x: Flick.xPosition < 0 ? -Flick.xPosition : Flick.xPosition > Flick.viewportWidth-Flick.width + ? -Flick.xPosition+Flick.viewportWidth-Flick.width : 0 + y: Flick.yPosition < 0 ? -Flick.yPosition : progressOff* + (Flick.yPosition>height?-height:-Flick.yPosition) + Text { + id: HeaderText + + text: WebView.title!='' || WebView.progress == 1.0 ? WebView.title : 'Loading...' + elide: "ElideRight" + + color: "white" + styleColor: "black" + style: "Raised" + + font.family: "Helvetica" + font.size: 10 + font.bold: true + + anchors.left: Header.left + anchors.right: Header.right + anchors.leftMargin: 4 + anchors.rightMargin: 4 + anchors.top: Header.top + anchors.topMargin: 4 + hAlign: "AlignHCenter" + } + Item { + width: parent.width + anchors.top: HeaderText.bottom + anchors.topMargin: 2 + anchors.bottom: parent.bottom + + Item { + id: UrlBox + height: 31 + anchors.left: parent.left + anchors.leftMargin: 12 + anchors.right: parent.right + anchors.rightMargin: 12 + anchors.top: parent.top + clip: true + Image { + source: "content/pics/addressbar.sci" + anchors.fill: UrlBox + } + Image { + id: UrlBoxhl + source: "content/pics/addressbar-filled.sci" + width: parent.width*WebView.progress + height: parent.height + opacity: 1-Header.progressOff + clip: true + } + + /* + KeyProxy { + id: proxy + anchors.left: UrlBox.left + anchors.fill: UrlBox + focusable: true + targets: [keyActions,EditUrl] + } + KeyActions { + id: keyActions + return: "WebBrowser.url = EditUrl.text; proxy.focus=false;" + } + */ + TextEdit { + id: EditUrl + + text: WebView.url == '' ? ' ' : WebView.url + wrap: false + font.size: 11 + color: "#555555" + focusOnPress: true + + anchors.left: UrlBox.left + anchors.right: UrlBox.right + anchors.leftMargin: 6 + anchors.verticalCenter: UrlBox.verticalCenter + anchors.verticalCenterOffset: 1 + } + } + } + + property real progressOff : 1 + states: [ + State { + name: "Normal" + when: WebView.progress == 1.0 + SetProperty { + target: Header + property: "progressOff" + value: 1 + } + }, + State { + name: "ProgressShown" + when: WebView.progress < 1.0 + SetProperty { + target: Header + property: "progressOff" + value: 0 + } + } + ] + transitions: [ + Transition { + NumericAnimation { + target: Header + properties: "progressOff" + easing: "easeInOutQuad" + duration: 300 + } + } + ] + } + } + Flickable { + id: Flick + width: parent.width + viewportWidth: Math.max(parent.width,WebView.width*WebView.scale) + viewportHeight: Math.max(parent.height,WebView.height*WebView.scale) + anchors.top: HeaderSpace.bottom + anchors.bottom: Footer.top + anchors.left: parent.left + anchors.right: parent.right + + property real centerX : 0 + property real centerY : 0 + + WebView { + id: WebView + cacheSize: 4000000 + + url: WebBrowser.url + smooth: true + focusable: true + focus: true + + idealWidth: Flick.width + idealHeight: Flick.height/scale + scale: (width > 0) ? Flick.width/width*zoomedOut+(1-zoomedOut) : 1 + + onUrlChanged: { Flick.xPosition=0; Flick.yPosition=0; zoomOut() } + onDoubleClick: { toggleZoom() } + + property real zoomedOut : 1 + } + Rect { + id: WebViewTint + color: "black" + opacity: 0 + anchors.fill: WebView + MouseRegion { + anchors.fill: WebViewTint + onClicked: { proxy.focus=false } + } + } + } + Image { + id: Footer + source: "content/pics/footer.sci" + width: parent.width + height: 43 + anchors.bottom: parent.bottom + Rect { + y: -1 + width: parent.width + height: 1 + color: "#555555" + } + Item { + id: backbutton + width: back_e.width + height: back_e.height + anchors.right: reload.left + anchors.rightMargin: 10 + anchors.verticalCenter: parent.verticalCenter + Image { + id: back_e + source: "content/pics/back.png" + anchors.fill: parent + } + Image { + id: back_d + source: "content/pics/back-disabled.png" + anchors.fill: parent + } + states: [ + State { + name: "Enabled" + when: WebView.back.enabled==true + SetProperty { + target: back_e + property: "opacity" + value: 1 + } + SetProperty { + target: back_d + property: "opacity" + value: 0 + } + }, + State { + name: "Disabled" + when: WebView.back.enabled==false + SetProperty { + target: back_e + property: "opacity" + value: 0 + } + SetProperty { + target: back_d + property: "opacity" + value: 1 + } + } + ] + transitions: [ + Transition { + NumericAnimation { + properties: "opacity" + easing: "easeInOutQuad" + duration: 300 + } + } + ] + MouseRegion { + anchors.fill: back_e + onClicked: { if (WebView.back.enabled) WebView.back.trigger() } + } + } + Image { + id: reload + source: "content/pics/reload.png" + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + } + MouseRegion { + anchors.fill: reload + onClicked: { WebView.reload.trigger() } + } + Item { + id: forwardbutton + width: forward_e.width + height: forward_e.height + anchors.left: reload.right + anchors.leftMargin: 10 + anchors.verticalCenter: parent.verticalCenter + Image { + id: forward_e + source: "content/pics/forward.png" + anchors.fill: parent + anchors.verticalCenter: parent.verticalCenter + } + Image { + id: forward_d + source: "content/pics/forward-disabled.png" + anchors.fill: parent + } + states: [ + State { + name: "Enabled" + when: WebView.forward.enabled==true + SetProperty { + target: forward_e + property: "opacity" + value: 1 + } + SetProperty { + target: forward_d + property: "opacity" + value: 0 + } + }, + State { + name: "Disabled" + when: WebView.forward.enabled==false + SetProperty { + target: forward_e + property: "opacity" + value: 0 + } + SetProperty { + target: forward_d + property: "opacity" + value: 1 + } + } + ] + transitions: [ + Transition { + NumericAnimation { + properties: "opacity" + easing: "easeInOutQuad" + duration: 320 + } + } + ] + MouseRegion { + anchors.fill: parent + onClicked: { if (WebView.forward.enabled) WebView.forward.trigger() } + } + } + } + } + states: [ + State { + name: "Normal" + SetProperty { + target: WebView + property: "zoomedOut" + value: 0 + } + SetProperty { + target: Flick + property: "xPosition" + value: Math.min(WebView.width-Flick.width,Math.max(0,Flick.centerX-Flick.width/2)) + } + SetProperty { + target: Flick + property: "yPosition" + value: Math.min(WebView.height-Flick.height,Math.max(0,Flick.centerY-Flick.height/2)) + } + }, + State { + name: "ZoomedOut" + SetProperty { + target: WebView + property: "zoomedOut" + value: 1 + } + } + ] + transitions: [ + Transition { + SequentialAnimation { + SetPropertyAction { + target: WebView + property: "smooth" + value: false + } + ParallelAnimation { + NumericAnimation { + target: WebView + properties: "zoomedOut" + easing: "easeInOutQuad" + duration: 200 + } + NumericAnimation { + target: Flick + properties: "xPosition,yPosition" + easing: "easeInOutQuad" + duration: 200 + } + } + SetPropertyAction { + target: WebView + property: "smooth" + value: true + } + } + } + ] +} |