Merge lp:~renatofilho/address-book-app/keyboard-navigation into lp:address-book-app
- keyboard-navigation
- Merge into trunk
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 |
Related bugs: |
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
PS Jenkins bot (ps-jenkins) wrote : | # |
- 506. By Renato Araujo Oliveira Filho
-
Fixed focus on test fields.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:506
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 507. By Renato Araujo Oliveira Filho
-
Fixed visual for field header.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:507
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 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.
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://
8)
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
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.
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.
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:/
>
> 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://
> app/imports/
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)
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.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:508
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:509
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 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.
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
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:511
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 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 RemoveContactsD
ialog.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:514
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:517
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 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.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:518
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:521
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 522. By Renato Araujo Oliveira Filho
-
Only set focus on list item after the key down pressed.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:522
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 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.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:524
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 527. By Renato Araujo Oliveira Filho
-
Fixed bottom edge editor page behaviour.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:526
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:527
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 528. By Renato Araujo Oliveira Filho
-
Avoid move contact index after editing it.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:528
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 529. By Renato Araujo Oliveira Filho
-
Trunk merged.
- 530. By Renato Araujo Oliveira Filho
-
Fixed view page connections after edit a contact.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:529
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:530
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 531. By Renato Araujo Oliveira Filho
-
Update FastScroll colors.
- 532. By Renato Araujo Oliveira Filho
-
Move list to desired contact on 'positionViewAt
Contact' . - 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.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:535
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 536. By Renato Araujo Oliveira Filho
-
Disable contact editor page while on bottom edge to avoid focus problems.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:536
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 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.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:538
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 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.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:542
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 543. By Renato Araujo Oliveira Filho
-
use gray background color for fasctroll tooltip.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:543
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 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.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:546
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Florian Boucault (fboucault) wrote : | # |
Can you explain the purpose of forceActiveFocus() in src/imports/
function reloadContact() {
[...]
}
Florian Boucault (fboucault) wrote : | # |
Can you explain the purpose of
Timer {
id: fetchNewContact
[...]
}
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.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:547
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:550
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Florian Boucault (fboucault) wrote : | # |
Much better! Thank you, code is good to go.
- 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
1 | === modified file 'src/app/addressbookapp.cpp' | |||
2 | --- src/app/addressbookapp.cpp 2015-12-11 16:43:39 +0000 | |||
3 | +++ src/app/addressbookapp.cpp 2015-12-16 18:38:23 +0000 | |||
4 | @@ -104,7 +104,8 @@ | |||
5 | 104 | m_netManager(new QNetworkConfigurationManager), | 104 | m_netManager(new QNetworkConfigurationManager), |
6 | 105 | m_pickingMode(false), | 105 | m_pickingMode(false), |
7 | 106 | m_testMode(false), | 106 | m_testMode(false), |
9 | 107 | m_withArgs(false) | 107 | m_withArgs(false), |
10 | 108 | m_withKeyboard(false) | ||
11 | 108 | { | 109 | { |
12 | 109 | s_elapsed.start(); | 110 | s_elapsed.start(); |
13 | 110 | setOrganizationName(SETTINGS_ORGANIZATION_NAME); | 111 | setOrganizationName(SETTINGS_ORGANIZATION_NAME); |
14 | @@ -447,6 +448,16 @@ | |||
15 | 447 | qDebug() << "ELAPSED:" << s_elapsed.elapsed() / 1000.0; | 448 | qDebug() << "ELAPSED:" << s_elapsed.elapsed() / 1000.0; |
16 | 448 | } | 449 | } |
17 | 449 | 450 | ||
18 | 451 | bool AddressBookApp::notify(QObject *obj, QEvent *event) | ||
19 | 452 | { | ||
20 | 453 | if ((event->type() == QEvent::KeyPress) && !m_withKeyboard) { | ||
21 | 454 | m_withKeyboard = true; | ||
22 | 455 | Q_EMIT usingKeyboardChanged(); | ||
23 | 456 | return true; | ||
24 | 457 | } | ||
25 | 458 | return QGuiApplication::notify(obj, event); | ||
26 | 459 | } | ||
27 | 460 | |||
28 | 450 | QString AddressBookApp::callbackApplication() const | 461 | QString AddressBookApp::callbackApplication() const |
29 | 451 | { | 462 | { |
30 | 452 | return m_callbackApplication; | 463 | return m_callbackApplication; |
31 | @@ -475,3 +486,8 @@ | |||
32 | 475 | { | 486 | { |
33 | 476 | return !m_updateWatcher.isNull(); | 487 | return !m_updateWatcher.isNull(); |
34 | 477 | } | 488 | } |
35 | 489 | |||
36 | 490 | bool AddressBookApp::usingKeyboard() const | ||
37 | 491 | { | ||
38 | 492 | return m_withKeyboard; | ||
39 | 493 | } | ||
40 | 478 | 494 | ||
41 | === modified file 'src/app/addressbookapp.h' | |||
42 | --- src/app/addressbookapp.h 2015-12-11 16:43:39 +0000 | |||
43 | +++ src/app/addressbookapp.h 2015-12-16 18:38:23 +0000 | |||
44 | @@ -32,6 +32,7 @@ | |||
45 | 32 | Q_PROPERTY(bool isOnline READ isOnline NOTIFY isOnlineChanged) | 32 | Q_PROPERTY(bool isOnline READ isOnline NOTIFY isOnlineChanged) |
46 | 33 | Q_PROPERTY(bool serverSafeMode READ serverSafeMode NOTIFY serverSafeModeChanged) | 33 | Q_PROPERTY(bool serverSafeMode READ serverSafeMode NOTIFY serverSafeModeChanged) |
47 | 34 | Q_PROPERTY(bool updating READ updating NOTIFY updatingChanged) | 34 | Q_PROPERTY(bool updating READ updating NOTIFY updatingChanged) |
48 | 35 | Q_PROPERTY(bool usingKeyboard READ usingKeyboard NOTIFY usingKeyboardChanged) | ||
49 | 35 | 36 | ||
50 | 36 | public: | 37 | public: |
51 | 37 | AddressBookApp(int &argc, char **argv); | 38 | AddressBookApp(int &argc, char **argv); |
52 | @@ -45,12 +46,14 @@ | |||
53 | 45 | bool isOnline() const; | 46 | bool isOnline() const; |
54 | 46 | bool serverSafeMode() const; | 47 | bool serverSafeMode() const; |
55 | 47 | bool updating() const; | 48 | bool updating() const; |
56 | 49 | bool usingKeyboard() const; | ||
57 | 48 | 50 | ||
58 | 49 | Q_SIGNALS: | 51 | Q_SIGNALS: |
59 | 50 | void callbackApplicationChanged(); | 52 | void callbackApplicationChanged(); |
60 | 51 | void isOnlineChanged(); | 53 | void isOnlineChanged(); |
61 | 52 | void serverSafeModeChanged(); | 54 | void serverSafeModeChanged(); |
62 | 53 | void updatingChanged(); | 55 | void updatingChanged(); |
63 | 56 | void usingKeyboardChanged(); | ||
64 | 54 | void sourcesChanged(); | 57 | void sourcesChanged(); |
65 | 55 | 58 | ||
66 | 56 | public Q_SLOTS: | 59 | public Q_SLOTS: |
67 | @@ -66,6 +69,9 @@ | |||
68 | 66 | // debug | 69 | // debug |
69 | 67 | void elapsed() const; | 70 | void elapsed() const; |
70 | 68 | 71 | ||
71 | 72 | protected: | ||
72 | 73 | bool notify(QObject *obj, QEvent *event); | ||
73 | 74 | |||
74 | 69 | private Q_SLOTS: | 75 | private Q_SLOTS: |
75 | 70 | void onUpdateCallFinished(QDBusPendingCallWatcher *watcher); | 76 | void onUpdateCallFinished(QDBusPendingCallWatcher *watcher); |
76 | 71 | 77 | ||
77 | @@ -84,6 +90,7 @@ | |||
78 | 84 | bool m_pickingMode; | 90 | bool m_pickingMode; |
79 | 85 | bool m_testMode; | 91 | bool m_testMode; |
80 | 86 | bool m_withArgs; | 92 | bool m_withArgs; |
81 | 93 | bool m_withKeyboard; | ||
82 | 87 | }; | 94 | }; |
83 | 88 | 95 | ||
84 | 89 | #endif | 96 | #endif |
85 | 90 | 97 | ||
86 | === modified file 'src/imports/ABContactEditorPage.qml' | |||
87 | --- src/imports/ABContactEditorPage.qml 2015-12-11 14:38:17 +0000 | |||
88 | +++ src/imports/ABContactEditorPage.qml 2015-12-16 18:38:23 +0000 | |||
89 | @@ -38,9 +38,11 @@ | |||
90 | 38 | 38 | ||
91 | 39 | text: i18n.tr("Cancel") | 39 | text: i18n.tr("Cancel") |
92 | 40 | iconName: "back" | 40 | iconName: "back" |
96 | 41 | onTriggered: { | 41 | // WORKAROUND: SDK does not unregister shortcut on object destruction |
97 | 42 | root.cancel() | 42 | // we need to do it manually. (bug #1518420) |
98 | 43 | } | 43 | enabled: root.active && root.enabled |
99 | 44 | shortcut: enabled ? "Esc" : undefined | ||
100 | 45 | onTriggered: root.cancel() | ||
101 | 44 | } | 46 | } |
102 | 45 | 47 | ||
103 | 46 | head.actions: [ | 48 | head.actions: [ |
104 | @@ -51,8 +53,8 @@ | |||
105 | 51 | 53 | ||
106 | 52 | text: i18n.tr("Save") | 54 | text: i18n.tr("Save") |
107 | 53 | iconName: "ok" | 55 | iconName: "ok" |
110 | 54 | // disable save button while avatar scale still running | 56 | enabled: root.isContactValid && root.active && root.enabled |
111 | 55 | enabled: root.isContactValid | 57 | shortcut: "Ctrl+s" |
112 | 56 | onTriggered: root.save() | 58 | onTriggered: root.save() |
113 | 57 | } | 59 | } |
114 | 58 | ] | 60 | ] |
115 | 59 | 61 | ||
116 | === modified file 'src/imports/ABContactListPage.qml' | |||
117 | --- src/imports/ABContactListPage.qml 2015-12-07 08:13:36 +0000 | |||
118 | +++ src/imports/ABContactListPage.qml 2015-12-16 18:38:23 +0000 | |||
119 | @@ -38,10 +38,11 @@ | |||
120 | 38 | property QtObject contactIndex: null | 38 | property QtObject contactIndex: null |
121 | 39 | property string newPhoneToAdd: "" | 39 | property string newPhoneToAdd: "" |
122 | 40 | property alias contactManager: contactList.manager | 40 | property alias contactManager: contactList.manager |
125 | 41 | property Page contactViewPage: null | 41 | property alias contactViewPage: contactViewPageConnections.target |
126 | 42 | property Page contactEditorPage: null | 42 | property alias contactEditorPage: contactEditorPageConnections.target |
127 | 43 | property var _busyDialog: null | 43 | property var _busyDialog: null |
128 | 44 | property bool _importingTestData: false | 44 | property bool _importingTestData: false |
129 | 45 | property bool _creatingContact: false | ||
130 | 45 | 46 | ||
131 | 46 | readonly property bool bottomEdgePageOpened: bottomEdge.opened && bottomEdge.fullLoaded | 47 | readonly property bool bottomEdgePageOpened: bottomEdge.opened && bottomEdge.fullLoaded |
132 | 47 | readonly property bool isEmpty: (contactList.count === 0) | 48 | readonly property bool isEmpty: (contactList.count === 0) |
133 | @@ -87,6 +88,12 @@ | |||
134 | 87 | 88 | ||
135 | 88 | function showContact(contact) | 89 | function showContact(contact) |
136 | 89 | { | 90 | { |
137 | 91 | var currentContact = contactList.listModel.contacts[contactList.currentIndex] | ||
138 | 92 | if (currentContact && contactViewPage && contactViewPage.contact && (contactViewPage.contact.contactId === currentContact.contactId)) { | ||
139 | 93 | console.debug("Skip show contact") | ||
140 | 94 | return | ||
141 | 95 | } | ||
142 | 96 | |||
143 | 90 | // go back to normal state if not searching | 97 | // go back to normal state if not searching |
144 | 91 | if ((state !== "searching") && | 98 | if ((state !== "searching") && |
145 | 92 | (state !== "vcardImported")) { | 99 | (state !== "vcardImported")) { |
146 | @@ -138,14 +145,12 @@ | |||
147 | 138 | 145 | ||
148 | 139 | function moveListToContact(contact) | 146 | function moveListToContact(contact) |
149 | 140 | { | 147 | { |
154 | 141 | // skipt it if searching or importing contacts | 148 | if ((state !== "searching") && |
155 | 142 | if ((state === "searching") || | 149 | (state !== "vcardImported")) { |
156 | 143 | (state === "vcardImported")) { | 150 | mainPage.state = "default" |
153 | 144 | return | ||
157 | 145 | } | 151 | } |
158 | 146 | 152 | ||
159 | 147 | contactIndex = contact | 153 | contactIndex = contact |
160 | 148 | mainPage.state = "default" | ||
161 | 149 | // this means a new contact was created | 154 | // this means a new contact was created |
162 | 150 | if (mainPage.allowToQuit) { | 155 | if (mainPage.allowToQuit) { |
163 | 151 | application.goBackToSourceApp() | 156 | application.goBackToSourceApp() |
164 | @@ -163,22 +168,53 @@ | |||
165 | 163 | contactList.currentIndex = -1; | 168 | contactList.currentIndex = -1; |
166 | 164 | mainPage.contactEditorPage = editorPage; | 169 | mainPage.contactEditorPage = editorPage; |
167 | 165 | pageStack.addPageToNextColumn(mainPage, editorPage); | 170 | pageStack.addPageToNextColumn(mainPage, editorPage); |
168 | 166 | editorPage.ready(); | ||
169 | 167 | editorPage.contactSaved.connect(onNewContactSaved); | 171 | editorPage.contactSaved.connect(onNewContactSaved); |
170 | 172 | editorPage.enabled = true | ||
171 | 168 | } | 173 | } |
172 | 169 | 174 | ||
173 | 170 | function onNewContactSaved(contact) { | 175 | function onNewContactSaved(contact) { |
174 | 176 | _creatingContact = true | ||
175 | 177 | moveListToContact(contact) | ||
176 | 171 | if (pageStack.columns > 1) { | 178 | if (pageStack.columns > 1) { |
177 | 172 | showContact(contact); | 179 | showContact(contact); |
178 | 173 | } | 180 | } |
179 | 174 | } | 181 | } |
180 | 175 | 182 | ||
181 | 183 | // Delay contact fetch for some msecs (check 'fetchNewContactTimer') | ||
182 | 184 | function delayFetchContact() | ||
183 | 185 | { | ||
184 | 186 | fetchNewContactTimer.restart() | ||
185 | 187 | } | ||
186 | 188 | |||
187 | 189 | function fetchContact() | ||
188 | 190 | { | ||
189 | 191 | if ((contactList.currentIndex >= 0) && (pageStack.columns > 1)) { | ||
190 | 192 | var currentContact = contactList.listModel.contacts[contactList.currentIndex] | ||
191 | 193 | if (contactViewPage && contactViewPage.contact && (contactViewPage.contact.contactId === currentContact.contactId)) | ||
192 | 194 | return | ||
193 | 195 | |||
194 | 196 | contactList.view._fetchContact(contactList.currentIndex, currentContact) | ||
195 | 197 | } | ||
196 | 198 | } | ||
197 | 199 | |||
198 | 200 | // This timer is to avoid fetch unecessary contact if the user select the contacts too fast | ||
199 | 201 | // while navigating on contact list with keyboard | ||
200 | 202 | Timer { | ||
201 | 203 | id: fetchNewContactTimer | ||
202 | 204 | |||
203 | 205 | interval: 300 | ||
204 | 206 | repeat: false | ||
205 | 207 | onTriggered: mainPage.fetchContact() | ||
206 | 208 | } | ||
207 | 209 | |||
208 | 176 | title: i18n.tr("Contacts") | 210 | title: i18n.tr("Contacts") |
209 | 177 | |||
210 | 178 | flickable: null | 211 | flickable: null |
211 | 212 | |||
212 | 179 | ContactsUI.ContactListView { | 213 | ContactsUI.ContactListView { |
213 | 180 | id: contactList | 214 | id: contactList |
214 | 181 | objectName: "contactListView" | 215 | objectName: "contactListView" |
215 | 216 | |||
216 | 217 | focus: true | ||
217 | 182 | showImportOptions: !mainPage.pickMode && | 218 | showImportOptions: !mainPage.pickMode && |
218 | 183 | mainPage.newPhoneToAdd === "" && | 219 | mainPage.newPhoneToAdd === "" && |
219 | 184 | (!mainPage.contactEditorPage || !mainPage.contactEditorPage.active) | 220 | (!mainPage.contactEditorPage || !mainPage.contactEditorPage.active) |
220 | @@ -188,10 +224,11 @@ | |||
221 | 188 | bottom: keyboard.top | 224 | bottom: keyboard.top |
222 | 189 | right: parent.right | 225 | right: parent.right |
223 | 190 | } | 226 | } |
224 | 227 | currentIndex: 0 | ||
225 | 191 | filterTerm: searchField.text | 228 | filterTerm: searchField.text |
226 | 192 | multiSelectionEnabled: true | 229 | multiSelectionEnabled: true |
227 | 193 | multipleSelection: (mainPage.pickMode && mainPage.pickMultipleContacts) || !mainPage.pickMode | 230 | multipleSelection: (mainPage.pickMode && mainPage.pickMultipleContacts) || !mainPage.pickMode |
229 | 194 | highlightSelected: pageStack.columns > 1 | 231 | highlightSelected: application.usingKeyboard && !mainPage._creatingContact |
230 | 195 | onAddContactClicked: mainPage.createContactWithPhoneNumber(label) | 232 | onAddContactClicked: mainPage.createContactWithPhoneNumber(label) |
231 | 196 | onAddNewContactClicked: mainPage.createContactWithPhoneNumber(mainPage.newPhoneToAdd) | 233 | onAddNewContactClicked: mainPage.createContactWithPhoneNumber(mainPage.newPhoneToAdd) |
232 | 197 | 234 | ||
233 | @@ -210,25 +247,71 @@ | |||
234 | 210 | } | 247 | } |
235 | 211 | 248 | ||
236 | 212 | onError: pageStack.contactModelError(error) | 249 | onError: pageStack.contactModelError(error) |
237 | 250 | onActiveFocusChanged: { | ||
238 | 251 | if (activeFocus && (contactList.currentIndex === -1)) { | ||
239 | 252 | contactList.currentIndex = 0 | ||
240 | 253 | } | ||
241 | 254 | } | ||
242 | 255 | onCountChanged: { | ||
243 | 256 | if (mainPage.active && | ||
244 | 257 | (pageStack.columns > 1) && | ||
245 | 258 | (contactList.currentIndex === -1)) { | ||
246 | 259 | contactList.currentIndex = 0 | ||
247 | 260 | } | ||
248 | 261 | mainPage.delayFetchContact() | ||
249 | 262 | } | ||
250 | 263 | onCurrentIndexChanged: { | ||
251 | 264 | if (!mainPage.contactIndex) | ||
252 | 265 | mainPage.delayFetchContact() | ||
253 | 266 | } | ||
254 | 267 | |||
255 | 268 | Keys.onReturnPressed: { | ||
256 | 269 | var currentContact = contactList.listModel.contacts[contactList.currentIndex] | ||
257 | 270 | if (contactViewPage && contactViewPage.contact && (contactViewPage.contact.contactId === currentContact.contactId)) | ||
258 | 271 | return | ||
259 | 272 | |||
260 | 273 | contactList.view._fetchContact(contactList.currentIndex, currentContact) | ||
261 | 274 | } | ||
262 | 275 | |||
263 | 276 | //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822 | ||
264 | 277 | //because of that we need this | ||
265 | 278 | Keys.onRightPressed: { | ||
266 | 279 | // only move focus away when in edit mode | ||
267 | 280 | if (mainPage.contactEditorPage) { | ||
268 | 281 | var next = pageStack._nextItemInFocusChain(view, true) | ||
269 | 282 | if (next === searchField) { | ||
270 | 283 | pageStack._nextItemInFocusChain(next, true) | ||
271 | 284 | } | ||
272 | 285 | } | ||
273 | 286 | } | ||
274 | 287 | Keys.onTabPressed: { | ||
275 | 288 | var next = pageStack._nextItemInFocusChain(view, true) | ||
276 | 289 | if (next === searchField) { | ||
277 | 290 | pageStack._nextItemInFocusChain(next, true) | ||
278 | 291 | } | ||
279 | 292 | } | ||
280 | 213 | } | 293 | } |
281 | 214 | 294 | ||
282 | 295 | |||
283 | 296 | |||
284 | 215 | TextField { | 297 | TextField { |
285 | 216 | id: searchField | 298 | id: searchField |
286 | 217 | 299 | ||
287 | 300 | //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822 | ||
288 | 301 | //because of that we need this | ||
289 | 302 | readonly property bool _allowFocus: true | ||
290 | 303 | |||
291 | 218 | anchors { | 304 | anchors { |
294 | 219 | left: parent.left | 305 | left: parent ? parent.left : undefined |
295 | 220 | right: parent.right | 306 | right: parent ? parent.right : undefined |
296 | 221 | rightMargin: units.gu(2) | 307 | rightMargin: units.gu(2) |
297 | 222 | } | 308 | } |
299 | 223 | focus: false | 309 | |
300 | 224 | visible: false | 310 | visible: false |
301 | 225 | onTextChanged: contactList.currentIndex = -1 | ||
302 | 226 | inputMethodHints: Qt.ImhNoPredictiveText | 311 | inputMethodHints: Qt.ImhNoPredictiveText |
303 | 227 | placeholderText: i18n.tr("Search...") | 312 | placeholderText: i18n.tr("Search...") |
308 | 228 | onFocusChanged: { | 313 | Keys.onTabPressed: contactList.forceActiveFocus() |
309 | 229 | if (visible && focus) | 314 | Keys.onDownPressed: contactList.forceActiveFocus() |
306 | 230 | searchField.forceActiveFocus() | ||
307 | 231 | } | ||
310 | 232 | } | 315 | } |
311 | 233 | 316 | ||
312 | 234 | Connections { | 317 | Connections { |
313 | @@ -267,6 +350,8 @@ | |||
314 | 267 | text: i18n.tr("Search") | 350 | text: i18n.tr("Search") |
315 | 268 | iconName: "search" | 351 | iconName: "search" |
316 | 269 | visible: !mainPage.isEmpty | 352 | visible: !mainPage.isEmpty |
317 | 353 | enabled: mainPage.state === "default" | ||
318 | 354 | shortcut: "Ctrl+F" | ||
319 | 270 | onTriggered: { | 355 | onTriggered: { |
320 | 271 | mainPage.state = (mainPage.state === "newphone" ? "newphoneSearching" : "searching") | 356 | mainPage.state = (mainPage.state === "newphone" ? "newphoneSearching" : "searching") |
321 | 272 | contactList.showAllContacts() | 357 | contactList.showAllContacts() |
322 | @@ -289,9 +374,21 @@ | |||
323 | 289 | Action { | 374 | Action { |
324 | 290 | text: i18n.tr("Settings") | 375 | text: i18n.tr("Settings") |
325 | 291 | iconName: "settings" | 376 | iconName: "settings" |
329 | 292 | onTriggered: pageStack.addPageToNextColumn(mainPage, | 377 | onTriggered:{ |
330 | 293 | Qt.resolvedUrl("./Settings/SettingsPage.qml"), | 378 | var incubator = pageStack.addPageToNextColumn(mainPage, |
331 | 294 | {"contactListModel": contactList.listModel}) | 379 | Qt.resolvedUrl("./Settings/SettingsPage.qml"), |
332 | 380 | {"contactListModel": contactList.listModel}) | ||
333 | 381 | incubator.onStatusChanged = function(status) { | ||
334 | 382 | if (status === Component.Ready) { | ||
335 | 383 | incubator.object.onActiveChanged.connect(function(active) { | ||
336 | 384 | if (!incubator.object.active) { | ||
337 | 385 | mainPage.delayFetchContact() | ||
338 | 386 | contactList.forceActiveFocus() | ||
339 | 387 | } | ||
340 | 388 | }) | ||
341 | 389 | } | ||
342 | 390 | } | ||
343 | 391 | } | ||
344 | 295 | } | 392 | } |
345 | 296 | ] | 393 | ] |
346 | 297 | PropertyChanges { | 394 | PropertyChanges { |
347 | @@ -305,6 +402,10 @@ | |||
348 | 305 | target: searchField | 402 | target: searchField |
349 | 306 | text: "" | 403 | text: "" |
350 | 307 | } | 404 | } |
351 | 405 | PropertyChanges { | ||
352 | 406 | target: bottomEdge | ||
353 | 407 | enabled: true | ||
354 | 408 | } | ||
355 | 308 | }, | 409 | }, |
356 | 309 | PageHeadState { | 410 | PageHeadState { |
357 | 310 | id: searchingState | 411 | id: searchingState |
358 | @@ -313,10 +414,12 @@ | |||
359 | 313 | backAction: Action { | 414 | backAction: Action { |
360 | 314 | iconName: "back" | 415 | iconName: "back" |
361 | 315 | text: i18n.tr("Cancel") | 416 | text: i18n.tr("Cancel") |
362 | 417 | enabled: mainPage.state === "searching" && !mainPage.contactEditorPage && mainPage.active | ||
363 | 418 | shortcut: "Esc" | ||
364 | 316 | onTriggered: { | 419 | onTriggered: { |
365 | 317 | contactList.forceActiveFocus() | ||
366 | 318 | mainPage.head.sections.selectedIndex = 0 | 420 | mainPage.head.sections.selectedIndex = 0 |
367 | 319 | mainPage.state = (mainPage.state === "newphoneSearching" ? "newphone" : "default") | 421 | mainPage.state = (mainPage.state === "newphoneSearching" ? "newphone" : "default") |
368 | 422 | contactList.forceActiveFocus() | ||
369 | 320 | } | 423 | } |
370 | 321 | } | 424 | } |
371 | 322 | 425 | ||
372 | @@ -349,6 +452,8 @@ | |||
373 | 349 | backAction: Action { | 452 | backAction: Action { |
374 | 350 | text: i18n.tr("Cancel selection") | 453 | text: i18n.tr("Cancel selection") |
375 | 351 | iconName: "back" | 454 | iconName: "back" |
376 | 455 | enabled: mainPage.state === "selection" | ||
377 | 456 | shortcut: "Esc" | ||
378 | 352 | onTriggered: contactList.cancelSelection() | 457 | onTriggered: contactList.cancelSelection() |
379 | 353 | } | 458 | } |
380 | 354 | actions: [ | 459 | actions: [ |
381 | @@ -495,8 +600,11 @@ | |||
382 | 495 | if (active && contactList.showAddNewButton) { | 600 | if (active && contactList.showAddNewButton) { |
383 | 496 | contactList.positionViewAtBeginning() | 601 | contactList.positionViewAtBeginning() |
384 | 497 | } | 602 | } |
385 | 603 | |||
386 | 498 | if (active && (state === "searching")) { | 604 | if (active && (state === "searching")) { |
387 | 499 | searchField.forceActiveFocus() | 605 | searchField.forceActiveFocus() |
388 | 606 | } else if (active) { | ||
389 | 607 | contactList.forceActiveFocus() | ||
390 | 500 | } | 608 | } |
391 | 501 | } | 609 | } |
392 | 502 | 610 | ||
393 | @@ -712,18 +820,19 @@ | |||
394 | 712 | var newContact = ContactsJS.createEmptyContact("", mainPage); | 820 | var newContact = ContactsJS.createEmptyContact("", mainPage); |
395 | 713 | createObjectAsynchronously(Qt.resolvedUrl("ABContactEditorPage.qml"), | 821 | createObjectAsynchronously(Qt.resolvedUrl("ABContactEditorPage.qml"), |
396 | 714 | {model: contactList.listModel, | 822 | {model: contactList.listModel, |
397 | 823 | enabled: false, | ||
398 | 715 | contact: newContact, | 824 | contact: newContact, |
399 | 716 | initialFocusSection: "name"}, | 825 | initialFocusSection: "name"}, |
401 | 717 | showContactEditorPage); | 826 | showContactEditorPage); |
402 | 718 | } | 827 | } |
403 | 719 | 828 | ||
404 | 720 | anchors.fill: parent | 829 | anchors.fill: parent |
406 | 721 | contentComponent: pageStack.columns == 1 ? editorPageBottomEdge : emptyContact | 830 | contentComponent: pageStack.columns === 1 ? editorPageBottomEdge : emptyContact |
407 | 722 | flickable: contactList | 831 | flickable: contactList |
408 | 723 | iconName: "contact-new" | 832 | iconName: "contact-new" |
409 | 724 | enabled: !contactList.isInSelectionMode | ||
410 | 725 | backGroundEffectEnabled: pageStack.columns === 1 | 833 | backGroundEffectEnabled: pageStack.columns === 1 |
411 | 726 | 834 | ||
412 | 835 | onBottomEdgeLoaded: contactList.forceActiveFocus() | ||
413 | 727 | onOpenBegin: { | 836 | onOpenBegin: { |
414 | 728 | contactList.prepareNewContact = true; | 837 | contactList.prepareNewContact = true; |
415 | 729 | contactList.positionViewAtBeginning(); | 838 | contactList.positionViewAtBeginning(); |
416 | @@ -732,7 +841,6 @@ | |||
417 | 732 | } | 841 | } |
418 | 733 | } | 842 | } |
419 | 734 | onOpenEnd: { | 843 | onOpenEnd: { |
420 | 735 | bottomEdge.visible = false; | ||
421 | 736 | contactList.showNewContact = true; | 844 | contactList.showNewContact = true; |
422 | 737 | if (pageStack.columns <= 1) { | 845 | if (pageStack.columns <= 1) { |
423 | 738 | showContactEditorPage(bottomEdge.content); | 846 | showContactEditorPage(bottomEdge.content); |
424 | @@ -746,10 +854,13 @@ | |||
425 | 746 | 854 | ||
426 | 747 | Connections { | 855 | Connections { |
427 | 748 | target: mainPage.contactModel | 856 | target: mainPage.contactModel |
428 | 857 | |||
429 | 749 | onContactsChanged: { | 858 | onContactsChanged: { |
430 | 750 | if (contactIndex) { | 859 | if (contactIndex) { |
431 | 751 | contactList.positionViewAtContact(mainPage.contactIndex) | 860 | contactList.positionViewAtContact(mainPage.contactIndex) |
432 | 752 | mainPage.contactIndex = null | 861 | mainPage.contactIndex = null |
433 | 862 | // at this point the operation has finished already | ||
434 | 863 | mainPage._creatingContact = false | ||
435 | 753 | } | 864 | } |
436 | 754 | } | 865 | } |
437 | 755 | onImportCompleted: { | 866 | onImportCompleted: { |
438 | @@ -779,20 +890,33 @@ | |||
439 | 779 | } | 890 | } |
440 | 780 | 891 | ||
441 | 781 | Connections { | 892 | Connections { |
445 | 782 | target: mainPage.contactViewPage | 893 | id: contactViewPageConnections |
446 | 783 | onEditContact: { | 894 | |
447 | 784 | openEditPage(editPageProperties, mainPage.contactViewPage); | 895 | ignoreUnknownSignals: true |
448 | 896 | onEditContact: openEditPage(editPageProperties, mainPage.contactViewPage); | ||
449 | 897 | onActiveChanged: { | ||
450 | 898 | if (mainPage.contactViewPage && | ||
451 | 899 | !mainPage.contactViewPage.active && | ||
452 | 900 | (mainPage.contactEditorPage == null)) { // not editing | ||
453 | 901 | mainPage.contactViewPage = null | ||
454 | 902 | } | ||
455 | 785 | } | 903 | } |
456 | 786 | } | 904 | } |
457 | 787 | 905 | ||
458 | 788 | Connections { | 906 | Connections { |
460 | 789 | target: mainPage.contactEditorPage | 907 | id: contactEditorPageConnections |
461 | 908 | |||
462 | 909 | ignoreUnknownSignals: true | ||
463 | 790 | onActiveChanged: { | 910 | onActiveChanged: { |
465 | 791 | if (!mainPage.contactEditorPage.active) { | 911 | if (mainPage.contactEditorPage && !mainPage.contactEditorPage.active) { |
466 | 792 | contactList.prepareNewContact = false; | 912 | contactList.prepareNewContact = false; |
467 | 793 | contactList.showNewContact = false; | 913 | contactList.showNewContact = false; |
468 | 794 | bottomEdge.visible = true; | ||
469 | 795 | bottomEdge.close(); | 914 | bottomEdge.close(); |
470 | 915 | mainPage.contactEditorPage = null | ||
471 | 916 | contactList.forceActiveFocus() | ||
472 | 917 | bottomEdge.enabled = true | ||
473 | 918 | } else if (mainPage.contactEditorPage && !mainPage.contactEditorPage.active) { | ||
474 | 919 | bottomEdge.enabled = false | ||
475 | 796 | } | 920 | } |
476 | 797 | } | 921 | } |
477 | 798 | } | 922 | } |
478 | 799 | 923 | ||
479 | === modified file 'src/imports/ABContactViewPage.qml' | |||
480 | --- src/imports/ABContactViewPage.qml 2015-10-28 01:08:39 +0000 | |||
481 | +++ src/imports/ABContactViewPage.qml 2015-12-16 18:38:23 +0000 | |||
482 | @@ -30,6 +30,16 @@ | |||
483 | 30 | property string addPhoneToContact: "" | 30 | property string addPhoneToContact: "" |
484 | 31 | signal editContact(var editPageProperties) | 31 | signal editContact(var editPageProperties) |
485 | 32 | 32 | ||
486 | 33 | // Override Action buttom to add shortcut to it | ||
487 | 34 | Action { | ||
488 | 35 | id: backAction | ||
489 | 36 | |||
490 | 37 | name: "cancel" | ||
491 | 38 | enabled: root.active && root.enabled && (pageStack.columns === 1) | ||
492 | 39 | shortcut: "Esc" | ||
493 | 40 | onTriggered: pageStack.removePages(root) | ||
494 | 41 | } | ||
495 | 42 | |||
496 | 33 | head.actions: [ | 43 | head.actions: [ |
497 | 34 | Action { | 44 | Action { |
498 | 35 | objectName: "share" | 45 | objectName: "share" |
499 | @@ -50,6 +60,8 @@ | |||
500 | 50 | 60 | ||
501 | 51 | text: i18n.tr("Edit") | 61 | text: i18n.tr("Edit") |
502 | 52 | iconName: "edit" | 62 | iconName: "edit" |
503 | 63 | enabled: root.active | ||
504 | 64 | shortcut: "Ctrl+e" | ||
505 | 53 | onTriggered: { | 65 | onTriggered: { |
506 | 54 | editContact({model: root.model, | 66 | editContact({model: root.model, |
507 | 55 | contact: root.contact}); | 67 | contact: root.contact}); |
508 | 56 | 68 | ||
509 | === modified file 'src/imports/BottomEdge.qml' | |||
510 | --- src/imports/BottomEdge.qml 2015-11-19 01:02:12 +0000 | |||
511 | +++ src/imports/BottomEdge.qml 2015-12-16 18:38:23 +0000 | |||
512 | @@ -32,7 +32,7 @@ | |||
513 | 32 | signal openBegin | 32 | signal openBegin |
514 | 33 | signal openEnd | 33 | signal openEnd |
515 | 34 | signal clicked | 34 | signal clicked |
517 | 35 | visible: enabled | 35 | signal bottomEdgeLoaded |
518 | 36 | 36 | ||
519 | 37 | function open() { | 37 | function open() { |
520 | 38 | bottomEdge.state = "expanded"; | 38 | bottomEdge.state = "expanded"; |
521 | @@ -42,6 +42,13 @@ | |||
522 | 42 | bottomEdge.state = "collapsed"; | 42 | bottomEdge.state = "collapsed"; |
523 | 43 | } | 43 | } |
524 | 44 | 44 | ||
525 | 45 | Action { | ||
526 | 46 | text: i18n.tr("New contact") | ||
527 | 47 | enabled: bottomEdge.visible | ||
528 | 48 | shortcut: "Ctrl+N" | ||
529 | 49 | onTriggered: bottomEdge.clicked() | ||
530 | 50 | } | ||
531 | 51 | |||
532 | 45 | Rectangle { | 52 | Rectangle { |
533 | 46 | id: darkBg | 53 | id: darkBg |
534 | 47 | 54 | ||
535 | @@ -90,6 +97,10 @@ | |||
536 | 90 | sourceComponent: bottomEdge.contentComponent | 97 | sourceComponent: bottomEdge.contentComponent |
537 | 91 | asynchronous: true | 98 | asynchronous: true |
538 | 92 | active: bottomEdge.enabled | 99 | active: bottomEdge.enabled |
539 | 100 | onStatusChanged: { | ||
540 | 101 | if (status === Loader.Ready) | ||
541 | 102 | bottomEdge.bottomEdgeLoaded() | ||
542 | 103 | } | ||
543 | 93 | } | 104 | } |
544 | 94 | } | 105 | } |
545 | 95 | 106 | ||
546 | @@ -318,4 +329,10 @@ | |||
547 | 318 | dragDirection = yOffset > 0 ? "BottomToTop" : "TopToBottom"; | 329 | dragDirection = yOffset > 0 ? "BottomToTop" : "TopToBottom"; |
548 | 319 | } | 330 | } |
549 | 320 | } | 331 | } |
550 | 332 | |||
551 | 333 | Binding { | ||
552 | 334 | target: bottomEdge | ||
553 | 335 | property: 'visible' | ||
554 | 336 | value: bottomEdge.enabled && !bottomEdge.opened | ||
555 | 337 | } | ||
556 | 321 | } | 338 | } |
557 | 322 | 339 | ||
558 | === modified file 'src/imports/MainWindow.qml' | |||
559 | --- src/imports/MainWindow.qml 2015-10-26 13:18:11 +0000 | |||
560 | +++ src/imports/MainWindow.qml 2015-12-16 18:38:23 +0000 | |||
561 | @@ -105,7 +105,6 @@ | |||
562 | 105 | AdaptivePageLayout { | 105 | AdaptivePageLayout { |
563 | 106 | id: mainStack | 106 | id: mainStack |
564 | 107 | 107 | ||
565 | 108 | primaryPage: contactPage | ||
566 | 109 | property var contactListPage: null | 108 | property var contactListPage: null |
567 | 110 | 109 | ||
568 | 111 | function resetStack() | 110 | function resetStack() |
569 | @@ -113,6 +112,28 @@ | |||
570 | 113 | mainStack.removePages(primaryPage); | 112 | mainStack.removePages(primaryPage); |
571 | 114 | } | 113 | } |
572 | 115 | 114 | ||
573 | 115 | function _nextItemInFocusChain(item, foward) | ||
574 | 116 | { | ||
575 | 117 | var next = item.nextItemInFocusChain(foward) | ||
576 | 118 | var first = next | ||
577 | 119 | //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822 | ||
578 | 120 | //because of that we need this | ||
579 | 121 | while (!next || !next.hasOwnProperty("_allowFocus")) { | ||
580 | 122 | next = next.nextItemInFocusChain(foward) | ||
581 | 123 | |||
582 | 124 | // avoid loop | ||
583 | 125 | if (next === first) { | ||
584 | 126 | next = null | ||
585 | 127 | break | ||
586 | 128 | } | ||
587 | 129 | } | ||
588 | 130 | if (next) { | ||
589 | 131 | next.forceActiveFocus() | ||
590 | 132 | } | ||
591 | 133 | return next | ||
592 | 134 | } | ||
593 | 135 | |||
594 | 136 | primaryPage: contactPage | ||
595 | 116 | onContactListPageChanged: { | 137 | onContactListPageChanged: { |
596 | 117 | if (contentHubLoader.status === Loader.Ready) { | 138 | if (contentHubLoader.status === Loader.Ready) { |
597 | 118 | contentHubLoader.item.pageStack = mainStack | 139 | contentHubLoader.item.pageStack = mainStack |
598 | @@ -141,6 +162,7 @@ | |||
599 | 141 | } | 162 | } |
600 | 142 | } | 163 | } |
601 | 143 | ] | 164 | ] |
602 | 165 | |||
603 | 144 | } | 166 | } |
604 | 145 | 167 | ||
605 | 146 | ABContactListPage { | 168 | ABContactListPage { |
606 | @@ -196,6 +218,10 @@ | |||
607 | 196 | 218 | ||
608 | 197 | // If application was called from uri handler and lost the focus reset the app to normal state | 219 | // If application was called from uri handler and lost the focus reset the app to normal state |
609 | 198 | onAppActiveChanged: { | 220 | onAppActiveChanged: { |
610 | 221 | if (appActive) { | ||
611 | 222 | mainStack.forceActiveFocus() | ||
612 | 223 | } | ||
613 | 224 | |||
614 | 199 | if (!appActive && mainStack.contactListPage) { | 225 | if (!appActive && mainStack.contactListPage) { |
615 | 200 | mainStack.contactListPage.returnToNormalState() | 226 | mainStack.contactListPage.returnToNormalState() |
616 | 201 | } | 227 | } |
617 | 202 | 228 | ||
618 | === modified file 'src/imports/Settings/SettingsPage.qml' | |||
619 | --- src/imports/Settings/SettingsPage.qml 2015-12-11 13:14:05 +0000 | |||
620 | +++ src/imports/Settings/SettingsPage.qml 2015-12-16 18:38:23 +0000 | |||
621 | @@ -1,4 +1,4 @@ | |||
623 | 1 | /* | 1 | /* |
624 | 2 | * Copyright (C) 2015 Canonical, Ltd. | 2 | * Copyright (C) 2015 Canonical, Ltd. |
625 | 3 | * | 3 | * |
626 | 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
627 | @@ -64,15 +64,66 @@ | |||
628 | 64 | onCountChanged: numberFlickable.contentY = 0 | 64 | onCountChanged: numberFlickable.contentY = 0 |
629 | 65 | } | 65 | } |
630 | 66 | ListItem.Standard { | 66 | ListItem.Standard { |
631 | 67 | id: addGoogleAccountItem | ||
632 | 68 | |||
633 | 69 | function activate() | ||
634 | 70 | { | ||
635 | 71 | onlineAccountsHelper.setupExec() | ||
636 | 72 | } | ||
637 | 73 | |||
638 | 67 | text: i18n.tr("Add Google account") | 74 | text: i18n.tr("Add Google account") |
639 | 68 | progression: true | 75 | progression: true |
641 | 69 | onClicked: onlineAccountsHelper.setupExec() | 76 | |
642 | 77 | onClicked: addGoogleAccountItem.activate() | ||
643 | 78 | Keys.onRightPressed: addGoogleAccountItem.activate() | ||
644 | 79 | Keys.onDownPressed: { | ||
645 | 80 | if (importFromSimItem.enabled) { | ||
646 | 81 | importFromSimItem.forceActiveFocus() | ||
647 | 82 | } | ||
648 | 83 | } | ||
649 | 84 | |||
650 | 85 | // Selection visual feedback | ||
651 | 86 | // | ||
652 | 87 | // FIXME: Using a private property here. This uses the old list item and the only way to change the text | ||
653 | 88 | // color is with this property. | ||
654 | 89 | // We should remove it when update the app to the new ListItem. | ||
655 | 90 | __foregroundColor: (activeFocus && (pageStack.columns > 1)) ? Theme.palette.normal.foregroundText : | ||
656 | 91 | Theme.palette.normal.foreground | ||
657 | 92 | Rectangle { | ||
658 | 93 | color: UbuntuColors.orange | ||
659 | 94 | anchors.fill: parent | ||
660 | 95 | visible:addGoogleAccountItem.activeFocus | ||
661 | 96 | z: -1 | ||
662 | 97 | } | ||
663 | 70 | } | 98 | } |
664 | 71 | ListItem.Standard { | 99 | ListItem.Standard { |
665 | 100 | id: importFromSimItem | ||
666 | 101 | |||
667 | 102 | function activate() | ||
668 | 103 | { | ||
669 | 104 | pageStack.addPageToCurrentColumn(root, simCardImportPageComponent) | ||
670 | 105 | } | ||
671 | 106 | |||
672 | 72 | text: i18n.tr("Import from SIM") | 107 | text: i18n.tr("Import from SIM") |
673 | 73 | progression: true | 108 | progression: true |
674 | 74 | onClicked: pageStack.addPageToCurrentColumn(root, simCardImportPageComponent) | ||
675 | 75 | enabled: (simList.sims.length > 0) && (simList.present.length > 0) | 109 | enabled: (simList.sims.length > 0) && (simList.present.length > 0) |
676 | 110 | onClicked: importFromSimItem.activate() | ||
677 | 111 | Keys.onRightPressed: importFromSimItem.activate() | ||
678 | 112 | Keys.onUpPressed: addGoogleAccountItem.forceActiveFocus() | ||
679 | 113 | |||
680 | 114 | // selection visual feedback | ||
681 | 115 | // | ||
682 | 116 | // FIXME: Using a private property here. This uses the old list item and the only way to change the text | ||
683 | 117 | // color is with this property. | ||
684 | 118 | // We should remove it when update the app to the new ListItem. | ||
685 | 119 | __foregroundColor: (activeFocus && (pageStack.columns > 1)) ? Theme.palette.normal.foregroundText : | ||
686 | 120 | Theme.palette.normal.foreground | ||
687 | 121 | Rectangle { | ||
688 | 122 | color: UbuntuColors.orange | ||
689 | 123 | anchors.fill: parent | ||
690 | 124 | visible: importFromSimItem.activeFocus | ||
691 | 125 | z: -1 | ||
692 | 126 | } | ||
693 | 76 | } | 127 | } |
694 | 77 | SettingsDefaultSyncTarget { | 128 | SettingsDefaultSyncTarget { |
695 | 78 | id: defaultSyncTarget | 129 | id: defaultSyncTarget |
696 | @@ -97,8 +148,13 @@ | |||
697 | 97 | } | 148 | } |
698 | 98 | } | 149 | } |
699 | 99 | 150 | ||
700 | 151 | Keys.onDownPressed: addGoogleAccountItem.forceActiveFocus() | ||
701 | 152 | Keys.onRightPressed: addGoogleAccountItem.forceActiveFocus() | ||
702 | 153 | Keys.onLeftPressed: pageStack.removePages(root) | ||
703 | 154 | Keys.onEscapePressed: pageStack.removePages(root) | ||
704 | 100 | onActiveChanged: { | 155 | onActiveChanged: { |
705 | 101 | if (active) { | 156 | if (active) { |
706 | 157 | root.forceActiveFocus() | ||
707 | 102 | defaultSyncTarget.update() | 158 | defaultSyncTarget.update() |
708 | 103 | } | 159 | } |
709 | 104 | } | 160 | } |
710 | 105 | 161 | ||
711 | === modified file 'src/imports/Ubuntu/AddressBook/Base/ContactDetailBase.qml' | |||
712 | --- src/imports/Ubuntu/AddressBook/Base/ContactDetailBase.qml 2015-10-26 13:18:11 +0000 | |||
713 | +++ src/imports/Ubuntu/AddressBook/Base/ContactDetailBase.qml 2015-12-16 18:38:23 +0000 | |||
714 | @@ -18,15 +18,19 @@ | |||
715 | 18 | import QtContacts 5.0 as QtContacts | 18 | import QtContacts 5.0 as QtContacts |
716 | 19 | import Ubuntu.Components.ListItems 1.3 as ListItem | 19 | import Ubuntu.Components.ListItems 1.3 as ListItem |
717 | 20 | 20 | ||
719 | 21 | ListItem.Empty { | 21 | FocusScope { |
720 | 22 | id: root | 22 | id: root |
721 | 23 | objectName: detail ? "base_" + detailToString(detail.type, -1) + "_" + index : "" | 23 | objectName: detail ? "base_" + detailToString(detail.type, -1) + "_" + index : "" |
722 | 24 | 24 | ||
723 | 25 | property variant action: null | ||
724 | 25 | property QtObject contact: null | 26 | property QtObject contact: null |
725 | 26 | property QtObject detail: null | 27 | property QtObject detail: null |
726 | 27 | property variant fields: null | 28 | property variant fields: null |
727 | 28 | // help to test used to retrieve the correct element | 29 | // help to test used to retrieve the correct element |
728 | 29 | property int index: -1 | 30 | property int index: -1 |
729 | 31 | property alias highlightOnFocus: highlight.visible | ||
730 | 32 | |||
731 | 33 | signal clicked() | ||
732 | 30 | 34 | ||
733 | 31 | function detailToString(detail, field) | 35 | function detailToString(detail, field) |
734 | 32 | { | 36 | { |
735 | @@ -98,13 +102,23 @@ | |||
736 | 98 | } | 102 | } |
737 | 99 | } | 103 | } |
738 | 100 | 104 | ||
739 | 101 | highlightWhenPressed: false | ||
740 | 102 | showDivider: false | ||
741 | 103 | |||
742 | 104 | Rectangle { | 105 | Rectangle { |
747 | 105 | anchors.fill: parent | 106 | id: highlight |
748 | 106 | opacity: 0.1 | 107 | |
749 | 107 | visible: root.selected | 108 | anchors.fill: parent |
750 | 108 | z: 100 | 109 | visible: root.activeFocus |
751 | 110 | color: Theme.palette.selected.background | ||
752 | 111 | z: -1 | ||
753 | 112 | } | ||
754 | 113 | |||
755 | 114 | MouseArea { | ||
756 | 115 | anchors.fill: parent | ||
757 | 116 | |||
758 | 117 | onClicked: { | ||
759 | 118 | if (action) { | ||
760 | 119 | action.triggered(action) | ||
761 | 120 | } | ||
762 | 121 | root.clicked() | ||
763 | 122 | } | ||
764 | 109 | } | 123 | } |
765 | 110 | } | 124 | } |
766 | 111 | 125 | ||
767 | === modified file 'src/imports/Ubuntu/AddressBook/Base/ContactDetailGroupBase.qml' | |||
768 | --- src/imports/Ubuntu/AddressBook/Base/ContactDetailGroupBase.qml 2015-10-26 13:18:11 +0000 | |||
769 | +++ src/imports/Ubuntu/AddressBook/Base/ContactDetailGroupBase.qml 2015-12-16 18:38:23 +0000 | |||
770 | @@ -33,6 +33,7 @@ | |||
771 | 33 | property int minimumHeight: 0 | 33 | property int minimumHeight: 0 |
772 | 34 | property bool loaded: false | 34 | property bool loaded: false |
773 | 35 | property bool showEmpty: true | 35 | property bool showEmpty: true |
774 | 36 | property bool forceFocusOnFieldCreation: false | ||
775 | 36 | 37 | ||
776 | 37 | signal newFieldAdded(var index) | 38 | signal newFieldAdded(var index) |
777 | 38 | 39 | ||
778 | @@ -146,7 +147,7 @@ | |||
779 | 146 | newFields.push(detailItem.item) | 147 | newFields.push(detailItem.item) |
780 | 147 | root.newFieldAdded(detailItem.item) | 148 | root.newFieldAdded(detailItem.item) |
781 | 148 | root.inputFields = newFields | 149 | root.inputFields = newFields |
783 | 149 | if (root.loaded) { | 150 | if (root.loaded && root.forceFocusOnFieldCreation) { |
784 | 150 | item.forceActiveFocus() | 151 | item.forceActiveFocus() |
785 | 151 | } | 152 | } |
786 | 152 | } | 153 | } |
787 | 153 | 154 | ||
788 | === modified file 'src/imports/Ubuntu/AddressBook/Base/RemoveContactsDialog.qml' | |||
789 | --- src/imports/Ubuntu/AddressBook/Base/RemoveContactsDialog.qml 2015-10-26 13:18:11 +0000 | |||
790 | +++ src/imports/Ubuntu/AddressBook/Base/RemoveContactsDialog.qml 2015-12-16 18:38:23 +0000 | |||
791 | @@ -53,6 +53,7 @@ | |||
792 | 53 | } | 53 | } |
793 | 54 | 54 | ||
794 | 55 | Button { | 55 | Button { |
795 | 56 | id: acceptButton | ||
796 | 56 | objectName: "removeContactsDialog.Yes" | 57 | objectName: "removeContactsDialog.Yes" |
797 | 57 | anchors { | 58 | anchors { |
798 | 58 | left: parent.left | 59 | left: parent.left |
799 | @@ -61,10 +62,14 @@ | |||
800 | 61 | } | 62 | } |
801 | 62 | text: i18n.dtr("address-book-app", "Yes") | 63 | text: i18n.dtr("address-book-app", "Yes") |
802 | 63 | color: UbuntuColors.green | 64 | color: UbuntuColors.green |
804 | 64 | onClicked: accepted() | 65 | action: Action { |
805 | 66 | shortcut: "return" | ||
806 | 67 | onTriggered: accepted() | ||
807 | 68 | } | ||
808 | 65 | } | 69 | } |
809 | 66 | 70 | ||
810 | 67 | Button { | 71 | Button { |
811 | 72 | id: cancelButton | ||
812 | 68 | objectName: "removeContactsDialog.No" | 73 | objectName: "removeContactsDialog.No" |
813 | 69 | anchors { | 74 | anchors { |
814 | 70 | left: parent.left | 75 | left: parent.left |
815 | @@ -73,6 +78,9 @@ | |||
816 | 73 | } | 78 | } |
817 | 74 | text: i18n.dtr("address-book-app", "No") | 79 | text: i18n.dtr("address-book-app", "No") |
818 | 75 | color: UbuntuColors.red | 80 | color: UbuntuColors.red |
820 | 76 | onClicked: canceled() | 81 | action: Action { |
821 | 82 | shortcut: "esc" | ||
822 | 83 | onTriggered: canceled() | ||
823 | 84 | } | ||
824 | 77 | } | 85 | } |
825 | 78 | } | 86 | } |
826 | 79 | 87 | ||
827 | === modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAvatarEditor.qml' | |||
828 | --- src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAvatarEditor.qml 2015-10-29 18:11:08 +0000 | |||
829 | +++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAvatarEditor.qml 2015-12-16 18:38:23 +0000 | |||
830 | @@ -68,6 +68,7 @@ | |||
831 | 68 | detail: contact ? contact.detail(ContactDetail.Avatar) : null | 68 | detail: contact ? contact.detail(ContactDetail.Avatar) : null |
832 | 69 | implicitHeight: units.gu(8) | 69 | implicitHeight: units.gu(8) |
833 | 70 | implicitWidth: units.gu(8) | 70 | implicitWidth: units.gu(8) |
834 | 71 | highlightOnFocus: false | ||
835 | 71 | 72 | ||
836 | 72 | UbuntuShape { | 73 | UbuntuShape { |
837 | 73 | id: avatar | 74 | id: avatar |
838 | 74 | 75 | ||
839 | === modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailGroupWithTypeEditor.qml' | |||
840 | --- src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailGroupWithTypeEditor.qml 2015-10-26 13:18:11 +0000 | |||
841 | +++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailGroupWithTypeEditor.qml 2015-12-16 18:38:23 +0000 | |||
842 | @@ -98,29 +98,19 @@ | |||
843 | 98 | return changed | 98 | return changed |
844 | 99 | } | 99 | } |
845 | 100 | 100 | ||
847 | 101 | headerDelegate: Empty { | 101 | forceFocusOnFieldCreation: true |
848 | 102 | headerDelegate: Label { | ||
849 | 102 | id: header | 103 | id: header |
871 | 103 | highlightWhenPressed: false | 104 | |
872 | 104 | 105 | width: root.width - units.gu(4) | |
873 | 105 | width: root.width | 106 | x: units.gu(2) |
874 | 106 | height: units.gu(5) | 107 | height: units.gu(4) |
875 | 107 | // disable listview mouse area | 108 | text: root.title |
876 | 108 | __mouseArea.visible: false | 109 | // style |
877 | 109 | divider.anchors.leftMargin: units.gu(2) | 110 | fontSize: "medium" |
878 | 110 | divider.anchors.rightMargin: units.gu(2) | 111 | verticalAlignment: Text.AlignVCenter |
879 | 111 | 112 | ThinDivider { | |
880 | 112 | Label { | 113 | anchors.bottom: parent.bottom |
860 | 113 | anchors { | ||
861 | 114 | verticalCenter: parent.verticalCenter | ||
862 | 115 | left: parent.left | ||
863 | 116 | right: parent.right | ||
864 | 117 | margins: units.gu(2) | ||
865 | 118 | } | ||
866 | 119 | |||
867 | 120 | text: root.title | ||
868 | 121 | |||
869 | 122 | // style | ||
870 | 123 | fontSize: "medium" | ||
881 | 124 | } | 114 | } |
882 | 125 | } | 115 | } |
883 | 126 | 116 | ||
884 | @@ -157,7 +147,6 @@ | |||
885 | 157 | fields: root.fields | 147 | fields: root.fields |
886 | 158 | height: implicitHeight | 148 | height: implicitHeight |
887 | 159 | width: root.width | 149 | width: root.width |
888 | 160 | selected: activeFocus | ||
889 | 161 | 150 | ||
890 | 162 | inputMethodHints: root.inputMethodHints | 151 | inputMethodHints: root.inputMethodHints |
891 | 163 | onDetailChanged: updateCombo(false) | 152 | onDetailChanged: updateCombo(false) |
892 | 164 | 153 | ||
893 | === modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailNameEditor.qml' | |||
894 | --- src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailNameEditor.qml 2015-10-26 13:18:11 +0000 | |||
895 | +++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailNameEditor.qml 2015-12-16 18:38:23 +0000 | |||
896 | @@ -55,6 +55,7 @@ | |||
897 | 55 | spacing: units.gu(1) | 55 | spacing: units.gu(1) |
898 | 56 | detail: root.contact ? root.contact.name : null | 56 | detail: root.contact ? root.contact.name : null |
899 | 57 | fields: [ Name.FirstName, Name.LastName ] | 57 | fields: [ Name.FirstName, Name.LastName ] |
900 | 58 | highlightOnFocus: false | ||
901 | 58 | 59 | ||
902 | 59 | fieldDelegate: TextInputDetail { | 60 | fieldDelegate: TextInputDetail { |
903 | 60 | id: textInputDetail | 61 | id: textInputDetail |
904 | 61 | 62 | ||
905 | === modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailSyncTargetEditor.qml' | |||
906 | --- src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailSyncTargetEditor.qml 2015-12-11 16:43:39 +0000 | |||
907 | +++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailSyncTargetEditor.qml 2015-12-16 18:38:23 +0000 | |||
908 | @@ -75,6 +75,7 @@ | |||
909 | 75 | 75 | ||
910 | 76 | detail: root.contact ? contact.detail(ContactDetail.SyncTarget) : null | 76 | detail: root.contact ? contact.detail(ContactDetail.SyncTarget) : null |
911 | 77 | implicitHeight: root.isNewContact && sources.model && (sources.model.count > 1) ? myHeight : 0 | 77 | implicitHeight: root.isNewContact && sources.model && (sources.model.count > 1) ? myHeight : 0 |
912 | 78 | visible: height > 0 | ||
913 | 78 | 79 | ||
914 | 79 | ContactModel { | 80 | ContactModel { |
915 | 80 | id: sourceModel | 81 | id: sourceModel |
916 | @@ -188,8 +189,12 @@ | |||
917 | 188 | ThinDivider { | 189 | ThinDivider { |
918 | 189 | id: divider | 190 | id: divider |
919 | 190 | 191 | ||
922 | 191 | anchors.top: label.bottom | 192 | anchors { |
923 | 192 | } | 193 | top: label.bottom |
924 | 194 | leftMargin: units.gu(2) | ||
925 | 195 | rightMargin: units.gu(2) | ||
926 | 196 | } | ||
927 | 197 | } | ||
928 | 193 | 198 | ||
929 | 194 | OptionSelector { | 199 | OptionSelector { |
930 | 195 | id: sources | 200 | id: sources |
931 | 196 | 201 | ||
932 | === modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailWithTypeEditor.qml' | |||
933 | --- src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailWithTypeEditor.qml 2015-10-26 13:18:11 +0000 | |||
934 | +++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailWithTypeEditor.qml 2015-12-16 18:38:23 +0000 | |||
935 | @@ -70,7 +70,6 @@ | |||
936 | 70 | } | 70 | } |
937 | 71 | 71 | ||
938 | 72 | // disable listview mouse area | 72 | // disable listview mouse area |
939 | 73 | __mouseArea.visible: false | ||
940 | 74 | enabled: root.detail ? !root.detail.readOnly : false | 73 | enabled: root.detail ? !root.detail.readOnly : false |
941 | 75 | implicitHeight: detailTypeSelector.height + fieldValues.height + units.gu(2) | 74 | implicitHeight: detailTypeSelector.height + fieldValues.height + units.gu(2) |
942 | 76 | opacity: enabled ? 1.0 : 0.5 | 75 | opacity: enabled ? 1.0 : 0.5 |
943 | 77 | 76 | ||
944 | === modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactEditorPage.qml' | |||
945 | --- src/imports/Ubuntu/AddressBook/ContactEditor/ContactEditorPage.qml 2015-10-26 13:18:11 +0000 | |||
946 | +++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactEditorPage.qml 2015-12-16 18:38:23 +0000 | |||
947 | @@ -31,7 +31,6 @@ | |||
948 | 31 | property QtObject model: null | 31 | property QtObject model: null |
949 | 32 | property QtObject activeItem: null | 32 | property QtObject activeItem: null |
950 | 33 | 33 | ||
951 | 34 | |||
952 | 35 | property string initialFocusSection: "" | 34 | property string initialFocusSection: "" |
953 | 36 | property var newDetails: [] | 35 | property var newDetails: [] |
954 | 37 | 36 | ||
955 | @@ -40,9 +39,6 @@ | |||
956 | 40 | 39 | ||
957 | 41 | signal contactSaved(var contact); | 40 | signal contactSaved(var contact); |
958 | 42 | 41 | ||
959 | 43 | // priv | ||
960 | 44 | property bool _edgeReady: false | ||
961 | 45 | |||
962 | 46 | function cancel() { | 42 | function cancel() { |
963 | 47 | for (var i = 0; i < contactEditor.newDetails.length; ++i) { | 43 | for (var i = 0; i < contactEditor.newDetails.length; ++i) { |
964 | 48 | contactEditor.contact.removeDetail(contactEditor.newDetails[i]) | 44 | contactEditor.contact.removeDetail(contactEditor.newDetails[i]) |
965 | @@ -105,7 +101,7 @@ | |||
966 | 105 | } | 101 | } |
967 | 106 | 102 | ||
968 | 107 | function makeMeVisible(item) { | 103 | function makeMeVisible(item) { |
970 | 108 | if (!_edgeReady || !item) { | 104 | if (!enabled || !item) { |
971 | 109 | return | 105 | return |
972 | 110 | } | 106 | } |
973 | 111 | 107 | ||
974 | @@ -133,8 +129,6 @@ | |||
975 | 133 | function ready() | 129 | function ready() |
976 | 134 | { | 130 | { |
977 | 135 | enabled = true | 131 | enabled = true |
978 | 136 | _edgeReady = true | ||
979 | 137 | |||
980 | 138 | switch (contactEditor.initialFocusSection) | 132 | switch (contactEditor.initialFocusSection) |
981 | 139 | { | 133 | { |
982 | 140 | case "phones": | 134 | case "phones": |
983 | @@ -153,6 +147,7 @@ | |||
984 | 153 | } | 147 | } |
985 | 154 | 148 | ||
986 | 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") |
987 | 150 | enabled: false | ||
988 | 156 | 151 | ||
989 | 157 | Timer { | 152 | Timer { |
990 | 158 | id: focusTimer | 153 | id: focusTimer |
991 | @@ -181,7 +176,9 @@ | |||
992 | 181 | contentWidth: parent.width | 176 | contentWidth: parent.width |
993 | 182 | 177 | ||
994 | 183 | //after add a new field we need to wait for the contentHeight to change to scroll to the correct position | 178 | //after add a new field we need to wait for the contentHeight to change to scroll to the correct position |
996 | 184 | onContentHeightChanged: contactEditor.makeMeVisible(contactEditor.activeItem) | 179 | onContentHeightChanged: { |
997 | 180 | contactEditor.makeMeVisible(contactEditor.activeItem) | ||
998 | 181 | } | ||
999 | 185 | 182 | ||
1000 | 186 | Column { | 183 | Column { |
1001 | 187 | id: contents | 184 | id: contents |
1002 | @@ -195,6 +192,7 @@ | |||
1003 | 195 | height: childrenRect.height | 192 | height: childrenRect.height |
1004 | 196 | 193 | ||
1005 | 197 | Row { | 194 | Row { |
1006 | 195 | id: editEditor | ||
1007 | 198 | function save() | 196 | function save() |
1008 | 199 | { | 197 | { |
1009 | 200 | var avatarSave = avatarEditor.save() | 198 | var avatarSave = avatarEditor.save() |
1010 | @@ -213,7 +211,7 @@ | |||
1011 | 213 | leftMargin: units.gu(2) | 211 | leftMargin: units.gu(2) |
1012 | 214 | right: parent.right | 212 | right: parent.right |
1013 | 215 | } | 213 | } |
1015 | 216 | height: Math.max(avatarEditor.height, nameEditor.height) - units.gu(4) | 214 | height: Math.max(avatarEditor.height, nameEditor.height) - units.gu(2) |
1016 | 217 | 215 | ||
1017 | 218 | ContactDetailAvatarEditor { | 216 | ContactDetailAvatarEditor { |
1018 | 219 | id: avatarEditor | 217 | id: avatarEditor |
1019 | @@ -221,6 +219,7 @@ | |||
1020 | 221 | contact: contactEditor.contact | 219 | contact: contactEditor.contact |
1021 | 222 | height: implicitHeight | 220 | height: implicitHeight |
1022 | 223 | width: implicitWidth | 221 | width: implicitWidth |
1023 | 222 | anchors.verticalCenter: editEditor.verticalCenter | ||
1024 | 224 | } | 223 | } |
1025 | 225 | 224 | ||
1026 | 226 | ContactDetailNameEditor { | 225 | ContactDetailNameEditor { |
1027 | @@ -232,6 +231,7 @@ | |||
1028 | 232 | } | 231 | } |
1029 | 233 | } | 232 | } |
1030 | 234 | 233 | ||
1031 | 234 | |||
1032 | 235 | ContactDetailPhoneNumbersEditor { | 235 | ContactDetailPhoneNumbersEditor { |
1033 | 236 | id: phonesEditor | 236 | id: phonesEditor |
1034 | 237 | objectName: "phones" | 237 | objectName: "phones" |
1035 | @@ -301,8 +301,6 @@ | |||
1036 | 301 | left: parent.left | 301 | left: parent.left |
1037 | 302 | right: parent.right | 302 | right: parent.right |
1038 | 303 | } | 303 | } |
1039 | 304 | height: implicitHeight | ||
1040 | 305 | |||
1041 | 306 | onChanged: { | 304 | onChanged: { |
1042 | 307 | if (contactEditor.enabled && | 305 | if (contactEditor.enabled && |
1043 | 308 | !contactEditor.isNewContact && | 306 | !contactEditor.isNewContact && |
1044 | @@ -383,9 +381,13 @@ | |||
1045 | 383 | right: parent.right | 381 | right: parent.right |
1046 | 384 | margins: units.gu(2) | 382 | margins: units.gu(2) |
1047 | 385 | } | 383 | } |
1051 | 386 | onClicked: { | 384 | action: Action { |
1052 | 387 | var dialog = PopupUtils.open(removeContactDialog, null) | 385 | enabled: contactEditor.active && deleteButton.visible |
1053 | 388 | dialog.contacts = [contactEditor.contact] | 386 | shortcut: "Ctrl+Delete" |
1054 | 387 | onTriggered: { | ||
1055 | 388 | var dialog = PopupUtils.open(removeContactDialog, null) | ||
1056 | 389 | dialog.contacts = [contactEditor.contact] | ||
1057 | 390 | } | ||
1058 | 389 | } | 391 | } |
1059 | 390 | } | 392 | } |
1060 | 391 | 393 | ||
1061 | @@ -410,8 +412,8 @@ | |||
1062 | 410 | } | 412 | } |
1063 | 411 | } | 413 | } |
1064 | 412 | 414 | ||
1067 | 413 | Component.onCompleted: { | 415 | onActiveChanged: { |
1068 | 414 | if (!enabled) { | 416 | if (!active) { |
1069 | 415 | return | 417 | return |
1070 | 416 | } | 418 | } |
1071 | 417 | 419 | ||
1072 | @@ -475,10 +477,14 @@ | |||
1073 | 475 | } | 477 | } |
1074 | 476 | 478 | ||
1075 | 477 | // hide virtual keyboard if necessary | 479 | // hide virtual keyboard if necessary |
1077 | 478 | Component.onCompleted: Qt.inputMethod.hide() | 480 | Component.onCompleted: { |
1078 | 481 | contactEditor.enabled = false | ||
1079 | 482 | Qt.inputMethod.hide() | ||
1080 | 483 | } | ||
1081 | 479 | 484 | ||
1082 | 480 | // WORKAROUND: SDK element crash if pop the page where the dialog was created | 485 | // WORKAROUND: SDK element crash if pop the page where the dialog was created |
1083 | 481 | Component.onDestruction: { | 486 | Component.onDestruction: { |
1084 | 487 | contactEditor.enabled = true | ||
1085 | 482 | if (popPages) { | 488 | if (popPages) { |
1086 | 483 | if (contactEditor.pageStack.removePages) { | 489 | if (contactEditor.pageStack.removePages) { |
1087 | 484 | contactEditor.pageStack.removePages(contactEditor) | 490 | contactEditor.pageStack.removePages(contactEditor) |
1088 | 485 | 491 | ||
1089 | === modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/TextInputDetail.qml' | |||
1090 | --- src/imports/Ubuntu/AddressBook/ContactEditor/TextInputDetail.qml 2015-10-26 13:18:11 +0000 | |||
1091 | +++ src/imports/Ubuntu/AddressBook/ContactEditor/TextInputDetail.qml 2015-12-16 18:38:23 +0000 | |||
1092 | @@ -25,7 +25,11 @@ | |||
1093 | 25 | FocusScope { | 25 | FocusScope { |
1094 | 26 | id: root | 26 | id: root |
1095 | 27 | 27 | ||
1096 | 28 | //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822 | ||
1097 | 29 | //because of that we need this | ||
1098 | 30 | readonly property bool _allowFocus: true | ||
1099 | 28 | readonly property bool isTextField: true | 31 | readonly property bool isTextField: true |
1100 | 32 | |||
1101 | 29 | property QtObject detail | 33 | property QtObject detail |
1102 | 30 | property int field: -1 | 34 | property int field: -1 |
1103 | 31 | property variant originalValue: root.detail && (root.field >= 0) ? root.detail.value(root.field) : null | 35 | property variant originalValue: root.detail && (root.field >= 0) ? root.detail.value(root.field) : null |
1104 | @@ -67,6 +71,22 @@ | |||
1105 | 67 | PhoneNumberField { | 71 | PhoneNumberField { |
1106 | 68 | id: field | 72 | id: field |
1107 | 69 | 73 | ||
1108 | 74 | //WORKAROUND: Due the SDK bug #1514822, #1514850 we can not disable focus for some items | ||
1109 | 75 | //because of that we keep the focus only for textFields. This will block the user | ||
1110 | 76 | //to use keyboard on "add-field" combo box and some other functionalities | ||
1111 | 77 | function forceActiveFocusForNextField(keyEvent) | ||
1112 | 78 | { | ||
1113 | 79 | var backward = (keyEvent.modifiers & Qt.ShiftModifier) | ||
1114 | 80 | var next = field.nextItemInFocusChain(!backward) | ||
1115 | 81 | // only focus on TextInputDetails | ||
1116 | 82 | while (!next || !next.hasOwnProperty("isTextField")) { | ||
1117 | 83 | next = next.nextItemInFocusChain(!backward) | ||
1118 | 84 | } | ||
1119 | 85 | if (next) { | ||
1120 | 86 | next.forceActiveFocus() | ||
1121 | 87 | } | ||
1122 | 88 | } | ||
1123 | 89 | |||
1124 | 70 | anchors.fill: parent | 90 | anchors.fill: parent |
1125 | 71 | defaultRegion: PhoneUtils.defaultRegion | 91 | defaultRegion: PhoneUtils.defaultRegion |
1126 | 72 | autoFormat: false | 92 | autoFormat: false |
1127 | @@ -93,15 +113,9 @@ | |||
1128 | 93 | family: "Ubuntu" | 113 | family: "Ubuntu" |
1129 | 94 | pixelSize: activeFocus ? FontUtils.sizeToPixels("large") : FontUtils.sizeToPixels("medium") | 114 | pixelSize: activeFocus ? FontUtils.sizeToPixels("large") : FontUtils.sizeToPixels("medium") |
1130 | 95 | } | 115 | } |
1141 | 96 | Keys.onReturnPressed: { | 116 | |
1142 | 97 | var next = field.nextItemInFocusChain(true) | 117 | Keys.onReturnPressed: forceActiveFocusForNextField(event) |
1143 | 98 | // only focus on TextInputDetails | 118 | Keys.onTabPressed: forceActiveFocusForNextField(event) |
1144 | 99 | while (!next || !next.hasOwnProperty("isTextField")) { | 119 | Keys.onBacktabPressed: forceActiveFocusForNextField(event) |
1135 | 100 | next = next.nextItemInFocusChain(true) | ||
1136 | 101 | } | ||
1137 | 102 | if (next) { | ||
1138 | 103 | next.forceActiveFocus() | ||
1139 | 104 | } | ||
1140 | 105 | } | ||
1145 | 106 | } | 120 | } |
1146 | 107 | } | 121 | } |
1147 | 108 | 122 | ||
1148 | === modified file 'src/imports/Ubuntu/AddressBook/ContactView/ActionButton.qml' | |||
1149 | --- src/imports/Ubuntu/AddressBook/ContactView/ActionButton.qml 2015-10-26 13:18:11 +0000 | |||
1150 | +++ src/imports/Ubuntu/AddressBook/ContactView/ActionButton.qml 2015-12-16 18:38:23 +0000 | |||
1151 | @@ -30,5 +30,6 @@ | |||
1152 | 30 | anchors.centerIn: parent | 30 | anchors.centerIn: parent |
1153 | 31 | height: root.iconSize | 31 | height: root.iconSize |
1154 | 32 | width: root.iconSize | 32 | width: root.iconSize |
1155 | 33 | color: root.activeFocus ? UbuntuColors.orange : "gray" | ||
1156 | 33 | } | 34 | } |
1157 | 34 | } | 35 | } |
1158 | 35 | 36 | ||
1159 | === modified file 'src/imports/Ubuntu/AddressBook/ContactView/BasicFieldView.qml' | |||
1160 | --- src/imports/Ubuntu/AddressBook/ContactView/BasicFieldView.qml 2015-10-26 13:18:11 +0000 | |||
1161 | +++ src/imports/Ubuntu/AddressBook/ContactView/BasicFieldView.qml 2015-12-16 18:38:23 +0000 | |||
1162 | @@ -27,6 +27,7 @@ | |||
1163 | 27 | property variant fields: null | 27 | property variant fields: null |
1164 | 28 | property int parentIndex: -1 | 28 | property int parentIndex: -1 |
1165 | 29 | 29 | ||
1166 | 30 | activeFocusOnTab: false | ||
1167 | 30 | implicitHeight: typeLabel.height + fieldValues.height + units.gu(2) | 31 | implicitHeight: typeLabel.height + fieldValues.height + units.gu(2) |
1168 | 31 | 32 | ||
1169 | 32 | Column { | 33 | Column { |
1170 | 33 | 34 | ||
1171 | === modified file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailAvatarView.qml' | |||
1172 | --- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailAvatarView.qml 2015-11-16 20:12:41 +0000 | |||
1173 | +++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailAvatarView.qml 2015-12-16 18:38:23 +0000 | |||
1174 | @@ -29,6 +29,7 @@ | |||
1175 | 29 | 29 | ||
1176 | 30 | implicitHeight: units.gu(12) | 30 | implicitHeight: units.gu(12) |
1177 | 31 | implicitWidth: parent.width | 31 | implicitWidth: parent.width |
1178 | 32 | activeFocusOnTab: false | ||
1179 | 32 | 33 | ||
1180 | 33 | Connections { | 34 | Connections { |
1181 | 34 | id: connections | 35 | id: connections |
1182 | 35 | 36 | ||
1183 | === modified file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailGroupWithTypeView.qml' | |||
1184 | --- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailGroupWithTypeView.qml 2015-10-26 13:18:11 +0000 | |||
1185 | +++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailGroupWithTypeView.qml 2015-12-16 18:38:23 +0000 | |||
1186 | @@ -18,8 +18,7 @@ | |||
1187 | 18 | import QtContacts 5.0 as QtContacts | 18 | import QtContacts 5.0 as QtContacts |
1188 | 19 | 19 | ||
1189 | 20 | import Ubuntu.Components 1.3 | 20 | import Ubuntu.Components 1.3 |
1192 | 21 | import Ubuntu.Components.ListItems 1.3 as ListItem | 21 | import Ubuntu.Components.ListItems 1.3 |
1191 | 22 | |||
1193 | 23 | import Ubuntu.AddressBook.Base 0.1 | 22 | import Ubuntu.AddressBook.Base 0.1 |
1194 | 24 | 23 | ||
1195 | 25 | ContactDetailGroupWithTypeBase { | 24 | ContactDetailGroupWithTypeBase { |
1196 | @@ -29,25 +28,18 @@ | |||
1197 | 29 | signal actionTrigerred(string actionName, QtObject detail) | 28 | signal actionTrigerred(string actionName, QtObject detail) |
1198 | 30 | 29 | ||
1199 | 31 | showEmpty: false | 30 | showEmpty: false |
1219 | 32 | headerDelegate: ListItem.Empty { | 31 | headerDelegate: Label { |
1220 | 33 | highlightWhenPressed: false | 32 | id: header |
1221 | 34 | 33 | ||
1222 | 35 | divider.anchors.leftMargin: units.gu(2) | 34 | width: root.width - units.gu(4) |
1223 | 36 | divider.anchors.rightMargin: units.gu(2) | 35 | x: units.gu(2) |
1224 | 37 | width: root.width | 36 | height: units.gu(4) |
1225 | 38 | height: units.gu(5) | 37 | text: root.title |
1226 | 39 | Label { | 38 | // style |
1227 | 40 | anchors { | 39 | fontSize: "medium" |
1228 | 41 | verticalCenter: parent.verticalCenter | 40 | verticalAlignment: Text.AlignVCenter |
1229 | 42 | left: parent.left | 41 | ThinDivider { |
1230 | 43 | right: parent.right | 42 | anchors.bottom: parent.bottom |
1212 | 44 | margins: units.gu(2) | ||
1213 | 45 | } | ||
1214 | 46 | |||
1215 | 47 | text: root.title | ||
1216 | 48 | |||
1217 | 49 | // style | ||
1218 | 50 | fontSize: "medium" | ||
1231 | 51 | } | 43 | } |
1232 | 52 | } | 44 | } |
1233 | 53 | 45 | ||
1234 | 54 | 46 | ||
1235 | === modified file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailNameView.qml' | |||
1236 | --- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailNameView.qml 2015-10-26 13:18:11 +0000 | |||
1237 | +++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailNameView.qml 2015-12-16 18:38:23 +0000 | |||
1238 | @@ -25,7 +25,7 @@ | |||
1239 | 25 | 25 | ||
1240 | 26 | detail: root.contact ? root.contact.name : null | 26 | detail: root.contact ? root.contact.name : null |
1241 | 27 | implicitHeight: label.paintedHeight + (label.anchors.margins * 2) | 27 | implicitHeight: label.paintedHeight + (label.anchors.margins * 2) |
1243 | 28 | 28 | activeFocusOnTab: false | |
1244 | 29 | 29 | ||
1245 | 30 | Label { | 30 | Label { |
1246 | 31 | id: label | 31 | id: label |
1247 | 32 | 32 | ||
1248 | === modified file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailSyncTargetView.qml' | |||
1249 | --- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailSyncTargetView.qml 2015-10-26 13:18:11 +0000 | |||
1250 | +++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailSyncTargetView.qml 2015-12-16 18:38:23 +0000 | |||
1251 | @@ -50,6 +50,7 @@ | |||
1252 | 50 | defaultIcon: "image://theme/contact-group" | 50 | defaultIcon: "image://theme/contact-group" |
1253 | 51 | detailType: ContactDetail.SyncTarget | 51 | detailType: ContactDetail.SyncTarget |
1254 | 52 | typeModel: null | 52 | typeModel: null |
1255 | 53 | activeFocusOnTab: false | ||
1256 | 53 | 54 | ||
1257 | 54 | fields: [ SyncTarget.SyncTarget ] | 55 | fields: [ SyncTarget.SyncTarget ] |
1258 | 55 | 56 | ||
1259 | @@ -76,7 +77,7 @@ | |||
1260 | 76 | 77 | ||
1261 | 77 | height: implicitHeight | 78 | height: implicitHeight |
1262 | 78 | width: root.width | 79 | width: root.width |
1264 | 79 | 80 | activeFocusOnTab: false | |
1265 | 80 | onClicked: root.actionTrigerred(root.defaultAction.name, detail) | 81 | onClicked: root.actionTrigerred(root.defaultAction.name, detail) |
1266 | 81 | 82 | ||
1267 | 82 | function overrideValue(detail, field) | 83 | function overrideValue(detail, field) |
1268 | 83 | 84 | ||
1269 | === modified file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailWithTypeView.qml' | |||
1270 | --- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailWithTypeView.qml 2015-10-26 13:18:11 +0000 | |||
1271 | +++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailWithTypeView.qml 2015-12-16 18:38:23 +0000 | |||
1272 | @@ -43,6 +43,7 @@ | |||
1273 | 43 | return detail.value(field) | 43 | return detail.value(field) |
1274 | 44 | } | 44 | } |
1275 | 45 | 45 | ||
1276 | 46 | activeFocusOnTab: icon.visible | ||
1277 | 46 | implicitHeight: view.implicitHeight | 47 | implicitHeight: view.implicitHeight |
1278 | 47 | onIsReadyChanged: populateValues() | 48 | onIsReadyChanged: populateValues() |
1279 | 48 | 49 | ||
1280 | @@ -78,5 +79,7 @@ | |||
1281 | 78 | width: root.action && (root.action.iconName !== "") ? units.gu(2.5) : 0 | 79 | width: root.action && (root.action.iconName !== "") ? units.gu(2.5) : 0 |
1282 | 79 | height: width | 80 | height: width |
1283 | 80 | name: root.action ? root.action.iconName : "" | 81 | name: root.action ? root.action.iconName : "" |
1284 | 82 | color: root.activeFocus ? UbuntuColors.orange : "gray" | ||
1285 | 83 | visible: width > 0 | ||
1286 | 81 | } | 84 | } |
1287 | 82 | } | 85 | } |
1288 | 83 | 86 | ||
1289 | === modified file 'src/imports/Ubuntu/Contacts/ContactListView.qml' | |||
1290 | --- src/imports/Ubuntu/Contacts/ContactListView.qml 2015-11-16 22:12:29 +0000 | |||
1291 | +++ src/imports/Ubuntu/Contacts/ContactListView.qml 2015-12-16 18:38:23 +0000 | |||
1292 | @@ -42,7 +42,7 @@ | |||
1293 | 42 | } | 42 | } |
1294 | 43 | \endqml | 43 | \endqml |
1295 | 44 | */ | 44 | */ |
1297 | 45 | Item { | 45 | FocusScope { |
1298 | 46 | id: root | 46 | id: root |
1299 | 47 | 47 | ||
1300 | 48 | readonly property alias view: view | 48 | readonly property alias view: view |
1301 | @@ -253,6 +253,10 @@ | |||
1302 | 253 | 253 | ||
1303 | 254 | property var _busyDialog: null | 254 | property var _busyDialog: null |
1304 | 255 | 255 | ||
1305 | 256 | //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822 | ||
1306 | 257 | //because of that we need this | ||
1307 | 258 | property bool _allowFocus: true | ||
1308 | 259 | |||
1309 | 256 | /*! | 260 | /*! |
1310 | 257 | This handler is called when the selection mode is finished without be canceled | 261 | This handler is called when the selection mode is finished without be canceled |
1311 | 258 | */ | 262 | */ |
1312 | @@ -372,6 +376,8 @@ | |||
1313 | 372 | buteoSync.startSyncByCategory("contacts") | 376 | buteoSync.startSyncByCategory("contacts") |
1314 | 373 | } | 377 | } |
1315 | 374 | 378 | ||
1316 | 379 | focus: true | ||
1317 | 380 | |||
1318 | 375 | ContactSimpleListView { | 381 | ContactSimpleListView { |
1319 | 376 | id: view | 382 | id: view |
1320 | 377 | 383 | ||
1321 | @@ -624,4 +630,23 @@ | |||
1322 | 624 | !view.favouritesIsSelected && | 630 | !view.favouritesIsSelected && |
1323 | 625 | !isSearching ? sourceFile : "" | 631 | !isSearching ? sourceFile : "" |
1324 | 626 | } | 632 | } |
1325 | 633 | |||
1326 | 634 | Keys.onUpPressed: { | ||
1327 | 635 | //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822 | ||
1328 | 636 | //because of that we need this | ||
1329 | 637 | if (view.currentIndex == 0) { | ||
1330 | 638 | pageStack._nextItemInFocusChain(view, false) | ||
1331 | 639 | } else { | ||
1332 | 640 | view.currentIndex -= 1 | ||
1333 | 641 | } | ||
1334 | 642 | } | ||
1335 | 643 | Keys.onDownPressed: { | ||
1336 | 644 | //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822 | ||
1337 | 645 | //because of that we need this | ||
1338 | 646 | if (view.currentIndex == (view.count - 1)) { | ||
1339 | 647 | //DO nothing | ||
1340 | 648 | } else { | ||
1341 | 649 | view.currentIndex += 1 | ||
1342 | 650 | } | ||
1343 | 651 | } | ||
1344 | 627 | } | 652 | } |
1345 | 628 | 653 | ||
1346 | === modified file 'src/imports/Ubuntu/Contacts/ContactSimpleListView.qml' | |||
1347 | --- src/imports/Ubuntu/Contacts/ContactSimpleListView.qml 2015-11-16 22:12:29 +0000 | |||
1348 | +++ src/imports/Ubuntu/Contacts/ContactSimpleListView.qml 2015-12-16 18:38:23 +0000 | |||
1349 | @@ -204,7 +204,8 @@ | |||
1350 | 204 | */ | 204 | */ |
1351 | 205 | function positionViewAtContact(contact) | 205 | function positionViewAtContact(contact) |
1352 | 206 | { | 206 | { |
1354 | 207 | positionViewAtIndex(getIndex(contact), ListView.Center) | 207 | currentIndex = getIndex(contact) |
1355 | 208 | positionViewAtIndex(currentIndex, ListView.Center) | ||
1356 | 208 | } | 209 | } |
1357 | 209 | 210 | ||
1358 | 210 | /*! | 211 | /*! |
1359 | @@ -213,7 +214,9 @@ | |||
1360 | 213 | */ | 214 | */ |
1361 | 214 | function _fetchContact(index, contact) | 215 | function _fetchContact(index, contact) |
1362 | 215 | { | 216 | { |
1364 | 216 | contactFetch.fetchContact(contact.contactId) | 217 | if (contact) { |
1365 | 218 | contactFetch.fetchContact(contact.contactId) | ||
1366 | 219 | } | ||
1367 | 217 | } | 220 | } |
1368 | 218 | 221 | ||
1369 | 219 | function _updateSwipeState(item) | 222 | function _updateSwipeState(item) |
1370 | @@ -235,7 +238,6 @@ | |||
1371 | 235 | } | 238 | } |
1372 | 236 | 239 | ||
1373 | 237 | highlightFollowsCurrentItem: true | 240 | highlightFollowsCurrentItem: true |
1374 | 238 | currentIndex: -1 | ||
1375 | 239 | section { | 241 | section { |
1376 | 240 | property: showSections ? "contact.tag.tag" : "" | 242 | property: showSections ? "contact.tag.tag" : "" |
1377 | 241 | criteria: ViewSection.FirstCharacter | 243 | criteria: ViewSection.FirstCharacter |
1378 | @@ -255,7 +257,6 @@ | |||
1379 | 255 | dirtyModel.restart() | 257 | dirtyModel.restart() |
1380 | 256 | } | 258 | } |
1381 | 257 | 259 | ||
1382 | 258 | onFlickStarted: view.currentIndex = -1 | ||
1383 | 259 | listDelegate: ContactDelegate { | 260 | listDelegate: ContactDelegate { |
1384 | 260 | id: contactDelegate | 261 | id: contactDelegate |
1385 | 261 | 262 | ||
1386 | @@ -270,6 +271,8 @@ | |||
1387 | 270 | width: parent.width | 271 | width: parent.width |
1388 | 271 | selected: (contactListView.multiSelectionEnabled && contactListView.isSelected(contactDelegate)) | 272 | selected: (contactListView.multiSelectionEnabled && contactListView.isSelected(contactDelegate)) |
1389 | 272 | || (contactListView.highlightSelected && (contactListView.currentIndex == index)) | 273 | || (contactListView.highlightSelected && (contactListView.currentIndex == index)) |
1390 | 274 | selectedColor: contactListView.parent.activeFocus && !contactListView.isInSelectionMode ? UbuntuColors.orange : | ||
1391 | 275 | Theme.palette.selected.background | ||
1392 | 273 | selectionMode: contactListView.isInSelectionMode | 276 | selectionMode: contactListView.isInSelectionMode |
1393 | 274 | defaultAvatarUrl: contactListView.defaultAvatarImageUrl | 277 | defaultAvatarUrl: contactListView.defaultAvatarImageUrl |
1394 | 275 | isCurrentItem: ListView.isCurrentItem | 278 | isCurrentItem: ListView.isCurrentItem |
1395 | @@ -371,13 +374,4 @@ | |||
1396 | 371 | property int pendingTargetIndex: 0 | 374 | property int pendingTargetIndex: 0 |
1397 | 372 | property variant pendingTargetMode: null | 375 | property variant pendingTargetMode: null |
1398 | 373 | } | 376 | } |
1399 | 374 | |||
1400 | 375 | Connections { | ||
1401 | 376 | target: Qt.application | ||
1402 | 377 | onActiveChanged: { | ||
1403 | 378 | if (!Qt.application.active) { | ||
1404 | 379 | currentIndex = -1 | ||
1405 | 380 | } | ||
1406 | 381 | } | ||
1407 | 382 | } | ||
1408 | 383 | } | 377 | } |
1409 | 384 | 378 | ||
1410 | === modified file 'src/imports/Ubuntu/Contacts/FastScroll.qml' | |||
1411 | --- src/imports/Ubuntu/Contacts/FastScroll.qml 2015-10-26 13:18:11 +0000 | |||
1412 | +++ src/imports/Ubuntu/Contacts/FastScroll.qml 2015-12-16 18:38:23 +0000 | |||
1413 | @@ -71,19 +71,11 @@ | |||
1414 | 71 | } | 71 | } |
1415 | 72 | } | 72 | } |
1416 | 73 | 73 | ||
1417 | 74 | Connections { | ||
1418 | 75 | target: listView | ||
1419 | 76 | onCurrentIndexChanged: { | ||
1420 | 77 | if (currentIndex != -1) { | ||
1421 | 78 | rail.opacity = 0.0 | ||
1422 | 79 | } | ||
1423 | 80 | } | ||
1424 | 81 | } | ||
1425 | 82 | 74 | ||
1426 | 83 | Rectangle { | 75 | Rectangle { |
1427 | 84 | id: magnified | 76 | id: magnified |
1428 | 85 | 77 | ||
1430 | 86 | color: Theme.palette.normal.overlay | 78 | color: Theme.palette.normal.foreground |
1431 | 87 | radius: height * 0.3 | 79 | radius: height * 0.3 |
1432 | 88 | height: pinSize * 2 | 80 | height: pinSize * 2 |
1433 | 89 | width: height | 81 | width: height |
1434 | @@ -99,6 +91,7 @@ | |||
1435 | 99 | } | 91 | } |
1436 | 100 | 92 | ||
1437 | 101 | Label { | 93 | Label { |
1438 | 94 | color: Theme.palette.normal.foregroundText | ||
1439 | 102 | anchors.fill: parent | 95 | anchors.fill: parent |
1440 | 103 | horizontalAlignment: Text.AlignHCenter | 96 | horizontalAlignment: Text.AlignHCenter |
1441 | 104 | verticalAlignment: Text.AlignVCenter | 97 | verticalAlignment: Text.AlignVCenter |
1442 | @@ -141,8 +134,7 @@ | |||
1443 | 141 | id: rail | 134 | id: rail |
1444 | 142 | 135 | ||
1445 | 143 | property bool isVisible: root.enabled && | 136 | property bool isVisible: root.enabled && |
1448 | 144 | (listView.flicking || dragArea.pressed) && | 137 | (listView.flicking || dragArea.pressed) |
1447 | 145 | (listView.currentIndex == -1) | ||
1449 | 146 | anchors { | 138 | anchors { |
1450 | 147 | right: parent.right | 139 | right: parent.right |
1451 | 148 | rightMargin: units.gu(2) | 140 | rightMargin: units.gu(2) |
1452 | @@ -181,7 +173,7 @@ | |||
1453 | 181 | horizontalAlignment: Text.AlignHCenter | 173 | horizontalAlignment: Text.AlignHCenter |
1454 | 182 | text: modelData | 174 | text: modelData |
1455 | 183 | fontSize: "x-small" | 175 | fontSize: "x-small" |
1457 | 184 | color: cursor.y === y ? "white" : Theme.palette.selected.backgroundText | 176 | color: cursor.y === y ? Theme.palette.normal.foregroundText : Theme.palette.selected.backgroundText |
1458 | 185 | opacity: !internal.modelDirty && Sections.contains(text) ? 1.0 : 0.5 | 177 | opacity: !internal.modelDirty && Sections.contains(text) ? 1.0 : 0.5 |
1459 | 186 | } | 178 | } |
1460 | 187 | } | 179 | } |
FAILED: Continuous integration, rev:505 jenkins. qa.ubuntu. com/job/ address- book-app- ci/1000/ jenkins. qa.ubuntu. com/job/ address- book-app- vivid-i386- ci/303/ console jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- vivid-touch/ 5114/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 5126/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/address- book-app- ci/1000/ rebuild
http://