Merge lp:~nik90/unav/revamp-poi-feature into lp:unav

Proposed by Nekhelesh Ramananthan
Status: Merged
Merged at revision: 2
Proposed branch: lp:~nik90/unav/revamp-poi-feature
Merge into: lp:unav
Diff against target: 516 lines (+157/-214)
3 files modified
qml/Main.qml (+1/-0)
qml/PoiListPage.qml (+49/-108)
qml/PoiPage.qml (+107/-106)
To merge this branch: bzr merge lp:~nik90/unav/revamp-poi-feature
Reviewer Review Type Date Requested Status
uNav developers Pending
Review via email: mp+290174@code.launchpad.net

Commit message

- Migrated PoiPage and PoiListPage to PageHeaders and ListItemLayout and improving the visuals.
- Added POI description to the PoiListPage if available
- Added keyboard shortcuts "Ctrl+F" to search for POI types (Convergence)
- Added Esc shortcut to close the search mode and to also close the PoiPage! (Convergence)
- Removed all uses of deprecated ListItem.Standard components in the Poi pages
- Add live search in the PoiPage. The list will update as you type.
- Remember distance header between sessions

Description of the change

This MP adds some really nice features listed below,
- Migrated PoiPage and PoiListPage to PageHeaders and ListItemLayout and improving the visuals.
- Added POI description to the PoiListPage if available
- Added keyboard shortcuts "Ctrl+F" to search for POI types (Convergence)
- Added Esc shortcut to close the search mode and to also close the PoiPage! (Convergence)
- Removed all uses of deprecated ListItem.Standard components in the Poi pages
- Add live search in the PoiPage. The list will update as you type.

To post a comment you must log in.
lp:~nik90/unav/revamp-poi-feature updated
7. By Marcos Costales

Remember distance header between sessions

8. By Nekhelesh Ramananthan

Enclosed section header in a rectangle to remove transparency issue

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'qml/Main.qml'
2--- qml/Main.qml 2016-03-26 18:53:17 +0000
3+++ qml/Main.qml 2016-03-27 10:05:29 +0000
4@@ -69,6 +69,7 @@
5 property bool headerVisible: true
6 property bool showTuto: true
7 property bool showAGPS: true
8+ property int defaultDistancePOI: 1
9 }
10
11 ScreenSaver {
12
13=== modified file 'qml/PoiListPage.qml'
14--- qml/PoiListPage.qml 2016-03-26 18:53:17 +0000
15+++ qml/PoiListPage.qml 2016-03-27 10:05:29 +0000
16@@ -2,6 +2,7 @@
17 * GPS Navigation http://launchpad.net/unav
18 * Copyright (C) 2015-2016 Marcos Alvarez Costales https://launchpad.net/~costales
19 * Copyright (C) 2015-2016 JkB https://launchpad.net/~joergberroth
20+ * Copyright (C) 2016 Nekhelesh Ramananthan http://launchpad.net/~nik90
21 *
22 * GPS Navigation is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24@@ -15,13 +16,10 @@
25 */
26
27 import QtQuick 2.4
28-import QtQuick.Layouts 1.1
29 import Ubuntu.Components 1.3
30 import Ubuntu.Components.Popups 1.3
31-import Ubuntu.Components.ListItems 1.3 as ListItems
32 import QtQuick.XmlListModel 2.0
33 import "js/utils.js" as QmlJs
34-import QtQml 2.0
35
36 Page {
37 id: poiListPage
38@@ -34,7 +32,24 @@
39
40 property double geoDistFactor: 1.0
41
42- title: poiType
43+ header: PageHeader {
44+ title: poiType
45+ flickable: resultsListView
46+ trailingActionBar.actions: Action {
47+ id: routeAction
48+ iconSource: "../nav/img/header/poimap.svg"
49+ text: i18n.tr("Show POIs on map")
50+ visible: sortedPoiModel.count !== 0
51+ onTriggered: {
52+ if (mainPageStack.center_onpos === 2)
53+ mainPageStack.center_onpos = 1;
54+ mainPageStack.executeJavaScript("ui.markers_POI_set(" + JSON.stringify(sortedPoiModel.allPOI()) + ");")
55+ mainPageStack.pop(poiListPage.fromPage)
56+ mainPageStack.pop(poiListPage)
57+ }
58+ }
59+ }
60+
61 anchors.fill: parent
62
63 Component.onCompleted: {
64@@ -47,50 +62,6 @@
65 }
66 }
67
68- head.contents: Item {
69- id: headerContentsItem
70- anchors.fill: parent
71-
72- Label { // Show number of poi in header
73- id: numberLabel
74- anchors {
75- right: parent.right
76- rightMargin: units.gu(-1)
77- verticalCenter: parent.verticalCenter
78- }
79- z: 500
80- width: units.gu(2)
81- visible: sortedPoiModel.count !== 0
82- horizontalAlignment: Text.AlignRight
83- text: (sortedPoiModel.count !== 50 ? i18n.tr("%1 POIs").arg(sortedPoiModel.count) : i18n.tr("First %1 POIs").arg(sortedPoiModel.count)) + " "
84- fontSize: "small"
85- color: UbuntuColors.purple
86- }
87-
88- Label {
89- id: pageTitleLabel
90- anchors {
91- verticalCenter: parent.verticalCenter
92- }
93- fontSize: "large"
94- text: poiType
95- }
96- }
97-
98- head.actions: Action {
99- id: routeAction
100- iconSource: "../nav/img/header/poimap.svg"
101- text: i18n.tr("Show POIs on map")
102- visible: sortedPoiModel.count !== 0
103- onTriggered: {
104- if (mainPageStack.center_onpos === 2)
105- mainPageStack.center_onpos = 1;
106- mainPageStack.executeJavaScript("ui.markers_POI_set(" + JSON.stringify(sortedPoiModel.allPOI()) + ");")
107- mainPageStack.pop(poiListPage.fromPage)
108- mainPageStack.pop(poiListPage)
109- }
110- }
111-
112 Label {
113 id: statusLabel
114 anchors {
115@@ -204,6 +175,7 @@
116
117 XmlRole { name: "osm_id"; query: "@place_id/string()"; }
118 XmlRole { name: "name"; query: "@display_name/string()"; }
119+ XmlRole { name: "description"; query: "extratags/tag[@key='description']/@value/string()"; }
120 XmlRole { name: "phone"; query: "extratags/tag[@key='phone']/@value/string()"; }
121 XmlRole { name: "website"; query: "extratags/tag[@key='website']/@value/string()"; }
122 // XmlRole { name: "cuisine"; query: "extratags/tag[@key='cuisine']/@value/string()"; }
123@@ -235,6 +207,7 @@
124 for (var i = 0; i < poiXmlModel.count; i++) {
125 item = {"osmid": poiXmlModel.get(i).osm_id,
126 "name": poiXmlModel.get(i).name.split(',')[0],
127+ "description": poiXmlModel.get(i).description,
128 "phone": poiXmlModel.get(i).phone,
129 "website": poiXmlModel.get(i).website,
130 // "cuisine": poiXmlModel.get(i).cuisine,
131@@ -272,13 +245,15 @@
132 }
133 }
134
135- UbuntuListView {
136+ ListView {
137 id: resultsListView
138+
139 model: sortedPoiModel
140 anchors.fill: parent
141 visible: false
142
143 delegate: ListItem {
144+ height: poiListItemLayout.height + divider.height
145 trailingActions: ListItemActions {
146 actions: [
147 Action {
148@@ -328,73 +303,39 @@
149 mainPageStack.executeJavaScript("ui.markers_POI_set([{title: \"" + model.name + "\", lat: " + model.lat + ", lng: " + model.lng + ", website: \"" + model.website + "\", phone: \"" + model.phone + "\"}]);");
150 }
151
152- contentItem.anchors {
153- leftMargin: units.gu(1)
154- rightMargin: units.gu(1)
155- topMargin: units.gu(0.5)
156- bottomMargin: units.gu(0.5)
157- }
158-
159- Label {
160- id: nameLabel
161- anchors {
162- top:parent.top
163- left: parent.left
164- right: acessibilityIcon.left
165- }
166- text: model.name !== "" ? model.name : poiListPage.poiType
167- font.weight: Font.DemiBold
168- fontSize: "medium"
169- elide: Text.ElideRight
170- }
171-
172- Label {
173- anchors.bottom: parent.bottom
174- width: parent.width *4/5
175-
176- text: model.openinghours !== "" ?
177- //TRANSLATORS: abbreviation for Monday
178- model.openinghours.replace("Mo", Qt.locale().dayName(1, Locale.ShortFormat)).
179- //TRANSLATORS: abbreviation for Tuesday
180+ ListItemLayout {
181+ id: poiListItemLayout
182+
183+ function getOpeningHours(openinghours) {
184+ openinghours.replace("Mo", Qt.locale().dayName(1, Locale.ShortFormat)).
185 replace("Tu", Qt.locale().dayName(2, Locale.ShortFormat)).
186- //TRANSLATORS: abbreviation for Wednesday
187 replace("We", Qt.locale().dayName(3, Locale.ShortFormat)).
188- //TRANSLATORS: abbreviation for Thursday
189 replace("Th", Qt.locale().dayName(4, Locale.ShortFormat)).
190- //TRANSLATORS: abbreviation for Friday
191 replace("Fr", Qt.locale().dayName(5, Locale.ShortFormat)).
192- //TRANSLATORS: abbreviation for Saturday
193 replace("Sa", Qt.locale().dayName(6, Locale.ShortFormat)).
194- //TRANSLATORS: abbreviation for Sunday
195 replace("Su", Qt.locale().dayName(0, Locale.ShortFormat)).
196 //TRANSLATORS: abbreviation for Public Holiday
197- replace("PH", i18n.tr("PH") ).
198+ replace("PH", i18n.tr("PH")).
199 //TRANSLATORS: "closed"
200- replace("off", i18n.tr("off") ) : ""
201- fontSize: "small"
202- elide: Text.ElideRight
203- wrapMode: Text.WordWrap
204- maximumLineCount: 2
205- }
206-
207- Label{
208- anchors.bottom: parent.bottom
209- width: parent.width /5
210- anchors.right: parent.right
211- horizontalAlignment: Text.AlignRight
212-
213- text: QmlJs.formatDistance(model.distance, navApp.settings.unit)
214- fontSize: "small"
215- }
216-
217- Icon {
218- id: acessibilityIcon
219- name: "preferences-desktop-accessibility-symbolic"
220-
221- visible: model.wheelchair === "yes" || model.wheelchair === "limited" // is limited enought as criteria?
222- anchors.top: parent.top
223- anchors.right: parent.right
224- width: parent.height /2
225+ replace("off", i18n.tr("off"))
226+
227+ return openinghours
228+ }
229+
230+ title.text: model.name !== "" ? model.name : poiListPage.poiType
231+ subtitle.text: model.openinghours !== "" ? "%1 | %2".arg(getOpeningHours(model.openinghours)).arg(QmlJs.formatDistance(model.distance, navApp.settings.unit))
232+ : QmlJs.formatDistance(model.distance, navApp.settings.unit)
233+ subtitle.maximumLineCount: 2
234+ summary.text: model.description
235+ summary.maximumLineCount: 3
236+
237+ Icon {
238+ id: acessibilityIcon
239+ name: "preferences-desktop-accessibility-symbolic"
240+ visible: model.wheelchair === "yes" || model.wheelchair === "limited" // is limited enough as criteria?
241+ width: parent.height / 2
242+ SlotsLayout.position: SlotsLayout.Last
243+ }
244 }
245 }
246 }
247
248=== modified file 'qml/PoiPage.qml'
249--- qml/PoiPage.qml 2016-03-26 18:53:17 +0000
250+++ qml/PoiPage.qml 2016-03-27 10:05:29 +0000
251@@ -2,6 +2,7 @@
252 * GPS Navigation http://launchpad.net/unav
253 * Copyright (C) 2015-2016 Marcos Alvarez Costales https://launchpad.net/~costales
254 * Copyright (C) 2015-2016 JkB https://launchpad.net/~joergberroth
255+ * Copyright (C) 2016 Nekhelesh Ramananthan http://launchpad.net/~nik90
256 *
257 * GPS Navigation is free software; you can redistribute it and/or modify
258 * it under the terms of the GNU General Public License as published by
259@@ -15,96 +16,95 @@
260 */
261
262 import QtQuick 2.4
263-import QtQuick.Layouts 1.1
264 import Ubuntu.Components 1.3
265-import Ubuntu.Components.ListItems 1.3 as ListItems
266 import QtQuick.XmlListModel 2.0
267+import QtQuick.LocalStorage 2.0
268+import "components"
269 import "js/PoiCategories.js" as Categories
270-import QtQuick.LocalStorage 2.0
271 import "js/db.js" as UnavDB
272
273 Page {
274 id: poiPage
275
276- title: i18n.tr("Nearby")
277- anchors.fill: parent
278-
279 property var fromPage
280 property var lat
281 property var lng
282 property string unit: navApp.settings.unit === 0 ? "km" : "mi"
283 property var factorList: ["1", "5", "15", "30", "50"]
284- state: "default"
285- states: [
286- PageHeadState {
287- name: "default"
288- head: poiPage.head
289-
290- backAction: Action {
291- iconName: "back"
292- text: i18n.tr("Back")
293- onTriggered: {
294- mainPageStack.pop(poiPage);
295- if (poiPage.fromPage === "RoutePage.qml")
296- mainPageStack.push(Qt.resolvedUrl("RoutePage.qml"));
297- }
298- }
299-
300- actions: [
301- Action {
302- id: searchAction
303- iconName: "find"
304- text: i18n.tr("Search")
305- onTriggered: {
306- poiPage.state = "search"
307- poiSearchField.forceActiveFocus()
308- }
309- }
310- ]
311- },
312-
313- PageHeadState {
314- name: "search"
315- head: poiPage.head
316-
317- backAction: Action {
318- iconName: "back"
319- text: i18n.tr("Back")
320- onTriggered: {
321- mainPageStack.pop(poiPage)
322- if (poiPage.fromPage === "RoutePage.qml")
323- mainPageStack.push(Qt.resolvedUrl("RoutePage.qml"));
324- }
325- }
326-
327- contents: TextField {
328- id: poiSearchField
329- anchors {
330- rightMargin: units.gu(2)
331- }
332- width: parent ? parent.width - units.gu(2) : undefined
333- inputMethodHints: Qt.ImhNoPredictiveText
334- hasClearButton: true
335- onTriggered: {
336- if ( text.length > 0) {
337- categoryList.searchString(text);
338- }
339- }
340- onTextChanged: {
341- if (text.length === 0) {
342- categoryListModel.clear();
343- categoryListModel.initialize();
344- poiSearchField.forceActiveFocus();
345- }
346- }
347- }
348- }
349- ]
350-
351- head {
352- sections {
353+
354+ header: standardHeader
355+ anchors.fill: parent
356+
357+ function goBackStandardMode() {
358+ mainPageStack.pop(poiPage);
359+ if (poiPage.fromPage === "RoutePage.qml")
360+ mainPageStack.push(Qt.resolvedUrl("RoutePage.qml"));
361+ }
362+
363+ function goBackSearchMode() {
364+ categoryList.forceActiveFocus()
365+ poiPage.header = standardHeader
366+ poiSearchField.text = ""
367+ }
368+
369+ Keys.onEscapePressed: {
370+ header === standardHeader ? goBackStandardMode()
371+ : goBackSearchMode()
372+ }
373+
374+ PageHeader {
375+ id: standardHeader
376+ visible: poiPage.header === standardHeader
377+ title: i18n.tr("Nearby")
378+ leadingActionBar.actions: Action {
379+ iconName: "back"
380+ text: i18n.tr("Back")
381+ onTriggered: {
382+ goBackStandardMode()
383+ }
384+ }
385+
386+ trailingActionBar.actions: Action {
387+ id: searchAction
388+ iconName: "find"
389+ text: i18n.tr("Search")
390+ shortcut: "Ctrl+F"
391+ onTriggered: {
392+ poiPage.header = searchHeader
393+ poiSearchField.forceActiveFocus()
394+ }
395+ }
396+
397+ extension: Sections {
398+ id: distanceSections
399+ anchors {
400+ left: parent.left
401+ bottom: parent.bottom
402+ }
403+
404 model: [factorList[0]+unit, factorList[1]+unit, factorList[2]+unit, factorList[3]+unit, factorList[4]+unit]
405- selectedIndex: 1
406+ selectedIndex: navApp.settings.defaultDistancePOI
407+ onSelectedIndexChanged: navApp.settings.defaultDistancePOI = distanceSections.selectedIndex;
408+ }
409+ }
410+
411+ PageHeader {
412+ id: searchHeader
413+ visible: poiPage.header === searchHeader
414+ leadingActionBar.actions: Action {
415+ iconName: "back"
416+ text: i18n.tr("Back")
417+ onTriggered: {
418+ goBackSearchMode()
419+ }
420+ }
421+
422+ contents: TextField {
423+ id: poiSearchField
424+ width: parent.width
425+ anchors.verticalCenter: parent.verticalCenter
426+ inputMethodHints: Qt.ImhNoPredictiveText
427+ hasClearButton: true
428 }
429 }
430
431@@ -133,54 +133,55 @@
432 Component.onCompleted: initialize()
433 }
434
435- Component {
436- id: sectionHeading
437-
438- Rectangle {
439- width: parent.width
440- height: childrenRect.height
441-
442- ListItems.Header {
443- id: listHeader
444- text: section
445- }
446- }
447+
448+ SortFilterModel {
449+ id: sortedCategoryListModel
450+ model: categoryListModel
451+ filter.property: "label"
452+ filter.pattern: poiPage.header === searchHeader ? RegExp(poiSearchField.text, "gi")
453+ : RegExp("", "gi")
454 }
455
456- UbuntuListView {
457+ ListView {
458 id: categoryList
459- model: categoryListModel
460
461+ model: sortedCategoryListModel
462 anchors.fill: parent
463+ anchors.topMargin: poiPage.header.height
464 clip: true
465
466- function searchString( string) {
467- categoryListModel.initialize();
468- for( var i = 0; i < categoryListModel.count; i++){
469- if (model.get(i).label.toLowerCase().indexOf(string.toLowerCase()) === -1) {
470- model.remove(i); i--;
471- }
472- }
473- }
474-
475 section.property: "theme"
476 section.criteria: ViewSection.FullString
477 section.labelPositioning: ViewSection.CurrentLabelAtStart + ViewSection.InlineLabels
478- section.delegate: sectionHeading
479- delegate: ListItems.Standard {
480+ section.delegate: Rectangle {
481+ width: parent.width
482+ height: sectionHeader.height
483+
484+ HeaderListItem {
485+ id: sectionHeader
486+ title: section
487+ }
488+ }
489+
490+ delegate: ListItem {
491 id: poiItem
492- showDivider: false
493- text: label
494- progression: true
495+ divider.visible: false
496+ height: poiItemLayout.height
497+ ListItemLayout {
498+ id: poiItemLayout
499+ title.text: label
500+ ProgressionSlot{}
501+ }
502 onClicked: {
503- //mainPageStack.pop(poiPage);
504+ poiSearchField.text = ""
505+ poiPage.header = standardHeader
506 mainPageStack.push(Qt.resolvedUrl("PoiListPage.qml"), {
507 fromPage: poiPage,
508 lat: poiPage.lat,
509 lng: poiPage.lng,
510 poiType: model.label,
511 clause: model.clause,
512- geoDistFactor: Number(factorList[poiPage.head.sections.selectedIndex])
513+ geoDistFactor: Number(factorList[distanceSections.selectedIndex])
514 });
515 if (navApp.settings.saveHistory) {
516 UnavDB.saveToNearByHistory(model.en_label, model.clause);

Subscribers

People subscribed via source and target branches