Merge lp:~renatofilho/address-book-app/keyboard-navigation into lp:address-book-app

Proposed by Renato Araujo Oliveira Filho
Status: Merged
Approved by: Bill Filler
Approved revision: 550
Merged at revision: 522
Proposed branch: lp:~renatofilho/address-book-app/keyboard-navigation
Merge into: lp:address-book-app
Diff against target: 1460 lines (+464/-156)
28 files modified
src/app/addressbookapp.cpp (+17/-1)
src/app/addressbookapp.h (+7/-0)
src/imports/ABContactEditorPage.qml (+7/-5)
src/imports/ABContactListPage.qml (+156/-32)
src/imports/ABContactViewPage.qml (+12/-0)
src/imports/BottomEdge.qml (+18/-1)
src/imports/MainWindow.qml (+27/-1)
src/imports/Settings/SettingsPage.qml (+59/-3)
src/imports/Ubuntu/AddressBook/Base/ContactDetailBase.qml (+22/-8)
src/imports/Ubuntu/AddressBook/Base/ContactDetailGroupBase.qml (+2/-1)
src/imports/Ubuntu/AddressBook/Base/RemoveContactsDialog.qml (+10/-2)
src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAvatarEditor.qml (+1/-0)
src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailGroupWithTypeEditor.qml (+12/-23)
src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailNameEditor.qml (+1/-0)
src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailSyncTargetEditor.qml (+7/-2)
src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailWithTypeEditor.qml (+0/-1)
src/imports/Ubuntu/AddressBook/ContactEditor/ContactEditorPage.qml (+23/-17)
src/imports/Ubuntu/AddressBook/ContactEditor/TextInputDetail.qml (+24/-10)
src/imports/Ubuntu/AddressBook/ContactView/ActionButton.qml (+1/-0)
src/imports/Ubuntu/AddressBook/ContactView/BasicFieldView.qml (+1/-0)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailAvatarView.qml (+1/-0)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailGroupWithTypeView.qml (+13/-21)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailNameView.qml (+1/-1)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailSyncTargetView.qml (+2/-1)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailWithTypeView.qml (+3/-0)
src/imports/Ubuntu/Contacts/ContactListView.qml (+26/-1)
src/imports/Ubuntu/Contacts/ContactSimpleListView.qml (+7/-13)
src/imports/Ubuntu/Contacts/FastScroll.qml (+4/-12)
To merge this branch: bzr merge lp:~renatofilho/address-book-app/keyboard-navigation
Reviewer Review Type Date Requested Status
Florian Boucault (community) Approve
PS Jenkins bot continuous-integration Needs Fixing
Bill Filler (community) Needs Fixing
Review via email: mp+277176@code.launchpad.net

Commit message

Implement keyboard navigation for contact list.
Fix 'tab' navigation for contact editor page.
Added shortcuts for the page actions.

Description of the change

Available shortcuts:

General
=======
Esc = Back (Page stack)

Contact List
============
Ctrl + F = Search
Ctrl + N = Bottom edge (create new)

Contact View
============
Ctrl + E = Edit

Contact Editor
==============
Ctrl + S = Save
Ctrl + Delete = Delete contact

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

Fixed focus on test fields.

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

Fixed visual for field header.

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

Merged: ~renatofilho/address-book-app/fix-1511477

509. By Renato Araujo Oliveira Filho

Make ActionButton icons 'orange' when it has focus.
Fixed some focus misbehavior.

Revision history for this message
Bill Filler (bfiller) wrote :

Some problems:

1) Ctrl F to search, then type your search string, press enter, down arrow should navigate to first item in results list and select it

2) When at top of the contact list and press up arrow focus should go to the section selector
a) right/left arrow in section selector should navigate between sections
b) down arrow when in section selector should navigate back to list

3) After saving a new contact, the new contact should be selected in the list and scrolled into view, but this is not working and first item in list is selected instead.

4) When you create a new contact and cancel (via esc), we should either select what was previously selected or the first item, but something should be selected. Currently nothing selected and right panel is blank which is not desirable.

5) When you enter edit mode, focus needs to be placed in the first field

6) In edit mode, Up/Down arrow keys should navigate the fields on the edit screen same as tabs do

7) In edit mode, left arrow key should bring focus back to contact list, if in contact list right arrow should navigate to first field in edit mode

8) Seeing of lots of these errors in log: file:///usr/share/address-book-app/imports/ABContactEditorPage.qml:45:9: QML Action: Invalid shortcut:

8)

review: Needs Fixing
Revision history for this message
Bill Filler (bfiller) wrote :

When press Settings button, focus should move to first item in settings list and up/down arrow should navigate, right arrow/enter should expand the item

review: Needs Fixing
Revision history for this message
Bill Filler (bfiller) wrote :

In edit mode, tab key and arrow keys should navigate to the Add Field button and Delete buttons, currently these are skipped in the navigation.

review: Needs Fixing
Revision history for this message
Bill Filler (bfiller) wrote :

In edit mode after making changes and saving the contact, the next contact in the list is selected instead of keeping the selection on the contact you just edited.

review: Needs Fixing
Revision history for this message
Renato Araujo Oliveira Filho (renatofilho) wrote :

> Some problems:
>
> 1) Ctrl F to search, then type your search string, press enter, down arrow
> should navigate to first item in results list and select it
I do not like to use arrows to navigate btw objects, the arrows is alreary consumed by the text input to navigate internally (up/down when multilines).
Could we use "Tab" here?

>
> 2) When at top of the contact list and press up arrow focus should go to the
> section selector
> a) right/left arrow in section selector should navigate between sections
> b) down arrow when in section selector should navigate back to list

This need to be implemented by SDK. We can implement WORKAROUNDS here to support that but I would like to avoid it if possible.

The correct here is set focus to the page section and it handle the arrows or tab.

>
> 3) After saving a new contact, the new contact should be selected in the list
> and scrolled into view, but this is not working and first item in list is
> selected instead.
>
> 4) When you create a new contact and cancel (via esc), we should either select
> what was previously selected or the first item, but something should be
> selected. Currently nothing selected and right panel is blank which is not
> desirable.
I will implement that.

>
> 5) When you enter edit mode, focus needs to be placed in the first field
As discussed on IRC, this is not possible at the moment since we can not detect if there is a keyboard connect to device or not.
Implementing it ad default behavior you bring regressions on the phone use case.
check: https://bugs.launchpad.net/ubuntu/+source/address-book-app/+bug/1268042

>
> 6) In edit mode, Up/Down arrow keys should navigate the fields on the edit
> screen same as tabs do
Are you sure about that? This is not how desktop apps work. Most of the apps uses Tab to go foward and "shift+tab" to go backward on items in the screen.

>
> 7) In edit mode, left arrow key should bring focus back to contact list, if in
> contact list right arrow should navigate to first field in edit mode

Left and Right arrow is already used by the fields to navigate internally on the text. The correct will be use "tab".

But again we will need some big WORKAROUNDS here, since the item that receives focus on the page will be the header and it does not handle focus very well at the moment.

>
> 8) Seeing of lots of these errors in log: file:///usr/share/address-book-
> app/imports/ABContactEditorPage.qml:45:9: QML Action: Invalid shortcut:
This is because a WORKAROUND that I am using to avoid bug #1514856.

Right now all shortcuts are enable even if the action is not active/visible, because of that I am using this WORKAROUND:

shortcut: root.active ? "Ctrl+s": ""

this warning message appear when setting the shortcut to "" (empty).

>
> 8)

Revision history for this message
Renato Araujo Oliveira Filho (renatofilho) wrote :

> In edit mode, tab key and arrow keys should navigate to the Add Field button
> and Delete buttons, currently these are skipped in the navigation.

The current SDK does not have focus visual feedback for buttons, allowing it to receive focus can cause confusion since the user will never know which button or item has focus or not.

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

Use tab to navigate to contact list from the search field.

511. By Renato Araujo Oliveira Filho

Move backwards on fields navigation when pressing 'Shif+Tab'

512. By Renato Araujo Oliveira Filho

Avoid load contact view page twice for the same contact.

513. By Renato Araujo Oliveira Filho

Make sure the contact list currentIndex does not change after editing a contact.

514. By Renato Araujo Oliveira Filho

Make sure that the app alwasy start with a selected contact when running on multi column.

Revision history for this message
Renato Araujo Oliveira Filho (renatofilho) wrote :

> Some problems:
>
> 1) Ctrl F to search, then type your search string, press enter, down arrow
> should navigate to first item in results list and select it
Fixed on rev. 510

> 3) After saving a new contact, the new contact should be selected in the list
> and scrolled into view, but this is not working and first item in list is
> selected instead.
Fixed on rev. 513

>
> 4) When you create a new contact and cancel (via esc), we should either select
> what was previously selected or the first item, but something should be
> selected. Currently nothing selected and right panel is blank which is not
> desirable.
Fixed on rev. 513

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

Move focus to contact list when pressing 'down' key on search field.

516. By Renato Araujo Oliveira Filho

WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822
because of that we create a new property called '_allowFocus' that we chack before set focus for any object.

517. By Renato Araujo Oliveira Filho

Added support for shortcuts on RemoveContactsDialog.

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

Trunk merged.

519. By Renato Araujo Oliveira Filho

Fixed bottom edge visibility.

520. By Renato Araujo Oliveira Filho

Implemented keyboard navigation on settings page.

521. By Renato Araujo Oliveira Filho

Fixed duplicated shortcut while editing a contact while searching.

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

Only set focus on list item after the key down pressed.

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

Fixed focus chain on TextField.

524. By Renato Araujo Oliveira Filho

Fixed currentIndex change while editing a contact.
Right arrow on search field give focus to First Field on editor page.

525. By Renato Araujo Oliveira Filho

"Right" arrow give focus for first field while editing.

526. By Renato Araujo Oliveira Filho

Get rid of 'invalid shortcut' error messages.

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

Fixed bottom edge editor page behaviour.

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

Avoid move contact index after editing it.

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

Trunk merged.

530. By Renato Araujo Oliveira Filho

Fixed view page connections after edit a contact.

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

Update FastScroll colors.

532. By Renato Araujo Oliveira Filho

Move list to desired contact on 'positionViewAtContact'.

533. By Renato Araujo Oliveira Filho

Change selected item color to organge if the contact list has focus.

534. By Renato Araujo Oliveira Filho

Do not move focus to next item when in the bottom of the list.

535. By Renato Araujo Oliveira Filho

Avoid warning messagins while creating Connection signals with null targes.
Move focus to editor when pressing tab in the contact list.

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

Disable contact editor page while on bottom edge to avoid focus problems.

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

Centralize contact when moving the list to it.

538. By Renato Araujo Oliveira Filho

Do not select any contact while creating a new one.

539. By Renato Araujo Oliveira Filho

Deos not change the foregroundColor of item on settings page if using the single column layout.

540. By Renato Araujo Oliveira Filho

Do not move to next item on right arrow press, while in search field.

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

Removed FastScroll magnified border.

542. By Renato Araujo Oliveira Filho

Does not move focus to search field on right key press.

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

use gray background color for fasctroll tooltip.

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

Close settings page with 'Esc' or 'left arrow'.

545. By Renato Araujo Oliveira Filho

Activate actions on settings page by pressing 'right' key.

546. By Renato Araujo Oliveira Filho

Use a orange rectangle to show the selected item in the settings page.

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

Can you explain the purpose of forceActiveFocus() in src/imports/ABContactListPage.qml

    function reloadContact() {
        [...]
        contactList.forceActiveFocus()
    }

Revision history for this message
Florian Boucault (fboucault) wrote :

Can you explain the purpose of
    Timer {
        id: fetchNewContactTimer
        [...]
    }

Is it a workaround? if so of what?

547. By Renato Araujo Oliveira Filho

Fixed severam comments from reviewer;

548. By Renato Araujo Oliveira Filho

Removed 'focus' property change.

549. By Renato Araujo Oliveira Filho

Fixed selected color.

550. By Renato Araujo Oliveira Filho

Use palette color instead of hardcoded one.

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

Much better! Thank you, code is good to go.

review: Approve
551. By Renato Araujo Oliveira Filho

Trunk merged.

552. By Renato Araujo Oliveira Filho

Created 'saveActionEnabled' property to avoid problems on tests.
Used that new property instead of search for Action.

553. By Renato Araujo Oliveira Filho

Switch to keyboard visuals as soon as any key is pressed.
Avoid crash on Contact list page with 'esc' key.

554. By Renato Araujo Oliveira Filho

Avoid crash app while saving a contact using shortcut.

555. By Renato Araujo Oliveira Filho

Avoid ambiguous shortcut while search and view contact page openend.

556. By Renato Araujo Oliveira Filho

Removed workarounds necessary for bug #1518420 (fixed)

557. By Renato Araujo Oliveira Filho

Trunk merged.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/app/addressbookapp.cpp'
--- src/app/addressbookapp.cpp 2015-12-11 16:43:39 +0000
+++ src/app/addressbookapp.cpp 2015-12-16 18:38:23 +0000
@@ -104,7 +104,8 @@
104 m_netManager(new QNetworkConfigurationManager),104 m_netManager(new QNetworkConfigurationManager),
105 m_pickingMode(false),105 m_pickingMode(false),
106 m_testMode(false),106 m_testMode(false),
107 m_withArgs(false)107 m_withArgs(false),
108 m_withKeyboard(false)
108{109{
109 s_elapsed.start();110 s_elapsed.start();
110 setOrganizationName(SETTINGS_ORGANIZATION_NAME);111 setOrganizationName(SETTINGS_ORGANIZATION_NAME);
@@ -447,6 +448,16 @@
447 qDebug() << "ELAPSED:" << s_elapsed.elapsed() / 1000.0;448 qDebug() << "ELAPSED:" << s_elapsed.elapsed() / 1000.0;
448}449}
449450
451bool AddressBookApp::notify(QObject *obj, QEvent *event)
452{
453 if ((event->type() == QEvent::KeyPress) && !m_withKeyboard) {
454 m_withKeyboard = true;
455 Q_EMIT usingKeyboardChanged();
456 return true;
457 }
458 return QGuiApplication::notify(obj, event);
459}
460
450QString AddressBookApp::callbackApplication() const461QString AddressBookApp::callbackApplication() const
451{462{
452 return m_callbackApplication;463 return m_callbackApplication;
@@ -475,3 +486,8 @@
475{486{
476 return !m_updateWatcher.isNull();487 return !m_updateWatcher.isNull();
477}488}
489
490bool AddressBookApp::usingKeyboard() const
491{
492 return m_withKeyboard;
493}
478494
=== modified file 'src/app/addressbookapp.h'
--- src/app/addressbookapp.h 2015-12-11 16:43:39 +0000
+++ src/app/addressbookapp.h 2015-12-16 18:38:23 +0000
@@ -32,6 +32,7 @@
32 Q_PROPERTY(bool isOnline READ isOnline NOTIFY isOnlineChanged)32 Q_PROPERTY(bool isOnline READ isOnline NOTIFY isOnlineChanged)
33 Q_PROPERTY(bool serverSafeMode READ serverSafeMode NOTIFY serverSafeModeChanged)33 Q_PROPERTY(bool serverSafeMode READ serverSafeMode NOTIFY serverSafeModeChanged)
34 Q_PROPERTY(bool updating READ updating NOTIFY updatingChanged)34 Q_PROPERTY(bool updating READ updating NOTIFY updatingChanged)
35 Q_PROPERTY(bool usingKeyboard READ usingKeyboard NOTIFY usingKeyboardChanged)
3536
36public:37public:
37 AddressBookApp(int &argc, char **argv);38 AddressBookApp(int &argc, char **argv);
@@ -45,12 +46,14 @@
45 bool isOnline() const;46 bool isOnline() const;
46 bool serverSafeMode() const;47 bool serverSafeMode() const;
47 bool updating() const;48 bool updating() const;
49 bool usingKeyboard() const;
4850
49Q_SIGNALS:51Q_SIGNALS:
50 void callbackApplicationChanged();52 void callbackApplicationChanged();
51 void isOnlineChanged();53 void isOnlineChanged();
52 void serverSafeModeChanged();54 void serverSafeModeChanged();
53 void updatingChanged();55 void updatingChanged();
56 void usingKeyboardChanged();
54 void sourcesChanged();57 void sourcesChanged();
5558
56public Q_SLOTS:59public Q_SLOTS:
@@ -66,6 +69,9 @@
66 // debug69 // debug
67 void elapsed() const;70 void elapsed() const;
6871
72protected:
73 bool notify(QObject *obj, QEvent *event);
74
69private Q_SLOTS:75private Q_SLOTS:
70 void onUpdateCallFinished(QDBusPendingCallWatcher *watcher);76 void onUpdateCallFinished(QDBusPendingCallWatcher *watcher);
7177
@@ -84,6 +90,7 @@
84 bool m_pickingMode;90 bool m_pickingMode;
85 bool m_testMode;91 bool m_testMode;
86 bool m_withArgs;92 bool m_withArgs;
93 bool m_withKeyboard;
87};94};
8895
89#endif96#endif
9097
=== modified file 'src/imports/ABContactEditorPage.qml'
--- src/imports/ABContactEditorPage.qml 2015-12-11 14:38:17 +0000
+++ src/imports/ABContactEditorPage.qml 2015-12-16 18:38:23 +0000
@@ -38,9 +38,11 @@
3838
39 text: i18n.tr("Cancel")39 text: i18n.tr("Cancel")
40 iconName: "back"40 iconName: "back"
41 onTriggered: {41 // WORKAROUND: SDK does not unregister shortcut on object destruction
42 root.cancel()42 // we need to do it manually. (bug #1518420)
43 }43 enabled: root.active && root.enabled
44 shortcut: enabled ? "Esc" : undefined
45 onTriggered: root.cancel()
44 }46 }
4547
46 head.actions: [48 head.actions: [
@@ -51,8 +53,8 @@
5153
52 text: i18n.tr("Save")54 text: i18n.tr("Save")
53 iconName: "ok"55 iconName: "ok"
54 // disable save button while avatar scale still running56 enabled: root.isContactValid && root.active && root.enabled
55 enabled: root.isContactValid57 shortcut: "Ctrl+s"
56 onTriggered: root.save()58 onTriggered: root.save()
57 }59 }
58 ]60 ]
5961
=== modified file 'src/imports/ABContactListPage.qml'
--- src/imports/ABContactListPage.qml 2015-12-07 08:13:36 +0000
+++ src/imports/ABContactListPage.qml 2015-12-16 18:38:23 +0000
@@ -38,10 +38,11 @@
38 property QtObject contactIndex: null38 property QtObject contactIndex: null
39 property string newPhoneToAdd: ""39 property string newPhoneToAdd: ""
40 property alias contactManager: contactList.manager40 property alias contactManager: contactList.manager
41 property Page contactViewPage: null41 property alias contactViewPage: contactViewPageConnections.target
42 property Page contactEditorPage: null42 property alias contactEditorPage: contactEditorPageConnections.target
43 property var _busyDialog: null43 property var _busyDialog: null
44 property bool _importingTestData: false44 property bool _importingTestData: false
45 property bool _creatingContact: false
4546
46 readonly property bool bottomEdgePageOpened: bottomEdge.opened && bottomEdge.fullLoaded47 readonly property bool bottomEdgePageOpened: bottomEdge.opened && bottomEdge.fullLoaded
47 readonly property bool isEmpty: (contactList.count === 0)48 readonly property bool isEmpty: (contactList.count === 0)
@@ -87,6 +88,12 @@
8788
88 function showContact(contact)89 function showContact(contact)
89 {90 {
91 var currentContact = contactList.listModel.contacts[contactList.currentIndex]
92 if (currentContact && contactViewPage && contactViewPage.contact && (contactViewPage.contact.contactId === currentContact.contactId)) {
93 console.debug("Skip show contact")
94 return
95 }
96
90 // go back to normal state if not searching97 // go back to normal state if not searching
91 if ((state !== "searching") &&98 if ((state !== "searching") &&
92 (state !== "vcardImported")) {99 (state !== "vcardImported")) {
@@ -138,14 +145,12 @@
138145
139 function moveListToContact(contact)146 function moveListToContact(contact)
140 {147 {
141 // skipt it if searching or importing contacts148 if ((state !== "searching") &&
142 if ((state === "searching") ||149 (state !== "vcardImported")) {
143 (state === "vcardImported")) {150 mainPage.state = "default"
144 return
145 }151 }
146152
147 contactIndex = contact153 contactIndex = contact
148 mainPage.state = "default"
149 // this means a new contact was created154 // this means a new contact was created
150 if (mainPage.allowToQuit) {155 if (mainPage.allowToQuit) {
151 application.goBackToSourceApp()156 application.goBackToSourceApp()
@@ -163,22 +168,53 @@
163 contactList.currentIndex = -1;168 contactList.currentIndex = -1;
164 mainPage.contactEditorPage = editorPage;169 mainPage.contactEditorPage = editorPage;
165 pageStack.addPageToNextColumn(mainPage, editorPage);170 pageStack.addPageToNextColumn(mainPage, editorPage);
166 editorPage.ready();
167 editorPage.contactSaved.connect(onNewContactSaved);171 editorPage.contactSaved.connect(onNewContactSaved);
172 editorPage.enabled = true
168 }173 }
169174
170 function onNewContactSaved(contact) {175 function onNewContactSaved(contact) {
176 _creatingContact = true
177 moveListToContact(contact)
171 if (pageStack.columns > 1) {178 if (pageStack.columns > 1) {
172 showContact(contact);179 showContact(contact);
173 }180 }
174 }181 }
175182
183 // Delay contact fetch for some msecs (check 'fetchNewContactTimer')
184 function delayFetchContact()
185 {
186 fetchNewContactTimer.restart()
187 }
188
189 function fetchContact()
190 {
191 if ((contactList.currentIndex >= 0) && (pageStack.columns > 1)) {
192 var currentContact = contactList.listModel.contacts[contactList.currentIndex]
193 if (contactViewPage && contactViewPage.contact && (contactViewPage.contact.contactId === currentContact.contactId))
194 return
195
196 contactList.view._fetchContact(contactList.currentIndex, currentContact)
197 }
198 }
199
200 // This timer is to avoid fetch unecessary contact if the user select the contacts too fast
201 // while navigating on contact list with keyboard
202 Timer {
203 id: fetchNewContactTimer
204
205 interval: 300
206 repeat: false
207 onTriggered: mainPage.fetchContact()
208 }
209
176 title: i18n.tr("Contacts")210 title: i18n.tr("Contacts")
177
178 flickable: null211 flickable: null
212
179 ContactsUI.ContactListView {213 ContactsUI.ContactListView {
180 id: contactList214 id: contactList
181 objectName: "contactListView"215 objectName: "contactListView"
216
217 focus: true
182 showImportOptions: !mainPage.pickMode &&218 showImportOptions: !mainPage.pickMode &&
183 mainPage.newPhoneToAdd === "" &&219 mainPage.newPhoneToAdd === "" &&
184 (!mainPage.contactEditorPage || !mainPage.contactEditorPage.active)220 (!mainPage.contactEditorPage || !mainPage.contactEditorPage.active)
@@ -188,10 +224,11 @@
188 bottom: keyboard.top224 bottom: keyboard.top
189 right: parent.right225 right: parent.right
190 }226 }
227 currentIndex: 0
191 filterTerm: searchField.text228 filterTerm: searchField.text
192 multiSelectionEnabled: true229 multiSelectionEnabled: true
193 multipleSelection: (mainPage.pickMode && mainPage.pickMultipleContacts) || !mainPage.pickMode230 multipleSelection: (mainPage.pickMode && mainPage.pickMultipleContacts) || !mainPage.pickMode
194 highlightSelected: pageStack.columns > 1231 highlightSelected: application.usingKeyboard && !mainPage._creatingContact
195 onAddContactClicked: mainPage.createContactWithPhoneNumber(label)232 onAddContactClicked: mainPage.createContactWithPhoneNumber(label)
196 onAddNewContactClicked: mainPage.createContactWithPhoneNumber(mainPage.newPhoneToAdd)233 onAddNewContactClicked: mainPage.createContactWithPhoneNumber(mainPage.newPhoneToAdd)
197234
@@ -210,25 +247,71 @@
210 }247 }
211248
212 onError: pageStack.contactModelError(error)249 onError: pageStack.contactModelError(error)
250 onActiveFocusChanged: {
251 if (activeFocus && (contactList.currentIndex === -1)) {
252 contactList.currentIndex = 0
253 }
254 }
255 onCountChanged: {
256 if (mainPage.active &&
257 (pageStack.columns > 1) &&
258 (contactList.currentIndex === -1)) {
259 contactList.currentIndex = 0
260 }
261 mainPage.delayFetchContact()
262 }
263 onCurrentIndexChanged: {
264 if (!mainPage.contactIndex)
265 mainPage.delayFetchContact()
266 }
267
268 Keys.onReturnPressed: {
269 var currentContact = contactList.listModel.contacts[contactList.currentIndex]
270 if (contactViewPage && contactViewPage.contact && (contactViewPage.contact.contactId === currentContact.contactId))
271 return
272
273 contactList.view._fetchContact(contactList.currentIndex, currentContact)
274 }
275
276 //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822
277 //because of that we need this
278 Keys.onRightPressed: {
279 // only move focus away when in edit mode
280 if (mainPage.contactEditorPage) {
281 var next = pageStack._nextItemInFocusChain(view, true)
282 if (next === searchField) {
283 pageStack._nextItemInFocusChain(next, true)
284 }
285 }
286 }
287 Keys.onTabPressed: {
288 var next = pageStack._nextItemInFocusChain(view, true)
289 if (next === searchField) {
290 pageStack._nextItemInFocusChain(next, true)
291 }
292 }
213 }293 }
214294
295
296
215 TextField {297 TextField {
216 id: searchField298 id: searchField
217299
300 //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822
301 //because of that we need this
302 readonly property bool _allowFocus: true
303
218 anchors {304 anchors {
219 left: parent.left305 left: parent ? parent.left : undefined
220 right: parent.right306 right: parent ? parent.right : undefined
221 rightMargin: units.gu(2)307 rightMargin: units.gu(2)
222 }308 }
223 focus: false309
224 visible: false310 visible: false
225 onTextChanged: contactList.currentIndex = -1
226 inputMethodHints: Qt.ImhNoPredictiveText311 inputMethodHints: Qt.ImhNoPredictiveText
227 placeholderText: i18n.tr("Search...")312 placeholderText: i18n.tr("Search...")
228 onFocusChanged: {313 Keys.onTabPressed: contactList.forceActiveFocus()
229 if (visible && focus)314 Keys.onDownPressed: contactList.forceActiveFocus()
230 searchField.forceActiveFocus()
231 }
232 }315 }
233316
234 Connections {317 Connections {
@@ -267,6 +350,8 @@
267 text: i18n.tr("Search")350 text: i18n.tr("Search")
268 iconName: "search"351 iconName: "search"
269 visible: !mainPage.isEmpty352 visible: !mainPage.isEmpty
353 enabled: mainPage.state === "default"
354 shortcut: "Ctrl+F"
270 onTriggered: {355 onTriggered: {
271 mainPage.state = (mainPage.state === "newphone" ? "newphoneSearching" : "searching")356 mainPage.state = (mainPage.state === "newphone" ? "newphoneSearching" : "searching")
272 contactList.showAllContacts()357 contactList.showAllContacts()
@@ -289,9 +374,21 @@
289 Action {374 Action {
290 text: i18n.tr("Settings")375 text: i18n.tr("Settings")
291 iconName: "settings"376 iconName: "settings"
292 onTriggered: pageStack.addPageToNextColumn(mainPage,377 onTriggered:{
293 Qt.resolvedUrl("./Settings/SettingsPage.qml"),378 var incubator = pageStack.addPageToNextColumn(mainPage,
294 {"contactListModel": contactList.listModel})379 Qt.resolvedUrl("./Settings/SettingsPage.qml"),
380 {"contactListModel": contactList.listModel})
381 incubator.onStatusChanged = function(status) {
382 if (status === Component.Ready) {
383 incubator.object.onActiveChanged.connect(function(active) {
384 if (!incubator.object.active) {
385 mainPage.delayFetchContact()
386 contactList.forceActiveFocus()
387 }
388 })
389 }
390 }
391 }
295 }392 }
296 ]393 ]
297 PropertyChanges {394 PropertyChanges {
@@ -305,6 +402,10 @@
305 target: searchField402 target: searchField
306 text: ""403 text: ""
307 }404 }
405 PropertyChanges {
406 target: bottomEdge
407 enabled: true
408 }
308 },409 },
309 PageHeadState {410 PageHeadState {
310 id: searchingState411 id: searchingState
@@ -313,10 +414,12 @@
313 backAction: Action {414 backAction: Action {
314 iconName: "back"415 iconName: "back"
315 text: i18n.tr("Cancel")416 text: i18n.tr("Cancel")
417 enabled: mainPage.state === "searching" && !mainPage.contactEditorPage && mainPage.active
418 shortcut: "Esc"
316 onTriggered: {419 onTriggered: {
317 contactList.forceActiveFocus()
318 mainPage.head.sections.selectedIndex = 0420 mainPage.head.sections.selectedIndex = 0
319 mainPage.state = (mainPage.state === "newphoneSearching" ? "newphone" : "default")421 mainPage.state = (mainPage.state === "newphoneSearching" ? "newphone" : "default")
422 contactList.forceActiveFocus()
320 }423 }
321 }424 }
322425
@@ -349,6 +452,8 @@
349 backAction: Action {452 backAction: Action {
350 text: i18n.tr("Cancel selection")453 text: i18n.tr("Cancel selection")
351 iconName: "back"454 iconName: "back"
455 enabled: mainPage.state === "selection"
456 shortcut: "Esc"
352 onTriggered: contactList.cancelSelection()457 onTriggered: contactList.cancelSelection()
353 }458 }
354 actions: [459 actions: [
@@ -495,8 +600,11 @@
495 if (active && contactList.showAddNewButton) {600 if (active && contactList.showAddNewButton) {
496 contactList.positionViewAtBeginning()601 contactList.positionViewAtBeginning()
497 }602 }
603
498 if (active && (state === "searching")) {604 if (active && (state === "searching")) {
499 searchField.forceActiveFocus()605 searchField.forceActiveFocus()
606 } else if (active) {
607 contactList.forceActiveFocus()
500 }608 }
501 }609 }
502610
@@ -712,18 +820,19 @@
712 var newContact = ContactsJS.createEmptyContact("", mainPage);820 var newContact = ContactsJS.createEmptyContact("", mainPage);
713 createObjectAsynchronously(Qt.resolvedUrl("ABContactEditorPage.qml"),821 createObjectAsynchronously(Qt.resolvedUrl("ABContactEditorPage.qml"),
714 {model: contactList.listModel,822 {model: contactList.listModel,
823 enabled: false,
715 contact: newContact,824 contact: newContact,
716 initialFocusSection: "name"},825 initialFocusSection: "name"},
717 showContactEditorPage);826 showContactEditorPage);
718 }827 }
719828
720 anchors.fill: parent829 anchors.fill: parent
721 contentComponent: pageStack.columns == 1 ? editorPageBottomEdge : emptyContact830 contentComponent: pageStack.columns === 1 ? editorPageBottomEdge : emptyContact
722 flickable: contactList831 flickable: contactList
723 iconName: "contact-new"832 iconName: "contact-new"
724 enabled: !contactList.isInSelectionMode
725 backGroundEffectEnabled: pageStack.columns === 1833 backGroundEffectEnabled: pageStack.columns === 1
726834
835 onBottomEdgeLoaded: contactList.forceActiveFocus()
727 onOpenBegin: {836 onOpenBegin: {
728 contactList.prepareNewContact = true;837 contactList.prepareNewContact = true;
729 contactList.positionViewAtBeginning();838 contactList.positionViewAtBeginning();
@@ -732,7 +841,6 @@
732 }841 }
733 }842 }
734 onOpenEnd: {843 onOpenEnd: {
735 bottomEdge.visible = false;
736 contactList.showNewContact = true;844 contactList.showNewContact = true;
737 if (pageStack.columns <= 1) {845 if (pageStack.columns <= 1) {
738 showContactEditorPage(bottomEdge.content);846 showContactEditorPage(bottomEdge.content);
@@ -746,10 +854,13 @@
746854
747 Connections {855 Connections {
748 target: mainPage.contactModel856 target: mainPage.contactModel
857
749 onContactsChanged: {858 onContactsChanged: {
750 if (contactIndex) {859 if (contactIndex) {
751 contactList.positionViewAtContact(mainPage.contactIndex)860 contactList.positionViewAtContact(mainPage.contactIndex)
752 mainPage.contactIndex = null861 mainPage.contactIndex = null
862 // at this point the operation has finished already
863 mainPage._creatingContact = false
753 }864 }
754 }865 }
755 onImportCompleted: {866 onImportCompleted: {
@@ -779,20 +890,33 @@
779 }890 }
780891
781 Connections {892 Connections {
782 target: mainPage.contactViewPage893 id: contactViewPageConnections
783 onEditContact: {894
784 openEditPage(editPageProperties, mainPage.contactViewPage);895 ignoreUnknownSignals: true
896 onEditContact: openEditPage(editPageProperties, mainPage.contactViewPage);
897 onActiveChanged: {
898 if (mainPage.contactViewPage &&
899 !mainPage.contactViewPage.active &&
900 (mainPage.contactEditorPage == null)) { // not editing
901 mainPage.contactViewPage = null
902 }
785 }903 }
786 }904 }
787905
788 Connections {906 Connections {
789 target: mainPage.contactEditorPage907 id: contactEditorPageConnections
908
909 ignoreUnknownSignals: true
790 onActiveChanged: {910 onActiveChanged: {
791 if (!mainPage.contactEditorPage.active) {911 if (mainPage.contactEditorPage && !mainPage.contactEditorPage.active) {
792 contactList.prepareNewContact = false;912 contactList.prepareNewContact = false;
793 contactList.showNewContact = false;913 contactList.showNewContact = false;
794 bottomEdge.visible = true;
795 bottomEdge.close();914 bottomEdge.close();
915 mainPage.contactEditorPage = null
916 contactList.forceActiveFocus()
917 bottomEdge.enabled = true
918 } else if (mainPage.contactEditorPage && !mainPage.contactEditorPage.active) {
919 bottomEdge.enabled = false
796 }920 }
797 }921 }
798 }922 }
799923
=== modified file 'src/imports/ABContactViewPage.qml'
--- src/imports/ABContactViewPage.qml 2015-10-28 01:08:39 +0000
+++ src/imports/ABContactViewPage.qml 2015-12-16 18:38:23 +0000
@@ -30,6 +30,16 @@
30 property string addPhoneToContact: ""30 property string addPhoneToContact: ""
31 signal editContact(var editPageProperties)31 signal editContact(var editPageProperties)
3232
33 // Override Action buttom to add shortcut to it
34 Action {
35 id: backAction
36
37 name: "cancel"
38 enabled: root.active && root.enabled && (pageStack.columns === 1)
39 shortcut: "Esc"
40 onTriggered: pageStack.removePages(root)
41 }
42
33 head.actions: [43 head.actions: [
34 Action {44 Action {
35 objectName: "share"45 objectName: "share"
@@ -50,6 +60,8 @@
5060
51 text: i18n.tr("Edit")61 text: i18n.tr("Edit")
52 iconName: "edit"62 iconName: "edit"
63 enabled: root.active
64 shortcut: "Ctrl+e"
53 onTriggered: {65 onTriggered: {
54 editContact({model: root.model,66 editContact({model: root.model,
55 contact: root.contact});67 contact: root.contact});
5668
=== modified file 'src/imports/BottomEdge.qml'
--- src/imports/BottomEdge.qml 2015-11-19 01:02:12 +0000
+++ src/imports/BottomEdge.qml 2015-12-16 18:38:23 +0000
@@ -32,7 +32,7 @@
32 signal openBegin32 signal openBegin
33 signal openEnd33 signal openEnd
34 signal clicked34 signal clicked
35 visible: enabled35 signal bottomEdgeLoaded
3636
37 function open() {37 function open() {
38 bottomEdge.state = "expanded";38 bottomEdge.state = "expanded";
@@ -42,6 +42,13 @@
42 bottomEdge.state = "collapsed";42 bottomEdge.state = "collapsed";
43 }43 }
4444
45 Action {
46 text: i18n.tr("New contact")
47 enabled: bottomEdge.visible
48 shortcut: "Ctrl+N"
49 onTriggered: bottomEdge.clicked()
50 }
51
45 Rectangle {52 Rectangle {
46 id: darkBg53 id: darkBg
4754
@@ -90,6 +97,10 @@
90 sourceComponent: bottomEdge.contentComponent97 sourceComponent: bottomEdge.contentComponent
91 asynchronous: true98 asynchronous: true
92 active: bottomEdge.enabled99 active: bottomEdge.enabled
100 onStatusChanged: {
101 if (status === Loader.Ready)
102 bottomEdge.bottomEdgeLoaded()
103 }
93 }104 }
94 }105 }
95106
@@ -318,4 +329,10 @@
318 dragDirection = yOffset > 0 ? "BottomToTop" : "TopToBottom";329 dragDirection = yOffset > 0 ? "BottomToTop" : "TopToBottom";
319 }330 }
320 }331 }
332
333 Binding {
334 target: bottomEdge
335 property: 'visible'
336 value: bottomEdge.enabled && !bottomEdge.opened
337 }
321}338}
322339
=== modified file 'src/imports/MainWindow.qml'
--- src/imports/MainWindow.qml 2015-10-26 13:18:11 +0000
+++ src/imports/MainWindow.qml 2015-12-16 18:38:23 +0000
@@ -105,7 +105,6 @@
105 AdaptivePageLayout {105 AdaptivePageLayout {
106 id: mainStack106 id: mainStack
107107
108 primaryPage: contactPage
109 property var contactListPage: null108 property var contactListPage: null
110109
111 function resetStack()110 function resetStack()
@@ -113,6 +112,28 @@
113 mainStack.removePages(primaryPage);112 mainStack.removePages(primaryPage);
114 }113 }
115114
115 function _nextItemInFocusChain(item, foward)
116 {
117 var next = item.nextItemInFocusChain(foward)
118 var first = next
119 //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822
120 //because of that we need this
121 while (!next || !next.hasOwnProperty("_allowFocus")) {
122 next = next.nextItemInFocusChain(foward)
123
124 // avoid loop
125 if (next === first) {
126 next = null
127 break
128 }
129 }
130 if (next) {
131 next.forceActiveFocus()
132 }
133 return next
134 }
135
136 primaryPage: contactPage
116 onContactListPageChanged: {137 onContactListPageChanged: {
117 if (contentHubLoader.status === Loader.Ready) {138 if (contentHubLoader.status === Loader.Ready) {
118 contentHubLoader.item.pageStack = mainStack139 contentHubLoader.item.pageStack = mainStack
@@ -141,6 +162,7 @@
141 }162 }
142 }163 }
143 ]164 ]
165
144 }166 }
145167
146 ABContactListPage {168 ABContactListPage {
@@ -196,6 +218,10 @@
196218
197 // If application was called from uri handler and lost the focus reset the app to normal state219 // If application was called from uri handler and lost the focus reset the app to normal state
198 onAppActiveChanged: {220 onAppActiveChanged: {
221 if (appActive) {
222 mainStack.forceActiveFocus()
223 }
224
199 if (!appActive && mainStack.contactListPage) {225 if (!appActive && mainStack.contactListPage) {
200 mainStack.contactListPage.returnToNormalState()226 mainStack.contactListPage.returnToNormalState()
201 }227 }
202228
=== modified file 'src/imports/Settings/SettingsPage.qml'
--- src/imports/Settings/SettingsPage.qml 2015-12-11 13:14:05 +0000
+++ src/imports/Settings/SettingsPage.qml 2015-12-16 18:38:23 +0000
@@ -1,4 +1,4 @@
1/*1/*
2 * Copyright (C) 2015 Canonical, Ltd.2 * Copyright (C) 2015 Canonical, Ltd.
3 *3 *
4 * This program is free software; you can redistribute it and/or modify4 * This program is free software; you can redistribute it and/or modify
@@ -64,15 +64,66 @@
64 onCountChanged: numberFlickable.contentY = 064 onCountChanged: numberFlickable.contentY = 0
65 }65 }
66 ListItem.Standard {66 ListItem.Standard {
67 id: addGoogleAccountItem
68
69 function activate()
70 {
71 onlineAccountsHelper.setupExec()
72 }
73
67 text: i18n.tr("Add Google account")74 text: i18n.tr("Add Google account")
68 progression: true75 progression: true
69 onClicked: onlineAccountsHelper.setupExec()76
77 onClicked: addGoogleAccountItem.activate()
78 Keys.onRightPressed: addGoogleAccountItem.activate()
79 Keys.onDownPressed: {
80 if (importFromSimItem.enabled) {
81 importFromSimItem.forceActiveFocus()
82 }
83 }
84
85 // Selection visual feedback
86 //
87 // FIXME: Using a private property here. This uses the old list item and the only way to change the text
88 // color is with this property.
89 // We should remove it when update the app to the new ListItem.
90 __foregroundColor: (activeFocus && (pageStack.columns > 1)) ? Theme.palette.normal.foregroundText :
91 Theme.palette.normal.foreground
92 Rectangle {
93 color: UbuntuColors.orange
94 anchors.fill: parent
95 visible:addGoogleAccountItem.activeFocus
96 z: -1
97 }
70 }98 }
71 ListItem.Standard {99 ListItem.Standard {
100 id: importFromSimItem
101
102 function activate()
103 {
104 pageStack.addPageToCurrentColumn(root, simCardImportPageComponent)
105 }
106
72 text: i18n.tr("Import from SIM")107 text: i18n.tr("Import from SIM")
73 progression: true108 progression: true
74 onClicked: pageStack.addPageToCurrentColumn(root, simCardImportPageComponent)
75 enabled: (simList.sims.length > 0) && (simList.present.length > 0)109 enabled: (simList.sims.length > 0) && (simList.present.length > 0)
110 onClicked: importFromSimItem.activate()
111 Keys.onRightPressed: importFromSimItem.activate()
112 Keys.onUpPressed: addGoogleAccountItem.forceActiveFocus()
113
114 // selection visual feedback
115 //
116 // FIXME: Using a private property here. This uses the old list item and the only way to change the text
117 // color is with this property.
118 // We should remove it when update the app to the new ListItem.
119 __foregroundColor: (activeFocus && (pageStack.columns > 1)) ? Theme.palette.normal.foregroundText :
120 Theme.palette.normal.foreground
121 Rectangle {
122 color: UbuntuColors.orange
123 anchors.fill: parent
124 visible: importFromSimItem.activeFocus
125 z: -1
126 }
76 }127 }
77 SettingsDefaultSyncTarget {128 SettingsDefaultSyncTarget {
78 id: defaultSyncTarget129 id: defaultSyncTarget
@@ -97,8 +148,13 @@
97 }148 }
98 }149 }
99150
151 Keys.onDownPressed: addGoogleAccountItem.forceActiveFocus()
152 Keys.onRightPressed: addGoogleAccountItem.forceActiveFocus()
153 Keys.onLeftPressed: pageStack.removePages(root)
154 Keys.onEscapePressed: pageStack.removePages(root)
100 onActiveChanged: {155 onActiveChanged: {
101 if (active) {156 if (active) {
157 root.forceActiveFocus()
102 defaultSyncTarget.update()158 defaultSyncTarget.update()
103 }159 }
104 }160 }
105161
=== modified file 'src/imports/Ubuntu/AddressBook/Base/ContactDetailBase.qml'
--- src/imports/Ubuntu/AddressBook/Base/ContactDetailBase.qml 2015-10-26 13:18:11 +0000
+++ src/imports/Ubuntu/AddressBook/Base/ContactDetailBase.qml 2015-12-16 18:38:23 +0000
@@ -18,15 +18,19 @@
18import QtContacts 5.0 as QtContacts18import QtContacts 5.0 as QtContacts
19import Ubuntu.Components.ListItems 1.3 as ListItem19import Ubuntu.Components.ListItems 1.3 as ListItem
2020
21ListItem.Empty {21FocusScope {
22 id: root22 id: root
23 objectName: detail ? "base_" + detailToString(detail.type, -1) + "_" + index : ""23 objectName: detail ? "base_" + detailToString(detail.type, -1) + "_" + index : ""
2424
25 property variant action: null
25 property QtObject contact: null26 property QtObject contact: null
26 property QtObject detail: null27 property QtObject detail: null
27 property variant fields: null28 property variant fields: null
28 // help to test used to retrieve the correct element29 // help to test used to retrieve the correct element
29 property int index: -130 property int index: -1
31 property alias highlightOnFocus: highlight.visible
32
33 signal clicked()
3034
31 function detailToString(detail, field)35 function detailToString(detail, field)
32 {36 {
@@ -98,13 +102,23 @@
98 }102 }
99 }103 }
100104
101 highlightWhenPressed: false
102 showDivider: false
103
104 Rectangle {105 Rectangle {
105 anchors.fill: parent106 id: highlight
106 opacity: 0.1107
107 visible: root.selected108 anchors.fill: parent
108 z: 100109 visible: root.activeFocus
110 color: Theme.palette.selected.background
111 z: -1
112 }
113
114 MouseArea {
115 anchors.fill: parent
116
117 onClicked: {
118 if (action) {
119 action.triggered(action)
120 }
121 root.clicked()
122 }
109 }123 }
110}124}
111125
=== modified file 'src/imports/Ubuntu/AddressBook/Base/ContactDetailGroupBase.qml'
--- src/imports/Ubuntu/AddressBook/Base/ContactDetailGroupBase.qml 2015-10-26 13:18:11 +0000
+++ src/imports/Ubuntu/AddressBook/Base/ContactDetailGroupBase.qml 2015-12-16 18:38:23 +0000
@@ -33,6 +33,7 @@
33 property int minimumHeight: 033 property int minimumHeight: 0
34 property bool loaded: false34 property bool loaded: false
35 property bool showEmpty: true35 property bool showEmpty: true
36 property bool forceFocusOnFieldCreation: false
3637
37 signal newFieldAdded(var index)38 signal newFieldAdded(var index)
3839
@@ -146,7 +147,7 @@
146 newFields.push(detailItem.item)147 newFields.push(detailItem.item)
147 root.newFieldAdded(detailItem.item)148 root.newFieldAdded(detailItem.item)
148 root.inputFields = newFields149 root.inputFields = newFields
149 if (root.loaded) {150 if (root.loaded && root.forceFocusOnFieldCreation) {
150 item.forceActiveFocus()151 item.forceActiveFocus()
151 }152 }
152 }153 }
153154
=== modified file 'src/imports/Ubuntu/AddressBook/Base/RemoveContactsDialog.qml'
--- src/imports/Ubuntu/AddressBook/Base/RemoveContactsDialog.qml 2015-10-26 13:18:11 +0000
+++ src/imports/Ubuntu/AddressBook/Base/RemoveContactsDialog.qml 2015-12-16 18:38:23 +0000
@@ -53,6 +53,7 @@
53 }53 }
5454
55 Button {55 Button {
56 id: acceptButton
56 objectName: "removeContactsDialog.Yes"57 objectName: "removeContactsDialog.Yes"
57 anchors {58 anchors {
58 left: parent.left59 left: parent.left
@@ -61,10 +62,14 @@
61 }62 }
62 text: i18n.dtr("address-book-app", "Yes")63 text: i18n.dtr("address-book-app", "Yes")
63 color: UbuntuColors.green64 color: UbuntuColors.green
64 onClicked: accepted()65 action: Action {
66 shortcut: "return"
67 onTriggered: accepted()
68 }
65 }69 }
6670
67 Button {71 Button {
72 id: cancelButton
68 objectName: "removeContactsDialog.No"73 objectName: "removeContactsDialog.No"
69 anchors {74 anchors {
70 left: parent.left75 left: parent.left
@@ -73,6 +78,9 @@
73 }78 }
74 text: i18n.dtr("address-book-app", "No")79 text: i18n.dtr("address-book-app", "No")
75 color: UbuntuColors.red80 color: UbuntuColors.red
76 onClicked: canceled()81 action: Action {
82 shortcut: "esc"
83 onTriggered: canceled()
84 }
77 }85 }
78}86}
7987
=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAvatarEditor.qml'
--- src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAvatarEditor.qml 2015-10-29 18:11:08 +0000
+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAvatarEditor.qml 2015-12-16 18:38:23 +0000
@@ -68,6 +68,7 @@
68 detail: contact ? contact.detail(ContactDetail.Avatar) : null68 detail: contact ? contact.detail(ContactDetail.Avatar) : null
69 implicitHeight: units.gu(8)69 implicitHeight: units.gu(8)
70 implicitWidth: units.gu(8)70 implicitWidth: units.gu(8)
71 highlightOnFocus: false
7172
72 UbuntuShape {73 UbuntuShape {
73 id: avatar74 id: avatar
7475
=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailGroupWithTypeEditor.qml'
--- src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailGroupWithTypeEditor.qml 2015-10-26 13:18:11 +0000
+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailGroupWithTypeEditor.qml 2015-12-16 18:38:23 +0000
@@ -98,29 +98,19 @@
98 return changed98 return changed
99 }99 }
100100
101 headerDelegate: Empty {101 forceFocusOnFieldCreation: true
102 headerDelegate: Label {
102 id: header103 id: header
103 highlightWhenPressed: false104
104105 width: root.width - units.gu(4)
105 width: root.width106 x: units.gu(2)
106 height: units.gu(5)107 height: units.gu(4)
107 // disable listview mouse area108 text: root.title
108 __mouseArea.visible: false109 // style
109 divider.anchors.leftMargin: units.gu(2)110 fontSize: "medium"
110 divider.anchors.rightMargin: units.gu(2)111 verticalAlignment: Text.AlignVCenter
111112 ThinDivider {
112 Label {113 anchors.bottom: parent.bottom
113 anchors {
114 verticalCenter: parent.verticalCenter
115 left: parent.left
116 right: parent.right
117 margins: units.gu(2)
118 }
119
120 text: root.title
121
122 // style
123 fontSize: "medium"
124 }114 }
125 }115 }
126116
@@ -157,7 +147,6 @@
157 fields: root.fields147 fields: root.fields
158 height: implicitHeight148 height: implicitHeight
159 width: root.width149 width: root.width
160 selected: activeFocus
161150
162 inputMethodHints: root.inputMethodHints151 inputMethodHints: root.inputMethodHints
163 onDetailChanged: updateCombo(false)152 onDetailChanged: updateCombo(false)
164153
=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailNameEditor.qml'
--- src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailNameEditor.qml 2015-10-26 13:18:11 +0000
+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailNameEditor.qml 2015-12-16 18:38:23 +0000
@@ -55,6 +55,7 @@
55 spacing: units.gu(1)55 spacing: units.gu(1)
56 detail: root.contact ? root.contact.name : null56 detail: root.contact ? root.contact.name : null
57 fields: [ Name.FirstName, Name.LastName ]57 fields: [ Name.FirstName, Name.LastName ]
58 highlightOnFocus: false
5859
59 fieldDelegate: TextInputDetail {60 fieldDelegate: TextInputDetail {
60 id: textInputDetail61 id: textInputDetail
6162
=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailSyncTargetEditor.qml'
--- src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailSyncTargetEditor.qml 2015-12-11 16:43:39 +0000
+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailSyncTargetEditor.qml 2015-12-16 18:38:23 +0000
@@ -75,6 +75,7 @@
7575
76 detail: root.contact ? contact.detail(ContactDetail.SyncTarget) : null76 detail: root.contact ? contact.detail(ContactDetail.SyncTarget) : null
77 implicitHeight: root.isNewContact && sources.model && (sources.model.count > 1) ? myHeight : 077 implicitHeight: root.isNewContact && sources.model && (sources.model.count > 1) ? myHeight : 0
78 visible: height > 0
7879
79 ContactModel {80 ContactModel {
80 id: sourceModel81 id: sourceModel
@@ -188,8 +189,12 @@
188 ThinDivider {189 ThinDivider {
189 id: divider190 id: divider
190191
191 anchors.top: label.bottom192 anchors {
192 }193 top: label.bottom
194 leftMargin: units.gu(2)
195 rightMargin: units.gu(2)
196 }
197 }
193198
194 OptionSelector {199 OptionSelector {
195 id: sources200 id: sources
196201
=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailWithTypeEditor.qml'
--- src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailWithTypeEditor.qml 2015-10-26 13:18:11 +0000
+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailWithTypeEditor.qml 2015-12-16 18:38:23 +0000
@@ -70,7 +70,6 @@
70 }70 }
7171
72 // disable listview mouse area72 // disable listview mouse area
73 __mouseArea.visible: false
74 enabled: root.detail ? !root.detail.readOnly : false73 enabled: root.detail ? !root.detail.readOnly : false
75 implicitHeight: detailTypeSelector.height + fieldValues.height + units.gu(2)74 implicitHeight: detailTypeSelector.height + fieldValues.height + units.gu(2)
76 opacity: enabled ? 1.0 : 0.575 opacity: enabled ? 1.0 : 0.5
7776
=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactEditorPage.qml'
--- src/imports/Ubuntu/AddressBook/ContactEditor/ContactEditorPage.qml 2015-10-26 13:18:11 +0000
+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactEditorPage.qml 2015-12-16 18:38:23 +0000
@@ -31,7 +31,6 @@
31 property QtObject model: null31 property QtObject model: null
32 property QtObject activeItem: null32 property QtObject activeItem: null
3333
34
35 property string initialFocusSection: ""34 property string initialFocusSection: ""
36 property var newDetails: []35 property var newDetails: []
3736
@@ -40,9 +39,6 @@
4039
41 signal contactSaved(var contact);40 signal contactSaved(var contact);
4241
43 // priv
44 property bool _edgeReady: false
45
46 function cancel() {42 function cancel() {
47 for (var i = 0; i < contactEditor.newDetails.length; ++i) {43 for (var i = 0; i < contactEditor.newDetails.length; ++i) {
48 contactEditor.contact.removeDetail(contactEditor.newDetails[i])44 contactEditor.contact.removeDetail(contactEditor.newDetails[i])
@@ -105,7 +101,7 @@
105 }101 }
106102
107 function makeMeVisible(item) {103 function makeMeVisible(item) {
108 if (!_edgeReady || !item) {104 if (!enabled || !item) {
109 return105 return
110 }106 }
111107
@@ -133,8 +129,6 @@
133 function ready()129 function ready()
134 {130 {
135 enabled = true131 enabled = true
136 _edgeReady = true
137
138 switch (contactEditor.initialFocusSection)132 switch (contactEditor.initialFocusSection)
139 {133 {
140 case "phones":134 case "phones":
@@ -153,6 +147,7 @@
153 }147 }
154148
155 title: isNewContact ? i18n.dtr("address-book-app", "New contact") : i18n.dtr("address-book-app", "Edit")149 title: isNewContact ? i18n.dtr("address-book-app", "New contact") : i18n.dtr("address-book-app", "Edit")
150 enabled: false
156151
157 Timer {152 Timer {
158 id: focusTimer153 id: focusTimer
@@ -181,7 +176,9 @@
181 contentWidth: parent.width176 contentWidth: parent.width
182177
183 //after add a new field we need to wait for the contentHeight to change to scroll to the correct position178 //after add a new field we need to wait for the contentHeight to change to scroll to the correct position
184 onContentHeightChanged: contactEditor.makeMeVisible(contactEditor.activeItem)179 onContentHeightChanged: {
180 contactEditor.makeMeVisible(contactEditor.activeItem)
181 }
185182
186 Column {183 Column {
187 id: contents184 id: contents
@@ -195,6 +192,7 @@
195 height: childrenRect.height192 height: childrenRect.height
196193
197 Row {194 Row {
195 id: editEditor
198 function save()196 function save()
199 {197 {
200 var avatarSave = avatarEditor.save()198 var avatarSave = avatarEditor.save()
@@ -213,7 +211,7 @@
213 leftMargin: units.gu(2)211 leftMargin: units.gu(2)
214 right: parent.right212 right: parent.right
215 }213 }
216 height: Math.max(avatarEditor.height, nameEditor.height) - units.gu(4)214 height: Math.max(avatarEditor.height, nameEditor.height) - units.gu(2)
217215
218 ContactDetailAvatarEditor {216 ContactDetailAvatarEditor {
219 id: avatarEditor217 id: avatarEditor
@@ -221,6 +219,7 @@
221 contact: contactEditor.contact219 contact: contactEditor.contact
222 height: implicitHeight220 height: implicitHeight
223 width: implicitWidth221 width: implicitWidth
222 anchors.verticalCenter: editEditor.verticalCenter
224 }223 }
225224
226 ContactDetailNameEditor {225 ContactDetailNameEditor {
@@ -232,6 +231,7 @@
232 }231 }
233 }232 }
234233
234
235 ContactDetailPhoneNumbersEditor {235 ContactDetailPhoneNumbersEditor {
236 id: phonesEditor236 id: phonesEditor
237 objectName: "phones"237 objectName: "phones"
@@ -301,8 +301,6 @@
301 left: parent.left301 left: parent.left
302 right: parent.right302 right: parent.right
303 }303 }
304 height: implicitHeight
305
306 onChanged: {304 onChanged: {
307 if (contactEditor.enabled &&305 if (contactEditor.enabled &&
308 !contactEditor.isNewContact &&306 !contactEditor.isNewContact &&
@@ -383,9 +381,13 @@
383 right: parent.right381 right: parent.right
384 margins: units.gu(2)382 margins: units.gu(2)
385 }383 }
386 onClicked: {384 action: Action {
387 var dialog = PopupUtils.open(removeContactDialog, null)385 enabled: contactEditor.active && deleteButton.visible
388 dialog.contacts = [contactEditor.contact]386 shortcut: "Ctrl+Delete"
387 onTriggered: {
388 var dialog = PopupUtils.open(removeContactDialog, null)
389 dialog.contacts = [contactEditor.contact]
390 }
389 }391 }
390 }392 }
391393
@@ -410,8 +412,8 @@
410 }412 }
411 }413 }
412414
413 Component.onCompleted: {415 onActiveChanged: {
414 if (!enabled) {416 if (!active) {
415 return417 return
416 }418 }
417419
@@ -475,10 +477,14 @@
475 }477 }
476478
477 // hide virtual keyboard if necessary479 // hide virtual keyboard if necessary
478 Component.onCompleted: Qt.inputMethod.hide()480 Component.onCompleted: {
481 contactEditor.enabled = false
482 Qt.inputMethod.hide()
483 }
479484
480 // WORKAROUND: SDK element crash if pop the page where the dialog was created485 // WORKAROUND: SDK element crash if pop the page where the dialog was created
481 Component.onDestruction: {486 Component.onDestruction: {
487 contactEditor.enabled = true
482 if (popPages) {488 if (popPages) {
483 if (contactEditor.pageStack.removePages) {489 if (contactEditor.pageStack.removePages) {
484 contactEditor.pageStack.removePages(contactEditor)490 contactEditor.pageStack.removePages(contactEditor)
485491
=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/TextInputDetail.qml'
--- src/imports/Ubuntu/AddressBook/ContactEditor/TextInputDetail.qml 2015-10-26 13:18:11 +0000
+++ src/imports/Ubuntu/AddressBook/ContactEditor/TextInputDetail.qml 2015-12-16 18:38:23 +0000
@@ -25,7 +25,11 @@
25FocusScope {25FocusScope {
26 id: root26 id: root
2727
28 //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822
29 //because of that we need this
30 readonly property bool _allowFocus: true
28 readonly property bool isTextField: true31 readonly property bool isTextField: true
32
29 property QtObject detail33 property QtObject detail
30 property int field: -134 property int field: -1
31 property variant originalValue: root.detail && (root.field >= 0) ? root.detail.value(root.field) : null35 property variant originalValue: root.detail && (root.field >= 0) ? root.detail.value(root.field) : null
@@ -67,6 +71,22 @@
67 PhoneNumberField {71 PhoneNumberField {
68 id: field72 id: field
6973
74 //WORKAROUND: Due the SDK bug #1514822, #1514850 we can not disable focus for some items
75 //because of that we keep the focus only for textFields. This will block the user
76 //to use keyboard on "add-field" combo box and some other functionalities
77 function forceActiveFocusForNextField(keyEvent)
78 {
79 var backward = (keyEvent.modifiers & Qt.ShiftModifier)
80 var next = field.nextItemInFocusChain(!backward)
81 // only focus on TextInputDetails
82 while (!next || !next.hasOwnProperty("isTextField")) {
83 next = next.nextItemInFocusChain(!backward)
84 }
85 if (next) {
86 next.forceActiveFocus()
87 }
88 }
89
70 anchors.fill: parent90 anchors.fill: parent
71 defaultRegion: PhoneUtils.defaultRegion91 defaultRegion: PhoneUtils.defaultRegion
72 autoFormat: false92 autoFormat: false
@@ -93,15 +113,9 @@
93 family: "Ubuntu"113 family: "Ubuntu"
94 pixelSize: activeFocus ? FontUtils.sizeToPixels("large") : FontUtils.sizeToPixels("medium")114 pixelSize: activeFocus ? FontUtils.sizeToPixels("large") : FontUtils.sizeToPixels("medium")
95 }115 }
96 Keys.onReturnPressed: {116
97 var next = field.nextItemInFocusChain(true)117 Keys.onReturnPressed: forceActiveFocusForNextField(event)
98 // only focus on TextInputDetails118 Keys.onTabPressed: forceActiveFocusForNextField(event)
99 while (!next || !next.hasOwnProperty("isTextField")) {119 Keys.onBacktabPressed: forceActiveFocusForNextField(event)
100 next = next.nextItemInFocusChain(true)
101 }
102 if (next) {
103 next.forceActiveFocus()
104 }
105 }
106 }120 }
107}121}
108122
=== modified file 'src/imports/Ubuntu/AddressBook/ContactView/ActionButton.qml'
--- src/imports/Ubuntu/AddressBook/ContactView/ActionButton.qml 2015-10-26 13:18:11 +0000
+++ src/imports/Ubuntu/AddressBook/ContactView/ActionButton.qml 2015-12-16 18:38:23 +0000
@@ -30,5 +30,6 @@
30 anchors.centerIn: parent30 anchors.centerIn: parent
31 height: root.iconSize31 height: root.iconSize
32 width: root.iconSize32 width: root.iconSize
33 color: root.activeFocus ? UbuntuColors.orange : "gray"
33 }34 }
34}35}
3536
=== modified file 'src/imports/Ubuntu/AddressBook/ContactView/BasicFieldView.qml'
--- src/imports/Ubuntu/AddressBook/ContactView/BasicFieldView.qml 2015-10-26 13:18:11 +0000
+++ src/imports/Ubuntu/AddressBook/ContactView/BasicFieldView.qml 2015-12-16 18:38:23 +0000
@@ -27,6 +27,7 @@
27 property variant fields: null27 property variant fields: null
28 property int parentIndex: -128 property int parentIndex: -1
2929
30 activeFocusOnTab: false
30 implicitHeight: typeLabel.height + fieldValues.height + units.gu(2)31 implicitHeight: typeLabel.height + fieldValues.height + units.gu(2)
3132
32 Column {33 Column {
3334
=== modified file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailAvatarView.qml'
--- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailAvatarView.qml 2015-11-16 20:12:41 +0000
+++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailAvatarView.qml 2015-12-16 18:38:23 +0000
@@ -29,6 +29,7 @@
2929
30 implicitHeight: units.gu(12)30 implicitHeight: units.gu(12)
31 implicitWidth: parent.width31 implicitWidth: parent.width
32 activeFocusOnTab: false
3233
33 Connections {34 Connections {
34 id: connections35 id: connections
3536
=== modified file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailGroupWithTypeView.qml'
--- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailGroupWithTypeView.qml 2015-10-26 13:18:11 +0000
+++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailGroupWithTypeView.qml 2015-12-16 18:38:23 +0000
@@ -18,8 +18,7 @@
18import QtContacts 5.0 as QtContacts18import QtContacts 5.0 as QtContacts
1919
20import Ubuntu.Components 1.320import Ubuntu.Components 1.3
21import Ubuntu.Components.ListItems 1.3 as ListItem21import Ubuntu.Components.ListItems 1.3
22
23import Ubuntu.AddressBook.Base 0.122import Ubuntu.AddressBook.Base 0.1
2423
25ContactDetailGroupWithTypeBase {24ContactDetailGroupWithTypeBase {
@@ -29,25 +28,18 @@
29 signal actionTrigerred(string actionName, QtObject detail)28 signal actionTrigerred(string actionName, QtObject detail)
3029
31 showEmpty: false30 showEmpty: false
32 headerDelegate: ListItem.Empty {31 headerDelegate: Label {
33 highlightWhenPressed: false32 id: header
3433
35 divider.anchors.leftMargin: units.gu(2)34 width: root.width - units.gu(4)
36 divider.anchors.rightMargin: units.gu(2)35 x: units.gu(2)
37 width: root.width36 height: units.gu(4)
38 height: units.gu(5)37 text: root.title
39 Label {38 // style
40 anchors {39 fontSize: "medium"
41 verticalCenter: parent.verticalCenter40 verticalAlignment: Text.AlignVCenter
42 left: parent.left41 ThinDivider {
43 right: parent.right42 anchors.bottom: parent.bottom
44 margins: units.gu(2)
45 }
46
47 text: root.title
48
49 // style
50 fontSize: "medium"
51 }43 }
52 }44 }
5345
5446
=== modified file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailNameView.qml'
--- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailNameView.qml 2015-10-26 13:18:11 +0000
+++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailNameView.qml 2015-12-16 18:38:23 +0000
@@ -25,7 +25,7 @@
2525
26 detail: root.contact ? root.contact.name : null26 detail: root.contact ? root.contact.name : null
27 implicitHeight: label.paintedHeight + (label.anchors.margins * 2)27 implicitHeight: label.paintedHeight + (label.anchors.margins * 2)
2828 activeFocusOnTab: false
2929
30 Label {30 Label {
31 id: label31 id: label
3232
=== modified file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailSyncTargetView.qml'
--- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailSyncTargetView.qml 2015-10-26 13:18:11 +0000
+++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailSyncTargetView.qml 2015-12-16 18:38:23 +0000
@@ -50,6 +50,7 @@
50 defaultIcon: "image://theme/contact-group"50 defaultIcon: "image://theme/contact-group"
51 detailType: ContactDetail.SyncTarget51 detailType: ContactDetail.SyncTarget
52 typeModel: null52 typeModel: null
53 activeFocusOnTab: false
5354
54 fields: [ SyncTarget.SyncTarget ]55 fields: [ SyncTarget.SyncTarget ]
5556
@@ -76,7 +77,7 @@
7677
77 height: implicitHeight78 height: implicitHeight
78 width: root.width79 width: root.width
7980 activeFocusOnTab: false
80 onClicked: root.actionTrigerred(root.defaultAction.name, detail)81 onClicked: root.actionTrigerred(root.defaultAction.name, detail)
8182
82 function overrideValue(detail, field)83 function overrideValue(detail, field)
8384
=== modified file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailWithTypeView.qml'
--- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailWithTypeView.qml 2015-10-26 13:18:11 +0000
+++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailWithTypeView.qml 2015-12-16 18:38:23 +0000
@@ -43,6 +43,7 @@
43 return detail.value(field)43 return detail.value(field)
44 }44 }
4545
46 activeFocusOnTab: icon.visible
46 implicitHeight: view.implicitHeight47 implicitHeight: view.implicitHeight
47 onIsReadyChanged: populateValues()48 onIsReadyChanged: populateValues()
4849
@@ -78,5 +79,7 @@
78 width: root.action && (root.action.iconName !== "") ? units.gu(2.5) : 079 width: root.action && (root.action.iconName !== "") ? units.gu(2.5) : 0
79 height: width80 height: width
80 name: root.action ? root.action.iconName : ""81 name: root.action ? root.action.iconName : ""
82 color: root.activeFocus ? UbuntuColors.orange : "gray"
83 visible: width > 0
81 }84 }
82}85}
8386
=== modified file 'src/imports/Ubuntu/Contacts/ContactListView.qml'
--- src/imports/Ubuntu/Contacts/ContactListView.qml 2015-11-16 22:12:29 +0000
+++ src/imports/Ubuntu/Contacts/ContactListView.qml 2015-12-16 18:38:23 +0000
@@ -42,7 +42,7 @@
42 }42 }
43 \endqml43 \endqml
44*/44*/
45Item {45FocusScope {
46 id: root46 id: root
4747
48 readonly property alias view: view48 readonly property alias view: view
@@ -253,6 +253,10 @@
253253
254 property var _busyDialog: null254 property var _busyDialog: null
255255
256 //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822
257 //because of that we need this
258 property bool _allowFocus: true
259
256 /*!260 /*!
257 This handler is called when the selection mode is finished without be canceled261 This handler is called when the selection mode is finished without be canceled
258 */262 */
@@ -372,6 +376,8 @@
372 buteoSync.startSyncByCategory("contacts")376 buteoSync.startSyncByCategory("contacts")
373 }377 }
374378
379 focus: true
380
375 ContactSimpleListView {381 ContactSimpleListView {
376 id: view382 id: view
377383
@@ -624,4 +630,23 @@
624 !view.favouritesIsSelected &&630 !view.favouritesIsSelected &&
625 !isSearching ? sourceFile : ""631 !isSearching ? sourceFile : ""
626 }632 }
633
634 Keys.onUpPressed: {
635 //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822
636 //because of that we need this
637 if (view.currentIndex == 0) {
638 pageStack._nextItemInFocusChain(view, false)
639 } else {
640 view.currentIndex -= 1
641 }
642 }
643 Keys.onDownPressed: {
644 //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822
645 //because of that we need this
646 if (view.currentIndex == (view.count - 1)) {
647 //DO nothing
648 } else {
649 view.currentIndex += 1
650 }
651 }
627}652}
628653
=== modified file 'src/imports/Ubuntu/Contacts/ContactSimpleListView.qml'
--- src/imports/Ubuntu/Contacts/ContactSimpleListView.qml 2015-11-16 22:12:29 +0000
+++ src/imports/Ubuntu/Contacts/ContactSimpleListView.qml 2015-12-16 18:38:23 +0000
@@ -204,7 +204,8 @@
204 */204 */
205 function positionViewAtContact(contact)205 function positionViewAtContact(contact)
206 {206 {
207 positionViewAtIndex(getIndex(contact), ListView.Center)207 currentIndex = getIndex(contact)
208 positionViewAtIndex(currentIndex, ListView.Center)
208 }209 }
209210
210 /*!211 /*!
@@ -213,7 +214,9 @@
213 */214 */
214 function _fetchContact(index, contact)215 function _fetchContact(index, contact)
215 {216 {
216 contactFetch.fetchContact(contact.contactId)217 if (contact) {
218 contactFetch.fetchContact(contact.contactId)
219 }
217 }220 }
218221
219 function _updateSwipeState(item)222 function _updateSwipeState(item)
@@ -235,7 +238,6 @@
235 }238 }
236239
237 highlightFollowsCurrentItem: true240 highlightFollowsCurrentItem: true
238 currentIndex: -1
239 section {241 section {
240 property: showSections ? "contact.tag.tag" : ""242 property: showSections ? "contact.tag.tag" : ""
241 criteria: ViewSection.FirstCharacter243 criteria: ViewSection.FirstCharacter
@@ -255,7 +257,6 @@
255 dirtyModel.restart()257 dirtyModel.restart()
256 }258 }
257259
258 onFlickStarted: view.currentIndex = -1
259 listDelegate: ContactDelegate {260 listDelegate: ContactDelegate {
260 id: contactDelegate261 id: contactDelegate
261262
@@ -270,6 +271,8 @@
270 width: parent.width271 width: parent.width
271 selected: (contactListView.multiSelectionEnabled && contactListView.isSelected(contactDelegate))272 selected: (contactListView.multiSelectionEnabled && contactListView.isSelected(contactDelegate))
272 || (contactListView.highlightSelected && (contactListView.currentIndex == index))273 || (contactListView.highlightSelected && (contactListView.currentIndex == index))
274 selectedColor: contactListView.parent.activeFocus && !contactListView.isInSelectionMode ? UbuntuColors.orange :
275 Theme.palette.selected.background
273 selectionMode: contactListView.isInSelectionMode276 selectionMode: contactListView.isInSelectionMode
274 defaultAvatarUrl: contactListView.defaultAvatarImageUrl277 defaultAvatarUrl: contactListView.defaultAvatarImageUrl
275 isCurrentItem: ListView.isCurrentItem278 isCurrentItem: ListView.isCurrentItem
@@ -371,13 +374,4 @@
371 property int pendingTargetIndex: 0374 property int pendingTargetIndex: 0
372 property variant pendingTargetMode: null375 property variant pendingTargetMode: null
373 }376 }
374
375 Connections {
376 target: Qt.application
377 onActiveChanged: {
378 if (!Qt.application.active) {
379 currentIndex = -1
380 }
381 }
382 }
383}377}
384378
=== modified file 'src/imports/Ubuntu/Contacts/FastScroll.qml'
--- src/imports/Ubuntu/Contacts/FastScroll.qml 2015-10-26 13:18:11 +0000
+++ src/imports/Ubuntu/Contacts/FastScroll.qml 2015-12-16 18:38:23 +0000
@@ -71,19 +71,11 @@
71 }71 }
72 }72 }
7373
74 Connections {
75 target: listView
76 onCurrentIndexChanged: {
77 if (currentIndex != -1) {
78 rail.opacity = 0.0
79 }
80 }
81 }
8274
83 Rectangle {75 Rectangle {
84 id: magnified76 id: magnified
8577
86 color: Theme.palette.normal.overlay78 color: Theme.palette.normal.foreground
87 radius: height * 0.379 radius: height * 0.3
88 height: pinSize * 280 height: pinSize * 2
89 width: height81 width: height
@@ -99,6 +91,7 @@
99 }91 }
10092
101 Label {93 Label {
94 color: Theme.palette.normal.foregroundText
102 anchors.fill: parent95 anchors.fill: parent
103 horizontalAlignment: Text.AlignHCenter96 horizontalAlignment: Text.AlignHCenter
104 verticalAlignment: Text.AlignVCenter97 verticalAlignment: Text.AlignVCenter
@@ -141,8 +134,7 @@
141 id: rail134 id: rail
142135
143 property bool isVisible: root.enabled &&136 property bool isVisible: root.enabled &&
144 (listView.flicking || dragArea.pressed) &&137 (listView.flicking || dragArea.pressed)
145 (listView.currentIndex == -1)
146 anchors {138 anchors {
147 right: parent.right139 right: parent.right
148 rightMargin: units.gu(2)140 rightMargin: units.gu(2)
@@ -181,7 +173,7 @@
181 horizontalAlignment: Text.AlignHCenter173 horizontalAlignment: Text.AlignHCenter
182 text: modelData174 text: modelData
183 fontSize: "x-small"175 fontSize: "x-small"
184 color: cursor.y === y ? "white" : Theme.palette.selected.backgroundText176 color: cursor.y === y ? Theme.palette.normal.foregroundText : Theme.palette.selected.backgroundText
185 opacity: !internal.modelDirty && Sections.contains(text) ? 1.0 : 0.5177 opacity: !internal.modelDirty && Sections.contains(text) ? 1.0 : 0.5
186 }178 }
187 }179 }

Subscribers

People subscribed via source and target branches