Merge pull request #5746 from leoetlino/disc-updates

Add support for installing disc updates from the game list
This commit is contained in:
Leo Lam
2017-08-16 19:02:42 +08:00
committed by GitHub
17 changed files with 491 additions and 119 deletions

View File

@ -29,6 +29,7 @@
#include "DolphinQt2/GameList/ListProxyModel.h"
#include "DolphinQt2/QtUtils/DoubleClickEventFilter.h"
#include "DolphinQt2/Settings.h"
#include "DolphinQt2/WiiUpdate.h"
static bool CompressCB(const std::string&, float, void*);
@ -164,6 +165,15 @@ void GameList::ShowContextMenu(const QPoint&)
menu->addSeparator();
}
if (platform == DiscIO::Platform::WII_DISC)
{
menu->addAction(tr("Perform System Update"), [this] {
WiiUpdate::PerformDiscUpdate(GetSelectedGame().toStdString(), this);
});
menu->setEnabled(!Core::IsRunning() || !SConfig::GetInstance().bWii);
}
if (platform == DiscIO::Platform::WII_WAD)
{
QAction* wad_install_action = new QAction(tr("Install to the NAND"), menu);

View File

@ -22,66 +22,9 @@
namespace WiiUpdate
{
void PerformOnlineUpdate(const std::string& region, QWidget* parent)
static void ShowResult(QWidget* parent, WiiUtils::UpdateResult result)
{
const int confirm = QMessageBox::question(
parent, QObject::tr("Confirm"),
QObject::tr("Connect to the Internet and perform an online system update?"));
if (confirm != QMessageBox::Yes)
return;
// Do not allow the user to close the dialog. Instead, wait until the update is finished
// or cancelled.
class UpdateProgressDialog final : public QProgressDialog
{
public:
using QProgressDialog::QProgressDialog;
protected:
void reject() override {}
};
UpdateProgressDialog dialog{parent};
dialog.setLabelText(QObject::tr("Preparing to update...\nThis can take a while."));
dialog.setWindowTitle(QObject::tr("Updating"));
dialog.setWindowFlags(dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint);
// QProgressDialog doesn't set its minimum size correctly.
dialog.setMinimumSize(360, 150);
// QProgressDialog doesn't allow us to disable the cancel button when it's pressed,
// so we have to pass it our own push button. Note: the dialog takes ownership of it.
auto* cancel_button = new QPushButton(QObject::tr("&Cancel"), parent);
dialog.setCancelButton(cancel_button);
Common::Flag was_cancelled;
QObject::disconnect(&dialog, &QProgressDialog::canceled, &dialog, &QProgressDialog::cancel);
QObject::connect(&dialog, &QProgressDialog::canceled, [&] {
dialog.setLabelText(QObject::tr("Finishing the update...\nThis can take a while."));
cancel_button->setEnabled(false);
was_cancelled.Set();
});
std::future<WiiUtils::UpdateResult> result = std::async(std::launch::async, [&] {
const WiiUtils::UpdateResult res = WiiUtils::DoOnlineUpdate(
[&](size_t processed, size_t total, u64 title_id) {
QueueOnObject(&dialog, [&dialog, &was_cancelled, processed, total, title_id]() {
if (was_cancelled.IsSet())
return;
dialog.setRange(0, static_cast<int>(total));
dialog.setValue(static_cast<int>(processed));
dialog.setLabelText(QObject::tr("Updating title %1...\nThis can take a while.")
.arg(title_id, 16, 16, QLatin1Char('0')));
});
return !was_cancelled.IsSet();
},
region);
QueueOnObject(&dialog, [&dialog] { dialog.close(); });
return res;
});
dialog.exec();
switch (result.get())
switch (result)
{
case WiiUtils::UpdateResult::Succeeded:
QMessageBox::information(parent, QObject::tr("Update completed"),
@ -114,6 +57,92 @@ void PerformOnlineUpdate(const std::string& region, QWidget* parent)
QObject::tr("The update has been cancelled. It is strongly recommended to "
"finish it in order to avoid inconsistent system software versions."));
break;
case WiiUtils::UpdateResult::RegionMismatch:
QMessageBox::critical(parent, QObject::tr("Update failed"),
QObject::tr("The game's region does not match your console's. "
"To avoid issues with the system menu, it is not possible "
"to update the emulated console using this disc."));
break;
case WiiUtils::UpdateResult::MissingUpdatePartition:
case WiiUtils::UpdateResult::DiscReadFailed:
QMessageBox::critical(parent, QObject::tr("Update failed"),
QObject::tr("The game disc does not contain any usable "
"update information."));
break;
}
}
template <typename Callable, typename... Args>
static WiiUtils::UpdateResult ShowProgress(QWidget* parent, Callable function, Args&&... args)
{
// Do not allow the user to close the dialog. Instead, wait until the update is finished
// or cancelled.
class UpdateProgressDialog final : public QProgressDialog
{
public:
using QProgressDialog::QProgressDialog;
protected:
void reject() override {}
};
UpdateProgressDialog dialog{parent};
dialog.setLabelText(QObject::tr("Preparing to update...\nThis can take a while."));
dialog.setWindowTitle(QObject::tr("Updating"));
dialog.setWindowFlags(dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint);
// QProgressDialog doesn't set its minimum size correctly.
dialog.setMinimumSize(360, 150);
// QProgressDialog doesn't allow us to disable the cancel button when it's pressed,
// so we have to pass it our own push button. Note: the dialog takes ownership of it.
auto* cancel_button = new QPushButton(QObject::tr("&Cancel"), parent);
dialog.setCancelButton(cancel_button);
Common::Flag was_cancelled;
QObject::disconnect(&dialog, &QProgressDialog::canceled, nullptr, nullptr);
QObject::connect(&dialog, &QProgressDialog::canceled, [&] {
dialog.setLabelText(QObject::tr("Finishing the update...\nThis can take a while."));
cancel_button->setEnabled(false);
was_cancelled.Set();
});
std::future<WiiUtils::UpdateResult> result = std::async(std::launch::async, [&] {
const WiiUtils::UpdateResult res = function(
[&](size_t processed, size_t total, u64 title_id) {
QueueOnObject(&dialog, [&dialog, &was_cancelled, processed, total, title_id] {
if (was_cancelled.IsSet())
return;
dialog.setRange(0, static_cast<int>(total));
dialog.setValue(static_cast<int>(processed));
dialog.setLabelText(QObject::tr("Updating title %1...\nThis can take a while.")
.arg(title_id, 16, 16, QLatin1Char('0')));
});
return !was_cancelled.IsSet();
},
std::forward<Args>(args)...);
QueueOnObject(&dialog, [&dialog] { dialog.done(0); });
return res;
});
dialog.exec();
return result.get();
}
void PerformOnlineUpdate(const std::string& region, QWidget* parent)
{
const int confirm = QMessageBox::question(
parent, QObject::tr("Confirm"),
QObject::tr("Connect to the Internet and perform an online system update?"));
if (confirm != QMessageBox::Yes)
return;
const WiiUtils::UpdateResult result = ShowProgress(parent, WiiUtils::DoOnlineUpdate, region);
ShowResult(parent, result);
}
void PerformDiscUpdate(const std::string& file_path, QWidget* parent)
{
const WiiUtils::UpdateResult result = ShowProgress(parent, WiiUtils::DoDiscUpdate, file_path);
ShowResult(parent, result);
}
} // namespace WiiUpdate

View File

@ -11,4 +11,5 @@ class QWidget;
namespace WiiUpdate
{
void PerformOnlineUpdate(const std::string& region, QWidget* parent = nullptr);
void PerformDiscUpdate(const std::string& file_path, QWidget* parent = nullptr);
} // namespace WiiUpdate