mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-06-13 00:58:29 +02:00
DolphinQt: Run tasks that use progress dialogs on separate threads
This commit is contained in:
108
Source/Core/DolphinQt/QtUtils/ParallelProgressDialog.h
Normal file
108
Source/Core/DolphinQt/QtUtils/ParallelProgressDialog.h
Normal file
@ -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;
|
||||
};
|
Reference in New Issue
Block a user