Merge lp:~renatofilho/address-book-app/improve-vcard-import into lp:address-book-app

Proposed by Renato Araujo Oliveira Filho
Status: Merged
Approved by: Arthur Mello
Approved revision: 516
Merged at revision: 510
Proposed branch: lp:~renatofilho/address-book-app/improve-vcard-import
Merge into: lp:address-book-app
Prerequisite: lp:~renatofilho/address-book-app/fix-1511477
Diff against target: 424 lines (+183/-116)
6 files modified
src/imports/ABContactListPage.qml (+136/-20)
src/imports/CMakeLists.txt (+0/-1)
src/imports/VCardImportDialog.qml (+0/-94)
tests/autopilot/address_book_app/tests/__init__.py (+5/-1)
tests/autopilot/address_book_app/tests/test_import_from_sim.py (+3/-0)
tests/autopilot/address_book_app/tests/test_import_vcard.py (+39/-0)
To merge this branch: bzr merge lp:~renatofilho/address-book-app/improve-vcard-import
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Arthur Mello (community) Approve
Review via email: mp+278165@code.launchpad.net

This proposal supersedes a proposal from 2015-11-18.

Commit message

Show a list of imported contacts when importing vcards.

Description of the change

Test vcard import
  Import a vcard into contacts app using content-hub:
  You can use gmail webapp or messaging app to receive vcards on the phone.
  Test if a list with imported contacts appear
  Test if the imported contact was imported to default address-book.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
504. By Renato Araujo Oliveira Filho

Merged: ~renatofilho/address-book-app/vcard-does-not-export-uid

505. By Renato Araujo Oliveira Filho

Merged: ~renatofilho/address-book-app/contact-view-editable

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
506. By Renato Araujo Oliveira Filho

Does not reset contact list state after edit a contact while importing contacts.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
507. By Renato Araujo Oliveira Filho

Show a 'busy' dialog while importing contacts.

508. By Renato Araujo Oliveira Filho

Make sure that the contact list is cleared before apply a new filter to avoid delays on contact populte.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
509. By Renato Araujo Oliveira Filho

Trunk merged.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
510. By Renato Araujo Oliveira Filho

Trunk merged.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
511. By Renato Araujo Oliveira Filho

Show a error message if the contact import fails.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
512. By Renato Araujo Oliveira Filho

Test import vcard.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Arthur Mello (artmello) :
513. By Renato Araujo Oliveira Filho

Typo fixed.

514. By Renato Araujo Oliveira Filho

Only try to stop maliit if it is running already.

Revision history for this message
Arthur Mello (artmello) wrote :

lgtm

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
515. By Renato Araujo Oliveira Filho

Avoid switch to importVcard state while loading test data.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
516. By Renato Araujo Oliveira Filho

Update import from sim autopilot test.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/imports/ABContactListPage.qml'
2--- src/imports/ABContactListPage.qml 2015-11-24 00:30:20 +0000
3+++ src/imports/ABContactListPage.qml 2015-11-25 18:33:17 +0000
4@@ -38,6 +38,8 @@
5 property alias contactManager: contactList.manager
6 property Page contactViewPage: null
7 property Page contactEditorPage: null
8+ property var _busyDialog: null
9+ property bool _importingTestData: false
10
11 readonly property bool bottomEdgePageOpened: bottomEdge.opened && bottomEdge.fullLoaded
12 readonly property bool isEmpty: (contactList.count === 0)
13@@ -84,7 +86,8 @@
14 function showContact(contact)
15 {
16 // go back to normal state if not searching
17- if (state !== "searching") {
18+ if ((state !== "searching") &&
19+ (state !== "vcardImported")) {
20 mainPage.state = "default";
21 }
22 openViewPage({model: contactList.listModel,
23@@ -106,14 +109,21 @@
24
25 function importContact(urls)
26 {
27- if (urls.length > 0) {
28- var importDialog = Qt.createQmlObject("VCardImportDialog{}",
29- mainPage,
30- "VCardImportDialog")
31- if (importDialog) {
32- importDialog.importVCards(contactList.listModel, urls)
33+ mainPage._busyDialog = PopupUtils.open(busyDialogComponent, mainPage)
34+
35+ var importing = false
36+ for(var i=0, iMax=urls.length; i < iMax; i++) {
37+ var url = urls[i]
38+ if (url && url != "") {
39+ importing = true
40+ contactList.listModel.importContacts(url)
41 }
42 }
43+
44+ if (!importing) {
45+ PopupUtils.close(mainPage._busyDialog)
46+ mainPage._busyDialog = null
47+ }
48 }
49
50 function startPickMode(isSingleSelection, activeTransfer)
51@@ -126,8 +136,9 @@
52
53 function moveListToContact(contact)
54 {
55- // skipt it if searching
56- if (state === "searching") {
57+ // skipt it if searching or importing contacts
58+ if ((state === "searching") ||
59+ (state === "vcardImported")) {
60 return
61 }
62
63@@ -428,6 +439,53 @@
64 detailToPick: -1
65 showAddNewButton: true
66 }
67+ PropertyChanges {
68+ target: bottomEdge
69+ enabled: false
70+ }
71+ },
72+ PageHeadState {
73+ id: vcardImportedState
74+
75+ name: "vcardImported"
76+ backAction: Action {
77+ iconName: "back"
78+ text: i18n.tr("Back")
79+ onTriggered: {
80+ contactList.forceActiveFocus()
81+ mainPage.state = "default"
82+ importedIdsFilter.ids = []
83+ }
84+ }
85+ PropertyChanges {
86+ target: mainPage.head
87+ backAction: vcardImportedState.backAction
88+ }
89+ PropertyChanges {
90+ target: bottomEdge
91+ enabled: false
92+ }
93+ PropertyChanges {
94+ target: mainPage
95+ title: i18n.tr("Imported contacts")
96+ }
97+ }
98+ ]
99+
100+ //WORKAROUND: we need to call 'changeFilter' manually to make sure that the model will be cleared
101+ // before update it with the new model. This is faster than do a match of contacts
102+ transitions: [
103+ Transition {
104+ from: "vcardImported"
105+ ScriptAction {
106+ script: contactList.listModel.changeFilter(null)
107+ }
108+ },
109+ Transition {
110+ to: "vcardImported"
111+ ScriptAction {
112+ script: contactList.listModel.changeFilter(importedIdsFilter)
113+ }
114 }
115 ]
116
117@@ -440,6 +498,10 @@
118 }
119 }
120
121+ IdFilter {
122+ id: importedIdsFilter
123+ }
124+
125 KeyboardRectangle {
126 id: keyboard
127 }
128@@ -492,16 +554,6 @@
129 }
130 }
131
132- Connections {
133- target: mainPage.contactModel
134- onContactsChanged: {
135- if (contactIndex) {
136- contactList.positionViewAtContact(mainPage.contactIndex)
137- mainPage.contactIndex = null
138- }
139- }
140- }
141-
142 ContactExporter {
143 id: contactExporter
144
145@@ -543,6 +595,35 @@
146 }
147
148 Component {
149+ id: busyDialogComponent
150+
151+ Popups.Dialog {
152+ id: busyDialog
153+
154+ property alias allowToClose: closeButton.visible
155+ property alias showActivity: busyIndicator.visible
156+
157+ title: i18n.tr("Importing...")
158+
159+ ActivityIndicator {
160+ id: busyIndicator
161+ running: visible
162+ visible: true
163+ }
164+ Button {
165+ id: closeButton
166+ text: i18n.tr("Close")
167+ visible: false
168+ color: UbuntuColors.red
169+ onClicked: {
170+ PopupUtils.close(mainPage._busyDialog)
171+ mainPage._busyDialog = null
172+ }
173+ }
174+ }
175+ }
176+
177+ Component {
178 id: contactShareComponent
179
180 ContactSharePage {
181@@ -552,7 +633,8 @@
182
183 Component.onCompleted: {
184 application.elapsed()
185- if ((typeof(TEST_DATA) !== "undefined") && (TEST_DATA !== "")) {
186+ if ((typeof(TEST_DATA) !== "undefined") && (TEST_DATA != "")) {
187+ mainPage._importingTestData = true
188 contactList.listModel.importContacts("file://" + TEST_DATA)
189 }
190
191@@ -661,6 +743,40 @@
192 }
193
194 Connections {
195+ target: mainPage.contactModel
196+ onContactsChanged: {
197+ if (contactIndex) {
198+ contactList.positionViewAtContact(mainPage.contactIndex)
199+ mainPage.contactIndex = null
200+ }
201+ }
202+ onImportCompleted: {
203+ if (mainPage._importingTestData) {
204+ mainPage._importingTestData = false
205+ return
206+ }
207+
208+ if (error !== ContactModel.ImportNoError) {
209+ console.error("Fail to import vcard:" + error)
210+ mainPage._busyDialog.title = i18n.tr("Fail to import contacts!")
211+ mainPage._busyDialog.allowToClose = true
212+ mainPage._busyDialog.showActivity = false
213+ } else {
214+ var importedIds = ids
215+ importedIds.concat(importedIdsFilter.ids)
216+ importedIdsFilter.ids = importedIds
217+ console.debug("Imported ids:" + importedIds)
218+ mainPage.state = "vcardImported"
219+
220+ if (mainPage._busyDialog) {
221+ PopupUtils.close(mainPage._busyDialog)
222+ mainPage._busyDialog = null
223+ }
224+ }
225+ }
226+ }
227+
228+ Connections {
229 target: mainPage.contactViewPage
230 onEditContact: {
231 openEditPage(editPageProperties, mainPage.contactViewPage);
232
233=== modified file 'src/imports/CMakeLists.txt'
234--- src/imports/CMakeLists.txt 2015-10-16 13:37:25 +0000
235+++ src/imports/CMakeLists.txt 2015-11-25 18:33:17 +0000
236@@ -6,7 +6,6 @@
237 ABContactViewPage.qml
238 ContentHubProxy.qml
239 MainWindow.qml
240- VCardImportDialog.qml
241 BottomEdgeShadow.qml
242 BottomEdge.qml
243 )
244
245=== removed file 'src/imports/VCardImportDialog.qml'
246--- src/imports/VCardImportDialog.qml 2015-10-26 13:18:11 +0000
247+++ src/imports/VCardImportDialog.qml 1970-01-01 00:00:00 +0000
248@@ -1,94 +0,0 @@
249-/*
250- * Copyright (C) 2014 Canonical, Ltd.
251- *
252- * This program is free software; you can redistribute it and/or modify
253- * it under the terms of the GNU General Public License as published by
254- * the Free Software Foundation; version 3.
255- *
256- * This program is distributed in the hope that it will be useful,
257- * but WITHOUT ANY WARRANTY; without even the implied warranty of
258- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
259- * GNU General Public License for more details.
260- *
261- * You should have received a copy of the GNU General Public License
262- * along with this program. If not, see <http://www.gnu.org/licenses/>.
263- */
264-
265-import QtQuick 2.4
266-import QtContacts 5.0
267-import Ubuntu.Components 1.3
268-import Ubuntu.Components.Popups 1.3 as Popups
269-
270-Item {
271- id: root
272-
273- property alias model: modelConnections.target
274- property var vcards: []
275- property var importedVcards: []
276- property var importErrors: []
277- property var dialog: null
278-
279- signal finished()
280-
281- function importVCards(model, vcards)
282- {
283- if (dialog || vcards.length === 0) {
284- return
285- }
286-
287- root.model = model
288- root.vcards = vcards
289- dialog = Popups.PopupUtils.open(importDialogComponent, root)
290-
291- for(var i=0, iMax=vcards.length; i < iMax; i++) {
292- var vcardUrl = vcards[i]
293- model.importContacts(vcardUrl)
294- }
295- }
296-
297- Connections {
298- id: modelConnections
299-
300- onImportCompleted: {
301- var imported = root.importedVcards
302- var importErrors = root.importErrors
303- imported.push(url)
304- if (error !== ContactModel.ImportNoError) {
305- root.importErrors.push(error)
306- console.error("Fail to import vcard:" + error)
307- }
308- root.importedVcards = imported
309- root.importErrors = importErrors
310- }
311- }
312-
313- Component {
314- id: importDialogComponent
315-
316- Popups.Dialog {
317- id: importDialog
318-
319- title: i18n.tr("Import vCards")
320- text: root.importedVcards.length === 0 ? i18n.tr("Importing...") : i18n.tr("%1 vCards imported").arg(root.importedVcards.length)
321-
322- Button {
323- anchors {
324- left: parent.left
325- right: parent.right
326- margins: units.gu(1)
327- }
328- text: i18n.tr("Close")
329- enabled: (root.importedVcards.length === root.vcards.length)
330- onClicked: {
331- root.dialog = null
332- Popups.PopupUtils.close(importDialog)
333- }
334- }
335-
336- Component.onDestruction: root.destroy()
337- }
338- }
339-}
340-
341-
342-
343
344=== modified file 'tests/autopilot/address_book_app/tests/__init__.py'
345--- tests/autopilot/address_book_app/tests/__init__.py 2015-09-29 18:05:25 +0000
346+++ tests/autopilot/address_book_app/tests/__init__.py 2015-11-25 18:33:17 +0000
347@@ -19,6 +19,7 @@
348 import os
349 import time
350 import subprocess
351+import re
352
353 from autopilot.testcase import AutopilotTestCase
354 from autopilot.matchers import Eventually
355@@ -47,7 +48,10 @@
356
357 # stop vkb
358 if model() != "Desktop":
359- subprocess.check_call(["/sbin/initctl", "stop", "maliit-server"])
360+ maliit_info = subprocess.Popen(['/sbin/initctl', 'status', 'maliit-server'], stdout=subprocess.PIPE)
361+ result = maliit_info.stdout.read()
362+ if b'start/running,' in result.split():
363+ subprocess.check_call(['/sbin/initctl', 'stop', 'maliit-server'])
364
365 if 'AUTOPILOT_APP' in os.environ:
366 self.app_bin = os.environ['AUTOPILOT_APP']
367
368=== modified file 'tests/autopilot/address_book_app/tests/test_import_from_sim.py'
369--- tests/autopilot/address_book_app/tests/test_import_from_sim.py 2015-04-30 17:22:48 +0000
370+++ tests/autopilot/address_book_app/tests/test_import_from_sim.py 2015-11-25 18:33:17 +0000
371@@ -70,6 +70,9 @@
372 self.assertThat(len(contacts), Equals(2))
373 self.app.main_window.confirm_import()
374
375+ # dismiss imported contact list
376+ self.app.main_window.cancel()
377+
378 # verify if the contact was imported
379 new_contacts = list_page.get_contacts()
380 self.assertThat(len(new_contacts), Equals(2))
381
382=== added file 'tests/autopilot/address_book_app/tests/test_import_vcard.py'
383--- tests/autopilot/address_book_app/tests/test_import_vcard.py 1970-01-01 00:00:00 +0000
384+++ tests/autopilot/address_book_app/tests/test_import_vcard.py 2015-11-25 18:33:17 +0000
385@@ -0,0 +1,39 @@
386+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
387+# Copyright 2015 Canonical
388+#
389+# This program is free software: you can redistribute it and/or modify it
390+# under the terms of the GNU General Public License version 3, as published
391+# by the Free Software Foundation.
392+
393+"""Tests for the Addressbook App"""
394+
395+from __future__ import absolute_import
396+from testtools.matchers import Equals
397+from autopilot.matchers import Eventually
398+import os
399+
400+from address_book_app.tests import AddressBookAppTestCase
401+
402+
403+class TeseImportVCard(AddressBookAppTestCase):
404+ """Tests import vcard"""
405+
406+ def setUp(self):
407+ vcard_path = AddressBookAppTestCase.VCARD_PATH_DEV
408+ if os.path.exists(AddressBookAppTestCase.VCARD_PATH_BIN):
409+ vcard_path = AddressBookAppTestCase.VCARD_PATH_BIN
410+
411+ self.ARGS.append("addressbook:///importvcard?url=file://%s" % vcard_path)
412+ super(TeseImportVCard, self).setUp()
413+
414+ def test_import_vcard_results(self):
415+ # check if app enter on import state
416+ list_page = self.app.main_window.get_contact_list_page()
417+ self.assertThat(list_page.state, Eventually(Equals('vcardImported')))
418+ self.assertThat(list_page.title, Eventually(Equals('Imported contacts')))
419+ self.assertThat(len(list_page.get_contacts()), Equals(3))
420+
421+ #leave import state and show full contact list
422+ self.app.main_window.cancel()
423+ self.assertThat(list_page.state, Eventually(Equals('default')))
424+ self.assertThat(list_page.title, Eventually(Equals('Contacts')))

Subscribers

People subscribed via source and target branches