├── .gitignore ├── app-contenthub.json ├── icon.png ├── clickable.json ├── nav ├── voices │ ├── 0.ogg │ ├── 1.ogg │ ├── 10.ogg │ ├── 11.ogg │ ├── 12.ogg │ ├── 13.ogg │ ├── 2.ogg │ ├── 3.ogg │ ├── 4.ogg │ ├── 5.ogg │ ├── 6.ogg │ ├── 70.ogg │ ├── 71.ogg │ ├── 72.ogg │ ├── 73.ogg │ ├── 74.ogg │ ├── 9.ogg │ ├── 99.ogg │ └── radar.ogg ├── img │ ├── about │ │ └── logo.png │ ├── voices │ │ ├── tick.svg │ │ └── no-tick.svg │ ├── panel │ │ ├── email.svg │ │ ├── phone.svg │ │ ├── website.svg │ │ ├── tick.svg │ │ ├── non-starred.svg │ │ ├── cancel.svg │ │ ├── send.svg │ │ └── share.svg │ ├── steps │ │ ├── 6.svg │ │ ├── 1.svg │ │ ├── 0.svg │ │ ├── 5.svg │ │ ├── 4.svg │ │ ├── 9.svg │ │ ├── 13.svg │ │ ├── 12.svg │ │ ├── 11.svg │ │ ├── 70.svg │ │ ├── 8.svg │ │ ├── 2.svg │ │ ├── 3.svg │ │ ├── 99.svg │ │ ├── 72.svg │ │ ├── 71.svg │ │ ├── 73.svg │ │ └── 74.svg │ ├── poi │ │ ├── Cemetery.svg │ │ ├── Tourism Information.svg │ │ ├── Car Rental.svg │ │ ├── Veterinary.svg │ │ ├── Pharmacy.svg │ │ ├── Campsite.svg │ │ ├── Parking.svg │ │ ├── School.svg │ │ ├── Motel.svg │ │ ├── ATM.svg │ │ ├── Supermarket.svg │ │ ├── Drinking Water.svg │ │ ├── Subway Entrance.svg │ │ ├── Cinema.svg │ │ ├── Charging Station.svg │ │ ├── Hotel.svg │ │ ├── Theatre.svg │ │ ├── Bureau de Change.svg │ │ ├── Toilet.svg │ │ ├── Monument.svg │ │ ├── Picnic Site.svg │ │ ├── Laundry.svg │ │ ├── Car Wash.svg │ │ └── Town Hall.svg │ ├── ui │ │ ├── geoDisabled.svg │ │ ├── geoEnabled.svg │ │ └── compass.svg │ ├── marker │ │ ├── car.svg │ │ └── POI.svg │ ├── mode │ │ ├── walk.svg │ │ └── car.svg │ └── radars │ │ ├── radar-30.svg │ │ ├── radar-60.svg │ │ ├── radar-70.svg │ │ └── radar-90.svg ├── locales │ ├── mo │ │ └── en │ │ │ └── LC_MESSAGES │ │ │ └── unav.mo │ ├── 3rdparty │ │ ├── README │ │ ├── poeditor_pull.py │ │ └── po2json.py │ └── README ├── libraries │ ├── dotimeout.min.js │ └── i18n.js ├── class │ └── Utils.js ├── css │ └── UT_toolkit.css └── UT_toolkit │ └── buttons.js ├── app-dispatcher.json ├── app-armor.json ├── manifest.json ├── app.desktop ├── qml ├── py │ └── fsutils.py ├── components │ ├── UNavPageSection.qml │ ├── CloseHeaderAction.qml │ ├── ListItemHeader.qml │ ├── UNavHeader.qml │ ├── ActionIcon.qml │ ├── UNavHeaderButton.qml │ ├── IconButton.qml │ ├── ContentHubModel.qml │ └── ExpandableListItem.qml ├── GPX.qml ├── Simulate.qml ├── GPXImport.qml ├── js │ └── utils.js ├── Share.qml └── Search.qml └── Makefile /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /app-contenthub.json: -------------------------------------------------------------------------------- 1 | { 2 | "share": [ 3 | "links" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/icon.png -------------------------------------------------------------------------------- /clickable.json: -------------------------------------------------------------------------------- 1 | { 2 | "builder": "pure", 3 | "kill": "qmlscene" 4 | } 5 | -------------------------------------------------------------------------------- /nav/voices/0.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/voices/0.ogg -------------------------------------------------------------------------------- /nav/voices/1.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/voices/1.ogg -------------------------------------------------------------------------------- /nav/voices/10.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/voices/10.ogg -------------------------------------------------------------------------------- /nav/voices/11.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/voices/11.ogg -------------------------------------------------------------------------------- /nav/voices/12.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/voices/12.ogg -------------------------------------------------------------------------------- /nav/voices/13.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/voices/13.ogg -------------------------------------------------------------------------------- /nav/voices/2.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/voices/2.ogg -------------------------------------------------------------------------------- /nav/voices/3.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/voices/3.ogg -------------------------------------------------------------------------------- /nav/voices/4.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/voices/4.ogg -------------------------------------------------------------------------------- /nav/voices/5.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/voices/5.ogg -------------------------------------------------------------------------------- /nav/voices/6.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/voices/6.ogg -------------------------------------------------------------------------------- /nav/voices/70.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/voices/70.ogg -------------------------------------------------------------------------------- /nav/voices/71.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/voices/71.ogg -------------------------------------------------------------------------------- /nav/voices/72.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/voices/72.ogg -------------------------------------------------------------------------------- /nav/voices/73.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/voices/73.ogg -------------------------------------------------------------------------------- /nav/voices/74.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/voices/74.ogg -------------------------------------------------------------------------------- /nav/voices/9.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/voices/9.ogg -------------------------------------------------------------------------------- /nav/voices/99.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/voices/99.ogg -------------------------------------------------------------------------------- /nav/img/about/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/img/about/logo.png -------------------------------------------------------------------------------- /nav/voices/radar.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/voices/radar.ogg -------------------------------------------------------------------------------- /nav/locales/mo/en/LC_MESSAGES/unav.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/costales/unav/HEAD/nav/locales/mo/en/LC_MESSAGES/unav.mo -------------------------------------------------------------------------------- /nav/locales/3rdparty/README: -------------------------------------------------------------------------------- 1 | po2json.py was downloaded from https://github.com/fileformat/lptools/blob/master/po2json.py. 2 | -------------------------------------------------------------------------------- /app-dispatcher.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "protocol": "https", 4 | "domain-suffix": "map.unav.me" 5 | }, 6 | { 7 | "protocol": "geo" 8 | } 9 | ] 10 | -------------------------------------------------------------------------------- /app-armor.json: -------------------------------------------------------------------------------- 1 | { 2 | "policy_groups": [ 3 | "networking", 4 | "webview", 5 | "audio", 6 | "location", 7 | "keep-display-on", 8 | "content_exchange", 9 | "content_exchange_source" 10 | ], 11 | "policy_version": 20.04 12 | } 13 | -------------------------------------------------------------------------------- /nav/locales/README: -------------------------------------------------------------------------------- 1 | Download translations from POEditor: 2 | https://github.com/costales/poeditor_pull 3 | 4 | To update the translation template, cd to the root of the source tree, 5 | and run `rm po/unav.pot ; make po/unav.pot`. 6 | 7 | To compile translation catalogs for use by the application in QML, HTML and 8 | javascript files, cd to the root of the source tree, 9 | and run `make translations`. 10 | 11 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "architecture": "all", 3 | "description": "Turn-by-turn GPS Navigation", 4 | "framework": "ubuntu-sdk-20.04", 5 | "hooks": { 6 | "navigator": { 7 | "apparmor": "app-armor.json", 8 | "desktop": "app.desktop", 9 | "urls": "app-dispatcher.json", 10 | "content-hub": "app-contenthub.json" 11 | } 12 | }, 13 | "maintainer": "Marcos Costales ", 14 | "name": "navigator.costales", 15 | "title": "uNav", 16 | "version": "3.20" 17 | } 18 | -------------------------------------------------------------------------------- /app.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=uNav 3 | Comment=Simple and easy GPS navigator 4 | Keywords=map;maps;GPS;navigator;navigation;OSM;OpenStreetMap; 5 | Type=Application 6 | Icon=icon.png 7 | Exec=qmlscene --scaling %u qml/Main.qml 8 | Terminal=false 9 | X-Ubuntu-Touch=true 10 | 11 | X-Ayatana-Appmenu-Show-Stubs=false 12 | X-Ubuntu-Single-Instance=true 13 | X-Ubuntu-Splash-Show-Header=false 14 | X-Ubuntu-Splash-Image=icon-splash.svg 15 | X-Ubuntu-Splash-Color-Header=#3575db 16 | X-Ubuntu-Splash-Color=#3575db 17 | X-Ubuntu-Splash-Color-Footer=#3575db 18 | -------------------------------------------------------------------------------- /qml/py/fsutils.py: -------------------------------------------------------------------------------- 1 | import os, tarfile 2 | 3 | dir_unav = '.local/share/navigator.costales' 4 | dir_download = '.local/share/ubuntu-download-manager/Downloads' 5 | 6 | def rm_older(): 7 | dir_src = os.path.join(os.path.expanduser('~'), dir_download) 8 | for filename in os.listdir(dir_src): 9 | if 'unav_' in filename and '.tar.gz' in filename: 10 | src = os.path.join(os.path.expanduser('~'), dir_download, filename) 11 | os.remove(src) 12 | 13 | def mv_voice(tar): 14 | print('tar.gz: ' + tar) 15 | 16 | tar = tarfile.open(tar) 17 | tar.extractall(os.path.join(os.path.expanduser('~'), dir_unav)) 18 | tar.close() 19 | 20 | rm_older() 21 | -------------------------------------------------------------------------------- /nav/locales/3rdparty/poeditor_pull.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import urllib 4 | import os 5 | 6 | 7 | project_api = os.environ["poeditor_api"] 8 | project_id = os.environ["poeditor_id"] 9 | 10 | print("Getting languages list") 11 | r_langs = requests.post('https://api.poeditor.com/v2/languages/list', dict(api_token=project_api, id=project_id)) 12 | 13 | json_langs = json.loads(r_langs.text) 14 | for lang in json_langs['result']['languages']: 15 | print("Downloading PO file:",lang['code']) 16 | r_lang = requests.post('https://api.poeditor.com/v2/projects/export', dict(api_token=project_api, id=project_id, language=lang['code'], type="po")) 17 | json_lang = json.loads(r_lang.text) 18 | url = json_lang['result']['url'] 19 | filename = './' + lang['code'] + '.po' 20 | urllib.request.urlretrieve(url, filename) -------------------------------------------------------------------------------- /qml/components/UNavPageSection.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * uNav https://github.com/costales/unav 3 | * Copyright (C) 2016 Nekhelesh Ramananthan https://launchpad.net/~nik90 4 | * 5 | * uNav is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * uNav is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | */ 15 | 16 | import QtQuick 2.4 17 | import Lomiri.Components 1.3 18 | 19 | Sections { 20 | StyleHints { 21 | sectionColor: "White" 22 | selectedSectionColor: "White" 23 | underlineColor: "Transparent" 24 | pressedBackgroundColor: "#6CC0FF" 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /nav/img/voices/tick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | image/svg+xml 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /qml/components/CloseHeaderAction.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * uNav https://github.com/costales/unav 3 | * Copyright (C) 2016 Nekhelesh Ramananthan https://launchpad.net/~nik90 4 | * 5 | * uNav is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * uNav is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | */ 15 | 16 | import QtQuick 2.4 17 | import Lomiri.Components 1.3 18 | 19 | Action { 20 | id: closeButton 21 | iconName: "close" 22 | visible: mainPageStack.columns !== 1 23 | shortcut: "Escape" 24 | onTriggered: { 25 | mainPageStack.hideSideBar(); 26 | mainPageStack.removePages(mainPageStack.primaryPage); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /nav/img/panel/email.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /qml/components/ListItemHeader.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * uNav https://github.com/costales/unav 3 | * Copyright (C) 2016 Nekhelesh Ramananthan https://launchpad.net/~nik90 4 | * 5 | * uNav is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * uNav is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | */ 15 | 16 | import QtQuick 2.4 17 | import Lomiri.Components 1.3 18 | 19 | ListItem { 20 | id: headerListItem 21 | 22 | property string title 23 | 24 | height: units.gu(4) 25 | Label { 26 | anchors { verticalCenter: parent.verticalCenter; left: parent.left; leftMargin: units.gu(2) } 27 | text: title 28 | font.bold: false 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /qml/components/UNavHeader.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * uNav https://github.com/costales/unav 3 | * Copyright (C) 2016 Nekhelesh Ramananthan https://launchpad.net/~nik90 4 | * 5 | * uNav is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * uNav is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | */ 15 | 16 | import QtQuick 2.4 17 | import Lomiri.Components 1.3 18 | 19 | PageHeader { 20 | StyleHints { 21 | backgroundColor: navApp.settings.dark_theme ? "#181716" : "#3575db" 22 | foregroundColor: "White" 23 | dividerColor: "White" 24 | } 25 | 26 | trailingActionBar.delegate: UNavHeaderButton {} 27 | leadingActionBar.delegate: UNavHeaderButton {} 28 | } 29 | -------------------------------------------------------------------------------- /nav/libraries/dotimeout.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery doTimeout: Like setTimeout, but better! - v1.0 - 3/3/2010 3 | * http://benalman.com/projects/jquery-dotimeout-plugin/ 4 | * 5 | * Copyright (c) 2010 "Cowboy" Ben Alman 6 | * Dual licensed under the MIT and GPL licenses. 7 | * http://benalman.com/about/license/ 8 | */ 9 | (function($){var a={},c="doTimeout",d=Array.prototype.slice;$[c]=function(){return b.apply(window,[0].concat(d.call(arguments)))};$.fn[c]=function(){var f=d.call(arguments),e=b.apply(this,[c+f[0]].concat(f));return typeof f[0]==="number"||typeof f[1]==="number"?this:e};function b(l){var m=this,h,k={},g=l?$.fn:$,n=arguments,i=4,f=n[1],j=n[2],p=n[3];if(typeof f!=="string"){i--;f=l=0;j=n[1];p=n[2]}if(l){h=m.eq(0);h.data(l,k=h.data(l)||{})}else{if(f){k=a[f]||(a[f]={})}}k.id&&clearTimeout(k.id);delete k.id;function e(){if(l){h.removeData(l)}else{if(f){delete a[f]}}}function o(){k.id=setTimeout(function(){k.fn()},j)}if(p){k.fn=function(q){if(typeof p==="string"){p=g[p]}p.apply(m,d.call(n,i))===true&&!q?o():e()};o()}else{if(k.fn){j===undefined?e():k.fn(j===false);return true}else{e()}}}})(jQuery); -------------------------------------------------------------------------------- /qml/components/ActionIcon.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * uNav https://github.com/costales/unav 3 | * Copyright (C) 2016 Nekhelesh Ramananthan https://launchpad.net/~nik90 4 | * 5 | * Ubuntu Clock App is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License version 3 as 7 | * published by the Free Software Foundation. 8 | * 9 | * Ubuntu Clock App is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | import QtQuick 2.4 19 | import Lomiri.Components 1.3 20 | 21 | AbstractButton { 22 | id: abstractButton 23 | 24 | property alias icon: _icon 25 | 26 | width: _icon.width + units.gu(2) 27 | height: width 28 | 29 | Icon { 30 | id: _icon 31 | width: units.gu(2) 32 | height: width 33 | anchors.centerIn: parent 34 | color: theme.palette.normal.foreground 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /nav/locales/3rdparty/po2json.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # convert .po to .json 4 | # 5 | 6 | import json 7 | import optparse 8 | import os 9 | import polib 10 | import re 11 | import string 12 | import sys 13 | 14 | parser = optparse.OptionParser(usage="usage: %prog [options] pofile...") 15 | parser.add_option("--quiet", action="store_false", default=True, dest="verbose", help="don't print status messages to stdout") 16 | 17 | (options, args) = parser.parse_args() 18 | 19 | if args == None or len(args) == 0: 20 | print("ERROR: you must specify at least one po file to translate"); 21 | sys.exit(1) 22 | 23 | paramFix = re.compile("(\\(([0-9])\\))") 24 | 25 | for srcfile in args: 26 | 27 | destfile = os.path.splitext(srcfile)[0] + ".json" 28 | if options.verbose: 29 | print("INFO: converting %s to %s" % (srcfile, destfile)) 30 | 31 | xlate_map = {} 32 | 33 | po = polib.pofile(srcfile, autodetect_encoding=False, encoding="utf-8", wrapwidth=-1) 34 | for entry in po: 35 | xlate_map[entry.msgid] = entry.msgstr; 36 | 37 | dest = open(destfile, "w") 38 | 39 | dest.write(json.dumps(xlate_map, sort_keys = True)); 40 | 41 | dest.close() 42 | 43 | -------------------------------------------------------------------------------- /qml/GPX.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * GPS Navigation https://github.com/costales/unav 3 | * Copyright (C) 2015-2020 Marcos Alvarez Costales https://costales.github.io 4 | * 5 | * GPS Navigation is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * GPS Navigation is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | */ 15 | 16 | import QtQuick 2.4 17 | import Lomiri.Components 1.3 18 | 19 | Item { 20 | id: gpx 21 | 22 | Column { 23 | id: importGPX 24 | anchors.centerIn: parent 25 | spacing: units.gu(1) 26 | Button { 27 | id: btnImport 28 | text: i18n.tr("Import track") 29 | width: units.gu(30) 30 | anchors.horizontalCenter: parent.horizontalCenter 31 | color: theme.palette.normal.positive 32 | onClicked: { 33 | mainPageStack.addPageToCurrentColumn(searchPage, Qt.resolvedUrl("GPXImport.qml")); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /qml/components/UNavHeaderButton.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * uNav https://github.com/costales/unav 3 | * Copyright (C) 2016 Nekhelesh Ramananthan https://launchpad.net/~nik90 4 | * 5 | * uNav is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * uNav is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | */ 15 | 16 | import QtQuick 2.4 17 | import Lomiri.Components 1.3 18 | 19 | AbstractButton { 20 | width: units.gu(4) 21 | height: parent ? parent.height : undefined 22 | action: modelData 23 | 24 | Rectangle { 25 | id: background 26 | color: parent.pressed ? "#6CC0FF" : "transparent" 27 | anchors.fill: parent 28 | } 29 | 30 | Icon { 31 | id: icon 32 | anchors.centerIn: parent 33 | width: units.gu(2) 34 | height: width 35 | source: action.iconSource 36 | name: action.iconName 37 | color: "White" 38 | opacity: parent.enabled ? 1.0 : 0.4 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /qml/Simulate.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * GPS Navigation https://github.com/costales/unav 3 | * Copyright (C) 2015-2020 Marcos Alvarez Costales https://costales.github.io 4 | * 5 | * GPS Navigation is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * GPS Navigation is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | */ 15 | 16 | import QtQuick 2.4 17 | import Lomiri.Components 1.3 18 | 19 | Item { 20 | id: gpx 21 | 22 | Column { 23 | id: simulate 24 | anchors.centerIn: parent 25 | spacing: units.gu(1) 26 | Button { 27 | id: btnFrom 28 | text: i18n.tr("Pick origin & destination") 29 | enabled: !mainPageStack.simulateRoute 30 | width: units.gu(30) 31 | anchors.horizontalCenter: parent.horizontalCenter 32 | color: theme.palette.normal.positive 33 | onClicked: { 34 | if (mainPageStack.columns === 1) 35 | mainPageStack.removePages(searchPage); 36 | mainPageStack.executeJavaScript("ui.set_pickingOnMap(1)"); 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /qml/components/IconButton.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Canonical Ltd. 3 | * 4 | * dialer-app is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; version 3. 7 | * 8 | * dialer-app is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | import QtQuick 2.4 18 | import Lomiri.Components 1.3 19 | 20 | AbstractButton { 21 | id: button 22 | 23 | readonly property string defaultColor: "#0F8B21" 24 | property alias color: shape.backgroundColor 25 | property alias icon: icon 26 | 27 | width: units.gu(5) 28 | height: units.gu(5) 29 | opacity: button.pressed ? 0.5 : (enabled ? 1 : 0.2) 30 | 31 | Behavior on opacity { 32 | LomiriNumberAnimation { } 33 | } 34 | 35 | LomiriShape { 36 | id: shape 37 | 38 | aspect: LomiriShape.Flat 39 | anchors.fill: parent 40 | backgroundColor: defaultColor 41 | radius: "medium" 42 | } 43 | 44 | Icon { 45 | id: icon 46 | 47 | anchors.centerIn: parent 48 | width: units.gu(3) 49 | height: units.gu(3) 50 | color: "white" 51 | z: 1 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /nav/class/Utils.js: -------------------------------------------------------------------------------- 1 | /* 2 | * uNav https://github.com/costales/unav 3 | * Copyright (C) 2015-2020 Marcos Alvarez Costales https://costales.github.io 4 | * 5 | * uNav is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * uNav is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | */ 15 | 16 | function Utils() { 17 | } 18 | 19 | Utils.prototype.parse_poi_url = function(poi_website) { 20 | if (poi_website.trim() == '') // No website 21 | return ''; 22 | var web = poi_website.replace(/ /g,''); 23 | if (web.substring(0, 8) === "https://" || web.substring(0, 7) === "http://") 24 | return web; 25 | else 26 | return "https://" + web; 27 | } 28 | 29 | Utils.prototype.parse_poi_phone = function(poi_phone) { 30 | if (poi_phone.trim() == '') // No phone 31 | return ''; 32 | return poi_phone.replace(/ /g,''); // Removes all spaces 33 | } 34 | 35 | Utils.prototype.fix_lng = function(lng) { // Fix bug openLayers #4522 36 | var lng_aux = lng; 37 | while(lng_aux > 180) 38 | lng_aux-=360; 39 | while(lng_aux < -180) 40 | lng_aux+=360; 41 | return lng_aux; 42 | } 43 | -------------------------------------------------------------------------------- /nav/img/voices/no-tick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 41 | 43 | 44 | 46 | image/svg+xml 47 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # -*- makefile -*- 3 | 4 | POT_FILE=po/unav.pot 5 | 6 | HTML_JS_FILE=nav/index.html 7 | HTML_STRINGS_FILE=nav/index.html.strings 8 | $(HTML_STRINGS_FILE): nav/index.html 9 | grep -Po 'data-localize=([^>]*)' $< > $@ 10 | $(HTML_STRINGS_FILE).h: $(HTML_STRINGS_FILE) 11 | intltool-extract --type=gettext/quoted $< 12 | 13 | QML_FILES=$(shell find -iname *.qml -printf '%P\n') 14 | JS_FILES=$(wildcard nav/class/*.js qml/js/*.js) 15 | 16 | I18N_FILES=$(sort $(QML_FILES) $(JS_FILES) $(HTML_JS_FILE) $(HTML_STRINGS_FILE).h) 17 | 18 | $(POT_FILE): $(I18N_FILES) 19 | xgettext -o $@ --from-code=UTF-8 -C --qt --add-comments=TRANSLATORS \ 20 | --keyword=tr --keyword=tr:1,2 --keyword=t --keyword=N_ \ 21 | --package-name=unav -D . $^ 22 | 23 | PO_FILES=$(wildcard po/*.po) 24 | 25 | MO_ROOT=nav/locales/mo 26 | MO_FILES=$(PO_FILES:po%.po=$(MO_ROOT)%/LC_MESSAGES/unav.mo) 27 | $(MO_ROOT)/%/LC_MESSAGES/unav.mo: po/%.po 28 | mkdir -p `dirname $@` 29 | msgfmt -o $@ $< 30 | 31 | JSON_ROOT=nav/locales/json 32 | JSON_FILES=$(PO_FILES:po/%po=$(JSON_ROOT)/messages-%json) 33 | $(JSON_ROOT)/messages-%.json: po/%.po 34 | python nav/locales/3rdparty/po2json.py $< 35 | mv $(subst .po,.json,$<) $@ 36 | cp $@ $(subst @,-,$(subst _,-,$@)) || true 37 | 38 | translations: $(MO_FILES) $(JSON_FILES) 39 | 40 | APPNAME=$(shell grep -Po '"name":\s*"([^>]*)"' manifest.json | cut -d\" -f4) 41 | APPVERSION=$(shell grep -Po '"version":\s*"([^>]*)"' manifest.json | cut -d\" -f4) 42 | APPARCH=all 43 | CLICKPKG=$(APPNAME)_$(APPVERSION)_$(APPARCH).click 44 | $(CLICKPKG): translations 45 | click build -I Makefile -I "*.click" -I po -I 3rdparty -I README . 46 | click: $(CLICKPKG) 47 | 48 | clean: 49 | rm -rf $(HTML_STRINGS_FILE) $(HTML_STRINGS_FILE).h *.click 50 | release: 51 | # Preserve API keys 52 | /home/costales/Code/unav/release.sh 53 | -------------------------------------------------------------------------------- /nav/img/steps/6.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml 48 | -------------------------------------------------------------------------------- /nav/img/panel/phone.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /nav/img/steps/1.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml 48 | -------------------------------------------------------------------------------- /nav/img/steps/0.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/steps/5.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml 49 | -------------------------------------------------------------------------------- /nav/css/UT_toolkit.css: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2013 Adnane Belmadiaf 4 | * License granted by Canonical Limited 5 | * 6 | * This file is part of ubuntu-html5-ui-toolkit. 7 | * 8 | * This package is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as 10 | * published by the Free Software Foundation; either version 3 of the 11 | * License, or 12 | * (at your option) any later version. 13 | 14 | * This package is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | 19 | * You should have received a copy of the GNU Lesser General Public 20 | * License along with this program. If not, see 21 | * 22 | */ 23 | /* ---------------------------------- 24 | * Buttons 25 | * ---------------------------------- */ 26 | [data-role="button"] { 27 | -webkit-box-sizing: border-box; 28 | box-sizing: border-box; 29 | display: inline-block; 30 | width: 100%; 31 | height: 42px; 32 | vertical-align: middle; 33 | text-overflow: ellipsis; 34 | white-space: nowrap; 35 | overflow: hidden; 36 | background: #dd4814; 37 | border: 2px solid #dd4814; 38 | border-radius: 6px; 39 | color: white; 40 | font-family: "Ubuntu"; 41 | font-size: 1rem; 42 | text-align: center; 43 | text-decoration: none; 44 | position: relative; 45 | } 46 | [data-role="button"].positive { 47 | background: #0E8420; 48 | color: white; 49 | border-color: #38b44a; 50 | } 51 | [data-role="button"].information { 52 | background: #2ab7ec; 53 | color: white; 54 | border-color: #2ab7ec; 55 | } 56 | [data-role="button"].secondary { 57 | background: white; 58 | color: #888888; 59 | } 60 | [data-role="button"].negative { 61 | background: #666666; 62 | color: white; 63 | border-color: #929292; 64 | } 65 | -------------------------------------------------------------------------------- /nav/img/steps/4.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml 49 | -------------------------------------------------------------------------------- /qml/GPXImport.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * uNav https://github.com/costales/unav 3 | * Copyright (C) 2015-2020 Marcos Alvarez Costales https://costales.github.io 4 | * 5 | * uNav is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * uNav is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | */ 15 | 16 | import QtQuick 2.4 17 | import Lomiri.Content 1.3 18 | import Lomiri.Components 1.3 19 | import "components" 20 | 21 | Page { 22 | id: picker 23 | 24 | // Property to indicate if the share page was opened directly (from a popup) or as a child (from the search page) 25 | property bool isParentPage: false 26 | 27 | header: UNavHeader { 28 | title: i18n.tr("Import GPX from") 29 | } 30 | 31 | ContentPeerPicker { 32 | id: peerPicker 33 | 34 | showTitle: false 35 | contentType: ContentType.Documents 36 | handler: ContentHandler.Source 37 | 38 | anchors.topMargin: picker.header.height 39 | 40 | onPeerSelected: { 41 | peer.selectionType = ContentTransfer.Single; 42 | picker.activeTransfer = peer.request(); 43 | stateChangeConnection.target = picker.activeTransfer; 44 | } 45 | 46 | onCancelPressed: { 47 | mainPageStack.removePages(picker); 48 | } 49 | 50 | } 51 | 52 | Connections { 53 | target: ContentHub 54 | 55 | onImportRequested: { 56 | var filePath = String(transfer.items[0].url).replace('file://', '') 57 | if (filePath.toLowerCase().endsWith(".gpx")) 58 | mainPageStack.executeJavaScript("import_gpx('" + filePath + "')"); 59 | 60 | if (mainPageStack.columns === 1) { 61 | mainPageStack.hideSideBar(); 62 | mainPageStack.removePages(mainPageStack.primaryPage); 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /qml/js/utils.js: -------------------------------------------------------------------------------- 1 | function rad(x) { 2 | return x * Math.PI / 180; 3 | }; 4 | // Calculate distance in Search page 5 | function distance2points(lng1, lat1, lng2, lat2) { 6 | if (lng1 == 'null' || lat1 == 'null') 7 | return 0; 8 | 9 | var R = 6378137; 10 | var dLat = rad(lat2 - lat1); 11 | var dLong = rad(lng2 - lng1); 12 | var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + 13 | Math.cos(rad(lat1)) * Math.cos(rad(lat2)) * 14 | Math.sin(dLong / 2) * Math.sin(dLong / 2); 15 | var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); 16 | var d = R * c; 17 | return Math.round(d); 18 | }; 19 | 20 | function validate_lat(lat) { 21 | try { 22 | if (!isNaN(lat) && lat.toString().indexOf('.') != -1 && lat >= -90 && lat <= 90) // It's a float 23 | return parseFloat(lat); 24 | } 25 | catch(e){ 26 | return null; 27 | } 28 | } 29 | function validate_lng(lng) { 30 | try { 31 | if (!isNaN(lng) && lng.toString().indexOf('.') != -1 && lng >= -180 && lng <= 180) // It's a float 32 | return parseFloat(lng); 33 | } 34 | catch(e){ 35 | return null; 36 | } 37 | } 38 | function split_unav_url(url) { 39 | var aux_url = url.replace('https://map.unav.me/?', '').replace('https://map.unav.me?', '').replace('%2C', ','); 40 | var params = aux_url.split(','); 41 | return {lng: validate_lng(params[1]), lat: validate_lat(params[0])}; 42 | } 43 | function split_geo_url(url) { 44 | var aux_url = url.replace('geo:', '').replace('?', ' ').replace(';', ' ').replace(',', ' '); 45 | var params = aux_url.split(' '); 46 | return {lng: validate_lng(params[1]), lat: validate_lat(params[0])}; 47 | } 48 | function get_url_coord(url_shared) { 49 | var url = url_shared.toLowerCase(); 50 | if (url.startsWith("https://map.unav.me")) { 51 | return split_unav_url(url); 52 | } 53 | if (url.startsWith("geo:")) { 54 | return split_geo_url(url); 55 | } 56 | return {lng: null, lat: null}; 57 | } 58 | 59 | -------------------------------------------------------------------------------- /nav/img/steps/9.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/panel/website.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Artboard 77 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /nav/img/steps/13.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/steps/12.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/poi/Cemetery.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/poi/Tourism Information.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/panel/tick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 41 | 43 | 44 | 46 | image/svg+xml 47 | 49 | 50 | 51 | 52 | 53 | 56 | 64 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /nav/UT_toolkit/buttons.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Adnane Belmadiaf 3 | * License granted by Canonical Limited 4 | * 5 | * This file is part of ubuntu-html5-ui-toolkit. 6 | * 7 | * This package is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 3 of the 10 | * License, or 11 | * (at your option) any later version. 12 | 13 | * This package is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this program. If not, see 20 | * . 21 | */ 22 | 23 | /** 24 | * A Button. 25 | 26 | Note the Ubuntu CSS style classes: positive, information, secondary, and negative 27 | 28 | * @class Button 29 | * @constructor 30 | * @namespace UbuntuUI 31 | * @example 32 | 33 | 34 | Javascript access: 35 | var button = UI.button("buttonID"); 36 | */ 37 | var Button = function (id) { 38 | this.id = id; 39 | }; 40 | 41 | Button.prototype = { 42 | /** 43 | * Associate a function with the button's Click event 44 | * @method click 45 | * @param {Function} callback - The function to execute on click 46 | * @example 47 | UI.button("buttonid").click(function(){ 48 | console.log("clicked"); 49 | }); 50 | */ 51 | click: function (callback) { 52 | if ( ! document.getElementById(this.id)) { 53 | throw "Invalid button ID: " + String(this.id); 54 | } 55 | new FastButton(document.getElementById(this.id), callback); 56 | }, 57 | /** 58 | * Returns the DOM element associated with the id this widget is bind to. 59 | * @method element 60 | * @return {DOMElement} 61 | * @example 62 | var mybutton = UI.button("buttonid").element(); 63 | */ 64 | element: function() { 65 | return document.getElementById(this.id); 66 | } 67 | }; 68 | -------------------------------------------------------------------------------- /nav/img/poi/Car Rental.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/poi/Veterinary.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/poi/Pharmacy.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/poi/Campsite.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/poi/Parking.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/poi/School.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | Artboard 14 28 | 29 | 30 | 31 | 33 | 53 | Artboard 14 55 | 59 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /nav/libraries/i18n.js: -------------------------------------------------------------------------------- 1 | /*! Localize - v0.2.0 - 2016-10-13 2 | * https://github.com/coderifous/jquery-localize 3 | * Copyright (c) 2016 coderifous; Licensed MIT */ 4 | !function(a){var b;return b=function(a){return a=a.replace(/_/,"-").toLowerCase(),a.length>3&&(a=a.substring(0,3)+a.substring(3).toUpperCase()),a},a.defaultLanguage=b(navigator.languages&&navigator.languages.length>0?navigator.languages[0]:navigator.language||navigator.userLanguage),a.localize=function(c,d){var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v;return null==d&&(d={}),v=this,h={},g=d.fileExtension||"json",f=a.Deferred(),k=function(a,b,c){var e;switch(null==c&&(c=1),c){case 1:return h={},d.loadBase?(e=a+("."+g),i(e,a,b,c)):k(a,b,2);case 2:return e=""+a+"-"+b.split("-")[0]+"."+g,i(e,a,b,c);case 3:return e=""+a+"-"+b.split("-").slice(0,2).join("-")+"."+g,i(e,a,b,c);default:return f.resolve()}},i=function(b,c,e,f){var g,i,j;return null!=d.pathPrefix&&(b=""+d.pathPrefix+"/"+b),j=function(b){return a.extend(h,b),q(h),k(c,e,f+1)},i=function(){return 2===f&&e.indexOf("-")>-1?k(c,e,f+1):d.fallback&&d.fallback!==e?k(c,d.fallback):void 0},g={url:b,dataType:"json",async:!0,timeout:null!=d.timeout?d.timeout:500,success:j,error:i},"file:"===window.location.protocol&&(g.error=function(b){return j(a.parseJSON(b.responseText))}),a.ajax(g)},q=function(a){return null!=d.callback?d.callback(a,e):e(a)},e=function(b){return a.localize.data[c]=b,v.each(function(){var c,d,e;return c=a(this),d=c.data("localize"),d||(d=c.attr("rel").match(/localize\[(.*?)\]/)[1]),e=u(d,b),null!=e?l(c,d,e):void 0})},l=function(b,c,d){return b.is("input")?o(b,c,d):b.is("textarea")?o(b,c,d):b.is("img")?n(b,c,d):b.is("optgroup")?p(b,c,d):a.isPlainObject(d)||b.html(d),a.isPlainObject(d)?m(b,d):void 0},o=function(b,c,d){var e;return e=a.isPlainObject(d)?d.value:d,b.is("[placeholder]")?b.attr("placeholder",e):b.val(e)},m=function(a,b){return s(a,"title",b),s(a,"href",b),t(a,"text",b)},p=function(a,b,c){return a.attr("label",c)},n=function(a,b,c){return s(a,"alt",c),s(a,"src",c)},u=function(a,b){var c,d,e,f;for(c=a.split(/\./),d=b,e=0,f=c.length;f>e;e++)a=c[e],d=null!=d?d[a]:null;return d},s=function(a,b,c){return c=u(b,c),null!=c?a.attr(b,c):void 0},t=function(a,b,c){return c=u(b,c),null!=c?a.text(c):void 0},r=function(a){var b;return"string"==typeof a?"^"+a+"$":null!=a.length?function(){var c,d,e;for(e=[],c=0,d=a.length;d>c;c++)b=a[c],e.push(r(b));return e}().join("|"):a},j=b(d.language?d.language:a.defaultLanguage),d.skipLanguage&&j.match(r(d.skipLanguage))?f.resolve():k(c,j,1),v.localizePromise=f,v},a.fn.localize=a.localize,a.localize.data={}}(jQuery); -------------------------------------------------------------------------------- /nav/img/steps/11.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | start, flag, marker 28 | 29 | 30 | 31 | 33 | 53 | start, flag, marker 55 | 58 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /nav/img/steps/70.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml 50 | -------------------------------------------------------------------------------- /nav/img/steps/8.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml 50 | -------------------------------------------------------------------------------- /qml/components/ContentHubModel.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import Lomiri.Components 1.3 3 | import Lomiri.Content 1.3 4 | import Lomiri.Components.Popups 1.3 5 | import "../components" 6 | 7 | Item { 8 | 9 | id: shareController 10 | property url uri: "" 11 | property alias clipboardText: mimeData.text 12 | 13 | signal done () 14 | signal shareRequested ( var transfer ) 15 | 16 | function toClipboard ( text ) { 17 | mimeData.text = text 18 | Clipboard.push( mimeData ) 19 | } 20 | 21 | function share(url, text, contentType) { 22 | uri = url 23 | var sharePopup = PopupUtils.open(shareDialog, shareController, {"contentType" : contentType}) 24 | sharePopup.items.push(contentItemComponent.createObject(shareController, {"url" : uri, "text": text})) 25 | } 26 | 27 | function shareLink( url ) { 28 | share( url, url, ContentType.Links) 29 | } 30 | 31 | function shareText( text ) { 32 | share( "", text, ContentType.Text) 33 | } 34 | 35 | function sharePicture( url, title ) { 36 | share( url, title, ContentType.Pictures) 37 | } 38 | 39 | function shareAudio( url, title ) { 40 | share( url, title, ContentType.Music) 41 | } 42 | 43 | function shareVideo( url, title ) { 44 | share( url, title, ContentType.Videos) 45 | } 46 | 47 | function shareFile( url, title ) { 48 | share( url, title, ContentType.Documents) 49 | } 50 | 51 | function shareAll( url, title ) { 52 | share( url, title, ContentType.All) 53 | } 54 | 55 | Connections { 56 | target: ContentHub 57 | onShareRequested: shareRequested(transfer) 58 | } 59 | 60 | Component { 61 | id: shareDialog 62 | PopupBase { 63 | id: sharePopUp 64 | anchors.fill: parent 65 | property var activeTransfer 66 | property var items: [] 67 | property alias contentType: peerPicker.contentType 68 | 69 | Rectangle { 70 | anchors.fill: parent 71 | ContentPeerPicker { 72 | id: peerPicker 73 | handler: ContentHandler.Share 74 | visible: parent.visible 75 | 76 | onPeerSelected: { 77 | activeTransfer = peer.request() 78 | activeTransfer.items = sharePopUp.items 79 | activeTransfer.state = ContentTransfer.Charged 80 | PopupUtils.close(sharePopUp) 81 | } 82 | 83 | onCancelPressed: { 84 | PopupUtils.close(sharePopUp) 85 | } 86 | } 87 | } 88 | } 89 | } 90 | 91 | Component { 92 | id: contentItemComponent 93 | ContentItem { } 94 | } 95 | 96 | MimeData { 97 | id: mimeData 98 | text: "" 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /nav/img/steps/2.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml 58 | -------------------------------------------------------------------------------- /nav/img/steps/3.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml 58 | -------------------------------------------------------------------------------- /nav/img/ui/geoDisabled.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/ui/geoEnabled.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /qml/Share.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * uNav https://github.com/costales/unav 3 | * Copyright (C) 2015-2020 Marcos Alvarez Costales https://costales.github.io 4 | * Copyright (C) 2016 Nekhelesh Ramananthan https://launchpad.net/~nik90 5 | * 6 | * uNav is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * uNav is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | import QtQuick 2.4 18 | import Lomiri.Content 1.3 19 | import Lomiri.Components 1.3 20 | import "components" 21 | 22 | Page { 23 | id: picker 24 | 25 | property var lat 26 | property var lng 27 | 28 | // Property to indicate if the share page was opened directly (from a popup) or as a child (from the search page) 29 | property bool isParentPage: false 30 | 31 | header: UNavHeader { 32 | title: i18n.tr("Share location to") 33 | trailingActionBar.actions: CloseHeaderAction { 34 | visible: mainPageStack.columns !== 1 && isParentPage 35 | } 36 | } 37 | 38 | Component.onDestruction: { 39 | // Hide 2nd column when returning to the map to avoid an empty white column 40 | if (mainPageStack.columns === 1 && isParentPage) 41 | mainPageStack.hideSideBar() 42 | } 43 | 44 | Component { 45 | id: resultComponent 46 | ContentItem {} 47 | } 48 | 49 | ContentPeerPicker { 50 | id: peerPicker 51 | 52 | showTitle: false 53 | contentType: ContentType.Links 54 | handler: ContentHandler.Share 55 | 56 | anchors.topMargin: picker.header.height 57 | 58 | onCancelPressed: { 59 | // Do not pop the share page when in a 2-column layout as it will leave an empty second column 60 | if (mainPageStack.columns === 1) { 61 | mainPageStack.removePages(picker); 62 | } 63 | } 64 | 65 | onPeerSelected: { 66 | var request = peer.request(); 67 | var url2shared = 'https://map.unav.me?' + parseFloat(picker.lat).toFixed(5) + ',' + parseFloat(picker.lng).toFixed(5); 68 | request.items = [ resultComponent.createObject(navApp.mainPageStack, {"url": url2shared}) ]; 69 | request.state = ContentTransfer.Charged; 70 | // Do not pop the share page when in a 2-column layout as it will leave 71 | // an empty second column 72 | if (mainPageStack.columns === 1) { 73 | mainPageStack.removePages(picker); 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /nav/img/poi/Motel.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/panel/non-starred.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /qml/components/ExpandableListItem.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * uNav https://github.com/costales/unav 3 | * Copyright (C) 2016 Nekhelesh Ramananthan https://launchpad.net/~nik90 4 | * 5 | * uNav is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License version 3 as 7 | * published by the Free Software Foundation. 8 | * 9 | * uNav is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | import QtQuick 2.4 19 | import Lomiri.Components 1.3 20 | 21 | /* 22 | Component which extends the SDK Expandable list item and provides a easy 23 | to use component where the title, subtitle and a listview can be displayed. It 24 | matches the design specification provided for clock. 25 | */ 26 | 27 | ListItem { 28 | id: expandableListItem 29 | 30 | // Public APIs 31 | property ListModel model 32 | property Component delegate 33 | property alias titleText: expandableHeader.title 34 | property alias subText: expandableHeader.subtitle 35 | property alias listViewHeight: expandableListLoader.height 36 | 37 | height: headerListItem.height 38 | expansion.height: headerListItem.height + expandableListLoader.height 39 | onClicked: toggleExpansion() 40 | 41 | function toggleExpansion() { 42 | expansion.expanded = !expansion.expanded 43 | } 44 | 45 | ListItem { 46 | id: headerListItem 47 | height: expandableHeader.height + divider.height 48 | divider.visible: false 49 | ListItemLayout { 50 | id: expandableHeader 51 | 52 | subtitle.textSize: Label.Medium 53 | subtitle.visible: !expansion.expanded 54 | Icon { 55 | id: arrow 56 | 57 | width: units.gu(2) 58 | height: width 59 | SlotsLayout.position: SlotsLayout.Trailing 60 | name: "go-down" 61 | rotation: expandableListItem.expansion.expanded ? 180 : 0 62 | 63 | Behavior on rotation { 64 | LomiriNumberAnimation {} 65 | } 66 | } 67 | } 68 | } 69 | 70 | Loader { 71 | id: expandableListLoader 72 | width: parent.width 73 | asynchronous: true 74 | anchors.top: headerListItem.bottom 75 | sourceComponent: expandableListItem.expansion.expanded ? expandableListComponent : undefined 76 | } 77 | 78 | Component { 79 | id: expandableListComponent 80 | ListView { 81 | id: expandableList 82 | interactive: false 83 | model: expandableListItem.model 84 | delegate: expandableListItem.delegate 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /nav/img/marker/car.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 55 | 60 | 65 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /nav/img/poi/ATM.svg: -------------------------------------------------------------------------------- 1 | 2 | 20 | 22 | 23 | 25 | image/svg+xml 26 | 28 | 97 29 | 30 | 31 | 32 | 34 | 54 | 97 56 | 59 | 63 | 67 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /nav/img/poi/Supermarket.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/poi/Drinking Water.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/mode/walk.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/panel/cancel.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /nav/img/poi/Subway Entrance.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | Underground 4.3 28 | 29 | 30 | 31 | 33 | 53 | Underground 4.3 55 | Created with Sketch. 57 | 61 | 64 | 68 | 72 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /nav/img/poi/Cinema.svg: -------------------------------------------------------------------------------- 1 | 2 | 20 | 22 | 23 | 25 | image/svg+xml 26 | 28 | 69 all 29 | 30 | 31 | 32 | 34 | 54 | 69 all 56 | 59 | 63 | 68 | 73 | 78 | 83 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /nav/img/steps/99.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/poi/Charging Station.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/steps/72.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml2 55 | 56 | -------------------------------------------------------------------------------- /nav/img/steps/71.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml1 55 | 56 | -------------------------------------------------------------------------------- /nav/img/poi/Hotel.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 200 Hotel 2 stars 27 | 28 | 29 | 30 | 32 | 52 | 200 Hotel 2 stars 54 | 57 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /nav/img/steps/73.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml3 57 | 58 | -------------------------------------------------------------------------------- /nav/img/steps/74.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml4 57 | 58 | -------------------------------------------------------------------------------- /nav/img/poi/Theatre.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/panel/send.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 30 | 50 | 53 | 62 | 72 | 81 | 87 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /nav/img/poi/Bureau de Change.svg: -------------------------------------------------------------------------------- 1 | 2 | 21 | 23 | 24 | 26 | image/svg+xml 27 | 29 | 30 | 31 | 32 | 33 | 35 | 55 | 60 | 61 | -------------------------------------------------------------------------------- /nav/img/poi/Toilet.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/marker/POI.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 49 | 51 | 58 | 62 | 67 | 68 | 69 | 72 | 77 | 83 | 90 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /nav/img/poi/Monument.svg: -------------------------------------------------------------------------------- 1 | 2 | 20 | 22 | 23 | 25 | image/svg+xml 26 | 28 | city elements solid ai 29 | 30 | 31 | 32 | 34 | 54 | city elements solid ai 56 | 61 | 62 | -------------------------------------------------------------------------------- /nav/img/poi/Picnic Site.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | halt 28 | 29 | 30 | 31 | 33 | 53 | halt 55 | Created with Sketch. 57 | 61 | 64 | 68 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /nav/img/panel/share.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /nav/img/poi/Laundry.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | laundry 28 | 29 | 30 | 31 | 33 | 53 | laundry 55 | 58 | 61 | 65 | 69 | 73 | 77 | 81 | 85 | 89 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /nav/img/ui/compass.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | 28 | 29 | 30 | 31 | 33 | 53 | 56 | 64 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /nav/img/mode/car.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /nav/img/poi/Car Wash.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | 28 | 29 | 30 | 31 | 33 | 53 | 58 | 59 | -------------------------------------------------------------------------------- /nav/img/poi/Town Hall.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /qml/Search.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * uNav https://github.com/costales/unav 3 | * Copyright (C) 2015-2020 Marcos Alvarez Costales https://costales.github.io 4 | * Copyright (C) 2015-2016 JkB https://launchpad.net/~joergberroth 5 | * Copyright (C) 2016 Nekhelesh Ramananthan https://launchpad.net/~nik90 6 | * 7 | * uNav is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * uNav is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | */ 17 | 18 | import QtQuick 2.4 19 | import Lomiri.Components 1.3 20 | import Lomiri.Components.Popups 1.3 21 | import "components" 22 | 23 | Page { 24 | id: searchPage 25 | 26 | Component.onCompleted: { 27 | mainPageStack.executeJavaScript("qml_current_pos()"); 28 | } 29 | 30 | Component.onDestruction: { 31 | mainPageStack.hideSideBar(); 32 | } 33 | 34 | header: UNavHeader { 35 | id: standardHeader 36 | 37 | contents: Label { 38 | textSize: Label.Large 39 | color: "White" 40 | font.weight: Font.Light 41 | text: i18n.tr("Search") 42 | verticalAlignment: Text.AlignVCenter 43 | width: parent.width; height: units.gu(4) 44 | anchors.verticalCenter: parent.verticalCenter 45 | } 46 | 47 | trailingActionBar.actions: [ 48 | CloseHeaderAction {} 49 | ] 50 | 51 | extension: UNavPageSection { 52 | id: typeSections 53 | anchors { 54 | left: parent.left 55 | right: parent.right 56 | bottom: parent.bottom 57 | } 58 | 59 | // TRANSLATORS: These are section headers. Please keep their translations short and not 60 | // longer than their original string lengths. 61 | model: [i18n.tr("Places"), i18n.tr("POIs"), i18n.tr("Favorites"), i18n.tr("Simulate"), i18n.tr("Track"), i18n.tr("Coordinate")] 62 | selectedIndex: navApp.settings.lastSearchTab 63 | 64 | onSelectedIndexChanged: { 65 | navApp.settings.lastSearchTab = selectedIndex; 66 | if (selectedIndex !== 1) { 67 | addActionList.hide() 68 | } 69 | } 70 | } 71 | } 72 | 73 | Loader { 74 | id: mainLoader 75 | anchors { top: (typeSections.selectedIndex == 3) ? standardHeader.bottom : standardHeader.bottom; left: parent.left; right: parent.right; bottom: parent.bottom } 76 | source: { 77 | switch(typeSections.selectedIndex) { 78 | case 0: 79 | if (navApp.settings.onlineSearch) 80 | return Qt.resolvedUrl("places/online.qml"); 81 | else 82 | return Qt.resolvedUrl("places/offline.qml"); 83 | break; 84 | case 1: 85 | return Qt.resolvedUrl("POIs.qml"); 86 | break; 87 | case 2: 88 | return Qt.resolvedUrl("Favorites.qml") 89 | break; 90 | case 3: 91 | return Qt.resolvedUrl("Simulate.qml") 92 | break; 93 | case 4: 94 | return Qt.resolvedUrl("GPX.qml") 95 | break; 96 | case 5: 97 | return Qt.resolvedUrl("Coordinate.qml") 98 | break; 99 | default: 100 | return ''; 101 | } 102 | } 103 | } 104 | 105 | ActionSelectionPopover { 106 | id: addActionList 107 | 108 | width: units.gu(25) 109 | anchors { 110 | top: parent.top 111 | right: parent.right 112 | rightMargin: units.gu(0.5) 113 | topMargin: searchPage.header.height 114 | } 115 | 116 | delegate: ListItem { 117 | Label { 118 | text: action.text 119 | elide: Text.ElideMiddle 120 | opacity: action.enabled ? 1.0 : 0.5 121 | anchors { left: parent.left; right: parent.right; margins: units.gu(2); verticalCenter: parent.verticalCenter } 122 | } 123 | } 124 | } 125 | } 126 | 127 | -------------------------------------------------------------------------------- /nav/img/radars/radar-30.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | Axle Weight Limit 28 | 29 | 30 | 31 | 33 | 53 | Axle Weight Limit 55 | Created with Sketch. 57 | 61 | 67 | 72 | 30 83 | 84 | 85 | -------------------------------------------------------------------------------- /nav/img/radars/radar-60.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | Axle Weight Limit 28 | 29 | 30 | 31 | 33 | 53 | Axle Weight Limit 55 | Created with Sketch. 57 | 61 | 67 | 72 | 60 83 | 84 | 85 | -------------------------------------------------------------------------------- /nav/img/radars/radar-70.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | Axle Weight Limit 28 | 29 | 30 | 31 | 33 | 53 | Axle Weight Limit 55 | Created with Sketch. 57 | 61 | 67 | 72 | 70 83 | 84 | 85 | -------------------------------------------------------------------------------- /nav/img/radars/radar-90.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | Axle Weight Limit 28 | 29 | 30 | 31 | 33 | 53 | Axle Weight Limit 55 | Created with Sketch. 57 | 61 | 67 | 72 | 90 83 | 84 | 85 | --------------------------------------------------------------------------------