Qt/NetPlayBrowser: Refresh session list asynchronously

This commit is contained in:
Techjar 2019-04-07 23:50:09 -04:00
parent 22f55906e4
commit c7c4196c38
2 changed files with 95 additions and 29 deletions

View File

@ -26,6 +26,7 @@
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h" #include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/RunOnObject.h"
NetPlayBrowser::NetPlayBrowser(QWidget* parent) : QDialog(parent) 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->verticalHeader()->setHidden(true);
m_table_widget->setAlternatingRowColors(true); m_table_widget->setAlternatingRowColors(true);
m_refresh_run.Set(true);
m_refresh_thread = std::thread([this] { RefreshLoop(); });
UpdateList();
Refresh(); Refresh();
} }
NetPlayBrowser::~NetPlayBrowser()
{
m_refresh_run.Set(false);
m_refresh_event.Set();
if (m_refresh_thread.joinable())
m_refresh_thread.join();
}
void NetPlayBrowser::CreateWidgets() void NetPlayBrowser::CreateWidgets()
{ {
auto* layout = new QVBoxLayout; auto* layout = new QVBoxLayout;
@ -107,6 +120,9 @@ void NetPlayBrowser::CreateWidgets()
void NetPlayBrowser::ConnectWidgets() void NetPlayBrowser::ConnectWidgets()
{ {
connect(m_region_combo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this, &NetPlayBrowser::Refresh);
connect(m_button_box, &QDialogButtonBox::accepted, this, &NetPlayBrowser::accept); connect(m_button_box, &QDialogButtonBox::accepted, this, &NetPlayBrowser::accept);
connect(m_button_box, &QDialogButtonBox::rejected, this, &NetPlayBrowser::reject); connect(m_button_box, &QDialogButtonBox::rejected, this, &NetPlayBrowser::reject);
connect(m_button_refresh, &QPushButton::pressed, this, &NetPlayBrowser::Refresh); connect(m_button_refresh, &QPushButton::pressed, this, &NetPlayBrowser::Refresh);
@ -123,25 +139,6 @@ void NetPlayBrowser::ConnectWidgets()
void NetPlayBrowser::Refresh() 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<std::string, std::string> filters; std::map<std::string, std::string> filters;
if (m_check_hide_incompatible->isChecked()) if (m_check_hide_incompatible->isChecked())
@ -159,22 +156,78 @@ void NetPlayBrowser::Refresh()
if (m_region_combo->currentIndex() != 0) if (m_region_combo->currentIndex() != 0)
filters["region"] = m_region_combo->currentData().toString().toStdString(); filters["region"] = m_region_combo->currentData().toString().toStdString();
auto entries = client.List(filters); std::unique_lock<std::mutex> lock(m_refresh_filters_mutex);
m_refresh_filters = std::move(filters);
if (!entries) m_refresh_event.Set();
{
m_status_label->setText(
tr("Error obtaining session list: %1").arg(QString::fromStdString(client.GetLastError())));
return;
} }
const int session_count = static_cast<int>(entries.value().size()); void NetPlayBrowser::RefreshLoop()
{
while (m_refresh_run.IsSet())
{
m_refresh_event.Wait();
std::unique_lock<std::mutex> 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<int>(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); m_table_widget->setRowCount(session_count);
for (int i = 0; i < session_count; i++) 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* region = new QTableWidgetItem(QString::fromStdString(entry.region));
auto* name = new QTableWidgetItem(QString::fromStdString(entry.name)); auto* name = new QTableWidgetItem(QString::fromStdString(entry.name));
@ -200,8 +253,6 @@ void NetPlayBrowser::Refresh()
m_status_label->setText( m_status_label->setText(
(session_count == 1 ? tr("%1 session found") : tr("%1 sessions found")).arg(session_count)); (session_count == 1 ? tr("%1 session found") : tr("%1 sessions found")).arg(session_count));
m_sessions = entries.value();
} }
void NetPlayBrowser::OnSelectionChanged() void NetPlayBrowser::OnSelectionChanged()

View File

@ -4,10 +4,16 @@
#pragma once #pragma once
#include <map>
#include <mutex>
#include <optional>
#include <thread>
#include <vector> #include <vector>
#include <QDialog> #include <QDialog>
#include "Common/Event.h"
#include "Common/Flag.h"
#include "UICommon/NetPlayIndex.h" #include "UICommon/NetPlayIndex.h"
class QCheckBox; class QCheckBox;
@ -24,6 +30,7 @@ class NetPlayBrowser : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit NetPlayBrowser(QWidget* parent = nullptr); explicit NetPlayBrowser(QWidget* parent = nullptr);
~NetPlayBrowser();
void accept() override; void accept() override;
signals: signals:
@ -34,6 +41,8 @@ private:
void ConnectWidgets(); void ConnectWidgets();
void Refresh(); void Refresh();
void RefreshLoop();
void UpdateList();
void OnSelectionChanged(); void OnSelectionChanged();
@ -51,4 +60,10 @@ private:
QRadioButton* m_radio_public; QRadioButton* m_radio_public;
std::vector<NetPlaySession> m_sessions; std::vector<NetPlaySession> m_sessions;
std::thread m_refresh_thread;
std::optional<std::map<std::string, std::string>> m_refresh_filters;
std::mutex m_refresh_filters_mutex;
Common::Flag m_refresh_run;
Common::Event m_refresh_event;
}; };