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.
This commit is contained in:
Evgenii Alekseev 2016-02-04 00:02:49 +07:00
parent 384097625c
commit 54e1545bb1
8 changed files with 270 additions and 100 deletions

View File

@ -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")

View File

@ -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;
}

View File

@ -21,19 +21,13 @@
#include <KNotifications/KNotification>
#include <QDesktopServices>
#include <QJsonDocument>
#include <QJsonParseError>
#include <QMessageBox>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QProcess>
#include <QProcessEnvironment>
#include <QStandardPaths>
#include <QUrl>
#include <fontdialog/fontdialog.h>
#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);
}

View File

@ -22,7 +22,7 @@
#include <QObject>
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;
};

View File

@ -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 <KI18n/KLocalizedString>
#include <QtConcurrent/QtConcurrent>
#include <QDesktopServices>
#include <QJsonDocument>
#include <QJsonParseError>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QSettings>
#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<QMessageBox *>(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;
}

View File

@ -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 <QMessageBox>
#include <QObject>
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 */

5
sources/changelog.cmake Normal file
View File

@ -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
)

View File

@ -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