[DeckEditor] Replace mainboard/sideboard with tokensboard for tokens (#6971)

* [DeckEditor] Replace mainboard/sideboard with tokensboard for token cards (#6546)

* [PrintingSelector] Replace std::tuple with ZoneCounts struct for readability (#6546)
This commit is contained in:
kongwu 2026-06-10 11:46:43 +08:00 committed by GitHub
parent da4ba222c0
commit f72c82d0f9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 115 additions and 29 deletions

View file

@ -255,6 +255,10 @@ bool DeckStateManager::swapCardAtIndex(const QModelIndex &idx)
} }
QString zoneName = gparent.siblingAtColumn(DeckListModelColumns::CARD_NAME).data(Qt::EditRole).toString(); QString zoneName = gparent.siblingAtColumn(DeckListModelColumns::CARD_NAME).data(Qt::EditRole).toString();
// tokens have no swap target
if (zoneName == DECK_ZONE_TOKENS) {
return false;
}
QString otherZoneName = zoneName == DECK_ZONE_MAIN ? DECK_ZONE_SIDE : DECK_ZONE_MAIN; QString otherZoneName = zoneName == DECK_ZONE_MAIN ? DECK_ZONE_SIDE : DECK_ZONE_MAIN;
QString reason = tr("Moved to %1 1 × \"%2\" (%3)") // QString reason = tr("Moved to %1 1 × \"%2\" (%3)") //

View file

@ -8,7 +8,7 @@
* @brief Constructor for the AllZonesCardAmountWidget class. * @brief Constructor for the AllZonesCardAmountWidget class.
* *
* Initializes the widget with its layout and sets up the connections and necessary * Initializes the widget with its layout and sets up the connections and necessary
* UI elements for managing card counts in both the mainboard and sideboard zones. * UI elements for managing card counts in all the mainboard, tokensboard and sideboard zones.
* *
* @param parent The parent widget. * @param parent The parent widget.
* @param deckStateManager Pointer to the DeckStateManager * @param deckStateManager Pointer to the DeckStateManager
@ -31,13 +31,28 @@ AllZonesCardAmountWidget::AllZonesCardAmountWidget(QWidget *parent,
buttonBoxMainboard = new CardAmountWidget(this, deckStateManager, cardSizeSlider, rootCard, DECK_ZONE_MAIN); buttonBoxMainboard = new CardAmountWidget(this, deckStateManager, cardSizeSlider, rootCard, DECK_ZONE_MAIN);
zoneLabelSideboard = new ShadowBackgroundLabel(this, tr("Sideboard")); zoneLabelSideboard = new ShadowBackgroundLabel(this, tr("Sideboard"));
buttonBoxSideboard = new CardAmountWidget(this, deckStateManager, cardSizeSlider, rootCard, DECK_ZONE_SIDE); buttonBoxSideboard = new CardAmountWidget(this, deckStateManager, cardSizeSlider, rootCard, DECK_ZONE_SIDE);
zoneLabelTokensboard = new ShadowBackgroundLabel(this, tr("Tokens"));
buttonBoxTokensboard = new CardAmountWidget(this, deckStateManager, cardSizeSlider, rootCard, DECK_ZONE_TOKENS);
layout->addWidget(zoneLabelMainboard, 0, Qt::AlignHCenter | Qt::AlignBottom); layout->addWidget(zoneLabelMainboard, 0, Qt::AlignHCenter | Qt::AlignBottom);
layout->addWidget(buttonBoxMainboard, 0, Qt::AlignHCenter | Qt::AlignTop); layout->addWidget(buttonBoxMainboard, 0, Qt::AlignHCenter | Qt::AlignTop);
layout->addSpacing(25); layout->addSpacing(12);
layout->addWidget(zoneLabelTokensboard, 0, Qt::AlignHCenter | Qt::AlignBottom);
layout->addWidget(buttonBoxTokensboard, 0, Qt::AlignHCenter | Qt::AlignTop);
layout->addSpacing(13);
layout->addWidget(zoneLabelSideboard, 0, Qt::AlignHCenter | Qt::AlignBottom); layout->addWidget(zoneLabelSideboard, 0, Qt::AlignHCenter | Qt::AlignBottom);
layout->addWidget(buttonBoxSideboard, 0, Qt::AlignHCenter | Qt::AlignTop); layout->addWidget(buttonBoxSideboard, 0, Qt::AlignHCenter | Qt::AlignTop);
// Show Tokens buttons for token cards, Mainboard/Sideboard for non-token cards
bool isToken = rootCard.getInfo().getIsToken();
zoneLabelMainboard->setVisible(!isToken);
buttonBoxMainboard->setVisible(!isToken);
zoneLabelTokensboard->setVisible(isToken);
buttonBoxTokensboard->setVisible(isToken);
zoneLabelSideboard->setVisible(!isToken);
buttonBoxSideboard->setVisible(!isToken);
connect(cardSizeSlider, &QSlider::valueChanged, this, &AllZonesCardAmountWidget::adjustFontSize); connect(cardSizeSlider, &QSlider::valueChanged, this, &AllZonesCardAmountWidget::adjustFontSize);
QTimer::singleShot(10, this, [this]() { adjustFontSize(this->cardSizeSlider->value()); }); QTimer::singleShot(10, this, [this]() { adjustFontSize(this->cardSizeSlider->value()); });
@ -67,15 +82,17 @@ void AllZonesCardAmountWidget::adjustFontSize(int scalePercentage)
zoneLabelFont.setPointSize(newFontSize); zoneLabelFont.setPointSize(newFontSize);
zoneLabelMainboard->setFont(zoneLabelFont); zoneLabelMainboard->setFont(zoneLabelFont);
zoneLabelSideboard->setFont(zoneLabelFont); zoneLabelSideboard->setFont(zoneLabelFont);
zoneLabelTokensboard->setFont(zoneLabelFont);
// Repaint the widget (if necessary) // Repaint the widget (if necessary)
repaint(); repaint();
} }
void AllZonesCardAmountWidget::setAmounts(int mainboardAmount, int sideboardAmount) void AllZonesCardAmountWidget::setAmounts(int mainboardAmount, int sideboardAmount, int tokensboardAmount)
{ {
buttonBoxMainboard->setAmount(mainboardAmount); buttonBoxMainboard->setAmount(mainboardAmount);
buttonBoxSideboard->setAmount(sideboardAmount); buttonBoxSideboard->setAmount(sideboardAmount);
buttonBoxTokensboard->setAmount(tokensboardAmount);
} }
/** /**
@ -99,11 +116,21 @@ int AllZonesCardAmountWidget::getSideboardAmount()
} }
/** /**
* @brief Checks if the amount is at least one in either the mainboard or sideboard. * @brief Gets the card count in the tokensboard zone.
*
* @return The number of cards in the tokensboard.
*/
int AllZonesCardAmountWidget::getTokensboardAmount()
{
return buttonBoxTokensboard->getAmount();
}
/**
* @brief Checks if the amount is at least one in either the mainboard or sideboard or tokensboard.
*/ */
bool AllZonesCardAmountWidget::isNonZero() bool AllZonesCardAmountWidget::isNonZero()
{ {
return getMainboardAmount() > 0 || getSideboardAmount() > 0; return getMainboardAmount() > 0 || getSideboardAmount() > 0 || getTokensboardAmount() > 0;
} }
/** /**

View file

@ -23,6 +23,7 @@ public:
const ExactCard &rootCard); const ExactCard &rootCard);
int getMainboardAmount(); int getMainboardAmount();
int getSideboardAmount(); int getSideboardAmount();
int getTokensboardAmount();
bool isNonZero(); bool isNonZero();
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
@ -33,7 +34,7 @@ public:
public slots: public slots:
void adjustFontSize(int scalePercentage); void adjustFontSize(int scalePercentage);
void setAmounts(int mainboardAmount, int sideboardAmount); void setAmounts(int mainboardAmount, int sideboardAmount, int tokensboardAmount);
private: private:
QVBoxLayout *layout; QVBoxLayout *layout;
@ -42,6 +43,8 @@ private:
CardAmountWidget *buttonBoxMainboard; CardAmountWidget *buttonBoxMainboard;
QLabel *zoneLabelSideboard; QLabel *zoneLabelSideboard;
CardAmountWidget *buttonBoxSideboard; CardAmountWidget *buttonBoxSideboard;
QLabel *zoneLabelTokensboard;
CardAmountWidget *buttonBoxTokensboard;
}; };
#endif // ALL_ZONES_CARD_AMOUNT_WIDGET_H #endif // ALL_ZONES_CARD_AMOUNT_WIDGET_H

View file

@ -11,7 +11,7 @@
* @param parent The parent widget. * @param parent The parent widget.
* @param cardSizeSlider Pointer to the QSlider for adjusting font size. * @param cardSizeSlider Pointer to the QSlider for adjusting font size.
* @param rootCard The root card to manage within the widget. * @param rootCard The root card to manage within the widget.
* @param zoneName The zone name (e.g., DECK_ZONE_MAIN or DECK_ZONE_SIDE). * @param zoneName The zone name (e.g., DECK_ZONE_MAIN , DECK_ZONE_SIDE, or DECK_ZONE_TOKENS).
*/ */
CardAmountWidget::CardAmountWidget(QWidget *parent, CardAmountWidget::CardAmountWidget(QWidget *parent,
DeckStateManager *deckStateManager, DeckStateManager *deckStateManager,
@ -36,13 +36,16 @@ CardAmountWidget::CardAmountWidget(QWidget *parent,
incrementButton->setFixedSize(parentWidget()->size().width() / 3, parentWidget()->size().height() / 9); incrementButton->setFixedSize(parentWidget()->size().width() / 3, parentWidget()->size().height() / 9);
decrementButton->setFixedSize(parentWidget()->size().width() / 3, parentWidget()->size().height() / 9); decrementButton->setFixedSize(parentWidget()->size().width() / 3, parentWidget()->size().height() / 9);
// Set up connections based on the zone (Mainboard or Sideboard) // Set up connections based on the zone (Mainboard, Sideboard, or Tokensboard)
if (zoneName == DECK_ZONE_MAIN) { if (zoneName == DECK_ZONE_MAIN) {
connect(incrementButton, &QPushButton::clicked, this, &CardAmountWidget::addPrintingMainboard); connect(incrementButton, &QPushButton::clicked, this, &CardAmountWidget::addPrintingMainboard);
connect(decrementButton, &QPushButton::clicked, this, &CardAmountWidget::removePrintingMainboard); connect(decrementButton, &QPushButton::clicked, this, &CardAmountWidget::removePrintingMainboard);
} else if (zoneName == DECK_ZONE_SIDE) { } else if (zoneName == DECK_ZONE_SIDE) {
connect(incrementButton, &QPushButton::clicked, this, &CardAmountWidget::addPrintingSideboard); connect(incrementButton, &QPushButton::clicked, this, &CardAmountWidget::addPrintingSideboard);
connect(decrementButton, &QPushButton::clicked, this, &CardAmountWidget::removePrintingSideboard); connect(decrementButton, &QPushButton::clicked, this, &CardAmountWidget::removePrintingSideboard);
} else if (zoneName == DECK_ZONE_TOKENS) {
connect(incrementButton, &QPushButton::clicked, this, &CardAmountWidget::addPrintingTokensboard);
connect(decrementButton, &QPushButton::clicked, this, &CardAmountWidget::removePrintingTokensboard);
} }
cardCountInZone = new QLabel(QString::number(amount), this); cardCountInZone = new QLabel(QString::number(amount), this);
@ -137,6 +140,19 @@ void CardAmountWidget::updateCardCount()
layout->activate(); layout->activate();
} }
static QString zoneLogName(const QString &zone)
{
if (zone == DECK_ZONE_MAIN) {
return "mainboard";
} else if (zone == DECK_ZONE_SIDE) {
return "sideboard";
} else if (zone == DECK_ZONE_TOKENS) {
return "tokens";
} else {
return "unknown";
}
}
static QModelIndex addAndReplacePrintings(DeckListModel *model, static QModelIndex addAndReplacePrintings(DeckListModel *model,
const QModelIndex &existing, const QModelIndex &existing,
const ExactCard &rootCard, const ExactCard &rootCard,
@ -161,9 +177,9 @@ static QModelIndex addAndReplacePrintings(DeckListModel *model,
} }
/** /**
* @brief Adds a printing of the card to the specified zone (Mainboard or Sideboard). * @brief Adds a printing of the card to the specified zone (Mainboard, Sideboard, or Tokensboard).
* *
* @param zone The zone to add the card to (DECK_ZONE_MAIN or DECK_ZONE_SIDE). * @param zone The zone to add the card to (DECK_ZONE_MAIN, DECK_ZONE_SIDE, or DECK_ZONE_TOKENS).
*/ */
void CardAmountWidget::addPrinting(const QString &zone) void CardAmountWidget::addPrinting(const QString &zone)
{ {
@ -183,12 +199,13 @@ void CardAmountWidget::addPrinting(const QString &zone)
} }
} }
QString zoneName = zoneLogName(zone);
QString reason = QString("Added %1 copies of '%2 (%3) %4' to %5 [ProviderID: %6]%7") QString reason = QString("Added %1 copies of '%2 (%3) %4' to %5 [ProviderID: %6]%7")
.arg(1 + extraCopies) .arg(1 + extraCopies)
.arg(rootCard.getName()) .arg(rootCard.getName())
.arg(rootCard.getPrinting().getSet()->getShortName()) .arg(rootCard.getPrinting().getSet()->getShortName())
.arg(rootCard.getPrinting().getProperty("num")) .arg(rootCard.getPrinting().getProperty("num"))
.arg(zone == DECK_ZONE_MAIN ? "mainboard" : "sideboard") .arg(zoneName)
.arg(rootCard.getPrinting().getUuid()) .arg(rootCard.getPrinting().getUuid())
.arg(replacingProviderless ? " (replaced providerless printings)" : ""); .arg(replacingProviderless ? " (replaced providerless printings)" : "");
@ -218,6 +235,14 @@ void CardAmountWidget::addPrintingSideboard()
addPrinting(DECK_ZONE_SIDE); addPrinting(DECK_ZONE_SIDE);
} }
/**
* @brief Adds a printing to the tokens zone.
*/
void CardAmountWidget::addPrintingTokensboard()
{
addPrinting(DECK_ZONE_TOKENS);
}
/** /**
* @brief Removes a printing from the mainboard zone. * @brief Removes a printing from the mainboard zone.
*/ */
@ -234,18 +259,27 @@ void CardAmountWidget::removePrintingSideboard()
decrementCardHelper(DECK_ZONE_SIDE); decrementCardHelper(DECK_ZONE_SIDE);
} }
/**
* @brief Removes a printing from the tokens zone.
*/
void CardAmountWidget::removePrintingTokensboard()
{
decrementCardHelper(DECK_ZONE_TOKENS);
}
/** /**
* @brief Helper function to decrement the card count for a given zone. * @brief Helper function to decrement the card count for a given zone.
* *
* @param zone The zone from which to remove the card (DECK_ZONE_MAIN or DECK_ZONE_SIDE). * @param zone The zone from which to remove the card (DECK_ZONE_MAIN, DECK_ZONE_SIDE, or DECK_ZONE_TOKENS).
*/ */
void CardAmountWidget::decrementCardHelper(const QString &zone) void CardAmountWidget::decrementCardHelper(const QString &zone)
{ {
QString zoneName = zoneLogName(zone);
QString reason = QString("Removed 1 copy of '%1 (%2) %3' from %4 [ProviderID: %5]") QString reason = QString("Removed 1 copy of '%1 (%2) %3' from %4 [ProviderID: %5]")
.arg(rootCard.getName()) .arg(rootCard.getName())
.arg(rootCard.getPrinting().getSet()->getShortName()) .arg(rootCard.getPrinting().getSet()->getShortName())
.arg(rootCard.getPrinting().getProperty("num")) .arg(rootCard.getPrinting().getProperty("num"))
.arg(zone == DECK_ZONE_MAIN ? "mainboard" : "sideboard") .arg(zoneName)
.arg(rootCard.getPrinting().getUuid()); .arg(rootCard.getPrinting().getUuid());
deckStateManager->modifyDeck(reason, [this, &zone](auto model) { deckStateManager->modifyDeck(reason, [this, &zone](auto model) {

View file

@ -60,8 +60,10 @@ private:
private slots: private slots:
void addPrintingMainboard(); void addPrintingMainboard();
void addPrintingSideboard(); void addPrintingSideboard();
void addPrintingTokensboard();
void removePrintingMainboard(); void removePrintingMainboard();
void removePrintingSideboard(); void removePrintingSideboard();
void removePrintingTokensboard();
void adjustFontSize(int scalePercentage); void adjustFontSize(int scalePercentage);
}; };

View file

@ -105,23 +105,30 @@ void PrintingSelector::printingsInDeckChanged()
} }
/** /**
* @return A map of uuid to amounts (main, side). * @return A map of uuid to amounts (main, side, tokens).
*/ */
static QMap<QString, QPair<int, int>> tallyUuidCounts(const DeckListModel *model, const QString &cardName) static QMap<QString, ZoneCounts> tallyUuidCounts(const DeckListModel *model, const QString &cardName)
{ {
QMap<QString, QPair<int, int>> map; QMap<QString, ZoneCounts> map;
auto mainNodes = model->getCardNodesForZone(DECK_ZONE_MAIN); auto mainNodes = model->getCardNodesForZone(DECK_ZONE_MAIN);
for (auto &node : mainNodes) { for (auto &node : mainNodes) {
if (node->getName() == cardName) { if (node->getName() == cardName) {
map[node->getCardProviderId()].first += node->getNumber(); map[node->getCardProviderId()].mainboard += node->getNumber();
} }
} }
auto sideNodes = model->getCardNodesForZone(DECK_ZONE_SIDE); auto sideNodes = model->getCardNodesForZone(DECK_ZONE_SIDE);
for (auto &node : sideNodes) { for (auto &node : sideNodes) {
if (node->getName() == cardName) { if (node->getName() == cardName) {
map[node->getCardProviderId()].second += node->getNumber(); map[node->getCardProviderId()].sideboard += node->getNumber();
}
}
auto tokensNodes = model->getCardNodesForZone(DECK_ZONE_TOKENS);
for (auto &node : tokensNodes) {
if (node->getName() == cardName) {
map[node->getCardProviderId()].tokensboard += node->getNumber();
} }
} }

View file

@ -22,6 +22,13 @@
#define BATCH_SIZE 10 #define BATCH_SIZE 10
struct ZoneCounts
{
int mainboard = 0;
int sideboard = 0;
int tokensboard = 0;
};
class DeckStateManager; class DeckStateManager;
class PrintingSelectorCardSearchWidget; class PrintingSelectorCardSearchWidget;
class PrintingSelectorCardSelectionWidget; class PrintingSelectorCardSelectionWidget;
@ -59,9 +66,9 @@ signals:
/** /**
* The amounts of the printings in the deck has changed * The amounts of the printings in the deck has changed
* @param uuidToAmounts Map of uuids to the amounts (maindeck, sideboard) in the deck * @param uuidToAmounts Map of uuids to the amounts (maindeck, sideboard, tokensboard) in the deck
*/ */
void cardAmountsChanged(const QMap<QString, QPair<int, int>> &uuidToAmounts); void cardAmountsChanged(const QMap<QString, ZoneCounts> &uuidToAmounts);
private: private:
QVBoxLayout *layout; QVBoxLayout *layout;

View file

@ -67,10 +67,10 @@ void PrintingSelectorCardDisplayWidget::clampSetNameToPicture()
update(); update();
} }
void PrintingSelectorCardDisplayWidget::updateCardAmounts(const QMap<QString, QPair<int, int>> &uuidToAmounts) void PrintingSelectorCardDisplayWidget::updateCardAmounts(const QMap<QString, ZoneCounts> &uuidToAmounts)
{ {
auto [main, side] = uuidToAmounts.value(rootCard.getPrinting().getUuid()); auto counts = uuidToAmounts.value(rootCard.getPrinting().getUuid());
overlayWidget->updateCardAmounts(main, side); overlayWidget->updateCardAmounts(counts.mainboard, counts.sideboard, counts.tokensboard);
} }
void PrintingSelectorCardDisplayWidget::resizeEvent(QResizeEvent *event) void PrintingSelectorCardDisplayWidget::resizeEvent(QResizeEvent *event)

View file

@ -27,7 +27,7 @@ public:
public slots: public slots:
void clampSetNameToPicture(); void clampSetNameToPicture();
void updateCardAmounts(const QMap<QString, QPair<int, int>> &uuidToAmounts); void updateCardAmounts(const QMap<QString, ZoneCounts> &uuidToAmounts);
void resizeEvent(QResizeEvent *event) override; void resizeEvent(QResizeEvent *event) override;

View file

@ -116,9 +116,11 @@ void PrintingSelectorCardOverlayWidget::enterEvent(QEvent *event)
updateVisibility(); updateVisibility();
} }
void PrintingSelectorCardOverlayWidget::updateCardAmounts(int mainboardAmount, int sideboardAmount) void PrintingSelectorCardOverlayWidget::updateCardAmounts(int mainboardAmount,
int sideboardAmount,
int tokensboardAmount)
{ {
allZonesCardAmountWidget->setAmounts(mainboardAmount, sideboardAmount); allZonesCardAmountWidget->setAmounts(mainboardAmount, sideboardAmount, tokensboardAmount);
updateVisibility(); updateVisibility();
} }
@ -173,8 +175,8 @@ void PrintingSelectorCardOverlayWidget::updatePinBadgeVisibility()
/** /**
* @brief Handles the mouse leave event when the cursor leaves the overlay widget area. * @brief Handles the mouse leave event when the cursor leaves the overlay widget area.
* *
* When the cursor leaves the widget, the card amount widget is hidden if both the mainboard and sideboard * When the cursor leaves the widget, the card amount widget is hidden if all of the mainboard, sideboard, and
* amounts are zero. * tokensboard amounts are zero.
* *
* @param event The event triggered when the mouse leaves the widget. * @param event The event triggered when the mouse leaves the widget.
*/ */

View file

@ -39,7 +39,7 @@ signals:
void cardPreferenceChanged(); void cardPreferenceChanged();
public slots: public slots:
void updateCardAmounts(int mainboardAmount, int sideboardAmount); void updateCardAmounts(int mainboardAmount, int sideboardAmount, int tokensboardAmount);
private slots: private slots:
void updateVisibility(); void updateVisibility();