Merge lp:~renatofilho/address-book-app/new-bottom-edge into lp:address-book-app

Proposed by Renato Araujo Oliveira Filho
Status: Superseded
Proposed branch: lp:~renatofilho/address-book-app/new-bottom-edge
Merge into: lp:address-book-app
Diff against target: 2077 lines (+541/-660)
31 files modified
src/imports/ABContactEditorPage.qml (+8/-5)
src/imports/ABContactListPage.qml (+161/-166)
src/imports/ABContactViewPage.qml (+31/-3)
src/imports/ABNewContactBottomEdge.qml (+67/-0)
src/imports/BottomEdge.qml (+0/-321)
src/imports/BottomEdgeShadow.qml (+0/-31)
src/imports/CMakeLists.txt (+1/-2)
src/imports/MainWindow.qml (+29/-1)
src/imports/Settings/SettingsPage.qml (+54/-3)
src/imports/Ubuntu/AddressBook/Base/ContactDetailBase.qml (+20/-5)
src/imports/Ubuntu/AddressBook/Base/ContactDetailGroupBase.qml (+2/-1)
src/imports/Ubuntu/AddressBook/Base/RemoveContactsDialog.qml (+19/-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 (+8/-3)
src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailWithTypeEditor.qml (+0/-1)
src/imports/Ubuntu/AddressBook/ContactEditor/ContactEditorPage.qml (+25/-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 (+2/-0)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailAvatarView.qml (+2/-0)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailGroupWithTypeView.qml (+13/-21)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailNameView.qml (+2/-1)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailSyncTargetView.qml (+2/-1)
src/imports/Ubuntu/AddressBook/ContactView/ContactDetailWithTypeView.qml (+4/-0)
src/imports/Ubuntu/AddressBook/ContactView/ContactViewPage.qml (+1/-0)
src/imports/Ubuntu/Contacts/ContactDelegate.qml (+1/-0)
src/imports/Ubuntu/Contacts/ContactListView.qml (+41/-19)
src/imports/Ubuntu/Contacts/ContactSimpleListView.qml (+6/-13)
src/imports/Ubuntu/Contacts/FastScroll.qml (+3/-11)
To merge this branch: bzr merge lp:~renatofilho/address-book-app/new-bottom-edge
Reviewer Review Type Date Requested Status
Ubuntu Phablet Team Pending
Review via email: mp+279612@code.launchpad.net

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

Commit message

Implement the new bottom edge using the SDK component.

To post a comment you must log in.
548. By Renato Araujo Oliveira Filho

Update BottomEdge editor page with the correct contact model.

549. By Renato Araujo Oliveira Filho

Removed support for deprecated application arguments.

550. By Renato Araujo Oliveira Filho

Make use of the new SDK PageHearder API.

551. By Renato Araujo Oliveira Filho

WORKAROUND: Set 'QuickUtils.mouseAttached = true' to avoid problems with bottom edge on desktop;

552. By Renato Araujo Oliveira Filho

Make sure that a contact is selected on application startup.

553. By Renato Araujo Oliveira Filho

Push contact view page component instead of object to avoid problems with page stack.

554. By Renato Araujo Oliveira Filho

Make bottom edge component on contact view available only when in dual column layout.

555. By Renato Araujo Oliveira Filho

Does not use navigationActions.

556. By Renato Araujo Oliveira Filho

Trunk merged.

557. By Renato Araujo Oliveira Filho

Fix problems with previous merge.

558. By Renato Araujo Oliveira Filho

Remove debug message.
Fix focus on contact list after close contact editor page.
Fix ambigous 'esc' short cut when editor page is opened.

559. By Renato Araujo Oliveira Filho

Create a empty state page for multi column layout.

560. By Renato Araujo Oliveira Filho

Move focus back to contaclist after close ContactEditor page.
Add 'esc' shortcut to close BottomEdge.

561. By Renato Araujo Oliveira Filho

Change bottom edge visual if a mouse is present.

562. By Renato Araujo Oliveira Filho

Update test to use new header API.

563. By Renato Araujo Oliveira Filho

Trunk merged.

564. By Renato Araujo Oliveira Filho

Create a leading actions property on Contact editor page to avoid problems with SDK replacing it.
Check if the mouse event is a real mouse event and not a touch event.

565. By Renato Araujo Oliveira Filho

Only enable keyboard visuals after pres 'down' key. To avoid enabling it while using the virtual keyboard.

566. By Renato Araujo Oliveira Filho

Sync load bottom edge page.

567. By Renato Araujo Oliveira Filho

Load BottomEdge component async to avoid delays on app startup.
Fix bottom edge contents size.

568. By Renato Araujo Oliveira Filho

Does not move contact list when vkb appears on bottom edge page.

569. By Renato Araujo Oliveira Filho

Trunk merged.

570. By Renato Araujo Oliveira Filho

Fixed 'back' action state while searching.

571. By Renato Araujo Oliveira Filho

Compile ContactEditorPage before push it on stack.

572. By Renato Araujo Oliveira Filho

Avoid stole contact list focus while creating bottom edge component.

573. By Renato Araujo Oliveira Filho

Disable edit button after first click on it. (avoid push the page more than once)

574. By Renato Araujo Oliveira Filho

highlight contact on click.

575. By Renato Araujo Oliveira Filho

Quick focus on contact name after open bottom edge page.

576. By Renato Araujo Oliveira Filho

Does not highlight settings item if not using keyboard.

577. By Renato Araujo Oliveira Filho

Update autopilot tests to work with the new bottom edge component.

578. By Renato Araujo Oliveira Filho

Removed debug message.

579. By Renato Araujo Oliveira Filho

Disable bottom edge while searching on multi colum layout.

580. By Renato Araujo Oliveira Filho

Cancel search after open bottom edge.

581. By Renato Araujo Oliveira Filho

Update contact view title on contact name change.

582. By Renato Araujo Oliveira Filho

Removed debug message.

583. By Renato Araujo Oliveira Filho

Fetch selected contact on application expansion.

584. By Renato Araujo Oliveira Filho

Use unity 8 private api to detect mouse and keyboard.

585. By Renato Araujo Oliveira Filho

Fetch first contact if no contact is selected after close bottom edge.

586. By Renato Araujo Oliveira Filho

Fixed field focus while adding new fields on contact editor.

587. By Renato Araujo Oliveira Filho

Disable bottom edge shortcut on contact list while it is not active.

588. By Renato Araujo Oliveira Filho

Update autopilot tests to work with the new bottom edge components.

589. By Renato Araujo Oliveira Filho

Update contact delegate click animation.

590. By Renato Araujo Oliveira Filho

Remove unused variables.

591. By Renato Araujo Oliveira Filho

Fixed focus on wrong field after add a new contact detail

592. By Renato Araujo Oliveira Filho

Focus contact list after close bottom edge.

593. By Renato Araujo Oliveira Filho

set minimum width and height for the app.

594. By Renato Araujo Oliveira Filho

Fixed focus on contact deletion.

595. By Renato Araujo Oliveira Filho

Fixed share component page to work with pagestack

596. By Renato Araujo Oliveira Filho

Reduce the application width necessary to change into multi column layout.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/imports/ABContactEditorPage.qml'
2--- src/imports/ABContactEditorPage.qml 2015-10-26 13:18:11 +0000
3+++ src/imports/ABContactEditorPage.qml 2015-12-04 15:09:43 +0000
4@@ -34,10 +34,10 @@
5 name: "cancel"
6
7 text: i18n.tr("Cancel")
8- iconName: "back"
9- onTriggered: {
10- root.cancel()
11- }
12+ iconName: "down"
13+ enabled: root.active && root.enabled
14+ shortcut: "Esc"
15+ onTriggered: root.cancel()
16 }
17
18 head.actions: [
19@@ -46,9 +46,10 @@
20 name: "save"
21
22 text: i18n.tr("Save")
23+ shortcut: "Ctrl+s"
24 iconName: "ok"
25 // disable save button while avatar scale still running
26- enabled: root.isContactValid
27+ enabled: root.isContactValid && root.active
28 onTriggered: root.save()
29 }
30 ]
31@@ -58,4 +59,6 @@
32 pageStack.contactListPage.moveListToContact(contact)
33 }
34 }
35+
36+ Component.onDestruction: console.debug("Destroy editor")
37 }
38
39=== modified file 'src/imports/ABContactListPage.qml'
40--- src/imports/ABContactListPage.qml 2015-11-25 16:59:11 +0000
41+++ src/imports/ABContactListPage.qml 2015-12-04 15:09:43 +0000
42@@ -1,4 +1,4 @@
43-/*
44+/*
45 * Copyright (C) 2012-2015 Canonical, Ltd.
46 *
47 * This program is free software; you can redistribute it and/or modify
48@@ -30,18 +30,19 @@
49 id: mainPage
50 objectName: "contactListPage"
51
52+ property var viewPage: null
53 property bool pickMode: false
54 property alias contentHubTransfer: contactExporter.activeTransfer
55 property bool pickMultipleContacts: false
56 property QtObject contactIndex: null
57 property string newPhoneToAdd: ""
58 property alias contactManager: contactList.manager
59- property Page contactViewPage: null
60- property Page contactEditorPage: null
61 property var _busyDialog: null
62 property bool _importingTestData: false
63+ property bool _creatingContact: false
64
65- readonly property bool bottomEdgePageOpened: bottomEdge.opened && bottomEdge.fullLoaded
66+ readonly property string currentViewContactId: viewPage && viewPage.contact ? viewPage.contact.contactId : ""
67+ readonly property bool bottomEdgePageOpened: false //bottomEdge.opened && bottomEdge.fullLoaded
68 readonly property bool isEmpty: (contactList.count === 0)
69 readonly property bool allowToQuit: (application.callbackApplication.length > 0)
70 readonly property var contactModel: contactList.listModel ? contactList.listModel : null
71@@ -61,30 +62,31 @@
72 function createContactWithPhoneNumber(phoneNumber)
73 {
74 var newContact = ContactsJS.createEmptyContact(phoneNumber, mainPage);
75- openEditPage({model: contactList.listModel,
76- contact: newContact,
77- initialFocusSection: "name"},
78- mainPage);
79- }
80-
81- function openEditPage(editPageProperties, sourcePage) {
82- var component = Qt.createComponent(Qt.resolvedUrl("ABContactEditorPage.qml"))
83- if (component.status === Component.Ready) {
84- mainPage.contactEditorPage = component.createObject(mainPage, editPageProperties)
85- pageStack.addPageToNextColumn(sourcePage, mainPage.contactEditorPage)
86- }
87+ pageStack.bottomEdge.editContact(newContact, mainPage.contactModel)
88 }
89
90 function openViewPage(viewPageProperties) {
91+ if (mainPage.viewPage) {
92+ pageStack.removePages(mainPage.viewPage)
93+ mainPage.viewPage.destroy()
94+ mainPage.viewPage = null
95+ }
96+
97 var component = Qt.createComponent(Qt.resolvedUrl("ABContactViewPage.qml"))
98 if (component.status === Component.Ready) {
99- mainPage.contactViewPage = component.createObject(mainPage, viewPageProperties)
100- pageStack.addPageToNextColumn(mainPage, mainPage.contactViewPage)
101+ mainPage.viewPage = component.createObject(mainPage, viewPageProperties)
102+ pageStack.addPageToNextColumn(mainPage, mainPage.viewPage)
103 }
104 }
105
106 function showContact(contact)
107 {
108+ var currentContact = contactList.listModel.contacts[contactList.currentIndex]
109+ if (currentContact && (mainPage.currentViewContactId === currentContact.contactId)) {
110+ console.debug("Skip show contact")
111+ return
112+ }
113+
114 // go back to normal state if not searching
115 if ((state !== "searching") &&
116 (state !== "vcardImported")) {
117@@ -136,14 +138,12 @@
118
119 function moveListToContact(contact)
120 {
121- // skipt it if searching or importing contacts
122- if ((state === "searching") ||
123- (state === "vcardImported")) {
124- return
125+ if ((state !== "searching") &&
126+ (state !== "vcardImported")) {
127+ mainPage.state = "default"
128 }
129
130 contactIndex = contact
131- mainPage.state = "default"
132 // this means a new contact was created
133 if (mainPage.allowToQuit) {
134 application.goBackToSourceApp()
135@@ -157,42 +157,62 @@
136 contactList.reset()
137 }
138
139- function showContactEditorPage(editorPage) {
140- contactList.currentIndex = -1;
141- mainPage.contactEditorPage = editorPage;
142- pageStack.addPageToNextColumn(mainPage, editorPage);
143- editorPage.ready();
144- editorPage.contactSaved.connect(onNewContactSaved);
145- }
146-
147 function onNewContactSaved(contact) {
148+ _creatingContact = true
149+ moveListToContact(contact)
150 if (pageStack.columns > 1) {
151 showContact(contact);
152 }
153 }
154
155+ function reloadContact()
156+ {
157+ fetchNewContactTimer.restart()
158+ contactList.forceActiveFocus()
159+ }
160+
161 title: i18n.tr("Contacts")
162
163 flickable: null
164+
165+ Timer {
166+ id: fetchNewContactTimer
167+
168+ interval: 0
169+ repeat: false
170+ onTriggered: {
171+ if ((contactList.currentIndex >= 0) && (pageStack.columns > 1)) {
172+ var currentContact = contactList.listModel.contacts[contactList.currentIndex]
173+ if (mainPage.currentViewContactId === currentContact.contactId)
174+ return
175+
176+ contactList.view._fetchContact(contactList.currentIndex, currentContact)
177+ }
178+ }
179+ }
180+
181 ContactsUI.ContactListView {
182 id: contactList
183 objectName: "contactListView"
184+
185+ focus: true
186 showImportOptions: !mainPage.pickMode &&
187 mainPage.newPhoneToAdd === "" &&
188- (!mainPage.contactEditorPage || !mainPage.contactEditorPage.active)
189+ pageStack.bottomEdge && (pageStack.bottomEdge.satus === BottomEdge.Hidden)
190 anchors {
191 top: parent.top
192 left: parent.left
193 bottom: keyboard.top
194 right: parent.right
195 }
196+ currentIndex: 0
197 filterTerm: searchField.text
198 multiSelectionEnabled: true
199 multipleSelection: (mainPage.pickMode && mainPage.pickMultipleContacts) || !mainPage.pickMode
200- highlightSelected: pageStack.columns > 1
201+ highlightSelected: pageStack.columns > 1 && !mainPage._creatingContact
202+ showNewContact: (pageStack.columns > 1) && pageStack.bottomEdge && (pageStack.bottomEdge.status === BottomEdge.Committed)
203 onAddContactClicked: mainPage.createContactWithPhoneNumber(label)
204 onAddNewContactClicked: mainPage.createContactWithPhoneNumber(mainPage.newPhoneToAdd)
205-
206 onContactClicked: mainPage.showContact(contact)
207 onIsInSelectionModeChanged: mainPage.state = isInSelectionMode ? "selection" : "default"
208 onSelectionCanceled: {
209@@ -208,25 +228,71 @@
210 }
211
212 onError: pageStack.contactModelError(error)
213+ onActiveFocusChanged: {
214+ if (activeFocus && (contactList.currentIndex === -1)) {
215+ contactList.currentIndex = 0
216+ }
217+ }
218+ onCountChanged: {
219+ if (mainPage.active &&
220+ (pageStack.columns > 1) &&
221+ (contactList.currentIndex === -1)) {
222+ contactList.currentIndex = 0
223+ }
224+ fetchNewContactTimer.restart()
225+ }
226+ onCurrentIndexChanged: {
227+ if (!mainPage.contactIndex)
228+ fetchNewContactTimer.restart()
229+ }
230+
231+ //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822
232+ //because of that we need this
233+ Keys.onRightPressed: {
234+ // only move focus away when in edit mode
235+ if (pageStack.bottomEdge.status === BottomEdge.Committed) {
236+ var next = pageStack._nextItemInFocusChain(view, true)
237+ if (next === searchField) {
238+ pageStack._nextItemInFocusChain(next, true)
239+ }
240+ }
241+ }
242+ Keys.onTabPressed: {
243+ var next = pageStack._nextItemInFocusChain(view, true)
244+ if (next === searchField) {
245+ pageStack._nextItemInFocusChain(next, true)
246+ }
247+ }
248 }
249
250 TextField {
251 id: searchField
252
253+ //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822
254+ //because of that we need this
255+ readonly property bool _allowFocus: true
256+
257 anchors {
258- left: parent.left
259- right: parent.right
260+ left: parent ? parent.left : undefined
261+ right: parent ? parent.right : undefined
262 rightMargin: units.gu(2)
263 }
264- focus: false
265+
266 visible: false
267- onTextChanged: contactList.currentIndex = -1
268 inputMethodHints: Qt.ImhNoPredictiveText
269 placeholderText: i18n.tr("Search...")
270- onFocusChanged: {
271- if (visible && focus)
272- searchField.forceActiveFocus()
273+ onVisibleChanged: {
274+ if (visible) {
275+ if (activeFocus) {
276+ Qt.inputMethod.show()
277+ } else {
278+ searchField.forceActiveFocus()
279+ }
280+ }
281 }
282+
283+ Keys.onTabPressed: contactList.forceActiveFocus()
284+ Keys.onDownPressed: contactList.forceActiveFocus()
285 }
286
287 Connections {
288@@ -265,6 +331,8 @@
289 text: i18n.tr("Search")
290 iconName: "search"
291 visible: !mainPage.isEmpty
292+ enabled: mainPage.state === "default"
293+ shortcut: "Ctrl+F"
294 onTriggered: {
295 mainPage.state = (mainPage.state === "newphone" ? "newphoneSearching" : "searching")
296 contactList.showAllContacts()
297@@ -287,9 +355,21 @@
298 Action {
299 text: i18n.tr("Settings")
300 iconName: "settings"
301- onTriggered: pageStack.addPageToNextColumn(mainPage,
302- Qt.resolvedUrl("./Settings/SettingsPage.qml"),
303- {"contactListModel": contactList.listModel})
304+ onTriggered:{
305+ var incubator = pageStack.addPageToNextColumn(mainPage,
306+ Qt.resolvedUrl("./Settings/SettingsPage.qml"),
307+ {"contactListModel": contactList.listModel})
308+ incubator.onStatusChanged = function(status) {
309+ if (status === Component.Ready) {
310+ incubator.object.onActiveChanged.connect(function(active) {
311+ console.debug("Active:" + incubator.object.active)
312+ if (!incubator.object.active) {
313+ mainPage.reloadContact()
314+ }
315+ })
316+ }
317+ }
318+ }
319 }
320 ]
321 PropertyChanges {
322@@ -303,6 +383,10 @@
323 target: searchField
324 text: ""
325 }
326+ PropertyChanges {
327+ target: bottomEdgeLoader
328+ enabled: true
329+ }
330 },
331 PageHeadState {
332 id: searchingState
333@@ -311,6 +395,8 @@
334 backAction: Action {
335 iconName: "back"
336 text: i18n.tr("Cancel")
337+ enabled: mainPage.state === "searching" && !mainPage.bottomEdgeOpenOnNextCollumn
338+ shortcut:"Esc"
339 onTriggered: {
340 contactList.forceActiveFocus()
341 mainPage.head.sections.selectedIndex = 0
342@@ -319,7 +405,7 @@
343 }
344
345 PropertyChanges {
346- target: bottomEdge
347+ target: bottomEdgeLoader
348 enabled: false
349 }
350
351@@ -347,7 +433,9 @@
352 backAction: Action {
353 text: i18n.tr("Cancel selection")
354 iconName: "back"
355+ enabled: mainPage.state === "selection"
356 onTriggered: contactList.cancelSelection()
357+ shortcut: "Esc"
358 }
359 actions: [
360 Action {
361@@ -405,7 +493,7 @@
362 actions: selectionState.actions
363 }
364 PropertyChanges {
365- target: bottomEdge
366+ target: bottomEdgeLoader
367 enabled: false
368 }
369 },
370@@ -440,7 +528,7 @@
371 showAddNewButton: true
372 }
373 PropertyChanges {
374- target: bottomEdge
375+ target: bottomEdgeLoader
376 enabled: false
377 }
378 },
379@@ -462,7 +550,7 @@
380 backAction: vcardImportedState.backAction
381 }
382 PropertyChanges {
383- target: bottomEdge
384+ target: bottomEdgeLoader
385 enabled: false
386 }
387 PropertyChanges {
388@@ -493,8 +581,11 @@
389 if (active && contactList.showAddNewButton) {
390 contactList.positionViewAtBeginning()
391 }
392+
393 if (active && (state === "searching")) {
394 searchField.forceActiveFocus()
395+ } else if (active) {
396+ contactList.forceActiveFocus()
397 }
398 }
399
400@@ -517,8 +608,8 @@
401 !contactList.favouritesIsSelected &&
402 mainPage.isEmpty &&
403 (mainPage.newPhoneToAdd === "") &&
404- !(contactList.filterTerm && contactList.filterTerm !== "")) &&
405- bottomEdge.visible
406+ !(contactList.filterTerm && contactList.filterTerm !== ""))
407+ //&& bottomEdge.visible
408
409 Behavior on visible {
410 SequentialAnimation {
411@@ -643,111 +734,34 @@
412 }
413 }
414
415- Component {
416- id: editorPageBottomEdge
417- ABContactEditorPage {
418- backIconName: "down"
419- implicitWidth: mainPage.width
420- implicitHeight: mainPage.height
421- model: contactList.listModel
422- contact: ContactsJS.createEmptyContact("", mainPage)
423- initialFocusSection: "name"
424- enabled: false
425- }
426- }
427-
428- Component {
429- id: emptyContact
430- ContactsUI.ContactDelegate {
431- property Contact contact: Contact {
432- Name {
433- firstName: i18n.tr("New contact")
434- }
435- Avatar {
436- imageUrl: "image://theme/contact"
437- }
438- }
439- width: mainPage.width
440- }
441- }
442-
443- BottomEdge {
444- id: bottomEdge
445- objectName: "bottomEdge"
446-
447- property var incubator
448-
449- // FIXME: this is a workaround for the lack of fully asynchronous loading
450- // of Pages in AdaptativePageLayout
451- function createObjectAsynchronously(url, properties, callback) {
452- var component = Qt.createComponent(url, Component.Asynchronous);
453- if (component.status == Component.Ready) {
454- incubateObject(component, properties, callback);
455- } else {
456- component.onStatusChanged.connect(function(status) {
457- if (status == Component.Ready) {
458- incubateObject(component, properties, callback);
459- }
460- });
461- }
462- }
463-
464- function incubateObject(component, properties, callback) {
465- if (component.status == Component.Ready) {
466- incubator = component.incubateObject(null,
467- properties,
468- Qt.Asynchronous);
469- incubator.onStatusChanged = function(status) {
470- if (status == Component.Ready) {
471- callback(incubator.object);
472- incubator = null;
473- }
474- }
475- }
476- }
477-
478- function loadEditorPage() {
479- var newContact = ContactsJS.createEmptyContact("", mainPage);
480- createObjectAsynchronously(Qt.resolvedUrl("ABContactEditorPage.qml"),
481- {model: contactList.listModel,
482- contact: newContact,
483- initialFocusSection: "name"},
484- showContactEditorPage);
485- }
486-
487- anchors.fill: parent
488- contentComponent: pageStack.columns == 1 ? editorPageBottomEdge : emptyContact
489- flickable: contactList
490- iconName: "contact-new"
491- enabled: !contactList.isInSelectionMode
492- backGroundEffectEnabled: pageStack.columns === 1
493-
494- onOpenBegin: {
495- contactList.prepareNewContact = true;
496- contactList.positionViewAtBeginning();
497- if (pageStack.columns > 1) {
498- loadEditorPage();
499- }
500- }
501- onOpenEnd: {
502- bottomEdge.visible = false;
503- contactList.showNewContact = true;
504- if (pageStack.columns <= 1) {
505- showContactEditorPage(bottomEdge.content);
506- }
507- }
508-
509- onClicked: {
510- bottomEdge.open();
511- }
512+ Loader {
513+ id: bottomEdgeLoader
514+
515+ enabled: false
516+ active: (pageStack.columns === 1) && bottomEdgeLoader.enabled
517+ sourceComponent: ABNewContactBottomEdge {
518+ pageStack: mainPage.pageStack
519+ parent: mainPage
520+ hint.flickable: contactList.view
521+ }
522+ }
523+
524+ Binding {
525+ target: pageStack
526+ property: 'bottomEdge'
527+ value: bottomEdgeLoader.item
528+ when: bottomEdgeLoader.status == Loader.Ready
529 }
530
531 Connections {
532 target: mainPage.contactModel
533+
534 onContactsChanged: {
535 if (contactIndex) {
536 contactList.positionViewAtContact(mainPage.contactIndex)
537 mainPage.contactIndex = null
538+ // at this point the operation has finished already
539+ mainPage._creatingContact = false
540 }
541 }
542 onImportCompleted: {
543@@ -775,23 +789,4 @@
544 }
545 }
546 }
547-
548- Connections {
549- target: mainPage.contactViewPage
550- onEditContact: {
551- openEditPage(editPageProperties, mainPage.contactViewPage);
552- }
553- }
554-
555- Connections {
556- target: mainPage.contactEditorPage
557- onActiveChanged: {
558- if (!mainPage.contactEditorPage.active) {
559- contactList.prepareNewContact = false;
560- contactList.showNewContact = false;
561- bottomEdge.visible = true;
562- bottomEdge.close();
563- }
564- }
565- }
566 }
567
568=== modified file 'src/imports/ABContactViewPage.qml'
569--- src/imports/ABContactViewPage.qml 2015-10-28 01:08:39 +0000
570+++ src/imports/ABContactViewPage.qml 2015-12-04 15:09:43 +0000
571@@ -1,4 +1,4 @@
572-/*
573+/*
574 * Copyright (C) 2012-2015 Canonical, Ltd.
575 *
576 * This program is free software; you can redistribute it and/or modify
577@@ -28,6 +28,7 @@
578 objectName: "contactViewPage"
579
580 property string addPhoneToContact: ""
581+ property var editorPage: null
582 signal editContact(var editPageProperties)
583
584 head.actions: [
585@@ -50,9 +51,14 @@
586
587 text: i18n.tr("Edit")
588 iconName: "edit"
589+ enabled: root.active
590+ shortcut: "Ctrl+e"
591 onTriggered: {
592- editContact({model: root.model,
593- contact: root.contact});
594+ pageStack.addPageToCurrentColumn(root,
595+ Qt.resolvedUrl("ABContactEditorPage.qml"),
596+ { model: root.model,
597+ contact: root.contact,
598+ backIconName: 'back'})
599 }
600 }
601 ]
602@@ -100,4 +106,26 @@
603 id: contactShareComponent
604 ContactSharePage {}
605 }
606+
607+ Loader {
608+ id: bottomEdgeLoader
609+
610+ active: root.pageStack && root.pageStack.columns > 1
611+ sourceComponent: ABNewContactBottomEdge {
612+ id: bottomEdge
613+
614+ parent: root
615+ pageStack: root.pageStack
616+ hint.flickable: root.flickable
617+ }
618+
619+ Binding {
620+ target: pageStack
621+ property: 'bottomEdge'
622+ value: bottomEdgeLoader.item
623+ when: bottomEdgeLoader.status == Loader.Ready
624+ }
625+ }
626+
627+ Component.onDestruction: console.debug("VIEW DESTROYED")
628 }
629
630=== added file 'src/imports/ABNewContactBottomEdge.qml'
631--- src/imports/ABNewContactBottomEdge.qml 1970-01-01 00:00:00 +0000
632+++ src/imports/ABNewContactBottomEdge.qml 2015-12-04 15:09:43 +0000
633@@ -0,0 +1,67 @@
634+/*
635+ * Copyright (C) 2012-2015 Canonical, Ltd.
636+ *
637+ * This program is free software; you can redistribute it and/or modify
638+ * it under the terms of the GNU General Public License as published by
639+ * the Free Software Foundation; version 3.
640+ *
641+ * This program is distributed in the hope that it will be useful,
642+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
643+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
644+ * GNU General Public License for more details.
645+ *
646+ * You should have received a copy of the GNU General Public License
647+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
648+ */
649+
650+import QtQuick 2.4
651+import Ubuntu.Components 1.3
652+import Ubuntu.Contacts 0.1 as ContactsUI
653+
654+BottomEdge {
655+ id: bottomEdge
656+ objectName: "bottomEdge"
657+
658+ property var pageStack: null
659+ property var _contactToEdit: null
660+ property var _modelToEdit: null
661+
662+ function editContact(contact, model)
663+ {
664+ _contactToEdit = contact
665+ _modelToEdit = model
666+ commit()
667+ }
668+
669+ hint {
670+ action: Action {
671+ iconName: "contact-new"
672+ onTriggered: bottomEdge.commit()
673+ shortcut: "ctrl+n"
674+ enabled: bottomEdge.enabled
675+ }
676+ }
677+ contentComponent: editorPageBottomEdge
678+ onCommitCompleted: {
679+ var editorPage = bottomEdge.contentItem
680+ bottomEdge.pageStack.addPageToCurrentColumn(bottomEdge.parent, bottomEdge.contentItem)
681+ editorPage.contact = bottomEdge._contactToEdit
682+ editorPage.model = bottomEdge._modelToEdit
683+ bottomEdge._contactToEdit = null
684+ bottomEdge._modelToEdit = null
685+ }
686+
687+ Component {
688+ id: editorPageBottomEdge
689+
690+ ABContactEditorPage {
691+ implicitWidth: mainPage.width
692+ implicitHeight: bottomEdge.height
693+ contact: ContactsUI.ContactsJS.createEmptyContact("", bottomEdge)
694+ initialFocusSection: "name"
695+ enabled: false
696+ visible: bottomEdge.satus != BottomEdge.Hidden
697+ onCanceled: bottomEdge.collapse()
698+ }
699+ }
700+}
701
702=== removed file 'src/imports/BottomEdge.qml'
703--- src/imports/BottomEdge.qml 2015-11-19 01:02:12 +0000
704+++ src/imports/BottomEdge.qml 1970-01-01 00:00:00 +0000
705@@ -1,321 +0,0 @@
706-/*
707- * Copyright (C) 2015 Canonical, Ltd.
708- *
709- * This program is free software; you can redistribute it and/or modify
710- * it under the terms of the GNU General Public License as published by
711- * the Free Software Foundation; version 3.
712- *
713- * This program is distributed in the hope that it will be useful,
714- * but WITHOUT ANY WARRANTY; without even the implied warranty of
715- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
716- * GNU General Public License for more details.
717- *
718- * You should have received a copy of the GNU General Public License
719- * along with this program. If not, see <http://www.gnu.org/licenses/>.
720- */
721-
722-import QtQuick 2.4
723-import Ubuntu.Components 1.3
724-
725-Item {
726- id: bottomEdge
727-
728- readonly property alias content: bottomEdgeLoader.item
729- readonly property bool fullLoaded: bottomEdgeLoader.status == Loader.Ready
730-
731- property bool opened: false
732- property Component contentComponent
733- property string iconName
734- property Item flickable
735- property alias backGroundEffectEnabled: darkBg.visible
736-
737- signal openBegin
738- signal openEnd
739- signal clicked
740- visible: enabled
741-
742- function open() {
743- bottomEdge.state = "expanded";
744- }
745-
746- function close() {
747- bottomEdge.state = "collapsed";
748- }
749-
750- Rectangle {
751- id: darkBg
752-
753- anchors.fill: parent
754- color: "black"
755- opacity: 0.0
756- }
757-
758- Item {
759- id: bottomEdgeBody
760- anchors {
761- left: parent.left
762- right: parent.right
763- }
764- height: bottomEdgeContent.height
765-
766- Item {
767- id: bottomEdgeContent
768- anchors {
769- left: parent.left
770- right: parent.right
771- }
772- height: bottomEdgeLoader.height
773-
774- Item {
775- id: bottomEdgeShadows
776- anchors.fill: bottomEdgeContent
777-
778- BottomEdgeShadow {
779- anchors.bottom: parent.top
780- }
781-
782- BottomEdgeShadow {
783- anchors.top: parent.bottom
784- rotation: 180
785- }
786- }
787-
788- Rectangle {
789- anchors.fill: parent
790- color: Theme.palette.normal.background
791- }
792-
793- Loader {
794- id: bottomEdgeLoader
795- sourceComponent: bottomEdge.contentComponent
796- asynchronous: true
797- active: bottomEdge.enabled
798- }
799- }
800-
801- BottomEdgeHint {
802- id: bottomEdgeHint
803-
804- anchors.bottom: bottomEdgeBody.top
805- iconName: bottomEdge.iconName
806- onClicked: bottomEdge.clicked()
807-
808- Connections {
809- target: bottomEdgeDragArea
810- onClosedChanged: {
811- if (!bottomEdgeDragArea.closed) {
812- bottomEdgeHint.state = "Visible";
813- }
814- }
815- }
816-
817- Connections {
818- target: flickable
819- onVerticalVelocityChanged: {
820- if (!bottomEdgeDragArea.closed) {
821- return;
822- }
823-
824- if (flickable.verticalVelocity > 0) {
825- bottomEdgeHint.state = "Hidden";
826- } else if (flickable.verticalVelocity < 0) {
827- bottomEdgeHint.state = "Visible";
828- }
829- }
830- }
831- }
832- }
833-
834-
835- state: "collapsed"
836- states: [
837- State {
838- name: "collapsed"
839- ParentChange {
840- target: bottomEdgeContent
841- parent: bottomEdgeBody
842- x: 0
843- y: 0
844- }
845- PropertyChanges {
846- target: bottomEdgeBody
847- y: bottomEdgeDragArea.drag.maximumY
848- }
849- PropertyChanges {
850- target: bottomEdgeContent
851- opacity: 0.0
852- }
853- PropertyChanges {
854- target: darkBg
855- opacity: 0.0
856- }
857- },
858- State {
859- name: "expanded"
860- ParentChange {
861- target: bottomEdgeContent
862- parent: bottomEdge
863- x: 0
864- y: 0
865- }
866- PropertyChanges {
867- target: bottomEdgeContent
868- opacity: 1.0
869- }
870- PropertyChanges {
871- target: bottomEdgeBody
872- y: 0
873- }
874- PropertyChanges {
875- target: bottomEdgeShadows
876- opacity: 0.0
877- visible: true
878- }
879- PropertyChanges {
880- target: darkBg
881- opacity: 0.8
882- }
883- },
884- State {
885- name: "floating"
886- when: bottomEdgeDragArea.drag.active
887- PropertyChanges {
888- target: bottomEdgeContent
889- opacity: 1.0
890- }
891- PropertyChanges {
892- target: darkBg
893- opacity: bottomEdgeBody.y > 0 ? 0.8 - (bottomEdgeBody.y / bottomEdgeDragArea.drag.maximumY) : 0.8
894- }
895- }
896- ]
897-
898- transitions: [
899- Transition {
900- to: "collapsed"
901- SequentialAnimation {
902- alwaysRunToEnd: true
903- ParallelAnimation {
904- ParentAnimation {
905- UbuntuNumberAnimation {
906- properties: "x,y"
907- duration: UbuntuAnimation.SlowDuration
908- target: bottomEdgeContent
909- }
910- }
911- UbuntuNumberAnimation {
912- target: bottomEdgeBody
913- property: "y"
914- duration: UbuntuAnimation.SlowDuration
915- }
916- UbuntuNumberAnimation {
917- target: darkBg
918- property: "opacity"
919- duration: UbuntuAnimation.SlowDuration
920- }
921- }
922- PropertyAction {
923- target: bottomEdgeContent
924- property: "opacity"
925- }
926- ScriptAction {
927- script: {
928- bottomEdgeLoader.active = false
929- bottomEdgeLoader.active = true
930- bottomEdge.opened = false
931- }
932- }
933- }
934- },
935- Transition {
936- to: "expanded"
937- SequentialAnimation {
938- alwaysRunToEnd: true
939- ParallelAnimation {
940- ScriptAction {
941- script: bottomEdge.openBegin()
942- }
943- ParentAnimation {
944- UbuntuNumberAnimation {
945- properties: "x,y"
946- duration: UbuntuAnimation.SlowDuration
947- target: bottomEdgeContent
948- }
949- }
950- UbuntuNumberAnimation {
951- target: bottomEdgeShadows
952- property: "opacity"
953- duration: UbuntuAnimation.SlowDuration
954- }
955- UbuntuNumberAnimation {
956- target: darkBg
957- property: "opacity"
958- duration: UbuntuAnimation.SlowDuration
959- }
960- }
961- UbuntuNumberAnimation {
962- target: bottomEdgeContent
963- property: "opacity"
964- duration: UbuntuAnimation.FastDuration
965- }
966- ScriptAction {
967- script: {
968- bottomEdge.opened = true
969- bottomEdge.openEnd()
970- }
971-
972- }
973- }
974- }
975- ]
976-
977- MouseArea {
978- id: bottomEdgeDragArea
979- objectName: "bottomEdgeDragArea"
980-
981- property real previousY: -1
982- property string dragDirection: "None"
983- property bool closed: drag.target.y == bottomEdgeDragArea.drag.maximumY
984- && !bottomEdgeDragArea.pressed
985-
986- preventStealing: true
987- propagateComposedEvents: true
988- drag {
989- axis: Drag.YAxis
990- target: bottomEdgeBody
991- minimumY: 0
992- maximumY: bottomEdge.height
993- }
994-
995- anchors {
996- left: parent.left
997- right: parent.right
998- bottom: parent.bottom
999- }
1000- height: bottomEdgeHint.height
1001-
1002- onPressed: {
1003- previousY = mouse.y;
1004- }
1005-
1006- onReleased: {
1007- if (dragDirection === "BottomToTop") {
1008- bottomEdge.state = "expanded";
1009- } else {
1010- bottomEdge.state = "collapsed";
1011- }
1012- previousY = -1;
1013- dragDirection = "None";
1014- }
1015-
1016- onMouseYChanged: {
1017- var yOffset = previousY - mouseY;
1018- // skip if was a small move
1019- if (Math.abs(yOffset) <= units.gu(2)) {
1020- return;
1021- }
1022- previousY = mouseY;
1023- dragDirection = yOffset > 0 ? "BottomToTop" : "TopToBottom";
1024- }
1025- }
1026-}
1027
1028=== removed file 'src/imports/BottomEdgeShadow.qml'
1029--- src/imports/BottomEdgeShadow.qml 2015-09-10 14:47:38 +0000
1030+++ src/imports/BottomEdgeShadow.qml 1970-01-01 00:00:00 +0000
1031@@ -1,31 +0,0 @@
1032-/*
1033- * Copyright (C) 2015 Canonical, Ltd.
1034- *
1035- * This program is free software; you can redistribute it and/or modify
1036- * it under the terms of the GNU General Public License as published by
1037- * the Free Software Foundation; version 3.
1038- *
1039- * This program is distributed in the hope that it will be useful,
1040- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1041- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1042- * GNU General Public License for more details.
1043- *
1044- * You should have received a copy of the GNU General Public License
1045- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1046- */
1047-
1048-import QtQuick 2.4
1049-import Ubuntu.Components 1.3
1050-
1051-Rectangle {
1052- id: bottomEdgeShadow
1053- anchors {
1054- left: parent.left
1055- right: parent.right
1056- }
1057- height: units.gu(1)
1058- gradient: Gradient {
1059- GradientStop { position: 0.0; color: Qt.rgba(0.0, 0.0, 0.0, 0.0) }
1060- GradientStop { position: 1.0; color: Qt.rgba(0.0, 0.0, 0.0, 0.3) }
1061- }
1062-}
1063
1064=== modified file 'src/imports/CMakeLists.txt'
1065--- src/imports/CMakeLists.txt 2015-11-19 14:41:18 +0000
1066+++ src/imports/CMakeLists.txt 2015-12-04 15:09:43 +0000
1067@@ -4,10 +4,9 @@
1068 ABContactListPage.qml
1069 ABContactEditorPage.qml
1070 ABContactViewPage.qml
1071+ ABNewContactBottomEdge.qml
1072 ContentHubProxy.qml
1073 MainWindow.qml
1074- BottomEdgeShadow.qml
1075- BottomEdge.qml
1076 )
1077
1078 install(FILES ${ADDRESS_BOOK_APP_QMLS}
1079
1080=== modified file 'src/imports/MainWindow.qml'
1081--- src/imports/MainWindow.qml 2015-10-26 13:18:11 +0000
1082+++ src/imports/MainWindow.qml 2015-12-04 15:09:43 +0000
1083@@ -101,18 +101,41 @@
1084 width: units.gu(90)
1085 height: units.gu(71)
1086 anchorToKeyboard: false
1087+ focus: false
1088
1089 AdaptivePageLayout {
1090 id: mainStack
1091
1092- primaryPage: contactPage
1093 property var contactListPage: null
1094+ property var bottomEdge: null
1095
1096 function resetStack()
1097 {
1098 mainStack.removePages(primaryPage);
1099 }
1100
1101+ function _nextItemInFocusChain(item, foward)
1102+ {
1103+ var next = item.nextItemInFocusChain(foward)
1104+ var first = next
1105+ //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822
1106+ //because of that we need this
1107+ while (!next || !next.hasOwnProperty("_allowFocus")) {
1108+ next = next.nextItemInFocusChain(foward)
1109+
1110+ // avoid loop
1111+ if (next === first) {
1112+ next = null
1113+ break
1114+ }
1115+ }
1116+ if (next) {
1117+ next.forceActiveFocus()
1118+ }
1119+ return next
1120+ }
1121+
1122+ primaryPage: contactPage
1123 onContactListPageChanged: {
1124 if (contentHubLoader.status === Loader.Ready) {
1125 contentHubLoader.item.pageStack = mainStack
1126@@ -141,6 +164,7 @@
1127 }
1128 }
1129 ]
1130+
1131 }
1132
1133 ABContactListPage {
1134@@ -196,6 +220,10 @@
1135
1136 // If application was called from uri handler and lost the focus reset the app to normal state
1137 onAppActiveChanged: {
1138+ if (appActive) {
1139+ mainStack.forceActiveFocus()
1140+ }
1141+
1142 if (!appActive && mainStack.contactListPage) {
1143 mainStack.contactListPage.returnToNormalState()
1144 }
1145
1146=== modified file 'src/imports/Settings/SettingsPage.qml'
1147--- src/imports/Settings/SettingsPage.qml 2015-10-26 13:18:11 +0000
1148+++ src/imports/Settings/SettingsPage.qml 2015-12-04 15:09:43 +0000
1149@@ -1,4 +1,4 @@
1150-/*
1151+/*
1152 * Copyright (C) 2015 Canonical, Ltd.
1153 *
1154 * This program is free software; you can redistribute it and/or modify
1155@@ -64,15 +64,56 @@
1156 onCountChanged: numberFlickable.contentY = 0
1157 }
1158 ListItem.Standard {
1159+ id: addGoogleAccountItem
1160+
1161+ function activate()
1162+ {
1163+ onlineAccountsHelper.setupExec()
1164+ }
1165+
1166 text: i18n.tr("Add Google account")
1167 progression: true
1168- onClicked: onlineAccountsHelper.setupExec()
1169+
1170+ onClicked: addGoogleAccountItem.activate()
1171+ Keys.onRightPressed: addGoogleAccountItem.activate()
1172+ Keys.onDownPressed: {
1173+ if (importFromSimItem.enabled) {
1174+ importFromSimItem.forceActiveFocus()
1175+ }
1176+ }
1177+
1178+ // selection visual feedback
1179+ __foregroundColor: (activeFocus && (pageStack.columns > 1)) ? "white" : Theme.palette.normal.foreground
1180+ Rectangle {
1181+ color: UbuntuColors.orange
1182+ anchors.fill: parent
1183+ visible:addGoogleAccountItem.activeFocus
1184+ z: -1
1185+ }
1186 }
1187 ListItem.Standard {
1188+ id: importFromSimItem
1189+
1190+ function activate()
1191+ {
1192+ pageStack.addPageToCurrentColumn(root, simCardImportPageComponent)
1193+ }
1194+
1195 text: i18n.tr("Import from SIM")
1196 progression: true
1197- onClicked: pageStack.addPageToCurrentColumn(root, simCardImportPageComponent)
1198 enabled: (simList.sims.length > 0) && (simList.present.length > 0)
1199+ onClicked: importFromSimItem.activate()
1200+ Keys.onRightPressed: importFromSimItem.activate()
1201+ Keys.onUpPressed: addGoogleAccountItem.forceActiveFocus()
1202+
1203+ // selection visual feedback
1204+ __foregroundColor: (activeFocus && (pageStack.columns > 1)) ? "white" : Theme.palette.normal.foreground
1205+ Rectangle {
1206+ color: UbuntuColors.orange
1207+ anchors.fill: parent
1208+ visible: importFromSimItem.activeFocus
1209+ z: -1
1210+ }
1211 }
1212 }
1213 }
1214@@ -89,4 +130,14 @@
1215 sims: simList.sims
1216 }
1217 }
1218+
1219+ Keys.onDownPressed: addGoogleAccountItem.forceActiveFocus()
1220+ Keys.onRightPressed: addGoogleAccountItem.forceActiveFocus()
1221+ Keys.onLeftPressed: pageStack.removePages(root)
1222+ Keys.onEscapePressed: pageStack.removePages(root)
1223+ onActiveChanged: {
1224+ if (active) {
1225+ root.forceActiveFocus()
1226+ }
1227+ }
1228 }
1229
1230=== modified file 'src/imports/Ubuntu/AddressBook/Base/ContactDetailBase.qml'
1231--- src/imports/Ubuntu/AddressBook/Base/ContactDetailBase.qml 2015-10-26 13:18:11 +0000
1232+++ src/imports/Ubuntu/AddressBook/Base/ContactDetailBase.qml 2015-12-04 15:09:43 +0000
1233@@ -18,15 +18,19 @@
1234 import QtContacts 5.0 as QtContacts
1235 import Ubuntu.Components.ListItems 1.3 as ListItem
1236
1237-ListItem.Empty {
1238+FocusScope {
1239 id: root
1240 objectName: detail ? "base_" + detailToString(detail.type, -1) + "_" + index : ""
1241
1242+ property variant action: null
1243 property QtObject contact: null
1244 property QtObject detail: null
1245 property variant fields: null
1246 // help to test used to retrieve the correct element
1247 property int index: -1
1248+ property alias highlightOnFocus: highlight.visible
1249+
1250+ signal clicked()
1251
1252 function detailToString(detail, field)
1253 {
1254@@ -98,13 +102,24 @@
1255 }
1256 }
1257
1258- highlightWhenPressed: false
1259- showDivider: false
1260-
1261 Rectangle {
1262+ id: highlight
1263+
1264 anchors.fill: parent
1265 opacity: 0.1
1266- visible: root.selected
1267+ visible: root.activeFocus
1268+ color: "black"
1269 z: 100
1270 }
1271+
1272+ MouseArea {
1273+ anchors.fill: parent
1274+
1275+ onClicked: {
1276+ if (action) {
1277+ action.triggered(action)
1278+ }
1279+ root.clicked()
1280+ }
1281+ }
1282 }
1283
1284=== modified file 'src/imports/Ubuntu/AddressBook/Base/ContactDetailGroupBase.qml'
1285--- src/imports/Ubuntu/AddressBook/Base/ContactDetailGroupBase.qml 2015-10-26 13:18:11 +0000
1286+++ src/imports/Ubuntu/AddressBook/Base/ContactDetailGroupBase.qml 2015-12-04 15:09:43 +0000
1287@@ -33,6 +33,7 @@
1288 property int minimumHeight: 0
1289 property bool loaded: false
1290 property bool showEmpty: true
1291+ property bool forceFocusOnFieldCreation: false
1292
1293 signal newFieldAdded(var index)
1294
1295@@ -146,7 +147,7 @@
1296 newFields.push(detailItem.item)
1297 root.newFieldAdded(detailItem.item)
1298 root.inputFields = newFields
1299- if (root.loaded) {
1300+ if (root.loaded && root.forceFocusOnFieldCreation) {
1301 item.forceActiveFocus()
1302 }
1303 }
1304
1305=== modified file 'src/imports/Ubuntu/AddressBook/Base/RemoveContactsDialog.qml'
1306--- src/imports/Ubuntu/AddressBook/Base/RemoveContactsDialog.qml 2015-10-26 13:18:11 +0000
1307+++ src/imports/Ubuntu/AddressBook/Base/RemoveContactsDialog.qml 2015-12-04 15:09:43 +0000
1308@@ -53,6 +53,7 @@
1309 }
1310
1311 Button {
1312+ id: acceptButton
1313 objectName: "removeContactsDialog.Yes"
1314 anchors {
1315 left: parent.left
1316@@ -61,10 +62,16 @@
1317 }
1318 text: i18n.dtr("address-book-app", "Yes")
1319 color: UbuntuColors.green
1320- onClicked: accepted()
1321+ action: Action {
1322+ shortcut: "return"
1323+ onTriggered: {
1324+ accepted()
1325+ }
1326+ }
1327 }
1328
1329 Button {
1330+ id: cancelButton
1331 objectName: "removeContactsDialog.No"
1332 anchors {
1333 left: parent.left
1334@@ -73,6 +80,16 @@
1335 }
1336 text: i18n.dtr("address-book-app", "No")
1337 color: UbuntuColors.red
1338- onClicked: canceled()
1339+ action: Action {
1340+ shortcut: "esc"
1341+ onTriggered: {
1342+ canceled()
1343+ }
1344+ }
1345+ }
1346+
1347+ Component.onDestruction: {
1348+ cancelButton.action.shortcut = ""
1349+ acceptButton.action.shortcut = ""
1350 }
1351 }
1352
1353=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAvatarEditor.qml'
1354--- src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAvatarEditor.qml 2015-10-29 18:11:08 +0000
1355+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailAvatarEditor.qml 2015-12-04 15:09:43 +0000
1356@@ -68,6 +68,7 @@
1357 detail: contact ? contact.detail(ContactDetail.Avatar) : null
1358 implicitHeight: units.gu(8)
1359 implicitWidth: units.gu(8)
1360+ highlightOnFocus: false
1361
1362 UbuntuShape {
1363 id: avatar
1364
1365=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailGroupWithTypeEditor.qml'
1366--- src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailGroupWithTypeEditor.qml 2015-10-26 13:18:11 +0000
1367+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailGroupWithTypeEditor.qml 2015-12-04 15:09:43 +0000
1368@@ -98,29 +98,19 @@
1369 return changed
1370 }
1371
1372- headerDelegate: Empty {
1373+ forceFocusOnFieldCreation: true
1374+ headerDelegate: Label {
1375 id: header
1376- highlightWhenPressed: false
1377-
1378- width: root.width
1379- height: units.gu(5)
1380- // disable listview mouse area
1381- __mouseArea.visible: false
1382- divider.anchors.leftMargin: units.gu(2)
1383- divider.anchors.rightMargin: units.gu(2)
1384-
1385- Label {
1386- anchors {
1387- verticalCenter: parent.verticalCenter
1388- left: parent.left
1389- right: parent.right
1390- margins: units.gu(2)
1391- }
1392-
1393- text: root.title
1394-
1395- // style
1396- fontSize: "medium"
1397+
1398+ width: root.width - units.gu(4)
1399+ x: units.gu(2)
1400+ height: units.gu(4)
1401+ text: root.title
1402+ // style
1403+ fontSize: "medium"
1404+ verticalAlignment: Text.AlignVCenter
1405+ ThinDivider {
1406+ anchors.bottom: parent.bottom
1407 }
1408 }
1409
1410@@ -157,7 +147,6 @@
1411 fields: root.fields
1412 height: implicitHeight
1413 width: root.width
1414- selected: activeFocus
1415
1416 inputMethodHints: root.inputMethodHints
1417 onDetailChanged: updateCombo(false)
1418
1419=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailNameEditor.qml'
1420--- src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailNameEditor.qml 2015-10-26 13:18:11 +0000
1421+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailNameEditor.qml 2015-12-04 15:09:43 +0000
1422@@ -55,6 +55,7 @@
1423 spacing: units.gu(1)
1424 detail: root.contact ? root.contact.name : null
1425 fields: [ Name.FirstName, Name.LastName ]
1426+ highlightOnFocus: false
1427
1428 fieldDelegate: TextInputDetail {
1429 id: textInputDetail
1430
1431=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailSyncTargetEditor.qml'
1432--- src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailSyncTargetEditor.qml 2015-10-26 13:18:11 +0000
1433+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailSyncTargetEditor.qml 2015-12-04 15:09:43 +0000
1434@@ -87,7 +87,8 @@
1435 property real myHeight: sources.currentlyExpanded ? sources.containerHeight + units.gu(6) + label.height : sources.itemHeight + units.gu(6) + label.height
1436
1437 detail: root.contact ? contact.detail(ContactDetail.SyncTarget) : null
1438- implicitHeight: root.isNewContact && sources.model && (sources.model.count > 1) ? myHeight : 0
1439+ height: root.isNewContact && sources.model && (sources.model.count > 1) ? myHeight : 0
1440+ visible: height > 0
1441
1442 ContactModel {
1443 id: sourceModel
1444@@ -144,8 +145,12 @@
1445 ThinDivider {
1446 id: divider
1447
1448- anchors.top: label.bottom
1449- }
1450+ anchors {
1451+ top: label.bottom
1452+ leftMargin: units.gu(2)
1453+ rightMargin: units.gu(2)
1454+ }
1455+ }
1456
1457 OptionSelector {
1458 id: sources
1459
1460=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailWithTypeEditor.qml'
1461--- src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailWithTypeEditor.qml 2015-10-26 13:18:11 +0000
1462+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactDetailWithTypeEditor.qml 2015-12-04 15:09:43 +0000
1463@@ -70,7 +70,6 @@
1464 }
1465
1466 // disable listview mouse area
1467- __mouseArea.visible: false
1468 enabled: root.detail ? !root.detail.readOnly : false
1469 implicitHeight: detailTypeSelector.height + fieldValues.height + units.gu(2)
1470 opacity: enabled ? 1.0 : 0.5
1471
1472=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/ContactEditorPage.qml'
1473--- src/imports/Ubuntu/AddressBook/ContactEditor/ContactEditorPage.qml 2015-10-26 13:18:11 +0000
1474+++ src/imports/Ubuntu/AddressBook/ContactEditor/ContactEditorPage.qml 2015-12-04 15:09:43 +0000
1475@@ -31,7 +31,6 @@
1476 property QtObject model: null
1477 property QtObject activeItem: null
1478
1479-
1480 property string initialFocusSection: ""
1481 property var newDetails: []
1482
1483@@ -39,9 +38,7 @@
1484 readonly property bool isContactValid: !avatarEditor.busy && (!nameEditor.isEmpty() || !phonesEditor.isEmpty())
1485
1486 signal contactSaved(var contact);
1487-
1488- // priv
1489- property bool _edgeReady: false
1490+ signal canceled()
1491
1492 function cancel() {
1493 for (var i = 0; i < contactEditor.newDetails.length; ++i) {
1494@@ -60,6 +57,7 @@
1495 } else {
1496 pageStack.pop()
1497 }
1498+ contactEditor.canceled()
1499 }
1500
1501 function save() {
1502@@ -105,7 +103,7 @@
1503 }
1504
1505 function makeMeVisible(item) {
1506- if (!_edgeReady || !item) {
1507+ if (!enabled || !item) {
1508 return
1509 }
1510
1511@@ -133,8 +131,6 @@
1512 function ready()
1513 {
1514 enabled = true
1515- _edgeReady = true
1516-
1517 switch (contactEditor.initialFocusSection)
1518 {
1519 case "phones":
1520@@ -153,6 +149,7 @@
1521 }
1522
1523 title: isNewContact ? i18n.dtr("address-book-app", "New contact") : i18n.dtr("address-book-app", "Edit")
1524+ enabled: false
1525
1526 Timer {
1527 id: focusTimer
1528@@ -181,7 +178,9 @@
1529 contentWidth: parent.width
1530
1531 //after add a new field we need to wait for the contentHeight to change to scroll to the correct position
1532- onContentHeightChanged: contactEditor.makeMeVisible(contactEditor.activeItem)
1533+ onContentHeightChanged: {
1534+ contactEditor.makeMeVisible(contactEditor.activeItem)
1535+ }
1536
1537 Column {
1538 id: contents
1539@@ -195,6 +194,7 @@
1540 height: childrenRect.height
1541
1542 Row {
1543+ id: editEditor
1544 function save()
1545 {
1546 var avatarSave = avatarEditor.save()
1547@@ -213,7 +213,7 @@
1548 leftMargin: units.gu(2)
1549 right: parent.right
1550 }
1551- height: Math.max(avatarEditor.height, nameEditor.height) - units.gu(4)
1552+ height: Math.max(avatarEditor.height, nameEditor.height) - units.gu(2)
1553
1554 ContactDetailAvatarEditor {
1555 id: avatarEditor
1556@@ -221,6 +221,7 @@
1557 contact: contactEditor.contact
1558 height: implicitHeight
1559 width: implicitWidth
1560+ anchors.verticalCenter: editEditor.verticalCenter
1561 }
1562
1563 ContactDetailNameEditor {
1564@@ -232,6 +233,7 @@
1565 }
1566 }
1567
1568+
1569 ContactDetailPhoneNumbersEditor {
1570 id: phonesEditor
1571 objectName: "phones"
1572@@ -301,8 +303,6 @@
1573 left: parent.left
1574 right: parent.right
1575 }
1576- height: implicitHeight
1577-
1578 onChanged: {
1579 if (contactEditor.enabled &&
1580 !contactEditor.isNewContact &&
1581@@ -383,9 +383,13 @@
1582 right: parent.right
1583 margins: units.gu(2)
1584 }
1585- onClicked: {
1586- var dialog = PopupUtils.open(removeContactDialog, null)
1587- dialog.contacts = [contactEditor.contact]
1588+ action: Action {
1589+ enabled: contactEditor.active && deleteButton.visible
1590+ shortcut: "Ctrl+Delete"
1591+ onTriggered: {
1592+ var dialog = PopupUtils.open(removeContactDialog, null)
1593+ dialog.contacts = [contactEditor.contact]
1594+ }
1595 }
1596 }
1597
1598@@ -410,8 +414,8 @@
1599 }
1600 }
1601
1602- Component.onCompleted: {
1603- if (!enabled) {
1604+ onActiveChanged: {
1605+ if (!active) {
1606 return
1607 }
1608
1609@@ -475,10 +479,14 @@
1610 }
1611
1612 // hide virtual keyboard if necessary
1613- Component.onCompleted: Qt.inputMethod.hide()
1614+ Component.onCompleted: {
1615+ contactEditor.enabled = false
1616+ Qt.inputMethod.hide()
1617+ }
1618
1619 // WORKAROUND: SDK element crash if pop the page where the dialog was created
1620 Component.onDestruction: {
1621+ contactEditor.enabled = true
1622 if (popPages) {
1623 if (contactEditor.pageStack.removePages) {
1624 contactEditor.pageStack.removePages(contactEditor)
1625
1626=== modified file 'src/imports/Ubuntu/AddressBook/ContactEditor/TextInputDetail.qml'
1627--- src/imports/Ubuntu/AddressBook/ContactEditor/TextInputDetail.qml 2015-10-26 13:18:11 +0000
1628+++ src/imports/Ubuntu/AddressBook/ContactEditor/TextInputDetail.qml 2015-12-04 15:09:43 +0000
1629@@ -25,7 +25,11 @@
1630 FocusScope {
1631 id: root
1632
1633+ //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822
1634+ //because of that we need this
1635+ readonly property bool _allowFocus: true
1636 readonly property bool isTextField: true
1637+
1638 property QtObject detail
1639 property int field: -1
1640 property variant originalValue: root.detail && (root.field >= 0) ? root.detail.value(root.field) : null
1641@@ -67,6 +71,22 @@
1642 PhoneNumberField {
1643 id: field
1644
1645+ //WORKAROUND: Due the SDK bug #1514822, #1514850 we can not disable focus for some items
1646+ //because of that we keep the focus only for textFields. This will block the user
1647+ //to use keyboard on "add-field" combo box and some other functionalities
1648+ function forceActiveFocusForNextField(keyEvent)
1649+ {
1650+ var backward = (keyEvent.modifiers & Qt.ShiftModifier)
1651+ var next = field.nextItemInFocusChain(!backward)
1652+ // only focus on TextInputDetails
1653+ while (!next || !next.hasOwnProperty("isTextField")) {
1654+ next = next.nextItemInFocusChain(!backward)
1655+ }
1656+ if (next) {
1657+ next.forceActiveFocus()
1658+ }
1659+ }
1660+
1661 anchors.fill: parent
1662 defaultRegion: PhoneUtils.defaultRegion
1663 autoFormat: false
1664@@ -93,15 +113,9 @@
1665 family: "Ubuntu"
1666 pixelSize: activeFocus ? FontUtils.sizeToPixels("large") : FontUtils.sizeToPixels("medium")
1667 }
1668- Keys.onReturnPressed: {
1669- var next = field.nextItemInFocusChain(true)
1670- // only focus on TextInputDetails
1671- while (!next || !next.hasOwnProperty("isTextField")) {
1672- next = next.nextItemInFocusChain(true)
1673- }
1674- if (next) {
1675- next.forceActiveFocus()
1676- }
1677- }
1678+
1679+ Keys.onReturnPressed: forceActiveFocusForNextField(event)
1680+ Keys.onTabPressed: forceActiveFocusForNextField(event)
1681+ Keys.onBacktabPressed: forceActiveFocusForNextField(event)
1682 }
1683 }
1684
1685=== modified file 'src/imports/Ubuntu/AddressBook/ContactView/ActionButton.qml'
1686--- src/imports/Ubuntu/AddressBook/ContactView/ActionButton.qml 2015-10-26 13:18:11 +0000
1687+++ src/imports/Ubuntu/AddressBook/ContactView/ActionButton.qml 2015-12-04 15:09:43 +0000
1688@@ -30,5 +30,6 @@
1689 anchors.centerIn: parent
1690 height: root.iconSize
1691 width: root.iconSize
1692+ color: root.activeFocus ? UbuntuColors.orange : "gray"
1693 }
1694 }
1695
1696=== modified file 'src/imports/Ubuntu/AddressBook/ContactView/BasicFieldView.qml'
1697--- src/imports/Ubuntu/AddressBook/ContactView/BasicFieldView.qml 2015-10-26 13:18:11 +0000
1698+++ src/imports/Ubuntu/AddressBook/ContactView/BasicFieldView.qml 2015-12-04 15:09:43 +0000
1699@@ -27,6 +27,8 @@
1700 property variant fields: null
1701 property int parentIndex: -1
1702
1703+ focus: false
1704+ activeFocusOnTab: false
1705 implicitHeight: typeLabel.height + fieldValues.height + units.gu(2)
1706
1707 Column {
1708
1709=== modified file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailAvatarView.qml'
1710--- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailAvatarView.qml 2015-11-16 20:12:41 +0000
1711+++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailAvatarView.qml 2015-12-04 15:09:43 +0000
1712@@ -29,6 +29,8 @@
1713
1714 implicitHeight: units.gu(12)
1715 implicitWidth: parent.width
1716+ activeFocusOnTab: false
1717+ focus: false
1718
1719 Connections {
1720 id: connections
1721
1722=== modified file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailGroupWithTypeView.qml'
1723--- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailGroupWithTypeView.qml 2015-10-26 13:18:11 +0000
1724+++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailGroupWithTypeView.qml 2015-12-04 15:09:43 +0000
1725@@ -18,8 +18,7 @@
1726 import QtContacts 5.0 as QtContacts
1727
1728 import Ubuntu.Components 1.3
1729-import Ubuntu.Components.ListItems 1.3 as ListItem
1730-
1731+import Ubuntu.Components.ListItems 1.3
1732 import Ubuntu.AddressBook.Base 0.1
1733
1734 ContactDetailGroupWithTypeBase {
1735@@ -29,25 +28,18 @@
1736 signal actionTrigerred(string actionName, QtObject detail)
1737
1738 showEmpty: false
1739- headerDelegate: ListItem.Empty {
1740- highlightWhenPressed: false
1741-
1742- divider.anchors.leftMargin: units.gu(2)
1743- divider.anchors.rightMargin: units.gu(2)
1744- width: root.width
1745- height: units.gu(5)
1746- Label {
1747- anchors {
1748- verticalCenter: parent.verticalCenter
1749- left: parent.left
1750- right: parent.right
1751- margins: units.gu(2)
1752- }
1753-
1754- text: root.title
1755-
1756- // style
1757- fontSize: "medium"
1758+ headerDelegate: Label {
1759+ id: header
1760+
1761+ width: root.width - units.gu(4)
1762+ x: units.gu(2)
1763+ height: units.gu(4)
1764+ text: root.title
1765+ // style
1766+ fontSize: "medium"
1767+ verticalAlignment: Text.AlignVCenter
1768+ ThinDivider {
1769+ anchors.bottom: parent.bottom
1770 }
1771 }
1772
1773
1774=== modified file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailNameView.qml'
1775--- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailNameView.qml 2015-10-26 13:18:11 +0000
1776+++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailNameView.qml 2015-12-04 15:09:43 +0000
1777@@ -25,7 +25,8 @@
1778
1779 detail: root.contact ? root.contact.name : null
1780 implicitHeight: label.paintedHeight + (label.anchors.margins * 2)
1781-
1782+ activeFocusOnTab: false
1783+ focus: false
1784
1785 Label {
1786 id: label
1787
1788=== modified file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailSyncTargetView.qml'
1789--- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailSyncTargetView.qml 2015-10-26 13:18:11 +0000
1790+++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailSyncTargetView.qml 2015-12-04 15:09:43 +0000
1791@@ -50,6 +50,7 @@
1792 defaultIcon: "image://theme/contact-group"
1793 detailType: ContactDetail.SyncTarget
1794 typeModel: null
1795+ activeFocusOnTab: false
1796
1797 fields: [ SyncTarget.SyncTarget ]
1798
1799@@ -76,7 +77,7 @@
1800
1801 height: implicitHeight
1802 width: root.width
1803-
1804+ activeFocusOnTab: false
1805 onClicked: root.actionTrigerred(root.defaultAction.name, detail)
1806
1807 function overrideValue(detail, field)
1808
1809=== modified file 'src/imports/Ubuntu/AddressBook/ContactView/ContactDetailWithTypeView.qml'
1810--- src/imports/Ubuntu/AddressBook/ContactView/ContactDetailWithTypeView.qml 2015-10-26 13:18:11 +0000
1811+++ src/imports/Ubuntu/AddressBook/ContactView/ContactDetailWithTypeView.qml 2015-12-04 15:09:43 +0000
1812@@ -43,6 +43,8 @@
1813 return detail.value(field)
1814 }
1815
1816+ activeFocusOnTab: icon.visible
1817+ focus: false
1818 implicitHeight: view.implicitHeight
1819 onIsReadyChanged: populateValues()
1820
1821@@ -78,5 +80,7 @@
1822 width: root.action && (root.action.iconName !== "") ? units.gu(2.5) : 0
1823 height: width
1824 name: root.action ? root.action.iconName : ""
1825+ color: root.activeFocus ? UbuntuColors.orange : "gray"
1826+ visible: width > 0
1827 }
1828 }
1829
1830=== modified file 'src/imports/Ubuntu/AddressBook/ContactView/ContactViewPage.qml'
1831--- src/imports/Ubuntu/AddressBook/ContactView/ContactViewPage.qml 2015-11-16 15:44:43 +0000
1832+++ src/imports/Ubuntu/AddressBook/ContactView/ContactViewPage.qml 2015-12-04 15:09:43 +0000
1833@@ -41,6 +41,7 @@
1834 }
1835 }
1836
1837+ focus: false
1838 title: contact ? ContactsJS.formatToDisplay(contact, i18n.dtr("address-book-app", "No name")) : ""
1839
1840 Connections {
1841
1842=== modified file 'src/imports/Ubuntu/Contacts/ContactDelegate.qml'
1843--- src/imports/Ubuntu/Contacts/ContactDelegate.qml 2015-10-26 13:18:11 +0000
1844+++ src/imports/Ubuntu/Contacts/ContactDelegate.qml 2015-12-04 15:09:43 +0000
1845@@ -32,6 +32,7 @@
1846 signal clicked(int index, QtObject contact)
1847 signal pressAndHold(int index, QtObject contact)
1848
1849+ focus: false
1850 implicitHeight: defaultHeight
1851 width: parent ? parent.width : 0
1852
1853
1854=== modified file 'src/imports/Ubuntu/Contacts/ContactListView.qml'
1855--- src/imports/Ubuntu/Contacts/ContactListView.qml 2015-11-16 22:12:29 +0000
1856+++ src/imports/Ubuntu/Contacts/ContactListView.qml 2015-12-04 15:09:43 +0000
1857@@ -42,7 +42,7 @@
1858 }
1859 \endqml
1860 */
1861-Item {
1862+FocusScope {
1863 id: root
1864
1865 readonly property alias view: view
1866@@ -202,12 +202,6 @@
1867 */
1868 property bool showAddNewButton: false
1869 /*!
1870- \qmlproperty bool prepareNewContact
1871-
1872- This property holds if space for a draft new contact should be made available or not
1873- */
1874- property bool prepareNewContact: false
1875- /*!
1876 \qmlproperty bool showNewContact
1877
1878 This property holds if a draft new contact should be visible or not
1879@@ -253,6 +247,10 @@
1880
1881 property var _busyDialog: null
1882
1883+ //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822
1884+ //because of that we need this
1885+ property bool _allowFocus: true
1886+
1887 /*!
1888 This handler is called when the selection mode is finished without be canceled
1889 */
1890@@ -372,6 +370,8 @@
1891 buteoSync.startSyncByCategory("contacts")
1892 }
1893
1894+ focus: true
1895+
1896 ContactSimpleListView {
1897 id: view
1898
1899@@ -401,6 +401,7 @@
1900 }
1901 anchors.fill: parent
1902
1903+
1904 // WORKAROUND: The SDK header causes the contactY to move to a wrong postion
1905 // calling the positionViewAtBeginning after the list created fix that
1906 Timer {
1907@@ -418,15 +419,18 @@
1908 right: parent.right
1909 }
1910
1911- Connections {
1912- target: root
1913- onPrepareNewContactChanged: {
1914- if (root.prepareNewContact) {
1915- view.contentY = Qt.binding(function() {return -view.headerItem.height});
1916- } else {
1917- view.contentY = view.contentY;
1918- }
1919- }
1920+ Binding {
1921+ target: view
1922+ property: 'contentY'
1923+ value: -view.headerItem.height
1924+ when: root.showNewContact
1925+ }
1926+
1927+ Binding {
1928+ target: view
1929+ property: 'currentIndex'
1930+ value: -1
1931+ when: root.showNewContact
1932 }
1933
1934 // AddNewButton
1935@@ -455,10 +459,9 @@
1936 }
1937 }
1938 selected: true
1939- visible: root.prepareNewContact
1940- height: root.prepareNewContact ? defaultHeight : 0
1941+ visible: root.showNewContact
1942+ height: root.showNewContact ? defaultHeight : 0
1943 Behavior on height {UbuntuNumberAnimation {}}
1944- opacity: root.showNewContact ? 1.0 : 0.0
1945 }
1946
1947 Column {
1948@@ -624,4 +627,23 @@
1949 !view.favouritesIsSelected &&
1950 !isSearching ? sourceFile : ""
1951 }
1952+
1953+ Keys.onUpPressed: {
1954+ //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822
1955+ //because of that we need this
1956+ if (view.currentIndex == 0) {
1957+ pageStack._nextItemInFocusChain(view, false)
1958+ } else {
1959+ view.currentIndex -= 1
1960+ }
1961+ }
1962+ Keys.onDownPressed: {
1963+ //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822
1964+ //because of that we need this
1965+ if (view.currentIndex == (view.count - 1)) {
1966+ //DO nothing
1967+ } else {
1968+ view.currentIndex += 1
1969+ }
1970+ }
1971 }
1972
1973=== modified file 'src/imports/Ubuntu/Contacts/ContactSimpleListView.qml'
1974--- src/imports/Ubuntu/Contacts/ContactSimpleListView.qml 2015-11-16 22:12:29 +0000
1975+++ src/imports/Ubuntu/Contacts/ContactSimpleListView.qml 2015-12-04 15:09:43 +0000
1976@@ -204,7 +204,8 @@
1977 */
1978 function positionViewAtContact(contact)
1979 {
1980- positionViewAtIndex(getIndex(contact), ListView.Center)
1981+ currentIndex = getIndex(contact)
1982+ positionViewAtIndex(currentIndex, ListView.Center)
1983 }
1984
1985 /*!
1986@@ -213,7 +214,9 @@
1987 */
1988 function _fetchContact(index, contact)
1989 {
1990- contactFetch.fetchContact(contact.contactId)
1991+ if (contact) {
1992+ contactFetch.fetchContact(contact.contactId)
1993+ }
1994 }
1995
1996 function _updateSwipeState(item)
1997@@ -235,7 +238,6 @@
1998 }
1999
2000 highlightFollowsCurrentItem: true
2001- currentIndex: -1
2002 section {
2003 property: showSections ? "contact.tag.tag" : ""
2004 criteria: ViewSection.FirstCharacter
2005@@ -255,7 +257,6 @@
2006 dirtyModel.restart()
2007 }
2008
2009- onFlickStarted: view.currentIndex = -1
2010 listDelegate: ContactDelegate {
2011 id: contactDelegate
2012
2013@@ -270,6 +271,7 @@
2014 width: parent.width
2015 selected: (contactListView.multiSelectionEnabled && contactListView.isSelected(contactDelegate))
2016 || (contactListView.highlightSelected && (contactListView.currentIndex == index))
2017+ selectedColor: contactListView.parent.activeFocus && !contactListView.isInSelectionMode ? UbuntuColors.orange : "#E6E6E6"
2018 selectionMode: contactListView.isInSelectionMode
2019 defaultAvatarUrl: contactListView.defaultAvatarImageUrl
2020 isCurrentItem: ListView.isCurrentItem
2021@@ -371,13 +373,4 @@
2022 property int pendingTargetIndex: 0
2023 property variant pendingTargetMode: null
2024 }
2025-
2026- Connections {
2027- target: Qt.application
2028- onActiveChanged: {
2029- if (!Qt.application.active) {
2030- currentIndex = -1
2031- }
2032- }
2033- }
2034 }
2035
2036=== modified file 'src/imports/Ubuntu/Contacts/FastScroll.qml'
2037--- src/imports/Ubuntu/Contacts/FastScroll.qml 2015-10-26 13:18:11 +0000
2038+++ src/imports/Ubuntu/Contacts/FastScroll.qml 2015-12-04 15:09:43 +0000
2039@@ -71,19 +71,11 @@
2040 }
2041 }
2042
2043- Connections {
2044- target: listView
2045- onCurrentIndexChanged: {
2046- if (currentIndex != -1) {
2047- rail.opacity = 0.0
2048- }
2049- }
2050- }
2051
2052 Rectangle {
2053 id: magnified
2054
2055- color: Theme.palette.normal.overlay
2056+ color: Theme.palette.normal.foreground
2057 radius: height * 0.3
2058 height: pinSize * 2
2059 width: height
2060@@ -99,6 +91,7 @@
2061 }
2062
2063 Label {
2064+ color: "white"
2065 anchors.fill: parent
2066 horizontalAlignment: Text.AlignHCenter
2067 verticalAlignment: Text.AlignVCenter
2068@@ -141,8 +134,7 @@
2069 id: rail
2070
2071 property bool isVisible: root.enabled &&
2072- (listView.flicking || dragArea.pressed) &&
2073- (listView.currentIndex == -1)
2074+ (listView.flicking || dragArea.pressed)
2075 anchors {
2076 right: parent.right
2077 rightMargin: units.gu(2)

Subscribers

People subscribed via source and target branches