Qt: Work around broken dialogs in MacOS 26

pull/3575/head
Stenzek 2 months ago
parent 1e41408753
commit ceb6757524
No known key found for this signature in database

@ -20,6 +20,7 @@ AchievementLoginDialog::AchievementLoginDialog(QWidget* parent, Achievements::Lo
title_font.setPixelSize(20); title_font.setPixelSize(20);
m_ui.titleLabel->setFont(title_font); m_ui.titleLabel->setFont(title_font);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setAttribute(Qt::WA_DeleteOnClose, true);
// Adjust text if needed based on reason. // Adjust text if needed based on reason.
if (reason == Achievements::LoginRequestReason::TokenInvalid) if (reason == Achievements::LoginRequestReason::TokenInvalid)

@ -237,10 +237,13 @@ void AchievementSettingsWidget::onLoginLogoutPressed()
return; return;
} }
AchievementLoginDialog login(this, Achievements::LoginRequestReason::UserInitiated); AchievementLoginDialog* login = new AchievementLoginDialog(this, Achievements::LoginRequestReason::UserInitiated);
if (login.exec() == QDialog::Rejected) connect(login, &AchievementLoginDialog::accepted, this, &AchievementSettingsWidget::onLoginCompleted);
return; login->show();
}
void AchievementSettingsWidget::onLoginCompleted()
{
updateLoginState(); updateLoginState();
// Login can enable achievements/hardcore. // Login can enable achievements/hardcore.

@ -23,6 +23,7 @@ private:
void onAchievementsNotificationDurationSliderChanged(); void onAchievementsNotificationDurationSliderChanged();
void onLeaderboardsNotificationDurationSliderChanged(); void onLeaderboardsNotificationDurationSliderChanged();
void onLoginLogoutPressed(); void onLoginLogoutPressed();
void onLoginCompleted();
void onViewProfilePressed(); void onViewProfilePressed();
void onAchievementsRefreshed(quint32 id, const QString& game_info_string); void onAchievementsRefreshed(quint32 id, const QString& game_info_string);

@ -189,15 +189,14 @@ void ConsoleSettingsWidget::onEnableCPUClockSpeedControlChecked(int state)
"system requirements.\n\nBy enabling this option you are agreeing to not create any bug reports unless you " "system requirements.\n\nBy enabling this option you are agreeing to not create any bug reports unless you "
"have confirmed the bug also occurs with overclocking disabled.\n\nThis warning will only be shown once."); "have confirmed the bug also occurs with overclocking disabled.\n\nThis warning will only be shown once.");
QMessageBox mb(QMessageBox::Warning, tr("CPU Overclocking Warning"), message, QMessageBox::NoButton, this); QMessageBox* mb =
mb.setWindowModality(Qt::WindowModal); new QMessageBox(QMessageBox::Warning, tr("CPU Overclocking Warning"), message, QMessageBox::NoButton, this);
const QAbstractButton* const yes_button = mb->setAttribute(Qt::WA_DeleteOnClose, true);
mb.addButton(tr("Yes, I will confirm bugs without overclocking before reporting."), QMessageBox::YesRole); mb->setWindowModality(Qt::WindowModal);
mb.addButton(tr("No, take me back to safety."), QMessageBox::NoRole); const QPushButton* const yes_button =
mb.exec(); mb->addButton(tr("Yes, I will confirm bugs without overclocking before reporting."), QMessageBox::YesRole);
const QPushButton* const no_button = mb->addButton(tr("No, take me back to safety."), QMessageBox::NoRole);
if (mb.clickedButton() != yes_button) connect(no_button, &QPushButton::clicked, this, [this]() {
{
QSignalBlocker sb(m_ui.enableCPUClockSpeedControl); QSignalBlocker sb(m_ui.enableCPUClockSpeedControl);
if (m_dialog->isPerGameSettings()) if (m_dialog->isPerGameSettings())
{ {
@ -210,11 +209,14 @@ void ConsoleSettingsWidget::onEnableCPUClockSpeedControlChecked(int state)
m_dialog->setBoolSettingValue("CPU", "OverclockEnable", false); m_dialog->setBoolSettingValue("CPU", "OverclockEnable", false);
} }
return; m_ui.cpuClockSpeed->setEnabled(m_dialog->getEffectiveBoolValue("CPU", "OverclockEnable", false));
} updateCPUClockSpeedLabel();
});
connect(yes_button, &QPushButton::clicked, this, []() {
Host::SetBaseBoolSettingValue("UI", "CPUOverclockingWarningShown", true); Host::SetBaseBoolSettingValue("UI", "CPUOverclockingWarningShown", true);
Host::CommitBaseSettingChanges(); Host::CommitBaseSettingChanges();
});
mb->show();
} }
m_ui.cpuClockSpeed->setEnabled(m_dialog->getEffectiveBoolValue("CPU", "OverclockEnable", false)); m_ui.cpuClockSpeed->setEnabled(m_dialog->getEffectiveBoolValue("CPU", "OverclockEnable", false));

@ -373,22 +373,23 @@ void GameSummaryWidget::populateTracksInfo()
void GameSummaryWidget::onCompatibilityCommentsClicked() void GameSummaryWidget::onCompatibilityCommentsClicked()
{ {
QDialog dlg(QtUtils::GetRootWidget(this)); QDialog* dlg = new QDialog(QtUtils::GetRootWidget(this));
dlg.resize(QSize(700, 400)); dlg->resize(QSize(700, 400));
dlg.setWindowModality(Qt::WindowModal); dlg->setWindowModality(Qt::WindowModal);
dlg.setWindowTitle(tr("Compatibility Report")); dlg->setWindowTitle(tr("Compatibility Report"));
dlg->setAttribute(Qt::WA_DeleteOnClose, true);
QVBoxLayout* layout = new QVBoxLayout(&dlg); QVBoxLayout* layout = new QVBoxLayout(dlg);
QTextBrowser* tb = new QTextBrowser(&dlg); QTextBrowser* tb = new QTextBrowser(dlg);
tb->setMarkdown(m_compatibility_comments); tb->setMarkdown(m_compatibility_comments);
layout->addWidget(tb, 1); layout->addWidget(tb, 1);
QDialogButtonBox* bb = new QDialogButtonBox(QDialogButtonBox::Close, &dlg); QDialogButtonBox* bb = new QDialogButtonBox(QDialogButtonBox::Close, dlg);
connect(bb, &QDialogButtonBox::rejected, &dlg, &QDialog::accept); connect(bb, &QDialogButtonBox::rejected, dlg, &QDialog::accept);
layout->addWidget(bb); layout->addWidget(bb);
dlg.exec(); dlg->show();
} }
void GameSummaryWidget::onInputProfileChanged(int index) void GameSummaryWidget::onInputProfileChanged(int index)

@ -401,10 +401,11 @@ void InputBindingWidget::unhookInputManager()
void InputBindingWidget::openDialog() void InputBindingWidget::openDialog()
{ {
InputBindingDialog binding_dialog(m_sif, m_bind_type, m_section_name, m_key_name, m_bindings, InputBindingDialog* dlg =
QtUtils::GetRootWidget(this)); new InputBindingDialog(m_sif, m_bind_type, m_section_name, m_key_name, m_bindings, QtUtils::GetRootWidget(this));
binding_dialog.exec(); dlg->setAttribute(Qt::WA_DeleteOnClose, true);
reloadBinding(); connect(dlg, &InputBindingDialog::finished, this, &InputBindingWidget::reloadBinding);
dlg->show();
} }
InputVibrationBindingWidget::InputVibrationBindingWidget(QWidget* parent) InputVibrationBindingWidget::InputVibrationBindingWidget(QWidget* parent)

@ -1141,51 +1141,47 @@ std::shared_ptr<SystemBootParameters> MainWindow::getSystemBootParameters(std::s
return ret; return ret;
} }
std::optional<bool> MainWindow::promptForResumeState(const std::string& save_state_path) bool MainWindow::openResumeStateDialog(const std::string& path, const std::string& serial)
{ {
System::FlushSaveStates(); System::FlushSaveStates();
FILESYSTEM_STAT_DATA sd; FILESYSTEM_STAT_DATA sd;
std::string save_state_path = System::GetGameSaveStatePath(serial, -1);
if (save_state_path.empty() || !FileSystem::StatFile(save_state_path.c_str(), &sd)) if (save_state_path.empty() || !FileSystem::StatFile(save_state_path.c_str(), &sd))
return false; return false;
QMessageBox msgbox(this); QMessageBox* msgbox = new QMessageBox(this);
msgbox.setIcon(QMessageBox::Question); msgbox->setIcon(QMessageBox::Question);
msgbox.setWindowTitle(tr("Load Resume State")); msgbox->setWindowTitle(tr("Load Resume State"));
msgbox.setWindowModality(Qt::WindowModal); msgbox->setWindowModality(Qt::WindowModal);
msgbox.setText( msgbox->setAttribute(Qt::WA_DeleteOnClose, true);
msgbox->setText(
tr("A resume save state was found for this game, saved at:\n\n%1.\n\nDo you want to load this state, " tr("A resume save state was found for this game, saved at:\n\n%1.\n\nDo you want to load this state, "
"or start from a fresh boot?") "or start from a fresh boot?")
.arg(QtHost::FormatNumber(Host::NumberFormatType::LongDateTime, static_cast<s64>(sd.ModificationTime)))); .arg(QtHost::FormatNumber(Host::NumberFormatType::LongDateTime, static_cast<s64>(sd.ModificationTime))));
QPushButton* load = msgbox.addButton(tr("Load State"), QMessageBox::AcceptRole); QPushButton* load = msgbox->addButton(tr("Load State"), QMessageBox::AcceptRole);
QPushButton* boot = msgbox.addButton(tr("Fresh Boot"), QMessageBox::RejectRole); QPushButton* boot = msgbox->addButton(tr("Fresh Boot"), QMessageBox::RejectRole);
QPushButton* delboot = msgbox.addButton(tr("Delete And Boot"), QMessageBox::RejectRole); QPushButton* delboot = msgbox->addButton(tr("Delete And Boot"), QMessageBox::RejectRole);
msgbox.addButton(QMessageBox::Cancel); msgbox->addButton(QMessageBox::Cancel);
msgbox.setDefaultButton(load); msgbox->setDefaultButton(load);
msgbox.exec();
QAbstractButton* clicked = msgbox.clickedButton(); connect(load, &QPushButton::clicked, [this, path, save_state_path]() mutable {
if (load == clicked) startFile(std::move(path), std::move(save_state_path), std::nullopt);
{ });
return true; connect(boot, &QPushButton::clicked,
} [this, path]() mutable { startFile(std::move(path), std::nullopt, std::nullopt); });
else if (boot == clicked) connect(delboot, &QPushButton::clicked, [this, path, save_state_path]() mutable {
{
return false;
}
else if (delboot == clicked)
{
if (!FileSystem::DeleteFile(save_state_path.c_str())) if (!FileSystem::DeleteFile(save_state_path.c_str()))
{ {
QMessageBox::critical(this, tr("Error"), QMessageBox::critical(this, tr("Error"),
tr("Failed to delete save state file '%1'.").arg(QString::fromStdString(save_state_path))); tr("Failed to delete save state file '%1'.").arg(QString::fromStdString(save_state_path)));
} }
startFile(std::move(path), std::nullopt, std::nullopt);
});
return false; msgbox->show();
} return true;
return std::nullopt;
} }
void MainWindow::startFile(std::string path, std::optional<std::string> save_path, std::optional<bool> fast_boot) void MainWindow::startFile(std::string path, std::optional<std::string> save_path, std::optional<bool> fast_boot)
@ -1198,34 +1194,24 @@ void MainWindow::startFile(std::string path, std::optional<std::string> save_pat
g_emu_thread->bootSystem(std::move(params)); g_emu_thread->bootSystem(std::move(params));
} }
void MainWindow::startFileOrChangeDisc(const QString& path) void MainWindow::startFileOrChangeDisc(const QString& qpath)
{ {
if (s_system_valid) if (s_system_valid)
{ {
// this is a disc change // this is a disc change
promptForDiscChange(path); promptForDiscChange(qpath);
return; return;
} }
// try to find the serial for the game std::string path = qpath.toStdString();
std::string path_str(path.toStdString());
std::string serial(GameDatabase::GetSerialForPath(path_str.c_str()));
std::optional<std::string> save_path;
if (!serial.empty())
{ {
std::string resume_path(System::GetGameSaveStatePath(serial.c_str(), -1)); const auto lock = GameList::GetLock();
std::optional<bool> resume = promptForResumeState(resume_path); const GameList::Entry* entry = GameList::GetEntryForPath(path);
if (!resume.has_value()) if (entry && !entry->serial.empty() && openResumeStateDialog(entry->path, entry->serial))
{
// cancelled
return; return;
} }
else if (resume.value())
save_path = std::move(resume_path);
}
// only resume if the option is enabled, and we have one for this game startFile(std::move(path), std::nullopt, std::nullopt);
startFile(std::move(path_str), std::move(save_path), std::nullopt);
} }
void MainWindow::promptForDiscChange(const QString& path) void MainWindow::promptForDiscChange(const QString& path)
@ -1557,22 +1543,11 @@ void MainWindow::onGameListEntryActivated()
return; return;
} }
std::optional<std::string> save_path; if (!entry->serial.empty() && openResumeStateDialog(entry->path, entry->serial))
if (!entry->serial.empty())
{
std::string resume_path(System::GetGameSaveStatePath(entry->serial.c_str(), -1));
std::optional<bool> resume = promptForResumeState(resume_path);
if (!resume.has_value())
{
// cancelled
return; return;
}
else if (resume.value())
save_path = std::move(resume_path);
}
// only resume if the option is enabled, and we have one for this game // only resume if the option is enabled, and we have one for this game
startFile(entry->path, std::move(save_path), std::nullopt); startFile(entry->path, std::nullopt, std::nullopt);
} }
void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point) void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
@ -2991,27 +2966,36 @@ void MainWindow::requestShutdown(bool allow_confirm, bool allow_save_to_state, b
SystemLock lock(pauseAndLockSystem()); SystemLock lock(pauseAndLockSystem());
QMessageBox msgbox(lock.getDialogParent()); QMessageBox* msgbox = new QMessageBox(lock.getDialogParent());
msgbox.setIcon(QMessageBox::Question); msgbox->setWindowTitle(tr("Confirm Shutdown"));
msgbox.setWindowTitle(tr("Confirm Shutdown")); msgbox->setWindowModality(Qt::WindowModal);
msgbox.setWindowModality(Qt::WindowModal); msgbox->setAttribute(Qt::WA_DeleteOnClose, true);
msgbox.setText(tr("Are you sure you want to shut down the virtual machine?")); msgbox->setIcon(QMessageBox::Question);
msgbox->setText(tr("Are you sure you want to shut down the virtual machine?"));
QCheckBox* save_cb = new QCheckBox(tr("Save State For Resume"), &msgbox); QCheckBox* const save_cb = new QCheckBox(tr("Save State For Resume"), msgbox);
save_cb->setChecked(allow_save_to_state && save_state); save_cb->setChecked(allow_save_to_state && save_state);
save_cb->setEnabled(allow_save_to_state); save_cb->setEnabled(allow_save_to_state);
msgbox.setCheckBox(save_cb); msgbox->setCheckBox(save_cb);
msgbox.addButton(QMessageBox::Yes); msgbox->addButton(QMessageBox::Yes);
msgbox.addButton(QMessageBox::No); msgbox->addButton(QMessageBox::No);
msgbox.setDefaultButton(QMessageBox::Yes); msgbox->setDefaultButton(QMessageBox::Yes);
if (msgbox.exec() != QMessageBox::Yes) connect(msgbox, &QMessageBox::finished, this,
[this, lock = std::move(lock), save_cb, allow_save_to_state, check_safety, check_pause, exit_fullscreen_ui,
quit_afterwards](int result) mutable {
if (result != QMessageBox::Yes)
return; return;
save_state = save_cb->isChecked();
// Don't switch back to fullscreen when we're shutting down anyway. // Don't switch back to fullscreen when we're shutting down anyway.
if (!QtHost::IsFullscreenUIStarted()) if (!QtHost::IsFullscreenUIStarted())
lock.cancelResume(); lock.cancelResume();
const bool save_state = save_cb->isChecked();
requestShutdown(false, allow_save_to_state, save_state, check_safety, check_pause, exit_fullscreen_ui,
quit_afterwards);
});
msgbox->show();
return;
} }
// If we're running in batch mode, don't show the main window after shutting down. // If we're running in batch mode, don't show the main window after shutting down.
@ -3134,10 +3118,11 @@ void MainWindow::openMemoryCardEditor(const QString& card_a_path, const QString&
void MainWindow::onAchievementsLoginRequested(Achievements::LoginRequestReason reason) void MainWindow::onAchievementsLoginRequested(Achievements::LoginRequestReason reason)
{ {
const auto lock = pauseAndLockSystem(); auto lock = pauseAndLockSystem();
AchievementLoginDialog dlg(lock.getDialogParent(), reason); AchievementLoginDialog* dlg = new AchievementLoginDialog(lock.getDialogParent(), reason);
dlg.exec(); connect(dlg, &AchievementLoginDialog::finished, this, [lock = std::move(lock)]() {});
dlg->show();
} }
void MainWindow::onAchievementsLoginSuccess(const QString& username, quint32 points, quint32 sc_points, void MainWindow::onAchievementsLoginSuccess(const QString& username, quint32 points, quint32 sc_points,
@ -3335,7 +3320,6 @@ void MainWindow::checkForUpdates(bool display_message)
{ {
QMessageBox mbox(this); QMessageBox mbox(this);
mbox.setWindowTitle(tr("Updater Error")); mbox.setWindowTitle(tr("Updater Error"));
mbox.setWindowModality(Qt::WindowModal);
mbox.setTextFormat(Qt::RichText); mbox.setTextFormat(Qt::RichText);
QString message; QString message;
@ -3440,20 +3424,26 @@ MainWindow::SystemLock MainWindow::pauseAndLockSystem()
} }
MainWindow::SystemLock::SystemLock(QWidget* dialog_parent, bool was_paused, bool was_fullscreen) MainWindow::SystemLock::SystemLock(QWidget* dialog_parent, bool was_paused, bool was_fullscreen)
: m_dialog_parent(dialog_parent), m_was_paused(was_paused), m_was_fullscreen(was_fullscreen) : m_dialog_parent(dialog_parent), m_was_paused(was_paused), m_was_fullscreen(was_fullscreen), m_valid(true)
{ {
} }
MainWindow::SystemLock::SystemLock(SystemLock&& lock) MainWindow::SystemLock::SystemLock(SystemLock&& lock)
: m_dialog_parent(lock.m_dialog_parent), m_was_paused(lock.m_was_paused), m_was_fullscreen(lock.m_was_fullscreen) : m_dialog_parent(lock.m_dialog_parent), m_was_paused(lock.m_was_paused), m_was_fullscreen(lock.m_was_fullscreen),
m_valid(true)
{ {
Assert(lock.m_valid);
lock.m_dialog_parent = nullptr; lock.m_dialog_parent = nullptr;
lock.m_was_paused = true; lock.m_was_paused = true;
lock.m_was_fullscreen = false; lock.m_was_fullscreen = false;
lock.m_valid = false;
} }
MainWindow::SystemLock::~SystemLock() MainWindow::SystemLock::~SystemLock()
{ {
if (!m_valid)
return;
DebugAssert(s_system_locked.load(std::memory_order_relaxed) > 0); DebugAssert(s_system_locked.load(std::memory_order_relaxed) > 0);
s_system_locked.fetch_sub(1, std::memory_order_release); s_system_locked.fetch_sub(1, std::memory_order_release);
if (m_was_fullscreen) if (m_was_fullscreen)

@ -73,6 +73,7 @@ public:
QWidget* m_dialog_parent; QWidget* m_dialog_parent;
bool m_was_paused; bool m_was_paused;
bool m_was_fullscreen; bool m_was_fullscreen;
bool m_valid;
}; };
public: public:
@ -214,9 +215,9 @@ private:
const GameList::Entry* resolveDiscSetEntry(const GameList::Entry* entry, const GameList::Entry* resolveDiscSetEntry(const GameList::Entry* entry,
std::unique_lock<std::recursive_mutex>& lock); std::unique_lock<std::recursive_mutex>& lock);
std::shared_ptr<SystemBootParameters> getSystemBootParameters(std::string file); std::shared_ptr<SystemBootParameters> getSystemBootParameters(std::string file);
std::optional<bool> promptForResumeState(const std::string& save_state_path); bool openResumeStateDialog(const std::string& path, const std::string& serial);
void startFile(std::string path, std::optional<std::string> save_path, std::optional<bool> fast_boot); void startFile(std::string path, std::optional<std::string> save_path, std::optional<bool> fast_boot);
void startFileOrChangeDisc(const QString& path); void startFileOrChangeDisc(const QString& qpath);
void promptForDiscChange(const QString& path); void promptForDiscChange(const QString& path);
std::optional<WindowInfo> acquireRenderWindow(RenderAPI render_api, bool fullscreen, bool exclusive_fullscreen, std::optional<WindowInfo> acquireRenderWindow(RenderAPI render_api, bool fullscreen, bool exclusive_fullscreen,

@ -651,11 +651,13 @@ void SetupWizardDialog::onAchievementsLoginLogoutClicked()
return; return;
} }
AchievementLoginDialog login(this, Achievements::LoginRequestReason::UserInitiated); AchievementLoginDialog* login = new AchievementLoginDialog(this, Achievements::LoginRequestReason::UserInitiated);
int res = login.exec(); connect(login, &AchievementLoginDialog::accepted, this, &SetupWizardDialog::onAchievementsLoginCompleted);
if (res == QDialog::Rejected) login->show();
return; }
void SetupWizardDialog::onAchievementsLoginCompleted()
{
updateAchievementsEnableState(); updateAchievementsEnableState();
updateAchievementsLoginState(); updateAchievementsLoginState();

@ -74,6 +74,7 @@ private:
void onGraphicsAspectRatioChanged(); void onGraphicsAspectRatioChanged();
void onAchievementsLoginLogoutClicked(); void onAchievementsLoginLogoutClicked();
void onAchievementsLoginCompleted();
void onAchievementsViewProfileClicked(); void onAchievementsViewProfileClicked();
void updateAchievementsEnableState(); void updateAchievementsEnableState();
void updateAchievementsLoginState(); void updateAchievementsLoginState();

Loading…
Cancel
Save