Merge pull request #7968 from Techjar/fix-netplay-browser-search-hang

Qt/NetPlayBrowser: Refresh session list asynchronously
This commit is contained in:
spycrab 2019-04-14 03:11:31 +02:00 committed by GitHub
commit 0f8e5ab207
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 95 additions and 29 deletions

View File

@ -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;
@ -109,6 +122,9 @@ void NetPlayBrowser::CreateWidgets()
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::rejected, this, &NetPlayBrowser::reject);
connect(m_button_refresh, &QPushButton::pressed, this, &NetPlayBrowser::Refresh);
@ -125,25 +141,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<std::string, std::string> filters;
if (m_check_hide_incompatible->isChecked())
@ -161,22 +158,78 @@ void NetPlayBrowser::Refresh()
if (m_region_combo->currentIndex() != 0)
filters["region"] = m_region_combo->currentData().toString().toStdString();
auto entries = client.List(filters);
if (!entries)
{
m_status_label->setText(
tr("Error obtaining session list: %1").arg(QString::fromStdString(client.GetLastError())));
return;
std::unique_lock<std::mutex> lock(m_refresh_filters_mutex);
m_refresh_filters = std::move(filters);
m_refresh_event.Set();
}
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);
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));
@ -202,8 +255,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()

View File

@ -4,10 +4,16 @@
#pragma once
#include <map>
#include <mutex>
#include <optional>
#include <thread>
#include <vector>
#include <QDialog>
#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<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;
};