diff --git a/ChangeLog.md b/ChangeLog.md index 347325f..5ff4dd8 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -10,7 +10,8 @@ Note: This file only contains high level features or important fixes. ## 3.4 -### 3.4.4 - Not yet released +### 3.4.4 - Stable +* Stable desktop versions now inform user at boot if newer version is available. * Multi-Vehicle Start Mission and Pause now work correctly. Issue #6864. ### 3.4.3 diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index 3db7b0f..3421324 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef QGC_ENABLE_BLUETOOTH #include @@ -87,6 +88,7 @@ #include "EditPositionDialogController.h" #include "FactValueSliderListModel.h" #include "KMLFileHelper.h" +#include "QGCFileDownload.h" #ifndef NO_SERIAL_LINK #include "SerialLink.h" @@ -149,17 +151,21 @@ static QObject* kmlFileHelperSingletonFactory(QQmlEngine*, QJSEngine*) QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting) #ifdef __mobile__ - : QGuiApplication (argc, argv) - , _qmlAppEngine (nullptr) + : QGuiApplication (argc, argv) + , _qmlAppEngine (nullptr) #else - : QApplication (argc, argv) + : QApplication (argc, argv) #endif - , _runningUnitTests (unitTesting) - , _logOutput (false) - , _fakeMobile (false) - , _settingsUpgraded (false) - , _toolbox (nullptr) - , _bluetoothAvailable (false) + , _runningUnitTests (unitTesting) + , _logOutput (false) + , _fakeMobile (false) + , _settingsUpgraded (false) + , _majorVersion (0) + , _minorVersion (0) + , _buildVersion (0) + , _currentVersionDownload (nullptr) + , _toolbox (nullptr) + , _bluetoothAvailable (false) { _app = this; @@ -330,6 +336,8 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting) _toolbox = new QGCToolbox(this); _toolbox->setChildToolboxes(); + + _checkForNewVersion(); } void QGCApplication::_shutdown(void) @@ -702,3 +710,68 @@ bool QGCApplication::isInternetAvailable() { return getQGCMapEngine()->isInternetActive(); } + +void QGCApplication::_checkForNewVersion(void) +{ +#ifndef __mobile__ + if (!_runningUnitTests) { + if (_parseVersionText(applicationVersion(), _majorVersion, _minorVersion, _buildVersion)) { + QString versionCheckFile = toolbox()->corePlugin()->stableVersionCheckFileUrl(); + if (!versionCheckFile.isEmpty()) { + _currentVersionDownload = new QGCFileDownload(this); + connect(_currentVersionDownload, &QGCFileDownload::downloadFinished, this, &QGCApplication::_currentVersionDownloadFinished); + connect(_currentVersionDownload, &QGCFileDownload::error, this, &QGCApplication::_currentVersionDownloadError); + _currentVersionDownload->download(versionCheckFile); + } + } + } +#endif +} + +void QGCApplication::_currentVersionDownloadFinished(QString remoteFile, QString localFile) +{ + Q_UNUSED(remoteFile); + +#ifdef __mobile__ + Q_UNUSED(localFile); +#else + QFile versionFile(localFile); + if (versionFile.open(QIODevice::ReadOnly)) { + QTextStream textStream(&versionFile); + QString version = textStream.readLine(); + + qDebug() << version; + + int majorVersion, minorVersion, buildVersion; + if (_parseVersionText(version, majorVersion, minorVersion, buildVersion)) { + if (_majorVersion < majorVersion || + (_majorVersion == majorVersion && _minorVersion < minorVersion) || + (_majorVersion == majorVersion && _minorVersion == minorVersion && _buildVersion < buildVersion)) { + QGCMessageBox::information(tr("New Version Available"), tr("There is a newer version of %1 available. You can download it from %2.").arg(applicationName()).arg(toolbox()->corePlugin()->stableDownloadLocation())); + } + } + } + + _currentVersionDownload->deleteLater(); +#endif +} + +void QGCApplication::_currentVersionDownloadError(QString errorMsg) +{ + Q_UNUSED(errorMsg); + _currentVersionDownload->deleteLater(); +} + +bool QGCApplication::_parseVersionText(const QString& versionString, int& majorVersion, int& minorVersion, int& buildVersion) +{ + QRegularExpression regExp("v(\\d+)\\.(\\d+)\\.(\\d+)"); + QRegularExpressionMatch match = regExp.match(versionString); + if (match.hasMatch() && match.lastCapturedIndex() == 3) { + majorVersion = match.captured(1).toInt(); + minorVersion = match.captured(2).toInt(); + buildVersion = match.captured(3).toInt(); + return true; + } + + return false; +} diff --git a/src/QGCApplication.h b/src/QGCApplication.h index 5c86cd5..b4aac9a 100644 --- a/src/QGCApplication.h +++ b/src/QGCApplication.h @@ -42,6 +42,7 @@ class QGCSingleton; class MainWindow; class QGCToolbox; +class QGCFileDownload; /** * @brief The main application and management class. @@ -148,9 +149,13 @@ public: private slots: void _missingParamsDisplay(void); + void _currentVersionDownloadFinished(QString remoteFile, QString localFile); + void _currentVersionDownloadError(QString errorMsg); + bool _parseVersionText(const QString& versionString, int& majorVersion, int& minorVersion, int& buildVersion); private: QObject* _rootQmlObject(void); + void _checkForNewVersion(void); #ifdef __mobile__ QQmlApplicationEngine* _qmlAppEngine; @@ -166,6 +171,10 @@ private: QStringList _missingParams; ///< List of missing facts to be displayed bool _fakeMobile; ///< true: Fake ui into displaying mobile interface bool _settingsUpgraded; ///< true: Settings format has been upgrade to new version + int _majorVersion; + int _minorVersion; + int _buildVersion; + QGCFileDownload* _currentVersionDownload; QGCToolbox* _toolbox; diff --git a/src/api/QGCCorePlugin.cc b/src/api/QGCCorePlugin.cc index b9e45ae..4cab316 100644 --- a/src/api/QGCCorePlugin.cc +++ b/src/api/QGCCorePlugin.cc @@ -319,3 +319,13 @@ bool QGCCorePlugin::guidedActionsControllerLogging(void) const { return GuidedActionsControllerLog().isDebugEnabled(); } + +QString QGCCorePlugin::stableVersionCheckFileUrl(void) const +{ +#ifdef QGC_CUSTOM_BUILD + // Custom builds must override to turn on and provide their own location + return QString(); +#else + return QString("https://s3-us-west-2.amazonaws.com/qgroundcontrol/latest/QGC.version.txt"); +#endif +} diff --git a/src/api/QGCCorePlugin.h b/src/api/QGCCorePlugin.h index 5fb2493..13deb75 100644 --- a/src/api/QGCCorePlugin.h +++ b/src/api/QGCCorePlugin.h @@ -127,6 +127,18 @@ public: virtual void preLoadFromJson (PlanMasterController* pController, QJsonObject& json) { Q_UNUSED(pController); Q_UNUSED(json); } virtual void postLoadFromJson (PlanMasterController* pController, QJsonObject& json) { Q_UNUSED(pController); Q_UNUSED(json); } + /// Returns the url to download the stable version check file. Return QString() to indicate no version check should be performed. + /// Default QGC mainline implemenentation returns QGC Stable file location. Default QGC custom build code returns QString(). + /// Custom builds can override to turn on and provide their own location. + /// The contents of this file should be a single line in the form: + /// v3.4.4 + /// This indicates the latest stable version number. + virtual QString stableVersionCheckFileUrl(void) const; + + /// Returns the user visible url to show user where to download new stable builds from. + /// Custom builds must override to provide their own location. + virtual QString stableDownloadLocation(void) const { return QString("qgroundcontrol.com"); } + bool showTouchAreas(void) const { return _showTouchAreas; } bool showAdvancedUI(void) const { return _showAdvancedUI; } void setShowTouchAreas(bool show);