[Card DB] Split out database loading and querying from main class (#6175)

* Simplify add card.

Took 25 minutes

Took 8 minutes

# Commit time for manual adjustment:
# Took 16 minutes

Took 7 seconds

* Refactor out db loading from card db.

Took 39 minutes

Took 9 minutes

Took 2 minutes


Took 17 seconds

* Refactor out db queries from card db.

Took 42 minutes

* Lint.

Took 3 minutes

* I guess.

Took 7 minutes

* Tests.

Took 15 minutes

* I don't understand this.

Took 9 minutes

* fix linker errors

* Rename to querier and promote to QObject

Took 39 minutes

* Lint.

Took 3 minutes

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
Co-authored-by: ebbit1q <ebbit1q@gmail.com>
This commit is contained in:
BruebachL 2025-09-27 00:27:15 +02:00 committed by GitHub
parent 754dd904d2
commit d31b044529
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
49 changed files with 719 additions and 572 deletions

View File

@ -22,7 +22,9 @@ set(cockatrice_SOURCES
src/client/tapped_out_interface.cpp
src/client/update_downloader.cpp
src/database/card_database.cpp
src/database/card_database_loader.cpp
src/database/card_database_manager.cpp
src/database/card_database_querier.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

View File

@ -96,7 +96,7 @@ void TappedOutInterface::analyzeDeck(DeckList *deck)
void TappedOutInterface::copyDeckSplitMainAndSide(DeckList &source, DeckList &mainboard, DeckList &sideboard)
{
auto copyMainOrSide = [this, &mainboard, &sideboard](const auto node, const auto card) {
CardInfoPtr dbCard = cardDatabase.getCardInfo(card->getName());
CardInfoPtr dbCard = cardDatabase.query()->getCardInfo(card->getName());
if (!dbCard || dbCard->getIsToken())
return;

View File

@ -2,7 +2,6 @@
#include "../picture_loader/picture_loader.h"
#include "../settings/cache_settings.h"
#include "../utility/card_set_comparator.h"
#include "parser/cockatrice_xml_3.h"
#include "parser/cockatrice_xml_4.h"
@ -14,7 +13,6 @@
#include <QMessageBox>
#include <QRegularExpression>
#include <algorithm>
#include <qrandom.h>
#include <utility>
CardDatabase::CardDatabase(QObject *parent) : QObject(parent), loadStatus(NotLoaded)
@ -22,23 +20,20 @@ CardDatabase::CardDatabase(QObject *parent) : QObject(parent), loadStatus(NotLoa
qRegisterMetaType<CardInfoPtr>("CardInfoPtr");
qRegisterMetaType<CardInfoPtr>("CardSetPtr");
// add new parsers here
availableParsers << new CockatriceXml4Parser;
availableParsers << new CockatriceXml3Parser;
// create loader and wire it up
loader = new CardDatabaseLoader(this, this);
// re-emit loader signals (so other code doesn't need to know about internals)
connect(loader, &CardDatabaseLoader::loadingFinished, this, &CardDatabase::cardDatabaseLoadingFinished);
connect(loader, &CardDatabaseLoader::loadingFailed, this, &CardDatabase::cardDatabaseLoadingFailed);
connect(loader, &CardDatabaseLoader::newSetsFound, this, &CardDatabase::cardDatabaseNewSetsFound);
connect(loader, &CardDatabaseLoader::allNewSetsEnabled, this, &CardDatabase::cardDatabaseAllNewSetsEnabled);
for (auto &parser : availableParsers) {
connect(parser, &ICardDatabaseParser::addCard, this, &CardDatabase::addCard, Qt::DirectConnection);
connect(parser, &ICardDatabaseParser::addSet, this, &CardDatabase::addSet, Qt::DirectConnection);
}
connect(&SettingsCache::instance(), &SettingsCache::cardDatabasePathChanged, this,
&CardDatabase::loadCardDatabases);
querier = new CardDatabaseQuerier(this, this);
}
CardDatabase::~CardDatabase()
{
clear();
qDeleteAll(availableParsers);
}
void CardDatabase::clear()
@ -60,91 +55,14 @@ void CardDatabase::clear()
loadStatus = NotLoaded;
}
LoadStatus CardDatabase::loadFromFile(const QString &fileName)
void CardDatabase::loadCardDatabases()
{
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 = loader->loadCardDatabases();
}
LoadStatus CardDatabase::loadCardDatabase(const QString &path)
bool CardDatabase::saveCustomTokensToFile()
{
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;
return loader->saveCustomTokensToFile();
}
void CardDatabase::refreshCachedReverseRelatedCards()
@ -210,135 +128,9 @@ void CardDatabase::removeCard(CardInfoPtr card)
emit cardRemoved(card);
}
/**
* Looks up the cardInfo corresponding to the cardName.
*
* @param cardName The card name to look up
* @return A CardInfoPtr, or null if not corresponding CardInfo is found.
*/
CardInfoPtr CardDatabase::getCardInfo(const QString &cardName) const
void CardDatabase::addSet(CardSetPtr set)
{
return cards.value(cardName);
}
/**
* Looks up the cardInfos for a list of card names.
*
* @param cardNames The card names to look up
* @return A List of CardInfoPtr. Any failed lookups will be ignored and dropped from the resulting list
*/
QList<CardInfoPtr> CardDatabase::getCardInfos(const QStringList &cardNames) const
{
QList<CardInfoPtr> cardInfos;
for (const QString &cardName : cardNames) {
CardInfoPtr ptr = cards.value(cardName);
if (ptr)
cardInfos.append(ptr);
}
return cardInfos;
}
/**
* Looks up the cards corresponding to the CardRefs.
* If the providerId is empty, will default to the preferred printing.
* If providerId is given but not found, the PrintingInfo will be empty.
*
* @param cardRefs The cards to look up. If providerId is empty for an entry, will default to the preferred printing for
* that entry. If providerId is given but not found, the PrintingInfo will be empty for that entry.
* @return A list of cards. Any failed lookups will be ignored and dropped from the resulting list.
*/
QList<ExactCard> CardDatabase::getCards(const QList<CardRef> &cardRefs) const
{
QList<ExactCard> cards;
for (const auto &cardRef : cardRefs) {
ExactCard card = getCard(cardRef);
if (card)
cards.append(card);
}
return cards;
}
/**
* Looks up the card corresponding to the CardRef.
* If the providerId is empty, will default to the preferred printing.
* If providerId is given but not found, the PrintingInfo will be empty.
*
* @param cardRef The card to look up.
* @return A specific printing of a card, or empty if not found.
*/
ExactCard CardDatabase::getCard(const CardRef &cardRef) const
{
auto info = getCardInfo(cardRef.name);
if (info.isNull()) {
return {};
}
if (cardRef.providerId.isEmpty() || cardRef.providerId.isNull()) {
return ExactCard(info, getPreferredPrinting(info));
}
return ExactCard(info, findPrintingWithId(info, cardRef.providerId));
}
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.
* If providerId is given but not found, the PrintingInfo will be empty.
*
* @param cardRef The card to look up.
* @return A specific printing of a card, or empty if not found.
*/
ExactCard CardDatabase::guessCard(const CardRef &cardRef) const
{
auto card = lookupCardByName(cardRef.name);
auto printing =
cardRef.providerId.isEmpty() ? getPreferredPrinting(card) : findPrintingWithId(card, cardRef.providerId);
return ExactCard(card, printing);
}
ExactCard CardDatabase::getRandomCard()
{
if (cards.isEmpty())
return {};
const auto keys = cards.keys();
int randomIndex = QRandomGenerator::global()->bounded(keys.size());
const QString &randomKey = keys.at(randomIndex);
CardInfoPtr randomCard = getCardInfo(randomKey);
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});
sets.insert(set->getShortName(), set);
}
CardSetPtr CardDatabase::getSet(const QString &setName)
@ -352,11 +144,6 @@ CardSetPtr CardDatabase::getSet(const QString &setName)
}
}
void CardDatabase::addSet(CardSetPtr set)
{
sets.insert(set->getShortName(), set);
}
SetList CardDatabase::getSetList() const
{
SetList result;
@ -366,187 +153,6 @@ SetList CardDatabase::getSetList() const
return result;
}
/**
* Finds the PrintingInfo in the cardInfo that has the given uuid field.
*
* @param cardInfo The CardInfo to search
* @param providerId The uuid to look for
* @return The PrintingInfo, or a default-constructed PrintingInfo if not found.
*/
PrintingInfo CardDatabase::findPrintingWithId(const CardInfoPtr &cardInfo, const QString &providerId)
{
for (const auto &printings : cardInfo->getSets()) {
for (const auto &printing : printings) {
if (printing.getUuid() == providerId) {
return printing;
}
}
}
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);
return getPreferredPrinting(cardInfo);
}
PrintingInfo CardDatabase::getPreferredPrinting(const CardInfoPtr &cardInfo) const
{
if (!cardInfo) {
return PrintingInfo(nullptr);
}
SetToPrintingsMap setMap = cardInfo->getSets();
if (setMap.empty()) {
return PrintingInfo(nullptr);
}
CardSetPtr preferredSet = nullptr;
PrintingInfo preferredPrinting;
SetPriorityComparator comparator;
for (const auto &printings : setMap) {
for (auto &printing : printings) {
CardSetPtr currentSet = printing.getSet();
if (!preferredSet || comparator(currentSet, preferredSet)) {
preferredSet = currentSet;
preferredPrinting = printing;
}
}
}
if (preferredSet) {
return preferredPrinting;
}
return PrintingInfo(nullptr);
}
QString CardDatabase::getPreferredPrintingProviderId(const QString &cardName) const
{
PrintingInfo preferredPrinting = getPreferredPrinting(cardName);
QString uuid = preferredPrinting.getUuid();
if (!uuid.isEmpty()) {
return uuid;
}
CardInfoPtr defaultCardInfo = getCardInfo(cardName);
if (defaultCardInfo.isNull()) {
return cardName;
}
return defaultCardInfo->getName();
}
QStringList CardDatabase::getAllMainCardTypes() const
{
QSet<QString> types;
for (const auto &card : cards.values()) {
types.insert(card->getMainCardType());
}
return types.values();
}
QMap<QString, int> CardDatabase::getAllMainCardTypesWithCount() const
{
QMap<QString, int> typeCounts;
for (const auto &card : cards.values()) {
QString type = card->getMainCardType();
typeCounts[type]++;
}
return typeCounts;
}
QMap<QString, int> CardDatabase::getAllSubCardTypesWithCount() const
{
QMap<QString, int> typeCounts;
for (const auto &card : cards.values()) {
QString type = card->getCardType();
QStringList parts = type.split("");
if (parts.size() > 1) { // Ensure there are subtypes
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QStringList subtypes = parts[1].split(" ", Qt::SkipEmptyParts);
#else
QStringList subtypes = parts[1].split(" ", QString::SkipEmptyParts);
#endif
for (const QString &subtype : subtypes) {
typeCounts[subtype]++;
}
}
}
return typeCounts;
}
void CardDatabase::checkUnknownSets()
{
auto _sets = getSetList();
@ -592,22 +198,3 @@ void CardDatabase::notifyEnabledSetsChanged()
// inform the carddatabasemodels that they need to re-check their list of cards
emit cardDatabaseEnabledSetsChanged();
}
bool CardDatabase::saveCustomTokensToFile()
{
QString fileName = SettingsCache::instance().getCustomCardDatabasePath() + "/" + CardSet::TOKENS_SETNAME + ".xml";
SetNameMap tmpSets;
CardSetPtr customTokensSet = getSet(CardSet::TOKENS_SETNAME);
tmpSets.insert(CardSet::TOKENS_SETNAME, customTokensSet);
CardNameMap tmpCards;
for (const CardInfoPtr &card : cards) {
if (card->getSets().contains(CardSet::TOKENS_SETNAME)) {
tmpCards.insert(card->getName(), card);
}
}
availableParsers.first()->saveToFile(tmpSets, tmpCards, fileName);
return true;
}

View File

@ -3,6 +3,8 @@
#include "../card/exact_card.h"
#include "../common/card_ref.h"
#include "card_database_loader.h"
#include "card_database_querier.h"
#include <QBasicMutex>
#include <QDate>
@ -14,20 +16,6 @@
#include <utility>
inline Q_LOGGING_CATEGORY(CardDatabaseLog, "card_database");
inline Q_LOGGING_CATEGORY(CardDatabaseLoadingLog, "card_database.loading");
inline Q_LOGGING_CATEGORY(CardDatabaseLoadingSuccessOrFailureLog, "card_database.loading.success_or_failure");
class ICardDatabaseParser;
enum LoadStatus
{
Ok,
VersionTooOld,
Invalid,
NotLoaded,
FileError,
NoCards
};
class CardDatabase : public QObject
{
@ -48,79 +36,50 @@ protected:
*/
SetNameMap sets;
// loader responsible for file discovery & parsing
CardDatabaseLoader *loader;
LoadStatus loadStatus;
QVector<ICardDatabaseParser *> availableParsers;
CardDatabaseQuerier *querier;
private:
void checkUnknownSets();
void refreshCachedReverseRelatedCards();
QBasicMutex *reloadDatabaseMutex = new QBasicMutex(), *clearDatabaseMutex = new QBasicMutex(),
*loadFromFileMutex = new QBasicMutex(), *addCardMutex = new QBasicMutex(),
QBasicMutex *clearDatabaseMutex = new QBasicMutex(), *addCardMutex = new QBasicMutex(),
*removeCardMutex = new QBasicMutex();
public:
explicit CardDatabase(QObject *parent = nullptr);
~CardDatabase() override;
void clear();
void removeCard(CardInfoPtr card);
void clear();
[[nodiscard]] CardInfoPtr getCardInfo(const QString &cardName) const;
[[nodiscard]] QList<CardInfoPtr> getCardInfos(const QStringList &cardNames) const;
QList<ExactCard> getCards(const QList<CardRef> &cardRefs) const;
[[nodiscard]] ExactCard getCard(const CardRef &cardRef) const;
[[nodiscard]] ExactCard getPreferredCard(const CardInfoPtr &cardInfo) const;
static PrintingInfo findPrintingWithId(const CardInfoPtr &cardInfo, const QString &providerId);
[[nodiscard]] PrintingInfo getPreferredPrinting(const QString &cardName) const;
[[nodiscard]] PrintingInfo getPreferredPrinting(const CardInfoPtr &cardInfo) const;
[[nodiscard]] PrintingInfo getSpecificPrinting(const CardRef &cardRef) const;
PrintingInfo
getSpecificPrinting(const QString &cardName, const QString &setShortName, const QString &collectorNumber) const;
QString getPreferredPrintingProviderId(const QString &cardName) const;
bool isPreferredPrinting(const CardRef &cardRef) const;
ExactCard getCardFromSameSet(const QString &cardName, const PrintingInfo &otherPrinting) const;
[[nodiscard]] ExactCard guessCard(const CardRef &cardRef) const;
[[nodiscard]] ExactCard getRandomCard();
/*
* Get a card by its simple name. The name will be simplified in this
* 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
{
return cards;
}
CardSetPtr getSet(const QString &setName);
SetList getSetList() const;
CardInfoPtr getCardFromMap(const CardNameMap &cardMap, const QString &cardName) const;
LoadStatus loadFromFile(const QString &fileName);
bool saveCustomTokensToFile();
QStringList getAllMainCardTypes() const;
QMap<QString, int> getAllMainCardTypesWithCount() const;
QMap<QString, int> getAllSubCardTypesWithCount() const;
LoadStatus getLoadStatus() const
{
return loadStatus;
}
CardDatabaseQuerier *query() const
{
return querier;
}
void enableAllUnknownSets();
void markAllSetsAsKnown();
void notifyEnabledSetsChanged();
static QStringList collectCustomDatabasePaths();
public slots:
LoadStatus loadCardDatabases();
void addCard(CardInfoPtr card);
void addSet(CardSetPtr set);
protected slots:
LoadStatus loadCardDatabase(const QString &path);
void loadCardDatabases();
bool saveCustomTokensToFile();
signals:
void cardDatabaseLoadingFinished();
void cardDatabaseLoadingFailed();
@ -129,6 +88,9 @@ signals:
void cardDatabaseEnabledSetsChanged();
void cardAdded(CardInfoPtr card);
void cardRemoved(CardInfoPtr card);
friend class CardDatabaseLoader;
friend class CardDatabaseQuerier;
};
#endif

View File

@ -0,0 +1,153 @@
#include "card_database_loader.h"
#include "../settings/cache_settings.h"
#include "card_database.h"
#include "parser/cockatrice_xml_3.h"
#include "parser/cockatrice_xml_4.h"
#include <QDebug>
#include <QDirIterator>
#include <QFile>
#include <QTime>
CardDatabaseLoader::CardDatabaseLoader(QObject *parent, CardDatabase *db) : QObject(parent), database(db)
{
// instantiate available parsers here and connect them to the database
availableParsers << new CockatriceXml4Parser;
availableParsers << new CockatriceXml3Parser;
for (auto *p : availableParsers) {
// connect parser outputs to the database adders
connect(p, &ICardDatabaseParser::addCard, database, &CardDatabase::addCard, Qt::DirectConnection);
connect(p, &ICardDatabaseParser::addSet, database, &CardDatabase::addSet, Qt::DirectConnection);
}
// when SettingsCache's path changes, trigger reloads
connect(&SettingsCache::instance(), &SettingsCache::cardDatabasePathChanged, this,
&CardDatabaseLoader::loadCardDatabases);
}
CardDatabaseLoader::~CardDatabaseLoader()
{
qDeleteAll(availableParsers);
availableParsers.clear();
}
LoadStatus CardDatabaseLoader::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 CardDatabaseLoader::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 =" << (database ? database->cards.size() : 0)
<< "Sets =" << (database ? database->sets.size() : 0) << QString("%1ms").arg(msecs);
return tempLoadStatus;
}
LoadStatus CardDatabaseLoader::loadCardDatabases()
{
QMutexLocker locker(reloadDatabaseMutex);
if (!database) {
qCWarning(CardDatabaseLoadingLog) << "Loader has no database pointer";
emit loadingFailed();
return FileError;
}
emit loadingStarted();
qCInfo(CardDatabaseLoadingLog) << "Card Database Loading Started";
database->clear(); // remove old db
LoadStatus 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
const QStringList customPaths = collectCustomDatabasePaths();
for (int i = 0; i < customPaths.size(); ++i) {
const auto &p = customPaths.at(i);
qCInfo(CardDatabaseLoadingLog) << "Loading Custom Set" << i << "(" << p << ")";
loadCardDatabase(p);
}
// AFTER all the cards have been loaded
// resolve the reverse-related tags
database->refreshCachedReverseRelatedCards();
if (loadStatus == Ok) {
database->checkUnknownSets(); // update deck editors, etc
qCInfo(CardDatabaseLoadingSuccessOrFailureLog) << "Card Database Loading Success";
emit loadingFinished();
} else {
qCInfo(CardDatabaseLoadingSuccessOrFailureLog) << "Card Database Loading Failed";
emit loadingFailed(); // bring up the settings dialog
}
return loadStatus;
}
QStringList CardDatabaseLoader::collectCustomDatabasePaths() const
{
QDirIterator it(SettingsCache::instance().getCustomCardDatabasePath(), {"*.xml"}, QDir::Files,
QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
QStringList paths;
while (it.hasNext())
paths << it.next();
paths.sort();
return paths;
}
bool CardDatabaseLoader::saveCustomTokensToFile()
{
if (!database) {
qCWarning(CardDatabaseLog) << "saveCustomTokensToFile: database pointer missing";
return false;
}
QString fileName = SettingsCache::instance().getCustomCardDatabasePath() + "/" + CardSet::TOKENS_SETNAME + ".xml";
SetNameMap tmpSets;
CardSetPtr customTokensSet = database->getSet(CardSet::TOKENS_SETNAME);
tmpSets.insert(CardSet::TOKENS_SETNAME, customTokensSet);
CardNameMap tmpCards;
for (const CardInfoPtr &card : database->cards) {
if (card->getSets().contains(CardSet::TOKENS_SETNAME)) {
tmpCards.insert(card->getName(), card);
}
}
availableParsers.first()->saveToFile(tmpSets, tmpCards, fileName);
return true;
}

View File

@ -0,0 +1,57 @@
#ifndef COCKATRICE_CARD_DATABASE_LOADER_H
#define COCKATRICE_CARD_DATABASE_LOADER_H
#include <QBasicMutex>
#include <QList>
#include <QLoggingCategory>
#include <QObject>
inline Q_LOGGING_CATEGORY(CardDatabaseLoadingLog, "card_database.loading");
inline Q_LOGGING_CATEGORY(CardDatabaseLoadingSuccessOrFailureLog, "card_database.loading.success_or_failure");
class CardDatabase;
class ICardDatabaseParser;
enum LoadStatus
{
Ok,
VersionTooOld,
Invalid,
NotLoaded,
FileError,
NoCards
};
class CardDatabaseLoader : public QObject
{
Q_OBJECT
public:
explicit CardDatabaseLoader(QObject *parent, CardDatabase *db);
~CardDatabaseLoader() override;
public slots:
LoadStatus loadCardDatabases(); // discover & load the configured databases
LoadStatus loadCardDatabase(const QString &path); // load a single file
bool saveCustomTokensToFile(); // write tokens to custom DB path
signals:
void loadingStarted();
void loadingFinished();
void loadingFailed();
void newSetsFound(int numSets, const QStringList &setNames);
void allNewSetsEnabled();
private:
LoadStatus loadFromFile(const QString &fileName); // internal helper
QStringList collectCustomDatabasePaths() const;
CardDatabase *database; // non-owning pointer to the container
// parsers
QList<ICardDatabaseParser *> availableParsers;
QBasicMutex *loadFromFileMutex = new QBasicMutex();
QBasicMutex *reloadDatabaseMutex = new QBasicMutex();
};
#endif // COCKATRICE_CARD_DATABASE_LOADER_H

View File

@ -4,4 +4,9 @@ CardDatabase *CardDatabaseManager::getInstance()
{
static CardDatabase instance; // Created only once, on first access
return &instance;
}
CardDatabaseQuerier *CardDatabaseManager::query()
{
return getInstance()->query();
}

View File

@ -1,4 +1,3 @@
#ifndef CARD_DATABASE_ACCESSOR_H
#define CARD_DATABASE_ACCESSOR_H
@ -14,6 +13,7 @@ public:
// Static method to access the singleton instance
static CardDatabase *getInstance();
static CardDatabaseQuerier *query();
private:
CardDatabaseManager() = default; // Private constructor

View File

@ -0,0 +1,322 @@
#include "card_database_querier.h"
#include "../utility/card_set_comparator.h"
#include "card_database.h"
#include <qrandom.h>
CardDatabaseQuerier::CardDatabaseQuerier(QObject *_parent, const CardDatabase *_db) : QObject(_parent), db(_db)
{
}
/**
* Looks up the cardInfo corresponding to the cardName.
*
* @param cardName The card name to look up
* @return A CardInfoPtr, or null if not corresponding CardInfo is found.
*/
CardInfoPtr CardDatabaseQuerier::getCardInfo(const QString &cardName) const
{
return db->cards.value(cardName);
}
/**
* Looks up the cardInfos for a list of card names.
*
* @param cardNames The card names to look up
* @return A List of CardInfoPtr. Any failed lookups will be ignored and dropped from the resulting list
*/
QList<CardInfoPtr> CardDatabaseQuerier::getCardInfos(const QStringList &cardNames) const
{
QList<CardInfoPtr> cardInfos;
for (const QString &cardName : cardNames) {
CardInfoPtr ptr = db->cards.value(cardName);
if (ptr)
cardInfos.append(ptr);
}
return cardInfos;
}
CardInfoPtr CardDatabaseQuerier::getCardBySimpleName(const QString &cardName) const
{
return db->simpleNameCards.value(CardInfo::simplifyName(cardName));
}
CardInfoPtr CardDatabaseQuerier::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 cards corresponding to the CardRefs.
* If the providerId is empty, will default to the preferred printing.
* If providerId is given but not found, the PrintingInfo will be empty.
*
* @param cardRefs The cards to look up. If providerId is empty for an entry, will default to the preferred printing for
* that entry. If providerId is given but not found, the PrintingInfo will be empty for that entry.
* @return A list of cards. Any failed lookups will be ignored and dropped from the resulting list.
*/
QList<ExactCard> CardDatabaseQuerier::getCards(const QList<CardRef> &cardRefs) const
{
QList<ExactCard> cards;
for (const auto &cardRef : cardRefs) {
ExactCard card = getCard(cardRef);
if (card)
cards.append(card);
}
return cards;
}
/**
* Looks up the card corresponding to the CardRef.
* If the providerId is empty, will default to the preferred printing.
* If providerId is given but not found, the PrintingInfo will be empty.
*
* @param cardRef The card to look up.
* @return A specific printing of a card, or empty if not found.
*/
ExactCard CardDatabaseQuerier::getCard(const CardRef &cardRef) const
{
auto info = getCardInfo(cardRef.name);
if (info.isNull()) {
return {};
}
if (cardRef.providerId.isEmpty() || cardRef.providerId.isNull()) {
return ExactCard(info, getPreferredPrinting(info));
}
return ExactCard(info, findPrintingWithId(info, cardRef.providerId));
}
/**
* Looks up the card by CardRef, simplifying the name if required.
* If the providerId is empty, will default to the preferred printing.
* If providerId is given but not found, the PrintingInfo will be empty.
*
* @param cardRef The card to look up.
* @return A specific printing of a card, or empty if not found.
*/
ExactCard CardDatabaseQuerier::guessCard(const CardRef &cardRef) const
{
auto card = lookupCardByName(cardRef.name);
auto printing =
cardRef.providerId.isEmpty() ? getPreferredPrinting(card) : findPrintingWithId(card, cardRef.providerId);
return ExactCard(card, printing);
}
ExactCard CardDatabaseQuerier::getRandomCard() const
{
if (db->cards.isEmpty())
return {};
const auto keys = db->cards.keys();
int randomIndex = QRandomGenerator::global()->bounded(keys.size());
const QString &randomKey = keys.at(randomIndex);
CardInfoPtr randomCard = getCardInfo(randomKey);
return ExactCard{randomCard, getPreferredPrinting(randomCard)};
}
ExactCard CardDatabaseQuerier::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});
}
/**
* Finds the PrintingInfo in the cardInfo that has the given uuid field.
*
* @param cardInfo The CardInfo to search
* @param providerId The uuid to look for
* @return The PrintingInfo, or a default-constructed PrintingInfo if not found.
*/
PrintingInfo CardDatabaseQuerier::findPrintingWithId(const CardInfoPtr &cardInfo, const QString &providerId) const
{
for (const auto &printings : cardInfo->getSets()) {
for (const auto &printing : printings) {
if (printing.getUuid() == providerId) {
return printing;
}
}
}
return PrintingInfo();
}
PrintingInfo CardDatabaseQuerier::getSpecificPrinting(const CardRef &cardRef) const
{
CardInfoPtr cardInfo = getCardInfo(cardRef.name);
if (!cardInfo) {
return PrintingInfo(nullptr);
}
return findPrintingWithId(cardInfo, cardRef.providerId);
}
PrintingInfo CardDatabaseQuerier::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 CardDatabaseQuerier::getPreferredCard(const CardInfoPtr &cardInfo) const
{
return ExactCard(cardInfo, getPreferredPrinting(cardInfo));
}
bool CardDatabaseQuerier::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 CardDatabaseQuerier::getPreferredPrinting(const QString &cardName) const
{
CardInfoPtr cardInfo = getCardInfo(cardName);
return getPreferredPrinting(cardInfo);
}
PrintingInfo CardDatabaseQuerier::getPreferredPrinting(const CardInfoPtr &cardInfo) const
{
if (!cardInfo) {
return PrintingInfo(nullptr);
}
SetToPrintingsMap setMap = cardInfo->getSets();
if (setMap.empty()) {
return PrintingInfo(nullptr);
}
CardSetPtr preferredSet = nullptr;
PrintingInfo preferredPrinting;
SetPriorityComparator comparator;
for (const auto &printings : setMap) {
for (auto &printing : printings) {
CardSetPtr currentSet = printing.getSet();
if (!preferredSet || comparator(currentSet, preferredSet)) {
preferredSet = currentSet;
preferredPrinting = printing;
}
}
}
if (preferredSet) {
return preferredPrinting;
}
return PrintingInfo(nullptr);
}
QString CardDatabaseQuerier::getPreferredPrintingProviderId(const QString &cardName) const
{
PrintingInfo preferredPrinting = getPreferredPrinting(cardName);
QString uuid = preferredPrinting.getUuid();
if (!uuid.isEmpty()) {
return uuid;
}
CardInfoPtr defaultCardInfo = getCardInfo(cardName);
if (defaultCardInfo.isNull()) {
return cardName;
}
return defaultCardInfo->getName();
}
QStringList CardDatabaseQuerier::getAllMainCardTypes() const
{
QSet<QString> types;
for (const auto &card : db->cards.values()) {
types.insert(card->getMainCardType());
}
return types.values();
}
QMap<QString, int> CardDatabaseQuerier::getAllMainCardTypesWithCount() const
{
QMap<QString, int> typeCounts;
for (const auto &card : db->cards.values()) {
QString type = card->getMainCardType();
typeCounts[type]++;
}
return typeCounts;
}
QMap<QString, int> CardDatabaseQuerier::getAllSubCardTypesWithCount() const
{
QMap<QString, int> typeCounts;
for (const auto &card : db->cards.values()) {
QString type = card->getCardType();
QStringList parts = type.split("");
if (parts.size() > 1) { // Ensure there are subtypes
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QStringList subtypes = parts[1].split(" ", Qt::SkipEmptyParts);
#else
QStringList subtypes = parts[1].split(" ", QString::SkipEmptyParts);
#endif
for (const QString &subtype : subtypes) {
typeCounts[subtype]++;
}
}
}
return typeCounts;
}

View File

@ -0,0 +1,54 @@
#ifndef COCKATRICE_CARD_DATABASE_QUERIER_H
#define COCKATRICE_CARD_DATABASE_QUERIER_H
#include "../card/exact_card.h"
#include "../common/card_ref.h"
#include <QObject>
class CardDatabase;
class CardDatabaseQuerier : public QObject
{
Q_OBJECT
public:
explicit CardDatabaseQuerier(QObject *parent, const CardDatabase *db);
[[nodiscard]] CardInfoPtr getCardInfo(const QString &cardName) const;
[[nodiscard]] QList<CardInfoPtr> getCardInfos(const QStringList &cardNames) const;
/*
* Get a card by its simple name. The name will be simplified in this
* function, so you don't need to simplify it beforehand.
*/
[[nodiscard]] CardInfoPtr getCardBySimpleName(const QString &cardName) const;
[[nodiscard]] ExactCard guessCard(const CardRef &cardRef) const;
[[nodiscard]] ExactCard getCard(const CardRef &cardRef) const;
[[nodiscard]] QList<ExactCard> getCards(const QList<CardRef> &cardRefs) const;
[[nodiscard]] ExactCard getRandomCard() const;
[[nodiscard]] ExactCard getCardFromSameSet(const QString &cardName, const PrintingInfo &otherPrinting) const;
[[nodiscard]] ExactCard getPreferredCard(const CardInfoPtr &card) const;
[[nodiscard]] bool isPreferredPrinting(const CardRef &cardRef) const;
[[nodiscard]] PrintingInfo getPreferredPrinting(const CardInfoPtr &card) const;
[[nodiscard]] PrintingInfo getPreferredPrinting(const QString &cardName) const;
[[nodiscard]] QString getPreferredPrintingProviderId(const QString &cardName) const;
[[nodiscard]] PrintingInfo getSpecificPrinting(const CardRef &cardRef) const;
[[nodiscard]] PrintingInfo
getSpecificPrinting(const QString &cardName, const QString &setCode, const QString &collectorNumber) const;
[[nodiscard]] PrintingInfo findPrintingWithId(const CardInfoPtr &card, const QString &providerId) const;
[[nodiscard]] QStringList getAllMainCardTypes() const;
[[nodiscard]] QMap<QString, int> getAllMainCardTypesWithCount() const;
[[nodiscard]] QMap<QString, int> getAllSubCardTypesWithCount() const;
private:
const CardDatabase *db;
CardInfoPtr lookupCardByName(const QString &name) const;
};
#endif // COCKATRICE_CARD_DATABASE_QUERIER_H

View File

@ -66,7 +66,7 @@ void DeckListModel::rebuildTree()
continue;
}
CardInfoPtr info = CardDatabaseManager::getInstance()->getCardInfo(currentCard->getName());
CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(currentCard->getName());
QString groupCriteria = getGroupCriteriaForCard(info);
auto *groupNode = dynamic_cast<InnerDecklistNode *>(node->findChild(groupCriteria));
@ -341,7 +341,7 @@ DecklistModelCardNode *DeckListModel::findCardNode(const QString &cardName,
return nullptr;
}
CardInfoPtr info = CardDatabaseManager::getInstance()->getCardInfo(cardName);
CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(cardName);
if (!info) {
return nullptr;
}
@ -371,7 +371,7 @@ QModelIndex DeckListModel::findCard(const QString &cardName,
QModelIndex DeckListModel::addPreferredPrintingCard(const QString &cardName, const QString &zoneName, bool abAddAnyway)
{
ExactCard card = CardDatabaseManager::getInstance()->getCard({cardName});
ExactCard card = CardDatabaseManager::query()->getCard({cardName});
if (!card) {
if (abAddAnyway) {
@ -566,7 +566,7 @@ QList<ExactCard> DeckListModel::getCards() const
if (!currentCard)
continue;
for (int k = 0; k < currentCard->getNumber(); ++k) {
ExactCard card = CardDatabaseManager::getInstance()->getCard(currentCard->toCardRef());
ExactCard card = CardDatabaseManager::query()->getCard(currentCard->toCardRef());
if (card) {
cards.append(card);
} else {
@ -599,7 +599,7 @@ QList<ExactCard> DeckListModel::getCardsForZone(const QString &zoneName) const
if (!currentCard)
continue;
for (int k = 0; k < currentCard->getNumber(); ++k) {
ExactCard card = CardDatabaseManager::getInstance()->getCard(currentCard->toCardRef());
ExactCard card = CardDatabaseManager::query()->getCard(currentCard->toCardRef());
if (card) {
cards.append(card);
} else {

View File

@ -282,7 +282,7 @@ QString DeckLoader::exportDeckToDecklist(DecklistWebsite website)
// Set up the function to call
auto formatDeckListForExport = [&mainBoardCards, &sideBoardCards](const auto *node, const auto *card) {
// Get the card name
CardInfoPtr dbCard = CardDatabaseManager::getInstance()->getCardInfo(card->getName());
CardInfoPtr dbCard = CardDatabaseManager::query()->getCardInfo(card->getName());
if (!dbCard || dbCard->getIsToken()) {
// If it's a token, we don't care about the card.
return;
@ -325,7 +325,7 @@ struct SetProviderIdToPreferred
void operator()(const InnerDecklistNode *node, DecklistCardNode *card) const
{
Q_UNUSED(node);
PrintingInfo preferredPrinting = CardDatabaseManager::getInstance()->getPreferredPrinting(card->getName());
PrintingInfo preferredPrinting = CardDatabaseManager::query()->getPreferredPrinting(card->getName());
QString providerId = preferredPrinting.getUuid();
QString setShortName = preferredPrinting.getSet()->getShortName();
QString collectorNumber = preferredPrinting.getProperty("num");
@ -359,6 +359,7 @@ void DeckLoader::resolveSetNameAndNumberToProviderID()
// Retrieve the providerId based on setName and collectorNumber
QString providerId =
CardDatabaseManager::getInstance()
->query()
->getSpecificPrinting(card->getName(), card->getCardSetShortName(), card->getCardCollectorNumber())
.getUuid();
@ -468,7 +469,7 @@ void DeckLoader::saveToStream_DeckZone(QTextStream &out,
for (int j = 0; j < zoneNode->size(); j++) {
auto *card = dynamic_cast<DecklistCardNode *>(zoneNode->at(j));
CardInfoPtr info = CardDatabaseManager::getInstance()->getCardInfo(card->getName());
CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(card->getName());
QString cardType = info ? info->getMainCardType() : "unknown";
cardsByType.insert(cardType, card);
@ -584,7 +585,7 @@ bool DeckLoader::convertToCockatriceFormat(QString fileName)
QString DeckLoader::getCardZoneFromName(QString cardName, QString currentZoneName)
{
CardInfoPtr card = CardDatabaseManager::getInstance()->getCardInfo(cardName);
CardInfoPtr card = CardDatabaseManager::query()->getCardInfo(cardName);
if (card && card->getIsToken()) {
return DECK_ZONE_TOKENS;
@ -596,7 +597,7 @@ QString DeckLoader::getCardZoneFromName(QString cardName, QString currentZoneNam
QString DeckLoader::getCompleteCardName(const QString &cardName) const
{
if (CardDatabaseManager::getInstance()) {
ExactCard temp = CardDatabaseManager::getInstance()->guessCard({cardName});
ExactCard temp = CardDatabaseManager::query()->guessCard({cardName});
if (temp) {
return temp.getName();
}

View File

@ -71,7 +71,7 @@ void DeckStatsInterface::analyzeDeck(DeckList *deck)
void DeckStatsInterface::copyDeckWithoutTokens(DeckList &source, DeckList &destination)
{
auto copyIfNotAToken = [this, &destination](const auto node, const auto card) {
CardInfoPtr dbCard = cardDatabase.getCardInfo(card->getName());
CardInfoPtr dbCard = cardDatabase.query()->getCardInfo(card->getName());
if (dbCard && !dbCard->getIsToken()) {
DecklistCardNode *addedCard = destination.addCard(card->getName(), node->getName(), -1);
addedCard->setNumber(card->getNumber());

View File

@ -153,7 +153,7 @@ void DlgEditTokens::actAddToken()
name = getTextWithMax(this, tr("Add token"), tr("Please enter the name of the token:"));
if (name.isEmpty())
return;
if (databaseModel->getDatabase()->getCardInfo(name)) {
if (databaseModel->getDatabase()->query()->getCardInfo(name)) {
QMessageBox::critical(this, tr("Error"),
tr("The chosen name conflicts with an existing card or token.\nMake sure to enable "
"the 'Token' set in the \"Manage sets\" dialog to display them correctly."));

View File

@ -152,8 +152,8 @@ void DlgSelectSetForCards::actOK()
continue;
}
model->removeRow(find_card.row(), find_card.parent());
CardInfoPtr cardInfo = CardDatabaseManager::getInstance()->getCardInfo(card);
PrintingInfo printing = CardDatabaseManager::getInstance()->getSpecificPrinting(card, modifiedSet, "");
CardInfoPtr cardInfo = CardDatabaseManager::query()->getCardInfo(card);
PrintingInfo printing = CardDatabaseManager::query()->getSpecificPrinting(card, modifiedSet, "");
model->addCard(ExactCard(cardInfo, printing), DECK_ZONE_MAIN);
}
}
@ -223,7 +223,7 @@ QMap<QString, int> DlgSelectSetForCards::getSetsForCards()
if (!currentCard)
continue;
CardInfoPtr infoPtr = CardDatabaseManager::getInstance()->getCardInfo(currentCard->getName());
CardInfoPtr infoPtr = CardDatabaseManager::query()->getCardInfo(currentCard->getName());
if (!infoPtr)
continue;
@ -291,13 +291,14 @@ void DlgSelectSetForCards::updateCardLists()
if (!found) {
// The card was not in any selected set
ExactCard card = CardDatabaseManager::getInstance()->getCard({currentCard->getName()});
ExactCard card = CardDatabaseManager::query()->getCard({currentCard->getName()});
CardInfoPictureWidget *picture_widget = new CardInfoPictureWidget(uneditedCardsFlowWidget);
picture_widget->setCard(card);
uneditedCardsFlowWidget->addWidget(picture_widget);
} else {
ExactCard card = CardDatabaseManager::getInstance()->getCard(
ExactCard card = CardDatabaseManager::query()->getCard(
{currentCard->getName(), CardDatabaseManager::getInstance()
->query()
->getSpecificPrinting(currentCard->getName(), foundSetName, "")
.getUuid()});
CardInfoPictureWidget *picture_widget = new CardInfoPictureWidget(modifiedCardsFlowWidget);
@ -377,7 +378,7 @@ QMap<QString, QStringList> DlgSelectSetForCards::getCardsForSets()
if (!currentCard)
continue;
CardInfoPtr infoPtr = CardDatabaseManager::getInstance()->getCardInfo(currentCard->getName());
CardInfoPtr infoPtr = CardDatabaseManager::query()->getCardInfo(currentCard->getName());
if (!infoPtr)
continue;
@ -627,17 +628,15 @@ void SetEntryWidget::updateCardDisplayWidgets()
for (const QString &cardName : possibleCards) {
CardInfoPictureWidget *picture_widget = new CardInfoPictureWidget(cardListContainer);
QString providerId =
CardDatabaseManager::getInstance()->getSpecificPrinting(cardName, setName, nullptr).getUuid();
picture_widget->setCard(CardDatabaseManager::getInstance()->getCard({cardName, providerId}));
QString providerId = CardDatabaseManager::query()->getSpecificPrinting(cardName, setName, nullptr).getUuid();
picture_widget->setCard(CardDatabaseManager::query()->getCard({cardName, providerId}));
cardListContainer->addWidget(picture_widget);
}
for (const QString &cardName : unusedCards) {
CardInfoPictureWidget *picture_widget = new CardInfoPictureWidget(alreadySelectedCardListContainer);
QString providerId =
CardDatabaseManager::getInstance()->getSpecificPrinting(cardName, setName, nullptr).getUuid();
picture_widget->setCard(CardDatabaseManager::getInstance()->getCard({cardName, providerId}));
QString providerId = CardDatabaseManager::query()->getSpecificPrinting(cardName, setName, nullptr).getUuid();
picture_widget->setCard(CardDatabaseManager::query()->getCard({cardName, providerId}));
alreadySelectedCardListContainer->addWidget(picture_widget);
}
}

View File

@ -118,7 +118,7 @@ static void setupParserRules()
return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) -> bool {
int count = 0;
deck->deckLoader->forEachCard([&](InnerDecklistNode *, const DecklistCardNode *node) {
auto cardInfoPtr = CardDatabaseManager::getInstance()->getCardInfo(node->getName());
auto cardInfoPtr = CardDatabaseManager::query()->getCardInfo(node->getName());
if (!cardInfoPtr.isNull() && cardFilter.check(cardInfoPtr)) {
count += node->getNumber();
}

View File

@ -57,7 +57,7 @@ void AbstractCardItem::pixmapUpdated()
void AbstractCardItem::refreshCardInfo()
{
exactCard = CardDatabaseManager::getInstance()->getCard(cardRef);
exactCard = CardDatabaseManager::query()->getCard(cardRef);
if (!exactCard && !cardRef.name.isEmpty()) {
auto info = CardInfo::newInstance(cardRef.name, "", true, {}, {}, {}, {}, false, false, -1, false);

View File

@ -332,7 +332,7 @@ void DeckViewContainer::deckSelectFinished(const Response &r)
{
const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext);
DeckLoader newDeck(QString::fromStdString(resp.deck()));
PictureLoader::cacheCardPixmaps(CardDatabaseManager::getInstance()->getCards(newDeck.getCardRefList()));
PictureLoader::cacheCardPixmaps(CardDatabaseManager::query()->getCards(newDeck.getCardRefList()));
setDeck(newDeck);
switchToDeckLoadedView();
}

View File

@ -205,9 +205,9 @@ void DlgCreateToken::tokenSelectionChanged(const QModelIndex &current, const QMo
CardRef ref;
ref.name = cardInfo->getName();
ref.providerId = cardProviderId;
pic->setCard(CardDatabaseManager::getInstance()->getCard(ref));
pic->setCard(CardDatabaseManager::query()->getCard(ref));
} else {
pic->setCard(CardDatabaseManager::getInstance()->getPreferredCard(cardInfo));
pic->setCard(CardDatabaseManager::query()->getPreferredCard(cardInfo));
}
}

View File

@ -322,7 +322,7 @@ void CardMenu::addRelatedCardView()
bool atLeastOneGoodRelationFound = false;
QList<CardRelation *> relatedCards = exactCard.getInfo().getAllRelatedCards();
for (const CardRelation *cardRelation : relatedCards) {
CardInfoPtr relatedCard = CardDatabaseManager::getInstance()->getCardInfo(cardRelation->getName());
CardInfoPtr relatedCard = CardDatabaseManager::query()->getCardInfo(cardRelation->getName());
if (relatedCard != nullptr) {
atLeastOneGoodRelationFound = true;
break;
@ -366,10 +366,10 @@ void CardMenu::addRelatedCardActions()
int index = 0;
QAction *createRelatedCards = nullptr;
for (const CardRelation *cardRelation : relatedCards) {
ExactCard relatedCard = CardDatabaseManager::getInstance()->getCardFromSameSet(cardRelation->getName(),
card->getCard().getPrinting());
ExactCard relatedCard =
CardDatabaseManager::query()->getCardFromSameSet(cardRelation->getName(), card->getCard().getPrinting());
if (!relatedCard) {
relatedCard = CardDatabaseManager::getInstance()->getCard({cardRelation->getName()});
relatedCard = CardDatabaseManager::query()->getCard({cardRelation->getName()});
}
if (!relatedCard) {
continue;

View File

@ -840,8 +840,7 @@ void PlayerActions::actCreateToken()
lastTokenInfo = dlg.getTokenInfo();
ExactCard correctedCard =
CardDatabaseManager::getInstance()->guessCard({lastTokenInfo.name, lastTokenInfo.providerId});
ExactCard correctedCard = CardDatabaseManager::query()->guessCard({lastTokenInfo.name, lastTokenInfo.providerId});
if (correctedCard) {
lastTokenInfo.name = correctedCard.getName();
lastTokenTableRow = TableZone::clampValidTableRow(2 - correctedCard.getInfo().getTableRow());
@ -903,7 +902,7 @@ void PlayerActions::setLastToken(CardInfoPtr cardInfo)
void PlayerActions::actCreatePredefinedToken()
{
auto *action = static_cast<QAction *>(sender());
CardInfoPtr cardInfo = CardDatabaseManager::getInstance()->getCardInfo(action->text());
CardInfoPtr cardInfo = CardDatabaseManager::query()->getCardInfo(action->text());
if (!cardInfo) {
return;
}
@ -929,8 +928,8 @@ void PlayerActions::actCreateRelatedCard()
* then let's allow it to be created via "create another token"
*/
if (createRelatedFromRelation(sourceCard, cardRelation) && cardRelation->getCanCreateAnother()) {
ExactCard relatedCard = CardDatabaseManager::getInstance()->getCardFromSameSet(
cardRelation->getName(), sourceCard->getCard().getPrinting());
ExactCard relatedCard = CardDatabaseManager::query()->getCardFromSameSet(cardRelation->getName(),
sourceCard->getCard().getPrinting());
setLastToken(relatedCard.getCardPtr());
}
}
@ -1010,7 +1009,7 @@ void PlayerActions::actCreateAllRelatedCards()
* then assign the first to the "Create another" shortcut.
*/
if (cardRelation != nullptr && cardRelation->getCanCreateAnother()) {
CardInfoPtr cardInfo = CardDatabaseManager::getInstance()->getCardInfo(cardRelation->getName());
CardInfoPtr cardInfo = CardDatabaseManager::query()->getCardInfo(cardRelation->getName());
setLastToken(cardInfo);
}
}
@ -1057,7 +1056,7 @@ void PlayerActions::createCard(const CardItem *sourceCard,
CardRelation::AttachType attachType,
bool persistent)
{
CardInfoPtr cardInfo = CardDatabaseManager::getInstance()->getCardInfo(dbCardName);
CardInfoPtr cardInfo = CardDatabaseManager::query()->getCardInfo(dbCardName);
if (cardInfo == nullptr || sourceCard == nullptr) {
return;
@ -1093,8 +1092,8 @@ void PlayerActions::createCard(const CardItem *sourceCard,
cmd.set_x(gridPoint.x());
cmd.set_y(gridPoint.y());
ExactCard relatedCard = CardDatabaseManager::getInstance()->getCardFromSameSet(cardInfo->getName(),
sourceCard->getCard().getPrinting());
ExactCard relatedCard =
CardDatabaseManager::query()->getCardFromSameSet(cardInfo->getName(), sourceCard->getCard().getPrinting());
switch (attachType) {
case CardRelation::DoesNotAttach:

View File

@ -55,7 +55,7 @@ QWidget *CardGroupDisplayWidget::constructWidgetForIndex(QPersistentModelIndex i
auto widget = new CardInfoPictureWithTextOverlayWidget(getLayoutParent(), true);
widget->setScaleFactor(cardSizeWidget->getSlider()->value());
widget->setCard(CardDatabaseManager::getInstance()->getCard({cardName, cardProviderId}));
widget->setCard(CardDatabaseManager::query()->getCard({cardName, cardProviderId}));
connect(widget, &CardInfoPictureWithTextOverlayWidget::imageClicked, this, &CardGroupDisplayWidget::onClick);
connect(widget, &CardInfoPictureWithTextOverlayWidget::hoveredOnCard, this, &CardGroupDisplayWidget::onHover);

View File

@ -57,7 +57,7 @@ void CardInfoDisplayWidget::setCard(const ExactCard &card)
void CardInfoDisplayWidget::setCard(const CardRef &cardRef)
{
setCard(CardDatabaseManager::getInstance()->guessCard(cardRef));
setCard(CardDatabaseManager::query()->guessCard(cardRef));
if (exactCard.isEmpty()) {
text->setInvalidCardName(cardRef.name);
}

View File

@ -160,12 +160,12 @@ void CardInfoFrameWidget::setCard(const ExactCard &card)
void CardInfoFrameWidget::setCard(const QString &cardName)
{
setCard(CardDatabaseManager::getInstance()->guessCard({cardName}));
setCard(CardDatabaseManager::query()->guessCard({cardName}));
}
void CardInfoFrameWidget::setCard(const CardRef &cardRef)
{
setCard(CardDatabaseManager::getInstance()->getCard(cardRef));
setCard(CardDatabaseManager::query()->getCard(cardRef));
}
void CardInfoFrameWidget::setCard(AbstractCardItem *card)

View File

@ -368,7 +368,7 @@ QMenu *CardInfoPictureWidget::createViewRelatedCardsMenu()
QList<CardRelation *> relatedCards = exactCard.getInfo().getAllRelatedCards();
auto relatedCardExists = [](const CardRelation *cardRelation) {
return CardDatabaseManager::getInstance()->getCardInfo(cardRelation->getName()) != nullptr;
return CardDatabaseManager::query()->getCardInfo(cardRelation->getName()) != nullptr;
};
bool atLeastOneGoodRelationFound = std::any_of(relatedCards.begin(), relatedCards.end(), relatedCardExists);
@ -383,7 +383,7 @@ QMenu *CardInfoPictureWidget::createViewRelatedCardsMenu()
QAction *viewCard = viewRelatedCards->addAction(relatedCardName);
connect(viewCard, &QAction::triggered, this, [this, &relatedCardName] {
emit cardChanged(
CardDatabaseManager::getInstance()->getCard({relatedCardName, exactCard.getPrinting().getUuid()}));
CardDatabaseManager::query()->getCard({relatedCardName, exactCard.getPrinting().getUuid()}));
});
viewRelatedCards->addAction(viewCard);
}

View File

@ -87,7 +87,7 @@ QHash<QString, int> ManaBaseWidget::analyzeManaBase()
continue;
for (int k = 0; k < currentCard->getNumber(); ++k) {
CardInfoPtr info = CardDatabaseManager::getInstance()->getCardInfo(currentCard->getName());
CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(currentCard->getName());
if (info) {
auto devotion = determineManaProduction(info->getText());
mergeManaCounts(manaBaseMap, devotion);

View File

@ -53,7 +53,7 @@ std::unordered_map<int, int> ManaCurveWidget::analyzeManaCurve()
continue;
for (int k = 0; k < currentCard->getNumber(); ++k) {
CardInfoPtr info = CardDatabaseManager::getInstance()->getCardInfo(currentCard->getName());
CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(currentCard->getName());
if (info) {
int cmc = info->getCmc().toInt();
manaCurveMap[cmc]++;

View File

@ -55,7 +55,7 @@ std::unordered_map<char, int> ManaDevotionWidget::analyzeManaDevotion()
continue;
for (int k = 0; k < currentCard->getNumber(); ++k) {
CardInfoPtr info = CardDatabaseManager::getInstance()->getCardInfo(currentCard->getName());
CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(currentCard->getName());
if (info) {
auto devotion = countManaSymbols(info->getManaCost());
mergeManaCounts(manaDevotionMap, devotion);

View File

@ -182,11 +182,11 @@ ExactCard DeckEditorDatabaseDisplayWidget::getCardOrPinnedPrinting(QString cardN
{
const auto &cardProviderId = SettingsCache::instance().cardOverrides().getCardPreferenceOverride(cardName);
ExactCard card = CardDatabaseManager::getInstance()->getCard({cardName});
ExactCard card = CardDatabaseManager::query()->getCard({cardName});
if (cardProviderId != "") {
return ExactCard(card.getCardPtr(),
CardDatabaseManager::getInstance()->getSpecificPrinting({cardName, cardProviderId}));
CardDatabaseManager::query()->getSpecificPrinting({cardName, cardProviderId}));
}
return card;

View File

@ -227,7 +227,7 @@ ExactCard DeckEditorDeckDockWidget::getCurrentCard()
if (!current.model()->hasChildren(current.sibling(current.row(), 0))) {
QString cardName = current.sibling(current.row(), 1).data().toString();
QString providerId = current.sibling(current.row(), 4).data().toString();
if (ExactCard selectedCard = CardDatabaseManager::getInstance()->getCard({cardName, providerId})) {
if (ExactCard selectedCard = CardDatabaseManager::query()->getCard({cardName, providerId})) {
return selectedCard;
}
}
@ -286,7 +286,7 @@ void DeckEditorDeckDockWidget::updateBannerCardComboBox()
continue;
for (int k = 0; k < currentCard->getNumber(); ++k) {
if (CardDatabaseManager::getInstance()->getCard(currentCard->toCardRef())) {
if (CardDatabaseManager::query()->getCard(currentCard->toCardRef())) {
bannerCardSet.insert({currentCard->getName(), currentCard->getCardProviderId()});
}
}
@ -486,7 +486,7 @@ bool DeckEditorDeckDockWidget::swapCard(const QModelIndex &currentIndex)
offsetCountAtIndex(currentIndex, -1);
const QString otherZoneName = zoneName == DECK_ZONE_MAIN ? DECK_ZONE_SIDE : DECK_ZONE_MAIN;
ExactCard card = CardDatabaseManager::getInstance()->getCard({cardName, cardProviderID});
ExactCard card = CardDatabaseManager::query()->getCard({cardName, cardProviderID});
QModelIndex newCardIndex = card ? deckModel->addCard(card, otherZoneName)
// Third argument (true) says create the card no matter what, even if not in DB
: deckModel->addPreferredPrintingCard(cardName, otherZoneName, true);

View File

@ -89,7 +89,7 @@ void HomeWidget::updateRandomCard()
break;
case BackgroundSources::RandomCardArt:
do {
newCard = CardDatabaseManager::getInstance()->getRandomCard();
newCard = CardDatabaseManager::query()->getRandomCard();
} while (newCard == backgroundSourceCard->getCard() &&
newCard.getCardPtr()->getProperty("layout") != "normal");
break;
@ -99,17 +99,17 @@ void HomeWidget::updateRandomCard()
if (!cardRefs.empty()) {
if (cardRefs.size() == 1) {
newCard = CardDatabaseManager::getInstance()->getCard(cardRefs.first());
newCard = CardDatabaseManager::query()->getCard(cardRefs.first());
} else {
// Keep picking until different
do {
int idx = QRandomGenerator::global()->bounded(cardRefs.size());
newCard = CardDatabaseManager::getInstance()->getCard(cardRefs.at(idx));
newCard = CardDatabaseManager::query()->getCard(cardRefs.at(idx));
} while (newCard == oldCard);
}
} else {
do {
newCard = CardDatabaseManager::getInstance()->getRandomCard();
newCard = CardDatabaseManager::query()->getRandomCard();
} while (newCard == oldCard);
}
break;

View File

@ -196,7 +196,7 @@ void PrintingSelectorCardOverlayWidget::customMenu(QPoint point)
const QString &relatedCardName = rel->getName();
QAction *relatedCard = relatedMenu->addAction(relatedCardName);
connect(relatedCard, &QAction::triggered, deckEditor, [this, relatedCardName] {
deckEditor->updateCard(CardDatabaseManager::getInstance()->getCard({relatedCardName}));
deckEditor->updateCard(CardDatabaseManager::query()->getCard({relatedCardName}));
deckEditor->showPrintingSelector();
});
}

View File

@ -12,7 +12,7 @@ VisualDatabaseDisplayMainTypeFilterWidget::VisualDatabaseDisplayMainTypeFilterWi
FilterTreeModel *_filterModel)
: QWidget(parent), filterModel(_filterModel)
{
allMainCardTypesWithCount = CardDatabaseManager::getInstance()->getAllMainCardTypesWithCount();
allMainCardTypesWithCount = CardDatabaseManager::query()->getAllMainCardTypesWithCount();
// Get all main card types with their count
setMaximumHeight(75);

View File

@ -13,7 +13,7 @@ VisualDatabaseDisplaySubTypeFilterWidget::VisualDatabaseDisplaySubTypeFilterWidg
FilterTreeModel *_filterModel)
: QWidget(parent), filterModel(_filterModel)
{
allSubCardTypesWithCount = CardDatabaseManager::getInstance()->getAllSubCardTypesWithCount();
allSubCardTypesWithCount = CardDatabaseManager::query()->getAllSubCardTypesWithCount();
setMinimumWidth(300);

View File

@ -303,7 +303,7 @@ void VisualDatabaseDisplayWidget::loadPage(int start, int end)
QVariant name = databaseDisplayModel->data(index, Qt::DisplayRole);
qCDebug(VisualDatabaseDisplayLog) << name.toString();
if (CardInfoPtr info = CardDatabaseManager::getInstance()->getCardInfo(name.toString())) {
if (CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(name.toString())) {
if (!setFilters.empty()) {
SetToPrintingsMap setMap = info->getSets();
for (const CardFilter *setFilter : setFilters) {
@ -314,7 +314,7 @@ void VisualDatabaseDisplayWidget::loadPage(int start, int end)
}
}
} else {
addCard(CardDatabaseManager::getInstance()->getPreferredCard(info));
addCard(CardDatabaseManager::query()->getPreferredCard(info));
}
} else {
qCDebug(VisualDatabaseDisplayLog) << "Card not found in database!";

View File

@ -101,7 +101,7 @@ QList<ExactCard> VisualDeckEditorSampleHandWidget::getRandomCards(int amountToGe
continue;
for (int k = 0; k < currentCard->getNumber(); ++k) {
ExactCard card = CardDatabaseManager::getInstance()->getCard(currentCard->toCardRef());
ExactCard card = CardDatabaseManager::query()->getCard(currentCard->toCardRef());
if (card) {
mainDeckCards.append(card);
}

View File

@ -42,7 +42,7 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, DeckListModel *_
if (!searchBar->hasFocus())
return;
ExactCard card = CardDatabaseManager::getInstance()->getCard({searchBar->text()});
ExactCard card = CardDatabaseManager::query()->getCard({searchBar->text()});
if (card) {
emit cardAdditionRequested(card);
}
@ -103,7 +103,7 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, DeckListModel *_
// Search button functionality
searchPushButton = new QPushButton(this);
connect(searchPushButton, &QPushButton::clicked, this, [=, this]() {
ExactCard card = CardDatabaseManager::getInstance()->getCard({searchBar->text()});
ExactCard card = CardDatabaseManager::query()->getCard({searchBar->text()});
if (card) {
emit cardAdditionRequested(card);
}

View File

@ -76,7 +76,7 @@ void DeckPreviewWidget::initializeUi(const bool deckLoadSuccess)
}
auto bannerCard = deckLoader->getBannerCard().name.isEmpty()
? ExactCard()
: CardDatabaseManager::getInstance()->getCard(deckLoader->getBannerCard());
: CardDatabaseManager::query()->getCard(deckLoader->getBannerCard());
bannerCardDisplayWidget->setCard(bannerCard);
bannerCardDisplayWidget->setFontSize(24);
@ -160,7 +160,7 @@ QString DeckPreviewWidget::getColorIdentity()
QSet<QChar> colorSet; // A set to collect unique color symbols (e.g., W, U, B, R, G)
for (const QString &cardName : cardList) {
CardInfoPtr currentCard = CardDatabaseManager::getInstance()->getCardInfo(cardName);
CardInfoPtr currentCard = CardDatabaseManager::query()->getCardInfo(cardName);
if (currentCard) {
QString colors = currentCard->getColors(); // Assuming this returns something like "WUB"
for (const QChar &color : colors) {
@ -293,7 +293,7 @@ void DeckPreviewWidget::setBannerCard(int /* changedIndex */)
CardRef cardRef = {name, id};
deckLoader->setBannerCard(cardRef);
deckLoader->saveToFile(filePath, DeckLoader::getFormatFromName(filePath));
bannerCardDisplayWidget->setCard(CardDatabaseManager::getInstance()->getCard(cardRef));
bannerCardDisplayWidget->setCard(CardDatabaseManager::query()->getCard(cardRef));
}
void DeckPreviewWidget::imageClickedEvent(QMouseEvent *event, DeckPreviewCardPictureWidget *instance)

View File

@ -161,7 +161,7 @@ void AbstractTabDeckEditor::openDeck(DeckLoader *deck)
void AbstractTabDeckEditor::setDeck(DeckLoader *_deck)
{
deckDockWidget->setDeck(_deck);
PictureLoader::cacheCardPixmaps(CardDatabaseManager::getInstance()->getCards(getDeckList()->getCardRefList()));
PictureLoader::cacheCardPixmaps(CardDatabaseManager::query()->getCards(getDeckList()->getCardRefList()));
setModified(false);
// If they load a deck, make the deck list appear

View File

@ -12,7 +12,7 @@ EdhrecApiResponseCardDetailsDisplayWidget::EdhrecApiResponseCardDetailsDisplayWi
setLayout(layout);
cardPictureWidget = new CardInfoPictureWidget(this);
cardPictureWidget->setCard(CardDatabaseManager::getInstance()->guessCard({toDisplay.sanitized}));
cardPictureWidget->setCard(CardDatabaseManager::query()->guessCard({toDisplay.sanitized}));
nameLabel = new QLabel(this);
nameLabel->setText(toDisplay.name);

View File

@ -15,7 +15,7 @@ EdhrecCommanderResponseCommanderDetailsDisplayWidget::EdhrecCommanderResponseCom
setLayout(layout);
commanderPicture = new CardInfoPictureWidget(this);
commanderPicture->setCard(CardDatabaseManager::getInstance()->getCard({commanderDetails.getName()}));
commanderPicture->setCard(CardDatabaseManager::query()->getCard({commanderDetails.getName()}));
QWidget *currentParent = parentWidget();
TabEdhRecMain *parentTab = nullptr;

View File

@ -136,7 +136,7 @@ void TabEdhRecMain::retranslateUi()
void TabEdhRecMain::doSearch()
{
CardInfoPtr searchedCard = CardDatabaseManager::getInstance()->getCardInfo(searchBar->text());
CardInfoPtr searchedCard = CardDatabaseManager::query()->getCardInfo(searchBar->text());
if (!searchedCard) {
return;
}

View File

@ -740,7 +740,7 @@ void TabGame::loadDeckForLocalPlayer(Player *localPlayer, int playerId, ServerIn
TabbedDeckViewContainer *deckViewContainer = deckViewContainers.value(playerId);
if (playerInfo.has_deck_list()) {
DeckLoader newDeck(QString::fromStdString(playerInfo.deck_list()));
PictureLoader::cacheCardPixmaps(CardDatabaseManager::getInstance()->getCards(newDeck.getCardRefList()));
PictureLoader::cacheCardPixmaps(CardDatabaseManager::query()->getCards(newDeck.getCardRefList()));
deckViewContainer->playerDeckView->setDeck(newDeck);
localPlayer->setDeck(newDeck);
}

View File

@ -20,8 +20,8 @@ bool DeckListSortFilterProxyModel::lessThan(const QModelIndex &left, const QMode
auto *lNode = static_cast<DecklistModelCardNode *>(left.internalPointer());
auto *rNode = static_cast<DecklistModelCardNode *>(right.internalPointer());
CardInfoPtr lInfo = CardDatabaseManager::getInstance()->guessCard({lNode->getName()}).getCardPtr();
CardInfoPtr rInfo = CardDatabaseManager::getInstance()->guessCard({rNode->getName()}).getCardPtr();
CardInfoPtr lInfo = CardDatabaseManager::query()->guessCard({lNode->getName()}).getCardPtr();
CardInfoPtr rInfo = CardDatabaseManager::query()->guessCard({rNode->getName()}).getCardPtr();
// Example: multiple tie-break criteria (colors > cmc > name)
for (const QString &crit : sortCriteria) {

View File

@ -8,6 +8,8 @@ set(dbconverter_SOURCES
../cockatrice/src/card/card_info.cpp
../cockatrice/src/card/exact_card.cpp
../cockatrice/src/database/card_database.cpp
../cockatrice/src/database/card_database_loader.cpp
../cockatrice/src/database/card_database_querier.cpp
../cockatrice/src/database/parser/card_database_parser.cpp
../cockatrice/src/database/parser/cockatrice_xml_3.cpp
../cockatrice/src/database/parser/cockatrice_xml_4.cpp

View File

@ -9,7 +9,7 @@ class CardDatabaseConverter : public CardDatabase
public:
LoadStatus loadCardDatabase(const QString &path)
{
return CardDatabase::loadCardDatabase(path);
return loader->loadCardDatabase(path);
}
bool saveCardDatabase(const QString &fileName)

View File

@ -21,6 +21,8 @@ add_executable(
../../cockatrice/src/card/card_info.cpp
../../cockatrice/src/card/exact_card.cpp
../../cockatrice/src/database/card_database.cpp
../../cockatrice/src/database/card_database_loader.cpp
../../cockatrice/src/database/card_database_querier.cpp
../../cockatrice/src/database/parser/card_database_parser.cpp
../../cockatrice/src/database/parser/cockatrice_xml_3.cpp
../../cockatrice/src/database/parser/cockatrice_xml_4.cpp
@ -35,6 +37,8 @@ add_executable(
../../cockatrice/src/card/card_info.cpp
../../cockatrice/src/card/exact_card.cpp
../../cockatrice/src/database/card_database.cpp
../../cockatrice/src/database/card_database_loader.cpp
../../cockatrice/src/database/card_database_querier.cpp
../../cockatrice/src/database/card_database_manager.cpp
../../cockatrice/src/database/parser/card_database_parser.cpp
../../cockatrice/src/database/parser/cockatrice_xml_3.cpp

View File

@ -13,21 +13,21 @@ TEST(CardDatabaseTest, LoadXml)
// ensure the card database is empty at start
ASSERT_EQ(0, db->getCardList().size()) << "Cards not empty at start";
ASSERT_EQ(0, db->getSetList().size()) << "Sets not empty at start";
ASSERT_EQ(0, db->getAllMainCardTypes().size()) << "Types not empty at start";
ASSERT_EQ(0, db->query()->getAllMainCardTypes().size()) << "Types not empty at start";
ASSERT_EQ(NotLoaded, db->getLoadStatus()) << "Incorrect status at start";
// load dummy cards and test result
db->loadCardDatabases();
ASSERT_EQ(9, db->getCardList().size()) << "Wrong card count after load";
ASSERT_EQ(5, db->getSetList().size()) << "Wrong sets count after load";
ASSERT_EQ(3, db->getAllMainCardTypes().size()) << "Wrong types count after load";
ASSERT_EQ(3, db->query()->getAllMainCardTypes().size()) << "Wrong types count after load";
ASSERT_EQ(Ok, db->getLoadStatus()) << "Wrong status after load";
// ensure the card database is empty after clear()
db->clear();
ASSERT_EQ(0, db->getCardList().size()) << "Cards not empty after clear";
ASSERT_EQ(0, db->getSetList().size()) << "Sets not empty after clear";
ASSERT_EQ(0, db->getAllMainCardTypes().size()) << "Types not empty after clear";
ASSERT_EQ(0, db->query()->getAllMainCardTypes().size()) << "Types not empty after clear";
ASSERT_EQ(NotLoaded, db->getLoadStatus()) << "Incorrect status after clear";
}
} // namespace

View File

@ -18,10 +18,10 @@ class CardQuery : public ::testing::Test
protected:
void SetUp() override
{
cat = CardDatabaseManager::getInstance()->getCardBySimpleName("Cat");
notDeadAfterAll = CardDatabaseManager::getInstance()->getCardBySimpleName("Not Dead");
truth = CardDatabaseManager::getInstance()->getCardBySimpleName("Truth");
doctor = CardDatabaseManager::getInstance()->getCardBySimpleName("Doctor");
cat = CardDatabaseManager::query()->getCardBySimpleName("Cat");
notDeadAfterAll = CardDatabaseManager::query()->getCardBySimpleName("Not Dead");
truth = CardDatabaseManager::query()->getCardBySimpleName("Truth");
doctor = CardDatabaseManager::query()->getCardBySimpleName("Doctor");
}
// void TearDown() override {}