Merge branch 'master' into ci/use-ninja-win-clean

This commit is contained in:
Bruno Alexandre Rosa 2026-03-23 18:32:00 -03:00
commit c477733c9e
10 changed files with 218 additions and 211 deletions

View file

@ -48,7 +48,7 @@ jobs:
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
if: github.ref_type == 'tag' if: github.ref_type == 'tag'
uses: docker/login-action@v3 uses: docker/login-action@v4
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}

View file

@ -513,6 +513,9 @@ private:
{"Player/aPlay", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Play Card"), {"Player/aPlay", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Play Card"),
parseSequenceString(""), parseSequenceString(""),
ShortcutGroup::Playing_Area)}, ShortcutGroup::Playing_Area)},
{"Player/aPlayFacedown", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Play Card, Face Down"),
parseSequenceString(""),
ShortcutGroup::Playing_Area)},
{"Player/aAttach", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Attach Card..."), {"Player/aAttach", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Attach Card..."),
parseSequenceString("Ctrl+Alt+A"), parseSequenceString("Ctrl+Alt+A"),
ShortcutGroup::Playing_Area)}, ShortcutGroup::Playing_Area)},
@ -560,12 +563,6 @@ private:
{"Player/aMoveToTopLibrary", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Top of Library"), {"Player/aMoveToTopLibrary", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Top of Library"),
parseSequenceString(""), parseSequenceString(""),
ShortcutGroup::Move_selected)}, ShortcutGroup::Move_selected)},
{"Player/aPlayFacedown", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Battlefield, Face Down"),
parseSequenceString(""),
ShortcutGroup::Move_selected)},
{"Player/aPlay", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Battlefield"),
parseSequenceString(""),
ShortcutGroup::Move_selected)},
{"Player/aViewHand", {"Player/aViewHand",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Hand"), parseSequenceString(""), ShortcutGroup::View)}, ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Hand"), parseSequenceString(""), ShortcutGroup::View)},
{"Player/aViewGraveyard", {"Player/aViewGraveyard",

View file

@ -12,8 +12,7 @@
#include <libcockatrice/card/database/card_database_manager.h> #include <libcockatrice/card/database/card_database_manager.h>
#include <libcockatrice/filters/filter_string.h> #include <libcockatrice/filters/filter_string.h>
DlgMoveTopCardsUntil::DlgMoveTopCardsUntil(QWidget *parent, QStringList exprs, uint _numberOfHits, bool autoPlay) DlgMoveTopCardsUntil::DlgMoveTopCardsUntil(QWidget *parent, const MoveTopCardsUntilOptions &options) : QDialog(parent)
: QDialog(parent)
{ {
exprLabel = new QLabel(tr("Card name (or search expressions):")); exprLabel = new QLabel(tr("Card name (or search expressions):"));
@ -21,13 +20,13 @@ DlgMoveTopCardsUntil::DlgMoveTopCardsUntil(QWidget *parent, QStringList exprs, u
exprComboBox->setFocus(); exprComboBox->setFocus();
exprComboBox->setEditable(true); exprComboBox->setEditable(true);
exprComboBox->setInsertPolicy(QComboBox::InsertAtTop); exprComboBox->setInsertPolicy(QComboBox::InsertAtTop);
exprComboBox->insertItems(0, exprs); exprComboBox->insertItems(0, options.exprs);
exprLabel->setBuddy(exprComboBox); exprLabel->setBuddy(exprComboBox);
numberOfHitsLabel = new QLabel(tr("Number of hits:")); numberOfHitsLabel = new QLabel(tr("Number of hits:"));
numberOfHitsEdit = new QSpinBox(this); numberOfHitsEdit = new QSpinBox(this);
numberOfHitsEdit->setRange(1, 99); numberOfHitsEdit->setRange(1, 99);
numberOfHitsEdit->setValue(_numberOfHits); numberOfHitsEdit->setValue(options.numberOfHits);
numberOfHitsLabel->setBuddy(numberOfHitsEdit); numberOfHitsLabel->setBuddy(numberOfHitsEdit);
auto *grid = new QGridLayout; auto *grid = new QGridLayout;
@ -35,7 +34,7 @@ DlgMoveTopCardsUntil::DlgMoveTopCardsUntil(QWidget *parent, QStringList exprs, u
grid->addWidget(numberOfHitsEdit, 0, 1); grid->addWidget(numberOfHitsEdit, 0, 1);
autoPlayCheckBox = new QCheckBox(tr("Auto play hits")); autoPlayCheckBox = new QCheckBox(tr("Auto play hits"));
autoPlayCheckBox->setChecked(autoPlay); autoPlayCheckBox->setChecked(options.autoPlay);
buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::accepted, this, &DlgMoveTopCardsUntil::validateAndAccept); connect(buttonBox, &QDialogButtonBox::accepted, this, &DlgMoveTopCardsUntil::validateAndAccept);
@ -118,6 +117,13 @@ QString DlgMoveTopCardsUntil::getExpr() const
return exprComboBox->currentText(); return exprComboBox->currentText();
} }
MoveTopCardsUntilOptions DlgMoveTopCardsUntil::getOptions() const
{
return {.exprs = getExprs(),
.numberOfHits = numberOfHitsEdit->text().toInt(),
.autoPlay = autoPlayCheckBox->isChecked()};
}
QStringList DlgMoveTopCardsUntil::getExprs() const QStringList DlgMoveTopCardsUntil::getExprs() const
{ {
QStringList exprs; QStringList exprs;
@ -126,13 +132,3 @@ QStringList DlgMoveTopCardsUntil::getExprs() const
} }
return exprs; return exprs;
} }
uint DlgMoveTopCardsUntil::getNumberOfHits() const
{
return numberOfHitsEdit->text().toUInt();
}
bool DlgMoveTopCardsUntil::isAutoPlay() const
{
return autoPlayCheckBox->isChecked();
}

View file

@ -16,6 +16,13 @@
class FilterString; class FilterString;
struct MoveTopCardsUntilOptions
{
QStringList exprs = {};
int numberOfHits = 1;
bool autoPlay = false;
};
class DlgMoveTopCardsUntil : public QDialog class DlgMoveTopCardsUntil : public QDialog
{ {
Q_OBJECT Q_OBJECT
@ -29,15 +36,12 @@ class DlgMoveTopCardsUntil : public QDialog
void validateAndAccept(); void validateAndAccept();
bool validateMatchExists(const FilterString &filterString); bool validateMatchExists(const FilterString &filterString);
public:
explicit DlgMoveTopCardsUntil(QWidget *parent = nullptr,
QStringList exprs = QStringList(),
uint numberOfHits = 1,
bool autoPlay = false);
[[nodiscard]] QString getExpr() const;
[[nodiscard]] QStringList getExprs() const; [[nodiscard]] QStringList getExprs() const;
[[nodiscard]] uint getNumberOfHits() const;
[[nodiscard]] bool isAutoPlay() const; public:
explicit DlgMoveTopCardsUntil(QWidget *parent = nullptr, const MoveTopCardsUntilOptions &options = {});
[[nodiscard]] QString getExpr() const;
[[nodiscard]] MoveTopCardsUntilOptions getOptions() const;
}; };
#endif // DLG_MOVE_TOP_CARDS_UNTIL_H #endif // DLG_MOVE_TOP_CARDS_UNTIL_H

View file

@ -485,22 +485,19 @@ void PlayerActions::actMoveTopCardsUntil()
{ {
stopMoveTopCardsUntil(); stopMoveTopCardsUntil();
DlgMoveTopCardsUntil dlg(player->getGame()->getTab(), movingCardsUntilExprs, movingCardsUntilNumberOfHits, DlgMoveTopCardsUntil dlg(player->getGame()->getTab(), movingCardsUntilOptions);
movingCardsUntilAutoPlay);
if (!dlg.exec()) { if (!dlg.exec()) {
return; return;
} }
auto expr = dlg.getExpr(); auto expr = dlg.getExpr();
movingCardsUntilExprs = dlg.getExprs(); movingCardsUntilOptions = dlg.getOptions();
movingCardsUntilNumberOfHits = dlg.getNumberOfHits();
movingCardsUntilAutoPlay = dlg.isAutoPlay();
if (player->getDeckZone()->getCards().empty()) { if (player->getDeckZone()->getCards().empty()) {
stopMoveTopCardsUntil(); stopMoveTopCardsUntil();
} else { } else {
movingCardsUntilFilter = FilterString(expr); movingCardsUntilFilter = FilterString(expr);
movingCardsUntilCounter = movingCardsUntilNumberOfHits; movingCardsUntilCounter = movingCardsUntilOptions.numberOfHits;
movingCardsUntil = true; movingCardsUntil = true;
actMoveTopCardToPlay(); actMoveTopCardToPlay();
} }
@ -512,7 +509,7 @@ void PlayerActions::moveOneCardUntil(CardItem *card)
const bool isMatch = card && movingCardsUntilFilter.check(card->getCard().getCardPtr()); const bool isMatch = card && movingCardsUntilFilter.check(card->getCard().getCardPtr());
if (isMatch && movingCardsUntilAutoPlay) { if (isMatch && movingCardsUntilOptions.autoPlay) {
// Directly calling playCard will deadlock, since we are already in the middle of processing an event. // Directly calling playCard will deadlock, since we are already in the middle of processing an event.
// Use QTimer::singleShot to queue up the playCard on the event loop. // Use QTimer::singleShot to queue up the playCard on the event loop.
QTimer::singleShot(0, this, [card, this] { playCard(card, false); }); QTimer::singleShot(0, this, [card, this] { playCard(card, false); });

View file

@ -8,6 +8,7 @@
#ifndef COCKATRICE_PLAYER_ACTIONS_H #ifndef COCKATRICE_PLAYER_ACTIONS_H
#define COCKATRICE_PLAYER_ACTIONS_H #define COCKATRICE_PLAYER_ACTIONS_H
#include "../dialogs/dlg_create_token.h" #include "../dialogs/dlg_create_token.h"
#include "../dialogs/dlg_move_top_cards_until.h"
#include "event_processing_options.h" #include "event_processing_options.h"
#include "player.h" #include "player.h"
@ -178,11 +179,9 @@ private:
bool movingCardsUntil; bool movingCardsUntil;
QTimer *moveTopCardTimer; QTimer *moveTopCardTimer;
QStringList movingCardsUntilExprs = {};
int movingCardsUntilNumberOfHits = 1;
bool movingCardsUntilAutoPlay = false;
FilterString movingCardsUntilFilter; FilterString movingCardsUntilFilter;
int movingCardsUntilCounter = 0; int movingCardsUntilCounter = 0;
MoveTopCardsUntilOptions movingCardsUntilOptions;
void moveTopCardsTo(const QString &targetZone, const QString &zoneDisplayName, bool faceDown); void moveTopCardsTo(const QString &targetZone, const QString &zoneDisplayName, bool faceDown);
void moveBottomCardsTo(const QString &targetZone, const QString &zoneDisplayName, bool faceDown); void moveBottomCardsTo(const QString &targetZone, const QString &zoneDisplayName, bool faceDown);

View file

@ -20,6 +20,7 @@ DlgLocalGameOptions::DlgLocalGameOptions(QWidget *parent) : QDialog(parent)
numberPlayersLabel->setBuddy(numberPlayersEdit); numberPlayersLabel->setBuddy(numberPlayersEdit);
auto *generalGrid = new QGridLayout; auto *generalGrid = new QGridLayout;
generalGrid->setContentsMargins(5, 5, 5, 5);
generalGrid->addWidget(numberPlayersLabel, 0, 0); generalGrid->addWidget(numberPlayersLabel, 0, 0);
generalGrid->addWidget(numberPlayersEdit, 0, 1); generalGrid->addWidget(numberPlayersEdit, 0, 1);
generalGroupBox = new QGroupBox(tr("General"), this); generalGroupBox = new QGroupBox(tr("General"), this);
@ -33,6 +34,7 @@ DlgLocalGameOptions::DlgLocalGameOptions(QWidget *parent) : QDialog(parent)
startingLifeTotalLabel->setBuddy(startingLifeTotalEdit); startingLifeTotalLabel->setBuddy(startingLifeTotalEdit);
auto *gameSetupGrid = new QGridLayout; auto *gameSetupGrid = new QGridLayout;
gameSetupGrid->setContentsMargins(5, 5, 5, 5);
gameSetupGrid->addWidget(startingLifeTotalLabel, 0, 0); gameSetupGrid->addWidget(startingLifeTotalLabel, 0, 0);
gameSetupGrid->addWidget(startingLifeTotalEdit, 0, 1); gameSetupGrid->addWidget(startingLifeTotalEdit, 0, 1);
gameSetupOptionsGroupBox = new QGroupBox(tr("Game setup options"), this); gameSetupOptionsGroupBox = new QGroupBox(tr("Game setup options"), this);

File diff suppressed because it is too large Load diff

View file

@ -16,7 +16,7 @@ services:
build: build:
context: . context: .
dockerfile: Dockerfile dockerfile: Dockerfile
image: servatrice image: ghcr.io/cockatrice/servatrice:latest
depends_on: depends_on:
- mysql - mysql
ports: ports:

View file

@ -16,7 +16,7 @@ services:
build: build:
context: . context: .
dockerfile: Dockerfile dockerfile: Dockerfile
image: servatrice image: ghcr.io/cockatrice/servatrice:latest
depends_on: depends_on:
- mysql - mysql
ports: ports: