Add a printings tab to the token dialog

The token list and the printing selector now share one tabbed surface. Picking a printing sets the provider id used by the live preview and by the created token, while an untouched dialog keeps the existing preference lookup. Names with no printings show a placeholder instead of an empty grid.
This commit is contained in:
Lukas Brübach 2026-11-09 11:15:11 +01:00
parent 0014bb4b44
commit f372fdda42
2 changed files with 84 additions and 7 deletions

View file

@ -1,8 +1,10 @@
#include "dlg_create_token.h"
#include "../../client/settings/cache_settings.h"
#include "../../interface/widgets/printing_selector/printing_selector.h"
#include "libcockatrice/card/card_info.h"
#include "libcockatrice/card/database/card_database_querier.h"
#include "libcockatrice/card/printing/exact_card.h"
#include "token_preview_widget.h"
#include <QByteArray>
@ -21,10 +23,12 @@
#include <QRadioButton>
#include <QSet>
#include <QSignalBlocker>
#include <QTabWidget>
#include <QTimer>
#include <QTreeView>
#include <QVBoxLayout>
#include <QVariant>
#include <QWidget>
#include <libcockatrice/card/card_localization.h>
#include <libcockatrice/card/database/card_database_manager.h>
#include <libcockatrice/models/database/card_database_model.h>
@ -150,18 +154,37 @@ DlgCreateToken::DlgCreateToken(const QStringList &_predefinedTokens, QWidget *pa
cardDatabaseDisplayModel->setCardNameSet(QSet<QString>(predefinedTokens.begin(), predefinedTokens.end()));
}
auto *tokenChooseLayout = new QVBoxLayout;
auto *tokenChoosePage = new QWidget;
tokenChoosePage->setObjectName("tokenChoosePage");
auto *tokenChooseLayout = new QVBoxLayout(tokenChoosePage);
tokenChooseLayout->setContentsMargins(0, 0, 0, 0);
tokenChooseLayout->addWidget(chooseTokenFromAllRadioButton);
tokenChooseLayout->addWidget(chooseTokenFromDeckRadioButton);
tokenChooseLayout->addWidget(chooseTokenView);
auto *tokenChooseGroupBox = new QGroupBox(tr("Choose token from list"));
tokenChooseGroupBox->setLayout(tokenChooseLayout);
auto *printingsPage = new QWidget;
printingsPage->setObjectName("tokenPrintingsPage");
auto *printingsLayout = new QVBoxLayout(printingsPage);
printingsLayout->setContentsMargins(0, 0, 0, 0);
printingSelector = new PrintingSelector(printingsPage, &printingSelectorHost);
printingSelector->setObjectName("tokenPrintingSelector");
printingsLayout->addWidget(printingSelector);
connect(printingSelector, &PrintingSelector::printingSelected, this, [this](const ExactCard &card) {
explicitProviderId = card.getPrinting().getUuid();
explicitProviderName = card.getName();
updatePreview();
});
tokenSourceTabs = new QTabWidget;
tokenSourceTabs->setObjectName("tokenSourceTabs");
tokenSourceTabs->addTab(tokenChoosePage, tr("&Tokens"));
tokenSourceTabs->addTab(printingsPage, tr("&Printings"));
auto *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->addWidget(tokenSourceTabs, 0, 1, 2, 1);
hbox->setColumnStretch(1, 1);
auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
@ -175,13 +198,15 @@ DlgCreateToken::DlgCreateToken(const QStringList &_predefinedTokens, QWidget *pa
setWindowTitle(tr("Create token"));
connect(nameEdit, &QLineEdit::textChanged, this, &DlgCreateToken::syncPrintingsToToken);
connect(nameEdit, &QLineEdit::textChanged, this, &DlgCreateToken::updatePreview);
connect(colorEdit, qOverload<int>(&QComboBox::currentIndexChanged), this, &DlgCreateToken::updatePreview);
connect(ptEdit, &QLineEdit::textChanged, this, &DlgCreateToken::updatePreview);
connect(annotationEdit, &QLineEdit::textChanged, this, &DlgCreateToken::updatePreview);
syncPrintingsToToken();
updatePreview();
resize(600, 500);
resize(900, 650);
restoreGeometry(SettingsCache::instance().layouts().getTokenDialogGeometry());
}
@ -228,9 +253,40 @@ void DlgCreateToken::tokenSelectionChanged(const QModelIndex &current, const QMo
// Filtering, changing the deck/all scope, or reloading the database can
// invalidate the current row. None of these actions discard the token draft.
syncPrintingsToToken();
updatePreview();
}
void DlgCreateToken::syncPrintingsToToken()
{
const CardInfoPtr cardInfo = CardDatabaseManager::query()->lookupCardByName(nameEdit->text());
if (!cardInfo) {
explicitProviderId.clear();
explicitProviderName.clear();
} else if (!explicitProviderId.isEmpty() && explicitProviderName != cardInfo->getName()) {
// A pick belongs to the token name it was made for.
explicitProviderId.clear();
explicitProviderName.clear();
}
if (!cardInfo || cardInfo->getSets().empty()) {
printingSelector->setCard(nullptr);
printingSelector->setSelectedProviderId(QString());
printingSelector->setPlaceholderText(tr("This token has no available printings."));
return;
}
printingSelector->setPlaceholderText(QString());
printingSelector->setCard(cardInfo);
const QString providerId =
explicitProviderId.isEmpty()
? SettingsCache::instance().cardOverrides().getCardPreferenceOverride(cardInfo->getName())
: explicitProviderId;
printingSelector->setSelectedProviderId(providerId);
}
void DlgCreateToken::updateSearchFieldWithoutUpdatingFilter(const QString &newValue) const
{
const QSignalBlocker blocker(nameEdit);
@ -275,14 +331,25 @@ void DlgCreateToken::actReject()
TokenInfo DlgCreateToken::tokenDraft() const
{
// Keep an explicit pick only while it still belongs to the current token.
QString providerId = explicitProviderId;
if (!providerId.isEmpty()) {
const CardInfoPtr pickedCard = CardDatabaseManager::query()->lookupCardByName(nameEdit->text());
if (!pickedCard || pickedCard->getName() != explicitProviderName) {
providerId.clear();
}
}
if (providerId.isEmpty()) {
providerId = SettingsCache::instance().cardOverrides().getCardPreferenceOverride(nameEdit->text());
}
TokenInfo token = {.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())};
.providerId = providerId};
// Match the normalization applied when the player creates the token, so
// manually typed aliases and the default P/T preview the actual result.

View file

@ -7,6 +7,8 @@
#ifndef DLG_CREATETOKEN_H
#define DLG_CREATETOKEN_H
#include "../../interface/widgets/printing_selector/printing_selector_selection_host.h"
#include <QDialog>
#include <QList>
#include <QString>
@ -19,10 +21,12 @@ class QLineEdit;
class QComboBox;
class QCheckBox;
class QRadioButton;
class QTabWidget;
class QTreeView;
class CardDatabaseModel;
class TokenDisplayModel;
class TokenPreviewWidget;
class PrintingSelector;
class QModelIndex;
class QWidget;
@ -39,6 +43,7 @@ private slots:
void faceDownCheckBoxToggled(bool checked);
void tokenSelectionChanged(const QModelIndex &current, const QModelIndex &previous);
void updateSearch(const QString &search);
void syncPrintingsToToken();
void updatePreview();
void actChooseTokenFromAll(bool checked);
void actChooseTokenFromDeck(bool checked);
@ -57,6 +62,11 @@ private:
QRadioButton *chooseTokenFromAllRadioButton, *chooseTokenFromDeckRadioButton;
TokenPreviewWidget *pic;
QTreeView *chooseTokenView;
QTabWidget *tokenSourceTabs;
PrintingSelector *printingSelector;
PrintingSelectorSelectionHost printingSelectorHost;
QString explicitProviderId;
QString explicitProviderName;
[[nodiscard]] TokenInfo tokenDraft() const;
void updateSearchFieldWithoutUpdatingFilter(const QString &newValue) const;