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/>.
18 import QtQuick.Layouts 1.1
19 import Ubuntu.Components 1.3
21 import Ubuntu.SystemSettings.TimeDate 1.1
22 import Utils 0.1 as Utils
23 import ".." as LocalComponents
25 LocalComponents.Page {
29 title: i18n.tr("Time Zone")
30 forwardButtonSourceComponent: forwardButton
32 property string selectedTimeZone: ""
33 property string selectedTimeZoneName: ""
34 readonly property bool showingMap: wideMode && width >= units.gu(110)
37 readonly property alias tdModule: timeDatePanel
39 function highlightTimezone(offset) {
40 highlightImage.source = "data/timezonemap/timezone_" + offset + ".png";
43 // geo coords conversion functions (adapted from libtimezonemap)
44 function radians(degrees) {
45 return degrees * Math.PI / 180;
48 function longitudeToX(longitude, map_width) {
49 const xdeg_offset = -6;
50 const x = (map_width * (180.0 + longitude) / 360.0) + (map_width * xdeg_offset / 180.0);
54 function latitudeToY(latitude, map_height) {
55 const bottom_lat = -59;
57 const top_per = top_lat / 180.0;
59 var y = 1.25 * Math.log(Math.tan(0.25*Math.PI + 0.4 * radians(latitude)));
60 const full_range = 4.6068250867599998;
61 const top_offset = full_range * top_per;
62 const map_range = Math.abs(1.25 * Math.log(Math.tan(0.25*Math.PI + 0.4 * radians(bottom_lat))) - top_offset);
63 y = Math.abs(y - top_offset);
69 function resetViews() {
71 selectedTimeZoneName = ""
72 tzList.currentIndex = -1
73 highlightImage.source = ""
82 onContentAnimationRunningChanged: {
83 if (!contentAnimationRunning) {
84 if (tzList.count == 1) { // preselect the first (and only) TZ
85 var tz = tzList.itemAt(0,0);
92 searchField.forceActiveFocus();
100 objectName: "tz" + index
101 highlightColor: backgroundColor
102 divider.colorFrom: dividerColor
103 divider.colorTo: backgroundColor
104 readonly property bool currentTz: ListView.view.currentIndex === index
107 anchors.verticalCenter: parent.verticalCenter
108 anchors.left: parent.left
109 anchors.leftMargin: !wideMode ? staticMargin : 0
110 anchors.right: image.left
111 anchors.rightMargin: units.gu(2)
116 font.weight: tz.currentTz ? Font.Normal : Font.Light
119 elide: Text.ElideMiddle
125 text: Utils.TimezoneFormatter.currentTimeInTimezoneWithAbbrev(timeZone)
126 font.weight: tz.currentTz ? Font.Normal : Font.Light
135 verticalCenter: parent.verticalCenter
136 rightMargin: !wideMode ? staticMargin : 0
138 fillMode: Image.PreserveAspectFit
139 height: units.gu(1.5)
141 source: "data/Tick@30.png"
142 visible: tz.currentTz
146 highlightTimezone(offset);
147 ListView.view.currentIndex = index;
148 selectedTimeZone = timeZone;
149 selectedTimeZoneName = city;
150 //print("Clicked at city with coords:", longitude, latitude);
151 //print("Clicked on TZ:", timeZone);
152 //print("Highlight at (x,y):", longitudeToX(longitude, map.width), latitudeToY(latitude, map.height));
153 pinImage.x = Qt.binding(function() { return longitudeToX(longitude, map.width) - pinImage.width; });
154 pinImage.y = Qt.binding(function() { return latitudeToY(latitude, map.height) - pinImage.height; });
165 bottom: content.bottom
166 right: !showingMap ? content.right : undefined
167 leftMargin: showingMap ? staticMargin : (wideMode ? tzPage.leftMargin : 0)
168 rightMargin: showingMap ? staticMargin : (wideMode ? tzPage.rightMargin : 0)
169 topMargin: customMargin
172 width: Math.min(parent.width, units.gu(34))
174 LocalComponents.WizardTextField {
176 objectName: "tzFilter"
177 anchors.left: parent.left
178 anchors.right: parent.right
179 anchors.leftMargin: !showingMap && !wideMode ? staticMargin : undefined
180 anchors.rightMargin: !showingMap && !wideMode ? staticMargin : undefined
181 placeholderText: i18n.tr("Enter your city")
182 inputMethodHints: Qt.ImhNoPredictiveText
183 onTextChanged: resetViews();
187 Layout.fillHeight: true
191 anchors.left: parent.left
192 anchors.right: parent.right
194 model: TimeZoneModel {
196 filter: searchField.text
197 country: i18n.language.split('_')[1].split('.')[0]
199 delegate: tzComponent
203 anchors.centerIn: tzList
204 running: tzList.count == 0 &&
205 searchField.length > 0 &&
206 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);