Merge lp:~renatofilho/address-book-app/fix-1377334 into lp:~phablet-team/address-book-app/staging

Proposed by Renato Araujo Oliveira Filho
Status: Rejected
Rejected by: Renato Araujo Oliveira Filho
Proposed branch: lp:~renatofilho/address-book-app/fix-1377334
Merge into: lp:~phablet-team/address-book-app/staging
Diff against target: 380 lines (+142/-128)
4 files modified
src/imports/ContactEdit/AvatarImport.qml (+96/-91)
src/imports/ContactEdit/ContactDetailAvatarEditor.qml (+14/-17)
src/imports/ContactList/ContactExporter.qml (+28/-2)
src/imports/ContactList/ContactListPage.qml (+4/-18)
To merge this branch: bzr merge lp:~renatofilho/address-book-app/fix-1377334
Reviewer Review Type Date Requested Status
Ken VanDine Approve
PS Jenkins bot continuous-integration Needs Fixing
Review via email: mp+237480@code.launchpad.net

Commit message

Implement AvatarImport as a Page.

Does not use dialog on content hub component, to avoid application to get stuck.
Handle operation aborted in pick mode.

To post a comment you must log in.
Revision history for this message
Ken VanDine (ken-vandine) wrote :

I haven't done a full review yet, but I would suggest perhaps it's worth talking about adding the title to ContentTransferHint rather than reimplementing it here. I worry about needing to maintain a copy of that code, and it seems like a nice feature for ContentTransferHint.

Revision history for this message
Ken VanDine (ken-vandine) wrote :

I haven't run it yet, I'll wait for a CI build for that. But from the code review it looks good, see a couple inline comments.

Also, unrelated to this MP, I see there is a copyImage function to copy the file. There is now an API for that in content-hub, ContentItem.move(). Now that content-hub provides an API for that, you could consider switching to that.

315. By Renato Araujo Oliveira Filho

Fixed contact export.

Revision history for this message
Renato Araujo Oliveira Filho (renatofilho) wrote :

> I haven't run it yet, I'll wait for a CI build for that. But from the code
> review it looks good, see a couple inline comments.
>
> Also, unrelated to this MP, I see there is a copyImage function to copy the
> file. There is now an API for that in content-hub, ContentItem.move(). Now
> that content-hub provides an API for that, you could consider switching to
> that.

The copyImage not only copy the image it resize it to a small size to be used as avatar.

Revision history for this message
Renato Araujo Oliveira Filho (renatofilho) :
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Ken VanDine (ken-vandine) wrote :

Works well on my mako, I tested the full path including adding the avatar from gallery as well as aborting the transfer. All worked well.

review: Approve

Unmerged revisions

315. By Renato Araujo Oliveira Filho

Fixed contact export.

314. By Renato Araujo Oliveira Filho

Implement AvatarImport as a Page.

Does not use dialogs on content hub component, to avoid application to get stuck.
Handle operation aborted in pick mode.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/imports/ContactEdit/AvatarImport.qml'
--- src/imports/ContactEdit/AvatarImport.qml 2014-08-13 20:52:57 +0000
+++ src/imports/ContactEdit/AvatarImport.qml 2014-10-07 20:52:25 +0000
@@ -18,103 +18,108 @@
1818
19import Ubuntu.Components 1.119import Ubuntu.Components 1.1
20import Ubuntu.Components.Popups 1.020import Ubuntu.Components.Popups 1.0
21import Ubuntu.Content 0.121import Ubuntu.Content 1.1
2222
23Item {23Page {
24 id: root24 id: root
2525
26 property var importDialog: null26 property var avatarListener: null
27 property alias activeTransfer: signalConnections.target
28 property alias isTransferRunning: activityIndicator.running
2729
28 signal avatarReceived(string avatarUrl)30 signal avatarReceived(string avatarUrl)
2931
30 function requestNewAvatar()32 title: i18n.tr("Import avatar from...")
31 {33
32 if (!root.importDialog) {34 Item {
33 root.importDialog = PopupUtils.open(contentHubDialog, null)35 id: transferHint
34 } else {36
35 console.warn("Import dialog already running")37 anchors.fill: parent
36 }38 visible: root.isTransferRunning
37 }39
3840 ActivityIndicator {
39 Component {41 id: activityIndicator
40 id: contentHubDialog42
4143 anchors {
42 PopupBase {44 horizontalCenter: parent.horizontalCenter
43 id: dialogue45 verticalCenter: parent.verticalCenter
4446 verticalCenterOffset: units.gu(-4)
45 property alias activeTransfer: signalConnections.target47 }
4648 running: root.activeTransfer
47 parent: QuickUtils.rootItem(this)49 }
48 focus: true50
4951 Label {
50 Rectangle {52 anchors {
51 anchors.fill: parent53 top: activityIndicator.bottom
5254 topMargin: units.gu(2)
53 ContentTransferHint {55 horizontalCenter: parent.horizontalCenter
54 anchors.fill: parent56 }
55 activeTransfer: dialogue.activeTransfer57 // TRANSLATORS: This message appear while waiting for a external application content,
56 }58 // %1 refers to the the name of source application
5759 text: i18n.tr("Waiting for content from %1...").arg(peerPicker.peer.name)
58 ContentPeerPicker {60 }
59 id: peerPicker61
6062 Button {
61 anchors.fill: parent63 id: cancelButton
62 visible: dialogue.done64
63 contentType: ContentType.Pictures65 enabled: root.activeTransfer && (root.activeTransfer.state === ContentTransfer.InProgress)
64 handler: ContentHandler.Source66 anchors {
6567 bottom: parent.bottom
66 onPeerSelected: {68 left: parent.left
67 peer.selectionType = ContentTransfer.Single69 right: parent.right
68 dialogue.activeTransfer = peer.request()70 margins: units.gu(2)
69 }71 }
7072 text: i18n.tr("Cancel")
71 onCancelPressed: {73 onClicked: root.activeTransfer.state = ContentTransfer.Aborted
72 PopupUtils.close(root.importDialog)74 }
73 }75 }
74 }76
75 }77 ContentPeerPicker {
7678 id: peerPicker
77 Connections {79
78 id: signalConnections80 anchors.fill: parent
7981 contentType: ContentType.Pictures
80 target: dialogue.activeTransfer82 handler: ContentHandler.Source
81 onStateChanged: {83 showTitle: false
82 var done = ((dialogue.activeTransfer.state === ContentTransfer.Charged) ||84 visible: !root.isTransferRunning
83 (dialogue.activeTransfer.state === ContentTransfer.Aborted))85
8486 onPeerSelected: {
85 if (dialogue.activeTransfer.state === ContentTransfer.Charged) {87 peer.selectionType = ContentTransfer.Single
86 dialogue.hide()88 root.activeTransfer = peer.request()
87 if (dialogue.activeTransfer.items.length > 0) {89 }
88 root.avatarReceived(dialogue.activeTransfer.items[0].url)90
89 }91 onCancelPressed: pageStack.pop()
90 }92 }
9193
92 if (done) {94 Connections {
93 acceptTimer.restart()95 id: signalConnections
94 }96
95 }97 target: null
96 }98 onStateChanged: {
9799 var done = ((root.activeTransfer.state === ContentTransfer.Charged) ||
98 // WORKAROUND: Work around for application becoming insensitive to touch events100 (root.activeTransfer.state === ContentTransfer.Aborted))
99 // if the dialog is dismissed while the application is inactive.101 transferHint.enabled = !done
100 // Just listening for changes to Qt.application.active doesn't appear102 if (root.activeTransfer.state === ContentTransfer.Charged) {
101 // to be enough to resolve this, so it seems that something else needs103 if (( root.activeTransfer.items.length > 0) && root.avatarListener) {
102 // to be happening first. As such there's a potential for a race104 root.avatarListener.avatarReceived( root.activeTransfer.items[0].url)
103 // condition here, although as yet no problem has been encountered.105 }
104 Timer {106 }
105 id: acceptTimer107
106108 if (done) {
107 interval: 100109 pageStack.pop()
108 repeat: true110 }
109 running: false111 }
110 onTriggered: {112 }
111 if(Qt.application.active) {113
112 PopupUtils.close(root.importDialog)114 Component.onDestruction: {
113 }115 if (root.avatarListener) {
114 }116 root.avatarListener.busy = false
115 }117 }
116118 }
117 Component.onDestruction: root.importDialog = null119
120 Component.onCompleted: {
121 if (root.avatarListener) {
122 root.avatarListener.busy = true
118 }123 }
119 }124 }
120}125}
121126
=== modified file 'src/imports/ContactEdit/ContactDetailAvatarEditor.qml'
--- src/imports/ContactEdit/ContactDetailAvatarEditor.qml 2014-09-29 13:20:08 +0000
+++ src/imports/ContactEdit/ContactDetailAvatarEditor.qml 2014-10-07 20:52:25 +0000
@@ -23,7 +23,7 @@
23ContactDetailBase {23ContactDetailBase {
24 id: root24 id: root
2525
26 readonly property alias busy: activityIndicator.running26 property alias busy: activityIndicator.running
27 readonly property string defaultAvatar: "image://theme/add"27 readonly property string defaultAvatar: "image://theme/add"
2828
29 function isEmpty() {29 function isEmpty() {
@@ -61,6 +61,16 @@
61 return avatarUrl61 return avatarUrl
62 }62 }
6363
64 function avatarReceived(avatarUrl)
65 {
66 // remove the previous image, this is nessary to make sure that the new image
67 // get updated otherwise if the new image has the same name the image will not
68 // be updated
69 avatarImage.source = ""
70 // Update with the new value
71 avatarImage.source = application.copyImage(root.contact, avatarUrl);
72 }
73
64 detail: contact ? contact.detail(ContactDetail.Avatar) : null74 detail: contact ? contact.detail(ContactDetail.Avatar) : null
65 implicitHeight: units.gu(8)75 implicitHeight: units.gu(8)
66 implicitWidth: units.gu(8)76 implicitWidth: units.gu(8)
@@ -81,7 +91,7 @@
81 anchors.centerIn: visible ? avatar : undefined91 anchors.centerIn: visible ? avatar : undefined
82 height: units.gu(3)92 height: units.gu(3)
83 width: units.gu(3)93 width: units.gu(3)
84 visible: source == defaultAvatar94 visible: source == defaultAvatar && !root.busy
8595
86 // When updating the avatar using the content picker the temporary file returned96 // When updating the avatar using the content picker the temporary file returned
87 // can contain the same name as the previous one and if the cache is enabled this97 // can contain the same name as the previous one and if the cache is enabled this
@@ -94,29 +104,16 @@
94 id: activityIndicator104 id: activityIndicator
95105
96 anchors.centerIn: avatar106 anchors.centerIn: avatar
97 running: (avatarImport.importDialog != null)
98 visible: running107 visible: running
99 }108 }
100109
101 AvatarImport {
102 id: avatarImport
103
104 onAvatarReceived: {
105 // remove the previous image, this is nessary to make sure that the new image
106 // get updated otherwise if the new image has the same name the image will not
107 // be updated
108 avatarImage.source = ""
109 // Update with the new value
110 avatarImage.source = application.copyImage(root.contact, avatarUrl);
111 }
112 }
113
114 MouseArea {110 MouseArea {
115 anchors.fill: parent111 anchors.fill: parent
116 onClicked: {112 onClicked: {
117 // make sure the OSK disappear113 // make sure the OSK disappear
118 root.forceActiveFocus()114 root.forceActiveFocus()
119 avatarImport.requestNewAvatar()115 root.busy = true
116 pageStack.push(Qt.resolvedUrl("AvatarImport.qml"), {avatarListener: root})
120 }117 }
121 }118 }
122}119}
123120
=== modified file 'src/imports/ContactList/ContactExporter.qml'
--- src/imports/ContactList/ContactExporter.qml 2014-09-30 21:17:25 +0000
+++ src/imports/ContactList/ContactExporter.qml 2014-10-07 20:52:25 +0000
@@ -16,15 +16,17 @@
1616
17import QtQuick 2.217import QtQuick 2.2
18import QtContacts 5.018import QtContacts 5.0
19import Ubuntu.Content 1.1
1920
20Item {21Item {
21 id: root22 id: root
2223
23 property var contactModel24 property var contactModel
24 property var outputFile25 property var outputFile
26 property var activeTransfer: null
2527
26 signal contactExported(int error, string url)
27 signal contactsFetched(var contacts)28 signal contactsFetched(var contacts)
29 signal done()
2830
29 function start(contacts) {31 function start(contacts) {
30 if (!contactModel) {32 if (!contactModel) {
@@ -59,7 +61,20 @@
5961
60 onExportCompleted: {62 onExportCompleted: {
61 priv.currentQueryId = -163 priv.currentQueryId = -1
62 root.contactExported(error, root.outputFile)64
65 // send contacts back to source app (pick mode)
66 if (error === ContactModel.ExportNoError) {
67 var obj = Qt.createQmlObject("import Ubuntu.Content 1.1; ContentItem { url: '" + url + "' }", root)
68 if (root.activeTransfer) {
69 root.activeTransfer.items = [obj]
70 root.activeTransfer.state = ContentTransfer.Charged
71 } else {
72 console.error("No active transfer")
73 }
74 } else {
75 console.error("Fail to export contacts:" + error)
76 }
77 root.done()
63 }78 }
6479
65 onContactsFetched: {80 onContactsFetched: {
@@ -74,5 +89,16 @@
74 }89 }
75 }90 }
76 }91 }
92
93 Connections {
94 target: root.activeTransfer
95
96 onStateChanged: {
97 if (root.activeTransfer.state === ContentTransfer.Aborted) {
98 root.activeTransfer = null
99 root.done()
100 }
101 }
102 }
77 }103 }
78}104}
79105
=== modified file 'src/imports/ContactList/ContactListPage.qml'
--- src/imports/ContactList/ContactListPage.qml 2014-10-03 21:45:23 +0000
+++ src/imports/ContactList/ContactListPage.qml 2014-10-07 20:52:25 +0000
@@ -21,7 +21,7 @@
21import Ubuntu.Components.ListItems 1.0 as ListItem21import Ubuntu.Components.ListItems 1.0 as ListItem
22import Ubuntu.Components.Popups 1.0 as Popups22import Ubuntu.Components.Popups 1.0 as Popups
23import Ubuntu.Contacts 0.1 as ContactsUI23import Ubuntu.Contacts 0.1 as ContactsUI
24import Ubuntu.Content 0.1 as ContentHub24import Ubuntu.Content 1.1 as ContentHub
2525
26import "../Common"26import "../Common"
2727
@@ -622,27 +622,13 @@
622 ContactExporter {622 ContactExporter {
623 id: contactExporter623 id: contactExporter
624624
625 property var activeTransfer: null
626
627 contactModel: contactList.listModel625 contactModel: contactList.listModel
628 outputFile: mainPage.pickMode ? "file:///tmp/address_book_app_export.vcf" : ""626 outputFile: mainPage.pickMode ? "file:///tmp/address_book_app_export.vcf" : ""
629 onContactExported: {627
630 // send contacts back to source app (pick mode)628 onDone: {
631 if (error === ContactModel.ExportNoError) {
632 var obj = Qt.createQmlObject("import Ubuntu.Content 0.1; ContentItem { url: '" + url + "' }", contactExporter)
633 if (activeTransfer) {
634 activeTransfer.items = [obj]
635 activeTransfer.state = ContentHub.ContentTransfer.Charged
636 } else {
637 console.error("No active transfer")
638 }
639 } else {
640 console.error("Fail to export contacts:" + error)
641 }
642 activeTransfer = null
643 mainPage.pickMode = false629 mainPage.pickMode = false
644 mainPage.state = "default"630 mainPage.state = "default"
645 application.returnVcard(url)631 application.returnVcard(contactExporter.outputFile)
646 }632 }
647633
648 onContactsFetched: {634 onContactsFetched: {

Subscribers

People subscribed via source and target branches