Merge lp:~renatofilho/address-book-app/release-2014-06-18 into lp:address-book-app
- release-2014-06-18
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 212 | ||||
Proposed branch: | lp:~renatofilho/address-book-app/release-2014-06-18 | ||||
Merge into: | lp:address-book-app | ||||
Diff against target: |
1955 lines (+671/-514) 36 files modified
src/app/imagescalethread.cpp (+1/-1) src/imports/Common/ContactDetailBase.qml (+1/-0) 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 (+3/-5) src/imports/ContactList/PageWithBottomEdge.qml (+39/-4) src/imports/ContactView/ActionButton.qml (+2/-2) src/imports/ContactView/BasicFieldView.qml (+27/-40) src/imports/ContactView/CMakeLists.txt (+0/-1) src/imports/ContactView/ContactDetailAvatarView.qml (+14/-60) src/imports/ContactView/ContactDetailFavoriteView.qml (+0/-43) src/imports/ContactView/ContactDetailGroupWithTypeView.qml (+2/-2) src/imports/ContactView/ContactDetailPhoneNumberView.qml (+15/-37) src/imports/ContactView/ContactDetailPhoneNumbersView.qml (+0/-5) src/imports/ContactView/ContactDetailWithTypeView.qml (+0/-2) src/imports/ContactView/ContactView.qml (+22/-20) src/imports/Ubuntu/Contacts/ContactAvatar.qml (+13/-3) src/imports/Ubuntu/Contacts/ContactDelegate.qml (+1/-2) src/imports/Ubuntu/Contacts/ContactDetailPickerPhoneNumberDelegate.qml (+7/-17) src/imports/Ubuntu/Contacts/ContactListView.qml (+5/-0) src/imports/Ubuntu/Contacts/ContactSimpleListView.qml (+3/-1) 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 (+2/-6) 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/release-2014-06-18 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Approve | |
Ubuntu Phablet Team | Pending | ||
Review via email:
|
Commit message
Update contact view page visuals
Update contact edit page visuals
Add a hide animation for the bottom edge title.
Description of the change
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
- 192. By Renato Araujo Oliveira Filho
-
To not keep track of contact in the ContactDetailPi
ckerPhoneNumber Delegate. This avoid crashes during the contact removal.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:192
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Renato Araujo Oliveira Filho (renatofilho) wrote : | # |
Are there any related MPs required for this MP to build/function as expected? YES
Is your branch in sync with latest trunk? YES
Did you perform an exploratory manual test run of your code change and any related functionality on device or emulator? YES
Did you successfully run all tests found in your component's Test Plan on device or emulator? YES
If you changed the UI, was the change specified/approved by design? YES
If you changed the packaging (debian), did you subscribe a core-dev to this MP? No package change
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 21:27:19 +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/ContactDetailBase.qml' |
15 | --- src/imports/Common/ContactDetailBase.qml 2014-05-08 18:10:28 +0000 |
16 | +++ src/imports/Common/ContactDetailBase.qml 2014-06-18 21:27:19 +0000 |
17 | @@ -93,6 +93,7 @@ |
18 | } |
19 | |
20 | highlightWhenPressed: false |
21 | + showDivider: false |
22 | |
23 | Rectangle { |
24 | anchors.fill: parent |
25 | |
26 | === modified file 'src/imports/Common/ContactDetailItem.qml' |
27 | --- src/imports/Common/ContactDetailItem.qml 2014-05-16 00:06:46 +0000 |
28 | +++ src/imports/Common/ContactDetailItem.qml 2014-06-18 21:27:19 +0000 |
29 | @@ -23,6 +23,7 @@ |
30 | |
31 | readonly property alias fieldDelegates: fieldsColumn.children |
32 | property Component fieldDelegate: null |
33 | + property alias spacing: fieldsColumn.spacing |
34 | |
35 | implicitHeight: fieldsColumn.height |
36 | Column { |
37 | |
38 | === added file 'src/imports/ContactEdit/AddFieldDialog.qml' |
39 | --- src/imports/ContactEdit/AddFieldDialog.qml 1970-01-01 00:00:00 +0000 |
40 | +++ src/imports/ContactEdit/AddFieldDialog.qml 2014-06-18 21:27:19 +0000 |
41 | @@ -0,0 +1,142 @@ |
42 | +/* |
43 | + * Copyright (C) 2012-2014 Canonical, Ltd. |
44 | + * |
45 | + * This program is free software; you can redistribute it and/or modify |
46 | + * it under the terms of the GNU General Public License as published by |
47 | + * the Free Software Foundation; version 3. |
48 | + * |
49 | + * This program is distributed in the hope that it will be useful, |
50 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
51 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
52 | + * GNU General Public License for more details. |
53 | + * |
54 | + * You should have received a copy of the GNU General Public License |
55 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
56 | + */ |
57 | + |
58 | +import QtQuick 2.2 |
59 | +import Ubuntu.Components 0.1 |
60 | +import QtContacts 5.0 |
61 | +import Ubuntu.Components.Popups 0.1 as Popups |
62 | + |
63 | + |
64 | +Item { |
65 | + id: root |
66 | + |
67 | + property QtObject contact: null |
68 | + property var currentDialog: null |
69 | + readonly property var validDetails: [ ContactDetail.PhoneNumber, |
70 | + ContactDetail.Email, |
71 | + ContactDetail.Address, |
72 | + ContactDetail.OnlineAccount, |
73 | + ContactDetail.Organization |
74 | + // TODO: Not supported yet |
75 | + // ContactDetail.Birthday, |
76 | + // ContactDetail.Note, |
77 | + // ContactDetail.Url |
78 | + ] |
79 | + readonly property var singleValueDetails: [ ContactDetail.Organization ] |
80 | + signal fieldSelected(string fieldName, string qmlTypeName) |
81 | + |
82 | + function showOptions() |
83 | + { |
84 | + if (currentDialog == null) { |
85 | + // make sure the OSK disappear |
86 | + root.forceActiveFocus() |
87 | + currentDialog = PopupUtils.open(addFieldDialog, null) |
88 | + } |
89 | + } |
90 | + |
91 | + function nameFromEnum(value) |
92 | + { |
93 | + switch (value) |
94 | + { |
95 | + case ContactDetail.PhoneNumber: |
96 | + return i18n.tr("Phone") |
97 | + case ContactDetail.Email: |
98 | + return i18n.tr("Email") |
99 | + case ContactDetail.Address: |
100 | + return i18n.tr("Address") |
101 | + case ContactDetail.OnlineAccount: |
102 | + return i18n.tr("Social") |
103 | + case ContactDetail.Organization: |
104 | + return i18n.tr("Professional Details") |
105 | + default: |
106 | + console.error("Invalid contact detail enum value:" + value) |
107 | + return "" |
108 | + } |
109 | + } |
110 | + |
111 | + function qmlTypeFromEnum(value) |
112 | + { |
113 | + switch (value) |
114 | + { |
115 | + case ContactDetail.PhoneNumber: |
116 | + return "PhoneNumber" |
117 | + case ContactDetail.Email: |
118 | + return "EmailAddress" |
119 | + case ContactDetail.Address: |
120 | + return "Address" |
121 | + case ContactDetail.OnlineAccount: |
122 | + return "OnlineAccount" |
123 | + case ContactDetail.Organization: |
124 | + return "Organization" |
125 | + default: |
126 | + console.error("Invalid contact detail enum value:" + value) |
127 | + return "" |
128 | + } |
129 | + } |
130 | + |
131 | + // check which details will be allowed to create |
132 | + // some details we only support one value |
133 | + function filterSingleDetails(details, contact) |
134 | + { |
135 | + var result = [] |
136 | + for(var i=0; i < details.length; i++) { |
137 | + var det = details[i] |
138 | + if (singleValueDetails.indexOf(det) != -1) { |
139 | + if (contact.details(det).length === 0) { |
140 | + result.push(det) |
141 | + } |
142 | + } else { |
143 | + result.push(det) |
144 | + } |
145 | + } |
146 | + return result |
147 | + } |
148 | + |
149 | + visible: false |
150 | + Component { |
151 | + id: addFieldDialog |
152 | + |
153 | + Popups.Dialog { |
154 | + id: dialogue |
155 | + objectName: "addFieldDialog" |
156 | + |
157 | + title: i18n.tr("Select a field") |
158 | + Repeater { |
159 | + model: root.filterSingleDetails(validDetails, root.contact) |
160 | + Button { |
161 | + objectName: text |
162 | + |
163 | + text: root.nameFromEnum(modelData) |
164 | + onClicked: { |
165 | + root.fieldSelected(text, root.qmlTypeFromEnum(modelData)) |
166 | + PopupUtils.close(root.currentDialog) |
167 | + root.currentDialog = null |
168 | + } |
169 | + } |
170 | + } |
171 | + Button { |
172 | + objectName: "cancel" |
173 | + |
174 | + text: i18n.tr("Cancel") |
175 | + gradient: UbuntuColors.greyGradient |
176 | + onClicked: { |
177 | + PopupUtils.close(root.currentDialog) |
178 | + root.currentDialog = null |
179 | + } |
180 | + } |
181 | + } |
182 | + } |
183 | +} |
184 | |
185 | === added file 'src/imports/ContactEdit/AvatarImport.qml' |
186 | --- src/imports/ContactEdit/AvatarImport.qml 1970-01-01 00:00:00 +0000 |
187 | +++ src/imports/ContactEdit/AvatarImport.qml 2014-06-18 21:27:19 +0000 |
188 | @@ -0,0 +1,78 @@ |
189 | +/* |
190 | + * Copyright (C) 2012-2014 Canonical, Ltd. |
191 | + * |
192 | + * This program is free software; you can redistribute it and/or modify |
193 | + * it under the terms of the GNU General Public License as published by |
194 | + * the Free Software Foundation; version 3. |
195 | + * |
196 | + * This program is distributed in the hope that it will be useful, |
197 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
198 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
199 | + * GNU General Public License for more details. |
200 | + * |
201 | + * You should have received a copy of the GNU General Public License |
202 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
203 | + */ |
204 | + |
205 | +import QtQuick 2.2 |
206 | +import Ubuntu.Components 0.1 |
207 | +import Ubuntu.Components.Popups 0.1 as Popups |
208 | +import Ubuntu.Content 0.1 as ContentHub |
209 | + |
210 | +Item { |
211 | + id: root |
212 | + |
213 | + property var activeTransfer: null |
214 | + property var loadingDialog: null |
215 | + |
216 | + signal avatarReceived(string avatarUrl) |
217 | + |
218 | + function requestNewAvatar() |
219 | + { |
220 | + if (!root.loadingDialog) { |
221 | + root.loadingDialog = PopupUtils.open(loadingDialog, null) |
222 | + root.activeTransfer = defaultSource.request(); |
223 | + } |
224 | + } |
225 | + |
226 | + ContentHub.ContentPeer { |
227 | + id: defaultSource |
228 | + |
229 | + contentType: ContentHub.ContentType.Pictures |
230 | + handler: ContentHub.ContentHandler.Source |
231 | + selectionType: ContentHub.ContentTransfer.Single |
232 | + } |
233 | + |
234 | + Connections { |
235 | + target: root.activeTransfer |
236 | + onStateChanged: { |
237 | + var done = ((root.activeTransfer.state === ContentHub.ContentTransfer.Charged) || |
238 | + (root.activeTransfer.state === ContentHub.ContentTransfer.Aborted)); |
239 | + |
240 | + if (root.activeTransfer.state === ContentHub.ContentTransfer.Charged) { |
241 | + if (root.activeTransfer.items.length > 0) { |
242 | + root.avatarReceived(root.activeTransfer.items[0].url) |
243 | + } |
244 | + } |
245 | + |
246 | + if (done) { |
247 | + PopupUtils.close(root.loadingDialog) |
248 | + root.loadingDialog = null |
249 | + } |
250 | + } |
251 | + } |
252 | + |
253 | + Component { |
254 | + id: loadingDialog |
255 | + |
256 | + Popups.Dialog { |
257 | + id: dialogue |
258 | + |
259 | + title: i18n.tr("Loading") |
260 | + ActivityIndicator { |
261 | + running: true |
262 | + visible: running |
263 | + } |
264 | + } |
265 | + } |
266 | +} |
267 | |
268 | === modified file 'src/imports/ContactEdit/CMakeLists.txt' |
269 | --- src/imports/ContactEdit/CMakeLists.txt 2014-06-09 22:45:19 +0000 |
270 | +++ src/imports/ContactEdit/CMakeLists.txt 2014-06-18 21:27:19 +0000 |
271 | @@ -1,4 +1,6 @@ |
272 | set(CONTACT_EDIT_QMLS |
273 | + AvatarImport.qml |
274 | + AddFieldDialog.qml |
275 | ContactDetailAddressesEditor.qml |
276 | ContactDetailAvatarEditor.qml |
277 | ContactDetailEmailsEditor.qml |
278 | |
279 | === modified file 'src/imports/ContactEdit/ContactDetailAvatarEditor.qml' |
280 | --- src/imports/ContactEdit/ContactDetailAvatarEditor.qml 2014-05-06 13:18:07 +0000 |
281 | +++ src/imports/ContactEdit/ContactDetailAvatarEditor.qml 2014-06-18 21:27:19 +0000 |
282 | @@ -17,15 +17,13 @@ |
283 | import QtQuick 2.2 |
284 | import Ubuntu.Components 0.1 |
285 | import QtContacts 5.0 |
286 | -import Ubuntu.Content 0.1 |
287 | -import Ubuntu.Components.Popups 0.1 as Popups |
288 | |
289 | import "../Common" |
290 | |
291 | ContactDetailBase { |
292 | id: root |
293 | |
294 | - readonly property string defaultAvatar: Qt.resolvedUrl("../../artwork/contact-default-profile.png") |
295 | + readonly property string defaultAvatar: "image://theme/contact" |
296 | |
297 | function isEmpty() { |
298 | return false; |
299 | @@ -62,98 +60,51 @@ |
300 | } |
301 | |
302 | detail: contact ? contact.detail(ContactDetail.Avatar) : null |
303 | - implicitHeight: units.gu(17) |
304 | - |
305 | - Image { |
306 | - id: avatarImage |
307 | - |
308 | - anchors.fill: parent |
309 | - source: root.getAvatar(root.detail) |
310 | - asynchronous: true |
311 | - fillMode: Image.PreserveAspectCrop |
312 | - // When updating the avatar using the content picker the temporary file returned |
313 | - // can contain the same name as the previous one and if the cache is enabled this |
314 | - // will cause the image to not be updated |
315 | - cache: false |
316 | - |
317 | - Component { |
318 | - id: loadingDialog |
319 | - |
320 | - Popups.Dialog { |
321 | - id: dialogue |
322 | - |
323 | - title: i18n.tr("Loading") |
324 | - |
325 | - ActivityIndicator { |
326 | - id: activity |
327 | - |
328 | - anchors.centerIn: parent |
329 | - running: true |
330 | - visible: running |
331 | - } |
332 | - } |
333 | - } |
334 | - |
335 | - Icon { |
336 | - anchors { |
337 | - right: parent.right |
338 | - rightMargin: units.gu(1.5) |
339 | - bottom: parent.bottom |
340 | - bottomMargin: units.gu(2) |
341 | - } |
342 | - width: units.gu(3) |
343 | - height: width |
344 | - name: "import-image" |
345 | - color: "white" |
346 | - } |
347 | - |
348 | - ContentPeer { |
349 | - id: defaultSource |
350 | - contentType: ContentType.Pictures |
351 | - handler: ContentHandler.Source |
352 | - selectionType: ContentTransfer.Single |
353 | - } |
354 | - |
355 | - MouseArea { |
356 | - id: changeButton |
357 | - |
358 | - property var activeTransfer |
359 | - property var loadingDialog: null |
360 | - |
361 | - anchors.fill: parent |
362 | - onClicked: { |
363 | - // make sure the OSK disappear |
364 | - root.forceActiveFocus() |
365 | - if (!changeButton.loadingDialog) { |
366 | - changeButton.loadingDialog = PopupUtils.open(loadingDialog, null) |
367 | - changeButton.activeTransfer = defaultSource.request(); |
368 | - } |
369 | - } |
370 | - |
371 | - Connections { |
372 | - target: changeButton.activeTransfer != null ? changeButton.activeTransfer : null |
373 | - onStateChanged: { |
374 | - var done = ((changeButton.activeTransfer.state === ContentTransfer.Charged) || |
375 | - (changeButton.activeTransfer.state === ContentTransfer.Aborted)); |
376 | - |
377 | - if (changeButton.activeTransfer.state === ContentTransfer.Charged) { |
378 | - if (changeButton.activeTransfer.items.length > 0) { |
379 | - // remove the previous image, this is nessary to make sure that the new image |
380 | - // get updated otherwise if the new image has the same name the image will not |
381 | - // be updated |
382 | - avatarImage.source = "" |
383 | - // Update with the new valu |
384 | - avatarImage.source = application.copyImage(root.contact, changeButton.activeTransfer.items[0].url); |
385 | - } |
386 | - } |
387 | - |
388 | - if (done) { |
389 | - PopupUtils.close(changeButton.loadingDialog) |
390 | - changeButton.loadingDialog = null |
391 | - } |
392 | - } |
393 | - } |
394 | + implicitHeight: units.gu(8) |
395 | + implicitWidth: units.gu(8) |
396 | + |
397 | + UbuntuShape { |
398 | + id: avatar |
399 | + |
400 | + radius: "medium" |
401 | + anchors.fill: parent |
402 | + image: Image { |
403 | + id: avatarImage |
404 | + |
405 | + fillMode: Image.PreserveAspectCrop |
406 | + asynchronous: true |
407 | + source: root.getAvatar(root.detail) |
408 | + height: units.gu(8) |
409 | + width: units.gu(8) |
410 | + |
411 | + // When updating the avatar using the content picker the temporary file returned |
412 | + // can contain the same name as the previous one and if the cache is enabled this |
413 | + // will cause the image to not be updated |
414 | + cache: false |
415 | + } |
416 | + } |
417 | + |
418 | + AvatarImport { |
419 | + id: avatarImport |
420 | + |
421 | + onAvatarReceived: { |
422 | + // remove the previous image, this is nessary to make sure that the new image |
423 | + // get updated otherwise if the new image has the same name the image will not |
424 | + // be updated |
425 | + avatarImage.source = "" |
426 | + // Update with the new value |
427 | + avatarImage.source = application.copyImage(root.contact, avatarUrl); |
428 | + } |
429 | + } |
430 | + |
431 | + MouseArea { |
432 | + anchors.fill: parent |
433 | + onClicked: { |
434 | + // make sure the OSK disappear |
435 | + root.forceActiveFocus() |
436 | + avatarImport.requestNewAvatar() |
437 | } |
438 | } |
439 | } |
440 | |
441 | + |
442 | |
443 | === modified file 'src/imports/ContactEdit/ContactDetailGroupWithTypeEditor.qml' |
444 | --- src/imports/ContactEdit/ContactDetailGroupWithTypeEditor.qml 2014-05-22 06:56:03 +0000 |
445 | +++ src/imports/ContactEdit/ContactDetailGroupWithTypeEditor.qml 2014-06-18 21:27:19 +0000 |
446 | @@ -95,7 +95,7 @@ |
447 | |
448 | return changed |
449 | } |
450 | - minimumHeight: units.gu(5) |
451 | + |
452 | headerDelegate: ListItem.Empty { |
453 | id: header |
454 | highlightWhenPressed: false |
455 | @@ -104,6 +104,9 @@ |
456 | height: units.gu(5) |
457 | // disable listview mouse area |
458 | __mouseArea.visible: false |
459 | + divider.anchors.leftMargin: units.gu(2) |
460 | + divider.anchors.rightMargin: units.gu(2) |
461 | + |
462 | Label { |
463 | anchors { |
464 | verticalCenter: parent.verticalCenter |
465 | @@ -117,35 +120,6 @@ |
466 | // style |
467 | fontSize: "medium" |
468 | } |
469 | - |
470 | - Icon { |
471 | - objectName: "newDetailButton" |
472 | - |
473 | - anchors { |
474 | - verticalCenter: parent.verticalCenter |
475 | - right: parent.right |
476 | - rightMargin: units.gu(2) |
477 | - } |
478 | - width: units.gu(2) |
479 | - height: units.gu(2) |
480 | - name: "add" |
481 | - } |
482 | - |
483 | - // Mouse area fill all title area to avoid problems with swipe from the right gesture |
484 | - MouseArea { |
485 | - anchors.fill: parent |
486 | - onClicked: { |
487 | - if (detailQmlTypeName) { |
488 | - var newDetail = Qt.createQmlObject("import QtContacts 5.0; " + detailQmlTypeName + "{}", root) |
489 | - if (newDetail) { |
490 | - var newDetailsCopy = root.newDetails |
491 | - newDetailsCopy.push(newDetail) |
492 | - root.newDetails = newDetailsCopy |
493 | - root.contact.addDetail(newDetail) |
494 | - } |
495 | - } |
496 | - } |
497 | - } |
498 | } |
499 | |
500 | detailDelegate: ContactDetailWithTypeEditor { |
501 | |
502 | === modified file 'src/imports/ContactEdit/ContactDetailNameEditor.qml' |
503 | --- src/imports/ContactEdit/ContactDetailNameEditor.qml 2014-05-09 20:00:09 +0000 |
504 | +++ src/imports/ContactEdit/ContactDetailNameEditor.qml 2014-06-18 21:27:19 +0000 |
505 | @@ -51,6 +51,7 @@ |
506 | return changed |
507 | } |
508 | |
509 | + spacing: units.gu(1) |
510 | detail: root.contact ? root.contact.name : null |
511 | fields: [ QtContacts.Name.FirstName, QtContacts.Name.LastName ] |
512 | |
513 | |
514 | === modified file 'src/imports/ContactEdit/ContactDetailSyncTargetEditor.qml' |
515 | --- src/imports/ContactEdit/ContactDetailSyncTargetEditor.qml 2014-05-28 15:22:38 +0000 |
516 | +++ src/imports/ContactEdit/ContactDetailSyncTargetEditor.qml 2014-06-18 21:27:19 +0000 |
517 | @@ -84,6 +84,12 @@ |
518 | height: units.gu(4) |
519 | } |
520 | |
521 | + ListItem.ThinDivider { |
522 | + id: divider |
523 | + |
524 | + anchors.top: label.bottom |
525 | + } |
526 | + |
527 | OptionSelector { |
528 | id: sources |
529 | |
530 | @@ -91,8 +97,8 @@ |
531 | anchors { |
532 | left: parent.left |
533 | leftMargin: units.gu(2) |
534 | - top: label.bottom |
535 | - topMargin: units.gu(1) |
536 | + top: divider.bottom |
537 | + topMargin: units.gu(2) |
538 | right: parent.right |
539 | rightMargin: units.gu(2) |
540 | bottom: parent.bottom |
541 | |
542 | === modified file 'src/imports/ContactEdit/ContactDetailWithTypeEditor.qml' |
543 | --- src/imports/ContactEdit/ContactDetailWithTypeEditor.qml 2014-05-16 01:59:36 +0000 |
544 | +++ src/imports/ContactEdit/ContactDetailWithTypeEditor.qml 2014-06-18 21:27:19 +0000 |
545 | @@ -73,41 +73,19 @@ |
546 | enabled: root.detail ? !root.detail.readOnly : false |
547 | implicitHeight: detailTypeSelector.height + fieldValues.height + units.gu(2) |
548 | opacity: enabled ? 1.0 : 0.5 |
549 | - ValueSelector { |
550 | - id: detailTypeSelector |
551 | - objectName: detail ? "type_" + detailToString(detail.type, -1) + "_" + index : "" |
552 | - |
553 | - readOnly: root.detail ? root.detail.readOnly : false |
554 | - visible: (currentIndex != -1) |
555 | - active: root.active |
556 | + |
557 | + Column { |
558 | + id: fieldValues |
559 | + |
560 | anchors { |
561 | left: parent.left |
562 | - leftMargin: units.gu(3) |
563 | + leftMargin: units.gu(2) |
564 | right: parent.right |
565 | rightMargin: units.gu(2) |
566 | top: parent.top |
567 | topMargin: units.gu(1) |
568 | } |
569 | - |
570 | - height: visible ? (root.active ? units.gu(4) : units.gu(3)) : 0 |
571 | - onExpandedChanged: { |
572 | - // Make sure that the inputfield get focus when clicking on type selector |
573 | - if (expanded) { |
574 | - root.forceActiveFocus() |
575 | - } |
576 | - } |
577 | - } |
578 | - |
579 | - Column { |
580 | - id: fieldValues |
581 | - |
582 | - anchors { |
583 | - left: detailTypeSelector.left |
584 | - right: detailTypeSelector.right |
585 | - top: detailTypeSelector.bottom |
586 | - } |
587 | height: childrenRect.height |
588 | - |
589 | Repeater { |
590 | id: fieldRepeater |
591 | |
592 | @@ -141,4 +119,26 @@ |
593 | } |
594 | } |
595 | } |
596 | + |
597 | + ValueSelector { |
598 | + id: detailTypeSelector |
599 | + objectName: detail ? "type_" + detailToString(detail.type, -1) + "_" + index : "" |
600 | + |
601 | + anchors { |
602 | + left: fieldValues.left |
603 | + right: fieldValues.right |
604 | + top: fieldValues.bottom |
605 | + } |
606 | + |
607 | + readOnly: root.detail ? root.detail.readOnly : false |
608 | + visible: (currentIndex != -1) |
609 | + active: root.active |
610 | + height: visible ? (root.active ? units.gu(4) : units.gu(3)) : 0 |
611 | + onExpandedChanged: { |
612 | + // Make sure that the inputfield get focus when clicking on type selector |
613 | + if (expanded) { |
614 | + root.forceActiveFocus() |
615 | + } |
616 | + } |
617 | + } |
618 | } |
619 | |
620 | === modified file 'src/imports/ContactEdit/ContactEditor.qml' |
621 | --- src/imports/ContactEdit/ContactEditor.qml 2014-06-16 12:59:15 +0000 |
622 | +++ src/imports/ContactEdit/ContactEditor.qml 2014-06-18 21:27:19 +0000 |
623 | @@ -161,7 +161,7 @@ |
624 | fill: parent |
625 | bottomMargin: keyboard.height |
626 | } |
627 | - contentHeight: contents.height |
628 | + contentHeight: contents.height + units.gu(2) |
629 | contentWidth: parent.width |
630 | |
631 | //after add a new field we need to wait for the contentHeight to change to scroll to the correct position |
632 | @@ -172,32 +172,48 @@ |
633 | |
634 | anchors { |
635 | top: parent.top |
636 | + topMargin: units.gu(2) |
637 | left: parent.left |
638 | right: parent.right |
639 | } |
640 | height: childrenRect.height |
641 | |
642 | - ContactDetailNameEditor { |
643 | - id: nameEditor |
644 | - |
645 | - |
646 | - anchors { |
647 | - left: parent.left |
648 | - right: parent.right |
649 | - } |
650 | - height: nameEditor.implicitHeight + units.gu(3) |
651 | - contact: contactEditor.contact |
652 | - } |
653 | - |
654 | - ContactDetailAvatarEditor { |
655 | - id: avatarEditor |
656 | - |
657 | - contact: contactEditor.contact |
658 | - anchors { |
659 | - left: parent.left |
660 | - right: parent.right |
661 | - } |
662 | - height: implicitHeight |
663 | + Row { |
664 | + function save() |
665 | + { |
666 | + var avatarSave = avatarEditor.save() |
667 | + var nameSave = nameEditor.save(); |
668 | + |
669 | + return (nameSave || avatarSave); |
670 | + } |
671 | + |
672 | + function isEmpty() |
673 | + { |
674 | + return (avatarEditor.isEmpty() && nameEditor.isEmpty()) |
675 | + } |
676 | + |
677 | + anchors { |
678 | + left: parent.left |
679 | + leftMargin: units.gu(2) |
680 | + right: parent.right |
681 | + } |
682 | + height: Math.max(avatarEditor.height, nameEditor.height) - units.gu(4) |
683 | + |
684 | + ContactDetailAvatarEditor { |
685 | + id: avatarEditor |
686 | + |
687 | + contact: contactEditor.contact |
688 | + height: implicitHeight |
689 | + width: implicitWidth |
690 | + } |
691 | + |
692 | + ContactDetailNameEditor { |
693 | + id: nameEditor |
694 | + |
695 | + width: parent.width - avatarEditor.width |
696 | + height: nameEditor.implicitHeight + units.gu(3) |
697 | + contact: contactEditor.contact |
698 | + } |
699 | } |
700 | |
701 | ContactDetailPhoneNumbersEditor { |
702 | @@ -272,13 +288,48 @@ |
703 | height: implicitHeight |
704 | } |
705 | |
706 | - // We need this extra element to correct align the deleteButton |
707 | + ListItem.ThinDivider {} |
708 | + |
709 | Item { |
710 | anchors { |
711 | left: parent.left |
712 | right: parent.right |
713 | } |
714 | - height: deleteButton.height + units.gu(2) |
715 | + height: units.gu(2) |
716 | + } |
717 | + |
718 | + Row { |
719 | + anchors { |
720 | + left: parent.left |
721 | + right: parent.right |
722 | + margins: units.gu(2) |
723 | + } |
724 | + height: units.gu(6) |
725 | + spacing: units.gu(2) |
726 | + |
727 | + // WORKAROUND: SDK uses a old version of qtquick components |
728 | + activeFocusOnTab: true |
729 | + onActiveFocusChanged: { |
730 | + if (activeFocus) { |
731 | + addNewFieldButton.forceActiveFocus() |
732 | + } |
733 | + } |
734 | + |
735 | + Button { |
736 | + id: addNewFieldButton |
737 | + objectName: "addNewFieldButton" |
738 | + |
739 | + text: i18n.tr("Add Field") |
740 | + gradient: UbuntuColors.greyGradient |
741 | + anchors { |
742 | + top: parent.top |
743 | + bottom: parent.bottom |
744 | + bottomMargin: units.gu(2) |
745 | + } |
746 | + width: (parent.width / 2) - units.gu(1) |
747 | + |
748 | + onClicked: addFieldDialog.showOptions() |
749 | + } |
750 | |
751 | Button { |
752 | id: deleteButton |
753 | @@ -286,12 +337,11 @@ |
754 | text: i18n.tr("Delete") |
755 | visible: !contactEditor.isNewContact |
756 | anchors { |
757 | - margins: units.gu(2) |
758 | top: parent.top |
759 | - left: parent.left |
760 | - right: parent.right |
761 | + bottom: parent.bottom |
762 | + bottomMargin: units.gu(2) |
763 | } |
764 | - |
765 | + width: (parent.width / 2) - units.gu(1) |
766 | onClicked: { |
767 | var dialog = Popups.PopupUtils.open(removeContactDialog, null) |
768 | dialog.contacts = [contactEditor.contact] |
769 | @@ -351,6 +401,23 @@ |
770 | } |
771 | } |
772 | |
773 | + AddFieldDialog { |
774 | + id: addFieldDialog |
775 | + |
776 | + contact: contactEditor.contact |
777 | + onFieldSelected: { |
778 | + if (qmlTypeName) { |
779 | + var newDetail = Qt.createQmlObject("import QtContacts 5.0; " + qmlTypeName + "{}", addFieldDialog) |
780 | + if (newDetail) { |
781 | + var newDetailsCopy = contactEditor.newDetails |
782 | + newDetailsCopy.push(newDetail) |
783 | + contactEditor.newDetails = newDetailsCopy |
784 | + contactEditor.contact.addDetail(newDetail) |
785 | + } |
786 | + } |
787 | + } |
788 | + } |
789 | + |
790 | Component { |
791 | id: removeContactDialog |
792 | |
793 | |
794 | === modified file 'src/imports/ContactEdit/TextInputDetail.qml' |
795 | --- src/imports/ContactEdit/TextInputDetail.qml 2014-05-28 15:19:53 +0000 |
796 | +++ src/imports/ContactEdit/TextInputDetail.qml 2014-06-18 21:27:19 +0000 |
797 | @@ -80,6 +80,7 @@ |
798 | overlaySpacing: 0 |
799 | frameSpacing: 0 |
800 | background: Item {} |
801 | + color: UbuntuColors.lightAubergine |
802 | } |
803 | onActiveFocusChanged: { |
804 | if (activeFocus) { |
805 | |
806 | === modified file 'src/imports/ContactEdit/ValueSelector.qml' |
807 | --- src/imports/ContactEdit/ValueSelector.qml 2014-06-06 17:52:58 +0000 |
808 | +++ src/imports/ContactEdit/ValueSelector.qml 2014-06-18 21:27:19 +0000 |
809 | @@ -59,22 +59,12 @@ |
810 | |
811 | // FIXME: workaround to close list after a while. |
812 | // we cant rely on focus since it hides the keyboard. |
813 | - MouseArea { |
814 | - anchors.fill: parent |
815 | - visible: expanded |
816 | - onPressed: { |
817 | - mouse.accepted = false |
818 | - timer.restart() |
819 | - } |
820 | - propagateComposedEvents: true |
821 | - z: 1 |
822 | - } |
823 | - |
824 | Timer { |
825 | id: timer |
826 | + |
827 | interval: 5000 |
828 | + running: false |
829 | onTriggered: state = "" |
830 | - running: false |
831 | } |
832 | |
833 | Item { |
834 | @@ -119,8 +109,12 @@ |
835 | |
836 | MouseArea { |
837 | anchors.fill: parent |
838 | - propagateComposedEvents: true |
839 | - onClicked: if (!readOnly) root.state = "expanded" |
840 | + onClicked: { |
841 | + if (!readOnly) { |
842 | + root.state = "expanded" |
843 | + timer.restart() |
844 | + } |
845 | + } |
846 | } |
847 | |
848 | ListView { |
849 | @@ -160,7 +154,10 @@ |
850 | width: parent.width + units.gu(0.5) |
851 | height: parent.height + units.gu(0.5) |
852 | anchors.centerIn: parent |
853 | - onClicked: currentIndex = index |
854 | + onClicked: { |
855 | + currentIndex = index |
856 | + timer.restart() |
857 | + } |
858 | } |
859 | } |
860 | |
861 | |
862 | === modified file 'src/imports/ContactList/ContactListPage.qml' |
863 | --- src/imports/ContactList/ContactListPage.qml 2014-06-16 12:59:54 +0000 |
864 | +++ src/imports/ContactList/ContactListPage.qml 2014-06-18 21:27:19 +0000 |
865 | @@ -43,10 +43,7 @@ |
866 | function createEmptyContact(phoneNumber) { |
867 | var details = [ {detail: "PhoneNumber", field: "number", value: phoneNumber}, |
868 | {detail: "EmailAddress", field: "emailAddress", value: ""}, |
869 | - {detail: "OnlineAccount", field: "accountUri", value: ""}, |
870 | - {detail: "Address", field: "street", value: ""}, |
871 | - {detail: "Name", field: "firstName", value: ""}, |
872 | - {detail: "Organization", field: "name", value: ""} |
873 | + {detail: "Name", field: "firstName", value: ""} |
874 | ] |
875 | |
876 | var newContact = Qt.createQmlObject("import QtContacts 5.0; Contact{ }", mainPage) |
877 | @@ -385,7 +382,8 @@ |
878 | {model: contactList.listModel, |
879 | contact: newContact, |
880 | active: false, |
881 | - enabled: false}) |
882 | + enabled: false, |
883 | + initialFocusSection: "name"}) |
884 | } |
885 | |
886 | Connections { |
887 | |
888 | === modified file 'src/imports/ContactList/PageWithBottomEdge.qml' |
889 | --- src/imports/ContactList/PageWithBottomEdge.qml 2014-06-16 13:00:42 +0000 |
890 | +++ src/imports/ContactList/PageWithBottomEdge.qml 2014-06-18 21:27:19 +0000 |
891 | @@ -142,6 +142,15 @@ |
892 | z: 1 |
893 | } |
894 | |
895 | + Timer { |
896 | + id: hideIndicator |
897 | + |
898 | + interval: 3000 |
899 | + running: true |
900 | + repeat: false |
901 | + onTriggered: tipContainer.y = -units.gu(1) |
902 | + } |
903 | + |
904 | Rectangle { |
905 | id: bottomEdge |
906 | objectName: "bottomEdge" |
907 | @@ -184,6 +193,9 @@ |
908 | clip: true |
909 | y: -bottomEdge.tipHeight |
910 | anchors.horizontalCenter: parent.horizontalCenter |
911 | + Behavior on y { |
912 | + UbuntuNumberAnimation {} |
913 | + } |
914 | |
915 | UbuntuShape { |
916 | id: tip |
917 | @@ -230,10 +242,7 @@ |
918 | } |
919 | } |
920 | |
921 | - onPressed: { |
922 | - bottomEdge.state = "floating" |
923 | - bottomEdge.y -= bottomEdge.tipHeight |
924 | - } |
925 | + onPressed: bottomEdge.state = "floating" |
926 | } |
927 | |
928 | Behavior on y { |
929 | @@ -252,6 +261,14 @@ |
930 | target: tip |
931 | opacity: 1.0 |
932 | } |
933 | + PropertyChanges { |
934 | + target: tipContainer |
935 | + y: -bottomEdge.tipHeight |
936 | + } |
937 | + PropertyChanges { |
938 | + target: hideIndicator |
939 | + running: true |
940 | + } |
941 | }, |
942 | State { |
943 | name: "expanded" |
944 | @@ -263,6 +280,14 @@ |
945 | target: tip |
946 | opacity: 0.0 |
947 | } |
948 | + PropertyChanges { |
949 | + target: tipContainer |
950 | + y: -bottomEdge.tipHeight |
951 | + } |
952 | + PropertyChanges { |
953 | + target: hideIndicator |
954 | + running: false |
955 | + } |
956 | }, |
957 | State { |
958 | name: "floating" |
959 | @@ -270,6 +295,14 @@ |
960 | target: shadow |
961 | opacity: 1.0 |
962 | } |
963 | + PropertyChanges { |
964 | + target: hideIndicator |
965 | + running: false |
966 | + } |
967 | + PropertyChanges { |
968 | + target: tipContainer |
969 | + y: -bottomEdge.tipHeight |
970 | + } |
971 | } |
972 | ] |
973 | |
974 | @@ -316,6 +349,8 @@ |
975 | |
976 | // load a new bottom page in memory |
977 | edgeLoader.active = true |
978 | + |
979 | + hideIndicator.restart() |
980 | } |
981 | } |
982 | } |
983 | |
984 | === modified file 'src/imports/ContactView/ActionButton.qml' |
985 | --- src/imports/ContactView/ActionButton.qml 2014-06-06 17:52:58 +0000 |
986 | +++ src/imports/ContactView/ActionButton.qml 2014-06-18 21:27:19 +0000 |
987 | @@ -27,7 +27,7 @@ |
988 | id: icon |
989 | |
990 | anchors.centerIn: parent |
991 | - height: units.gu(3) |
992 | - width: height |
993 | + height: units.gu(2.5) |
994 | + width: units.gu(2.5) |
995 | } |
996 | } |
997 | |
998 | === modified file 'src/imports/ContactView/BasicFieldView.qml' |
999 | --- src/imports/ContactView/BasicFieldView.qml 2014-06-06 17:52:58 +0000 |
1000 | +++ src/imports/ContactView/BasicFieldView.qml 2014-06-18 21:27:19 +0000 |
1001 | @@ -24,56 +24,23 @@ |
1002 | |
1003 | property alias typeLabel: typeLabel.text |
1004 | property alias values: valueList.model |
1005 | - property alias iconSource: actionIcon.source |
1006 | - property double lineHeight: units.gu(3) |
1007 | + property double lineHeight: units.gu(2) |
1008 | property QtObject detail: null |
1009 | property variant fields: null |
1010 | property int parentIndex: -1 |
1011 | |
1012 | - implicitHeight: typeLabel.height + (root.lineHeight * valueList.count) + units.gu(2) |
1013 | + implicitHeight: typeLabel.height + fieldValues.height + units.gu(2) |
1014 | |
1015 | - Image { |
1016 | - id: actionIcon |
1017 | + Column { |
1018 | + id: fieldValues |
1019 | |
1020 | anchors { |
1021 | - verticalCenter: parent.verticalCenter |
1022 | left: parent.left |
1023 | - } |
1024 | - height: units.gu(2.5) |
1025 | - width: visible ? units.gu(2.5) : 0 |
1026 | - visible: iconSource && iconSource != "" |
1027 | - } |
1028 | - |
1029 | - Label { |
1030 | - id: typeLabel |
1031 | - objectName: detail ? "type_" + detailToString(detail.type, -1) + "_" + root.parentIndex : "" |
1032 | - |
1033 | - elide: Text.ElideRight |
1034 | - visible: text != "" |
1035 | - anchors { |
1036 | - left: actionIcon.right |
1037 | - leftMargin: actionIcon.visible ? units.gu(2) : 0 |
1038 | top: parent.top |
1039 | topMargin: units.gu(1) |
1040 | - right: root.right |
1041 | - } |
1042 | - height: visible ? units.gu(2) : 0 |
1043 | - verticalAlignment: Text.AlignVCenter |
1044 | - |
1045 | - // style |
1046 | - fontSize: "small" |
1047 | - opacity: 0.8 |
1048 | - } |
1049 | - |
1050 | - Column { |
1051 | - id: fieldValues |
1052 | - |
1053 | - anchors { |
1054 | - left: typeLabel.left |
1055 | - top: typeLabel.bottom |
1056 | right: parent.right |
1057 | - bottom: parent.bottom |
1058 | } |
1059 | + height: (valueList.count * root.lineHeight) |
1060 | |
1061 | Repeater { |
1062 | id: valueList |
1063 | @@ -83,8 +50,8 @@ |
1064 | objectName: detail && fields ? "label_" + detailToString(detail.type, fields[index]) + "_" + root.parentIndex + "." + index : "" |
1065 | |
1066 | anchors { |
1067 | - left: parent ? parent.left : null |
1068 | - right: parent ? parent.right : null |
1069 | + left: parent ? parent.left : undefined |
1070 | + right: parent ? parent.right : undefined |
1071 | } |
1072 | height: root.lineHeight |
1073 | verticalAlignment: Text.AlignVCenter |
1074 | @@ -97,4 +64,24 @@ |
1075 | } |
1076 | } |
1077 | } |
1078 | + |
1079 | + Label { |
1080 | + id: typeLabel |
1081 | + objectName: detail ? "type_" + detailToString(detail.type, -1) + "_" + root.parentIndex : "" |
1082 | + |
1083 | + elide: Text.ElideRight |
1084 | + visible: text != "" |
1085 | + anchors { |
1086 | + left: parent.left |
1087 | + top: fieldValues.bottom |
1088 | + //topMargin: units.gu(0.0) |
1089 | + right: parent.right |
1090 | + } |
1091 | + height: visible ? units.gu(2) : 0 |
1092 | + verticalAlignment: Text.AlignVCenter |
1093 | + |
1094 | + // style |
1095 | + fontSize: "small" |
1096 | + opacity: 0.8 |
1097 | + } |
1098 | } |
1099 | |
1100 | === modified file 'src/imports/ContactView/CMakeLists.txt' |
1101 | --- src/imports/ContactView/CMakeLists.txt 2014-06-09 22:45:19 +0000 |
1102 | +++ src/imports/ContactView/CMakeLists.txt 2014-06-18 21:27:19 +0000 |
1103 | @@ -4,7 +4,6 @@ |
1104 | ContactDetailAddressesView.qml |
1105 | ContactDetailAvatarView.qml |
1106 | ContactDetailEmailsView.qml |
1107 | - ContactDetailFavoriteView.qml |
1108 | ContactDetailGroupWithTypeView.qml |
1109 | ContactDetailNameView.qml |
1110 | ContactDetailOnlineAccountsView.qml |
1111 | |
1112 | === modified file 'src/imports/ContactView/ContactDetailAvatarView.qml' |
1113 | --- src/imports/ContactView/ContactDetailAvatarView.qml 2014-05-07 18:13:12 +0000 |
1114 | +++ src/imports/ContactView/ContactDetailAvatarView.qml 2014-06-18 21:27:19 +0000 |
1115 | @@ -17,74 +17,28 @@ |
1116 | import QtQuick 2.2 |
1117 | import QtContacts 5.0 |
1118 | import Ubuntu.Components 0.1 |
1119 | +import Ubuntu.Contacts 0.1 as ContactsUI |
1120 | |
1121 | import "../Common" |
1122 | |
1123 | ContactDetailBase { |
1124 | id: root |
1125 | |
1126 | - readonly property string defaultAvatar: Qt.resolvedUrl("../../artwork/contact-default-profile.png") |
1127 | - |
1128 | - function getAvatar(avatarDetail) |
1129 | - { |
1130 | - // use this verbose mode to avoid problems with binding loops |
1131 | - var avatarUrl = defaultAvatar |
1132 | - if (avatarDetail) { |
1133 | - var avatarValue = avatarDetail.value(Avatar.ImageUrl) |
1134 | - if (avatarValue != "") { |
1135 | - avatarUrl = avatarValue |
1136 | - } |
1137 | - } |
1138 | - return avatarUrl |
1139 | - } |
1140 | - |
1141 | - detail: contact ? contact.detail(ContactDetail.Avatar) : null |
1142 | - implicitHeight: units.gu(17) |
1143 | - |
1144 | - // update the contact detail in case of the contact change |
1145 | + implicitHeight: units.gu(8) |
1146 | + implicitWidth: units.gu(10) |
1147 | + |
1148 | Connections { |
1149 | - target: root.contact |
1150 | - onContactChanged: { |
1151 | - if (root.contact) { |
1152 | - root.detail = contact.detail(ContactDetail.Avatar) |
1153 | - } else { |
1154 | - root.detail = null |
1155 | - } |
1156 | - } |
1157 | - } |
1158 | - |
1159 | - onDetailChanged: { |
1160 | - var newAvatar = root.getAvatar(root.detail) |
1161 | - if (newAvatar !== defaultAvatar) { |
1162 | - avatar.source = newAvatar |
1163 | - } else { |
1164 | - updateAvatar.restart() |
1165 | - } |
1166 | - } |
1167 | - |
1168 | - // Wait some milliseconds before update the avatar, in some cases the avatac get update later and this cause the image flick |
1169 | - Timer { |
1170 | - id: updateAvatar |
1171 | - |
1172 | - interval: 100 |
1173 | - running: false |
1174 | - repeat: false |
1175 | - onTriggered: { |
1176 | - if (root.detail && contact) { |
1177 | - avatar.source = root.getAvatar(root.detail) |
1178 | - } else { |
1179 | - avatar.source = root.defaultAvatar |
1180 | - } |
1181 | - } |
1182 | - } |
1183 | - |
1184 | - Image { |
1185 | + target: root.contact.avatar |
1186 | + onDetailChanged: avatar.reload() |
1187 | + } |
1188 | + |
1189 | + ContactsUI.ContactAvatar { |
1190 | id: avatar |
1191 | |
1192 | - anchors.fill: parent |
1193 | - asynchronous: true |
1194 | - smooth: true |
1195 | - source: root.defaultAvatar |
1196 | - fillMode: Image.PreserveAspectCrop |
1197 | + contactElement: root.contact |
1198 | + anchors { |
1199 | + fill: parent |
1200 | + leftMargin: units.gu(2) |
1201 | + } |
1202 | } |
1203 | } |
1204 | |
1205 | === removed file 'src/imports/ContactView/ContactDetailFavoriteView.qml' |
1206 | --- src/imports/ContactView/ContactDetailFavoriteView.qml 2014-05-06 13:18:07 +0000 |
1207 | +++ src/imports/ContactView/ContactDetailFavoriteView.qml 1970-01-01 00:00:00 +0000 |
1208 | @@ -1,43 +0,0 @@ |
1209 | -/* |
1210 | - * Copyright (C) 2012-2013 Canonical, Ltd. |
1211 | - * |
1212 | - * This program is free software; you can redistribute it and/or modify |
1213 | - * it under the terms of the GNU General Public License as published by |
1214 | - * the Free Software Foundation; version 3. |
1215 | - * |
1216 | - * This program is distributed in the hope that it will be useful, |
1217 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1218 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1219 | - * GNU General Public License for more details. |
1220 | - * |
1221 | - * You should have received a copy of the GNU General Public License |
1222 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1223 | - */ |
1224 | - |
1225 | -import QtQuick 2.2 |
1226 | -import Ubuntu.Components 0.1 |
1227 | -import QtContacts 5.0 |
1228 | - |
1229 | -import "../Common" |
1230 | - |
1231 | -ContactDetailBase { |
1232 | - id: root |
1233 | - |
1234 | - detail: root.contact ? root.contact.favorite : null |
1235 | - showDivider: false |
1236 | - |
1237 | - Icon { |
1238 | - id: icon |
1239 | - |
1240 | - anchors.fill: parent |
1241 | - name: root.detail && root.detail.favorite ? "favorite-selected" : "favorite-unselected" |
1242 | - color: UbuntuColors.orange |
1243 | - MouseArea { |
1244 | - anchors.fill: parent |
1245 | - onClicked: { |
1246 | - root.detail.favorite = !root.detail.favorite |
1247 | - root.contact.save() |
1248 | - } |
1249 | - } |
1250 | - } |
1251 | -} |
1252 | |
1253 | === modified file 'src/imports/ContactView/ContactDetailGroupWithTypeView.qml' |
1254 | --- src/imports/ContactView/ContactDetailGroupWithTypeView.qml 2014-06-06 17:52:58 +0000 |
1255 | +++ src/imports/ContactView/ContactDetailGroupWithTypeView.qml 2014-06-18 21:27:19 +0000 |
1256 | @@ -31,6 +31,8 @@ |
1257 | headerDelegate: ListItem.Empty { |
1258 | highlightWhenPressed: false |
1259 | |
1260 | + divider.anchors.leftMargin: units.gu(2) |
1261 | + divider.anchors.rightMargin: units.gu(2) |
1262 | width: root.width |
1263 | height: units.gu(5) |
1264 | Label { |
1265 | @@ -45,7 +47,6 @@ |
1266 | |
1267 | // style |
1268 | fontSize: "medium" |
1269 | - opacity: 0.8 |
1270 | } |
1271 | } |
1272 | |
1273 | @@ -56,7 +57,6 @@ |
1274 | contact: root.contact |
1275 | fields: root.fields |
1276 | typeLabel: detailType ? detailType.label : "" |
1277 | - typeIcon: detailType && detailType.icon ? detailType.icon : "" |
1278 | |
1279 | height: implicitHeight |
1280 | width: root.width |
1281 | |
1282 | === modified file 'src/imports/ContactView/ContactDetailPhoneNumberView.qml' |
1283 | --- src/imports/ContactView/ContactDetailPhoneNumberView.qml 2014-05-06 13:18:07 +0000 |
1284 | +++ src/imports/ContactView/ContactDetailPhoneNumberView.qml 2014-06-18 21:27:19 +0000 |
1285 | @@ -55,62 +55,40 @@ |
1286 | anchors { |
1287 | left: parent.left |
1288 | top: parent.top |
1289 | - right: div0.left |
1290 | + right: messageActions.left |
1291 | bottom: parent.bottom |
1292 | leftMargin: units.gu(2) |
1293 | } |
1294 | - iconSource: root.action ? root.action.iconSource : "" |
1295 | } |
1296 | |
1297 | - Image { |
1298 | - id: div0 |
1299 | + ActionButton { |
1300 | + id: messageActions |
1301 | |
1302 | anchors { |
1303 | - top: parent.top |
1304 | right: callActions.left |
1305 | - bottom: parent.bottom |
1306 | + rightMargin: units.gu(1) |
1307 | + verticalCenter: parent.verticalCenter |
1308 | } |
1309 | - width: 2 |
1310 | - fillMode: Image.TileVertically |
1311 | - source: "artwork:/vertical-div.png" |
1312 | + width: units.gu(4) |
1313 | + height: units.gu(4) |
1314 | + iconName: "messages" |
1315 | + onClicked: Qt.openUrlExternally("message:///" + encodeURIComponent(view.values[0])) |
1316 | } |
1317 | |
1318 | + |
1319 | ActionButton { |
1320 | id: callActions |
1321 | |
1322 | anchors { |
1323 | - right: div1.left |
1324 | + right: parent.right |
1325 | + rightMargin: units.gu(2) |
1326 | top: parent.top |
1327 | - bottom: parent.bottom |
1328 | + verticalCenter: parent.verticalCenter |
1329 | } |
1330 | - width: height |
1331 | + width: units.gu(4) |
1332 | + height: units.gu(4) |
1333 | iconName: "call-start" |
1334 | onClicked: Qt.openUrlExternally("tel:///" + encodeURIComponent(view.values[0])) |
1335 | } |
1336 | |
1337 | - Image { |
1338 | - id: div1 |
1339 | - |
1340 | - anchors { |
1341 | - top: parent.top |
1342 | - right: messageActions.left |
1343 | - bottom: parent.bottom |
1344 | - } |
1345 | - width: 2 |
1346 | - fillMode: Image.TileVertically |
1347 | - source: "artwork:/vertical-div.png" |
1348 | - } |
1349 | - |
1350 | - ActionButton { |
1351 | - id: messageActions |
1352 | - |
1353 | - anchors { |
1354 | - right: parent.right |
1355 | - top: parent.top |
1356 | - bottom: parent.bottom |
1357 | - } |
1358 | - width: height |
1359 | - iconName: "messages" |
1360 | - onClicked: Qt.openUrlExternally("message:///" + encodeURIComponent(view.values[0])) |
1361 | - } |
1362 | } |
1363 | |
1364 | === modified file 'src/imports/ContactView/ContactDetailPhoneNumbersView.qml' |
1365 | --- src/imports/ContactView/ContactDetailPhoneNumbersView.qml 2014-05-06 13:18:07 +0000 |
1366 | +++ src/imports/ContactView/ContactDetailPhoneNumbersView.qml 2014-06-18 21:27:19 +0000 |
1367 | @@ -29,11 +29,6 @@ |
1368 | |
1369 | title: i18n.tr("Phone") |
1370 | typeModel: ContactDetailPhoneNumberTypeModel { } |
1371 | - defaultAction: Action { |
1372 | - text: i18n.tr("Favorite") |
1373 | - iconSource: "artwork:/contact-call.png" |
1374 | - } |
1375 | - |
1376 | detailDelegate: ContactDetailPhoneNumberView { |
1377 | property variant detailType: detail && root.contact && root.typeModelReady ? root.getType(detail) : null |
1378 | |
1379 | |
1380 | === modified file 'src/imports/ContactView/ContactDetailWithTypeView.qml' |
1381 | --- src/imports/ContactView/ContactDetailWithTypeView.qml 2014-05-06 13:18:07 +0000 |
1382 | +++ src/imports/ContactView/ContactDetailWithTypeView.qml 2014-06-18 21:27:19 +0000 |
1383 | @@ -25,7 +25,6 @@ |
1384 | id: root |
1385 | |
1386 | property alias typeLabel: view.typeLabel |
1387 | - property string typeIcon: null |
1388 | property alias lineHeight: view.lineHeight |
1389 | readonly property bool isReady: (fields != null) && (detail != null) |
1390 | |
1391 | @@ -61,6 +60,5 @@ |
1392 | left: parent.left |
1393 | leftMargin: units.gu(2) |
1394 | } |
1395 | - iconSource: typeIcon ? typeIcon : (root.action ? root.action.iconSource : "") |
1396 | } |
1397 | } |
1398 | |
1399 | === modified file 'src/imports/ContactView/ContactView.qml' |
1400 | --- src/imports/ContactView/ContactView.qml 2014-06-11 21:25:08 +0000 |
1401 | +++ src/imports/ContactView/ContactView.qml 2014-06-18 21:27:19 +0000 |
1402 | @@ -67,7 +67,7 @@ |
1403 | anchors.fill: parent |
1404 | //WORKAROUND: There is a bug on SDK page that causes the page to appear flicked with small contents |
1405 | // see bug #1223050 |
1406 | - contentHeight: Math.max(contents.height, parent.height) |
1407 | + contentHeight: Math.max(contents.height, parent.height) + units.gu(2) |
1408 | contentWidth: parent.width |
1409 | visible: !busyIndicator.visible |
1410 | |
1411 | @@ -77,27 +77,16 @@ |
1412 | height: childrenRect.height |
1413 | anchors { |
1414 | top: parent.top |
1415 | + topMargin: units.gu(2) |
1416 | left: parent.left |
1417 | right: parent.right |
1418 | } |
1419 | |
1420 | ContactDetailAvatarView { |
1421 | contact: root.contact |
1422 | - anchors { |
1423 | - left: parent.left |
1424 | - right: parent.right |
1425 | - } |
1426 | + anchors.left: parent.left |
1427 | height: implicitHeight |
1428 | - ContactDetailFavoriteView { |
1429 | - contact: root.contact |
1430 | - anchors { |
1431 | - left: parent.left |
1432 | - bottom: parent.bottom |
1433 | - margins: units.gu(2) |
1434 | - } |
1435 | - width: units.gu(4) |
1436 | - height: units.gu(4) |
1437 | - } |
1438 | + width: implicitWidth |
1439 | } |
1440 | |
1441 | ContactDetailPhoneNumbersView { |
1442 | @@ -202,15 +191,28 @@ |
1443 | tools: ToolbarItems { |
1444 | ToolbarButton { |
1445 | action: Action { |
1446 | - objectName: "share" |
1447 | - text: i18n.tr("Share") |
1448 | - iconName: "share" |
1449 | + objectName: "favorite" |
1450 | + text: i18n.tr("Favorite") |
1451 | + iconName: root.contact && root.contact.favorite.favorite ? "favorite-selected" : "favorite-unselected" |
1452 | onTriggered: { |
1453 | - pageStack.push(Qt.resolvedUrl("../ContactShare/ContactSharePage.qml"), |
1454 | - { contactModel: root.model, contact: root.contact}) |
1455 | + root.contact.favorite.favorite = !root.contact.favorite.favorite |
1456 | + root.contact.save() |
1457 | } |
1458 | } |
1459 | } |
1460 | + // FIXME: Having more than 3 options in the header causes a bug that make difficult to reach the component behind it. |
1461 | + // Enable it again when the bug #1329557 get fix |
1462 | +// ToolbarButton { |
1463 | +// action: Action { |
1464 | +// objectName: "share" |
1465 | +// text: i18n.tr("Share") |
1466 | +// iconName: "share" |
1467 | +// onTriggered: { |
1468 | +// pageStack.push(Qt.resolvedUrl("../ContactShare/ContactSharePage.qml"), |
1469 | +// { contactModel: root.model, contact: root.contact}) |
1470 | +// } |
1471 | +// } |
1472 | +// } |
1473 | ToolbarButton { |
1474 | action: Action { |
1475 | objectName: "edit" |
1476 | |
1477 | === modified file 'src/imports/Ubuntu/Contacts/ContactAvatar.qml' |
1478 | --- src/imports/Ubuntu/Contacts/ContactAvatar.qml 2014-06-06 17:52:58 +0000 |
1479 | +++ src/imports/Ubuntu/Contacts/ContactAvatar.qml 2014-06-18 21:27:19 +0000 |
1480 | @@ -24,7 +24,14 @@ |
1481 | |
1482 | property var contactElement: null |
1483 | property string displayName: ContactsJS.formatToDisplay(contactElement, ContactDetail.Name, [Name.FirstName, Name.LastName]) |
1484 | + readonly property string defaultAvatar: "image://theme/contact" |
1485 | readonly property string avatarUrl: ContactsJS.getAvatar(contactElement, "") |
1486 | + readonly property bool useDefaultAvatar: (displayName === "" || contact.tag.tag === "") && (avatarUrl === "") |
1487 | + |
1488 | + function reload() |
1489 | + { |
1490 | + img.source = ContactsJS.getAvatar(contactElement, "") |
1491 | + } |
1492 | |
1493 | radius: "medium" |
1494 | color: Theme.palette.normal.overlay |
1495 | @@ -34,13 +41,16 @@ |
1496 | text: ContactsJS.getNameItials(displayName) |
1497 | font.pointSize: 88 |
1498 | color: UbuntuColors.lightAubergine |
1499 | - visible: avatarUrl === "" |
1500 | + visible: (img.status != Image.Ready) |
1501 | } |
1502 | |
1503 | image: Image { |
1504 | + id: img |
1505 | + |
1506 | fillMode: Image.PreserveAspectCrop |
1507 | asynchronous: true |
1508 | - source: avatarUrl |
1509 | - visible: source !== "" |
1510 | + source: avatar.useDefaultAvatar ? avatar.defaultAvatar : avatar.avatarUrl |
1511 | + height: avatar.height |
1512 | + width: avatar.width |
1513 | } |
1514 | } |
1515 | |
1516 | === modified file 'src/imports/Ubuntu/Contacts/ContactDelegate.qml' |
1517 | --- src/imports/Ubuntu/Contacts/ContactDelegate.qml 2014-06-06 22:40:23 +0000 |
1518 | +++ src/imports/Ubuntu/Contacts/ContactDelegate.qml 2014-06-18 21:27:19 +0000 |
1519 | @@ -154,8 +154,7 @@ |
1520 | |
1521 | onStatusChanged: { |
1522 | if (status == Loader.Ready) { |
1523 | - pickerLoader.item.contactsModel = listModel |
1524 | - pickerLoader.item.contactId = contact.contactId |
1525 | + pickerLoader.item.updateDetails(contact) |
1526 | pickerLoader.item.detailClicked.connect(root._onDetailClicked) |
1527 | } |
1528 | } |
1529 | |
1530 | === modified file 'src/imports/Ubuntu/Contacts/ContactDetailPickerPhoneNumberDelegate.qml' |
1531 | --- src/imports/Ubuntu/Contacts/ContactDetailPickerPhoneNumberDelegate.qml 2014-06-06 20:14:24 +0000 |
1532 | +++ src/imports/Ubuntu/Contacts/ContactDetailPickerPhoneNumberDelegate.qml 2014-06-18 21:27:19 +0000 |
1533 | @@ -21,9 +21,6 @@ |
1534 | Item { |
1535 | id: root |
1536 | |
1537 | - property string contactId |
1538 | - property alias contactsModel: contactFetch.model |
1539 | - |
1540 | signal detailClicked(QtObject detail, string action) |
1541 | |
1542 | function containsPointer(item, point) |
1543 | @@ -32,9 +29,12 @@ |
1544 | (point.y >= item.y) && (point.y <= item.y + item.height)); |
1545 | } |
1546 | |
1547 | + function updateDetails(contact) |
1548 | + { |
1549 | + phoneNumberEntries.model = contact.phoneNumbers |
1550 | + } |
1551 | + |
1552 | height: detailItems.height + units.gu(2) |
1553 | - onContactIdChanged: contactFetch.fetchContact(contactId) |
1554 | - |
1555 | Column { |
1556 | id: detailItems |
1557 | |
1558 | @@ -48,15 +48,15 @@ |
1559 | |
1560 | ListItem.Standard { |
1561 | id: noNumberMessage |
1562 | - |
1563 | showDivider: false |
1564 | text: "No phone numbers." |
1565 | - visible: false |
1566 | + visible: phoneNumberEntries.count == 0 |
1567 | } |
1568 | |
1569 | Repeater { |
1570 | id: phoneNumberEntries |
1571 | |
1572 | + model: contact.phoneNumbers |
1573 | ListItem.Subtitled { |
1574 | anchors { |
1575 | left: parent.left |
1576 | @@ -119,14 +119,4 @@ |
1577 | ContactDetailPhoneNumberTypeModel { |
1578 | id: phoneTypeModel |
1579 | } |
1580 | - |
1581 | - ContactFetch { |
1582 | - id: contactFetch |
1583 | - |
1584 | - // do not keep track of contact to avoid problems during the delete destruction |
1585 | - onContactFetched: { |
1586 | - phoneNumberEntries.model = contact.phoneNumbers |
1587 | - noNumberMessage.visible = (contact.phoneNumbers.length === 0) |
1588 | - } |
1589 | - } |
1590 | } |
1591 | |
1592 | === modified file 'src/imports/Ubuntu/Contacts/ContactListView.qml' |
1593 | --- src/imports/Ubuntu/Contacts/ContactListView.qml 2014-06-12 12:49:51 +0000 |
1594 | +++ src/imports/Ubuntu/Contacts/ContactListView.qml 2014-06-18 21:27:19 +0000 |
1595 | @@ -481,6 +481,11 @@ |
1596 | //new contacts as soon as it arrives in the model |
1597 | if (contactsModel._clearModel && contacts.length === 0) { |
1598 | contactsModel._clearModel = false |
1599 | + // do a new update if autoUpdate is false |
1600 | + if (!contactsModel.autoUpdate) { |
1601 | + contactsModel.update() |
1602 | + } |
1603 | + |
1604 | } |
1605 | } |
1606 | } |
1607 | |
1608 | === modified file 'src/imports/Ubuntu/Contacts/ContactSimpleListView.qml' |
1609 | --- src/imports/Ubuntu/Contacts/ContactSimpleListView.qml 2014-06-09 15:52:06 +0000 |
1610 | +++ src/imports/Ubuntu/Contacts/ContactSimpleListView.qml 2014-06-18 21:27:19 +0000 |
1611 | @@ -99,7 +99,9 @@ |
1612 | */ |
1613 | property var fetchHint : FetchHint { |
1614 | detailTypesHint: { |
1615 | - var hints = [ ContactDetail.Tag, contactListView.titleDetail ] |
1616 | + var hints = [ ContactDetail.Tag, // sections |
1617 | + ContactDetail.PhoneNumber, // expansion |
1618 | + contactListView.titleDetail ] |
1619 | |
1620 | if (contactListView.showAvatar) { |
1621 | hints.push(ContactDetail.Avatar) |
1622 | |
1623 | === modified file 'src/imports/Ubuntu/Contacts/MultipleSelectionListView.qml' |
1624 | --- src/imports/Ubuntu/Contacts/MultipleSelectionListView.qml 2014-06-06 17:52:58 +0000 |
1625 | +++ src/imports/Ubuntu/Contacts/MultipleSelectionListView.qml 2014-06-18 21:27:19 +0000 |
1626 | @@ -55,7 +55,7 @@ |
1627 | \endqml |
1628 | */ |
1629 | |
1630 | -UbuntuListView { |
1631 | +ListView { |
1632 | id: listView |
1633 | |
1634 | /*! |
1635 | @@ -188,4 +188,12 @@ |
1636 | MultipleSelectionVisualModel { |
1637 | id: visualModel |
1638 | } |
1639 | + |
1640 | + Component.onCompleted: { |
1641 | + // FIXME: workaround for qtubuntu not returning values depending on the grid unit definition |
1642 | + // for Flickable.maximumFlickVelocity and Flickable.flickDeceleration |
1643 | + var scaleFactor = units.gridUnit / 8; |
1644 | + maximumFlickVelocity = maximumFlickVelocity * scaleFactor; |
1645 | + flickDeceleration = flickDeceleration * scaleFactor; |
1646 | + } |
1647 | } |
1648 | |
1649 | === modified file 'tests/autopilot/address_book_app/pages/_contact_editor.py' |
1650 | --- tests/autopilot/address_book_app/pages/_contact_editor.py 2014-05-22 12:50:28 +0000 |
1651 | +++ tests/autopilot/address_book_app/pages/_contact_editor.py 2014-06-18 21:27:19 +0000 |
1652 | @@ -51,6 +51,36 @@ |
1653 | class ContactEditor(_common.PageWithHeader): |
1654 | """Custom proxy object for the Contact Editor.""" |
1655 | |
1656 | + _DETAIL_ALIAS = { |
1657 | + 'phones': 'Phone', |
1658 | + 'emails': 'Email', |
1659 | + 'ims': 'Social', |
1660 | + 'addresses': 'Address', |
1661 | + 'professionalDetails': 'Professional Details' |
1662 | + } |
1663 | + |
1664 | + @autopilot.logging.log_action(logger.info) |
1665 | + def add_field(self, detail_name): |
1666 | + """Create a new field into the edit contact form. |
1667 | + |
1668 | + :param detail_name: The detail field name |
1669 | + |
1670 | + """ |
1671 | + |
1672 | + add_field_button = self.select_single( |
1673 | + 'Button', objectName='addNewFieldButton') |
1674 | + add_field_button.swipe_into_view() |
1675 | + |
1676 | + self.pointing_device.click_object(add_field_button) |
1677 | + |
1678 | + add_field_dialog = self.get_root_instance().wait_select_single( |
1679 | + 'Dialog', objectName='addFieldDialog') |
1680 | + new_field_button = add_field_dialog.select_single( |
1681 | + 'Button', |
1682 | + objectName=self._DETAIL_ALIAS[detail_name]) |
1683 | + |
1684 | + self.pointing_device.click_object(new_field_button) |
1685 | + |
1686 | @autopilot.logging.log_action(logger.info) |
1687 | def fill_form(self, contact_information): |
1688 | """Fill the edit contact form. |
1689 | @@ -90,7 +120,7 @@ |
1690 | def _fill_detail_group(self, object_name, details): |
1691 | editor = self.select_single( |
1692 | ContactDetailGroupWithTypeEditor, objectName=object_name) |
1693 | - editor.fill(details) |
1694 | + editor.fill(self, details) |
1695 | |
1696 | def _get_form_values(self): |
1697 | first_name = _get_text_field(self, 'first_name').text |
1698 | @@ -135,12 +165,12 @@ |
1699 | 'professionalDetails': 'base_unknown_{}' |
1700 | } |
1701 | |
1702 | - def fill(self, details): |
1703 | + def fill(self, editor, details): |
1704 | """Fill a contact detail group.""" |
1705 | - for index, detail in enumerate(details[:-1]): |
1706 | + for index, detail in enumerate(details): |
1707 | + if self.detailsCount <= index: |
1708 | + editor.add_field(self.objectName) |
1709 | self._fill_detail(index, detail) |
1710 | - self._add_detail() |
1711 | - self._fill_detail(len(details) - 1, details[-1]) |
1712 | |
1713 | def _fill_detail(self, index, detail): |
1714 | detail_editor = self._get_detail_editor_by_index(index) |
1715 | @@ -175,15 +205,16 @@ |
1716 | """Custom proxy object for the ContactDetailWithTypeEditor widget.""" |
1717 | |
1718 | def fill(self, field, index, detail): |
1719 | + self._fill_value(field, index, detail) |
1720 | self._select_type(detail) |
1721 | - self._fill_value(field, index, detail) |
1722 | |
1723 | def _select_type(self, detail): |
1724 | type_index = detail.TYPES.index(detail.type) |
1725 | - selected_type_index = self._get_selected_type_index() |
1726 | - if type_index != selected_type_index: |
1727 | - # TODO --elopio - 2014-03-01 |
1728 | - raise NotImplementedError('Type selection not yet implemented.') |
1729 | + value_selector = self.select_single('ValueSelector') |
1730 | + |
1731 | + while(value_selector.currentIndex != type_index): |
1732 | + ubuntuuitoolkit.get_keyboard().press_and_release("Shift+Right") |
1733 | + time.sleep(0.1) |
1734 | |
1735 | def _get_selected_type_index(self): |
1736 | value_selector = self.select_single('ValueSelector') |
1737 | @@ -210,16 +241,7 @@ |
1738 | self._make_field_visible_and_write(text_field, value) |
1739 | |
1740 | def _make_field_visible_and_write(self, text_field, value): |
1741 | - while not text_field.activeFocus: |
1742 | - # XXX We should just swipe the text field into view. |
1743 | - # Update this once bug http://pad.lv/1286479 is implemented. |
1744 | - # --elopio - 2014-03-01 |
1745 | - text_field.keyboard.press_and_release('Tab') |
1746 | - time.sleep(0.1) |
1747 | - contact_editor = self.get_root_instance().select_single( |
1748 | - ContactEditor, objectName='contactEditorPage', active=True) |
1749 | - contact_editor.wait_to_stop_moving() |
1750 | - |
1751 | + text_field.swipe_into_view() |
1752 | text_field.write(value) |
1753 | |
1754 | def _fill_address(self, index, address): |
1755 | |
1756 | === modified file 'tests/autopilot/address_book_app/tests/__init__.py' |
1757 | --- tests/autopilot/address_book_app/tests/__init__.py 2014-06-06 22:40:23 +0000 |
1758 | +++ tests/autopilot/address_book_app/tests/__init__.py 2014-06-18 21:27:19 +0000 |
1759 | @@ -143,6 +143,7 @@ |
1760 | self.pointing_device.click_object(clear_button) |
1761 | self.assertThat(field.text, Eventually(Equals(""))) |
1762 | |
1763 | + # FIXME: Remove this function use ContactEditor.add_field |
1764 | def create_new_detail(self, detailGroup): |
1765 | detCount = detailGroup.detailsCount |
1766 | add_button = detailGroup.select_single("Icon", |
1767 | @@ -155,17 +156,12 @@ |
1768 | list_page = self.main_window.get_contact_list_page() |
1769 | list_page.open_contact(index) |
1770 | |
1771 | - list_page = self.main_window.get_contact_list_page() |
1772 | self.assertThat(list_page.visible, Eventually(Equals(False))) |
1773 | - |
1774 | view_page = self.main_window.get_contact_view_page() |
1775 | self.assertThat(view_page.visible, Eventually(Equals(True))) |
1776 | |
1777 | # Edit contact |
1778 | - self.main_window.get_header().click_action_button("edit") |
1779 | - self.assertThat(view_page.visible, Eventually(Equals(False))) |
1780 | - |
1781 | - edit_page = self.main_window.get_contact_edit_page() |
1782 | + edit_page = view_page.go_to_edit_contact() |
1783 | self.assertThat(edit_page.visible, Eventually(Equals(True))) |
1784 | |
1785 | return edit_page |
1786 | |
1787 | === modified file 'tests/autopilot/address_book_app/tests/test_add_contact.py' |
1788 | --- tests/autopilot/address_book_app/tests/test_add_contact.py 2014-06-08 13:51:45 +0000 |
1789 | +++ tests/autopilot/address_book_app/tests/test_add_contact.py 2014-06-18 21:27:19 +0000 |
1790 | @@ -173,28 +173,23 @@ |
1791 | self.assertThat(list_view.count, Eventually(Equals(1))) |
1792 | |
1793 | def test_email_label_save(self): |
1794 | - # execute add new contact |
1795 | contact_editor = self.app.main_window.go_to_add_contact() |
1796 | |
1797 | - # fill name |
1798 | - contact_editor.fill_form( |
1799 | - data.Contact(first_name='Sherlock', last_name='Holmes')) |
1800 | + my_emails = [] |
1801 | + my_emails.append(data.Email(type_="Home", address="home@email.com")) |
1802 | + my_emails.append(data.Email(type_="Work", address="work@email.com")) |
1803 | + my_emails.append(data.Email(type_="Other", address="other@email.com")) |
1804 | |
1805 | - # Home |
1806 | - self.set_email_address(0, "home@email.com", 0) |
1807 | - # Work |
1808 | - self.set_email_address(1, "work@email.com", 1) |
1809 | - # Other |
1810 | - self.set_email_address(2, "other@email.com", 2) |
1811 | + test_contact = data.Contact(first_name="Sherlock", |
1812 | + last_name="Holmes", |
1813 | + emails=my_emails) |
1814 | + contact_editor.fill_form(test_contact) |
1815 | |
1816 | # Save contact |
1817 | self.app.main_window.save() |
1818 | |
1819 | list_page = self.app.main_window.get_contact_list_page() |
1820 | - list_page.open_contact(0) |
1821 | - |
1822 | - # check if contacts was saved with the correct labels |
1823 | - view_page = self.app.main_window.get_contact_view_page() |
1824 | + view_page = list_page.open_contact(0) |
1825 | self.assertThat(view_page.visible, Eventually(Equals(True))) |
1826 | |
1827 | # check if we have 3 emails""" |
1828 | @@ -223,33 +218,26 @@ |
1829 | self.assertThat(len(emails), Equals(0)) |
1830 | |
1831 | def test_phone_label_save(self): |
1832 | - # execute add new contact |
1833 | contact_editor = self.app.main_window.go_to_add_contact() |
1834 | |
1835 | - # fill name |
1836 | - contact_editor.fill_form( |
1837 | - data.Contact(first_name='Sherlock', last_name='Holmes')) |
1838 | + my_phones = [] |
1839 | + my_phones.append(data.Phone(type_="Home", number="(000) 000-0000")) |
1840 | + my_phones.append(data.Phone(type_="Work", number="(000) 000-0001")) |
1841 | + my_phones.append(data.Phone(type_="Mobile", number="(000) 000-0002")) |
1842 | + my_phones.append(data.Phone(type_="Work Mobile", number="(000) 000-0003")) |
1843 | + my_phones.append(data.Phone(type_="Other", number="(000) 000-0004")) |
1844 | |
1845 | - # Home |
1846 | - self.set_phone_number(0, "(000) 000-0000", 0) |
1847 | - # Work |
1848 | - self.set_phone_number(1, "(000) 000-0001", 1) |
1849 | - # Mobile |
1850 | - self.set_phone_number(2, "(000) 000-0002", 2) |
1851 | - # Work Mobile |
1852 | - self.set_phone_number(3, "(000) 000-0003", 3) |
1853 | - # Other |
1854 | - self.set_phone_number(4, "(000) 000-0004", 4) |
1855 | + test_contact = data.Contact(first_name="Sherlock", |
1856 | + last_name="Holmes", |
1857 | + phones=my_phones) |
1858 | + contact_editor.fill_form(test_contact) |
1859 | |
1860 | # Save contact |
1861 | self.app.main_window.save() |
1862 | |
1863 | # Open contact view |
1864 | list_page = self.app.main_window.get_contact_list_page() |
1865 | - list_page.open_contact(0) |
1866 | - |
1867 | - # check if contacts was saved with the correct labels |
1868 | - view_page = self.app.main_window.get_contact_view_page() |
1869 | + view_page = list_page.open_contact(0) |
1870 | self.assertThat(view_page.visible, Eventually(Equals(True))) |
1871 | |
1872 | # check if we have five phones""" |
1873 | |
1874 | === modified file 'tests/autopilot/address_book_app/tests/test_edit_contact.py' |
1875 | --- tests/autopilot/address_book_app/tests/test_edit_contact.py 2014-05-30 07:11:42 +0000 |
1876 | +++ tests/autopilot/address_book_app/tests/test_edit_contact.py 2014-06-18 21:27:19 +0000 |
1877 | @@ -37,10 +37,7 @@ |
1878 | edit_page = self.edit_contact(0) |
1879 | |
1880 | # Add a new phone |
1881 | - phoneGroup = edit_page.select_single( |
1882 | - "ContactDetailGroupWithTypeEditor", |
1883 | - objectName="phones") |
1884 | - self.create_new_detail(phoneGroup) |
1885 | + edit_page.add_field('phones') |
1886 | |
1887 | # fill phone number |
1888 | phone_number_1 = self.app.main_window.select_single( |
1889 | @@ -67,11 +64,18 @@ |
1890 | self.assertThat(phone_label_1.text, Eventually(Equals(self.PHONE_NUMBERS[1]))) |
1891 | |
1892 | def test_remove_phone(self): |
1893 | - self.add_contact("Fulano", "de Tal", self.PHONE_NUMBERS[1:3]) |
1894 | - edit_page = self.edit_contact(0) |
1895 | + contact_editor = self.app.main_window.go_to_add_contact() |
1896 | + my_phones = [] |
1897 | + for n in self.PHONE_NUMBERS[1:3]: |
1898 | + my_phones.append(data.Phone(type_='Mobile', number=n)) |
1899 | + |
1900 | + test_contact = data.Contact(first_name="Fulano", |
1901 | + last_name="de Tal", |
1902 | + phones=my_phones) |
1903 | + contact_editor.fill_form(test_contact) |
1904 | |
1905 | # clear phone 1 |
1906 | - phone_number_1 = edit_page.select_single( |
1907 | + phone_number_1 = contact_editor.wait_select_single( |
1908 | "TextInputDetail", |
1909 | objectName="phoneNumber_1") |
1910 | self.clear_text_on_field(phone_number_1) |
1911 | @@ -79,8 +83,11 @@ |
1912 | # Save contact |
1913 | self.app.main_window.save() |
1914 | |
1915 | + # Go to contact view |
1916 | + list_page = self.main_window.get_contact_list_page() |
1917 | + |
1918 | # check if we have onlye one phone |
1919 | - view_page = self.app.main_window.get_contact_view_page() |
1920 | + view_page = list_page.open_contact(0) |
1921 | phone_group = view_page.select_single( |
1922 | "ContactDetailGroupWithTypeView", |
1923 | objectName="phones") |
1924 | @@ -95,11 +102,7 @@ |
1925 | def test_add_email(self): |
1926 | self.add_contact("Fulano", "") |
1927 | edit_page = self.edit_contact(0) |
1928 | - |
1929 | - emailGroup = edit_page.select_single( |
1930 | - "ContactDetailGroupWithTypeEditor", |
1931 | - objectName="emails") |
1932 | - self.create_new_detail(emailGroup) |
1933 | + edit_page.add_field("emails") |
1934 | |
1935 | # fill email address |
1936 | email_field = edit_page.select_single( |
1937 | @@ -174,7 +177,17 @@ |
1938 | self.assertThat(view_page.title, Eventually(Equals("Fulano de Tal"))) |
1939 | |
1940 | def test_im_type(self): |
1941 | - self.add_contact("Fulano", "de Tal", im_address=["im@account.com"]) |
1942 | + contact_editor = self.app.main_window.go_to_add_contact() |
1943 | + alias = data.SocialAlias(type_="Skype", alias="im@account.com") |
1944 | + test_contact = data.Contact(first_name="Fulano", |
1945 | + last_name="de Tal", |
1946 | + social_aliases=[alias]) |
1947 | + contact_editor.fill_form(test_contact) |
1948 | + |
1949 | + # Save contact |
1950 | + self.app.main_window.save() |
1951 | + |
1952 | + # edit again |
1953 | edit_page = self.edit_contact(0) |
1954 | |
1955 | # Change Im type |
FAILED: Continuous integration, rev:191 jenkins. qa.ubuntu. com/job/ address- book-app- ci/589/ jenkins. qa.ubuntu. com/job/ address- book-app- utopic- amd64-ci/ 42 jenkins. qa.ubuntu. com/job/ address- book-app- utopic- armhf-ci/ 42 jenkins. qa.ubuntu. com/job/ address- book-app- utopic- armhf-ci/ 42/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ address- book-app- utopic- i386-ci/ 42 jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- utopic- touch/1014 jenkins. qa.ubuntu. com/job/ generic- mediumtests- utopic/ 915 jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- runner- mako/1396 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/1786 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/1786/ artifact/ work/output/ *zip*/output. zip s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 8602 jenkins. qa.ubuntu. com/job/ autopilot- testrunner- otto-utopic/ 790 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- amd64/1057 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- amd64/1057/ artifact/ work/output/ *zip*/output. zip
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/address- book-app- ci/589/ rebuild
http://