Merge lp:~renatofilho/address-book-app/fix-test_import_from_sim into lp:address-book-app

Proposed by Renato Araujo Oliveira Filho
Status: Superseded
Proposed branch: lp:~renatofilho/address-book-app/fix-test_import_from_sim
Merge into: lp:address-book-app
Diff against target: 8750 lines (+3847/-3489)
135 files modified
CMakeLists.txt (+1/-0)
debian/control (+12/-1)
debian/qtdeclarative5-ubuntu-addressbook0.1.install (+4/-0)
src/app/CMakeLists.txt (+0/-2)
src/app/addressbookapp.cpp (+1/-24)
src/app/addressbookapp.h (+1/-2)
src/app/main.cpp (+1/-1)
src/imports/ABContactEditorPage.qml (+56/-0)
src/imports/ABContactListPage.qml (+530/-0)
src/imports/ABContactViewPage.qml (+87/-0)
src/imports/CMakeLists.txt (+3/-5)
src/imports/Common/CMakeLists.txt (+0/-15)
src/imports/Common/ContactDetailItem.qml (+0/-62)
src/imports/Common/ContactExporter.qml (+0/-167)
src/imports/Common/KeyboardRectangle.qml (+0/-74)
src/imports/Common/RemoveContactsDialog.qml (+0/-78)
src/imports/Common/StandardAnimation.qml (+0/-22)
src/imports/ContactEdit/ContactEditor.qml (+0/-461)
src/imports/ContactList/CMakeLists.txt (+0/-11)
src/imports/ContactList/ContactListPage.qml (+0/-554)
src/imports/ContactList/VCardImportDialog.qml (+0/-94)
src/imports/ContactShare/CMakeLists.txt (+0/-10)
src/imports/ContactShare/ContactSharePage.qml (+0/-56)
src/imports/ContactView/ContactView.qml (+0/-123)
src/imports/ContentHubProxy.qml (+1/-1)
src/imports/MainWindow.qml (+1/-2)
src/imports/Ubuntu/AddressBook/Base/CMakeLists.txt (+30/-0)
src/imports/Ubuntu/AddressBook/Base/ContactDetailBase.qml (+112/-0)
src/imports/Ubuntu/AddressBook/Base/ContactDetailGroupBase.qml (+159/-0)
src/imports/Ubuntu/AddressBook/Base/ContactDetailGroupWithTypeBase.qml (+132/-0)
src/imports/Ubuntu/AddressBook/Base/ContactDetailItem.qml (+62/-0)
src/imports/Ubuntu/AddressBook/Base/ContactExporter.qml (+167/-0)
src/imports/Ubuntu/AddressBook/Base/KeyboardRectangle.qml (+70/-0)
src/imports/Ubuntu/AddressBook/Base/RemoveContactsDialog.qml (+78/-0)
src/imports/Ubuntu/AddressBook/Base/qmldir (+9/-0)
src/imports/Ubuntu/AddressBook/CMakeLists.txt (+4/-0)
src/imports/Ubuntu/AddressBook/ContactEditor/CMakeLists.txt (+20/-7)
src/imports/Ubuntu/AddressBook/ContactEditor/ComboButtonAddField.qml (+5/-5)
src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAddressesEditor.qml (+7/-7)
src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAvatarEditor.qml (+7/-1)
src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailEmailsEditor.qml (+3/-3)
src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailGroupWithTypeEditor.qml (+3/-1)
src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailNameEditor.qml (+4/-3)
src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailOnlineAccountsEditor.qml (+3/-3)
src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailOrganizationsEditor.qml (+5/-5)
src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailPhoneNumbersEditor.qml (+3/-3)
src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailSyncTargetEditor.qml (+4/-2)
src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailWithTypeEditor.qml (+3/-1)
src/imports/Ubuntu/AddressBook/ContactEditor/ContactEditorPage.qml (+444/-0)
src/imports/Ubuntu/AddressBook/ContactEditor/TextInputDetail.qml (+2/-2)
src/imports/Ubuntu/AddressBook/ContactEditor/ValueSelector.qml (+1/-1)
src/imports/Ubuntu/AddressBook/ContactEditor/qmldir (+18/-0)
src/imports/Ubuntu/AddressBook/ContactShare/CMakeLists.txt (+26/-0)
src/imports/Ubuntu/AddressBook/ContactShare/ContactSharePage.qml (+60/-0)
src/imports/Ubuntu/AddressBook/ContactShare/qmldir (+3/-0)
src/imports/Ubuntu/AddressBook/ContactView/ActionButton.qml (+34/-0)
src/imports/Ubuntu/AddressBook/ContactView/BasicFieldView.qml (+85/-0)
src/imports/Ubuntu/AddressBook/ContactView/CMakeLists.txt (+32/-7)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailAddressesView.qml (+32/-0)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailAvatarView.qml (+89/-0)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailEmailsView.qml (+29/-0)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailGroupWithTypeView.qml (+66/-0)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailNameView.qml (+2/-2)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailOnlineAccountsView.qml (+31/-0)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailOrganizationsView.qml (+32/-0)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailPhoneNumberView.qml (+94/-0)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailPhoneNumbersView.qml (+41/-0)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailSyncTargetView.qml (+1/-1)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailWithTypeView.qml (+62/-0)
src/imports/Ubuntu/AddressBook/ContactView/ContactFetchError.qml (+5/-8)
src/imports/Ubuntu/AddressBook/ContactView/ContactViewPage.qml (+198/-0)
src/imports/Ubuntu/AddressBook/ContactView/qmldir (+19/-0)
src/imports/Ubuntu/CMakeLists.txt (+3/-1)
src/imports/Ubuntu/Contacts/ActionButton.qml (+1/-1)
src/imports/Ubuntu/Contacts/BasicFieldView.qml (+0/-85)
src/imports/Ubuntu/Contacts/CMakeLists.txt (+4/-18)
src/imports/Ubuntu/Contacts/ContactDelegate.qml (+1/-1)
src/imports/Ubuntu/Contacts/ContactDetailAddressesView.qml (+0/-32)
src/imports/Ubuntu/Contacts/ContactDetailAvatarView.qml (+0/-86)
src/imports/Ubuntu/Contacts/ContactDetailBase.qml (+0/-110)
src/imports/Ubuntu/Contacts/ContactDetailEmailsView.qml (+0/-29)
src/imports/Ubuntu/Contacts/ContactDetailGroupBase.qml (+0/-159)
src/imports/Ubuntu/Contacts/ContactDetailGroupWithTypeBase.qml (+0/-126)
src/imports/Ubuntu/Contacts/ContactDetailGroupWithTypeView.qml (+0/-63)
src/imports/Ubuntu/Contacts/ContactDetailOnlineAccountTypeModel.qml (+1/-1)
src/imports/Ubuntu/Contacts/ContactDetailOnlineAccountsView.qml (+0/-29)
src/imports/Ubuntu/Contacts/ContactDetailOrganizationsView.qml (+0/-32)
src/imports/Ubuntu/Contacts/ContactDetailPhoneNumberTypeModel.qml (+1/-1)
src/imports/Ubuntu/Contacts/ContactDetailPhoneNumberView.qml (+0/-90)
src/imports/Ubuntu/Contacts/ContactDetailPhoneNumbersView.qml (+0/-38)
src/imports/Ubuntu/Contacts/ContactDetailPickerPhoneNumberDelegate.qml (+1/-1)
src/imports/Ubuntu/Contacts/ContactDetailWithTypeView.qml (+0/-60)
src/imports/Ubuntu/Contacts/ContactFetch.qml (+1/-1)
src/imports/Ubuntu/Contacts/ContactList.js (+1/-1)
src/imports/Ubuntu/Contacts/ContactListModel.qml (+1/-1)
src/imports/Ubuntu/Contacts/ContactListView.qml (+5/-5)
src/imports/Ubuntu/Contacts/ContactPreviewPage.qml (+0/-131)
src/imports/Ubuntu/Contacts/ContactSimpleListView.qml (+1/-1)
src/imports/Ubuntu/Contacts/Contacts.js (+24/-0)
src/imports/Ubuntu/Contacts/MostCalledModel.qml (+11/-11)
src/imports/Ubuntu/Contacts/MultipleSelectionVisualModel.qml (+1/-1)
src/imports/Ubuntu/Contacts/SIMCardImportPage.qml (+11/-11)
src/imports/Ubuntu/Contacts/contacts.cpp (+26/-0)
src/imports/Ubuntu/Contacts/contacts.h (+2/-1)
src/imports/Ubuntu/Contacts/imagescalethread.cpp (+1/-1)
src/imports/Ubuntu/Contacts/imagescalethread.h (+1/-1)
src/imports/Ubuntu/Contacts/mostcalledproxymodel.cpp (+1/-1)
src/imports/Ubuntu/Contacts/mostcalledproxymodel.h (+1/-1)
src/imports/Ubuntu/Contacts/plugin.cpp (+1/-1)
src/imports/Ubuntu/Contacts/plugin.h (+1/-1)
src/imports/Ubuntu/Contacts/qmldir (+1/-16)
tests/autopilot/address_book_app/__init__.py (+6/-5)
tests/autopilot/address_book_app/address_book/__init__.py (+32/-0)
tests/autopilot/address_book_app/address_book/_common.py (+52/-0)
tests/autopilot/address_book_app/address_book/_contact_editor_page.py (+303/-0)
tests/autopilot/address_book_app/address_book/_contact_view_page.py (+28/-0)
tests/autopilot/address_book_app/address_book/_remove_contact_dialog.py (+36/-0)
tests/autopilot/address_book_app/address_book/_sim_card_import_page.py (+101/-0)
tests/autopilot/address_book_app/pages/__init__.py (+7/-8)
tests/autopilot/address_book_app/pages/_ab_contact_list_page.py (+136/-0)
tests/autopilot/address_book_app/pages/_ab_contact_view_page.py (+28/-0)
tests/autopilot/address_book_app/pages/_common.py (+0/-52)
tests/autopilot/address_book_app/pages/_contact_editor.py (+0/-299)
tests/autopilot/address_book_app/pages/_contact_list_page.py.THIS (+6/-0)
tests/autopilot/address_book_app/pages/_contact_view.py (+0/-28)
tests/autopilot/address_book_app/pages/_sim_card_import_page.py (+0/-103)
tests/autopilot/address_book_app/tests/test_add_contact.py (+2/-2)
tests/autopilot/address_book_app/tests/test_custom_proxy_objects.py (+2/-1)
tests/autopilot/address_book_app/tests/test_data.py (+1/-1)
tests/autopilot/address_book_app/tests/test_edit_contact.py (+1/-1)
tests/autopilot/address_book_app/tests/test_import_from_sim.py (+2/-7)
tests/qml/tst_ContactEditor.qml (+2/-2)
tests/qml/tst_ContactList.qml (+2/-2)
tests/qml/tst_ContactListView.qml (+0/-1)
tests/qml/tst_ContactPreviewPage.qml (+3/-1)
To merge this branch: bzr merge lp:~renatofilho/address-book-app/fix-test_import_from_sim
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Leo Arias (community) Approve
Omer Akram (community) Approve
Review via email: mp+256204@code.launchpad.net

This proposal has been superseded by a proposal from 2015-05-12.

Commit message

Updated autopilot test:

Check if "import from sim button" is invisible when all SIM cards get removed.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Omer Akram (om26er) wrote :

Now that the test behavior have been changed, please change the test name to something like:

test_import_item_disabled_without_sim_card()

review: Needs Fixing
Revision history for this message
Omer Akram (om26er) wrote :

Other than that code looks good to me.

424. By Renato Araujo Oliveira Filho

Renamed test.

Revision history for this message
Omer Akram (om26er) wrote :

Looks good now.

review: Approve
425. By Renato Araujo Oliveira Filho

Cleaned up the test.

Revision history for this message
Leo Arias (elopio) wrote :

Every failed test is an opportunity to clean up the test and make it more readable.
Take a look at:
https://code.launchpad.net/~canonical-platform-qa/address-book-app/fix-test_import_from_sim-cleanup/+merge/257931

In there, I removed the initial check because it has nothing to do with the name of the test. It should be tested elsewhere that when you open the app, no contacts are shown.

Also, I moved the selection to the page helper object. Every time you have a select single in the test body, there's something wrong. If we move them to the page object it will be easier to read and easier to maintain.

After the cleanup, it seems to me that this is a good candidate to be turned into a QML test. Here we are only checking that a button is not shown if certain conditions are not met. That's purely UI, it has nothing to do with a user story so autopilot seems like a tool too big and slow for it. Do you agree?

Finally, the name of the test still sounds wrong: test_import_item_disabled_without_sim_card
We are not checking that the item is disabled. We are checking that it is not visible.

review: Needs Fixing
Revision history for this message
Leo Arias (elopio) wrote :

ah, and this might conflicts with federico's flake8 branch:
https://code.launchpad.net/~canonical-platform-qa/address-book-app/flake8-fixes/+merge/256684

It would be safer using that branch as a prerequisite.

426. By Renato Araujo Oliveira Filho

renamed test function.

Revision history for this message
Leo Arias (elopio) :
review: Approve
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)
427. By Renato Araujo Oliveira Filho

Trunk merged.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2015-02-04 14:27:31 +0000
3+++ CMakeLists.txt 2015-05-12 21:19:18 +0000
4@@ -75,6 +75,7 @@
5
6 set(DESKTOP_EXEC "${ADDRESS_BOOK_APP_BINDIR}/address-book-app")
7 set(QMLPLUGIN_INSTALL_PREFIX "${QT_IMPORTS_DIR}/Ubuntu/Contacts.${API_VERSION}/")
8+set(ADDRESS_BOOK_QMLPLUGIN_INSTALL_PREFIX "${QT_IMPORTS_DIR}/Ubuntu/AddressBook/")
9 set(ADDRESS_BOOK_APP_DESKTOP_FILE address-book-app.desktop)
10 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
11
12
13=== modified file 'debian/control'
14--- debian/control 2015-03-17 17:39:31 +0000
15+++ debian/control 2015-05-12 21:19:18 +0000
16@@ -48,7 +48,7 @@
17 qtdeclarative5-qtcontacts-plugin,
18 qtdeclarative5-qtquick2-plugin,
19 qtdeclarative5-ofono0.2,
20- qtdeclarative5-ubuntu-contacts0.1 (= ${binary:Version}),
21+ qtdeclarative5-ubuntu-addressbook0.1 (= ${binary:Version}),
22 qtdeclarative5-ubuntu-content1,
23 qtdeclarative5-ubuntu-history0.1,
24 qtdeclarative5-ubuntu-keyboard-extensions0.1,
25@@ -75,6 +75,17 @@
26 .
27 This package contains the Ubuntu Contacts Components QML plugin.
28
29+Package: qtdeclarative5-ubuntu-addressbook0.1
30+Architecture: any
31+Depends: qtdeclarative5-ubuntu-contacts0.1 (= ${binary:Version}),
32+ ${misc:Depends},
33+ ${shlibs:Depends},
34+Description: Qt Ubuntu Address Book Components - QML plugin
35+ Qt Ubuntu Address Book Components offers a set of reusable user interface
36+ related with address book for Qt Quick 2 / QML.
37+ .
38+ This package contains the Ubuntu Address Book Components QML plugin.
39+
40 Package: address-book-app-dbg
41 Architecture: amd64 armhf i386
42 Section: debug
43
44=== added file 'debian/qtdeclarative5-ubuntu-addressbook0.1.install'
45--- debian/qtdeclarative5-ubuntu-addressbook0.1.install 1970-01-01 00:00:00 +0000
46+++ debian/qtdeclarative5-ubuntu-addressbook0.1.install 2015-05-12 21:19:18 +0000
47@@ -0,0 +1,4 @@
48+usr/lib/*/qt5/qml/Ubuntu/AddressBook/Base/*
49+usr/lib/*/qt5/qml/Ubuntu/AddressBook/ContactView/*
50+usr/lib/*/qt5/qml/Ubuntu/AddressBook/ContactEditor/*
51+usr/lib/*/qt5/qml/Ubuntu/AddressBook/ContactShare/*
52
53=== modified file 'src/app/CMakeLists.txt'
54--- src/app/CMakeLists.txt 2014-06-11 21:25:08 +0000
55+++ src/app/CMakeLists.txt 2015-05-12 21:19:18 +0000
56@@ -9,8 +9,6 @@
57 set(ADDRESS_BOOK_APP_SRCS
58 addressbookapp.h
59 addressbookapp.cpp
60- imagescalethread.h
61- imagescalethread.cpp
62 main.cpp
63 )
64
65
66=== modified file 'src/app/addressbookapp.cpp'
67--- src/app/addressbookapp.cpp 2015-02-09 14:06:06 +0000
68+++ src/app/addressbookapp.cpp 2015-05-12 21:19:18 +0000
69@@ -1,5 +1,5 @@
70 /*
71- * Copyright (C) 2012-2013 Canonical, Ltd.
72+ * Copyright (C) 2012-2015 Canonical, Ltd.
73 *
74 * This program is free software; you can redistribute it and/or modify
75 * it under the terms of the GNU General Public License as published by
76@@ -16,7 +16,6 @@
77
78 #include "config.h"
79 #include "addressbookapp.h"
80-#include "imagescalethread.h"
81
82 #include <QDir>
83 #include <QUrl>
84@@ -407,28 +406,6 @@
85 }
86 }
87
88-QUrl AddressBookApp::copyImage(QObject *contact, const QUrl &imageUrl)
89-{
90- // keep track of threads to avoid memory leeak
91- ImageScaleThread *imgThread;
92- QVariant oldThread = contact->property("IMAGE_SCALE_THREAD");
93- if (!oldThread.isNull()) {
94- imgThread = oldThread.value<ImageScaleThread *>();
95- imgThread->updateImageUrl(imageUrl);
96- } else {
97- imgThread = new ImageScaleThread(imageUrl, contact);
98- contact->setProperty("IMAGE_SCALE_THREAD", QVariant::fromValue<ImageScaleThread*>(imgThread));
99- }
100-
101- imgThread->start();
102-
103- while(imgThread->isRunning()) {
104- this->processEvents(QEventLoop::AllEvents, 3000);
105- }
106-
107- return imgThread->outputFile();
108-}
109-
110 void AddressBookApp::elapsed() const
111 {
112 qDebug() << "ELAPSED:" << s_elapsed.elapsed() / 1000.0;
113
114=== modified file 'src/app/addressbookapp.h'
115--- src/app/addressbookapp.h 2015-02-09 14:06:06 +0000
116+++ src/app/addressbookapp.h 2015-05-12 21:19:18 +0000
117@@ -1,5 +1,5 @@
118 /*
119- * Copyright (C) 2012-2013 Canonical, Ltd.
120+ * Copyright (C) 2012-2015 Canonical, Ltd.
121 *
122 * This program is free software; you can redistribute it and/or modify
123 * it under the terms of the GNU General Public License as published by
124@@ -44,7 +44,6 @@
125
126 public Q_SLOTS:
127 void activateWindow();
128- QUrl copyImage(QObject *contact, const QUrl &imageUrl);
129 void parseUrl(const QString &arg);
130 void onViewStatusChanged(QQuickView::Status status);
131 void returnVcard(const QUrl &url);
132
133=== modified file 'src/app/main.cpp'
134--- src/app/main.cpp 2014-02-18 14:09:02 +0000
135+++ src/app/main.cpp 2015-05-12 21:19:18 +0000
136@@ -1,5 +1,5 @@
137 /*
138- * Copyright (C) 2012-2013 Canonical, Ltd.
139+ * Copyright (C) 2012-2015 Canonical, Ltd.
140 *
141 * This program is free software; you can redistribute it and/or modify
142 * it under the terms of the GNU General Public License as published by
143
144=== added file 'src/imports/ABContactEditorPage.qml'
145--- src/imports/ABContactEditorPage.qml 1970-01-01 00:00:00 +0000
146+++ src/imports/ABContactEditorPage.qml 2015-05-12 21:19:18 +0000
147@@ -0,0 +1,56 @@
148+/*
149+ * Copyright (C) 2012-2015 Canonical, Ltd.
150+ *
151+ * This program is free software; you can redistribute it and/or modify
152+ * it under the terms of the GNU General Public License as published by
153+ * the Free Software Foundation; version 3.
154+ *
155+ * This program is distributed in the hope that it will be useful,
156+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
157+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
158+ * GNU General Public License for more details.
159+ *
160+ * You should have received a copy of the GNU General Public License
161+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
162+ */
163+
164+import QtQuick 2.2
165+import QtContacts 5.0
166+
167+import Ubuntu.Components 1.1
168+
169+import Ubuntu.AddressBook.ContactEditor 0.1
170+
171+ContactEditorPage {
172+ id: root
173+ objectName: "contactEditorPage"
174+
175+ head.backAction: Action {
176+ objectName: "cancel"
177+
178+ text: i18n.tr("Cancel")
179+ iconName: "back"
180+ onTriggered: {
181+ root.cancel()
182+ root.active = false
183+ }
184+ }
185+
186+ head.actions: [
187+ Action {
188+ objectName: "save"
189+
190+ text: i18n.tr("Save")
191+ iconName: "ok"
192+ // disable save button while avatar scale still running
193+ enabled: root.isContactValid
194+ onTriggered: root.save()
195+ }
196+ ]
197+
198+ onContactSaved: {
199+ if (pageStack.contactListPage) {
200+ pageStack.contactListPage.moveListToContact(contact)
201+ }
202+ }
203+}
204
205=== added file 'src/imports/ABContactListPage.qml'
206--- src/imports/ABContactListPage.qml 1970-01-01 00:00:00 +0000
207+++ src/imports/ABContactListPage.qml 2015-05-12 21:19:18 +0000
208@@ -0,0 +1,530 @@
209+/*
210+ * Copyright (C) 2012-2015 Canonical, Ltd.
211+ *
212+ * This program is free software; you can redistribute it and/or modify
213+ * it under the terms of the GNU General Public License as published by
214+ * the Free Software Foundation; version 3.
215+ *
216+ * This program is distributed in the hope that it will be useful,
217+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
218+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
219+ * GNU General Public License for more details.
220+ *
221+ * You should have received a copy of the GNU General Public License
222+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
223+ */
224+
225+import QtQuick 2.2
226+import QtContacts 5.0
227+
228+import Ubuntu.Components 1.1
229+import Ubuntu.Components.ListItems 1.0 as ListItem
230+import Ubuntu.Components.Popups 1.0 as Popups
231+import Ubuntu.Contacts 0.1 as ContactsUI
232+import Ubuntu.Content 1.1 as ContentHub
233+
234+import Ubuntu.AddressBook.Base 0.1
235+
236+ContactsUI.PageWithBottomEdge {
237+ id: mainPage
238+ objectName: "contactListPage"
239+
240+ property bool pickMode: false
241+ property alias contentHubTransfer: contactExporter.activeTransfer
242+ property bool pickMultipleContacts: false
243+ property QtObject contactIndex: null
244+ property string newPhoneToAdd: ""
245+ property alias contactManager: contactList.manager
246+
247+ readonly property bool isEmpty: (contactList.count === 0)
248+ readonly property bool allowToQuit: (application.callbackApplication.length > 0)
249+ readonly property var contactModel: contactList.listModel ? contactList.listModel : null
250+ readonly property bool searching: (state === "searching" || state === "newphoneSearching")
251+
252+ // this function is used to reset the contact list page to the default state if it was called
253+ // from the uri. For example when called to add a new contact
254+ function returnToNormalState()
255+ {
256+ // these two states are the only state that need to be reset
257+ if (state == "newphoneSearching" || state == "newphone") {
258+ state = "default"
259+ }
260+ application.callbackApplication = ""
261+ }
262+
263+ function createContactWithPhoneNumber(phoneNumber)
264+ {
265+ var newContact = ContactsJS.createEmptyContact(phoneNumber, mainPage)
266+ //WORKAROUND: SKD changes the page header as soon as the page get created
267+ // setting active false will avoid that
268+ if (bottomEdgeEnabled) {
269+ mainPage.showBottomEdgePage(Qt.resolvedUrl("ABContactEditorPage.qml"),
270+ {model: contactList.listModel,
271+ contact: newContact,
272+ active: false,
273+ enabled: false,
274+ initialFocusSection: "name"})
275+ } else {
276+ pageStack.push(Qt.resolvedUrl("ABContactEditorPage.qml"),
277+ {model: contactList.listModel,
278+ contact: newContact,
279+ initialFocusSection: "name"})
280+ }
281+ }
282+
283+ function showContact(contactId)
284+ {
285+ pageStack.push(Qt.resolvedUrl("ABContactViewPage.qml"),
286+ {model: contactList.listModel, contactId: contactId})
287+ }
288+
289+ function addPhoneToContact(contactId, phoneNumber)
290+ {
291+ pageStack.push(Qt.resolvedUrl("ABContactViewPage.qml"),
292+ {model: contactList.listModel,
293+ contactId: contactId,
294+ addPhoneToContact: phoneNumber})
295+ }
296+
297+ function importContact(urls)
298+ {
299+ if (urls.length > 0) {
300+ var importDialog = Qt.createQmlObject("VCardImportDialog{}",
301+ mainPage,
302+ "VCardImportDialog")
303+ if (importDialog) {
304+ importDialog.importVCards(contactList.listModel, urls)
305+ }
306+ }
307+ }
308+
309+ function startPickMode(isSingleSelection, activeTransfer)
310+ {
311+ contentHubTransfer = activeTransfer
312+ pickMode = true
313+ pickMultipleContacts = !isSingleSelection
314+ contactList.startSelection()
315+ }
316+
317+ function moveListToContact(contact)
318+ {
319+ contactIndex = contact
320+ mainPage.state = "default"
321+ // this means a new contact was created
322+ if (mainPage.allowToQuit) {
323+ application.goBackToSourceApp()
324+ }
325+ }
326+
327+ function addNewPhone(phoneNumber)
328+ {
329+ newPhoneToAdd = phoneNumber
330+ state = "newphone"
331+ contactList.reset()
332+ }
333+
334+ title: i18n.tr("Contacts")
335+ bottomEdgeTitle: "+"
336+ bottomEdgeEnabled: !contactList.isInSelectionMode
337+
338+ flickable: null
339+ ContactsUI.ContactListView {
340+ id: contactList
341+ objectName: "contactListView"
342+ showImportOptions: !mainPage.pickMode &&
343+ mainPage.newPhoneToAdd === ""
344+ anchors {
345+ top: parent.top
346+ left: parent.left
347+ bottom: keyboard.top
348+ right: parent.right
349+ }
350+ filterTerm: searchField.text
351+ detailToPick: ContactDetail.PhoneNumber
352+ multiSelectionEnabled: true
353+ multipleSelection: (mainPage.pickMode && mainPage.pickMultipleContacts) || !mainPage.pickMode
354+
355+ onAddContactClicked: mainPage.createContactWithPhoneNumber(label)
356+ onAddNewContactClicked: mainPage.createContactWithPhoneNumber(mainPage.newPhoneToAdd)
357+
358+ onInfoRequested: {
359+ mainPage.state = "default"
360+ pageStack.push(Qt.resolvedUrl("ABContactViewPage.qml"),
361+ {model: contactList.listModel,
362+ contact: contact})
363+ }
364+
365+ onDetailClicked: {
366+ if (action == "call")
367+ Qt.openUrlExternally("tel:///" + encodeURIComponent(detail.number))
368+ else if (action == "message")
369+ Qt.openUrlExternally("message:///" + encodeURIComponent(detail.number))
370+ else if ((mainPage.state === "newphone") || (mainPage.state === "newphoneSearching")) {
371+ mainPage.addPhoneToContact(contact.contactId, mainPage.newPhoneToAdd)
372+ }
373+ }
374+
375+ onAddDetailClicked: mainPage.addPhoneToContact(contact.contactId, " ")
376+ onIsInSelectionModeChanged: mainPage.state = isInSelectionMode ? "selection" : "default"
377+ onSelectionCanceled: {
378+ if (pickMode) {
379+ if (contentHubTransfer) {
380+ contentHubTransfer.state = ContentHub.ContentTransfer.Aborted
381+ }
382+ pickMode = false
383+ contentHubTransfer = null
384+ application.returnVcard("")
385+ }
386+ mainPage.state = "default"
387+ }
388+
389+ onError: pageStack.contactModelError(error)
390+ }
391+
392+ TextField {
393+ id: searchField
394+
395+ anchors {
396+ left: parent.left
397+ right: parent.right
398+ rightMargin: units.gu(2)
399+ }
400+ visible: mainPage.searching
401+ onTextChanged: contactList.currentIndex = -1
402+ inputMethodHints: Qt.ImhNoPredictiveText
403+ placeholderText: i18n.tr("Search...")
404+ }
405+
406+ Connections {
407+ target: mainPage.head.sections
408+ onSelectedIndexChanged: {
409+ switch (mainPage.head.sections.selectedIndex) {
410+ case 0:
411+ contactList.showAllContacts()
412+ break;
413+ case 1:
414+ contactList.showFavoritesContacts()
415+ break;
416+ default:
417+ break;
418+ }
419+ }
420+ }
421+
422+ state: "default"
423+ states: [
424+ PageHeadState {
425+ id: defaultState
426+
427+ name: "default"
428+ backAction: Action {
429+ visible: mainPage.allowToQuit
430+ iconName: "back"
431+ text: i18n.tr("Quit")
432+ onTriggered: {
433+ application.goBackToSourceApp()
434+ mainPage.returnToNormalState()
435+ }
436+ }
437+ actions: [
438+ Action {
439+ text: i18n.tr("Search")
440+ iconName: "search"
441+ visible: !mainPage.isEmpty
442+ onTriggered: {
443+ mainPage.state = (mainPage.state === "newphone" ? "newphoneSearching" : "searching")
444+ contactList.showAllContacts()
445+ searchField.forceActiveFocus()
446+ }
447+ },
448+ Action {
449+ visible: contactList.syncEnabled
450+ text: contactList.syncing ? i18n.tr("Syncing") : i18n.tr("Sync")
451+ iconName: "reload"
452+ enabled: !contactList.syncing
453+ onTriggered: contactList.sync()
454+ },
455+ Action {
456+ text: i18n.tr("Settings")
457+ iconName: "settings"
458+ onTriggered: pageStack.push(Qt.resolvedUrl("../Settings/SettingsPage.qml"),
459+ {"contactListModel": contactList.listModel})
460+ }
461+ ]
462+ PropertyChanges {
463+ target: mainPage.head
464+ backAction: defaultState.backAction
465+ actions: defaultState.actions
466+ // TRANSLATORS: this refers to all contacts
467+ sections.model: [i18n.tr("All"), i18n.tr("Favorites")]
468+ }
469+ PropertyChanges {
470+ target: searchField
471+ text: ""
472+ }
473+ },
474+ PageHeadState {
475+ id: searchingState
476+
477+ name: "searching"
478+ backAction: Action {
479+ iconName: "back"
480+ text: i18n.tr("Cancel")
481+ onTriggered: {
482+ contactList.forceActiveFocus()
483+ mainPage.head.sections.selectedIndex = 0
484+ mainPage.state = (mainPage.state === "newphoneSearching" ? "newphone" : "default")
485+ }
486+ }
487+
488+ PropertyChanges {
489+ target: mainPage.head
490+ backAction: searchingState.backAction
491+ contents: searchField
492+ }
493+
494+ PropertyChanges {
495+ target: searchField
496+ text: ""
497+ }
498+ },
499+ PageHeadState {
500+ id: selectionState
501+
502+ name: "selection"
503+ backAction: Action {
504+ text: i18n.tr("Cancel selection")
505+ iconName: "back"
506+ onTriggered: contactList.cancelSelection()
507+ }
508+ actions: [
509+ Action {
510+ text: (contactList.selectedItems.count === contactList.count) ? i18n.tr("Unselect All") : i18n.tr("Select All")
511+ iconName: "select"
512+ onTriggered: {
513+ if (contactList.selectedItems.count === contactList.count) {
514+ contactList.clearSelection()
515+ } else {
516+ contactList.selectAll()
517+ }
518+ }
519+ visible: contactList.multipleSelection && !mainPage.isEmpty
520+ },
521+ Action {
522+ objectName: "share"
523+ text: i18n.tr("Share")
524+ iconName: mainPage.pickMode ? "tick" : "share"
525+ enabled: (contactList.selectedItems.count > 0)
526+ visible: contactList.isInSelectionMode
527+ onTriggered: {
528+ var contacts = []
529+ var items = contactList.selectedItems
530+
531+ for (var i=0, iMax=items.count; i < iMax; i++) {
532+ contacts.push(items.get(i).model.contact)
533+ }
534+ contactExporter.start(contacts)
535+ contactList.endSelection()
536+ }
537+ },
538+ Action {
539+ objectName: "delete"
540+ text: i18n.tr("Delete")
541+ iconName: "delete"
542+ enabled: (contactList.selectedItems.count > 0)
543+ visible: contactList.isInSelectionMode && !mainPage.pickMode
544+ onTriggered: {
545+ var contacts = []
546+ var items = contactList.selectedItems
547+
548+ for (var i=0, iMax=items.count; i < iMax; i++) {
549+ contacts.push(items.get(i).model.contact)
550+ }
551+
552+ var dialog = PopupUtils.open(removeContactDialog, null)
553+ dialog.contacts = contacts
554+ contactList.endSelection()
555+ }
556+ }
557+ ]
558+ PropertyChanges {
559+ target: mainPage.head
560+ backAction: selectionState.backAction
561+ actions: selectionState.actions
562+ }
563+ PropertyChanges {
564+ target: mainPage
565+ bottomEdgeEnabled: false
566+ title: " "
567+ }
568+ },
569+ PageHeadState {
570+ name: "newphone"
571+ extend: "default"
572+ head: mainPage.head
573+ PropertyChanges {
574+ target: contactList
575+ showAddNewButton: true
576+ }
577+ PropertyChanges {
578+ target: mainPage
579+ bottomEdgeEnabled: false
580+ title: i18n.tr("Add contact")
581+ }
582+ PropertyChanges {
583+ target: contactList
584+ detailToPick: -1
585+ }
586+ },
587+ PageHeadState {
588+ name: "newphoneSearching"
589+ extend: "searching"
590+ head: mainPage.head
591+ PropertyChanges {
592+ target: contactList
593+ detailToPick: -1
594+ showAddNewButton: true
595+ }
596+ PropertyChanges {
597+ target: mainPage
598+ bottomEdgeEnabled: false
599+ }
600+ }
601+ ]
602+ onActiveChanged: {
603+ if (active && contactList.showAddNewButton) {
604+ contactList.positionViewAtBeginning()
605+ }
606+ }
607+
608+ // We need to reset the page proprerties in case of the page was created pre-populated,
609+ // with phonenumber or contact.
610+ onBottomEdgeDismissed: {
611+ //WORKAROUND: SKD changes the page header as soon as the page get created
612+ // setting active false will avoid that
613+ var newContact = ContactsUI.ContactsJS.createEmptyContact("", mainPage)
614+ mainPage.setBottomEdgePage(Qt.resolvedUrl("ABContactEditorPage.qml"),
615+ {model: contactList.listModel,
616+ contact: newContact,
617+ active: false,
618+ enabled: false,
619+ initialFocusSection: "name"})
620+ }
621+
622+ KeyboardRectangle {
623+ id: keyboard
624+ }
625+
626+ Column {
627+ id: emptyStateScreen
628+
629+ anchors.centerIn: parent
630+ height: childrenRect.height
631+ width: childrenRect.width
632+ spacing: units.gu(2)
633+ visible: (!contactList.busy &&
634+ !contactList.favouritesIsSelected &&
635+ mainPage.isEmpty &&
636+ (mainPage.newPhoneToAdd === "") &&
637+ !(contactList.filterTerm && contactList.filterTerm !== ""))
638+
639+ Behavior on visible {
640+ SequentialAnimation {
641+ PauseAnimation {
642+ duration: !emptyStateScreen.visible ? 500 : 0
643+ }
644+ PropertyAction {
645+ target: emptyStateScreen
646+ property: "visible"
647+ }
648+ }
649+ }
650+
651+ Icon {
652+ id: emptyStateIcon
653+ anchors.horizontalCenter: emptyStateLabel.horizontalCenter
654+ height: units.gu(5)
655+ width: units.gu(5)
656+ opacity: 0.3
657+ name: "contact"
658+ }
659+ Label {
660+ id: emptyStateLabel
661+ width: mainPage.width - units.gu(12)
662+ height: paintedHeight
663+ text: mainPage.pickMode ?
664+ i18n.tr("You have no contacts.") :
665+ i18n.tr("Create a new contact by swiping up from the bottom of the screen.")
666+ color: "#5d5d5d"
667+ fontSize: "x-large"
668+ wrapMode: Text.WordWrap
669+ horizontalAlignment: Text.AlignHCenter
670+ }
671+ }
672+
673+ Connections {
674+ target: mainPage.contactModel
675+ onContactsChanged: {
676+ if (contactIndex) {
677+ contactList.positionViewAtContact(mainPage.contactIndex)
678+ mainPage.contactIndex = null
679+ }
680+ }
681+ }
682+
683+ ContactExporter {
684+ id: contactExporter
685+
686+ contactModel: contactList.listModel
687+ exportToDisk: mainPage.pickMode
688+ onDone: {
689+ mainPage.pickMode = false
690+ mainPage.state = "default"
691+ application.returnVcard(outputFile)
692+ }
693+
694+ onContactsFetched: {
695+ // Share contacts to an application chosen by the user
696+ if (!mainPage.pickMode) {
697+ contactExporter.dismissBusyDialog()
698+ pageStack.push(Qt.resolvedUrl("../ContactShare/ContactSharePage.qml"),
699+ { contactModel: contactExporter.contactModel, contacts: contacts })
700+ }
701+ }
702+ }
703+
704+ Component {
705+ id: removeContactDialog
706+
707+ RemoveContactsDialog {
708+ id: removeContactsDialogMessage
709+
710+ onCanceled: {
711+ PopupUtils.close(removeContactsDialogMessage)
712+ }
713+
714+ onAccepted: {
715+ removeContacts(contactList.listModel)
716+ PopupUtils.close(removeContactsDialogMessage)
717+ }
718+ }
719+ }
720+
721+ Component.onCompleted: {
722+ application.elapsed()
723+ if ((typeof(TEST_DATA) !== "undefined") && (TEST_DATA !== "")) {
724+ contactList.listModel.importContacts("file://" + TEST_DATA)
725+ }
726+
727+ mainPage.setBottomEdgePage(Qt.resolvedUrl("ABContactEditorPage.qml"),
728+ {model: contactList.listModel,
729+ contact: ContactsUI.ContactsJS.createEmptyContact("", mainPage),
730+ active: false,
731+ enabled: false,
732+ initialFocusSection: "name"})
733+
734+ if (pageStack) {
735+ pageStack.contactListPage = mainPage
736+ }
737+ }
738+}
739
740=== added file 'src/imports/ABContactViewPage.qml'
741--- src/imports/ABContactViewPage.qml 1970-01-01 00:00:00 +0000
742+++ src/imports/ABContactViewPage.qml 2015-05-12 21:19:18 +0000
743@@ -0,0 +1,87 @@
744+/*
745+ * Copyright (C) 2012-2015 Canonical, Ltd.
746+ *
747+ * This program is free software; you can redistribute it and/or modify
748+ * it under the terms of the GNU General Public License as published by
749+ * the Free Software Foundation; version 3.
750+ *
751+ * This program is distributed in the hope that it will be useful,
752+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
753+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
754+ * GNU General Public License for more details.
755+ *
756+ * You should have received a copy of the GNU General Public License
757+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
758+ */
759+
760+import QtQuick 2.2
761+import Ubuntu.Components 1.1
762+import Ubuntu.Components.Popups 1.0 as Popups
763+import Ubuntu.Contacts 0.1
764+
765+import Ubuntu.AddressBook.Base 0.1
766+import Ubuntu.AddressBook.ContactView 0.1
767+import Ubuntu.AddressBook.ContactShare 0.1
768+
769+ContactViewPage {
770+ id: root
771+ objectName: "contactViewPage"
772+
773+ property string addPhoneToContact: ""
774+
775+ head.actions: [
776+ Action {
777+ objectName: "share"
778+ text: i18n.tr("Share")
779+ iconName: "share"
780+ onTriggered: {
781+ pageStack.push(contactShareComponent, {contactModel: root.model, contacts: [root.contact]})
782+ }
783+ },
784+ Action {
785+ objectName: "edit"
786+ text: i18n.tr("Edit")
787+ iconName: "edit"
788+ onTriggered: {
789+ pageStack.push(Qt.resolvedUrl("ABContactEditorPage.qml"),
790+ { model: root.model, contact: root.contact})
791+ }
792+ }
793+ ]
794+
795+ onContactRemoved: pageStack.pop()
796+
797+ extensions: ContactDetailSyncTargetView {
798+ contact: root.contact
799+ anchors {
800+ left: parent.left
801+ right: parent.right
802+ }
803+ height: implicitHeight
804+ }
805+
806+ // This will load the contact information when the app was launched with
807+ // the URI: addressbook:///contact?id=<id>
808+ onContactFetched: {
809+ if (root.addPhoneToContact != "") {
810+ var detailSourceTemplate = "import QtContacts 5.0; PhoneNumber{ number: \"" + root.addPhoneToContact.trim() + "\" }"
811+ var newDetail = Qt.createQmlObject(detailSourceTemplate, contact)
812+ if (newDetail) {
813+ contact.addDetail(newDetail)
814+ pageStack.push(Qt.resolvedUrl("ABContactEditorPage.qml"),
815+ { model: root.model,
816+ contact: contact,
817+ initialFocusSection: "phones",
818+ newDetails: [newDetail]})
819+ root.addPhoneToContact = ""
820+ }
821+ }
822+ }
823+
824+ onActionTrigerred: Qt.openUrlExternally(("%1:///%2").arg(action).arg(detail.value(0)))
825+
826+ Component {
827+ id: contactShareComponent
828+ ContactSharePage {}
829+ }
830+}
831
832=== modified file 'src/imports/CMakeLists.txt'
833--- src/imports/CMakeLists.txt 2015-03-06 13:59:58 +0000
834+++ src/imports/CMakeLists.txt 2015-05-12 21:19:18 +0000
835@@ -1,6 +1,9 @@
836 project(imports)
837
838 set(ADDRESS_BOOK_APP_QMLS
839+ ABContactListPage.qml
840+ ABContactEditorPage.qml
841+ ABContactViewPage.qml
842 ContentHubProxy.qml
843 MainWindow.qml
844 )
845@@ -12,10 +15,5 @@
846 # make the files visible on qtcreator
847 add_custom_target(address_book_QMlFiles ALL SOURCES ${ADDRESS_BOOK_APP_QMLS})
848
849-add_subdirectory(Common)
850-add_subdirectory(ContactList)
851-add_subdirectory(ContactView)
852-add_subdirectory(ContactEdit)
853-add_subdirectory(ContactShare)
854 add_subdirectory(Settings)
855 add_subdirectory(Ubuntu)
856
857=== removed directory 'src/imports/Common'
858=== removed file 'src/imports/Common/CMakeLists.txt'
859--- src/imports/Common/CMakeLists.txt 2014-10-09 17:39:12 +0000
860+++ src/imports/Common/CMakeLists.txt 1970-01-01 00:00:00 +0000
861@@ -1,15 +0,0 @@
862-set(CONTACT_COMMON_QMLS
863- ContactDetailItem.qml
864- ContactExporter.qml
865- KeyboardRectangle.qml
866- RemoveContactsDialog.qml
867- StandardAnimation.qml
868-)
869-
870-install(FILES ${CONTACT_COMMON_QMLS}
871- DESTINATION ${ADDRESS_BOOK_APP_DIR}/imports/Common
872-)
873-
874-# make the files visible on qtcreator
875-add_custom_target(contact_common_QmlFiles ALL SOURCES ${CONTACT_COMMON_QMLS})
876-
877
878=== removed file 'src/imports/Common/ContactDetailItem.qml'
879--- src/imports/Common/ContactDetailItem.qml 2014-08-13 20:52:57 +0000
880+++ src/imports/Common/ContactDetailItem.qml 1970-01-01 00:00:00 +0000
881@@ -1,62 +0,0 @@
882-/*
883- * Copyright (C) 2012-2013 Canonical, Ltd.
884- *
885- * This program is free software; you can redistribute it and/or modify
886- * it under the terms of the GNU General Public License as published by
887- * the Free Software Foundation; version 3.
888- *
889- * This program is distributed in the hope that it will be useful,
890- * but WITHOUT ANY WARRANTY; without even the implied warranty of
891- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
892- * GNU General Public License for more details.
893- *
894- * You should have received a copy of the GNU General Public License
895- * along with this program. If not, see <http://www.gnu.org/licenses/>.
896- */
897-
898-import QtQuick 2.2
899-
900-import Ubuntu.Components 1.1
901-import Ubuntu.Contacts 0.1
902-
903-ContactDetailBase {
904- id: root
905-
906- readonly property alias fieldDelegates: fieldsColumn.children
907- property Component fieldDelegate: null
908- property alias spacing: fieldsColumn.spacing
909-
910- implicitHeight: fieldsColumn.height
911- Column {
912- id: fieldsColumn
913-
914- anchors {
915- left: parent.left
916- right: parent.right
917- }
918- spacing: units.gu(2)
919-
920- height: childrenRect.height
921- Repeater {
922- id: fieldRepeater
923-
924- model: root.fields
925- Loader {
926- id: field
927-
928- sourceComponent: fieldDelegate
929- Binding {
930- target: item
931- property: "field"
932- value: modelData
933- }
934-
935- Binding {
936- target: item
937- property: "detail"
938- value: root.detail
939- }
940- }
941- }
942- }
943-}
944
945=== removed file 'src/imports/Common/ContactExporter.qml'
946--- src/imports/Common/ContactExporter.qml 2015-02-13 19:29:27 +0000
947+++ src/imports/Common/ContactExporter.qml 1970-01-01 00:00:00 +0000
948@@ -1,167 +0,0 @@
949-/*
950- * Copyright (C) 2012-2013 Canonical, Ltd.
951- *
952- * This program is free software; you can redistribute it and/or modify
953- * it under the terms of the GNU General Public License as published by
954- * the Free Software Foundation; version 3.
955- *
956- * This program is distributed in the hope that it will be useful,
957- * but WITHOUT ANY WARRANTY; without even the implied warranty of
958- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
959- * GNU General Public License for more details.
960- *
961- * You should have received a copy of the GNU General Public License
962- * along with this program. If not, see <http://www.gnu.org/licenses/>.
963- */
964-
965-import QtQuick 2.2
966-import QtContacts 5.0
967-
968-import Ubuntu.Components 1.1
969-import Ubuntu.Content 1.1
970-import Ubuntu.Components.Popups 1.0
971-
972-Item {
973- id: root
974-
975- property var contactModel
976- property bool exportToDisk: true
977- property var activeTransfer: null
978-
979- signal contactsFetched(var contacts)
980- signal done(string outputFile)
981-
982- function start(contacts) {
983- if (!contactModel) {
984- console.error("No contact model defined")
985- return
986- }
987-
988- // skip if a query is running
989- if (priv.currentQueryId != -1) {
990- console.error("Export already running")
991- return
992- }
993-
994- if (!priv.busyDialog) {
995- priv.busyDialog = PopupUtils.open(busyDialogComponent, root)
996- }
997-
998- var ids = []
999- for (var i=0; i < contacts.length; i++) {
1000- ids.push(contacts[i].contactId)
1001- }
1002- if (ids.length == 0) {
1003- console.debug("The contact list is empty")
1004- done("")
1005- } else {
1006- priv.currentQueryId = contactModel.fetchContacts(ids)
1007- }
1008- }
1009-
1010- function dismissBusyDialog()
1011- {
1012- if (priv.busyDialog) {
1013- PopupUtils.close(priv.busyDialog)
1014- priv.busyDialog = null
1015- }
1016- }
1017-
1018- Item {
1019- id: priv
1020-
1021- property var busyDialog: null
1022- property int currentQueryId: -1
1023- readonly property var detailsBlackList: [ ContactDetail.Favorite, ContactDetail.Tag ]
1024-
1025- function filterContactDetails(contact)
1026- {
1027- var newContact = Qt.createQmlObject("import QtContacts 5.0; Contact { }", root)
1028- var allDetails = contact.contactDetails
1029- for(var i=0; i < allDetails.length; i++) {
1030- var det = allDetails[i]
1031- if (detailsBlackList.indexOf(det.type) == -1) {
1032- newContact.addDetail(det)
1033- }
1034- }
1035- return newContact
1036- }
1037-
1038- function generateOutputFileName(contacts)
1039- {
1040- if (contacts.length === 1) {
1041- return "file:///tmp/%1.vcf".arg(contacts[0].displayLabel.label.replace(/\s/g, ''))
1042- } else {
1043- return "file:///tmp/ubuntu_contacts.vcf";
1044- }
1045- }
1046-
1047- Connections {
1048- target: root.contactModel
1049-
1050- onExportCompleted: {
1051- // send contacts back to source app (pick mode)
1052- if (error === ContactModel.ExportNoError) {
1053- var obj = Qt.createQmlObject("import Ubuntu.Content 1.1; ContentItem { url: '" + url + "' }", root)
1054- if (root.activeTransfer) {
1055- root.activeTransfer.items = [obj]
1056- root.activeTransfer.state = ContentTransfer.Charged
1057- } else {
1058- console.error("No active transfer")
1059- }
1060- } else {
1061- root.activeTransfer = ContentHub.ContentTransfer.Aborted
1062- console.error("Fail to export contacts:" + error)
1063- }
1064- root.dismissBusyDialog()
1065- root.done(url)
1066- }
1067-
1068- onContactsFetched: {
1069- // currentQueryId == -2 is used during a fetch using "memory" manager
1070- if ((priv.currentQueryId == -2) || (requestId == priv.currentQueryId)) {
1071- if (root.exportToDisk) {
1072- var contacts = []
1073- // remove unnecessary info from contacts
1074- for(var i=0; i < fetchedContacts.length; i++) {
1075- contacts.push(priv.filterContactDetails(fetchedContacts[i]))
1076- }
1077- // update outputFile with a friendly name
1078- var outputFile = priv.generateOutputFileName(contacts)
1079- root.contactModel.exportContacts(outputFile,
1080- [],
1081- contacts)
1082- }
1083- root.contactsFetched(fetchedContacts)
1084- priv.currentQueryId = -1
1085- }
1086- }
1087- }
1088-
1089- Connections {
1090- target: root.activeTransfer
1091-
1092- onStateChanged: {
1093- if (root.activeTransfer.state === ContentTransfer.Aborted) {
1094- root.activeTransfer = null
1095- root.done("")
1096- }
1097- }
1098- }
1099- }
1100-
1101- Component {
1102- id: busyDialogComponent
1103-
1104- Dialog {
1105- title: i18n.tr("Exporting contacts...")
1106-
1107- ActivityIndicator {
1108- id: activity
1109-
1110- anchors.horizontalCenter: parent.horizontalCenter
1111- running: true
1112- }
1113- }
1114- }
1115-}
1116
1117=== removed file 'src/imports/Common/KeyboardRectangle.qml'
1118--- src/imports/Common/KeyboardRectangle.qml 2014-06-05 16:46:28 +0000
1119+++ src/imports/Common/KeyboardRectangle.qml 1970-01-01 00:00:00 +0000
1120@@ -1,74 +0,0 @@
1121-/*
1122- * Copyright (C) 2012-2013 Canonical, Ltd.
1123- *
1124- * This program is free software; you can redistribute it and/or modify
1125- * it under the terms of the GNU General Public License as published by
1126- * the Free Software Foundation; version 3.
1127- *
1128- * This program is distributed in the hope that it will be useful,
1129- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1130- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1131- * GNU General Public License for more details.
1132- *
1133- * You should have received a copy of the GNU General Public License
1134- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1135- */
1136-
1137-import QtQuick 2.2
1138-
1139-Item {
1140- id: keyboardRect
1141- anchors.left: parent.left
1142- anchors.right: parent.right
1143- anchors.bottom: parent.bottom
1144- height: Qt.inputMethod.visible ? Qt.inputMethod.keyboardRectangle.height : 0
1145-
1146- Behavior on height {
1147- StandardAnimation { }
1148- }
1149-
1150- states: [
1151- State {
1152- name: "hidden"
1153- when: keyboardRect.height == 0
1154- },
1155- State {
1156- name: "shown"
1157- when: keyboardRect.height == Qt.inputMethod.keyboardRectangle.height
1158- }
1159- ]
1160-
1161- function recursiveFindFocusedItem(parent) {
1162- if (parent.activeFocus) {
1163- return parent;
1164- }
1165-
1166- for (var i in parent.children) {
1167- var child = parent.children[i];
1168- if (child.activeFocus) {
1169- return child;
1170- }
1171-
1172- var item = recursiveFindFocusedItem(child);
1173-
1174- if (item != null) {
1175- return item;
1176- }
1177- }
1178-
1179- return null;
1180- }
1181-
1182- Connections {
1183- target: Qt.inputMethod
1184-
1185- onVisibleChanged: {
1186- if (!Qt.inputMethod.visible) {
1187- var focusedItem = recursiveFindFocusedItem(keyboardRect.parent);
1188- if (focusedItem != null) {
1189- focusedItem.focus = false;
1190- }
1191- }
1192- }
1193- }
1194-}
1195
1196=== removed file 'src/imports/Common/RemoveContactsDialog.qml'
1197--- src/imports/Common/RemoveContactsDialog.qml 2014-09-03 19:17:35 +0000
1198+++ src/imports/Common/RemoveContactsDialog.qml 1970-01-01 00:00:00 +0000
1199@@ -1,78 +0,0 @@
1200-/*
1201- * Copyright (C) 2014 Canonical, Ltd.
1202- *
1203- * This program is free software; you can redistribute it and/or modify
1204- * it under the terms of the GNU General Public License as published by
1205- * the Free Software Foundation; version 3.
1206- *
1207- * This program is distributed in the hope that it will be useful,
1208- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1209- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1210- * GNU General Public License for more details.
1211- *
1212- * You should have received a copy of the GNU General Public License
1213- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1214- */
1215-
1216-import QtQuick 2.2
1217-import Ubuntu.Components 1.1
1218-import Ubuntu.Components.Popups 1.0
1219-
1220-Dialog {
1221- objectName: "removeContactsDialog"
1222-
1223- property var contacts: []
1224-
1225- signal canceled()
1226- signal accepted()
1227-
1228- function removeContacts(model)
1229- {
1230- var ids = []
1231- for(var i=0, iMax=contacts.length; i < iMax; i++) {
1232- ids.push(contacts[i].contactId)
1233- }
1234- model.removeContacts(ids)
1235- }
1236-
1237- title: {
1238- if (contacts.length == 0) {
1239- return i18n.tr("No contact selected.")
1240- } else if (contacts.length == 1) {
1241- return contacts[0].displayLabel.label
1242- } else {
1243- return i18n.tr("Multiple contacts")
1244- }
1245- }
1246- text: {
1247- if (contacts.length == 1) {
1248- return i18n.tr("Are you sure that you want to remove this contact?")
1249- } else {
1250- return i18n.tr("Are you sure that you want to remove all selected contacts?")
1251- }
1252- }
1253-
1254- Button {
1255- objectName: "removeContactsDialog.Yes"
1256- anchors {
1257- left: parent.left
1258- right: parent.right
1259- margins: units.gu(1)
1260- }
1261- text: i18n.tr("Yes")
1262- color: UbuntuColors.green
1263- onClicked: accepted()
1264- }
1265-
1266- Button {
1267- objectName: "removeContactsDialog.No"
1268- anchors {
1269- left: parent.left
1270- right: parent.right
1271- margins: units.gu(1)
1272- }
1273- text: i18n.tr("No")
1274- color: UbuntuColors.red
1275- onClicked: canceled()
1276- }
1277-}
1278
1279=== removed file 'src/imports/Common/StandardAnimation.qml'
1280--- src/imports/Common/StandardAnimation.qml 2014-06-05 16:46:28 +0000
1281+++ src/imports/Common/StandardAnimation.qml 1970-01-01 00:00:00 +0000
1282@@ -1,22 +0,0 @@
1283-/*
1284- * Copyright (C) 2012-2013 Canonical, Ltd.
1285- *
1286- * This program is free software; you can redistribute it and/or modify
1287- * it under the terms of the GNU General Public License as published by
1288- * the Free Software Foundation; version 3.
1289- *
1290- * This program is distributed in the hope that it will be useful,
1291- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1292- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1293- * GNU General Public License for more details.
1294- *
1295- * You should have received a copy of the GNU General Public License
1296- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1297- */
1298-
1299-import QtQuick 2.2
1300-
1301-NumberAnimation {
1302- duration: 300
1303- easing.type: Easing.InOutQuad
1304-}
1305
1306=== removed file 'src/imports/ContactEdit/ContactEditor.qml'
1307--- src/imports/ContactEdit/ContactEditor.qml 2015-01-09 19:16:00 +0000
1308+++ src/imports/ContactEdit/ContactEditor.qml 1970-01-01 00:00:00 +0000
1309@@ -1,461 +0,0 @@
1310-/*
1311- * Copyright (C) 2012-2013 Canonical, Ltd.
1312- *
1313- * This program is free software; you can redistribute it and/or modify
1314- * it under the terms of the GNU General Public License as published by
1315- * the Free Software Foundation; version 3.
1316- *
1317- * This program is distributed in the hope that it will be useful,
1318- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1319- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1320- * GNU General Public License for more details.
1321- *
1322- * You should have received a copy of the GNU General Public License
1323- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1324- */
1325-
1326-import QtQuick 2.2
1327-import QtContacts 5.0
1328-
1329-import Ubuntu.Components 1.1
1330-import Ubuntu.Components.ListItems 1.0
1331-import Ubuntu.Components.Popups 1.0
1332-
1333-import "../Common"
1334-
1335-Page {
1336- id: contactEditor
1337- objectName: "contactEditorPage"
1338-
1339- property QtObject contact: null
1340- property QtObject model: null
1341- property QtObject activeItem: null
1342- readonly property bool isNewContact: contact && (contact.contactId === "qtcontacts:::")
1343- property string initialFocusSection: ""
1344- property var newDetails: []
1345-
1346- // priv
1347- property bool _edgeReady: false
1348-
1349- function cancel() {
1350- for (var i = 0; i < contactEditor.newDetails.length; ++i) {
1351- contactEditor.contact.removeDetail(contactEditor.newDetails[i])
1352- }
1353- contactEditor.newDetails = []
1354-
1355- for(var i = 0; i < contents.children.length; ++i) {
1356- var field = contents.children[i]
1357- if (field.cancel) {
1358- field.cancel()
1359- }
1360- }
1361- pageStack.pop()
1362- }
1363-
1364- function save() {
1365- var changed = false
1366- for(var i = 0; i < contents.children.length; ++i) {
1367- var field = contents.children[i]
1368- if (field.save) {
1369- if (field.save()) {
1370- changed = true
1371- }
1372- }
1373- }
1374-
1375- // new contact and there is only two details (name, avatar)
1376- // name and avatar, are not removable details, because of that the contact will have at least 2 details
1377- if (isNewContact &&
1378- (contact.contactDetails.length === 2)) {
1379-
1380- // if name is empty this means that the contact is empty
1381- var nameDetail = contact.detail(ContactDetail.Name)
1382- if (nameDetail &&
1383- (nameDetail.firstName && nameDetail.firstName != "") ||
1384- (nameDetail.lastName && nameDetail.lastName != "")) {
1385- // save contact
1386- } else {
1387- changed = false
1388- }
1389- }
1390-
1391- if (changed) {
1392- // backend error will be handled by the root page (contact list)
1393- var newContact = (contact.model == null)
1394- contactEditor.model.saveContact(contact)
1395- if (newContact && pageStack.contactListPage) {
1396- pageStack.contactListPage.moveListToContact(contact)
1397- }
1398- }
1399- pageStack.pop()
1400- }
1401-
1402- function makeMeVisible(item) {
1403- if (!_edgeReady || !item) {
1404- return
1405- }
1406-
1407- activeItem = item
1408- var position = scrollArea.contentItem.mapFromItem(item, 0, activeItem.y);
1409-
1410- // check if the item is already visible
1411- var bottomY = scrollArea.contentY + scrollArea.height
1412- var itemBottom = position.y + (item.height * 3) // extra margin
1413- if (position.y >= scrollArea.contentY && itemBottom <= bottomY) {
1414- return;
1415- }
1416-
1417- // if it is not, try to scroll and make it visible
1418- var targetY = itemBottom - scrollArea.height
1419- if (targetY >= 0 && position.y) {
1420- scrollArea.contentY = targetY;
1421- } else if (position.y < scrollArea.contentY) {
1422- // if it is hidden at the top, also show it
1423- scrollArea.contentY = position.y;
1424- }
1425- scrollArea.returnToBounds()
1426- }
1427-
1428- function ready()
1429- {
1430- enabled = true
1431- _edgeReady = true
1432-
1433- switch (contactEditor.initialFocusSection)
1434- {
1435- case "phones":
1436- contactEditor.focusToLastPhoneField()
1437- break;
1438- case "name":
1439- nameEditor.fieldDelegates[0].forceActiveFocus()
1440- break;
1441- }
1442- contactEditor.initialFocusSection = ""
1443- }
1444-
1445- function focusToLastPhoneField()
1446- {
1447- var lastPhoneField = phonesEditor.detailDelegates[phonesEditor.detailDelegates.length - 2].item
1448- lastPhoneField.forceActiveFocus()
1449- }
1450-
1451- title: isNewContact ? i18n.tr("New contact") : i18n.tr("Edit")
1452-
1453- Timer {
1454- id: focusTimer
1455-
1456- interval: 1000
1457- running: false
1458- repeat: false
1459- onTriggered: contactEditor.ready()
1460- }
1461-
1462- flickable: null
1463- Flickable {
1464- id: scrollArea
1465- objectName: "scrollArea"
1466-
1467- // this is necessary to avoid the page to appear bellow the header
1468- clip: true
1469- flickableDirection: Flickable.VerticalFlick
1470- anchors {
1471- fill: parent
1472- bottomMargin: keyboard.height
1473- }
1474- contentHeight: contents.height + units.gu(2)
1475- contentWidth: parent.width
1476-
1477- //after add a new field we need to wait for the contentHeight to change to scroll to the correct position
1478- onContentHeightChanged: contactEditor.makeMeVisible(contactEditor.activeItem)
1479-
1480- Column {
1481- id: contents
1482-
1483- anchors {
1484- top: parent.top
1485- topMargin: units.gu(2)
1486- left: parent.left
1487- right: parent.right
1488- }
1489- height: childrenRect.height
1490-
1491- Row {
1492- function save()
1493- {
1494- var avatarSave = avatarEditor.save()
1495- var nameSave = nameEditor.save();
1496-
1497- return (nameSave || avatarSave);
1498- }
1499-
1500- function isEmpty()
1501- {
1502- return (avatarEditor.isEmpty() && nameEditor.isEmpty())
1503- }
1504-
1505- anchors {
1506- left: parent.left
1507- leftMargin: units.gu(2)
1508- right: parent.right
1509- }
1510- height: Math.max(avatarEditor.height, nameEditor.height) - units.gu(4)
1511-
1512- ContactDetailAvatarEditor {
1513- id: avatarEditor
1514-
1515- contact: contactEditor.contact
1516- height: implicitHeight
1517- width: implicitWidth
1518- }
1519-
1520- ContactDetailNameEditor {
1521- id: nameEditor
1522-
1523- width: parent.width - avatarEditor.width
1524- height: nameEditor.implicitHeight + units.gu(3)
1525- contact: contactEditor.contact
1526- }
1527- }
1528-
1529- ContactDetailPhoneNumbersEditor {
1530- id: phonesEditor
1531- objectName: "phones"
1532-
1533- contact: contactEditor.contact
1534- anchors {
1535- left: parent.left
1536- right: parent.right
1537- }
1538- height: implicitHeight
1539- }
1540-
1541- ContactDetailEmailsEditor {
1542- id: emailsEditor
1543- objectName: "emails"
1544-
1545- contact: contactEditor.contact
1546- anchors {
1547- left: parent.left
1548- right: parent.right
1549- }
1550- height: implicitHeight
1551- }
1552-
1553- ContactDetailOnlineAccountsEditor {
1554- id: accountsEditor
1555- objectName: "ims"
1556-
1557- contact: contactEditor.contact
1558- anchors {
1559- left: parent.left
1560- right: parent.right
1561- }
1562- height: implicitHeight
1563- }
1564-
1565- ContactDetailAddressesEditor {
1566- id: addressesEditor
1567- objectName: "addresses"
1568-
1569- contact: contactEditor.contact
1570- anchors {
1571- left: parent.left
1572- right: parent.right
1573- }
1574- height: implicitHeight
1575- }
1576-
1577- ContactDetailOrganizationsEditor {
1578- id: organizationsEditor
1579- objectName: "professionalDetails"
1580-
1581- contact: contactEditor.contact
1582- anchors {
1583- left: parent.left
1584- right: parent.right
1585- }
1586- height: implicitHeight
1587- }
1588-
1589- ContactDetailSyncTargetEditor {
1590- id: syncTargetEditor
1591-
1592- active: contactEditor.active
1593- contact: contactEditor.contact
1594- anchors {
1595- left: parent.left
1596- right: parent.right
1597- }
1598- height: implicitHeight
1599- }
1600-
1601- ThinDivider {}
1602-
1603- Item {
1604- anchors {
1605- left: parent.left
1606- right: parent.right
1607- }
1608- height: units.gu(2)
1609- }
1610-
1611- ComboButtonAddField {
1612- id: addNewFieldButton
1613- objectName: "addNewFieldButton"
1614-
1615- contact: contactEditor.contact
1616- text: i18n.tr("Add Field")
1617- anchors {
1618- left: parent.left
1619- right: parent.right
1620- margins: units.gu(2)
1621- }
1622- height: implicitHeight
1623- onHeightChanged: {
1624- if (expanded && (height === expandedHeight) && !scrollArea.atYEnd) {
1625- moveToBottom.start()
1626- }
1627- }
1628-
1629- UbuntuNumberAnimation {
1630- id: moveToBottom
1631-
1632- target: scrollArea
1633- property: "contentY"
1634- from: scrollArea.contentY
1635- to: Math.min(scrollArea.contentHeight - scrollArea.height,
1636- scrollArea.contentY + (addNewFieldButton.height - addNewFieldButton.collapsedHeight - units.gu(3)))
1637- }
1638-
1639- onFieldSelected: {
1640- if (qmlTypeName) {
1641- var newDetail = Qt.createQmlObject("import QtContacts 5.0; " + qmlTypeName + "{}", contactEditor)
1642- if (newDetail) {
1643- var newDetailsCopy = contactEditor.newDetails
1644- newDetailsCopy.push(newDetail)
1645- contactEditor.newDetails = newDetailsCopy
1646- contactEditor.contact.addDetail(newDetail)
1647- }
1648- }
1649- }
1650- }
1651-
1652-
1653- Item {
1654- anchors {
1655- left: parent.left
1656- right: parent.right
1657- }
1658- height: units.gu(2)
1659- }
1660-
1661- Button {
1662- id: deleteButton
1663-
1664- text: i18n.tr("Delete")
1665- visible: !contactEditor.isNewContact
1666- color: UbuntuColors.red
1667- anchors {
1668- left: parent.left
1669- right: parent.right
1670- margins: units.gu(2)
1671- }
1672- onClicked: {
1673- var dialog = PopupUtils.open(removeContactDialog, null)
1674- dialog.contacts = [contactEditor.contact]
1675- }
1676- }
1677-
1678-
1679- Item {
1680- anchors {
1681- left: parent.left
1682- right: parent.right
1683- }
1684- height: units.gu(2)
1685- }
1686- }
1687- }
1688-
1689- KeyboardRectangle {
1690- id: keyboard
1691-
1692- onHeightChanged: {
1693- if (activeItem) {
1694- makeMeVisible(activeItem)
1695- }
1696- }
1697- }
1698-
1699- tools: ToolbarItems {
1700- id: toolbar
1701-
1702- back: ToolbarButton {
1703- action: Action {
1704- objectName: "cancel"
1705-
1706- iconName: "back"
1707- text: i18n.tr("Cancel")
1708- onTriggered: {
1709- contactEditor.cancel()
1710- contactEditor.active = false
1711- }
1712- }
1713- }
1714-
1715- ToolbarButton {
1716- action: Action {
1717- objectName: "save"
1718-
1719- iconName: "ok"
1720- text: i18n.tr("Save")
1721- // disable save button while avatar scale still running
1722- enabled: !avatarEditor.busy && (!nameEditor.isEmpty() || !phonesEditor.isEmpty())
1723- onTriggered: contactEditor.save()
1724- }
1725- }
1726- }
1727-
1728- Component.onCompleted: {
1729- if (!enabled) {
1730- return
1731- }
1732-
1733- if (contactEditor.initialFocusSection != "") {
1734- focusTimer.restart()
1735- } else {
1736- contactEditor.ready()
1737- }
1738- }
1739-
1740- Component {
1741- id: removeContactDialog
1742-
1743- RemoveContactsDialog {
1744- id: removeContactsDialogMessage
1745-
1746- property bool popPages: false
1747-
1748- onCanceled: {
1749- PopupUtils.close(removeContactsDialogMessage)
1750- }
1751-
1752- onAccepted: {
1753- popPages = true
1754- removeContacts(contactEditor.model)
1755- PopupUtils.close(removeContactsDialogMessage)
1756- }
1757-
1758- // hide virtual keyboard if necessary
1759- Component.onCompleted: Qt.inputMethod.hide()
1760-
1761- // WORKAROUND: SDK element crash if pop the page where the dialog was created
1762- Component.onDestruction: {
1763- if (popPages) {
1764- contactEditor.pageStack.pop() // editor page
1765- contactEditor.pageStack.pop() // view page
1766- }
1767- }
1768- }
1769- }
1770-}
1771
1772=== removed directory 'src/imports/ContactList'
1773=== removed file 'src/imports/ContactList/CMakeLists.txt'
1774--- src/imports/ContactList/CMakeLists.txt 2015-02-05 16:18:10 +0000
1775+++ src/imports/ContactList/CMakeLists.txt 1970-01-01 00:00:00 +0000
1776@@ -1,11 +0,0 @@
1777-set(CONTACT_LIST_QMLS
1778- ContactListPage.qml
1779- VCardImportDialog.qml
1780-)
1781-
1782-install(FILES ${CONTACT_LIST_QMLS}
1783- DESTINATION ${ADDRESS_BOOK_APP_DIR}/imports/ContactList
1784-)
1785-
1786-# make the files visible on qtcreator
1787-add_custom_target(contact_list_QmlFiles ALL SOURCES ${CONTACT_LIST_QMLS})
1788
1789=== removed file 'src/imports/ContactList/ContactListPage.qml'
1790--- src/imports/ContactList/ContactListPage.qml 2015-03-06 13:59:58 +0000
1791+++ src/imports/ContactList/ContactListPage.qml 1970-01-01 00:00:00 +0000
1792@@ -1,554 +0,0 @@
1793-/*
1794- * Copyright (C) 2012-2013 Canonical, Ltd.
1795- *
1796- * This program is free software; you can redistribute it and/or modify
1797- * it under the terms of the GNU General Public License as published by
1798- * the Free Software Foundation; version 3.
1799- *
1800- * This program is distributed in the hope that it will be useful,
1801- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1802- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1803- * GNU General Public License for more details.
1804- *
1805- * You should have received a copy of the GNU General Public License
1806- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1807- */
1808-
1809-import QtQuick 2.2
1810-import QtContacts 5.0
1811-
1812-import Ubuntu.Components 1.1
1813-import Ubuntu.Components.ListItems 1.0 as ListItem
1814-import Ubuntu.Components.Popups 1.0 as Popups
1815-import Ubuntu.Contacts 0.1 as ContactsUI
1816-import Ubuntu.Content 1.1 as ContentHub
1817-
1818-import "../Common"
1819-
1820-ContactsUI.PageWithBottomEdge {
1821- id: mainPage
1822- objectName: "contactListPage"
1823-
1824- property bool pickMode: false
1825- property alias contentHubTransfer: contactExporter.activeTransfer
1826- property bool pickMultipleContacts: false
1827- property QtObject contactIndex: null
1828- property string newPhoneToAdd: ""
1829- property alias contactManager: contactList.manager
1830-
1831- readonly property bool isEmpty: (contactList.count === 0)
1832- readonly property bool allowToQuit: (application.callbackApplication.length > 0)
1833- readonly property var contactModel: contactList.listModel ? contactList.listModel : null
1834- readonly property bool searching: (state === "searching" || state === "newphoneSearching")
1835-
1836- // this function is used to reset the contact list page to the default state if it was called
1837- // from the uri. For example when called to add a new contact
1838- function returnToNormalState()
1839- {
1840- // these two states are the only state that need to be reset
1841- if (state == "newphoneSearching" || state == "newphone") {
1842- state = "default"
1843- }
1844- application.callbackApplication = ""
1845- }
1846-
1847- function createEmptyContact(phoneNumber)
1848- {
1849- var details = [ {detail: "PhoneNumber", field: "number", value: phoneNumber},
1850- {detail: "EmailAddress", field: "emailAddress", value: ""},
1851- {detail: "Name", field: "firstName", value: ""}
1852- ]
1853-
1854- var newContact = Qt.createQmlObject("import QtContacts 5.0; Contact{ }", mainPage)
1855- var detailSourceTemplate = "import QtContacts 5.0; %1{ %2: \"%3\" }"
1856- for (var i=0; i < details.length; i++) {
1857- var detailMetaData = details[i]
1858- var newDetail = Qt.createQmlObject(detailSourceTemplate.arg(detailMetaData.detail)
1859- .arg(detailMetaData.field)
1860- .arg(detailMetaData.value), mainPage)
1861- newContact.addDetail(newDetail)
1862- }
1863- return newContact
1864- }
1865-
1866- function createContactWithPhoneNumber(phoneNumber)
1867- {
1868- var newContact = mainPage.createEmptyContact(phoneNumber)
1869- //WORKAROUND: SKD changes the page header as soon as the page get created
1870- // setting active false will avoid that
1871- if (bottomEdgeEnabled) {
1872- mainPage.showBottomEdgePage(Qt.resolvedUrl("../ContactEdit/ContactEditor.qml"),
1873- {model: contactList.listModel,
1874- contact: newContact,
1875- active: false,
1876- enabled: false,
1877- initialFocusSection: "name"})
1878- } else {
1879- pageStack.push(Qt.resolvedUrl("../ContactEdit/ContactEditor.qml"),
1880- {model: contactList.listModel,
1881- contact: newContact,
1882- initialFocusSection: "name"})
1883- }
1884- }
1885-
1886- function showContact(contactId)
1887- {
1888- pageStack.push(Qt.resolvedUrl("../ContactView/ContactView.qml"),
1889- {model: contactList.listModel, contactId: contactId})
1890- }
1891-
1892- function addPhoneToContact(contactId, phoneNumber)
1893- {
1894- pageStack.push(Qt.resolvedUrl("../ContactView/ContactView.qml"),
1895- {model: contactList.listModel,
1896- contactId: contactId,
1897- addPhoneToContact: phoneNumber})
1898- }
1899-
1900- function importContact(urls)
1901- {
1902- if (urls.length > 0) {
1903- var importDialog = Qt.createQmlObject("VCardImportDialog{}",
1904- mainPage,
1905- "VCardImportDialog")
1906- if (importDialog) {
1907- importDialog.importVCards(contactList.listModel, urls)
1908- }
1909- }
1910- }
1911-
1912- function startPickMode(isSingleSelection, activeTransfer)
1913- {
1914- contentHubTransfer = activeTransfer
1915- pickMode = true
1916- pickMultipleContacts = !isSingleSelection
1917- contactList.startSelection()
1918- }
1919-
1920- function moveListToContact(contact)
1921- {
1922- contactIndex = contact
1923- mainPage.state = "default"
1924- // this means a new contact was created
1925- if (mainPage.allowToQuit) {
1926- application.goBackToSourceApp()
1927- }
1928- }
1929-
1930- function addNewPhone(phoneNumber)
1931- {
1932- newPhoneToAdd = phoneNumber
1933- state = "newphone"
1934- contactList.reset()
1935- }
1936-
1937- title: i18n.tr("Contacts")
1938- bottomEdgeTitle: "+"
1939- bottomEdgeEnabled: !contactList.isInSelectionMode
1940-
1941- flickable: null
1942- ContactsUI.ContactListView {
1943- id: contactList
1944- objectName: "contactListView"
1945- showImportOptions: !mainPage.pickMode &&
1946- mainPage.newPhoneToAdd === ""
1947- anchors {
1948- top: parent.top
1949- left: parent.left
1950- bottom: keyboard.top
1951- right: parent.right
1952- }
1953- filterTerm: searchField.text
1954- detailToPick: ContactDetail.PhoneNumber
1955- multiSelectionEnabled: true
1956- multipleSelection: (mainPage.pickMode && mainPage.pickMultipleContacts) || !mainPage.pickMode
1957-
1958- leftSideAction: Action {
1959- iconName: "delete"
1960- text: i18n.tr("Delete")
1961- onTriggered: value.remove()
1962- }
1963- onAddContactClicked: mainPage.createContactWithPhoneNumber(label)
1964- onAddNewContactClicked: mainPage.createContactWithPhoneNumber(mainPage.newPhoneToAdd)
1965-
1966- onInfoRequested: {
1967- mainPage.state = "default"
1968- pageStack.push(Qt.resolvedUrl("../ContactView/ContactView.qml"),
1969- {model: contactList.listModel,
1970- contact: contact})
1971- }
1972-
1973- onDetailClicked: {
1974- if (action == "call")
1975- Qt.openUrlExternally("tel:///" + encodeURIComponent(detail.number))
1976- else if (action == "message")
1977- Qt.openUrlExternally("message:///" + encodeURIComponent(detail.number))
1978- else if ((mainPage.state === "newphone") || (mainPage.state === "newphoneSearching")) {
1979- mainPage.addPhoneToContact(contact.contactId, mainPage.newPhoneToAdd)
1980- }
1981- }
1982-
1983- onAddDetailClicked: mainPage.addPhoneToContact(contact.contactId, " ")
1984- onIsInSelectionModeChanged: mainPage.state = isInSelectionMode ? "selection" : "default"
1985- onSelectionCanceled: {
1986- if (pickMode) {
1987- if (contentHubTransfer) {
1988- contentHubTransfer.state = ContentHub.ContentTransfer.Aborted
1989- }
1990- pickMode = false
1991- contentHubTransfer = null
1992- application.returnVcard("")
1993- }
1994- mainPage.state = "default"
1995- }
1996-
1997- onError: pageStack.contactModelError(error)
1998- }
1999-
2000- TextField {
2001- id: searchField
2002-
2003- anchors {
2004- left: parent.left
2005- right: parent.right
2006- rightMargin: units.gu(2)
2007- }
2008- visible: mainPage.searching
2009- onTextChanged: contactList.currentIndex = -1
2010- inputMethodHints: Qt.ImhNoPredictiveText
2011- placeholderText: i18n.tr("Search...")
2012- }
2013-
2014- Connections {
2015- target: mainPage.head.sections
2016- onSelectedIndexChanged: {
2017- switch (mainPage.head.sections.selectedIndex) {
2018- case 0:
2019- contactList.showAllContacts()
2020- break;
2021- case 1:
2022- contactList.showFavoritesContacts()
2023- break;
2024- default:
2025- break;
2026- }
2027- }
2028- }
2029-
2030- state: "default"
2031- states: [
2032- PageHeadState {
2033- id: defaultState
2034-
2035- name: "default"
2036- backAction: Action {
2037- visible: mainPage.allowToQuit
2038- iconName: "back"
2039- text: i18n.tr("Quit")
2040- onTriggered: {
2041- application.goBackToSourceApp()
2042- mainPage.returnToNormalState()
2043- }
2044- }
2045- actions: [
2046- Action {
2047- text: i18n.tr("Search")
2048- iconName: "search"
2049- visible: !mainPage.isEmpty
2050- onTriggered: {
2051- mainPage.state = (mainPage.state === "newphone" ? "newphoneSearching" : "searching")
2052- contactList.showAllContacts()
2053- searchField.forceActiveFocus()
2054- }
2055- },
2056- Action {
2057- visible: contactList.syncEnabled
2058- text: contactList.syncing ? i18n.tr("Syncing") : i18n.tr("Sync")
2059- iconName: "reload"
2060- enabled: !contactList.syncing
2061- onTriggered: contactList.sync()
2062- },
2063- Action {
2064- text: i18n.tr("Settings")
2065- iconName: "settings"
2066- onTriggered: pageStack.push(Qt.resolvedUrl("../Settings/SettingsPage.qml"),
2067- {"contactListModel": contactList.listModel})
2068- }
2069- ]
2070- PropertyChanges {
2071- target: mainPage.head
2072- backAction: defaultState.backAction
2073- actions: defaultState.actions
2074- // TRANSLATORS: this refers to all contacts
2075- sections.model: [i18n.tr("All"), i18n.tr("Favorites")]
2076- }
2077- PropertyChanges {
2078- target: searchField
2079- text: ""
2080- }
2081- },
2082- PageHeadState {
2083- id: searchingState
2084-
2085- name: "searching"
2086- backAction: Action {
2087- iconName: "back"
2088- text: i18n.tr("Cancel")
2089- onTriggered: {
2090- contactList.forceActiveFocus()
2091- mainPage.head.sections.selectedIndex = 0
2092- mainPage.state = (mainPage.state === "newphoneSearching" ? "newphone" : "default")
2093- }
2094- }
2095-
2096- PropertyChanges {
2097- target: mainPage.head
2098- backAction: searchingState.backAction
2099- contents: searchField
2100- }
2101-
2102- PropertyChanges {
2103- target: searchField
2104- text: ""
2105- }
2106- },
2107- PageHeadState {
2108- id: selectionState
2109-
2110- name: "selection"
2111- backAction: Action {
2112- text: i18n.tr("Cancel selection")
2113- iconName: "back"
2114- onTriggered: contactList.cancelSelection()
2115- }
2116- actions: [
2117- Action {
2118- text: (contactList.selectedItems.count === contactList.count) ? i18n.tr("Unselect All") : i18n.tr("Select All")
2119- iconName: "select"
2120- onTriggered: {
2121- if (contactList.selectedItems.count === contactList.count) {
2122- contactList.clearSelection()
2123- } else {
2124- contactList.selectAll()
2125- }
2126- }
2127- visible: contactList.multipleSelection && !mainPage.isEmpty
2128- },
2129- Action {
2130- objectName: "share"
2131- text: i18n.tr("Share")
2132- iconName: mainPage.pickMode ? "tick" : "share"
2133- enabled: (contactList.selectedItems.count > 0)
2134- visible: contactList.isInSelectionMode
2135- onTriggered: {
2136- var contacts = []
2137- var items = contactList.selectedItems
2138-
2139- for (var i=0, iMax=items.count; i < iMax; i++) {
2140- contacts.push(items.get(i).model.contact)
2141- }
2142- contactExporter.start(contacts)
2143- contactList.endSelection()
2144- }
2145- },
2146- Action {
2147- objectName: "delete"
2148- text: i18n.tr("Delete")
2149- iconName: "delete"
2150- enabled: (contactList.selectedItems.count > 0)
2151- visible: contactList.isInSelectionMode && !mainPage.pickMode
2152- onTriggered: {
2153- var contacts = []
2154- var items = contactList.selectedItems
2155-
2156- for (var i=0, iMax=items.count; i < iMax; i++) {
2157- contacts.push(items.get(i).model.contact)
2158- }
2159-
2160- var dialog = PopupUtils.open(removeContactDialog, null)
2161- dialog.contacts = contacts
2162- contactList.endSelection()
2163- }
2164- }
2165- ]
2166- PropertyChanges {
2167- target: mainPage.head
2168- backAction: selectionState.backAction
2169- actions: selectionState.actions
2170- }
2171- PropertyChanges {
2172- target: mainPage
2173- bottomEdgeEnabled: false
2174- title: " "
2175- }
2176- },
2177- PageHeadState {
2178- name: "newphone"
2179- extend: "default"
2180- head: mainPage.head
2181- PropertyChanges {
2182- target: contactList
2183- showAddNewButton: true
2184- }
2185- PropertyChanges {
2186- target: mainPage
2187- bottomEdgeEnabled: false
2188- title: i18n.tr("Add contact")
2189- }
2190- PropertyChanges {
2191- target: contactList
2192- detailToPick: -1
2193- }
2194- },
2195- PageHeadState {
2196- name: "newphoneSearching"
2197- extend: "searching"
2198- head: mainPage.head
2199- PropertyChanges {
2200- target: contactList
2201- detailToPick: -1
2202- showAddNewButton: true
2203- }
2204- PropertyChanges {
2205- target: mainPage
2206- bottomEdgeEnabled: false
2207- }
2208- }
2209- ]
2210- onActiveChanged: {
2211- if (active && contactList.showAddNewButton) {
2212- contactList.positionViewAtBeginning()
2213- }
2214- }
2215-
2216- // We need to reset the page proprerties in case of the page was created pre-populated,
2217- // with phonenumber or contact.
2218- onBottomEdgeDismissed: {
2219- //WORKAROUND: SKD changes the page header as soon as the page get created
2220- // setting active false will avoid that
2221- var newContact = mainPage.createEmptyContact("")
2222- mainPage.setBottomEdgePage(Qt.resolvedUrl("../ContactEdit/ContactEditor.qml"),
2223- {model: contactList.listModel,
2224- contact: newContact,
2225- active: false,
2226- enabled: false,
2227- initialFocusSection: "name"})
2228- }
2229-
2230- KeyboardRectangle {
2231- id: keyboard
2232- }
2233-
2234- Column {
2235- id: emptyStateScreen
2236-
2237- anchors.centerIn: parent
2238- height: childrenRect.height
2239- width: childrenRect.width
2240- spacing: units.gu(2)
2241- visible: (!contactList.busy &&
2242- !contactList.favouritesIsSelected &&
2243- mainPage.isEmpty &&
2244- (mainPage.newPhoneToAdd === "") &&
2245- !(contactList.filterTerm && contactList.filterTerm !== ""))
2246-
2247- Behavior on visible {
2248- SequentialAnimation {
2249- PauseAnimation {
2250- duration: !emptyStateScreen.visible ? 500 : 0
2251- }
2252- PropertyAction {
2253- target: emptyStateScreen
2254- property: "visible"
2255- }
2256- }
2257- }
2258-
2259- Icon {
2260- id: emptyStateIcon
2261- anchors.horizontalCenter: emptyStateLabel.horizontalCenter
2262- height: units.gu(5)
2263- width: units.gu(5)
2264- opacity: 0.3
2265- name: "contact"
2266- }
2267- Label {
2268- id: emptyStateLabel
2269- width: mainPage.width - units.gu(12)
2270- height: paintedHeight
2271- text: mainPage.pickMode ?
2272- i18n.tr("You have no contacts.") :
2273- i18n.tr("Create a new contact by swiping up from the bottom of the screen.")
2274- color: "#5d5d5d"
2275- fontSize: "x-large"
2276- wrapMode: Text.WordWrap
2277- horizontalAlignment: Text.AlignHCenter
2278- }
2279- }
2280-
2281- Connections {
2282- target: mainPage.contactModel
2283- onContactsChanged: {
2284- if (contactIndex) {
2285- contactList.positionViewAtContact(mainPage.contactIndex)
2286- mainPage.contactIndex = null
2287- }
2288- }
2289- }
2290-
2291- ContactExporter {
2292- id: contactExporter
2293-
2294- contactModel: contactList.listModel
2295- exportToDisk: mainPage.pickMode
2296- onDone: {
2297- mainPage.pickMode = false
2298- mainPage.state = "default"
2299- application.returnVcard(outputFile)
2300- }
2301-
2302- onContactsFetched: {
2303- // Share contacts to an application chosen by the user
2304- if (!mainPage.pickMode) {
2305- contactExporter.dismissBusyDialog()
2306- pageStack.push(Qt.resolvedUrl("../ContactShare/ContactSharePage.qml"),
2307- { contactModel: contactExporter.contactModel, contacts: contacts })
2308- }
2309- }
2310- }
2311-
2312- Component {
2313- id: removeContactDialog
2314-
2315- RemoveContactsDialog {
2316- id: removeContactsDialogMessage
2317-
2318- onCanceled: {
2319- PopupUtils.close(removeContactsDialogMessage)
2320- }
2321-
2322- onAccepted: {
2323- removeContacts(contactList.listModel)
2324- PopupUtils.close(removeContactsDialogMessage)
2325- }
2326- }
2327- }
2328-
2329- Component.onCompleted: {
2330- application.elapsed()
2331- if ((typeof(TEST_DATA) !== "undefined") && (TEST_DATA !== "")) {
2332- contactList.listModel.importContacts("file://" + TEST_DATA)
2333- }
2334-
2335- mainPage.setBottomEdgePage(Qt.resolvedUrl("../ContactEdit/ContactEditor.qml"),
2336- {model: contactList.listModel,
2337- contact: mainPage.createEmptyContact(""),
2338- active: false,
2339- enabled: false,
2340- initialFocusSection: "name"})
2341-
2342- if (pageStack) {
2343- pageStack.contactListPage = mainPage
2344- }
2345- }
2346-}
2347
2348=== removed file 'src/imports/ContactList/VCardImportDialog.qml'
2349--- src/imports/ContactList/VCardImportDialog.qml 2014-07-20 20:23:20 +0000
2350+++ src/imports/ContactList/VCardImportDialog.qml 1970-01-01 00:00:00 +0000
2351@@ -1,94 +0,0 @@
2352-/*
2353- * Copyright (C) 2014 Canonical, Ltd.
2354- *
2355- * This program is free software; you can redistribute it and/or modify
2356- * it under the terms of the GNU General Public License as published by
2357- * the Free Software Foundation; version 3.
2358- *
2359- * This program is distributed in the hope that it will be useful,
2360- * but WITHOUT ANY WARRANTY; without even the implied warranty of
2361- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2362- * GNU General Public License for more details.
2363- *
2364- * You should have received a copy of the GNU General Public License
2365- * along with this program. If not, see <http://www.gnu.org/licenses/>.
2366- */
2367-
2368-import QtQuick 2.2
2369-import QtContacts 5.0
2370-import Ubuntu.Components 1.1
2371-import Ubuntu.Components.Popups 1.0 as Popups
2372-
2373-Item {
2374- id: root
2375-
2376- property alias model: modelConnections.target
2377- property var vcards: []
2378- property var importedVcards: []
2379- property var importErrors: []
2380- property var dialog: null
2381-
2382- signal finished()
2383-
2384- function importVCards(model, vcards)
2385- {
2386- if (dialog || vcards.length === 0) {
2387- return
2388- }
2389-
2390- root.model = model
2391- root.vcards = vcards
2392- dialog = Popups.PopupUtils.open(importDialogComponent, root)
2393-
2394- for(var i=0, iMax=vcards.length; i < iMax; i++) {
2395- var vcardUrl = vcards[i]
2396- model.importContacts(vcardUrl)
2397- }
2398- }
2399-
2400- Connections {
2401- id: modelConnections
2402-
2403- onImportCompleted: {
2404- var imported = root.importedVcards
2405- var importErrors = root.importErrors
2406- imported.push(url)
2407- if (error !== ContactModel.ImportNoError) {
2408- root.importErrors.push(error)
2409- console.error("Fail to import vcard:" + error)
2410- }
2411- root.importedVcards = imported
2412- root.importErrors = importErrors
2413- }
2414- }
2415-
2416- Component {
2417- id: importDialogComponent
2418-
2419- Popups.Dialog {
2420- id: importDialog
2421-
2422- title: i18n.tr("Import vCards")
2423- text: root.importedVcards.length === 0 ? i18n.tr("Importing...") : i18n.tr("%1 vCards imported").arg(root.importedVcards.length)
2424-
2425- Button {
2426- anchors {
2427- left: parent.left
2428- right: parent.right
2429- margins: units.gu(1)
2430- }
2431- text: i18n.tr("Close")
2432- enabled: (root.importedVcards.length === root.vcards.length)
2433- onClicked: {
2434- root.dialog = null
2435- Popups.PopupUtils.close(importDialog)
2436- }
2437- }
2438-
2439- Component.onDestruction: root.destroy()
2440- }
2441- }
2442-}
2443-
2444-
2445-
2446
2447=== removed directory 'src/imports/ContactShare'
2448=== removed file 'src/imports/ContactShare/CMakeLists.txt'
2449--- src/imports/ContactShare/CMakeLists.txt 2014-06-11 21:25:08 +0000
2450+++ src/imports/ContactShare/CMakeLists.txt 1970-01-01 00:00:00 +0000
2451@@ -1,10 +0,0 @@
2452-set(CONTACT_SHARE_QMLS
2453- ContactSharePage.qml
2454-)
2455-
2456-install(FILES ${CONTACT_SHARE_QMLS}
2457- DESTINATION ${ADDRESS_BOOK_APP_DIR}/imports/ContactShare
2458-)
2459-
2460-# make the files visible on qtcreator
2461-add_custom_target(contact_share_QmlFiles ALL SOURCES ${CONTACT_SHARE_QMLS})
2462
2463=== removed file 'src/imports/ContactShare/ContactSharePage.qml'
2464--- src/imports/ContactShare/ContactSharePage.qml 2014-10-09 17:39:12 +0000
2465+++ src/imports/ContactShare/ContactSharePage.qml 1970-01-01 00:00:00 +0000
2466@@ -1,56 +0,0 @@
2467-/*
2468- * Copyright (C) 2012-2014 Canonical, Ltd.
2469- *
2470- * This program is free software; you can redistribute it and/or modify
2471- * it under the terms of the GNU General Public License as published by
2472- * the Free Software Foundation; version 3.
2473- *
2474- * This program is distributed in the hope that it will be useful,
2475- * but WITHOUT ANY WARRANTY; without even the implied warranty of
2476- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2477- * GNU General Public License for more details.
2478- *
2479- * You should have received a copy of the GNU General Public License
2480- * along with this program. If not, see <http://www.gnu.org/licenses/>.
2481- */
2482-
2483-import QtQuick 2.2
2484-import QtContacts 5.0
2485-import Ubuntu.Components 1.1
2486-import Ubuntu.Content 1.1 as ContentHub
2487-import "../Common"
2488-
2489-Page {
2490- id: picker
2491-
2492- property alias contactModel: exporter.contactModel
2493- property var contacts
2494- property var curTransfer
2495-
2496- ContentHub.ContentPeerPicker {
2497- visible: true
2498- anchors.fill: parent
2499- contentType: ContentHub.ContentType.Contacts
2500- handler: ContentHub.ContentHandler.Share
2501-
2502- onPeerSelected: {
2503- exporter.activeTransfer = peer.request();
2504- if (exporter.activeTransfer.state === ContentHub.ContentTransfer.InProgress) {
2505- exporter.start(picker.contacts)
2506- }
2507- }
2508-
2509- onCancelPressed: {
2510- if (exporter.activeTransfer) {
2511- exporter.activeTransfer.state = ContentHub.ContentTransfer.Aborted
2512- }
2513- pageStack.pop()
2514- }
2515- }
2516-
2517- ContactExporter {
2518- id: exporter
2519-
2520- onDone: pageStack.pop()
2521- }
2522-}
2523
2524=== removed file 'src/imports/ContactView/ContactView.qml'
2525--- src/imports/ContactView/ContactView.qml 2014-09-17 18:36:48 +0000
2526+++ src/imports/ContactView/ContactView.qml 1970-01-01 00:00:00 +0000
2527@@ -1,123 +0,0 @@
2528-/*
2529- * Copyright (C) 2012-2013 Canonical, Ltd.
2530- *
2531- * This program is free software; you can redistribute it and/or modify
2532- * it under the terms of the GNU General Public License as published by
2533- * the Free Software Foundation; version 3.
2534- *
2535- * This program is distributed in the hope that it will be useful,
2536- * but WITHOUT ANY WARRANTY; without even the implied warranty of
2537- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2538- * GNU General Public License for more details.
2539- *
2540- * You should have received a copy of the GNU General Public License
2541- * along with this program. If not, see <http://www.gnu.org/licenses/>.
2542- */
2543-
2544-import QtQuick 2.2
2545-import Ubuntu.Components 1.1
2546-import Ubuntu.Components.Popups 1.0 as Popups
2547-import Ubuntu.Contacts 0.1
2548-
2549-ContactPreviewPage {
2550- id: root
2551- objectName: "contactViewPage"
2552-
2553- property alias model: contactFetch.model
2554- // used by main page to open the contact view on app startup
2555- property string contactId: ""
2556- property string addPhoneToContact: ""
2557-
2558- onActiveChanged: {
2559- if (active) {
2560- //WORKAROUND: to correct scroll back the page
2561- flickable.returnToBounds()
2562- }
2563- }
2564-
2565- // Page page if the contact get removed
2566- onContactChanged: {
2567- if (!contact) {
2568- pageStack.pop()
2569- }
2570- }
2571-
2572- extensions: ContactDetailSyncTargetView {
2573- contact: root.contact
2574- anchors {
2575- left: parent.left
2576- right: parent.right
2577- }
2578- height: implicitHeight
2579- }
2580-
2581- ActivityIndicator {
2582- id: busyIndicator
2583-
2584- parent: root
2585-
2586- running: (root.contact === null) && contactFetch.running
2587- visible: running
2588- anchors.centerIn: parent
2589- }
2590-
2591- ContactFetchError {
2592- id: fetchErrorDialog
2593- }
2594-
2595- ContactFetch {
2596- id: contactFetch
2597-
2598- onContactRemoved: {
2599- pageStack.pop()
2600- }
2601-
2602- onContactNotFound: Popups.PopupUtils.open(fetchErrorDialog, pageStack)
2603-
2604- onContactFetched: {
2605- root.contact = contact
2606- if (root.addPhoneToContact != "") {
2607- var detailSourceTemplate = "import QtContacts 5.0; PhoneNumber{ number: \"" + root.addPhoneToContact.trim() + "\" }"
2608- var newDetail = Qt.createQmlObject(detailSourceTemplate, root.contact)
2609- if (newDetail) {
2610- root.contact.addDetail(newDetail)
2611- pageStack.push(Qt.resolvedUrl("../ContactEdit/ContactEditor.qml"),
2612- { model: root.model,
2613- contact: root.contact,
2614- initialFocusSection: "phones",
2615- newDetails: [newDetail]})
2616- root.addPhoneToContact = ""
2617- }
2618- }
2619- }
2620- }
2621-
2622- head.actions: [
2623- Action {
2624- objectName: "share"
2625- text: i18n.tr("Share")
2626- iconName: "share"
2627- onTriggered: {
2628- pageStack.push(Qt.resolvedUrl("../ContactShare/ContactSharePage.qml"),
2629- { contactModel: root.model, contacts: [root.contact] })
2630- }
2631- },
2632- Action {
2633- objectName: "edit"
2634- text: i18n.tr("Edit")
2635- iconName: "edit"
2636- onTriggered: {
2637- pageStack.push(Qt.resolvedUrl("../ContactEdit/ContactEditor.qml"),
2638- { model: root.model, contact: root.contact})
2639- }
2640- }
2641- ]
2642-
2643- // This will load the contact information when the app was launched with
2644- // the URI: addressbook:///contact?id=<id>
2645- Component.onCompleted: {
2646- if (contactId !== "") {
2647- contactFetch.fetchContact(contactId)
2648- }
2649- }
2650-}
2651
2652=== modified file 'src/imports/ContentHubProxy.qml'
2653--- src/imports/ContentHubProxy.qml 2014-10-10 13:12:18 +0000
2654+++ src/imports/ContentHubProxy.qml 2015-05-12 21:19:18 +0000
2655@@ -1,5 +1,5 @@
2656 /*
2657- * Copyright (C) 2012-2013 Canonical, Ltd.
2658+ * Copyright (C) 2012-2015 Canonical, Ltd.
2659 *
2660 * This program is free software; you can redistribute it and/or modify
2661 * it under the terms of the GNU General Public License as published by
2662
2663=== modified file 'src/imports/MainWindow.qml'
2664--- src/imports/MainWindow.qml 2015-02-19 06:58:37 +0000
2665+++ src/imports/MainWindow.qml 2015-05-12 21:19:18 +0000
2666@@ -18,7 +18,6 @@
2667 import Ubuntu.Components 1.0
2668 import Ubuntu.Components.Popups 1.0 as Popups
2669
2670-
2671 MainView {
2672 id: mainWindow
2673 objectName: "addressBookAppMainWindow"
2674@@ -140,7 +139,7 @@
2675 application.elapsed()
2676 i18n.domain = "address-book-app"
2677 i18n.bindtextdomain("address-book-app", i18nDirectory)
2678- mainStack.push(Qt.resolvedUrl("./ContactList/ContactListPage.qml"))
2679+ mainStack.push(Qt.resolvedUrl("ABContactListPage.qml"))
2680 mainWindow.applicationReady()
2681 }
2682
2683
2684=== added directory 'src/imports/Ubuntu/AddressBook'
2685=== added directory 'src/imports/Ubuntu/AddressBook/Base'
2686=== added file 'src/imports/Ubuntu/AddressBook/Base/CMakeLists.txt'
2687--- src/imports/Ubuntu/AddressBook/Base/CMakeLists.txt 1970-01-01 00:00:00 +0000
2688+++ src/imports/Ubuntu/AddressBook/Base/CMakeLists.txt 2015-05-12 21:19:18 +0000
2689@@ -0,0 +1,30 @@
2690+set(AB_CONTACT_COMMON_QMLS
2691+ ContactDetailBase.qml
2692+ ContactDetailItem.qml
2693+ ContactDetailGroupBase.qml
2694+ ContactDetailGroupWithTypeBase.qml
2695+ ContactExporter.qml
2696+ KeyboardRectangle.qml
2697+ RemoveContactsDialog.qml
2698+ qmldir
2699+)
2700+
2701+# make the files visible on qtcreator
2702+add_custom_target(contact_common_QmlFiles ALL SOURCES ${AB_CONTACT_COMMON_QMLS})
2703+
2704+if(INSTALL_COMPONENTS)
2705+ install(FILES ${AB_CONTACT_COMMON_QMLS} DESTINATION ${ADDRESS_BOOK_QMLPLUGIN_INSTALL_PREFIX}/Base)
2706+endif()
2707+
2708+#copy qml files to build dir to make it possible to run without install
2709+foreach(QML_FILE ${AB_CONTACT_COMMON_QMLS})
2710+ add_custom_command(TARGET contact_common_QmlFiles PRE_BUILD
2711+ COMMAND ${CMAKE_COMMAND} -E
2712+ copy ${CMAKE_CURRENT_SOURCE_DIR}/${QML_FILE} ${CMAKE_CURRENT_BINARY_DIR}/)
2713+endforeach()
2714+
2715+if (NOT ${CMAKE_CURRENT_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
2716+ add_dependencies(copyqmlfiles contact_common_QmlFiles)
2717+endif()
2718+
2719+
2720
2721=== added file 'src/imports/Ubuntu/AddressBook/Base/ContactDetailBase.qml'
2722--- src/imports/Ubuntu/AddressBook/Base/ContactDetailBase.qml 1970-01-01 00:00:00 +0000
2723+++ src/imports/Ubuntu/AddressBook/Base/ContactDetailBase.qml 2015-05-12 21:19:18 +0000
2724@@ -0,0 +1,112 @@
2725+/*
2726+ * Copyright (C) 2012-2015 Canonical, Ltd.
2727+ *
2728+ * This program is free software; you can redistribute it and/or modify
2729+ * it under the terms of the GNU General Public License as published by
2730+ * the Free Software Foundation; version 3.
2731+ *
2732+ * This program is distributed in the hope that it will be useful,
2733+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2734+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2735+ * GNU General Public License for more details.
2736+ *
2737+ * You should have received a copy of the GNU General Public License
2738+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2739+ */
2740+
2741+import QtQuick 2.2
2742+import QtContacts 5.0 as QtContacts
2743+import Ubuntu.Components.ListItems 1.0 as ListItem
2744+
2745+ListItem.Empty {
2746+ id: root
2747+ objectName: detail ? "base_" + detailToString(detail.type, -1) + "_" + index : ""
2748+
2749+ property QtObject contact: null
2750+ property QtObject detail: null
2751+ property variant fields: null
2752+ signal actionTrigerred(string action)
2753+
2754+ // help to test used to retrieve the correct element
2755+ property int index: -1
2756+
2757+ function detailToString(detail, field)
2758+ {
2759+ // name
2760+ var nameMap = {}
2761+ nameMap[QtContacts.Name.FirstName] = "firstName"
2762+ nameMap[QtContacts.Name.LastName] = "lastName"
2763+
2764+ // phone
2765+ var phoneMap = {}
2766+ phoneMap[QtContacts.PhoneNumber.Number] = "phoneNumber"
2767+
2768+ // email
2769+ var emailMap = {}
2770+ emailMap[QtContacts.EmailAddress.EmailAddress] = "emailAddress"
2771+
2772+ // address
2773+ var addressMap = {}
2774+ addressMap[QtContacts.Address.Street] = "streetAddress"
2775+ addressMap[QtContacts.Address.Locality] = "localityAddress"
2776+ addressMap[QtContacts.Address.Region] = "regionAddress"
2777+ addressMap[QtContacts.Address.Postcode] = "postcodeAddress"
2778+ addressMap[QtContacts.Address.Country] = "countryAddress"
2779+ addressMap[QtContacts.Address.PostOfficeBox] = "postOfficeBoxAddress"
2780+
2781+ // im
2782+ var imMap = {}
2783+ imMap[QtContacts.OnlineAccount.AccountUri] = "imUri"
2784+ imMap[QtContacts.OnlineAccount.ServiceProvider] = "imProvider"
2785+ imMap[QtContacts.OnlineAccount.Protocol] = "imProtocol"
2786+ imMap[QtContacts.OnlineAccount.Capabilities] = "imCaps"
2787+
2788+ // organization
2789+ var organizationMap = {}
2790+ organizationMap[QtContacts.Organization.Name] = 'orgName'
2791+ organizationMap[QtContacts.Organization.Role] = 'orgRole'
2792+ organizationMap[QtContacts.Organization.Title] = 'orgTitle'
2793+
2794+ // SyncTarget
2795+ var syncTargetMap = {}
2796+ syncTargetMap[QtContacts.SyncTarget.SyncTarget] = "syncTarget"
2797+
2798+ // all
2799+ var detailMap = {}
2800+ detailMap[QtContacts.ContactDetail.Name] = nameMap
2801+ detailMap[QtContacts.ContactDetail.PhoneNumber] = phoneMap
2802+ detailMap[QtContacts.ContactDetail.Email] = emailMap
2803+ detailMap[QtContacts.ContactDetail.Address] = addressMap
2804+ detailMap[QtContacts.ContactDetail.OnlineAccount] = imMap
2805+ detailMap[QtContacts.ContactDetail.Organization] = organizationMap
2806+ detailMap[QtContacts.ContactDetail.SyncTarget] = syncTargetMap
2807+
2808+ // detail name
2809+ var detailNameMap = {}
2810+ detailNameMap[QtContacts.ContactDetail.Name] = "name"
2811+ detailNameMap[QtContacts.ContactDetail.PhoneNumber] = "phoneNumber"
2812+ detailNameMap[QtContacts.ContactDetail.Email] = "email"
2813+ detailNameMap[QtContacts.ContactDetail.Address] = "address"
2814+ detailNameMap[QtContacts.ContactDetail.OnlineAccount] = "onlineAccount"
2815+ detailNameMap[QtContacts.ContactDetail.SyncTarget] = "syncTarget"
2816+
2817+ if ((detail in detailMap) && (field in detailMap[detail])) {
2818+ return detailMap[detail][field]
2819+ } else if ((detail in detailNameMap) && (field == -1)){
2820+ return detailNameMap[detail]
2821+ } else {
2822+ console.debug("Unknown : [" + detail + "] [" + field + "]")
2823+ return "unknown"
2824+ }
2825+ }
2826+
2827+ highlightWhenPressed: false
2828+ showDivider: false
2829+
2830+ Rectangle {
2831+ anchors.fill: parent
2832+ opacity: 0.1
2833+ visible: root.selected
2834+ z: 100
2835+ }
2836+}
2837
2838=== added file 'src/imports/Ubuntu/AddressBook/Base/ContactDetailGroupBase.qml'
2839--- src/imports/Ubuntu/AddressBook/Base/ContactDetailGroupBase.qml 1970-01-01 00:00:00 +0000
2840+++ src/imports/Ubuntu/AddressBook/Base/ContactDetailGroupBase.qml 2015-05-12 21:19:18 +0000
2841@@ -0,0 +1,159 @@
2842+/*
2843+ * Copyright (C) 2012-2015 Canonical, Ltd.
2844+ *
2845+ * This program is free software; you can redistribute it and/or modify
2846+ * it under the terms of the GNU General Public License as published by
2847+ * the Free Software Foundation; version 3.
2848+ *
2849+ * This program is distributed in the hope that it will be useful,
2850+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2851+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2852+ * GNU General Public License for more details.
2853+ *
2854+ * You should have received a copy of the GNU General Public License
2855+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2856+ */
2857+
2858+import QtQuick 2.2
2859+
2860+FocusScope {
2861+ id: root
2862+
2863+ property var details: []
2864+ readonly property alias detailDelegates: contents.children
2865+ readonly property int detailsCount: detailsModel.count
2866+
2867+ property variant inputFields: []
2868+ property QtObject contact: null
2869+ property int detailType: 0
2870+ property variant fields
2871+ property string title: null
2872+ property alias headerDelegate: headerItem.sourceComponent
2873+ property Component detailDelegate
2874+ property int minimumHeight: 0
2875+ property bool loaded: false
2876+ property bool showEmpty: true
2877+
2878+ signal newFieldAdded(var index)
2879+
2880+ function reloadDetails(clearFields)
2881+ {
2882+ if (clearFields) {
2883+ root.inputFields = []
2884+ }
2885+
2886+ if (contact && detailType) {
2887+ root.details = contact.details(detailType)
2888+ } else {
2889+ root.details = []
2890+ }
2891+ }
2892+
2893+ function filterDetails(details) {
2894+ var result = []
2895+ for(var d in details) {
2896+ var isEmpty = true
2897+ for(var f in root.fields) {
2898+ var fieldValue = details[d].value(root.fields[f])
2899+ if (fieldValue && (String(fieldValue) !== "")) {
2900+ isEmpty = false
2901+ break;
2902+ }
2903+ }
2904+ if (!isEmpty) {
2905+ result.push(details[d])
2906+ }
2907+ }
2908+ return result
2909+ }
2910+
2911+ onContactChanged: reloadDetails(true)
2912+ onDetailTypeChanged: reloadDetails(true)
2913+
2914+ Connections {
2915+ target: root.contact
2916+ onContactChanged: reloadDetails(false)
2917+ }
2918+
2919+ implicitHeight: detailsCount > 0 ? contents.implicitHeight : minimumHeight
2920+ visible: implicitHeight > 0
2921+
2922+ // This model is used to avoid rebuild the repeater every time that the details change
2923+ // With this model the changed info on the fields will remain after add a new field
2924+ ListModel {
2925+ id: detailsModel
2926+
2927+ property var values: root.showEmpty && root.details ? root.details : filterDetails(root.details)
2928+
2929+ onValuesChanged: {
2930+ if (!values) {
2931+ root.inputFields = []
2932+ clear()
2933+ return
2934+ }
2935+
2936+ while (count > values.length) {
2937+ remove(count - 1)
2938+ }
2939+
2940+ var modelCount = count
2941+ for(var i=0; i < values.length; i++) {
2942+ if (modelCount <= i) {
2943+ append({"detail": values[i]})
2944+ } else if (get(i) != values[i]) {
2945+ set(i, {"detail": values[i]})
2946+ }
2947+ }
2948+ }
2949+ }
2950+
2951+ Column {
2952+ id: contents
2953+
2954+ anchors {
2955+ left: parent.left
2956+ right: parent.right
2957+ }
2958+
2959+ Loader {
2960+ id: headerItem
2961+ }
2962+
2963+ Repeater {
2964+ id: detailFields
2965+
2966+ model: detailsModel
2967+
2968+ Loader {
2969+ id: detailItem
2970+
2971+ sourceComponent: root.detailDelegate
2972+ Binding {
2973+ target: detailItem.item
2974+ property: "detail"
2975+ value: model.detail
2976+ }
2977+
2978+ Binding {
2979+ target: detailItem.item
2980+ property: "index"
2981+ value: index
2982+ }
2983+
2984+ onStatusChanged: {
2985+ if (status === Loader.Ready) {
2986+ var newFields = root.inputFields
2987+ newFields.push(detailItem.item)
2988+ root.newFieldAdded(detailItem.item)
2989+ root.inputFields = newFields
2990+ if (root.loaded) {
2991+ item.forceActiveFocus()
2992+ }
2993+ }
2994+ }
2995+ }
2996+ }
2997+ }
2998+
2999+ Component.onCompleted: root.loaded = true
3000+}
3001
3002=== added file 'src/imports/Ubuntu/AddressBook/Base/ContactDetailGroupWithTypeBase.qml'
3003--- src/imports/Ubuntu/AddressBook/Base/ContactDetailGroupWithTypeBase.qml 1970-01-01 00:00:00 +0000
3004+++ src/imports/Ubuntu/AddressBook/Base/ContactDetailGroupWithTypeBase.qml 2015-05-12 21:19:18 +0000
3005@@ -0,0 +1,132 @@
3006+/*
3007+ * Copyright (C) 2012-2015 Canonical, Ltd.
3008+ *
3009+ * This program is free software; you can redistribute it and/or modify
3010+ * it under the terms of the GNU General Public License as published by
3011+ * the Free Software Foundation; version 3.
3012+ *
3013+ * This program is distributed in the hope that it will be useful,
3014+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3015+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3016+ * GNU General Public License for more details.
3017+ *
3018+ * You should have received a copy of the GNU General Public License
3019+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3020+ */
3021+
3022+import QtQuick 2.2
3023+import QtContacts 5.0 as QtContacts
3024+
3025+ContactDetailGroupBase {
3026+ id: root
3027+
3028+ property string defaultIcon : "artwork:/protocol-other.png"
3029+ property ListModel typeModel
3030+ property bool typeModelReady: false
3031+
3032+ function getType(detail) {
3033+ if (typeModel) {
3034+ return typeModel.get(typeModel.getTypeIndex(detail))
3035+ } else {
3036+ return ""
3037+ }
3038+ }
3039+
3040+ function updateDetail(detail, index) {
3041+ if (typeModel) {
3042+ return typeModel.updateDetail(detail, index)
3043+ }
3044+ return false
3045+ }
3046+
3047+ typeModel: ListModel {
3048+ signal loaded()
3049+
3050+ function getTypeIndex(detail) {
3051+ var context = -1;
3052+ for (var i = 0; i < detail.contexts.length; i++) {
3053+ context = detail.contexts[i];
3054+ break;
3055+ }
3056+ var subType = -1;
3057+ // not all details have subTypes
3058+ if (detail.subTypes) {
3059+ for (var i = 0; i < detail.subTypes.length; i++) {
3060+ subType = detail.subTypes[i];
3061+ break;
3062+ }
3063+ }
3064+ if (context === QtContacts.ContactDetail.ContextHome) {
3065+ return 0
3066+ } else if (context === QtContacts.ContactDetail.ContextWork) {
3067+ return 1
3068+ } else if (context === QtContacts.ContactDetail.ContextOther) {
3069+ return 2
3070+ } else {
3071+ return 0 // default value is "Home"
3072+ }
3073+ }
3074+
3075+ function isNotAModelValue(value) {
3076+ for(var i=0; i < count; i++) {
3077+ if (value === get(i).value) {
3078+ return false
3079+ }
3080+ }
3081+ return true
3082+ }
3083+
3084+ function compareList(listA, listB) {
3085+ if (!listA && !listB) {
3086+ return true
3087+ }
3088+
3089+ if (!listA || !listB) {
3090+ return false
3091+ }
3092+
3093+ if (listA.length != listB.length) {
3094+ return false
3095+ }
3096+ for(var i=0; i < listA.length; i++) {
3097+ if (listA[i] != listB[i]) {
3098+ return false
3099+ }
3100+ }
3101+ return true
3102+ }
3103+
3104+ function updateDetail(detail, index) {
3105+ var modelData = get(index)
3106+ if (!modelData) {
3107+ return false
3108+ }
3109+
3110+ var newContext = detail.contexts.filter(isNotAModelValue)
3111+ newContext.push(modelData.value)
3112+ if (!compareList(newContext, detail.contexts)) {
3113+ detail.contexts = newContext
3114+ return true
3115+ }
3116+ return false
3117+ }
3118+
3119+ Component.onCompleted: {
3120+ append({"value": QtContacts.ContactDetail.ContextHome,
3121+ "label": i18n.dtr("address-book-app", "Home"),
3122+ "icon": null})
3123+ append({"value": QtContacts.ContactDetail.ContextWork,
3124+ "label": i18n.dtr("address-book-app", "Work"),
3125+ "icon": null})
3126+ append({"value": QtContacts.ContactDetail.ContextOther,
3127+ "label": i18n.dtr("address-book-app", "Other"),
3128+ "icon": null})
3129+ loaded()
3130+ }
3131+ }
3132+ onTypeModelChanged: root.typeModelReady = false
3133+ Connections {
3134+ target: root.typeModel
3135+ onLoaded: root.typeModelReady = true
3136+ }
3137+}
3138
3139=== added file 'src/imports/Ubuntu/AddressBook/Base/ContactDetailItem.qml'
3140--- src/imports/Ubuntu/AddressBook/Base/ContactDetailItem.qml 1970-01-01 00:00:00 +0000
3141+++ src/imports/Ubuntu/AddressBook/Base/ContactDetailItem.qml 2015-05-12 21:19:18 +0000
3142@@ -0,0 +1,62 @@
3143+/*
3144+ * Copyright (C) 2012-2015 Canonical, Ltd.
3145+ *
3146+ * This program is free software; you can redistribute it and/or modify
3147+ * it under the terms of the GNU General Public License as published by
3148+ * the Free Software Foundation; version 3.
3149+ *
3150+ * This program is distributed in the hope that it will be useful,
3151+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3152+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3153+ * GNU General Public License for more details.
3154+ *
3155+ * You should have received a copy of the GNU General Public License
3156+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3157+ */
3158+
3159+import QtQuick 2.2
3160+
3161+import Ubuntu.Components 1.1
3162+import Ubuntu.Contacts 0.1
3163+
3164+ContactDetailBase {
3165+ id: root
3166+
3167+ readonly property alias fieldDelegates: fieldsColumn.children
3168+ property Component fieldDelegate: null
3169+ property alias spacing: fieldsColumn.spacing
3170+
3171+ implicitHeight: fieldsColumn.height
3172+ Column {
3173+ id: fieldsColumn
3174+
3175+ anchors {
3176+ left: parent.left
3177+ right: parent.right
3178+ }
3179+ spacing: units.gu(2)
3180+
3181+ height: childrenRect.height
3182+ Repeater {
3183+ id: fieldRepeater
3184+
3185+ model: root.fields
3186+ Loader {
3187+ id: field
3188+
3189+ sourceComponent: fieldDelegate
3190+ Binding {
3191+ target: item
3192+ property: "field"
3193+ value: modelData
3194+ }
3195+
3196+ Binding {
3197+ target: item
3198+ property: "detail"
3199+ value: root.detail
3200+ }
3201+ }
3202+ }
3203+ }
3204+}
3205
3206=== added file 'src/imports/Ubuntu/AddressBook/Base/ContactExporter.qml'
3207--- src/imports/Ubuntu/AddressBook/Base/ContactExporter.qml 1970-01-01 00:00:00 +0000
3208+++ src/imports/Ubuntu/AddressBook/Base/ContactExporter.qml 2015-05-12 21:19:18 +0000
3209@@ -0,0 +1,167 @@
3210+/*
3211+ * Copyright (C) 2012-2015 Canonical, Ltd.
3212+ *
3213+ * This program is free software; you can redistribute it and/or modify
3214+ * it under the terms of the GNU General Public License as published by
3215+ * the Free Software Foundation; version 3.
3216+ *
3217+ * This program is distributed in the hope that it will be useful,
3218+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3219+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3220+ * GNU General Public License for more details.
3221+ *
3222+ * You should have received a copy of the GNU General Public License
3223+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3224+ */
3225+
3226+import QtQuick 2.2
3227+import QtContacts 5.0
3228+
3229+import Ubuntu.Components 1.1
3230+import Ubuntu.Content 1.1
3231+import Ubuntu.Components.Popups 1.0
3232+
3233+Item {
3234+ id: root
3235+
3236+ property var contactModel
3237+ property bool exportToDisk: true
3238+ property var activeTransfer: null
3239+
3240+ signal contactsFetched(var contacts)
3241+ signal done(string outputFile)
3242+
3243+ function start(contacts) {
3244+ if (!contactModel) {
3245+ console.error("No contact model defined")
3246+ return
3247+ }
3248+
3249+ // skip if a query is running
3250+ if (priv.currentQueryId != -1) {
3251+ console.error("Export already running")
3252+ return
3253+ }
3254+
3255+ if (!priv.busyDialog) {
3256+ priv.busyDialog = PopupUtils.open(busyDialogComponent, root)
3257+ }
3258+
3259+ var ids = []
3260+ for (var i=0; i < contacts.length; i++) {
3261+ ids.push(contacts[i].contactId)
3262+ }
3263+ if (ids.length == 0) {
3264+ console.debug("The contact list is empty")
3265+ done("")
3266+ } else {
3267+ priv.currentQueryId = contactModel.fetchContacts(ids)
3268+ }
3269+ }
3270+
3271+ function dismissBusyDialog()
3272+ {
3273+ if (priv.busyDialog) {
3274+ PopupUtils.close(priv.busyDialog)
3275+ priv.busyDialog = null
3276+ }
3277+ }
3278+
3279+ Item {
3280+ id: priv
3281+
3282+ property var busyDialog: null
3283+ property int currentQueryId: -1
3284+ readonly property var detailsBlackList: [ ContactDetail.Favorite, ContactDetail.Tag ]
3285+
3286+ function filterContactDetails(contact)
3287+ {
3288+ var newContact = Qt.createQmlObject("import QtContacts 5.0; Contact { }", root)
3289+ var allDetails = contact.contactDetails
3290+ for(var i=0; i < allDetails.length; i++) {
3291+ var det = allDetails[i]
3292+ if (detailsBlackList.indexOf(det.type) == -1) {
3293+ newContact.addDetail(det)
3294+ }
3295+ }
3296+ return newContact
3297+ }
3298+
3299+ function generateOutputFileName(contacts)
3300+ {
3301+ if (contacts.length === 1) {
3302+ return "file:///tmp/%1.vcf".arg(contacts[0].displayLabel.label.replace(/\s/g, ''))
3303+ } else {
3304+ return "file:///tmp/ubuntu_contacts.vcf";
3305+ }
3306+ }
3307+
3308+ Connections {
3309+ target: root.contactModel
3310+
3311+ onExportCompleted: {
3312+ // send contacts back to source app (pick mode)
3313+ if (error === ContactModel.ExportNoError) {
3314+ var obj = Qt.createQmlObject("import Ubuntu.Content 1.1; ContentItem { url: '" + url + "' }", root)
3315+ if (root.activeTransfer) {
3316+ root.activeTransfer.items = [obj]
3317+ root.activeTransfer.state = ContentTransfer.Charged
3318+ } else {
3319+ console.error("No active transfer")
3320+ }
3321+ } else {
3322+ root.activeTransfer = ContentHub.ContentTransfer.Aborted
3323+ console.error("Fail to export contacts:" + error)
3324+ }
3325+ root.dismissBusyDialog()
3326+ root.done(url)
3327+ }
3328+
3329+ onContactsFetched: {
3330+ // currentQueryId == -2 is used during a fetch using "memory" manager
3331+ if ((priv.currentQueryId == -2) || (requestId == priv.currentQueryId)) {
3332+ if (root.exportToDisk) {
3333+ var contacts = []
3334+ // remove unnecessary info from contacts
3335+ for(var i=0; i < fetchedContacts.length; i++) {
3336+ contacts.push(priv.filterContactDetails(fetchedContacts[i]))
3337+ }
3338+ // update outputFile with a friendly name
3339+ var outputFile = priv.generateOutputFileName(contacts)
3340+ root.contactModel.exportContacts(outputFile,
3341+ [],
3342+ contacts)
3343+ }
3344+ root.contactsFetched(fetchedContacts)
3345+ priv.currentQueryId = -1
3346+ }
3347+ }
3348+ }
3349+
3350+ Connections {
3351+ target: root.activeTransfer
3352+
3353+ onStateChanged: {
3354+ if (root.activeTransfer.state === ContentTransfer.Aborted) {
3355+ root.activeTransfer = null
3356+ root.done("")
3357+ }
3358+ }
3359+ }
3360+ }
3361+
3362+ Component {
3363+ id: busyDialogComponent
3364+
3365+ Dialog {
3366+ title: i18n.dtr("address-book-app", "Exporting contacts...")
3367+
3368+ ActivityIndicator {
3369+ id: activity
3370+
3371+ anchors.horizontalCenter: parent.horizontalCenter
3372+ running: true
3373+ }
3374+ }
3375+ }
3376+}
3377
3378=== added file 'src/imports/Ubuntu/AddressBook/Base/KeyboardRectangle.qml'
3379--- src/imports/Ubuntu/AddressBook/Base/KeyboardRectangle.qml 1970-01-01 00:00:00 +0000
3380+++ src/imports/Ubuntu/AddressBook/Base/KeyboardRectangle.qml 2015-05-12 21:19:18 +0000
3381@@ -0,0 +1,70 @@
3382+/*
3383+ * Copyright (C) 2012-2015 Canonical, Ltd.
3384+ *
3385+ * This program is free software; you can redistribute it and/or modify
3386+ * it under the terms of the GNU General Public License as published by
3387+ * the Free Software Foundation; version 3.
3388+ *
3389+ * This program is distributed in the hope that it will be useful,
3390+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3391+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3392+ * GNU General Public License for more details.
3393+ *
3394+ * You should have received a copy of the GNU General Public License
3395+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3396+ */
3397+
3398+import QtQuick 2.2
3399+
3400+Item {
3401+ id: keyboardRect
3402+ anchors.left: parent.left
3403+ anchors.right: parent.right
3404+ anchors.bottom: parent.bottom
3405+ height: Qt.inputMethod.visible ? Qt.inputMethod.keyboardRectangle.height : 0
3406+
3407+ states: [
3408+ State {
3409+ name: "hidden"
3410+ when: keyboardRect.height == 0
3411+ },
3412+ State {
3413+ name: "shown"
3414+ when: keyboardRect.height == Qt.inputMethod.keyboardRectangle.height
3415+ }
3416+ ]
3417+
3418+ function recursiveFindFocusedItem(parent) {
3419+ if (parent.activeFocus) {
3420+ return parent;
3421+ }
3422+
3423+ for (var i in parent.children) {
3424+ var child = parent.children[i];
3425+ if (child.activeFocus) {
3426+ return child;
3427+ }
3428+
3429+ var item = recursiveFindFocusedItem(child);
3430+
3431+ if (item != null) {
3432+ return item;
3433+ }
3434+ }
3435+
3436+ return null;
3437+ }
3438+
3439+ Connections {
3440+ target: Qt.inputMethod
3441+
3442+ onVisibleChanged: {
3443+ if (!Qt.inputMethod.visible) {
3444+ var focusedItem = recursiveFindFocusedItem(keyboardRect.parent);
3445+ if (focusedItem != null) {
3446+ focusedItem.focus = false;
3447+ }
3448+ }
3449+ }
3450+ }
3451+}
3452
3453=== added file 'src/imports/Ubuntu/AddressBook/Base/RemoveContactsDialog.qml'
3454--- src/imports/Ubuntu/AddressBook/Base/RemoveContactsDialog.qml 1970-01-01 00:00:00 +0000
3455+++ src/imports/Ubuntu/AddressBook/Base/RemoveContactsDialog.qml 2015-05-12 21:19:18 +0000
3456@@ -0,0 +1,78 @@
3457+/*
3458+ * Copyright (C) 2014 Canonical, Ltd.
3459+ *
3460+ * This program is free software; you can redistribute it and/or modify
3461+ * it under the terms of the GNU General Public License as published by
3462+ * the Free Software Foundation; version 3.
3463+ *
3464+ * This program is distributed in the hope that it will be useful,
3465+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3466+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3467+ * GNU General Public License for more details.
3468+ *
3469+ * You should have received a copy of the GNU General Public License
3470+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3471+ */
3472+
3473+import QtQuick 2.2
3474+import Ubuntu.Components 1.1
3475+import Ubuntu.Components.Popups 1.0
3476+
3477+Dialog {
3478+ objectName: "removeContactsDialog"
3479+
3480+ property var contacts: []
3481+
3482+ signal canceled()
3483+ signal accepted()
3484+
3485+ function removeContacts(model)
3486+ {
3487+ var ids = []
3488+ for(var i=0, iMax=contacts.length; i < iMax; i++) {
3489+ ids.push(contacts[i].contactId)
3490+ }
3491+ model.removeContacts(ids)
3492+ }
3493+
3494+ title: {
3495+ if (contacts.length == 0) {
3496+ return i18n.dtr("address-book-app", "No contact selected.")
3497+ } else if (contacts.length == 1) {
3498+ return contacts[0].displayLabel.label
3499+ } else {
3500+ return i18n.dtr("address-book-app", "Multiple contacts")
3501+ }
3502+ }
3503+ text: {
3504+ if (contacts.length == 1) {
3505+ return i18n.dtr("address-book-app", "Are you sure that you want to remove this contact?")
3506+ } else {
3507+ return i18n.dtr("address-book-app", "Are you sure that you want to remove all selected contacts?")
3508+ }
3509+ }
3510+
3511+ Button {
3512+ objectName: "removeContactsDialog.Yes"
3513+ anchors {
3514+ left: parent.left
3515+ right: parent.right
3516+ margins: units.gu(1)
3517+ }
3518+ text: i18n.dtr("address-book-app", "Yes")
3519+ color: UbuntuColors.green
3520+ onClicked: accepted()
3521+ }
3522+
3523+ Button {
3524+ objectName: "removeContactsDialog.No"
3525+ anchors {
3526+ left: parent.left
3527+ right: parent.right
3528+ margins: units.gu(1)
3529+ }
3530+ text: i18n.dtr("address-book-app", "No")
3531+ color: UbuntuColors.red
3532+ onClicked: canceled()
3533+ }
3534+}
3535
3536=== added file 'src/imports/Ubuntu/AddressBook/Base/qmldir'
3537--- src/imports/Ubuntu/AddressBook/Base/qmldir 1970-01-01 00:00:00 +0000
3538+++ src/imports/Ubuntu/AddressBook/Base/qmldir 2015-05-12 21:19:18 +0000
3539@@ -0,0 +1,9 @@
3540+module Ubuntu.AddressBook.Base
3541+
3542+ContactDetailBase 0.1 ContactDetailBase.qml
3543+ContactDetailItem 0.1 ContactDetailItem.qml
3544+ContactDetailGroupBase 0.1 ContactDetailGroupBase.qml
3545+ContactDetailGroupWithTypeBase 0.1 ContactDetailGroupWithTypeBase.qml
3546+ContactExporter 0.1 ContactExporter.qml
3547+RemoveContactsDialog 0.1 RemoveContactsDialog.qml
3548+KeyboardRectangle 0.1 KeyboardRectangle.qml
3549
3550=== added file 'src/imports/Ubuntu/AddressBook/CMakeLists.txt'
3551--- src/imports/Ubuntu/AddressBook/CMakeLists.txt 1970-01-01 00:00:00 +0000
3552+++ src/imports/Ubuntu/AddressBook/CMakeLists.txt 2015-05-12 21:19:18 +0000
3553@@ -0,0 +1,4 @@
3554+add_subdirectory(Base)
3555+add_subdirectory(ContactEditor)
3556+add_subdirectory(ContactView)
3557+add_subdirectory(ContactShare)
3558
3559=== renamed directory 'src/imports/ContactEdit' => 'src/imports/Ubuntu/AddressBook/ContactEditor'
3560=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/CMakeLists.txt'
3561--- src/imports/ContactEdit/CMakeLists.txt 2014-08-20 18:27:37 +0000
3562+++ src/imports/Ubuntu/AddressBook/ContactEditor/CMakeLists.txt 2015-05-12 21:19:18 +0000
3563@@ -1,4 +1,4 @@
3564-set(CONTACT_EDIT_QMLS
3565+set(AB_CONTACT_EDITOR_QMLS
3566 AvatarImport.qml
3567 ComboButtonAddField.qml
3568 ContactDetailAddressesEditor.qml
3569@@ -11,14 +11,27 @@
3570 ContactDetailPhoneNumbersEditor.qml
3571 ContactDetailSyncTargetEditor.qml
3572 ContactDetailWithTypeEditor.qml
3573- ContactEditor.qml
3574+ ContactEditorPage.qml
3575 TextInputDetail.qml
3576 ValueSelector.qml
3577-)
3578-
3579-install(FILES ${CONTACT_EDIT_QMLS}
3580- DESTINATION ${ADDRESS_BOOK_APP_DIR}/imports/ContactEdit
3581+ qmldir
3582 )
3583
3584 # make the files visible on qtcreator
3585-add_custom_target(contact_edit_QmlFiles ALL SOURCES ${CONTACT_EDIT_QMLS})
3586+add_custom_target(contact_editor_QmlFiles ALL SOURCES ${AB_CONTACT_EDITOR_QMLS})
3587+
3588+if(INSTALL_COMPONENTS)
3589+ install(FILES ${AB_CONTACT_EDITOR_QMLS} DESTINATION ${ADDRESS_BOOK_QMLPLUGIN_INSTALL_PREFIX}/ContactEditor)
3590+endif()
3591+
3592+#copy qml files to build dir to make it possible to run without install
3593+foreach(QML_FILE ${AB_CONTACT_EDITOR_QMLS})
3594+ add_custom_command(TARGET contact_editor_QmlFiles PRE_BUILD
3595+ COMMAND ${CMAKE_COMMAND} -E
3596+ copy ${CMAKE_CURRENT_SOURCE_DIR}/${QML_FILE} ${CMAKE_CURRENT_BINARY_DIR}/)
3597+endforeach()
3598+
3599+if (NOT ${CMAKE_CURRENT_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
3600+ add_dependencies(copyqmlfiles contact_editor_QmlFiles)
3601+endif()
3602+
3603
3604=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ComboButtonAddField.qml'
3605--- src/imports/ContactEdit/ComboButtonAddField.qml 2014-09-03 19:21:20 +0000
3606+++ src/imports/Ubuntu/AddressBook/ContactEditor/ComboButtonAddField.qml 2015-05-12 21:19:18 +0000
3607@@ -44,15 +44,15 @@
3608 switch (value)
3609 {
3610 case ContactDetail.PhoneNumber:
3611- return i18n.tr("Phone")
3612+ return i18n.dtr("address-book-app", "Phone")
3613 case ContactDetail.Email:
3614- return i18n.tr("Email")
3615+ return i18n.dtr("address-book-app", "Email")
3616 case ContactDetail.Address:
3617- return i18n.tr("Address")
3618+ return i18n.dtr("address-book-app", "Address")
3619 case ContactDetail.OnlineAccount:
3620- return i18n.tr("Social")
3621+ return i18n.dtr("address-book-app", "Social")
3622 case ContactDetail.Organization:
3623- return i18n.tr("Professional Details")
3624+ return i18n.dtr("address-book-app", "Professional Details")
3625 default:
3626 console.error("Invalid contact detail enum value:" + value)
3627 return ""
3628
3629=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAddressesEditor.qml'
3630--- src/imports/ContactEdit/ContactDetailAddressesEditor.qml 2014-08-13 20:52:57 +0000
3631+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAddressesEditor.qml 2015-05-12 21:19:18 +0000
3632@@ -1,5 +1,5 @@
3633 /*
3634- * Copyright (C) 2012-2013 Canonical, Ltd.
3635+ * Copyright (C) 2012-2015 Canonical, Ltd.
3636 *
3637 * This program is free software; you can redistribute it and/or modify
3638 * it under the terms of the GNU General Public License as published by
3639@@ -20,7 +20,7 @@
3640 import Ubuntu.Contacts 0.1
3641
3642 ContactDetailGroupWithTypeEditor {
3643- title: i18n.tr("Address")
3644+ title: i18n.dtr("address-book-app", "Address")
3645 detailQmlTypeName: "Address"
3646 detailType: ContactDetail.Address
3647 fields: [ Address.Street,
3648@@ -28,10 +28,10 @@
3649 Address.Region,
3650 Address.Postcode,
3651 Address.Country ]
3652- placeholderTexts: [ i18n.tr("Street"),
3653- i18n.tr("Locality"),
3654- i18n.tr("Region"),
3655- i18n.tr("Post code"),
3656- i18n.tr("Country") ]
3657+ placeholderTexts: [ i18n.dtr("address-book-app", "Street"),
3658+ i18n.dtr("address-book-app", "Locality"),
3659+ i18n.dtr("address-book-app", "Region"),
3660+ i18n.dtr("address-book-app", "Post code"),
3661+ i18n.dtr("address-book-app", "Country") ]
3662 inputMethodHints: Qt.ImhNoPredictiveText
3663 }
3664
3665=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAvatarEditor.qml'
3666--- src/imports/ContactEdit/ContactDetailAvatarEditor.qml 2015-02-25 15:44:06 +0000
3667+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAvatarEditor.qml 2015-05-12 21:19:18 +0000
3668@@ -18,7 +18,9 @@
3669 import QtContacts 5.0
3670
3671 import Ubuntu.Components 1.1
3672+
3673 import Ubuntu.Contacts 0.1
3674+import Ubuntu.AddressBook.Base 0.1
3675
3676 ContactDetailBase {
3677 id: root
3678@@ -83,6 +85,10 @@
3679 height: units.gu(3)
3680 width: units.gu(3)
3681 visible: source == defaultAvatar
3682+ sourceSize {
3683+ width: units.gu(3)
3684+ height: units.gu(3)
3685+ }
3686
3687 // When updating the avatar using the content picker the temporary file returned
3688 // can contain the same name as the previous one and if the cache is enabled this
3689@@ -108,7 +114,7 @@
3690 // be updated
3691 avatarImage.source = ""
3692 // Update with the new value
3693- avatarImage.source = application.copyImage(root.contact, avatarUrl);
3694+ avatarImage.source = Contacts.copyImage(root.contact, avatarUrl);
3695 }
3696 }
3697
3698
3699=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailEmailsEditor.qml'
3700--- src/imports/ContactEdit/ContactDetailEmailsEditor.qml 2014-08-13 20:52:57 +0000
3701+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailEmailsEditor.qml 2015-05-12 21:19:18 +0000
3702@@ -1,5 +1,5 @@
3703 /*
3704- * Copyright (C) 2012-2013 Canonical, Ltd.
3705+ * Copyright (C) 2012-2015 Canonical, Ltd.
3706 *
3707 * This program is free software; you can redistribute it and/or modify
3708 * it under the terms of the GNU General Public License as published by
3709@@ -21,10 +21,10 @@
3710
3711
3712 ContactDetailGroupWithTypeEditor {
3713- title: i18n.tr("Email")
3714+ title: i18n.dtr("address-book-app", "Email")
3715 detailQmlTypeName: "EmailAddress"
3716 detailType: ContactDetail.Email
3717 fields: [ 0 ]
3718- placeholderTexts: [ i18n.tr("Enter an email address") ]
3719+ placeholderTexts: [ i18n.dtr("address-book-app", "Enter an email address") ]
3720 inputMethodHints: Qt.ImhEmailCharactersOnly
3721 }
3722
3723=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailGroupWithTypeEditor.qml'
3724--- src/imports/ContactEdit/ContactDetailGroupWithTypeEditor.qml 2014-08-13 20:52:57 +0000
3725+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailGroupWithTypeEditor.qml 2015-05-12 21:19:18 +0000
3726@@ -1,5 +1,5 @@
3727 /*
3728- * Copyright (C) 2012-2013 Canonical, Ltd.
3729+ * Copyright (C) 2012-2015 Canonical, Ltd.
3730 *
3731 * This program is free software; you can redistribute it and/or modify
3732 * it under the terms of the GNU General Public License as published by
3733@@ -21,6 +21,8 @@
3734 import Ubuntu.Components.ListItems 1.0
3735 import Ubuntu.Contacts 0.1
3736
3737+import Ubuntu.AddressBook.Base 0.1
3738+
3739 ContactDetailGroupWithTypeBase {
3740 id: root
3741
3742
3743=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailNameEditor.qml'
3744--- src/imports/ContactEdit/ContactDetailNameEditor.qml 2014-08-13 20:52:57 +0000
3745+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailNameEditor.qml 2015-05-12 21:19:18 +0000
3746@@ -1,5 +1,5 @@
3747 /*
3748- * Copyright (C) 2012-2013 Canonical, Ltd.
3749+ * Copyright (C) 2012-2015 Canonical, Ltd.
3750 *
3751 * This program is free software; you can redistribute it and/or modify
3752 * it under the terms of the GNU General Public License as published by
3753@@ -19,7 +19,7 @@
3754
3755 import Ubuntu.Components 1.1
3756
3757-import "../Common"
3758+import Ubuntu.AddressBook.Base 0.1
3759
3760 ContactDetailItem {
3761 id: root
3762@@ -81,7 +81,8 @@
3763 x: units.gu(2)
3764 detail: root.detail
3765 height: units.gu(4)
3766- placeholderText: field == Name.FirstName ? i18n.tr("First name") : i18n.tr("Last name")
3767+ placeholderText: field == Name.FirstName ? i18n.dtr("address-book-app", "First name") :
3768+ i18n.dtr("address-book-app", "Last name")
3769 inputMethodHints: Qt.ImhNoPredictiveText
3770 onTextChanged: checkIsEmpty()
3771 onFieldChanged: checkIsEmpty()
3772
3773=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailOnlineAccountsEditor.qml'
3774--- src/imports/ContactEdit/ContactDetailOnlineAccountsEditor.qml 2014-08-13 20:52:57 +0000
3775+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailOnlineAccountsEditor.qml 2015-05-12 21:19:18 +0000
3776@@ -1,5 +1,5 @@
3777 /*
3778- * Copyright (C) 2012-2013 Canonical, Ltd.
3779+ * Copyright (C) 2012-2015 Canonical, Ltd.
3780 *
3781 * This program is free software; you can redistribute it and/or modify
3782 * it under the terms of the GNU General Public License as published by
3783@@ -20,11 +20,11 @@
3784 import Ubuntu.Contacts 0.1
3785
3786 ContactDetailGroupWithTypeEditor {
3787- title: i18n.tr("IM")
3788+ title: i18n.dtr("address-book-app", "IM")
3789 detailType: ContactDetail.OnlineAccount
3790 detailQmlTypeName: "OnlineAccount"
3791 fields: [ OnlineAccount.AccountUri ]
3792- placeholderTexts: [ i18n.tr("Enter a social alias") ]
3793+ placeholderTexts: [ i18n.dtr("address-book-app", "Enter a social alias") ]
3794 typeModel: ContactDetailOnlineAccountTypeModel { }
3795 inputMethodHints: Qt.ImhEmailCharactersOnly
3796 }
3797
3798=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailOrganizationsEditor.qml'
3799--- src/imports/ContactEdit/ContactDetailOrganizationsEditor.qml 2014-08-14 20:20:42 +0000
3800+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailOrganizationsEditor.qml 2015-05-12 21:19:18 +0000
3801@@ -1,5 +1,5 @@
3802 /*
3803- * Copyright (C) 2012-2013 Canonical, Ltd.
3804+ * Copyright (C) 2012-2015 Canonical, Ltd.
3805 *
3806 * This program is free software; you can redistribute it and/or modify
3807 * it under the terms of the GNU General Public License as published by
3808@@ -18,16 +18,16 @@
3809 import QtContacts 5.0
3810
3811 ContactDetailGroupWithTypeEditor {
3812- title: i18n.tr("Professional Details")
3813+ title: i18n.dtr("address-book-app", "Professional Details")
3814 typeModel: null
3815 detailQmlTypeName: "Organization"
3816 detailType: ContactDetail.Organization
3817 fields: [ Organization.Name,
3818 Organization.Role,
3819 Organization.Title ]
3820- placeholderTexts: [ i18n.tr("Organization"),
3821- i18n.tr("Role"),
3822- i18n.tr("Title")
3823+ placeholderTexts: [ i18n.dtr("address-book-app", "Organization"),
3824+ i18n.dtr("address-book-app", "Role"),
3825+ i18n.dtr("address-book-app", "Title")
3826 ]
3827 inputMethodHints: Qt.ImhNoPredictiveText
3828 }
3829
3830=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailPhoneNumbersEditor.qml'
3831--- src/imports/ContactEdit/ContactDetailPhoneNumbersEditor.qml 2014-08-13 20:52:57 +0000
3832+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailPhoneNumbersEditor.qml 2015-05-12 21:19:18 +0000
3833@@ -1,5 +1,5 @@
3834 /*
3835- * Copyright (C) 2012-2013 Canonical, Ltd.
3836+ * Copyright (C) 2012-2015 Canonical, Ltd.
3837 *
3838 * This program is free software; you can redistribute it and/or modify
3839 * it under the terms of the GNU General Public License as published by
3840@@ -20,11 +20,11 @@
3841 import Ubuntu.Contacts 0.1
3842
3843 ContactDetailGroupWithTypeEditor {
3844- title: i18n.tr("Phone")
3845+ title: i18n.dtr("address-book-app", "Phone")
3846 detailType: ContactDetail.PhoneNumber
3847 detailQmlTypeName: "PhoneNumber"
3848 fields: [ PhoneNumber.Number ]
3849- placeholderTexts: [ i18n.tr("Enter a number") ]
3850+ placeholderTexts: [ i18n.dtr("address-book-app", "Enter a number") ]
3851 typeModel: ContactDetailPhoneNumberTypeModel { }
3852 inputMethodHints: Qt.ImhDialableCharactersOnly
3853 usePhoneFormat: true
3854
3855=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailSyncTargetEditor.qml'
3856--- src/imports/ContactEdit/ContactDetailSyncTargetEditor.qml 2014-09-03 19:21:20 +0000
3857+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailSyncTargetEditor.qml 2015-05-12 21:19:18 +0000
3858@@ -1,5 +1,5 @@
3859 /*
3860- * Copyright (C) 2012-2013 Canonical, Ltd.
3861+ * Copyright (C) 2012-2015 Canonical, Ltd.
3862 *
3863 * This program is free software; you can redistribute it and/or modify
3864 * it under the terms of the GNU General Public License as published by
3865@@ -19,7 +19,9 @@
3866
3867 import Ubuntu.Components 1.1
3868 import Ubuntu.Components.ListItems 1.0
3869+
3870 import Ubuntu.Contacts 0.1
3871+import Ubuntu.AddressBook.Base 0.1
3872
3873 ContactDetailBase {
3874 id: root
3875@@ -73,7 +75,7 @@
3876 Label {
3877 id: label
3878
3879- text: i18n.tr("Addressbook")
3880+ text: i18n.dtr("address-book-app", "Addressbook")
3881 anchors {
3882 left: parent.left
3883 top: parent.top
3884
3885=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailWithTypeEditor.qml'
3886--- src/imports/ContactEdit/ContactDetailWithTypeEditor.qml 2014-08-13 20:52:57 +0000
3887+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailWithTypeEditor.qml 2015-05-12 21:19:18 +0000
3888@@ -1,5 +1,5 @@
3889 /*
3890- * Copyright (C) 2012-2013 Canonical, Ltd.
3891+ * Copyright (C) 2012-2015 Canonical, Ltd.
3892 *
3893 * This program is free software; you can redistribute it and/or modify
3894 * it under the terms of the GNU General Public License as published by
3895@@ -18,7 +18,9 @@
3896 import QtContacts 5.0
3897
3898 import Ubuntu.Components 1.1
3899+
3900 import Ubuntu.Contacts 0.1
3901+import Ubuntu.AddressBook.Base 0.1
3902
3903 ContactDetailBase {
3904 id: root
3905
3906=== added file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactEditorPage.qml'
3907--- src/imports/Ubuntu/AddressBook/ContactEditor/ContactEditorPage.qml 1970-01-01 00:00:00 +0000
3908+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactEditorPage.qml 2015-05-12 21:19:18 +0000
3909@@ -0,0 +1,444 @@
3910+/*
3911+ * Copyright (C) 2012-2015 Canonical, Ltd.
3912+ *
3913+ * This program is free software; you can redistribute it and/or modify
3914+ * it under the terms of the GNU General Public License as published by
3915+ * the Free Software Foundation; version 3.
3916+ *
3917+ * This program is distributed in the hope that it will be useful,
3918+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3919+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3920+ * GNU General Public License for more details.
3921+ *
3922+ * You should have received a copy of the GNU General Public License
3923+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3924+ */
3925+
3926+import QtQuick 2.2
3927+import QtContacts 5.0
3928+
3929+import Ubuntu.Components 1.1
3930+import Ubuntu.Components.ListItems 1.0
3931+import Ubuntu.Components.Popups 1.0
3932+
3933+import Ubuntu.AddressBook.Base 0.1
3934+
3935+Page {
3936+ id: contactEditor
3937+
3938+ property QtObject contact: null
3939+ property QtObject model: null
3940+ property QtObject activeItem: null
3941+
3942+
3943+ property string initialFocusSection: ""
3944+ property var newDetails: []
3945+
3946+ readonly property bool isNewContact: contact && (contact.contactId === "qtcontacts:::")
3947+ readonly property bool isContactValid: !avatarEditor.busy && (!nameEditor.isEmpty() || !phonesEditor.isEmpty())
3948+
3949+ signal contactSaved(var contact);
3950+
3951+ // priv
3952+ property bool _edgeReady: false
3953+
3954+ function cancel() {
3955+ for (var i = 0; i < contactEditor.newDetails.length; ++i) {
3956+ contactEditor.contact.removeDetail(contactEditor.newDetails[i])
3957+ }
3958+ contactEditor.newDetails = []
3959+
3960+ for(var i = 0; i < contents.children.length; ++i) {
3961+ var field = contents.children[i]
3962+ if (field.cancel) {
3963+ field.cancel()
3964+ }
3965+ }
3966+ pageStack.pop()
3967+ }
3968+
3969+ function save() {
3970+ var changed = false
3971+ for(var i = 0; i < contents.children.length; ++i) {
3972+ var field = contents.children[i]
3973+ if (field.save) {
3974+ if (field.save()) {
3975+ changed = true
3976+ }
3977+ }
3978+ }
3979+
3980+ // new contact and there is only two details (name, avatar)
3981+ // name and avatar, are not removable details, because of that the contact will have at least 2 details
3982+ if (isNewContact &&
3983+ (contact.contactDetails.length === 2)) {
3984+
3985+ // if name is empty this means that the contact is empty
3986+ var nameDetail = contact.detail(ContactDetail.Name)
3987+ if (nameDetail &&
3988+ (nameDetail.firstName && nameDetail.firstName != "") ||
3989+ (nameDetail.lastName && nameDetail.lastName != "")) {
3990+ // save contact
3991+ } else {
3992+ changed = false
3993+ }
3994+ }
3995+
3996+ if (changed) {
3997+ // backend error will be handled by the root page (contact list)
3998+ var newContact = (contact.model == null)
3999+ contactEditor.model.saveContact(contact)
4000+ if (newContact) {
4001+ contactEditor.contactSaved(contact)
4002+ }
4003+ }
4004+ pageStack.pop()
4005+ }
4006+
4007+ function makeMeVisible(item) {
4008+ if (!_edgeReady || !item) {
4009+ return
4010+ }
4011+
4012+ activeItem = item
4013+ var position = scrollArea.contentItem.mapFromItem(item, 0, activeItem.y);
4014+
4015+ // check if the item is already visible
4016+ var bottomY = scrollArea.contentY + scrollArea.height
4017+ var itemBottom = position.y + (item.height * 3) // extra margin
4018+ if (position.y >= scrollArea.contentY && itemBottom <= bottomY) {
4019+ return;
4020+ }
4021+
4022+ // if it is not, try to scroll and make it visible
4023+ var targetY = itemBottom - scrollArea.height
4024+ if (targetY >= 0 && position.y) {
4025+ scrollArea.contentY = targetY;
4026+ } else if (position.y < scrollArea.contentY) {
4027+ // if it is hidden at the top, also show it
4028+ scrollArea.contentY = position.y;
4029+ }
4030+ scrollArea.returnToBounds()
4031+ }
4032+
4033+ function ready()
4034+ {
4035+ console.debug("READYYYYY: " + contactEditor.initialFocusSection)
4036+ enabled = true
4037+ _edgeReady = true
4038+
4039+ switch (contactEditor.initialFocusSection)
4040+ {
4041+ case "phones":
4042+ contactEditor.focusToLastPhoneField()
4043+ break;
4044+ case "name":
4045+ nameEditor.fieldDelegates[0].forceActiveFocus()
4046+ break;
4047+ }
4048+ contactEditor.initialFocusSection = ""
4049+ }
4050+
4051+ function focusToLastPhoneField()
4052+ {
4053+ var lastPhoneField = phonesEditor.detailDelegates[phonesEditor.detailDelegates.length - 2].item
4054+ console.debug("Focus last phone field:" + lastPhoneField)
4055+ console.debug("PHONES SIZE>" + phonesEditor.detailDelegates.length)
4056+ lastPhoneField.forceActiveFocus()
4057+ }
4058+
4059+ title: isNewContact ? i18n.dtr("address-book-app", "New contact") : i18n.dtr("address-book-app", "Edit")
4060+
4061+ Timer {
4062+ id: focusTimer
4063+
4064+ interval: 1000
4065+ running: false
4066+ repeat: false
4067+ onTriggered: contactEditor.ready()
4068+ }
4069+
4070+ flickable: null
4071+ Flickable {
4072+ id: scrollArea
4073+ objectName: "scrollArea"
4074+
4075+ // this is necessary to avoid the page to appear bellow the header
4076+ clip: true
4077+ flickableDirection: Flickable.VerticalFlick
4078+ anchors{
4079+ left: parent.left
4080+ top: parent.top
4081+ right: parent.right
4082+ bottom: keyboardRectangle.top
4083+ }
4084+ contentHeight: contents.height + units.gu(2)
4085+ contentWidth: parent.width
4086+
4087+ //after add a new field we need to wait for the contentHeight to change to scroll to the correct position
4088+ onContentHeightChanged: contactEditor.makeMeVisible(contactEditor.activeItem)
4089+
4090+ Column {
4091+ id: contents
4092+
4093+ anchors {
4094+ top: parent.top
4095+ topMargin: units.gu(2)
4096+ left: parent.left
4097+ right: parent.right
4098+ }
4099+ height: childrenRect.height
4100+
4101+ Row {
4102+ function save()
4103+ {
4104+ var avatarSave = avatarEditor.save()
4105+ var nameSave = nameEditor.save();
4106+
4107+ return (nameSave || avatarSave);
4108+ }
4109+
4110+ function isEmpty()
4111+ {
4112+ return (avatarEditor.isEmpty() && nameEditor.isEmpty())
4113+ }
4114+
4115+ anchors {
4116+ left: parent.left
4117+ leftMargin: units.gu(2)
4118+ right: parent.right
4119+ }
4120+ height: Math.max(avatarEditor.height, nameEditor.height) - units.gu(4)
4121+
4122+ ContactDetailAvatarEditor {
4123+ id: avatarEditor
4124+
4125+ contact: contactEditor.contact
4126+ height: implicitHeight
4127+ width: implicitWidth
4128+ }
4129+
4130+ ContactDetailNameEditor {
4131+ id: nameEditor
4132+
4133+ width: parent.width - avatarEditor.width
4134+ height: nameEditor.implicitHeight + units.gu(3)
4135+ contact: contactEditor.contact
4136+ }
4137+ }
4138+
4139+ ContactDetailPhoneNumbersEditor {
4140+ id: phonesEditor
4141+ objectName: "phones"
4142+
4143+ contact: contactEditor.contact
4144+ anchors {
4145+ left: parent.left
4146+ right: parent.right
4147+ }
4148+ height: implicitHeight
4149+ }
4150+
4151+ ContactDetailEmailsEditor {
4152+ id: emailsEditor
4153+ objectName: "emails"
4154+
4155+ contact: contactEditor.contact
4156+ anchors {
4157+ left: parent.left
4158+ right: parent.right
4159+ }
4160+ height: implicitHeight
4161+ }
4162+
4163+ ContactDetailOnlineAccountsEditor {
4164+ id: accountsEditor
4165+ objectName: "ims"
4166+
4167+ contact: contactEditor.contact
4168+ anchors {
4169+ left: parent.left
4170+ right: parent.right
4171+ }
4172+ height: implicitHeight
4173+ }
4174+
4175+ ContactDetailAddressesEditor {
4176+ id: addressesEditor
4177+ objectName: "addresses"
4178+
4179+ contact: contactEditor.contact
4180+ anchors {
4181+ left: parent.left
4182+ right: parent.right
4183+ }
4184+ height: implicitHeight
4185+ }
4186+
4187+ ContactDetailOrganizationsEditor {
4188+ id: organizationsEditor
4189+ objectName: "professionalDetails"
4190+
4191+ contact: contactEditor.contact
4192+ anchors {
4193+ left: parent.left
4194+ right: parent.right
4195+ }
4196+ height: implicitHeight
4197+ }
4198+
4199+ ContactDetailSyncTargetEditor {
4200+ id: syncTargetEditor
4201+
4202+ active: contactEditor.active
4203+ contact: contactEditor.contact
4204+ anchors {
4205+ left: parent.left
4206+ right: parent.right
4207+ }
4208+ height: implicitHeight
4209+ }
4210+
4211+ ThinDivider {}
4212+
4213+ Item {
4214+ anchors {
4215+ left: parent.left
4216+ right: parent.right
4217+ }
4218+ height: units.gu(2)
4219+ }
4220+
4221+ ComboButtonAddField {
4222+ id: addNewFieldButton
4223+ objectName: "addNewFieldButton"
4224+
4225+ contact: contactEditor.contact
4226+ text: i18n.dtr("address-book-app", "Add Field")
4227+ anchors {
4228+ left: parent.left
4229+ right: parent.right
4230+ margins: units.gu(2)
4231+ }
4232+ height: implicitHeight
4233+ onHeightChanged: {
4234+ if (expanded && (height === expandedHeight) && !scrollArea.atYEnd) {
4235+ moveToBottom.start()
4236+ }
4237+ }
4238+
4239+ UbuntuNumberAnimation {
4240+ id: moveToBottom
4241+
4242+ target: scrollArea
4243+ property: "contentY"
4244+ from: scrollArea.contentY
4245+ to: Math.min(scrollArea.contentHeight - scrollArea.height,
4246+ scrollArea.contentY + (addNewFieldButton.height - addNewFieldButton.collapsedHeight - units.gu(3)))
4247+ }
4248+
4249+ onFieldSelected: {
4250+ if (qmlTypeName) {
4251+ var newDetail = Qt.createQmlObject("import QtContacts 5.0; " + qmlTypeName + "{}", contactEditor)
4252+ if (newDetail) {
4253+ var newDetailsCopy = contactEditor.newDetails
4254+ newDetailsCopy.push(newDetail)
4255+ contactEditor.newDetails = newDetailsCopy
4256+ contactEditor.contact.addDetail(newDetail)
4257+ }
4258+ }
4259+ }
4260+ }
4261+
4262+
4263+ Item {
4264+ anchors {
4265+ left: parent.left
4266+ right: parent.right
4267+ }
4268+ height: units.gu(2)
4269+ }
4270+
4271+ Button {
4272+ id: deleteButton
4273+
4274+ text: i18n.dtr("address-book-app", "Delete")
4275+ visible: !contactEditor.isNewContact
4276+ color: UbuntuColors.red
4277+ anchors {
4278+ left: parent.left
4279+ right: parent.right
4280+ margins: units.gu(2)
4281+ }
4282+ onClicked: {
4283+ var dialog = PopupUtils.open(removeContactDialog, null)
4284+ dialog.contacts = [contactEditor.contact]
4285+ }
4286+ }
4287+
4288+
4289+ Item {
4290+ anchors {
4291+ left: parent.left
4292+ right: parent.right
4293+ }
4294+ height: units.gu(2)
4295+ }
4296+ }
4297+ }
4298+
4299+ KeyboardRectangle {
4300+ id: keyboardRectangle
4301+
4302+ onHeightChanged: {
4303+ if (activeItem) {
4304+ makeMeVisible(activeItem)
4305+ }
4306+ }
4307+ }
4308+
4309+ Component.onCompleted: {
4310+ console.debug("Editor completed: " + enabled)
4311+ if (!enabled) {
4312+ return
4313+ }
4314+
4315+ console.debug("initialFocusSection: " + contactEditor.initialFocusSection)
4316+ if (contactEditor.initialFocusSection != "") {
4317+ focusTimer.restart()
4318+ } else {
4319+ contactEditor.ready()
4320+ }
4321+ }
4322+
4323+ Component {
4324+ id: removeContactDialog
4325+
4326+ RemoveContactsDialog {
4327+ id: removeContactsDialogMessage
4328+
4329+ property bool popPages: false
4330+
4331+ onCanceled: {
4332+ PopupUtils.close(removeContactsDialogMessage)
4333+ }
4334+
4335+ onAccepted: {
4336+ popPages = true
4337+ removeContacts(contactEditor.model)
4338+ PopupUtils.close(removeContactsDialogMessage)
4339+ }
4340+
4341+ // hide virtual keyboard if necessary
4342+ Component.onCompleted: Qt.inputMethod.hide()
4343+
4344+ // WORKAROUND: SDK element crash if pop the page where the dialog was created
4345+ Component.onDestruction: {
4346+ if (popPages) {
4347+ contactEditor.pageStack.pop() // editor page
4348+ contactEditor.pageStack.pop() // view page
4349+ }
4350+ }
4351+ }
4352+ }
4353+}
4354
4355=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/TextInputDetail.qml'
4356--- src/imports/ContactEdit/TextInputDetail.qml 2014-10-31 13:41:27 +0000
4357+++ src/imports/Ubuntu/AddressBook/ContactEditor/TextInputDetail.qml 2015-05-12 21:19:18 +0000
4358@@ -1,5 +1,5 @@
4359 /*
4360- * Copyright (C) 2012-2013 Canonical, Ltd.
4361+ * Copyright (C) 2012-2015 Canonical, Ltd.
4362 *
4363 * This program is free software; you can redistribute it and/or modify
4364 * it under the terms of the GNU General Public License as published by
4365@@ -73,7 +73,7 @@
4366 // Ubuntu.Keyboard
4367 // TRANSLATORS: This is the text that will be used on the "return" key for the virtual keyboard,
4368 // this word must be less than 5 characters
4369- InputMethod.extensions: { "enterKeyText": i18n.tr("Next") }
4370+ InputMethod.extensions: { "enterKeyText": i18n.dtr("address-book-app", "Next") }
4371 readOnly: root.detail ? root.detail.readOnly : true
4372 style: TextFieldStyle {
4373 overlaySpacing: 0
4374
4375=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ValueSelector.qml'
4376--- src/imports/ContactEdit/ValueSelector.qml 2014-07-22 23:09:03 +0000
4377+++ src/imports/Ubuntu/AddressBook/ContactEditor/ValueSelector.qml 2015-05-12 21:19:18 +0000
4378@@ -1,5 +1,5 @@
4379 /*
4380- * Copyright (C) 2012-2013 Canonical, Ltd.
4381+ * Copyright (C) 2012-2015 Canonical, Ltd.
4382 *
4383 * This program is free software; you can redistribute it and/or modify
4384 * it under the terms of the GNU General Public License as published by
4385
4386=== added file 'src/imports/Ubuntu/AddressBook/ContactEditor/qmldir'
4387--- src/imports/Ubuntu/AddressBook/ContactEditor/qmldir 1970-01-01 00:00:00 +0000
4388+++ src/imports/Ubuntu/AddressBook/ContactEditor/qmldir 2015-05-12 21:19:18 +0000
4389@@ -0,0 +1,18 @@
4390+module Ubuntu.AddressBook.ContactView
4391+
4392+ContactEditorPage 0.1 ContactEditorPage.qml
4393+
4394+internal AvatarImport AvatarImport.qml
4395+internal ComboButtonAddField ComboButtonAddField.qml
4396+internal ContactDetailAddressesEditor ContactDetailAddressesEditor.qml
4397+internal ContactDetailAvatarEditor ContactDetailAvatarEditor.qml
4398+internal ContactDetailEmailsEditor ContactDetailEmailsEditor.qml
4399+internal ContactDetailGroupWithTypeEditor ContactDetailGroupWithTypeEditor.qml
4400+internal ContactDetailNameEditor ContactDetailNameEditor.qml
4401+internal ContactDetailOnlineAccountsEditor ContactDetailOnlineAccountsEditor.qml
4402+internal ContactDetailOrganizationsEditor ContactDetailOrganizationsEditor.qml
4403+internal ContactDetailPhoneNumbersEditor ContactDetailPhoneNumbersEditor.qml
4404+internal ContactDetailSyncTargetEditor ContactDetailSyncTargetEditor.qml
4405+internal ContactDetailWithTypeEditor ContactDetailWithTypeEditor.qml
4406+internal TextInputDetail TextInputDetail.qml
4407+internal ValueSelector ValueSelector.qml
4408
4409=== added directory 'src/imports/Ubuntu/AddressBook/ContactShare'
4410=== added file 'src/imports/Ubuntu/AddressBook/ContactShare/CMakeLists.txt'
4411--- src/imports/Ubuntu/AddressBook/ContactShare/CMakeLists.txt 1970-01-01 00:00:00 +0000
4412+++ src/imports/Ubuntu/AddressBook/ContactShare/CMakeLists.txt 2015-05-12 21:19:18 +0000
4413@@ -0,0 +1,26 @@
4414+set(AB_CONTACT_SHARE_QMLS
4415+ ContactSharePage.qml
4416+ qmldir
4417+)
4418+
4419+install(FILES ${AB_CONTACT_SHARE_QMLS}
4420+ DESTINATION ${ADDRESS_BOOK_APP_DIR}/imports/ContactShare
4421+)
4422+
4423+# make the files visible on qtcreator
4424+add_custom_target(contact_share_QmlFiles ALL SOURCES ${AB_CONTACT_SHARE_QMLS})
4425+
4426+if(INSTALL_COMPONENTS)
4427+ install(FILES ${AB_CONTACT_SHARE_QMLS} DESTINATION ${ADDRESS_BOOK_QMLPLUGIN_INSTALL_PREFIX}/ContactShare)
4428+endif()
4429+
4430+#copy qml files to build dir to make it possible to run without install
4431+foreach(QML_FILE ${AB_CONTACT_SHARE_QMLS})
4432+ add_custom_command(TARGET contact_share_QmlFiles PRE_BUILD
4433+ COMMAND ${CMAKE_COMMAND} -E
4434+ copy ${CMAKE_CURRENT_SOURCE_DIR}/${QML_FILE} ${CMAKE_CURRENT_BINARY_DIR}/)
4435+endforeach()
4436+
4437+if (NOT ${CMAKE_CURRENT_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
4438+ add_dependencies(copyqmlfiles contact_share_QmlFiles)
4439+endif()
4440
4441=== added file 'src/imports/Ubuntu/AddressBook/ContactShare/ContactSharePage.qml'
4442--- src/imports/Ubuntu/AddressBook/ContactShare/ContactSharePage.qml 1970-01-01 00:00:00 +0000
4443+++ src/imports/Ubuntu/AddressBook/ContactShare/ContactSharePage.qml 2015-05-12 21:19:18 +0000
4444@@ -0,0 +1,60 @@
4445+/*
4446+ * Copyright (C) 2012-2014 Canonical, Ltd.
4447+ *
4448+ * This program is free software; you can redistribute it and/or modify
4449+ * it under the terms of the GNU General Public License as published by
4450+ * the Free Software Foundation; version 3.
4451+ *
4452+ * This program is distributed in the hope that it will be useful,
4453+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4454+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4455+ * GNU General Public License for more details.
4456+ *
4457+ * You should have received a copy of the GNU General Public License
4458+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4459+ */
4460+
4461+import QtQuick 2.2
4462+import QtContacts 5.0
4463+
4464+import Ubuntu.Components 1.1
4465+import Ubuntu.Content 1.1 as ContentHub
4466+
4467+import Ubuntu.AddressBook.Base 0.1
4468+
4469+Page {
4470+ id: root
4471+
4472+ property alias contactModel: exporter.contactModel
4473+ property var contacts
4474+
4475+ signal canceled()
4476+ signal completed()
4477+
4478+ ContentHub.ContentPeerPicker {
4479+ visible: true
4480+ anchors.fill: parent
4481+ contentType: ContentHub.ContentType.Contacts
4482+ handler: ContentHub.ContentHandler.Share
4483+
4484+ onPeerSelected: {
4485+ exporter.activeTransfer = peer.request();
4486+ if (exporter.activeTransfer.state === ContentHub.ContentTransfer.InProgress) {
4487+ exporter.start(root.contacts)
4488+ }
4489+ }
4490+
4491+ onCancelPressed: {
4492+ if (exporter.activeTransfer) {
4493+ exporter.activeTransfer.state = ContentHub.ContentTransfer.Aborted
4494+ }
4495+ pageStack.pop()
4496+ }
4497+ }
4498+
4499+ ContactExporter {
4500+ id: exporter
4501+
4502+ onDone: pageStack.pop()
4503+ }
4504+}
4505
4506=== added file 'src/imports/Ubuntu/AddressBook/ContactShare/qmldir'
4507--- src/imports/Ubuntu/AddressBook/ContactShare/qmldir 1970-01-01 00:00:00 +0000
4508+++ src/imports/Ubuntu/AddressBook/ContactShare/qmldir 2015-05-12 21:19:18 +0000
4509@@ -0,0 +1,3 @@
4510+module Ubuntu.AddressBook.ContactShare
4511+
4512+ContactSharePage 0.1 ContactSharePage.qml
4513
4514=== renamed directory 'src/imports/ContactView' => 'src/imports/Ubuntu/AddressBook/ContactView'
4515=== added file 'src/imports/Ubuntu/AddressBook/ContactView/ActionButton.qml'
4516--- src/imports/Ubuntu/AddressBook/ContactView/ActionButton.qml 1970-01-01 00:00:00 +0000
4517+++ src/imports/Ubuntu/AddressBook/ContactView/ActionButton.qml 2015-05-12 21:19:18 +0000
4518@@ -0,0 +1,34 @@
4519+/*
4520+ * Copyright (C) 2012-2015 Canonical, Ltd.
4521+ *
4522+ * This program is free software; you can redistribute it and/or modify
4523+ * it under the terms of the GNU General Public License as published by
4524+ * the Free Software Foundation; version 3.
4525+ *
4526+ * This program is distributed in the hope that it will be useful,
4527+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4528+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4529+ * GNU General Public License for more details.
4530+ *
4531+ * You should have received a copy of the GNU General Public License
4532+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4533+ */
4534+
4535+import QtQuick 2.2
4536+import Ubuntu.Components 1.1
4537+
4538+AbstractButton {
4539+ id: root
4540+
4541+ property QtObject actions
4542+ property alias iconName: icon.name
4543+ property real iconSize: units.gu(2.5)
4544+
4545+ Icon {
4546+ id: icon
4547+
4548+ anchors.centerIn: parent
4549+ height: root.iconSize
4550+ width: root.iconSize
4551+ }
4552+}
4553
4554=== added file 'src/imports/Ubuntu/AddressBook/ContactView/BasicFieldView.qml'
4555--- src/imports/Ubuntu/AddressBook/ContactView/BasicFieldView.qml 1970-01-01 00:00:00 +0000
4556+++ src/imports/Ubuntu/AddressBook/ContactView/BasicFieldView.qml 2015-05-12 21:19:18 +0000
4557@@ -0,0 +1,85 @@
4558+/*
4559+ * Copyright (C) 2012-2015 Canonical, Ltd.
4560+ *
4561+ * This program is free software; you can redistribute it and/or modify
4562+ * it under the terms of the GNU General Public License as published by
4563+ * the Free Software Foundation; version 3.
4564+ *
4565+ * This program is distributed in the hope that it will be useful,
4566+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4567+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4568+ * GNU General Public License for more details.
4569+ *
4570+ * You should have received a copy of the GNU General Public License
4571+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4572+ */
4573+
4574+import QtQuick 2.2
4575+import Ubuntu.Components 1.1
4576+
4577+ Item {
4578+ id: root
4579+
4580+ property alias typeLabel: typeLabel.text
4581+ property alias values: valueList.model
4582+ property double lineHeight: units.gu(2)
4583+ property QtObject detail: null
4584+ property variant fields: null
4585+ property int parentIndex: -1
4586+
4587+ implicitHeight: typeLabel.height + fieldValues.height + units.gu(2)
4588+
4589+ Column {
4590+ id: fieldValues
4591+
4592+ anchors {
4593+ left: parent.left
4594+ top: parent.top
4595+ topMargin: units.gu(1)
4596+ right: parent.right
4597+ }
4598+ height: (valueList.count * root.lineHeight)
4599+
4600+ Repeater {
4601+ id: valueList
4602+
4603+ Label {
4604+ id: label
4605+ objectName: detail && fields ? "label_" + detailToString(detail.type, fields[index]) + "_" + root.parentIndex + "." + index : ""
4606+
4607+ anchors {
4608+ left: parent ? parent.left : undefined
4609+ right: parent ? parent.right : undefined
4610+ }
4611+ height: root.lineHeight
4612+ verticalAlignment: Text.AlignVCenter
4613+ text: modelData ? modelData : ""
4614+ elide: Text.ElideRight
4615+
4616+ // style
4617+ fontSize: "medium"
4618+ color: UbuntuColors.lightAubergine
4619+ }
4620+ }
4621+ }
4622+
4623+ Label {
4624+ id: typeLabel
4625+ objectName: detail ? "type_" + detailToString(detail.type, -1) + "_" + root.parentIndex : ""
4626+
4627+ elide: Text.ElideRight
4628+ visible: text != ""
4629+ anchors {
4630+ left: parent.left
4631+ top: fieldValues.bottom
4632+ //topMargin: units.gu(0.0)
4633+ right: parent.right
4634+ }
4635+ height: visible ? units.gu(2) : 0
4636+ verticalAlignment: Text.AlignVCenter
4637+
4638+ // style
4639+ fontSize: "small"
4640+ opacity: 0.8
4641+ }
4642+}
4643
4644=== modified file 'src/imports/Ubuntu/AddressBook/ContactView/CMakeLists.txt'
4645--- src/imports/ContactView/CMakeLists.txt 2014-08-13 20:52:57 +0000
4646+++ src/imports/Ubuntu/AddressBook/ContactView/CMakeLists.txt 2015-05-12 21:19:18 +0000
4647@@ -1,12 +1,37 @@
4648-set(CONTACT_VIEW_QMLS
4649+set(AB_CONTACT_VIEW_QMLS
4650+ ActionButton.qml
4651+ BasicFieldView.qml
4652+ ContactDetailAddressesView.qml
4653+ ContactDetailAvatarView.qml
4654+ ContactDetailEmailsView.qml
4655+ ContactDetailGroupWithTypeView.qml
4656+ ContactDetailNameView.qml
4657+ ContactDetailOnlineAccountsView.qml
4658+ ContactDetailOrganizationsView.qml
4659+ ContactDetailPhoneNumbersView.qml
4660+ ContactDetailPhoneNumberView.qml
4661 ContactDetailSyncTargetView.qml
4662+ ContactDetailWithTypeView.qml
4663 ContactFetchError.qml
4664- ContactView.qml
4665-)
4666-
4667-install(FILES ${CONTACT_VIEW_QMLS}
4668- DESTINATION ${ADDRESS_BOOK_APP_DIR}/imports/ContactView
4669+ #ContactHeaderView.qml
4670+ ContactViewPage.qml
4671+ qmldir
4672 )
4673
4674 # make the files visible on qtcreator
4675-add_custom_target(contact_view_QmlFiles ALL SOURCES ${CONTACT_VIEW_QMLS})
4676+add_custom_target(contact_view_QmlFiles ALL SOURCES ${AB_CONTACT_VIEW_QMLS})
4677+
4678+if(INSTALL_COMPONENTS)
4679+ install(FILES ${AB_CONTACT_VIEW_QMLS} DESTINATION ${ADDRESS_BOOK_QMLPLUGIN_INSTALL_PREFIX}/ContactView)
4680+endif()
4681+
4682+#copy qml files to build dir to make it possible to run without install
4683+foreach(QML_FILE ${AB_CONTACT_VIEW_QMLS})
4684+ add_custom_command(TARGET contact_view_QmlFiles PRE_BUILD
4685+ COMMAND ${CMAKE_COMMAND} -E
4686+ copy ${CMAKE_CURRENT_SOURCE_DIR}/${QML_FILE} ${CMAKE_CURRENT_BINARY_DIR}/)
4687+endforeach()
4688+
4689+if (NOT ${CMAKE_CURRENT_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
4690+ add_dependencies(copyqmlfiles contact_view_QmlFiles)
4691+endif()
4692
4693=== added file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailAddressesView.qml'
4694--- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailAddressesView.qml 1970-01-01 00:00:00 +0000
4695+++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailAddressesView.qml 2015-05-12 21:19:18 +0000
4696@@ -0,0 +1,32 @@
4697+/*
4698+ * Copyright (C) 2012-2015 Canonical, Ltd.
4699+ *
4700+ * This program is free software; you can redistribute it and/or modify
4701+ * it under the terms of the GNU General Public License as published by
4702+ * the Free Software Foundation; version 3.
4703+ *
4704+ * This program is distributed in the hope that it will be useful,
4705+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4706+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4707+ * GNU General Public License for more details.
4708+ *
4709+ * You should have received a copy of the GNU General Public License
4710+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4711+ */
4712+
4713+import QtQuick 2.2
4714+import QtContacts 5.0 as QtContacts
4715+import Ubuntu.Components 1.1
4716+
4717+ContactDetailGroupWithTypeView {
4718+ id: root
4719+
4720+ title: i18n.dtr("address-book-app", "Address")
4721+ defaultIcon: "image://theme/location"
4722+ detailType: QtContacts.ContactDetail.Address
4723+ fields: [ QtContacts.Address.Street,
4724+ QtContacts.Address.Locality,
4725+ QtContacts.Address.Region,
4726+ QtContacts.Address.Postcode,
4727+ QtContacts.Address.Country]
4728+}
4729
4730=== added file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailAvatarView.qml'
4731--- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailAvatarView.qml 1970-01-01 00:00:00 +0000
4732+++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailAvatarView.qml 2015-05-12 21:19:18 +0000
4733@@ -0,0 +1,89 @@
4734+/*
4735+ * Copyright (C) 2012-2015 Canonical, Ltd.
4736+ *
4737+ * This program is free software; you can redistribute it and/or modify
4738+ * it under the terms of the GNU General Public License as published by
4739+ * the Free Software Foundation; version 3.
4740+ *
4741+ * This program is distributed in the hope that it will be useful,
4742+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4743+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4744+ * GNU General Public License for more details.
4745+ *
4746+ * You should have received a copy of the GNU General Public License
4747+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4748+ */
4749+
4750+import QtQuick 2.2
4751+import QtGraphicalEffects 1.0
4752+import QtContacts 5.0
4753+import Ubuntu.Components 1.1
4754+
4755+import Ubuntu.Contacts 0.1
4756+import Ubuntu.AddressBook.Base 0.1
4757+
4758+ContactDetailBase {
4759+ id: root
4760+
4761+ implicitHeight: units.gu(12)
4762+ implicitWidth: parent.width
4763+
4764+ Connections {
4765+ id: connections
4766+
4767+ target: avatar.contactElement
4768+ ignoreUnknownSignals: true
4769+ onContactChanged: avatar.reload()
4770+ }
4771+
4772+ Image {
4773+ id: imageBg
4774+
4775+ source: avatar.avatarUrl
4776+ anchors.fill: parent
4777+ fillMode: Image.PreserveAspectCrop
4778+ visible: false
4779+ }
4780+
4781+ FastBlur {
4782+ anchors.fill: imageBg
4783+ source: imageBg
4784+ radius: 32
4785+ visible: avatar.avatarUrl !== avatar.fallbackAvatarUrl
4786+ }
4787+
4788+ ContactAvatar {
4789+ id: avatar
4790+ objectName: "contactAvatarDetail"
4791+
4792+ contactElement: root.contact
4793+ height: units.gu(8)
4794+ width: height
4795+
4796+ anchors {
4797+ left: parent.left
4798+ verticalCenter: parent.verticalCenter
4799+ leftMargin: units.gu(2)
4800+ }
4801+
4802+ }
4803+
4804+ ActionButton {
4805+ id: favImage
4806+
4807+ iconName: root.contact && root.contact.favorite.favorite ? "starred" : "non-starred"
4808+ height: units.gu(4)
4809+ iconSize: units.gu(3)
4810+ width: height
4811+ anchors {
4812+ right: parent.right
4813+ rightMargin: units.gu(2)
4814+ verticalCenter: parent.verticalCenter
4815+ }
4816+
4817+ onClicked: {
4818+ root.contact.favorite.favorite = !root.contact.favorite.favorite
4819+ root.contact.save()
4820+ }
4821+ }
4822+}
4823
4824=== added file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailEmailsView.qml'
4825--- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailEmailsView.qml 1970-01-01 00:00:00 +0000
4826+++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailEmailsView.qml 2015-05-12 21:19:18 +0000
4827@@ -0,0 +1,29 @@
4828+/*
4829+ * Copyright (C) 2012-2015 Canonical, Ltd.
4830+ *
4831+ * This program is free software; you can redistribute it and/or modify
4832+ * it under the terms of the GNU General Public License as published by
4833+ * the Free Software Foundation; version 3.
4834+ *
4835+ * This program is distributed in the hope that it will be useful,
4836+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4837+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4838+ * GNU General Public License for more details.
4839+ *
4840+ * You should have received a copy of the GNU General Public License
4841+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4842+ */
4843+
4844+import QtQuick 2.2
4845+import QtContacts 5.0 as QtContacts
4846+import Ubuntu.Components 1.1
4847+
4848+ContactDetailGroupWithTypeView {
4849+ detailType: QtContacts.ContactDetail.Email
4850+ title: i18n.dtr("address-book-app", "Email")
4851+ fields: [ 0 ]
4852+ defaultAction: Action {
4853+ text: i18n.dtr("address-book-app", "Email")
4854+ iconName: "email"
4855+ }
4856+}
4857
4858=== added file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailGroupWithTypeView.qml'
4859--- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailGroupWithTypeView.qml 1970-01-01 00:00:00 +0000
4860+++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailGroupWithTypeView.qml 2015-05-12 21:19:18 +0000
4861@@ -0,0 +1,66 @@
4862+/*
4863+ * Copyright (C) 2012-2015 Canonical, Ltd.
4864+ *
4865+ * This program is free software; you can redistribute it and/or modify
4866+ * it under the terms of the GNU General Public License as published by
4867+ * the Free Software Foundation; version 3.
4868+ *
4869+ * This program is distributed in the hope that it will be useful,
4870+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4871+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4872+ * GNU General Public License for more details.
4873+ *
4874+ * You should have received a copy of the GNU General Public License
4875+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4876+ */
4877+
4878+import QtQuick 2.2
4879+import QtContacts 5.0 as QtContacts
4880+
4881+import Ubuntu.Components 1.1
4882+import Ubuntu.Components.ListItems 1.0 as ListItem
4883+
4884+import Ubuntu.AddressBook.Base 0.1
4885+
4886+ContactDetailGroupWithTypeBase {
4887+ id: root
4888+
4889+ property Action defaultAction
4890+ signal actionTrigerred(string action, QtObject detail)
4891+
4892+ showEmpty: false
4893+ headerDelegate: ListItem.Empty {
4894+ highlightWhenPressed: false
4895+
4896+ divider.anchors.leftMargin: units.gu(2)
4897+ divider.anchors.rightMargin: units.gu(2)
4898+ width: root.width
4899+ height: units.gu(5)
4900+ Label {
4901+ anchors {
4902+ verticalCenter: parent.verticalCenter
4903+ left: parent.left
4904+ right: parent.right
4905+ margins: units.gu(2)
4906+ }
4907+
4908+ text: root.title
4909+
4910+ // style
4911+ fontSize: "medium"
4912+ }
4913+ }
4914+
4915+ detailDelegate: ContactDetailWithTypeView {
4916+ property variant detailType: detail && root.contact && root.typeModelReady ? root.getType(detail) : ""
4917+
4918+ action: root.defaultAction
4919+ contact: root.contact
4920+ fields: root.fields
4921+ typeLabel: detailType ? detailType.label : ""
4922+
4923+ height: implicitHeight
4924+ width: root.width
4925+ onClicked: root.actionTrigerred(action, detail)
4926+ }
4927+}
4928
4929=== modified file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailNameView.qml'
4930--- src/imports/ContactView/ContactDetailNameView.qml 2014-07-20 20:23:20 +0000
4931+++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailNameView.qml 2015-05-12 21:19:18 +0000
4932@@ -1,5 +1,5 @@
4933 /*
4934- * Copyright (C) 2012-2013 Canonical, Ltd.
4935+ * Copyright (C) 2012-2015 Canonical, Ltd.
4936 *
4937 * This program is free software; you can redistribute it and/or modify
4938 * it under the terms of the GNU General Public License as published by
4939@@ -18,7 +18,7 @@
4940 import Ubuntu.Components 1.1
4941 import QtContacts 5.0
4942
4943-import "../Common"
4944+import Ubuntu.AddressBook.Base 0.1
4945
4946 ContactDetailBase {
4947 id: root
4948
4949=== added file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailOnlineAccountsView.qml'
4950--- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailOnlineAccountsView.qml 1970-01-01 00:00:00 +0000
4951+++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailOnlineAccountsView.qml 2015-05-12 21:19:18 +0000
4952@@ -0,0 +1,31 @@
4953+/*
4954+ * Copyright (C) 2012-2015 Canonical, Ltd.
4955+ *
4956+ * This program is free software; you can redistribute it and/or modify
4957+ * it under the terms of the GNU General Public License as published by
4958+ * the Free Software Foundation; version 3.
4959+ *
4960+ * This program is distributed in the hope that it will be useful,
4961+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4962+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4963+ * GNU General Public License for more details.
4964+ *
4965+ * You should have received a copy of the GNU General Public License
4966+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4967+ */
4968+
4969+import QtQuick 2.2
4970+import QtContacts 5.0 as QtContacts
4971+
4972+import Ubuntu.Components 1.1
4973+import Ubuntu.Contacts 0.1
4974+
4975+ContactDetailGroupWithTypeView {
4976+ detailType: QtContacts.ContactDetail.OnlineAccount
4977+ fields: [ QtContacts.OnlineAccount.AccountUri ]
4978+ title: i18n.dtr("address-book-app", "Social")
4979+ typeModel: ContactDetailOnlineAccountTypeModel { }
4980+ defaultAction: Action {
4981+ text: i18n.dtr("address-book-app", "Touch")
4982+ }
4983+}
4984
4985=== added file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailOrganizationsView.qml'
4986--- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailOrganizationsView.qml 1970-01-01 00:00:00 +0000
4987+++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailOrganizationsView.qml 2015-05-12 21:19:18 +0000
4988@@ -0,0 +1,32 @@
4989+/*
4990+ * Copyright (C) 2012-2015 Canonical, Ltd.
4991+ *
4992+ * This program is free software; you can redistribute it and/or modify
4993+ * it under the terms of the GNU General Public License as published by
4994+ * the Free Software Foundation; version 3.
4995+ *
4996+ * This program is distributed in the hope that it will be useful,
4997+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4998+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4999+ * GNU General Public License for more details.
5000+ *
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches