Kstars

LocationEdit.qml
1 // SPDX-FileCopyrightText: 2016 Artem Fedoskin <[email protected]>
2 // SPDX-License-Identifier: GPL-2.0-or-later
3 
4 import QtQuick.Controls 2.0
5 import QtQuick 2.7
6 import QtQuick.Layouts 1.1
7 import "../../constants" 1.0
8 import "../../modules"
9 import QtPositioning 5.2
10 
11 KSPage {
12  id: locationEdit
13  title: editMode ? xi18n("Edit location") : (isReadOnly ? xi18n("View location") : xi18n("Add location"))
14  property bool editMode: false
15  property bool isAvailable: positionSource.valid
16  property bool isReadOnly: false
17  property string geoName
18  property bool fieldsChanged: false //true whenever either city, province or country fields are changed. Turned to false every time this page is opened
19  property string loadingText //Text used in location loading popup
20  property string fetchingCoordinatesLoading: xi18n("Please, wait while we are fetching coordinates")
21 
22  property bool fetchingName: false // true when we are fetchingN name of location
23  property bool addAutomatically: false //true if user wants add location automatically without manually editing the fields
24 
25  signal locationFetched(var _lat, var _lng) //emitted when location is fetched in auto mode
26  signal locNameFetched(var _city, var _region, var _country) //emitted when location nane is fetched or was failed to fetch in auto mode
27 
28  /*This function sets coordinates from GPS automatically, without asking user to fill information
29  about location */
30  function setAutomaticallyFromGPS() {
31  addAutomatically = true
32  positionSource.stop()
33  positionSource.start()
34  loadingText = fetchingCoordinatesLoading
35  if(!positionSource.valid) {
36  positionSource.stop()
37  skyMapLite.notification.showNotification(xi18("Positioning is not available on your device"))
38  }
39  }
40 
41  property double lat
42  property double lng
43  property string city
44  property string region
45  property string country
46  property int tz
47 
48  onLocationFetched: {
49  lat = _lat
50  lng = _lng
51  }
52 
53  Timer {
54  id: nameFetchTimeout
55  interval: 20000;
56  onTriggered: {
57  locationLoading.close()
58  var city = xi18n("Default city")
59  var province = xi18n("Default province")
60  var country = xi18n("Default country")
61  if(addAutomatically) {
62  skyMapLite.notification.showNotification(xi18n("Could not fetch location name (check your Internet connection). Added with default name"))
63  if(!LocationDialogLite.addCity(city, province, country,
64  lat, lng, tz,
65  "--")) {
66  skyMapLite.notification.showNotification(xi18n("Failed to set location"))
67  return
68  }
69 
70  if(LocationDialogLite.setLocation(city + ", " + province + ", " + country)) {
71  skyMapLite.notification.showNotification(xi18n("Successfully set your location"))
72  } else {
73  skyMapLite.notification.showNotification(xi18n("Could not set your location"))
74  }
75  } else {
76  skyMapLite.notification.showNotification(xi18n("Could not fetch location name (check your Internet connection). Set default name"))
77  cityField.text = city
78  provinceField.text = province
79  countryField.text = country
80  comboBoxTZ.currentIndex = comboBoxTZ.find(tz)
81  }
82  fetchingName = false
83  addAutomatically = false
84  }
85  }
86 
87  onLocNameFetched: {
88  nameFetchTimeout.running = false
89  city = _city
90  region = _region
91  country = _country
92 
93  if(!LocationDialogLite.addCity(city, region, country,
94  lat, lng, tz,
95  "--")) {
96  skyMapLite.notification.showNotification(xi18n("Failed to set location"))
97  }
98 
99  if(LocationDialogLite.setLocation(city + ", " + region + ", " + country)) {
100  skyMapLite.notification.showNotification(xi18n("Successfully set your location"))
101  } else {
102  skyMapLite.notification.showNotification(xi18n("Could not set your location"))
103  }
104 
105  addAutomatically = false
106  }
107 
108  function openAdd() {
109  editMode = false
110  isReadOnly = false
111  stackView.push(this)
112  fieldsChanged = false
113  }
114 
115  function openEdit(fullName, readOnly) {
116  geoName = fullName
117  isReadOnly = readOnly
118 
119  if(!readOnly) {
120  editMode = true
121  }
122 
123  cityField.text = LocationDialogLite.getCity(fullName)
124  provinceField.text = LocationDialogLite.getProvince(fullName)
125  countryField.text = LocationDialogLite.getCountry(fullName)
126 
127  latField.text = LocationDialogLite.getLatitude(fullName)
128  longField.text = LocationDialogLite.getLongitude(fullName)
129 
130  comboBoxTZ.currentIndex = LocationDialogLite.getTZ(fullName)
131  comboBoxDST.currentIndex = LocationDialogLite.getDST(fullName)
132  stackView.push(this)
133  fieldsChanged = false
134  }
135 
136  PositionSource {
137  id: positionSource
138 
139  property bool error: false
140 
141  onSourceErrorChanged: {
142  if (sourceError == PositionSource.NoError)
143  return
144 
145  var errorDesc = ""
146 
147  if (sourceError == 2 || sourceError == 1) {
148  errorDesc = xi18n("No location service (GPS, cellular service, etc.) is available.\nPlease, switch on the location service, and retry")
149  } else if (sourceError == 4) {
150  errorDesc = xi18n("Unknown error occurred. Please contact the application developer.")
151  }
152 
153  skyMapLite.notification.showNotification(errorDesc)
154  positionSource.stop()
155  error = true
156  locationLoading.close()
157  }
158 
159  onUpdateTimeout: {
160  skyMapLite.notification.showNotification(xi18n("Timeout occurred. Try again."))
161  locationLoading.close()
162  }
163 
164  onActiveChanged: {
165  if(positionSource.active && !error) {
166  locationLoading.open()
167  } else if (!fetchingName) {
168  locationLoading.close()
169  error = false
170  }
171  }
172 
173  onPositionChanged: {
174  if(isLoaded) {
175  skyMapLite.notification.showNotification(xi18n("Found your longitude and altitude"))
176  var lat = positionSource.position.coordinate.latitude
177  var lng = positionSource.position.coordinate.longitude
178  latField.text = lat
179  longField.text = lng
180  if(addAutomatically) {
181  locationFetched(lat, lng)
182  }
183 
184  tz = (new Date().getTimezoneOffset()/60)*-1
185  loadingText = xi18n("Please, wait while we are retrieving location name")
186  fetchingName = true // must be set to true before we are stopping positioning service
187  positionSource.stop()
189  nameFetchTimeout.running = true
190  setTZComboBox(new Date().getTimezoneOffset())
191  }
192  }
193  preferredPositioningMethods: PositionSource.AllPositioningMethods
194  }
195 
196  function setTZComboBox(TZMinutes) {
197  var TZ = (TZMinutes/60)*-1
198  comboBoxTZ.currentIndex = comboBoxTZ.find(TZ)
199  }
200 
201  Connections {
202  target: LocationDialogLite
203  onNewNameFromCoordinates: {
204  if(addAutomatically) {
205  locNameFetched(city, region, country)
206  }
207  cityField.text = city
208  provinceField.text = region
209  countryField.text = country
210  fetchingName = false
211  locationLoading.close()
212  addAutomatically = false
213  }
214  }
215 
216  //close the popup and clears all text fields
217  onVisibleChanged: {
218  if(!visible) {
219  cityField.clear()
220  provinceField.clear()
221  countryField.clear()
222  latField.clear()
223  longField.clear()
224  }
225  }
226 
227  ColumnLayout {
228  anchors {
229  left: parent.left
230  right: parent.right
231  }
232 
233  GridLayout {
234  anchors {
235  left: parent.left
236  right: parent.right
237  }
238 
239  flow: window.isPortrait ? GridLayout.TopToBottom : GridLayout.LeftToRight
240 
241  ColumnLayout {
242  anchors.top: parent.top
243  Layout.maximumWidth: window.isPortrait ? parent.width : parent.width/2
244 
245  RowLayout {
246  KSLabel {
247  text: xi18n("City: ")
248  }
249 
250  KSTextField {
251  id: cityField
252  Layout.fillWidth: true
253  onTextChanged: fieldsChanged = true
254  readOnly: isReadOnly
255  }
256  }
257 
258  RowLayout {
259  KSLabel {
260  text: xi18n("Province: ")
261  }
262 
263  KSTextField {
264  id: provinceField
265  Layout.fillWidth: true
266  onTextChanged: fieldsChanged = true
267  readOnly: isReadOnly
268  }
269  }
270 
271  RowLayout {
272  KSLabel {
273  text: xi18n("Country: ")
274  }
275 
276  KSTextField {
277  id: countryField
278  Layout.fillWidth: true
279  onTextChanged: fieldsChanged = true
280  readOnly: isReadOnly
281  }
282  }
283  }
284 
285  Item {
286  height: window.isPortrait ? 15 : 0
287  }
288 
289  ColumnLayout {
290  Layout.maximumWidth: window.isPortrait ? parent.width : parent.width/2
291 
292  RowLayout {
293  KSLabel {
294  text: xi18n("Latitude: ")
295  }
296 
297  KSTextField {
298  id: latField
299  Layout.fillWidth: true
300  readOnly: isReadOnly
301  }
302  }
303 
304  RowLayout {
305 
306  KSLabel {
307  text: xi18n("Longitude: ")
308  }
309 
310  KSTextField {
311  id: longField
312  Layout.fillWidth: true
313  readOnly: isReadOnly
314  }
315  }
316 
317  Flow {
318  Layout.fillWidth: true
319  spacing: 10
320 
321  RowLayout {
322  KSLabel {
323  text: xi18n("UT offset: ")
324  }
325 
326  ComboBox {
327  id: comboBoxTZ
328  model: LocationDialogLite.TZList
329  }
330  }
331 
332  RowLayout {
333  KSLabel {
334  text: xi18n("DST rule: ")
335  }
336 
337  ComboBox {
338  id: comboBoxDST
339  model: LocationDialogLite.DSTRules
340  }
341  }
342  }
343  }
344  }
345 
346  Flow {
347  Layout.fillWidth: true
348  spacing: 10
349 
350  Button {
351  visible: !isReadOnly
352  text: xi18n("Set from GPS")
353  enabled: isAvailable
354  onClicked: {
355  positionSource.stop()
356  positionSource.start()
357  loadingText = fetchingCoordinatesLoading
358  if(!positionSource.valid) {
359  positionSource.stop()
360  skyMapLite.notification.showNotification(xi18("Positioning is not available on your device"))
361  }
362  }
363 
364  Connections {
365  target: locationLoading
366  onClosed: {
367  positionSource.stop()
368  }
369  }
370  }
371 
372  Button {
373  //enabled:
374  visible: !isReadOnly
375  text: editMode ? xi18n("Save") : xi18n("Add")
376  onClicked: {
377  if(cityField.text == "") {
378  skyMapLite.notification.showNotification(xi18n("Please, fill in the city"))
379  return
380  } else if(countryField.text == "") {
381  skyMapLite.notification.showNotification(xi18n("Please, fill in the country"))
382  return
383  } else if(latField.text == "") {
384  skyMapLite.notification.showNotification(xi18n("Please, fill in the latitude"))
385  return
386  } else if(longField.text == "") {
387  skyMapLite.notification.showNotification(xi18n("Please, fill in the longitude"))
388  return
389  }
390 
391  if(!LocationDialogLite.checkLongLat(longField.text, latField.text)) {
392  skyMapLite.notification.showNotification(xi18n("Either the longitude or the latitude values are not valid"))
393  return
394  }
395 
396  if(fieldsChanged) {
397  if(LocationDialogLite.isDuplicate(cityField.text, provinceField.text, countryField.text)) {
398  skyMapLite.notification.showNotification(xi18n("This location already exists. Change either the city, the province or the country"))
399  return
400  }
401  }
402 
403  //Fullname of new location
404  var fullName = cityField.text + ", "
405  if(provinceField.text != "") {
406  fullName += provinceField.text + ", "
407  }
408  fullName += countryField.text
409 
410  if(!editMode) {
411  if(!LocationDialogLite.addCity(cityField.text, provinceField.text, countryField.text,
412  latField.text, longField.text, comboBoxTZ.currentText,
413  comboBoxDST.currentText)) {
414  skyMapLite.notification.showNotification(xi18n("Failed to add location"))
415  return
416  } else {
417  skyMapLite.notification.showNotification(xi18n("Added new location - %1", fullName))
418  }
419  } else {
420  if(!LocationDialogLite.editCity(geoName, cityField.text, provinceField.text, countryField.text,
421  latField.text, longField.text, comboBoxTZ.currentText,
422  comboBoxDST.currentText)) {
423  skyMapLite.notification.showNotification(xi18n("Failed to edit city"))
424  return
425  }
426  }
427 
428  locationDialog.filterCities()
429  if(!editMode) {
430  //If we are adding location then open menu with newly added location
431  locationsGeoMenu.openMenu(fullName)
432  }
433 
434  stackView.pop()
435  }
436  }
437 
438  Button {
439  text: xi18n("Cancel")
440  onClicked: {
441  stackView.pop()
442  }
443  }
444  }
445  }
446 }
QTextStream & right(QTextStream &stream)
Q_INVOKABLE bool checkLongLat(const QString &longitude, const QString &latitude)
checkLongLat checks whether given longitude and latitude are valid
QTextStream & left(QTextStream &stream)
KI18NLOCALEDATA_EXPORT KCountry country(const char *ianaId)
Q_INVOKABLE void getNameFromCoordinates(double latitude, double longitude)
Retrieve name of location by latitude and longitude.
QString xi18n(const char *text, const TYPE &arg...)
QTextStream & left(QTextStream &s)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
QTextStream & right(QTextStream &s)
KJOBWIDGETS_EXPORT QWidget * window(KJob *job)
QString fullName(const PartType &type)
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Fri Aug 19 2022 03:57:52 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.