From 54e1545bb1f9fd37e3311e31c3cef6eebf03c1d1 Mon Sep 17 00:00:00 2001 From: arcan1s Date: Thu, 4 Feb 2016 00:02:49 +0700 Subject: [PATCH] create update helper class Move old chechUpdates() method to this class. Create ability to show ChangeLog after updates (by using global config with version). Changelog (only for the latest version) will be written to version.h during cmake run. --- sources/CMakeLists.txt | 4 + sources/awdebug.cpp | 2 +- sources/awesome-widget/plugin/awactions.cpp | 102 +-------- sources/awesome-widget/plugin/awactions.h | 9 +- .../awesome-widget/plugin/awupdatehelper.cpp | 195 ++++++++++++++++++ .../awesome-widget/plugin/awupdatehelper.h | 52 +++++ sources/changelog.cmake | 5 + sources/version.h.in | 1 + 8 files changed, 270 insertions(+), 100 deletions(-) create mode 100644 sources/awesome-widget/plugin/awupdatehelper.cpp create mode 100644 sources/awesome-widget/plugin/awupdatehelper.h create mode 100644 sources/changelog.cmake diff --git a/sources/CMakeLists.txt b/sources/CMakeLists.txt index 1ff1734..1ed556e 100644 --- a/sources/CMakeLists.txt +++ b/sources/CMakeLists.txt @@ -39,6 +39,10 @@ option(BUILD_TESTING "Build with additional test abilities" OFF) set(CLANGFORMAT_EXECUTABLE "/usr/bin/clang-format" CACHE STRING "Path to clang-format executable") set(CPPCHECK_EXECUTABLE "/usr/bin/cppcheck" CACHE STRING "Path to cppcheck executable") +# generate changelog +set(PROJECT_CHANGELOG "Changelog" CACHE INTERNAL "") +include(changelog.cmake) + # flags if (CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "-Wall -Wno-cpp -std=c++14") diff --git a/sources/awdebug.cpp b/sources/awdebug.cpp index eee61e1..40a8d5f 100644 --- a/sources/awdebug.cpp +++ b/sources/awdebug.cpp @@ -78,7 +78,7 @@ const QStringList getBuildData() metadata.append( QString(" CPPCHECK_EXECUTABLE: %1").arg(CPPCHECK_EXECUTABLE)); metadata.append(QString(" PROP_FUTURE: %1").arg(PROP_FUTURE)); - metadata.append(QString(" PROP_FUTURE: %1").arg(PROP_FUTURE)); + metadata.append(QString(" PROP_TEST: %1").arg(PROP_TEST)); return metadata; } diff --git a/sources/awesome-widget/plugin/awactions.cpp b/sources/awesome-widget/plugin/awactions.cpp index f519632..93efb56 100644 --- a/sources/awesome-widget/plugin/awactions.cpp +++ b/sources/awesome-widget/plugin/awactions.cpp @@ -21,19 +21,13 @@ #include #include -#include -#include -#include -#include -#include -#include #include -#include -#include +#include #include #include "awdebug.h" +#include "awupdatehelper.h" #include "version.h" @@ -41,12 +35,16 @@ AWActions::AWActions(QObject *parent) : QObject(parent) { qCDebug(LOG_AW) << __PRETTY_FUNCTION__; + + m_updateHelper = new AWUpdateHelper(this); } AWActions::~AWActions() { qCDebug(LOG_AW) << __PRETTY_FUNCTION__; + + delete m_updateHelper; } @@ -54,15 +52,8 @@ void AWActions::checkUpdates(const bool showAnyway) { qCDebug(LOG_AW) << "Show anyway" << showAnyway; - // showAnyway options requires to show message if no updates found on direct - // request. In case of automatic check no message will be shown - QNetworkAccessManager *manager = new QNetworkAccessManager(nullptr); - connect(manager, &QNetworkAccessManager::finished, - [showAnyway, this](QNetworkReply *reply) { - return versionReplyRecieved(reply, showAnyway); - }); - - manager->get(QNetworkRequest(QUrl(VERSION_API))); + if (!m_updateHelper->checkVersion()) + m_updateHelper->checkUpdates(showAnyway); } @@ -86,7 +77,7 @@ bool AWActions::runCmd(const QString cmd) const // HACK: this method uses variable from version.h void AWActions::showReadme() const { - QDesktopServices::openUrl(QString(HOMEPAGE)); + QDesktopServices::openUrl(QUrl(HOMEPAGE)); } @@ -186,78 +177,3 @@ void AWActions::sendNotification(const QString eventId, const QString message) notification->setComponentName( QString("plasma-applet-org.kde.plasma.awesome-widget")); } - - -void AWActions::showInfo(const QString version) const -{ - qCDebug(LOG_AW) << "Version" << version; - - QString text = i18n("You are using the actual version %1", version); - if (!QString(COMMIT_SHA).isEmpty()) - text += QString(" (%1)").arg(QString(COMMIT_SHA)); - QMessageBox::information(nullptr, i18n("No new version found"), text); -} - - -void AWActions::showUpdates(const QString version) const -{ - qCDebug(LOG_AW) << "Version" << version; - - QString text; - text += i18n("Current version : %1", QString(VERSION)); - text += QString(COMMIT_SHA).isEmpty() - ? QString("\n") - : QString(" (%1)\n").arg(QString(COMMIT_SHA)); - text += i18n("New version : %1", version) + QString("\n\n"); - text += i18n("Click \"Ok\" to download"); - - int select - = QMessageBox::information(nullptr, i18n("There are updates"), text, - QMessageBox::Ok | QMessageBox::Cancel); - switch (select) { - case QMessageBox::Ok: - QDesktopServices::openUrl(QString(RELEASES) + version); - break; - case QMessageBox::Cancel: - default: - break; - } -} - - -void AWActions::versionReplyRecieved(QNetworkReply *reply, - const bool showAnyway) const -{ - qCDebug(LOG_AW) << "Return code" << reply->error() << "with message" - << reply->errorString() << "and show anyway" << showAnyway; - - QJsonParseError error; - QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error); - if ((reply->error() != QNetworkReply::NoError) - || (error.error != QJsonParseError::NoError)) { - qCWarning(LOG_AW) << "Parse error" << error.errorString(); - return; - } - reply->deleteLater(); - - // convert to map - QVariantMap firstRelease = jsonDoc.toVariant().toList().first().toMap(); - QString version = firstRelease[QString("tag_name")].toString(); - version.remove(QString("V.")); - qCInfo(LOG_AW) << "Found version" << version; - - // FIXME: possible there is a better way to check versions - int old_major = QString(VERSION).split(QChar('.')).at(0).toInt(); - int old_minor = QString(VERSION).split(QChar('.')).at(1).toInt(); - int old_patch = QString(VERSION).split(QChar('.')).at(2).toInt(); - int new_major = version.split(QChar('.')).at(0).toInt(); - int new_minor = version.split(QChar('.')).at(1).toInt(); - int new_patch = version.split(QChar('.')).at(2).toInt(); - if ((old_major < new_major) - || ((old_major == new_major) && (old_minor < new_minor)) - || ((old_major == new_major) && (old_minor == new_minor) - && (old_patch < new_patch))) - return showUpdates(version); - else if (showAnyway) - return showInfo(version); -} diff --git a/sources/awesome-widget/plugin/awactions.h b/sources/awesome-widget/plugin/awactions.h index af1374a..2f14650 100644 --- a/sources/awesome-widget/plugin/awactions.h +++ b/sources/awesome-widget/plugin/awactions.h @@ -22,7 +22,7 @@ #include -class QNetworkReply; +class AWUpdateHelper; class AWActions : public QObject { @@ -44,11 +44,8 @@ public slots: Q_INVOKABLE static void sendNotification(const QString eventId, const QString message); -private slots: - void showInfo(const QString version) const; - void showUpdates(const QString version) const; - void versionReplyRecieved(QNetworkReply *reply, - const bool showAnyway) const; +private: + AWUpdateHelper *m_updateHelper = nullptr; }; diff --git a/sources/awesome-widget/plugin/awupdatehelper.cpp b/sources/awesome-widget/plugin/awupdatehelper.cpp new file mode 100644 index 0000000..32a50e6 --- /dev/null +++ b/sources/awesome-widget/plugin/awupdatehelper.cpp @@ -0,0 +1,195 @@ +/*************************************************************************** + * This file is part of awesome-widgets * + * * + * awesome-widgets is free software: you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * awesome-widgets is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with awesome-widgets. If not, see http://www.gnu.org/licenses/ * + ***************************************************************************/ + +#include "awupdatehelper.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "awdebug.h" +#include "version.h" + + +AWUpdateHelper::AWUpdateHelper(QObject *parent) + : QObject(parent) +{ + qCDebug(LOG_AW) << __PRETTY_FUNCTION__; + + m_foundVersion = QString(VERSION); + m_genericConfig = QString("%1/awesomewidgets/generic.ini") + .arg(QStandardPaths::writableLocation( + QStandardPaths::GenericDataLocation)); +} + + +AWUpdateHelper::~AWUpdateHelper() +{ + qCDebug(LOG_AW) << __PRETTY_FUNCTION__; +} + + +void AWUpdateHelper::checkUpdates(const bool showAnyway) +{ + qCDebug(LOG_AW) << "Show anyway" << showAnyway; + + // showAnyway options requires to show message if no updates found on direct + // request. In case of automatic check no message will be shown + QNetworkAccessManager *manager = new QNetworkAccessManager(nullptr); + connect(manager, &QNetworkAccessManager::finished, + [showAnyway, this](QNetworkReply *reply) { + return versionReplyRecieved(reply, showAnyway); + }); + + manager->get(QNetworkRequest(QUrl(VERSION_API))); +} + + +bool AWUpdateHelper::checkVersion() +{ + QSettings settings(m_genericConfig, QSettings::IniFormat); + QString version + = settings.value(QString("Version"), QString(VERSION)).toString(); + // update version + settings.setValue(QString("Version"), QString(VERSION)); + settings.sync(); + + qCInfo(LOG_AW) << "Found version" << version << "actual one is" << VERSION; + if (version != QString(VERSION)) { + genMessageBox(i18n("Changelog of %1", VERSION), + QString(CHANGELOG).replace(QChar('@'), QChar('\n')), + QMessageBox::Ok) + ->open(); + return true; + } else { + qCInfo(LOG_AW) << "No need to update version"; + } + + return false; +} + + +void AWUpdateHelper::showInfo(const QString version) +{ + qCDebug(LOG_AW) << "Version" << version; + + QString text = i18n("You are using the actual version %1", version); + if (!QString(COMMIT_SHA).isEmpty()) + text += QString(" (%1)").arg(QString(COMMIT_SHA)); + return genMessageBox(i18n("No new version found"), text, QMessageBox::Ok) + ->open(); +} + + +void AWUpdateHelper::showUpdates(const QString version) +{ + qCDebug(LOG_AW) << "Version" << version; + + QString text; + text += i18n("Current version : %1", QString(VERSION)); + text += QString(COMMIT_SHA).isEmpty() + ? QString("\n") + : QString(" (%1)\n").arg(QString(COMMIT_SHA)); + text += i18n("New version : %1", version) + QString("\n\n"); + text += i18n("Click \"Ok\" to download"); + + genMessageBox(i18n("There are updates"), text, + QMessageBox::Ok | QMessageBox::Cancel) + ->open(this, SLOT(userReplyOnUpdates(QAbstractButton *))); +} + + +void AWUpdateHelper::userReplyOnUpdates(QAbstractButton *button) +{ + int ret = static_cast(sender())->buttonRole(button); + qCInfo(LOG_AW) << "User select" << ret; + + switch (ret) { + case QMessageBox::Ok: + QDesktopServices::openUrl(QString(RELEASES) + m_foundVersion); + break; + case QMessageBox::Cancel: + default: + break; + } +} + + +void AWUpdateHelper::versionReplyRecieved(QNetworkReply *reply, + const bool showAnyway) +{ + qCDebug(LOG_AW) << "Return code" << reply->error() << "with message" + << reply->errorString() << "and show anyway" << showAnyway; + + QJsonParseError error; + QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error); + if ((reply->error() != QNetworkReply::NoError) + || (error.error != QJsonParseError::NoError)) { + qCWarning(LOG_AW) << "Parse error" << error.errorString(); + return; + } + reply->deleteLater(); + + // convert to map + QVariantMap firstRelease = jsonDoc.toVariant().toList().first().toMap(); + QString version = firstRelease[QString("tag_name")].toString(); + version.remove(QString("V.")); + m_foundVersion = version; + qCInfo(LOG_AW) << "Update found version to" << m_foundVersion; + + // FIXME: possible there is a better way to check versions + int old_major = QString(VERSION).split(QChar('.')).at(0).toInt(); + int old_minor = QString(VERSION).split(QChar('.')).at(1).toInt(); + int old_patch = QString(VERSION).split(QChar('.')).at(2).toInt(); + int new_major = version.split(QChar('.')).at(0).toInt(); + int new_minor = version.split(QChar('.')).at(1).toInt(); + int new_patch = version.split(QChar('.')).at(2).toInt(); + if ((old_major < new_major) + || ((old_major == new_major) && (old_minor < new_minor)) + || ((old_major == new_major) && (old_minor == new_minor) + && (old_patch < new_patch))) + return showUpdates(version); + else if (showAnyway) + return showInfo(version); +} + + +// additional method which is used to show message box which does not block UI +QMessageBox * +AWUpdateHelper::genMessageBox(const QString title, const QString body, + const QMessageBox::StandardButtons buttons) +{ + qCDebug(LOG_AW) << "Construct message box with title" << title << "and body" + << body; + + QMessageBox *msgBox = new QMessageBox(nullptr); + msgBox->setAttribute(Qt::WA_DeleteOnClose); + msgBox->setModal(false); + msgBox->setWindowTitle(title); + msgBox->setText(body); + msgBox->setStandardButtons(buttons); + msgBox->setIcon(QMessageBox::Information); + + return msgBox; +} diff --git a/sources/awesome-widget/plugin/awupdatehelper.h b/sources/awesome-widget/plugin/awupdatehelper.h new file mode 100644 index 0000000..9c6a42d --- /dev/null +++ b/sources/awesome-widget/plugin/awupdatehelper.h @@ -0,0 +1,52 @@ +/*************************************************************************** + * This file is part of awesome-widgets * + * * + * awesome-widgets is free software: you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * awesome-widgets is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with awesome-widgets. If not, see http://www.gnu.org/licenses/ * + ***************************************************************************/ + + +#ifndef AWUPDATEHELPER_H +#define AWUPDATEHELPER_H + +#include +#include + + +class QNetworkReply; + +class AWUpdateHelper : public QObject +{ + Q_OBJECT + +public: + explicit AWUpdateHelper(QObject *parent = nullptr); + virtual ~AWUpdateHelper(); + void checkUpdates(const bool showAnyway = false); + bool checkVersion(); + +private slots: + void showInfo(const QString version); + void showUpdates(const QString version); + void userReplyOnUpdates(QAbstractButton *button); + void versionReplyRecieved(QNetworkReply *reply, const bool showAnyway); + +private: + QMessageBox *genMessageBox(const QString title, const QString body, + const QMessageBox::StandardButtons buttons); + QString m_foundVersion; + QString m_genericConfig; +}; + + +#endif /* AWUPDATEHELPER_H */ diff --git a/sources/changelog.cmake b/sources/changelog.cmake new file mode 100644 index 0000000..abc78e7 --- /dev/null +++ b/sources/changelog.cmake @@ -0,0 +1,5 @@ +exec_program( + "sed -n '1,/^Ver/ p' CHANGELOG | grep -v '^Ver' | tr '\n' '@'" + ${CMAKE_CURRENT_SOURCE_DIR}/.. + OUTPUT_VARIABLE PROJECT_CHANGELOG +) diff --git a/sources/version.h.in b/sources/version.h.in index b9fdfb6..31f8744 100644 --- a/sources/version.h.in +++ b/sources/version.h.in @@ -12,6 +12,7 @@ #define LICENSE "@PROJECT_LICENSE@" #define TRDPARTY_LICENSE "tasks,BSD,https://github.com/mhogomchungu/tasks;QReplyTimeout wrapper,no,http://codereview.stackexchange.com/questions/30031/qnetworkreply-network-reply-timeout-helper" #define SPECIAL_THANKS "Yahoo! Finance,https://finance.yahoo.com/;Yahoo! Weather,https://weather.yahoo.com/;JetBrains,https://www.jetbrains.com/" +#define CHANGELOG "@PROJECT_CHANGELOG@" // configuraion // graphical items api version