Merge lp:~renatofilho/address-book-app/split-app into lp:address-book-app

Proposed by Renato Araujo Oliveira Filho on 2015-05-12
Status: Merged
Approved by: Gustavo Pichorim Boiko on 2015-05-14
Approved revision: 451
Merged at revision: 436
Proposed branch: lp:~renatofilho/address-book-app/split-app
Merge into: lp:address-book-app
Prerequisite: lp:~renatofilho/address-book-app/fix-test_import_from_sim
Diff against target: 8831 lines (+3920/-3613)
134 files modified
CMakeLists.txt (+1/-0)
debian/control (+13/-2)
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 (+2/-2)
src/imports/Ubuntu/Contacts/ContactList.js (+1/-1)
src/imports/Ubuntu/Contacts/ContactListModel.qml (+1/-1)
src/imports/Ubuntu/Contacts/ContactListView.qml (+1/-1)
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 (+4/-3)
src/imports/Ubuntu/Contacts/MultipleSelectionVisualModel.qml (+1/-1)
src/imports/Ubuntu/Contacts/contacts.cpp (+25/-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)
src/imports/VCardImportDialog.qml (+94/-0)
tests/autopilot/address_book_app/__init__.py (+6/-5)
tests/autopilot/address_book_app/address_book/__init__.py (+34/-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 (+142/-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 (+0/-152)
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/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/split-app
Reviewer Review Type Date Requested Status
Ricardo Salveti packaging Approve on 2015-06-04
Sebastien Bacher Needs Fixing on 2015-05-29
Gustavo Pichorim Boiko (community) 2015-05-12 Approve on 2015-05-14
PS Jenkins bot continuous-integration 2015-05-12 Approve on 2015-05-14
Review via email: mp+258937@code.launchpad.net

This proposal supersedes a proposal from 2015-04-28.

Commit Message

Split the app in modules to be used by dialer and messaging app.

To post a comment you must log in.

Are there any related MPs required for this MP to build/function as expected?
YES: lp:~renatofilho/address-book-app/fix-test_import_from_sim

Is your branch in sync with latest trunk?
YES

Did you perform an exploratory manual test run of your code change and any related functionality on device or emulator?
YES

Did you successfully run all tests found in your component's Test Plan on device or emulator?
YES

If you changed the UI, was the change specified/approved by design?
NO UI CHANGE

If you changed the packaging (debian), did you add a core-dev as a reviewer to this MP?
NO PACKAGE CHANGE

Gustavo Pichorim Boiko (boiko) wrote :

+ imgThread->start();
+ imgThread->wait();
+
+ // FIXME: implement this as async function
+ while(imgThread->isRunning()) {

I think the imgThread->wait() there is wrong, it was not in the original code and it will block the execution.

review: Needs Fixing
447. By Renato Araujo Oliveira Filho on 2015-05-13

Revert wrong change on copyImage function.

> + imgThread->start();
> + imgThread->wait();
> +
> + // FIXME: implement this as async function
> + while(imgThread->isRunning()) {
>
> I think the imgThread->wait() there is wrong, it was not in the original code
> and it will block the execution.

Fixed

448. By Renato Araujo Oliveira Filho on 2015-05-13

Added qtdeclarative5-ubuntu-content1 in the dep list.

449. By Renato Araujo Oliveira Filho on 2015-05-13

Fixed deps.

Gustavo Pichorim Boiko (boiko) wrote :

- model: MostCalledContactsModel {
- id: mostCalledModel
+// model: MostCalledContactsModel {
+// id: mostCalledModel

I think this was done for testing and should be re-enabled, right?

review: Needs Fixing
450. By Renato Araujo Oliveira Filho on 2015-05-13

Revert changes on MostCalledModel.qml.

451. By Renato Araujo Oliveira Filho on 2015-05-14

Update MostCalledList.qml.

Gustavo Pichorim Boiko (boiko) wrote :

Did you perform an exploratory manual test run of the code change and any related functionality on device or emulator?
Yes

Did CI run pass? If not, please explain why.
Yes

Have you checked that submitter has accurately filled out the submitter checklist and has taken no shortcut?
Yes

Code looks good and works as expected!

review: Approve
Sebastien Bacher (seb128) wrote :

that's going to need a rebase on trunk after the landing of the recent translation fix that makes use of the correct domain

review: Needs Fixing
452. By Renato Araujo Oliveira Filho on 2015-06-01

Does not try to fetch contact with invalid model.

453. By Renato Araujo Oliveira Filho on 2015-06-01

Show empty string instead of "No name" if contact is not fetched yet.

454. By Renato Araujo Oliveira Filho on 2015-06-01

Trunk merged.

455. By Renato Araujo Oliveira Filho on 2015-06-01

Show empty title while contact is invalid.

456. By Renato Araujo Oliveira Filho on 2015-06-01

Added VCardImportDialog.qml file back.

Ricardo Salveti (rsalveti) wrote :

Packaging changes look fine.

review: Approve (packaging)

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

Subscribers

People subscribed via source and target branches