mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-08 11:03:25 -08:00
[Refactor] Split CreateGameFormWidget out of DlgCreateGame (#7801)
* Extract CreateGameFormWidget from DlgCreateGame * Address review findings
This commit is contained in:
parent
554368967d
commit
39220a2ea9
10 changed files with 864 additions and 325 deletions
|
|
@ -216,6 +216,7 @@ set(cockatrice_SOURCES
|
|||
src/interface/widgets/deck_editor/deck_state_manager.cpp
|
||||
src/interface/widgets/deck_editor/deck_zone_dialog.cpp
|
||||
src/interface/widgets/deck_editor/printing_disabled_info_widget.cpp
|
||||
src/interface/widgets/game_hosting/create_game_form_widget.cpp
|
||||
src/interface/widgets/game_hosting/game_creation_options.cpp
|
||||
src/interface/widgets/general/background_sources.cpp
|
||||
src/interface/widgets/general/display/background_plate_widget.cpp
|
||||
|
|
|
|||
|
|
@ -1,341 +1,109 @@
|
|||
#include "dlg_create_game.h"
|
||||
|
||||
#include "../../../client/settings/cache_settings.h"
|
||||
#include "../interface/widgets/game_hosting/game_creation_options.h"
|
||||
#include "../interface/widgets/tabs/tab_room.h"
|
||||
#include "../game_hosting/create_game_form_widget.h"
|
||||
#include "../game_hosting/game_creation_options.h"
|
||||
#include "../tabs/tab_room.h"
|
||||
#include "libcockatrice/protocol/pb/response.pb.h"
|
||||
#include "libcockatrice/protocol/pb/room_commands.pb.h"
|
||||
#include "libcockatrice/protocol/pb/serverinfo_game.pb.h"
|
||||
#include "libcockatrice/protocol/pb/serverinfo_user.pb.h"
|
||||
#include "libcockatrice/utility/macros.h"
|
||||
#include "libcockatrice/protocol/pending_command.h"
|
||||
#include "libcockatrice/settings/game_settings.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDebug>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QList>
|
||||
#include <QMapIterator>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QRadioButton>
|
||||
#include <QSet>
|
||||
#include <QSharedPointer>
|
||||
#include <QSize>
|
||||
#include <QSpinBox>
|
||||
#include <QVBoxLayout>
|
||||
#include <libcockatrice/protocol/pb/serverinfo_game.pb.h>
|
||||
#include <libcockatrice/protocol/pending_command.h>
|
||||
#include <libcockatrice/settings/game_settings.h>
|
||||
#include <libcockatrice/utility/string_limits.h>
|
||||
#include <qnamespace.h>
|
||||
#include <string>
|
||||
|
||||
class QWidget;
|
||||
|
||||
void DlgCreateGame::sharedCtor()
|
||||
{
|
||||
rememberGameSettings = new QCheckBox(tr("Re&member settings"));
|
||||
descriptionLabel = new QLabel(tr("&Description:"));
|
||||
descriptionEdit = new QLineEdit;
|
||||
descriptionEdit->setMaxLength(MAX_NAME_LENGTH);
|
||||
descriptionLabel->setBuddy(descriptionEdit);
|
||||
|
||||
maxPlayersLabel = new QLabel(tr("P&layers:"));
|
||||
maxPlayersEdit = new QSpinBox();
|
||||
maxPlayersEdit->setMinimum(1);
|
||||
maxPlayersEdit->setMaximum(100);
|
||||
maxPlayersEdit->setValue(2);
|
||||
maxPlayersLabel->setBuddy(maxPlayersEdit);
|
||||
|
||||
auto *generalGrid = new QGridLayout;
|
||||
generalGrid->addWidget(descriptionLabel, 0, 0);
|
||||
generalGrid->addWidget(descriptionEdit, 0, 1);
|
||||
generalGrid->addWidget(maxPlayersLabel, 1, 0);
|
||||
generalGrid->addWidget(maxPlayersEdit, 1, 1);
|
||||
generalGroupBox = new QGroupBox(tr("General"));
|
||||
generalGroupBox->setLayout(generalGrid);
|
||||
|
||||
auto *gameTypeLayout = new QVBoxLayout;
|
||||
QMapIterator<int, QString> gameTypeIterator(gameTypes);
|
||||
while (gameTypeIterator.hasNext()) {
|
||||
gameTypeIterator.next();
|
||||
auto *gameTypeRadioButton = new QRadioButton(gameTypeIterator.value(), this);
|
||||
gameTypeLayout->addWidget(gameTypeRadioButton);
|
||||
gameTypeCheckBoxes.insert(gameTypeIterator.key(), gameTypeRadioButton);
|
||||
bool isChecked = SettingsCache::instance().game().getGameTypes().contains(gameTypeIterator.value() + ", ");
|
||||
gameTypeCheckBoxes[gameTypeIterator.key()]->setChecked(isChecked);
|
||||
}
|
||||
auto *gameTypeGroupBox = new QGroupBox(tr("Game type"));
|
||||
gameTypeGroupBox->setLayout(gameTypeLayout);
|
||||
|
||||
passwordLabel = new QLabel(tr("&Password:"));
|
||||
passwordEdit = new QLineEdit;
|
||||
passwordEdit->setMaxLength(MAX_NAME_LENGTH);
|
||||
passwordLabel->setBuddy(passwordEdit);
|
||||
|
||||
onlyBuddiesCheckBox = new QCheckBox(tr("Only &buddies can join"));
|
||||
onlyRegisteredCheckBox = new QCheckBox(tr("Only ®istered users can join"));
|
||||
if (room && room->getUserInfo()->user_level() & ServerInfo_User::IsRegistered) {
|
||||
onlyRegisteredCheckBox->setChecked(true);
|
||||
} else {
|
||||
onlyBuddiesCheckBox->setEnabled(false);
|
||||
onlyRegisteredCheckBox->setEnabled(false);
|
||||
}
|
||||
|
||||
auto *joinRestrictionsLayout = new QGridLayout;
|
||||
joinRestrictionsLayout->addWidget(passwordLabel, 0, 0);
|
||||
joinRestrictionsLayout->addWidget(passwordEdit, 0, 1);
|
||||
joinRestrictionsLayout->addWidget(onlyBuddiesCheckBox, 1, 0, 1, 2);
|
||||
joinRestrictionsLayout->addWidget(onlyRegisteredCheckBox, 2, 0, 1, 2);
|
||||
|
||||
auto *joinRestrictionsGroupBox = new QGroupBox(tr("Joining restrictions"));
|
||||
joinRestrictionsGroupBox->setLayout(joinRestrictionsLayout);
|
||||
|
||||
spectatorsAllowedCheckBox = new QCheckBox(tr("&Spectators can watch"));
|
||||
spectatorsAllowedCheckBox->setChecked(true);
|
||||
connect(spectatorsAllowedCheckBox, &QCheckBox::QT_STATE_CHANGED, this, &DlgCreateGame::spectatorsAllowedChanged);
|
||||
spectatorsNeedPasswordCheckBox = new QCheckBox(tr("Spectators &need a password to watch"));
|
||||
spectatorsCanTalkCheckBox = new QCheckBox(tr("Spectators can &chat"));
|
||||
spectatorsSeeEverythingCheckBox = new QCheckBox(tr("Spectators can see &hands"));
|
||||
createGameAsSpectatorCheckBox = new QCheckBox(tr("Create game as spectator"));
|
||||
auto *spectatorsLayout = new QVBoxLayout;
|
||||
spectatorsLayout->addWidget(spectatorsAllowedCheckBox);
|
||||
spectatorsLayout->addWidget(spectatorsNeedPasswordCheckBox);
|
||||
spectatorsLayout->addWidget(spectatorsCanTalkCheckBox);
|
||||
spectatorsLayout->addWidget(spectatorsSeeEverythingCheckBox);
|
||||
spectatorsLayout->addWidget(createGameAsSpectatorCheckBox);
|
||||
spectatorsGroupBox = new QGroupBox(tr("Spectators"));
|
||||
spectatorsGroupBox->setLayout(spectatorsLayout);
|
||||
|
||||
startingLifeTotalLabel = new QLabel(tr("Starting life total:"));
|
||||
startingLifeTotalEdit = new QSpinBox();
|
||||
startingLifeTotalEdit->setMinimum(1);
|
||||
startingLifeTotalEdit->setMaximum(99999); ///< Arbitrary but we can raise this when people start complaining.
|
||||
startingLifeTotalEdit->setValue(20);
|
||||
startingLifeTotalLabel->setBuddy(startingLifeTotalEdit);
|
||||
|
||||
shareDecklistsOnLoadCheckBox = new QCheckBox(tr("Open decklists in lobby"));
|
||||
|
||||
shufflePlayersCheckBox = new QCheckBox(tr("Randomize turn order (seats) on each game start"));
|
||||
|
||||
createGameAsJudgeCheckBox = new QCheckBox(tr("Create game as judge"));
|
||||
|
||||
auto *gameSetupOptionsLayout = new QGridLayout;
|
||||
gameSetupOptionsLayout->addWidget(startingLifeTotalLabel, 0, 0);
|
||||
gameSetupOptionsLayout->addWidget(startingLifeTotalEdit, 0, 1);
|
||||
gameSetupOptionsLayout->addWidget(shareDecklistsOnLoadCheckBox, 1, 0, 1, 2);
|
||||
gameSetupOptionsLayout->addWidget(shufflePlayersCheckBox, 2, 0, 1, 2);
|
||||
if (room && room->getUserInfo()->user_level() & ServerInfo_User::IsJudge) {
|
||||
gameSetupOptionsLayout->addWidget(createGameAsJudgeCheckBox, 3, 0, 1, 2);
|
||||
} else {
|
||||
createGameAsJudgeCheckBox->setChecked(false);
|
||||
createGameAsJudgeCheckBox->setHidden(true);
|
||||
}
|
||||
gameSetupOptionsGroupBox = new QGroupBox(tr("Game setup options"));
|
||||
gameSetupOptionsGroupBox->setLayout(gameSetupOptionsLayout);
|
||||
|
||||
auto *grid = new QGridLayout;
|
||||
|
||||
// Top row
|
||||
grid->addWidget(generalGroupBox, 0, 0);
|
||||
grid->addWidget(joinRestrictionsGroupBox, 0, 1);
|
||||
|
||||
// Middle row: left column
|
||||
grid->addWidget(gameTypeGroupBox, 1, 0);
|
||||
|
||||
// Middle row: right column (game setup + spectators)
|
||||
auto *rightLayout = new QVBoxLayout;
|
||||
rightLayout->addWidget(spectatorsGroupBox, Qt::AlignTop); // top
|
||||
rightLayout->addWidget(gameSetupOptionsGroupBox); // bottom
|
||||
|
||||
grid->addLayout(rightLayout, 1, 1);
|
||||
|
||||
// Bottom row
|
||||
grid->addWidget(rememberGameSettings, 3, 0, 1, 2); // span both columns if needed
|
||||
|
||||
buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &DlgCreateGame::reject);
|
||||
|
||||
auto *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(grid);
|
||||
mainLayout->addWidget(buttonBox);
|
||||
|
||||
setLayout(mainLayout);
|
||||
|
||||
setFixedHeight(sizeHint().height());
|
||||
}
|
||||
|
||||
DlgCreateGame::DlgCreateGame(TabRoom *_room, const QMap<int, QString> &_gameTypes, QWidget *parent)
|
||||
: QDialog(parent), room(_room), gameTypes(_gameTypes)
|
||||
: QDialog(parent), room(_room)
|
||||
{
|
||||
sharedCtor();
|
||||
const bool registered = room && (room->getUserInfo()->user_level() & ServerInfo_User::IsRegistered);
|
||||
const bool judge = room && (room->getUserInfo()->user_level() & ServerInfo_User::IsJudge);
|
||||
|
||||
rememberGameSettings->setChecked(SettingsCache::instance().game().getRememberGameSettings());
|
||||
descriptionEdit->setText(SettingsCache::instance().game().getGameDescription());
|
||||
maxPlayersEdit->setValue(SettingsCache::instance().game().getMaxPlayers());
|
||||
if (room && room->getUserInfo()->user_level() & ServerInfo_User::IsRegistered) {
|
||||
onlyBuddiesCheckBox->setChecked(SettingsCache::instance().game().getOnlyBuddies());
|
||||
onlyRegisteredCheckBox->setChecked(SettingsCache::instance().game().getOnlyRegistered());
|
||||
form = new CreateGameFormWidget(_gameTypes, registered, judge, this);
|
||||
const bool rememberSettings = SettingsCache::instance().game().getRememberGameSettings();
|
||||
form->setRememberSettingsChecked(rememberSettings);
|
||||
if (rememberSettings) {
|
||||
form->setOptions(GameCreationOptions::fromSettings(SettingsCache::instance().game(), _gameTypes, registered));
|
||||
} else {
|
||||
onlyBuddiesCheckBox->setEnabled(false);
|
||||
onlyRegisteredCheckBox->setEnabled(false);
|
||||
form->resetToDefaults();
|
||||
}
|
||||
spectatorsAllowedCheckBox->setChecked(SettingsCache::instance().game().getSpectatorsAllowed());
|
||||
spectatorsNeedPasswordCheckBox->setChecked(SettingsCache::instance().game().getSpectatorsNeedPassword());
|
||||
spectatorsCanTalkCheckBox->setChecked(SettingsCache::instance().game().getSpectatorsCanTalk());
|
||||
spectatorsSeeEverythingCheckBox->setChecked(SettingsCache::instance().game().getSpectatorsCanSeeEverything());
|
||||
createGameAsSpectatorCheckBox->setChecked(SettingsCache::instance().game().getCreateGameAsSpectator());
|
||||
startingLifeTotalEdit->setValue(SettingsCache::instance().game().getDefaultStartingLifeTotal());
|
||||
shareDecklistsOnLoadCheckBox->setChecked(SettingsCache::instance().game().getShareDecklistsOnLoad());
|
||||
shufflePlayersCheckBox->setChecked(SettingsCache::instance().game().getShufflePlayers());
|
||||
form->focusDescription();
|
||||
|
||||
if (!rememberGameSettings->isChecked()) {
|
||||
actReset();
|
||||
}
|
||||
errorLabel = new QLabel(this);
|
||||
errorLabel->setObjectName("createGameErrorLabel");
|
||||
errorLabel->setWordWrap(true);
|
||||
errorLabel->setVisible(false);
|
||||
|
||||
descriptionEdit->setFocus();
|
||||
clearButton = new QPushButton(tr("&Clear"));
|
||||
buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok, this);
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &DlgCreateGame::reject);
|
||||
clearButton = new QPushButton(tr("&Clear"), this);
|
||||
buttonBox->addButton(QDialogButtonBox::Cancel);
|
||||
buttonBox->addButton(clearButton, QDialogButtonBox::ActionRole);
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &DlgCreateGame::actOK);
|
||||
connect(clearButton, &QPushButton::clicked, this, &DlgCreateGame::actReset);
|
||||
|
||||
auto *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addWidget(form);
|
||||
mainLayout->addWidget(errorLabel);
|
||||
mainLayout->addWidget(buttonBox);
|
||||
|
||||
setLayout(mainLayout);
|
||||
setWindowTitle(tr("Create game"));
|
||||
}
|
||||
|
||||
DlgCreateGame::DlgCreateGame(const ServerInfo_Game &gameInfo, const QMap<int, QString> &_gameTypes, QWidget *parent)
|
||||
: QDialog(parent), room(0), gameTypes(_gameTypes)
|
||||
: QDialog(parent), room(nullptr)
|
||||
{
|
||||
sharedCtor();
|
||||
|
||||
rememberGameSettings->setEnabled(false);
|
||||
descriptionEdit->setEnabled(false);
|
||||
maxPlayersEdit->setEnabled(false);
|
||||
passwordEdit->setEnabled(false);
|
||||
onlyBuddiesCheckBox->setEnabled(false);
|
||||
onlyRegisteredCheckBox->setEnabled(false);
|
||||
spectatorsAllowedCheckBox->setEnabled(false);
|
||||
spectatorsNeedPasswordCheckBox->setEnabled(false);
|
||||
spectatorsCanTalkCheckBox->setEnabled(false);
|
||||
spectatorsSeeEverythingCheckBox->setEnabled(false);
|
||||
createGameAsSpectatorCheckBox->setEnabled(false);
|
||||
startingLifeTotalEdit->setEnabled(false);
|
||||
shareDecklistsOnLoadCheckBox->setEnabled(false);
|
||||
shufflePlayersCheckBox->setEnabled(false);
|
||||
|
||||
descriptionEdit->setText(QString::fromStdString(gameInfo.description()));
|
||||
maxPlayersEdit->setValue(gameInfo.max_players());
|
||||
onlyBuddiesCheckBox->setChecked(gameInfo.only_buddies());
|
||||
onlyRegisteredCheckBox->setChecked(gameInfo.only_registered());
|
||||
spectatorsAllowedCheckBox->setChecked(gameInfo.spectators_allowed());
|
||||
spectatorsNeedPasswordCheckBox->setChecked(gameInfo.spectators_need_password());
|
||||
spectatorsCanTalkCheckBox->setChecked(gameInfo.spectators_can_chat());
|
||||
spectatorsSeeEverythingCheckBox->setChecked(gameInfo.spectators_omniscient());
|
||||
shareDecklistsOnLoadCheckBox->setChecked(gameInfo.share_decklists_on_load());
|
||||
shufflePlayersCheckBox->setChecked(gameInfo.shuffle_players());
|
||||
|
||||
QSet<int> types;
|
||||
for (int i = 0; i < gameInfo.game_types_size(); ++i) {
|
||||
types.insert(gameInfo.game_types(i));
|
||||
}
|
||||
|
||||
QMapIterator<int, QString> gameTypeIterator(gameTypes);
|
||||
while (gameTypeIterator.hasNext()) {
|
||||
gameTypeIterator.next();
|
||||
|
||||
QRadioButton *gameTypeCheckBox = gameTypeCheckBoxes.value(gameTypeIterator.key());
|
||||
gameTypeCheckBox->setEnabled(false);
|
||||
gameTypeCheckBox->setChecked(types.contains(gameTypeIterator.key()));
|
||||
}
|
||||
form = new CreateGameFormWidget(_gameTypes, false, false, this);
|
||||
form->setOptions(GameCreationOptions::fromGameInfo(gameInfo, _gameTypes));
|
||||
form->setReadOnly(true);
|
||||
|
||||
buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok, this);
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &DlgCreateGame::accept);
|
||||
|
||||
auto *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addWidget(form);
|
||||
mainLayout->addWidget(buttonBox);
|
||||
|
||||
setLayout(mainLayout);
|
||||
setWindowTitle(tr("Game information"));
|
||||
}
|
||||
|
||||
void DlgCreateGame::actReset()
|
||||
{
|
||||
descriptionEdit->setText("");
|
||||
maxPlayersEdit->setValue(2);
|
||||
|
||||
passwordEdit->setText("");
|
||||
onlyBuddiesCheckBox->setChecked(false);
|
||||
onlyRegisteredCheckBox->setChecked(room && room->getUserInfo()->user_level() & ServerInfo_User::IsRegistered);
|
||||
|
||||
spectatorsAllowedCheckBox->setChecked(true);
|
||||
spectatorsNeedPasswordCheckBox->setChecked(false);
|
||||
spectatorsCanTalkCheckBox->setChecked(false);
|
||||
spectatorsSeeEverythingCheckBox->setChecked(false);
|
||||
createGameAsSpectatorCheckBox->setChecked(false);
|
||||
|
||||
startingLifeTotalEdit->setValue(20);
|
||||
shareDecklistsOnLoadCheckBox->setChecked(false);
|
||||
shufflePlayersCheckBox->setChecked(false);
|
||||
createGameAsJudgeCheckBox->setChecked(false);
|
||||
|
||||
QMapIterator<int, QRadioButton *> gameTypeCheckBoxIterator(gameTypeCheckBoxes);
|
||||
while (gameTypeCheckBoxIterator.hasNext()) {
|
||||
gameTypeCheckBoxIterator.next();
|
||||
// must set auto enclusive to false to be able to set the check to false
|
||||
gameTypeCheckBoxIterator.value()->setAutoExclusive(false);
|
||||
gameTypeCheckBoxIterator.value()->setChecked(false);
|
||||
gameTypeCheckBoxIterator.value()->setAutoExclusive(true);
|
||||
}
|
||||
|
||||
descriptionEdit->setFocus();
|
||||
form->resetToDefaults();
|
||||
clearError();
|
||||
}
|
||||
|
||||
void DlgCreateGame::actOK()
|
||||
{
|
||||
auto _gameTypes = QString();
|
||||
QList<int> gameTypeIds;
|
||||
QMapIterator<int, QRadioButton *> gameTypeCheckBoxIterator(gameTypeCheckBoxes);
|
||||
while (gameTypeCheckBoxIterator.hasNext()) {
|
||||
gameTypeCheckBoxIterator.next();
|
||||
if (gameTypeCheckBoxIterator.value()->isChecked()) {
|
||||
gameTypeIds.append(gameTypeCheckBoxIterator.key());
|
||||
_gameTypes += gameTypeCheckBoxIterator.value()->text() + ", ";
|
||||
}
|
||||
}
|
||||
|
||||
GameCreationOptions options{
|
||||
.description = descriptionEdit->text(),
|
||||
.password = passwordEdit->text(),
|
||||
.maxPlayers = maxPlayersEdit->value(),
|
||||
.onlyBuddies = onlyBuddiesCheckBox->isChecked(),
|
||||
.onlyRegistered = onlyRegisteredCheckBox->isChecked(),
|
||||
.spectatorsAllowed = spectatorsAllowedCheckBox->isChecked(),
|
||||
.spectatorsNeedPassword = spectatorsNeedPasswordCheckBox->isChecked(),
|
||||
.spectatorsCanTalk = spectatorsCanTalkCheckBox->isChecked(),
|
||||
.spectatorsSeeEverything = spectatorsSeeEverythingCheckBox->isChecked(),
|
||||
.joinAsJudge = createGameAsJudgeCheckBox->isChecked(),
|
||||
.joinAsSpectator = createGameAsSpectatorCheckBox->isChecked(),
|
||||
.startingLifeTotal = startingLifeTotalEdit->value(),
|
||||
.shareDecklistsOnLoad = shareDecklistsOnLoadCheckBox->isChecked(),
|
||||
.shufflePlayers = shufflePlayersCheckBox->isChecked(),
|
||||
.gameTypeIds = gameTypeIds,
|
||||
};
|
||||
clearError();
|
||||
|
||||
const GameCreationOptions options = form->options();
|
||||
Command_CreateGame cmd = options.toCreateGameCommand();
|
||||
|
||||
SettingsCache::instance().game().setRememberGameSettings(rememberGameSettings->isChecked());
|
||||
if (rememberGameSettings->isChecked()) {
|
||||
SettingsCache::instance().game().setGameDescription(descriptionEdit->text());
|
||||
SettingsCache::instance().game().setMaxPlayers(maxPlayersEdit->value());
|
||||
SettingsCache::instance().game().setOnlyBuddies(onlyBuddiesCheckBox->isChecked());
|
||||
SettingsCache::instance().game().setOnlyRegistered(onlyRegisteredCheckBox->isChecked());
|
||||
SettingsCache::instance().game().setSpectatorsAllowed(spectatorsAllowedCheckBox->isChecked());
|
||||
SettingsCache::instance().game().setSpectatorsNeedPassword(spectatorsNeedPasswordCheckBox->isChecked());
|
||||
SettingsCache::instance().game().setSpectatorsCanTalk(spectatorsCanTalkCheckBox->isChecked());
|
||||
SettingsCache::instance().game().setSpectatorsCanSeeEverything(spectatorsSeeEverythingCheckBox->isChecked());
|
||||
SettingsCache::instance().game().setCreateGameAsSpectator(createGameAsSpectatorCheckBox->isChecked());
|
||||
SettingsCache::instance().game().setDefaultStartingLifeTotal(startingLifeTotalEdit->value());
|
||||
SettingsCache::instance().game().setShareDecklistsOnLoad(shareDecklistsOnLoadCheckBox->isChecked());
|
||||
SettingsCache::instance().game().setShufflePlayers(shufflePlayersCheckBox->isChecked());
|
||||
SettingsCache::instance().game().setGameTypes(_gameTypes);
|
||||
const bool rememberSettings = form->isRememberSettingsChecked();
|
||||
auto &gameSettings = SettingsCache::instance().game();
|
||||
gameSettings.setRememberGameSettings(rememberSettings);
|
||||
if (rememberSettings) {
|
||||
gameSettings.setGameDescription(options.description);
|
||||
gameSettings.setMaxPlayers(options.maxPlayers);
|
||||
gameSettings.setOnlyBuddies(options.onlyBuddies);
|
||||
gameSettings.setOnlyRegistered(options.onlyRegistered);
|
||||
gameSettings.setSpectatorsAllowed(options.spectatorsAllowed);
|
||||
gameSettings.setSpectatorsNeedPassword(options.spectatorsNeedPassword);
|
||||
gameSettings.setSpectatorsCanTalk(options.spectatorsCanTalk);
|
||||
gameSettings.setSpectatorsCanSeeEverything(options.spectatorsSeeEverything);
|
||||
gameSettings.setCreateGameAsSpectator(options.joinAsSpectator);
|
||||
gameSettings.setDefaultStartingLifeTotal(options.startingLifeTotal);
|
||||
gameSettings.setShareDecklistsOnLoad(options.shareDecklistsOnLoad);
|
||||
gameSettings.setShufflePlayers(options.shufflePlayers);
|
||||
gameSettings.setGameTypes(form->selectedGameTypesSettingString());
|
||||
}
|
||||
|
||||
PendingCommand *pend = room->prepareRoomCommand(cmd);
|
||||
connect(pend, &PendingCommand::finished, this, &DlgCreateGame::checkResponse);
|
||||
room->sendRoomCommand(pend);
|
||||
|
|
@ -350,14 +118,26 @@ void DlgCreateGame::checkResponse(const Response &response)
|
|||
if (response.response_code() == Response::RespOk) {
|
||||
accept();
|
||||
} else {
|
||||
QMessageBox::critical(this, tr("Error"), tr("Server error."));
|
||||
return;
|
||||
showError(tr("Server error."));
|
||||
}
|
||||
}
|
||||
|
||||
void DlgCreateGame::spectatorsAllowedChanged(QT_STATE_CHANGED_T state)
|
||||
void DlgCreateGame::showError(const QString &message)
|
||||
{
|
||||
spectatorsNeedPasswordCheckBox->setEnabled(state);
|
||||
spectatorsCanTalkCheckBox->setEnabled(state);
|
||||
spectatorsSeeEverythingCheckBox->setEnabled(state);
|
||||
if (!errorLabel) {
|
||||
return;
|
||||
}
|
||||
errorLabel->setText(message);
|
||||
errorLabel->setVisible(true);
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
void DlgCreateGame::clearError()
|
||||
{
|
||||
if (!errorLabel) {
|
||||
return;
|
||||
}
|
||||
errorLabel->clear();
|
||||
errorLabel->setVisible(false);
|
||||
adjustSize();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
* @file dlg_create_game.h
|
||||
* @ingroup RoomDialogs
|
||||
*/
|
||||
//! \todo Document this file.
|
||||
|
||||
#ifndef DLG_CREATEGAME_H
|
||||
#define DLG_CREATEGAME_H
|
||||
|
|
@ -10,21 +9,15 @@
|
|||
#include <QDialog>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <libcockatrice/utility/macros.h>
|
||||
#include <qtmetamacros.h>
|
||||
|
||||
class QCheckBox;
|
||||
class CreateGameFormWidget;
|
||||
class QDialogButtonBox;
|
||||
class QGroupBox;
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
class QPushButton;
|
||||
class QRadioButton;
|
||||
class QSpinBox;
|
||||
class Response;
|
||||
class ServerInfo_Game;
|
||||
class TabRoom;
|
||||
class QWidget;
|
||||
|
||||
class DlgCreateGame : public QDialog
|
||||
{
|
||||
|
|
@ -36,27 +29,16 @@ private slots:
|
|||
void actOK();
|
||||
void actReset();
|
||||
void checkResponse(const Response &response);
|
||||
void spectatorsAllowedChanged(QT_STATE_CHANGED_T state);
|
||||
|
||||
private:
|
||||
TabRoom *room;
|
||||
QMap<int, QString> gameTypes;
|
||||
QMap<int, QRadioButton *> gameTypeCheckBoxes;
|
||||
CreateGameFormWidget *form = nullptr;
|
||||
QDialogButtonBox *buttonBox = nullptr;
|
||||
QPushButton *clearButton = nullptr;
|
||||
QLabel *errorLabel = nullptr;
|
||||
|
||||
QGroupBox *generalGroupBox, *spectatorsGroupBox, *gameSetupOptionsGroupBox;
|
||||
QLabel *descriptionLabel, *passwordLabel, *maxPlayersLabel, *startingLifeTotalLabel, *shareDecklistsOnLoadLabel;
|
||||
QLineEdit *descriptionEdit, *passwordEdit;
|
||||
QSpinBox *maxPlayersEdit, *startingLifeTotalEdit;
|
||||
QCheckBox *onlyBuddiesCheckBox, *onlyRegisteredCheckBox;
|
||||
QCheckBox *spectatorsAllowedCheckBox, *spectatorsNeedPasswordCheckBox, *spectatorsCanTalkCheckBox,
|
||||
*spectatorsSeeEverythingCheckBox, *createGameAsJudgeCheckBox, *createGameAsSpectatorCheckBox;
|
||||
QCheckBox *shareDecklistsOnLoadCheckBox;
|
||||
QCheckBox *shufflePlayersCheckBox;
|
||||
QDialogButtonBox *buttonBox;
|
||||
QPushButton *clearButton;
|
||||
QCheckBox *rememberGameSettings;
|
||||
|
||||
void sharedCtor();
|
||||
void showError(const QString &message);
|
||||
void clearError();
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // DLG_CREATEGAME_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,260 @@
|
|||
#include "create_game_form_widget.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QRadioButton>
|
||||
#include <QSpinBox>
|
||||
#include <QVBoxLayout>
|
||||
#include <libcockatrice/utility/string_limits.h>
|
||||
#include <qnamespace.h>
|
||||
|
||||
CreateGameFormWidget::CreateGameFormWidget(const QMap<int, QString> &gameTypes,
|
||||
bool _registeredUser,
|
||||
bool judge,
|
||||
QWidget *parent)
|
||||
: QWidget(parent), registeredUser(_registeredUser)
|
||||
{
|
||||
setObjectName("createGameForm");
|
||||
|
||||
rememberGameSettings = new QCheckBox(tr("Re&member settings"));
|
||||
auto *descriptionLabel = new QLabel(tr("&Description:"));
|
||||
descriptionEdit = new QLineEdit;
|
||||
descriptionEdit->setMaxLength(MAX_NAME_LENGTH);
|
||||
descriptionLabel->setBuddy(descriptionEdit);
|
||||
|
||||
auto *maxPlayersLabel = new QLabel(tr("P&layers:"));
|
||||
maxPlayersEdit = new QSpinBox();
|
||||
maxPlayersEdit->setMinimum(1);
|
||||
maxPlayersEdit->setMaximum(100);
|
||||
maxPlayersEdit->setValue(2);
|
||||
maxPlayersLabel->setBuddy(maxPlayersEdit);
|
||||
|
||||
auto *generalGrid = new QGridLayout;
|
||||
generalGrid->addWidget(descriptionLabel, 0, 0);
|
||||
generalGrid->addWidget(descriptionEdit, 0, 1);
|
||||
generalGrid->addWidget(maxPlayersLabel, 1, 0);
|
||||
generalGrid->addWidget(maxPlayersEdit, 1, 1);
|
||||
auto *generalGroupBox = new QGroupBox(tr("General"));
|
||||
generalGroupBox->setLayout(generalGrid);
|
||||
|
||||
auto *gameTypeLayout = new QVBoxLayout;
|
||||
for (auto it = gameTypes.cbegin(); it != gameTypes.cend(); ++it) {
|
||||
auto *gameTypeRadioButton = new QRadioButton(it.value(), this);
|
||||
gameTypeLayout->addWidget(gameTypeRadioButton);
|
||||
gameTypeCheckBoxes.insert(it.key(), gameTypeRadioButton);
|
||||
}
|
||||
auto *gameTypeGroupBox = new QGroupBox(tr("Game type"));
|
||||
gameTypeGroupBox->setLayout(gameTypeLayout);
|
||||
|
||||
auto *passwordLabel = new QLabel(tr("&Password:"));
|
||||
passwordEdit = new QLineEdit;
|
||||
passwordEdit->setMaxLength(MAX_NAME_LENGTH);
|
||||
passwordLabel->setBuddy(passwordEdit);
|
||||
|
||||
onlyBuddiesCheckBox = new QCheckBox(tr("Only &buddies can join"));
|
||||
onlyRegisteredCheckBox = new QCheckBox(tr("Only ®istered users can join"));
|
||||
if (registeredUser) {
|
||||
onlyRegisteredCheckBox->setChecked(true);
|
||||
} else {
|
||||
onlyBuddiesCheckBox->setEnabled(false);
|
||||
onlyRegisteredCheckBox->setEnabled(false);
|
||||
}
|
||||
|
||||
auto *joinRestrictionsLayout = new QGridLayout;
|
||||
joinRestrictionsLayout->addWidget(passwordLabel, 0, 0);
|
||||
joinRestrictionsLayout->addWidget(passwordEdit, 0, 1);
|
||||
joinRestrictionsLayout->addWidget(onlyBuddiesCheckBox, 1, 0, 1, 2);
|
||||
joinRestrictionsLayout->addWidget(onlyRegisteredCheckBox, 2, 0, 1, 2);
|
||||
|
||||
auto *joinRestrictionsGroupBox = new QGroupBox(tr("Joining restrictions"));
|
||||
joinRestrictionsGroupBox->setLayout(joinRestrictionsLayout);
|
||||
|
||||
spectatorsAllowedCheckBox = new QCheckBox(tr("&Spectators can watch"));
|
||||
spectatorsAllowedCheckBox->setChecked(true);
|
||||
connect(spectatorsAllowedCheckBox, &QCheckBox::QT_STATE_CHANGED, this,
|
||||
&CreateGameFormWidget::spectatorsAllowedChanged);
|
||||
spectatorsNeedPasswordCheckBox = new QCheckBox(tr("Spectators &need a password to watch"));
|
||||
spectatorsCanTalkCheckBox = new QCheckBox(tr("Spectators can &chat"));
|
||||
spectatorsSeeEverythingCheckBox = new QCheckBox(tr("Spectators can see &hands"));
|
||||
createGameAsSpectatorCheckBox = new QCheckBox(tr("Create game as spectator"));
|
||||
auto *spectatorsLayout = new QVBoxLayout;
|
||||
spectatorsLayout->addWidget(spectatorsAllowedCheckBox);
|
||||
spectatorsLayout->addWidget(spectatorsNeedPasswordCheckBox);
|
||||
spectatorsLayout->addWidget(spectatorsCanTalkCheckBox);
|
||||
spectatorsLayout->addWidget(spectatorsSeeEverythingCheckBox);
|
||||
spectatorsLayout->addWidget(createGameAsSpectatorCheckBox);
|
||||
auto *spectatorsGroupBox = new QGroupBox(tr("Spectators"));
|
||||
spectatorsGroupBox->setLayout(spectatorsLayout);
|
||||
|
||||
auto *startingLifeTotalLabel = new QLabel(tr("Starting life total:"));
|
||||
startingLifeTotalEdit = new QSpinBox();
|
||||
startingLifeTotalEdit->setMinimum(1);
|
||||
startingLifeTotalEdit->setMaximum(99999); ///< Arbitrary but we can raise this when people start complaining.
|
||||
startingLifeTotalEdit->setValue(20);
|
||||
startingLifeTotalLabel->setBuddy(startingLifeTotalEdit);
|
||||
|
||||
shareDecklistsOnLoadCheckBox = new QCheckBox(tr("Open decklists in lobby"));
|
||||
|
||||
shufflePlayersCheckBox = new QCheckBox(tr("Randomize turn order (seats) on each game start"));
|
||||
|
||||
createGameAsJudgeCheckBox = new QCheckBox(tr("Create game as judge"));
|
||||
|
||||
auto *gameSetupOptionsLayout = new QGridLayout;
|
||||
gameSetupOptionsLayout->addWidget(startingLifeTotalLabel, 0, 0);
|
||||
gameSetupOptionsLayout->addWidget(startingLifeTotalEdit, 0, 1);
|
||||
gameSetupOptionsLayout->addWidget(shareDecklistsOnLoadCheckBox, 1, 0, 1, 2);
|
||||
gameSetupOptionsLayout->addWidget(shufflePlayersCheckBox, 2, 0, 1, 2);
|
||||
if (judge) {
|
||||
gameSetupOptionsLayout->addWidget(createGameAsJudgeCheckBox, 3, 0, 1, 2);
|
||||
} else {
|
||||
createGameAsJudgeCheckBox->setChecked(false);
|
||||
createGameAsJudgeCheckBox->setHidden(true);
|
||||
}
|
||||
auto *gameSetupOptionsGroupBox = new QGroupBox(tr("Game setup options"));
|
||||
gameSetupOptionsGroupBox->setLayout(gameSetupOptionsLayout);
|
||||
|
||||
auto *grid = new QGridLayout;
|
||||
|
||||
// Top row
|
||||
grid->addWidget(generalGroupBox, 0, 0);
|
||||
grid->addWidget(joinRestrictionsGroupBox, 0, 1);
|
||||
|
||||
// Middle row: left column
|
||||
grid->addWidget(gameTypeGroupBox, 1, 0);
|
||||
|
||||
// Middle row: right column (game setup + spectators)
|
||||
auto *rightLayout = new QVBoxLayout;
|
||||
rightLayout->addWidget(spectatorsGroupBox, Qt::AlignTop); // top
|
||||
rightLayout->addWidget(gameSetupOptionsGroupBox); // bottom
|
||||
|
||||
grid->addLayout(rightLayout, 1, 1);
|
||||
|
||||
// Bottom row
|
||||
grid->addWidget(rememberGameSettings, 3, 0, 1, 2); // span both columns if needed
|
||||
|
||||
setLayout(grid);
|
||||
}
|
||||
|
||||
void CreateGameFormWidget::setOptions(const GameCreationOptions &options)
|
||||
{
|
||||
descriptionEdit->setText(options.description);
|
||||
maxPlayersEdit->setValue(options.maxPlayers);
|
||||
passwordEdit->setText(options.password);
|
||||
onlyBuddiesCheckBox->setChecked(options.onlyBuddies);
|
||||
onlyRegisteredCheckBox->setChecked(options.onlyRegistered);
|
||||
spectatorsAllowedCheckBox->setChecked(options.spectatorsAllowed);
|
||||
spectatorsNeedPasswordCheckBox->setChecked(options.spectatorsNeedPassword);
|
||||
spectatorsCanTalkCheckBox->setChecked(options.spectatorsCanTalk);
|
||||
spectatorsSeeEverythingCheckBox->setChecked(options.spectatorsSeeEverything);
|
||||
createGameAsJudgeCheckBox->setChecked(options.joinAsJudge);
|
||||
createGameAsSpectatorCheckBox->setChecked(options.joinAsSpectator);
|
||||
startingLifeTotalEdit->setValue(options.startingLifeTotal);
|
||||
shareDecklistsOnLoadCheckBox->setChecked(options.shareDecklistsOnLoad);
|
||||
shufflePlayersCheckBox->setChecked(options.shufflePlayers);
|
||||
|
||||
for (auto it = gameTypeCheckBoxes.cbegin(); it != gameTypeCheckBoxes.cend(); ++it) {
|
||||
it.value()->setChecked(options.gameTypeIds.contains(it.key()));
|
||||
}
|
||||
}
|
||||
|
||||
GameCreationOptions CreateGameFormWidget::options() const
|
||||
{
|
||||
GameCreationOptions options;
|
||||
options.description = descriptionEdit->text();
|
||||
options.password = passwordEdit->text();
|
||||
options.maxPlayers = maxPlayersEdit->value();
|
||||
options.onlyBuddies = onlyBuddiesCheckBox->isChecked();
|
||||
options.onlyRegistered = onlyRegisteredCheckBox->isChecked();
|
||||
options.spectatorsAllowed = spectatorsAllowedCheckBox->isChecked();
|
||||
options.spectatorsNeedPassword = spectatorsNeedPasswordCheckBox->isChecked();
|
||||
options.spectatorsCanTalk = spectatorsCanTalkCheckBox->isChecked();
|
||||
options.spectatorsSeeEverything = spectatorsSeeEverythingCheckBox->isChecked();
|
||||
options.joinAsJudge = createGameAsJudgeCheckBox->isChecked();
|
||||
options.joinAsSpectator = createGameAsSpectatorCheckBox->isChecked();
|
||||
options.startingLifeTotal = startingLifeTotalEdit->value();
|
||||
options.shareDecklistsOnLoad = shareDecklistsOnLoadCheckBox->isChecked();
|
||||
options.shufflePlayers = shufflePlayersCheckBox->isChecked();
|
||||
|
||||
for (auto it = gameTypeCheckBoxes.cbegin(); it != gameTypeCheckBoxes.cend(); ++it) {
|
||||
if (it.value()->isChecked()) {
|
||||
options.gameTypeIds.append(it.key());
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
QString CreateGameFormWidget::selectedGameTypesSettingString() const
|
||||
{
|
||||
QString gameTypes;
|
||||
for (auto it = gameTypeCheckBoxes.cbegin(); it != gameTypeCheckBoxes.cend(); ++it) {
|
||||
if (it.value()->isChecked()) {
|
||||
gameTypes += it.value()->text() + ", ";
|
||||
}
|
||||
}
|
||||
return gameTypes;
|
||||
}
|
||||
|
||||
void CreateGameFormWidget::resetToDefaults()
|
||||
{
|
||||
GameCreationOptions defaults;
|
||||
defaults.onlyRegistered = registeredUser;
|
||||
setOptions(defaults);
|
||||
|
||||
// An exclusive button group refuses to uncheck its selected button, which setOptions
|
||||
// cannot do, so clear the exclusive flag while resetting the game type selection.
|
||||
for (auto *gameTypeCheckBox : gameTypeCheckBoxes) {
|
||||
gameTypeCheckBox->setAutoExclusive(false);
|
||||
gameTypeCheckBox->setChecked(false);
|
||||
gameTypeCheckBox->setAutoExclusive(true);
|
||||
}
|
||||
|
||||
descriptionEdit->setFocus();
|
||||
}
|
||||
|
||||
void CreateGameFormWidget::setReadOnly(bool readOnly)
|
||||
{
|
||||
const bool editable = !readOnly;
|
||||
rememberGameSettings->setEnabled(editable);
|
||||
descriptionEdit->setEnabled(editable);
|
||||
maxPlayersEdit->setEnabled(editable);
|
||||
passwordEdit->setEnabled(editable);
|
||||
onlyBuddiesCheckBox->setEnabled(editable && registeredUser);
|
||||
onlyRegisteredCheckBox->setEnabled(editable && registeredUser);
|
||||
spectatorsAllowedCheckBox->setEnabled(editable);
|
||||
spectatorsNeedPasswordCheckBox->setEnabled(editable);
|
||||
spectatorsCanTalkCheckBox->setEnabled(editable);
|
||||
spectatorsSeeEverythingCheckBox->setEnabled(editable);
|
||||
createGameAsSpectatorCheckBox->setEnabled(editable);
|
||||
startingLifeTotalEdit->setEnabled(editable);
|
||||
shareDecklistsOnLoadCheckBox->setEnabled(editable);
|
||||
shufflePlayersCheckBox->setEnabled(editable);
|
||||
for (auto *gameTypeCheckBox : gameTypeCheckBoxes) {
|
||||
gameTypeCheckBox->setEnabled(editable);
|
||||
}
|
||||
}
|
||||
|
||||
void CreateGameFormWidget::focusDescription()
|
||||
{
|
||||
descriptionEdit->setFocus();
|
||||
}
|
||||
|
||||
bool CreateGameFormWidget::isRememberSettingsChecked() const
|
||||
{
|
||||
return rememberGameSettings->isChecked();
|
||||
}
|
||||
|
||||
void CreateGameFormWidget::setRememberSettingsChecked(bool checked)
|
||||
{
|
||||
rememberGameSettings->setChecked(checked);
|
||||
}
|
||||
|
||||
void CreateGameFormWidget::spectatorsAllowedChanged(QT_STATE_CHANGED_T state)
|
||||
{
|
||||
spectatorsNeedPasswordCheckBox->setEnabled(state);
|
||||
spectatorsCanTalkCheckBox->setEnabled(state);
|
||||
spectatorsSeeEverythingCheckBox->setEnabled(state);
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* @file create_game_form_widget.h
|
||||
* @ingroup RoomWidgets
|
||||
*/
|
||||
|
||||
#ifndef CREATE_GAME_FORM_WIDGET_H
|
||||
#define CREATE_GAME_FORM_WIDGET_H
|
||||
|
||||
#include "game_creation_options.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QWidget>
|
||||
#include <libcockatrice/utility/macros.h>
|
||||
#include <qtmetamacros.h>
|
||||
|
||||
class QCheckBox;
|
||||
class QLineEdit;
|
||||
class QRadioButton;
|
||||
class QSpinBox;
|
||||
|
||||
/**
|
||||
* @brief The editable create-game form, independent of settings, the network, and the room.
|
||||
*
|
||||
* The dialog loads @ref GameCreationOptions into it and reads them back; a future host
|
||||
* activity can do the same without duplicating the widget layout.
|
||||
*/
|
||||
class CreateGameFormWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CreateGameFormWidget(const QMap<int, QString> &gameTypes,
|
||||
bool registeredUser,
|
||||
bool judge,
|
||||
QWidget *parent = nullptr);
|
||||
|
||||
void setOptions(const GameCreationOptions &options);
|
||||
[[nodiscard]] GameCreationOptions options() const;
|
||||
[[nodiscard]] QString selectedGameTypesSettingString() const;
|
||||
void resetToDefaults();
|
||||
void setReadOnly(bool readOnly);
|
||||
void focusDescription();
|
||||
[[nodiscard]] bool isRememberSettingsChecked() const;
|
||||
void setRememberSettingsChecked(bool checked);
|
||||
|
||||
private slots:
|
||||
void spectatorsAllowedChanged(QT_STATE_CHANGED_T state);
|
||||
|
||||
private:
|
||||
bool registeredUser;
|
||||
QMap<int, QRadioButton *> gameTypeCheckBoxes;
|
||||
|
||||
QLineEdit *descriptionEdit;
|
||||
QLineEdit *passwordEdit;
|
||||
QSpinBox *maxPlayersEdit;
|
||||
QSpinBox *startingLifeTotalEdit;
|
||||
QCheckBox *onlyBuddiesCheckBox;
|
||||
QCheckBox *onlyRegisteredCheckBox;
|
||||
QCheckBox *spectatorsAllowedCheckBox;
|
||||
QCheckBox *spectatorsNeedPasswordCheckBox;
|
||||
QCheckBox *spectatorsCanTalkCheckBox;
|
||||
QCheckBox *spectatorsSeeEverythingCheckBox;
|
||||
QCheckBox *createGameAsJudgeCheckBox;
|
||||
QCheckBox *createGameAsSpectatorCheckBox;
|
||||
QCheckBox *shareDecklistsOnLoadCheckBox;
|
||||
QCheckBox *shufflePlayersCheckBox;
|
||||
QCheckBox *rememberGameSettings;
|
||||
};
|
||||
|
||||
#endif // CREATE_GAME_FORM_WIDGET_H
|
||||
|
|
@ -1,5 +1,69 @@
|
|||
#include "game_creation_options.h"
|
||||
|
||||
#include <QSet>
|
||||
#include <libcockatrice/interfaces/interface_game_settings_provider.h>
|
||||
#include <libcockatrice/protocol/pb/serverinfo_game.pb.h>
|
||||
|
||||
GameCreationOptions GameCreationOptions::fromSettings(const IGameSettingsProvider &settings,
|
||||
const QMap<int, QString> &gameTypes,
|
||||
bool registeredUser)
|
||||
{
|
||||
GameCreationOptions options;
|
||||
options.description = settings.getGameDescription();
|
||||
options.maxPlayers = settings.getMaxPlayers();
|
||||
if (registeredUser) {
|
||||
options.onlyBuddies = settings.getOnlyBuddies();
|
||||
options.onlyRegistered = settings.getOnlyRegistered();
|
||||
}
|
||||
options.spectatorsAllowed = settings.getSpectatorsAllowed();
|
||||
options.spectatorsNeedPassword = settings.getSpectatorsNeedPassword();
|
||||
options.spectatorsCanTalk = settings.getSpectatorsCanTalk();
|
||||
options.spectatorsSeeEverything = settings.getSpectatorsCanSeeEverything();
|
||||
options.joinAsSpectator = settings.getCreateGameAsSpectator();
|
||||
options.startingLifeTotal = settings.getDefaultStartingLifeTotal();
|
||||
options.shareDecklistsOnLoad = settings.getShareDecklistsOnLoad();
|
||||
options.shufflePlayers = settings.getShufflePlayers();
|
||||
|
||||
// The old dialog stored game type names as "Name, " in one string; keep the exact
|
||||
// substring test so an existing game.ini selects the same types after the split.
|
||||
const QString savedGameTypes = settings.getGameTypes();
|
||||
for (auto it = gameTypes.cbegin(); it != gameTypes.cend(); ++it) {
|
||||
if (savedGameTypes.contains(it.value() + ", ")) {
|
||||
options.gameTypeIds.append(it.key());
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
GameCreationOptions GameCreationOptions::fromGameInfo(const ServerInfo_Game &gameInfo,
|
||||
const QMap<int, QString> &gameTypes)
|
||||
{
|
||||
GameCreationOptions options;
|
||||
options.description = QString::fromStdString(gameInfo.description());
|
||||
options.maxPlayers = gameInfo.max_players();
|
||||
options.onlyBuddies = gameInfo.only_buddies();
|
||||
options.onlyRegistered = gameInfo.only_registered();
|
||||
options.spectatorsAllowed = gameInfo.spectators_allowed();
|
||||
options.spectatorsNeedPassword = gameInfo.spectators_need_password();
|
||||
options.spectatorsCanTalk = gameInfo.spectators_can_chat();
|
||||
options.spectatorsSeeEverything = gameInfo.spectators_omniscient();
|
||||
options.shareDecklistsOnLoad = gameInfo.share_decklists_on_load();
|
||||
options.shufflePlayers = gameInfo.shuffle_players();
|
||||
|
||||
QSet<int> selectedTypes;
|
||||
for (int i = 0; i < gameInfo.game_types_size(); ++i) {
|
||||
selectedTypes.insert(gameInfo.game_types(i));
|
||||
}
|
||||
for (auto it = gameTypes.cbegin(); it != gameTypes.cend(); ++it) {
|
||||
if (selectedTypes.contains(it.key())) {
|
||||
options.gameTypeIds.append(it.key());
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
Command_CreateGame GameCreationOptions::toCreateGameCommand() const
|
||||
{
|
||||
Command_CreateGame cmd;
|
||||
|
|
|
|||
|
|
@ -9,8 +9,12 @@
|
|||
#include "libcockatrice/protocol/pb/room_commands.pb.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
|
||||
class IGameSettingsProvider;
|
||||
class ServerInfo_Game;
|
||||
|
||||
/**
|
||||
* @brief The values needed to create a game, independent of the widgets that edit them.
|
||||
*
|
||||
|
|
@ -35,6 +39,22 @@ struct GameCreationOptions
|
|||
bool shufflePlayers = false;
|
||||
QList<int> gameTypeIds;
|
||||
|
||||
/**
|
||||
* @brief Reads the remembered create-game settings.
|
||||
*
|
||||
* Join restrictions are only meaningful for registered users, so they are left
|
||||
* unset for an unregistered host. Game type ids are resolved from the room's map
|
||||
* by matching the remembered names.
|
||||
*/
|
||||
[[nodiscard]] static GameCreationOptions
|
||||
fromSettings(const IGameSettingsProvider &settings, const QMap<int, QString> &gameTypes, bool registeredUser);
|
||||
|
||||
/**
|
||||
* @brief Reads the read-only fields shown in the game information view.
|
||||
*/
|
||||
[[nodiscard]] static GameCreationOptions fromGameInfo(const ServerInfo_Game &gameInfo,
|
||||
const QMap<int, QString> &gameTypes);
|
||||
|
||||
/**
|
||||
* @brief Builds the room command, simplifying the description's whitespace.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -469,6 +469,20 @@ cockatrice_add_test(
|
|||
${CMAKE_SOURCE_DIR}/cockatrice/src/interface/widgets/game_hosting/game_creation_options.cpp
|
||||
game_creation_options_test.cpp
|
||||
LIBS
|
||||
libcockatrice_interfaces
|
||||
libcockatrice_protocol
|
||||
INCLUDE_DIRS
|
||||
${CMAKE_SOURCE_DIR}/cockatrice/src
|
||||
)
|
||||
cockatrice_add_test(
|
||||
NAME
|
||||
create_game_form_widget_test
|
||||
SOURCES
|
||||
${CMAKE_SOURCE_DIR}/cockatrice/src/interface/widgets/game_hosting/create_game_form_widget.cpp
|
||||
${CMAKE_SOURCE_DIR}/cockatrice/src/interface/widgets/game_hosting/game_creation_options.cpp
|
||||
create_game_form_widget_test.cpp
|
||||
LIBS
|
||||
libcockatrice_interfaces
|
||||
libcockatrice_protocol
|
||||
INCLUDE_DIRS
|
||||
${CMAKE_SOURCE_DIR}/cockatrice/src
|
||||
|
|
|
|||
132
tests/create_game_form_widget_test.cpp
Normal file
132
tests/create_game_form_widget_test.cpp
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
#include "interface/widgets/game_hosting/create_game_form_widget.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QMap>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
const QMap<int, QString> gameTypes{{1, "Draft"}, {2, "Commander"}};
|
||||
|
||||
void expectSameOptions(const GameCreationOptions &actual, const GameCreationOptions &expected)
|
||||
{
|
||||
EXPECT_EQ(actual.description, expected.description);
|
||||
EXPECT_EQ(actual.password, expected.password);
|
||||
EXPECT_EQ(actual.maxPlayers, expected.maxPlayers);
|
||||
EXPECT_EQ(actual.onlyBuddies, expected.onlyBuddies);
|
||||
EXPECT_EQ(actual.onlyRegistered, expected.onlyRegistered);
|
||||
EXPECT_EQ(actual.spectatorsAllowed, expected.spectatorsAllowed);
|
||||
EXPECT_EQ(actual.spectatorsNeedPassword, expected.spectatorsNeedPassword);
|
||||
EXPECT_EQ(actual.spectatorsCanTalk, expected.spectatorsCanTalk);
|
||||
EXPECT_EQ(actual.spectatorsSeeEverything, expected.spectatorsSeeEverything);
|
||||
EXPECT_EQ(actual.joinAsJudge, expected.joinAsJudge);
|
||||
EXPECT_EQ(actual.joinAsSpectator, expected.joinAsSpectator);
|
||||
EXPECT_EQ(actual.startingLifeTotal, expected.startingLifeTotal);
|
||||
EXPECT_EQ(actual.shareDecklistsOnLoad, expected.shareDecklistsOnLoad);
|
||||
EXPECT_EQ(actual.shufflePlayers, expected.shufflePlayers);
|
||||
EXPECT_EQ(actual.gameTypeIds, expected.gameTypeIds);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST(CreateGameFormWidget, RegisteredHostDefaultsToRegisteredOnly)
|
||||
{
|
||||
const CreateGameFormWidget form(gameTypes, true, false);
|
||||
|
||||
const GameCreationOptions options = form.options();
|
||||
|
||||
EXPECT_TRUE(options.onlyRegistered);
|
||||
EXPECT_FALSE(options.onlyBuddies);
|
||||
EXPECT_EQ(options.maxPlayers, 2);
|
||||
EXPECT_TRUE(options.spectatorsAllowed);
|
||||
EXPECT_EQ(options.startingLifeTotal, 20);
|
||||
EXPECT_TRUE(options.gameTypeIds.isEmpty());
|
||||
}
|
||||
|
||||
TEST(CreateGameFormWidget, UnregisteredHostDefaultsToOpenJoin)
|
||||
{
|
||||
const CreateGameFormWidget form(gameTypes, false, false);
|
||||
|
||||
const GameCreationOptions options = form.options();
|
||||
|
||||
EXPECT_FALSE(options.onlyRegistered);
|
||||
EXPECT_FALSE(options.onlyBuddies);
|
||||
}
|
||||
|
||||
TEST(CreateGameFormWidget, SetOptionsRoundTripsEveryField)
|
||||
{
|
||||
CreateGameFormWidget form(gameTypes, true, true);
|
||||
|
||||
GameCreationOptions expected;
|
||||
expected.description = "Some game";
|
||||
expected.password = "hunter2";
|
||||
expected.maxPlayers = 5;
|
||||
expected.onlyBuddies = true;
|
||||
expected.onlyRegistered = false;
|
||||
expected.spectatorsAllowed = false;
|
||||
expected.spectatorsNeedPassword = true;
|
||||
expected.spectatorsCanTalk = true;
|
||||
expected.spectatorsSeeEverything = true;
|
||||
expected.joinAsJudge = true;
|
||||
expected.joinAsSpectator = true;
|
||||
expected.startingLifeTotal = 40;
|
||||
expected.shareDecklistsOnLoad = true;
|
||||
expected.shufflePlayers = true;
|
||||
expected.gameTypeIds = {2};
|
||||
|
||||
form.setOptions(expected);
|
||||
|
||||
expectSameOptions(form.options(), expected);
|
||||
}
|
||||
|
||||
TEST(CreateGameFormWidget, ResetRestoresDefaultsAndClearsTheGameType)
|
||||
{
|
||||
CreateGameFormWidget form(gameTypes, true, false);
|
||||
GameCreationOptions configured;
|
||||
configured.description = "Configured";
|
||||
configured.maxPlayers = 8;
|
||||
configured.onlyBuddies = true;
|
||||
configured.joinAsJudge = true;
|
||||
configured.gameTypeIds = {2};
|
||||
form.setOptions(configured);
|
||||
|
||||
form.resetToDefaults();
|
||||
|
||||
const GameCreationOptions options = form.options();
|
||||
EXPECT_TRUE(options.description.isEmpty());
|
||||
EXPECT_EQ(options.maxPlayers, 2);
|
||||
EXPECT_FALSE(options.onlyBuddies);
|
||||
EXPECT_TRUE(options.onlyRegistered);
|
||||
EXPECT_TRUE(options.spectatorsAllowed);
|
||||
EXPECT_EQ(options.startingLifeTotal, 20);
|
||||
EXPECT_FALSE(options.joinAsJudge);
|
||||
EXPECT_TRUE(options.gameTypeIds.isEmpty());
|
||||
}
|
||||
|
||||
TEST(CreateGameFormWidget, RememberSettingsFlagRoundTrips)
|
||||
{
|
||||
CreateGameFormWidget form(gameTypes, true, false);
|
||||
|
||||
EXPECT_FALSE(form.isRememberSettingsChecked());
|
||||
|
||||
form.setRememberSettingsChecked(true);
|
||||
|
||||
EXPECT_TRUE(form.isRememberSettingsChecked());
|
||||
}
|
||||
|
||||
TEST(CreateGameFormWidget, SelectedGameTypesSettingStringUsesTheLegacyEncoding)
|
||||
{
|
||||
CreateGameFormWidget form(gameTypes, true, false);
|
||||
GameCreationOptions configured;
|
||||
configured.gameTypeIds = {1};
|
||||
form.setOptions(configured);
|
||||
|
||||
EXPECT_EQ(form.selectedGameTypesSettingString(), "Draft, ");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
qputenv("QT_QPA_PLATFORM", "offscreen");
|
||||
QApplication app(argc, argv);
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
|
@ -1,7 +1,100 @@
|
|||
#include "interface/widgets/game_hosting/game_creation_options.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <libcockatrice/interfaces/interface_game_settings_provider.h>
|
||||
#include <libcockatrice/protocol/pb/room_commands.pb.h>
|
||||
#include <libcockatrice/protocol/pb/serverinfo_game.pb.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
/**
|
||||
* @brief The remembered settings a test hands to fromSettings.
|
||||
*
|
||||
* The fake cannot itself be an aggregate (it derives from a polymorphic interface), so the
|
||||
* remembered values live in a GameCreationOptions member and the getters read them from
|
||||
* there. That keeps the test data in one designated initializer.
|
||||
*/
|
||||
class FakeGameSettings : public IGameSettingsProvider
|
||||
{
|
||||
public:
|
||||
explicit FakeGameSettings(const GameCreationOptions &_options = {}) : options(_options)
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] QString getGameDescription() const override
|
||||
{
|
||||
return options.description;
|
||||
}
|
||||
[[nodiscard]] int getMaxPlayers() const override
|
||||
{
|
||||
return options.maxPlayers;
|
||||
}
|
||||
[[nodiscard]] QString getGameTypes() const override
|
||||
{
|
||||
return gameTypes;
|
||||
}
|
||||
[[nodiscard]] bool getOnlyBuddies() const override
|
||||
{
|
||||
return options.onlyBuddies;
|
||||
}
|
||||
[[nodiscard]] bool getOnlyRegistered() const override
|
||||
{
|
||||
return options.onlyRegistered;
|
||||
}
|
||||
[[nodiscard]] bool getSpectatorsAllowed() const override
|
||||
{
|
||||
return options.spectatorsAllowed;
|
||||
}
|
||||
[[nodiscard]] bool getSpectatorsNeedPassword() const override
|
||||
{
|
||||
return options.spectatorsNeedPassword;
|
||||
}
|
||||
[[nodiscard]] bool getSpectatorsCanTalk() const override
|
||||
{
|
||||
return options.spectatorsCanTalk;
|
||||
}
|
||||
[[nodiscard]] bool getSpectatorsCanSeeEverything() const override
|
||||
{
|
||||
return options.spectatorsSeeEverything;
|
||||
}
|
||||
[[nodiscard]] bool getCreateGameAsSpectator() const override
|
||||
{
|
||||
return options.joinAsSpectator;
|
||||
}
|
||||
[[nodiscard]] int getDefaultStartingLifeTotal() const override
|
||||
{
|
||||
return options.startingLifeTotal;
|
||||
}
|
||||
[[nodiscard]] bool getShareDecklistsOnLoad() const override
|
||||
{
|
||||
return options.shareDecklistsOnLoad;
|
||||
}
|
||||
[[nodiscard]] bool getShufflePlayers() const override
|
||||
{
|
||||
return options.shufflePlayers;
|
||||
}
|
||||
[[nodiscard]] bool getRememberGameSettings() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
[[nodiscard]] bool getLocalGameRememberSettings() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
[[nodiscard]] int getLocalGameMaxPlayers() const override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
[[nodiscard]] int getLocalGameStartingLifeTotal() const override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
GameCreationOptions options;
|
||||
/// The legacy "Name, " list; it has no GameCreationOptions counterpart.
|
||||
QString gameTypes;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
TEST(GameCreationOptions, DefaultsMatchTheDialog)
|
||||
{
|
||||
|
|
@ -91,3 +184,127 @@ TEST(GameCreationOptions, DescriptionWhitespaceIsSimplified)
|
|||
|
||||
EXPECT_EQ(cmd.description(), "a b");
|
||||
}
|
||||
|
||||
TEST(GameCreationOptions, FromSettingsCopiesEveryRememberedField)
|
||||
{
|
||||
const FakeGameSettings settings{GameCreationOptions{.description = "Remembered game",
|
||||
.password = {},
|
||||
.maxPlayers = 6,
|
||||
.onlyBuddies = true,
|
||||
.onlyRegistered = true,
|
||||
.spectatorsAllowed = false,
|
||||
.spectatorsNeedPassword = true,
|
||||
.spectatorsCanTalk = true,
|
||||
.spectatorsSeeEverything = true,
|
||||
.joinAsJudge = false,
|
||||
.joinAsSpectator = true,
|
||||
.startingLifeTotal = 40,
|
||||
.shareDecklistsOnLoad = true,
|
||||
.shufflePlayers = true,
|
||||
.gameTypeIds = {}}};
|
||||
|
||||
const GameCreationOptions options = GameCreationOptions::fromSettings(settings, {}, true);
|
||||
|
||||
EXPECT_EQ(options.description, "Remembered game");
|
||||
EXPECT_EQ(options.maxPlayers, 6);
|
||||
EXPECT_TRUE(options.onlyBuddies);
|
||||
EXPECT_TRUE(options.onlyRegistered);
|
||||
EXPECT_FALSE(options.spectatorsAllowed);
|
||||
EXPECT_TRUE(options.spectatorsNeedPassword);
|
||||
EXPECT_TRUE(options.spectatorsCanTalk);
|
||||
EXPECT_TRUE(options.spectatorsSeeEverything);
|
||||
EXPECT_TRUE(options.joinAsSpectator);
|
||||
EXPECT_EQ(options.startingLifeTotal, 40);
|
||||
EXPECT_TRUE(options.shareDecklistsOnLoad);
|
||||
EXPECT_TRUE(options.shufflePlayers);
|
||||
}
|
||||
|
||||
TEST(GameCreationOptions, FromSettingsDropsJoinRestrictionsForUnregisteredHosts)
|
||||
{
|
||||
FakeGameSettings settings;
|
||||
settings.options.onlyBuddies = true;
|
||||
settings.options.onlyRegistered = true;
|
||||
|
||||
const GameCreationOptions options = GameCreationOptions::fromSettings(settings, {}, false);
|
||||
|
||||
EXPECT_FALSE(options.onlyBuddies);
|
||||
EXPECT_FALSE(options.onlyRegistered);
|
||||
}
|
||||
|
||||
TEST(GameCreationOptions, FromSettingsMatchesGameTypesByTheLegacyNameList)
|
||||
{
|
||||
FakeGameSettings settings;
|
||||
settings.gameTypes = "Draft, Commander, ";
|
||||
const QMap<int, QString> gameTypes{{1, "Draft"}, {2, "Commander"}, {3, "Standard"}};
|
||||
|
||||
const GameCreationOptions options = GameCreationOptions::fromSettings(settings, gameTypes, true);
|
||||
|
||||
EXPECT_EQ(options.gameTypeIds, QList<int>({1, 2}));
|
||||
}
|
||||
|
||||
TEST(GameCreationOptions, FromSettingsDoesNotMatchGameTypesWithoutTheLegacySeparator)
|
||||
{
|
||||
FakeGameSettings settings;
|
||||
settings.gameTypes = "Draft Commander";
|
||||
const QMap<int, QString> gameTypes{{1, "Draft"}, {2, "Commander"}};
|
||||
|
||||
const GameCreationOptions options = GameCreationOptions::fromSettings(settings, gameTypes, true);
|
||||
|
||||
EXPECT_TRUE(options.gameTypeIds.isEmpty());
|
||||
}
|
||||
|
||||
TEST(GameCreationOptions, FromGameInfoCopiesTheVisibleFields)
|
||||
{
|
||||
ServerInfo_Game gameInfo;
|
||||
gameInfo.set_description("Some game");
|
||||
gameInfo.set_max_players(4);
|
||||
gameInfo.set_only_buddies(true);
|
||||
gameInfo.set_only_registered(true);
|
||||
gameInfo.set_spectators_allowed(false);
|
||||
gameInfo.set_spectators_need_password(true);
|
||||
gameInfo.set_spectators_can_chat(true);
|
||||
gameInfo.set_spectators_omniscient(true);
|
||||
gameInfo.set_share_decklists_on_load(true);
|
||||
gameInfo.set_shuffle_players(true);
|
||||
gameInfo.add_game_types(2);
|
||||
|
||||
const QMap<int, QString> gameTypes{{1, "Draft"}, {2, "Commander"}};
|
||||
const GameCreationOptions options = GameCreationOptions::fromGameInfo(gameInfo, gameTypes);
|
||||
|
||||
EXPECT_EQ(options.description, "Some game");
|
||||
EXPECT_EQ(options.maxPlayers, 4);
|
||||
EXPECT_TRUE(options.onlyBuddies);
|
||||
EXPECT_TRUE(options.onlyRegistered);
|
||||
EXPECT_FALSE(options.spectatorsAllowed);
|
||||
EXPECT_TRUE(options.spectatorsNeedPassword);
|
||||
EXPECT_TRUE(options.spectatorsCanTalk);
|
||||
EXPECT_TRUE(options.spectatorsSeeEverything);
|
||||
EXPECT_TRUE(options.shareDecklistsOnLoad);
|
||||
EXPECT_TRUE(options.shufflePlayers);
|
||||
EXPECT_EQ(options.gameTypeIds, QList<int>({2}));
|
||||
}
|
||||
|
||||
TEST(GameCreationOptions, FromGameInfoLeavesUnshownFieldsAtDefaults)
|
||||
{
|
||||
ServerInfo_Game gameInfo;
|
||||
gameInfo.set_max_players(3);
|
||||
|
||||
const GameCreationOptions options = GameCreationOptions::fromGameInfo(gameInfo, {});
|
||||
|
||||
EXPECT_TRUE(options.password.isEmpty());
|
||||
EXPECT_EQ(options.startingLifeTotal, 20);
|
||||
EXPECT_FALSE(options.joinAsJudge);
|
||||
EXPECT_FALSE(options.joinAsSpectator);
|
||||
}
|
||||
|
||||
TEST(GameCreationOptions, FromGameInfoIgnoresUnknownGameTypeIds)
|
||||
{
|
||||
ServerInfo_Game gameInfo;
|
||||
gameInfo.add_game_types(7);
|
||||
gameInfo.add_game_types(9);
|
||||
|
||||
const QMap<int, QString> gameTypes{{1, "Draft"}, {7, "Commander"}};
|
||||
const GameCreationOptions options = GameCreationOptions::fromGameInfo(gameInfo, gameTypes);
|
||||
|
||||
EXPECT_EQ(options.gameTypeIds, QList<int>({7}));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue