Initial self update implementation
This commit is contained in:
@@ -12,7 +12,7 @@ qmake=$(wine) $(pwd)/Qt/5.11.1/mingw53_32/bin/qmake.exe
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
mkdir -p GitAddonsManager && cd GitAddonsManager && qmake-qt5 .. -spec linux-g++ && make
|
||||
mkdir -p GitAddonsManager && cd GitAddonsManager && qmake-qt5 .. -spec linux-g++ GAM_BUILD_NAME="Linux_x64" && make
|
||||
|
||||
cmake-3.12.0-rc3-win32-x86.msi:
|
||||
wget https://cmake.org/files/v3.12/cmake-3.12.0-rc3-win32-x86.msi
|
||||
@@ -75,7 +75,7 @@ libgit2-0.27.2/build/libgit2.dll: wine/drive_c/Program\ Files\ (x86)/CMake libgi
|
||||
$(wine) mingw32-make -C libgit2-0.27.2/build -j $(shell nproc)
|
||||
|
||||
build_win32/GitAddonsManager.exe: Qt libgit2-0.27.2/build/libgit2.dll
|
||||
mkdir -p build_win32 && cd build_win32 && $(qmake) $(qmake_opts) ../GitAddonsManager.pro GIT_DESCRIBE="$(shell git describe --tags)"
|
||||
mkdir -p build_win32 && cd build_win32 && $(qmake) $(qmake_opts) ../GitAddonsManager.pro GIT_DESCRIBE="$(shell git describe --tags)" GAM_BUILD_NAME="Win32"
|
||||
$(wine) mingw32-make -C build_win32
|
||||
|
||||
winbuild: build_win32/GitAddonsManager.exe
|
||||
|
||||
+74
@@ -20,13 +20,19 @@
|
||||
#include <QFutureWatcher>
|
||||
#include <QQuickStyle>
|
||||
#include <QQuickStyle>
|
||||
#include <QDesktopServices>
|
||||
#include "addon.h"
|
||||
#include <git2.h>
|
||||
#include <QDebug>
|
||||
#include <QtConcurrent>
|
||||
#include <type_traits>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QApplication>
|
||||
|
||||
Control *Control::m_instance = nullptr;
|
||||
QNetworkAccessManager nam;
|
||||
|
||||
Control::Control(QObject *parent) : QObject(parent),
|
||||
m_progress(0), m_total(0), m_status(Status::Ready), m_statusMessage(""), m_pool(new QThreadPool(this)),
|
||||
@@ -39,6 +45,7 @@ Control::Control(QObject *parent) : QObject(parent),
|
||||
connect(this, &Control::addonsPathChanged, this, &Control::scanForAddons);
|
||||
connect(this, &Control::addonsPathChanged, this, &Control::saveAddonsPath);
|
||||
delegate("Initializing libgit2...", [](){git_libgit2_init();},[this](){scanForAddons();});
|
||||
checkForUpdates();
|
||||
}
|
||||
|
||||
void Control::delegate(QString taskname, auto work, auto callback)
|
||||
@@ -147,6 +154,11 @@ QStringList Control::availableStyles() const
|
||||
return m_availableStyles;
|
||||
}
|
||||
|
||||
Control::UpdateStatus Control::updateStatus() const
|
||||
{
|
||||
return m_updateStatus;
|
||||
}
|
||||
|
||||
void Control::setAddons(QList<QObject *> addons)
|
||||
{
|
||||
if (m_addons == addons)
|
||||
@@ -326,3 +338,65 @@ void Control::setAvailableStyles(QStringList availableStyles)
|
||||
m_availableStyles = availableStyles;
|
||||
emit availableStylesChanged(m_availableStyles);
|
||||
}
|
||||
|
||||
void Control::checkForUpdates()
|
||||
{
|
||||
#ifdef GAM_BUILD_NAME
|
||||
QNetworkRequest req(QUrl(QString("https://gitlab.com/woblight/GitAddonsManager/-/jobs/artifacts/master/download?job=%1").arg(GAM_BUILD_NAME)));
|
||||
req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
auto reply = nam.head(req);
|
||||
setUpdateStatus(UpdateStatus::CheckingForUpdate);
|
||||
connect(reply, &QNetworkReply::finished,[this, reply](){
|
||||
QRegExp shaCapt(QString("GitAddonsManager_%1-(\\w{40})\\.zip").arg(GAM_BUILD_NAME));
|
||||
if (shaCapt.indexIn(reply->url().toString()) != -1) {
|
||||
if (!QString(GIT_DESCRIBE).endsWith(shaCapt.cap(1).chopped(33)))
|
||||
setUpdateStatus(UpdateStatus::UpdateAvailable);
|
||||
else setUpdateStatus(UpdateStatus::NoUpdate);
|
||||
};
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void Control::downloadUpdate()
|
||||
{
|
||||
#ifdef GAM_BUILD_NAME
|
||||
QFile *zip = new QFile("GitAddonsManager.zip");
|
||||
if (!zip->open(QFile::WriteOnly)) {
|
||||
setUpdateStatus(UpdateStatus::UpdateError);
|
||||
return;
|
||||
}
|
||||
|
||||
QNetworkRequest req(QUrl(QString("https://gitlab.com/woblight/GitAddonsManager/-/jobs/artifacts/master/download?job=%1").arg(GAM_BUILD_NAME)));
|
||||
req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
auto reply = nam.get(req);
|
||||
setUpdateStatus(UpdateStatus::DownloadingUpdate);
|
||||
connect(reply, &QNetworkReply::readyRead,[reply, zip]() {
|
||||
zip->write(reply->readAll());
|
||||
});
|
||||
connect(reply, &QNetworkReply::finished, [this, reply, zip]() {
|
||||
zip->close();
|
||||
delete zip;
|
||||
setUpdateStatus(reply->error() == QNetworkReply::NoError ? UpdateStatus::UpdateReady : UpdateStatus::UpdateError);
|
||||
reply->deleteLater();
|
||||
});
|
||||
connect(reply, &QNetworkReply::downloadProgress, [this](qint64 recieved, qint64 bytesTotal) {
|
||||
setTotal(bytesTotal);
|
||||
setProgress(recieved);
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void Control::executeUpdate()
|
||||
{
|
||||
QDesktopServices::openUrl(QDir().absolutePath());
|
||||
QApplication::exit(2);
|
||||
}
|
||||
|
||||
void Control::setUpdateStatus(Control::UpdateStatus updateStatus)
|
||||
{
|
||||
if (m_updateStatus == updateStatus)
|
||||
return;
|
||||
|
||||
m_updateStatus = updateStatus;
|
||||
emit updateStatusChanged(m_updateStatus);
|
||||
}
|
||||
|
||||
@@ -63,6 +63,16 @@ public:
|
||||
Q_ENUM(MinimizeToTray)
|
||||
Q_PROPERTY(MinimizeToTray minimizeToTray READ minimizeToTray WRITE setMinimizeToTray NOTIFY minimizeToTrayChanged)
|
||||
|
||||
enum class UpdateStatus {
|
||||
UpdateError = -1,
|
||||
NoUpdate,
|
||||
UpdateAvailable,
|
||||
DownloadingUpdate,
|
||||
UpdateReady,
|
||||
CheckingForUpdate
|
||||
};
|
||||
Q_ENUM(UpdateStatus)
|
||||
Q_PROPERTY(UpdateStatus updateStatus READ updateStatus WRITE setUpdateStatus NOTIFY updateStatusChanged)
|
||||
QList<QObject *> addons() const;
|
||||
|
||||
QString addonsPath() const;
|
||||
@@ -85,6 +95,8 @@ public:
|
||||
|
||||
QStringList availableStyles() const;
|
||||
|
||||
UpdateStatus updateStatus() const;
|
||||
|
||||
private:
|
||||
static Control *m_instance;
|
||||
explicit Control(QObject *parent = nullptr);
|
||||
@@ -110,6 +122,8 @@ private:
|
||||
|
||||
QStringList m_availableStyles;
|
||||
|
||||
UpdateStatus m_updateStatus = UpdateStatus::NoUpdate;
|
||||
|
||||
signals:
|
||||
void addonsChanged(QList<QObject *> addons);
|
||||
|
||||
@@ -131,6 +145,8 @@ signals:
|
||||
|
||||
void availableStylesChanged(QStringList availableStyles);
|
||||
|
||||
void updateStatusChanged(UpdateStatus updateStatus);
|
||||
|
||||
public slots:
|
||||
void setAddons(QList<QObject *> addons);
|
||||
void setAddonsPath(QString addonsPath);
|
||||
@@ -145,6 +161,10 @@ public slots:
|
||||
void setMinimizeToTray(MinimizeToTray minimizeToTray);
|
||||
void setStyle(QString style);
|
||||
void setAvailableStyles(QStringList availableStyles);
|
||||
void checkForUpdates();
|
||||
void downloadUpdate();
|
||||
void executeUpdate();
|
||||
void setUpdateStatus(UpdateStatus updateStatus);
|
||||
};
|
||||
Q_DECLARE_METATYPE(Control::MinimizeToTray)
|
||||
|
||||
|
||||
@@ -149,6 +149,37 @@ ApplicationWindow {
|
||||
selectByMouse: true
|
||||
onFocusChanged: if (focus) selectAll()
|
||||
}
|
||||
Button {
|
||||
id: updateButton
|
||||
contentItem: RowLayout {
|
||||
BusyIndicator {
|
||||
implicitHeight: parent.height
|
||||
implicitWidth: implicitHeight
|
||||
running: !updateButton.enabled
|
||||
visible: running
|
||||
}
|
||||
Label {
|
||||
text:
|
||||
Engine.updateStatus === Engine.NoUpdate ?
|
||||
qsTr("Check for update") :
|
||||
Engine.updateStatus === Engine.CheckingForUpdate ?
|
||||
qsTr("Checking for update...") :
|
||||
Engine.updateStatus === Engine.UpdateAvailable ?
|
||||
qsTr("Download update") :
|
||||
Engine.updateStatus === Engine.DownloadingUpdate ?
|
||||
qsTr("Downloading update...") :
|
||||
Engine.updateStatus === Engine.UpdateReady ?
|
||||
qsTr("Apply update") : qsTr("error")
|
||||
}
|
||||
}
|
||||
onClicked: Engine.updateStatus === Engine.NoUpdate ?
|
||||
Engine.checkForUpdates() :
|
||||
Engine.updateStatus === Engine.UpdateAvailable ?
|
||||
Engine.downloadUpdate() :
|
||||
Engine.updateStatus === Engine.UpdateReady ?
|
||||
Engine.executeUpdate() : {}
|
||||
enabled: Engine.updateStatus === Engine.NoUpdate || Engine.updateStatus === Engine.UpdateAvailable || Engine.updateStatus === Engine.UpdateReady
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -315,4 +346,47 @@ ApplicationWindow {
|
||||
modal: true
|
||||
standardButtons: Dialog.Close
|
||||
}
|
||||
Dialog {
|
||||
x: (parent.width - width) / 2
|
||||
y: (parent.height - height) / 2
|
||||
visible: Engine.updateStatus === Engine.UpdateAvailable || Engine.updateStatus === Engine.DownloadingUpdate || Engine.updateStatus === Engine.UpdateReady
|
||||
id: updateDialog
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
id: updateMessage
|
||||
text: Engine.updateStatus === Engine.UpdateAvailable ?
|
||||
qsTr("<h1>A newer version of GitAddonsManager is available</h1>") :
|
||||
Engine.updateStatus === Engine.DownloadingUpdate ?
|
||||
qsTr("Downloading update...") : qsTr("Download finished.<br/>To complete the update click \"Close & Update\", then extract GitAddonsManager.zip and replace old files.")
|
||||
textFormat: Text.RichText
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
ProgressBar {
|
||||
Layout.fillWidth: true
|
||||
id: updateProgress
|
||||
to: Engine.total
|
||||
value: Engine.progress
|
||||
indeterminate: to == -1
|
||||
visible: Engine.updateStatus === Engine.DownloadingUpdate
|
||||
}
|
||||
}
|
||||
|
||||
modal: true
|
||||
footer: DialogButtonBox {
|
||||
Button {
|
||||
visible: Engine.updateStatus === Engine.UpdateAvailable
|
||||
text: qsTr("Download")
|
||||
onClicked: Engine.downloadUpdate()
|
||||
}
|
||||
Button {
|
||||
visible: Engine.updateStatus === Engine.UpdateReady
|
||||
text: qsTr("Close && Update")
|
||||
onClicked: Engine.executeUpdate()
|
||||
}
|
||||
}
|
||||
closePolicy: Engine.updateStatus !== Engine.DownloadingUpdate ? Dialog.CloseOnPressOutside | Dialog.CloseOnEscape : Dialog.NoAutoClose
|
||||
standardButtons: Engine.updateStatus !== Engine.DownloadingUpdate ? Dialog.Close : Dialog.NoButton
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user