Warning, /education/kstars/kstars/kstarslite/qml/dialogs/helpers/LocationEdit.qml is written in an unsupported language. File is not indexed.

0001 // SPDX-FileCopyrightText: 2016 Artem Fedoskin <afedoskin3@gmail.com>
0002 // SPDX-License-Identifier: GPL-2.0-or-later
0003 
0004 import QtQuick.Controls 2.0
0005 import QtQuick 2.7
0006 import QtQuick.Layouts 1.1
0007 import "../../constants" 1.0
0008 import "../../modules"
0009 import QtPositioning 5.2
0010 
0011 KSPage {
0012     id: locationEdit
0013     title: editMode ? xi18n("Edit location") : (isReadOnly ? xi18n("View location") : xi18n("Add location"))
0014     property bool editMode: false
0015     property bool isAvailable: positionSource.valid
0016     property bool isReadOnly: false
0017     property string geoName
0018     property bool fieldsChanged: false //true whenever either city, province or country fields are changed. Turned to false every time this page is opened
0019     property string loadingText //Text used in location loading popup
0020     property string fetchingCoordinatesLoading: xi18n("Please, wait while we are fetching coordinates")
0021 
0022     property bool fetchingName: false // true when we are fetchingN name of location
0023     property bool addAutomatically: false //true if user wants add location automatically without manually editing the fields
0024 
0025     signal locationFetched(var _lat, var _lng) //emitted when location is fetched in auto mode
0026     signal locNameFetched(var _city, var _region, var _country) //emitted when location nane is fetched or was failed to fetch in auto mode
0027 
0028     /*This function sets coordinates from GPS automatically, without asking user to fill information
0029     about location */
0030     function setAutomaticallyFromGPS() {
0031         addAutomatically = true
0032         positionSource.stop()
0033         positionSource.start()
0034         loadingText = fetchingCoordinatesLoading
0035         if(!positionSource.valid) {
0036             positionSource.stop()
0037             skyMapLite.notification.showNotification(xi18("Positioning is not available on your device"))
0038         }
0039     }
0040 
0041     property double lat
0042     property double lng
0043     property string city
0044     property string region
0045     property string country
0046     property int tz
0047 
0048     onLocationFetched: {
0049         lat = _lat
0050         lng = _lng
0051     }
0052 
0053     Timer {
0054         id: nameFetchTimeout
0055         interval: 20000;
0056         onTriggered: {
0057             locationLoading.close()
0058             var city = xi18n("Default city")
0059             var province = xi18n("Default province")
0060             var country = xi18n("Default country")
0061             if(addAutomatically) {
0062                 skyMapLite.notification.showNotification(xi18n("Could not fetch location name (check your Internet connection). Added with default name"))
0063                 if(!LocationDialogLite.addCity(city, province, country,
0064                                                lat, lng, tz,
0065                                                "--")) {
0066                     skyMapLite.notification.showNotification(xi18n("Failed to set location"))
0067                     return
0068                 }
0069 
0070                 if(LocationDialogLite.setLocation(city + ", " + province + ", " + country)) {
0071                     skyMapLite.notification.showNotification(xi18n("Successfully set your location"))
0072                 } else {
0073                     skyMapLite.notification.showNotification(xi18n("Could not set your location"))
0074                 }
0075             } else {
0076                 skyMapLite.notification.showNotification(xi18n("Could not fetch location name (check your Internet connection). Set default name"))
0077                 cityField.text = city
0078                 provinceField.text = province
0079                 countryField.text = country
0080                 comboBoxTZ.currentIndex = comboBoxTZ.find(tz)
0081             }
0082             fetchingName = false
0083             addAutomatically = false
0084         }
0085     }
0086 
0087     onLocNameFetched: {
0088         nameFetchTimeout.running = false
0089         city = _city
0090         region = _region
0091         country = _country
0092 
0093         if(!LocationDialogLite.addCity(city, region, country,
0094                                        lat, lng, tz,
0095                                        "--")) {
0096             skyMapLite.notification.showNotification(xi18n("Failed to set location"))
0097         }
0098 
0099         if(LocationDialogLite.setLocation(city + ", " + region + ", " + country)) {
0100             skyMapLite.notification.showNotification(xi18n("Successfully set your location"))
0101         } else {
0102             skyMapLite.notification.showNotification(xi18n("Could not set your location"))
0103         }
0104 
0105         addAutomatically = false
0106     }
0107 
0108     function openAdd() {
0109         editMode = false
0110         isReadOnly = false
0111         stackView.push(this)
0112         fieldsChanged = false
0113     }
0114 
0115     function openEdit(fullName, readOnly) {
0116         geoName = fullName
0117         isReadOnly = readOnly
0118 
0119         if(!readOnly) {
0120             editMode = true
0121         }
0122 
0123         cityField.text = LocationDialogLite.getCity(fullName)
0124         provinceField.text = LocationDialogLite.getProvince(fullName)
0125         countryField.text =  LocationDialogLite.getCountry(fullName)
0126 
0127         latField.text = LocationDialogLite.getLatitude(fullName)
0128         longField.text = LocationDialogLite.getLongitude(fullName)
0129 
0130         comboBoxTZ.currentIndex = LocationDialogLite.getTZ(fullName)
0131         comboBoxDST.currentIndex = LocationDialogLite.getDST(fullName)
0132         stackView.push(this)
0133         fieldsChanged = false
0134     }
0135 
0136     PositionSource {
0137         id: positionSource
0138 
0139         property bool error: false
0140 
0141         onSourceErrorChanged: {
0142             if (sourceError == PositionSource.NoError)
0143                 return
0144 
0145             var errorDesc = ""
0146 
0147             if (sourceError == 2 || sourceError == 1) {
0148                 errorDesc = xi18n("No location service (GPS, cellular service, etc.) is available.\nPlease, switch on the location service, and retry")
0149             } else if (sourceError == 4) {
0150                 errorDesc = xi18n("Unknown error occurred. Please contact the application developer.")
0151             }
0152 
0153             skyMapLite.notification.showNotification(errorDesc)
0154             positionSource.stop()
0155             error = true
0156             locationLoading.close()
0157         }
0158 
0159         onUpdateTimeout: {
0160             skyMapLite.notification.showNotification(xi18n("Timeout occurred. Try again."))
0161             locationLoading.close()
0162         }
0163 
0164         onActiveChanged: {
0165             if(positionSource.active && !error) {
0166                 locationLoading.open()
0167             } else if (!fetchingName) {
0168                 locationLoading.close()
0169                 error = false
0170             }
0171         }
0172 
0173         onPositionChanged: {
0174             if(isLoaded) {
0175                 skyMapLite.notification.showNotification(xi18n("Found your longitude and altitude"))
0176                 var lat = positionSource.position.coordinate.latitude
0177                 var lng = positionSource.position.coordinate.longitude
0178                 latField.text = lat
0179                 longField.text = lng
0180                 if(addAutomatically) {
0181                     locationFetched(lat, lng)
0182                 }
0183 
0184                 tz = (new Date().getTimezoneOffset()/60)*-1
0185                 loadingText = xi18n("Please, wait while we are retrieving location name")
0186                 fetchingName = true // must be set to true before we are stopping positioning service
0187                 positionSource.stop()
0188                 LocationDialogLite.getNameFromCoordinates(lat, lng)
0189                 nameFetchTimeout.running = true
0190                 setTZComboBox(new Date().getTimezoneOffset())
0191             }
0192         }
0193         preferredPositioningMethods: PositionSource.AllPositioningMethods
0194     }
0195 
0196     function setTZComboBox(TZMinutes) {
0197         var TZ = (TZMinutes/60)*-1
0198         comboBoxTZ.currentIndex = comboBoxTZ.find(TZ)
0199     }
0200 
0201     Connections {
0202         target: LocationDialogLite
0203         onNewNameFromCoordinates: {
0204             if(addAutomatically) {
0205                 locNameFetched(city, region, country)
0206             }
0207             cityField.text = city
0208             provinceField.text = region
0209             countryField.text = country
0210             fetchingName = false
0211             locationLoading.close()
0212             addAutomatically = false
0213         }
0214     }
0215 
0216     //close the popup and clears all text fields
0217     onVisibleChanged: {
0218         if(!visible) {
0219             cityField.clear()
0220             provinceField.clear()
0221             countryField.clear()
0222             latField.clear()
0223             longField.clear()
0224         }
0225     }
0226 
0227     ColumnLayout {
0228         anchors {
0229             left: parent.left
0230             right: parent.right
0231         }
0232 
0233         GridLayout {
0234             anchors {
0235                 left: parent.left
0236                 right: parent.right
0237             }
0238 
0239             flow: window.isPortrait ? GridLayout.TopToBottom : GridLayout.LeftToRight
0240 
0241             ColumnLayout {
0242                 anchors.top: parent.top
0243                 Layout.maximumWidth: window.isPortrait ? parent.width : parent.width/2
0244 
0245                 RowLayout {
0246                     KSLabel {
0247                         text: xi18n("City: ")
0248                     }
0249 
0250                     KSTextField {
0251                         id: cityField
0252                         Layout.fillWidth: true
0253                         onTextChanged: fieldsChanged = true
0254                         readOnly: isReadOnly
0255                     }
0256                 }
0257 
0258                 RowLayout {
0259                     KSLabel {
0260                         text: xi18n("Province: ")
0261                     }
0262 
0263                     KSTextField {
0264                         id: provinceField
0265                         Layout.fillWidth: true
0266                         onTextChanged: fieldsChanged = true
0267                         readOnly: isReadOnly
0268                     }
0269                 }
0270 
0271                 RowLayout {
0272                     KSLabel {
0273                         text: xi18n("Country: ")
0274                     }
0275 
0276                     KSTextField {
0277                         id: countryField
0278                         Layout.fillWidth: true
0279                         onTextChanged: fieldsChanged = true
0280                         readOnly: isReadOnly
0281                     }
0282                 }
0283             }
0284 
0285             Item {
0286                 height: window.isPortrait ? 15 : 0
0287             }
0288 
0289             ColumnLayout {
0290                 Layout.maximumWidth: window.isPortrait ? parent.width : parent.width/2
0291 
0292                 RowLayout {
0293                     KSLabel {
0294                         text: xi18n("Latitude: ")
0295                     }
0296 
0297                     KSTextField {
0298                         id: latField
0299                         Layout.fillWidth: true
0300                         readOnly: isReadOnly
0301                     }
0302                 }
0303 
0304                 RowLayout {
0305 
0306                     KSLabel {
0307                         text: xi18n("Longitude: ")
0308                     }
0309 
0310                     KSTextField {
0311                         id: longField
0312                         Layout.fillWidth: true
0313                         readOnly: isReadOnly
0314                     }
0315                 }
0316 
0317                 Flow {
0318                     Layout.fillWidth: true
0319                     spacing: 10
0320 
0321                     RowLayout {
0322                         KSLabel {
0323                             text: xi18n("UT offset: ")
0324                         }
0325 
0326                         ComboBox {
0327                             id: comboBoxTZ
0328                             model: LocationDialogLite.TZList
0329                         }
0330                     }
0331 
0332                     RowLayout {
0333                         KSLabel {
0334                             text: xi18n("DST rule: ")
0335                         }
0336 
0337                         ComboBox {
0338                             id: comboBoxDST
0339                             model: LocationDialogLite.DSTRules
0340                         }
0341                     }
0342                 }
0343             }
0344         }
0345 
0346         Flow {
0347             Layout.fillWidth: true
0348             spacing: 10
0349 
0350             Button {
0351                 visible: !isReadOnly
0352                 text: xi18n("Set from GPS")
0353                 enabled: isAvailable
0354                 onClicked: {
0355                     positionSource.stop()
0356                     positionSource.start()
0357                     loadingText = fetchingCoordinatesLoading
0358                     if(!positionSource.valid) {
0359                         positionSource.stop()
0360                         skyMapLite.notification.showNotification(xi18("Positioning is not available on your device"))
0361                     }
0362                 }
0363 
0364                 Connections {
0365                     target: locationLoading
0366                     onClosed: {
0367                         positionSource.stop()
0368                     }
0369                 }
0370             }
0371 
0372             Button {
0373                 //enabled:
0374                 visible: !isReadOnly
0375                 text: editMode ? xi18n("Save") : xi18n("Add")
0376                 onClicked: {
0377                     if(cityField.text == "") {
0378                         skyMapLite.notification.showNotification(xi18n("Please, fill in the city"))
0379                         return
0380                     } else if(countryField.text == "") {
0381                         skyMapLite.notification.showNotification(xi18n("Please, fill in the country"))
0382                         return
0383                     } else if(latField.text == "") {
0384                         skyMapLite.notification.showNotification(xi18n("Please, fill in the latitude"))
0385                         return
0386                     } else if(longField.text == "") {
0387                         skyMapLite.notification.showNotification(xi18n("Please, fill in the longitude"))
0388                         return
0389                     }
0390 
0391                     if(!LocationDialogLite.checkLongLat(longField.text, latField.text)) {
0392                         skyMapLite.notification.showNotification(xi18n("Either the longitude or the latitude values are not valid"))
0393                         return
0394                     }
0395 
0396                     if(fieldsChanged) {
0397                         if(LocationDialogLite.isDuplicate(cityField.text, provinceField.text, countryField.text)) {
0398                             skyMapLite.notification.showNotification(xi18n("This location already exists. Change either the city, the province or the country"))
0399                             return
0400                         }
0401                     }
0402 
0403                     //Fullname of new location
0404                     var fullName = cityField.text + ", "
0405                     if(provinceField.text != "") {
0406                         fullName += provinceField.text + ", "
0407                     }
0408                     fullName += countryField.text
0409 
0410                     if(!editMode) {
0411                         if(!LocationDialogLite.addCity(cityField.text, provinceField.text, countryField.text,
0412                                                        latField.text, longField.text, comboBoxTZ.currentText,
0413                                                        comboBoxDST.currentText)) {
0414                             skyMapLite.notification.showNotification(xi18n("Failed to add location"))
0415                             return
0416                         } else {
0417                             skyMapLite.notification.showNotification(xi18n("Added new location - %1", fullName))
0418                         }
0419                     } else {
0420                         if(!LocationDialogLite.editCity(geoName, cityField.text, provinceField.text, countryField.text,
0421                                                         latField.text, longField.text, comboBoxTZ.currentText,
0422                                                         comboBoxDST.currentText)) {
0423                             skyMapLite.notification.showNotification(xi18n("Failed to edit city"))
0424                             return
0425                         }
0426                     }
0427 
0428                     locationDialog.filterCities()
0429                     if(!editMode) {
0430                         //If we are adding location then open menu with newly added location
0431                         locationsGeoMenu.openMenu(fullName)
0432                     }
0433 
0434                     stackView.pop()
0435                 }
0436             }
0437 
0438             Button {
0439                 text: xi18n("Cancel")
0440                 onClicked: {
0441                     stackView.pop()
0442                 }
0443             }
0444         }
0445     }
0446 }