Clean up inter-library dependencies with interfaces (#6280)

* Have CardDatabase::getPreferredPrintingInfo respect card provider ID overrides (pinned printings)

Took 13 minutes

Took 37 seconds

Took 10 seconds

Took 10 seconds

# Commit time for manual adjustment:
# Took 30 seconds

Took 15 seconds


Took 8 minutes

Took 21 seconds

* Move settings cache and settings card preference provider out of libcockatrice_settings and into cockatrice

Took 52 minutes

Took 9 minutes

Took 1 minute

* Temp cache.

Took 16 minutes

* Dependency Injection for SettingsCache

* Turn SettingsCache into a QSharedPointer.
* Implement interfaces for settings that need it

Took 2 hours 38 minutes

* Adjust oracle.

Took 5 minutes

* Move abstract/noop interfaces to libcockatrice_interfaces so they can be linked against independently.

Took 52 minutes

* Clean up some links.

Took 3 minutes

* Cleanup two includes.

Took 3 minutes

* More fixes.

Took 7 minutes

* More includes that slipped past.

Took 3 minutes

* Stop mocking and start injecting for tests.

Took 15 minutes

* I don't know why remote_client was including main.

Took 4 minutes

* Include.

Took 3 minutes

* Lint.

Took 2 minutes

* Don't use Qt pointers.

Took 1 hour 7 minutes

* Make parser use CardSettingsInterface

Took 13 minutes

* Also adjust constructor lol.

Took 8 minutes

* Lint.

Took 32 minutes

* Revert "Lint."

This reverts commit ecb596c39e.


Took 3 minutes

* Test.

Took 3 minutes

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
BruebachL 2025-11-08 22:19:40 +01:00 committed by GitHub
parent fb30515f72
commit a8a3fca8c9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
152 changed files with 609 additions and 750 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

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,34 @@
/**
* @file card_counter_settings.h
* @ingroup GameSettings
* @brief TODO: Document this.
*/
#ifndef CARD_COUNTER_SETTINGS_H
#define CARD_COUNTER_SETTINGS_H
#include <QObject>
#include <libcockatrice/settings/settings_manager.h>
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

@ -0,0 +1,167 @@
#include "shortcut_treeview.h"
#include "cache_settings.h"
#include "shortcuts_settings.h"
#include <QHeaderView>
ShortcutFilterProxyModel::ShortcutFilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent)
{
}
/**
* Appends the parent and source row together before doing the regex match.
*/
bool ShortcutFilterProxyModel::filterAcceptsRow(const int sourceRow, const QModelIndex &sourceParent) const
{
QModelIndex nameIndex = sourceModel()->index(sourceRow, filterKeyColumn(), sourceParent);
QModelIndex parentIndex = sourceModel()->index(sourceParent.row(), filterKeyColumn(), sourceParent.parent());
QString name = sourceModel()->data(nameIndex).toString();
QString parentName = sourceModel()->data(parentIndex).toString();
QString searchedString = parentName + " " + name;
return searchedString.contains(filterRegularExpression());
}
ShortcutTreeView::ShortcutTreeView(QWidget *parent) : QTreeView(parent)
{
// model
shortcutsModel = new QStandardItemModel(this);
shortcutsModel->setColumnCount(3);
populateShortcutsModel();
// filter proxy
proxyModel = new ShortcutFilterProxyModel(this);
proxyModel->setRecursiveFilteringEnabled(true);
proxyModel->setSourceModel(shortcutsModel);
proxyModel->setDynamicSortFilter(true);
proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
proxyModel->setFilterKeyColumn(0);
QTreeView::setModel(proxyModel);
// treeview
hideColumn(2);
setUniformRowHeights(true);
setAlternatingRowColors(true);
setSortingEnabled(true);
proxyModel->sort(0, Qt::AscendingOrder);
header()->setSectionResizeMode(QHeaderView::Interactive);
header()->setSortIndicator(0, Qt::AscendingOrder);
setSelectionMode(SingleSelection);
setSelectionBehavior(SelectRows);
expandAll();
connect(&SettingsCache::instance().shortcuts(), &ShortcutsSettings::shortCutChanged, this,
&ShortcutTreeView::refreshShortcuts);
}
void ShortcutTreeView::populateShortcutsModel()
{
QHash<QString, QStandardItem *> parentItems;
QStandardItem *curParent = nullptr;
for (const auto &key : SettingsCache::instance().shortcuts().getAllShortcutKeys()) {
QString name = SettingsCache::instance().shortcuts().getShortcut(key).getName();
QString group = SettingsCache::instance().shortcuts().getShortcut(key).getGroupName();
QString shortcut = SettingsCache::instance().shortcuts().getShortcutString(key);
if (parentItems.contains(group)) {
curParent = parentItems.value(group);
} else {
curParent = new QStandardItem(group);
static QFont font = curParent->font();
font.setBold(true);
curParent->setFont(font);
parentItems.insert(group, curParent);
}
QList<QStandardItem *> list = {};
list << new QStandardItem(name) << new QStandardItem(shortcut) << new QStandardItem(key);
curParent->appendRow(list);
}
for (const auto &parent : parentItems) {
shortcutsModel->appendRow(parent);
}
}
void ShortcutTreeView::retranslateUi()
{
shortcutsModel->setHeaderData(0, Qt::Horizontal, tr("Action"));
shortcutsModel->setHeaderData(1, Qt::Horizontal, tr("Shortcut"));
refreshShortcuts();
}
/**
* Loops over the model and reloads all rows
*/
static void loopOverModel(QAbstractItemModel *model, const QModelIndex &parent = QModelIndex())
{
for (int r = 0; r < model->rowCount(parent); ++r) {
const auto friendlyNameIndex = model->index(r, 0, parent);
if (model->hasChildren(friendlyNameIndex)) {
const auto childIndex = model->index(0, 2, friendlyNameIndex);
const auto key = model->data(childIndex).toString();
const auto shortcutGroupName = SettingsCache::instance().shortcuts().getShortcut(key).getGroupName();
model->setData(friendlyNameIndex, shortcutGroupName);
loopOverModel(model, friendlyNameIndex);
} else {
const auto shortcutSequenceIndex = model->index(r, 1, parent);
const auto keyIndex = model->index(r, 2, parent);
const auto key = model->data(keyIndex).toString();
const auto shortcutKey = SettingsCache::instance().shortcuts().getShortcut(key).getName();
const auto shortcutSequence = SettingsCache::instance().shortcuts().getShortcutString(key);
model->setData(friendlyNameIndex, shortcutKey);
model->setData(shortcutSequenceIndex, shortcutSequence);
}
}
}
void ShortcutTreeView::refreshShortcuts()
{
loopOverModel(shortcutsModel);
}
void ShortcutTreeView::currentChanged(const QModelIndex &current, const QModelIndex & /* previous */)
{
QTreeView::scrollTo(current, QAbstractItemView::EnsureVisible);
if (current.parent().isValid()) {
auto shortcutName = model()->data(model()->index(current.row(), 2, current.parent())).toString();
emit currentItemChanged(shortcutName);
} else {
// emit empty string if the selection is a category header
emit currentItemChanged("");
}
}
/**
* The search string is split by word.
* A String is a match as long as it contains all the words in the search string in order
*/
void ShortcutTreeView::updateSearchString(const QString &searchString)
{
#if QT_VERSION > QT_VERSION_CHECK(5, 14, 0)
const auto skipEmptyParts = Qt::SkipEmptyParts;
#else
const auto skipEmptyParts = QString::SkipEmptyParts;
#endif
QStringList searchWords = searchString.split(" ", skipEmptyParts);
auto escapeRegex = [](const QString &s) { return QRegularExpression::escape(s); };
std::transform(searchWords.begin(), searchWords.end(), searchWords.begin(), escapeRegex);
auto regex = QRegularExpression(searchWords.join(".*"), QRegularExpression::CaseInsensitiveOption);
proxyModel->setFilterRegularExpression(regex);
expandAll();
}

View file

@ -0,0 +1,53 @@
/**
* @file shortcut_treeview.h
* @ingroup CoreSettings
* @brief TODO: Document this.
*/
#ifndef SHORTCUT_TREEVIEW_H
#define SHORTCUT_TREEVIEW_H
#include <QModelIndex>
#include <QSortFilterProxyModel>
#include <QStandardItemModel>
#include <QTreeView>
/**
* Custom implementation of QSortFilterProxyModel that appends the source and parent strings together when filtering
*/
class ShortcutFilterProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
explicit ShortcutFilterProxyModel(QObject *parent = nullptr);
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
};
class ShortcutTreeView : public QTreeView
{
Q_OBJECT
public:
explicit ShortcutTreeView(QWidget *parent);
void retranslateUi();
signals:
void currentItemChanged(const QString &shortcut);
public slots:
void updateSearchString(const QString &searchString);
private:
QStandardItemModel *shortcutsModel;
ShortcutFilterProxyModel *proxyModel;
void populateShortcutsModel();
private slots:
void refreshShortcuts();
protected:
void currentChanged(const QModelIndex &current, const QModelIndex &previous) override;
};
#endif // SHORTCUT_TREEVIEW_H

View file

@ -0,0 +1,263 @@
#include "shortcuts_settings.h"
#include <QDebug>
#include <QFile>
#include <QMessageBox>
#include <QStringList>
#include <utility>
ShortcutKey::ShortcutKey(const QString &_name, QList<QKeySequence> _sequence, ShortcutGroup::Groups _group)
: QList<QKeySequence>(_sequence), name(_name), group(_group)
{
}
ShortcutsSettings::ShortcutsSettings(const QString &settingsPath, QObject *parent) : QObject(parent)
{
shortCuts = defaultShortCuts;
settingsFilePath = settingsPath;
settingsFilePath.append("shortcuts.ini");
bool exists = QFile(settingsFilePath).exists();
QSettings shortCutsFile(settingsFilePath, QSettings::IniFormat);
if (exists) {
shortCutsFile.beginGroup(custom);
const QStringList customKeys = shortCutsFile.allKeys();
QMap<QString, QString> invalidItems;
for (QStringList::const_iterator it = customKeys.constBegin(); it != customKeys.constEnd(); ++it) {
QString stringSequence = shortCutsFile.value(*it).toString();
// check whether shortcut name exists
if (!shortCuts.contains(*it)) {
qCWarning(ShortcutsSettingsLog) << "Unknown shortcut name:" << *it;
continue;
}
// check whether shortcut is forbidden
if (isKeyAllowed(*it, stringSequence)) {
auto shortcut = getShortcut(*it);
shortcut.setSequence(parseSequenceString(stringSequence));
shortCuts.insert(*it, shortcut);
} else {
invalidItems.insert(*it, stringSequence);
}
}
shortCutsFile.endGroup();
if (!invalidItems.isEmpty()) {
// warning message in case of invalid items
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Warning);
msgBox.setText(tr("Your configuration file contained invalid shortcuts.\n"
"Please check your shortcut settings!"));
QString detailedMessage = tr("The following shortcuts have been set to default:\n");
for (QMap<QString, QString>::const_iterator item = invalidItems.constBegin();
item != invalidItems.constEnd(); ++item) {
detailedMessage += item.key() + " - \"" + item.value() + "\"\n";
}
msgBox.setDetailedText(detailedMessage);
msgBox.exec();
}
}
}
/// PR 5079 changes Textbox/unfocusTextBox to Player/unfocusTextBox and tab_game/aFocusChat to Player/aFocusChat.
/// A migration is necessary to let players keep their already configured shortcuts.
void ShortcutsSettings::migrateShortcuts()
{
if (QFile(settingsFilePath).exists()) {
QSettings shortCutsFile(settingsFilePath, QSettings::IniFormat);
shortCutsFile.beginGroup(custom);
if (shortCutsFile.contains("Textbox/unfocusTextBox")) {
qCInfo(ShortcutsSettingsLog)
<< "[ShortcutsSettings] Textbox/unfocusTextBox shortcut found. Migrating to Player/unfocusTextBox.";
QString unfocusTextBox = shortCutsFile.value("Textbox/unfocusTextBox", "").toString();
this->setShortcuts("Player/unfocusTextBox", unfocusTextBox);
shortCutsFile.remove("Textbox/unfocusTextBox");
}
if (shortCutsFile.contains("tab_game/aFocusChat")) {
qCInfo(ShortcutsSettingsLog)
<< "[ShortcutsSettings] tab_game/aFocusChat shortcut found. Migrating to Player/aFocusChat.";
QString aFocusChat = shortCutsFile.value("tab_game/aFocusChat", "").toString();
this->setShortcuts("Player/aFocusChat", aFocusChat);
shortCutsFile.remove("tab_game/aFocusChat");
}
// PR #5564 changes "MainWindow/aDeckEditor" to "Tabs/aTabDeckEditor"
if (shortCutsFile.contains("MainWindow/aDeckEditor")) {
qCInfo(ShortcutsSettingsLog) << "MainWindow/aDeckEditor shortcut found. Migrating to Tabs/aTabDeckEditor.";
QString keySequence = shortCutsFile.value("MainWindow/aDeckEditor", "").toString();
this->setShortcuts("Tabs/aTabDeckEditor", keySequence);
shortCutsFile.remove("MainWindow/aDeckEditor");
}
shortCutsFile.endGroup();
}
}
ShortcutKey ShortcutsSettings::getDefaultShortcut(const QString &name) const
{
return defaultShortCuts.value(name, ShortcutKey());
}
ShortcutKey ShortcutsSettings::getShortcut(const QString &name) const
{
if (shortCuts.contains(name)) {
return shortCuts.value(name);
}
return getDefaultShortcut(name);
}
/**
* Gets the first shortcut for the given action.
*
* NOTE: In most cases you should be using ShortcutsSettings::getShortcut instead,
* as that will return all shortcuts if there are multiple shortcuts.
* The only reason to use this method is if an object does not accept multiple shortcuts, such as with QButtons.
*/
QKeySequence ShortcutsSettings::getSingleShortcut(const QString &name) const
{
return getShortcut(name).at(0);
}
QString ShortcutsSettings::getDefaultShortcutString(const QString &name) const
{
return stringifySequence(getDefaultShortcut(name));
}
QString ShortcutsSettings::getShortcutString(const QString &name) const
{
return stringifySequence(getShortcut(name));
}
QString ShortcutsSettings::getShortcutFriendlyName(const QString &shortcutName) const
{
for (auto it = defaultShortCuts.cbegin(); it != defaultShortCuts.cend(); ++it) {
if (shortcutName == it.key()) {
return it.value().getName();
}
}
return {};
}
QString ShortcutsSettings::stringifySequence(const QList<QKeySequence> &Sequence) const
{
QStringList stringSequence;
for (const auto &i : Sequence) {
stringSequence.append(i.toString(QKeySequence::PortableText));
}
return stringSequence.join(sep);
}
QList<QKeySequence> ShortcutsSettings::parseSequenceString(const QString &stringSequence) const
{
QList<QKeySequence> SequenceList;
for (const QString &shortcut : stringSequence.split(sep)) {
SequenceList.append(QKeySequence(shortcut, QKeySequence::PortableText));
}
return SequenceList;
}
void ShortcutsSettings::setShortcuts(const QString &name, const QList<QKeySequence> &Sequence)
{
shortCuts[name].setSequence(Sequence);
QSettings shortCutsFile(settingsFilePath, QSettings::IniFormat);
shortCutsFile.beginGroup(custom);
shortCutsFile.setValue(name, stringifySequence(Sequence));
shortCutsFile.endGroup();
emit shortCutChanged();
}
void ShortcutsSettings::setShortcuts(const QString &name, const QKeySequence &Sequence)
{
setShortcuts(name, QList<QKeySequence>{Sequence});
}
void ShortcutsSettings::setShortcuts(const QString &name, const QString &sequences)
{
setShortcuts(name, parseSequenceString(sequences));
}
void ShortcutsSettings::resetAllShortcuts()
{
shortCuts = defaultShortCuts;
QSettings shortCutsFile(settingsFilePath, QSettings::IniFormat);
shortCutsFile.beginGroup(custom);
shortCutsFile.remove("");
shortCutsFile.endGroup();
emit shortCutChanged();
}
void ShortcutsSettings::clearAllShortcuts()
{
QSettings shortCutsFile(settingsFilePath, QSettings::IniFormat);
shortCutsFile.beginGroup(custom);
for (auto it = shortCuts.begin(); it != shortCuts.end(); ++it) {
it.value().setSequence(parseSequenceString(""));
shortCutsFile.setValue(it.key(), "");
}
shortCutsFile.endGroup();
emit shortCutChanged();
}
bool ShortcutsSettings::isKeyAllowed(const QString &name, const QString &sequences) const
{
// if the shortcut is not to be used in deck-editor then it doesn't matter
if (name.startsWith("Player") || name.startsWith("Replays")) {
return true;
}
QString checkSequence = sequences.split(sep).last();
QStringList forbiddenKeys{"Del", "Backspace", "Down", "Up", "Left", "Right",
"Return", "Enter", "Menu", "Ctrl+Alt+-", "Ctrl+Alt+=", "Ctrl+Alt+[",
"Ctrl+Alt+]", "Tab", "Space", "Shift+S", "Shift+Left", "Shift+Right"};
return !forbiddenKeys.contains(checkSequence);
}
/**
* Checks that the shortcut doesn't overlap with an existing shortcut
*
* @param name The name of the shortcut
* @param sequences The shortcut key sequence
* @return Whether the shortcut is valid.
*/
bool ShortcutsSettings::isValid(const QString &name, const QString &sequences) const
{
return findOverlaps(name, sequences).isEmpty();
}
/**
* Checks if the shortcut is a shortcut that is active in all windows
*/
static bool isAlwaysActiveShortcut(const QString &shortcutName)
{
return shortcutName.startsWith("MainWindow") || shortcutName.startsWith("Tabs");
}
QStringList ShortcutsSettings::findOverlaps(const QString &name, const QString &sequences) const
{
QString checkSequence = sequences.split(sep).last();
QString checkKey = name.left(name.indexOf("/"));
QStringList overlaps;
for (const auto &key : shortCuts.keys()) {
if (key.startsWith(checkKey) || isAlwaysActiveShortcut(key) || isAlwaysActiveShortcut(checkKey)) {
QString storedSequence = stringifySequence(shortCuts.value(key));
if (storedSequence.split(sep).contains(checkSequence)) {
overlaps.append(getShortcutFriendlyName(key));
}
}
}
return overlaps;
}

View file

@ -0,0 +1,737 @@
/**
* @file shortcuts_settings.h
* @ingroup CoreSettings
* @brief TODO: Document this.
*/
#ifndef SHORTCUTSSETTINGS_H
#define SHORTCUTSSETTINGS_H
#include <QApplication>
#include <QKeySequence>
#include <QLoggingCategory>
#include <QSettings>
inline Q_LOGGING_CATEGORY(ShortcutsSettingsLog, "shortcuts_settings");
class ShortcutGroup
{
public:
enum Groups
{
Main_Window,
Deck_Editor,
Game_Lobby,
Card_Counters,
Player_Counters,
Power_Toughness,
Game_Phases,
Playing_Area,
Move_selected,
View,
Move_top,
Move_bottom,
Gameplay,
Drawing,
Chat_room,
Game_window,
Load_deck,
Replays,
Tabs
};
static QString getGroupName(ShortcutGroup::Groups group)
{
switch (group) {
case Main_Window:
return QApplication::translate("shortcutsTab", "Main Window");
case Deck_Editor:
return QApplication::translate("shortcutsTab", "Deck Editor");
case Game_Lobby:
return QApplication::translate("shortcutsTab", "Game Lobby");
case Card_Counters:
return QApplication::translate("shortcutsTab", "Card Counters");
case Player_Counters:
return QApplication::translate("shortcutsTab", "Player Counters");
case Power_Toughness:
return QApplication::translate("shortcutsTab", "Power and Toughness");
case Game_Phases:
return QApplication::translate("shortcutsTab", "Game Phases");
case Playing_Area:
return QApplication::translate("shortcutsTab", "Playing Area");
case Move_selected:
return QApplication::translate("shortcutsTab", "Move Selected Card");
case View:
return QApplication::translate("shortcutsTab", "View");
case Move_top:
return QApplication::translate("shortcutsTab", "Move Top Card");
case Move_bottom:
return QApplication::translate("shortcutsTab", "Move Bottom Card");
case Gameplay:
return QApplication::translate("shortcutsTab", "Gameplay");
case Drawing:
return QApplication::translate("shortcutsTab", "Drawing");
case Chat_room:
return QApplication::translate("shortcutsTab", "Chat Room");
case Game_window:
return QApplication::translate("shortcutsTab", "Game Window");
case Load_deck:
return QApplication::translate("shortcutsTab", "Load Deck from Clipboard");
case Replays:
return QApplication::translate("shortcutsTab", "Replays");
case Tabs:
return QApplication::translate("shortcutsTab", "Tabs");
}
return {};
}
};
class ShortcutKey : public QList<QKeySequence>
{
public:
explicit ShortcutKey(const QString &_name = QString(),
QList _sequence = QList(),
ShortcutGroup::Groups _group = ShortcutGroup::Main_Window);
void setSequence(const QList &_sequence)
{
QList::operator=(_sequence);
};
QString getName() const
{
return QApplication::translate("shortcutsTab", name.toUtf8().data());
};
QString getGroupName() const
{
return ShortcutGroup::getGroupName(group);
};
private:
QString name;
ShortcutGroup::Groups group;
};
class ShortcutsSettings : public QObject
{
Q_OBJECT
public:
explicit ShortcutsSettings(const QString &settingsFilePath, QObject *parent = nullptr);
ShortcutKey getDefaultShortcut(const QString &name) const;
ShortcutKey getShortcut(const QString &name) const;
QKeySequence getSingleShortcut(const QString &name) const;
QString getDefaultShortcutString(const QString &name) const;
QString getShortcutString(const QString &name) const;
QString getShortcutFriendlyName(const QString &shortcutName) const;
QList<QString> getAllShortcutKeys() const
{
return shortCuts.keys();
};
void setShortcuts(const QString &name, const QList<QKeySequence> &Sequence);
void setShortcuts(const QString &name, const QKeySequence &Sequence);
void setShortcuts(const QString &name, const QString &sequences);
bool isKeyAllowed(const QString &name, const QString &sequences) const;
bool isValid(const QString &name, const QString &sequences) const;
QStringList findOverlaps(const QString &name, const QString &sequences) const;
void resetAllShortcuts();
void clearAllShortcuts();
void migrateShortcuts();
signals:
void shortCutChanged();
private:
const QChar sep = ';';
const QString custom = "Custom"; // name of custom group in shortCutsFile
QString settingsFilePath;
QHash<QString, ShortcutKey> shortCuts;
QString stringifySequence(const QList<QKeySequence> &Sequence) const;
QList<QKeySequence> parseSequenceString(const QString &stringSequence) const;
const QHash<QString, ShortcutKey> defaultShortCuts = {
{"MainWindow/aCheckCardUpdates", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Check for Card Updates..."),
parseSequenceString(""),
ShortcutGroup::Main_Window)},
{"MainWindow/aConnect", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Connect..."),
parseSequenceString("Ctrl+L"),
ShortcutGroup::Main_Window)},
{"MainWindow/aDisconnect", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Disconnect"),
parseSequenceString(""),
ShortcutGroup::Main_Window)},
{"MainWindow/aExit",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Exit"), parseSequenceString(""), ShortcutGroup::Main_Window)},
{"MainWindow/aFullScreen", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Full screen"),
parseSequenceString("Ctrl+F"),
ShortcutGroup::Main_Window)},
{"MainWindow/aRegister", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Register..."),
parseSequenceString(""),
ShortcutGroup::Main_Window)},
{"MainWindow/aSettings", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Settings..."),
parseSequenceString("Ctrl+Shift+P"),
ShortcutGroup::Main_Window)},
{"MainWindow/aSinglePlayer", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Start a Local Game..."),
parseSequenceString("Ctrl+Shift+L"),
ShortcutGroup::Main_Window)},
{"MainWindow/aWatchReplay", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Watch Replay..."),
parseSequenceString(""),
ShortcutGroup::Main_Window)},
{"MainWindow/aStatusBar", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Show Status Bar"),
parseSequenceString(""),
ShortcutGroup::Main_Window)},
{"TabDeckEditor/aAnalyzeDeck", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Analyze Deck (deckstats.net)"),
parseSequenceString(""),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aAnalyzeDeckTappedout",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Analyze Deck (tappedout.net)"),
parseSequenceString(""),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aClearFilterAll", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Clear All Filters"),
parseSequenceString(""),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aClearFilterOne", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Clear Selected Filter"),
parseSequenceString(""),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aClose",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Close"), parseSequenceString(""), ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aDecrement", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Card"),
parseSequenceString("-"),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aManageSets", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Manage Sets..."),
parseSequenceString(""),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aEditTokens", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Edit Custom Tokens..."),
parseSequenceString(""),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aExportDeckDecklist",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Export Deck (decklist.org)"),
parseSequenceString(""),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aExportDeckDecklistXyz",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Export Deck (decklist.xyz)"),
parseSequenceString(""),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aIncrement", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add Card"),
parseSequenceString("+"),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aLoadDeck", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Load Deck..."),
parseSequenceString("Ctrl+O"),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aLoadDeckFromClipboard",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Load Deck from Clipboard..."),
parseSequenceString("Ctrl+Shift+V"),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aEditDeckInClipboard",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Edit Deck in Clipboard, Annotated"),
parseSequenceString(""),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aEditDeckInClipboardRaw",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Edit Deck in Clipboard"),
parseSequenceString(""),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aNewDeck", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "New Deck"),
parseSequenceString("Ctrl+N"),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aOpenCustomFolder",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Open Custom Pictures Folder"),
parseSequenceString(""),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aPrintDeck", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Print Deck..."),
parseSequenceString("Ctrl+P"),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aRemoveCard", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Delete Card"),
parseSequenceString(""),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aResetLayout", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Reset Layout"),
parseSequenceString(""),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aSaveDeck", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Save Deck"),
parseSequenceString("Ctrl+S"),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aSaveDeckAs", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Save Deck as..."),
parseSequenceString("Ctrl+Shift+S"),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aSaveDeckToClipboard",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Save Deck to Clipboard, Annotated"),
parseSequenceString("Ctrl+Shift+C"),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aSaveDeckToClipboardNoSetInfo",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Save Deck to Clipboard, Annotated (No Set Info)"),
parseSequenceString(""),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aSaveDeckToClipboardRaw",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Save Deck to Clipboard"),
parseSequenceString("Ctrl+Shift+R"),
ShortcutGroup::Deck_Editor)},
{"TabDeckEditor/aSaveDeckToClipboardRawNoSetInfo",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Save Deck to Clipboard (No Set Info)"),
parseSequenceString(""),
ShortcutGroup::Deck_Editor)},
{"DeckViewContainer/loadLocalButton", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Load Local Deck..."),
parseSequenceString("Ctrl+O"),
ShortcutGroup::Game_Lobby)},
{"DeckViewContainer/loadRemoteButton", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Load Remote Deck..."),
parseSequenceString("Ctrl+Alt+O"),
ShortcutGroup::Game_Lobby)},
{"DeckViewContainer/loadFromClipboardButton",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Load Deck from Clipboard..."),
parseSequenceString("Ctrl+Shift+V"),
ShortcutGroup::Game_Lobby)},
{"DeckViewContainer/unloadDeckButton", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Unload Deck"),
parseSequenceString("Ctrl+Alt+U"),
ShortcutGroup::Game_Lobby)},
{"DeckViewContainer/readyStartButton", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Ready to Start"),
parseSequenceString("Ctrl+Shift+S"),
ShortcutGroup::Game_Lobby)},
{"DeckViewContainer/sideboardLockButton",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Toggle Sideboard Lock"),
parseSequenceString("Ctrl+Shift+B"),
ShortcutGroup::Game_Lobby)},
{"DeckViewContainer/forceStartGameButton", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Force Start"),
parseSequenceString(""),
ShortcutGroup::Game_Lobby)},
{"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 Card Counter (C)"),
parseSequenceString("Ctrl+<"),
ShortcutGroup::Card_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 Card Counter (B)"),
parseSequenceString("Ctrl+."),
ShortcutGroup::Card_Counters)},
{"Player/aRCYellow", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Card Counter (B)"),
parseSequenceString("Ctrl+,"),
ShortcutGroup::Card_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 Card Counter (A)"),
parseSequenceString("Alt+."),
ShortcutGroup::Card_Counters)},
{"Player/aRCRed", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Card Counter (A)"),
parseSequenceString("Alt+,"),
ShortcutGroup::Card_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"),
parseSequenceString("F12"),
ShortcutGroup::Player_Counters)},
{"Player/aDec", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Life Counter"),
parseSequenceString("F11"),
ShortcutGroup::Player_Counters)},
{"Player/aSet", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Life Counters..."),
parseSequenceString("Ctrl+L"),
ShortcutGroup::Player_Counters)},
{"Player/aIncCounter_w", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add White Counter"),
parseSequenceString(""),
ShortcutGroup::Player_Counters)},
{"Player/aDecCounter_w", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove White Counter"),
parseSequenceString(""),
ShortcutGroup::Player_Counters)},
{"Player/aSetCounter_w", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set White Counters..."),
parseSequenceString(""),
ShortcutGroup::Player_Counters)},
{"Player/aIncCounter_u", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add Blue Counter"),
parseSequenceString(""),
ShortcutGroup::Player_Counters)},
{"Player/aDecCounter_u", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Blue Counter"),
parseSequenceString(""),
ShortcutGroup::Player_Counters)},
{"Player/aSetCounter_u", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Blue Counters..."),
parseSequenceString(""),
ShortcutGroup::Player_Counters)},
{"Player/aIncCounter_b", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add Black Counter"),
parseSequenceString(""),
ShortcutGroup::Player_Counters)},
{"Player/aDecCounter_b", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Black Counter"),
parseSequenceString(""),
ShortcutGroup::Player_Counters)},
{"Player/aSetCounter_b", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Black Counters..."),
parseSequenceString(""),
ShortcutGroup::Player_Counters)},
{"Player/aIncCounter_r", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add Red Counter"),
parseSequenceString(""),
ShortcutGroup::Player_Counters)},
{"Player/aDecCounter_r", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Red Counter"),
parseSequenceString(""),
ShortcutGroup::Player_Counters)},
{"Player/aSetCounter_r", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Red Counters..."),
parseSequenceString(""),
ShortcutGroup::Player_Counters)},
{"Player/aIncCounter_g", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add Green Counter"),
parseSequenceString(""),
ShortcutGroup::Player_Counters)},
{"Player/aDecCounter_g", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Green Counter"),
parseSequenceString(""),
ShortcutGroup::Player_Counters)},
{"Player/aSetCounter_g", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Green Counters..."),
parseSequenceString(""),
ShortcutGroup::Player_Counters)},
{"Player/aIncCounter_x", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add Colorless Counter"),
parseSequenceString(""),
ShortcutGroup::Player_Counters)},
{"Player/aDecCounter_x", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Colorless Counter"),
parseSequenceString(""),
ShortcutGroup::Player_Counters)},
{"Player/aSetCounter_x", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Colorless Counters..."),
parseSequenceString(""),
ShortcutGroup::Player_Counters)},
{"Player/aIncCounter_storm", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add Other Counter"),
parseSequenceString("Ctrl+]"),
ShortcutGroup::Player_Counters)},
{"Player/aDecCounter_storm", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Other Counter"),
parseSequenceString("Ctrl+["),
ShortcutGroup::Player_Counters)},
{"Player/aSetCounter_storm", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Other Counters..."),
parseSequenceString("Ctrl+\\"),
ShortcutGroup::Player_Counters)},
{"Player/aIncrementAllCardCounters",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Increment all card counters"),
parseSequenceString("Ctrl+Shift+A"),
ShortcutGroup::Playing_Area)},
{"Player/aIncP", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add Power (+1/+0)"),
parseSequenceString("Ctrl++;Ctrl+="),
ShortcutGroup::Power_Toughness)},
{"Player/aDecP", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Power (-1/-0)"),
parseSequenceString("Ctrl+-"),
ShortcutGroup::Power_Toughness)},
{"Player/aFlowP", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Move Toughness to Power (+1/-1)"),
parseSequenceString(""),
ShortcutGroup::Power_Toughness)},
{"Player/aIncT", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add Toughness (+0/+1)"),
parseSequenceString("Alt++;Alt+="),
ShortcutGroup::Power_Toughness)},
{"Player/aDecT", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Toughness (-0/-1)"),
parseSequenceString("Alt+-"),
ShortcutGroup::Power_Toughness)},
{"Player/aFlowT", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Move Power to Toughness (-1/+1)"),
parseSequenceString(""),
ShortcutGroup::Power_Toughness)},
{"Player/aIncPT", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Add Power and Toughness (+1/+1)"),
parseSequenceString("Ctrl+Alt++;Ctrl+Alt+="),
ShortcutGroup::Power_Toughness)},
{"Player/aDecPT", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Power and Toughness (-1/-1)"),
parseSequenceString("Ctrl+Alt+-"),
ShortcutGroup::Power_Toughness)},
{"Player/aSetPT", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Power and Toughness..."),
parseSequenceString("Ctrl+P"),
ShortcutGroup::Power_Toughness)},
{"Player/aResetPT", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Reset Power and Toughness"),
parseSequenceString("Ctrl+Alt+0"),
ShortcutGroup::Power_Toughness)},
{"Player/phase0", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Untap"),
parseSequenceString("F5"),
ShortcutGroup::Game_Phases)},
{"Player/phase1",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Upkeep"), parseSequenceString(""), ShortcutGroup::Game_Phases)},
{"Player/phase2",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Draw"), parseSequenceString("F6"), ShortcutGroup::Game_Phases)},
{"Player/phase3", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "First Main Phase"),
parseSequenceString("F7"),
ShortcutGroup::Game_Phases)},
{"Player/phase4", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Start Combat"),
parseSequenceString("F8"),
ShortcutGroup::Game_Phases)},
{"Player/phase5",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Attack"), parseSequenceString(""), ShortcutGroup::Game_Phases)},
{"Player/phase6",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Block"), parseSequenceString(""), ShortcutGroup::Game_Phases)},
{"Player/phase7",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Damage"), parseSequenceString(""), ShortcutGroup::Game_Phases)},
{"Player/phase8", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "End Combat"),
parseSequenceString(""),
ShortcutGroup::Game_Phases)},
{"Player/phase9", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Second Main Phase"),
parseSequenceString("F9"),
ShortcutGroup::Game_Phases)},
{"Player/phase10",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "End"), parseSequenceString("F10"), ShortcutGroup::Game_Phases)},
{"Player/aNextPhase", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Next Phase"),
parseSequenceString("Ctrl+Space;Tab"),
ShortcutGroup::Game_Phases)},
{"Player/aNextPhaseAction", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Next Phase Action"),
parseSequenceString("Shift+Tab"),
ShortcutGroup::Game_Phases)},
{"Player/aNextTurn", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Next Turn"),
parseSequenceString("Ctrl+Return;Ctrl+Enter"),
ShortcutGroup::Game_Phases)},
{"Player/aHide", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Hide Card in Reveal Window"),
parseSequenceString("Alt+H"),
ShortcutGroup::Playing_Area)},
{"Player/aTap", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Tap / Untap Card"),
parseSequenceString(""),
ShortcutGroup::Playing_Area)},
{"Player/aUntapAll", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Untap All"),
parseSequenceString("Ctrl+U"),
ShortcutGroup::Playing_Area)},
{"Player/aDoesntUntap", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Toggle Untap"),
parseSequenceString("Alt+U"),
ShortcutGroup::Playing_Area)},
{"Player/aFlip", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Turn Card Over"),
parseSequenceString("Alt+F"),
ShortcutGroup::Playing_Area)},
{"Player/aPeek", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Peek Card"),
parseSequenceString("Alt+L"),
ShortcutGroup::Playing_Area)},
{"Player/aPlay", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Play Card"),
parseSequenceString(""),
ShortcutGroup::Playing_Area)},
{"Player/aAttach", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Attach Card..."),
parseSequenceString("Ctrl+Alt+A"),
ShortcutGroup::Playing_Area)},
{"Player/aUnattach", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Unattach Card"),
parseSequenceString("Ctrl+Alt+U"),
ShortcutGroup::Playing_Area)},
{"Player/aClone", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Clone Card"),
parseSequenceString("Ctrl+J"),
ShortcutGroup::Playing_Area)},
{"Player/aCreateToken", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Create Token..."),
parseSequenceString("Ctrl+T"),
ShortcutGroup::Playing_Area)},
{"Player/aCreateRelatedTokens", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Create All Related Tokens"),
parseSequenceString("Ctrl+Shift+T"),
ShortcutGroup::Playing_Area)},
{"Player/aCreateAnotherToken", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Create Another Token"),
parseSequenceString("Ctrl+G"),
ShortcutGroup::Playing_Area)},
{"Player/aSetAnnotation", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Annotation..."),
parseSequenceString("Alt+N"),
ShortcutGroup::Playing_Area)},
{"Player/aSelectAll", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Select All Cards in Zone"),
parseSequenceString("Ctrl+A"),
ShortcutGroup::Playing_Area)},
{"Player/aSelectRow", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Select All Cards in Row"),
parseSequenceString("Ctrl+Shift+X"),
ShortcutGroup::Playing_Area)},
{"Player/aSelectColumn", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Select All Cards in Column"),
parseSequenceString("Ctrl+Shift+C"),
ShortcutGroup::Playing_Area)},
{"Player/aMoveToBottomLibrary", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Bottom of Library"),
parseSequenceString("Ctrl+B"),
ShortcutGroup::Move_selected)},
{"Player/aMoveToExile", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Exile"),
parseSequenceString(""),
ShortcutGroup::Move_selected)},
{"Player/aMoveToGraveyard", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Graveyard"),
parseSequenceString("Ctrl+Del"),
ShortcutGroup::Move_selected)},
{"Player/aMoveToHand",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Hand"), parseSequenceString(""), ShortcutGroup::Move_selected)},
{"Player/aMoveToTopLibrary", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Top of Library"),
parseSequenceString(""),
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",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Hand"), parseSequenceString(""), ShortcutGroup::View)},
{"Player/aSortHand", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Sort Hand"),
parseSequenceString("Ctrl+Shift+H"),
ShortcutGroup::View)},
{"Player/aViewGraveyard",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Graveyard"), parseSequenceString("F4"), ShortcutGroup::View)},
{"Player/aViewLibrary",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Library"), parseSequenceString("F3"), ShortcutGroup::View)},
{"Player/aViewRfg",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Exile"), parseSequenceString(""), ShortcutGroup::View)},
{"Player/aViewSideboard", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Sideboard"),
parseSequenceString("Ctrl+F3"),
ShortcutGroup::View)},
{"Player/aViewTopCards", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Top Cards of Library"),
parseSequenceString("Ctrl+W"),
ShortcutGroup::View)},
{"Player/aViewBottomCards", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Bottom Cards of Library"),
parseSequenceString("Ctrl+Shift+W"),
ShortcutGroup::View)},
{"Player/aCloseMostRecentZoneView", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Close Recent View"),
parseSequenceString("Esc"),
ShortcutGroup::View)},
{"Player/aMoveTopToPlay", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Stack"),
parseSequenceString("Ctrl+Y"),
ShortcutGroup::Move_top)},
{"Player/aMoveTopToPlayFaceDown", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Battlefield, Face Down"),
parseSequenceString("Ctrl+Shift+E"),
ShortcutGroup::Move_top)},
{"Player/aMoveTopCardToGraveyard", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Graveyard"),
parseSequenceString("Alt+Y"),
ShortcutGroup::Move_top)},
{"Player/aMoveTopCardsToGraveyard", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Graveyard (Multiple)"),
parseSequenceString("Alt+M"),
ShortcutGroup::Move_top)},
{"Player/aMoveTopCardToExile",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Exile"), parseSequenceString(""), ShortcutGroup::Move_top)},
{"Player/aMoveTopCardsToExile", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Exile (Multiple)"),
parseSequenceString(""),
ShortcutGroup::Move_top)},
{"Player/aMoveTopCardsUntil", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Stack Until Found"),
parseSequenceString("Ctrl+Shift+Y"),
ShortcutGroup::Move_top)},
{"Player/aMoveTopCardToBottom", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Bottom of Library"),
parseSequenceString(""),
ShortcutGroup::Move_top)},
{"Player/aMoveBottomToPlay",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Stack"), parseSequenceString(""), ShortcutGroup::Move_bottom)},
{"Player/aMoveBottomToPlayFaceDown", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Battlefield, Face Down"),
parseSequenceString(""),
ShortcutGroup::Move_bottom)},
{"Player/aMoveBottomCardToGrave", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Graveyard"),
parseSequenceString(""),
ShortcutGroup::Move_bottom)},
{"Player/aMoveBottomCardsToGrave", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Graveyard (Multiple)"),
parseSequenceString(""),
ShortcutGroup::Move_bottom)},
{"Player/aMoveBottomCardToExile",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Exile"), parseSequenceString(""), ShortcutGroup::Move_bottom)},
{"Player/aMoveBottomCardsToExile", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Exile (Multiple)"),
parseSequenceString(""),
ShortcutGroup::Move_bottom)},
{"Player/aMoveBottomCardToTop", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Top of Library"),
parseSequenceString(""),
ShortcutGroup::Move_bottom)},
{"Player/aDrawBottomCard", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Draw Bottom Card"),
parseSequenceString(""),
ShortcutGroup::Move_bottom)},
{"Player/aDrawBottomCards", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Draw Multiple Cards from Bottom..."),
parseSequenceString(""),
ShortcutGroup::Move_bottom)},
{"Player/aDrawArrow", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Draw Arrow..."),
parseSequenceString("Alt+A"),
ShortcutGroup::Gameplay)},
{"Player/aRemoveLocalArrows", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Remove Local Arrows"),
parseSequenceString("Ctrl+R"),
ShortcutGroup::Gameplay)},
{"Player/aLeaveGame", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Leave Game"),
parseSequenceString("Ctrl+Q"),
ShortcutGroup::Gameplay)},
{"Player/aConcede",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Concede"), parseSequenceString("F2"), ShortcutGroup::Gameplay)},
{"Player/aRollDie", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Roll Dice..."),
parseSequenceString("Ctrl+I"),
ShortcutGroup::Gameplay)},
{"Player/aShuffle", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Shuffle Library"),
parseSequenceString("Ctrl+S"),
ShortcutGroup::Gameplay)},
{"Player/aShuffleTopCards", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Shuffle Top Cards of Library"),
parseSequenceString(""),
ShortcutGroup::Gameplay)},
{"Player/aShuffleBottomCards", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Shuffle Bottom Cards of Library"),
parseSequenceString(""),
ShortcutGroup::Gameplay)},
{"Player/aMulligan", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Mulligan"),
parseSequenceString("Ctrl+M"),
ShortcutGroup::Drawing)},
{"Player/aDrawCard", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Draw a Card"),
parseSequenceString("Ctrl+D"),
ShortcutGroup::Drawing)},
{"Player/aDrawCards", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Draw Multiple Cards..."),
parseSequenceString("Ctrl+E"),
ShortcutGroup::Drawing)},
{"Player/aUndoDraw", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Undo Draw"),
parseSequenceString("Ctrl+Shift+D"),
ShortcutGroup::Drawing)},
{"Player/aAlwaysRevealTopCard", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Always Reveal Top Card"),
parseSequenceString("Ctrl+N"),
ShortcutGroup::Drawing)},
{"Player/aAlwaysLookAtTopCard", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Always Look At Top Card"),
parseSequenceString("Ctrl+Shift+N"),
ShortcutGroup::Drawing)},
{"Player/aRotateViewCW", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Rotate View Clockwise"),
parseSequenceString(""),
ShortcutGroup::Gameplay)},
{"Player/aRotateViewCCW", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Rotate View Counterclockwise"),
parseSequenceString(""),
ShortcutGroup::Gameplay)},
{"Player/unfocusTextBox", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Unfocus Text Box"),
parseSequenceString("Esc"),
ShortcutGroup::Chat_room)},
{"Player/aFocusChat", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Focus Chat"),
parseSequenceString("Shift+Return"),
ShortcutGroup::Chat_room)},
{"tab_room/aClearChat", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Clear Chat"),
parseSequenceString("F12"),
ShortcutGroup::Chat_room)},
{"Player/aResetLayout", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Reset Layout"),
parseSequenceString(""),
ShortcutGroup::Game_window)},
{"DlgLoadDeckFromClipboard/refreshButton", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Refresh"),
parseSequenceString("F5"),
ShortcutGroup::Load_deck)},
{"Replays/aSkipForward", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Skip Forward"),
parseSequenceString("Right"),
ShortcutGroup::Replays)},
{"Replays/aSkipBackward", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Skip Backward"),
parseSequenceString("Left"),
ShortcutGroup::Replays)},
{"Replays/aSkipForwardBig", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Skip Forward by a lot"),
parseSequenceString("Ctrl+Right"),
ShortcutGroup::Replays)},
{"Replays/aSkipBackwardBig", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Skip Backward by a lot"),
parseSequenceString("Ctrl+Left"),
ShortcutGroup::Replays)},
{"Replays/playButton", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Play/Pause"),
parseSequenceString("Space"),
ShortcutGroup::Replays)},
{"Replays/fastForwardButton", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Toggle Fast Forward"),
parseSequenceString("Ctrl+P"),
ShortcutGroup::Replays)},
{"Tabs/aTabDeckEditor",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Deck Editor"), parseSequenceString(""), ShortcutGroup::Tabs)},
{"Tabs/aTabHome",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Home"), parseSequenceString(""), ShortcutGroup::Tabs)},
{"Tabs/aTabVisualDeckStorage", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Visual Deck Storage"),
parseSequenceString(""),
ShortcutGroup::Tabs)},
{"Tabs/aTabDeckStorage",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Deck Storage"), parseSequenceString(""), ShortcutGroup::Tabs)},
{"Tabs/aTabReplays",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Replays"), parseSequenceString(""), ShortcutGroup::Tabs)},
{"Tabs/aTabServer",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Server"), parseSequenceString(""), ShortcutGroup::Tabs)},
{"Tabs/aTabAccount",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Account"), parseSequenceString(""), ShortcutGroup::Tabs)},
{"Tabs/aTabAdmin", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Administration"),
parseSequenceString(""),
ShortcutGroup::Tabs)},
{"Tabs/aTabLogs",
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Logs"), parseSequenceString(""), ShortcutGroup::Tabs)},
};
};
#endif // SHORTCUTSSETTINGS_H