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

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

Took 13 minutes

Took 37 seconds

Took 10 seconds

Took 10 seconds

# Commit time for manual adjustment:
# Took 30 seconds

Took 15 seconds


Took 8 minutes

Took 21 seconds

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

Took 52 minutes

Took 9 minutes

Took 1 minute

* Temp cache.

Took 16 minutes

* Dependency Injection for SettingsCache

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

Took 2 hours 38 minutes

* Adjust oracle.

Took 5 minutes

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

Took 52 minutes

* Clean up some links.

Took 3 minutes

* Cleanup two includes.

Took 3 minutes

* More fixes.

Took 7 minutes

* More includes that slipped past.

Took 3 minutes

* Stop mocking and start injecting for tests.

Took 15 minutes

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

Took 4 minutes

* Include.

Took 3 minutes

* Lint.

Took 2 minutes

* Don't use Qt pointers.

Took 1 hour 7 minutes

* Make parser use CardSettingsInterface

Took 13 minutes

* Also adjust constructor lol.

Took 8 minutes

* Lint.

Took 32 minutes

* Revert "Lint."

This reverts commit ecb596c39e.


Took 3 minutes

* Test.

Took 3 minutes

---------

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

View File

@@ -51,6 +51,7 @@ target_include_directories(
target_link_libraries(
libcockatrice_card
PUBLIC libcockatrice_settings
PUBLIC libcockatrice_interfaces
PUBLIC libcockatrice_utility
PUBLIC ${QT_CORE_MODULE}
)

View File

@@ -11,7 +11,6 @@
#include <QString>
#include <QVariant>
#include <algorithm>
#include <libcockatrice/settings/cache_settings.h>
#include <utility>
class CardRelation;

View File

@@ -9,26 +9,28 @@
#include <QDir>
#include <QDirIterator>
#include <QFile>
#include <QMessageBox>
#include <QRegularExpression>
#include <algorithm>
#include <libcockatrice/settings/cache_settings.h>
#include <utility>
CardDatabase::CardDatabase(QObject *parent) : QObject(parent), loadStatus(NotLoaded)
CardDatabase::CardDatabase(QObject *parent,
ICardPreferenceProvider *prefs,
ICardDatabasePathProvider *pathProvider,
ICardSetPriorityController *_setPriorityController)
: QObject(parent), setPriorityController(_setPriorityController), loadStatus(NotLoaded)
{
qRegisterMetaType<CardInfoPtr>("CardInfoPtr");
qRegisterMetaType<CardInfoPtr>("CardSetPtr");
// create loader and wire it up
loader = new CardDatabaseLoader(this, this);
loader = new CardDatabaseLoader(this, this, pathProvider, prefs);
// 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);
querier = new CardDatabaseQuerier(this, this);
querier = new CardDatabaseQuerier(this, this, prefs);
}
CardDatabase::~CardDatabase()
@@ -138,7 +140,7 @@ CardSetPtr CardDatabase::getSet(const QString &setName)
if (sets.contains(setName)) {
return sets.value(setName);
} else {
CardSetPtr newSet = CardSet::newInstance(setName);
CardSetPtr newSet = CardSet::newInstance(setPriorityController, setName);
sets.insert(setName, newSet);
return newSet;
}

View File

@@ -18,6 +18,7 @@
#include <QLoggingCategory>
#include <QStringList>
#include <QVector>
#include <libcockatrice/interfaces/interface_card_database_path_provider.h>
#include <libcockatrice/utility/card_ref.h>
#include <utility>
@@ -27,6 +28,8 @@ class CardDatabase : public QObject
{
Q_OBJECT
protected:
ICardSetPriorityController *setPriorityController;
/*
* The cards, indexed by name.
*/
@@ -57,7 +60,10 @@ private:
*removeCardMutex = new QBasicMutex();
public:
explicit CardDatabase(QObject *parent = nullptr);
explicit CardDatabase(QObject *parent = nullptr,
ICardPreferenceProvider *prefs = nullptr,
ICardDatabasePathProvider *pathProvider = nullptr,
ICardSetPriorityController *setPriorityController = nullptr);
~CardDatabase() override;
void removeCard(CardInfoPtr card);

View File

@@ -8,12 +8,15 @@
#include <QDirIterator>
#include <QFile>
#include <QTime>
#include <libcockatrice/settings/cache_settings.h>
CardDatabaseLoader::CardDatabaseLoader(QObject *parent, CardDatabase *db) : QObject(parent), database(db)
CardDatabaseLoader::CardDatabaseLoader(QObject *parent,
CardDatabase *db,
ICardDatabasePathProvider *_pathProvider,
ICardPreferenceProvider *_preferenceProvider)
: QObject(parent), database(db), pathProvider(_pathProvider)
{
// instantiate available parsers here and connect them to the database
availableParsers << new CockatriceXml4Parser;
availableParsers << new CockatriceXml4Parser(_preferenceProvider);
availableParsers << new CockatriceXml3Parser;
for (auto *p : availableParsers) {
@@ -23,7 +26,7 @@ CardDatabaseLoader::CardDatabaseLoader(QObject *parent, CardDatabase *db) : QObj
}
// when SettingsCache's path changes, trigger reloads
connect(&SettingsCache::instance(), &SettingsCache::cardDatabasePathChanged, this,
connect(pathProvider, &ICardDatabasePathProvider::cardDatabasePathChanged, this,
&CardDatabaseLoader::loadCardDatabases);
}
@@ -83,10 +86,9 @@ LoadStatus CardDatabaseLoader::loadCardDatabases()
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
LoadStatus loadStatus = loadCardDatabase(pathProvider->getCardDatabasePath()); // load main card database
loadCardDatabase(pathProvider->getTokenDatabasePath()); // load tokens database
loadCardDatabase(pathProvider->getSpoilerCardDatabasePath()); // load spoilers database
// find all custom card databases, recursively & following symlinks
// then load them alphabetically
@@ -117,7 +119,7 @@ LoadStatus CardDatabaseLoader::loadCardDatabases()
QStringList CardDatabaseLoader::collectCustomDatabasePaths() const
{
QDirIterator it(SettingsCache::instance().getCustomCardDatabasePath(), {"*.xml"}, QDir::Files,
QDirIterator it(pathProvider->getCustomCardDatabasePath(), {"*.xml"}, QDir::Files,
QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
QStringList paths;
@@ -134,7 +136,7 @@ bool CardDatabaseLoader::saveCustomTokensToFile()
return false;
}
QString fileName = SettingsCache::instance().getCustomCardDatabasePath() + "/" + CardSet::TOKENS_SETNAME + ".xml";
QString fileName = pathProvider->getCustomCardDatabasePath() + "/" + CardSet::TOKENS_SETNAME + ".xml";
SetNameMap tmpSets;
CardSetPtr customTokensSet = database->getSet(CardSet::TOKENS_SETNAME);

View File

@@ -11,6 +11,8 @@
#include <QList>
#include <QLoggingCategory>
#include <QObject>
#include <libcockatrice/interfaces/interface_card_database_path_provider.h>
#include <libcockatrice/interfaces/interface_card_preference_provider.h>
inline Q_LOGGING_CATEGORY(CardDatabaseLoadingLog, "card_database.loading");
inline Q_LOGGING_CATEGORY(CardDatabaseLoadingSuccessOrFailureLog, "card_database.loading.success_or_failure");
@@ -32,7 +34,10 @@ class CardDatabaseLoader : public QObject
{
Q_OBJECT
public:
explicit CardDatabaseLoader(QObject *parent, CardDatabase *db);
explicit CardDatabaseLoader(QObject *parent,
CardDatabase *db,
ICardDatabasePathProvider *pathProvider,
ICardPreferenceProvider *preferenceProvider);
~CardDatabaseLoader() override;
public slots:
@@ -53,6 +58,8 @@ private:
CardDatabase *database; // non-owning pointer to the container
ICardDatabasePathProvider *pathProvider; // pointer to the implementation providing the paths
// parsers
QList<ICardDatabaseParser *> availableParsers;

View File

@@ -1,8 +1,31 @@
#include "card_database_manager.h"
#include <libcockatrice/interfaces/noop_card_database_path_provider.h>
#include <libcockatrice/interfaces/noop_card_preference_provider.h>
#include <libcockatrice/interfaces/noop_card_set_priority_controller.h>
ICardPreferenceProvider *CardDatabaseManager::cardPreferenceProvider = new NoopCardPreferenceProvider();
ICardDatabasePathProvider *CardDatabaseManager::pathProvider = new NoopCardDatabasePathProvider();
ICardSetPriorityController *CardDatabaseManager::setPriorityController = new NoopCardSetPriorityController();
void CardDatabaseManager::setCardPreferenceProvider(ICardPreferenceProvider *provider)
{
cardPreferenceProvider = provider;
}
void CardDatabaseManager::setCardDatabasePathProvider(ICardDatabasePathProvider *provider)
{
pathProvider = provider;
}
void CardDatabaseManager::setCardSetPriorityController(ICardSetPriorityController *controller)
{
setPriorityController = controller;
}
CardDatabase *CardDatabaseManager::getInstance()
{
static CardDatabase instance; // Created only once, on first access
static CardDatabase instance(nullptr, cardPreferenceProvider, pathProvider, setPriorityController);
return &instance;
}

View File

@@ -17,6 +17,11 @@ public:
CardDatabaseManager(const CardDatabaseManager &) = delete;
CardDatabaseManager &operator=(const CardDatabaseManager &) = delete;
// To be called once, before instantiation of the manager
static void setCardPreferenceProvider(ICardPreferenceProvider *provider);
static void setCardDatabasePathProvider(ICardDatabasePathProvider *provider);
static void setCardSetPriorityController(ICardSetPriorityController *controller);
// Static method to access the singleton instance
static CardDatabase *getInstance();
static CardDatabaseQuerier *query();
@@ -24,6 +29,9 @@ public:
private:
CardDatabaseManager() = default; // Private constructor
~CardDatabaseManager() = default;
static ICardPreferenceProvider *cardPreferenceProvider;
static ICardDatabasePathProvider *pathProvider;
static ICardSetPriorityController *setPriorityController;
};
#endif // CARD_DATABASE_ACCESSOR_H

View File

@@ -7,7 +7,10 @@
#include <qrandom.h>
CardDatabaseQuerier::CardDatabaseQuerier(QObject *_parent, const CardDatabase *_db) : QObject(_parent), db(_db)
CardDatabaseQuerier::CardDatabaseQuerier(QObject *_parent,
const CardDatabase *_db,
const ICardPreferenceProvider *prefs)
: QObject(_parent), db(_db), prefs(prefs)
{
}
@@ -204,6 +207,17 @@ PrintingInfo CardDatabaseQuerier::getSpecificPrinting(const QString &cardName,
return PrintingInfo(nullptr);
}
/**
* Gets the card representing the preferred printing of the cardInfo
*
* @param cardName The cardName to find the preferred card and printing for
* @return A specific printing of a card
*/
ExactCard CardDatabaseQuerier::getPreferredCard(const QString &cardName) const
{
return getPreferredCard(getCardInfo(cardName));
}
/**
* Gets the card representing the preferred printing of the cardInfo
*
@@ -236,6 +250,12 @@ PrintingInfo CardDatabaseQuerier::getPreferredPrinting(const CardInfoPtr &cardIn
return PrintingInfo(nullptr);
}
const auto &pinnedPrintingProviderId = prefs->getCardPreferenceOverride(cardInfo->getName());
if (!pinnedPrintingProviderId.isEmpty()) {
return getSpecificPrinting({cardInfo->getName(), pinnedPrintingProviderId});
}
SetToPrintingsMap setMap = cardInfo->getSets();
if (setMap.empty()) {
return PrintingInfo(nullptr);

View File

@@ -11,6 +11,7 @@
#include "../printing/exact_card.h"
#include <QObject>
#include <libcockatrice/interfaces/interface_card_preference_provider.h>
#include <libcockatrice/utility/card_ref.h>
class CardDatabase;
@@ -19,7 +20,7 @@ class CardDatabaseQuerier : public QObject
Q_OBJECT
public:
explicit CardDatabaseQuerier(QObject *parent, const CardDatabase *db);
explicit CardDatabaseQuerier(QObject *parent, const CardDatabase *db, const ICardPreferenceProvider *prefs);
[[nodiscard]] CardInfoPtr getCardInfo(const QString &cardName) const;
[[nodiscard]] QList<CardInfoPtr> getCardInfos(const QStringList &cardNames) const;
@@ -46,6 +47,7 @@ public:
[[nodiscard]] PrintingInfo getSpecificPrinting(const CardRef &cardRef) const;
[[nodiscard]] PrintingInfo
getSpecificPrinting(const QString &cardName, const QString &setCode, const QString &collectorNumber) const;
ExactCard getPreferredCard(const QString &cardName) const;
[[nodiscard]] PrintingInfo findPrintingWithId(const CardInfoPtr &card, const QString &providerId) const;
[[nodiscard]] QStringList getAllMainCardTypes() const;
@@ -55,6 +57,8 @@ public:
private:
const CardDatabase *db;
const ICardPreferenceProvider *prefs;
CardInfoPtr lookupCardByName(const QString &name) const;
};

View File

@@ -1,5 +1,7 @@
#include "card_database_parser.h"
#include <libcockatrice/interfaces/noop_card_set_priority_controller.h>
SetNameMap ICardDatabaseParser::sets;
void ICardDatabaseParser::clearSetlist()
@@ -17,7 +19,7 @@ CardSetPtr ICardDatabaseParser::internalAddSet(const QString &setName,
return sets.value(setName);
}
CardSetPtr newSet = CardSet::newInstance(setName);
CardSetPtr newSet = CardSet::newInstance(new NoopCardSetPriorityController(), setName);
newSet->setLongName(longName);
newSet->setSetType(setType);
newSet->setReleaseDate(releaseDate);

View File

@@ -6,7 +6,6 @@
#include <QDebug>
#include <QFile>
#include <QXmlStreamReader>
#include <libcockatrice/settings/cache_settings.h>
#include <version_string.h>
#define COCKATRICE_XML4_TAGNAME "cockatrice_carddatabase"
@@ -14,6 +13,11 @@
#define COCKATRICE_XML4_SCHEMALOCATION \
"https://raw.githubusercontent.com/Cockatrice/Cockatrice/master/doc/carddatabase_v4/cards.xsd"
CockatriceXml4Parser::CockatriceXml4Parser(ICardPreferenceProvider *_cardPreferenceProvider)
: cardPreferenceProvider(_cardPreferenceProvider)
{
}
bool CockatriceXml4Parser::getCanParseFile(const QString &fileName, QIODevice &device)
{
qCInfo(CockatriceXml4Log) << "Trying to parse: " << fileName;
@@ -132,7 +136,7 @@ QVariantHash CockatriceXml4Parser::loadCardPropertiesFromXml(QXmlStreamReader &x
void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
{
bool includeRebalancedCards = SettingsCache::instance().getIncludeRebalancedCards();
bool includeRebalancedCards = cardPreferenceProvider->getIncludeRebalancedCards();
while (!xml.atEnd()) {
if (xml.readNext() == QXmlStreamReader::EndElement) {
break;

View File

@@ -11,6 +11,7 @@
#include <QLoggingCategory>
#include <QXmlStreamReader>
#include <libcockatrice/interfaces/interface_card_preference_provider.h>
inline Q_LOGGING_CATEGORY(CockatriceXml4Log, "cockatrice_xml.xml_4_parser");
@@ -18,7 +19,7 @@ class CockatriceXml4Parser : public ICardDatabaseParser
{
Q_OBJECT
public:
CockatriceXml4Parser() = default;
CockatriceXml4Parser(ICardPreferenceProvider *cardPreferenceProvider);
~CockatriceXml4Parser() override = default;
bool getCanParseFile(const QString &name, QIODevice &device) override;
void parseFile(QIODevice &device) override;
@@ -29,6 +30,8 @@ public:
const QString &sourceVersion = "unknown") override;
private:
ICardPreferenceProvider *cardPreferenceProvider;
QVariantHash loadCardPropertiesFromXml(QXmlStreamReader &xml);
void loadCardsFromXml(QXmlStreamReader &xml);
void loadSetsFromXml(QXmlStreamReader &xml);

View File

@@ -1,26 +1,30 @@
#include "card_set.h"
#include <libcockatrice/settings/cache_settings.h>
#include <QSet>
#include <utility>
const char *CardSet::TOKENS_SETNAME = "TK";
CardSet::CardSet(const QString &_shortName,
CardSet::CardSet(ICardSetPriorityController *_priorityController,
const QString &_shortName,
const QString &_longName,
const QString &_setType,
const QDate &_releaseDate,
const CardSet::Priority _priority)
: shortName(_shortName), longName(_longName), releaseDate(_releaseDate), setType(_setType), priority(_priority)
: priorityController(std::move(_priorityController)), shortName(_shortName), longName(_longName),
releaseDate(_releaseDate), setType(_setType), priority(_priority)
{
loadSetOptions();
}
CardSetPtr CardSet::newInstance(const QString &_shortName,
CardSetPtr CardSet::newInstance(ICardSetPriorityController *_priorityController,
const QString &_shortName,
const QString &_longName,
const QString &_setType,
const QDate &_releaseDate,
const Priority _priority)
{
CardSetPtr ptr(new CardSet(_shortName, _longName, _setType, _releaseDate, _priority));
CardSetPtr ptr(new CardSet(_priorityController, _shortName, _longName, _setType, _releaseDate, _priority));
// ptr->setSmartPointer(ptr);
return ptr;
}
@@ -57,25 +61,25 @@ QString CardSet::getCorrectedShortName() const
void CardSet::loadSetOptions()
{
sortKey = SettingsCache::instance().cardDatabase().getSortKey(shortName);
enabled = SettingsCache::instance().cardDatabase().isEnabled(shortName);
isknown = SettingsCache::instance().cardDatabase().isKnown(shortName);
sortKey = priorityController->getSortKey(shortName);
enabled = priorityController->isEnabled(shortName);
isknown = priorityController->isKnown(shortName);
}
void CardSet::setSortKey(unsigned int _sortKey)
{
sortKey = _sortKey;
SettingsCache::instance().cardDatabase().setSortKey(shortName, _sortKey);
priorityController->setSortKey(shortName, _sortKey);
}
void CardSet::setEnabled(bool _enabled)
{
enabled = _enabled;
SettingsCache::instance().cardDatabase().setEnabled(shortName, _enabled);
priorityController->setEnabled(shortName, _enabled);
}
void CardSet::setIsKnown(bool _isknown)
{
isknown = _isknown;
SettingsCache::instance().cardDatabase().setIsKnown(shortName, _isknown);
priorityController->setIsKnown(shortName, _isknown);
}

View File

@@ -5,6 +5,7 @@
#include <QList>
#include <QSharedPointer>
#include <QString>
#include <libcockatrice/interfaces/interface_card_set_priority_controller.h>
class CardInfo;
using CardInfoPtr = QSharedPointer<CardInfo>;
@@ -28,6 +29,7 @@ public:
static const char *TOKENS_SETNAME;
private:
QSharedPointer<ICardSetPriorityController> priorityController;
QString shortName, longName;
unsigned int sortKey;
QDate releaseDate;
@@ -36,13 +38,15 @@ private:
bool enabled, isknown;
public:
explicit CardSet(const QString &_shortName = QString(),
explicit CardSet(ICardSetPriorityController *priorityController,
const QString &_shortName = QString(),
const QString &_longName = QString(),
const QString &_setType = QString(),
const QDate &_releaseDate = QDate(),
const Priority _priority = PriorityFallback);
static CardSetPtr newInstance(const QString &_shortName = QString(),
static CardSetPtr newInstance(ICardSetPriorityController *priorityController,
const QString &_shortName = QString(),
const QString &_longName = QString(),
const QString &_setType = QString(),
const QDate &_releaseDate = QDate(),