mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
Add an option for auto-updates on Windows
With the update server hosted on my laptop... Fun fact: Updates are really easy to mess up right now. If I forget to update the update server, everyone gets downgraded. Upload a bad file and everyone will crash. Fun stuff. Upates Are Experimental™ and off by default.
This commit is contained in:
parent
45e20187cc
commit
0054787826
|
@ -18,12 +18,15 @@
|
||||||
#include "src/autoupdate.h"
|
#include "src/autoupdate.h"
|
||||||
#include "src/misc/serialize.h"
|
#include "src/misc/serialize.h"
|
||||||
#include "src/misc/settings.h"
|
#include "src/misc/settings.h"
|
||||||
|
#include "src/widget/widget.h"
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
#include <QtConcurrent/QtConcurrent>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -37,7 +40,7 @@ const QString AutoUpdater::updaterBin = "qtox-updater.exe";
|
||||||
const QString AutoUpdater::platform;
|
const QString AutoUpdater::platform;
|
||||||
const QString AutoUpdater::updaterBin;
|
const QString AutoUpdater::updaterBin;
|
||||||
#endif
|
#endif
|
||||||
const QString AutoUpdater::updateServer = "http://127.0.0.1";
|
const QString AutoUpdater::updateServer = "http://mlkj.bounceme.net";
|
||||||
const QString AutoUpdater::checkURI = AutoUpdater::updateServer+"/qtox/"+AutoUpdater::platform+"/version";
|
const QString AutoUpdater::checkURI = AutoUpdater::updateServer+"/qtox/"+AutoUpdater::platform+"/version";
|
||||||
const QString AutoUpdater::flistURI = AutoUpdater::updateServer+"/qtox/"+AutoUpdater::platform+"/flist";
|
const QString AutoUpdater::flistURI = AutoUpdater::updateServer+"/qtox/"+AutoUpdater::platform+"/flist";
|
||||||
const QString AutoUpdater::filesURI = AutoUpdater::updateServer+"/qtox/"+AutoUpdater::platform+"/files/";
|
const QString AutoUpdater::filesURI = AutoUpdater::updateServer+"/qtox/"+AutoUpdater::platform+"/files/";
|
||||||
|
@ -392,3 +395,20 @@ fail:
|
||||||
QDir(updateDirStr).removeRecursively();
|
QDir(updateDirStr).removeRecursively();
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AutoUpdater::checkUpdatesAsyncInteractive()
|
||||||
|
{
|
||||||
|
QtConcurrent::run(&AutoUpdater::checkUpdatesAsyncInteractiveWorker);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoUpdater::checkUpdatesAsyncInteractiveWorker()
|
||||||
|
{
|
||||||
|
if (!isUpdateAvailable())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Widget::getInstance()->askMsgboxQuestion(QObject::tr("Update", "The title of a message box"),
|
||||||
|
QObject::tr("An update is available, do you want to download it now ?\nIt will be installed when qTox restarts.")))
|
||||||
|
{
|
||||||
|
downloadUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -57,6 +57,10 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/// Connects to the qTox update server, if an updat is found shows a dialog to the user asking to download it
|
||||||
|
/// Runs asynchronously in its own thread, and will return immediatly
|
||||||
|
/// Will call isUpdateAvailable, and as such may processEvents
|
||||||
|
static void checkUpdatesAsyncInteractive();
|
||||||
/// Connects to the qTox update server, returns true if an update is available for download
|
/// Connects to the qTox update server, returns true if an update is available for download
|
||||||
/// Will call getUpdateVersion, and as such may block and processEvents
|
/// Will call getUpdateVersion, and as such may block and processEvents
|
||||||
static bool isUpdateAvailable();
|
static bool isUpdateAvailable();
|
||||||
|
@ -90,6 +94,9 @@ protected:
|
||||||
/// Note that a file with an empty but non-null QByteArray is not an error, merely a file of size 0.
|
/// Note that a file with an empty but non-null QByteArray is not an error, merely a file of size 0.
|
||||||
/// Will try to follow qTox's proxy settings, may block and processEvents
|
/// Will try to follow qTox's proxy settings, may block and processEvents
|
||||||
static UpdateFile getUpdateFile(UpdateFileMeta fileMeta);
|
static UpdateFile getUpdateFile(UpdateFileMeta fileMeta);
|
||||||
|
/// Does the actual work for checkUpdatesAsyncInteractive
|
||||||
|
/// Blocking, but otherwise has the same properties than checkUpdatesAsyncInteractive
|
||||||
|
static void checkUpdatesAsyncInteractiveWorker();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AutoUpdater() = delete;
|
AutoUpdater() = delete;
|
||||||
|
|
|
@ -119,6 +119,7 @@ void Settings::load()
|
||||||
proxyPort = s.value("proxyPort", 0).toInt();
|
proxyPort = s.value("proxyPort", 0).toInt();
|
||||||
currentProfile = s.value("currentProfile", "").toString();
|
currentProfile = s.value("currentProfile", "").toString();
|
||||||
autoAwayTime = s.value("autoAwayTime", 10).toInt();
|
autoAwayTime = s.value("autoAwayTime", 10).toInt();
|
||||||
|
checkUpdates = s.value("checkUpdates", false).toBool();
|
||||||
s.endGroup();
|
s.endGroup();
|
||||||
|
|
||||||
s.beginGroup("Widgets");
|
s.beginGroup("Widgets");
|
||||||
|
@ -255,6 +256,7 @@ void Settings::save(QString path)
|
||||||
s.setValue("proxyPort", proxyPort);
|
s.setValue("proxyPort", proxyPort);
|
||||||
s.setValue("currentProfile", currentProfile);
|
s.setValue("currentProfile", currentProfile);
|
||||||
s.setValue("autoAwayTime", autoAwayTime);
|
s.setValue("autoAwayTime", autoAwayTime);
|
||||||
|
s.setValue("checkUpdates", checkUpdates);
|
||||||
s.endGroup();
|
s.endGroup();
|
||||||
|
|
||||||
s.beginGroup("Widgets");
|
s.beginGroup("Widgets");
|
||||||
|
@ -727,6 +729,16 @@ void Settings::setWindowState(const QByteArray &value)
|
||||||
windowState = value;
|
windowState = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Settings::getCheckUpdates() const
|
||||||
|
{
|
||||||
|
return checkUpdates;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::setCheckUpdates(bool newValue)
|
||||||
|
{
|
||||||
|
checkUpdates = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray Settings::getSplitterState() const
|
QByteArray Settings::getSplitterState() const
|
||||||
{
|
{
|
||||||
return splitterState;
|
return splitterState;
|
||||||
|
|
|
@ -99,6 +99,9 @@ public:
|
||||||
int getAutoAwayTime() const;
|
int getAutoAwayTime() const;
|
||||||
void setAutoAwayTime(int newValue);
|
void setAutoAwayTime(int newValue);
|
||||||
|
|
||||||
|
bool getCheckUpdates() const;
|
||||||
|
void setCheckUpdates(bool newValue);
|
||||||
|
|
||||||
QPixmap getSavedAvatar(const QString& ownerId);
|
QPixmap getSavedAvatar(const QString& ownerId);
|
||||||
void saveAvatar(QPixmap& pic, const QString& ownerId);
|
void saveAvatar(QPixmap& pic, const QString& ownerId);
|
||||||
|
|
||||||
|
@ -219,6 +222,7 @@ private:
|
||||||
bool closeToTray;
|
bool closeToTray;
|
||||||
bool minimizeToTray;
|
bool minimizeToTray;
|
||||||
bool useEmoticons;
|
bool useEmoticons;
|
||||||
|
bool checkUpdates;
|
||||||
|
|
||||||
bool forceTCP;
|
bool forceTCP;
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
|
||||||
|
#include "src/autoupdate.h"
|
||||||
|
|
||||||
static QStringList locales = {"bg", "de", "en", "fr", "it", "mannol", "pirate", "pl", "ru", "fi", "sv", "uk"};
|
static QStringList locales = {"bg", "de", "en", "fr", "it", "mannol", "pirate", "pl", "ru", "fi", "sv", "uk"};
|
||||||
static QStringList langs = {"Български", "Deustch", "English", "Français", "Italiano", "mannol", "Pirate", "Polski", "Русский", "Suomi", "Svenska", "Українська"};
|
static QStringList langs = {"Български", "Deustch", "English", "Français", "Italiano", "mannol", "Pirate", "Polski", "Русский", "Suomi", "Svenska", "Українська"};
|
||||||
|
|
||||||
|
@ -39,6 +41,9 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) :
|
||||||
|
|
||||||
bodyUI = new Ui::GeneralSettings;
|
bodyUI = new Ui::GeneralSettings;
|
||||||
bodyUI->setupUi(this);
|
bodyUI->setupUi(this);
|
||||||
|
|
||||||
|
bodyUI->checkUpdates->setVisible(AUTOUPDATE_ENABLED);
|
||||||
|
bodyUI->checkUpdates->setChecked(Settings::getInstance().getCheckUpdates());
|
||||||
|
|
||||||
bodyUI->cbEnableIPv6->setChecked(Settings::getInstance().getEnableIPv6());
|
bodyUI->cbEnableIPv6->setChecked(Settings::getInstance().getEnableIPv6());
|
||||||
for (int i = 0; i < langs.size(); i++)
|
for (int i = 0; i < langs.size(); i++)
|
||||||
|
@ -93,6 +98,7 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) :
|
||||||
onUseProxyUpdated();
|
onUseProxyUpdated();
|
||||||
|
|
||||||
//general
|
//general
|
||||||
|
connect(bodyUI->checkUpdates, &QCheckBox::stateChanged, this, &GeneralForm::onCheckUpdateChanged);
|
||||||
connect(bodyUI->transComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onTranslationUpdated()));
|
connect(bodyUI->transComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onTranslationUpdated()));
|
||||||
connect(bodyUI->cbMakeToxPortable, &QCheckBox::stateChanged, this, &GeneralForm::onMakeToxPortableUpdated);
|
connect(bodyUI->cbMakeToxPortable, &QCheckBox::stateChanged, this, &GeneralForm::onMakeToxPortableUpdated);
|
||||||
connect(bodyUI->startInTray, &QCheckBox::stateChanged, this, &GeneralForm::onSetAutostartInTray);
|
connect(bodyUI->startInTray, &QCheckBox::stateChanged, this, &GeneralForm::onSetAutostartInTray);
|
||||||
|
@ -280,3 +286,8 @@ void GeneralForm::reloadSmiles()
|
||||||
bodyUI->smile4->setToolTip(smiles[3]);
|
bodyUI->smile4->setToolTip(smiles[3]);
|
||||||
bodyUI->smile5->setToolTip(smiles[4]);
|
bodyUI->smile5->setToolTip(smiles[4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GeneralForm::onCheckUpdateChanged()
|
||||||
|
{
|
||||||
|
Settings::getInstance().setCheckUpdates(bodyUI->checkUpdates->isChecked());
|
||||||
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ private slots:
|
||||||
void onReconnectClicked();
|
void onReconnectClicked();
|
||||||
void onAutoAcceptFileChange();
|
void onAutoAcceptFileChange();
|
||||||
void onAutoSaveDirChange();
|
void onAutoSaveDirChange();
|
||||||
|
void onCheckUpdateChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::GeneralSettings *bodyUI;
|
Ui::GeneralSettings *bodyUI;
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>511</width>
|
<width>511</width>
|
||||||
<height>739</height>
|
<height>720</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="0,0,1">
|
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="0,0,1">
|
||||||
|
@ -121,6 +121,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkUpdates">
|
||||||
|
<property name="text">
|
||||||
|
<string>Check for updates on startup (unstable)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<item alignment="Qt::AlignLeft">
|
<item alignment="Qt::AlignLeft">
|
||||||
|
|
|
@ -245,6 +245,11 @@ void Widget::init()
|
||||||
coreThread->start();
|
coreThread->start();
|
||||||
|
|
||||||
addFriendForm->show(*ui);
|
addFriendForm->show(*ui);
|
||||||
|
|
||||||
|
#if (AUTOUPDATE_ENABLED)
|
||||||
|
if (Settings::getInstance().getCheckUpdates())
|
||||||
|
AutoUpdater::checkUpdatesAsyncInteractive();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::setTranslation()
|
void Widget::setTranslation()
|
||||||
|
@ -1096,3 +1101,20 @@ void Widget::setEnabledThreadsafe(bool enabled)
|
||||||
return setEnabled(enabled);
|
return setEnabled(enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Widget::askMsgboxQuestion(const QString& title, const QString& msg)
|
||||||
|
{
|
||||||
|
// We can only display widgets from the GUI thread
|
||||||
|
if (QThread::currentThread() != qApp->thread())
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
QMetaObject::invokeMethod(this, "askMsgboxQuestion", Qt::BlockingQueuedConnection,
|
||||||
|
Q_RETURN_ARG(bool, ret),
|
||||||
|
Q_ARG(const QString&, title), Q_ARG(const QString&, msg));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return QMessageBox::question(this, title, msg) == QMessageBox::StandardButton::Yes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -67,6 +67,7 @@ public:
|
||||||
Q_INVOKABLE QMessageBox::StandardButton showWarningMsgBox(const QString& title, const QString& msg,
|
Q_INVOKABLE QMessageBox::StandardButton showWarningMsgBox(const QString& title, const QString& msg,
|
||||||
QMessageBox::StandardButtons buttonss = QMessageBox::Ok);
|
QMessageBox::StandardButtons buttonss = QMessageBox::Ok);
|
||||||
Q_INVOKABLE void setEnabledThreadsafe(bool enabled);
|
Q_INVOKABLE void setEnabledThreadsafe(bool enabled);
|
||||||
|
Q_INVOKABLE bool askMsgboxQuestion(const QString& title, const QString& msg);
|
||||||
~Widget();
|
~Widget();
|
||||||
|
|
||||||
virtual void closeEvent(QCloseEvent *event);
|
virtual void closeEvent(QCloseEvent *event);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user