summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2020-04-21 23:59:37 -0400
committerGitHub <noreply@github.com>2020-04-21 23:59:37 -0400
commita5bd263dfba780de6a6fc88ccc996d42d350d416 (patch)
tree0337aa4a34d5c405926dc0ca49c761cc44522bf2 /Source
parentc33565295dd913991a543147f81be8687f3be737 (diff)
parent55f787b89898d28bd6245ec6768247659dd85b88 (diff)
Merge pull request #8714 from JosJuice/progress-dialog-thread
DolphinQt: Run tasks that use progress dialogs on separate threads
Diffstat (limited to 'Source')
-rw-r--r--Source/Android/jni/MainAndroid.cpp4
-rw-r--r--Source/Core/Core/Host.h1
-rw-r--r--Source/Core/DolphinNoGUI/MainNoGUI.cpp4
-rw-r--r--Source/Core/DolphinQt/CMakeLists.txt1
-rw-r--r--Source/Core/DolphinQt/Config/FilesystemWidget.cpp44
-rw-r--r--Source/Core/DolphinQt/Config/InfoWidget.cpp1
-rw-r--r--Source/Core/DolphinQt/Config/VerifyWidget.cpp73
-rw-r--r--Source/Core/DolphinQt/DolphinQt.vcxproj4
-rw-r--r--Source/Core/DolphinQt/GameList/GameList.cpp59
-rw-r--r--Source/Core/DolphinQt/Host.cpp6
-rw-r--r--Source/Core/DolphinQt/Host.h1
-rw-r--r--Source/Core/DolphinQt/MainWindow.cpp50
-rw-r--r--Source/Core/DolphinQt/MainWindow.h4
-rw-r--r--Source/Core/DolphinQt/NetPlay/NetPlayDialog.cpp1
-rw-r--r--Source/Core/DolphinQt/QtUtils/ParallelProgressDialog.h108
-rw-r--r--Source/DSPTool/StubHost.cpp3
-rw-r--r--Source/UnitTests/StubHost.cpp3
17 files changed, 230 insertions, 137 deletions
diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp
index 2bebbc4e8d..122f3fd6d9 100644
--- a/Source/Android/jni/MainAndroid.cpp
+++ b/Source/Android/jni/MainAndroid.cpp
@@ -140,10 +140,6 @@ void Host_YieldToUI()
{
}
-void Host_UpdateProgressDialog(const char* caption, int position, int total)
-{
-}
-
void Host_TitleChanged()
{
}
diff --git a/Source/Core/Core/Host.h b/Source/Core/Core/Host.h
index d3f5ee4b61..cf65c22eb0 100644
--- a/Source/Core/Core/Host.h
+++ b/Source/Core/Core/Host.h
@@ -43,5 +43,4 @@ void Host_UpdateDisasmDialog();
void Host_UpdateMainFrame();
void Host_UpdateTitle(const std::string& title);
void Host_YieldToUI();
-void Host_UpdateProgressDialog(const char* caption, int position, int total);
void Host_TitleChanged();
diff --git a/Source/Core/DolphinNoGUI/MainNoGUI.cpp b/Source/Core/DolphinNoGUI/MainNoGUI.cpp
index 14fac966c9..1278d46c40 100644
--- a/Source/Core/DolphinNoGUI/MainNoGUI.cpp
+++ b/Source/Core/DolphinNoGUI/MainNoGUI.cpp
@@ -99,10 +99,6 @@ void Host_YieldToUI()
{
}
-void Host_UpdateProgressDialog(const char* caption, int position, int total)
-{
-}
-
void Host_TitleChanged()
{
#ifdef USE_DISCORD_PRESENCE
diff --git a/Source/Core/DolphinQt/CMakeLists.txt b/Source/Core/DolphinQt/CMakeLists.txt
index f0951cb3b5..6a124cd03b 100644
--- a/Source/Core/DolphinQt/CMakeLists.txt
+++ b/Source/Core/DolphinQt/CMakeLists.txt
@@ -224,6 +224,7 @@ add_executable(dolphin-emu
QtUtils/FlowLayout.h
QtUtils/ModalMessageBox.cpp
QtUtils/ModalMessageBox.h
+ QtUtils/ParallelProgressDialog.h
QtUtils/ImageConverter.cpp
QtUtils/ImageConverter.h
QtUtils/WindowActivationEventFilter.cpp
diff --git a/Source/Core/DolphinQt/Config/FilesystemWidget.cpp b/Source/Core/DolphinQt/Config/FilesystemWidget.cpp
index 461a83ccc6..ddffe76963 100644
--- a/Source/Core/DolphinQt/Config/FilesystemWidget.cpp
+++ b/Source/Core/DolphinQt/Config/FilesystemWidget.cpp
@@ -10,7 +10,6 @@
#include <QFileInfo>
#include <QHeaderView>
#include <QMenu>
-#include <QProgressDialog>
#include <QStandardItemModel>
#include <QStyleFactory>
#include <QTreeView>
@@ -23,6 +22,7 @@
#include "DiscIO/Volume.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
+#include "DolphinQt/QtUtils/ParallelProgressDialog.h"
#include "DolphinQt/Resources.h"
#include "UICommon/UICommon.h"
@@ -282,28 +282,34 @@ void FilesystemWidget::ExtractDirectory(const DiscIO::Partition& partition, cons
std::unique_ptr<DiscIO::FileInfo> info = filesystem->FindFileInfo(path.toStdString());
u32 size = info->GetTotalChildren();
- QProgressDialog* dialog = new QProgressDialog(this);
- dialog->setWindowFlags(dialog->windowFlags() & ~Qt::WindowContextHelpButtonHint);
- dialog->setMinimum(0);
- dialog->setMaximum(size);
- dialog->show();
- dialog->setWindowTitle(tr("Progress"));
+ ParallelProgressDialog dialog(this);
+ dialog.GetRaw()->setMinimum(0);
+ dialog.GetRaw()->setMaximum(size);
+ dialog.GetRaw()->setWindowTitle(tr("Progress"));
- bool all = path.isEmpty();
+ const bool all = path.isEmpty();
- DiscIO::ExportDirectory(
- *m_volume, partition, *info, true, path.toStdString(), out.toStdString(),
- [all, dialog](const std::string& current) {
- dialog->setLabelText(
- (all ? QObject::tr("Extracting All Files...") : QObject::tr("Extracting Directory..."))
- .append(QStringLiteral(" %1").arg(QString::fromStdString(current))));
- dialog->setValue(dialog->value() + 1);
+ std::future<void> future = std::async(std::launch::async, [&] {
+ int progress = 0;
- QCoreApplication::processEvents();
- return dialog->wasCanceled();
- });
+ DiscIO::ExportDirectory(
+ *m_volume, partition, *info, true, path.toStdString(), out.toStdString(),
+ [all, &dialog, &progress](const std::string& current) {
+ dialog.SetLabelText(
+ (all ? QObject::tr("Extracting All Files...") :
+ QObject::tr("Extracting Directory..."))
+ .append(QStringLiteral(" %1").arg(QString::fromStdString(current))));
+ dialog.SetValue(++progress);
- dialog->close();
+ QCoreApplication::processEvents();
+ return dialog.WasCanceled();
+ });
+
+ dialog.Reset();
+ });
+
+ dialog.GetRaw()->exec();
+ future.get();
}
void FilesystemWidget::ExtractFile(const DiscIO::Partition& partition, const QString& path,
diff --git a/Source/Core/DolphinQt/Config/InfoWidget.cpp b/Source/Core/DolphinQt/Config/InfoWidget.cpp
index 416c1a8866..c382c7dc1b 100644
--- a/Source/Core/DolphinQt/Config/InfoWidget.cpp
+++ b/Source/Core/DolphinQt/Config/InfoWidget.cpp
@@ -10,7 +10,6 @@
#include <QGroupBox>
#include <QLabel>
#include <QLineEdit>
-#include <QProgressDialog>
#include <QPushButton>
#include <QTextEdit>
diff --git a/Source/Core/DolphinQt/Config/VerifyWidget.cpp b/Source/Core/DolphinQt/Config/VerifyWidget.cpp
index 925409a81c..ce221bce8f 100644
--- a/Source/Core/DolphinQt/Config/VerifyWidget.cpp
+++ b/Source/Core/DolphinQt/Config/VerifyWidget.cpp
@@ -4,7 +4,9 @@
#include "DolphinQt/Config/VerifyWidget.h"
+#include <future>
#include <memory>
+#include <optional>
#include <tuple>
#include <vector>
@@ -12,12 +14,12 @@
#include <QHBoxLayout>
#include <QHeaderView>
#include <QLabel>
-#include <QProgressDialog>
#include <QVBoxLayout>
#include "Common/CommonTypes.h"
#include "DiscIO/Volume.h"
#include "DiscIO/VolumeVerifier.h"
+#include "DolphinQt/QtUtils/ParallelProgressDialog.h"
VerifyWidget::VerifyWidget(std::shared_ptr<DiscIO::Volume> volume) : m_volume(std::move(volume))
{
@@ -131,33 +133,44 @@ void VerifyWidget::Verify()
// We have to divide the number of processed bytes with something so it won't make ints overflow
constexpr int DIVISOR = 0x100;
- QProgressDialog progress(tr("Verifying"), tr("Cancel"), 0, verifier.GetTotalBytes() / DIVISOR,
- this);
- progress.setWindowTitle(tr("Verifying"));
- progress.setWindowFlags(progress.windowFlags() & ~Qt::WindowContextHelpButtonHint);
- progress.setMinimumDuration(500);
- progress.setWindowModality(Qt::WindowModal);
-
- verifier.Start();
- while (verifier.GetBytesProcessed() != verifier.GetTotalBytes())
- {
- progress.setValue(verifier.GetBytesProcessed() / DIVISOR);
- if (progress.wasCanceled())
- return;
-
- verifier.Process();
- }
- verifier.Finish();
-
- DiscIO::VolumeVerifier::Result result = verifier.GetResult();
- progress.setValue(verifier.GetBytesProcessed() / DIVISOR);
-
- m_summary_text->setText(QString::fromStdString(result.summary_text));
-
- m_problems->setRowCount(static_cast<int>(result.problems.size()));
+ ParallelProgressDialog progress(tr("Verifying"), tr("Cancel"), 0,
+ static_cast<int>(verifier.GetTotalBytes() / DIVISOR), this);
+ progress.GetRaw()->setWindowTitle(tr("Verifying"));
+ progress.GetRaw()->setMinimumDuration(500);
+ progress.GetRaw()->setWindowModality(Qt::WindowModal);
+
+ auto future =
+ std::async(std::launch::async,
+ [&verifier, &progress]() -> std::optional<DiscIO::VolumeVerifier::Result> {
+ progress.SetValue(0);
+ verifier.Start();
+ while (verifier.GetBytesProcessed() != verifier.GetTotalBytes())
+ {
+ progress.SetValue(static_cast<int>(verifier.GetBytesProcessed() / DIVISOR));
+ if (progress.WasCanceled())
+ return std::nullopt;
+
+ verifier.Process();
+ }
+ verifier.Finish();
+
+ const DiscIO::VolumeVerifier::Result result = verifier.GetResult();
+ progress.Reset();
+
+ return result;
+ });
+ progress.GetRaw()->exec();
+
+ std::optional<DiscIO::VolumeVerifier::Result> result = future.get();
+ if (!result)
+ return;
+
+ m_summary_text->setText(QString::fromStdString(result->summary_text));
+
+ m_problems->setRowCount(static_cast<int>(result->problems.size()));
for (int i = 0; i < m_problems->rowCount(); ++i)
{
- const DiscIO::VolumeVerifier::Problem problem = result.problems[i];
+ const DiscIO::VolumeVerifier::Problem problem = result->problems[i];
QString severity;
switch (problem.severity)
@@ -179,12 +192,12 @@ void VerifyWidget::Verify()
SetProblemCellText(i, 1, severity);
}
- SetHash(m_crc32_line_edit, result.hashes.crc32);
- SetHash(m_md5_line_edit, result.hashes.md5);
- SetHash(m_sha1_line_edit, result.hashes.sha1);
+ SetHash(m_crc32_line_edit, result->hashes.crc32);
+ SetHash(m_md5_line_edit, result->hashes.md5);
+ SetHash(m_sha1_line_edit, result->hashes.sha1);
if (m_redump_line_edit)
- m_redump_line_edit->setText(QString::fromStdString(result.redump.message));
+ m_redump_line_edit->setText(QString::fromStdString(result->redump.message));
}
void VerifyWidget::SetProblemCellText(int row, int column, QString text)
diff --git a/Source/Core/DolphinQt/DolphinQt.vcxproj b/Source/Core/DolphinQt/DolphinQt.vcxproj
index de228eba5f..1763c06300 100644
--- a/Source/Core/DolphinQt/DolphinQt.vcxproj
+++ b/Source/Core/DolphinQt/DolphinQt.vcxproj
@@ -181,6 +181,7 @@
<QtMoc Include="QtUtils\FileOpenEventFilter.h" />
<QtMoc Include="QtUtils\FlowLayout.h" />
<QtMoc Include="QtUtils\ModalMessageBox.h" />
+ <QtMoc Include="QtUtils\ParallelProgressDialog.h" />
<QtMoc Include="QtUtils\WindowActivationEventFilter.h" />
<QtMoc Include="QtUtils\WrapInScrollArea.h" />
<QtMoc Include="RenderWidget.h" />
@@ -282,6 +283,7 @@
<ClCompile Include="$(QtMocOutPrefix)NewBreakpointDialog.cpp" />
<ClCompile Include="$(QtMocOutPrefix)NewPatchDialog.cpp" />
<ClCompile Include="$(QtMocOutPrefix)PadMappingDialog.cpp" />
+ <ClCompile Include="$(QtMocOutPrefix)ParallelProgressDialog.cpp" />
<ClCompile Include="$(QtMocOutPrefix)PatchesWidget.cpp" />
<ClCompile Include="$(QtMocOutPrefix)PatchInstructionDialog.cpp" />
<ClCompile Include="$(QtMocOutPrefix)PathPane.cpp" />
@@ -541,4 +543,4 @@
<Message Text="Copy: @(BinaryFiles) -&gt; $(BinaryOutputDir)" Importance="High" />
<Copy SourceFiles="@(BinaryFiles)" DestinationFolder="$(BinaryOutputDir)" />
</Target>
-</Project>
+</Project> \ No newline at end of file
diff --git a/Source/Core/DolphinQt/GameList/GameList.cpp b/Source/Core/DolphinQt/GameList/GameList.cpp
index f15b20664f..a635bee291 100644
--- a/Source/Core/DolphinQt/GameList/GameList.cpp
+++ b/Source/Core/DolphinQt/GameList/GameList.cpp
@@ -6,6 +6,7 @@
#include <algorithm>
#include <cmath>
+#include <future>
#include <QDesktopServices>
#include <QDir>
@@ -20,7 +21,6 @@
#include <QListView>
#include <QMap>
#include <QMenu>
-#include <QProgressDialog>
#include <QShortcut>
#include <QSortFilterProxyModel>
#include <QTableView>
@@ -46,6 +46,7 @@
#include "DolphinQt/MenuBar.h"
#include "DolphinQt/QtUtils/DoubleClickEventFilter.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
+#include "DolphinQt/QtUtils/ParallelProgressDialog.h"
#include "DolphinQt/Resources.h"
#include "DolphinQt/Settings.h"
#include "DolphinQt/WiiUpdate.h"
@@ -577,34 +578,50 @@ void GameList::CompressISO(bool decompress)
}
}
- QProgressDialog progress_dialog(decompress ? tr("Decompressing...") : tr("Compressing..."),
- tr("Abort"), 0, 100, this);
- progress_dialog.setWindowModality(Qt::WindowModal);
- progress_dialog.setWindowFlags(progress_dialog.windowFlags() &
- ~Qt::WindowContextHelpButtonHint);
- progress_dialog.setWindowTitle(tr("Progress"));
+ ParallelProgressDialog progress_dialog(
+ decompress ? tr("Decompressing...") : tr("Compressing..."), tr("Abort"), 0, 100, this);
+ progress_dialog.GetRaw()->setWindowModality(Qt::WindowModal);
+ progress_dialog.GetRaw()->setWindowTitle(tr("Progress"));
- bool good;
+ std::future<bool> good;
if (decompress)
{
if (files.size() > 1)
- progress_dialog.setLabelText(tr("Decompressing...") + QLatin1Char{'\n'} +
- QFileInfo(QString::fromStdString(original_path)).fileName());
- good = DiscIO::DecompressBlobToFile(original_path, dst_path.toStdString(), &CompressCB,
- &progress_dialog);
+ {
+ progress_dialog.GetRaw()->setLabelText(
+ tr("Decompressing...") + QLatin1Char{'\n'} +
+ QFileInfo(QString::fromStdString(original_path)).fileName());
+ }
+
+ good = std::async(std::launch::async, [&] {
+ const bool good = DiscIO::DecompressBlobToFile(original_path, dst_path.toStdString(),
+ &CompressCB, &progress_dialog);
+ progress_dialog.Reset();
+ return good;
+ });
}
else
{
if (files.size() > 1)
- progress_dialog.setLabelText(tr("Compressing...") + QLatin1Char{'\n'} +
- QFileInfo(QString::fromStdString(original_path)).fileName());
- good = DiscIO::CompressFileToBlob(original_path, dst_path.toStdString(),
- file->GetPlatform() == DiscIO::Platform::WiiDisc ? 1 : 0,
- 16384, &CompressCB, &progress_dialog);
+ {
+ progress_dialog.GetRaw()->setLabelText(
+ tr("Compressing...") + QLatin1Char{'\n'} +
+ QFileInfo(QString::fromStdString(original_path)).fileName());
+ }
+
+ good = std::async(std::launch::async, [&] {
+ const bool good =
+ DiscIO::CompressFileToBlob(original_path, dst_path.toStdString(),
+ file->GetPlatform() == DiscIO::Platform::WiiDisc ? 1 : 0,
+ 16384, &CompressCB, &progress_dialog);
+ progress_dialog.Reset();
+ return good;
+ });
}
- if (!good)
+ progress_dialog.GetRaw()->exec();
+ if (!good.get())
{
QErrorMessage(this).showMessage(tr("Dolphin failed to complete the requested action."));
return;
@@ -937,10 +954,10 @@ static bool CompressCB(const std::string& text, float percent, void* ptr)
if (ptr == nullptr)
return false;
- auto* progress_dialog = static_cast<QProgressDialog*>(ptr);
+ auto* progress_dialog = static_cast<ParallelProgressDialog*>(ptr);
- progress_dialog->setValue(percent * 100);
- return !progress_dialog->wasCanceled();
+ progress_dialog->SetValue(percent * 100);
+ return !progress_dialog->WasCanceled();
}
void GameList::OnSectionResized(int index, int, int)
diff --git a/Source/Core/DolphinQt/Host.cpp b/Source/Core/DolphinQt/Host.cpp
index fc53954195..cb910854d1 100644
--- a/Source/Core/DolphinQt/Host.cpp
+++ b/Source/Core/DolphinQt/Host.cpp
@@ -6,7 +6,6 @@
#include <QAbstractEventDispatcher>
#include <QApplication>
-#include <QProgressDialog>
#include <imgui.h>
@@ -126,11 +125,6 @@ void Host_UpdateDisasmDialog()
QueueOnObject(QApplication::instance(), [] { emit Host::GetInstance()->UpdateDisasmDialog(); });
}
-void Host_UpdateProgressDialog(const char* caption, int position, int total)
-{
- emit Host::GetInstance()->UpdateProgressDialog(QString::fromUtf8(caption), position, total);
-}
-
void Host::RequestNotifyMapLoaded()
{
QueueOnObject(QApplication::instance(), [this] { emit NotifyMapLoaded(); });
diff --git a/Source/Core/DolphinQt/Host.h b/Source/Core/DolphinQt/Host.h
index 9a25d217a9..e1c44b91a2 100644
--- a/Source/Core/DolphinQt/Host.h
+++ b/Source/Core/DolphinQt/Host.h
@@ -33,7 +33,6 @@ signals:
void RequestTitle(const QString& title);
void RequestStop();
void RequestRenderSize(int w, int h);
- void UpdateProgressDialog(QString label, int position, int maximum);
void UpdateDisasmDialog();
void NotifyMapLoaded();
diff --git a/Source/Core/DolphinQt/MainWindow.cpp b/Source/Core/DolphinQt/MainWindow.cpp
index 6080457c5a..89a19b42ba 100644
--- a/Source/Core/DolphinQt/MainWindow.cpp
+++ b/Source/Core/DolphinQt/MainWindow.cpp
@@ -12,7 +12,6 @@
#include <QFileInfo>
#include <QIcon>
#include <QMimeData>
-#include <QProgressDialog>
#include <QStackedWidget>
#include <QVBoxLayout>
#include <QWindow>
@@ -87,6 +86,7 @@
#include "DolphinQt/NetPlay/NetPlaySetupDialog.h"
#include "DolphinQt/QtUtils/FileOpenEventFilter.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
+#include "DolphinQt/QtUtils/ParallelProgressDialog.h"
#include "DolphinQt/QtUtils/QueueOnObject.h"
#include "DolphinQt/QtUtils/RunOnObject.h"
#include "DolphinQt/QtUtils/WindowActivationEventFilter.h"
@@ -615,8 +615,6 @@ void MainWindow::ConnectRenderWidget()
void MainWindow::ConnectHost()
{
- connect(Host::GetInstance(), &Host::UpdateProgressDialog, this,
- &MainWindow::OnUpdateProgressDialog);
connect(Host::GetInstance(), &Host::RequestStop, this, &MainWindow::RequestStop);
}
@@ -1510,23 +1508,21 @@ void MainWindow::OnImportNANDBackup()
if (file.isEmpty())
return;
- QProgressDialog* dialog = new QProgressDialog(this);
- dialog->setMinimum(0);
- dialog->setMaximum(0);
- dialog->setLabelText(tr("Importing NAND backup"));
- dialog->setCancelButton(nullptr);
+ ParallelProgressDialog dialog(this);
+ dialog.GetRaw()->setMinimum(0);
+ dialog.GetRaw()->setMaximum(0);
+ dialog.GetRaw()->setLabelText(tr("Importing NAND backup"));
+ dialog.GetRaw()->setCancelButton(nullptr);
auto beginning = QDateTime::currentDateTime().toMSecsSinceEpoch();
- auto result = std::async(std::launch::async, [&] {
+ std::future<void> result = std::async(std::launch::async, [&] {
DiscIO::NANDImporter().ImportNANDBin(
file.toStdString(),
[&dialog, beginning] {
- QueueOnObject(dialog, [&dialog, beginning] {
- dialog->setLabelText(
- tr("Importing NAND backup\n Time elapsed: %1s")
- .arg((QDateTime::currentDateTime().toMSecsSinceEpoch() - beginning) / 1000));
- });
+ dialog.SetLabelText(
+ tr("Importing NAND backup\n Time elapsed: %1s")
+ .arg((QDateTime::currentDateTime().toMSecsSinceEpoch() - beginning) / 1000));
},
[this] {
std::optional<std::string> keys_file = RunOnObject(this, [this] {
@@ -1540,10 +1536,10 @@ void MainWindow::OnImportNANDBackup()
return *keys_file;
return std::string("");
});
- QueueOnObject(dialog, &QProgressDialog::close);
+ dialog.Reset();
});
- dialog->exec();
+ dialog.GetRaw()->exec();
result.wait();
@@ -1703,28 +1699,6 @@ void MainWindow::ShowCheatsManager()
m_cheats_manager->show();
}
-void MainWindow::OnUpdateProgressDialog(QString title, int progress, int total)
-{
- if (!m_progress_dialog)
- {
- m_progress_dialog = new QProgressDialog(m_render_widget, Qt::WindowTitleHint);
- m_progress_dialog->show();
- m_progress_dialog->setCancelButton(nullptr);
- m_progress_dialog->setWindowTitle(tr("Dolphin"));
- }
-
- m_progress_dialog->setValue(progress);
- m_progress_dialog->setLabelText(title);
- m_progress_dialog->setMaximum(total);
-
- if (total < 0 || progress >= total)
- {
- m_progress_dialog->hide();
- m_progress_dialog->deleteLater();
- m_progress_dialog = nullptr;
- }
-}
-
void MainWindow::Show()
{
if (!Settings::Instance().IsBatchModeEnabled())
diff --git a/Source/Core/DolphinQt/MainWindow.h b/Source/Core/DolphinQt/MainWindow.h
index acc93df540..50fea52a24 100644
--- a/Source/Core/DolphinQt/MainWindow.h
+++ b/Source/Core/DolphinQt/MainWindow.h
@@ -11,7 +11,6 @@
#include <optional>
#include <string>
-class QProgressDialog;
class QStackedWidget;
class QString;
@@ -167,8 +166,6 @@ private:
void OnSignal();
#endif
- void OnUpdateProgressDialog(QString label, int progress, int total);
-
void OnPlayRecording();
void OnStartRecording();
void OnStopRecording();
@@ -193,7 +190,6 @@ private:
std::unique_ptr<X11Utils::XRRConfiguration> m_xrr_config;
#endif
- QProgressDialog* m_progress_dialog = nullptr;
QStackedWidget* m_stack;
ToolBar* m_tool_bar;
MenuBar* m_menu_bar;
diff --git a/Source/Core/DolphinQt/NetPlay/NetPlayDialog.cpp b/Source/Core/DolphinQt/NetPlay/NetPlayDialog.cpp
index 31abe2f384..230823b8b6 100644
--- a/Source/Core/DolphinQt/NetPlay/NetPlayDialog.cpp
+++ b/Source/Core/DolphinQt/NetPlay/NetPlayDialog.cpp
@@ -14,7 +14,6 @@
#include <QLabel>
#include <QLineEdit>
#include <QMenu>
-#include <QProgressDialog>
#include <QPushButton>
#include <QSignalBlocker>
#include <QSpinBox>
diff --git a/Source/Core/DolphinQt/QtUtils/ParallelProgressDialog.h b/Source/Core/DolphinQt/QtUtils/ParallelProgressDialog.h
new file mode 100644
index 0000000000..274e3d4b11
--- /dev/null
+++ b/Source/Core/DolphinQt/QtUtils/ParallelProgressDialog.h
@@ -0,0 +1,108 @@
+#pragma once
+
+#include <chrono>
+#include <utility>
+
+#include <QObject>
+#include <QProgressDialog>
+#include <QString>
+
+#include "Common/Flag.h"
+
+class ParallelProgressDialog final : public QObject
+{
+ Q_OBJECT
+
+public:
+ // Only use this from the main thread
+ template <typename... Args>
+ ParallelProgressDialog(Args&&... args) : m_dialog{std::forward<Args>(args)...}
+ {
+ setParent(m_dialog.parent());
+ m_dialog.setWindowFlags(m_dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ ConnectSignalsAndSlots();
+ }
+
+ // Only use this from the main thread
+ QProgressDialog* GetRaw() { return &m_dialog; }
+
+ // All of the following can be called from any thread
+ void Cancel() { emit CancelSignal(); }
+ void Reset() { emit ResetSignal(); }
+ void SetCancelButtonText(const QString& text) { emit SetCancelButtonText(text); }
+ void SetLabelText(const QString& text) { emit SetLabelTextSignal(text); }
+ void SetMaximum(int maximum) { emit SetMaximumSignal(maximum); }
+ void SetMinimum(int minimum) { emit SetMinimumSignal(minimum); }
+ void SetMinimumDuration(int ms) { emit SetMinimumDurationSignal(ms); }
+ void SetRange(int minimum, int maximum) { emit SetRangeSignal(minimum, maximum); }
+
+ // Can be called from any thread, but only from one thread at a time
+ void SetValue(int progress)
+ {
+ // HACK: To avoid the https://bugreports.qt.io/browse/QTBUG-10561 stack overflow,
+ // limit how often QProgressDialog::setValue can run
+ const auto current_time = std::chrono::steady_clock::now();
+ if (current_time - m_last_setvalue_time >= std::chrono::milliseconds(50))
+ {
+ m_last_setvalue_time = current_time;
+ emit SetValueSignal(progress);
+ }
+ }
+
+ // Can be called from any thread
+ bool WasCanceled() { return m_was_cancelled.IsSet(); }
+
+signals:
+ void CancelSignal();
+ void ResetSignal();
+ void SetCancelButtonTextSignal(const QString& cancel_button_text);
+ void SetLabelTextSignal(const QString& text);
+ void SetMaximumSignal(int maximum);
+ void SetMinimumSignal(int minimum);
+ void SetMinimumDurationSignal(int ms);
+ void SetRangeSignal(int minimum, int maximum);
+ void SetValueSignal(int progress);
+
+ void Canceled();
+ void Finished(int result);
+
+private slots:
+ void OnCancelled() { m_was_cancelled.Set(); }
+
+private:
+ template <typename Func1, typename Func2>
+ void ConnectSignal(Func1 signal, Func2 slot)
+ {
+ QObject::connect(this, signal, &m_dialog, slot);
+ }
+
+ template <typename Func1, typename Func2>
+ void ConnectSlot(Func1 signal, Func2 slot)
+ {
+ QObject::connect(&m_dialog, signal, this, slot);
+ }
+
+ void ConnectSignalsAndSlots()
+ {
+ ConnectSignal(&ParallelProgressDialog::CancelSignal, &QProgressDialog::cancel);
+ ConnectSignal(&ParallelProgressDialog::ResetSignal, &QProgressDialog::reset);
+ ConnectSignal(&ParallelProgressDialog::SetCancelButtonTextSignal,
+ &QProgressDialog::setCancelButtonText);
+ ConnectSignal(&ParallelProgressDialog::SetLabelTextSignal, &QProgressDialog::setLabelText);
+ ConnectSignal(&ParallelProgressDialog::SetMaximumSignal, &QProgressDialog::setMaximum);
+ ConnectSignal(&ParallelProgressDialog::SetMinimumSignal, &QProgressDialog::setMinimum);
+ ConnectSignal(&ParallelProgressDialog::SetMinimumDurationSignal,
+ &QProgressDialog::setMinimumDuration);
+ ConnectSignal(&ParallelProgressDialog::SetRangeSignal, &QProgressDialog::setRange);
+ ConnectSignal(&ParallelProgressDialog::SetValueSignal, &QProgressDialog::setValue);
+
+ ConnectSlot(&QProgressDialog::canceled, &ParallelProgressDialog::OnCancelled);
+
+ ConnectSlot(&QProgressDialog::canceled, &ParallelProgressDialog::Canceled);
+ ConnectSlot(&QProgressDialog::finished, &ParallelProgressDialog::Finished);
+ }
+
+ QProgressDialog m_dialog;
+ Common::Flag m_was_cancelled;
+ std::chrono::time_point<std::chrono::steady_clock> m_last_setvalue_time;
+};
diff --git a/Source/DSPTool/StubHost.cpp b/Source/DSPTool/StubHost.cpp
index 75dd66296d..488a49d2cd 100644
--- a/Source/DSPTool/StubHost.cpp
+++ b/Source/DSPTool/StubHost.cpp
@@ -45,9 +45,6 @@ bool Host_RendererIsFullscreen()
void Host_YieldToUI()
{
}
-void Host_UpdateProgressDialog(const char* caption, int position, int total)
-{
-}
void Host_TitleChanged()
{
}
diff --git a/Source/UnitTests/StubHost.cpp b/Source/UnitTests/StubHost.cpp
index 4fa45ef1c2..211ee8bfba 100644
--- a/Source/UnitTests/StubHost.cpp
+++ b/Source/UnitTests/StubHost.cpp
@@ -46,9 +46,6 @@ bool Host_RendererIsFullscreen()
void Host_YieldToUI()
{
}
-void Host_UpdateProgressDialog(const char* caption, int position, int total)
-{
-}
void Host_TitleChanged()
{
}