mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-29 15:55:04 +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 \
|
||||
plugins/PluginManager.cpp \
|
||||
common/BasicBlockHighlighter.cpp \
|
||||
dialogs/LinkTypeDialog.cpp
|
||||
dialogs/LinkTypeDialog.cpp \
|
||||
common/UpdateWorker.cpp
|
||||
|
||||
HEADERS += \
|
||||
core/Cutter.h \
|
||||
@ -429,6 +430,7 @@ HEADERS += \
|
||||
common/PythonManager.h \
|
||||
plugins/PluginManager.h \
|
||||
common/BasicBlockHighlighter.h \
|
||||
common/UpdateWorker.h \
|
||||
dialogs/LinkTypeDialog.h
|
||||
|
||||
FORMS += \
|
||||
|
@ -23,6 +23,10 @@
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <QtNetwork/QtNetwork>
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
CutterApplication::CutterApplication(int &argc, char **argv) : QApplication(argc, argv)
|
||||
{
|
||||
// Setup application information
|
||||
@ -32,6 +36,13 @@ CutterApplication::CutterApplication(int &argc, char **argv) : QApplication(argc
|
||||
setLayoutDirection(Qt::LeftToRight);
|
||||
|
||||
// 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
|
||||
if (!loadTranslations()) {
|
||||
qWarning() << "Cannot load translations";
|
||||
|
14
src/Main.cpp
14
src/Main.cpp
@ -1,6 +1,8 @@
|
||||
|
||||
#include "CutterApplication.h"
|
||||
#include "core/MainWindow.h"
|
||||
#include "common/UpdateWorker.h"
|
||||
#include "CutterConfig.h"
|
||||
|
||||
/**
|
||||
* @brief Migrate Settings used before Cutter 1.8
|
||||
@ -34,6 +36,18 @@ int main(int argc, char *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();
|
||||
|
||||
return ret;
|
||||
|
@ -136,6 +136,16 @@ void Configuration::resetAll()
|
||||
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
|
||||
* @return a QLocale object describes user's current locale
|
||||
|
@ -46,6 +46,10 @@ public:
|
||||
|
||||
void resetAll();
|
||||
|
||||
// Auto update
|
||||
bool getAutoUpdateEnabled() const;
|
||||
void setAutoUpdateEnabled(bool au);
|
||||
|
||||
// Languages
|
||||
QLocale getCurrLocale() const;
|
||||
void setLocale(const QLocale &l);
|
||||
@ -58,7 +62,7 @@ public:
|
||||
|
||||
// Colors
|
||||
bool windowColorIsDark();
|
||||
void setLastThemeOf(const CutterQtTheme &currQtTheme, const QString& theme);
|
||||
void setLastThemeOf(const CutterQtTheme &currQtTheme, const QString &theme);
|
||||
QString getLastThemeOf(const CutterQtTheme &currQtTheme) const;
|
||||
const QColor getColor(const QString &name) const;
|
||||
void setTheme(int theme);
|
||||
|
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 <QTimer>
|
||||
#include <QEventLoop>
|
||||
#include <QJsonObject>
|
||||
#include <QProgressBar>
|
||||
#include <QProgressDialog>
|
||||
#include <UpdateWorker.h>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
|
||||
@ -25,29 +27,32 @@ AboutDialog::AboutDialog(QWidget *parent) :
|
||||
ui->logoSvgWidget->load(Config()->getLogoFile());
|
||||
|
||||
QString aboutString("<h1>Cutter</h1>"
|
||||
+ tr("Version") + " " CUTTER_VERSION_FULL "<br/>"
|
||||
+ tr("Using r2-") + R2_GITTAP
|
||||
+ "<p><b>" + tr("Optional Features:") + "</b><br/>"
|
||||
+ QString("Jupyter: %1<br/>").arg(
|
||||
+ tr("Version") + " " CUTTER_VERSION_FULL "<br/>"
|
||||
+ tr("Using r2-") + R2_GITTAP
|
||||
+ "<p><b>" + tr("Optional Features:") + "</b><br/>"
|
||||
+ QString("Jupyter: %1<br/>").arg(
|
||||
#ifdef CUTTER_ENABLE_JUPYTER
|
||||
"ON"
|
||||
"ON"
|
||||
#else
|
||||
"OFF"
|
||||
"OFF"
|
||||
#endif
|
||||
)
|
||||
+ QString("QtWebEngine: %2</p>").arg(
|
||||
)
|
||||
+ QString("QtWebEngine: %2</p>").arg(
|
||||
#ifdef CUTTER_ENABLE_QTWEBENGINE
|
||||
"ON"
|
||||
"ON"
|
||||
#else
|
||||
"OFF"
|
||||
"OFF"
|
||||
#endif
|
||||
)
|
||||
+ "<h2>" + tr("License") + "</h2>"
|
||||
+ tr("This Software is released under the GNU General Public License v3.0")
|
||||
+ "<h2>" + tr("Authors") + "</h2>"
|
||||
"xarkes, thestr4ng3r, ballessay<br/>"
|
||||
"Based on work by Hugo Teso <hugo.teso@gmail.org> (originally Iaito).");
|
||||
)
|
||||
+ "<h2>" + tr("License") + "</h2>"
|
||||
+ tr("This Software is released under the GNU General Public License v3.0")
|
||||
+ "<h2>" + tr("Authors") + "</h2>"
|
||||
"xarkes, thestr4ng3r, ballessay<br/>"
|
||||
"Based on work by Hugo Teso <hugo.teso@gmail.org> (originally Iaito).");
|
||||
ui->label->setText(aboutString);
|
||||
|
||||
QSignalBlocker s(ui->updatesCheckBox);
|
||||
ui->updatesCheckBox->setChecked(Config()->getAutoUpdateEnabled());
|
||||
}
|
||||
|
||||
AboutDialog::~AboutDialog() {}
|
||||
@ -75,9 +80,7 @@ void AboutDialog::on_showPluginsButton_clicked()
|
||||
|
||||
void AboutDialog::on_checkForUpdatesButton_clicked()
|
||||
{
|
||||
QUrl url("https://api.github.com/repos/radareorg/cutter/releases/latest");
|
||||
QNetworkRequest request;
|
||||
request.setUrl(url);
|
||||
UpdateWorker updateWorker;
|
||||
|
||||
QProgressDialog waitDialog;
|
||||
QProgressBar *bar = new QProgressBar(&waitDialog);
|
||||
@ -86,56 +89,25 @@ void AboutDialog::on_checkForUpdatesButton_clicked()
|
||||
waitDialog.setBar(bar);
|
||||
waitDialog.setLabel(new QLabel(tr("Checking for updates..."), &waitDialog));
|
||||
|
||||
QNetworkAccessManager nm;
|
||||
|
||||
QTimer timeoutTimer;
|
||||
timeoutTimer.setSingleShot(true);
|
||||
timeoutTimer.setInterval(7000);
|
||||
|
||||
connect(&nm, &QNetworkAccessManager::finished, &timeoutTimer, &QTimer::stop);
|
||||
connect(&nm, &QNetworkAccessManager::finished, &waitDialog, &QProgressDialog::cancel);
|
||||
connect(&nm, &QNetworkAccessManager::finished, this, &AboutDialog::serveVersionCheckReply);
|
||||
|
||||
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();
|
||||
connect(&updateWorker, &UpdateWorker::checkComplete, &waitDialog, &QProgressDialog::cancel);
|
||||
connect(&updateWorker, &UpdateWorker::checkComplete,
|
||||
[&updateWorker](const QString & version, const QString & error) {
|
||||
if (error != "") {
|
||||
QMessageBox::critical(nullptr, tr("Error!"), error);
|
||||
} else {
|
||||
if (version == CUTTER_VERSION_FULL) {
|
||||
QMessageBox::information(nullptr, tr("Version control"), tr("Cutter is up to date!"));
|
||||
} else {
|
||||
updateWorker.showUpdateDialog(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
updateWorker.checkCurrentVersion(7000);
|
||||
waitDialog.exec();
|
||||
delete reply;
|
||||
}
|
||||
|
||||
void AboutDialog::serveVersionCheckReply(QNetworkReply *reply)
|
||||
void AboutDialog::on_updatesCheckBox_stateChanged(int state)
|
||||
{
|
||||
QString currVersion = "";
|
||||
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();
|
||||
Config()->setAutoUpdateEnabled(!Config()->getAutoUpdateEnabled());
|
||||
}
|
||||
|
@ -21,8 +21,20 @@ private slots:
|
||||
void on_buttonBox_rejected();
|
||||
void on_showVersionButton_clicked();
|
||||
void on_showPluginsButton_clicked();
|
||||
|
||||
/**
|
||||
* @fn AboutDialog::on_checkForUpdatesButton_clicked()
|
||||
*
|
||||
* @brief Initiates process of checking for updates.
|
||||
*/
|
||||
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:
|
||||
std::unique_ptr<Ui::AboutDialog> ui;
|
||||
|
@ -76,6 +76,19 @@
|
||||
</property>
|
||||
</widget>
|
||||
</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>
|
||||
</item>
|
||||
</layout>
|
||||
|
@ -20,8 +20,9 @@ WelcomeDialog::WelcomeDialog(QWidget *parent) :
|
||||
ui->logoSvgWidget->load(Config()->getLogoFile());
|
||||
ui->versionLabel->setText("<font color='#a4a9b2'>" + tr("Version ") + CUTTER_VERSION_FULL + "</font>");
|
||||
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();
|
||||
ui->languageComboBox->addItems(langs);
|
||||
@ -97,3 +98,8 @@ void WelcomeDialog::on_continueButton_clicked()
|
||||
{
|
||||
accept();
|
||||
}
|
||||
|
||||
void WelcomeDialog::on_updatesCheckBox_stateChanged(int state)
|
||||
{
|
||||
Config()->setAutoUpdateEnabled(!Config()->getAutoUpdateEnabled());
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ private slots:
|
||||
void onLanguageComboBox_currentIndexChanged(int index);
|
||||
void on_checkUpdateButton_clicked();
|
||||
void on_continueButton_clicked();
|
||||
void on_updatesCheckBox_stateChanged(int state);
|
||||
|
||||
private:
|
||||
Ui::WelcomeDialog *ui;
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>806</width>
|
||||
<height>488</height>
|
||||
<height>620</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -122,84 +122,118 @@
|
||||
</spacer>
|
||||
</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">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetFixedSize</enum>
|
||||
</property>
|
||||
<property name="horizontalSpacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item row="28" column="1">
|
||||
<widget class="QComboBox" name="languageComboBox"/>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="27" column="1">
|
||||
<widget class="QComboBox" name="themeComboBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>9</number>
|
||||
</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="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>160</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMaximumSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Native Theme</string>
|
||||
</property>
|
||||
<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>
|
||||
<property name="text">
|
||||
<string>Dark Theme</string>
|
||||
</property>
|
||||
<widget class="QComboBox" name="themeComboBox">
|
||||
<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="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Native Theme</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Dark Theme</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</widget>
|
||||
<item>
|
||||
<widget class="QComboBox" name="languageComboBox"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="updatesCheckBox">
|
||||
<property name="text">
|
||||
<string>Check for updates on start</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="26" column="1">
|
||||
<widget class="QPushButton" name="checkUpdateButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>About</string>
|
||||
</property>
|
||||
</widget>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
Loading…
Reference in New Issue
Block a user