Skip to content

Commit

Permalink
Added Update Checker
Browse files Browse the repository at this point in the history
for release binaries.
  • Loading branch information
rodlie committed Dec 25, 2024
1 parent 168c7ce commit 18535ea
Show file tree
Hide file tree
Showing 6 changed files with 254 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/app/GUI/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ MainWindow::MainWindow(Document& document,
, mColorPickLabel(nullptr)
, mToolBarMainAct(nullptr)
, mToolBarColorAct(nullptr)
#ifdef PROJECT_OFFICIAL
, mUpdate(nullptr)
#endif
{
Q_ASSERT(!sInstance);
sInstance = this;
Expand Down Expand Up @@ -1728,6 +1731,10 @@ void MainWindow::readSettings(const QString &openProject)
[this,
openProject]() { openFile(openProject); });
} else { openWelcomeDialog(); }

#ifdef PROJECT_OFFICIAL
mUpdate = new Ui::UpdateChecker(this);
#endif
}

void MainWindow::writeSettings()
Expand Down
8 changes: 8 additions & 0 deletions src/app/GUI/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@
#include "widgets/uilayout.h"
#include "widgets/toolbar.h"

#ifdef PROJECT_OFFICIAL
#include "updater/updatechecker.h"
#endif

class VideoEncoder;
class RenderWidget;
class ActionButton;
Expand Down Expand Up @@ -403,6 +407,10 @@ class MainWindow : public QMainWindow
QAction *mToolBarMainAct;
QAction *mToolBarColorAct;

#ifdef PROJECT_OFFICIAL
Friction::Ui::UpdateChecker *mUpdate;
#endif

protected:
void keyPressEvent(QKeyEvent *event);
bool eventFilter(QObject *obj, QEvent *e);
Expand Down
2 changes: 2 additions & 0 deletions src/cmake/friction-common.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ find_package(
Multimedia
Qml
Xml
Network
#Svg
REQUIRED
)
Expand All @@ -106,6 +107,7 @@ set(QT_LIBRARIES
Qt${QT_VERSION_MAJOR}::Multimedia
Qt${QT_VERSION_MAJOR}::Qml
Qt${QT_VERSION_MAJOR}::Xml
Qt${QT_VERSION_MAJOR}::Network
#Qt${QT_VERSION_MAJOR}::Svg
)

Expand Down
2 changes: 2 additions & 0 deletions src/ui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ set(
optimalscrollarena/scrollwidget.cpp
optimalscrollarena/scrollwidgetvisiblepart.cpp
optimalscrollarena/singlewidget.cpp
updater/updatechecker.cpp
widgets/aboutwidget.cpp
widgets/actionbutton.cpp
widgets/alignwidget.cpp
Expand Down Expand Up @@ -136,6 +137,7 @@ set(
optimalscrollarena/scrollwidget.h
optimalscrollarena/scrollwidgetvisiblepart.h
optimalscrollarena/singlewidget.h
updater/updatechecker.h
widgets/aboutwidget.h
widgets/actionbutton.h
widgets/alignwidget.h
Expand Down
166 changes: 166 additions & 0 deletions src/ui/updater/updatechecker.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/*
#
# Friction - https://friction.graphics
#
# Copyright (c) Ole-André Rodlie and contributors
#
# This program 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.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
#
# See 'README.md' for more information.
#
*/

#include "updatechecker.h"
#include "appsupport.h"

#include <QXmlStreamReader>
#include <QMessageBox>
#include <QIcon>
#include <QPixmap>
#include <QPushButton>
#include <QDesktopServices>
#include <QDateTime>
#include <QTimer>

using namespace Friction::Ui;

UpdateChecker::UpdateChecker(QObject *parent)
: QObject{parent}
, mNet(nullptr)
{
mNet = new QNetworkAccessManager(this);
connect(mNet, &QNetworkAccessManager::finished,
this, &UpdateChecker::handleReply);

const bool doCheck = AppSupport::getSettings("updater", "check", true).toBool();
if (!doCheck) { return; }

QDateTime lastCheck = AppSupport::getSettings("updater",
"last",
QDateTime::currentDateTime()).toDateTime();
int interval = AppSupport::getSettings("updater", "interval", 7).toInt();
if (lastCheck.daysTo(QDateTime::currentDateTime()) >= interval) {
QTimer::singleShot(5000, this, [this]() { check(); });
}
}

void UpdateChecker::check()
{
const auto internalVersion = parseVersion(AppSupport::getAppVersion());
if (internalVersion.major == 0) { return; }

AppSupport::setSettings("updater", "last", QDateTime::currentDateTime());
mNet->get(QNetworkRequest(QUrl("http://friction.graphics/update.xml")));
}

bool UpdateChecker::hasNewVersion(const fVersion &from,
const fVersion &to)
{
if (to.major < from.major) { return false; }
if (to.minor < from.minor) { return false; }
if (to.patch < from.patch) { return false; }
if (to.micro < from.micro) { return false; }
return true;
}

const QString UpdateChecker::parseVersionXml(const QString &xml,
const bool &devel)
{
const QString branch = devel ? "devel" : "stable";
QXmlStreamReader r(xml);
while (r.readNextStartElement()) {
while (r.readNextStartElement()) {
if (r.qualifiedName().toString() == branch) { return r.readElementText(); }
else { r.readElementText(); }
}
}
return QString();
}

const UpdateChecker::fVersion UpdateChecker::parseVersion(const QString &version)
{
fVersion output{0, 0, 0, 0};
if (version.simplified().isEmpty()) { return output; }

QStringList versionList;
if (version.contains("-")) {
const auto list = version.simplified().split("-");
if (list.count() == 2) {
const QString custom = list.at(1).simplified();
const bool isBeta = custom.startsWith("beta.");
const bool isRc = custom.startsWith("rc.");
if (isBeta || isRc) {
double devel = custom.split(".").takeLast().toInt();
if (devel > 0) {
versionList = list.at(0).simplified().split(".");
versionList << QString::number(isBeta ? devel / 100 : devel / 10);
}
}
}
} else { versionList = version.simplified().split("."); }

if (versionList.count() >= 3) {
output.major = versionList.at(0).toInt();
output.minor = versionList.at(1).toInt();
output.patch = versionList.at(2).toInt();
if (versionList.count() >= 4) {
output.micro = versionList.at(3).toDouble();
}
}

return output;
}

void UpdateChecker::handleReply(QNetworkReply *reply)
{
if (!reply) { return; }
const QString xml = reply->readAll();
reply->deleteLater();

checkXml(xml);
}

void UpdateChecker::checkXml(const QString &xml)
{
if (xml.isEmpty()) { return; }

const QString appVersion = AppSupport::getAppVersion();
const QString xmlVersion = parseVersionXml(xml, (appVersion.contains("-beta.") ||
appVersion.contains("-rc.")));
const auto internalVersion = parseVersion(appVersion);
const auto updateVersion = parseVersion(xmlVersion);

if (!hasNewVersion(internalVersion,
updateVersion)) { return; }

QMessageBox box;
box.setWindowTitle(tr("Update available"));
box.setIconPixmap(QPixmap(QIcon::fromTheme(AppSupport::getAppID()).pixmap(64)));
box.setText(tr("<h3>Friction %1</h3>"
"<p>Friction %1 is now available for download. "
"See release notes for more information.</p>").arg(xmlVersion));
box.addButton(tr("Ignore"), QMessageBox::NoRole);
const auto never = box.addButton(tr("Disable"), QMessageBox::ResetRole);
const auto download = box.addButton(tr("Download"), QMessageBox::YesRole);
download->setFocus();

box.exec();

if (box.clickedButton() == download) {
QString url = QString("https://friction.graphics/releases/friction-%1.html").arg(QString(xmlVersion).replace(".", ""));
QDesktopServices::openUrl(QUrl::fromUserInput(url));
} else if (box.clickedButton() == never) {
AppSupport::setSettings("updater", "check", false);
}
}
69 changes: 69 additions & 0 deletions src/ui/updater/updatechecker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
#
# Friction - https://friction.graphics
#
# Copyright (c) Ole-André Rodlie and contributors
#
# This program 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.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
#
# See 'README.md' for more information.
#
*/

#ifndef FRICTION_UPDATE_CHECKER_H
#define FRICTION_UPDATE_CHECKER_H

#include "ui_global.h"

#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>

namespace Friction
{
namespace Ui
{
class UI_EXPORT UpdateChecker : public QObject
{
Q_OBJECT
public:
struct fVersion {
int major;
int minor;
int patch;
double micro;
};

explicit UpdateChecker(QObject *parent = nullptr);

void check();

private:
QNetworkAccessManager *mNet;

bool hasNewVersion(const fVersion &from,
const fVersion &to);

const QString parseVersionXml(const QString &xml,
const bool &devel = false);
const fVersion parseVersion(const QString &version);

void handleReply(QNetworkReply *reply);

void checkXml(const QString &xml);
};
}
}

#endif // FRICTION_UPDATE_CHECKER_H

0 comments on commit 18535ea

Please sign in to comment.