mirror of
https://github.com/rizinorg/cutter.git
synced 2025-02-01 09:07:26 +00:00
Auto update check (#1235)
* init commit * bug fix * call slot of null object bug fix * delete extra disconnect() func * change api and add doc * run astyle * some improvements * memory leak fix * add check on start checkbox * add checkbox to about page * serve version check reply using lambda instead of slot * fix grammar mistakes * more docs * save some lines * change button text * astyle * change message text * dont use QApplication pointer as a parent for network manager * proper deletion of QNetworkReply* * VersionChecker -> UpdateWorker * windows dll hack * after rebase fix * some improvements * better determination of arch * more docs * improvements * add UpdateWorker::showUpdateDialog * remove odd condition * more improvements * fix windows bug * make dialog non-blocking * change text in download progress dialog * bug fix * remove debug conditions * change docs format
This commit is contained in:
parent
d4a6b031ff
commit
3fed97ad86
@ -312,7 +312,8 @@ SOURCES += \
|
|||||||
common/PythonManager.cpp \
|
common/PythonManager.cpp \
|
||||||
plugins/PluginManager.cpp \
|
plugins/PluginManager.cpp \
|
||||||
common/BasicBlockHighlighter.cpp \
|
common/BasicBlockHighlighter.cpp \
|
||||||
dialogs/LinkTypeDialog.cpp
|
dialogs/LinkTypeDialog.cpp \
|
||||||
|
common/UpdateWorker.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
core/Cutter.h \
|
core/Cutter.h \
|
||||||
@ -429,6 +430,7 @@ HEADERS += \
|
|||||||
common/PythonManager.h \
|
common/PythonManager.h \
|
||||||
plugins/PluginManager.h \
|
plugins/PluginManager.h \
|
||||||
common/BasicBlockHighlighter.h \
|
common/BasicBlockHighlighter.h \
|
||||||
|
common/UpdateWorker.h \
|
||||||
dialogs/LinkTypeDialog.h
|
dialogs/LinkTypeDialog.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
|
@ -23,6 +23,10 @@
|
|||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include <QtNetwork/QtNetwork>
|
||||||
|
#endif // Q_OS_WIN
|
||||||
|
|
||||||
CutterApplication::CutterApplication(int &argc, char **argv) : QApplication(argc, argv)
|
CutterApplication::CutterApplication(int &argc, char **argv) : QApplication(argc, argv)
|
||||||
{
|
{
|
||||||
// Setup application information
|
// Setup application information
|
||||||
@ -32,6 +36,13 @@ CutterApplication::CutterApplication(int &argc, char **argv) : QApplication(argc
|
|||||||
setLayoutDirection(Qt::LeftToRight);
|
setLayoutDirection(Qt::LeftToRight);
|
||||||
|
|
||||||
// WARN!!! Put initialization code below this line. Code above this line is mandatory to be run First
|
// WARN!!! Put initialization code below this line. Code above this line is mandatory to be run First
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
// Hack to force Cutter load internet connection related DLL's
|
||||||
|
QSslSocket s;
|
||||||
|
s.sslConfiguration();
|
||||||
|
#endif // Q_OS_WIN
|
||||||
|
|
||||||
// Load translations
|
// Load translations
|
||||||
if (!loadTranslations()) {
|
if (!loadTranslations()) {
|
||||||
qWarning() << "Cannot load translations";
|
qWarning() << "Cannot load translations";
|
||||||
|
14
src/Main.cpp
14
src/Main.cpp
@ -1,6 +1,8 @@
|
|||||||
|
|
||||||
#include "CutterApplication.h"
|
#include "CutterApplication.h"
|
||||||
#include "core/MainWindow.h"
|
#include "core/MainWindow.h"
|
||||||
|
#include "common/UpdateWorker.h"
|
||||||
|
#include "CutterConfig.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Migrate Settings used before Cutter 1.8
|
* @brief Migrate Settings used before Cutter 1.8
|
||||||
@ -34,6 +36,18 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
CutterApplication a(argc, argv);
|
CutterApplication a(argc, argv);
|
||||||
|
|
||||||
|
if (Config()->getAutoUpdateEnabled()) {
|
||||||
|
UpdateWorker *updateWorker = new UpdateWorker;
|
||||||
|
QObject::connect(updateWorker, &UpdateWorker::checkComplete,
|
||||||
|
[=](const QString & version, const QString & error) {
|
||||||
|
if (error == "" && version != CUTTER_VERSION_FULL) {
|
||||||
|
updateWorker->showUpdateDialog(true);
|
||||||
|
}
|
||||||
|
updateWorker->deleteLater();
|
||||||
|
});
|
||||||
|
updateWorker->checkCurrentVersion(7000);
|
||||||
|
}
|
||||||
|
|
||||||
int ret = a.exec();
|
int ret = a.exec();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -136,6 +136,16 @@ void Configuration::resetAll()
|
|||||||
emit fontsUpdated();
|
emit fontsUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Configuration::getAutoUpdateEnabled() const
|
||||||
|
{
|
||||||
|
return s.value("autoUpdateEnabled", false).toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Configuration::setAutoUpdateEnabled(bool au)
|
||||||
|
{
|
||||||
|
s.setValue("autoUpdateEnabled", au);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get the current Locale set in Cutter's user configuration
|
* @brief get the current Locale set in Cutter's user configuration
|
||||||
* @return a QLocale object describes user's current locale
|
* @return a QLocale object describes user's current locale
|
||||||
|
@ -46,6 +46,10 @@ public:
|
|||||||
|
|
||||||
void resetAll();
|
void resetAll();
|
||||||
|
|
||||||
|
// Auto update
|
||||||
|
bool getAutoUpdateEnabled() const;
|
||||||
|
void setAutoUpdateEnabled(bool au);
|
||||||
|
|
||||||
// Languages
|
// Languages
|
||||||
QLocale getCurrLocale() const;
|
QLocale getCurrLocale() const;
|
||||||
void setLocale(const QLocale &l);
|
void setLocale(const QLocale &l);
|
||||||
|
211
src/common/UpdateWorker.cpp
Normal file
211
src/common/UpdateWorker.cpp
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
#include "UpdateWorker.h"
|
||||||
|
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QEventLoop>
|
||||||
|
#include <QDataStream>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QtNetwork/QNetworkReply>
|
||||||
|
#include <QtNetwork/QNetworkRequest>
|
||||||
|
|
||||||
|
#include <QProgressDialog>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include "common/Configuration.h"
|
||||||
|
#include "CutterConfig.h"
|
||||||
|
|
||||||
|
UpdateWorker::UpdateWorker(QObject *parent) :
|
||||||
|
QObject(parent), latestVersion(""), pending(false)
|
||||||
|
{
|
||||||
|
connect(&t, &QTimer::timeout, [this]() {
|
||||||
|
if (pending) {
|
||||||
|
disconnect(checkReply, nullptr, this, nullptr);
|
||||||
|
checkReply->close();
|
||||||
|
checkReply->deleteLater();
|
||||||
|
emit checkComplete("", tr("Time limit exceeded during version check. Please check your "
|
||||||
|
"internet connection and try again."));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateWorker::checkCurrentVersion(time_t timeoutMs)
|
||||||
|
{
|
||||||
|
QUrl url("https://api.github.com/repos/radareorg/cutter/releases/latest");
|
||||||
|
QNetworkRequest request;
|
||||||
|
request.setUrl(url);
|
||||||
|
|
||||||
|
t.setInterval(timeoutMs);
|
||||||
|
t.setSingleShot(true);
|
||||||
|
t.start();
|
||||||
|
|
||||||
|
checkReply = nm.get(request);
|
||||||
|
connect(checkReply, &QNetworkReply::finished,
|
||||||
|
this, &UpdateWorker::serveVersionCheckReply);
|
||||||
|
pending = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateWorker::download(QString filename, QString version)
|
||||||
|
{
|
||||||
|
downloadFile.setFileName(filename);
|
||||||
|
downloadFile.open(QIODevice::WriteOnly);
|
||||||
|
|
||||||
|
QNetworkRequest request;
|
||||||
|
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||||
|
QUrl url(QString("https://github.com/radareorg/cutter/releases/"
|
||||||
|
"download/v%1/%2").arg(version).arg(getRepositoryFileName()));
|
||||||
|
request.setUrl(url);
|
||||||
|
|
||||||
|
downloadReply = nm.get(request);
|
||||||
|
connect(downloadReply, &QNetworkReply::downloadProgress,
|
||||||
|
this, &UpdateWorker::process);
|
||||||
|
connect(downloadReply, &QNetworkReply::finished,
|
||||||
|
this, &UpdateWorker::serveDownloadFinish);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateWorker::showUpdateDialog(bool showDontCheckForUpdatesButton)
|
||||||
|
{
|
||||||
|
QMessageBox mb;
|
||||||
|
mb.setWindowTitle(tr("Version control"));
|
||||||
|
mb.setText(tr("There is an update available for Cutter.<br/>")
|
||||||
|
+ "<b>" + tr("Current version:") + "</b> " CUTTER_VERSION_FULL "<br/>"
|
||||||
|
+ "<b>" + tr("Latest version:") + "</b> " + latestVersion + "<br/><br/>"
|
||||||
|
+ tr("For update, please check the link:<br/>")
|
||||||
|
+ QString("<a href=\"https://github.com/radareorg/cutter/releases/tag/v%1\">"
|
||||||
|
"https://github.com/radareorg/cutter/releases/tag/v%1</a><br/>").arg(latestVersion)
|
||||||
|
+ tr("or click \"Download\" to download latest version of Cutter."));
|
||||||
|
if (showDontCheckForUpdatesButton) {
|
||||||
|
mb.setStandardButtons(QMessageBox::Save | QMessageBox::Reset | QMessageBox::Ok);
|
||||||
|
mb.button(QMessageBox::Reset)->setText(tr("Don't check for updates"));
|
||||||
|
} else {
|
||||||
|
mb.setStandardButtons(QMessageBox::Save | QMessageBox::Ok);
|
||||||
|
}
|
||||||
|
mb.button(QMessageBox::Save)->setText(tr("Download"));
|
||||||
|
mb.setDefaultButton(QMessageBox::Ok);
|
||||||
|
int ret = mb.exec();
|
||||||
|
if (ret == QMessageBox::Reset) {
|
||||||
|
Config()->setAutoUpdateEnabled(false);
|
||||||
|
} else if (ret == QMessageBox::Save) {
|
||||||
|
QString fullFileName =
|
||||||
|
QFileDialog::getSaveFileName(nullptr,
|
||||||
|
tr("Choose directory for downloading"),
|
||||||
|
QStandardPaths::writableLocation(QStandardPaths::HomeLocation) +
|
||||||
|
QDir::separator() + getRepositoryFileName(),
|
||||||
|
QString("%1 (*.%1)").arg(getRepositeryExt()));
|
||||||
|
if (fullFileName != "") {
|
||||||
|
QProgressDialog progressDial(tr("Downloading update..."),
|
||||||
|
tr("Cancel"),
|
||||||
|
0, 100);
|
||||||
|
connect(this, &UpdateWorker::downloadProcess,
|
||||||
|
[&progressDial](size_t curr, size_t total) {
|
||||||
|
progressDial.setValue(100.0f * curr / total);
|
||||||
|
});
|
||||||
|
connect(&progressDial, &QProgressDialog::canceled,
|
||||||
|
this, &UpdateWorker::abortDownload);
|
||||||
|
connect(this, &UpdateWorker::downloadFinished,
|
||||||
|
&progressDial, &QProgressDialog::cancel);
|
||||||
|
connect(this, &UpdateWorker::downloadFinished,
|
||||||
|
[](QString filePath){
|
||||||
|
QMessageBox info(QMessageBox::Information,
|
||||||
|
tr("Download finished!"),
|
||||||
|
tr("Latest version of Cutter was succesfully downloaded!"),
|
||||||
|
QMessageBox::Yes | QMessageBox::Open | QMessageBox::Ok,
|
||||||
|
nullptr);
|
||||||
|
info.button(QMessageBox::Open)->setText(tr("Open file"));
|
||||||
|
info.button(QMessageBox::Yes)->setText(tr("Open download folder"));
|
||||||
|
int r = info.exec();
|
||||||
|
if (r == QMessageBox::Open) {
|
||||||
|
QDesktopServices::openUrl(filePath);
|
||||||
|
} else if (r == QMessageBox::Yes) {
|
||||||
|
auto path = filePath.split('/');
|
||||||
|
path.removeLast();
|
||||||
|
QDesktopServices::openUrl(path.join('/'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
download(fullFileName, latestVersion);
|
||||||
|
// Calling show() before exec() is only way make dialog non-modal
|
||||||
|
// it seems wierd, but it works
|
||||||
|
progressDial.show();
|
||||||
|
progressDial.exec();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateWorker::abortDownload()
|
||||||
|
{
|
||||||
|
disconnect(downloadReply, &QNetworkReply::finished,
|
||||||
|
this, &UpdateWorker::serveDownloadFinish);
|
||||||
|
disconnect(downloadReply, &QNetworkReply::downloadProgress,
|
||||||
|
this, &UpdateWorker::process);
|
||||||
|
downloadReply->close();
|
||||||
|
downloadReply->deleteLater();
|
||||||
|
downloadFile.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateWorker::serveVersionCheckReply()
|
||||||
|
{
|
||||||
|
pending = false;
|
||||||
|
QString versionReply = "";
|
||||||
|
QString errStr = "";
|
||||||
|
if (checkReply->error()) {
|
||||||
|
errStr = checkReply->errorString();
|
||||||
|
} else {
|
||||||
|
versionReply = QJsonDocument::fromJson(checkReply->readAll()).object().value("tag_name").toString();
|
||||||
|
versionReply.remove('v');
|
||||||
|
}
|
||||||
|
latestVersion = versionReply;
|
||||||
|
checkReply->close();
|
||||||
|
checkReply->deleteLater();
|
||||||
|
emit checkComplete(versionReply, errStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateWorker::serveDownloadFinish()
|
||||||
|
{
|
||||||
|
downloadReply->close();
|
||||||
|
downloadReply->deleteLater();
|
||||||
|
if (downloadReply->error()) {
|
||||||
|
emit downloadError(downloadReply->errorString());
|
||||||
|
} else {
|
||||||
|
emit downloadFinished(downloadFile.fileName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateWorker::process(size_t bytesReceived, size_t bytesTotal)
|
||||||
|
{
|
||||||
|
downloadFile.write(downloadReply->readAll());
|
||||||
|
emit downloadProcess(bytesReceived, bytesTotal);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString UpdateWorker::getRepositeryExt() const
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
return "AppImage";
|
||||||
|
#elif defined (Q_OS_WIN64) || defined (Q_OS_WIN32)
|
||||||
|
return "zip";
|
||||||
|
#elif defined (Q_OS_MACOS)
|
||||||
|
return "dmg";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
QString UpdateWorker::getRepositoryFileName() const
|
||||||
|
{
|
||||||
|
QString downloadFileName;
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
downloadFileName = "Cutter-v%1-x%2.Linux.AppImage";
|
||||||
|
#elif defined (Q_OS_WIN64) || defined (Q_OS_WIN32)
|
||||||
|
downloadFileName = "Cutter-v%1-x%2.Windows.zip";
|
||||||
|
#elif defined (Q_OS_MACOS)
|
||||||
|
downloadFileName = "Cutter-v%1-x%2.macOS.dmg";
|
||||||
|
#endif
|
||||||
|
downloadFileName = downloadFileName
|
||||||
|
.arg(latestVersion)
|
||||||
|
.arg(QSysInfo::buildAbi().split('-').at(2).contains("64")
|
||||||
|
? "64"
|
||||||
|
: "32");
|
||||||
|
|
||||||
|
return downloadFileName;
|
||||||
|
}
|
123
src/common/UpdateWorker.h
Normal file
123
src/common/UpdateWorker.h
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
#ifndef UPDATEWORKER_H
|
||||||
|
#define UPDATEWORKER_H
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QtNetwork/QNetworkAccessManager>
|
||||||
|
|
||||||
|
class QNetworkReply;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class UpdateWorker
|
||||||
|
* @brief The UpdateWorker class is a class providing API to check for current Cutter version
|
||||||
|
* and download specific version of one.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class UpdateWorker : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit UpdateWorker(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn void UpdateWorker::checkCurrentVersion(time_t timeoutMs)
|
||||||
|
*
|
||||||
|
* Sends request to determine current version of Cutter.
|
||||||
|
* If there is no response in @a timeoutMs milliseconds, emits
|
||||||
|
* @fn UpdateWorker::checkComplete(const QString& currVerson, const QString& errorMsg)
|
||||||
|
* with timeout error message.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @sa checkComplete(const QString& verson, const QString& errorMsg)
|
||||||
|
*/
|
||||||
|
|
||||||
|
void checkCurrentVersion(time_t timeoutMs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn void UpdateWorker::download(QDir downloadPath, QString version)
|
||||||
|
*
|
||||||
|
* @brief Downloads provided @a version of Cutter into @a downloadDir.
|
||||||
|
*
|
||||||
|
* @sa downloadProcess(size_t bytesReceived, size_t bytesTotal)
|
||||||
|
*/
|
||||||
|
void download(QString filename, QString version);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn void UpdateWorker::showUpdateDialog()
|
||||||
|
*
|
||||||
|
* Shows dialog that allows user to either download latest version of Cutter from website
|
||||||
|
* or download it by clicking on a button. This dialog also has "Don't check for updates"
|
||||||
|
* button which disables on-start update checks if @a showDontCheckForUpdatesButton is true.
|
||||||
|
*
|
||||||
|
* @sa downloadProcess(size_t bytesReceived, size_t bytesTotal)
|
||||||
|
*/
|
||||||
|
void showUpdateDialog(bool showDontCheckForUpdatesButton);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
/**
|
||||||
|
* @fn void UpdateWorker::abortDownload()
|
||||||
|
*
|
||||||
|
* @brief Stops current process of downloading.
|
||||||
|
*
|
||||||
|
* @note UpdateWorker::downloadFinished(QString filename) is not send after this function.
|
||||||
|
*
|
||||||
|
* @sa download(QDir downloadDir, QString version)
|
||||||
|
*/
|
||||||
|
void abortDownload();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
/**
|
||||||
|
* @fn UpdateWorker::checkComplete(const QString& verson, const QString& errorMsg)
|
||||||
|
*
|
||||||
|
* The signal is emitted when check has been done with an empty @a errorMsg string.
|
||||||
|
* In case of an error @a currVerson is empty and @a errorMsg contains description
|
||||||
|
* of error.
|
||||||
|
*/
|
||||||
|
void checkComplete(const QString &currVerson, const QString &errorMsg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn UpdateWorker::downloadProcess(size_t bytesReceived, size_t bytesTotal)
|
||||||
|
*
|
||||||
|
* The signal is emitted each time when some amount of bytes was downloaded.
|
||||||
|
* May be used as indicator of download progress.
|
||||||
|
*/
|
||||||
|
void downloadProcess(size_t bytesReceived, size_t bytesTotal);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn UpdateWorker::downloadFinished(QString filename)
|
||||||
|
*
|
||||||
|
* @brief The signal is emitted as soon as downloading completes.
|
||||||
|
*/
|
||||||
|
void downloadFinished(QString filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn UpdateWorker::downloadError(QString errorStr)
|
||||||
|
*
|
||||||
|
* @brief The signal is emitted when error occures during download.
|
||||||
|
*/
|
||||||
|
void downloadError(QString errorStr);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void serveVersionCheckReply();
|
||||||
|
|
||||||
|
void serveDownloadFinish();
|
||||||
|
|
||||||
|
void process(size_t bytesReceived, size_t bytesTotal);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString getRepositeryExt() const;
|
||||||
|
QString getRepositoryFileName() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QNetworkAccessManager nm;
|
||||||
|
QString latestVersion;
|
||||||
|
QTimer t;
|
||||||
|
bool pending;
|
||||||
|
QFile downloadFile;
|
||||||
|
QNetworkReply *downloadReply;
|
||||||
|
QNetworkReply *checkReply;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // UPDATEWORKER_H
|
@ -8,9 +8,11 @@
|
|||||||
|
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QEventLoop>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QProgressBar>
|
#include <QProgressBar>
|
||||||
#include <QProgressDialog>
|
#include <QProgressDialog>
|
||||||
|
#include <UpdateWorker.h>
|
||||||
#include <QtNetwork/QNetworkRequest>
|
#include <QtNetwork/QNetworkRequest>
|
||||||
#include <QtNetwork/QNetworkAccessManager>
|
#include <QtNetwork/QNetworkAccessManager>
|
||||||
|
|
||||||
@ -48,6 +50,9 @@ AboutDialog::AboutDialog(QWidget *parent) :
|
|||||||
"xarkes, thestr4ng3r, ballessay<br/>"
|
"xarkes, thestr4ng3r, ballessay<br/>"
|
||||||
"Based on work by Hugo Teso <hugo.teso@gmail.org> (originally Iaito).");
|
"Based on work by Hugo Teso <hugo.teso@gmail.org> (originally Iaito).");
|
||||||
ui->label->setText(aboutString);
|
ui->label->setText(aboutString);
|
||||||
|
|
||||||
|
QSignalBlocker s(ui->updatesCheckBox);
|
||||||
|
ui->updatesCheckBox->setChecked(Config()->getAutoUpdateEnabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
AboutDialog::~AboutDialog() {}
|
AboutDialog::~AboutDialog() {}
|
||||||
@ -75,9 +80,7 @@ void AboutDialog::on_showPluginsButton_clicked()
|
|||||||
|
|
||||||
void AboutDialog::on_checkForUpdatesButton_clicked()
|
void AboutDialog::on_checkForUpdatesButton_clicked()
|
||||||
{
|
{
|
||||||
QUrl url("https://api.github.com/repos/radareorg/cutter/releases/latest");
|
UpdateWorker updateWorker;
|
||||||
QNetworkRequest request;
|
|
||||||
request.setUrl(url);
|
|
||||||
|
|
||||||
QProgressDialog waitDialog;
|
QProgressDialog waitDialog;
|
||||||
QProgressBar *bar = new QProgressBar(&waitDialog);
|
QProgressBar *bar = new QProgressBar(&waitDialog);
|
||||||
@ -86,56 +89,25 @@ void AboutDialog::on_checkForUpdatesButton_clicked()
|
|||||||
waitDialog.setBar(bar);
|
waitDialog.setBar(bar);
|
||||||
waitDialog.setLabel(new QLabel(tr("Checking for updates..."), &waitDialog));
|
waitDialog.setLabel(new QLabel(tr("Checking for updates..."), &waitDialog));
|
||||||
|
|
||||||
QNetworkAccessManager nm;
|
connect(&updateWorker, &UpdateWorker::checkComplete, &waitDialog, &QProgressDialog::cancel);
|
||||||
|
connect(&updateWorker, &UpdateWorker::checkComplete,
|
||||||
QTimer timeoutTimer;
|
[&updateWorker](const QString & version, const QString & error) {
|
||||||
timeoutTimer.setSingleShot(true);
|
if (error != "") {
|
||||||
timeoutTimer.setInterval(7000);
|
QMessageBox::critical(nullptr, tr("Error!"), error);
|
||||||
|
} else {
|
||||||
connect(&nm, &QNetworkAccessManager::finished, &timeoutTimer, &QTimer::stop);
|
if (version == CUTTER_VERSION_FULL) {
|
||||||
connect(&nm, &QNetworkAccessManager::finished, &waitDialog, &QProgressDialog::cancel);
|
QMessageBox::information(nullptr, tr("Version control"), tr("Cutter is up to date!"));
|
||||||
connect(&nm, &QNetworkAccessManager::finished, this, &AboutDialog::serveVersionCheckReply);
|
} else {
|
||||||
|
updateWorker.showUpdateDialog(false);
|
||||||
QNetworkReply *reply = nm.get(request);
|
}
|
||||||
timeoutTimer.start();
|
}
|
||||||
|
|
||||||
connect(&timeoutTimer, &QTimer::timeout, []() {
|
|
||||||
QMessageBox mb;
|
|
||||||
mb.setIcon(QMessageBox::Critical);
|
|
||||||
mb.setStandardButtons(QMessageBox::Ok);
|
|
||||||
mb.setWindowTitle(tr("Timeout error!"));
|
|
||||||
mb.setText(tr("Please check your internet connection and try again."));
|
|
||||||
mb.exec();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
updateWorker.checkCurrentVersion(7000);
|
||||||
waitDialog.exec();
|
waitDialog.exec();
|
||||||
delete reply;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AboutDialog::serveVersionCheckReply(QNetworkReply *reply)
|
void AboutDialog::on_updatesCheckBox_stateChanged(int state)
|
||||||
{
|
{
|
||||||
QString currVersion = "";
|
Config()->setAutoUpdateEnabled(!Config()->getAutoUpdateEnabled());
|
||||||
QMessageBox mb;
|
|
||||||
mb.setStandardButtons(QMessageBox::Ok);
|
|
||||||
if (reply->error()) {
|
|
||||||
mb.setIcon(QMessageBox::Critical);
|
|
||||||
mb.setWindowTitle(tr("Error!"));
|
|
||||||
mb.setText(reply->errorString());
|
|
||||||
} else {
|
|
||||||
currVersion = QJsonDocument::fromJson(reply->readAll()).object().value("tag_name").toString();
|
|
||||||
currVersion.remove('v');
|
|
||||||
|
|
||||||
mb.setWindowTitle(tr("Version control"));
|
|
||||||
mb.setIcon(QMessageBox::Information);
|
|
||||||
if (currVersion == CUTTER_VERSION_FULL) {
|
|
||||||
mb.setText(tr("You have latest version and no need to update!"));
|
|
||||||
} else {
|
|
||||||
mb.setText("<b>" + tr("Current version:") + "</b> " CUTTER_VERSION_FULL "<br/>"
|
|
||||||
+ "<b>" + tr("Latest version:") + "</b> " + currVersion + "<br/><br/>"
|
|
||||||
+ tr("For update, please check the link:")
|
|
||||||
+ "<a href=\"https://github.com/radareorg/cutter/releases\">"
|
|
||||||
+ "https://github.com/radareorg/cutter/releases</a>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mb.exec();
|
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,20 @@ private slots:
|
|||||||
void on_buttonBox_rejected();
|
void on_buttonBox_rejected();
|
||||||
void on_showVersionButton_clicked();
|
void on_showVersionButton_clicked();
|
||||||
void on_showPluginsButton_clicked();
|
void on_showPluginsButton_clicked();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn AboutDialog::on_checkForUpdatesButton_clicked()
|
||||||
|
*
|
||||||
|
* @brief Initiates process of checking for updates.
|
||||||
|
*/
|
||||||
void on_checkForUpdatesButton_clicked();
|
void on_checkForUpdatesButton_clicked();
|
||||||
void serveVersionCheckReply(QNetworkReply *reply);
|
|
||||||
|
/**
|
||||||
|
* @fn AboutDialog::on_updatesCheckBox_stateChanged(int state)
|
||||||
|
*
|
||||||
|
* @brief Changes value of autoUpdateEnabled option in settings.
|
||||||
|
*/
|
||||||
|
void on_updatesCheckBox_stateChanged(int state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<Ui::AboutDialog> ui;
|
std::unique_ptr<Ui::AboutDialog> ui;
|
||||||
|
@ -76,6 +76,19 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="updatesCheckBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Check for updates on start</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -20,8 +20,9 @@ WelcomeDialog::WelcomeDialog(QWidget *parent) :
|
|||||||
ui->logoSvgWidget->load(Config()->getLogoFile());
|
ui->logoSvgWidget->load(Config()->getLogoFile());
|
||||||
ui->versionLabel->setText("<font color='#a4a9b2'>" + tr("Version ") + CUTTER_VERSION_FULL + "</font>");
|
ui->versionLabel->setText("<font color='#a4a9b2'>" + tr("Version ") + CUTTER_VERSION_FULL + "</font>");
|
||||||
ui->themeComboBox->setCurrentIndex(Config()->getTheme());
|
ui->themeComboBox->setCurrentIndex(Config()->getTheme());
|
||||||
ui->themeComboBox->setFixedWidth(200);
|
|
||||||
ui->themeComboBox->view()->setFixedWidth(200);
|
QSignalBlocker s(ui->updatesCheckBox);
|
||||||
|
ui->updatesCheckBox->setChecked(Config()->getAutoUpdateEnabled());
|
||||||
|
|
||||||
QStringList langs = Config()->getAvailableTranslations();
|
QStringList langs = Config()->getAvailableTranslations();
|
||||||
ui->languageComboBox->addItems(langs);
|
ui->languageComboBox->addItems(langs);
|
||||||
@ -97,3 +98,8 @@ void WelcomeDialog::on_continueButton_clicked()
|
|||||||
{
|
{
|
||||||
accept();
|
accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WelcomeDialog::on_updatesCheckBox_stateChanged(int state)
|
||||||
|
{
|
||||||
|
Config()->setAutoUpdateEnabled(!Config()->getAutoUpdateEnabled());
|
||||||
|
}
|
||||||
|
@ -30,6 +30,7 @@ private slots:
|
|||||||
void onLanguageComboBox_currentIndexChanged(int index);
|
void onLanguageComboBox_currentIndexChanged(int index);
|
||||||
void on_checkUpdateButton_clicked();
|
void on_checkUpdateButton_clicked();
|
||||||
void on_continueButton_clicked();
|
void on_continueButton_clicked();
|
||||||
|
void on_updatesCheckBox_stateChanged(int state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::WelcomeDialog *ui;
|
Ui::WelcomeDialog *ui;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>806</width>
|
<width>806</width>
|
||||||
<height>488</height>
|
<height>620</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -122,20 +122,54 @@
|
|||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" columnstretch="3,2,3,0,0,0">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<property name="sizeConstraint">
|
<item>
|
||||||
<enum>QLayout::SetFixedSize</enum>
|
<spacer name="horizontalSpacer_4">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="horizontalSpacing">
|
<property name="sizeHint" stdset="0">
|
||||||
<number>0</number>
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="verticalSpacing">
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<property name="spacing">
|
||||||
<number>9</number>
|
<number>9</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="28" column="1">
|
<property name="sizeConstraint">
|
||||||
<widget class="QComboBox" name="languageComboBox"/>
|
<enum>QLayout::SetMaximumSize</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="checkUpdateButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16777215</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>About</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="27" column="1">
|
<item>
|
||||||
<widget class="QComboBox" name="themeComboBox">
|
<widget class="QComboBox" name="themeComboBox">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
@ -160,7 +194,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="iconSize">
|
<property name="iconSize">
|
||||||
<size>
|
<size>
|
||||||
<width>160</width>
|
<width>16</width>
|
||||||
<height>16</height>
|
<height>16</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
@ -176,33 +210,33 @@
|
|||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="26" column="1">
|
<item>
|
||||||
<widget class="QPushButton" name="checkUpdateButton">
|
<widget class="QComboBox" name="languageComboBox"/>
|
||||||
<property name="sizePolicy">
|
</item>
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<item>
|
||||||
<horstretch>0</horstretch>
|
<widget class="QCheckBox" name="updatesCheckBox">
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>16777215</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>About</string>
|
<string>Check for updates on start</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
Loading…
Reference in New Issue
Block a user