diff --git a/data/mainRes.qrc b/data/mainRes.qrc index 36645d488c7af..f7c902cd71f61 100644 --- a/data/mainRes.qrc +++ b/data/mainRes.qrc @@ -2,6 +2,9 @@ icon.bmp + + timezone.tab + shaders/xyYToRGB.glsl shaders/preethamAtmosphere.vert diff --git a/data/timezone.tab b/data/timezone.tab new file mode 100644 index 0000000000000..5783041e2906e --- /dev/null +++ b/data/timezone.tab @@ -0,0 +1,79 @@ +# Missing and wrong time zones +# +# This file contains a table of missing and/or wrong time zones. +# Columns are separated by a single tab. Lines beginning with '#' are comments. +# All text uses UTF-8 encoding. The columns of the table are as follows: +# +# 1. DB name +# 2. Name as we display it in the program +# +# This file is automatically retrieved on demand. Do not edit! + +# Reported April 25, 2023. (#3200) +America/Yellowknife America/Edmonton +# Seen February 06, 2023. +America/Ciudad_Juarez America/Ojinaga +# Seen November 11, 2022. +America/Thunder_Bay America/Toronto +Europe/Uzhgorod Europe/Kyiv +# Seen on October 27, 2022. TZ Removed? +Europe/Zaporozhye Europe/Kyiv +# Seen on September 26, 2022. Officially renamed. +Europe/Kyiv Europe/Kiev +Europe/Kiev Europe/Kyiv +# Seen in an unrelated bug report, 2022-08-30 +Asia/Pyongyang UTC+09:00 +# reported in SF forum on 2017-03-27 +Europe/Minsk UTC+03:00 +Europe/Samara UTC+04:00 +America/Cancun UTC-05:00 +Asia/Kamchatka UTC+12:00 +# Missing on Qt5.7/Win10 as of 2017-03-18. +Europe/Astrakhan UTC+04:00 +Europe/Ulyanovsk UTC+04:00 +Europe/Kirov UTC+03:00 +Asia/Hebron Asia/Jerusalem +# or use UTC+2:00? (political issue...) +Asia/Gaza Asia/Jerusalem +Asia/Kolkata Asia/Calcutta +Asia/Kathmandu Asia/Katmandu +Asia/Tomsk Asia/Novosibirsk +Asia/Barnaul UTC+07:00 +Asia/Ho_Chi_Minh Asia/Saigon +Asia/Hovd UTC+07:00 +America/Argentina/Buenos_Aires America/Buenos_Aires +America/Argentina/Jujuy America/Jujuy +America/Argentina/Mendoza America/Mendoza +America/Argentina/Catamarca America/Catamarca +America/Argentina/Cordoba America/Cordoba +America/Indiana/Indianapolis America/Indianapolis +America/Kentucky/Louisville America/Louisville +# Small Canadian island. +America/Miquelon UTC-03:00 +Africa/Asmara Africa/Asmera +Atlantic/Faroe Atlantic/Faeroe +Pacific/Pohnpei Pacific/Ponape +Pacific/Norfolk UTC+11:00 +Pacific/Pitcairn UTC-08:00 +# Missing on Qt5.5.1/Ubuntu 16.04.1 LTE as of 2017-03-18: +# NOTE: We must add these following zones for lookup in both ways: When the binary file is being created for publication on Linux, Rangoon/Yangon is being translated. +# UTC+6:30 Yangon missing on Ubuntu/Qt5.5.1. +Asia/Rangoon Asia/Yangon +# This can translate from the binary location file back to the zone name as known on Windows. +Asia/Yangon Asia/Rangoon +# Missing on Qt5.9.5/Ubuntu 18.04.4 +America/Godthab UTC-03:00 +# Missing on Qt5.12.10/Win7 +# no DST; https://www.zeitverschiebung.net/en/timezone/asia--qostanay +Asia/Qostanay UTC+06:00 +# no DST; https://www.zeitverschiebung.net/en/timezone/europe--saratov +Europe/Saratov UTC+04:00 +# no DST; https://www.zeitverschiebung.net/en/timezone/asia--atyrau +Asia/Atyrau UTC+05:00 +# Asia/Nicosia has no DST, but Asia/Famagusta has DST! +Asia/Famagusta Asia/Nicosia +# no DST; https://www.zeitverschiebung.net/en/timezone/america--punta_arenas +America/Punta_Arenas UTC-03:00 +# Missing on Qt5.15.2/Win10 +America/Nuuk America/Godthab +#:EOF \ No newline at end of file diff --git a/plugins/Exoplanets/src/Exoplanets.cpp b/plugins/Exoplanets/src/Exoplanets.cpp index 3cb2149df83de..158942d53ebbe 100644 --- a/plugins/Exoplanets/src/Exoplanets.cpp +++ b/plugins/Exoplanets/src/Exoplanets.cpp @@ -965,7 +965,7 @@ void Exoplanets::updateDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) while (bytesTotal > 1024) { bytesReceived = static_cast(std::floor(static_cast(bytesReceived) / 1024.)); - bytesTotal = static_cast(std::floor(static_cast(bytesTotal) / 1024.)); + bytesTotal = static_cast(std::floor(static_cast(bytesTotal) / 1024.)); } currentValue = static_cast(bytesReceived); endValue = static_cast(bytesTotal); diff --git a/src/core/StelLocationMgr.cpp b/src/core/StelLocationMgr.cpp index abbae22677b3a..40500a69eb629 100644 --- a/src/core/StelLocationMgr.cpp +++ b/src/core/StelLocationMgr.cpp @@ -42,10 +42,11 @@ #include TimezoneNameMap StelLocationMgr::locationDBToIANAtranslations; - +QString StelLocationMgr::tzfFileName = "data/timezone.tab"; QList StelLocationMgr::regions; QMap StelLocationMgr::countryCodeToRegionMap; QMap StelLocationMgr::countryNameToCodeMap; +bool StelLocationMgr::unknownTZ = false; #ifdef ENABLE_GPS #ifdef ENABLE_LIBGPS @@ -408,75 +409,11 @@ void NMEALookupHelper::nmeaTimeout() StelLocationMgr::StelLocationMgr() : nmeaHelper(Q_NULLPTR), libGpsHelper(Q_NULLPTR) { - // initialize the static QMap first if necessary. - // The first entry is the DB name, the second is as we display it in the program. - if (locationDBToIANAtranslations.isEmpty()) - { - // Reported April 25, 2023. (#3200) - locationDBToIANAtranslations.insert("America/Yellowknife","America/Edmonton"); - // Seen February 06, 2023. - locationDBToIANAtranslations.insert("America/Ciudad_Juarez","America/Ojinaga"); - // Seen November 11, 2022. - locationDBToIANAtranslations.insert("America/Thunder_Bay","America/Toronto"); - locationDBToIANAtranslations.insert("Europe/Uzhgorod", "Europe/Kyiv"); - // Seen on October 27, 2022. TZ Removed? - locationDBToIANAtranslations.insert("Europe/Zaporozhye","Europe/Kyiv"); - // Seen on September 26, 2022. Officially renamed. - locationDBToIANAtranslations.insert("Europe/Kyiv", "Europe/Kiev"); - locationDBToIANAtranslations.insert("Europe/Kiev", "Europe/Kyiv"); - // Seen in an unrelated bug report, 2022-08-30 - locationDBToIANAtranslations.insert("Asia/Pyongyang", "UTC+09:00"); - // reported in SF forum on 2017-03-27 - locationDBToIANAtranslations.insert("Europe/Minsk", "UTC+03:00"); - locationDBToIANAtranslations.insert("Europe/Samara", "UTC+04:00"); - locationDBToIANAtranslations.insert("America/Cancun", "UTC-05:00"); - locationDBToIANAtranslations.insert("Asia/Kamchatka", "UTC+12:00"); - // Missing on Qt5.7/Win10 as of 2017-03-18. - locationDBToIANAtranslations.insert("Europe/Astrakhan", "UTC+04:00"); - locationDBToIANAtranslations.insert("Europe/Ulyanovsk", "UTC+04:00"); - locationDBToIANAtranslations.insert("Europe/Kirov", "UTC+03:00"); - locationDBToIANAtranslations.insert("Asia/Hebron", "Asia/Jerusalem"); - locationDBToIANAtranslations.insert("Asia/Gaza", "Asia/Jerusalem"); // or use UTC+2:00? (political issue...) - locationDBToIANAtranslations.insert("Asia/Kolkata", "Asia/Calcutta"); - locationDBToIANAtranslations.insert("Asia/Kathmandu", "Asia/Katmandu"); - locationDBToIANAtranslations.insert("Asia/Tomsk", "Asia/Novosibirsk"); - locationDBToIANAtranslations.insert("Asia/Barnaul", "UTC+07:00"); - locationDBToIANAtranslations.insert("Asia/Ho_Chi_Minh", "Asia/Saigon"); - locationDBToIANAtranslations.insert("Asia/Hovd", "UTC+07:00"); - locationDBToIANAtranslations.insert("America/Argentina/Buenos_Aires", "America/Buenos_Aires"); - locationDBToIANAtranslations.insert("America/Argentina/Jujuy", "America/Jujuy"); - locationDBToIANAtranslations.insert("America/Argentina/Mendoza", "America/Mendoza"); - locationDBToIANAtranslations.insert("America/Argentina/Catamarca", "America/Catamarca"); - locationDBToIANAtranslations.insert("America/Argentina/Cordoba", "America/Cordoba"); - locationDBToIANAtranslations.insert("America/Indiana/Indianapolis", "America/Indianapolis"); - locationDBToIANAtranslations.insert("America/Kentucky/Louisville", "America/Louisville"); - locationDBToIANAtranslations.insert("America/Miquelon", "UTC-03:00"); // Small Canadian island. - locationDBToIANAtranslations.insert("Africa/Asmara", "Africa/Asmera"); - locationDBToIANAtranslations.insert("Atlantic/Faroe", "Atlantic/Faeroe"); - locationDBToIANAtranslations.insert("Pacific/Pohnpei", "Pacific/Ponape"); - locationDBToIANAtranslations.insert("Pacific/Norfolk", "UTC+11:00"); - locationDBToIANAtranslations.insert("Pacific/Pitcairn", "UTC-08:00"); - // Missing on Qt5.5.1/Ubuntu 16.04.1 LTE as of 2017-03-18: - // NOTE: We must add these following zones for lookup in both ways: When the binary file is being created for publication on Linux, Rangoon/Yangon is being translated. - locationDBToIANAtranslations.insert("Asia/Rangoon", "Asia/Yangon"); // UTC+6:30 Yangon missing on Ubuntu/Qt5.5.1. - locationDBToIANAtranslations.insert("Asia/Yangon", "Asia/Rangoon"); // This can translate from the binary location file back to the zone name as known on Windows. - locationDBToIANAtranslations.insert( "", "UTC"); - // Missing on Qt5.9.5/Ubuntu 18.04.4 - locationDBToIANAtranslations.insert("America/Godthab", "UTC-03:00"); - // Missing on Qt5.12.10/Win7 - locationDBToIANAtranslations.insert("Asia/Qostanay", "UTC+06:00"); // no DST; https://www.zeitverschiebung.net/en/timezone/asia--qostanay - locationDBToIANAtranslations.insert("Europe/Saratov", "UTC+04:00"); // no DST; https://www.zeitverschiebung.net/en/timezone/europe--saratov - locationDBToIANAtranslations.insert("Asia/Atyrau", "UTC+05:00"); // no DST; https://www.zeitverschiebung.net/en/timezone/asia--atyrau - locationDBToIANAtranslations.insert("Asia/Famagusta", "Asia/Nicosia"); // Asia/Nicosia has no DST, but Asia/Famagusta has DST! - locationDBToIANAtranslations.insert("America/Punta_Arenas", "UTC-03:00"); // no DST; https://www.zeitverschiebung.net/en/timezone/america--punta_arenas - // Missing on Qt5.15.2/Win10 - locationDBToIANAtranslations.insert("America/Nuuk", "America/Godthab"); - // N.B. Further missing TZ names will be printed out in the log.txt. Resolve these by adding into this list. - // TODO later: create a text file in user data directory, and auto-update it weekly. - } - QSettings* conf = StelApp::getInstance().getSettings(); + // N.B. Further missing TZ names will be printed out in the log.txt. Resolve these by adding into data/timezone.tab file. + loadTimeZoneFixes(); + loadCountries(); loadRegions(); // The line below allows to re-generate the location file, you still need to gunzip it manually afterward. @@ -591,9 +528,10 @@ LocationMap StelLocationMgr::loadCitiesBin(const QString& fileName) } } } - if (unknownTZlist.length()>0) + if (!unknownTZlist.isEmpty()) { unknownTZlist.removeDuplicates(); + unknownTZ = true; qDebug() << "StelLocationMgr::loadCitiesBin(): Summary of unknown TimeZones:"; for (const auto& tz : unknownTZlist) { @@ -1246,6 +1184,51 @@ void StelLocationMgr::loadCountries() countryNameToCodeMap.insert("Taiwan (Provice of China)", "tw"); } +void StelLocationMgr::loadTimeZoneFixes() +{ + QString tzFilePath = StelFileMgr::findFile(tzfFileName); + if (tzFilePath.isEmpty()) + { + tzFilePath = StelFileMgr::findFile(tzfFileName, StelFileMgr::New); + // Create a default TZF (timezone fixes) file + QFile tzSrc(":/data/timezone.tab"); + if (!tzSrc.copy(tzFilePath)) + { + qWarning() << "Cannot copy timezone fixes to " + QDir::toNativeSeparators(tzFilePath); + return; + } + QFile dest(tzFilePath); + // fix file permissions + dest.setPermissions(dest.permissions() | QFile::WriteOwner); + } + QFile tzFile(tzFilePath); + + if(tzFile.open(QFile::ReadOnly | QFile::Text)) + { + locationDBToIANAtranslations.clear(); + QString line; + locationDBToIANAtranslations.insert("", "UTC"); // a first fix + int readOk = 1; + static const QRegularExpression dataRx("^([\\w\\/]+)\\t([\\w\\/\\+\\-:]+)\\s*(.*)$"); + while(!tzFile.atEnd()) + { + line = QString::fromUtf8(tzFile.readLine()); + if (line.startsWith("//") || line.startsWith("#") || line.isEmpty()) + continue; + + QRegularExpressionMatch dataMatch = dataRx.match(line); + if (dataMatch.hasMatch()) + { + // The first entry is the DB name, the second is as we display it in the program. + locationDBToIANAtranslations.insert(dataMatch.captured(1).trimmed().toUtf8(), dataMatch.captured(2).trimmed().toUtf8()); + readOk++; + } + } + qDebug() << "Loaded" << readOk << "fixes for time zones"; + tzFile.close(); + } +} + void StelLocationMgr::loadRegions() { QFile geoFile(StelFileMgr::findFile("data/regions-geoscheme.tab")); diff --git a/src/core/StelLocationMgr.hpp b/src/core/StelLocationMgr.hpp index 93b5fd70bf43f..f5c75588d19df 100644 --- a/src/core/StelLocationMgr.hpp +++ b/src/core/StelLocationMgr.hpp @@ -104,6 +104,9 @@ class StelLocationMgr : public QObject //! Pick region name from region code static QString pickRegionFromCode(int regionCode); + static QString getTZFFileName() { return tzfFileName; } + static bool unknownTimezonesDetected() { return unknownTZ; } + public slots: //! Return the StelLocation for a given string //! Can match location name, or coordinates @@ -160,6 +163,7 @@ private slots: private: void loadRegions(); void loadCountries(); + void loadTimeZoneFixes(); void generateBinaryLocationFile(const QString& txtFile, bool isUserLocation, const QString& binFile) const; //! Load cities from a file @@ -182,6 +186,8 @@ private slots: static QList regions; static QMap countryCodeToRegionMap; static QMap countryNameToCodeMap; + static QString tzfFileName; + static bool unknownTZ; StelLocation lastResortLocation; diff --git a/src/gui/LocationDialog.cpp b/src/gui/LocationDialog.cpp index babd2bfd5a785..ab6f49e77fdd8 100644 --- a/src/gui/LocationDialog.cpp +++ b/src/gui/LocationDialog.cpp @@ -33,6 +33,7 @@ #include "StelFileMgr.hpp" #include "StelGui.hpp" #include "StelSkyCultureMgr.hpp" +#include "StelProgressController.hpp" #include #include @@ -45,6 +46,10 @@ LocationDialog::LocationDialog(QObject* parent) : StelDialog("Location", parent) , isEditingNew(false) + , updateState(CompleteNoUpdates) + , networkManager(nullptr) + , downloadReply(nullptr) + , progressBar(nullptr) , allModel(nullptr) , pickedModel(nullptr) , proxyModel(nullptr) @@ -209,6 +214,13 @@ void LocationDialog::createDialogContent() }); ui->citySearchLineEdit->setFocus(); + + // Set up download manager for checker of updates + //networkManager = StelApp::getInstance().getNetworkAccessManager(); + networkManager = new QNetworkAccessManager(this); + updateState = CompleteNoUpdates; + ui->updateTZFButton->setVisible(locMgr->unknownTimezonesDetected()); + connect(ui->updateTZFButton, SIGNAL(clicked()), this, SLOT(updateTZF())); } void LocationDialog::setDisplayFormatForSpins(bool flagDecimalDegrees) @@ -981,3 +993,116 @@ void LocationDialog::filterSitesByRegion() ui->citySearchLineEdit->setText(""); // https://wiki.qt.io/Technical_FAQ#Why_does_the_memory_keep_increasing_when_repeatedly_pasting_text_and_calling_clear.28.29_in_a_QLineEdit.3F ui->citySearchLineEdit->setFocus(); } + +void LocationDialog::updateTZF() +{ + if (updateState==LocationDialog::Updating) + { + qWarning() << "Already updating... will not start again until current update is complete."; + return; + } + + if (progressBar == Q_NULLPTR) + progressBar = StelApp::getInstance().addProgressBar(); + progressBar->setValue(0); + progressBar->setRange(0, 0); + + qDebug() << "Updating timezone fixes..."; + + QSettings* conf = StelApp::getInstance().getSettings(); + QUrl URL(conf->value("main/timezone_url", "https://www.stellarium.org/files/timezone.tab").toString()); + connect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(downloadComplete(QNetworkReply*))); + QNetworkRequest request; + request.setUrl(URL); + request.setRawHeader("User-Agent", StelUtils::getUserAgentString().toUtf8()); +#if (QT_VERSIONget(request); + connect(downloadReply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(updateDownloadProgress(qint64,qint64))); + + updateState = LocationDialog::Updating; +} + +void LocationDialog::downloadComplete(QNetworkReply *reply) +{ + if (reply == nullptr) + return; + + disconnect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(downloadComplete(QNetworkReply*))); + + if (reply->error() || reply->bytesAvailable()==0) + { + qWarning() << "Error: While trying to access" + << reply->url().toString() + << "the following error occurred:" + << reply->errorString(); + + updateState = LocationDialog::DownloadError; + } + else + { + QByteArray data = reply->readAll(); + if (QString(data).endsWith(":EOF")) // Qt5-compatible check + { + QString tzfFilePath = StelFileMgr::findFile(StelLocationMgr::getTZFFileName()); + QFile tzfFile(tzfFilePath); + if (tzfFile.exists()) + tzfFile.remove(); + + if (tzfFile.open(QIODevice::WriteOnly | QIODevice::Text)) + { + tzfFile.write(data); + tzfFile.close(); + } + qWarning() << "Updating timezone fixes are complete... The new data will be apply on next startup."; + updateState = LocationDialog::CompleteUpdates; + } + else + { + qWarning() << "Downloaded timezone fixes are not completed, restore the data!"; + updateState = LocationDialog::OtherError; + } + } + + deleteDownloadProgressBar(); + + reply->deleteLater(); + downloadReply = nullptr; + emit updateTZFComplete(); +} + +void LocationDialog::updateDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) +{ + if (progressBar == Q_NULLPTR) + return; + + int currentValue = 0; + int endValue = 0; + + if (bytesTotal > -1 && bytesReceived <= bytesTotal) + { + //Round to the greatest possible derived unit + while (bytesTotal > 1024) + { + bytesReceived /= 1024; + bytesTotal /= 1024; + } + currentValue = static_cast(bytesReceived); + endValue = static_cast(bytesTotal); + } + + progressBar->setValue(currentValue); + progressBar->setRange(0, endValue); +} + +void LocationDialog::deleteDownloadProgressBar() +{ + disconnect(this, SLOT(updateDownloadProgress(qint64,qint64))); + + if (progressBar) + { + StelApp::getInstance().removeProgressBar(progressBar); + progressBar = Q_NULLPTR; + } +} diff --git a/src/gui/LocationDialog.hpp b/src/gui/LocationDialog.hpp index 658a725dd5138..842410eb14306 100644 --- a/src/gui/LocationDialog.hpp +++ b/src/gui/LocationDialog.hpp @@ -22,6 +22,8 @@ #include #include "StelDialog.hpp" +#include +#include class Ui_locationDialogForm; class QModelIndex; @@ -33,6 +35,16 @@ class LocationDialog : public StelDialog { Q_OBJECT public: + //! @enum UpdateState + //! Used for keeping for track of the download/update status + enum UpdateState { + Updating, //!< Update in progress + CompleteNoUpdates, //!< Update completed, there we no updates + CompleteUpdates, //!< Update completed, there were updates + DownloadError, //!< Error during download phase + OtherError //!< Other error + }; + LocationDialog(QObject* parent); ~LocationDialog() override; @@ -86,7 +98,17 @@ public slots: //! Populates tooltips for GUI elements. void populateTooltips(); - + + // variables and functions for the updater + UpdateState updateState; + QNetworkAccessManager * networkManager; + QNetworkReply * downloadReply; + class StelProgressController* progressBar; + void deleteDownloadProgressBar(); + +signals: + void updateTZFComplete(void); + private slots: //! Called whenever the StelLocationMgr is updated void reloadLocations(); @@ -163,6 +185,10 @@ private slots: //! Updates the check state and the enabled/disabled status. void updateTimeZoneControls(bool useCustomTimeZone); + void updateTZF(void); + void downloadComplete(QNetworkReply * reply); + void updateDownloadProgress(qint64 bytesReceived, qint64 bytesTotal); + private: QString lastPlanet; // for caching when switching map QString customTimeZone; // for caching when switching around timezones. diff --git a/src/gui/locationDialogGui.ui b/src/gui/locationDialogGui.ui index ea15a6976fb56..2f8c06ca4fe75 100644 --- a/src/gui/locationDialogGui.ui +++ b/src/gui/locationDialogGui.ui @@ -6,7 +6,7 @@ 0 0 - 630 + 641 542 @@ -693,38 +693,13 @@ 0 - - - - - 0 - 0 - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - true - - - QComboBox::NoInsert + + + + - - - - - - New Location + + Enable daylight saving time @@ -735,17 +710,17 @@ - - + + - Use custom time zone + Region: - - + + - Time zone: + Use custom time zone @@ -756,10 +731,25 @@ - - - - true + + + + + 0 + 0 + + + + + 0 + 24 + + + + + 16777215 + 24 + true @@ -797,20 +787,37 @@ - - - - Region: + + + + true + + + true + + + QComboBox::NoInsert - - - - + + + + New Location + + + + - Enable daylight saving time + Time zone: + + + + + + + Update time zones @@ -832,6 +839,11 @@
Dialog.hpp
1 + + StelCloseButton + QPushButton +
gui/StelCloseButton.hpp
+
AngleSpinBox QSpinBox @@ -842,11 +854,6 @@ QWidget
MapWidget.hpp
- - StelCloseButton - QPushButton -
gui/StelCloseButton.hpp
-
citySearchLineEdit