Merge lp:~renatofilho/address-book-app/new-bottom-edge into lp:address-book-app
- new-bottom-edge
- Merge into trunk
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 |
Related bugs: |
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.
Description of the change
- 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
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) |