mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-03-21 17:55:21 -05:00
[Game] implement Select All Matching action
This commit is contained in:
parent
5cc21f591d
commit
57b4b2b73b
|
|
@ -71,6 +71,7 @@ set(cockatrice_SOURCES
|
|||
src/game/dialogs/dlg_create_token.cpp
|
||||
src/game/dialogs/dlg_move_top_cards_until.cpp
|
||||
src/game/dialogs/dlg_roll_dice.cpp
|
||||
src/game/dialogs/dlg_select_all_matching.cpp
|
||||
src/game/game.cpp
|
||||
src/game/game_event_handler.cpp
|
||||
src/game/game_meta_info.cpp
|
||||
|
|
|
|||
|
|
@ -546,6 +546,10 @@ private:
|
|||
{"Player/aSelectColumn", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Select All Cards in Column"),
|
||||
parseSequenceString("Ctrl+Shift+C"),
|
||||
ShortcutGroup::Playing_Area)},
|
||||
{"Player/aSelectAllMatching",
|
||||
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Select All Cards in Zone Matching Expression"),
|
||||
parseSequenceString(""),
|
||||
ShortcutGroup::Playing_Area)},
|
||||
{"Player/aRevealToAll", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Reveal Selected Cards to All Players"),
|
||||
parseSequenceString(""),
|
||||
ShortcutGroup::Playing_Area)},
|
||||
|
|
|
|||
119
cockatrice/src/game/dialogs/dlg_select_all_matching.cpp
Normal file
119
cockatrice/src/game/dialogs/dlg_select_all_matching.cpp
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
#include "dlg_select_all_matching.h"
|
||||
|
||||
#include "libcockatrice/card/card_info.h"
|
||||
#include "libcockatrice/card/database/card_database_manager.h"
|
||||
#include "libcockatrice/filters/filter_string.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QLabel>
|
||||
#include <QMessageBox>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
DlgSelectAllMatching::DlgSelectAllMatching(QWidget *parent, const SelectAllMatchingOptions &options) : 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, options.exprs);
|
||||
exprLabel->setBuddy(exprComboBox);
|
||||
|
||||
clearSelectionCheckBox = new QCheckBox(tr("Clear existing selection first"));
|
||||
clearSelectionCheckBox->setChecked(options.clearSelection);
|
||||
|
||||
toggleSelectedCheckBox = new QCheckBox(tr("Toggle already selected matches"));
|
||||
toggleSelectedCheckBox->setChecked(options.toggleSelected);
|
||||
|
||||
buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &DlgSelectAllMatching::validateAndAccept);
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
auto *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addWidget(exprLabel);
|
||||
mainLayout->addWidget(exprComboBox);
|
||||
mainLayout->addWidget(clearSelectionCheckBox);
|
||||
mainLayout->addWidget(toggleSelectedCheckBox);
|
||||
mainLayout->addWidget(buttonBox);
|
||||
|
||||
setLayout(mainLayout);
|
||||
setWindowTitle(tr("Select all cards matching..."));
|
||||
}
|
||||
|
||||
/**
|
||||
* @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();
|
||||
}
|
||||
|
||||
bool DlgSelectAllMatching::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 DlgSelectAllMatching::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 DlgSelectAllMatching::getExpr() const
|
||||
{
|
||||
return exprComboBox->currentText();
|
||||
}
|
||||
|
||||
SelectAllMatchingOptions DlgSelectAllMatching::getOptions() const
|
||||
{
|
||||
return {.exprs = getExprs(),
|
||||
.clearSelection = clearSelectionCheckBox->isChecked(),
|
||||
.toggleSelected = toggleSelectedCheckBox->isChecked()};
|
||||
}
|
||||
|
||||
QStringList DlgSelectAllMatching::getExprs() const
|
||||
{
|
||||
QStringList exprs;
|
||||
for (int i = 0; i < exprComboBox->count(); ++i) {
|
||||
exprs.append(exprComboBox->itemText(i));
|
||||
}
|
||||
return exprs;
|
||||
}
|
||||
42
cockatrice/src/game/dialogs/dlg_select_all_matching.h
Normal file
42
cockatrice/src/game/dialogs/dlg_select_all_matching.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#ifndef COCKATRICE_DLG_SELECT_ALL_MATCHING_H
|
||||
#define COCKATRICE_DLG_SELECT_ALL_MATCHING_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class FilterString;
|
||||
class QCheckBox;
|
||||
class QDialogButtonBox;
|
||||
class QSpinBox;
|
||||
class QComboBox;
|
||||
class QLabel;
|
||||
|
||||
struct SelectAllMatchingOptions
|
||||
{
|
||||
QStringList exprs = {};
|
||||
bool clearSelection = true;
|
||||
bool toggleSelected = false;
|
||||
};
|
||||
|
||||
class DlgSelectAllMatching : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QLabel *exprLabel;
|
||||
QComboBox *exprComboBox;
|
||||
QCheckBox *clearSelectionCheckBox;
|
||||
QCheckBox *toggleSelectedCheckBox;
|
||||
QDialogButtonBox *buttonBox;
|
||||
|
||||
void validateAndAccept();
|
||||
bool validateMatchExists(const FilterString &filterString);
|
||||
|
||||
[[nodiscard]] QStringList getExprs() const;
|
||||
|
||||
public:
|
||||
explicit DlgSelectAllMatching(QWidget *parent, const SelectAllMatchingOptions &options);
|
||||
|
||||
[[nodiscard]] QString getExpr() const;
|
||||
[[nodiscard]] SelectAllMatchingOptions getOptions() const;
|
||||
};
|
||||
|
||||
#endif // COCKATRICE_DLG_SELECT_ALL_MATCHING_H
|
||||
|
|
@ -59,6 +59,8 @@ CardMenu::CardMenu(Player *_player, const CardItem *_card, bool _shortcutsActive
|
|||
connect(aSelectRow, &QAction::triggered, playerActions, &PlayerActions::actSelectRow);
|
||||
aSelectColumn = new QAction(this);
|
||||
connect(aSelectColumn, &QAction::triggered, playerActions, &PlayerActions::actSelectColumn);
|
||||
aSelectAllMatching = new QAction(this);
|
||||
connect(aSelectAllMatching, &QAction::triggered, playerActions, &PlayerActions::actSelectAllMatching);
|
||||
|
||||
aPlay = new QAction(this);
|
||||
connect(aPlay, &QAction::triggered, playerActions, &PlayerActions::actPlay);
|
||||
|
|
@ -111,6 +113,7 @@ CardMenu::CardMenu(Player *_player, const CardItem *_card, bool _shortcutsActive
|
|||
addAction(aClone);
|
||||
addSeparator();
|
||||
addAction(aSelectAll);
|
||||
addAction(aSelectAllMatching);
|
||||
addAction(aSelectColumn);
|
||||
addRelatedCardView();
|
||||
} else {
|
||||
|
|
@ -155,6 +158,7 @@ void CardMenu::createTableMenu(bool canModifyCard)
|
|||
addAction(aClone);
|
||||
addSeparator();
|
||||
addAction(aSelectAll);
|
||||
addAction(aSelectAllMatching);
|
||||
addAction(aSelectRow);
|
||||
return;
|
||||
}
|
||||
|
|
@ -183,6 +187,7 @@ void CardMenu::createTableMenu(bool canModifyCard)
|
|||
addMenu(new MoveMenu(player));
|
||||
addSeparator();
|
||||
addAction(aSelectAll);
|
||||
addAction(aSelectAllMatching);
|
||||
addAction(aSelectRow);
|
||||
|
||||
addSeparator();
|
||||
|
|
@ -210,12 +215,14 @@ void CardMenu::createStackMenu(bool canModifyCard)
|
|||
addMenu(new MoveMenu(player));
|
||||
addSeparator();
|
||||
addAction(aSelectAll);
|
||||
addAction(aSelectAllMatching);
|
||||
} else {
|
||||
addAction(aDrawArrow);
|
||||
addSeparator();
|
||||
addAction(aClone);
|
||||
addSeparator();
|
||||
addAction(aSelectAll);
|
||||
addAction(aSelectAllMatching);
|
||||
}
|
||||
|
||||
addRelatedCardView();
|
||||
|
|
@ -234,6 +241,7 @@ void CardMenu::createGraveyardOrExileMenu(bool canModifyCard)
|
|||
addMenu(new MoveMenu(player));
|
||||
addSeparator();
|
||||
addAction(aSelectAll);
|
||||
addAction(aSelectAllMatching);
|
||||
addAction(aSelectColumn);
|
||||
|
||||
addSeparator();
|
||||
|
|
@ -243,6 +251,7 @@ void CardMenu::createGraveyardOrExileMenu(bool canModifyCard)
|
|||
addAction(aClone);
|
||||
addSeparator();
|
||||
addAction(aSelectAll);
|
||||
addAction(aSelectAllMatching);
|
||||
addAction(aSelectColumn);
|
||||
addSeparator();
|
||||
addAction(aDrawArrow);
|
||||
|
|
@ -263,6 +272,7 @@ void CardMenu::createHandOrCustomZoneMenu(bool canModifyCard)
|
|||
addAction(aClone);
|
||||
addSeparator();
|
||||
addAction(aSelectAll);
|
||||
addAction(aSelectAllMatching);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -289,6 +299,7 @@ void CardMenu::createHandOrCustomZoneMenu(bool canModifyCard)
|
|||
|
||||
addSeparator();
|
||||
addAction(aSelectAll);
|
||||
addAction(aSelectAllMatching);
|
||||
if (qobject_cast<ZoneViewZoneLogic *>(card->getZone())) {
|
||||
addAction(aSelectColumn);
|
||||
}
|
||||
|
|
@ -442,6 +453,7 @@ void CardMenu::retranslateUi()
|
|||
aSelectAll->setText(tr("&Select All"));
|
||||
aSelectRow->setText(tr("S&elect Row"));
|
||||
aSelectColumn->setText(tr("S&elect Column"));
|
||||
aSelectAllMatching->setText(tr("Select All Matching..."));
|
||||
|
||||
aPlay->setText(tr("&Play"));
|
||||
aHide->setText(tr("&Hide"));
|
||||
|
|
@ -498,6 +510,7 @@ void CardMenu::setShortcutsActive()
|
|||
aSelectAll->setShortcuts(shortcuts.getShortcut("Player/aSelectAll"));
|
||||
aSelectRow->setShortcuts(shortcuts.getShortcut("Player/aSelectRow"));
|
||||
aSelectColumn->setShortcuts(shortcuts.getShortcut("Player/aSelectColumn"));
|
||||
aSelectAllMatching->setShortcuts(shortcuts.getShortcut("Player/aSelectAllMatching"));
|
||||
|
||||
static const QStringList colorWords = {"Red", "Yellow", "Green", "Cyan", "Purple", "Magenta"};
|
||||
for (int i = 0; i < aAddCounter.size(); i++) {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ public:
|
|||
QAction *aRevealToAll;
|
||||
QAction *aHide;
|
||||
QAction *aClone;
|
||||
QAction *aSelectAll, *aSelectRow, *aSelectColumn;
|
||||
QAction *aSelectAll, *aSelectRow, *aSelectColumn, *aSelectAllMatching;
|
||||
QAction *aDrawArrow;
|
||||
QAction *aTap, *aDoesntUntap;
|
||||
QAction *aFlip, *aPeek;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "../board/card_item.h"
|
||||
#include "../dialogs/dlg_move_top_cards_until.h"
|
||||
#include "../dialogs/dlg_roll_dice.h"
|
||||
#include "../dialogs/dlg_select_all_matching.h"
|
||||
#include "../zones/hand_zone.h"
|
||||
#include "../zones/logic/view_zone_logic.h"
|
||||
#include "../zones/table_zone.h"
|
||||
|
|
@ -696,10 +697,12 @@ void PlayerActions::actMoveBottomCardToTop()
|
|||
*
|
||||
* @param zone The zone to select from
|
||||
* @param filter A predicate to filter which cards are selected. Defaults to always returning true.
|
||||
* @param toggleSelected If true, toggles the selection state if card is already selected
|
||||
*/
|
||||
static void selectCardsInZone(
|
||||
const CardZoneLogic *zone,
|
||||
std::function<bool(const CardItem *)> filter = [](const CardItem *) { return true; })
|
||||
std::function<bool(const CardItem *)> filter = [](const CardItem *) { return true; },
|
||||
bool toggleSelected = false)
|
||||
{
|
||||
if (!zone) {
|
||||
return;
|
||||
|
|
@ -707,7 +710,11 @@ static void selectCardsInZone(
|
|||
|
||||
for (auto &cardItem : zone->getCards()) {
|
||||
if (cardItem && filter(cardItem)) {
|
||||
cardItem->setSelected(true);
|
||||
if (toggleSelected) {
|
||||
cardItem->setSelected(!cardItem->isSelected());
|
||||
} else {
|
||||
cardItem->setSelected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -746,6 +753,33 @@ void PlayerActions::actSelectColumn()
|
|||
selectCardsInZone(card->getZone(), isSameColumn);
|
||||
}
|
||||
|
||||
void PlayerActions::actSelectAllMatching()
|
||||
{
|
||||
const CardItem *card = player->getGame()->getActiveCard();
|
||||
if (!card) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto dlg = DlgSelectAllMatching(player->getGame()->getTab(), lastSelectAllMatchingOptions);
|
||||
if (!dlg.exec()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString expr = dlg.getExpr();
|
||||
lastSelectAllMatchingOptions = dlg.getOptions();
|
||||
|
||||
if (lastSelectAllMatchingOptions.clearSelection) {
|
||||
player->getGameScene()->clearSelection();
|
||||
}
|
||||
|
||||
auto filterString = FilterString(expr);
|
||||
auto matches = [filterString](const CardItem *cardItem) {
|
||||
return filterString.check(cardItem->getCard().getCardPtr());
|
||||
};
|
||||
|
||||
selectCardsInZone(card->getZone(), matches, lastSelectAllMatchingOptions.toggleSelected);
|
||||
}
|
||||
|
||||
void PlayerActions::actDrawBottomCard()
|
||||
{
|
||||
if (player->getDeckZone()->getCards().empty()) {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#define COCKATRICE_PLAYER_ACTIONS_H
|
||||
#include "../dialogs/dlg_create_token.h"
|
||||
#include "../dialogs/dlg_move_top_cards_until.h"
|
||||
#include "../dialogs/dlg_select_all_matching.h"
|
||||
#include "event_processing_options.h"
|
||||
#include "player.h"
|
||||
|
||||
|
|
@ -119,6 +120,7 @@ public slots:
|
|||
void actSelectAll();
|
||||
void actSelectRow();
|
||||
void actSelectColumn();
|
||||
void actSelectAllMatching();
|
||||
|
||||
void actViewLibrary();
|
||||
void actViewHand();
|
||||
|
|
@ -183,6 +185,8 @@ private:
|
|||
int movingCardsUntilCounter = 0;
|
||||
MoveTopCardsUntilOptions movingCardsUntilOptions;
|
||||
|
||||
SelectAllMatchingOptions lastSelectAllMatchingOptions;
|
||||
|
||||
void moveTopCardsTo(const QString &targetZone, const QString &zoneDisplayName, bool faceDown);
|
||||
void moveBottomCardsTo(const QString &targetZone, const QString &zoneDisplayName, bool faceDown);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user