From 789642aee3f7cb37a98f7f8733a17eabf0e09529 Mon Sep 17 00:00:00 2001 From: DawnFire42 Date: Thu, 5 Mar 2026 23:19:25 -0500 Subject: [PATCH] Add local game options dialog. Introduces LocalGameOptions struct and DlgLocalGameOptions dialog to replace the previous QInputDialog for starting local games. Encapsulates game configuration with a simple interface that prevents parameter explosion as options are added. The dialog provides UI with settings persistence via SettingsCache --- cockatrice/CMakeLists.txt | 1 + cockatrice/src/game/local_game_options.h | 23 +++++ .../dialogs/dlg_local_game_options.cpp | 89 +++++++++++++++++++ .../widgets/dialogs/dlg_local_game_options.h | 50 +++++++++++ 4 files changed, 163 insertions(+) create mode 100644 cockatrice/src/game/local_game_options.h create mode 100644 cockatrice/src/interface/widgets/dialogs/dlg_local_game_options.cpp create mode 100644 cockatrice/src/interface/widgets/dialogs/dlg_local_game_options.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index d675b809d..1ca3c77c2 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -39,6 +39,7 @@ set(cockatrice_SOURCES src/interface/widgets/dialogs/dlg_load_deck_from_clipboard.cpp src/interface/widgets/dialogs/dlg_load_deck_from_website.cpp src/interface/widgets/dialogs/dlg_load_remote_deck.cpp + src/interface/widgets/dialogs/dlg_local_game_options.cpp src/interface/widgets/dialogs/dlg_manage_sets.cpp src/interface/widgets/dialogs/dlg_register.cpp src/interface/widgets/dialogs/dlg_select_set_for_cards.cpp diff --git a/cockatrice/src/game/local_game_options.h b/cockatrice/src/game/local_game_options.h new file mode 100644 index 000000000..df1d10e10 --- /dev/null +++ b/cockatrice/src/game/local_game_options.h @@ -0,0 +1,23 @@ +/** + * @file local_game_options.h + * @ingroup Game + * @brief Configuration options for local games. + * + * This struct encapsulates all settings that can be configured when starting + * a local game, providing a clean interface that prevents parameter explosion + * as more options are added in the future. + * + * @note User documentation: doc/doxygen/extra-pages/user_documentation/local_game/starting_a_local_game.md + */ + +#ifndef LOCAL_GAME_OPTIONS_H +#define LOCAL_GAME_OPTIONS_H + +struct LocalGameOptions +{ + int numberPlayers = 1; + int startingLifeTotal = 20; + bool spectatorsSeeEverything = false; +}; + +#endif // LOCAL_GAME_OPTIONS_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_local_game_options.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_local_game_options.cpp new file mode 100644 index 000000000..c6db0f04c --- /dev/null +++ b/cockatrice/src/interface/widgets/dialogs/dlg_local_game_options.cpp @@ -0,0 +1,89 @@ +#include "dlg_local_game_options.h" + +#include "../../../client/settings/cache_settings.h" + +#include +#include +#include +#include +#include +#include +#include + +DlgLocalGameOptions::DlgLocalGameOptions(QWidget *parent) : QDialog(parent) +{ + numberPlayersLabel = new QLabel(tr("P&layers:"), this); + numberPlayersEdit = new QSpinBox(this); + numberPlayersEdit->setMinimum(1); + numberPlayersEdit->setMaximum(8); + numberPlayersEdit->setValue(1); + numberPlayersLabel->setBuddy(numberPlayersEdit); + + auto *generalGrid = new QGridLayout; + generalGrid->addWidget(numberPlayersLabel, 0, 0); + generalGrid->addWidget(numberPlayersEdit, 0, 1); + generalGroupBox = new QGroupBox(tr("General"), this); + generalGroupBox->setLayout(generalGrid); + + startingLifeTotalLabel = new QLabel(tr("Starting &life total:"), this); + startingLifeTotalEdit = new QSpinBox(this); + startingLifeTotalEdit->setMinimum(1); + startingLifeTotalEdit->setMaximum(99999); + startingLifeTotalEdit->setValue(20); + startingLifeTotalLabel->setBuddy(startingLifeTotalEdit); + + spectatorsSeeEverythingCheckBox = new QCheckBox(tr("Spectators can see &everything"), this); + + auto *gameSetupGrid = new QGridLayout; + gameSetupGrid->addWidget(startingLifeTotalLabel, 0, 0); + gameSetupGrid->addWidget(startingLifeTotalEdit, 0, 1); + gameSetupGrid->addWidget(spectatorsSeeEverythingCheckBox, 1, 0, 1, 2); + gameSetupOptionsGroupBox = new QGroupBox(tr("Game setup options"), this); + gameSetupOptionsGroupBox->setLayout(gameSetupGrid); + + rememberSettingsCheckBox = new QCheckBox(tr("Re&member settings"), this); + + buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); + connect(buttonBox, &QDialogButtonBox::accepted, this, &DlgLocalGameOptions::actOK); + connect(buttonBox, &QDialogButtonBox::rejected, this, &DlgLocalGameOptions::reject); + + auto *mainLayout = new QVBoxLayout; + mainLayout->addWidget(generalGroupBox); + mainLayout->addWidget(gameSetupOptionsGroupBox); + mainLayout->addWidget(rememberSettingsCheckBox); + mainLayout->addWidget(buttonBox); + setLayout(mainLayout); + + rememberSettingsCheckBox->setChecked(SettingsCache::instance().getRememberGameSettings()); + if (rememberSettingsCheckBox->isChecked()) { + numberPlayersEdit->setValue(SettingsCache::instance().getMaxPlayers()); + startingLifeTotalEdit->setValue(SettingsCache::instance().getDefaultStartingLifeTotal()); + spectatorsSeeEverythingCheckBox->setChecked(SettingsCache::instance().getSpectatorsCanSeeEverything()); + } + + setWindowTitle(tr("Local game options")); + setFixedHeight(sizeHint().height()); + + numberPlayersEdit->setFocus(); +} + +void DlgLocalGameOptions::actOK() +{ + SettingsCache::instance().setRememberGameSettings(rememberSettingsCheckBox->isChecked()); + if (rememberSettingsCheckBox->isChecked()) { + SettingsCache::instance().setMaxPlayers(numberPlayersEdit->value()); + SettingsCache::instance().setDefaultStartingLifeTotal(startingLifeTotalEdit->value()); + SettingsCache::instance().setSpectatorsCanSeeEverything(spectatorsSeeEverythingCheckBox->isChecked()); + } + + accept(); +} + +LocalGameOptions DlgLocalGameOptions::getOptions() const +{ + return LocalGameOptions{ + .numberPlayers = numberPlayersEdit->value(), + .startingLifeTotal = startingLifeTotalEdit->value(), + .spectatorsSeeEverything = spectatorsSeeEverythingCheckBox->isChecked(), + }; +} diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_local_game_options.h b/cockatrice/src/interface/widgets/dialogs/dlg_local_game_options.h new file mode 100644 index 000000000..9284f3853 --- /dev/null +++ b/cockatrice/src/interface/widgets/dialogs/dlg_local_game_options.h @@ -0,0 +1,50 @@ +/** + * @file dlg_local_game_options.h + * @ingroup RoomDialogs + * @brief Dialog for configuring local game options. + * + * Provides a user interface for setting up local games with configurable + * number of players, starting life total, and spectator visibility options. + */ + +#ifndef DLG_LOCAL_GAME_OPTIONS_H +#define DLG_LOCAL_GAME_OPTIONS_H + +#include "../../../game/local_game_options.h" + +#include + +class QCheckBox; +class QDialogButtonBox; +class QGroupBox; +class QLabel; +class QSpinBox; + +class DlgLocalGameOptions : public QDialog +{ + Q_OBJECT +public: + explicit DlgLocalGameOptions(QWidget *parent = nullptr); + + [[nodiscard]] LocalGameOptions getOptions() const; + +private slots: + void actOK(); + +private: + QGroupBox *generalGroupBox; + QGroupBox *gameSetupOptionsGroupBox; + + QLabel *numberPlayersLabel; + QSpinBox *numberPlayersEdit; + + QLabel *startingLifeTotalLabel; + QSpinBox *startingLifeTotalEdit; + + QCheckBox *spectatorsSeeEverythingCheckBox; + QCheckBox *rememberSettingsCheckBox; + + QDialogButtonBox *buttonBox; +}; + +#endif // DLG_LOCAL_GAME_OPTIONS_H