diff --git a/include/config.h b/include/config.h index 485e97eb..54398cca 100644 --- a/include/config.h +++ b/include/config.h @@ -10,9 +10,12 @@ #include #include #include +#include #include "events.h" +static const QVersionNumber porymapVersion = QVersionNumber::fromString(PORYMAP_VERSION); + // In both versions the default new map border is a generic tree #define DEFAULT_BORDER_RSE (QList{0x1D4, 0x1D5, 0x1DC, 0x1DD}) #define DEFAULT_BORDER_FRLG (QList{0x14, 0x15, 0x1C, 0x1D}) @@ -78,6 +81,7 @@ public: this->warpBehaviorWarningDisabled = false; this->checkForUpdates = true; this->lastUpdateCheckTime = QDateTime(); + this->lastUpdateCheckVersion = porymapVersion; this->rateLimitTimes.clear(); } void addRecentProject(QString project); @@ -112,6 +116,7 @@ public: void setWarpBehaviorWarningDisabled(bool disabled); void setCheckForUpdates(bool enabled); void setLastUpdateCheckTime(QDateTime time); + void setLastUpdateCheckVersion(QVersionNumber version); void setRateLimitTimes(QMap map); QString getRecentProject(); QStringList getRecentProjects(); @@ -145,6 +150,7 @@ public: bool getWarpBehaviorWarningDisabled(); bool getCheckForUpdates(); QDateTime getLastUpdateCheckTime(); + QVersionNumber getLastUpdateCheckVersion(); QMap getRateLimitTimes(); protected: virtual QString getConfigFilepath() override; @@ -196,6 +202,7 @@ private: bool warpBehaviorWarningDisabled; bool checkForUpdates; QDateTime lastUpdateCheckTime; + QVersionNumber lastUpdateCheckVersion; QMap rateLimitTimes; }; diff --git a/include/ui/updatepromoter.h b/include/ui/updatepromoter.h index b3abd381..8b67c69e 100644 --- a/include/ui/updatepromoter.h +++ b/include/ui/updatepromoter.h @@ -5,6 +5,7 @@ #include #include +#include namespace Ui { class UpdatePromoter; @@ -29,7 +30,7 @@ private: QString changelog; QUrl downloadUrl; - bool breakingChanges; + QVersionNumber newVersion; bool foundReleases; QSet visitedUrls; // Prevent infinite redirection @@ -38,7 +39,6 @@ private: void get(const QUrl &url); void processWebpage(const QJsonDocument &data, const QUrl &nextUrl); void error(const QString &err, const QDateTime time = QDateTime()); - bool isNewerVersion(int major, int minor, int patch); private slots: void dialogButtonClicked(QAbstractButton *button); diff --git a/porymap.pro b/porymap.pro index cf4cc451..43eef36b 100644 --- a/porymap.pro +++ b/porymap.pro @@ -14,14 +14,8 @@ RC_ICONS = resources/icons/porymap-icon-2.ico ICON = resources/icons/porymap.icns QMAKE_CXXFLAGS += -std=c++17 -Wall QMAKE_TARGET_BUNDLE_PREFIX = com.pret -VERSION_MAJOR = 5 -VERSION_MINOR = 3 -VERSION_PATCH = 0 -VERSION = $${VERSION_MAJOR}.$${VERSION_MINOR}.$${VERSION_PATCH} -DEFINES += PORYMAP_VERSION_MAJOR=$$VERSION_MAJOR \ - PORYMAP_VERSION_MINOR=$$VERSION_MINOR \ - PORYMAP_VERSION_PATCH=$$VERSION_PATCH \ - PORYMAP_VERSION=\\\"$$VERSION\\\" +VERSION = 5.3.0 +DEFINES += PORYMAP_VERSION=\\\"$$VERSION\\\" SOURCES += src/core/block.cpp \ src/core/bitpacker.cpp \ diff --git a/src/config.cpp b/src/config.cpp index 967c21c8..177aeafa 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -411,6 +411,14 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) { this->checkForUpdates = getConfigBool(key, value); } else if (key == "last_update_check_time") { this->lastUpdateCheckTime = QDateTime::fromString(value).toLocalTime(); + } else if (key == "last_update_check_version") { + auto version = QVersionNumber::fromString(value); + if (version.segmentCount() != 3) { + logWarn(QString("Invalid config value for %1: '%2'. Must be 3 numbers separated by '.'").arg(key).arg(value)); + this->lastUpdateCheckVersion = porymapVersion; + } else { + this->lastUpdateCheckVersion = version; + } } else if (key.startsWith("rate_limit_time/")) { static const QRegularExpression regex("\\brate_limit_time/(?.+)"); QRegularExpressionMatch match = regex.match(key); @@ -465,6 +473,7 @@ QMap PorymapConfig::getKeyValueMap() { map.insert("warp_behavior_warning_disabled", QString::number(this->warpBehaviorWarningDisabled)); map.insert("check_for_updates", QString::number(this->checkForUpdates)); map.insert("last_update_check_time", this->lastUpdateCheckTime.toUTC().toString()); + map.insert("last_update_check_version", this->lastUpdateCheckVersion.toString()); for (auto i = this->rateLimitTimes.cbegin(), end = this->rateLimitTimes.cend(); i != end; i++){ // Only include rate limit times that are still active (i.e., in the future) const QDateTime time = i.value(); @@ -664,6 +673,11 @@ void PorymapConfig::setLastUpdateCheckTime(QDateTime time) { this->save(); } +void PorymapConfig::setLastUpdateCheckVersion(QVersionNumber version) { + this->lastUpdateCheckVersion = version; + this->save(); +} + void PorymapConfig::setRateLimitTimes(QMap map) { this->rateLimitTimes = map; this->save(); @@ -831,6 +845,10 @@ QDateTime PorymapConfig::getLastUpdateCheckTime() { return this->lastUpdateCheckTime; } +QVersionNumber PorymapConfig::getLastUpdateCheckVersion() { + return this->lastUpdateCheckVersion; +} + QMap PorymapConfig::getRateLimitTimes() { return this->rateLimitTimes; } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 3d094be2..fb08e898 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -65,7 +65,7 @@ MainWindow::MainWindow(QWidget *parent) : ui->setupUi(this); cleanupLargeLog(); - logInfo(QString("Launching Porymap v%1").arg(PORYMAP_VERSION)); + logInfo(QString("Launching Porymap v%1").arg(QCoreApplication::applicationVersion())); this->initWindow(); if (porymapConfig.getReopenOnLaunch() && this->openProject(porymapConfig.getRecentProject(), true)) diff --git a/src/scriptapi/scripting.cpp b/src/scriptapi/scripting.cpp index aa547724..112585c7 100644 --- a/src/scriptapi/scripting.cpp +++ b/src/scriptapi/scripting.cpp @@ -78,9 +78,9 @@ void Scripting::populateGlobalObject(MainWindow *mainWindow) { // Get version numbers QJSValue version = instance->engine->newObject(); - version.setProperty("major", PORYMAP_VERSION_MAJOR); - version.setProperty("minor", PORYMAP_VERSION_MINOR); - version.setProperty("patch", PORYMAP_VERSION_PATCH); + version.setProperty("major", porymapVersion.majorVersion()); + version.setProperty("minor", porymapVersion.minorVersion()); + version.setProperty("patch", porymapVersion.microVersion()); constants.setProperty("version", version); // Get basic tileset information diff --git a/src/ui/aboutporymap.cpp b/src/ui/aboutporymap.cpp index 96f20ee8..38c28144 100644 --- a/src/ui/aboutporymap.cpp +++ b/src/ui/aboutporymap.cpp @@ -8,7 +8,7 @@ AboutPorymap::AboutPorymap(QWidget *parent) : { ui->setupUi(this); - this->ui->label_Version->setText(QString("Version %1 - %2").arg(PORYMAP_VERSION).arg(QStringLiteral(__DATE__))); + this->ui->label_Version->setText(QString("Version %1 - %2").arg(QCoreApplication::applicationVersion()).arg(QStringLiteral(__DATE__))); this->ui->textBrowser->setSource(QUrl("qrc:/CHANGELOG.md")); } diff --git a/src/ui/updatepromoter.cpp b/src/ui/updatepromoter.cpp index 5305a647..8ca2b6cd 100644 --- a/src/ui/updatepromoter.cpp +++ b/src/ui/updatepromoter.cpp @@ -43,7 +43,7 @@ void UpdatePromoter::resetDialog() { this->changelog = QString(); this->downloadUrl = QString(); - this->breakingChanges = false; + this->newVersion = QVersionNumber(); this->foundReleases = false; this->visitedUrls.clear(); } @@ -87,19 +87,12 @@ void UpdatePromoter::processWebpage(const QJsonDocument &data, const QUrl &nextU // Convert tag string to version numbers const QString tagName = release.value("tag_name").toString(); - const QStringList tag = tagName.split("."); - if (tag.length() != 3) continue; - bool ok; - int major = tag.at(0).toInt(&ok); - if (!ok) continue; - int minor = tag.at(1).toInt(&ok); - if (!ok) continue; - int patch = tag.at(2).toInt(&ok); - if (!ok) continue; + const QVersionNumber version = QVersionNumber::fromString(tagName); + if (version.segmentCount() != 3) continue; // We've found a valid release tag. If the version number is not newer than the host version then we can stop looking at releases. this->foundReleases = true; - if (!this->isNewerVersion(major, minor, patch)) + if (porymapVersion >= version) break; const QString description = release.value("body").toString(); @@ -116,7 +109,7 @@ void UpdatePromoter::processWebpage(const QJsonDocument &data, const QUrl &nextU continue; } this->downloadUrl = url; - this->breakingChanges = (major > PORYMAP_VERSION_MAJOR); + this->newVersion = version; } // Record the changelog of this release so we can show all changes since the host release. @@ -137,20 +130,25 @@ void UpdatePromoter::processWebpage(const QJsonDocument &data, const QUrl &nextU } // Populate dialog with result - bool updateAvailable = !this->changelog.isEmpty(); - ui->label_Status->setText(updateAvailable ? "A new version of Porymap is available!" - : "Your version of Porymap is up to date!"); - ui->label_Warning->setVisible(this->breakingChanges); ui->text_Changelog->setMarkdown(this->changelog); - ui->text_Changelog->setVisible(updateAvailable); + ui->text_Changelog->setVisible(!this->changelog.isEmpty()); this->button_Downloads->setEnabled(!this->downloadUrl.isEmpty()); this->button_Retry->setEnabled(true); + if (!this->newVersion.isNull()) { + ui->label_Status->setText("A new version of Porymap is available!"); + ui->label_Warning->setVisible(this->newVersion.majorVersion() > porymapVersion.majorVersion()); - // Alert the user if there's a new update available and the dialog wasn't already open. - // Show the window, but also show the option to turn off automatic alerts in the future. - if (updateAvailable && !this->isVisible()) { - ui->checkBox_StopAlerts->setVisible(true); - this->show(); + // Alert the user about the new version if the dialog wasn't already open. + // Show the window, but also show the option to turn off automatic alerts in the future. + // We only show this alert once for a given release. + if (!this->isVisible() && this->newVersion > porymapConfig.getLastUpdateCheckVersion()) { + ui->checkBox_StopAlerts->setVisible(true); + this->show(); + } + porymapConfig.setLastUpdateCheckVersion(this->newVersion); + } else { + ui->label_Status->setText("Your version of Porymap is up to date!"); + ui->label_Warning->setVisible(false); } } @@ -173,14 +171,6 @@ void UpdatePromoter::error(const QString &err, const QDateTime retryAfter) { } } -bool UpdatePromoter::isNewerVersion(int major, int minor, int patch) { - if (major != PORYMAP_VERSION_MAJOR) - return major > PORYMAP_VERSION_MAJOR; - if (minor != PORYMAP_VERSION_MINOR) - return minor > PORYMAP_VERSION_MINOR; - return patch > PORYMAP_VERSION_PATCH; -} - void UpdatePromoter::updatePreferences() { const QSignalBlocker blocker(ui->checkBox_StopAlerts); ui->checkBox_StopAlerts->setChecked(!porymapConfig.getCheckForUpdates());