QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
QGCVersionCheck.cc
Go to the documentation of this file.
1#include "QGCVersionCheck.h"
2
3#include <optional>
4
5#include <QtCore/QApplicationStatic>
6#include <QtCore/QCoreApplication>
7#include <QtCore/QFile>
8#include <QtCore/QRegularExpression>
9#include <QtCore/QTextStream>
10#include <QtCore/QVersionNumber>
11
12#include "AppSettings.h"
13#include "Fact.h"
14#include "QGCApplication.h"
15#include "QGCCorePlugin.h"
16#include "QGCFileDownload.h"
17#include "QGCLoggingCategory.h"
18#include "SettingsManager.h"
19
20QGC_LOGGING_CATEGORY(QGCVersionCheckLog, "Utilities.QGCVersionCheck")
21
22Q_APPLICATION_STATIC(QGCVersionCheck, _qgcVersionCheckInstance);
23
24namespace {
25
26std::optional<QVersionNumber> _parseVersion(const QString& versionString)
27{
28 static const QRegularExpression regExp(QStringLiteral("^v(\\d+)\\.(\\d+)\\.(\\d+)"));
29 const QRegularExpressionMatch match = regExp.match(versionString.trimmed());
30 if (!match.hasMatch()) {
31 return std::nullopt;
32 }
33
34 return QVersionNumber(match.captured(1).toInt(), match.captured(2).toInt(), match.captured(3).toInt());
35}
36
37} // namespace
38
40 : QObject(parent)
41{}
42
44{
45 return _qgcVersionCheckInstance();
46}
47
48bool QGCVersionCheck::isNewerVersion(const QString& currentVersion, const QString& latestVersion)
49{
50 const std::optional<QVersionNumber> current = _parseVersion(currentVersion);
51 const std::optional<QVersionNumber> latest = _parseVersion(latestVersion);
52 return current && latest && (*latest > *current);
53}
54
55bool QGCVersionCheck::shouldNotify(const QString& latestVersion, const QString& lastNotifiedVersion)
56{
57 const std::optional<QVersionNumber> latest = _parseVersion(latestVersion);
58 if (!latest) {
59 return false;
60 }
61
62 const std::optional<QVersionNumber> lastNotified = _parseVersion(lastNotifiedVersion);
63 return !lastNotified || (*latest > *lastNotified);
64}
65
67{
68 if (!_parseVersion(QCoreApplication::applicationVersion())) {
69 return;
70 }
71
72 const QString versionCheckFile = QGCCorePlugin::instance()->stableVersionCheckFileUrl();
73 if (versionCheckFile.isEmpty()) {
74 return;
75 }
76
77 QGCFileDownload* const download = new QGCFileDownload(this);
78 (void) connect(download, &QGCFileDownload::finished, this,
79 [this, download](bool success, const QString& localFile, const QString& errorMsg) {
80 download->deleteLater();
81 _downloadComplete(success, localFile, errorMsg);
82 });
83 if (!download->start(versionCheckFile)) {
84 qCDebug(QGCVersionCheckLog) << "Download QGC stable version failed to start" << download->errorString();
85 download->deleteLater();
86 }
87}
88
89void QGCVersionCheck::_downloadComplete(bool success, const QString& localFile, const QString& errorMsg)
90{
91 if (!success) {
92 if (!errorMsg.isEmpty()) {
93 qCDebug(QGCVersionCheckLog) << "Download QGC stable version failed" << errorMsg;
94 }
95 return;
96 }
97
98 QFile versionFile(localFile);
99 if (!versionFile.open(QIODevice::ReadOnly)) {
100 return;
101 }
102
103 QTextStream textStream(&versionFile);
104 const QString version = textStream.readLine();
105 qCDebug(QGCVersionCheckLog) << version;
106
107 if (!isNewerVersion(QCoreApplication::applicationVersion(), version)) {
108 return;
109 }
110
111 _newStableVersion = version;
113
114 Fact* const lastNotifiedFact = SettingsManager::instance()->appSettings()->lastNotifiedStableVersion();
115 if (shouldNotify(version, lastNotifiedFact->rawValue().toString())) {
116 lastNotifiedFact->setRawValue(version);
117 const QString url = QGCCorePlugin::instance()->stableDownloadUrl();
118 qgcApp()->showAppMessage(
119 tr("There is a newer version of %1 available. You can download it from <a href=\"%2\">%2</a>.")
120 .arg(QCoreApplication::applicationName(), url),
121 tr("New Version Available"));
122 }
123}
#define qgcApp()
Unified file download utility with decompression, verification, and QML support.
#define QGC_LOGGING_CATEGORY(name, categoryStr)
Q_APPLICATION_STATIC(QGCVersionCheck, _qgcVersionCheckInstance)
A Fact is used to hold a single value within the system.
Definition Fact.h:15
void setRawValue(const QVariant &value)
Definition Fact.cc:135
QVariant rawValue() const
Definition Fact.h:87
virtual QString stableDownloadUrl() const
virtual QString stableVersionCheckFileUrl() const
static QGCCorePlugin * instance()
File download with progress, decompression, and hash verification.
void finished(bool success, const QString &localPath, const QString &errorMessage)
bool start(const QString &remoteUrl)
QString errorString() const
static bool isNewerVersion(const QString &currentVersion, const QString &latestVersion)
QGCVersionCheck(QObject *parent=nullptr)
static bool shouldNotify(const QString &latestVersion, const QString &lastNotifiedVersion)
static QGCVersionCheck * instance()
void newStableVersionChanged()
void start()
Starts the asynchronous download of the stable version file.
static SettingsManager * instance()
AppSettings * appSettings() const