mirror of https://github.com/PCSX2/pcsx2.git
Qt: Use HTTPDownloader instead of QtNetwork for updates
This commit is contained in:
parent
15091cea54
commit
d096fed8db
|
@ -1,5 +1,5 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
|
@ -18,6 +18,7 @@
|
|||
#include "AutoUpdaterDialog.h"
|
||||
#include "MainWindow.h"
|
||||
#include "QtHost.h"
|
||||
#include "QtProgressCallback.h"
|
||||
#include "QtUtils.h"
|
||||
|
||||
#include "pcsx2/Host.h"
|
||||
|
@ -26,11 +27,14 @@
|
|||
|
||||
#include "updater/UpdaterExtractor.h"
|
||||
|
||||
#include "common/Assertions.h"
|
||||
#include "common/CocoaTools.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/HTTPDownloader.h"
|
||||
#include "common/StringUtil.h"
|
||||
|
||||
#include <functional>
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QJsonArray>
|
||||
|
@ -39,34 +43,34 @@
|
|||
#include <QtCore/QJsonValue>
|
||||
#include <QtCore/QProcess>
|
||||
#include <QtCore/QString>
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
#include <QtWidgets/QDialog>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtWidgets/QProgressDialog>
|
||||
|
||||
// Interval at which HTTP requests are polled.
|
||||
static constexpr u32 HTTP_POLL_INTERVAL = 10;
|
||||
|
||||
// Logic to detect whether we can use the auto updater.
|
||||
// We use tagged commit, because this gets set on nightly builds.
|
||||
#if (defined(_WIN32) || defined(__linux__) || defined(__APPLE__)) && defined(GIT_TAG_LO)
|
||||
|
||||
#define AUTO_UPDATER_SUPPORTED 1
|
||||
#define AUTO_UPDATER_SUPPORTED 1
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define UPDATE_PLATFORM_STR "Windows"
|
||||
#elif defined(__linux__)
|
||||
#define UPDATE_PLATFORM_STR "Linux"
|
||||
#elif defined(__APPLE__)
|
||||
#define UPDATE_PLATFORM_STR "MacOS"
|
||||
#endif
|
||||
#if defined(_WIN32)
|
||||
#define UPDATE_PLATFORM_STR "Windows"
|
||||
#elif defined(__linux__)
|
||||
#define UPDATE_PLATFORM_STR "Linux"
|
||||
#elif defined(__APPLE__)
|
||||
#define UPDATE_PLATFORM_STR "MacOS"
|
||||
#endif
|
||||
|
||||
#ifdef MULTI_ISA_SHARED_COMPILATION
|
||||
// #undef UPDATE_ADDITIONAL_TAGS
|
||||
#elif _M_SSE >= 0x501
|
||||
#define UPDATE_ADDITIONAL_TAGS "AVX2"
|
||||
#else
|
||||
#define UPDATE_ADDITIONAL_TAGS "SSE4"
|
||||
#endif
|
||||
#ifdef MULTI_ISA_SHARED_COMPILATION
|
||||
// #undef UPDATE_ADDITIONAL_TAGS
|
||||
#elif _M_SSE >= 0x501
|
||||
#define UPDATE_ADDITIONAL_TAGS "AVX2"
|
||||
#else
|
||||
#define UPDATE_ADDITIONAL_TAGS "SSE4"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -86,8 +90,6 @@ static const char* UPDATE_TAGS[] = {"stable", "nightly"};
|
|||
AutoUpdaterDialog::AutoUpdaterDialog(QWidget* parent /* = nullptr */)
|
||||
: QDialog(parent)
|
||||
{
|
||||
m_network_access_mgr = new QNetworkAccessManager(this);
|
||||
|
||||
m_ui.setupUi(this);
|
||||
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
@ -95,6 +97,10 @@ AutoUpdaterDialog::AutoUpdaterDialog(QWidget* parent /* = nullptr */)
|
|||
connect(m_ui.downloadAndInstall, &QPushButton::clicked, this, &AutoUpdaterDialog::downloadUpdateClicked);
|
||||
connect(m_ui.skipThisUpdate, &QPushButton::clicked, this, &AutoUpdaterDialog::skipThisUpdateClicked);
|
||||
connect(m_ui.remindMeLater, &QPushButton::clicked, this, &AutoUpdaterDialog::remindMeLaterClicked);
|
||||
|
||||
m_http = HTTPDownloader::Create(Host::GetHTTPUserAgent());
|
||||
if (!m_http)
|
||||
Console.Error("Failed to create HTTP downloader, auto updater will not be available.");
|
||||
}
|
||||
|
||||
AutoUpdaterDialog::~AutoUpdaterDialog() = default;
|
||||
|
@ -172,35 +178,66 @@ void AutoUpdaterDialog::reportError(const char* msg, ...)
|
|||
QMessageBox::critical(this, tr("Updater Error"), QString::fromStdString(full_msg));
|
||||
}
|
||||
|
||||
bool AutoUpdaterDialog::ensureHttpReady()
|
||||
{
|
||||
if (!m_http)
|
||||
return false;
|
||||
|
||||
if (!m_http_poll_timer)
|
||||
{
|
||||
m_http_poll_timer = new QTimer(this);
|
||||
m_http_poll_timer->connect(m_http_poll_timer, &QTimer::timeout, this, &AutoUpdaterDialog::httpPollTimerPoll);
|
||||
}
|
||||
|
||||
if (!m_http_poll_timer->isActive())
|
||||
{
|
||||
m_http_poll_timer->setSingleShot(false);
|
||||
m_http_poll_timer->setInterval(HTTP_POLL_INTERVAL);
|
||||
m_http_poll_timer->start();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AutoUpdaterDialog::httpPollTimerPoll()
|
||||
{
|
||||
pxAssert(m_http);
|
||||
m_http->PollRequests();
|
||||
|
||||
if (!m_http->HasAnyRequests())
|
||||
{
|
||||
Console.WriteLn("(AutoUpdaterDialog) All HTTP requests done.");
|
||||
m_http_poll_timer->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void AutoUpdaterDialog::queueUpdateCheck(bool display_message)
|
||||
{
|
||||
m_display_messages = display_message;
|
||||
|
||||
#ifdef AUTO_UPDATER_SUPPORTED
|
||||
connect(m_network_access_mgr, &QNetworkAccessManager::finished, this, &AutoUpdaterDialog::getLatestReleaseComplete);
|
||||
if (!ensureHttpReady())
|
||||
{
|
||||
emit updateCheckCompleted();
|
||||
return;
|
||||
}
|
||||
|
||||
QUrl url(QStringLiteral(LATEST_RELEASE_URL).arg(getCurrentUpdateTag()));
|
||||
QNetworkRequest request(url);
|
||||
m_network_access_mgr->get(request);
|
||||
m_http->CreateRequest(QStringLiteral(LATEST_RELEASE_URL).arg(getCurrentUpdateTag()).toStdString(),
|
||||
std::bind(&AutoUpdaterDialog::getLatestReleaseComplete, this, std::placeholders::_1, std::placeholders::_3));
|
||||
#else
|
||||
emit updateCheckCompleted();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AutoUpdaterDialog::getLatestReleaseComplete(QNetworkReply* reply)
|
||||
void AutoUpdaterDialog::getLatestReleaseComplete(s32 status_code, std::vector<u8> data)
|
||||
{
|
||||
#ifdef AUTO_UPDATER_SUPPORTED
|
||||
// this might fail due to a lack of internet connection - in which case, don't spam the user with messages every time.
|
||||
m_network_access_mgr->disconnect(this);
|
||||
reply->deleteLater();
|
||||
|
||||
bool found_update_info = false;
|
||||
|
||||
if (reply->error() == QNetworkReply::NoError)
|
||||
if (status_code == HTTPDownloader::HTTP_STATUS_OK)
|
||||
{
|
||||
const QByteArray reply_json(reply->readAll());
|
||||
QJsonParseError parse_error;
|
||||
QJsonDocument doc(QJsonDocument::fromJson(reply_json, &parse_error));
|
||||
QJsonDocument doc(QJsonDocument::fromJson(QByteArray(reinterpret_cast<const char*>(data.data()), data.size()), &parse_error));
|
||||
if (doc.isObject())
|
||||
{
|
||||
const QJsonObject doc_object(doc.object());
|
||||
|
@ -304,7 +341,7 @@ void AutoUpdaterDialog::getLatestReleaseComplete(QNetworkReply* reply)
|
|||
}
|
||||
else
|
||||
{
|
||||
reportError("Failed to download latest release info: %d", static_cast<int>(reply->error()));
|
||||
reportError("Failed to download latest release info: %d", status_code);
|
||||
}
|
||||
|
||||
if (found_update_info)
|
||||
|
@ -317,29 +354,21 @@ void AutoUpdaterDialog::getLatestReleaseComplete(QNetworkReply* reply)
|
|||
void AutoUpdaterDialog::queueGetChanges()
|
||||
{
|
||||
#ifdef AUTO_UPDATER_SUPPORTED
|
||||
connect(m_network_access_mgr, &QNetworkAccessManager::finished, this, &AutoUpdaterDialog::getChangesComplete);
|
||||
if (!ensureHttpReady())
|
||||
return;
|
||||
|
||||
const QString url_string(QStringLiteral(CHANGES_URL).arg(GIT_HASH).arg(m_latest_version));
|
||||
QUrl url(url_string);
|
||||
QNetworkRequest request(url);
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
#endif
|
||||
m_network_access_mgr->get(request);
|
||||
m_http->CreateRequest(QStringLiteral(CHANGES_URL).arg(GIT_HASH).arg(m_latest_version).toStdString(),
|
||||
std::bind(&AutoUpdaterDialog::getChangesComplete, this, std::placeholders::_1, std::placeholders::_3));
|
||||
#endif
|
||||
}
|
||||
|
||||
void AutoUpdaterDialog::getChangesComplete(QNetworkReply* reply)
|
||||
void AutoUpdaterDialog::getChangesComplete(s32 status_code, std::vector<u8> data)
|
||||
{
|
||||
#ifdef AUTO_UPDATER_SUPPORTED
|
||||
m_network_access_mgr->disconnect(this);
|
||||
reply->deleteLater();
|
||||
|
||||
if (reply->error() == QNetworkReply::NoError)
|
||||
if (status_code == HTTPDownloader::HTTP_STATUS_OK)
|
||||
{
|
||||
const QByteArray reply_json(reply->readAll());
|
||||
QJsonParseError parse_error;
|
||||
QJsonDocument doc(QJsonDocument::fromJson(reply_json, &parse_error));
|
||||
QJsonDocument doc(QJsonDocument::fromJson(QByteArray(reinterpret_cast<const char*>(data.data()), data.size()), &parse_error));
|
||||
if (doc.isObject())
|
||||
{
|
||||
const QJsonObject doc_object(doc.object());
|
||||
|
@ -400,7 +429,7 @@ void AutoUpdaterDialog::getChangesComplete(QNetworkReply* reply)
|
|||
}
|
||||
else
|
||||
{
|
||||
reportError("Failed to download change list: %d", static_cast<int>(reply->error()));
|
||||
reportError("Failed to download change list: %d", status_code);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -427,61 +456,53 @@ void AutoUpdaterDialog::downloadUpdateClicked()
|
|||
}
|
||||
|
||||
m_display_messages = true;
|
||||
QUrl url(m_download_url);
|
||||
QNetworkRequest request(url);
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
#endif
|
||||
QNetworkReply* reply = m_network_access_mgr->get(request);
|
||||
|
||||
QProgressDialog progress(tr("Downloading %1...").arg(m_download_url), tr("Cancel"), 0, 1);
|
||||
progress.setWindowTitle(tr("Automatic Updater"));
|
||||
progress.setWindowIcon(windowIcon());
|
||||
progress.setAutoClose(false);
|
||||
std::optional<bool> download_result;
|
||||
QtModalProgressCallback progress(this);
|
||||
progress.SetTitle(tr("Automatic Updater").toUtf8().constData());
|
||||
progress.SetStatusText(tr("Downloading %1...").arg(m_latest_version).toUtf8().constData());
|
||||
progress.GetDialog().setWindowIcon(windowIcon());
|
||||
progress.SetCancellable(true);
|
||||
|
||||
connect(reply, &QNetworkReply::downloadProgress, [&progress](quint64 received, quint64 total) {
|
||||
progress.setRange(0, static_cast<int>(total));
|
||||
progress.setValue(static_cast<int>(received));
|
||||
});
|
||||
m_http->CreateRequest(
|
||||
m_download_url.toStdString(),
|
||||
[this, &download_result, &progress](s32 status_code, const std::string&, std::vector<u8> data) {
|
||||
if (status_code == HTTPDownloader::HTTP_STATUS_CANCELLED)
|
||||
return;
|
||||
|
||||
connect(m_network_access_mgr, &QNetworkAccessManager::finished, [this, &progress](QNetworkReply* reply) {
|
||||
m_network_access_mgr->disconnect();
|
||||
if (status_code != HTTPDownloader::HTTP_STATUS_OK)
|
||||
{
|
||||
reportError("Download failed: %d", status_code);
|
||||
download_result = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply->error() != QNetworkReply::NoError)
|
||||
{
|
||||
reportError("Download failed: %s", reply->errorString().toUtf8().constData());
|
||||
progress.done(-1);
|
||||
return;
|
||||
}
|
||||
if (data.empty())
|
||||
{
|
||||
reportError("Download failed: Update is empty");
|
||||
download_result = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const QByteArray data = reply->readAll();
|
||||
if (data.isEmpty())
|
||||
{
|
||||
reportError("Download failed: Update is empty");
|
||||
progress.done(-1);
|
||||
return;
|
||||
}
|
||||
download_result = processUpdate(data, progress.GetDialog());
|
||||
},
|
||||
&progress);
|
||||
|
||||
if (processUpdate(data, progress))
|
||||
progress.done(1);
|
||||
else
|
||||
progress.done(-1);
|
||||
});
|
||||
|
||||
const int result = progress.exec();
|
||||
if (result == 0)
|
||||
// Block until completion.
|
||||
while (m_http->HasAnyRequests())
|
||||
{
|
||||
// cancelled
|
||||
reply->abort();
|
||||
QApplication::processEvents(QEventLoop::AllEvents, HTTP_POLL_INTERVAL);
|
||||
m_http->PollRequests();
|
||||
}
|
||||
else if (result == 1)
|
||||
|
||||
if (download_result.value_or(false))
|
||||
{
|
||||
// updater started. since we're a modal on the main window, we have to queue this.
|
||||
QMetaObject::invokeMethod(g_main_window, "requestExit", Qt::QueuedConnection, Q_ARG(bool, true));
|
||||
done(0);
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
// download error or cancelled
|
||||
}
|
||||
|
||||
void AutoUpdaterDialog::checkIfUpdateNeeded()
|
||||
|
@ -490,8 +511,8 @@ void AutoUpdaterDialog::checkIfUpdateNeeded()
|
|||
QString::fromStdString(Host::GetBaseStringSettingValue("AutoUpdater", "LastVersion")));
|
||||
|
||||
Console.WriteLn(Color_StrongGreen, "Current version: %s", GIT_TAG);
|
||||
Console.WriteLn(Color_StrongYellow, "Latest SHA: %s", m_latest_version.toUtf8().constData());
|
||||
Console.WriteLn(Color_StrongOrange, "Last Checked SHA: %s", last_checked_version.toUtf8().constData());
|
||||
Console.WriteLn(Color_StrongYellow, "Latest version: %s", m_latest_version.toUtf8().constData());
|
||||
Console.WriteLn(Color_StrongOrange, "Last checked version: %s", last_checked_version.toUtf8().constData());
|
||||
if (m_latest_version == GIT_TAG || m_latest_version == last_checked_version)
|
||||
{
|
||||
Console.WriteLn(Color_StrongGreen, "No update needed.");
|
||||
|
@ -522,7 +543,9 @@ void AutoUpdaterDialog::checkIfUpdateNeeded()
|
|||
m_ui.downloadSize->setText(tr("Download Size: %1 MB").arg(static_cast<double>(m_download_size) / 1048576.0, 0, 'f', 2));
|
||||
m_ui.updateNotes->setText(tr("Loading..."));
|
||||
queueGetChanges();
|
||||
exec();
|
||||
|
||||
// We have to defer this, because it comes back through the timer/HTTP callback...
|
||||
QMetaObject::invokeMethod(this, "exec", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void AutoUpdaterDialog::skipThisUpdateClicked()
|
||||
|
@ -539,7 +562,7 @@ void AutoUpdaterDialog::remindMeLaterClicked()
|
|||
|
||||
#if defined(_WIN32)
|
||||
|
||||
bool AutoUpdaterDialog::processUpdate(const QByteArray& update_data, QProgressDialog&)
|
||||
bool AutoUpdaterDialog::processUpdate(const std::vector<u8>& data, QProgressDialog&)
|
||||
{
|
||||
const QString update_directory = QCoreApplication::applicationDirPath();
|
||||
const QString update_zip_path = QStringLiteral("%1" FS_OSPATH_SEPARATOR_STR "%2").arg(update_directory).arg(UPDATER_ARCHIVE_NAME);
|
||||
|
@ -555,7 +578,8 @@ bool AutoUpdaterDialog::processUpdate(const QByteArray& update_data, QProgressDi
|
|||
|
||||
{
|
||||
QFile update_zip_file(update_zip_path);
|
||||
if (!update_zip_file.open(QIODevice::WriteOnly) || update_zip_file.write(update_data) != update_data.size())
|
||||
if (!update_zip_file.open(QIODevice::WriteOnly) ||
|
||||
update_zip_file.write(reinterpret_cast<const char*>(data.data()), static_cast<qint64>(data.size())) != static_cast<qint64>(data.size()))
|
||||
{
|
||||
reportError("Writing update zip to '%s' failed", update_zip_path.toUtf8().constData());
|
||||
return false;
|
||||
|
@ -615,7 +639,7 @@ void AutoUpdaterDialog::cleanupAfterUpdate()
|
|||
|
||||
#elif defined(__linux__)
|
||||
|
||||
bool AutoUpdaterDialog::processUpdate(const QByteArray& update_data, QProgressDialog&)
|
||||
bool AutoUpdaterDialog::processUpdate(const std::vector<u8>& data, QProgressDialog&)
|
||||
{
|
||||
const char* appimage_path = std::getenv("APPIMAGE");
|
||||
if (!appimage_path || !FileSystem::FileExists(appimage_path))
|
||||
|
@ -655,7 +679,9 @@ bool AutoUpdaterDialog::processUpdate(const QByteArray& update_data, QProgressDi
|
|||
QFile old_file(qappimage_path);
|
||||
const QFileDevice::Permissions old_permissions = old_file.permissions();
|
||||
QFile new_file(new_appimage_path);
|
||||
if (!new_file.open(QIODevice::WriteOnly) || new_file.write(update_data) != update_data.size() || !new_file.setPermissions(old_permissions))
|
||||
if (!new_file.open(QIODevice::WriteOnly) ||
|
||||
new_file.write(reinterpret_cast<const char*>(data.data()), static_cast<qint64>(data.size())) != static_cast<qint64>(data.size()) ||
|
||||
!new_file.setPermissions(old_permissions))
|
||||
{
|
||||
QFile::remove(new_appimage_path);
|
||||
reportError("Failed to write new destination AppImage: %s", new_appimage_path.toUtf8().constData());
|
||||
|
@ -725,7 +751,7 @@ static QString UpdateVersionNumberInName(QString name, QStringView new_version)
|
|||
return name;
|
||||
}
|
||||
|
||||
bool AutoUpdaterDialog::processUpdate(const QByteArray& update_data, QProgressDialog& progress)
|
||||
bool AutoUpdaterDialog::processUpdate(const std::vector<u8>& data, QProgressDialog& progress)
|
||||
{
|
||||
std::optional<std::string> path = CocoaTools::GetNonTranslocatedBundlePath();
|
||||
if (!path.has_value())
|
||||
|
@ -754,20 +780,21 @@ bool AutoUpdaterDialog::processUpdate(const QByteArray& update_data, QProgressDi
|
|||
return false;
|
||||
}
|
||||
|
||||
constexpr qsizetype chunk_size = 65536;
|
||||
constexpr size_t chunk_size = 65536;
|
||||
progress.setLabelText(QStringLiteral("Unpacking update..."));
|
||||
progress.reset();
|
||||
progress.setRange(0, static_cast<int>((update_data.size() + chunk_size - 1) / chunk_size));
|
||||
progress.setRange(0, static_cast<int>((data.size() + chunk_size - 1) / chunk_size));
|
||||
|
||||
QProcess untar;
|
||||
untar.setProgram(QStringLiteral("/usr/bin/tar"));
|
||||
untar.setArguments({QStringLiteral("xC"), temp_dir.path()});
|
||||
untar.start();
|
||||
for (qsizetype i = 0; i < update_data.size(); i += chunk_size)
|
||||
for (size_t i = 0; i < data.size(); i += chunk_size)
|
||||
{
|
||||
progress.setValue(static_cast<int>(i / chunk_size));
|
||||
const qsizetype amt = std::min(update_data.size() - i, chunk_size);
|
||||
if (progress.wasCanceled() || untar.write(update_data.data() + i, amt) != amt)
|
||||
const size_t amt = std::min(data.size() - i, chunk_size);
|
||||
if (progress.wasCanceled() ||
|
||||
untar.write(reinterpret_cast<const char*>(data.data() + i), static_cast<qsizetype>(amt)) != static_cast<qsizetype>(amt))
|
||||
{
|
||||
if (!progress.wasCanceled())
|
||||
reportError("Failed to unpack update (write stopped short)");
|
||||
|
@ -796,7 +823,7 @@ bool AutoUpdaterDialog::processUpdate(const QByteArray& update_data, QProgressDi
|
|||
}
|
||||
|
||||
QFileInfoList temp_dir_contents = QDir(temp_dir.path()).entryInfoList(QDir::Filter::Dirs | QDir::Filter::NoDotAndDotDot);
|
||||
auto new_app = std::find_if(temp_dir_contents.begin(), temp_dir_contents.end(), [](const QFileInfo& file){ return file.suffix() == QStringLiteral("app"); });
|
||||
auto new_app = std::find_if(temp_dir_contents.begin(), temp_dir_contents.end(), [](const QFileInfo& file) { return file.suffix() == QStringLiteral("app"); });
|
||||
if (new_app == temp_dir_contents.end())
|
||||
{
|
||||
reportError("Couldn't find application in update package");
|
||||
|
@ -814,7 +841,7 @@ bool AutoUpdaterDialog::processUpdate(const QByteArray& update_data, QProgressDi
|
|||
{
|
||||
QFile::rename(QString::fromStdString(*trashed_path), info.filePath());
|
||||
reportError("Failed to move new application into place (couldn't rename '%s' to '%s')",
|
||||
new_app->absoluteFilePath().toUtf8().constData(), open_path.toUtf8().constData());
|
||||
new_app->absoluteFilePath().toUtf8().constData(), open_path.toUtf8().constData());
|
||||
return false;
|
||||
}
|
||||
QDir(QString::fromStdString(*trashed_path)).removeRecursively();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
|
@ -14,14 +14,20 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
|
||||
#include "ui_AutoUpdaterDialog.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtWidgets/QDialog>
|
||||
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkReply;
|
||||
class HTTPDownloader;
|
||||
class QProgressDialog;
|
||||
|
||||
class AutoUpdaterDialog final : public QDialog
|
||||
|
@ -46,28 +52,33 @@ public Q_SLOTS:
|
|||
void queueUpdateCheck(bool display_message);
|
||||
|
||||
private Q_SLOTS:
|
||||
void getLatestReleaseComplete(QNetworkReply* reply);
|
||||
|
||||
void queueGetChanges();
|
||||
void getChangesComplete(QNetworkReply* reply);
|
||||
|
||||
void httpPollTimerPoll();
|
||||
void downloadUpdateClicked();
|
||||
void skipThisUpdateClicked();
|
||||
void remindMeLaterClicked();
|
||||
|
||||
private:
|
||||
void reportError(const char* msg, ...);
|
||||
|
||||
bool ensureHttpReady();
|
||||
|
||||
void checkIfUpdateNeeded();
|
||||
QString getCurrentUpdateTag() const;
|
||||
|
||||
bool processUpdate(const QByteArray& update_data, QProgressDialog& progress);
|
||||
void getLatestReleaseComplete(s32 status_code, std::vector<u8> data);
|
||||
|
||||
void queueGetChanges();
|
||||
void getChangesComplete(s32 status_code, std::vector<u8> data);
|
||||
|
||||
bool processUpdate(const std::vector<u8>& data, QProgressDialog& progress);
|
||||
#if defined(_WIN32)
|
||||
bool doUpdate(const QString& zip_path, const QString& updater_path, const QString& destination_path);
|
||||
#endif
|
||||
|
||||
Ui::AutoUpdaterDialog m_ui;
|
||||
|
||||
QNetworkAccessManager* m_network_access_mgr = nullptr;
|
||||
std::unique_ptr<HTTPDownloader> m_http;
|
||||
QTimer* m_http_poll_timer = nullptr;
|
||||
QString m_latest_version;
|
||||
QDateTime m_latest_version_timestamp;
|
||||
QString m_download_url;
|
||||
|
|
Loading…
Reference in New Issue