From 23612ba6ecb53f005239fc7d3050b482664433d5 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Thu, 25 Sep 2025 16:35:29 +0200 Subject: [PATCH 1/2] [Card DB Models] Move refactor (#6172) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Refactor CardDatabaseDisplayModel, TokenDisplayModel and TokenEditModel out of CardDatabaseModel. Move every model into an appropriate folder. Took 54 minutes * No folder for database models. Took 6 minutes --------- Co-authored-by: Lukas Brübach --- cockatrice/CMakeLists.txt | 9 +- .../card}/card_completer_proxy_model.cpp | 0 .../card}/card_completer_proxy_model.h | 0 .../{ => model/card}/card_search_model.cpp | 3 +- .../{ => model/card}/card_search_model.h | 2 +- .../card_database_display_model.cpp} | 193 +----------------- .../card_database_display_model.h} | 79 +------ .../database/model/card_database_model.cpp | 146 +++++++++++++ .../src/database/model/card_database_model.h | 56 +++++ .../model/token/token_display_model.cpp | 19 ++ .../model/token/token_display_model.h | 17 ++ .../database/model/token/token_edit_model.cpp | 19 ++ .../database/model/token/token_edit_model.h | 17 ++ cockatrice/src/dialogs/dlg_edit_tokens.cpp | 3 +- .../src/game/dialogs/dlg_create_token.cpp | 3 +- .../deck_editor_database_display_widget.h | 3 +- .../deck_editor_filter_dock_widget.cpp | 2 +- .../visual_database_display_widget.h | 2 +- .../visual_deck_editor_widget.cpp | 6 +- .../visual_deck_editor_widget.h | 5 +- .../src/tabs/abstract_tab_deck_editor.cpp | 2 +- .../src/tabs/api/edhrec/tab_edhrec_main.cpp | 4 +- cockatrice/src/tabs/tab_deck_editor.cpp | 2 +- .../tab_deck_editor_visual.cpp | 2 +- .../tab_deck_storage_visual.cpp | 2 +- 25 files changed, 315 insertions(+), 281 deletions(-) rename cockatrice/src/database/{ => model/card}/card_completer_proxy_model.cpp (100%) rename cockatrice/src/database/{ => model/card}/card_completer_proxy_model.h (100%) rename cockatrice/src/database/{ => model/card}/card_search_model.cpp (96%) rename cockatrice/src/database/{ => model/card}/card_search_model.h (94%) rename cockatrice/src/database/{card_database_model.cpp => model/card_database_display_model.cpp} (56%) rename cockatrice/src/database/{card_database_model.h => model/card_database_display_model.h} (52%) create mode 100644 cockatrice/src/database/model/card_database_model.cpp create mode 100644 cockatrice/src/database/model/card_database_model.h create mode 100644 cockatrice/src/database/model/token/token_display_model.cpp create mode 100644 cockatrice/src/database/model/token/token_display_model.h create mode 100644 cockatrice/src/database/model/token/token_edit_model.cpp create mode 100644 cockatrice/src/database/model/token/token_edit_model.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 8ab72174d..11b5275e6 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -21,11 +21,14 @@ set(cockatrice_SOURCES src/client/sound_engine.cpp src/client/tapped_out_interface.cpp src/client/update_downloader.cpp - src/database/card_completer_proxy_model.cpp src/database/card_database.cpp src/database/card_database_manager.cpp - src/database/card_database_model.cpp - src/database/card_search_model.cpp + src/database/model/card_database_model.cpp + src/database/model/card_database_display_model.cpp + src/database/model/card/card_completer_proxy_model.cpp + src/database/model/card/card_search_model.cpp + src/database/model/token/token_display_model.cpp + src/database/model/token/token_edit_model.cpp src/database/parser/card_database_parser.cpp src/database/parser/cockatrice_xml_3.cpp src/database/parser/cockatrice_xml_4.cpp diff --git a/cockatrice/src/database/card_completer_proxy_model.cpp b/cockatrice/src/database/model/card/card_completer_proxy_model.cpp similarity index 100% rename from cockatrice/src/database/card_completer_proxy_model.cpp rename to cockatrice/src/database/model/card/card_completer_proxy_model.cpp diff --git a/cockatrice/src/database/card_completer_proxy_model.h b/cockatrice/src/database/model/card/card_completer_proxy_model.h similarity index 100% rename from cockatrice/src/database/card_completer_proxy_model.h rename to cockatrice/src/database/model/card/card_completer_proxy_model.h diff --git a/cockatrice/src/database/card_search_model.cpp b/cockatrice/src/database/model/card/card_search_model.cpp similarity index 96% rename from cockatrice/src/database/card_search_model.cpp rename to cockatrice/src/database/model/card/card_search_model.cpp index e1240cecf..d39a2207d 100644 --- a/cockatrice/src/database/card_search_model.cpp +++ b/cockatrice/src/database/model/card/card_search_model.cpp @@ -1,6 +1,7 @@ #include "card_search_model.h" -#include "../utility/levenshtein.h" +#include "../../../utility/levenshtein.h" +#include "../card_database_model.h" #include diff --git a/cockatrice/src/database/card_search_model.h b/cockatrice/src/database/model/card/card_search_model.h similarity index 94% rename from cockatrice/src/database/card_search_model.h rename to cockatrice/src/database/model/card/card_search_model.h index c0575cb61..aa9939662 100644 --- a/cockatrice/src/database/card_search_model.h +++ b/cockatrice/src/database/model/card/card_search_model.h @@ -1,7 +1,7 @@ #ifndef CARD_SEARCH_MODEL_H #define CARD_SEARCH_MODEL_H -#include "card_database_model.h" +#include "../card_database_display_model.h" #include diff --git a/cockatrice/src/database/card_database_model.cpp b/cockatrice/src/database/model/card_database_display_model.cpp similarity index 56% rename from cockatrice/src/database/card_database_model.cpp rename to cockatrice/src/database/model/card_database_display_model.cpp index 6d99e563b..fc1b20cf6 100644 --- a/cockatrice/src/database/card_database_model.cpp +++ b/cockatrice/src/database/model/card_database_display_model.cpp @@ -1,157 +1,7 @@ +#include "card_database_display_model.h" + #include "card_database_model.h" -#include "../filters/filter_tree.h" - -#include - -#define CARDDBMODEL_COLUMNS 6 - -CardDatabaseModel::CardDatabaseModel(CardDatabase *_db, bool _showOnlyCardsFromEnabledSets, QObject *parent) - : QAbstractListModel(parent), db(_db), showOnlyCardsFromEnabledSets(_showOnlyCardsFromEnabledSets) -{ - connect(db, &CardDatabase::cardAdded, this, &CardDatabaseModel::cardAdded); - connect(db, &CardDatabase::cardRemoved, this, &CardDatabaseModel::cardRemoved); - connect(db, &CardDatabase::cardDatabaseEnabledSetsChanged, this, - &CardDatabaseModel::cardDatabaseEnabledSetsChanged); - - cardDatabaseEnabledSetsChanged(); -} - -CardDatabaseModel::~CardDatabaseModel() = default; - -QMap CardDatabaseDisplayModel::characterTranslation = {{L'“', L'\"'}, - {L'”', L'\"'}, - {L'‘', L'\''}, - {L'’', L'\''}}; - -int CardDatabaseModel::rowCount(const QModelIndex & /*parent*/) const -{ - return cardList.size(); -} - -int CardDatabaseModel::columnCount(const QModelIndex & /*parent*/) const -{ - return CARDDBMODEL_COLUMNS; -} - -QVariant CardDatabaseModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid() || index.row() >= cardList.size() || index.column() >= CARDDBMODEL_COLUMNS || - (role != Qt::DisplayRole && role != SortRole)) - return QVariant(); - - CardInfoPtr card = cardList.at(index.row()); - switch (index.column()) { - case NameColumn: - return card->getName(); - case SetListColumn: - return card->getSetsNames(); - case ManaCostColumn: - return role == SortRole ? QString("%1%2").arg(card->getCmc(), 4, QChar('0')).arg(card->getManaCost()) - : card->getManaCost(); - case CardTypeColumn: - return card->getCardType(); - case PTColumn: - return card->getPowTough(); - case ColorColumn: - return card->getColors(); - default: - return QVariant(); - } -} - -QVariant CardDatabaseModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (role != Qt::DisplayRole) - return QVariant(); - if (orientation != Qt::Horizontal) - return QVariant(); - switch (section) { - case NameColumn: - return QString(tr("Name")); - case SetListColumn: - return QString(tr("Sets")); - case ManaCostColumn: - return QString(tr("Mana cost")); - case CardTypeColumn: - return QString(tr("Card type")); - case PTColumn: - return QString(tr("P/T")); - case ColorColumn: - return QString(tr("Color(s)")); - default: - return QVariant(); - } -} - -void CardDatabaseModel::cardInfoChanged(CardInfoPtr card) -{ - const int row = cardList.indexOf(card); - if (row == -1) - return; - - emit dataChanged(index(row, 0), index(row, CARDDBMODEL_COLUMNS - 1)); -} - -bool CardDatabaseModel::checkCardHasAtLeastOneEnabledSet(CardInfoPtr card) -{ - if (!showOnlyCardsFromEnabledSets) - return true; - - for (const auto &printings : card->getSets()) { - for (const auto &printing : printings) { - if (printing.getSet()->getEnabled()) - return true; - } - } - - return false; -} - -void CardDatabaseModel::cardDatabaseEnabledSetsChanged() -{ - // remove all the cards no more present in at least one enabled set - for (const CardInfoPtr &card : cardList) { - if (!checkCardHasAtLeastOneEnabledSet(card)) { - cardRemoved(card); - } - } - - // re-check all the card currently not shown, maybe their part of a newly-enabled set - for (const CardInfoPtr &card : db->getCardList()) { - if (!cardListSet.contains(card)) { - cardAdded(card); - } - } -} - -void CardDatabaseModel::cardAdded(CardInfoPtr card) -{ - if (checkCardHasAtLeastOneEnabledSet(card)) { - // add the card if it's present in at least one enabled set - beginInsertRows(QModelIndex(), cardList.size(), cardList.size()); - cardList.append(card); - cardListSet.insert(card); - connect(card.data(), &CardInfo::cardInfoChanged, this, &CardDatabaseModel::cardInfoChanged); - endInsertRows(); - } -} - -void CardDatabaseModel::cardRemoved(CardInfoPtr card) -{ - const int row = cardList.indexOf(card); - if (row == -1) { - return; - } - - beginRemoveRows(QModelIndex(), row, row); - disconnect(card.data(), nullptr, this, nullptr); - cardListSet.remove(card); - card.clear(); - cardList.removeAt(row); - endRemoveRows(); -} - CardDatabaseDisplayModel::CardDatabaseDisplayModel(QObject *parent) : QSortFilterProxyModel(parent), isToken(ShowAll), filterString(nullptr) { @@ -165,6 +15,11 @@ CardDatabaseDisplayModel::CardDatabaseDisplayModel(QObject *parent) loadedRowCount = 0; } +QMap CardDatabaseDisplayModel::characterTranslation = {{L'“', L'\"'}, + {L'”', L'\"'}, + {L'‘', L'\''}, + {L'’', L'\''}}; + bool CardDatabaseDisplayModel::canFetchMore(const QModelIndex &index) const { return loadedRowCount < sourceModel()->rowCount(index); @@ -362,36 +217,4 @@ const QString CardDatabaseDisplayModel::sanitizeCardName(const QString &dirtyNam } } return QString::fromStdWString(toReturn); -} - -TokenDisplayModel::TokenDisplayModel(QObject *parent) : CardDatabaseDisplayModel(parent) -{ -} - -bool TokenDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex & /*sourceParent*/) const -{ - CardInfoPtr info = static_cast(sourceModel())->getCard(sourceRow); - return info->getIsToken() && rowMatchesCardName(info); -} - -int TokenDisplayModel::rowCount(const QModelIndex &parent) const -{ - // always load all tokens at start - return QSortFilterProxyModel::rowCount(parent); -} - -TokenEditModel::TokenEditModel(QObject *parent) : CardDatabaseDisplayModel(parent) -{ -} - -bool TokenEditModel::filterAcceptsRow(int sourceRow, const QModelIndex & /*sourceParent*/) const -{ - CardInfoPtr info = static_cast(sourceModel())->getCard(sourceRow); - return info->getIsToken() && info->getSets().contains(CardSet::TOKENS_SETNAME) && rowMatchesCardName(info); -} - -int TokenEditModel::rowCount(const QModelIndex &parent) const -{ - // always load all tokens at start - return QSortFilterProxyModel::rowCount(parent); -} +} \ No newline at end of file diff --git a/cockatrice/src/database/card_database_model.h b/cockatrice/src/database/model/card_database_display_model.h similarity index 52% rename from cockatrice/src/database/card_database_model.h rename to cockatrice/src/database/model/card_database_display_model.h index 9f11c6611..0515c7624 100644 --- a/cockatrice/src/database/card_database_model.h +++ b/cockatrice/src/database/model/card_database_display_model.h @@ -1,63 +1,14 @@ -#ifndef CARDDATABASEMODEL_H -#define CARDDATABASEMODEL_H +#ifndef COCKATRICE_CARD_DATABASE_DISPLAY_MODEL_H +#define COCKATRICE_CARD_DATABASE_DISPLAY_MODEL_H -#include "../filters/filter_string.h" -#include "card_database.h" +#include "../../filters/filter_string.h" -#include #include #include #include #include class FilterTree; - -class CardDatabaseModel : public QAbstractListModel -{ - Q_OBJECT -public: - enum Columns - { - NameColumn, - SetListColumn, - ManaCostColumn, - PTColumn, - CardTypeColumn, - ColorColumn - }; - enum Role - { - SortRole = Qt::UserRole - }; - CardDatabaseModel(CardDatabase *_db, bool _showOnlyCardsFromEnabledSets, QObject *parent = nullptr); - ~CardDatabaseModel() override; - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - int columnCount(const QModelIndex &parent = QModelIndex()) const override; - QVariant data(const QModelIndex &index, int role) const override; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - CardDatabase *getDatabase() const - { - return db; - } - CardInfoPtr getCard(int index) const - { - return cardList[index]; - } - -private: - QList cardList; - QSet cardListSet; // Supports faster lookups in cardDatabaseEnabledSetsChanged() - CardDatabase *db; - bool showOnlyCardsFromEnabledSets; - - inline bool checkCardHasAtLeastOneEnabledSet(CardInfoPtr card); -private slots: - void cardAdded(CardInfoPtr card); - void cardRemoved(CardInfoPtr card); - void cardInfoChanged(CardInfoPtr card); - void cardDatabaseEnabledSetsChanged(); -}; - class CardDatabaseDisplayModel : public QSortFilterProxyModel { Q_OBJECT @@ -138,26 +89,4 @@ private slots: const QString sanitizeCardName(const QString &dirtyName, const QMap &table); }; -class TokenDisplayModel : public CardDatabaseDisplayModel -{ - Q_OBJECT -public: - explicit TokenDisplayModel(QObject *parent = nullptr); - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - -protected: - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; -}; - -class TokenEditModel : public CardDatabaseDisplayModel -{ - Q_OBJECT -public: - explicit TokenEditModel(QObject *parent = nullptr); - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - -protected: - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; -}; - -#endif +#endif // COCKATRICE_CARD_DATABASE_DISPLAY_MODEL_H diff --git a/cockatrice/src/database/model/card_database_model.cpp b/cockatrice/src/database/model/card_database_model.cpp new file mode 100644 index 000000000..02175081b --- /dev/null +++ b/cockatrice/src/database/model/card_database_model.cpp @@ -0,0 +1,146 @@ +#include "card_database_model.h" + +#include + +#define CARDDBMODEL_COLUMNS 6 + +CardDatabaseModel::CardDatabaseModel(CardDatabase *_db, bool _showOnlyCardsFromEnabledSets, QObject *parent) + : QAbstractListModel(parent), db(_db), showOnlyCardsFromEnabledSets(_showOnlyCardsFromEnabledSets) +{ + connect(db, &CardDatabase::cardAdded, this, &CardDatabaseModel::cardAdded); + connect(db, &CardDatabase::cardRemoved, this, &CardDatabaseModel::cardRemoved); + connect(db, &CardDatabase::cardDatabaseEnabledSetsChanged, this, + &CardDatabaseModel::cardDatabaseEnabledSetsChanged); + + cardDatabaseEnabledSetsChanged(); +} + +CardDatabaseModel::~CardDatabaseModel() = default; + +int CardDatabaseModel::rowCount(const QModelIndex & /*parent*/) const +{ + return cardList.size(); +} + +int CardDatabaseModel::columnCount(const QModelIndex & /*parent*/) const +{ + return CARDDBMODEL_COLUMNS; +} + +QVariant CardDatabaseModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() >= cardList.size() || index.column() >= CARDDBMODEL_COLUMNS || + (role != Qt::DisplayRole && role != SortRole)) + return QVariant(); + + CardInfoPtr card = cardList.at(index.row()); + switch (index.column()) { + case NameColumn: + return card->getName(); + case SetListColumn: + return card->getSetsNames(); + case ManaCostColumn: + return role == SortRole ? QString("%1%2").arg(card->getCmc(), 4, QChar('0')).arg(card->getManaCost()) + : card->getManaCost(); + case CardTypeColumn: + return card->getCardType(); + case PTColumn: + return card->getPowTough(); + case ColorColumn: + return card->getColors(); + default: + return QVariant(); + } +} + +QVariant CardDatabaseModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role != Qt::DisplayRole) + return QVariant(); + if (orientation != Qt::Horizontal) + return QVariant(); + switch (section) { + case NameColumn: + return QString(tr("Name")); + case SetListColumn: + return QString(tr("Sets")); + case ManaCostColumn: + return QString(tr("Mana cost")); + case CardTypeColumn: + return QString(tr("Card type")); + case PTColumn: + return QString(tr("P/T")); + case ColorColumn: + return QString(tr("Color(s)")); + default: + return QVariant(); + } +} + +void CardDatabaseModel::cardInfoChanged(CardInfoPtr card) +{ + const int row = cardList.indexOf(card); + if (row == -1) + return; + + emit dataChanged(index(row, 0), index(row, CARDDBMODEL_COLUMNS - 1)); +} + +bool CardDatabaseModel::checkCardHasAtLeastOneEnabledSet(CardInfoPtr card) +{ + if (!showOnlyCardsFromEnabledSets) + return true; + + for (const auto &printings : card->getSets()) { + for (const auto &printing : printings) { + if (printing.getSet()->getEnabled()) + return true; + } + } + + return false; +} + +void CardDatabaseModel::cardDatabaseEnabledSetsChanged() +{ + // remove all the cards no more present in at least one enabled set + for (const CardInfoPtr &card : cardList) { + if (!checkCardHasAtLeastOneEnabledSet(card)) { + cardRemoved(card); + } + } + + // re-check all the card currently not shown, maybe their part of a newly-enabled set + for (const CardInfoPtr &card : db->getCardList()) { + if (!cardListSet.contains(card)) { + cardAdded(card); + } + } +} + +void CardDatabaseModel::cardAdded(CardInfoPtr card) +{ + if (checkCardHasAtLeastOneEnabledSet(card)) { + // add the card if it's present in at least one enabled set + beginInsertRows(QModelIndex(), cardList.size(), cardList.size()); + cardList.append(card); + cardListSet.insert(card); + connect(card.data(), &CardInfo::cardInfoChanged, this, &CardDatabaseModel::cardInfoChanged); + endInsertRows(); + } +} + +void CardDatabaseModel::cardRemoved(CardInfoPtr card) +{ + const int row = cardList.indexOf(card); + if (row == -1) { + return; + } + + beginRemoveRows(QModelIndex(), row, row); + disconnect(card.data(), nullptr, this, nullptr); + cardListSet.remove(card); + card.clear(); + cardList.removeAt(row); + endRemoveRows(); +} diff --git a/cockatrice/src/database/model/card_database_model.h b/cockatrice/src/database/model/card_database_model.h new file mode 100644 index 000000000..fac099f5a --- /dev/null +++ b/cockatrice/src/database/model/card_database_model.h @@ -0,0 +1,56 @@ +#ifndef CARDDATABASEMODEL_H +#define CARDDATABASEMODEL_H + +#include "../card_database.h" + +#include +#include +#include + +class CardDatabaseModel : public QAbstractListModel +{ + Q_OBJECT +public: + enum Columns + { + NameColumn, + SetListColumn, + ManaCostColumn, + PTColumn, + CardTypeColumn, + ColorColumn + }; + enum Role + { + SortRole = Qt::UserRole + }; + CardDatabaseModel(CardDatabase *_db, bool _showOnlyCardsFromEnabledSets, QObject *parent = nullptr); + ~CardDatabaseModel() override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + CardDatabase *getDatabase() const + { + return db; + } + CardInfoPtr getCard(int index) const + { + return cardList[index]; + } + +private: + QList cardList; + QSet cardListSet; // Supports faster lookups in cardDatabaseEnabledSetsChanged() + CardDatabase *db; + bool showOnlyCardsFromEnabledSets; + + inline bool checkCardHasAtLeastOneEnabledSet(CardInfoPtr card); +private slots: + void cardAdded(CardInfoPtr card); + void cardRemoved(CardInfoPtr card); + void cardInfoChanged(CardInfoPtr card); + void cardDatabaseEnabledSetsChanged(); +}; + +#endif diff --git a/cockatrice/src/database/model/token/token_display_model.cpp b/cockatrice/src/database/model/token/token_display_model.cpp new file mode 100644 index 000000000..4282c6dc8 --- /dev/null +++ b/cockatrice/src/database/model/token/token_display_model.cpp @@ -0,0 +1,19 @@ +#include "token_display_model.h" + +#include "../card_database_model.h" + +TokenDisplayModel::TokenDisplayModel(QObject *parent) : CardDatabaseDisplayModel(parent) +{ +} + +bool TokenDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex & /*sourceParent*/) const +{ + CardInfoPtr info = static_cast(sourceModel())->getCard(sourceRow); + return info->getIsToken() && rowMatchesCardName(info); +} + +int TokenDisplayModel::rowCount(const QModelIndex &parent) const +{ + // always load all tokens at start + return QSortFilterProxyModel::rowCount(parent); +} \ No newline at end of file diff --git a/cockatrice/src/database/model/token/token_display_model.h b/cockatrice/src/database/model/token/token_display_model.h new file mode 100644 index 000000000..50d351653 --- /dev/null +++ b/cockatrice/src/database/model/token/token_display_model.h @@ -0,0 +1,17 @@ +#ifndef COCKATRICE_TOKEN_DISPLAY_MODEL_H +#define COCKATRICE_TOKEN_DISPLAY_MODEL_H + +#include "../card_database_display_model.h" + +class TokenDisplayModel : public CardDatabaseDisplayModel +{ + Q_OBJECT +public: + explicit TokenDisplayModel(QObject *parent = nullptr); + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + +protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; +}; + +#endif // COCKATRICE_TOKEN_DISPLAY_MODEL_H diff --git a/cockatrice/src/database/model/token/token_edit_model.cpp b/cockatrice/src/database/model/token/token_edit_model.cpp new file mode 100644 index 000000000..ad6891d2e --- /dev/null +++ b/cockatrice/src/database/model/token/token_edit_model.cpp @@ -0,0 +1,19 @@ +#include "token_edit_model.h" + +#include "../card_database_model.h" + +TokenEditModel::TokenEditModel(QObject *parent) : CardDatabaseDisplayModel(parent) +{ +} + +bool TokenEditModel::filterAcceptsRow(int sourceRow, const QModelIndex & /*sourceParent*/) const +{ + CardInfoPtr info = static_cast(sourceModel())->getCard(sourceRow); + return info->getIsToken() && info->getSets().contains(CardSet::TOKENS_SETNAME) && rowMatchesCardName(info); +} + +int TokenEditModel::rowCount(const QModelIndex &parent) const +{ + // always load all tokens at start + return QSortFilterProxyModel::rowCount(parent); +} \ No newline at end of file diff --git a/cockatrice/src/database/model/token/token_edit_model.h b/cockatrice/src/database/model/token/token_edit_model.h new file mode 100644 index 000000000..3ae2278cf --- /dev/null +++ b/cockatrice/src/database/model/token/token_edit_model.h @@ -0,0 +1,17 @@ +#ifndef COCKATRICE_TOKEN_EDIT_MODEL_H +#define COCKATRICE_TOKEN_EDIT_MODEL_H + +#include "../card_database_display_model.h" + +class TokenEditModel : public CardDatabaseDisplayModel +{ + Q_OBJECT +public: + explicit TokenEditModel(QObject *parent = nullptr); + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + +protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; +}; + +#endif // COCKATRICE_TOKEN_EDIT_MODEL_H diff --git a/cockatrice/src/dialogs/dlg_edit_tokens.cpp b/cockatrice/src/dialogs/dlg_edit_tokens.cpp index 2c302d774..8ad0fdbbc 100644 --- a/cockatrice/src/dialogs/dlg_edit_tokens.cpp +++ b/cockatrice/src/dialogs/dlg_edit_tokens.cpp @@ -3,7 +3,8 @@ #include "../client/get_text_with_max.h" #include "../database/card_database.h" #include "../database/card_database_manager.h" -#include "../database/card_database_model.h" +#include "../database/model/card_database_model.h" +#include "../database/model/token/token_edit_model.h" #include "../main.h" #include "trice_limits.h" diff --git a/cockatrice/src/game/dialogs/dlg_create_token.cpp b/cockatrice/src/game/dialogs/dlg_create_token.cpp index 132ee988c..101727bee 100644 --- a/cockatrice/src/game/dialogs/dlg_create_token.cpp +++ b/cockatrice/src/game/dialogs/dlg_create_token.cpp @@ -1,7 +1,8 @@ #include "dlg_create_token.h" #include "../../database/card_database_manager.h" -#include "../../database/card_database_model.h" +#include "../../database/model/card_database_model.h" +#include "../../database/model/token/token_display_model.h" #include "../../interface/widgets/cards/card_info_picture_widget.h" #include "../../main.h" #include "../../settings/cache_settings.h" diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.h b/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.h index 40bd95062..3944b03f6 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.h +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.h @@ -1,7 +1,8 @@ #ifndef DECK_EDITOR_DATABASE_DISPLAY_WIDGET_H #define DECK_EDITOR_DATABASE_DISPLAY_WIDGET_H -#include "../../../database/card_database_model.h" +#include "../../../database/model/card_database_display_model.h" +#include "../../../database/model/card_database_model.h" #include "../../../deck/custom_line_edit.h" #include "../../../tabs/abstract_tab_deck_editor.h" #include "../../../utility/key_signals.h" diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.cpp index 32b9c66c4..51d0cdbbe 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.cpp @@ -1,6 +1,6 @@ #include "deck_editor_filter_dock_widget.h" -#include "../../../database/card_database_model.h" +#include "../../../database/model/card_database_model.h" #include "../../../filters/filter_builder.h" #include "../../../filters/filter_tree_model.h" #include "../../../settings/cache_settings.h" diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h index ea9deebc0..ec7bc9d5c 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h @@ -2,7 +2,7 @@ #define VISUAL_DATABASE_DISPLAY_WIDGET_H #include "../../../database/card_database.h" -#include "../../../database/card_database_model.h" +#include "../../../database/model/card_database_model.h" #include "../../../deck/custom_line_edit.h" #include "../../../deck/deck_list_model.h" #include "../../../filters/filter_tree_model.h" diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp index 0f73bbf6c..369e09be2 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp @@ -1,10 +1,10 @@ #include "visual_deck_editor_widget.h" -#include "../../../database/card_completer_proxy_model.h" #include "../../../database/card_database.h" #include "../../../database/card_database_manager.h" -#include "../../../database/card_database_model.h" -#include "../../../database/card_search_model.h" +#include "../../../database/model/card/card_completer_proxy_model.h" +#include "../../../database/model/card/card_search_model.h" +#include "../../../database/model/card_database_model.h" #include "../../../deck/deck_list_model.h" #include "../../../deck/deck_loader.h" #include "../../../main.h" diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h index 2386c20b6..cd5cfcd98 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h @@ -1,9 +1,10 @@ #ifndef VISUAL_DECK_EDITOR_H #define VISUAL_DECK_EDITOR_H -#include "../../../database/card_completer_proxy_model.h" #include "../../../database/card_database.h" -#include "../../../database/card_database_model.h" +#include "../../../database/model/card/card_completer_proxy_model.h" +#include "../../../database/model/card_database_display_model.h" +#include "../../../database/model/card_database_model.h" #include "../../../deck/deck_list_model.h" #include "../cards/card_info_picture_with_text_overlay_widget.h" #include "../cards/card_size_widget.h" diff --git a/cockatrice/src/tabs/abstract_tab_deck_editor.cpp b/cockatrice/src/tabs/abstract_tab_deck_editor.cpp index f5717cd85..455b5ca29 100644 --- a/cockatrice/src/tabs/abstract_tab_deck_editor.cpp +++ b/cockatrice/src/tabs/abstract_tab_deck_editor.cpp @@ -2,7 +2,7 @@ #include "../client/tapped_out_interface.h" #include "../database/card_database_manager.h" -#include "../database/card_database_model.h" +#include "../database/model/card_database_model.h" #include "../deck/deck_stats_interface.h" #include "../dialogs/dlg_load_deck.h" #include "../dialogs/dlg_load_deck_from_clipboard.h" diff --git a/cockatrice/src/tabs/api/edhrec/tab_edhrec_main.cpp b/cockatrice/src/tabs/api/edhrec/tab_edhrec_main.cpp index 97bc6b5a9..4a0afc099 100644 --- a/cockatrice/src/tabs/api/edhrec/tab_edhrec_main.cpp +++ b/cockatrice/src/tabs/api/edhrec/tab_edhrec_main.cpp @@ -1,8 +1,8 @@ #include "tab_edhrec_main.h" -#include "../../../database/card_completer_proxy_model.h" #include "../../../database/card_database_manager.h" -#include "../../../database/card_search_model.h" +#include "../../../database/model/card/card_completer_proxy_model.h" +#include "../../../database/model/card/card_search_model.h" #include "../../tab_supervisor.h" #include "api_response/average_deck/edhrec_average_deck_api_response.h" #include "api_response/commander/edhrec_commander_api_response.h" diff --git a/cockatrice/src/tabs/tab_deck_editor.cpp b/cockatrice/src/tabs/tab_deck_editor.cpp index e6e0258d4..b17eb5ff1 100644 --- a/cockatrice/src/tabs/tab_deck_editor.cpp +++ b/cockatrice/src/tabs/tab_deck_editor.cpp @@ -3,7 +3,7 @@ #include "../client/deck_editor_menu.h" #include "../client/tapped_out_interface.h" #include "../database/card_database_manager.h" -#include "../database/card_database_model.h" +#include "../database/model/card_database_model.h" #include "../dialogs/dlg_load_deck.h" #include "../dialogs/dlg_load_deck_from_clipboard.h" #include "../filters/filter_builder.h" diff --git a/cockatrice/src/tabs/visual_deck_editor/tab_deck_editor_visual.cpp b/cockatrice/src/tabs/visual_deck_editor/tab_deck_editor_visual.cpp index 502ef09e1..d8584433d 100644 --- a/cockatrice/src/tabs/visual_deck_editor/tab_deck_editor_visual.cpp +++ b/cockatrice/src/tabs/visual_deck_editor/tab_deck_editor_visual.cpp @@ -1,6 +1,6 @@ #include "tab_deck_editor_visual.h" -#include "../../database/card_database_model.h" +#include "../../database/model/card_database_model.h" #include "../../deck/deck_list_model.h" #include "../../deck/deck_stats_interface.h" #include "../../filters/filter_builder.h" diff --git a/cockatrice/src/tabs/visual_deck_storage/tab_deck_storage_visual.cpp b/cockatrice/src/tabs/visual_deck_storage/tab_deck_storage_visual.cpp index e8b6bce6f..ea8822213 100644 --- a/cockatrice/src/tabs/visual_deck_storage/tab_deck_storage_visual.cpp +++ b/cockatrice/src/tabs/visual_deck_storage/tab_deck_storage_visual.cpp @@ -1,6 +1,6 @@ #include "tab_deck_storage_visual.h" -#include "../../database/card_database_model.h" +#include "../../database/model/card_database_model.h" #include "../../interface/widgets/cards/deck_preview_card_picture_widget.h" #include "../../interface/widgets/visual_deck_storage/visual_deck_storage_widget.h" #include "../tab_supervisor.h" From 762ea47b8ea73092371896583e2e236a69cb1302 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Thu, 25 Sep 2025 19:36:46 +0200 Subject: [PATCH 2/2] [Card DB] Various little fixes and cleanups (#6174) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Simplify add card. Took 25 minutes Took 6 minutes * Simplify guessCard. Took 2 minutes * Simplify loadCardDatabases. Took 3 minutes Took 6 seconds * Clean up mutexes instead of manually locking/unlocking. Took 5 minutes * Fix null/empty check. Took 3 minutes * Move some stuff around inside the file. Took 4 minutes * Move some more things. Took 2 minutes * Clean up refreshCachedReverseRelatedCards. Took 2 minutes Took 6 seconds * Clean up getCardFromSameSet. Took 2 minutes * Lint. Took 5 minutes * Fix compiler warning. Took 4 minutes --------- Co-authored-by: Lukas Brübach --- cockatrice/src/database/card_database.cpp | 424 +++++++++++----------- cockatrice/src/database/card_database.h | 2 + 2 files changed, 207 insertions(+), 219 deletions(-) diff --git a/cockatrice/src/database/card_database.cpp b/cockatrice/src/database/card_database.cpp index 315716884..9ed89a11d 100644 --- a/cockatrice/src/database/card_database.cpp +++ b/cockatrice/src/database/card_database.cpp @@ -43,7 +43,7 @@ CardDatabase::~CardDatabase() void CardDatabase::clear() { - clearDatabaseMutex->lock(); + QMutexLocker locker(clearDatabaseMutex); for (const auto &card : cards.values()) { if (card) { @@ -58,8 +58,110 @@ void CardDatabase::clear() ICardDatabaseParser::clearSetlist(); loadStatus = NotLoaded; +} - clearDatabaseMutex->unlock(); +LoadStatus CardDatabase::loadFromFile(const QString &fileName) +{ + QFile file(fileName); + file.open(QIODevice::ReadOnly); + if (!file.isOpen()) { + return FileError; + } + + for (auto parser : availableParsers) { + file.reset(); + if (parser->getCanParseFile(fileName, file)) { + file.reset(); + parser->parseFile(file); + return Ok; + } + } + + return Invalid; +} + +LoadStatus CardDatabase::loadCardDatabase(const QString &path) +{ + auto startTime = QTime::currentTime(); + LoadStatus tempLoadStatus = NotLoaded; + if (!path.isEmpty()) { + QMutexLocker locker(loadFromFileMutex); + tempLoadStatus = loadFromFile(path); + } + + int msecs = startTime.msecsTo(QTime::currentTime()); + qCInfo(CardDatabaseLoadingLog) << "Loaded card database: Path =" << path << "Status =" << tempLoadStatus + << "Cards =" << cards.size() << "Sets =" << sets.size() + << QString("%1ms").arg(msecs); + + return tempLoadStatus; +} + +LoadStatus CardDatabase::loadCardDatabases() +{ + QMutexLocker locker(reloadDatabaseMutex); + qCInfo(CardDatabaseLoadingLog) << "Card Database Loading Started"; + + clear(); // remove old db + + loadStatus = loadCardDatabase(SettingsCache::instance().getCardDatabasePath()); // load main card database + loadCardDatabase(SettingsCache::instance().getTokenDatabasePath()); // load tokens database + loadCardDatabase(SettingsCache::instance().getSpoilerCardDatabasePath()); // load spoilers database + + // find all custom card databases, recursively & following symlinks + // then load them alphabetically + auto customPaths = collectCustomDatabasePaths(); + for (int i = 0, n = customPaths.size(); i < n; ++i) { + const auto &path = customPaths.at(i); + qCInfo(CardDatabaseLoadingLog) << "Loading Custom Set" << i << "(" << path << ")"; + loadCardDatabase(path); + } + + // AFTER all the cards have been loaded + + // resolve the reverse-related tags + + refreshCachedReverseRelatedCards(); + + if (loadStatus == Ok) { + checkUnknownSets(); // update deck editors, etc + qCInfo(CardDatabaseLoadingSuccessOrFailureLog) << "Card Database Loading Success"; + emit cardDatabaseLoadingFinished(); + } else { + qCInfo(CardDatabaseLoadingSuccessOrFailureLog) << "Card Database Loading Failed"; + emit cardDatabaseLoadingFailed(); // bring up the settings dialog + } + + return loadStatus; +} + +QStringList CardDatabase::collectCustomDatabasePaths() +{ + QDirIterator it(SettingsCache::instance().getCustomCardDatabasePath(), {"*.xml"}, QDir::Files, + QDirIterator::Subdirectories | QDirIterator::FollowSymlinks); + + QStringList paths; + while (it.hasNext()) + paths << it.next(); + paths.sort(); + return paths; +} + +void CardDatabase::refreshCachedReverseRelatedCards() +{ + for (const auto &card : cards) { + card->resetReverseRelatedCards2Me(); + } + + for (const auto &card : cards) { + for (auto *rel : card->getReverseRelatedCards()) { + if (auto target = cards.value(rel->getName())) { + auto *newRel = new CardRelation(card->getName(), rel->getAttachType(), rel->getIsCreateAllExclusion(), + rel->getIsVariable(), rel->getDefaultCount(), rel->getIsPersistent()); + target->addReverseRelatedCards2Me(newRel); + } + } + } } void CardDatabase::addCard(CardInfoPtr card) @@ -69,21 +171,20 @@ void CardDatabase::addCard(CardInfoPtr card) return; } - // if card already exists just add the new set property - if (cards.contains(card->getName())) { - CardInfoPtr sameCard = cards[card->getName()]; - for (const auto &printings : card->getSets()) { - for (const PrintingInfo &printing : printings) { - sameCard->addToSet(printing.getSet(), printing); - } - } + auto name = card->getName(); + + // If a card already exists, just add the new set property. + if (auto existing = cards.value(name)) { + for (const auto &printings : card->getSets()) + for (const auto &printing : printings) + existing->addToSet(printing.getSet(), printing); return; } - addCardMutex->lock(); - cards.insert(card->getName(), card); + QMutexLocker locker(addCardMutex); + cards.insert(name, card); simpleNameCards.insert(card->getSimpleName(), card); - addCardMutex->unlock(); + emit cardAdded(card); } @@ -103,10 +204,9 @@ void CardDatabase::removeCard(CardInfoPtr card) for (auto *cardRelation : card->getReverseRelatedCards2Me()) cardRelation->deleteLater(); - removeCardMutex->lock(); + QMutexLocker locker(removeCardMutex); cards.remove(card->getName()); simpleNameCards.remove(card->getSimpleName()); - removeCardMutex->unlock(); emit cardRemoved(card); } @@ -187,6 +287,15 @@ CardInfoPtr CardDatabase::getCardBySimpleName(const QString &cardName) const return simpleNameCards.value(CardInfo::simplifyName(cardName)); } +CardInfoPtr CardDatabase::lookupCardByName(const QString &name) const +{ + if (auto info = getCardInfo(name)) + return info; + if (auto info = getCardBySimpleName(name)) + return info; + return getCardBySimpleName(CardInfo::simplifyName(name)); +} + /** * Looks up the card by CardRef, simplifying the name if required. * If the providerId is empty, will default to the preferred printing. @@ -197,21 +306,11 @@ CardInfoPtr CardDatabase::getCardBySimpleName(const QString &cardName) const */ ExactCard CardDatabase::guessCard(const CardRef &cardRef) const { - CardInfoPtr temp = getCardInfo(cardRef.name); + auto card = lookupCardByName(cardRef.name); + auto printing = + cardRef.providerId.isEmpty() ? getPreferredPrinting(card) : findPrintingWithId(card, cardRef.providerId); - if (temp == nullptr) { // get card by simple name instead - temp = getCardBySimpleName(cardRef.name); - if (temp == nullptr) { // still could not find the card, so simplify the cardName too - const auto &simpleCardName = CardInfo::simplifyName(cardRef.name); - temp = getCardBySimpleName(simpleCardName); - } - } - - if (cardRef.providerId.isEmpty() || cardRef.providerId.isNull()) { - return ExactCard(temp, getPreferredPrinting(temp)); - } - - return ExactCard(temp, findPrintingWithId(temp, cardRef.providerId)); + return ExactCard(card, printing); } ExactCard CardDatabase::getRandomCard() @@ -227,6 +326,21 @@ ExactCard CardDatabase::getRandomCard() return ExactCard{randomCard, getPreferredPrinting(randomCard)}; } +ExactCard CardDatabase::getCardFromSameSet(const QString &cardName, const PrintingInfo &otherPrinting) const +{ + // The source card does not have a printing defined, which means we can't get a card from the same set. + if (otherPrinting == PrintingInfo()) { + return getCard({cardName}); + } + + // The source card does have a printing defined, which means we can attempt to get a card from the same set. + PrintingInfo relatedPrinting = getSpecificPrinting(cardName, otherPrinting.getSet()->getCorrectedShortName(), ""); + ExactCard relatedCard(guessCard({cardName}).getCardPtr(), relatedPrinting); + + // If we didn't find a card from the same set, just try to find any card with the same name. + return relatedCard ? relatedCard : getCard({cardName}); +} + CardSetPtr CardDatabase::getSet(const QString &setName) { if (sets.contains(setName)) { @@ -252,112 +366,6 @@ SetList CardDatabase::getSetList() const return result; } -LoadStatus CardDatabase::loadFromFile(const QString &fileName) -{ - QFile file(fileName); - file.open(QIODevice::ReadOnly); - if (!file.isOpen()) { - return FileError; - } - - for (auto parser : availableParsers) { - file.reset(); - if (parser->getCanParseFile(fileName, file)) { - file.reset(); - parser->parseFile(file); - return Ok; - } - } - - return Invalid; -} - -LoadStatus CardDatabase::loadCardDatabase(const QString &path) -{ - auto startTime = QTime::currentTime(); - LoadStatus tempLoadStatus = NotLoaded; - if (!path.isEmpty()) { - loadFromFileMutex->lock(); - tempLoadStatus = loadFromFile(path); - loadFromFileMutex->unlock(); - } - - int msecs = startTime.msecsTo(QTime::currentTime()); - qCInfo(CardDatabaseLoadingLog) << "Loaded card database: Path =" << path << "Status =" << tempLoadStatus - << "Cards =" << cards.size() << "Sets =" << sets.size() - << QString("%1ms").arg(msecs); - - return tempLoadStatus; -} - -LoadStatus CardDatabase::loadCardDatabases() -{ - reloadDatabaseMutex->lock(); - - qCInfo(CardDatabaseLoadingLog) << "Card Database Loading Started"; - - clear(); // remove old db - - loadStatus = loadCardDatabase(SettingsCache::instance().getCardDatabasePath()); // load main card database - loadCardDatabase(SettingsCache::instance().getTokenDatabasePath()); // load tokens database - loadCardDatabase(SettingsCache::instance().getSpoilerCardDatabasePath()); // load spoilers database - - // find all custom card databases, recursively & following symlinks - // then load them alphabetically - QDirIterator customDatabaseIterator(SettingsCache::instance().getCustomCardDatabasePath(), QStringList() << "*.xml", - QDir::Files, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks); - QStringList databasePaths; - while (customDatabaseIterator.hasNext()) { - customDatabaseIterator.next(); - databasePaths.push_back(customDatabaseIterator.filePath()); - } - databasePaths.sort(); - - for (auto i = 0; i < databasePaths.size(); ++i) { - const auto &databasePath = databasePaths.at(i); - qCInfo(CardDatabaseLoadingLog) << "Loading Custom Set" << i << "(" << databasePath << ")"; - loadCardDatabase(databasePath); - } - - // AFTER all the cards have been loaded - - // resolve the reverse-related tags - refreshCachedReverseRelatedCards(); - - if (loadStatus == Ok) { - checkUnknownSets(); // update deck editors, etc - qCInfo(CardDatabaseLoadingSuccessOrFailureLog) << "Card Database Loading Success"; - emit cardDatabaseLoadingFinished(); - } else { - qCInfo(CardDatabaseLoadingSuccessOrFailureLog) << "Card Database Loading Failed"; - emit cardDatabaseLoadingFailed(); // bring up the settings dialog - } - - reloadDatabaseMutex->unlock(); - return loadStatus; -} - -/** - * Gets the card representing the preferred printing of the cardInfo - * - * @param cardInfo The cardInfo to find the preferred printing for - * @return A specific printing of a card - */ -ExactCard CardDatabase::getPreferredCard(const CardInfoPtr &cardInfo) const -{ - return ExactCard(cardInfo, getPreferredPrinting(cardInfo)); -} - -PrintingInfo CardDatabase::getSpecificPrinting(const CardRef &cardRef) const -{ - CardInfoPtr cardInfo = getCardInfo(cardRef.name); - if (!cardInfo) { - return PrintingInfo(nullptr); - } - - return findPrintingWithId(cardInfo, cardRef.providerId); -} - /** * Finds the PrintingInfo in the cardInfo that has the given uuid field. * @@ -378,6 +386,68 @@ PrintingInfo CardDatabase::findPrintingWithId(const CardInfoPtr &cardInfo, const return PrintingInfo(); } +PrintingInfo CardDatabase::getSpecificPrinting(const CardRef &cardRef) const +{ + CardInfoPtr cardInfo = getCardInfo(cardRef.name); + if (!cardInfo) { + return PrintingInfo(nullptr); + } + + return findPrintingWithId(cardInfo, cardRef.providerId); +} + +PrintingInfo CardDatabase::getSpecificPrinting(const QString &cardName, + const QString &setShortName, + const QString &collectorNumber) const +{ + CardInfoPtr cardInfo = getCardInfo(cardName); + if (!cardInfo) { + return PrintingInfo(nullptr); + } + + SetToPrintingsMap setMap = cardInfo->getSets(); + if (setMap.empty()) { + return PrintingInfo(nullptr); + } + + for (const auto &printings : setMap) { + for (auto &cardInfoForSet : printings) { + if (!collectorNumber.isEmpty()) { + if (cardInfoForSet.getSet()->getShortName() == setShortName && + cardInfoForSet.getProperty("num") == collectorNumber) { + return cardInfoForSet; + } + } else { + if (cardInfoForSet.getSet()->getShortName() == setShortName) { + return cardInfoForSet; + } + } + } + } + + return PrintingInfo(nullptr); +} + +/** + * Gets the card representing the preferred printing of the cardInfo + * + * @param cardInfo The cardInfo to find the preferred printing for + * @return A specific printing of a card + */ +ExactCard CardDatabase::getPreferredCard(const CardInfoPtr &cardInfo) const +{ + return ExactCard(cardInfo, getPreferredPrinting(cardInfo)); +} + +bool CardDatabase::isPreferredPrinting(const CardRef &cardRef) const +{ + if (cardRef.providerId.startsWith("card_")) { + return cardRef.providerId == + QLatin1String("card_") + cardRef.name + QString("_") + getPreferredPrintingProviderId(cardRef.name); + } + return cardRef.providerId == getPreferredPrintingProviderId(cardRef.name); +} + PrintingInfo CardDatabase::getPreferredPrinting(const QString &cardName) const { CardInfoPtr cardInfo = getCardInfo(cardName); @@ -416,38 +486,6 @@ PrintingInfo CardDatabase::getPreferredPrinting(const CardInfoPtr &cardInfo) con return PrintingInfo(nullptr); } -PrintingInfo CardDatabase::getSpecificPrinting(const QString &cardName, - const QString &setShortName, - const QString &collectorNumber) const -{ - CardInfoPtr cardInfo = getCardInfo(cardName); - if (!cardInfo) { - return PrintingInfo(nullptr); - } - - SetToPrintingsMap setMap = cardInfo->getSets(); - if (setMap.empty()) { - return PrintingInfo(nullptr); - } - - for (const auto &printings : setMap) { - for (auto &cardInfoForSet : printings) { - if (collectorNumber != nullptr) { - if (cardInfoForSet.getSet()->getShortName() == setShortName && - cardInfoForSet.getProperty("num") == collectorNumber) { - return cardInfoForSet; - } - } else { - if (cardInfoForSet.getSet()->getShortName() == setShortName) { - return cardInfoForSet; - } - } - } - } - - return PrintingInfo(nullptr); -} - QString CardDatabase::getPreferredPrintingProviderId(const QString &cardName) const { PrintingInfo preferredPrinting = getPreferredPrinting(cardName); @@ -463,58 +501,6 @@ QString CardDatabase::getPreferredPrintingProviderId(const QString &cardName) co return defaultCardInfo->getName(); } -bool CardDatabase::isPreferredPrinting(const CardRef &cardRef) const -{ - if (cardRef.providerId.startsWith("card_")) { - return cardRef.providerId == - QLatin1String("card_") + cardRef.name + QString("_") + getPreferredPrintingProviderId(cardRef.name); - } - return cardRef.providerId == getPreferredPrintingProviderId(cardRef.name); -} - -ExactCard CardDatabase::getCardFromSameSet(const QString &cardName, const PrintingInfo &otherPrinting) const -{ - // The source card does not have a printing defined, which means we can't get a card from the same set. - if (otherPrinting == PrintingInfo()) { - return getCard({cardName}); - } - - // The source card does have a printing defined, which means we can attempt to get a card from the same set. - PrintingInfo relatedPrinting = getSpecificPrinting(cardName, otherPrinting.getSet()->getCorrectedShortName(), ""); - ExactCard relatedCard = ExactCard(guessCard({cardName}).getCardPtr(), relatedPrinting); - - // We didn't find a card from the same set, just try to find any card with the same name. - if (!relatedCard) { - return getCard({cardName}); - } - - return relatedCard; -} - -void CardDatabase::refreshCachedReverseRelatedCards() -{ - for (const CardInfoPtr &card : cards) - card->resetReverseRelatedCards2Me(); - - for (const CardInfoPtr &card : cards) { - if (card->getReverseRelatedCards().isEmpty()) { - continue; - } - - for (CardRelation *cardRelation : card->getReverseRelatedCards()) { - const QString &targetCard = cardRelation->getName(); - if (!cards.contains(targetCard)) { - continue; - } - - auto *newCardRelation = new CardRelation( - card->getName(), cardRelation->getAttachType(), cardRelation->getIsCreateAllExclusion(), - cardRelation->getIsVariable(), cardRelation->getDefaultCount(), cardRelation->getIsPersistent()); - cards.value(targetCard)->addReverseRelatedCards2Me(newCardRelation); - } - } -} - QStringList CardDatabase::getAllMainCardTypes() const { QSet types; diff --git a/cockatrice/src/database/card_database.h b/cockatrice/src/database/card_database.h index ecfb850ac..d3d98d368 100644 --- a/cockatrice/src/database/card_database.h +++ b/cockatrice/src/database/card_database.h @@ -92,6 +92,7 @@ public: * function, so you don't need to simplify it beforehand. */ [[nodiscard]] CardInfoPtr getCardBySimpleName(const QString &cardName) const; + CardInfoPtr lookupCardByName(const QString &name) const; CardSetPtr getSet(const QString &setName); const CardNameMap &getCardList() const @@ -112,6 +113,7 @@ public: void enableAllUnknownSets(); void markAllSetsAsKnown(); void notifyEnabledSetsChanged(); + static QStringList collectCustomDatabasePaths(); public slots: LoadStatus loadCardDatabases();