Dependency Injection for SettingsCache

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

Took 2 hours 38 minutes
This commit is contained in:
Lukas Brübach 2025-11-06 18:47:12 +01:00
parent b773909dfd
commit 35d18b5fa9
127 changed files with 1012 additions and 803 deletions

View file

@ -9,8 +9,12 @@ set(HEADERS
libcockatrice/card/database/card_database_loader.h
libcockatrice/card/database/card_database_manager.h
libcockatrice/card/database/card_database_querier.h
libcockatrice/card/database/interface/interface_card_database_path_provider.h
libcockatrice/card/database/interface/interface_card_preference_provider.h
libcockatrice/card/database/interface/interface_card_set_priority_controller.h
libcockatrice/card/database/interface/noop_card_database_path_provider.h
libcockatrice/card/database/interface/noop_card_preference_provider.h
libcockatrice/card/database/interface/noop_card_set_priority_controller.h
libcockatrice/card/database/parser/card_database_parser.h
libcockatrice/card/database/parser/cockatrice_xml_3.h
libcockatrice/card/database/parser/cockatrice_xml_4.h

View file

@ -4,25 +4,26 @@
#include "parser/cockatrice_xml_3.h"
#include "parser/cockatrice_xml_4.h"
#include <../../../../cockatrice/src/client/settings/cache_settings.h>
#include <QCryptographicHash>
#include <QDebug>
#include <QDir>
#include <QDirIterator>
#include <QFile>
#include <QMessageBox>
#include <QRegularExpression>
#include <algorithm>
#include <utility>
CardDatabase::CardDatabase(QObject *parent, QSharedPointer<ICardPreferenceProvider> prefs)
: QObject(parent), loadStatus(NotLoaded)
CardDatabase::CardDatabase(QObject *parent,
QSharedPointer<ICardPreferenceProvider> prefs,
QSharedPointer<ICardDatabasePathProvider> pathProvider,
QSharedPointer<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);
// 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);
@ -139,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

@ -10,6 +10,7 @@
#include "../set/card_set_list.h"
#include "card_database_loader.h"
#include "card_database_querier.h"
#include "interface/interface_card_database_path_provider.h"
#include "interface/noop_card_preference_provider.h"
#include <QBasicMutex>
@ -28,6 +29,8 @@ class CardDatabase : public QObject
{
Q_OBJECT
protected:
QSharedPointer<ICardSetPriorityController> setPriorityController;
/*
* The cards, indexed by name.
*/
@ -58,7 +61,10 @@ private:
*removeCardMutex = new QBasicMutex();
public:
explicit CardDatabase(QObject *parent = nullptr, QSharedPointer<ICardPreferenceProvider> prefs = nullptr);
explicit CardDatabase(QObject *parent = nullptr,
QSharedPointer<ICardPreferenceProvider> prefs = nullptr,
QSharedPointer<ICardDatabasePathProvider> pathProvider = nullptr,
QSharedPointer<ICardSetPriorityController> setPriorityController = nullptr);
~CardDatabase() override;
void removeCard(CardInfoPtr card);

View file

@ -4,13 +4,15 @@
#include "parser/cockatrice_xml_3.h"
#include "parser/cockatrice_xml_4.h"
#include <../../../../cockatrice/src/client/settings/cache_settings.h>
#include <QDebug>
#include <QDirIterator>
#include <QFile>
#include <QTime>
CardDatabaseLoader::CardDatabaseLoader(QObject *parent, CardDatabase *db) : QObject(parent), database(db)
CardDatabaseLoader::CardDatabaseLoader(QObject *parent,
CardDatabase *db,
QSharedPointer<ICardDatabasePathProvider> _pathProvider)
: QObject(parent), database(db), pathProvider(_pathProvider)
{
// instantiate available parsers here and connect them to the database
availableParsers << new CockatriceXml4Parser;
@ -23,7 +25,7 @@ CardDatabaseLoader::CardDatabaseLoader(QObject *parent, CardDatabase *db) : QObj
}
// when SettingsCache's path changes, trigger reloads
connect(&SettingsCache::instance(), &SettingsCache::cardDatabasePathChanged, this,
connect(pathProvider.get(), &ICardDatabasePathProvider::cardDatabasePathChanged, this,
&CardDatabaseLoader::loadCardDatabases);
}
@ -83,10 +85,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 +118,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 +135,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

@ -7,6 +7,8 @@
#ifndef COCKATRICE_CARD_DATABASE_LOADER_H
#define COCKATRICE_CARD_DATABASE_LOADER_H
#include "interface/interface_card_database_path_provider.h"
#include <QBasicMutex>
#include <QList>
#include <QLoggingCategory>
@ -32,7 +34,9 @@ class CardDatabaseLoader : public QObject
{
Q_OBJECT
public:
explicit CardDatabaseLoader(QObject *parent, CardDatabase *db);
explicit CardDatabaseLoader(QObject *parent,
CardDatabase *db,
QSharedPointer<ICardDatabasePathProvider> pathProvider);
~CardDatabaseLoader() override;
public slots:
@ -53,6 +57,8 @@ private:
CardDatabase *database; // non-owning pointer to the container
QSharedPointer<ICardDatabasePathProvider> pathProvider; // pointer to the implementation providing the paths
// parsers
QList<ICardDatabaseParser *> availableParsers;

View file

@ -1,16 +1,33 @@
#include "card_database_manager.h"
#include "interface/noop_card_database_path_provider.h"
#include "interface/noop_card_set_priority_controller.h"
QSharedPointer<ICardPreferenceProvider> CardDatabaseManager::cardPreferenceProvider =
QSharedPointer<NoopCardPreferenceProvider>::create();
QSharedPointer<ICardDatabasePathProvider> CardDatabaseManager::pathProvider =
QSharedPointer<NoopCardDatabasePathProvider>::create();
QSharedPointer<ICardSetPriorityController> CardDatabaseManager::setPriorityController =
QSharedPointer<NoopCardSetPriorityController>::create();
void CardDatabaseManager::setCardPreferenceProvider(QSharedPointer<ICardPreferenceProvider> provider)
{
cardPreferenceProvider = provider;
}
void CardDatabaseManager::setCardDatabasePathProvider(QSharedPointer<ICardDatabasePathProvider> provider)
{
pathProvider = provider;
}
void CardDatabaseManager::setCardSetPriorityController(QSharedPointer<ICardSetPriorityController> controller)
{
setPriorityController = controller;
}
CardDatabase *CardDatabaseManager::getInstance()
{
static CardDatabase instance(nullptr, cardPreferenceProvider);
static CardDatabase instance(nullptr, cardPreferenceProvider, pathProvider, setPriorityController);
return &instance;
}

View file

@ -19,6 +19,8 @@ public:
// To be called once, before instantiation of the manager
static void setCardPreferenceProvider(QSharedPointer<ICardPreferenceProvider> provider);
static void setCardDatabasePathProvider(QSharedPointer<ICardDatabasePathProvider> provider);
static void setCardSetPriorityController(QSharedPointer<ICardSetPriorityController> controller);
// Static method to access the singleton instance
static CardDatabase *getInstance();
@ -28,6 +30,8 @@ private:
CardDatabaseManager() = default; // Private constructor
~CardDatabaseManager() = default;
static QSharedPointer<ICardPreferenceProvider> cardPreferenceProvider;
static QSharedPointer<ICardDatabasePathProvider> pathProvider;
static QSharedPointer<ICardSetPriorityController> setPriorityController;
};
#endif // CARD_DATABASE_ACCESSOR_H

View file

@ -0,0 +1,21 @@
#ifndef COCKATRICE_INTERFACE_CARD_DATABASE_PATH_PROVIDER_H
#define COCKATRICE_INTERFACE_CARD_DATABASE_PATH_PROVIDER_H
#include <QObject>
class ICardDatabasePathProvider : public QObject
{
Q_OBJECT
public:
virtual ~ICardDatabasePathProvider() = default;
virtual QString getCardDatabasePath() const = 0;
virtual QString getCustomCardDatabasePath() const = 0;
virtual QString getTokenDatabasePath() const = 0;
virtual QString getSpoilerCardDatabasePath() const = 0;
signals:
void cardDatabasePathChanged();
};
#endif // COCKATRICE_INTERFACE_CARD_DATABASE_PATH_PROVIDER_H

View file

@ -0,0 +1,19 @@
#ifndef COCKATRICE_INTERFACE_CARD_SET_PRIORITY_CONTROLLER_H
#define COCKATRICE_INTERFACE_CARD_SET_PRIORITY_CONTROLLER_H
#include <QString>
class ICardSetPriorityController
{
public:
virtual ~ICardSetPriorityController() = default;
virtual void setSortKey(QString shortName, unsigned int sortKey) = 0;
virtual void setEnabled(QString shortName, bool enabled) = 0;
virtual void setIsKnown(QString shortName, bool isknown) = 0;
virtual unsigned int getSortKey(QString shortName) = 0;
virtual bool isEnabled(QString shortName) = 0;
virtual bool isKnown(QString shortName) = 0;
};
#endif // COCKATRICE_INTERFACE_CARD_SET_PRIORITY_CONTROLLER_H

View file

@ -0,0 +1,26 @@
#ifndef COCKATRICE_NOOP_CARD_DATABASE_PATH_PROVIDER_H
#define COCKATRICE_NOOP_CARD_DATABASE_PATH_PROVIDER_H
#include "interface_card_database_path_provider.h"
class NoopCardDatabasePathProvider : public ICardDatabasePathProvider
{
public:
QString getCardDatabasePath() const override
{
return "";
}
QString getCustomCardDatabasePath() const override
{
return "";
}
QString getTokenDatabasePath() const override
{
return "";
}
QString getSpoilerCardDatabasePath() const override
{
return "";
}
};
#endif // COCKATRICE_NOOP_CARD_DATABASE_PATH_PROVIDER_H

View file

@ -0,0 +1,32 @@
#ifndef COCKATRICE_NOOP_CARD_SET_PRIORITY_CONTROLLER_H
#define COCKATRICE_NOOP_CARD_SET_PRIORITY_CONTROLLER_H
#include "interface_card_set_priority_controller.h"
class NoopCardSetPriorityController : public ICardSetPriorityController
{
public:
void setSortKey(QString /* shortName */, unsigned int /* sortKey */)
{
}
void setEnabled(QString /* shortName */, bool /* enabled */)
{
}
void setIsKnown(QString /* shortName */, bool /* isknown */)
{
}
unsigned int getSortKey(QString /* shortName */)
{
return 0;
}
bool isEnabled(QString /* shortName */)
{
return true;
}
bool isKnown(QString /* shortName */)
{
return true;
}
};
#endif // COCKATRICE_NOOP_CARD_SET_PRIORITY_CONTROLLER_H

View file

@ -1,5 +1,7 @@
#include "card_database_parser.h"
#include "libcockatrice/card/database/interface/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(QSharedPointer<NoopCardSetPriorityController>::create(), setName);
newSet->setLongName(longName);
newSet->setSetType(setType);
newSet->setReleaseDate(releaseDate);

View file

@ -132,7 +132,7 @@ QVariantHash CockatriceXml4Parser::loadCardPropertiesFromXml(QXmlStreamReader &x
void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
{
bool includeRebalancedCards =
true; // TODO: MOVE THIS OUT OF THE PARSER SettingsCache::instance().getIncludeRebalancedCards();
true; // TODO: MOVE THIS OUT OF THE PARSER SettingsCache::instance()->getIncludeRebalancedCards();
while (!xml.atEnd()) {
if (xml.readNext() == QXmlStreamReader::EndElement) {
break;

View file

@ -1,26 +1,29 @@
#include "card_set.h"
#include <../../../../cockatrice/src/client/settings/cache_settings.h>
#include <utility>
const char *CardSet::TOKENS_SETNAME = "TK";
CardSet::CardSet(const QString &_shortName,
CardSet::CardSet(QSharedPointer<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(QSharedPointer<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 +60,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

@ -1,6 +1,8 @@
#ifndef COCKATRICE_CARD_SET_H
#define COCKATRICE_CARD_SET_H
#include "libcockatrice/card/database/interface/interface_card_set_priority_controller.h"
#include <QDate>
#include <QList>
#include <QSharedPointer>
@ -28,6 +30,7 @@ public:
static const char *TOKENS_SETNAME;
private:
QSharedPointer<ICardSetPriorityController> priorityController;
QString shortName, longName;
unsigned int sortKey;
QDate releaseDate;
@ -36,13 +39,15 @@ private:
bool enabled, isknown;
public:
explicit CardSet(const QString &_shortName = QString(),
explicit CardSet(QSharedPointer<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(QSharedPointer<ICardSetPriorityController> priorityController,
const QString &_shortName = QString(),
const QString &_longName = QString(),
const QString &_setType = QString(),
const QDate &_releaseDate = QDate(),