From 0f29a5be9fc6700a50b2743f79377eb8ec7e1b71 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Tue, 12 Mar 2024 22:45:40 +0100 Subject: [PATCH] Qt: replace refresh progress slot with timer For some reason setValue crashes in the progressValueChanged slot for no apparent reason --- rpcs3/rpcs3qt/game_list_frame.cpp | 70 +++++++++++++++++-------------- rpcs3/rpcs3qt/game_list_frame.h | 4 +- rpcs3/rpcs3qt/progress_dialog.cpp | 4 +- 3 files changed, 44 insertions(+), 34 deletions(-) diff --git a/rpcs3/rpcs3qt/game_list_frame.cpp b/rpcs3/rpcs3qt/game_list_frame.cpp index 665cbbd895..aa3a39c2f8 100644 --- a/rpcs3/rpcs3qt/game_list_frame.cpp +++ b/rpcs3/rpcs3qt/game_list_frame.cpp @@ -75,14 +75,23 @@ game_list_frame::game_list_frame(std::shared_ptr gui_settings, std m_gui_settings->SetValue(gui::gl_textFactor, m_text_factor); // Only show the progress dialog after some time has passed - m_progress_dialog_timer = new QTimer(this); - m_progress_dialog_timer->setSingleShot(true); - m_progress_dialog_timer->setInterval(200); - connect(m_progress_dialog_timer, &QTimer::timeout, this, [this]() + m_progress_dialog_timer.setSingleShot(true); + m_progress_dialog_timer.setInterval(200); + connect(&m_progress_dialog_timer, &QTimer::timeout, this, [this]() { if (m_progress_dialog) { m_progress_dialog->show(); + m_progress_dialog_update_timer.start(); + } + }); + + m_progress_dialog_update_timer.setInterval(16); + connect(&m_progress_dialog_update_timer, &QTimer::timeout, this, [this]() + { + if (m_progress_dialog) + { + m_progress_dialog->SetValue(m_progress_dialog_value); } }); @@ -163,10 +172,12 @@ game_list_frame::game_list_frame(std::shared_ptr gui_settings, std m_serials.clear(); m_games.pop_all(); - if (m_progress_dialog) + m_progress_dialog_update_timer.stop(); + + if (progress_dialog* dlg = m_progress_dialog) { - m_progress_dialog->accept(); - m_progress_dialog = nullptr; + m_progress_dialog = nullptr; // Clear first to avoid further slots + dlg->accept(); } }); connect(&m_refresh_watcher, &QFutureWatcher::progressRangeChanged, this, [this](int minimum, int maximum) @@ -175,14 +186,11 @@ game_list_frame::game_list_frame(std::shared_ptr gui_settings, std { m_progress_dialog->SetRange(minimum, maximum); } - }, Qt::QueuedConnection); + }); connect(&m_refresh_watcher, &QFutureWatcher::progressValueChanged, this, [this](int value) { - if (m_progress_dialog) - { - m_progress_dialog->SetValue(value); - } - }, Qt::QueuedConnection); + m_progress_dialog_value = value; + }); connect(m_game_list, &QTableWidget::customContextMenuRequested, this, &game_list_frame::ShowContextMenu); connect(m_game_list, &QTableWidget::itemSelectionChanged, this, &game_list_frame::ItemSelectionChangedSlot); @@ -314,16 +322,14 @@ void game_list_frame::Refresh(const bool from_drive, const bool scroll_after) gui::utils::stop_future_watcher(m_parsing_watcher, from_drive); gui::utils::stop_future_watcher(m_refresh_watcher, from_drive); - if (m_progress_dialog_timer) - { - m_progress_dialog_timer->stop(); - } + m_progress_dialog_update_timer.stop(); + m_progress_dialog_timer.stop(); - if (m_progress_dialog) + if (progress_dialog* dlg = m_progress_dialog) { - m_progress_dialog->SetValue(m_progress_dialog->maximum()); - m_progress_dialog->accept(); - m_progress_dialog = nullptr; + m_progress_dialog = nullptr; // Clear first to avoid further slots + dlg->SetValue(dlg->maximum()); + dlg->accept(); } if (from_drive) @@ -339,7 +345,10 @@ void game_list_frame::Refresh(const bool from_drive, const bool scroll_after) connect(m_progress_dialog, &QProgressDialog::finished, this, [this]() { - m_progress_dialog = nullptr; + if (m_progress_dialog == QObject::sender()) + { + m_progress_dialog = nullptr; + } }); connect(m_progress_dialog, &QProgressDialog::canceled, this, [this]() { @@ -353,18 +362,15 @@ void game_list_frame::Refresh(const bool from_drive, const bool scroll_after) m_notes.clear(); m_games.pop_all(); - if (m_progress_dialog_timer) - { - m_progress_dialog_timer->stop(); - } + m_progress_dialog_timer.stop(); - m_progress_dialog = nullptr; + if (m_progress_dialog == QObject::sender()) + { + m_progress_dialog = nullptr; + } }); - if (m_progress_dialog_timer) - { - m_progress_dialog_timer->start(); - } + m_progress_dialog_timer.start(); const std::string games_dir = g_cfg_vfs.get(g_cfg_vfs.games_dir, rpcs3::utils::get_emu_dir()); const u32 games_added = Emu.AddGamesFromDir(games_dir); @@ -675,6 +681,8 @@ void game_list_frame::OnParsingFinished() } }; + m_progress_dialog_value = 0; + m_refresh_watcher.setFuture(QtConcurrent::map(m_path_entries, [this, _hdd, add_disc_dir, add_game](const path_entry& entry) { std::vector legit_paths; diff --git a/rpcs3/rpcs3qt/game_list_frame.h b/rpcs3/rpcs3qt/game_list_frame.h index 86b7e63aca..36ce32c16d 100644 --- a/rpcs3/rpcs3qt/game_list_frame.h +++ b/rpcs3/rpcs3qt/game_list_frame.h @@ -158,7 +158,9 @@ private: game_list_table* m_game_list = nullptr; game_compatibility* m_game_compat = nullptr; progress_dialog* m_progress_dialog = nullptr; - QTimer* m_progress_dialog_timer = nullptr; + atomic_t m_progress_dialog_value = 0; // Workaround for inexplicable setValue crash in progressValueChanged slot + QTimer m_progress_dialog_update_timer; // Workaround for inexplicable setValue crash in progressValueChanged slot + QTimer m_progress_dialog_timer; QList m_columnActs; Qt::SortOrder m_col_sort_order{}; int m_sort_column{}; diff --git a/rpcs3/rpcs3qt/progress_dialog.cpp b/rpcs3/rpcs3qt/progress_dialog.cpp index 7fc560e564..98e5febf87 100644 --- a/rpcs3/rpcs3qt/progress_dialog.cpp +++ b/rpcs3/rpcs3qt/progress_dialog.cpp @@ -37,7 +37,7 @@ void progress_dialog::SetRange(int min, int max) { m_progress_indicator->set_range(min, max); - QProgressDialog::setRange(min, max); + setRange(min, max); } void progress_dialog::SetValue(int progress) @@ -46,7 +46,7 @@ void progress_dialog::SetValue(int progress) m_progress_indicator->set_value(value); - QProgressDialog::setValue(value); + setValue(value); } void progress_dialog::SetDeleteOnClose()