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

KDE's Doxygen guidelines are available online.