diff --git a/src/citra_qt/configuration/config.cpp b/src/citra_qt/configuration/config.cpp index 389a3becf8..54c8c4f4b4 100644 --- a/src/citra_qt/configuration/config.cpp +++ b/src/citra_qt/configuration/config.cpp @@ -54,7 +54,7 @@ const std::array, Settings::NativeAnalog::NumAnalogs> Config: // This must be in alphabetical order according to action name as it must have the same order as // UISetting::values.shortcuts, which is alphabetically ordered. // clang-format off -const std::array Config::default_hotkeys {{ +const std::array Config::default_hotkeys {{ {QStringLiteral("Advance Frame"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::ApplicationShortcut}}, {QStringLiteral("Audio Mute/Unmute"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+M"), Qt::WindowShortcut}}, {QStringLiteral("Audio Volume Down"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::WindowShortcut}}, @@ -71,6 +71,11 @@ const std::array Config::default_hotkeys {{ {QStringLiteral("Load Amiibo"), QStringLiteral("Main Window"), {QStringLiteral("F2"), Qt::WidgetWithChildrenShortcut}}, {QStringLiteral("Load File"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+O"), Qt::WidgetWithChildrenShortcut}}, {QStringLiteral("Load from Newest Slot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+V"), Qt::WindowShortcut}}, + {QStringLiteral("Multiplayer Browse Public Game Lobby"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+B"), Qt::ApplicationShortcut}}, + {QStringLiteral("Multiplayer Create Room"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+N"), Qt::ApplicationShortcut}}, + {QStringLiteral("Multiplayer Direct Connect to Room"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Shift"), Qt::ApplicationShortcut}}, + {QStringLiteral("Multiplayer Leave Room"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+L"), Qt::ApplicationShortcut}}, + {QStringLiteral("Multiplayer Show Current Room"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+R"), Qt::ApplicationShortcut}}, {QStringLiteral("Remove Amiibo"), QStringLiteral("Main Window"), {QStringLiteral("F3"), Qt::ApplicationShortcut}}, {QStringLiteral("Restart Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F6"), Qt::WindowShortcut}}, {QStringLiteral("Rotate Screens Upright"), QStringLiteral("Main Window"), {QStringLiteral("F8"), Qt::WindowShortcut}}, @@ -557,6 +562,15 @@ void Config::ReadMultiplayerValues() { UISettings::values.game_id = ReadSetting(QStringLiteral("game_id"), 0).toULongLong(); UISettings::values.room_description = ReadSetting(QStringLiteral("room_description"), QString{}).toString(); + UISettings::values.multiplayer_filter_text = + ReadSetting(QStringLiteral("multiplayer_filter_text"), QString{}).toString(); + UISettings::values.multiplayer_filter_games_owned = + ReadSetting(QStringLiteral("multiplayer_filter_games_owned"), false).toBool(); + UISettings::values.multiplayer_filter_hide_empty = + ReadSetting(QStringLiteral("multiplayer_filter_hide_empty"), false).toBool(); + UISettings::values.multiplayer_filter_hide_full = + ReadSetting(QStringLiteral("multiplayer_filter_hide_full"), false).toBool(); + // Read ban list back int size = qt_config->beginReadArray(QStringLiteral("username_ban_list")); UISettings::values.ban_list.first.resize(size); @@ -1074,6 +1088,15 @@ void Config::SaveMultiplayerValues() { WriteSetting(QStringLiteral("game_id"), UISettings::values.game_id, 0); WriteSetting(QStringLiteral("room_description"), UISettings::values.room_description, QString{}); + WriteSetting(QStringLiteral("multiplayer_filter_text"), + UISettings::values.multiplayer_filter_text, QString{}); + WriteSetting(QStringLiteral("multiplayer_filter_games_owned"), + UISettings::values.multiplayer_filter_games_owned, false); + WriteSetting(QStringLiteral("multiplayer_filter_hide_empty"), + UISettings::values.multiplayer_filter_hide_empty, false); + WriteSetting(QStringLiteral("multiplayer_filter_hide_full"), + UISettings::values.multiplayer_filter_hide_full, false); + // Write ban list qt_config->beginWriteArray(QStringLiteral("username_ban_list")); for (std::size_t i = 0; i < UISettings::values.ban_list.first.size(); ++i) { diff --git a/src/citra_qt/configuration/config.h b/src/citra_qt/configuration/config.h index 27be93711a..521c6baf9d 100644 --- a/src/citra_qt/configuration/config.h +++ b/src/citra_qt/configuration/config.h @@ -26,7 +26,7 @@ public: static const std::array default_buttons; static const std::array, Settings::NativeAnalog::NumAnalogs> default_analogs; - static const std::array default_hotkeys; + static const std::array default_hotkeys; private: void Initialize(const std::string& config_name); diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 807da30e3c..4f179a35c4 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -647,6 +647,13 @@ void GMainWindow::InitializeHotkeys() { link_action_shortcut(ui->action_Advance_Frame, QStringLiteral("Advance Frame")); link_action_shortcut(ui->action_Load_from_Newest_Slot, QStringLiteral("Load from Newest Slot")); link_action_shortcut(ui->action_Save_to_Oldest_Slot, QStringLiteral("Save to Oldest Slot")); + link_action_shortcut(ui->action_View_Lobby, + QStringLiteral("Multiplayer Browse Public Game Lobby")); + link_action_shortcut(ui->action_Start_Room, QStringLiteral("Multiplayer Create Room")); + link_action_shortcut(ui->action_Connect_To_Room, + QStringLiteral("Multiplayer Direct Connect to Room")); + link_action_shortcut(ui->action_Show_Room, QStringLiteral("Multiplayer Show Current Room")); + link_action_shortcut(ui->action_Leave_Room, QStringLiteral("Multiplayer Leave Room")); const auto add_secondary_window_hotkey = [this](QKeySequence hotkey, const char* slot) { // This action will fire specifically when secondary_window is in focus diff --git a/src/citra_qt/multiplayer/direct_connect.cpp b/src/citra_qt/multiplayer/direct_connect.cpp index 936fd0435c..bdc866a753 100644 --- a/src/citra_qt/multiplayer/direct_connect.cpp +++ b/src/citra_qt/multiplayer/direct_connect.cpp @@ -80,9 +80,8 @@ void DirectConnectWindow::Connect() { // Store settings UISettings::values.nickname = ui->nickname->text(); UISettings::values.ip = ui->ip->text(); - UISettings::values.port = (ui->port->isModified() && !ui->port->text().isEmpty()) - ? ui->port->text() - : UISettings::values.port; + UISettings::values.port = + !ui->port->text().isEmpty() ? ui->port->text() : UISettings::values.port; // attempt to connect in a different thread QFuture f = QtConcurrent::run([&] { diff --git a/src/citra_qt/multiplayer/lobby.cpp b/src/citra_qt/multiplayer/lobby.cpp index 7cd2ae7e1f..00671b8420 100644 --- a/src/citra_qt/multiplayer/lobby.cpp +++ b/src/citra_qt/multiplayer/lobby.cpp @@ -63,10 +63,10 @@ Lobby::Lobby(Core::System& system_, QWidget* parent, QStandardItemModel* list, // UI Buttons connect(ui->refresh_list, &QPushButton::clicked, this, &Lobby::RefreshLobby); + connect(ui->search, &QLineEdit::textChanged, proxy, &LobbyFilterProxyModel::SetFilterSearch); connect(ui->games_owned, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterOwned); connect(ui->hide_empty, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterEmpty); connect(ui->hide_full, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterFull); - connect(ui->search, &QLineEdit::textChanged, proxy, &LobbyFilterProxyModel::SetFilterSearch); connect(ui->room_list, &QTreeView::doubleClicked, this, &Lobby::OnJoinRoom); connect(ui->room_list, &QTreeView::clicked, this, &Lobby::OnExpandRoom); @@ -74,6 +74,12 @@ Lobby::Lobby(Core::System& system_, QWidget* parent, QStandardItemModel* list, connect(&room_list_watcher, &QFutureWatcher::finished, this, &Lobby::OnRefreshLobby); + // Load persistent filters after events are connected to make sure they apply + ui->search->setText(UISettings::values.multiplayer_filter_text); + ui->games_owned->setChecked(UISettings::values.multiplayer_filter_games_owned); + ui->hide_empty->setChecked(UISettings::values.multiplayer_filter_hide_empty); + ui->hide_full->setChecked(UISettings::values.multiplayer_filter_hide_full); + // manually start a refresh when the window is opening // TODO(jroweboy): if this refresh is slow for people with bad internet, then don't do it as // part of the constructor, but offload the refresh until after the window shown. perhaps emit a @@ -180,6 +186,10 @@ void Lobby::OnJoinRoom(const QModelIndex& source) { UISettings::values.nickname = ui->nickname->text(); UISettings::values.ip = proxy->data(connection_index, LobbyItemHost::HostIPRole).toString(); UISettings::values.port = proxy->data(connection_index, LobbyItemHost::HostPortRole).toString(); + UISettings::values.multiplayer_filter_text = ui->search->text(); + UISettings::values.multiplayer_filter_games_owned = ui->games_owned->isChecked(); + UISettings::values.multiplayer_filter_hide_empty = ui->hide_empty->isChecked(); + UISettings::values.multiplayer_filter_hide_full = ui->hide_full->isChecked(); } void Lobby::ResetModel() { diff --git a/src/citra_qt/multiplayer/lobby_p.h b/src/citra_qt/multiplayer/lobby_p.h index 16db78eae5..f1890fdefc 100644 --- a/src/citra_qt/multiplayer/lobby_p.h +++ b/src/citra_qt/multiplayer/lobby_p.h @@ -188,12 +188,37 @@ public: } QVariant data(int role) const override { - if (role != Qt::DisplayRole) { + switch (role) { + case Qt::DisplayRole: { + auto members = data(MemberListRole).toList(); + return QStringLiteral("%1 / %2").arg(QString::number(members.size()), + data(MaxPlayerRole).toString()); + } + case Qt::ForegroundRole: { + auto members = data(MemberListRole).toList(); + auto max_players = data(MaxPlayerRole).toInt(); + const QColor room_full_color(255, 48, 32); + const QColor room_almost_full_color(255, 140, 32); + const QColor room_has_players_color(32, 160, 32); + const QColor room_empty_color(128, 128, 128); + + if (members.size() >= max_players) { + return QBrush(room_full_color); + } else if (members.size() == (max_players - 1)) { + return QBrush(room_almost_full_color); + } else if (members.size() == 0) { + return QBrush(room_empty_color); + } else if (members.size() > 0 && members.size() < (max_players - 1)) { + return QBrush(room_has_players_color); + } + + // FIXME: How to return a value that tells Qt not to modify the + // text color from the default (as if Qt::ForegroundRole wasn't overridden)? + return QBrush(nullptr); + } + default: return LobbyItem::data(role); } - auto members = data(MemberListRole).toList(); - return QStringLiteral("%1 / %2").arg(QString::number(members.size()), - data(MaxPlayerRole).toString()); } bool operator<(const QStandardItem& other) const override { diff --git a/src/citra_qt/uisettings.h b/src/citra_qt/uisettings.h index 8e671f49f2..6dedff0f00 100644 --- a/src/citra_qt/uisettings.h +++ b/src/citra_qt/uisettings.h @@ -138,6 +138,11 @@ struct Values { QString room_description; std::pair, std::vector> ban_list; + QString multiplayer_filter_text; + bool multiplayer_filter_games_owned; + bool multiplayer_filter_hide_empty; + bool multiplayer_filter_hide_full; + // logging Settings::Setting show_console{false, "showConsole"}; };