Merge lp:~renatofilho/address-book-app/new-visual-contact-editor into lp:~phablet-team/address-book-app/staging
- new-visual-contact-editor
- Merge into staging
Status: | Merged |
---|---|
Approved by: | Tiago Salem Herrmann |
Approved revision: | 215 |
Merged at revision: | 190 |
Proposed branch: | lp:~renatofilho/address-book-app/new-visual-contact-editor |
Merge into: | lp:~phablet-team/address-book-app/staging |
Prerequisite: | lp:~renatofilho/address-book-app/new-visual-contact-view |
Diff against target: |
1303 lines (+540/-278) 24 files modified
src/app/imagescalethread.cpp (+1/-1) src/imports/Common/ContactDetailItem.qml (+1/-0) src/imports/ContactEdit/AddFieldDialog.qml (+142/-0) src/imports/ContactEdit/AvatarImport.qml (+78/-0) src/imports/ContactEdit/CMakeLists.txt (+2/-0) src/imports/ContactEdit/ContactDetailAvatarEditor.qml (+45/-94) src/imports/ContactEdit/ContactDetailGroupWithTypeEditor.qml (+4/-30) src/imports/ContactEdit/ContactDetailNameEditor.qml (+1/-0) src/imports/ContactEdit/ContactDetailSyncTargetEditor.qml (+8/-2) src/imports/ContactEdit/ContactDetailWithTypeEditor.qml (+27/-27) src/imports/ContactEdit/ContactEditor.qml (+95/-28) src/imports/ContactEdit/TextInputDetail.qml (+1/-0) src/imports/ContactEdit/ValueSelector.qml (+12/-15) src/imports/ContactList/ContactListPage.qml (+1/-4) src/imports/ContactView/BasicFieldView.qml (+2/-2) src/imports/ContactView/ContactDetailAvatarView.qml (+6/-2) src/imports/ContactView/ContactDetailGroupWithTypeView.qml (+2/-0) src/imports/ContactView/ContactView.qml (+2/-1) src/imports/Ubuntu/Contacts/ContactAvatar.qml (+11/-3) src/imports/Ubuntu/Contacts/MultipleSelectionListView.qml (+9/-1) tests/autopilot/address_book_app/pages/_contact_editor.py (+42/-20) tests/autopilot/address_book_app/tests/__init__.py (+1/-2) tests/autopilot/address_book_app/tests/test_add_contact.py (+20/-32) tests/autopilot/address_book_app/tests/test_edit_contact.py (+27/-14) |
To merge this branch: | bzr merge lp:~renatofilho/address-book-app/new-visual-contact-editor |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Approve | |
Tiago Salem Herrmann (community) | Approve | ||
Review via email: mp+223009@code.launchpad.net |
Commit message
Update contact editor page visuals.
Description of the change
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:194
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:198
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:199
http://
Executed test runs:
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:201
http://
Executed test runs:
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:204
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:205
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Leo Arias (elopio) : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:206
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:209
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:209
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:210
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Tiago Salem Herrmann (tiagosh) wrote : | # |
looks good to me now.
Thanks.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:211
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:213
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:213
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:215
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:215
http://
Executed test runs:
None: http://
None: http://
None: http://
None: http://
None: http://
None: http://
None: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) : | # |
Preview Diff
1 | === modified file 'src/app/imagescalethread.cpp' |
2 | --- src/app/imagescalethread.cpp 2013-10-15 14:34:03 +0000 |
3 | +++ src/app/imagescalethread.cpp 2014-06-18 14:13:24 +0000 |
4 | @@ -57,7 +57,7 @@ |
5 | } |
6 | |
7 | // Create the temporary file |
8 | - m_tmpFile = new QTemporaryFile(); |
9 | + m_tmpFile = new QTemporaryFile("avatar_XXXXXX.png"); |
10 | if (!m_tmpFile->open()) { |
11 | return; |
12 | } |
13 | |
14 | === modified file 'src/imports/Common/ContactDetailItem.qml' |
15 | --- src/imports/Common/ContactDetailItem.qml 2014-05-16 00:06:46 +0000 |
16 | +++ src/imports/Common/ContactDetailItem.qml 2014-06-18 14:13:24 +0000 |
17 | @@ -23,6 +23,7 @@ |
18 | |
19 | readonly property alias fieldDelegates: fieldsColumn.children |
20 | property Component fieldDelegate: null |
21 | + property alias spacing: fieldsColumn.spacing |
22 | |
23 | implicitHeight: fieldsColumn.height |
24 | Column { |
25 | |
26 | === added file 'src/imports/ContactEdit/AddFieldDialog.qml' |
27 | --- src/imports/ContactEdit/AddFieldDialog.qml 1970-01-01 00:00:00 +0000 |
28 | +++ src/imports/ContactEdit/AddFieldDialog.qml 2014-06-18 14:13:24 +0000 |
29 | @@ -0,0 +1,142 @@ |
30 | +/* |
31 | + * Copyright (C) 2012-2014 Canonical, Ltd. |
32 | + * |
33 | + * This program is free software; you can redistribute it and/or modify |
34 | + * it under the terms of the GNU General Public License as published by |
35 | + * the Free Software Foundation; version 3. |
36 | + * |
37 | + * This program is distributed in the hope that it will be useful, |
38 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
39 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
40 | + * GNU General Public License for more details. |
41 | + * |
42 | + * You should have received a copy of the GNU General Public License |
43 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
44 | + */ |
45 | + |
46 | +import QtQuick 2.2 |
47 | +import Ubuntu.Components 0.1 |
48 | +import QtContacts 5.0 |
49 | +import Ubuntu.Components.Popups 0.1 as Popups |
50 | + |
51 | + |
52 | +Item { |
53 | + id: root |
54 | + |
55 | + property QtObject contact: null |
56 | + property var currentDialog: null |
57 | + readonly property var validDetails: [ ContactDetail.PhoneNumber, |
58 | + ContactDetail.Email, |
59 | + ContactDetail.Address, |
60 | + ContactDetail.OnlineAccount, |
61 | + ContactDetail.Organization |
62 | + // TODO: Not supported yet |
63 | + // ContactDetail.Birthday, |
64 | + // ContactDetail.Note, |
65 | + // ContactDetail.Url |
66 | + ] |
67 | + readonly property var singleValueDetails: [ ContactDetail.Organization ] |
68 | + signal fieldSelected(string fieldName, string qmlTypeName) |
69 | + |
70 | + function showOptions() |
71 | + { |
72 | + if (currentDialog == null) { |
73 | + // make sure the OSK disappear |
74 | + root.forceActiveFocus() |
75 | + currentDialog = PopupUtils.open(addFieldDialog, null) |
76 | + } |
77 | + } |
78 | + |
79 | + function nameFromEnum(value) |
80 | + { |
81 | + switch (value) |
82 | + { |
83 | + case ContactDetail.PhoneNumber: |
84 | + return i18n.tr("Phone") |
85 | + case ContactDetail.Email: |
86 | + return i18n.tr("Email") |
87 | + case ContactDetail.Address: |
88 | + return i18n.tr("Address") |
89 | + case ContactDetail.OnlineAccount: |
90 | + return i18n.tr("Social") |
91 | + case ContactDetail.Organization: |
92 | + return i18n.tr("Professional Details") |
93 | + default: |
94 | + console.error("Invalid contact detail enum value:" + value) |
95 | + return "" |
96 | + } |
97 | + } |
98 | + |
99 | + function qmlTypeFromEnum(value) |
100 | + { |
101 | + switch (value) |
102 | + { |
103 | + case ContactDetail.PhoneNumber: |
104 | + return "PhoneNumber" |
105 | + case ContactDetail.Email: |
106 | + return "EmailAddress" |
107 | + case ContactDetail.Address: |
108 | + return "Address" |
109 | + case ContactDetail.OnlineAccount: |
110 | + return "OnlineAccount" |
111 | + case ContactDetail.Organization: |
112 | + return "Organization" |
113 | + default: |
114 | + console.error("Invalid contact detail enum value:" + value) |
115 | + return "" |
116 | + } |
117 | + } |
118 | + |
119 | + // check which details will be allowed to create |
120 | + // some details we only support one value |
121 | + function filterSingleDetails(details, contact) |
122 | + { |
123 | + var result = [] |
124 | + for(var i=0; i < details.length; i++) { |
125 | + var det = details[i] |
126 | + if (singleValueDetails.indexOf(det) != -1) { |
127 | + if (contact.details(det).length === 0) { |
128 | + result.push(det) |
129 | + } |
130 | + } else { |
131 | + result.push(det) |
132 | + } |
133 | + } |
134 | + return result |
135 | + } |
136 | + |
137 | + visible: false |
138 | + Component { |
139 | + id: addFieldDialog |
140 | + |
141 | + Popups.Dialog { |
142 | + id: dialogue |
143 | + objectName: "addFieldDialog" |
144 | + |
145 | + title: i18n.tr("Select a field") |
146 | + Repeater { |
147 | + model: root.filterSingleDetails(validDetails, root.contact) |
148 | + Button { |
149 | + objectName: text |
150 | + |
151 | + text: root.nameFromEnum(modelData) |
152 | + onClicked: { |
153 | + root.fieldSelected(text, root.qmlTypeFromEnum(modelData)) |
154 | + PopupUtils.close(root.currentDialog) |
155 | + root.currentDialog = null |
156 | + } |
157 | + } |
158 | + } |
159 | + Button { |
160 | + objectName: "cancel" |
161 | + |
162 | + text: i18n.tr("Cancel") |
163 | + gradient: UbuntuColors.greyGradient |
164 | + onClicked: { |
165 | + PopupUtils.close(root.currentDialog) |
166 | + root.currentDialog = null |
167 | + } |
168 | + } |
169 | + } |
170 | + } |
171 | +} |
172 | |
173 | === added file 'src/imports/ContactEdit/AvatarImport.qml' |
174 | --- src/imports/ContactEdit/AvatarImport.qml 1970-01-01 00:00:00 +0000 |
175 | +++ src/imports/ContactEdit/AvatarImport.qml 2014-06-18 14:13:24 +0000 |
176 | @@ -0,0 +1,78 @@ |
177 | +/* |
178 | + * Copyright (C) 2012-2014 Canonical, Ltd. |
179 | + * |
180 | + * This program is free software; you can redistribute it and/or modify |
181 | + * it under the terms of the GNU General Public License as published by |
182 | + * the Free Software Foundation; version 3. |
183 | + * |
184 | + * This program is distributed in the hope that it will be useful, |
185 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
186 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
187 | + * GNU General Public License for more details. |
188 | + * |
189 | + * You should have received a copy of the GNU General Public License |
190 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
191 | + */ |
192 | + |
193 | +import QtQuick 2.2 |
194 | +import Ubuntu.Components 0.1 |
195 | +import Ubuntu.Components.Popups 0.1 as Popups |
196 | +import Ubuntu.Content 0.1 as ContentHub |
197 | + |
198 | +Item { |
199 | + id: root |
200 | + |
201 | + property var activeTransfer: null |
202 | + property var loadingDialog: null |
203 | + |
204 | + signal avatarReceived(string avatarUrl) |
205 | + |
206 | + function requestNewAvatar() |
207 | + { |
208 | + if (!root.loadingDialog) { |
209 | + root.loadingDialog = PopupUtils.open(loadingDialog, null) |
210 | + root.activeTransfer = defaultSource.request(); |
211 | + } |
212 | + } |
213 | + |
214 | + ContentHub.ContentPeer { |
215 | + id: defaultSource |
216 | + |
217 | + contentType: ContentHub.ContentType.Pictures |
218 | + handler: ContentHub.ContentHandler.Source |
219 | + selectionType: ContentHub.ContentTransfer.Single |
220 | + } |
221 | + |
222 | + Connections { |
223 | + target: root.activeTransfer |
224 | + onStateChanged: { |
225 | + var done = ((root.activeTransfer.state === ContentHub.ContentTransfer.Charged) || |
226 | + (root.activeTransfer.state === ContentHub.ContentTransfer.Aborted)); |
227 | + |
228 | + if (root.activeTransfer.state === ContentHub.ContentTransfer.Charged) { |
229 | + if (root.activeTransfer.items.length > 0) { |
230 | + root.avatarReceived(root.activeTransfer.items[0].url) |
231 | + } |
232 | + } |
233 | + |
234 | + if (done) { |
235 | + PopupUtils.close(root.loadingDialog) |
236 | + root.loadingDialog = null |
237 | + } |
238 | + } |
239 | + } |
240 | + |
241 | + Component { |
242 | + id: loadingDialog |
243 | + |
244 | + Popups.Dialog { |
245 | + id: dialogue |
246 | + |
247 | + title: i18n.tr("Loading") |
248 | + ActivityIndicator { |
249 | + running: true |
250 | + visible: running |
251 | + } |
252 | + } |
253 | + } |
254 | +} |
255 | |
256 | === modified file 'src/imports/ContactEdit/CMakeLists.txt' |
257 | --- src/imports/ContactEdit/CMakeLists.txt 2014-06-09 22:45:19 +0000 |
258 | +++ src/imports/ContactEdit/CMakeLists.txt 2014-06-18 14:13:24 +0000 |
259 | @@ -1,4 +1,6 @@ |
260 | set(CONTACT_EDIT_QMLS |
261 | + AvatarImport.qml |
262 | + AddFieldDialog.qml |
263 | ContactDetailAddressesEditor.qml |
264 | ContactDetailAvatarEditor.qml |
265 | ContactDetailEmailsEditor.qml |
266 | |
267 | === modified file 'src/imports/ContactEdit/ContactDetailAvatarEditor.qml' |
268 | --- src/imports/ContactEdit/ContactDetailAvatarEditor.qml 2014-05-06 13:18:07 +0000 |
269 | +++ src/imports/ContactEdit/ContactDetailAvatarEditor.qml 2014-06-18 14:13:24 +0000 |
270 | @@ -17,15 +17,13 @@ |
271 | import QtQuick 2.2 |
272 | import Ubuntu.Components 0.1 |
273 | import QtContacts 5.0 |
274 | -import Ubuntu.Content 0.1 |
275 | -import Ubuntu.Components.Popups 0.1 as Popups |
276 | |
277 | import "../Common" |
278 | |
279 | ContactDetailBase { |
280 | id: root |
281 | |
282 | - readonly property string defaultAvatar: Qt.resolvedUrl("../../artwork/contact-default-profile.png") |
283 | + readonly property string defaultAvatar: "image://theme/contact" |
284 | |
285 | function isEmpty() { |
286 | return false; |
287 | @@ -62,98 +60,51 @@ |
288 | } |
289 | |
290 | detail: contact ? contact.detail(ContactDetail.Avatar) : null |
291 | - implicitHeight: units.gu(17) |
292 | - |
293 | - Image { |
294 | - id: avatarImage |
295 | - |
296 | - anchors.fill: parent |
297 | - source: root.getAvatar(root.detail) |
298 | - asynchronous: true |
299 | - fillMode: Image.PreserveAspectCrop |
300 | - // When updating the avatar using the content picker the temporary file returned |
301 | - // can contain the same name as the previous one and if the cache is enabled this |
302 | - // will cause the image to not be updated |
303 | - cache: false |
304 | - |
305 | - Component { |
306 | - id: loadingDialog |
307 | - |
308 | - Popups.Dialog { |
309 | - id: dialogue |
310 | - |
311 | - title: i18n.tr("Loading") |
312 | - |
313 | - ActivityIndicator { |
314 | - id: activity |
315 | - |
316 | - anchors.centerIn: parent |
317 | - running: true |
318 | - visible: running |
319 | - } |
320 | - } |
321 | - } |
322 | - |
323 | - Icon { |
324 | - anchors { |
325 | - right: parent.right |
326 | - rightMargin: units.gu(1.5) |
327 | - bottom: parent.bottom |
328 | - bottomMargin: units.gu(2) |
329 | - } |
330 | - width: units.gu(3) |
331 | - height: width |
332 | - name: "import-image" |
333 | - color: "white" |
334 | - } |
335 | - |
336 | - ContentPeer { |
337 | - id: defaultSource |
338 | - contentType: ContentType.Pictures |
339 | - handler: ContentHandler.Source |
340 | - selectionType: ContentTransfer.Single |
341 | - } |
342 | - |
343 | - MouseArea { |
344 | - id: changeButton |
345 | - |
346 | - property var activeTransfer |
347 | - property var loadingDialog: null |
348 | - |
349 | - anchors.fill: parent |
350 | - onClicked: { |
351 | - // make sure the OSK disappear |
352 | - root.forceActiveFocus() |
353 | - if (!changeButton.loadingDialog) { |
354 | - changeButton.loadingDialog = PopupUtils.open(loadingDialog, null) |
355 | - changeButton.activeTransfer = defaultSource.request(); |
356 | - } |
357 | - } |
358 | - |
359 | - Connections { |
360 | - target: changeButton.activeTransfer != null ? changeButton.activeTransfer : null |
361 | - onStateChanged: { |
362 | - var done = ((changeButton.activeTransfer.state === ContentTransfer.Charged) || |
363 | - (changeButton.activeTransfer.state === ContentTransfer.Aborted)); |
364 | - |
365 | - if (changeButton.activeTransfer.state === ContentTransfer.Charged) { |
366 | - if (changeButton.activeTransfer.items.length > 0) { |
367 | - // remove the previous image, this is nessary to make sure that the new image |
368 | - // get updated otherwise if the new image has the same name the image will not |
369 | - // be updated |
370 | - avatarImage.source = "" |
371 | - // Update with the new valu |
372 | - avatarImage.source = application.copyImage(root.contact, changeButton.activeTransfer.items[0].url); |
373 | - } |
374 | - } |
375 | - |
376 | - if (done) { |
377 | - PopupUtils.close(changeButton.loadingDialog) |
378 | - changeButton.loadingDialog = null |
379 | - } |
380 | - } |
381 | - } |
382 | + implicitHeight: units.gu(8) |
383 | + implicitWidth: units.gu(8) |
384 | + |
385 | + UbuntuShape { |
386 | + id: avatar |
387 | + |
388 | + radius: "medium" |
389 | + anchors.fill: parent |
390 | + image: Image { |
391 | + id: avatarImage |
392 | + |
393 | + fillMode: Image.PreserveAspectCrop |
394 | + asynchronous: true |
395 | + source: root.getAvatar(root.detail) |
396 | + height: units.gu(8) |
397 | + width: units.gu(8) |
398 | + |
399 | + // When updating the avatar using the content picker the temporary file returned |
400 | + // can contain the same name as the previous one and if the cache is enabled this |
401 | + // will cause the image to not be updated |
402 | + cache: false |
403 | + } |
404 | + } |
405 | + |
406 | + AvatarImport { |
407 | + id: avatarImport |
408 | + |
409 | + onAvatarReceived: { |
410 | + // remove the previous image, this is nessary to make sure that the new image |
411 | + // get updated otherwise if the new image has the same name the image will not |
412 | + // be updated |
413 | + avatarImage.source = "" |
414 | + // Update with the new value |
415 | + avatarImage.source = application.copyImage(root.contact, avatarUrl); |
416 | + } |
417 | + } |
418 | + |
419 | + MouseArea { |
420 | + anchors.fill: parent |
421 | + onClicked: { |
422 | + // make sure the OSK disappear |
423 | + root.forceActiveFocus() |
424 | + avatarImport.requestNewAvatar() |
425 | } |
426 | } |
427 | } |
428 | |
429 | + |
430 | |
431 | === modified file 'src/imports/ContactEdit/ContactDetailGroupWithTypeEditor.qml' |
432 | --- src/imports/ContactEdit/ContactDetailGroupWithTypeEditor.qml 2014-05-22 06:56:03 +0000 |
433 | +++ src/imports/ContactEdit/ContactDetailGroupWithTypeEditor.qml 2014-06-18 14:13:24 +0000 |
434 | @@ -95,7 +95,7 @@ |
435 | |
436 | return changed |
437 | } |
438 | - minimumHeight: units.gu(5) |
439 | + |
440 | headerDelegate: ListItem.Empty { |
441 | id: header |
442 | highlightWhenPressed: false |
443 | @@ -104,6 +104,9 @@ |
444 | height: units.gu(5) |
445 | // disable listview mouse area |
446 | __mouseArea.visible: false |
447 | + divider.anchors.leftMargin: units.gu(2) |
448 | + divider.anchors.rightMargin: units.gu(2) |
449 | + |
450 | Label { |
451 | anchors { |
452 | verticalCenter: parent.verticalCenter |
453 | @@ -117,35 +120,6 @@ |
454 | // style |
455 | fontSize: "medium" |
456 | } |
457 | - |
458 | - Icon { |
459 | - objectName: "newDetailButton" |
460 | - |
461 | - anchors { |
462 | - verticalCenter: parent.verticalCenter |
463 | - right: parent.right |
464 | - rightMargin: units.gu(2) |
465 | - } |
466 | - width: units.gu(2) |
467 | - height: units.gu(2) |
468 | - name: "add" |
469 | - } |
470 | - |
471 | - // Mouse area fill all title area to avoid problems with swipe from the right gesture |
472 | - MouseArea { |
473 | - anchors.fill: parent |
474 | - onClicked: { |
475 | - if (detailQmlTypeName) { |
476 | - var newDetail = Qt.createQmlObject("import QtContacts 5.0; " + detailQmlTypeName + "{}", root) |
477 | - if (newDetail) { |
478 | - var newDetailsCopy = root.newDetails |
479 | - newDetailsCopy.push(newDetail) |
480 | - root.newDetails = newDetailsCopy |
481 | - root.contact.addDetail(newDetail) |
482 | - } |
483 | - } |
484 | - } |
485 | - } |
486 | } |
487 | |
488 | detailDelegate: ContactDetailWithTypeEditor { |
489 | |
490 | === modified file 'src/imports/ContactEdit/ContactDetailNameEditor.qml' |
491 | --- src/imports/ContactEdit/ContactDetailNameEditor.qml 2014-05-09 20:00:09 +0000 |
492 | +++ src/imports/ContactEdit/ContactDetailNameEditor.qml 2014-06-18 14:13:24 +0000 |
493 | @@ -51,6 +51,7 @@ |
494 | return changed |
495 | } |
496 | |
497 | + spacing: units.gu(1) |
498 | detail: root.contact ? root.contact.name : null |
499 | fields: [ QtContacts.Name.FirstName, QtContacts.Name.LastName ] |
500 | |
501 | |
502 | === modified file 'src/imports/ContactEdit/ContactDetailSyncTargetEditor.qml' |
503 | --- src/imports/ContactEdit/ContactDetailSyncTargetEditor.qml 2014-05-28 15:22:38 +0000 |
504 | +++ src/imports/ContactEdit/ContactDetailSyncTargetEditor.qml 2014-06-18 14:13:24 +0000 |
505 | @@ -84,6 +84,12 @@ |
506 | height: units.gu(4) |
507 | } |
508 | |
509 | + ListItem.ThinDivider { |
510 | + id: divider |
511 | + |
512 | + anchors.top: label.bottom |
513 | + } |
514 | + |
515 | OptionSelector { |
516 | id: sources |
517 | |
518 | @@ -91,8 +97,8 @@ |
519 | anchors { |
520 | left: parent.left |
521 | leftMargin: units.gu(2) |
522 | - top: label.bottom |
523 | - topMargin: units.gu(1) |
524 | + top: divider.bottom |
525 | + topMargin: units.gu(2) |
526 | right: parent.right |
527 | rightMargin: units.gu(2) |
528 | bottom: parent.bottom |
529 | |
530 | === modified file 'src/imports/ContactEdit/ContactDetailWithTypeEditor.qml' |
531 | --- src/imports/ContactEdit/ContactDetailWithTypeEditor.qml 2014-05-16 01:59:36 +0000 |
532 | +++ src/imports/ContactEdit/ContactDetailWithTypeEditor.qml 2014-06-18 14:13:24 +0000 |
533 | @@ -73,41 +73,19 @@ |
534 | enabled: root.detail ? !root.detail.readOnly : false |
535 | implicitHeight: detailTypeSelector.height + fieldValues.height + units.gu(2) |
536 | opacity: enabled ? 1.0 : 0.5 |
537 | - ValueSelector { |
538 | - id: detailTypeSelector |
539 | - objectName: detail ? "type_" + detailToString(detail.type, -1) + "_" + index : "" |
540 | - |
541 | - readOnly: root.detail ? root.detail.readOnly : false |
542 | - visible: (currentIndex != -1) |
543 | - active: root.active |
544 | + |
545 | + Column { |
546 | + id: fieldValues |
547 | + |
548 | anchors { |
549 | left: parent.left |
550 | - leftMargin: units.gu(3) |
551 | + leftMargin: units.gu(2) |
552 | right: parent.right |
553 | rightMargin: units.gu(2) |
554 | top: parent.top |
555 | topMargin: units.gu(1) |
556 | } |
557 | - |
558 | - height: visible ? (root.active ? units.gu(4) : units.gu(3)) : 0 |
559 | - onExpandedChanged: { |
560 | - // Make sure that the inputfield get focus when clicking on type selector |
561 | - if (expanded) { |
562 | - root.forceActiveFocus() |
563 | - } |
564 | - } |
565 | - } |
566 | - |
567 | - Column { |
568 | - id: fieldValues |
569 | - |
570 | - anchors { |
571 | - left: detailTypeSelector.left |
572 | - right: detailTypeSelector.right |
573 | - top: detailTypeSelector.bottom |
574 | - } |
575 | height: childrenRect.height |
576 | - |
577 | Repeater { |
578 | id: fieldRepeater |
579 | |
580 | @@ -141,4 +119,26 @@ |
581 | } |
582 | } |
583 | } |
584 | + |
585 | + ValueSelector { |
586 | + id: detailTypeSelector |
587 | + objectName: detail ? "type_" + detailToString(detail.type, -1) + "_" + index : "" |
588 | + |
589 | + anchors { |
590 | + left: fieldValues.left |
591 | + right: fieldValues.right |
592 | + top: fieldValues.bottom |
593 | + } |
594 | + |
595 | + readOnly: root.detail ? root.detail.readOnly : false |
596 | + visible: (currentIndex != -1) |
597 | + active: root.active |
598 | + height: visible ? (root.active ? units.gu(4) : units.gu(3)) : 0 |
599 | + onExpandedChanged: { |
600 | + // Make sure that the inputfield get focus when clicking on type selector |
601 | + if (expanded) { |
602 | + root.forceActiveFocus() |
603 | + } |
604 | + } |
605 | + } |
606 | } |
607 | |
608 | === modified file 'src/imports/ContactEdit/ContactEditor.qml' |
609 | --- src/imports/ContactEdit/ContactEditor.qml 2014-06-16 12:59:15 +0000 |
610 | +++ src/imports/ContactEdit/ContactEditor.qml 2014-06-18 14:13:24 +0000 |
611 | @@ -161,7 +161,7 @@ |
612 | fill: parent |
613 | bottomMargin: keyboard.height |
614 | } |
615 | - contentHeight: contents.height |
616 | + contentHeight: contents.height + units.gu(2) |
617 | contentWidth: parent.width |
618 | |
619 | //after add a new field we need to wait for the contentHeight to change to scroll to the correct position |
620 | @@ -172,32 +172,48 @@ |
621 | |
622 | anchors { |
623 | top: parent.top |
624 | + topMargin: units.gu(2) |
625 | left: parent.left |
626 | right: parent.right |
627 | } |
628 | height: childrenRect.height |
629 | |
630 | - ContactDetailNameEditor { |
631 | - id: nameEditor |
632 | - |
633 | - |
634 | - anchors { |
635 | - left: parent.left |
636 | - right: parent.right |
637 | - } |
638 | - height: nameEditor.implicitHeight + units.gu(3) |
639 | - contact: contactEditor.contact |
640 | - } |
641 | - |
642 | - ContactDetailAvatarEditor { |
643 | - id: avatarEditor |
644 | - |
645 | - contact: contactEditor.contact |
646 | - anchors { |
647 | - left: parent.left |
648 | - right: parent.right |
649 | - } |
650 | - height: implicitHeight |
651 | + Row { |
652 | + function save() |
653 | + { |
654 | + var avatarSave = avatarEditor.save() |
655 | + var nameSave = nameEditor.save(); |
656 | + |
657 | + return (nameSave || avatarSave); |
658 | + } |
659 | + |
660 | + function isEmpty() |
661 | + { |
662 | + return (avatarEditor.isEmpty() && nameEditor.isEmpty()) |
663 | + } |
664 | + |
665 | + anchors { |
666 | + left: parent.left |
667 | + leftMargin: units.gu(2) |
668 | + right: parent.right |
669 | + } |
670 | + height: Math.max(avatarEditor.height, nameEditor.height) - units.gu(4) |
671 | + |
672 | + ContactDetailAvatarEditor { |
673 | + id: avatarEditor |
674 | + |
675 | + contact: contactEditor.contact |
676 | + height: implicitHeight |
677 | + width: implicitWidth |
678 | + } |
679 | + |
680 | + ContactDetailNameEditor { |
681 | + id: nameEditor |
682 | + |
683 | + width: parent.width - avatarEditor.width |
684 | + height: nameEditor.implicitHeight + units.gu(3) |
685 | + contact: contactEditor.contact |
686 | + } |
687 | } |
688 | |
689 | ContactDetailPhoneNumbersEditor { |
690 | @@ -272,13 +288,48 @@ |
691 | height: implicitHeight |
692 | } |
693 | |
694 | - // We need this extra element to correct align the deleteButton |
695 | + ListItem.ThinDivider {} |
696 | + |
697 | Item { |
698 | anchors { |
699 | left: parent.left |
700 | right: parent.right |
701 | } |
702 | - height: deleteButton.height + units.gu(2) |
703 | + height: units.gu(2) |
704 | + } |
705 | + |
706 | + Row { |
707 | + anchors { |
708 | + left: parent.left |
709 | + right: parent.right |
710 | + margins: units.gu(2) |
711 | + } |
712 | + height: units.gu(6) |
713 | + spacing: units.gu(2) |
714 | + |
715 | + // WORKAROUND: SDK uses a old version of qtquick components |
716 | + activeFocusOnTab: true |
717 | + onActiveFocusChanged: { |
718 | + if (activeFocus) { |
719 | + addNewFieldButton.forceActiveFocus() |
720 | + } |
721 | + } |
722 | + |
723 | + Button { |
724 | + id: addNewFieldButton |
725 | + objectName: "addNewFieldButton" |
726 | + |
727 | + text: i18n.tr("Add Field") |
728 | + gradient: UbuntuColors.greyGradient |
729 | + anchors { |
730 | + top: parent.top |
731 | + bottom: parent.bottom |
732 | + bottomMargin: units.gu(2) |
733 | + } |
734 | + width: (parent.width / 2) - units.gu(1) |
735 | + |
736 | + onClicked: addFieldDialog.showOptions() |
737 | + } |
738 | |
739 | Button { |
740 | id: deleteButton |
741 | @@ -286,12 +337,11 @@ |
742 | text: i18n.tr("Delete") |
743 | visible: !contactEditor.isNewContact |
744 | anchors { |
745 | - margins: units.gu(2) |
746 | top: parent.top |
747 | - left: parent.left |
748 | - right: parent.right |
749 | + bottom: parent.bottom |
750 | + bottomMargin: units.gu(2) |
751 | } |
752 | - |
753 | + width: (parent.width / 2) - units.gu(1) |
754 | onClicked: { |
755 | var dialog = Popups.PopupUtils.open(removeContactDialog, null) |
756 | dialog.contacts = [contactEditor.contact] |
757 | @@ -351,6 +401,23 @@ |
758 | } |
759 | } |
760 | |
761 | + AddFieldDialog { |
762 | + id: addFieldDialog |
763 | + |
764 | + contact: contactEditor.contact |
765 | + onFieldSelected: { |
766 | + if (qmlTypeName) { |
767 | + var newDetail = Qt.createQmlObject("import QtContacts 5.0; " + qmlTypeName + "{}", addFieldDialog) |
768 | + if (newDetail) { |
769 | + var newDetailsCopy = contactEditor.newDetails |
770 | + newDetailsCopy.push(newDetail) |
771 | + contactEditor.newDetails = newDetailsCopy |
772 | + contactEditor.contact.addDetail(newDetail) |
773 | + } |
774 | + } |
775 | + } |
776 | + } |
777 | + |
778 | Component { |
779 | id: removeContactDialog |
780 | |
781 | |
782 | === modified file 'src/imports/ContactEdit/TextInputDetail.qml' |
783 | --- src/imports/ContactEdit/TextInputDetail.qml 2014-05-28 15:19:53 +0000 |
784 | +++ src/imports/ContactEdit/TextInputDetail.qml 2014-06-18 14:13:24 +0000 |
785 | @@ -80,6 +80,7 @@ |
786 | overlaySpacing: 0 |
787 | frameSpacing: 0 |
788 | background: Item {} |
789 | + color: UbuntuColors.lightAubergine |
790 | } |
791 | onActiveFocusChanged: { |
792 | if (activeFocus) { |
793 | |
794 | === modified file 'src/imports/ContactEdit/ValueSelector.qml' |
795 | --- src/imports/ContactEdit/ValueSelector.qml 2014-06-06 17:52:58 +0000 |
796 | +++ src/imports/ContactEdit/ValueSelector.qml 2014-06-18 14:13:24 +0000 |
797 | @@ -59,22 +59,12 @@ |
798 | |
799 | // FIXME: workaround to close list after a while. |
800 | // we cant rely on focus since it hides the keyboard. |
801 | - MouseArea { |
802 | - anchors.fill: parent |
803 | - visible: expanded |
804 | - onPressed: { |
805 | - mouse.accepted = false |
806 | - timer.restart() |
807 | - } |
808 | - propagateComposedEvents: true |
809 | - z: 1 |
810 | - } |
811 | - |
812 | Timer { |
813 | id: timer |
814 | + |
815 | interval: 5000 |
816 | + running: false |
817 | onTriggered: state = "" |
818 | - running: false |
819 | } |
820 | |
821 | Item { |
822 | @@ -119,8 +109,12 @@ |
823 | |
824 | MouseArea { |
825 | anchors.fill: parent |
826 | - propagateComposedEvents: true |
827 | - onClicked: if (!readOnly) root.state = "expanded" |
828 | + onClicked: { |
829 | + if (!readOnly) { |
830 | + root.state = "expanded" |
831 | + timer.restart() |
832 | + } |
833 | + } |
834 | } |
835 | |
836 | ListView { |
837 | @@ -160,7 +154,10 @@ |
838 | width: parent.width + units.gu(0.5) |
839 | height: parent.height + units.gu(0.5) |
840 | anchors.centerIn: parent |
841 | - onClicked: currentIndex = index |
842 | + onClicked: { |
843 | + currentIndex = index |
844 | + timer.restart() |
845 | + } |
846 | } |
847 | } |
848 | |
849 | |
850 | === modified file 'src/imports/ContactList/ContactListPage.qml' |
851 | --- src/imports/ContactList/ContactListPage.qml 2014-06-16 12:59:54 +0000 |
852 | +++ src/imports/ContactList/ContactListPage.qml 2014-06-18 14:13:24 +0000 |
853 | @@ -43,10 +43,7 @@ |
854 | function createEmptyContact(phoneNumber) { |
855 | var details = [ {detail: "PhoneNumber", field: "number", value: phoneNumber}, |
856 | {detail: "EmailAddress", field: "emailAddress", value: ""}, |
857 | - {detail: "OnlineAccount", field: "accountUri", value: ""}, |
858 | - {detail: "Address", field: "street", value: ""}, |
859 | - {detail: "Name", field: "firstName", value: ""}, |
860 | - {detail: "Organization", field: "name", value: ""} |
861 | + {detail: "Name", field: "firstName", value: ""} |
862 | ] |
863 | |
864 | var newContact = Qt.createQmlObject("import QtContacts 5.0; Contact{ }", mainPage) |
865 | |
866 | === modified file 'src/imports/ContactView/BasicFieldView.qml' |
867 | --- src/imports/ContactView/BasicFieldView.qml 2014-06-12 18:54:18 +0000 |
868 | +++ src/imports/ContactView/BasicFieldView.qml 2014-06-18 14:13:24 +0000 |
869 | @@ -50,8 +50,8 @@ |
870 | objectName: detail && fields ? "label_" + detailToString(detail.type, fields[index]) + "_" + root.parentIndex + "." + index : "" |
871 | |
872 | anchors { |
873 | - left: parent ? parent.left : null |
874 | - right: parent ? parent.right : null |
875 | + left: parent ? parent.left : undefined |
876 | + right: parent ? parent.right : undefined |
877 | } |
878 | height: root.lineHeight |
879 | verticalAlignment: Text.AlignVCenter |
880 | |
881 | === modified file 'src/imports/ContactView/ContactDetailAvatarView.qml' |
882 | --- src/imports/ContactView/ContactDetailAvatarView.qml 2014-06-12 18:53:50 +0000 |
883 | +++ src/imports/ContactView/ContactDetailAvatarView.qml 2014-06-18 14:13:24 +0000 |
884 | @@ -24,9 +24,14 @@ |
885 | ContactDetailBase { |
886 | id: root |
887 | |
888 | - implicitHeight: units.gu(10) |
889 | + implicitHeight: units.gu(8) |
890 | implicitWidth: units.gu(10) |
891 | |
892 | + Connections { |
893 | + target: root.contact.avatar |
894 | + onDetailChanged: avatar.reload() |
895 | + } |
896 | + |
897 | ContactsUI.ContactAvatar { |
898 | id: avatar |
899 | |
900 | @@ -34,7 +39,6 @@ |
901 | anchors { |
902 | fill: parent |
903 | leftMargin: units.gu(2) |
904 | - topMargin: units.gu(2) |
905 | } |
906 | } |
907 | } |
908 | |
909 | === modified file 'src/imports/ContactView/ContactDetailGroupWithTypeView.qml' |
910 | --- src/imports/ContactView/ContactDetailGroupWithTypeView.qml 2014-06-12 18:54:18 +0000 |
911 | +++ src/imports/ContactView/ContactDetailGroupWithTypeView.qml 2014-06-18 14:13:24 +0000 |
912 | @@ -31,6 +31,8 @@ |
913 | headerDelegate: ListItem.Empty { |
914 | highlightWhenPressed: false |
915 | |
916 | + divider.anchors.leftMargin: units.gu(2) |
917 | + divider.anchors.rightMargin: units.gu(2) |
918 | width: root.width |
919 | height: units.gu(5) |
920 | Label { |
921 | |
922 | === modified file 'src/imports/ContactView/ContactView.qml' |
923 | --- src/imports/ContactView/ContactView.qml 2014-06-13 15:05:40 +0000 |
924 | +++ src/imports/ContactView/ContactView.qml 2014-06-18 14:13:24 +0000 |
925 | @@ -67,7 +67,7 @@ |
926 | anchors.fill: parent |
927 | //WORKAROUND: There is a bug on SDK page that causes the page to appear flicked with small contents |
928 | // see bug #1223050 |
929 | - contentHeight: Math.max(contents.height, parent.height) |
930 | + contentHeight: Math.max(contents.height, parent.height) + units.gu(2) |
931 | contentWidth: parent.width |
932 | visible: !busyIndicator.visible |
933 | |
934 | @@ -77,6 +77,7 @@ |
935 | height: childrenRect.height |
936 | anchors { |
937 | top: parent.top |
938 | + topMargin: units.gu(2) |
939 | left: parent.left |
940 | right: parent.right |
941 | } |
942 | |
943 | === modified file 'src/imports/Ubuntu/Contacts/ContactAvatar.qml' |
944 | --- src/imports/Ubuntu/Contacts/ContactAvatar.qml 2014-06-06 17:52:58 +0000 |
945 | +++ src/imports/Ubuntu/Contacts/ContactAvatar.qml 2014-06-18 14:13:24 +0000 |
946 | @@ -24,7 +24,12 @@ |
947 | |
948 | property var contactElement: null |
949 | property string displayName: ContactsJS.formatToDisplay(contactElement, ContactDetail.Name, [Name.FirstName, Name.LastName]) |
950 | - readonly property string avatarUrl: ContactsJS.getAvatar(contactElement, "") |
951 | + property string avatarUrl: ContactsJS.getAvatar(contactElement, "") |
952 | + |
953 | + function reload() |
954 | + { |
955 | + avatarUrl = ContactsJS.getAvatar(contactElement, "") |
956 | + } |
957 | |
958 | radius: "medium" |
959 | color: Theme.palette.normal.overlay |
960 | @@ -34,13 +39,16 @@ |
961 | text: ContactsJS.getNameItials(displayName) |
962 | font.pointSize: 88 |
963 | color: UbuntuColors.lightAubergine |
964 | - visible: avatarUrl === "" |
965 | + visible: (img.status != Image.Ready) |
966 | } |
967 | |
968 | image: Image { |
969 | + id: img |
970 | + |
971 | fillMode: Image.PreserveAspectCrop |
972 | asynchronous: true |
973 | source: avatarUrl |
974 | - visible: source !== "" |
975 | + height: avatar.height |
976 | + width: avatar.width |
977 | } |
978 | } |
979 | |
980 | === modified file 'src/imports/Ubuntu/Contacts/MultipleSelectionListView.qml' |
981 | --- src/imports/Ubuntu/Contacts/MultipleSelectionListView.qml 2014-06-06 17:52:58 +0000 |
982 | +++ src/imports/Ubuntu/Contacts/MultipleSelectionListView.qml 2014-06-18 14:13:24 +0000 |
983 | @@ -55,7 +55,7 @@ |
984 | \endqml |
985 | */ |
986 | |
987 | -UbuntuListView { |
988 | +ListView { |
989 | id: listView |
990 | |
991 | /*! |
992 | @@ -188,4 +188,12 @@ |
993 | MultipleSelectionVisualModel { |
994 | id: visualModel |
995 | } |
996 | + |
997 | + Component.onCompleted: { |
998 | + // FIXME: workaround for qtubuntu not returning values depending on the grid unit definition |
999 | + // for Flickable.maximumFlickVelocity and Flickable.flickDeceleration |
1000 | + var scaleFactor = units.gridUnit / 8; |
1001 | + maximumFlickVelocity = maximumFlickVelocity * scaleFactor; |
1002 | + flickDeceleration = flickDeceleration * scaleFactor; |
1003 | + } |
1004 | } |
1005 | |
1006 | === modified file 'tests/autopilot/address_book_app/pages/_contact_editor.py' |
1007 | --- tests/autopilot/address_book_app/pages/_contact_editor.py 2014-05-22 12:50:28 +0000 |
1008 | +++ tests/autopilot/address_book_app/pages/_contact_editor.py 2014-06-18 14:13:24 +0000 |
1009 | @@ -51,6 +51,36 @@ |
1010 | class ContactEditor(_common.PageWithHeader): |
1011 | """Custom proxy object for the Contact Editor.""" |
1012 | |
1013 | + _DETAIL_ALIAS = { |
1014 | + 'phones': 'Phone', |
1015 | + 'emails': 'Email', |
1016 | + 'ims': 'Social', |
1017 | + 'addresses': 'Address', |
1018 | + 'professionalDetails': 'Professional Details' |
1019 | + } |
1020 | + |
1021 | + @autopilot.logging.log_action(logger.info) |
1022 | + def add_field(self, detail_name): |
1023 | + """Create a new field into the edit contact form. |
1024 | + |
1025 | + :param detail_name: The detail field name |
1026 | + |
1027 | + """ |
1028 | + |
1029 | + add_field_button = self.select_single( |
1030 | + 'Button', objectName='addNewFieldButton') |
1031 | + add_field_button.swipe_into_view() |
1032 | + |
1033 | + self.pointing_device.click_object(add_field_button) |
1034 | + |
1035 | + add_field_dialog = self.get_root_instance().wait_select_single( |
1036 | + 'Dialog', objectName='addFieldDialog') |
1037 | + new_field_button = add_field_dialog.select_single( |
1038 | + 'Button', |
1039 | + objectName=self._DETAIL_ALIAS[detail_name]) |
1040 | + |
1041 | + self.pointing_device.click_object(new_field_button) |
1042 | + |
1043 | @autopilot.logging.log_action(logger.info) |
1044 | def fill_form(self, contact_information): |
1045 | """Fill the edit contact form. |
1046 | @@ -90,7 +120,7 @@ |
1047 | def _fill_detail_group(self, object_name, details): |
1048 | editor = self.select_single( |
1049 | ContactDetailGroupWithTypeEditor, objectName=object_name) |
1050 | - editor.fill(details) |
1051 | + editor.fill(self, details) |
1052 | |
1053 | def _get_form_values(self): |
1054 | first_name = _get_text_field(self, 'first_name').text |
1055 | @@ -135,12 +165,12 @@ |
1056 | 'professionalDetails': 'base_unknown_{}' |
1057 | } |
1058 | |
1059 | - def fill(self, details): |
1060 | + def fill(self, editor, details): |
1061 | """Fill a contact detail group.""" |
1062 | - for index, detail in enumerate(details[:-1]): |
1063 | + for index, detail in enumerate(details): |
1064 | + if self.detailsCount <= index: |
1065 | + editor.add_field(self.objectName) |
1066 | self._fill_detail(index, detail) |
1067 | - self._add_detail() |
1068 | - self._fill_detail(len(details) - 1, details[-1]) |
1069 | |
1070 | def _fill_detail(self, index, detail): |
1071 | detail_editor = self._get_detail_editor_by_index(index) |
1072 | @@ -175,15 +205,16 @@ |
1073 | """Custom proxy object for the ContactDetailWithTypeEditor widget.""" |
1074 | |
1075 | def fill(self, field, index, detail): |
1076 | + self._fill_value(field, index, detail) |
1077 | self._select_type(detail) |
1078 | - self._fill_value(field, index, detail) |
1079 | |
1080 | def _select_type(self, detail): |
1081 | type_index = detail.TYPES.index(detail.type) |
1082 | - selected_type_index = self._get_selected_type_index() |
1083 | - if type_index != selected_type_index: |
1084 | - # TODO --elopio - 2014-03-01 |
1085 | - raise NotImplementedError('Type selection not yet implemented.') |
1086 | + value_selector = self.select_single('ValueSelector') |
1087 | + |
1088 | + while(value_selector.currentIndex != type_index): |
1089 | + ubuntuuitoolkit.get_keyboard().press_and_release("Shift+Right") |
1090 | + time.sleep(0.1) |
1091 | |
1092 | def _get_selected_type_index(self): |
1093 | value_selector = self.select_single('ValueSelector') |
1094 | @@ -210,16 +241,7 @@ |
1095 | self._make_field_visible_and_write(text_field, value) |
1096 | |
1097 | def _make_field_visible_and_write(self, text_field, value): |
1098 | - while not text_field.activeFocus: |
1099 | - # XXX We should just swipe the text field into view. |
1100 | - # Update this once bug http://pad.lv/1286479 is implemented. |
1101 | - # --elopio - 2014-03-01 |
1102 | - text_field.keyboard.press_and_release('Tab') |
1103 | - time.sleep(0.1) |
1104 | - contact_editor = self.get_root_instance().select_single( |
1105 | - ContactEditor, objectName='contactEditorPage', active=True) |
1106 | - contact_editor.wait_to_stop_moving() |
1107 | - |
1108 | + text_field.swipe_into_view() |
1109 | text_field.write(value) |
1110 | |
1111 | def _fill_address(self, index, address): |
1112 | |
1113 | === modified file 'tests/autopilot/address_book_app/tests/__init__.py' |
1114 | --- tests/autopilot/address_book_app/tests/__init__.py 2014-06-13 00:23:37 +0000 |
1115 | +++ tests/autopilot/address_book_app/tests/__init__.py 2014-06-18 14:13:24 +0000 |
1116 | @@ -143,6 +143,7 @@ |
1117 | self.pointing_device.click_object(clear_button) |
1118 | self.assertThat(field.text, Eventually(Equals(""))) |
1119 | |
1120 | + # FIXME: Remove this function use ContactEditor.add_field |
1121 | def create_new_detail(self, detailGroup): |
1122 | detCount = detailGroup.detailsCount |
1123 | add_button = detailGroup.select_single("Icon", |
1124 | @@ -155,9 +156,7 @@ |
1125 | list_page = self.main_window.get_contact_list_page() |
1126 | list_page.open_contact(index) |
1127 | |
1128 | - list_page = self.main_window.get_contact_list_page() |
1129 | self.assertThat(list_page.visible, Eventually(Equals(False))) |
1130 | - |
1131 | view_page = self.main_window.get_contact_view_page() |
1132 | self.assertThat(view_page.visible, Eventually(Equals(True))) |
1133 | |
1134 | |
1135 | === modified file 'tests/autopilot/address_book_app/tests/test_add_contact.py' |
1136 | --- tests/autopilot/address_book_app/tests/test_add_contact.py 2014-06-08 13:51:45 +0000 |
1137 | +++ tests/autopilot/address_book_app/tests/test_add_contact.py 2014-06-18 14:13:24 +0000 |
1138 | @@ -173,28 +173,23 @@ |
1139 | self.assertThat(list_view.count, Eventually(Equals(1))) |
1140 | |
1141 | def test_email_label_save(self): |
1142 | - # execute add new contact |
1143 | contact_editor = self.app.main_window.go_to_add_contact() |
1144 | |
1145 | - # fill name |
1146 | - contact_editor.fill_form( |
1147 | - data.Contact(first_name='Sherlock', last_name='Holmes')) |
1148 | + my_emails = [] |
1149 | + my_emails.append(data.Email(type_="Home", address="home@email.com")) |
1150 | + my_emails.append(data.Email(type_="Work", address="work@email.com")) |
1151 | + my_emails.append(data.Email(type_="Other", address="other@email.com")) |
1152 | |
1153 | - # Home |
1154 | - self.set_email_address(0, "home@email.com", 0) |
1155 | - # Work |
1156 | - self.set_email_address(1, "work@email.com", 1) |
1157 | - # Other |
1158 | - self.set_email_address(2, "other@email.com", 2) |
1159 | + test_contact = data.Contact(first_name="Sherlock", |
1160 | + last_name="Holmes", |
1161 | + emails=my_emails) |
1162 | + contact_editor.fill_form(test_contact) |
1163 | |
1164 | # Save contact |
1165 | self.app.main_window.save() |
1166 | |
1167 | list_page = self.app.main_window.get_contact_list_page() |
1168 | - list_page.open_contact(0) |
1169 | - |
1170 | - # check if contacts was saved with the correct labels |
1171 | - view_page = self.app.main_window.get_contact_view_page() |
1172 | + view_page = list_page.open_contact(0) |
1173 | self.assertThat(view_page.visible, Eventually(Equals(True))) |
1174 | |
1175 | # check if we have 3 emails""" |
1176 | @@ -223,33 +218,26 @@ |
1177 | self.assertThat(len(emails), Equals(0)) |
1178 | |
1179 | def test_phone_label_save(self): |
1180 | - # execute add new contact |
1181 | contact_editor = self.app.main_window.go_to_add_contact() |
1182 | |
1183 | - # fill name |
1184 | - contact_editor.fill_form( |
1185 | - data.Contact(first_name='Sherlock', last_name='Holmes')) |
1186 | + my_phones = [] |
1187 | + my_phones.append(data.Phone(type_="Home", number="(000) 000-0000")) |
1188 | + my_phones.append(data.Phone(type_="Work", number="(000) 000-0001")) |
1189 | + my_phones.append(data.Phone(type_="Mobile", number="(000) 000-0002")) |
1190 | + my_phones.append(data.Phone(type_="Work Mobile", number="(000) 000-0003")) |
1191 | + my_phones.append(data.Phone(type_="Other", number="(000) 000-0004")) |
1192 | |
1193 | - # Home |
1194 | - self.set_phone_number(0, "(000) 000-0000", 0) |
1195 | - # Work |
1196 | - self.set_phone_number(1, "(000) 000-0001", 1) |
1197 | - # Mobile |
1198 | - self.set_phone_number(2, "(000) 000-0002", 2) |
1199 | - # Work Mobile |
1200 | - self.set_phone_number(3, "(000) 000-0003", 3) |
1201 | - # Other |
1202 | - self.set_phone_number(4, "(000) 000-0004", 4) |
1203 | + test_contact = data.Contact(first_name="Sherlock", |
1204 | + last_name="Holmes", |
1205 | + phones=my_phones) |
1206 | + contact_editor.fill_form(test_contact) |
1207 | |
1208 | # Save contact |
1209 | self.app.main_window.save() |
1210 | |
1211 | # Open contact view |
1212 | list_page = self.app.main_window.get_contact_list_page() |
1213 | - list_page.open_contact(0) |
1214 | - |
1215 | - # check if contacts was saved with the correct labels |
1216 | - view_page = self.app.main_window.get_contact_view_page() |
1217 | + view_page = list_page.open_contact(0) |
1218 | self.assertThat(view_page.visible, Eventually(Equals(True))) |
1219 | |
1220 | # check if we have five phones""" |
1221 | |
1222 | === modified file 'tests/autopilot/address_book_app/tests/test_edit_contact.py' |
1223 | --- tests/autopilot/address_book_app/tests/test_edit_contact.py 2014-05-30 07:11:42 +0000 |
1224 | +++ tests/autopilot/address_book_app/tests/test_edit_contact.py 2014-06-18 14:13:24 +0000 |
1225 | @@ -37,10 +37,7 @@ |
1226 | edit_page = self.edit_contact(0) |
1227 | |
1228 | # Add a new phone |
1229 | - phoneGroup = edit_page.select_single( |
1230 | - "ContactDetailGroupWithTypeEditor", |
1231 | - objectName="phones") |
1232 | - self.create_new_detail(phoneGroup) |
1233 | + edit_page.add_field('phones') |
1234 | |
1235 | # fill phone number |
1236 | phone_number_1 = self.app.main_window.select_single( |
1237 | @@ -67,11 +64,18 @@ |
1238 | self.assertThat(phone_label_1.text, Eventually(Equals(self.PHONE_NUMBERS[1]))) |
1239 | |
1240 | def test_remove_phone(self): |
1241 | - self.add_contact("Fulano", "de Tal", self.PHONE_NUMBERS[1:3]) |
1242 | - edit_page = self.edit_contact(0) |
1243 | + contact_editor = self.app.main_window.go_to_add_contact() |
1244 | + my_phones = [] |
1245 | + for n in self.PHONE_NUMBERS[1:3]: |
1246 | + my_phones.append(data.Phone(type_='Mobile', number=n)) |
1247 | + |
1248 | + test_contact = data.Contact(first_name="Fulano", |
1249 | + last_name="de Tal", |
1250 | + phones=my_phones) |
1251 | + contact_editor.fill_form(test_contact) |
1252 | |
1253 | # clear phone 1 |
1254 | - phone_number_1 = edit_page.select_single( |
1255 | + phone_number_1 = contact_editor.wait_select_single( |
1256 | "TextInputDetail", |
1257 | objectName="phoneNumber_1") |
1258 | self.clear_text_on_field(phone_number_1) |
1259 | @@ -79,8 +83,11 @@ |
1260 | # Save contact |
1261 | self.app.main_window.save() |
1262 | |
1263 | + # Go to contact view |
1264 | + list_page = self.main_window.get_contact_list_page() |
1265 | + |
1266 | # check if we have onlye one phone |
1267 | - view_page = self.app.main_window.get_contact_view_page() |
1268 | + view_page = list_page.open_contact(0) |
1269 | phone_group = view_page.select_single( |
1270 | "ContactDetailGroupWithTypeView", |
1271 | objectName="phones") |
1272 | @@ -95,11 +102,7 @@ |
1273 | def test_add_email(self): |
1274 | self.add_contact("Fulano", "") |
1275 | edit_page = self.edit_contact(0) |
1276 | - |
1277 | - emailGroup = edit_page.select_single( |
1278 | - "ContactDetailGroupWithTypeEditor", |
1279 | - objectName="emails") |
1280 | - self.create_new_detail(emailGroup) |
1281 | + edit_page.add_field("emails") |
1282 | |
1283 | # fill email address |
1284 | email_field = edit_page.select_single( |
1285 | @@ -174,7 +177,17 @@ |
1286 | self.assertThat(view_page.title, Eventually(Equals("Fulano de Tal"))) |
1287 | |
1288 | def test_im_type(self): |
1289 | - self.add_contact("Fulano", "de Tal", im_address=["im@account.com"]) |
1290 | + contact_editor = self.app.main_window.go_to_add_contact() |
1291 | + alias = data.SocialAlias(type_="Skype", alias="im@account.com") |
1292 | + test_contact = data.Contact(first_name="Fulano", |
1293 | + last_name="de Tal", |
1294 | + social_aliases=[alias]) |
1295 | + contact_editor.fill_form(test_contact) |
1296 | + |
1297 | + # Save contact |
1298 | + self.app.main_window.save() |
1299 | + |
1300 | + # edit again |
1301 | edit_page = self.edit_contact(0) |
1302 | |
1303 | # Change Im type |
FAILED: Continuous integration, rev:193 jenkins. qa.ubuntu. com/job/ phablet- team-address- book-app- staging- ci/133/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- utopic- touch/839 jenkins. qa.ubuntu. com/job/ generic- mediumtests- utopic/ 776 jenkins. qa.ubuntu. com/job/ phablet- team-address- book-app- staging- utopic- amd64-ci/ 133 jenkins. qa.ubuntu. com/job/ phablet- team-address- book-app- staging- utopic- armhf-ci/ 133 jenkins. qa.ubuntu. com/job/ phablet- team-address- book-app- staging- utopic- armhf-ci/ 133/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ phablet- team-address- book-app- staging- utopic- i386-ci/ 133/console jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- runner- mako/1254 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/1539 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/1539/ artifact/ work/output/ *zip*/output. zip s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 8374 jenkins. qa.ubuntu. com/job/ autopilot- testrunner- otto-utopic/ 688/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- amd64/915 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- amd64/915/ artifact/ work/output/ *zip*/output. zip
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
FAILURE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/phablet- team-address- book-app- staging- ci/133/ rebuild
http://