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.0
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 readonly property bool showingMap: wideMode && width >= units.gu(110)
36 readonly property alias tdModule: timeDatePanel
38 function highlightTimezone(offset) {
39 highlightImage.source = "data/timezonemap/timezone_" + offset + ".png";
42 // geo coords conversion functions (adapted from libtimezonemap)
43 function radians(degrees) {
44 return degrees * Math.PI / 180;
47 function longitudeToX(longitude, map_width) {
48 const xdeg_offset = -6;
49 const x = (map_width * (180.0 + longitude) / 360.0) + (map_width * xdeg_offset / 180.0);
53 function latitudeToY(latitude, map_height) {
54 const bottom_lat = -59;
56 const top_per = top_lat / 180.0;
58 var y = 1.25 * Math.log(Math.tan(0.25*Math.PI + 0.4 * radians(latitude)));
59 const full_range = 4.6068250867599998;
60 const top_offset = full_range * top_per;
61 const map_range = Math.abs(1.25 * Math.log(Math.tan(0.25*Math.PI + 0.4 * radians(bottom_lat))) - top_offset);
62 y = Math.abs(y - top_offset);
68 function resetViews() {
70 tzList.currentIndex = -1
71 highlightImage.source = ""
80 onContentAnimationRunningChanged: {
81 if (!contentAnimationRunning) {
82 if (tzList.count == 1) { // preselect the first (and only) TZ
83 var tz = tzList.itemAt(0,0);
90 searchField.forceActiveFocus();
98 objectName: "tz" + index
99 highlightColor: backgroundColor
100 divider.colorFrom: dividerColor
101 divider.colorTo: backgroundColor
102 readonly property bool currentTz: ListView.view.currentIndex === index
105 anchors.verticalCenter: parent.verticalCenter
106 anchors.left: parent.left
107 anchors.leftMargin: !wideMode ? staticMargin : 0
108 anchors.right: image.left
109 anchors.rightMargin: units.gu(2)
114 font.weight: tz.currentTz ? Font.Normal : Font.Light
117 elide: Text.ElideMiddle
123 text: Utils.TimezoneFormatter.currentTimeInTimezoneWithAbbrev(timeZone)
124 font.weight: tz.currentTz ? Font.Normal : Font.Light
133 verticalCenter: parent.verticalCenter
134 rightMargin: !wideMode ? staticMargin : 0
136 fillMode: Image.PreserveAspectFit
137 height: units.gu(1.5)
139 source: "data/Tick@30.png"
140 visible: tz.currentTz
144 highlightTimezone(offset);
145 ListView.view.currentIndex = index;
146 selectedTimeZone = timeZone;
147 //print("Clicked at city with coords:", longitude, latitude);
148 //print("Clicked on TZ:", timeZone);
149 //print("Highlight at (x,y):", longitudeToX(longitude, map.width), latitudeToY(latitude, map.height));
150 pinImage.x = Qt.binding(function() { return longitudeToX(longitude, map.width) - pinImage.width; });
151 pinImage.y = Qt.binding(function() { return latitudeToY(latitude, map.height) - pinImage.height; });
162 bottom: content.bottom
163 right: !showingMap ? content.right : undefined
164 leftMargin: showingMap ? staticMargin : (wideMode ? tzPage.leftMargin : 0)
165 rightMargin: showingMap ? staticMargin : (wideMode ? tzPage.rightMargin : 0)
166 topMargin: customMargin
169 width: Math.min(parent.width, units.gu(34))
171 LocalComponents.WizardTextField {
173 objectName: "tzFilter"
174 anchors.left: parent.left
175 anchors.right: parent.right
176 anchors.leftMargin: !showingMap && !wideMode ? staticMargin : undefined
177 anchors.rightMargin: !showingMap && !wideMode ? staticMargin : undefined
178 placeholderText: i18n.tr("Enter your city")
179 inputMethodHints: Qt.ImhNoPredictiveText
180 onTextChanged: resetViews();
184 Layout.fillHeight: true
188 anchors.left: parent.left
189 anchors.right: parent.right
191 model: TimeZoneModel {
193 filter: searchField.text
194 country: i18n.language.split('_')[1].split('.')[0]
196 delegate: tzComponent
200 anchors.centerIn: tzList
201 running: tzList.count == 0 &&
202 searchField.length > 0 &&
203 timeZoneModel.listUpdating
210 visible: showingMap && !contentAnimationRunning
214 left: leftColumn.right
215 leftMargin: units.gu(4)
217 rightMargin: staticMargin
219 topMargin: customMargin
220 bottom: parent.bottom
221 bottomMargin: buttonBarHeight
226 width: Math.min(parent.width, height * 1.95) // keep our aspect ratio
227 height: parent.height
234 source: "data/timezonemap/map.png"
235 sourceSize: Qt.size(map.width, map.height)
236 fillMode: Image.PreserveAspectFit
238 visible: mapContainer.visible
245 sourceSize: Qt.size(map.width, map.height)
246 fillMode: Image.PreserveAspectFit
248 visible: selectedTimeZone != ""
250 anchors.fill: backgroundImage
255 source: "data/timezonemap/pin.png"
256 visible: x != 0 && y != 0
266 LocalComponents.StackButton {
267 text: i18n.tr("Next")
268 enabled: selectedTimeZone != ""
270 timeDatePanel.timeZone = selectedTimeZone;