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