From c7c4196c38206730a3e5cfbf70e26b420f3145b3 Mon Sep 17 00:00:00 2001 From: Techjar Date: Sun, 7 Apr 2019 23:50:09 -0400 Subject: [PATCH] Qt/NetPlayBrowser: Refresh session list asynchronously --- .../Core/DolphinQt/NetPlay/NetPlayBrowser.cpp | 109 +++++++++++++----- .../Core/DolphinQt/NetPlay/NetPlayBrowser.h | 15 +++ 2 files changed, 95 insertions(+), 29 deletions(-) diff --git a/Source/Core/DolphinQt/NetPlay/NetPlayBrowser.cpp b/Source/Core/DolphinQt/NetPlay/NetPlayBrowser.cpp index 4ea2c21bbe..13ad201184 100644 --- a/Source/Core/DolphinQt/NetPlay/NetPlayBrowser.cpp +++ b/Source/Core/DolphinQt/NetPlay/NetPlayBrowser.cpp @@ -26,6 +26,7 @@ #include "Core/ConfigManager.h" #include "DolphinQt/QtUtils/ModalMessageBox.h" +#include "DolphinQt/QtUtils/RunOnObject.h" NetPlayBrowser::NetPlayBrowser(QWidget* parent) : QDialog(parent) { @@ -40,9 +41,21 @@ NetPlayBrowser::NetPlayBrowser(QWidget* parent) : QDialog(parent) m_table_widget->verticalHeader()->setHidden(true); m_table_widget->setAlternatingRowColors(true); + m_refresh_run.Set(true); + m_refresh_thread = std::thread([this] { RefreshLoop(); }); + + UpdateList(); Refresh(); } +NetPlayBrowser::~NetPlayBrowser() +{ + m_refresh_run.Set(false); + m_refresh_event.Set(); + if (m_refresh_thread.joinable()) + m_refresh_thread.join(); +} + void NetPlayBrowser::CreateWidgets() { auto* layout = new QVBoxLayout; @@ -107,6 +120,9 @@ void NetPlayBrowser::CreateWidgets() void NetPlayBrowser::ConnectWidgets() { + connect(m_region_combo, static_cast(&QComboBox::currentIndexChanged), + this, &NetPlayBrowser::Refresh); + connect(m_button_box, &QDialogButtonBox::accepted, this, &NetPlayBrowser::accept); connect(m_button_box, &QDialogButtonBox::rejected, this, &NetPlayBrowser::reject); connect(m_button_refresh, &QPushButton::pressed, this, &NetPlayBrowser::Refresh); @@ -123,25 +139,6 @@ void NetPlayBrowser::ConnectWidgets() void NetPlayBrowser::Refresh() { - m_status_label->setText(tr("Refreshing...")); - - m_table_widget->clear(); - m_table_widget->setColumnCount(7); - m_table_widget->setHorizontalHeaderLabels({tr("Region"), tr("Name"), tr("Password?"), - tr("In-Game?"), tr("Game"), tr("Players"), - tr("Version")}); - - auto* hor_header = m_table_widget->horizontalHeader(); - - hor_header->setSectionResizeMode(0, QHeaderView::ResizeToContents); - hor_header->setSectionResizeMode(1, QHeaderView::Stretch); - hor_header->setSectionResizeMode(2, QHeaderView::ResizeToContents); - hor_header->setSectionResizeMode(3, QHeaderView::ResizeToContents); - hor_header->setSectionResizeMode(4, QHeaderView::Stretch); - hor_header->setHighlightSections(false); - - NetPlayIndex client; - std::map filters; if (m_check_hide_incompatible->isChecked()) @@ -159,22 +156,78 @@ void NetPlayBrowser::Refresh() if (m_region_combo->currentIndex() != 0) filters["region"] = m_region_combo->currentData().toString().toStdString(); - auto entries = client.List(filters); + std::unique_lock lock(m_refresh_filters_mutex); + m_refresh_filters = std::move(filters); + m_refresh_event.Set(); +} - if (!entries) +void NetPlayBrowser::RefreshLoop() +{ + while (m_refresh_run.IsSet()) { - m_status_label->setText( - tr("Error obtaining session list: %1").arg(QString::fromStdString(client.GetLastError()))); - return; - } + m_refresh_event.Wait(); - const int session_count = static_cast(entries.value().size()); + std::unique_lock lock(m_refresh_filters_mutex); + if (m_refresh_filters) + { + auto filters = std::move(*m_refresh_filters); + m_refresh_filters.reset(); + + lock.unlock(); + + RunOnObject(this, [this] { + m_status_label->setText(tr("Refreshing...")); + return nullptr; + }); + + NetPlayIndex client; + + auto entries = client.List(filters); + + if (entries) + { + RunOnObject(this, [this, &entries] { + m_sessions = *entries; + UpdateList(); + return nullptr; + }); + } + else + { + RunOnObject(this, [this, &client] { + m_status_label->setText(tr("Error obtaining session list: %1") + .arg(QString::fromStdString(client.GetLastError()))); + return nullptr; + }); + } + } + } +} + +void NetPlayBrowser::UpdateList() +{ + const int session_count = static_cast(m_sessions.size()); + + m_table_widget->clear(); + m_table_widget->setColumnCount(7); + m_table_widget->setHorizontalHeaderLabels({tr("Region"), tr("Name"), tr("Password?"), + tr("In-Game?"), tr("Game"), tr("Players"), + tr("Version")}); + + auto* hor_header = m_table_widget->horizontalHeader(); + + hor_header->setSectionResizeMode(0, QHeaderView::ResizeToContents); + hor_header->setSectionResizeMode(1, QHeaderView::Stretch); + hor_header->setSectionResizeMode(2, QHeaderView::ResizeToContents); + hor_header->setSectionResizeMode(3, QHeaderView::ResizeToContents); + hor_header->setSectionResizeMode(4, QHeaderView::Stretch); + hor_header->setHighlightSections(false); m_table_widget->setRowCount(session_count); for (int i = 0; i < session_count; i++) { - const auto& entry = entries.value()[i]; + const auto& entry = m_sessions[i]; auto* region = new QTableWidgetItem(QString::fromStdString(entry.region)); auto* name = new QTableWidgetItem(QString::fromStdString(entry.name)); @@ -200,8 +253,6 @@ void NetPlayBrowser::Refresh() m_status_label->setText( (session_count == 1 ? tr("%1 session found") : tr("%1 sessions found")).arg(session_count)); - - m_sessions = entries.value(); } void NetPlayBrowser::OnSelectionChanged() diff --git a/Source/Core/DolphinQt/NetPlay/NetPlayBrowser.h b/Source/Core/DolphinQt/NetPlay/NetPlayBrowser.h index 12c7f85963..dfe949f93b 100644 --- a/Source/Core/DolphinQt/NetPlay/NetPlayBrowser.h +++ b/Source/Core/DolphinQt/NetPlay/NetPlayBrowser.h @@ -4,10 +4,16 @@ #pragma once +#include +#include +#include +#include #include #include +#include "Common/Event.h" +#include "Common/Flag.h" #include "UICommon/NetPlayIndex.h" class QCheckBox; @@ -24,6 +30,7 @@ class NetPlayBrowser : public QDialog Q_OBJECT public: explicit NetPlayBrowser(QWidget* parent = nullptr); + ~NetPlayBrowser(); void accept() override; signals: @@ -34,6 +41,8 @@ private: void ConnectWidgets(); void Refresh(); + void RefreshLoop(); + void UpdateList(); void OnSelectionChanged(); @@ -51,4 +60,10 @@ private: QRadioButton* m_radio_public; std::vector m_sessions; + + std::thread m_refresh_thread; + std::optional> m_refresh_filters; + std::mutex m_refresh_filters_mutex; + Common::Flag m_refresh_run; + Common::Event m_refresh_event; };