From 94c3108494706016e2d37ea0b48be709d799751f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 9 Oct 2022 18:51:01 +0200 Subject: [PATCH] GUI: Detect when version is old --- cmake/findDependencies.cmake | 2 +- cmake/qtCompat.cmake | 4 +- gui/CMakeLists.txt | 2 +- gui/common.h | 1 + gui/gui.pro | 1 + gui/mainwindow.cpp | 77 ++++++++++++++++++++++++++++++++++++ gui/mainwindow.h | 8 ++++ gui/mainwindow.ui | 59 +++++++++++++++++++++++++-- 8 files changed, 148 insertions(+), 6 deletions(-) diff --git a/cmake/findDependencies.cmake b/cmake/findDependencies.cmake index 5a265e54d..3ad0e366f 100644 --- a/cmake/findDependencies.cmake +++ b/cmake/findDependencies.cmake @@ -1,5 +1,5 @@ if (BUILD_GUI) - list(APPEND qt_components Core Gui Widgets PrintSupport LinguistTools Help) + list(APPEND qt_components Core Gui Widgets PrintSupport LinguistTools Help Network) if (WITH_QCHART) list(APPEND qt_components Charts) endif() diff --git a/cmake/qtCompat.cmake b/cmake/qtCompat.cmake index 9f39be728..ad2b56984 100644 --- a/cmake/qtCompat.cmake +++ b/cmake/qtCompat.cmake @@ -28,6 +28,7 @@ if (QT_VERSION VERSION_LESS 5.15) set(QT_HELP_LIB Qt5::Help) set(QT_PRINTSUPPORT_LIB Qt5::PrintSupport) set(QT_CHARTS_LIB Qt5::Charts) + set(QT_NETWORK_LIB Qt5::Network) else() # use "versionless" targets - no need for wrapper functions @@ -38,4 +39,5 @@ else() set(QT_HELP_LIB Qt::Help) set(QT_PRINTSUPPORT_LIB Qt::PrintSupport) set(QT_CHARTS_LIB Qt::Charts) -endif() \ No newline at end of file + set(QT_NETWORK_LIB Qt::Network) +endif() diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 17680621f..d7c6edc47 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -47,7 +47,7 @@ CheckOptions: if(tinyxml2_FOUND AND NOT USE_BUNDLED_TINYXML2) target_link_libraries(cppcheck-gui ${tinyxml2_LIBRARIES}) endif() - target_link_libraries(cppcheck-gui ${QT_CORE_LIB} ${QT_GUI_LIB} ${QT_WIDGETS_LIB} ${QT_PRINTSUPPORT_LIB} ${QT_HELP_LIB}) + target_link_libraries(cppcheck-gui ${QT_CORE_LIB} ${QT_GUI_LIB} ${QT_WIDGETS_LIB} ${QT_PRINTSUPPORT_LIB} ${QT_HELP_LIB} ${QT_NETWORK_LIB}) if(WITH_QCHART) target_compile_definitions (cppcheck-gui PRIVATE HAVE_QCHART) target_link_libraries(cppcheck-gui ${QT_CHARTS_LIB}) diff --git a/gui/common.h b/gui/common.h index e816ccc8b..3a780f152 100644 --- a/gui/common.h +++ b/gui/common.h @@ -89,6 +89,7 @@ #define SETTINGS_SHOW_ERROR_ID "Show error Id" #define SETTINGS_SHOW_STATISTICS "Show statistics" #define SETTINGS_OPEN_PROJECT "Open Project" +#define SETTINGS_CHECK_VERSION "Check Version" // The maximum value for the progress bar #define PROGRESS_MAX 1024.0 diff --git a/gui/gui.pro b/gui/gui.pro index d8c8202a0..759d80310 100644 --- a/gui/gui.pro +++ b/gui/gui.pro @@ -10,6 +10,7 @@ INCLUDEPATH += . \ QT += widgets QT += printsupport QT += help +QT += network # Build online help onlinehelp.target = online-help.qhc diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index cb3bdb25d..754041809 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -66,6 +66,8 @@ #include #include #include +#include +#include static const QString OnlineHelpURL("https://cppcheck.sourceforge.io/manual.html"); static const QString compile_commands_json("compile_commands.json"); @@ -246,6 +248,24 @@ MainWindow::MainWindow(TranslationHandler* th, QSettings* settings) : #endif Platform &platform = mPlatforms.get((Settings::PlatformType)mSettings->value(SETTINGS_CHECKED_PLATFORM, defaultPlatform).toInt()); platform.mActMainWindow->setChecked(true); + + mNetworkAccessManager = new QNetworkAccessManager(this); + connect(mNetworkAccessManager, &QNetworkAccessManager::finished, + this, &MainWindow::replyFinished); + + mUI->mLabelInformation->setVisible(false); + mUI->mButtonHideInformation->setVisible(false); + connect(mUI->mButtonHideInformation, &QPushButton::clicked, + this, &MainWindow::hideInformation); + + // Is there a new version? + if (isCppcheckPremium()) { + const QUrl url("https://files.cppchecksolutions.com/version.txt"); + mNetworkAccessManager->get(QNetworkRequest(url)); + } else { + const QUrl url("https://cppcheck.sourceforge.io/version.txt"); + mNetworkAccessManager->get(QNetworkRequest(url)); + } } MainWindow::~MainWindow() @@ -1880,6 +1900,63 @@ void MainWindow::suppressIds(QStringList ids) mProjectFile->write(); } +static int getVersion(const QString& nameWithVersion) { + int ret = 0; + int v = 0; + int dot = 0; + for (const auto c: nameWithVersion) { + if (c == '\n' || c == '\r') + break; + else if (c == ' ') + dot = ret = v = 0; + else if (c == '.') { + ++dot; + ret = ret * 1000 + v; + v = 0; + } else if (c >= '0' && c <= '9') + v = v * 10 + (c.toLatin1() - '0'); + } + ret = ret * 1000 + v; + while (dot < 2) { + ++dot; + ret *= 1000; + } + return ret; +} + +void MainWindow::replyFinished(QNetworkReply *reply) { + reply->deleteLater(); + if (reply->error()) { + // TODO? + qDebug() << "Response: ERROR"; + return; + } + const QString str = reply->readAll(); + qDebug() << "Response: " << str; + if (reply->url().fileName() == "version.txt") { + QString nameWithVersion = QString("Cppcheck %1").arg(CppCheck::version()); + if (!mCppcheckCfgProductName.isEmpty()) + nameWithVersion = mCppcheckCfgProductName; + const int appVersion = getVersion(nameWithVersion); + const int latestVersion = getVersion(str.trimmed()); + if (appVersion < latestVersion) { + if (mSettings->value(SETTINGS_CHECK_VERSION, 0).toInt() != latestVersion) { + mUI->mButtonHideInformation->setVisible(true); + mUI->mLabelInformation->setVisible(true); + mUI->mLabelInformation->setText(tr("New version available: %1").arg(str.trimmed())); + } + } + } +} + +void MainWindow::hideInformation() { + int version = getVersion(mUI->mLabelInformation->text()); + mSettings->setValue(SETTINGS_CHECK_VERSION, version); + mUI->mLabelInformation->setVisible(false); + mUI->mButtonHideInformation->setVisible(false); +} + bool MainWindow::isCppcheckPremium() const { return mCppcheckCfgProductName.startsWith("Cppcheck Premium "); } + diff --git a/gui/mainwindow.h b/gui/mainwindow.h index 617c8187a..67d4799a4 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -40,6 +40,8 @@ class QLineEdit; class ImportProject; class QCloseEvent; class QObject; +class QNetworkAccessManager; +class QNetworkReply; namespace Ui { class MainWindow; } @@ -228,6 +230,10 @@ protected slots: /** Suppress error ids */ void suppressIds(QStringList ids); +private slots: + void replyFinished(QNetworkReply *reply); + + void hideInformation(); private: bool isCppcheckPremium() const; @@ -465,6 +471,8 @@ private: QString mCppcheckCfgAbout; QString mCppcheckCfgProductName; + + QNetworkAccessManager *mNetworkAccessManager = nullptr; }; /// @} #endif // MAINWINDOW_H diff --git a/gui/mainwindow.ui b/gui/mainwindow.ui index b2ccc3ad5..5bc78689b 100644 --- a/gui/mainwindow.ui +++ b/gui/mainwindow.ui @@ -50,9 +50,62 @@ 16777215 - + - + + + + 0 + 0 + + + + + + + + QLayout::SetDefaultConstraint + + + + + + 0 + 0 + + + + + 16777215 + 25 + + + + TextLabel + + + + + + + Hide + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + @@ -62,7 +115,7 @@ 0 0 640 - 28 + 30