2 * Copyright (C) 2015-2016 Canonical Ltd.
4 * This program 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.
8 * This program 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.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18import QtQuick.Layouts 1.1
19import Lomiri.Components 1.3
21import Lomiri.SystemSettings.TimeDate 1.1
22import Utils 0.1 as Utils
23import ".." as LocalComponents
24import "../../Components"
30 title: i18n.tr("Time Zone")
31 focusItem: searchField
32 forwardButtonSourceComponent: forwardButton
34 property string selectedTimeZone: ""
35 property string selectedTimeZoneName: ""
36 readonly property bool showingMap: wideMode && width >= units.gu(110)
39 readonly property alias tdModule: timeDatePanel
42 function highlightTimezone(offset) {
43 highlightImage.source = "data/timezonemap/timezone_" + offset + ".png";
46 // geo coords conversion functions (adapted from libtimezonemap)
47 function radians(degrees) {
48 return degrees * Math.PI / 180;
51 function longitudeToX(longitude, map_width) {
52 const xdeg_offset = -6;
53 const x = (map_width * (180.0 + longitude) / 360.0) + (map_width * xdeg_offset / 180.0);
57 function latitudeToY(latitude, map_height) {
58 const bottom_lat = -59;
60 const top_per = top_lat / 180.0;
62 var y = 1.25 * Math.log(Math.tan(0.25*Math.PI + 0.4 * radians(latitude)));
63 const full_range = 4.6068250867599998;
64 const top_offset = full_range * top_per;
65 const map_range = Math.abs(1.25 * Math.log(Math.tan(0.25*Math.PI + 0.4 * radians(bottom_lat))) - top_offset);
66 y = Math.abs(y - top_offset);
72 function resetViews() {
74 selectedTimeZoneName = ""
75 tzList.currentIndex = -1
76 highlightImage.source = ""
85 onContentAnimationRunningChanged: {
86 if (!contentAnimationRunning) {
87 if (tzList.count == 1) { // preselect the first (and only) TZ
88 var tz = tzList.itemAt(0,0);
102 objectName: "tz" + index
103 highlightColor: backgroundColor
104 divider.colorFrom: dividerColor
105 divider.colorTo: backgroundColor
106 readonly property bool currentTz: ListView.view.currentIndex === index
109 anchors.verticalCenter: parent.verticalCenter
110 anchors.left: parent.left
111 anchors.leftMargin: !wideMode ? staticMargin : 0
112 anchors.right: image.left
113 anchors.rightMargin: units.gu(2)
118 font.weight: tz.currentTz ? Font.Normal : Font.Light
121 elide: Text.ElideMiddle
127 text: Utils.TimezoneFormatter.currentTimeInTimezoneWithAbbrev(timeZone)
128 font.weight: tz.currentTz ? Font.Normal : Font.Light
137 verticalCenter: parent.verticalCenter
138 rightMargin: !wideMode ? staticMargin : 0
140 fillMode: Image.PreserveAspectFit
141 height: units.gu(1.5)
143 source: "data/Tick@30.png"
144 visible: tz.currentTz
148 highlightTimezone(offset);
149 ListView.view.currentIndex = index;
150 selectedTimeZone = timeZone;
151 selectedTimeZoneName = city;
152 //print("Clicked at city with coords:", longitude, latitude);
153 //print("Clicked on TZ:", timeZone);
154 //print("Highlight at (x,y):", longitudeToX(longitude, map.width), latitudeToY(latitude, map.height));
155 pinImage.x = Qt.binding(function() { return longitudeToX(longitude, map.width) - pinImage.width; });
156 pinImage.y = Qt.binding(function() { return latitudeToY(latitude, map.height) - pinImage.height; });
167 bottom: content.bottom
168 right: !showingMap ? content.right : undefined
169 leftMargin: showingMap ? staticMargin : (wideMode ? tzPage.leftMargin : 0)
170 rightMargin: showingMap ? staticMargin : (wideMode ? tzPage.rightMargin : 0)
171 topMargin: customMargin
174 width: Math.min(parent.width, units.gu(34))
176 LocalComponents.WizardTextField {
177 Layout.fillWidth: true
179 objectName: "tzFilter"
180 anchors.leftMargin: !showingMap && !wideMode ? staticMargin : undefined
181 anchors.rightMargin: !showingMap && !wideMode ? staticMargin : undefined
182 placeholderText: i18n.tr("Enter your city")
183 inputMethodHints: Qt.ImhNoPredictiveText
184 onTextChanged: resetViews();
188 Layout.fillWidth: true
189 Layout.fillHeight: true
194 model: TimeZoneModel {
196 filter: searchField.text
197 country: i18n.language.split('_')[1].split('.')[0]
199 delegate: tzComponent
202 anchors.centerIn: parent
203 running: tzList.count == 0 &&
204 searchField.length > 0 &&
205 timeZoneModel.listUpdating
213 visible: showingMap && !contentAnimationRunning
217 left: leftColumn.right
218 leftMargin: units.gu(4)
220 rightMargin: staticMargin
222 topMargin: customMargin
223 bottom: parent.bottom
224 bottomMargin: buttonBarHeight
229 width: Math.min(parent.width, height * 1.95) // keep our aspect ratio
230 height: parent.height
237 source: "data/timezonemap/map.png"
238 sourceSize: Qt.size(map.width, map.height)
239 fillMode: Image.PreserveAspectFit
241 visible: mapContainer.visible
248 sourceSize: Qt.size(map.width, map.height)
249 fillMode: Image.PreserveAspectFit
251 visible: selectedTimeZone != ""
253 anchors.fill: backgroundImage
258 source: "data/timezonemap/pin.png"
259 visible: x != 0 && y != 0
269 LocalComponents.StackButton {
270 text: i18n.tr("Next")
271 enabled: selectedTimeZone != ""
273 timeDatePanel.setTimeZone(selectedTimeZone, selectedTimeZoneName);