mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-07-02 03:23:56 -07:00
* move message_log_widget to game * move files * update headers * fix cmakelists * oracle fixes * split implementation out to cpp * fix recursive import * fix main file * format
This commit is contained in:
parent
f484c98152
commit
17dcaf9afa
337 changed files with 728 additions and 721 deletions
|
|
@ -1,8 +1,8 @@
|
|||
#include "abstract_card_item.h"
|
||||
|
||||
#include "../../client/ui/picture_loader/picture_loader.h"
|
||||
#include "../../database/card_database.h"
|
||||
#include "../../database/card_database_manager.h"
|
||||
#include "../../picture_loader/picture_loader.h"
|
||||
#include "../../settings/cache_settings.h"
|
||||
#include "../game_scene.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
#include "abstract_counter.h"
|
||||
|
||||
#include "../../client/tabs/tab_game.h"
|
||||
#include "../../client/translate_counter_name.h"
|
||||
#include "../../settings/cache_settings.h"
|
||||
#include "../../tabs/tab_game.h"
|
||||
#include "../player/player.h"
|
||||
#include "expression.h"
|
||||
#include "pb/command_inc_counter.pb.h"
|
||||
#include "pb/command_set_counter.pb.h"
|
||||
#include "translate_counter_name.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QApplication>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef COUNTER_H
|
||||
#define COUNTER_H
|
||||
|
||||
#include "../../client/tearoff_menu.h"
|
||||
#include "../../interface/tearoff_menu.h"
|
||||
|
||||
#include <QGraphicsItem>
|
||||
#include <QInputDialog>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
#include "card_item.h"
|
||||
|
||||
#include "../../card/card_info.h"
|
||||
#include "../../client/tabs/tab_game.h"
|
||||
#include "../../settings/cache_settings.h"
|
||||
#include "../../settings/card_counter_settings.h"
|
||||
#include "../../tabs/tab_game.h"
|
||||
#include "../game_scene.h"
|
||||
#include "../player/player.h"
|
||||
#include "../zones/card_zone.h"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "counter_general.h"
|
||||
|
||||
#include "../../client/ui/pixel_map_generator.h"
|
||||
#include "../../interface/pixel_map_generator.h"
|
||||
#include "abstract_graphics_item.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
|
|
|||
11
cockatrice/src/game/board/translate_counter_name.cpp
Normal file
11
cockatrice/src/game/board/translate_counter_name.cpp
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#include "translate_counter_name.h"
|
||||
|
||||
const QMap<QString, QString> TranslateCounterName::translated = {
|
||||
{"life", QT_TRANSLATE_NOOP("TranslateCounterName", "Life")},
|
||||
{"w", QT_TRANSLATE_NOOP("TranslateCounterName", "White")},
|
||||
{"u", QT_TRANSLATE_NOOP("TranslateCounterName", "Blue")},
|
||||
{"b", QT_TRANSLATE_NOOP("TranslateCounterName", "Black")},
|
||||
{"r", QT_TRANSLATE_NOOP("TranslateCounterName", "Red")},
|
||||
{"g", QT_TRANSLATE_NOOP("TranslateCounterName", "Green")},
|
||||
{"x", QT_TRANSLATE_NOOP("TranslateCounterName", "Colorless")},
|
||||
{"storm", QT_TRANSLATE_NOOP("TranslateCounterName", "Other")}};
|
||||
24
cockatrice/src/game/board/translate_counter_name.h
Normal file
24
cockatrice/src/game/board/translate_counter_name.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef TRANSLATECOUNTERNAME_H
|
||||
#define TRANSLATECOUNTERNAME_H
|
||||
|
||||
#include <QString>
|
||||
#include <QtCore>
|
||||
|
||||
class TranslateCounterName
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(TranslateCounterName)
|
||||
|
||||
static const QMap<QString, QString> translated;
|
||||
|
||||
public:
|
||||
static QString getDisplayName(const QString &name)
|
||||
{
|
||||
if (translated.contains(name)) {
|
||||
return tr(translated[name].toLatin1());
|
||||
} else {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // TRANSLATECOUNTERNAME_H
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#include "deck_view.h"
|
||||
|
||||
#include "../../card/card_info.h"
|
||||
#include "../../client/ui/theme_manager.h"
|
||||
#include "../../interface/theme_manager.h"
|
||||
#include "../../settings/cache_settings.h"
|
||||
#include "deck_list.h"
|
||||
#include "deck_list_card_node.h"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#include "deck_view_container.h"
|
||||
|
||||
#include "../../client/tabs/tab_game.h"
|
||||
#include "../../client/ui/picture_loader/picture_loader.h"
|
||||
#include "../../database/card_database.h"
|
||||
#include "../../database/card_database_manager.h"
|
||||
#include "../../deck/deck_loader.h"
|
||||
|
|
@ -9,8 +7,10 @@
|
|||
#include "../../dialogs/dlg_load_deck_from_clipboard.h"
|
||||
#include "../../dialogs/dlg_load_deck_from_website.h"
|
||||
#include "../../dialogs/dlg_load_remote_deck.h"
|
||||
#include "../../picture_loader/picture_loader.h"
|
||||
#include "../../server/pending_command.h"
|
||||
#include "../../settings/cache_settings.h"
|
||||
#include "../../tabs/tab_game.h"
|
||||
#include "../game_scene.h"
|
||||
#include "deck_view.h"
|
||||
#include "pb/command_deck_select.pb.h"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "tabbed_deck_view_container.h"
|
||||
|
||||
#include "../../client/tabs/tab_game.h"
|
||||
#include "../../tabs/tab_game.h"
|
||||
#include "deck_view.h"
|
||||
|
||||
TabbedDeckViewContainer::TabbedDeckViewContainer(int _playerId, TabGame *parent)
|
||||
|
|
|
|||
264
cockatrice/src/game/dialogs/dlg_create_token.cpp
Normal file
264
cockatrice/src/game/dialogs/dlg_create_token.cpp
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
#include "dlg_create_token.h"
|
||||
|
||||
#include "../../database/card_database_manager.h"
|
||||
#include "../../database/card_database_model.h"
|
||||
#include "../../interface/widgets/cards/card_info_picture_widget.h"
|
||||
#include "../../main.h"
|
||||
#include "../../settings/cache_settings.h"
|
||||
#include "deck_list.h"
|
||||
#include "trice_limits.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QCloseEvent>
|
||||
#include <QComboBox>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QHeaderView>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QRadioButton>
|
||||
#include <QTreeView>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
DlgCreateToken::DlgCreateToken(const QStringList &_predefinedTokens, QWidget *parent)
|
||||
: QDialog(parent), predefinedTokens(_predefinedTokens)
|
||||
{
|
||||
pic = new CardInfoPictureWidget();
|
||||
pic->setObjectName("pic");
|
||||
|
||||
nameLabel = new QLabel(tr("&Name:"));
|
||||
nameEdit = new QLineEdit(tr("Token"));
|
||||
nameEdit->setMaxLength(MAX_NAME_LENGTH);
|
||||
QTimer::singleShot(100, this, [=, this]() {
|
||||
nameEdit->selectAll();
|
||||
nameEdit->setFocus();
|
||||
});
|
||||
|
||||
connect(nameEdit, &QLineEdit::textChanged, this, &DlgCreateToken::updateSearch);
|
||||
nameLabel->setBuddy(nameEdit);
|
||||
|
||||
colorLabel = new QLabel(tr("C&olor:"));
|
||||
colorEdit = new QComboBox;
|
||||
colorEdit->addItem(tr("white"), QChar('w'));
|
||||
colorEdit->addItem(tr("blue"), QChar('u'));
|
||||
colorEdit->addItem(tr("black"), QChar('b'));
|
||||
colorEdit->addItem(tr("red"), QChar('r'));
|
||||
colorEdit->addItem(tr("green"), QChar('g'));
|
||||
colorEdit->addItem(tr("multicolor"), QChar('m'));
|
||||
colorEdit->addItem(tr("colorless"), QChar());
|
||||
colorLabel->setBuddy(colorEdit);
|
||||
|
||||
ptLabel = new QLabel(tr("&P/T:"));
|
||||
ptEdit = new QLineEdit;
|
||||
ptEdit->setMaxLength(MAX_NAME_LENGTH);
|
||||
ptLabel->setBuddy(ptEdit);
|
||||
|
||||
annotationLabel = new QLabel(tr("&Annotation:"));
|
||||
annotationEdit = new QLineEdit;
|
||||
annotationEdit->setMaxLength(MAX_NAME_LENGTH);
|
||||
annotationLabel->setBuddy(annotationEdit);
|
||||
|
||||
destroyCheckBox = new QCheckBox(tr("&Destroy token when it leaves the table"));
|
||||
destroyCheckBox->setChecked(true);
|
||||
|
||||
faceDownCheckBox = new QCheckBox(tr("Create face-down (Only hides name)"));
|
||||
connect(faceDownCheckBox, &QCheckBox::toggled, this, &DlgCreateToken::faceDownCheckBoxToggled);
|
||||
|
||||
QGridLayout *grid = new QGridLayout;
|
||||
grid->addWidget(nameLabel, 0, 0);
|
||||
grid->addWidget(nameEdit, 0, 1);
|
||||
grid->addWidget(colorLabel, 1, 0);
|
||||
grid->addWidget(colorEdit, 1, 1);
|
||||
grid->addWidget(ptLabel, 2, 0);
|
||||
grid->addWidget(ptEdit, 2, 1);
|
||||
grid->addWidget(annotationLabel, 3, 0);
|
||||
grid->addWidget(annotationEdit, 3, 1);
|
||||
grid->addWidget(destroyCheckBox, 4, 0, 1, 2);
|
||||
grid->addWidget(faceDownCheckBox, 5, 0, 1, 2);
|
||||
|
||||
QGroupBox *tokenDataGroupBox = new QGroupBox(tr("Token data"));
|
||||
tokenDataGroupBox->setLayout(grid);
|
||||
|
||||
cardDatabaseModel = new CardDatabaseModel(CardDatabaseManager::getInstance(), false, this);
|
||||
cardDatabaseDisplayModel = new TokenDisplayModel(this);
|
||||
cardDatabaseDisplayModel->setSourceModel(cardDatabaseModel);
|
||||
|
||||
chooseTokenFromAllRadioButton = new QRadioButton(tr("Show &all tokens"));
|
||||
connect(chooseTokenFromAllRadioButton, &QRadioButton::toggled, this, &DlgCreateToken::actChooseTokenFromAll);
|
||||
chooseTokenFromDeckRadioButton = new QRadioButton(tr("Show tokens from this &deck"));
|
||||
connect(chooseTokenFromDeckRadioButton, &QRadioButton::toggled, this, &DlgCreateToken::actChooseTokenFromDeck);
|
||||
|
||||
QByteArray deckHeaderState = SettingsCache::instance().layouts().getDeckEditorDbHeaderState();
|
||||
chooseTokenView = new QTreeView;
|
||||
chooseTokenView->setModel(cardDatabaseDisplayModel);
|
||||
chooseTokenView->setUniformRowHeights(true);
|
||||
chooseTokenView->setRootIsDecorated(false);
|
||||
chooseTokenView->setAlternatingRowColors(true);
|
||||
chooseTokenView->setSortingEnabled(true);
|
||||
chooseTokenView->sortByColumn(0, Qt::AscendingOrder);
|
||||
chooseTokenView->resizeColumnToContents(0);
|
||||
chooseTokenView->setWordWrap(true);
|
||||
|
||||
if (!deckHeaderState.isNull())
|
||||
chooseTokenView->header()->restoreState(deckHeaderState);
|
||||
|
||||
chooseTokenView->header()->setStretchLastSection(false);
|
||||
chooseTokenView->header()->hideSection(1); // Sets
|
||||
chooseTokenView->header()->hideSection(2); // Mana Cost
|
||||
chooseTokenView->header()->setSectionResizeMode(5, QHeaderView::ResizeToContents); // Color(s)
|
||||
connect(chooseTokenView->selectionModel(), &QItemSelectionModel::currentRowChanged, this,
|
||||
&DlgCreateToken::tokenSelectionChanged);
|
||||
connect(chooseTokenView, &QTreeView::doubleClicked, this, &DlgCreateToken::actOk);
|
||||
|
||||
if (predefinedTokens.isEmpty()) {
|
||||
chooseTokenFromAllRadioButton->setChecked(true);
|
||||
chooseTokenFromDeckRadioButton->setDisabled(true); // No tokens in deck = no need for option
|
||||
} else {
|
||||
chooseTokenFromDeckRadioButton->setChecked(true);
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
cardDatabaseDisplayModel->setCardNameSet(QSet<QString>(predefinedTokens.begin(), predefinedTokens.end()));
|
||||
#else
|
||||
cardDatabaseDisplayModel->setCardNameSet(QSet<QString>::fromList(predefinedTokens));
|
||||
#endif
|
||||
}
|
||||
|
||||
QVBoxLayout *tokenChooseLayout = new QVBoxLayout;
|
||||
tokenChooseLayout->addWidget(chooseTokenFromAllRadioButton);
|
||||
tokenChooseLayout->addWidget(chooseTokenFromDeckRadioButton);
|
||||
tokenChooseLayout->addWidget(chooseTokenView);
|
||||
|
||||
QGroupBox *tokenChooseGroupBox = new QGroupBox(tr("Choose token from list"));
|
||||
tokenChooseGroupBox->setLayout(tokenChooseLayout);
|
||||
|
||||
QGridLayout *hbox = new QGridLayout;
|
||||
hbox->addWidget(pic, 0, 0, 1, 1);
|
||||
hbox->addWidget(tokenDataGroupBox, 1, 0, 1, 1);
|
||||
hbox->addWidget(tokenChooseGroupBox, 0, 1, 2, 1);
|
||||
hbox->setColumnStretch(1, 1);
|
||||
|
||||
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &DlgCreateToken::actOk);
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &DlgCreateToken::actReject);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(hbox);
|
||||
mainLayout->addWidget(buttonBox);
|
||||
setLayout(mainLayout);
|
||||
|
||||
setWindowTitle(tr("Create token"));
|
||||
|
||||
resize(600, 500);
|
||||
restoreGeometry(SettingsCache::instance().getTokenDialogGeometry());
|
||||
}
|
||||
|
||||
void DlgCreateToken::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
event->accept();
|
||||
SettingsCache::instance().setTokenDialogGeometry(saveGeometry());
|
||||
}
|
||||
|
||||
void DlgCreateToken::faceDownCheckBoxToggled(bool checked)
|
||||
{
|
||||
if (checked) {
|
||||
colorEdit->setCurrentIndex(6);
|
||||
colorEdit->setEnabled(false);
|
||||
ptEdit->clear();
|
||||
ptEdit->clearFocus();
|
||||
ptEdit->setEnabled(false);
|
||||
} else {
|
||||
colorEdit->setEnabled(true);
|
||||
ptEdit->setEnabled(true);
|
||||
annotationEdit->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void DlgCreateToken::tokenSelectionChanged(const QModelIndex ¤t, const QModelIndex & /*previous*/)
|
||||
{
|
||||
const QModelIndex realIndex = cardDatabaseDisplayModel->mapToSource(current);
|
||||
|
||||
CardInfoPtr cardInfo;
|
||||
|
||||
if (current.row() >= 0) {
|
||||
cardInfo = cardDatabaseModel->getCard(realIndex.row());
|
||||
}
|
||||
|
||||
if (cardInfo) {
|
||||
updateSearchFieldWithoutUpdatingFilter(cardInfo->getName());
|
||||
const QChar cardColor = cardInfo->getColorChar();
|
||||
colorEdit->setCurrentIndex(colorEdit->findData(cardColor, Qt::UserRole, Qt::MatchFixedString));
|
||||
ptEdit->setText(cardInfo->getPowTough());
|
||||
if (SettingsCache::instance().getAnnotateTokens())
|
||||
annotationEdit->setText(cardInfo->getText());
|
||||
} else {
|
||||
nameEdit->setText("");
|
||||
colorEdit->setCurrentIndex(colorEdit->findData(QString(), Qt::UserRole, Qt::MatchFixedString));
|
||||
ptEdit->setText("");
|
||||
annotationEdit->setText("");
|
||||
}
|
||||
|
||||
const auto &cardProviderId =
|
||||
SettingsCache::instance().cardOverrides().getCardPreferenceOverride(cardInfo->getName());
|
||||
if (!cardProviderId.isEmpty()) {
|
||||
CardRef ref;
|
||||
ref.name = cardInfo->getName();
|
||||
ref.providerId = cardProviderId;
|
||||
pic->setCard(CardDatabaseManager::getInstance()->getCard(ref));
|
||||
} else {
|
||||
pic->setCard(CardDatabaseManager::getInstance()->getPreferredCard(cardInfo));
|
||||
}
|
||||
}
|
||||
|
||||
void DlgCreateToken::updateSearchFieldWithoutUpdatingFilter(const QString &newValue) const
|
||||
{
|
||||
nameEdit->blockSignals(true);
|
||||
nameEdit->setText(newValue);
|
||||
nameEdit->blockSignals(false);
|
||||
}
|
||||
|
||||
void DlgCreateToken::updateSearch(const QString &search)
|
||||
{
|
||||
cardDatabaseDisplayModel->setCardName(search);
|
||||
}
|
||||
|
||||
void DlgCreateToken::actChooseTokenFromAll(bool checked)
|
||||
{
|
||||
if (checked) {
|
||||
cardDatabaseDisplayModel->setCardNameSet(QSet<QString>());
|
||||
}
|
||||
}
|
||||
|
||||
void DlgCreateToken::actChooseTokenFromDeck(bool checked)
|
||||
{
|
||||
if (checked) {
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
cardDatabaseDisplayModel->setCardNameSet(QSet<QString>(predefinedTokens.begin(), predefinedTokens.end()));
|
||||
#else
|
||||
cardDatabaseDisplayModel->setCardNameSet(QSet<QString>::fromList(predefinedTokens));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void DlgCreateToken::actOk()
|
||||
{
|
||||
SettingsCache::instance().setTokenDialogGeometry(saveGeometry());
|
||||
accept();
|
||||
}
|
||||
|
||||
void DlgCreateToken::actReject()
|
||||
{
|
||||
SettingsCache::instance().setTokenDialogGeometry(saveGeometry());
|
||||
reject();
|
||||
}
|
||||
|
||||
TokenInfo DlgCreateToken::getTokenInfo() const
|
||||
{
|
||||
return {.name = nameEdit->text(),
|
||||
.color = colorEdit->itemData(colorEdit->currentIndex()).toString(),
|
||||
.pt = ptEdit->text(),
|
||||
.annotation = annotationEdit->text(),
|
||||
.destroy = destroyCheckBox->isChecked(),
|
||||
.faceDown = faceDownCheckBox->isChecked(),
|
||||
.providerId = SettingsCache::instance().cardOverrides().getCardPreferenceOverride(nameEdit->text())};
|
||||
}
|
||||
65
cockatrice/src/game/dialogs/dlg_create_token.h
Normal file
65
cockatrice/src/game/dialogs/dlg_create_token.h
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
#ifndef DLG_CREATETOKEN_H
|
||||
#define DLG_CREATETOKEN_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QModelIndex>
|
||||
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
class QComboBox;
|
||||
class QCheckBox;
|
||||
class QPushButton;
|
||||
class QRadioButton;
|
||||
class QCloseEvent;
|
||||
class QTreeView;
|
||||
class DeckList;
|
||||
class CardDatabaseModel;
|
||||
class TokenDisplayModel;
|
||||
class CardInfoPictureWidget;
|
||||
|
||||
struct TokenInfo
|
||||
{
|
||||
QString name;
|
||||
QString color;
|
||||
QString pt;
|
||||
QString annotation;
|
||||
bool destroy = true;
|
||||
bool faceDown = false;
|
||||
QString providerId;
|
||||
};
|
||||
|
||||
class DlgCreateToken : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DlgCreateToken(const QStringList &_predefinedTokens, QWidget *parent = nullptr);
|
||||
TokenInfo getTokenInfo() const;
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
private slots:
|
||||
void faceDownCheckBoxToggled(bool checked);
|
||||
void tokenSelectionChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
void updateSearch(const QString &search);
|
||||
void actChooseTokenFromAll(bool checked);
|
||||
void actChooseTokenFromDeck(bool checked);
|
||||
void actOk();
|
||||
void actReject();
|
||||
|
||||
private:
|
||||
CardDatabaseModel *cardDatabaseModel;
|
||||
TokenDisplayModel *cardDatabaseDisplayModel;
|
||||
QStringList predefinedTokens;
|
||||
QLabel *nameLabel, *colorLabel, *ptLabel, *annotationLabel;
|
||||
QComboBox *colorEdit;
|
||||
QLineEdit *nameEdit, *ptEdit, *annotationEdit;
|
||||
QCheckBox *destroyCheckBox;
|
||||
QCheckBox *faceDownCheckBox;
|
||||
QRadioButton *chooseTokenFromAllRadioButton, *chooseTokenFromDeckRadioButton;
|
||||
CardInfoPictureWidget *pic;
|
||||
QTreeView *chooseTokenView;
|
||||
|
||||
void updateSearchFieldWithoutUpdatingFilter(const QString &newValue) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
139
cockatrice/src/game/dialogs/dlg_move_top_cards_until.cpp
Normal file
139
cockatrice/src/game/dialogs/dlg_move_top_cards_until.cpp
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
#include "dlg_move_top_cards_until.h"
|
||||
|
||||
#include "../../database/card_database.h"
|
||||
#include "../../database/card_database_manager.h"
|
||||
#include "../../filters/filter_string.h"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QMessageBox>
|
||||
#include <QSpinBox>
|
||||
#include <QString>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
DlgMoveTopCardsUntil::DlgMoveTopCardsUntil(QWidget *parent, QStringList exprs, uint _numberOfHits, bool autoPlay)
|
||||
: QDialog(parent)
|
||||
{
|
||||
exprLabel = new QLabel(tr("Card name (or search expressions):"));
|
||||
|
||||
exprComboBox = new QComboBox(this);
|
||||
exprComboBox->setFocus();
|
||||
exprComboBox->setEditable(true);
|
||||
exprComboBox->setInsertPolicy(QComboBox::InsertAtTop);
|
||||
exprComboBox->insertItems(0, exprs);
|
||||
exprLabel->setBuddy(exprComboBox);
|
||||
|
||||
numberOfHitsLabel = new QLabel(tr("Number of hits:"));
|
||||
numberOfHitsEdit = new QSpinBox(this);
|
||||
numberOfHitsEdit->setRange(1, 99);
|
||||
numberOfHitsEdit->setValue(_numberOfHits);
|
||||
numberOfHitsLabel->setBuddy(numberOfHitsEdit);
|
||||
|
||||
auto *grid = new QGridLayout;
|
||||
grid->addWidget(numberOfHitsLabel, 0, 0);
|
||||
grid->addWidget(numberOfHitsEdit, 0, 1);
|
||||
|
||||
autoPlayCheckBox = new QCheckBox(tr("Auto play hits"));
|
||||
autoPlayCheckBox->setChecked(autoPlay);
|
||||
|
||||
buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &DlgMoveTopCardsUntil::validateAndAccept);
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
auto *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addWidget(exprLabel);
|
||||
mainLayout->addWidget(exprComboBox);
|
||||
mainLayout->addItem(grid);
|
||||
mainLayout->addWidget(autoPlayCheckBox);
|
||||
mainLayout->addWidget(buttonBox);
|
||||
|
||||
setLayout(mainLayout);
|
||||
setWindowTitle(tr("Put top cards on stack until..."));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if a card matching the expr exists in the card database.
|
||||
*
|
||||
* @returns true if a card matching the expression exists.
|
||||
*/
|
||||
static bool matchExistsInDb(const FilterString &filterString)
|
||||
{
|
||||
const auto *cardDatabase = CardDatabaseManager::getInstance();
|
||||
const auto &allCards = cardDatabase->getCardList();
|
||||
|
||||
const auto it = std::find_if(allCards.begin(), allCards.end(),
|
||||
[&filterString](const CardInfoPtr &card) { return filterString.check(card); });
|
||||
|
||||
return it != allCards.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Validates that a card matching the expr exists in the card database.
|
||||
* If no match is found, then pop up a window to warn the user, giving them a chance to back out.
|
||||
*
|
||||
* @returns whether to proceed with the action
|
||||
*/
|
||||
bool DlgMoveTopCardsUntil::validateMatchExists(const FilterString &filterString)
|
||||
{
|
||||
if (matchExistsInDb(filterString)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto msg = tr("No cards matching the search expression exists in the card database. Proceed anyways?");
|
||||
const auto res =
|
||||
QMessageBox::warning(this, tr("Cockatrice"), msg, QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||
if (res == QMessageBox::No) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DlgMoveTopCardsUntil::validateAndAccept()
|
||||
{
|
||||
auto movingCardsUntilFilter = FilterString(exprComboBox->currentText());
|
||||
if (!movingCardsUntilFilter.valid()) {
|
||||
QMessageBox::warning(this, tr("Invalid filter"), movingCardsUntilFilter.error(), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!validateMatchExists(movingCardsUntilFilter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// move currently selected text to top of history list
|
||||
if (exprComboBox->currentIndex() != 0) {
|
||||
QString currentExpr = exprComboBox->currentText();
|
||||
exprComboBox->removeItem(exprComboBox->currentIndex());
|
||||
exprComboBox->insertItem(0, currentExpr);
|
||||
exprComboBox->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
accept();
|
||||
}
|
||||
|
||||
QString DlgMoveTopCardsUntil::getExpr() const
|
||||
{
|
||||
return exprComboBox->currentText();
|
||||
}
|
||||
|
||||
QStringList DlgMoveTopCardsUntil::getExprs() const
|
||||
{
|
||||
QStringList exprs;
|
||||
for (int i = 0; i < exprComboBox->count(); ++i) {
|
||||
exprs.append(exprComboBox->itemText(i));
|
||||
}
|
||||
return exprs;
|
||||
}
|
||||
|
||||
uint DlgMoveTopCardsUntil::getNumberOfHits() const
|
||||
{
|
||||
return numberOfHitsEdit->text().toUInt();
|
||||
}
|
||||
|
||||
bool DlgMoveTopCardsUntil::isAutoPlay() const
|
||||
{
|
||||
return autoPlayCheckBox->isChecked();
|
||||
}
|
||||
37
cockatrice/src/game/dialogs/dlg_move_top_cards_until.h
Normal file
37
cockatrice/src/game/dialogs/dlg_move_top_cards_until.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef DLG_MOVE_TOP_CARDS_UNTIL_H
|
||||
#define DLG_MOVE_TOP_CARDS_UNTIL_H
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QLabel>
|
||||
#include <QSpinBox>
|
||||
|
||||
class FilterString;
|
||||
|
||||
class DlgMoveTopCardsUntil : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QLabel *exprLabel, *numberOfHitsLabel;
|
||||
QComboBox *exprComboBox;
|
||||
QSpinBox *numberOfHitsEdit;
|
||||
QDialogButtonBox *buttonBox;
|
||||
QCheckBox *autoPlayCheckBox;
|
||||
|
||||
void validateAndAccept();
|
||||
bool validateMatchExists(const FilterString &filterString);
|
||||
|
||||
public:
|
||||
explicit DlgMoveTopCardsUntil(QWidget *parent = nullptr,
|
||||
QStringList exprs = QStringList(),
|
||||
uint numberOfHits = 1,
|
||||
bool autoPlay = false);
|
||||
QString getExpr() const;
|
||||
QStringList getExprs() const;
|
||||
uint getNumberOfHits() const;
|
||||
bool isAutoPlay() const;
|
||||
};
|
||||
|
||||
#endif // DLG_MOVE_TOP_CARDS_UNTIL_H
|
||||
52
cockatrice/src/game/dialogs/dlg_roll_dice.cpp
Normal file
52
cockatrice/src/game/dialogs/dlg_roll_dice.cpp
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#include "dlg_roll_dice.h"
|
||||
|
||||
#include "trice_limits.h"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QLabel>
|
||||
#include <QSpinBox>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
DlgRollDice::DlgRollDice(QWidget *parent) : QDialog(parent)
|
||||
{
|
||||
numberOfSidesLabel = new QLabel(tr("Number of sides:"));
|
||||
numberOfSidesEdit = new QSpinBox(this);
|
||||
numberOfSidesEdit->setValue(DEFAULT_NUMBER_SIDES_DIE);
|
||||
numberOfSidesEdit->setRange(MINIMUM_DIE_SIDES, MAXIMUM_DIE_SIDES);
|
||||
numberOfSidesEdit->setFocus();
|
||||
numberOfSidesLabel->setBuddy(numberOfSidesEdit);
|
||||
|
||||
numberOfDiceLabel = new QLabel(tr("Number of dice:"));
|
||||
numberOfDiceEdit = new QSpinBox(this);
|
||||
numberOfDiceEdit->setValue(DEFAULT_NUMBER_DICE_TO_ROLL);
|
||||
numberOfDiceEdit->setRange(MINIMUM_DICE_TO_ROLL, MAXIMUM_DICE_TO_ROLL);
|
||||
numberOfDiceLabel->setBuddy(numberOfDiceEdit);
|
||||
|
||||
auto *grid = new QGridLayout;
|
||||
grid->addWidget(numberOfSidesLabel, 0, 0);
|
||||
grid->addWidget(numberOfSidesEdit, 0, 1);
|
||||
grid->addWidget(numberOfDiceLabel, 1, 0);
|
||||
grid->addWidget(numberOfDiceEdit, 1, 1);
|
||||
|
||||
buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
auto *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addItem(grid);
|
||||
mainLayout->addWidget(buttonBox);
|
||||
|
||||
setLayout(mainLayout);
|
||||
setWindowTitle(tr("Roll Dice"));
|
||||
}
|
||||
|
||||
uint DlgRollDice::getDieSideCount() const
|
||||
{
|
||||
return numberOfSidesEdit->text().toUInt();
|
||||
}
|
||||
|
||||
uint DlgRollDice::getDiceToRollCount() const
|
||||
{
|
||||
return numberOfDiceEdit->text().toUInt();
|
||||
}
|
||||
26
cockatrice/src/game/dialogs/dlg_roll_dice.h
Normal file
26
cockatrice/src/game/dialogs/dlg_roll_dice.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef DLG_ROLL_DICE_H
|
||||
#define DLG_ROLL_DICE_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QLabel>
|
||||
#include <QSpinBox>
|
||||
|
||||
class DlgRollDice : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
static constexpr uint DEFAULT_NUMBER_SIDES_DIE = 20;
|
||||
static constexpr uint DEFAULT_NUMBER_DICE_TO_ROLL = 1;
|
||||
|
||||
QLabel *numberOfSidesLabel, *numberOfDiceLabel;
|
||||
QSpinBox *numberOfSidesEdit, *numberOfDiceEdit;
|
||||
QDialogButtonBox *buttonBox;
|
||||
|
||||
public:
|
||||
explicit DlgRollDice(QWidget *parent = nullptr);
|
||||
[[nodiscard]] uint getDieSideCount() const;
|
||||
[[nodiscard]] uint getDiceToRollCount() const;
|
||||
};
|
||||
|
||||
#endif // DLG_ROLL_DICE_H
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "game.h"
|
||||
|
||||
#include "../client/tabs/tab_game.h"
|
||||
#include "../tabs/tab_game.h"
|
||||
#include "pb/event_game_joined.pb.h"
|
||||
|
||||
Game::Game(TabGame *_tab,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
#include "game_event_handler.h"
|
||||
|
||||
#include "../client/tabs/tab_game.h"
|
||||
#include "../server/abstract_client.h"
|
||||
#include "../server/message_log_widget.h"
|
||||
#include "../server/pending_command.h"
|
||||
#include "../tabs/tab_game.h"
|
||||
#include "abstract_game.h"
|
||||
#include "get_pb_extension.h"
|
||||
#include "log/message_log_widget.h"
|
||||
#include "pb/command_concede.pb.h"
|
||||
#include "pb/command_delete_arrow.pb.h"
|
||||
#include "pb/command_game_say.pb.h"
|
||||
|
|
@ -501,4 +501,4 @@ void GameEventHandler::eventSetActivePhase(const Event_SetActivePhase &event,
|
|||
}
|
||||
game->getGameState()->setCurrentPhase(phase);
|
||||
emitUserEvent();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#include "game_scene.h"
|
||||
|
||||
#include "../client/ui/phases_toolbar.h"
|
||||
#include "../settings/cache_settings.h"
|
||||
#include "board/card_item.h"
|
||||
#include "phases_toolbar.h"
|
||||
#include "player/player.h"
|
||||
#include "player/player_graphics_item.h"
|
||||
#include "zones/view_zone.h"
|
||||
|
|
|
|||
|
|
@ -1,393 +0,0 @@
|
|||
#include "game_selector.h"
|
||||
|
||||
#include "../client/get_text_with_max.h"
|
||||
#include "../client/tabs/tab_account.h"
|
||||
#include "../client/tabs/tab_game.h"
|
||||
#include "../client/tabs/tab_room.h"
|
||||
#include "../client/tabs/tab_supervisor.h"
|
||||
#include "../dialogs/dlg_create_game.h"
|
||||
#include "../dialogs/dlg_filter_games.h"
|
||||
#include "../server/abstract_client.h"
|
||||
#include "../server/pending_command.h"
|
||||
#include "../server/user/user_list_manager.h"
|
||||
#include "games_model.h"
|
||||
#include "pb/response.pb.h"
|
||||
#include "pb/room_commands.pb.h"
|
||||
#include "pb/serverinfo_game.pb.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCheckBox>
|
||||
#include <QDebug>
|
||||
#include <QHBoxLayout>
|
||||
#include <QHeaderView>
|
||||
#include <QInputDialog>
|
||||
#include <QLabel>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QTreeView>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
GameSelector::GameSelector(AbstractClient *_client,
|
||||
TabSupervisor *_tabSupervisor,
|
||||
TabRoom *_room,
|
||||
const QMap<int, QString> &_rooms,
|
||||
const QMap<int, GameTypeMap> &_gameTypes,
|
||||
const bool restoresettings,
|
||||
const bool _showfilters,
|
||||
QWidget *parent)
|
||||
: QGroupBox(parent), client(_client), tabSupervisor(_tabSupervisor), room(_room), showFilters(_showfilters)
|
||||
{
|
||||
gameListView = new QTreeView;
|
||||
gameListView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(gameListView, &QTreeView::customContextMenuRequested, this, &GameSelector::customContextMenu);
|
||||
|
||||
gameListModel = new GamesModel(_rooms, _gameTypes, this);
|
||||
if (showFilters) {
|
||||
gameListProxyModel = new GamesProxyModel(this, tabSupervisor->getUserListManager());
|
||||
gameListProxyModel->setSourceModel(gameListModel);
|
||||
gameListProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
gameListView->setModel(gameListProxyModel);
|
||||
} else {
|
||||
gameListView->setModel(gameListModel);
|
||||
}
|
||||
gameListView->setIconSize(QSize(13, 13));
|
||||
gameListView->setSortingEnabled(true);
|
||||
gameListView->sortByColumn(gameListModel->startTimeColIndex(), Qt::AscendingOrder);
|
||||
gameListView->setAlternatingRowColors(true);
|
||||
gameListView->setRootIsDecorated(true);
|
||||
// game created width
|
||||
gameListView->setColumnWidth(1, gameListView->columnWidth(2) * 0.7);
|
||||
// players width
|
||||
gameListView->resizeColumnToContents(6);
|
||||
// description width
|
||||
gameListView->setColumnWidth(2, gameListView->columnWidth(2) * 1.7);
|
||||
// creator width
|
||||
gameListView->setColumnWidth(3, gameListView->columnWidth(3) * 1.2);
|
||||
// game type width
|
||||
gameListView->setColumnWidth(4, gameListView->columnWidth(4) * 1.4);
|
||||
if (_room)
|
||||
gameListView->header()->hideSection(gameListModel->roomColIndex());
|
||||
|
||||
if (room)
|
||||
gameTypeMap = gameListModel->getGameTypes().value(room->getRoomId());
|
||||
|
||||
if (showFilters && restoresettings)
|
||||
gameListProxyModel->loadFilterParameters(gameTypeMap);
|
||||
|
||||
gameListView->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
|
||||
|
||||
filterButton = new QPushButton;
|
||||
filterButton->setIcon(QPixmap("theme:icons/search"));
|
||||
connect(filterButton, &QPushButton::clicked, this, &GameSelector::actSetFilter);
|
||||
clearFilterButton = new QPushButton;
|
||||
clearFilterButton->setIcon(QPixmap("theme:icons/clearsearch"));
|
||||
bool filtersSetToDefault = showFilters && gameListProxyModel->areFilterParametersSetToDefaults();
|
||||
clearFilterButton->setEnabled(!filtersSetToDefault);
|
||||
connect(clearFilterButton, &QPushButton::clicked, this, &GameSelector::actClearFilter);
|
||||
|
||||
if (room) {
|
||||
createButton = new QPushButton;
|
||||
connect(createButton, &QPushButton::clicked, this, &GameSelector::actCreate);
|
||||
} else {
|
||||
createButton = nullptr;
|
||||
}
|
||||
joinButton = new QPushButton;
|
||||
spectateButton = new QPushButton;
|
||||
|
||||
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
||||
if (showFilters) {
|
||||
buttonLayout->addWidget(filterButton);
|
||||
buttonLayout->addWidget(clearFilterButton);
|
||||
}
|
||||
buttonLayout->addStretch();
|
||||
if (room)
|
||||
buttonLayout->addWidget(createButton);
|
||||
buttonLayout->addWidget(joinButton);
|
||||
buttonLayout->addWidget(spectateButton);
|
||||
buttonLayout->setAlignment(Qt::AlignTop);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addWidget(gameListView);
|
||||
mainLayout->addLayout(buttonLayout);
|
||||
|
||||
retranslateUi();
|
||||
setLayout(mainLayout);
|
||||
|
||||
setMinimumWidth((qreal)(gameListView->columnWidth(0) * gameListModel->columnCount()) / 1.5);
|
||||
setMinimumHeight(200);
|
||||
|
||||
connect(joinButton, &QPushButton::clicked, this, &GameSelector::actJoin);
|
||||
connect(spectateButton, &QPushButton::clicked, this, &GameSelector::actSpectate);
|
||||
connect(gameListView->selectionModel(), &QItemSelectionModel::currentRowChanged, this,
|
||||
&GameSelector::actSelectedGameChanged);
|
||||
connect(gameListView, &QTreeView::activated, this, &GameSelector::actJoin);
|
||||
|
||||
connect(client, &AbstractClient::ignoreListReceived, this, &GameSelector::ignoreListReceived);
|
||||
connect(client, &AbstractClient::addToListEventReceived, this, &GameSelector::processAddToListEvent);
|
||||
connect(client, &AbstractClient::removeFromListEventReceived, this, &GameSelector::processRemoveFromListEvent);
|
||||
}
|
||||
|
||||
void GameSelector::ignoreListReceived(const QList<ServerInfo_User> &)
|
||||
{
|
||||
gameListProxyModel->refresh();
|
||||
}
|
||||
|
||||
void GameSelector::processAddToListEvent(const Event_AddToList &event)
|
||||
{
|
||||
if (event.list_name() == "ignore") {
|
||||
gameListProxyModel->refresh();
|
||||
}
|
||||
updateTitle();
|
||||
}
|
||||
|
||||
void GameSelector::processRemoveFromListEvent(const Event_RemoveFromList &event)
|
||||
{
|
||||
if (event.list_name() == "ignore") {
|
||||
gameListProxyModel->refresh();
|
||||
}
|
||||
updateTitle();
|
||||
}
|
||||
|
||||
void GameSelector::actSetFilter()
|
||||
{
|
||||
DlgFilterGames dlg(gameTypeMap, gameListProxyModel, this);
|
||||
|
||||
if (!dlg.exec())
|
||||
return;
|
||||
|
||||
gameListProxyModel->setHideBuddiesOnlyGames(dlg.getHideBuddiesOnlyGames());
|
||||
gameListProxyModel->setHideFullGames(dlg.getHideFullGames());
|
||||
gameListProxyModel->setHideGamesThatStarted(dlg.getHideGamesThatStarted());
|
||||
gameListProxyModel->setHidePasswordProtectedGames(dlg.getHidePasswordProtectedGames());
|
||||
gameListProxyModel->setHideIgnoredUserGames(dlg.getHideIgnoredUserGames());
|
||||
gameListProxyModel->setHideNotBuddyCreatedGames(dlg.getHideNotBuddyCreatedGames());
|
||||
gameListProxyModel->setHideOpenDecklistGames(dlg.getHideOpenDecklistGames());
|
||||
gameListProxyModel->setGameNameFilter(dlg.getGameNameFilter());
|
||||
gameListProxyModel->setCreatorNameFilter(dlg.getCreatorNameFilter());
|
||||
gameListProxyModel->setGameTypeFilter(dlg.getGameTypeFilter());
|
||||
gameListProxyModel->setMaxPlayersFilter(dlg.getMaxPlayersFilterMin(), dlg.getMaxPlayersFilterMax());
|
||||
gameListProxyModel->setMaxGameAge(dlg.getMaxGameAge());
|
||||
gameListProxyModel->setShowOnlyIfSpectatorsCanWatch(dlg.getShowOnlyIfSpectatorsCanWatch());
|
||||
gameListProxyModel->setShowSpectatorPasswordProtected(dlg.getShowSpectatorPasswordProtected());
|
||||
gameListProxyModel->setShowOnlyIfSpectatorsCanChat(dlg.getShowOnlyIfSpectatorsCanChat());
|
||||
gameListProxyModel->setShowOnlyIfSpectatorsCanSeeHands(dlg.getShowOnlyIfSpectatorsCanSeeHands());
|
||||
gameListProxyModel->saveFilterParameters(gameTypeMap);
|
||||
|
||||
clearFilterButton->setEnabled(!gameListProxyModel->areFilterParametersSetToDefaults());
|
||||
|
||||
updateTitle();
|
||||
}
|
||||
|
||||
void GameSelector::actClearFilter()
|
||||
{
|
||||
clearFilterButton->setEnabled(false);
|
||||
|
||||
gameListProxyModel->resetFilterParameters();
|
||||
gameListProxyModel->saveFilterParameters(gameTypeMap);
|
||||
|
||||
updateTitle();
|
||||
}
|
||||
|
||||
void GameSelector::actCreate()
|
||||
{
|
||||
if (room == nullptr) {
|
||||
qWarning() << "Attempted to create game, but the room was null";
|
||||
return;
|
||||
}
|
||||
|
||||
DlgCreateGame dlg(room, room->getGameTypes(), this);
|
||||
dlg.exec();
|
||||
updateTitle();
|
||||
}
|
||||
|
||||
void GameSelector::checkResponse(const Response &response)
|
||||
{
|
||||
// NB: We re-enable buttons for the currently selected game, which may not
|
||||
// be the same game as the one for which we are processing a response.
|
||||
// This could lead to situations where we join a game, select a different
|
||||
// game, join the new game, then receive the response for the original
|
||||
// join, which would re-activate the buttons for the second game too soon.
|
||||
// However, that is better than doing things the other ways, because then
|
||||
// the response to the first game could lock us out of join/join as
|
||||
// spectator for the second game!
|
||||
//
|
||||
// Ideally we should have a way to figure out if the current game is the
|
||||
// same as the one we are getting a response for, but it's probably not
|
||||
// worth the trouble.
|
||||
enableButtons();
|
||||
|
||||
switch (response.response_code()) {
|
||||
case Response::RespNotInRoom:
|
||||
QMessageBox::critical(this, tr("Error"), tr("Please join the appropriate room first."));
|
||||
break;
|
||||
case Response::RespWrongPassword:
|
||||
QMessageBox::critical(this, tr("Error"), tr("Wrong password."));
|
||||
break;
|
||||
case Response::RespSpectatorsNotAllowed:
|
||||
QMessageBox::critical(this, tr("Error"), tr("Spectators are not allowed in this game."));
|
||||
break;
|
||||
case Response::RespGameFull:
|
||||
QMessageBox::critical(this, tr("Error"), tr("The game is already full."));
|
||||
break;
|
||||
case Response::RespNameNotFound:
|
||||
QMessageBox::critical(this, tr("Error"), tr("The game does not exist any more."));
|
||||
break;
|
||||
case Response::RespUserLevelTooLow:
|
||||
QMessageBox::critical(this, tr("Error"), tr("This game is only open to registered users."));
|
||||
break;
|
||||
case Response::RespOnlyBuddies:
|
||||
QMessageBox::critical(this, tr("Error"), tr("This game is only open to its creator's buddies."));
|
||||
break;
|
||||
case Response::RespInIgnoreList:
|
||||
QMessageBox::critical(this, tr("Error"), tr("You are being ignored by the creator of this game."));
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
void GameSelector::actJoin()
|
||||
{
|
||||
return joinGame(false);
|
||||
}
|
||||
|
||||
void GameSelector::actSpectate()
|
||||
{
|
||||
return joinGame(true);
|
||||
}
|
||||
|
||||
void GameSelector::customContextMenu(const QPoint &point)
|
||||
{
|
||||
const auto &index = gameListView->indexAt(point);
|
||||
if (!index.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QAction joinGame(tr("Join Game"));
|
||||
connect(&joinGame, &QAction::triggered, this, &GameSelector::actJoin);
|
||||
|
||||
QAction spectateGame(tr("Spectate Game"));
|
||||
connect(&spectateGame, &QAction::triggered, this, &GameSelector::actSpectate);
|
||||
|
||||
QAction getGameInfo(tr("Game Information"));
|
||||
connect(&getGameInfo, &QAction::triggered, this, [=, this]() {
|
||||
const ServerInfo_Game &gameInfo = gameListModel->getGame(index.data(Qt::UserRole).toInt());
|
||||
const QMap<int, QString> &gameTypes = gameListModel->getGameTypes().value(gameInfo.room_id());
|
||||
|
||||
DlgCreateGame dlg(gameInfo, gameTypes, this);
|
||||
dlg.exec();
|
||||
});
|
||||
|
||||
QMenu menu;
|
||||
menu.addAction(&joinGame);
|
||||
menu.addAction(&spectateGame);
|
||||
menu.addAction(&getGameInfo);
|
||||
menu.exec(gameListView->mapToGlobal(point));
|
||||
}
|
||||
|
||||
void GameSelector::joinGame(const bool isSpectator)
|
||||
{
|
||||
QModelIndex ind = gameListView->currentIndex();
|
||||
if (!ind.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ServerInfo_Game &game = gameListModel->getGame(ind.data(Qt::UserRole).toInt());
|
||||
if (tabSupervisor->switchToGameTabIfAlreadyExists(game.game_id())) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool spectator = isSpectator || game.player_count() == game.max_players();
|
||||
|
||||
bool overrideRestrictions = !tabSupervisor->getAdminLocked();
|
||||
QString password;
|
||||
if (game.with_password() && !(spectator && !game.spectators_need_password()) && !overrideRestrictions) {
|
||||
bool ok;
|
||||
password = getTextWithMax(this, tr("Join game"), tr("Password:"), QLineEdit::Password, QString(), &ok);
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Command_JoinGame cmd;
|
||||
cmd.set_game_id(game.game_id());
|
||||
cmd.set_password(password.toStdString());
|
||||
cmd.set_spectator(spectator);
|
||||
cmd.set_override_restrictions(overrideRestrictions);
|
||||
cmd.set_join_as_judge((QApplication::keyboardModifiers() & Qt::ShiftModifier) != 0);
|
||||
|
||||
TabRoom *r = tabSupervisor->getRoomTabs().value(game.room_id());
|
||||
if (!r) {
|
||||
QMessageBox::critical(this, tr("Error"), tr("Please join the respective room first."));
|
||||
return;
|
||||
}
|
||||
|
||||
PendingCommand *pend = r->prepareRoomCommand(cmd);
|
||||
connect(pend, &PendingCommand::finished, this, &GameSelector::checkResponse);
|
||||
r->sendRoomCommand(pend);
|
||||
|
||||
disableButtons();
|
||||
}
|
||||
|
||||
void GameSelector::disableButtons()
|
||||
{
|
||||
if (createButton)
|
||||
createButton->setEnabled(false);
|
||||
|
||||
joinButton->setEnabled(false);
|
||||
spectateButton->setEnabled(false);
|
||||
}
|
||||
|
||||
void GameSelector::enableButtons()
|
||||
{
|
||||
if (createButton)
|
||||
createButton->setEnabled(true);
|
||||
|
||||
// Enable buttons for the currently selected game
|
||||
enableButtonsForIndex(gameListView->currentIndex());
|
||||
}
|
||||
|
||||
void GameSelector::enableButtonsForIndex(const QModelIndex ¤t)
|
||||
{
|
||||
if (!current.isValid())
|
||||
return;
|
||||
|
||||
const ServerInfo_Game &game = gameListModel->getGame(current.data(Qt::UserRole).toInt());
|
||||
bool overrideRestrictions = !tabSupervisor->getAdminLocked();
|
||||
|
||||
spectateButton->setEnabled(game.spectators_allowed() || overrideRestrictions);
|
||||
joinButton->setEnabled(game.player_count() < game.max_players() || overrideRestrictions);
|
||||
}
|
||||
|
||||
void GameSelector::retranslateUi()
|
||||
{
|
||||
filterButton->setText(tr("&Filter games"));
|
||||
clearFilterButton->setText(tr("C&lear filter"));
|
||||
if (createButton)
|
||||
createButton->setText(tr("C&reate"));
|
||||
joinButton->setText(tr("&Join"));
|
||||
spectateButton->setText(tr("J&oin as spectator"));
|
||||
|
||||
updateTitle();
|
||||
}
|
||||
|
||||
void GameSelector::processGameInfo(const ServerInfo_Game &info)
|
||||
{
|
||||
gameListModel->updateGameList(info);
|
||||
updateTitle();
|
||||
}
|
||||
|
||||
void GameSelector::actSelectedGameChanged(const QModelIndex ¤t, const QModelIndex & /* previous */)
|
||||
{
|
||||
enableButtonsForIndex(current);
|
||||
}
|
||||
|
||||
void GameSelector::updateTitle()
|
||||
{
|
||||
if (showFilters) {
|
||||
const int totalGames = gameListModel->rowCount();
|
||||
const int shownGames = totalGames - gameListProxyModel->getNumFilteredGames();
|
||||
setTitle(tr("Games shown: %1 / %2").arg(shownGames).arg(totalGames));
|
||||
} else {
|
||||
setTitle(tr("Games"));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
#ifndef GAMESELECTOR_H
|
||||
#define GAMESELECTOR_H
|
||||
|
||||
#include "game_type_map.h"
|
||||
|
||||
#include <QGroupBox>
|
||||
#include <common/pb/event_add_to_list.pb.h>
|
||||
#include <common/pb/event_remove_from_list.pb.h>
|
||||
#include <pb/commands.pb.h>
|
||||
|
||||
class QTreeView;
|
||||
class GamesModel;
|
||||
class GamesProxyModel;
|
||||
class QPushButton;
|
||||
class QCheckBox;
|
||||
class QLabel;
|
||||
class AbstractClient;
|
||||
class TabSupervisor;
|
||||
class TabRoom;
|
||||
class ServerInfo_Game;
|
||||
class Response;
|
||||
|
||||
class GameSelector : public QGroupBox
|
||||
{
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
void actSetFilter();
|
||||
void actClearFilter();
|
||||
void actCreate();
|
||||
|
||||
void actJoin();
|
||||
void actSpectate();
|
||||
void customContextMenu(const QPoint &point);
|
||||
|
||||
void actSelectedGameChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
void checkResponse(const Response &response);
|
||||
|
||||
void ignoreListReceived(const QList<ServerInfo_User> &_ignoreList);
|
||||
void processAddToListEvent(const Event_AddToList &event);
|
||||
void processRemoveFromListEvent(const Event_RemoveFromList &event);
|
||||
signals:
|
||||
void gameJoined(int gameId);
|
||||
|
||||
private:
|
||||
AbstractClient *client;
|
||||
TabSupervisor *tabSupervisor;
|
||||
TabRoom *room;
|
||||
|
||||
QTreeView *gameListView;
|
||||
GamesModel *gameListModel;
|
||||
GamesProxyModel *gameListProxyModel;
|
||||
QPushButton *filterButton, *clearFilterButton, *createButton, *joinButton, *spectateButton;
|
||||
const bool showFilters;
|
||||
GameTypeMap gameTypeMap;
|
||||
|
||||
void updateTitle();
|
||||
void disableButtons();
|
||||
void enableButtons();
|
||||
void enableButtonsForIndex(const QModelIndex ¤t);
|
||||
void joinGame(const bool isSpectator);
|
||||
|
||||
public:
|
||||
GameSelector(AbstractClient *_client,
|
||||
TabSupervisor *_tabSupervisor,
|
||||
TabRoom *_room,
|
||||
const QMap<int, QString> &_rooms,
|
||||
const QMap<int, GameTypeMap> &_gameTypes,
|
||||
const bool restoresettings,
|
||||
const bool _showfilters,
|
||||
QWidget *parent = nullptr);
|
||||
void retranslateUi();
|
||||
void processGameInfo(const ServerInfo_Game &info);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef GAMETYPEMAP_H
|
||||
#define GAMETYPEMAP_H
|
||||
|
||||
#include <QMap>
|
||||
|
||||
typedef QMap<int, QString> GameTypeMap;
|
||||
|
||||
#endif
|
||||
|
|
@ -1,581 +0,0 @@
|
|||
#include "games_model.h"
|
||||
|
||||
#include "../client/tabs/tab_account.h"
|
||||
#include "../client/ui/pixel_map_generator.h"
|
||||
#include "../server/user/user_list_manager.h"
|
||||
#include "../server/user/user_list_widget.h"
|
||||
#include "../settings/cache_settings.h"
|
||||
#include "pb/serverinfo_game.pb.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QIcon>
|
||||
#include <QStringList>
|
||||
#include <QTime>
|
||||
#include <QTimeZone>
|
||||
|
||||
enum GameListColumn
|
||||
{
|
||||
ROOM,
|
||||
CREATED,
|
||||
DESCRIPTION,
|
||||
CREATOR,
|
||||
GAME_TYPE,
|
||||
RESTRICTIONS,
|
||||
PLAYERS,
|
||||
SPECTATORS
|
||||
};
|
||||
|
||||
const int DEFAULT_MAX_PLAYERS_MIN = 1;
|
||||
const int DEFAULT_MAX_PLAYERS_MAX = 99;
|
||||
constexpr QTime DEFAULT_MAX_GAME_AGE = QTime();
|
||||
|
||||
const QString GamesModel::getGameCreatedString(const int secs)
|
||||
{
|
||||
static const QTime zeroTime{0, 0};
|
||||
static const int halfHourSecs = zeroTime.secsTo(QTime(1, 0)) / 2;
|
||||
static const int halfMinSecs = zeroTime.secsTo(QTime(0, 1)) / 2;
|
||||
static const int wrapSeconds = zeroTime.secsTo(zeroTime.addSecs(-halfHourSecs)); // round up
|
||||
|
||||
if (secs >= wrapSeconds) { // QTime wraps after a day
|
||||
return tr(">1 day");
|
||||
}
|
||||
|
||||
QTime total = zeroTime.addSecs(secs);
|
||||
QTime totalRounded = total.addSecs(halfMinSecs); // round up
|
||||
QString form;
|
||||
int amount;
|
||||
if (totalRounded.hour()) {
|
||||
amount = total.addSecs(halfHourSecs).hour(); // round up separately
|
||||
form = tr("%1%2 hr", "short age in hours", amount);
|
||||
} else if (total.minute() < 2) { // games are new during their first minute
|
||||
return tr("new");
|
||||
} else {
|
||||
amount = totalRounded.minute();
|
||||
form = tr("%1%2 min", "short age in minutes", amount);
|
||||
}
|
||||
|
||||
for (int aggregate : {40, 20, 10, 5}) { // floor to values in this list
|
||||
if (amount >= aggregate) {
|
||||
return form.arg(">").arg(aggregate);
|
||||
}
|
||||
}
|
||||
return form.arg("").arg(amount);
|
||||
}
|
||||
|
||||
GamesModel::GamesModel(const QMap<int, QString> &_rooms, const QMap<int, GameTypeMap> &_gameTypes, QObject *parent)
|
||||
: QAbstractTableModel(parent), rooms(_rooms), gameTypes(_gameTypes)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant GamesModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
if (role == Qt::UserRole)
|
||||
return index.row();
|
||||
if (role != Qt::DisplayRole && role != SORT_ROLE && role != Qt::DecorationRole && role != Qt::TextAlignmentRole)
|
||||
return QVariant();
|
||||
if ((index.row() >= gameList.size()) || (index.column() >= columnCount()))
|
||||
return QVariant();
|
||||
|
||||
const ServerInfo_Game &gameentry = gameList[index.row()];
|
||||
switch (index.column()) {
|
||||
case ROOM:
|
||||
return rooms.value(gameentry.room_id());
|
||||
case CREATED: {
|
||||
switch (role) {
|
||||
case Qt::DisplayRole: {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)
|
||||
auto then = QDateTime::fromSecsSinceEpoch(gameentry.start_time(), QTimeZone::UTC);
|
||||
#else
|
||||
auto then = QDateTime::fromSecsSinceEpoch(gameentry.start_time(), Qt::UTC);
|
||||
#endif
|
||||
int secs = then.secsTo(QDateTime::currentDateTimeUtc());
|
||||
return getGameCreatedString(secs);
|
||||
}
|
||||
case SORT_ROLE:
|
||||
return QVariant(-static_cast<qint64>(gameentry.start_time()));
|
||||
case Qt::TextAlignmentRole:
|
||||
return Qt::AlignCenter;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
case DESCRIPTION:
|
||||
switch (role) {
|
||||
case SORT_ROLE:
|
||||
case Qt::DisplayRole:
|
||||
return QString::fromStdString(gameentry.description());
|
||||
case Qt::TextAlignmentRole:
|
||||
return Qt::AlignLeft;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
case CREATOR: {
|
||||
switch (role) {
|
||||
case SORT_ROLE:
|
||||
case Qt::DisplayRole:
|
||||
return QString::fromStdString(gameentry.creator_info().name());
|
||||
case Qt::DecorationRole: {
|
||||
return UserLevelPixmapGenerator::generateIcon(
|
||||
13, UserLevelFlags(gameentry.creator_info().user_level()),
|
||||
gameentry.creator_info().pawn_colors(), false,
|
||||
QString::fromStdString(gameentry.creator_info().privlevel()));
|
||||
}
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
case GAME_TYPE:
|
||||
switch (role) {
|
||||
case SORT_ROLE:
|
||||
case Qt::DisplayRole: {
|
||||
QStringList result;
|
||||
GameTypeMap gameTypeMap = gameTypes.value(gameentry.room_id());
|
||||
for (int i = gameentry.game_types_size() - 1; i >= 0; --i)
|
||||
result.append(gameTypeMap.value(gameentry.game_types(i)));
|
||||
return result.join(", ");
|
||||
}
|
||||
case Qt::TextAlignmentRole:
|
||||
return Qt::AlignLeft;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
case RESTRICTIONS:
|
||||
switch (role) {
|
||||
case SORT_ROLE:
|
||||
case Qt::DisplayRole: {
|
||||
QStringList result;
|
||||
if (gameentry.with_password())
|
||||
result.append(tr("password"));
|
||||
if (gameentry.only_buddies())
|
||||
result.append(tr("buddies only"));
|
||||
if (gameentry.only_registered())
|
||||
result.append(tr("reg. users only"));
|
||||
if (gameentry.share_decklists_on_load())
|
||||
result.append(tr("open decklists"));
|
||||
return result.join(", ");
|
||||
}
|
||||
case Qt::DecorationRole: {
|
||||
return gameentry.with_password() ? QIcon(LockPixmapGenerator::generatePixmap(13)) : QVariant();
|
||||
case Qt::TextAlignmentRole:
|
||||
return Qt::AlignLeft;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
case PLAYERS:
|
||||
switch (role) {
|
||||
case SORT_ROLE:
|
||||
case Qt::DisplayRole:
|
||||
return QString("%1/%2").arg(gameentry.player_count()).arg(gameentry.max_players());
|
||||
case Qt::TextAlignmentRole:
|
||||
return Qt::AlignCenter;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case SPECTATORS:
|
||||
switch (role) {
|
||||
case SORT_ROLE:
|
||||
case Qt::DisplayRole: {
|
||||
if (gameentry.spectators_allowed()) {
|
||||
QString result;
|
||||
result.append(QString::number(gameentry.spectators_count()));
|
||||
|
||||
if (gameentry.spectators_can_chat() && gameentry.spectators_omniscient()) {
|
||||
result.append(" (")
|
||||
.append(tr("can chat"))
|
||||
.append(" & ")
|
||||
.append(tr("see hands"))
|
||||
.append(")");
|
||||
} else if (gameentry.spectators_can_chat()) {
|
||||
result.append(" (").append(tr("can chat")).append(")");
|
||||
} else if (gameentry.spectators_omniscient()) {
|
||||
result.append(" (").append(tr("can see hands")).append(")");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return QVariant(tr("not allowed"));
|
||||
}
|
||||
case Qt::TextAlignmentRole:
|
||||
return Qt::AlignLeft;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant GamesModel::headerData(int section, Qt::Orientation /*orientation*/, int role) const
|
||||
{
|
||||
if ((role != Qt::DisplayRole) && (role != Qt::TextAlignmentRole))
|
||||
return QVariant();
|
||||
switch (section) {
|
||||
case ROOM:
|
||||
return tr("Room");
|
||||
case CREATED: {
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return tr("Age");
|
||||
case Qt::TextAlignmentRole:
|
||||
return Qt::AlignCenter;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
case DESCRIPTION:
|
||||
return tr("Description");
|
||||
case CREATOR:
|
||||
return tr("Creator");
|
||||
case GAME_TYPE:
|
||||
return tr("Type");
|
||||
case RESTRICTIONS:
|
||||
return tr("Restrictions");
|
||||
case PLAYERS: {
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return tr("Players");
|
||||
case Qt::TextAlignmentRole:
|
||||
return Qt::AlignCenter;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
case SPECTATORS:
|
||||
return tr("Spectators");
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
const ServerInfo_Game &GamesModel::getGame(int row)
|
||||
{
|
||||
Q_ASSERT(row < gameList.size());
|
||||
return gameList[row];
|
||||
}
|
||||
|
||||
void GamesModel::updateGameList(const ServerInfo_Game &game)
|
||||
{
|
||||
for (int i = 0; i < gameList.size(); i++) {
|
||||
if (gameList[i].game_id() == game.game_id()) {
|
||||
if (game.closed()) {
|
||||
beginRemoveRows(QModelIndex(), i, i);
|
||||
gameList.removeAt(i);
|
||||
endRemoveRows();
|
||||
} else {
|
||||
gameList[i].MergeFrom(game);
|
||||
emit dataChanged(index(i, 0), index(i, NUM_COLS - 1));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
beginInsertRows(QModelIndex(), gameList.size(), gameList.size());
|
||||
gameList.append(game);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
GamesProxyModel::GamesProxyModel(QObject *parent, const UserListProxy *_userListProxy)
|
||||
: QSortFilterProxyModel(parent), userListProxy(_userListProxy)
|
||||
{
|
||||
resetFilterParameters();
|
||||
setSortRole(GamesModel::SORT_ROLE);
|
||||
setDynamicSortFilter(true);
|
||||
}
|
||||
|
||||
void GamesProxyModel::setHideBuddiesOnlyGames(bool _showBuddiesOnlyGames)
|
||||
{
|
||||
hideBuddiesOnlyGames = _showBuddiesOnlyGames;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void GamesProxyModel::setHideIgnoredUserGames(bool _hideIgnoredUserGames)
|
||||
{
|
||||
hideIgnoredUserGames = _hideIgnoredUserGames;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void GamesProxyModel::setHideFullGames(bool _showFullGames)
|
||||
{
|
||||
hideFullGames = _showFullGames;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void GamesProxyModel::setHideGamesThatStarted(bool _showGamesThatStarted)
|
||||
{
|
||||
hideGamesThatStarted = _showGamesThatStarted;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void GamesProxyModel::setHidePasswordProtectedGames(bool _showPasswordProtectedGames)
|
||||
{
|
||||
hidePasswordProtectedGames = _showPasswordProtectedGames;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void GamesProxyModel::setHideNotBuddyCreatedGames(bool value)
|
||||
{
|
||||
hideNotBuddyCreatedGames = value;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void GamesProxyModel::setHideOpenDecklistGames(bool _hideOpenDecklistGames)
|
||||
{
|
||||
hideOpenDecklistGames = _hideOpenDecklistGames;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void GamesProxyModel::setGameNameFilter(const QString &_gameNameFilter)
|
||||
{
|
||||
gameNameFilter = _gameNameFilter;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void GamesProxyModel::setCreatorNameFilter(const QString &_creatorNameFilter)
|
||||
{
|
||||
creatorNameFilter = _creatorNameFilter;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void GamesProxyModel::setGameTypeFilter(const QSet<int> &_gameTypeFilter)
|
||||
{
|
||||
gameTypeFilter = _gameTypeFilter;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void GamesProxyModel::setMaxPlayersFilter(int _maxPlayersFilterMin, int _maxPlayersFilterMax)
|
||||
{
|
||||
maxPlayersFilterMin = _maxPlayersFilterMin;
|
||||
maxPlayersFilterMax = _maxPlayersFilterMax;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void GamesProxyModel::setMaxGameAge(const QTime &_maxGameAge)
|
||||
{
|
||||
maxGameAge = _maxGameAge;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void GamesProxyModel::setShowOnlyIfSpectatorsCanWatch(bool _showOnlyIfSpectatorsCanWatch)
|
||||
{
|
||||
showOnlyIfSpectatorsCanWatch = _showOnlyIfSpectatorsCanWatch;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void GamesProxyModel::setShowSpectatorPasswordProtected(bool _showSpectatorPasswordProtected)
|
||||
{
|
||||
showSpectatorPasswordProtected = _showSpectatorPasswordProtected;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void GamesProxyModel::setShowOnlyIfSpectatorsCanChat(bool _showOnlyIfSpectatorsCanChat)
|
||||
{
|
||||
showOnlyIfSpectatorsCanChat = _showOnlyIfSpectatorsCanChat;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void GamesProxyModel::setShowOnlyIfSpectatorsCanSeeHands(bool _showOnlyIfSpectatorsCanSeeHands)
|
||||
{
|
||||
showOnlyIfSpectatorsCanSeeHands = _showOnlyIfSpectatorsCanSeeHands;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
int GamesProxyModel::getNumFilteredGames() const
|
||||
{
|
||||
GamesModel *model = qobject_cast<GamesModel *>(sourceModel());
|
||||
if (!model)
|
||||
return 0;
|
||||
|
||||
int numFilteredGames = 0;
|
||||
for (int row = 0; row < model->rowCount(); ++row) {
|
||||
if (!filterAcceptsRow(row)) {
|
||||
++numFilteredGames;
|
||||
}
|
||||
}
|
||||
return numFilteredGames;
|
||||
}
|
||||
|
||||
void GamesProxyModel::resetFilterParameters()
|
||||
{
|
||||
hideFullGames = false;
|
||||
hideGamesThatStarted = false;
|
||||
hidePasswordProtectedGames = false;
|
||||
hideBuddiesOnlyGames = false;
|
||||
hideIgnoredUserGames = false;
|
||||
hideNotBuddyCreatedGames = false;
|
||||
hideOpenDecklistGames = false;
|
||||
gameNameFilter = QString();
|
||||
creatorNameFilter = QString();
|
||||
gameTypeFilter.clear();
|
||||
maxPlayersFilterMin = DEFAULT_MAX_PLAYERS_MIN;
|
||||
maxPlayersFilterMax = DEFAULT_MAX_PLAYERS_MAX;
|
||||
maxGameAge = DEFAULT_MAX_GAME_AGE;
|
||||
showOnlyIfSpectatorsCanWatch = false;
|
||||
showSpectatorPasswordProtected = false;
|
||||
showOnlyIfSpectatorsCanChat = false;
|
||||
showOnlyIfSpectatorsCanSeeHands = false;
|
||||
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
bool GamesProxyModel::areFilterParametersSetToDefaults() const
|
||||
{
|
||||
return !hideFullGames && !hideGamesThatStarted && !hidePasswordProtectedGames && !hideBuddiesOnlyGames &&
|
||||
!hideOpenDecklistGames && !hideIgnoredUserGames && !hideNotBuddyCreatedGames && gameNameFilter.isEmpty() &&
|
||||
creatorNameFilter.isEmpty() && gameTypeFilter.isEmpty() && maxPlayersFilterMin == DEFAULT_MAX_PLAYERS_MIN &&
|
||||
maxPlayersFilterMax == DEFAULT_MAX_PLAYERS_MAX && maxGameAge == DEFAULT_MAX_GAME_AGE &&
|
||||
!showOnlyIfSpectatorsCanWatch && !showSpectatorPasswordProtected && !showOnlyIfSpectatorsCanChat &&
|
||||
!showOnlyIfSpectatorsCanSeeHands;
|
||||
}
|
||||
|
||||
void GamesProxyModel::loadFilterParameters(const QMap<int, QString> &allGameTypes)
|
||||
{
|
||||
GameFiltersSettings &gameFilters = SettingsCache::instance().gameFilters();
|
||||
hideFullGames = gameFilters.isHideFullGames();
|
||||
hideGamesThatStarted = gameFilters.isHideGamesThatStarted();
|
||||
hidePasswordProtectedGames = gameFilters.isHidePasswordProtectedGames();
|
||||
hideIgnoredUserGames = gameFilters.isHideIgnoredUserGames();
|
||||
hideBuddiesOnlyGames = gameFilters.isHideBuddiesOnlyGames();
|
||||
hideNotBuddyCreatedGames = gameFilters.isHideNotBuddyCreatedGames();
|
||||
hideOpenDecklistGames = gameFilters.isHideOpenDecklistGames();
|
||||
gameNameFilter = gameFilters.getGameNameFilter();
|
||||
creatorNameFilter = gameFilters.getCreatorNameFilter();
|
||||
maxPlayersFilterMin = gameFilters.getMinPlayers();
|
||||
maxPlayersFilterMax = gameFilters.getMaxPlayers();
|
||||
maxGameAge = gameFilters.getMaxGameAge();
|
||||
showOnlyIfSpectatorsCanWatch = gameFilters.isShowOnlyIfSpectatorsCanWatch();
|
||||
showSpectatorPasswordProtected = gameFilters.isShowSpectatorPasswordProtected();
|
||||
showOnlyIfSpectatorsCanChat = gameFilters.isShowOnlyIfSpectatorsCanChat();
|
||||
showOnlyIfSpectatorsCanSeeHands = gameFilters.isShowOnlyIfSpectatorsCanSeeHands();
|
||||
|
||||
QMapIterator<int, QString> gameTypesIterator(allGameTypes);
|
||||
while (gameTypesIterator.hasNext()) {
|
||||
gameTypesIterator.next();
|
||||
if (gameFilters.isGameTypeEnabled(gameTypesIterator.value())) {
|
||||
gameTypeFilter.insert(gameTypesIterator.key());
|
||||
}
|
||||
}
|
||||
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void GamesProxyModel::saveFilterParameters(const QMap<int, QString> &allGameTypes)
|
||||
{
|
||||
GameFiltersSettings &gameFilters = SettingsCache::instance().gameFilters();
|
||||
gameFilters.setHideBuddiesOnlyGames(hideBuddiesOnlyGames);
|
||||
gameFilters.setHideFullGames(hideFullGames);
|
||||
gameFilters.setHideGamesThatStarted(hideGamesThatStarted);
|
||||
gameFilters.setHidePasswordProtectedGames(hidePasswordProtectedGames);
|
||||
gameFilters.setHideIgnoredUserGames(hideIgnoredUserGames);
|
||||
gameFilters.setHideNotBuddyCreatedGames(hideNotBuddyCreatedGames);
|
||||
gameFilters.setHideOpenDecklistGames(hideOpenDecklistGames);
|
||||
gameFilters.setGameNameFilter(gameNameFilter);
|
||||
gameFilters.setCreatorNameFilter(creatorNameFilter);
|
||||
|
||||
QMapIterator<int, QString> gameTypeIterator(allGameTypes);
|
||||
while (gameTypeIterator.hasNext()) {
|
||||
gameTypeIterator.next();
|
||||
bool enabled = gameTypeFilter.contains(gameTypeIterator.key());
|
||||
gameFilters.setGameTypeEnabled(gameTypeIterator.value(), enabled);
|
||||
}
|
||||
|
||||
gameFilters.setMinPlayers(maxPlayersFilterMin);
|
||||
gameFilters.setMaxPlayers(maxPlayersFilterMax);
|
||||
gameFilters.setMaxGameAge(maxGameAge);
|
||||
|
||||
gameFilters.setShowOnlyIfSpectatorsCanWatch(showOnlyIfSpectatorsCanWatch);
|
||||
gameFilters.setShowSpectatorPasswordProtected(showSpectatorPasswordProtected);
|
||||
gameFilters.setShowOnlyIfSpectatorsCanChat(showOnlyIfSpectatorsCanChat);
|
||||
gameFilters.setShowOnlyIfSpectatorsCanSeeHands(showOnlyIfSpectatorsCanSeeHands);
|
||||
}
|
||||
|
||||
bool GamesProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex & /*sourceParent*/) const
|
||||
{
|
||||
return filterAcceptsRow(sourceRow);
|
||||
}
|
||||
|
||||
bool GamesProxyModel::filterAcceptsRow(int sourceRow) const
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)
|
||||
static const QDate epochDate = QDateTime::fromSecsSinceEpoch(0, QTimeZone::UTC).date();
|
||||
#elif (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
|
||||
static const QDate epochDate = QDateTime::fromSecsSinceEpoch(0, Qt::UTC).date();
|
||||
#else
|
||||
static const QDate epochDate = QDateTime::fromTime_t(0, Qt::UTC).date();
|
||||
#endif
|
||||
auto *model = qobject_cast<GamesModel *>(sourceModel());
|
||||
if (!model)
|
||||
return false;
|
||||
|
||||
const ServerInfo_Game &game = model->getGame(sourceRow);
|
||||
|
||||
if (hideBuddiesOnlyGames && game.only_buddies()) {
|
||||
return false;
|
||||
}
|
||||
if (hideOpenDecklistGames && game.share_decklists_on_load()) {
|
||||
return false;
|
||||
}
|
||||
if (hideIgnoredUserGames && userListProxy->isUserIgnored(QString::fromStdString(game.creator_info().name()))) {
|
||||
return false;
|
||||
}
|
||||
if (hideNotBuddyCreatedGames && !userListProxy->isUserBuddy(QString::fromStdString(game.creator_info().name()))) {
|
||||
return false;
|
||||
}
|
||||
if (hideFullGames && game.player_count() == game.max_players())
|
||||
return false;
|
||||
if (hideGamesThatStarted && game.started())
|
||||
return false;
|
||||
if (!userListProxy->isOwnUserRegistered())
|
||||
if (game.only_registered())
|
||||
return false;
|
||||
if (hidePasswordProtectedGames && game.with_password())
|
||||
return false;
|
||||
if (!gameNameFilter.isEmpty())
|
||||
if (!QString::fromStdString(game.description()).contains(gameNameFilter, Qt::CaseInsensitive))
|
||||
return false;
|
||||
if (!creatorNameFilter.isEmpty())
|
||||
if (!QString::fromStdString(game.creator_info().name()).contains(creatorNameFilter, Qt::CaseInsensitive))
|
||||
return false;
|
||||
|
||||
QSet<int> gameTypes;
|
||||
for (int i = 0; i < game.game_types_size(); ++i)
|
||||
gameTypes.insert(game.game_types(i));
|
||||
if (!gameTypeFilter.isEmpty() && gameTypes.intersect(gameTypeFilter).isEmpty())
|
||||
return false;
|
||||
|
||||
if (game.max_players() < maxPlayersFilterMin)
|
||||
return false;
|
||||
if (game.max_players() > maxPlayersFilterMax)
|
||||
return false;
|
||||
|
||||
if (maxGameAge.isValid()) {
|
||||
QDateTime now = QDateTime::currentDateTimeUtc();
|
||||
qint64 signed_start_time = game.start_time(); // cast to 64 bit value to allow signed value
|
||||
QDateTime total = now.addSecs(-signed_start_time); // a 32 bit value would wrap at 2038-1-19
|
||||
// games shouldn't have negative ages but we'll not filter them
|
||||
// because qtime wraps after a day we consider all games older than a day to be too old
|
||||
if (total.isValid() && total.date() >= epochDate && (total.date() > epochDate || total.time() > maxGameAge)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (showOnlyIfSpectatorsCanWatch) {
|
||||
if (!game.spectators_allowed())
|
||||
return false;
|
||||
if (!showSpectatorPasswordProtected && game.spectators_need_password())
|
||||
return false;
|
||||
if (showOnlyIfSpectatorsCanChat && !game.spectators_can_chat())
|
||||
return false;
|
||||
if (showOnlyIfSpectatorsCanSeeHands && !game.spectators_omniscient())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GamesProxyModel::refresh()
|
||||
{
|
||||
invalidateFilter();
|
||||
}
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
#ifndef GAMESMODEL_H
|
||||
#define GAMESMODEL_H
|
||||
|
||||
#include "game_type_map.h"
|
||||
#include "pb/serverinfo_game.pb.h"
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QList>
|
||||
#include <QSet>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QStringList>
|
||||
#include <QTime>
|
||||
|
||||
class UserListProxy;
|
||||
|
||||
class GamesModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
QList<ServerInfo_Game> gameList;
|
||||
QMap<int, QString> rooms;
|
||||
QMap<int, GameTypeMap> gameTypes;
|
||||
|
||||
static const int NUM_COLS = 8;
|
||||
|
||||
public:
|
||||
static const int SORT_ROLE = Qt::UserRole + 1;
|
||||
|
||||
GamesModel(const QMap<int, QString> &_rooms, const QMap<int, GameTypeMap> &_gameTypes, QObject *parent = nullptr);
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override
|
||||
{
|
||||
return parent.isValid() ? 0 : gameList.size();
|
||||
}
|
||||
int columnCount(const QModelIndex & /*parent*/ = QModelIndex()) const override
|
||||
{
|
||||
return NUM_COLS;
|
||||
}
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
static const QString getGameCreatedString(const int secs);
|
||||
const ServerInfo_Game &getGame(int row);
|
||||
|
||||
/**
|
||||
* Update game list with a (possibly new) game.
|
||||
*/
|
||||
void updateGameList(const ServerInfo_Game &game);
|
||||
|
||||
int roomColIndex()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int startTimeColIndex()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
const QMap<int, GameTypeMap> &getGameTypes()
|
||||
{
|
||||
return gameTypes;
|
||||
}
|
||||
};
|
||||
|
||||
class ServerInfo_User;
|
||||
|
||||
class GamesProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
const UserListProxy *userListProxy;
|
||||
|
||||
// If adding any additional filters, make sure to update:
|
||||
// - GamesProxyModel()
|
||||
// - resetFilterParameters()
|
||||
// - areFilterParametersSetToDefaults()
|
||||
// - loadFilterParameters()
|
||||
// - saveFilterParameters()
|
||||
// - filterAcceptsRow()
|
||||
bool hideBuddiesOnlyGames;
|
||||
bool hideIgnoredUserGames;
|
||||
bool hideFullGames;
|
||||
bool hideGamesThatStarted;
|
||||
bool hidePasswordProtectedGames;
|
||||
bool hideNotBuddyCreatedGames;
|
||||
bool hideOpenDecklistGames;
|
||||
QString gameNameFilter, creatorNameFilter;
|
||||
QSet<int> gameTypeFilter;
|
||||
quint32 maxPlayersFilterMin, maxPlayersFilterMax;
|
||||
QTime maxGameAge;
|
||||
bool showOnlyIfSpectatorsCanWatch, showSpectatorPasswordProtected, showOnlyIfSpectatorsCanChat,
|
||||
showOnlyIfSpectatorsCanSeeHands;
|
||||
|
||||
public:
|
||||
explicit GamesProxyModel(QObject *parent = nullptr, const UserListProxy *_userListProxy = nullptr);
|
||||
|
||||
bool getHideBuddiesOnlyGames() const
|
||||
{
|
||||
return hideBuddiesOnlyGames;
|
||||
}
|
||||
void setHideBuddiesOnlyGames(bool _showBuddiesOnlyGames);
|
||||
bool getHideIgnoredUserGames() const
|
||||
{
|
||||
return hideIgnoredUserGames;
|
||||
}
|
||||
void setHideIgnoredUserGames(bool _hideIgnoredUserGames);
|
||||
bool getHideFullGames() const
|
||||
{
|
||||
return hideFullGames;
|
||||
}
|
||||
void setHideFullGames(bool _showFullGames);
|
||||
bool getHideGamesThatStarted() const
|
||||
{
|
||||
return hideGamesThatStarted;
|
||||
}
|
||||
void setHideGamesThatStarted(bool _showGamesThatStarted);
|
||||
bool getHidePasswordProtectedGames() const
|
||||
{
|
||||
return hidePasswordProtectedGames;
|
||||
}
|
||||
void setHidePasswordProtectedGames(bool _showPasswordProtectedGames);
|
||||
bool getHideNotBuddyCreatedGames() const
|
||||
{
|
||||
return hideNotBuddyCreatedGames;
|
||||
}
|
||||
void setHideNotBuddyCreatedGames(bool value);
|
||||
bool getHideOpenDecklistGames() const
|
||||
{
|
||||
return hideOpenDecklistGames;
|
||||
}
|
||||
void setHideOpenDecklistGames(bool _hideOpenDecklistGames);
|
||||
QString getGameNameFilter() const
|
||||
{
|
||||
return gameNameFilter;
|
||||
}
|
||||
void setGameNameFilter(const QString &_gameNameFilter);
|
||||
QString getCreatorNameFilter() const
|
||||
{
|
||||
return creatorNameFilter;
|
||||
}
|
||||
void setCreatorNameFilter(const QString &_creatorNameFilter);
|
||||
QSet<int> getGameTypeFilter() const
|
||||
{
|
||||
return gameTypeFilter;
|
||||
}
|
||||
void setGameTypeFilter(const QSet<int> &_gameTypeFilter);
|
||||
int getMaxPlayersFilterMin() const
|
||||
{
|
||||
return maxPlayersFilterMin;
|
||||
}
|
||||
int getMaxPlayersFilterMax() const
|
||||
{
|
||||
return maxPlayersFilterMax;
|
||||
}
|
||||
void setMaxPlayersFilter(int _maxPlayersFilterMin, int _maxPlayersFilterMax);
|
||||
const QTime &getMaxGameAge() const
|
||||
{
|
||||
return maxGameAge;
|
||||
}
|
||||
void setMaxGameAge(const QTime &_maxGameAge);
|
||||
bool getShowOnlyIfSpectatorsCanWatch() const
|
||||
{
|
||||
return showOnlyIfSpectatorsCanWatch;
|
||||
}
|
||||
void setShowOnlyIfSpectatorsCanWatch(bool _showOnlyIfSpectatorsCanWatch);
|
||||
bool getShowSpectatorPasswordProtected() const
|
||||
{
|
||||
return showSpectatorPasswordProtected;
|
||||
}
|
||||
void setShowSpectatorPasswordProtected(bool _showSpectatorPasswordProtected);
|
||||
bool getShowOnlyIfSpectatorsCanChat() const
|
||||
{
|
||||
return showOnlyIfSpectatorsCanChat;
|
||||
}
|
||||
void setShowOnlyIfSpectatorsCanChat(bool _showOnlyIfSpectatorsCanChat);
|
||||
bool getShowOnlyIfSpectatorsCanSeeHands() const
|
||||
{
|
||||
return showOnlyIfSpectatorsCanSeeHands;
|
||||
}
|
||||
void setShowOnlyIfSpectatorsCanSeeHands(bool _showOnlyIfSpectatorsCanSeeHands);
|
||||
|
||||
int getNumFilteredGames() const;
|
||||
void resetFilterParameters();
|
||||
bool areFilterParametersSetToDefaults() const;
|
||||
void loadFilterParameters(const QMap<int, QString> &allGameTypes);
|
||||
void saveFilterParameters(const QMap<int, QString> &allGameTypes);
|
||||
void refresh();
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
bool filterAcceptsRow(int sourceRow) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef HANDCOUNTER_H
|
||||
#define HANDCOUNTER_H
|
||||
|
||||
#include "../game/board/abstract_graphics_item.h"
|
||||
#include "board/abstract_graphics_item.h"
|
||||
#include "board/graphics_item_type.h"
|
||||
|
||||
#include <QString>
|
||||
|
|
|
|||
842
cockatrice/src/game/log/message_log_widget.cpp
Normal file
842
cockatrice/src/game/log/message_log_widget.cpp
Normal file
|
|
@ -0,0 +1,842 @@
|
|||
#include "message_log_widget.h"
|
||||
|
||||
#include "../../client/sound_engine.h"
|
||||
#include "../../settings/card_counter_settings.h"
|
||||
#include "../../tabs/tab_game.h"
|
||||
#include "../board/card_item.h"
|
||||
#include "../board/translate_counter_name.h"
|
||||
#include "../phase.h"
|
||||
#include "../player/player.h"
|
||||
#include "../zones/card_zone.h"
|
||||
#include "pb/context_move_card.pb.h"
|
||||
#include "pb/context_mulligan.pb.h"
|
||||
#include "pb/serverinfo_user.pb.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
static const QString TABLE_ZONE_NAME = "table";
|
||||
static const QString GRAVE_ZONE_NAME = "grave";
|
||||
static const QString EXILE_ZONE_NAME = "rfg";
|
||||
static const QString HAND_ZONE_NAME = "hand";
|
||||
static const QString DECK_ZONE_NAME = "deck";
|
||||
static const QString SIDEBOARD_ZONE_NAME = "sb";
|
||||
static const QString STACK_ZONE_NAME = "stack";
|
||||
|
||||
static QString sanitizeHtml(QString dirty)
|
||||
{
|
||||
return dirty.replace("&", "&").replace("<", "<").replace(">", ">").replace("\"", """);
|
||||
}
|
||||
|
||||
static QString cardLink(const QString &cardName)
|
||||
{
|
||||
return QString("<i><a href=\"card://%1\">%2</a></i>").arg(cardName).arg(cardName);
|
||||
}
|
||||
|
||||
QPair<QString, QString>
|
||||
MessageLogWidget::getFromStr(CardZoneLogic *zone, QString cardName, int position, bool ownerChange)
|
||||
{
|
||||
bool cardNameContainsStartZone = false;
|
||||
QString fromStr;
|
||||
QString zoneName = zone->getName();
|
||||
|
||||
if (zoneName == TABLE_ZONE_NAME) {
|
||||
fromStr = tr(" from play");
|
||||
} else if (zoneName == GRAVE_ZONE_NAME) {
|
||||
fromStr = tr(" from their graveyard");
|
||||
} else if (zoneName == EXILE_ZONE_NAME) {
|
||||
fromStr = tr(" from exile");
|
||||
} else if (zoneName == HAND_ZONE_NAME) {
|
||||
fromStr = tr(" from their hand");
|
||||
} else if (zoneName == DECK_ZONE_NAME) {
|
||||
if (position == 0) {
|
||||
if (cardName.isEmpty()) {
|
||||
if (ownerChange) {
|
||||
cardName = tr("the top card of %1's library").arg(zone->getPlayer()->getPlayerInfo()->getName());
|
||||
} else {
|
||||
cardName = tr("the top card of their library");
|
||||
}
|
||||
cardNameContainsStartZone = true;
|
||||
} else {
|
||||
if (ownerChange) {
|
||||
fromStr = tr(" from the top of %1's library").arg(zone->getPlayer()->getPlayerInfo()->getName());
|
||||
} else {
|
||||
fromStr = tr(" from the top of their library");
|
||||
}
|
||||
}
|
||||
} else if (position >= zone->getCards().size() - 1) {
|
||||
if (cardName.isEmpty()) {
|
||||
if (ownerChange) {
|
||||
cardName = tr("the bottom card of %1's library").arg(zone->getPlayer()->getPlayerInfo()->getName());
|
||||
} else {
|
||||
cardName = tr("the bottom card of their library");
|
||||
}
|
||||
cardNameContainsStartZone = true;
|
||||
} else {
|
||||
if (ownerChange) {
|
||||
fromStr = tr(" from the bottom of %1's library").arg(zone->getPlayer()->getPlayerInfo()->getName());
|
||||
} else {
|
||||
fromStr = tr(" from the bottom of their library");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ownerChange) {
|
||||
fromStr = tr(" from %1's library").arg(zone->getPlayer()->getPlayerInfo()->getName());
|
||||
} else {
|
||||
fromStr = tr(" from their library");
|
||||
}
|
||||
}
|
||||
} else if (zoneName == SIDEBOARD_ZONE_NAME) {
|
||||
fromStr = tr(" from sideboard");
|
||||
} else if (zoneName == STACK_ZONE_NAME) {
|
||||
fromStr = tr(" from the stack");
|
||||
} else {
|
||||
fromStr = tr(" from custom zone '%1'").arg(zoneName);
|
||||
}
|
||||
|
||||
if (!cardNameContainsStartZone) {
|
||||
cardName.clear();
|
||||
}
|
||||
return {cardName, fromStr};
|
||||
}
|
||||
|
||||
void MessageLogWidget::containerProcessingDone()
|
||||
{
|
||||
currentContext = MessageContext_None;
|
||||
messageSuffix = messagePrefix = QString();
|
||||
}
|
||||
|
||||
void MessageLogWidget::containerProcessingStarted(const GameEventContext &context)
|
||||
{
|
||||
if (context.HasExtension(Context_MoveCard::ext)) {
|
||||
currentContext = MessageContext_MoveCard;
|
||||
} else if (context.HasExtension(Context_Mulligan::ext)) {
|
||||
currentContext = MessageContext_Mulligan;
|
||||
}
|
||||
}
|
||||
|
||||
void MessageLogWidget::logAlwaysRevealTopCard(Player *player, CardZoneLogic *zone, bool reveal)
|
||||
{
|
||||
appendHtmlServerMessage((reveal ? tr("%1 is now keeping the top card %2 revealed.")
|
||||
: tr("%1 is not revealing the top card %2 any longer."))
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(zone->getTranslatedName(true, CaseTopCardsOfZone)));
|
||||
}
|
||||
|
||||
void MessageLogWidget::logAlwaysLookAtTopCard(Player *player, CardZoneLogic *zone, bool reveal)
|
||||
{
|
||||
appendHtmlServerMessage((reveal ? tr("%1 can now look at top card %2 at any time.")
|
||||
: tr("%1 no longer can look at top card %2 at any time."))
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(zone->getTranslatedName(true, CaseTopCardsOfZone)));
|
||||
}
|
||||
|
||||
void MessageLogWidget::logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName)
|
||||
{
|
||||
appendHtmlServerMessage(tr("%1 attaches %2 to %3's %4.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(cardLink(std::move(cardName)))
|
||||
.arg(sanitizeHtml(targetPlayer->getPlayerInfo()->getName()))
|
||||
.arg(cardLink(std::move(targetCardName))));
|
||||
}
|
||||
|
||||
void MessageLogWidget::logConcede(int playerId)
|
||||
{
|
||||
soundEngine->playSound("player_concede");
|
||||
appendHtmlServerMessage(
|
||||
tr("%1 has conceded the game.")
|
||||
.arg(sanitizeHtml(game->getPlayerManager()->getPlayer(playerId)->getPlayerInfo()->getName())),
|
||||
true);
|
||||
}
|
||||
|
||||
void MessageLogWidget::logUnconcede(int playerId)
|
||||
{
|
||||
soundEngine->playSound("player_concede");
|
||||
appendHtmlServerMessage(
|
||||
tr("%1 has unconceded the game.")
|
||||
.arg(sanitizeHtml(game->getPlayerManager()->getPlayer(playerId)->getPlayerInfo()->getName())),
|
||||
true);
|
||||
}
|
||||
|
||||
void MessageLogWidget::logConnectionStateChanged(Player *player, bool connectionState)
|
||||
{
|
||||
if (connectionState) {
|
||||
soundEngine->playSound("player_reconnect");
|
||||
appendHtmlServerMessage(
|
||||
tr("%1 has restored connection to the game.").arg(sanitizeHtml(player->getPlayerInfo()->getName())), true);
|
||||
} else {
|
||||
soundEngine->playSound("player_disconnect");
|
||||
appendHtmlServerMessage(
|
||||
tr("%1 has lost connection to the game.").arg(sanitizeHtml(player->getPlayerInfo()->getName())), true);
|
||||
}
|
||||
}
|
||||
|
||||
void MessageLogWidget::logCreateArrow(Player *player,
|
||||
Player *startPlayer,
|
||||
QString startCard,
|
||||
Player *targetPlayer,
|
||||
QString targetCard,
|
||||
bool playerTarget)
|
||||
{
|
||||
startCard = cardLink(startCard);
|
||||
targetCard = cardLink(targetCard);
|
||||
QString str;
|
||||
if (playerTarget) {
|
||||
if (player == startPlayer && player == targetPlayer) {
|
||||
str = tr("%1 points from their %2 to themselves.");
|
||||
appendHtmlServerMessage(str.arg(sanitizeHtml(player->getPlayerInfo()->getName())).arg(startCard));
|
||||
} else if (player == startPlayer) {
|
||||
str = tr("%1 points from their %2 to %3.");
|
||||
appendHtmlServerMessage(str.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(startCard)
|
||||
.arg(sanitizeHtml(targetPlayer->getPlayerInfo()->getName())));
|
||||
} else if (player == targetPlayer) {
|
||||
str = tr("%1 points from %2's %3 to themselves.");
|
||||
appendHtmlServerMessage(str.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(sanitizeHtml(startPlayer->getPlayerInfo()->getName()))
|
||||
.arg(startCard));
|
||||
} else {
|
||||
str = tr("%1 points from %2's %3 to %4.");
|
||||
appendHtmlServerMessage(str.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(sanitizeHtml(startPlayer->getPlayerInfo()->getName()))
|
||||
.arg(startCard)
|
||||
.arg(sanitizeHtml(targetPlayer->getPlayerInfo()->getName())));
|
||||
}
|
||||
} else {
|
||||
if (player == startPlayer && player == targetPlayer) {
|
||||
str = tr("%1 points from their %2 to their %3.");
|
||||
appendHtmlServerMessage(
|
||||
str.arg(sanitizeHtml(player->getPlayerInfo()->getName())).arg(startCard).arg(targetCard));
|
||||
} else if (player == startPlayer) {
|
||||
str = tr("%1 points from their %2 to %3's %4.");
|
||||
appendHtmlServerMessage(str.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(startCard)
|
||||
.arg(sanitizeHtml(targetPlayer->getPlayerInfo()->getName()))
|
||||
.arg(targetCard));
|
||||
} else if (player == targetPlayer) {
|
||||
str = tr("%1 points from %2's %3 to their own %4.");
|
||||
appendHtmlServerMessage(str.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(sanitizeHtml(startPlayer->getPlayerInfo()->getName()))
|
||||
.arg(startCard)
|
||||
.arg(targetCard));
|
||||
} else {
|
||||
str = tr("%1 points from %2's %3 to %4's %5.");
|
||||
appendHtmlServerMessage(str.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(sanitizeHtml(startPlayer->getPlayerInfo()->getName()))
|
||||
.arg(startCard)
|
||||
.arg(sanitizeHtml(targetPlayer->getPlayerInfo()->getName()))
|
||||
.arg(targetCard));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MessageLogWidget::logCreateToken(Player *player, QString cardName, QString pt, bool faceDown)
|
||||
{
|
||||
if (faceDown) {
|
||||
appendHtmlServerMessage(
|
||||
tr("%1 creates a face down token.").arg(sanitizeHtml(player->getPlayerInfo()->getName())));
|
||||
} else {
|
||||
appendHtmlServerMessage(tr("%1 creates token: %2%3.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(cardLink(std::move(cardName)))
|
||||
.arg(pt.isEmpty() ? QString() : QString(" (%1)").arg(sanitizeHtml(pt))));
|
||||
}
|
||||
}
|
||||
|
||||
void MessageLogWidget::logDeckSelect(Player *player, QString deckHash, int sideboardSize)
|
||||
{
|
||||
if (sideboardSize < 0) {
|
||||
appendHtmlServerMessage(
|
||||
tr("%1 has loaded a deck (%2).").arg(sanitizeHtml(player->getPlayerInfo()->getName())).arg(deckHash));
|
||||
} else {
|
||||
appendHtmlServerMessage(tr("%1 has loaded a deck with %2 sideboard cards (%3).")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg("<font class=\"blue\">" + QString::number(sideboardSize) + "</font>")
|
||||
.arg(deckHash));
|
||||
}
|
||||
}
|
||||
|
||||
void MessageLogWidget::logDestroyCard(Player *player, QString cardName)
|
||||
{
|
||||
appendHtmlServerMessage(
|
||||
tr("%1 destroys %2.").arg(sanitizeHtml(player->getPlayerInfo()->getName())).arg(cardLink(std::move(cardName))));
|
||||
}
|
||||
|
||||
void MessageLogWidget::logMoveCard(Player *player,
|
||||
CardItem *card,
|
||||
CardZoneLogic *startZone,
|
||||
int oldX,
|
||||
CardZoneLogic *targetZone,
|
||||
int newX)
|
||||
{
|
||||
if (currentContext == MessageContext_Mulligan) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString startZoneName = startZone->getName();
|
||||
QString targetZoneName = targetZone->getName();
|
||||
bool ownerChanged = startZone->getPlayer() != targetZone->getPlayer();
|
||||
|
||||
// do not log if moved within the same zone
|
||||
if ((startZoneName == TABLE_ZONE_NAME && targetZoneName == TABLE_ZONE_NAME && !ownerChanged) ||
|
||||
(startZoneName == HAND_ZONE_NAME && targetZoneName == HAND_ZONE_NAME) ||
|
||||
(startZoneName == EXILE_ZONE_NAME && targetZoneName == EXILE_ZONE_NAME)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString cardName = card->getName();
|
||||
QPair<QString, QString> nameFrom = getFromStr(startZone, cardName, oldX, ownerChanged);
|
||||
if (!nameFrom.first.isEmpty()) {
|
||||
cardName = nameFrom.first;
|
||||
}
|
||||
|
||||
QString cardStr;
|
||||
if (!nameFrom.first.isEmpty()) {
|
||||
cardStr = cardName;
|
||||
} else if (cardName.isEmpty()) {
|
||||
cardStr = tr("a card");
|
||||
} else {
|
||||
cardStr = cardLink(cardName);
|
||||
}
|
||||
|
||||
if (ownerChanged && (startZone->getPlayer() == player)) {
|
||||
appendHtmlServerMessage(tr("%1 gives %2 control over %3.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(sanitizeHtml(targetZone->getPlayer()->getPlayerInfo()->getName()))
|
||||
.arg(cardStr));
|
||||
return;
|
||||
}
|
||||
|
||||
QString finalStr;
|
||||
std::optional<QString> fourthArg;
|
||||
if (targetZoneName == TABLE_ZONE_NAME) {
|
||||
soundEngine->playSound("play_card");
|
||||
if (card->getFaceDown()) {
|
||||
finalStr = tr("%1 puts %2 into play%3 face down.");
|
||||
} else {
|
||||
finalStr = tr("%1 puts %2 into play%3.");
|
||||
}
|
||||
} else if (targetZoneName == GRAVE_ZONE_NAME) {
|
||||
finalStr = tr("%1 puts %2%3 into their graveyard.");
|
||||
} else if (targetZoneName == EXILE_ZONE_NAME) {
|
||||
finalStr = tr("%1 exiles %2%3.");
|
||||
} else if (targetZoneName == HAND_ZONE_NAME) {
|
||||
finalStr = tr("%1 moves %2%3 to their hand.");
|
||||
} else if (targetZoneName == DECK_ZONE_NAME) {
|
||||
if (newX == -1) {
|
||||
finalStr = tr("%1 puts %2%3 into their library.");
|
||||
} else if (newX >= targetZone->getCards().size()) {
|
||||
finalStr = tr("%1 puts %2%3 onto the bottom of their library.");
|
||||
} else if (newX == 0) {
|
||||
finalStr = tr("%1 puts %2%3 on top of their library.");
|
||||
} else {
|
||||
++newX;
|
||||
fourthArg = QString::number(newX);
|
||||
finalStr = tr("%1 puts %2%3 into their library %4 cards from the top.");
|
||||
}
|
||||
} else if (targetZoneName == SIDEBOARD_ZONE_NAME) {
|
||||
finalStr = tr("%1 moves %2%3 to sideboard.");
|
||||
} else if (targetZoneName == STACK_ZONE_NAME) {
|
||||
soundEngine->playSound("play_card");
|
||||
finalStr = tr("%1 plays %2%3.");
|
||||
} else {
|
||||
fourthArg = targetZoneName;
|
||||
finalStr = tr("%1 moves %2%3 to custom zone '%4'.");
|
||||
}
|
||||
|
||||
QString message = finalStr.arg(sanitizeHtml(player->getPlayerInfo()->getName()), cardStr, nameFrom.second);
|
||||
|
||||
if (fourthArg.has_value()) {
|
||||
message = message.arg(fourthArg.value());
|
||||
}
|
||||
|
||||
appendHtmlServerMessage(message);
|
||||
}
|
||||
|
||||
void MessageLogWidget::logDrawCards(Player *player, int number, bool deckIsEmpty)
|
||||
{
|
||||
soundEngine->playSound("draw_card");
|
||||
if (currentContext == MessageContext_Mulligan) {
|
||||
logMulligan(player, number);
|
||||
} else {
|
||||
if (deckIsEmpty && number == 0) {
|
||||
appendHtmlServerMessage(
|
||||
tr("%1 tries to draw from an empty library").arg(sanitizeHtml(player->getPlayerInfo()->getName())));
|
||||
} else {
|
||||
appendHtmlServerMessage(tr("%1 draws %2 card(s).", "", number)
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg("<font class=\"blue\">" + QString::number(number) + "</font>"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MessageLogWidget::logDumpZone(Player *player, CardZoneLogic *zone, int numberCards, bool isReversed)
|
||||
{
|
||||
if (numberCards == -1) {
|
||||
appendHtmlServerMessage(tr("%1 is looking at %2.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(zone->getTranslatedName(zone->getPlayer() == player, CaseLookAtZone)));
|
||||
} else {
|
||||
appendHtmlServerMessage(
|
||||
tr("%1 is looking at the %4 %3 card(s) %2.", "top card for singular, top %3 cards for plural", numberCards)
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(zone->getTranslatedName(zone->getPlayer() == player, CaseTopCardsOfZone))
|
||||
.arg("<font class=\"blue\">" + QString::number(numberCards) + "</font>")
|
||||
.arg(isReversed ? tr("bottom") : tr("top")));
|
||||
}
|
||||
}
|
||||
|
||||
void MessageLogWidget::logFlipCard(Player *player, QString cardName, bool faceDown)
|
||||
{
|
||||
if (faceDown) {
|
||||
appendHtmlServerMessage(
|
||||
tr("%1 turns %2 face-down.").arg(sanitizeHtml(player->getPlayerInfo()->getName())).arg(cardLink(cardName)));
|
||||
} else {
|
||||
appendHtmlServerMessage(
|
||||
tr("%1 turns %2 face-up.").arg(sanitizeHtml(player->getPlayerInfo()->getName())).arg(cardLink(cardName)));
|
||||
}
|
||||
}
|
||||
|
||||
void MessageLogWidget::logGameClosed()
|
||||
{
|
||||
appendHtmlServerMessage(tr("The game has been closed."));
|
||||
}
|
||||
|
||||
void MessageLogWidget::logGameStart()
|
||||
{
|
||||
appendHtmlServerMessage(tr("The game has started."));
|
||||
}
|
||||
|
||||
void MessageLogWidget::logGameFlooded()
|
||||
{
|
||||
appendMessage(tr("You are flooding the game. Please wait a couple of seconds."));
|
||||
}
|
||||
|
||||
void MessageLogWidget::logJoin(Player *player)
|
||||
{
|
||||
soundEngine->playSound("player_join");
|
||||
appendHtmlServerMessage(tr("%1 has joined the game.").arg(sanitizeHtml(player->getPlayerInfo()->getName())));
|
||||
}
|
||||
|
||||
void MessageLogWidget::logJoinSpectator(QString name)
|
||||
{
|
||||
soundEngine->playSound("spectator_join");
|
||||
appendHtmlServerMessage(tr("%1 is now watching the game.").arg(sanitizeHtml(std::move(name))));
|
||||
}
|
||||
|
||||
void MessageLogWidget::logKicked()
|
||||
{
|
||||
appendHtmlServerMessage(tr("You have been kicked out of the game."), true);
|
||||
}
|
||||
|
||||
void MessageLogWidget::logLeave(Player *player, QString reason)
|
||||
{
|
||||
soundEngine->playSound("player_leave");
|
||||
appendHtmlServerMessage(tr("%1 has left the game (%2).")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()), sanitizeHtml(std::move(reason))),
|
||||
true);
|
||||
}
|
||||
|
||||
void MessageLogWidget::logLeaveSpectator(QString name, QString reason)
|
||||
{
|
||||
soundEngine->playSound("spectator_leave");
|
||||
appendHtmlServerMessage(tr("%1 is not watching the game any more (%2).")
|
||||
.arg(sanitizeHtml(std::move(name)), sanitizeHtml(std::move(reason))));
|
||||
}
|
||||
|
||||
void MessageLogWidget::logNotReadyStart(Player *player)
|
||||
{
|
||||
appendHtmlServerMessage(
|
||||
tr("%1 is not ready to start the game any more.").arg(sanitizeHtml(player->getPlayerInfo()->getName())));
|
||||
}
|
||||
|
||||
void MessageLogWidget::logMulligan(Player *player, int number)
|
||||
{
|
||||
if (!player) {
|
||||
return;
|
||||
}
|
||||
if (number > 0) {
|
||||
appendHtmlServerMessage(tr("%1 shuffles their deck and draws a new hand of %2 card(s).", "", number)
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(number));
|
||||
} else {
|
||||
appendHtmlServerMessage(
|
||||
tr("%1 shuffles their deck and draws a new hand.").arg(sanitizeHtml(player->getPlayerInfo()->getName())));
|
||||
}
|
||||
}
|
||||
|
||||
void MessageLogWidget::logReplayStarted(int gameId)
|
||||
{
|
||||
appendHtmlServerMessage(tr("You are watching a replay of game #%1.").arg(gameId));
|
||||
}
|
||||
|
||||
void MessageLogWidget::logReadyStart(Player *player)
|
||||
{
|
||||
appendHtmlServerMessage(tr("%1 is ready to start the game.").arg(sanitizeHtml(player->getPlayerInfo()->getName())));
|
||||
}
|
||||
|
||||
void MessageLogWidget::logRevealCards(Player *player,
|
||||
CardZoneLogic *zone,
|
||||
int cardId,
|
||||
QString cardName,
|
||||
Player *otherPlayer,
|
||||
bool faceDown,
|
||||
int amount,
|
||||
bool isLentToAnotherPlayer)
|
||||
{
|
||||
// getFromStr uses cardname.empty() to check if it should contain the start zone, it's not actually used
|
||||
QPair<QString, QString> temp = getFromStr(zone, amount == 1 ? cardName : QString::number(amount), cardId, false);
|
||||
bool cardNameContainsStartZone = false;
|
||||
if (!temp.first.isEmpty()) {
|
||||
cardNameContainsStartZone = true;
|
||||
cardName = temp.first;
|
||||
}
|
||||
QString fromStr = temp.second;
|
||||
|
||||
QString cardStr;
|
||||
if (cardNameContainsStartZone) {
|
||||
cardStr = cardName;
|
||||
} else if (cardName.isEmpty()) {
|
||||
if (amount == 0) {
|
||||
cardStr = tr("cards", "an unknown amount of cards");
|
||||
} else {
|
||||
cardStr = tr("%1 card(s)", "a card for singular, %1 cards for plural", amount)
|
||||
.arg("<font class=\"blue\">" + QString::number(amount) + "</font>");
|
||||
}
|
||||
} else {
|
||||
cardStr = cardLink(cardName);
|
||||
}
|
||||
if (cardId == -1) {
|
||||
if (otherPlayer) {
|
||||
if (isLentToAnotherPlayer) {
|
||||
appendHtmlServerMessage(tr("%1 lends %2 to %3.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(zone->getTranslatedName(true, CaseRevealZone))
|
||||
.arg(sanitizeHtml(otherPlayer->getPlayerInfo()->getName())));
|
||||
} else {
|
||||
appendHtmlServerMessage(tr("%1 reveals %2 to %3.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(zone->getTranslatedName(true, CaseRevealZone))
|
||||
.arg(sanitizeHtml(otherPlayer->getPlayerInfo()->getName())));
|
||||
}
|
||||
} else {
|
||||
appendHtmlServerMessage(tr("%1 reveals %2.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(zone->getTranslatedName(true, CaseRevealZone)));
|
||||
}
|
||||
} else if (cardId == -2) {
|
||||
if (otherPlayer) {
|
||||
appendHtmlServerMessage(tr("%1 randomly reveals %2%3 to %4.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(cardStr)
|
||||
.arg(fromStr)
|
||||
.arg(sanitizeHtml(otherPlayer->getPlayerInfo()->getName())));
|
||||
} else {
|
||||
appendHtmlServerMessage(tr("%1 randomly reveals %2%3.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(cardStr)
|
||||
.arg(fromStr));
|
||||
}
|
||||
} else {
|
||||
if (faceDown && player == otherPlayer) {
|
||||
if (cardName.isEmpty()) {
|
||||
appendHtmlServerMessage(tr("%1 peeks at face down card #%2.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(cardId));
|
||||
} else {
|
||||
appendHtmlServerMessage(tr("%1 peeks at face down card #%2: %3.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(cardId)
|
||||
.arg(cardStr));
|
||||
}
|
||||
} else if (otherPlayer) {
|
||||
appendHtmlServerMessage(tr("%1 reveals %2%3 to %4.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(cardStr)
|
||||
.arg(fromStr)
|
||||
.arg(sanitizeHtml(otherPlayer->getPlayerInfo()->getName())));
|
||||
} else {
|
||||
appendHtmlServerMessage(
|
||||
tr("%1 reveals %2%3.").arg(sanitizeHtml(player->getPlayerInfo()->getName())).arg(cardStr).arg(fromStr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MessageLogWidget::logReverseTurn(Player *player, bool reversed)
|
||||
{
|
||||
appendHtmlServerMessage(tr("%1 reversed turn order, now it's %2.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(reversed ? tr("reversed") : tr("normal")));
|
||||
}
|
||||
|
||||
void MessageLogWidget::logRollDie(Player *player, int sides, const QList<uint> &rolls)
|
||||
{
|
||||
if (rolls.length() == 1) {
|
||||
const auto roll = rolls.at(0);
|
||||
if (sides == 2) {
|
||||
QString coinOptions[2] = {tr("Heads") + " (1)", tr("Tails") + " (2)"};
|
||||
appendHtmlServerMessage(tr("%1 flipped a coin. It landed as %2.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg("<font class=\"blue\">" + coinOptions[roll - 1] + "</font>"));
|
||||
} else {
|
||||
appendHtmlServerMessage(tr("%1 rolls a %2 with a %3-sided die.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg("<font class=\"blue\">" + QString::number(roll) + "</font>")
|
||||
.arg("<font class=\"blue\">" + QString::number(sides) + "</font>"));
|
||||
}
|
||||
} else {
|
||||
if (sides == 2) {
|
||||
appendHtmlServerMessage(tr("%1 flips %2 coins. There are %3 heads and %4 tails.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg("<font class=\"blue\">" + QString::number(rolls.length()) + "</font>")
|
||||
.arg("<font class=\"blue\">" + QString::number(rolls.count(1)) + "</font>")
|
||||
.arg("<font class=\"blue\">" + QString::number(rolls.count(2)) + "</font>"));
|
||||
} else {
|
||||
QStringList rollsStrings;
|
||||
for (const auto &roll : rolls) {
|
||||
rollsStrings.append(QString::number(roll));
|
||||
}
|
||||
appendHtmlServerMessage(tr("%1 rolls a %2-sided dice %3 times: %4.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg("<font class=\"blue\">" + QString::number(sides) + "</font>")
|
||||
.arg("<font class=\"blue\">" + QString::number(rolls.length()) + "</font>")
|
||||
.arg("<font class=\"blue\">" + rollsStrings.join(", ") + "</font>"));
|
||||
}
|
||||
}
|
||||
soundEngine->playSound("roll_dice");
|
||||
}
|
||||
|
||||
void MessageLogWidget::logSay(Player *player, QString message)
|
||||
{
|
||||
appendMessage(std::move(message), {}, *player->getPlayerInfo()->getUserInfo(), true);
|
||||
}
|
||||
|
||||
void MessageLogWidget::logSetActivePhase(int phaseNumber)
|
||||
{
|
||||
Phase phase = Phases::getPhase(phaseNumber);
|
||||
|
||||
soundEngine->playSound(phase.soundFileName);
|
||||
|
||||
appendHtml("<font color=\"" + phase.color + "\"><b>" + QDateTime::currentDateTime().toString("[hh:mm:ss] ") +
|
||||
phase.getName() + "</b></font>");
|
||||
}
|
||||
|
||||
void MessageLogWidget::logSetActivePlayer(Player *player)
|
||||
{
|
||||
appendHtml("<br><font color=\"green\"><b>" + QDateTime::currentDateTime().toString("[hh:mm:ss] ") +
|
||||
QString(tr("%1's turn.")).arg(player->getPlayerInfo()->getName()) + "</b></font><br>");
|
||||
}
|
||||
|
||||
void MessageLogWidget::logSetAnnotation(Player *player, CardItem *card, QString newAnnotation)
|
||||
{
|
||||
appendHtmlServerMessage(
|
||||
QString(tr("%1 sets annotation of %2 to %3."))
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(cardLink(card->getName()))
|
||||
.arg(QString(""<font class=\"blue\">%1</font>"").arg(sanitizeHtml(std::move(newAnnotation)))));
|
||||
}
|
||||
|
||||
void MessageLogWidget::logSetCardCounter(Player *player, QString cardName, int counterId, int value, int oldValue)
|
||||
{
|
||||
QString finalStr;
|
||||
int delta = abs(oldValue - value);
|
||||
if (value > oldValue) {
|
||||
finalStr = tr("%1 places %2 \"%3\" counter(s) on %4 (now %5).", "", delta);
|
||||
} else {
|
||||
finalStr = tr("%1 removes %2 \"%3\" counter(s) from %4 (now %5).", "", delta);
|
||||
}
|
||||
|
||||
auto &cardCounterSettings = SettingsCache::instance().cardCounters();
|
||||
appendHtmlServerMessage(finalStr.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg("<font class=\"blue\">" + QString::number(delta) + "</font>")
|
||||
.arg(cardCounterSettings.displayName(counterId))
|
||||
.arg(cardLink(std::move(cardName)))
|
||||
.arg(value));
|
||||
}
|
||||
|
||||
void MessageLogWidget::logSetCounter(Player *player, QString counterName, int value, int oldValue)
|
||||
{
|
||||
if (counterName == "life") {
|
||||
soundEngine->playSound("life_change");
|
||||
}
|
||||
|
||||
QString counterDisplayName = TranslateCounterName::getDisplayName(counterName);
|
||||
appendHtmlServerMessage(tr("%1 sets counter %2 to %3 (%4%5).")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(QString("<font class=\"blue\">%1</font>").arg(sanitizeHtml(counterDisplayName)))
|
||||
.arg(QString("<font class=\"blue\">%1</font>").arg(value))
|
||||
.arg(value > oldValue ? "+" : "")
|
||||
.arg(value - oldValue));
|
||||
}
|
||||
|
||||
void MessageLogWidget::logSetDoesntUntap(Player *player, CardItem *card, bool doesntUntap)
|
||||
{
|
||||
QString str;
|
||||
if (doesntUntap) {
|
||||
str = tr("%1 sets %2 to not untap normally.");
|
||||
} else {
|
||||
str = tr("%1 sets %2 to untap normally.");
|
||||
}
|
||||
appendHtmlServerMessage(str.arg(sanitizeHtml(player->getPlayerInfo()->getName())).arg(cardLink(card->getName())));
|
||||
}
|
||||
|
||||
void MessageLogWidget::logSetPT(Player *player, CardItem *card, QString newPT)
|
||||
{
|
||||
if (currentContext == MessageContext_MoveCard) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString name = card->getName();
|
||||
if (name.isEmpty()) {
|
||||
name = QString("<font class=\"blue\">card #%1</font>").arg(sanitizeHtml(QString::number(card->getId())));
|
||||
} else {
|
||||
name = cardLink(name);
|
||||
}
|
||||
QString playerName = sanitizeHtml(player->getPlayerInfo()->getName());
|
||||
if (newPT.isEmpty()) {
|
||||
appendHtmlServerMessage(tr("%1 removes the PT of %2.").arg(playerName).arg(name));
|
||||
} else {
|
||||
QString oldPT = card->getPT();
|
||||
if (oldPT.isEmpty()) {
|
||||
appendHtmlServerMessage(
|
||||
tr("%1 changes the PT of %2 from nothing to %4.").arg(playerName).arg(name).arg(newPT));
|
||||
} else {
|
||||
appendHtmlServerMessage(
|
||||
tr("%1 changes the PT of %2 from %3 to %4.").arg(playerName).arg(name).arg(oldPT).arg(newPT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MessageLogWidget::logSetSideboardLock(Player *player, bool locked)
|
||||
{
|
||||
if (locked) {
|
||||
appendHtmlServerMessage(
|
||||
tr("%1 has locked their sideboard.").arg(sanitizeHtml(player->getPlayerInfo()->getName())));
|
||||
} else {
|
||||
appendHtmlServerMessage(
|
||||
tr("%1 has unlocked their sideboard.").arg(sanitizeHtml(player->getPlayerInfo()->getName())));
|
||||
}
|
||||
}
|
||||
|
||||
void MessageLogWidget::logSetTapped(Player *player, CardItem *card, bool tapped)
|
||||
{
|
||||
if (currentContext == MessageContext_MoveCard) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tapped) {
|
||||
soundEngine->playSound("tap_card");
|
||||
} else {
|
||||
soundEngine->playSound("untap_card");
|
||||
}
|
||||
|
||||
QString str;
|
||||
if (!card) {
|
||||
appendHtmlServerMessage((tapped ? tr("%1 taps their permanents.") : tr("%1 untaps their permanents."))
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName())));
|
||||
} else {
|
||||
appendHtmlServerMessage((tapped ? tr("%1 taps %2.") : tr("%1 untaps %2."))
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(cardLink(card->getName())));
|
||||
}
|
||||
}
|
||||
|
||||
void MessageLogWidget::logShuffle(Player *player, CardZoneLogic *zone, int start, int end)
|
||||
{
|
||||
if (currentContext == MessageContext_Mulligan) {
|
||||
return;
|
||||
}
|
||||
|
||||
soundEngine->playSound("shuffle");
|
||||
// start and end are indexes into the portion of the deck that was shuffled
|
||||
// with negitive numbers counging from the bottom up.
|
||||
if (start == 0 && end == -1) {
|
||||
appendHtmlServerMessage(tr("%1 shuffles %2.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(zone->getTranslatedName(true, CaseShuffleZone)));
|
||||
} else if (start < 0 && end == -1) {
|
||||
appendHtmlServerMessage(tr("%1 shuffles the bottom %3 cards of %2.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(zone->getTranslatedName(true, CaseShuffleZone))
|
||||
.arg(-start));
|
||||
} else if (start < 0 && end > 0) {
|
||||
appendHtmlServerMessage(tr("%1 shuffles the top %3 cards of %2.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(zone->getTranslatedName(true, CaseShuffleZone))
|
||||
.arg(end + 1));
|
||||
} else {
|
||||
appendHtmlServerMessage(tr("%1 shuffles cards %3 - %4 of %2.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(zone->getTranslatedName(true, CaseShuffleZone))
|
||||
.arg(start)
|
||||
.arg(end));
|
||||
}
|
||||
}
|
||||
|
||||
void MessageLogWidget::logSpectatorSay(const ServerInfo_User &spectator, QString message)
|
||||
{
|
||||
appendMessage(std::move(message), {}, spectator, false);
|
||||
}
|
||||
|
||||
void MessageLogWidget::logUnattachCard(Player *player, QString cardName)
|
||||
{
|
||||
appendHtmlServerMessage(tr("%1 unattaches %2.")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(cardLink(std::move(cardName))));
|
||||
}
|
||||
|
||||
void MessageLogWidget::logUndoDraw(Player *player, QString cardName)
|
||||
{
|
||||
if (cardName.isEmpty()) {
|
||||
appendHtmlServerMessage(tr("%1 undoes their last draw.").arg(sanitizeHtml(player->getPlayerInfo()->getName())));
|
||||
} else {
|
||||
appendHtmlServerMessage(
|
||||
tr("%1 undoes their last draw (%2).")
|
||||
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
|
||||
.arg(QString("<a href=\"card://%1\">%2</a>").arg(sanitizeHtml(cardName)).arg(sanitizeHtml(cardName))));
|
||||
}
|
||||
}
|
||||
|
||||
void MessageLogWidget::setContextJudgeName(QString name)
|
||||
{
|
||||
messagePrefix = QString("<span style=\"color:black\">");
|
||||
messageSuffix = QString("</span> [<img height=12 src=\"theme:icons/scales\"> %1]").arg(sanitizeHtml(name));
|
||||
}
|
||||
|
||||
void MessageLogWidget::appendHtmlServerMessage(const QString &html, bool optionalIsBold, QString optionalFontColor)
|
||||
{
|
||||
|
||||
ChatView::appendHtmlServerMessage(messagePrefix + html + messageSuffix, optionalIsBold, optionalFontColor);
|
||||
}
|
||||
|
||||
void MessageLogWidget::connectToPlayerEventHandler(PlayerEventHandler *playerEventHandler)
|
||||
{
|
||||
connect(playerEventHandler, &PlayerEventHandler::logSay, this, &MessageLogWidget::logSay);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logShuffle, this, &MessageLogWidget::logShuffle);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logRollDie, this, &MessageLogWidget::logRollDie);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logCreateArrow, this, &MessageLogWidget::logCreateArrow);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logCreateToken, this, &MessageLogWidget::logCreateToken);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logSetCounter, this, &MessageLogWidget::logSetCounter);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logSetCardCounter, this, &MessageLogWidget::logSetCardCounter);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logSetTapped, this, &MessageLogWidget::logSetTapped);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logSetDoesntUntap, this, &MessageLogWidget::logSetDoesntUntap);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logSetPT, this, &MessageLogWidget::logSetPT);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logSetAnnotation, this, &MessageLogWidget::logSetAnnotation);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logMoveCard, this, &MessageLogWidget::logMoveCard);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logFlipCard, this, &MessageLogWidget::logFlipCard);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logDestroyCard, this, &MessageLogWidget::logDestroyCard);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logAttachCard, this, &MessageLogWidget::logAttachCard);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logUnattachCard, this, &MessageLogWidget::logUnattachCard);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logDumpZone, this, &MessageLogWidget::logDumpZone);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logDrawCards, this, &MessageLogWidget::logDrawCards);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logUndoDraw, this, &MessageLogWidget::logUndoDraw);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logRevealCards, this, &MessageLogWidget::logRevealCards);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logAlwaysRevealTopCard, this,
|
||||
&MessageLogWidget::logAlwaysRevealTopCard);
|
||||
connect(playerEventHandler, &PlayerEventHandler::logAlwaysLookAtTopCard, this,
|
||||
&MessageLogWidget::logAlwaysLookAtTopCard);
|
||||
}
|
||||
|
||||
MessageLogWidget::MessageLogWidget(TabSupervisor *_tabSupervisor, AbstractGame *_game, QWidget *parent)
|
||||
: ChatView(_tabSupervisor, _game, true, parent), currentContext(MessageContext_None)
|
||||
{
|
||||
}
|
||||
104
cockatrice/src/game/log/message_log_widget.h
Normal file
104
cockatrice/src/game/log/message_log_widget.h
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
#ifndef MESSAGELOGWIDGET_H
|
||||
#define MESSAGELOGWIDGET_H
|
||||
|
||||
#include "../../client/translation.h"
|
||||
#include "../../server/chat_view/chat_view.h"
|
||||
#include "../zones/logic/card_zone_logic.h"
|
||||
#include "user_level.h"
|
||||
|
||||
class AbstractGame;
|
||||
class CardItem;
|
||||
class GameEventContext;
|
||||
class Player;
|
||||
class PlayerEventHandler;
|
||||
|
||||
class MessageLogWidget : public ChatView
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
enum MessageContext
|
||||
{
|
||||
MessageContext_None,
|
||||
MessageContext_MoveCard,
|
||||
MessageContext_Mulligan
|
||||
};
|
||||
|
||||
MessageContext currentContext;
|
||||
QString messagePrefix, messageSuffix;
|
||||
|
||||
static QPair<QString, QString> getFromStr(CardZoneLogic *zone, QString cardName, int position, bool ownerChange);
|
||||
|
||||
public:
|
||||
void connectToPlayerEventHandler(PlayerEventHandler *player);
|
||||
MessageLogWidget(TabSupervisor *_tabSupervisor, AbstractGame *_game, QWidget *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void containerProcessingDone();
|
||||
void containerProcessingStarted(const GameEventContext &context);
|
||||
void logAlwaysRevealTopCard(Player *player, CardZoneLogic *zone, bool reveal);
|
||||
void logAlwaysLookAtTopCard(Player *player, CardZoneLogic *zone, bool reveal);
|
||||
void logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName);
|
||||
void logConcede(int playerId);
|
||||
void logUnconcede(int playerId);
|
||||
void logConnectionStateChanged(Player *player, bool connectionState);
|
||||
void logCreateArrow(Player *player,
|
||||
Player *startPlayer,
|
||||
QString startCard,
|
||||
Player *targetPlayer,
|
||||
QString targetCard,
|
||||
bool playerTarget);
|
||||
void logCreateToken(Player *player, QString cardName, QString pt, bool faceDown);
|
||||
void logDeckSelect(Player *player, QString deckHash, int sideboardSize);
|
||||
void logDestroyCard(Player *player, QString cardName);
|
||||
void logDrawCards(Player *player, int number, bool deckIsEmpty);
|
||||
void logDumpZone(Player *player, CardZoneLogic *zone, int numberCards, bool isReversed = false);
|
||||
void logFlipCard(Player *player, QString cardName, bool faceDown);
|
||||
void logGameClosed();
|
||||
void logGameStart();
|
||||
void logGameFlooded();
|
||||
void logJoin(Player *player);
|
||||
void logJoinSpectator(QString name);
|
||||
void logKicked();
|
||||
void logLeave(Player *player, QString reason);
|
||||
void logLeaveSpectator(QString name, QString reason);
|
||||
void logNotReadyStart(Player *player);
|
||||
void logMoveCard(Player *player,
|
||||
CardItem *card,
|
||||
CardZoneLogic *startZone,
|
||||
int oldX,
|
||||
CardZoneLogic *targetZone,
|
||||
int newX);
|
||||
void logMulligan(Player *player, int number);
|
||||
void logReplayStarted(int gameId);
|
||||
void logReadyStart(Player *player);
|
||||
void logRevealCards(Player *player,
|
||||
CardZoneLogic *zone,
|
||||
int cardId,
|
||||
QString cardName,
|
||||
Player *otherPlayer,
|
||||
bool faceDown,
|
||||
int amount,
|
||||
bool isLentToAnotherPlayer);
|
||||
void logReverseTurn(Player *player, bool reversed);
|
||||
void logRollDie(Player *player, int sides, const QList<uint> &rolls);
|
||||
void logSay(Player *player, QString message);
|
||||
void logSetActivePhase(int phase);
|
||||
void logSetActivePlayer(Player *player);
|
||||
void logSetAnnotation(Player *player, CardItem *card, QString newAnnotation);
|
||||
void logSetCardCounter(Player *player, QString cardName, int counterId, int value, int oldValue);
|
||||
void logSetCounter(Player *player, QString counterName, int value, int oldValue);
|
||||
void logSetDoesntUntap(Player *player, CardItem *card, bool doesntUntap);
|
||||
void logSetPT(Player *player, CardItem *card, QString newPT);
|
||||
void logSetSideboardLock(Player *player, bool locked);
|
||||
void logSetTapped(Player *player, CardItem *card, bool tapped);
|
||||
void logShuffle(Player *player, CardZoneLogic *zone, int start, int end);
|
||||
void logSpectatorSay(const ServerInfo_User &spectator, QString message);
|
||||
void logUnattachCard(Player *player, QString cardName);
|
||||
void logUndoDraw(Player *player, QString cardName);
|
||||
void setContextJudgeName(QString player);
|
||||
void appendHtmlServerMessage(const QString &html,
|
||||
bool optionalIsBold = false,
|
||||
QString optionalFontColor = QString()) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
275
cockatrice/src/game/phases_toolbar.cpp
Normal file
275
cockatrice/src/game/phases_toolbar.cpp
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
#include "phases_toolbar.h"
|
||||
|
||||
#include "../interface/pixel_map_generator.h"
|
||||
#include "pb/command_draw_cards.pb.h"
|
||||
#include "pb/command_next_turn.pb.h"
|
||||
#include "pb/command_set_active_phase.pb.h"
|
||||
#include "pb/command_set_card_attr.pb.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
#include <QPen>
|
||||
#include <QTimer>
|
||||
|
||||
PhaseButton::PhaseButton(const QString &_name, QGraphicsItem *parent, QAction *_doubleClickAction, bool _highlightable)
|
||||
: QObject(), QGraphicsItem(parent), name(_name), active(false), highlightable(_highlightable),
|
||||
activeAnimationCounter(0), doubleClickAction(_doubleClickAction), width(50)
|
||||
{
|
||||
if (highlightable) {
|
||||
activeAnimationTimer = new QTimer(this);
|
||||
connect(activeAnimationTimer, &QTimer::timeout, this, &PhaseButton::updateAnimation);
|
||||
activeAnimationTimer->setSingleShot(false);
|
||||
} else
|
||||
activeAnimationCounter = 9;
|
||||
|
||||
setCacheMode(DeviceCoordinateCache);
|
||||
}
|
||||
|
||||
QRectF PhaseButton::boundingRect() const
|
||||
{
|
||||
return {0, 0, width, width};
|
||||
}
|
||||
|
||||
void PhaseButton::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
|
||||
{
|
||||
QRectF iconRect = boundingRect().adjusted(3, 3, -3, -3);
|
||||
QRectF translatedIconRect = painter->combinedTransform().mapRect(iconRect);
|
||||
qreal scaleFactor = translatedIconRect.width() / iconRect.width();
|
||||
QPixmap iconPixmap = PhasePixmapGenerator::generatePixmap(qRound(translatedIconRect.height()), name);
|
||||
|
||||
painter->setBrush(QColor(static_cast<int>(220 * (activeAnimationCounter / 10.0)),
|
||||
static_cast<int>(220 * (activeAnimationCounter / 10.0)),
|
||||
static_cast<int>(220 * (activeAnimationCounter / 10.0))));
|
||||
painter->setPen(Qt::gray);
|
||||
painter->drawRect(0, 0, static_cast<int>(width - 1), static_cast<int>(width - 1));
|
||||
painter->save();
|
||||
resetPainterTransform(painter);
|
||||
painter->drawPixmap(iconPixmap.rect().translated(qRound(3 * scaleFactor), qRound(3 * scaleFactor)), iconPixmap,
|
||||
iconPixmap.rect());
|
||||
painter->restore();
|
||||
|
||||
painter->setBrush(QColor(0, 0, 0, static_cast<int>(255 * ((10 - activeAnimationCounter) / 15.0))));
|
||||
painter->setPen(Qt::gray);
|
||||
painter->drawRect(0, 0, static_cast<int>(width - 1), static_cast<int>(width - 1));
|
||||
}
|
||||
|
||||
void PhaseButton::setWidth(double _width)
|
||||
{
|
||||
prepareGeometryChange();
|
||||
width = _width;
|
||||
}
|
||||
|
||||
void PhaseButton::setActive(bool _active)
|
||||
{
|
||||
if ((active == _active) || !highlightable)
|
||||
return;
|
||||
|
||||
active = _active;
|
||||
activeAnimationTimer->start(25);
|
||||
}
|
||||
|
||||
void PhaseButton::updateAnimation()
|
||||
{
|
||||
if (!highlightable)
|
||||
return;
|
||||
|
||||
// the counter ticks up to 10 when active and down to 0 when inactive
|
||||
if (active && activeAnimationCounter < 10) {
|
||||
++activeAnimationCounter;
|
||||
} else if (!active && activeAnimationCounter > 0) {
|
||||
--activeAnimationCounter;
|
||||
} else {
|
||||
activeAnimationTimer->stop();
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void PhaseButton::mousePressEvent(QGraphicsSceneMouseEvent * /*event*/)
|
||||
{
|
||||
emit clicked();
|
||||
}
|
||||
|
||||
void PhaseButton::mouseDoubleClickEvent(QGraphicsSceneMouseEvent * /*event*/)
|
||||
{
|
||||
triggerDoubleClickAction();
|
||||
}
|
||||
|
||||
void PhaseButton::triggerDoubleClickAction()
|
||||
{
|
||||
if (doubleClickAction)
|
||||
doubleClickAction->trigger();
|
||||
}
|
||||
|
||||
PhasesToolbar::PhasesToolbar(QGraphicsItem *parent)
|
||||
: QGraphicsItem(parent), width(100), height(100), ySpacing(1), symbolSize(8)
|
||||
{
|
||||
auto *aUntapAll = new QAction(this);
|
||||
connect(aUntapAll, &QAction::triggered, this, &PhasesToolbar::actUntapAll);
|
||||
auto *aDrawCard = new QAction(this);
|
||||
connect(aDrawCard, &QAction::triggered, this, &PhasesToolbar::actDrawCard);
|
||||
|
||||
PhaseButton *untapButton = new PhaseButton("untap", this, aUntapAll);
|
||||
PhaseButton *upkeepButton = new PhaseButton("upkeep", this);
|
||||
PhaseButton *drawButton = new PhaseButton("draw", this, aDrawCard);
|
||||
PhaseButton *main1Button = new PhaseButton("main1", this);
|
||||
PhaseButton *combatStartButton = new PhaseButton("combat_start", this);
|
||||
PhaseButton *combatAttackersButton = new PhaseButton("combat_attackers", this);
|
||||
PhaseButton *combatBlockersButton = new PhaseButton("combat_blockers", this);
|
||||
PhaseButton *combatDamageButton = new PhaseButton("combat_damage", this);
|
||||
PhaseButton *combatEndButton = new PhaseButton("combat_end", this);
|
||||
PhaseButton *main2Button = new PhaseButton("main2", this);
|
||||
PhaseButton *cleanupButton = new PhaseButton("cleanup", this);
|
||||
|
||||
buttonList << untapButton << upkeepButton << drawButton << main1Button << combatStartButton << combatAttackersButton
|
||||
<< combatBlockersButton << combatDamageButton << combatEndButton << main2Button << cleanupButton;
|
||||
|
||||
for (auto &i : buttonList)
|
||||
connect(i, &PhaseButton::clicked, this, &PhasesToolbar::phaseButtonClicked);
|
||||
|
||||
nextTurnButton = new PhaseButton("nextturn", this, nullptr, false);
|
||||
connect(nextTurnButton, &PhaseButton::clicked, this, &PhasesToolbar::actNextTurn);
|
||||
|
||||
rearrangeButtons();
|
||||
|
||||
retranslateUi();
|
||||
}
|
||||
|
||||
QRectF PhasesToolbar::boundingRect() const
|
||||
{
|
||||
return {0, 0, width, height};
|
||||
}
|
||||
|
||||
void PhasesToolbar::retranslateUi()
|
||||
{
|
||||
for (int i = 0; i < buttonList.size(); ++i)
|
||||
buttonList[i]->setToolTip(getLongPhaseName(i));
|
||||
}
|
||||
|
||||
QString PhasesToolbar::getLongPhaseName(int phase) const
|
||||
{
|
||||
switch (phase) {
|
||||
case 0:
|
||||
return tr("Untap step");
|
||||
case 1:
|
||||
return tr("Upkeep step");
|
||||
case 2:
|
||||
return tr("Draw step");
|
||||
case 3:
|
||||
return tr("First main phase");
|
||||
case 4:
|
||||
return tr("Beginning of combat step");
|
||||
case 5:
|
||||
return tr("Declare attackers step");
|
||||
case 6:
|
||||
return tr("Declare blockers step");
|
||||
case 7:
|
||||
return tr("Combat damage step");
|
||||
case 8:
|
||||
return tr("End of combat step");
|
||||
case 9:
|
||||
return tr("Second main phase");
|
||||
case 10:
|
||||
return tr("End of turn step");
|
||||
default:
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
void PhasesToolbar::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
|
||||
{
|
||||
painter->fillRect(boundingRect(), QColor(50, 50, 50));
|
||||
}
|
||||
|
||||
const double PhasesToolbar::marginSize = 3;
|
||||
|
||||
void PhasesToolbar::rearrangeButtons()
|
||||
{
|
||||
for (auto &i : buttonList)
|
||||
i->setWidth(symbolSize);
|
||||
nextTurnButton->setWidth(symbolSize);
|
||||
|
||||
double y = marginSize;
|
||||
buttonList[0]->setPos(marginSize, y);
|
||||
buttonList[1]->setPos(marginSize, y += symbolSize);
|
||||
buttonList[2]->setPos(marginSize, y += symbolSize);
|
||||
y += ySpacing;
|
||||
buttonList[3]->setPos(marginSize, y += symbolSize);
|
||||
y += ySpacing;
|
||||
buttonList[4]->setPos(marginSize, y += symbolSize);
|
||||
buttonList[5]->setPos(marginSize, y += symbolSize);
|
||||
buttonList[6]->setPos(marginSize, y += symbolSize);
|
||||
buttonList[7]->setPos(marginSize, y += symbolSize);
|
||||
buttonList[8]->setPos(marginSize, y += symbolSize);
|
||||
y += ySpacing;
|
||||
buttonList[9]->setPos(marginSize, y += symbolSize);
|
||||
y += ySpacing;
|
||||
buttonList[10]->setPos(marginSize, y += symbolSize);
|
||||
y += ySpacing;
|
||||
y += ySpacing;
|
||||
nextTurnButton->setPos(marginSize, y + symbolSize);
|
||||
}
|
||||
|
||||
void PhasesToolbar::setHeight(double _height)
|
||||
{
|
||||
prepareGeometryChange();
|
||||
|
||||
height = _height;
|
||||
ySpacing = (height - 2 * marginSize) / (buttonCount * 5 + spaceCount);
|
||||
symbolSize = ySpacing * 5;
|
||||
width = symbolSize + 2 * marginSize;
|
||||
|
||||
rearrangeButtons();
|
||||
}
|
||||
|
||||
void PhasesToolbar::setActivePhase(int phase)
|
||||
{
|
||||
if (phase >= buttonList.size())
|
||||
return;
|
||||
|
||||
for (int i = 0; i < buttonList.size(); ++i)
|
||||
buttonList[i]->setActive(i == phase);
|
||||
}
|
||||
|
||||
void PhasesToolbar::triggerPhaseAction(int phase)
|
||||
{
|
||||
if (0 <= phase && phase < buttonList.size()) {
|
||||
buttonList[phase]->triggerDoubleClickAction();
|
||||
}
|
||||
}
|
||||
|
||||
void PhasesToolbar::phaseButtonClicked()
|
||||
{
|
||||
auto *button = qobject_cast<PhaseButton *>(sender());
|
||||
if (button->getActive())
|
||||
button->triggerDoubleClickAction();
|
||||
|
||||
Command_SetActivePhase cmd;
|
||||
cmd.set_phase(static_cast<google::protobuf::uint32>(buttonList.indexOf(button)));
|
||||
|
||||
emit sendGameCommand(cmd, -1);
|
||||
}
|
||||
|
||||
void PhasesToolbar::actNextTurn()
|
||||
{
|
||||
emit sendGameCommand(Command_NextTurn(), -1);
|
||||
}
|
||||
|
||||
void PhasesToolbar::actUntapAll()
|
||||
{
|
||||
Command_SetCardAttr cmd;
|
||||
cmd.set_zone("table");
|
||||
cmd.set_attribute(AttrTapped);
|
||||
cmd.set_attr_value("0");
|
||||
|
||||
emit sendGameCommand(cmd, -1);
|
||||
}
|
||||
|
||||
void PhasesToolbar::actDrawCard()
|
||||
{
|
||||
Command_DrawCards cmd;
|
||||
cmd.set_number(1);
|
||||
|
||||
emit sendGameCommand(cmd, -1);
|
||||
}
|
||||
100
cockatrice/src/game/phases_toolbar.h
Normal file
100
cockatrice/src/game/phases_toolbar.h
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
#ifndef PHASESTOOLBAR_H
|
||||
#define PHASESTOOLBAR_H
|
||||
|
||||
#include "board/abstract_graphics_item.h"
|
||||
|
||||
#include <QFrame>
|
||||
#include <QGraphicsObject>
|
||||
#include <QList>
|
||||
|
||||
namespace google
|
||||
{
|
||||
namespace protobuf
|
||||
{
|
||||
class Message;
|
||||
}
|
||||
} // namespace google
|
||||
class Player;
|
||||
class GameCommand;
|
||||
|
||||
class PhaseButton : public QObject, public QGraphicsItem
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QGraphicsItem)
|
||||
private:
|
||||
QString name;
|
||||
bool active, highlightable;
|
||||
int activeAnimationCounter;
|
||||
QTimer *activeAnimationTimer;
|
||||
QAction *doubleClickAction;
|
||||
double width;
|
||||
|
||||
// void updatePixmap(QPixmap &pixmap);
|
||||
private slots:
|
||||
void updateAnimation();
|
||||
|
||||
public:
|
||||
explicit PhaseButton(const QString &_name,
|
||||
QGraphicsItem *parent = nullptr,
|
||||
QAction *_doubleClickAction = nullptr,
|
||||
bool _highlightable = true);
|
||||
QRectF boundingRect() const override;
|
||||
void setWidth(double _width);
|
||||
void setActive(bool _active);
|
||||
bool getActive() const
|
||||
{
|
||||
return active;
|
||||
}
|
||||
void triggerDoubleClickAction();
|
||||
signals:
|
||||
void clicked();
|
||||
|
||||
protected:
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/) override;
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
};
|
||||
|
||||
class PhasesToolbar : public QObject, public QGraphicsItem
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QGraphicsItem)
|
||||
private:
|
||||
QList<PhaseButton *> buttonList;
|
||||
PhaseButton *nextTurnButton;
|
||||
double width, height, ySpacing, symbolSize;
|
||||
static const int buttonCount = 12;
|
||||
static const int spaceCount = 6;
|
||||
static const double marginSize;
|
||||
void rearrangeButtons();
|
||||
|
||||
public:
|
||||
explicit PhasesToolbar(QGraphicsItem *parent = nullptr);
|
||||
QRectF boundingRect() const override;
|
||||
void retranslateUi();
|
||||
void setHeight(double _height);
|
||||
double getWidth() const
|
||||
{
|
||||
return width;
|
||||
}
|
||||
int phaseCount() const
|
||||
{
|
||||
return buttonList.size();
|
||||
}
|
||||
QString getLongPhaseName(int phase) const;
|
||||
public slots:
|
||||
void setActivePhase(int phase);
|
||||
void triggerPhaseAction(int phase);
|
||||
private slots:
|
||||
void phaseButtonClicked();
|
||||
void actNextTurn();
|
||||
void actUntapAll();
|
||||
void actDrawCard();
|
||||
signals:
|
||||
void sendGameCommand(const ::google::protobuf::Message &command, int playerId);
|
||||
|
||||
protected:
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
#include "card_menu.h"
|
||||
|
||||
#include "../../../client/tabs/tab_game.h"
|
||||
#include "../../../database/card_database_manager.h"
|
||||
#include "../../../settings/card_counter_settings.h"
|
||||
#include "../../../tabs/tab_game.h"
|
||||
#include "../../board/card_item.h"
|
||||
#include "../../zones/logic/view_zone_logic.h"
|
||||
#include "../card_menu_action_type.h"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef COCKATRICE_GRAVE_MENU_H
|
||||
#define COCKATRICE_GRAVE_MENU_H
|
||||
|
||||
#include "../../../client/tearoff_menu.h"
|
||||
#include "../../../interface/tearoff_menu.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef COCKATRICE_HAND_MENU_H
|
||||
#define COCKATRICE_HAND_MENU_H
|
||||
|
||||
#include "../../../client/tearoff_menu.h"
|
||||
#include "../../../interface/tearoff_menu.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef COCKATRICE_LIBRARY_MENU_H
|
||||
#define COCKATRICE_LIBRARY_MENU_H
|
||||
|
||||
#include "../../../client/tearoff_menu.h"
|
||||
#include "../../../interface/tearoff_menu.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#include "player_menu.h"
|
||||
|
||||
#include "../../../client/tabs/tab_game.h"
|
||||
#include "../../../common/pb/command_reveal_cards.pb.h"
|
||||
#include "../../../database/card_database_manager.h"
|
||||
#include "../../../tabs/tab_game.h"
|
||||
#include "../../board/card_item.h"
|
||||
#include "../../zones/hand_zone.h"
|
||||
#include "../card_menu_action_type.h"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef COCKATRICE_PLAYER_MENU_H
|
||||
#define COCKATRICE_PLAYER_MENU_H
|
||||
|
||||
#include "../../../client/tearoff_menu.h"
|
||||
#include "../../../interface/tearoff_menu.h"
|
||||
#include "../player.h"
|
||||
#include "custom_zone_menu.h"
|
||||
#include "grave_menu.h"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef COCKATRICE_RFG_MENU_H
|
||||
#define COCKATRICE_RFG_MENU_H
|
||||
|
||||
#include "../../../client/tearoff_menu.h"
|
||||
#include "../../../interface/tearoff_menu.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "player.h"
|
||||
|
||||
#include "../../client/tabs/tab_game.h"
|
||||
#include "../../client/ui/theme_manager.h"
|
||||
#include "../../interface/theme_manager.h"
|
||||
#include "../../tabs/tab_game.h"
|
||||
#include "../board/arrow_item.h"
|
||||
#include "../board/card_item.h"
|
||||
#include "../board/card_list.h"
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
#define PLAYER_H
|
||||
|
||||
#include "../../card/card_info.h"
|
||||
#include "../../client/tearoff_menu.h"
|
||||
#include "../../dialogs/dlg_create_token.h"
|
||||
#include "../../filters/filter_string.h"
|
||||
#include "../../interface/tearoff_menu.h"
|
||||
#include "../board/abstract_graphics_item.h"
|
||||
#include "../dialogs/dlg_create_token.h"
|
||||
#include "menu/player_menu.h"
|
||||
#include "pb/card_attributes.pb.h"
|
||||
#include "pb/game_event.pb.h"
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
#include "../../../common/pb/context_move_card.pb.h"
|
||||
#include "../../client/get_text_with_max.h"
|
||||
#include "../../client/tabs/tab_game.h"
|
||||
#include "../../database/card_database_manager.h"
|
||||
#include "../../dialogs/dlg_move_top_cards_until.h"
|
||||
#include "../../dialogs/dlg_roll_dice.h"
|
||||
#include "../../tabs/tab_game.h"
|
||||
#include "../board/card_item.h"
|
||||
#include "../dialogs/dlg_move_top_cards_until.h"
|
||||
#include "../dialogs/dlg_roll_dice.h"
|
||||
#include "../zones/logic/view_zone_logic.h"
|
||||
#include "card_menu_action_type.h"
|
||||
#include "pb/command_attach_card.pb.h"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "player_area.h"
|
||||
|
||||
#include "../../client/ui/theme_manager.h"
|
||||
#include "../../interface/theme_manager.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "player_event_handler.h"
|
||||
|
||||
#include "../../client/tabs/tab_game.h"
|
||||
#include "../../tabs/tab_game.h"
|
||||
#include "../board/arrow_item.h"
|
||||
#include "../board/card_item.h"
|
||||
#include "../board/card_list.h"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "player_graphics_item.h"
|
||||
|
||||
#include "../../client/tabs/tab_game.h"
|
||||
#include "../../tabs/tab_game.h"
|
||||
#include "../hand_counter.h"
|
||||
|
||||
PlayerGraphicsItem::PlayerGraphicsItem(Player *_player) : player(_player)
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
#include "player_list_widget.h"
|
||||
|
||||
#include "../../client/tabs/tab_account.h"
|
||||
#include "../../client/tabs/tab_game.h"
|
||||
#include "../../client/tabs/tab_supervisor.h"
|
||||
#include "../../client/ui/pixel_map_generator.h"
|
||||
#include "../../interface/pixel_map_generator.h"
|
||||
#include "../../server/abstract_client.h"
|
||||
#include "../../server/user/user_context_menu.h"
|
||||
#include "../../server/user/user_list_manager.h"
|
||||
#include "../../server/user/user_list_widget.h"
|
||||
#include "../../tabs/tab_account.h"
|
||||
#include "../../tabs/tab_game.h"
|
||||
#include "../../tabs/tab_supervisor.h"
|
||||
#include "pb/command_kick_from_game.pb.h"
|
||||
#include "pb/serverinfo_playerproperties.pb.h"
|
||||
#include "pb/session_commands.pb.h"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "player_target.h"
|
||||
|
||||
#include "../../client/ui/pixel_map_generator.h"
|
||||
#include "../../interface/pixel_map_generator.h"
|
||||
#include "pb/serverinfo_user.pb.h"
|
||||
#include "player.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "replay.h"
|
||||
|
||||
#include "../client/tabs/tab_game.h"
|
||||
#include "../tabs/tab_game.h"
|
||||
|
||||
Replay::Replay(TabGame *_tab, GameReplay *_replay) : AbstractGame(_tab)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "hand_zone.h"
|
||||
|
||||
#include "../../client/ui/theme_manager.h"
|
||||
#include "../../interface/theme_manager.h"
|
||||
#include "../../settings/cache_settings.h"
|
||||
#include "../board/card_drag_item.h"
|
||||
#include "../board/card_item.h"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "stack_zone.h"
|
||||
|
||||
#include "../../client/ui/theme_manager.h"
|
||||
#include "../../interface/theme_manager.h"
|
||||
#include "../../settings/cache_settings.h"
|
||||
#include "../board/arrow_item.h"
|
||||
#include "../board/card_drag_item.h"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "table_zone.h"
|
||||
|
||||
#include "../../card/card_info.h"
|
||||
#include "../../client/ui/theme_manager.h"
|
||||
#include "../../interface/theme_manager.h"
|
||||
#include "../../settings/cache_settings.h"
|
||||
#include "../board/arrow_item.h"
|
||||
#include "../board/card_drag_item.h"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "view_zone_widget.h"
|
||||
|
||||
#include "../../client/ui/pixel_map_generator.h"
|
||||
#include "../../filters/syntax_help.h"
|
||||
#include "../../interface/pixel_map_generator.h"
|
||||
#include "../../settings/cache_settings.h"
|
||||
#include "../board/card_item.h"
|
||||
#include "../game_scene.h"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue