feat: Configurable colors for card counter (#5882)

* feat: Configurable colors for card counter

This patch adds support for:

 - User-defined colors for card counters;
 - 3 additional types of card counters.

The colors used for counters is stored locally and not shared with other
users. This is intentional as the feature is likely to be used for
improved accessibility.

In order to preserve backwards-compatibility, and because I don't have a
better idea, counters keep their existing color-based names (Red, Green,
Yellow) in menus and in the message log. For consistency, the new
counters also get assigned color-based names (Cyan, Purple, Magenta).

This choice is a compromise, as allowing user-defined names for counters
raises many additional (UI/UX) questions that I don't know how to
answer. A good long-term solution would be to include counter names as
part of a game definition system and hence would be in scope for #1740.

The choice of adding 3 additional types of counters and the Cyan, Purple
and Magenta names are not random. The existing code for determining
counter colors goes: Red, Green, Yellow, Cyan, Purple, Magenta, Black
(unreadable) and thus 6 is the maximum number of counters that existing
versions of Cockatrice are able to support. This way, released clients
get a degraded experience (cannot interact with the new counters,
messages in the server log say "Player X places 1 on Card (now 1)"
without specifying 1 of what), but do see the counters properly.

Fixes #2020

* Do not use %n

* Use SettingsManager

* Use qSin instead of sin

Fix build failures with old GCC.

* Use letters for card counter names

* Place card counter actions in separate menu

* Remove copy-paste error

* include QtMath

* Do not color whole settings page

* derp

---------

Co-authored-by: Zach H <zahalpern+github@gmail.com>
This commit is contained in:
Basile Clement 2025-06-13 04:12:46 +02:00 committed by GitHub
parent 0b34d20716
commit 33946e61bb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 240 additions and 45 deletions

View File

@ -234,6 +234,7 @@ set(cockatrice_SOURCES
src/server/user/user_list_manager.cpp
src/server/user/user_list_widget.cpp
src/settings/cache_settings.cpp
src/settings/card_counter_settings.cpp
src/settings/card_database_settings.cpp
src/settings/card_override_settings.cpp
src/settings/debug_settings.cpp

View File

@ -12,13 +12,17 @@
#include "../game/cards/card_database_manager.h"
#include "../main.h"
#include "../settings/cache_settings.h"
#include "../settings/card_counter_settings.h"
#include "../settings/shortcut_treeview.h"
#include "../utility/sequence_edit.h"
#include <QAbstractButton>
#include <QAbstractListModel>
#include <QAction>
#include <QApplication>
#include <QCheckBox>
#include <QCloseEvent>
#include <QColorDialog>
#include <QComboBox>
#include <QDebug>
#include <QDesktopServices>
@ -42,7 +46,7 @@
#include <QStackedWidget>
#include <QToolBar>
#include <QTranslator>
#include <qabstractbutton.h>
#include <QVariant>
#define WIKI_CUSTOM_PIC_URL "https://github.com/Cockatrice/Cockatrice/wiki/Custom-Picture-Download-URLs"
#define WIKI_CUSTOM_SHORTCUTS "https://github.com/Cockatrice/Cockatrice/wiki/Custom-Keyboard-Shortcuts"
@ -442,6 +446,51 @@ AppearanceSettingsPage::AppearanceSettingsPage()
cardsGroupBox = new QGroupBox;
cardsGroupBox->setLayout(cardsGrid);
// Card counter colors
auto *cardCounterColorsLayout = new QGridLayout;
cardCounterColorsLayout->setColumnStretch(1, 1);
cardCounterColorsLayout->setColumnStretch(3, 1);
cardCounterColorsLayout->setColumnStretch(5, 1);
auto &cardCounterSettings = SettingsCache::instance().cardCounters();
for (int index = 0; index < 6; ++index) {
auto *pushButton = new QPushButton;
pushButton->setStyleSheet(QString("background-color: %1").arg(cardCounterSettings.color(index).name()));
connect(&SettingsCache::instance().cardCounters(), &CardCounterSettings::colorChanged, pushButton,
[index, pushButton](int changedIndex, const QColor &color) {
if (index == changedIndex) {
pushButton->setStyleSheet(QString("background-color: %1").arg(color.name()));
}
});
connect(pushButton, &QPushButton::clicked, this, [index, this]() {
auto &cardCounterSettings = SettingsCache::instance().cardCounters();
auto newColor = QColorDialog::getColor(cardCounterSettings.color(index), this);
if (!newColor.isValid())
return;
cardCounterSettings.setColor(index, newColor);
});
auto *colorName = new QLabel;
cardCounterNames.append(colorName);
int row = index / 3;
int column = 2 * (index % 3);
cardCounterColorsLayout->addWidget(pushButton, row, column);
cardCounterColorsLayout->addWidget(colorName, row, column + 1);
}
auto *cardCountersLayout = new QVBoxLayout;
cardCountersLayout->addLayout(cardCounterColorsLayout, 1);
cardCountersGroupBox = new QGroupBox;
cardCountersGroupBox->setLayout(cardCountersLayout);
// Hand layout
horizontalHandCheckBox.setChecked(settings.getHorizontalHand());
connect(&horizontalHandCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, &SettingsCache::setHorizontalHand);
@ -489,6 +538,7 @@ AppearanceSettingsPage::AppearanceSettingsPage()
mainLayout->addWidget(themeGroupBox);
mainLayout->addWidget(menuGroupBox);
mainLayout->addWidget(cardsGroupBox);
mainLayout->addWidget(cardCountersGroupBox);
mainLayout->addWidget(handGroupBox);
mainLayout->addWidget(tableGroupBox);
mainLayout->addStretch();
@ -577,6 +627,13 @@ void AppearanceSettingsPage::retranslateUi()
cardViewExpandedRowsMaxLabel.setText(tr("Maximum expanded height for card view window:"));
cardViewExpandedRowsMaxBox.setSuffix(tr(" rows"));
cardCountersGroupBox->setTitle(tr("Card counters"));
auto &cardCounterSettings = SettingsCache::instance().cardCounters();
for (int index = 0; index < cardCounterNames.size(); ++index) {
cardCounterNames[index]->setText(tr("Counter %1").arg(cardCounterSettings.displayName(index)));
}
handGroupBox->setTitle(tr("Hand layout"));
horizontalHandCheckBox.setText(tr("Display hand horizontally (wastes space)"));
leftJustifiedHandCheckBox.setText(tr("Enable left justification"));

View File

@ -125,6 +125,8 @@ private:
QGroupBox *cardsGroupBox;
QGroupBox *handGroupBox;
QGroupBox *tableGroupBox;
QGroupBox *cardCountersGroupBox;
QList<QLabel *> cardCounterNames;
QSpinBox minPlayersForMultiColumnLayoutEdit;
QSpinBox maxFontSizeForCardsEdit;

View File

@ -2,6 +2,7 @@
#include "../../client/tabs/tab_game.h"
#include "../../settings/cache_settings.h"
#include "../../settings/card_counter_settings.h"
#include "../cards/card_info.h"
#include "../game_scene.h"
#include "../player/player.h"
@ -32,6 +33,11 @@ CardItem::CardItem(Player *_owner,
ptMenu = new QMenu;
moveMenu = new QMenu;
connect(&SettingsCache::instance().cardCounters(), &CardCounterSettings::colorChanged, this, [this](int counterId) {
if (counters.contains(counterId))
update();
});
retranslateUi();
}
@ -84,6 +90,8 @@ void CardItem::retranslateUi()
void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
auto &cardCounterSettings = SettingsCache::instance().cardCounters();
painter->save();
AbstractCardItem::paint(painter, option, widget);
@ -91,8 +99,7 @@ void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QMapIterator<int, int> counterIterator(counters);
while (counterIterator.hasNext()) {
counterIterator.next();
QColor _color;
_color.setHsv(counterIterator.key() * 60, 150, 255);
QColor _color = cardCounterSettings.color(counterIterator.key());
paintNumberEllipse(counterIterator.value(), 14, _color, i, counters.size(), painter);
++i;

View File

@ -8,6 +8,7 @@
#include "../../dialogs/dlg_roll_dice.h"
#include "../../main.h"
#include "../../settings/cache_settings.h"
#include "../../settings/card_counter_settings.h"
#include "../board/arrow_item.h"
#include "../board/card_item.h"
#include "../board/card_list.h"
@ -419,6 +420,8 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, bool _judge, T
createPredefinedTokenMenu = new QMenu(QString());
createPredefinedTokenMenu->setEnabled(false);
mCardCounters = new QMenu;
playerMenu->addSeparator();
countersMenu = playerMenu->addMenu(QString());
playerMenu->addSeparator();
@ -461,6 +464,7 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, bool _judge, T
mCustomZones = nullptr;
aCreateAnotherToken = nullptr;
createPredefinedTokenMenu = nullptr;
mCardCounters = nullptr;
}
aTap = new QAction(this);
@ -538,7 +542,7 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, bool _judge, T
aPlayFacedown = new QAction(this);
connect(aPlayFacedown, &QAction::triggered, this, &Player::actPlayFacedown);
for (int i = 0; i < 3; ++i) {
for (int i = 0; i < 6; ++i) {
auto *tempAddCounter = new QAction(this);
tempAddCounter->setData(9 + i * 1000);
auto *tempRemoveCounter = new QAction(this);
@ -892,19 +896,17 @@ void Player::retranslateUi()
aResetPT->setText(tr("Reset p&ower and toughness"));
aSetAnnotation->setText(tr("&Set annotation..."));
QStringList counterColors;
counterColors.append(tr("Red"));
counterColors.append(tr("Yellow"));
counterColors.append(tr("Green"));
auto &cardCounterSettings = SettingsCache::instance().cardCounters();
mCardCounters->setTitle(tr("Ca&rd counters"));
for (int i = 0; i < aAddCounter.size(); ++i) {
aAddCounter[i]->setText(tr("&Add counter (%1)").arg(counterColors[i]));
aAddCounter[i]->setText(tr("&Add counter (%1)").arg(cardCounterSettings.displayName(i)));
}
for (int i = 0; i < aRemoveCounter.size(); ++i) {
aRemoveCounter[i]->setText(tr("&Remove counter (%1)").arg(counterColors[i]));
aRemoveCounter[i]->setText(tr("&Remove counter (%1)").arg(cardCounterSettings.displayName(i)));
}
for (int i = 0; i < aSetCounter.size(); ++i) {
aSetCounter[i]->setText(tr("&Set counters (%1)...").arg(counterColors[i]));
aSetCounter[i]->setText(tr("&Set counters (%1)...").arg(cardCounterSettings.displayName(i)));
}
aMoveToTopLibrary->setText(tr("&Top of library in random order"));
@ -960,24 +962,33 @@ void Player::setShortcutsActive()
addCCShortCuts.append(shortcuts.getSingleShortcut("Player/aCCRed"));
addCCShortCuts.append(shortcuts.getSingleShortcut("Player/aCCYellow"));
addCCShortCuts.append(shortcuts.getSingleShortcut("Player/aCCGreen"));
addCCShortCuts.append(shortcuts.getSingleShortcut("Player/aCCCyan"));
addCCShortCuts.append(shortcuts.getSingleShortcut("Player/aCCPurple"));
addCCShortCuts.append(shortcuts.getSingleShortcut("Player/aCCMagenta"));
QList<QKeySequence> removeCCShortCuts;
removeCCShortCuts.append(shortcuts.getSingleShortcut("Player/aRCRed"));
removeCCShortCuts.append(shortcuts.getSingleShortcut("Player/aRCYellow"));
removeCCShortCuts.append(shortcuts.getSingleShortcut("Player/aRCGreen"));
removeCCShortCuts.append(shortcuts.getSingleShortcut("Player/aRCCyan"));
removeCCShortCuts.append(shortcuts.getSingleShortcut("Player/aRCPurple"));
removeCCShortCuts.append(shortcuts.getSingleShortcut("Player/aRCMagenta"));
QList<QKeySequence> setCCShortCuts;
setCCShortCuts.append(shortcuts.getSingleShortcut("Player/aSCRed"));
setCCShortCuts.append(shortcuts.getSingleShortcut("Player/aSCYellow"));
setCCShortCuts.append(shortcuts.getSingleShortcut("Player/aSCGreen"));
setCCShortCuts.append(shortcuts.getSingleShortcut("Player/aSCCyan"));
setCCShortCuts.append(shortcuts.getSingleShortcut("Player/aSCPurple"));
setCCShortCuts.append(shortcuts.getSingleShortcut("Player/aSCMagenta"));
for (int i = 0; i < aAddCounter.size(); ++i) {
for (int i = 0; i < addCCShortCuts.size(); ++i) {
aAddCounter[i]->setShortcut(addCCShortCuts.at(i));
}
for (int i = 0; i < aRemoveCounter.size(); ++i) {
for (int i = 0; i < removeCCShortCuts.size(); ++i) {
aRemoveCounter[i]->setShortcut(removeCCShortCuts.at(i));
}
for (int i = 0; i < aSetCounter.size(); ++i) {
for (int i = 0; i < setCCShortCuts.size(); ++i) {
aSetCounter[i]->setShortcut(setCCShortCuts.at(i));
}
@ -3944,15 +3955,18 @@ void Player::updateCardMenu(const CardItem *card)
cardMenu->addAction(aSelectAll);
cardMenu->addAction(aSelectRow);
cardMenu->addSeparator();
mCardCounters->clear();
for (int i = 0; i < aAddCounter.size(); ++i) {
cardMenu->addSeparator();
cardMenu->addAction(aAddCounter[i]);
mCardCounters->addSeparator();
mCardCounters->addAction(aAddCounter[i]);
if (card->getCounters().contains(i)) {
cardMenu->addAction(aRemoveCounter[i]);
mCardCounters->addAction(aRemoveCounter[i]);
}
cardMenu->addAction(aSetCounter[i]);
mCardCounters->addAction(aSetCounter[i]);
}
cardMenu->addSeparator();
cardMenu->addMenu(mCardCounters);
} else if (card->getZone()->getName() == "stack") {
// Card is on the stack
if (canModifyCard) {

View File

@ -253,7 +253,7 @@ public:
private:
TabGame *game;
QMenu *sbMenu, *countersMenu, *sayMenu, *createPredefinedTokenMenu, *mRevealLibrary, *mLendLibrary, *mRevealTopCard,
*mRevealHand, *mRevealRandomHandCard, *mRevealRandomGraveyardCard, *mCustomZones;
*mRevealHand, *mRevealRandomHandCard, *mRevealRandomGraveyardCard, *mCustomZones, *mCardCounters;
TearOffMenu *moveGraveMenu, *moveRfgMenu, *graveMenu, *moveHandMenu, *handMenu, *libraryMenu, *topLibraryMenu,
*bottomLibraryMenu, *rfgMenu, *playerMenu;
QList<QMenu *> playerLists;

View File

@ -6,6 +6,7 @@
#include "../game/phase.h"
#include "../game/player/player.h"
#include "../game/zones/card_zone.h"
#include "../settings/card_counter_settings.h"
#include "pb/context_move_card.pb.h"
#include "pb/context_mulligan.pb.h"
#include "pb/serverinfo_user.pb.h"
@ -613,28 +614,15 @@ void MessageLogWidget::logSetCardCounter(Player *player, QString cardName, int c
QString finalStr;
int delta = abs(oldValue - value);
if (value > oldValue) {
finalStr = tr("%1 places %2 %3 on %4 (now %5).");
finalStr = tr("%1 places %2 \"%3\" counter(s) on %4 (now %5).", "", delta);
} else {
finalStr = tr("%1 removes %2 %3 from %4 (now %5).");
}
QString colorStr;
switch (counterId) {
case 0:
colorStr = tr("red counter(s)", "", delta);
break;
case 1:
colorStr = tr("yellow counter(s)", "", delta);
break;
case 2:
colorStr = tr("green counter(s)", "", delta);
break;
default:;
finalStr = tr("%1 removes %2 \"%3\" counter(s) from %4 (now %5).", "", delta);
}
auto &cardCounterSettings = SettingsCache::instance().cardCounters();
appendHtmlServerMessage(finalStr.arg(sanitizeHtml(player->getName()))
.arg("<font class=\"blue\">" + QString::number(delta) + "</font>")
.arg(colorStr)
.arg(cardCounterSettings.displayName(counterId))
.arg(cardLink(std::move(cardName)))
.arg(value));
}

View File

@ -1,8 +1,10 @@
#include "cache_settings.h"
#include "../client/network/release_channel.h"
#include "card_counter_settings.h"
#include "card_override_settings.h"
#include <QAbstractListModel>
#include <QApplication>
#include <QDebug>
#include <QDir>
@ -179,6 +181,8 @@ SettingsCache::SettingsCache()
cardOverrideSettings = new CardOverrideSettings(settingsPath, this);
debugSettings = new DebugSettings(settingsPath, this);
cardCounterSettings = new CardCounterSettings(settingsPath, this);
if (!QFile(settingsPath + "global.ini").exists())
translateLegacySettings();
@ -1423,3 +1427,8 @@ SettingsCache &SettingsCache::instance()
{
return *settingsCache;
}
CardCounterSettings &SettingsCache::cardCounters() const
{
return *cardCounterSettings;
}

View File

@ -43,6 +43,7 @@ constexpr int NETWORK_CACHE_SIZE_MAX = 1024 * 1024; // 1 TB
#define DEFAULT_FONT_SIZE 12
class QSettings;
class CardCounterSettings;
class SettingsCache : public QObject
{
@ -104,6 +105,7 @@ private:
RecentsSettings *recentsSettings;
CardOverrideSettings *cardOverrideSettings;
DebugSettings *debugSettings;
CardCounterSettings *cardCounterSettings;
QByteArray mainWindowGeometry;
QByteArray tokenDialogGeometry;
@ -779,6 +781,8 @@ public:
{
return *debugSettings;
}
CardCounterSettings &cardCounters() const;
bool getIsPortableBuild() const
{
return isPortableBuild;

View File

@ -0,0 +1,56 @@
#include "card_counter_settings.h"
#include <QColor>
#include <QSettings>
#include <QtMath>
CardCounterSettings::CardCounterSettings(const QString &settingsPath, QObject *parent)
: SettingsManager(settingsPath + "global.ini", parent)
{
}
void CardCounterSettings::setColor(int counterId, const QColor &color)
{
QString key = QString("cards/counters/%1/color").arg(counterId);
if (settings.value(key).value<QColor>() == color)
return;
settings.setValue(key, color);
emit colorChanged(counterId, color);
}
QColor CardCounterSettings::color(int counterId) const
{
QColor defaultColor;
if (counterId < 6) {
// Preserve legacy colors
defaultColor = QColor::fromHsv(counterId * 60, 150, 255);
} else {
// Future-proof support for more counters with pseudo-random colors
int h = (counterId * 37) % 360;
int s = 128 + 64 * qSin((counterId * 97) * 0.1); // 64-192
int v = 196 + 32 * qSin((counterId * 101) * 0.07); // 164-228
defaultColor = QColor::fromHsv(h, s, v);
}
return settings.value(QString("cards/counters/%1/color").arg(counterId), defaultColor).value<QColor>();
}
QString CardCounterSettings::displayName(int counterId) const
{
// Currently, card counters name are fixed to A, B, ..., Z, AA, AB, ...
auto nChars = 1 + counterId / 26;
QString str;
str.resize(nChars);
for (auto it = str.rbegin(); it != str.rend(); ++it) {
*it = QChar('A' + (counterId) % 26);
counterId /= 26;
}
return str;
}

View File

@ -0,0 +1,29 @@
#ifndef CARD_COUNTER_SETTINGS_H
#define CARD_COUNTER_SETTINGS_H
#include "settings_manager.h"
#include <QObject>
class QSettings;
class QColor;
class CardCounterSettings : public SettingsManager
{
Q_OBJECT
public:
CardCounterSettings(const QString &settingsPath, QObject *parent = nullptr);
QColor color(int counterId) const;
QString displayName(int counterId) const;
public slots:
void setColor(int counterId, const QColor &color);
signals:
void colorChanged(int counterId, const QColor &color);
};
#endif // CARD_COUNTER_SETTINGS_H

View File

@ -284,31 +284,58 @@ private:
{"DeckViewContainer/forceStartGameButton", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Force Start"),
parseSequenceString(""),
ShortcutGroup::Game_Lobby)},
{"Player/aCCGreen", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add Green Counter"),
{"Player/aCCMagenta", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add Card Counter (F)"),
parseSequenceString(""),
ShortcutGroup::Card_Counters)},
{"Player/aRCMagenta", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Card Counter (F)"),
parseSequenceString(""),
ShortcutGroup::Card_Counters)},
{"Player/aSCMagenta", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Card Counters (F)..."),
parseSequenceString(""),
ShortcutGroup::Card_Counters)},
{"Player/aCCPurple", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add Card Counter (E)"),
parseSequenceString(""),
ShortcutGroup::Card_Counters)},
{"Player/aRCPurple", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Card Counter (E)"),
parseSequenceString(""),
ShortcutGroup::Card_Counters)},
{"Player/aSCPurple", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Card Counters (E)..."),
parseSequenceString(""),
ShortcutGroup::Card_Counters)},
{"Player/aCCCyan", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add Card Counter(D)"),
parseSequenceString(""),
ShortcutGroup::Card_Counters)},
{"Player/aRCCyan", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Card Counter (D)"),
parseSequenceString(""),
ShortcutGroup::Card_Counters)},
{"Player/aSCCyan", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Card Counters (D)..."),
parseSequenceString(""),
ShortcutGroup::Card_Counters)},
{"Player/aCCGreen", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add Card Counter (C)"),
parseSequenceString("Ctrl+>"),
ShortcutGroup::Card_Counters)},
{"Player/aRCGreen", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Green Counter"),
{"Player/aRCGreen", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Card Counter (C)"),
parseSequenceString("Ctrl+<"),
ShortcutGroup::Card_Counters)},
{"Player/aSCGreen", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Green Counters..."),
{"Player/aSCGreen", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Card Counters (C)..."),
parseSequenceString("Ctrl+?"),
ShortcutGroup::Card_Counters)},
{"Player/aCCYellow", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add Yellow Counter"),
{"Player/aCCYellow", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add Card Counter (B)"),
parseSequenceString("Ctrl+."),
ShortcutGroup::Card_Counters)},
{"Player/aRCYellow", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Yellow Counter"),
{"Player/aRCYellow", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Card Counter (B)"),
parseSequenceString("Ctrl+,"),
ShortcutGroup::Card_Counters)},
{"Player/aSCYellow", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Yellow Counters..."),
{"Player/aSCYellow", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Card Counters (B)..."),
parseSequenceString("Ctrl+/"),
ShortcutGroup::Card_Counters)},
{"Player/aCCRed", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add Red Counter"),
{"Player/aCCRed", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add Card Counter (A)"),
parseSequenceString("Alt+."),
ShortcutGroup::Card_Counters)},
{"Player/aRCRed", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Red Counter"),
{"Player/aRCRed", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Card Counter (A)"),
parseSequenceString("Alt+,"),
ShortcutGroup::Card_Counters)},
{"Player/aSCRed", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Red Counters..."),
{"Player/aSCRed", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Card Counters (A)..."),
parseSequenceString("Alt+/"),
ShortcutGroup::Card_Counters)},
{"Player/aInc", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add Life Counter"),

View File

@ -33,6 +33,7 @@ set(oracle_SOURCES
../cockatrice/src/game/cards/card_database_parser/cockatrice_xml_4.cpp
../cockatrice/src/settings/cache_settings.cpp
../cockatrice/src/settings/shortcuts_settings.cpp
../cockatrice/src/settings/card_counter_settings.cpp
../cockatrice/src/settings/card_database_settings.cpp
../cockatrice/src/settings/servers_settings.cpp
../cockatrice/src/settings/settings_manager.cpp