Kstars

locationdialog.cpp
1/*
2 SPDX-FileCopyrightText: 2001 Jason Harris <jharris@30doradus.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "locationdialog.h"
8
9#include "kspaths.h"
10#include "kstarsdata.h"
11#include "Options.h"
12#include "ksnotification.h"
13#include "kstars_debug.h"
14#include "ksutils.h"
15
16#include <QSqlQuery>
17
18#ifdef HAVE_GEOCLUE2
19#include <QGeoPositionInfoSource>
20#endif
21#include <QJsonArray>
22#include <QJsonDocument>
23#include <QJsonObject>
24#include <QJsonValue>
25#include <QNetworkAccessManager>
26#include <QNetworkConfigurationManager>
27#include <QNetworkReply>
28#include <QNetworkSession>
29#include <QQmlContext>
30#include <QUrlQuery>
31#include <QPlainTextEdit>
32
33
34LocationDialogUI::LocationDialogUI(QWidget *parent) : QFrame(parent)
35{
36 setupUi(this);
37}
38
40{
41#ifdef Q_OS_OSX
43#endif
44 KStarsData *data = KStarsData::Instance();
45
46 SelectedCity = nullptr;
47 ld = new LocationDialogUI(this);
48
49 QVBoxLayout *mainLayout = new QVBoxLayout;
50 mainLayout->addWidget(ld);
51 setLayout(mainLayout);
52
53 ld->MapView->setLocationDialog(this);
54
55 setWindowTitle(i18nc("@title:window", "Set Geographic Location"));
56
58 mainLayout->addWidget(buttonBox);
59 connect(buttonBox, SIGNAL(accepted()), this, SLOT(slotOk()));
60 connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
61
62 for (int i = 0; i < 25; ++i)
63 ld->TZBox->addItem(QLocale().toString(static_cast<double>(i - 12)));
64
65 //Populate DSTRuleBox
66 foreach (const QString &key, data->getRulebook().keys())
67 {
68 if (!key.isEmpty())
69 ld->DSTRuleBox->addItem(key);
70 }
71
72 connect(ld->CityFilter, SIGNAL(textChanged(QString)), this, SLOT(enqueueFilterCity()));
73 connect(ld->ProvinceFilter, SIGNAL(textChanged(QString)), this, SLOT(enqueueFilterCity()));
74 connect(ld->CountryFilter, SIGNAL(textChanged(QString)), this, SLOT(enqueueFilterCity()));
75 connect(ld->NewCityName, SIGNAL(textChanged(QString)), this, SLOT(nameChanged()));
76 connect(ld->NewProvinceName, SIGNAL(textChanged(QString)), this, SLOT(nameChanged()));
77 connect(ld->NewCountryName, SIGNAL(textChanged(QString)), this, SLOT(nameChanged()));
78 connect(ld->NewLong, SIGNAL(textChanged(QString)), this, SLOT(dataChanged()));
79 connect(ld->NewLat, SIGNAL(textChanged(QString)), this, SLOT(dataChanged()));
80 connect(ld->NewElev, SIGNAL(valueChanged(double)), this, SLOT(dataChanged()));
81
82 connect(ld->TZBox, SIGNAL(activated(int)), this, SLOT(dataChanged()));
83 connect(ld->DSTRuleBox, SIGNAL(activated(int)), this, SLOT(dataChanged()));
84 connect(ld->GeoBox, SIGNAL(itemSelectionChanged()), this, SLOT(changeCity()));
85 connect(ld->AddCityButton, SIGNAL(clicked()), this, SLOT(addCity()));
86 connect(ld->ClearFieldsButton, SIGNAL(clicked()), this, SLOT(clearFields()));
87 connect(ld->RemoveButton, SIGNAL(clicked()), this, SLOT(removeCity()));
88 connect(ld->UpdateButton, SIGNAL(clicked()), this, SLOT(updateCity()));
89
90 // FIXME Disable this until Qt5 works with Geoclue2
91#ifdef HAVE_GEOCLUE_2
93 source->setPreferredPositioningMethods(QGeoPositionInfoSource::SatellitePositioningMethods);
94 qDebug() << Q_FUNC_INFO << "Last known position" << source->lastKnownPosition().coordinate();
95
96 connect(source, SIGNAL(positionUpdated(QGeoPositionInfo)), this, SLOT(positionUpdated(QGeoPositionInfo)));
99
100 connect(ld->GetLocationButton, SIGNAL(clicked()), this, SLOT(requestUpdate()));
101#endif
102
103 ld->DSTLabel->setText("<a href=\"showrules\">" + i18n("DST rule:") + "</a>");
104 connect(ld->DSTLabel, SIGNAL(linkActivated(QString)), this, SLOT(showTZRules()));
105
106 dataModified = false;
107 nameModified = false;
108 ld->AddCityButton->setEnabled(false);
109
110 ld->errorLabel->setText(QString());
111
112 // FIXME Disable this until Qt5 works with Geoclue2
113#ifdef HAVE_GEOCLUE_2
114 nam = new QNetworkAccessManager(this);
115 connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(processLocationNameData(QNetworkReply*)));
116#endif
117
118 initCityList();
119 resize(640, 480);
120}
121
123{
124 KStarsData *data = KStarsData::Instance();
125 foreach (GeoLocation *loc, data->getGeoList())
126 {
127 ld->GeoBox->addItem(loc->fullName());
128 filteredCityList.append(loc);
129
130 //If TZ is not an even integer value, add it to listbox
131 if (loc->TZ0() - int(loc->TZ0()) && ld->TZBox->findText(QLocale().toString(loc->TZ0())) != -1)
132 {
133 for (int i = 0; i < ld->TZBox->count(); ++i)
134 {
135 if (ld->TZBox->itemText(i).toDouble() > loc->TZ0())
136 {
137 ld->TZBox->addItem(QLocale().toString(loc->TZ0()), i - 1);
138 break;
139 }
140 }
141 }
142 }
143
144 //Sort the list of Cities alphabetically...note that filteredCityList may now have a different ordering!
145 ld->GeoBox->sortItems();
146
147 ld->CountLabel->setText(
148 i18np("One city matches search criteria", "%1 cities match search criteria", ld->GeoBox->count()));
149
150 // attempt to highlight the current kstars location in the GeoBox
151 ld->GeoBox->setCurrentItem(nullptr);
152 for (int i = 0; i < ld->GeoBox->count(); i++)
153 {
154 if (ld->GeoBox->item(i)->text() == data->geo()->fullName())
155 {
156 ld->GeoBox->setCurrentRow(i);
157 break;
158 }
159 }
160}
161
163{
164 if (timer)
165 timer->stop();
166 else
167 {
168 timer = new QTimer(this);
169 timer->setSingleShot(true);
170 connect(timer, SIGNAL(timeout()), this, SLOT(filterCity()));
171 }
172 timer->start(500);
173}
174
176{
177 KStarsData *data = KStarsData::Instance();
178 ld->GeoBox->clear();
179 //Do NOT delete members of filteredCityList!
180 while (!filteredCityList.isEmpty())
181 filteredCityList.takeFirst();
182
183 nameModified = false;
184 dataModified = false;
185 ld->AddCityButton->setEnabled(false);
186 ld->UpdateButton->setEnabled(false);
187
188 foreach (GeoLocation *loc, data->getGeoList())
189 {
190 QString sc(loc->translatedName());
191 QString ss(loc->translatedCountry());
192 QString sp = "";
193 if (!loc->province().isEmpty())
194 sp = loc->translatedProvince();
195
196 if (sc.startsWith(ld->CityFilter->text(), Qt::CaseInsensitive) &&
197 sp.startsWith(ld->ProvinceFilter->text(), Qt::CaseInsensitive) &&
198 ss.startsWith(ld->CountryFilter->text(), Qt::CaseInsensitive))
199 {
200 ld->GeoBox->addItem(loc->fullName());
201 filteredCityList.append(loc);
202 }
203 }
204
205 ld->GeoBox->sortItems();
206
207 ld->CountLabel->setText(
208 i18np("One city matches search criteria", "%1 cities match search criteria", ld->GeoBox->count()));
209
210 if (ld->GeoBox->count() > 0) // set first item in list as selected
211 ld->GeoBox->setCurrentItem(ld->GeoBox->item(0));
212
213 ld->MapView->repaint();
214}
215
217{
218 KStarsData *data = KStarsData::Instance();
219
220 //when the selected city changes, set newCity, and redraw map
221 SelectedCity = nullptr;
222 if (ld->GeoBox->currentItem())
223 {
224 for (auto &loc : filteredCityList)
225 {
226 if (loc->fullName() == ld->GeoBox->currentItem()->text())
227 {
228 SelectedCity = loc;
229 break;
230 }
231 }
232 }
233
234 ld->MapView->repaint();
235
236 //Fill the fields at the bottom of the window with the selected city's data.
237 if (SelectedCity)
238 {
239 ld->NewCityName->setText(SelectedCity->translatedName());
240 if (SelectedCity->province().isEmpty())
241 ld->NewProvinceName->setText(QString());
242 else
243 ld->NewProvinceName->setText(SelectedCity->translatedProvince());
244
245 ld->NewCountryName->setText(SelectedCity->translatedCountry());
246 ld->NewLong->show(SelectedCity->lng());
247 ld->NewLat->show(SelectedCity->lat());
248 ld->TZBox->setEditText(QLocale().toString(SelectedCity->TZ0()));
249 ld->NewElev->setValue(SelectedCity->elevation());
250
251 //Pick the City's rule from the rulebook
252 for (int i = 0; i < ld->DSTRuleBox->count(); ++i)
253 {
254 TimeZoneRule tzr = data->getRulebook().value(ld->DSTRuleBox->itemText(i));
255 if (tzr.equals(SelectedCity->tzrule()))
256 {
257 ld->DSTRuleBox->setCurrentIndex(i);
258 break;
259 }
260 }
261
262 ld->RemoveButton->setEnabled(SelectedCity->isReadOnly() == false);
263 }
264
265 nameModified = false;
266 dataModified = false;
267 ld->AddCityButton->setEnabled(false);
268 ld->UpdateButton->setEnabled(false);
269}
270
272{
273 return updateCity(CITY_ADD);
274}
275
277{
278 if (SelectedCity == nullptr)
279 return false;
280
281 return updateCity(CITY_UPDATE);
282}
283
285{
286 if (SelectedCity == nullptr)
287 return false;
288
289 return updateCity(CITY_REMOVE);
290}
291
292bool LocationDialog::updateCity(CityOperation operation)
293{
294 if (operation == CITY_REMOVE)
295 {
296 QString message = i18n("Are you sure you want to remove %1?", selectedCityName());
297 if (KMessageBox::questionYesNo(nullptr, message, i18n("Remove City?")) == KMessageBox::No)
298 return false; //user answered No.
299 }
300 else if (!nameModified && !dataModified)
301 {
302 QString message = i18n("This city already exists in the database.");
303 KSNotification::sorry(message, i18n("Error: Duplicate Entry"));
304 return false;
305 }
306
307 bool latOk(false), lngOk(false), tzOk(false);
308 dms lat = ld->NewLat->createDms(&latOk);
309 dms lng = ld->NewLong->createDms(&lngOk);
310 QString TimeZoneString = ld->TZBox->lineEdit()->text();
311 TimeZoneString.replace(QLocale().decimalPoint(), ".");
312 double TZ = TimeZoneString.toDouble(&tzOk);
313 double height = ld->NewElev->value();
314
315 if (ld->NewCityName->text().isEmpty() || ld->NewCountryName->text().isEmpty())
316 {
317 QString message = i18n("All fields (except province) must be filled to add this location.");
318 KSNotification::sorry(message, i18n("Fields are Empty"));
319 return false;
320 }
321 else if (!latOk || !lngOk)
322 {
323 QString message = i18n("Could not parse the Latitude/Longitude.");
324 KSNotification::sorry(message, i18n("Bad Coordinates"));
325 return false;
326 }
327 else if (!tzOk)
328 {
329 QString message = i18n("UTC Offset must be selected.");
330 KSNotification::sorry(message, i18n("UTC Offset"));
331 return false;
332 }
333
334 // If name is still the same then it's an update operation
335 if (operation == CITY_ADD && !nameModified)
336 operation = CITY_UPDATE;
337
338 /*if ( !nameModified )
339 {
340 QString message = i18n( "Really override original data for this city?" );
341 if ( KMessageBox::questionYesNo( 0, message, i18n( "Override Existing Data?" ), KGuiItem(i18n("Override Data")), KGuiItem(i18n("Do Not Override"))) == KMessageBox::No )
342 return false; //user answered No.
343 }*/
344
346 QString dbfile = QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).filePath("mycitydb.sqlite");
347
348 // If it doesn't exist, create it
349 if (QFile::exists(dbfile) == false)
350 {
351 mycitydb.setDatabaseName(dbfile);
352 mycitydb.open();
354 QString query("CREATE TABLE city ( "
355 "id INTEGER DEFAULT NULL PRIMARY KEY AUTOINCREMENT, "
356 "Name TEXT DEFAULT NULL, "
357 "Province TEXT DEFAULT NULL, "
358 "Country TEXT DEFAULT NULL, "
359 "Latitude TEXT DEFAULT NULL, "
360 "Longitude TEXT DEFAULT NULL, "
361 "TZ REAL DEFAULT NULL, "
362 "TZRule TEXT DEFAULT NULL,"
363 "Elevation REAL NOT NULL DEFAULT -10 )");
364
365 if (create_query.exec(query) == false)
366 {
367 qCWarning(KSTARS) << create_query.lastError();
368 return false;
369 }
370 }
371 else if (mycitydb.open() == false)
372 {
373 qCWarning(KSTARS) << mycitydb.lastError();
374 return false;
375 }
376
377 //Strip off white space
378 QString name = ld->NewCityName->text().trimmed();
379 QString province = ld->NewProvinceName->text().trimmed();
380 QString country = ld->NewCountryName->text().trimmed();
381 QString TZrule = ld->DSTRuleBox->currentText();
382 double Elevation = ld->NewElev->value();
383 GeoLocation *g = nullptr;
384
385 switch (operation)
386 {
387 case CITY_ADD:
388 {
390 add_query.prepare("INSERT INTO city(Name, Province, Country, Latitude, Longitude, TZ, TZRule, Elevation) "
391 "VALUES(:Name, :Province, :Country, :Latitude, :Longitude, :TZ, :TZRule, :Elevation)");
392 add_query.bindValue(":Name", name);
393 add_query.bindValue(":Province", province);
394 add_query.bindValue(":Country", country);
395 add_query.bindValue(":Latitude", lat.toDMSString());
396 add_query.bindValue(":Longitude", lng.toDMSString());
397 add_query.bindValue(":TZ", TZ);
398 add_query.bindValue(":TZRule", TZrule);
399 add_query.bindValue(":Elevation", Elevation);
400 if (add_query.exec() == false)
401 {
402 qCWarning(KSTARS) << add_query.lastError();
403 return false;
404 }
405
406 //Add city to geoList...don't need to insert it alphabetically, since we always sort GeoList
407 g = new GeoLocation(lng, lat, name, province, country, TZ, &KStarsData::Instance()->Rulebook[TZrule], Elevation);
408 KStarsData::Instance()->getGeoList().append(g);
409 }
410 break;
411
412 case CITY_UPDATE:
413 {
414 g = SelectedCity;
415
417 update_query.prepare("UPDATE city SET Name = :newName, Province = :newProvince, Country = :newCountry, "
418 "Latitude = :Latitude, Longitude = :Longitude, TZ = :TZ, TZRule = :TZRule, Elevation = :Elevation WHERE "
419 "Name = :Name AND Province = :Province AND Country = :Country");
420 update_query.bindValue(":newName", name);
421 update_query.bindValue(":newProvince", province);
422 update_query.bindValue(":newCountry", country);
423 update_query.bindValue(":Name", SelectedCity->name());
424 update_query.bindValue(":Province", SelectedCity->province());
425 update_query.bindValue(":Country", SelectedCity->country());
426 update_query.bindValue(":Latitude", lat.toDMSString());
427 update_query.bindValue(":Longitude", lng.toDMSString());
428 update_query.bindValue(":TZ", TZ);
429 update_query.bindValue(":TZRule", TZrule);
430 update_query.bindValue(":Elevation", Elevation);
431 if (update_query.exec() == false)
432 {
433 qCWarning(KSTARS) << update_query.lastError();
434 return false;
435 }
436
437 g->setName(name);
438 g->setProvince(province);
439 g->setCountry(country);
440 g->setLat(lat);
441 g->setLong(lng);
442 g->setTZ0(TZ);
443 g->setTZRule(&KStarsData::Instance()->Rulebook[TZrule]);
445
446 }
447 break;
448
449 case CITY_REMOVE:
450 {
451 g = SelectedCity;
453 delete_query.prepare("DELETE FROM city WHERE Name = :Name AND Province = :Province AND Country = :Country");
454 delete_query.bindValue(":Name", name);
455 delete_query.bindValue(":Province", province);
456 delete_query.bindValue(":Country", country);
457 if (delete_query.exec() == false)
458 {
459 qCWarning(KSTARS) << delete_query.lastError();
460 return false;
461 }
462
463 filteredCityList.removeOne(g);
464 KStarsData::Instance()->getGeoList().removeOne(g);
465 delete g;
466 g = nullptr;
467 }
468 break;
469 }
470
471 //(possibly) insert new city into GeoBox by running filterCity()
472 filterCity();
473
474 //Attempt to highlight new city in list
475 ld->GeoBox->setCurrentItem(nullptr);
476 if (g && ld->GeoBox->count())
477 {
478 for (int i = 0; i < ld->GeoBox->count(); i++)
479 {
480 if (ld->GeoBox->item(i)->text() == g->fullName())
481 {
482 ld->GeoBox->setCurrentRow(i);
483 break;
484 }
485 }
486 }
487
488 mycitydb.commit();
489 mycitydb.close();
490
491 return true;
492}
493
494void LocationDialog::findCitiesNear(int lng, int lat)
495{
496 KStarsData *data = KStarsData::Instance();
497 //find all cities within 3 degrees of (lng, lat); list them in GeoBox
498 ld->GeoBox->clear();
499 //Remember, do NOT delete members of filteredCityList
500 while (!filteredCityList.isEmpty())
501 filteredCityList.takeFirst();
502
503 foreach (GeoLocation *loc, data->getGeoList())
504 {
505 if ((abs(lng - int(loc->lng()->Degrees())) < 3) && (abs(lat - int(loc->lat()->Degrees())) < 3))
506 {
507 ld->GeoBox->addItem(loc->fullName());
508 filteredCityList.append(loc);
509 }
510 }
511
512 ld->GeoBox->sortItems();
513 ld->CountLabel->setText(
514 i18np("One city matches search criteria", "%1 cities match search criteria", ld->GeoBox->count()));
515
516 if (ld->GeoBox->count() > 0) // set first item in list as selected
517 ld->GeoBox->setCurrentItem(ld->GeoBox->item(0));
518
519 repaint();
520}
521
522bool LocationDialog::checkLongLat()
523{
524 if (ld->NewLong->text().isEmpty() || ld->NewLat->text().isEmpty())
525 return false;
526
527 bool ok;
528 double lng = ld->NewLong->createDms(&ok).Degrees();
529 if (!ok)
530 return false;
531 double lat = ld->NewLat->createDms(&ok).Degrees();
532 if (!ok)
533 return false;
534
535 if (fabs(lng) > 180 || fabs(lat) > 90)
536 return false;
537
538 return true;
539}
540
541void LocationDialog::clearFields()
542{
543 ld->CityFilter->clear();
544 ld->ProvinceFilter->clear();
545 ld->CountryFilter->clear();
546 ld->NewCityName->clear();
547 ld->NewProvinceName->clear();
548 ld->NewCountryName->clear();
549 ld->NewLong->clearFields();
550 ld->NewLat->clearFields();
551 ld->NewElev->setValue(-10);
552 ld->TZBox->setCurrentIndex(-1);
553 // JM 2017-09-16: No, let's not assume it is 0. User have to explicitly set TZ so avoid mistakes.
554 //ld->TZBox->lineEdit()->setText(QLocale().toString(0.0));
555 ld->DSTRuleBox->setCurrentIndex(0);
556 nameModified = true;
557 dataModified = false;
558
559 ld->AddCityButton->setEnabled(false);
560 ld->UpdateButton->setEnabled(false);
561 ld->NewCityName->setFocus();
562}
563
564void LocationDialog::showTZRules()
565{
566 QFile file;
567
568 if (KSUtils::openDataFile(file, "TZrules.dat") == false)
569 return;
570
571 QTextStream stream(&file);
572
573 QString message = i18n("Daylight Saving Time Rules");
574
575 QPointer<QDialog> tzd = new QDialog(this);
576 tzd->setWindowTitle(message);
577
579 textEdit->setReadOnly(true);
580 while (stream.atEnd() == false)
581 {
582 QString line = stream.readLine();
583 if (line.startsWith('#'))
584 textEdit->appendPlainText(line);
585 }
586 textEdit->moveCursor(QTextCursor::Start);
587 textEdit->ensureCursorVisible();
588
589 QVBoxLayout *mainLayout = new QVBoxLayout;
590 mainLayout->addWidget(textEdit);
591
593 mainLayout->addWidget(buttonBox);
594 connect(buttonBox, SIGNAL(rejected()), tzd, SLOT(reject()));
595
596 tzd->setLayout(mainLayout);
597
598 tzd->exec();
599
600 delete tzd;
601}
602
603void LocationDialog::nameChanged()
604{
605 nameModified = true;
606 dataChanged();
607}
608
609//do not enable Add button until all data are present and valid.
610void LocationDialog::dataChanged()
611{
612 dataModified = true;
613 ld->AddCityButton->setEnabled(nameModified && !ld->NewCityName->text().isEmpty() &&
614 !ld->NewCountryName->text().isEmpty() && checkLongLat() && ld->TZBox->currentIndex() != -1);
615 if (SelectedCity)
616 ld->UpdateButton->setEnabled(SelectedCity->isReadOnly() == false && !ld->NewCityName->text().isEmpty() &&
617 !ld->NewCountryName->text().isEmpty() && checkLongLat() && ld->TZBox->currentIndex() != -1);
618
619 if (ld->AddCityButton->isEnabled() == false && ld->UpdateButton->isEnabled() == false)
620 {
621 if (ld->NewCityName->text().isEmpty())
622 {
623 ld->errorLabel->setText(i18n("Cannot add new location -- city name blank"));
624 }
625 else if (ld->NewCountryName->text().isEmpty())
626 {
627 ld->errorLabel->setText(i18n("Cannot add new location -- country name blank"));
628 }
629 else if (!checkLongLat())
630 {
631 ld->errorLabel->setText(i18n("Cannot add new location -- invalid latitude / longitude"));
632 }
633 else if (ld->TZBox->currentIndex() == -1)
634 {
635 ld->errorLabel->setText(i18n("Cannot add new location -- missing UTC Offset"));
636 }
637 else if (SelectedCity && SelectedCity->isReadOnly())
638 {
639 ld->errorLabel->setText(i18n("City is Read Only. Change name to add new city."));
640 }
641 }
642 else
643 {
644 ld->errorLabel->setText(QString());
645 }
646}
647
648void LocationDialog::slotOk()
649{
650 if (ld->AddCityButton->isEnabled())
651 {
652 if (addCity())
653 accept();
654 }
655 else
656 accept();
657}
658
659// FIXME Disable this until Qt5 works with Geoclue2
660#ifdef HAVE_GEOCLUE_2
661void LocationDialog::getNameFromCoordinates(double latitude, double longitude)
662{
663 QString lat = QString::number(latitude);
664 QString lon = QString::number(longitude);
665 QString latlng(lat + ", " + lon);
666
667 QUrl url("http://maps.googleapis.com/maps/api/geocode/json");
669 query.addQueryItem("latlng", latlng);
670 url.setQuery(query);
671 qDebug() << Q_FUNC_INFO << "submitting request";
672
673 nam->get(QNetworkRequest(url));
674 connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(processLocationNameData(QNetworkReply*)));
675}
676
677void LocationDialog::processLocationNameData(QNetworkReply *networkReply)
678{
679 if (!networkReply)
680 return;
681
682 if (!networkReply->error())
683 {
685
686 if (document.isObject())
687 {
688 QJsonObject obj = document.object();
689 QJsonValue val;
690
691 if (obj.contains(QStringLiteral("results")))
692 {
693 val = obj["results"];
694
695 QString city =
696 val.toArray()[0].toObject()["address_components"].toArray()[2].toObject()["long_name"].toString();
697 QString region =
698 val.toArray()[0].toObject()["address_components"].toArray()[3].toObject()["long_name"].toString();
700 val.toArray()[0].toObject()["address_components"].toArray()[4].toObject()["long_name"].toString();
701
702 //emit newNameFromCoordinates(city, region, country);
703 }
704 else
705 {
706 }
707 }
708 }
709 networkReply->deleteLater();
710}
711
712void LocationDialog::requestUpdate()
713{
714 source->requestUpdate(15000);
715}
716
717void LocationDialog::positionUpdated(const QGeoPositionInfo &info)
718{
719 qDebug() << Q_FUNC_INFO << "Position updated:" << info;
720}
721
722void LocationDialog::positionUpdateError(QGeoPositionInfoSource::Error error)
723{
724 qDebug() << Q_FUNC_INFO << "Position update error: " << error;
725}
726
727void LocationDialog::positionUpdateTimeout()
728{
729 qDebug() << Q_FUNC_INFO << "Timed out!";
730 qDebug() << Q_FUNC_INFO << source->error();
731}
732#endif
Contains all relevant information for specifying a location on Earth: City Name, State/Province name,...
Definition geolocation.h:28
void setName(const QString &n)
Set City name according to argument.
QString country() const
QString fullName() const
const CachingDms * lat() const
Definition geolocation.h:70
const CachingDms * lng() const
Definition geolocation.h:64
QString translatedCountry() const
double elevation() const
Definition geolocation.h:76
void setLong(const dms &l)
Set longitude according to dms argument.
void setLat(const dms &l)
Set latitude according to dms argument.
double TZ0() const
void setTZ0(double value)
Set Time zone.
void setElevation(double hg)
Set elevation above sea level.
void setTZRule(TimeZoneRule *value)
Set Time zone rule.
QString province() const
QString translatedName() const
void setProvince(const QString &n)
Set Province name according to argument.
QString translatedProvince() const
TimeZoneRule * tzrule()
void setCountry(const QString &n)
Set Country name according to argument.
QString name() const
KStarsData is the backbone of KStars.
Definition kstarsdata.h:72
QList< GeoLocation * > & getGeoList()
Definition kstarsdata.h:236
GeoLocation * geo()
Definition kstarsdata.h:230
const QMap< QString, TimeZoneRule > & getRulebook() const
Return map for daylight saving rules.
Definition kstarsdata.h:262
void enqueueFilterCity()
Filter by city / province / country only after a few milliseconds.
bool updateCity()
When the "Update City" QPushButton is clicked, update the city information in the user's custom city ...
QString selectedCityName() const
void filterCity()
When text is entered in the City/Province/Country Filter KLineEdits, the List of cities is trimmed to...
void initCityList(void)
Initialize list of cities.
LocationDialog(QWidget *parent)
Constructor.
void findCitiesNear(int longitude, int latitude)
Show only cities within 3 degrees of point specified by arguments.
bool addCity()
When the "Add new city" QPushButton is clicked, add the manually-entered city information to the user...
bool removeCity()
When the "Remove City" QPushButton is clicked, remove the city information from the user's custom cit...
void changeCity()
When the selected city in the QListBox changes, repaint the MapCanvas so that the crosshairs icon app...
This class provides the information needed to determine whether Daylight Savings Time (DST; a....
An angle, stored as degrees, but expressible in many ways.
Definition dms.h:38
const QString toDMSString(const bool forceSign=false, const bool machineReadable=false, const bool highPrecision=false) const
Definition dms.cpp:287
QString i18np(const char *singular, const char *plural, const TYPE &arg...)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
std::optional< QSqlQuery > query(const QString &queryStatement)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
KI18NLOCALEDATA_EXPORT KCountry country(const char *ianaId)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
QDialog(QWidget *parent, Qt::WindowFlags f)
virtual void accept()
void accepted()
void finished(int result)
virtual void reject()
void rejected()
QString filePath(const QString &fileName) const const
bool exists() const const
QGeoPositionInfoSource * createDefaultSource(QObject *parent)
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
bool isObject() const const
QJsonObject object() const const
bool contains(QLatin1StringView key) const const
QJsonArray toArray() const const
void append(QList< T > &&value)
bool isEmpty() const const
bool removeOne(const AT &t)
value_type takeFirst()
QString toString(QDate date, FormatType format) const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QSqlDatabase database(const QString &connectionName, bool open)
bool isEmpty() const const
QString number(double n, char format, int precision)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
CaseInsensitive
void setEnabled(bool)
void repaint()
void setFocus()
void setLayout(QLayout *layout)
void show()
void resize(const QSize &)
void setWindowFlags(Qt::WindowFlags type)
void setWindowTitle(const QString &)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 17 2024 11:48:25 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.