[Refactor] Pass around LoadedDeck instead of DeckLoader (#6422)

This commit is contained in:
RickyRister 2025-12-20 04:39:00 -08:00 committed by GitHub
parent 367507e054
commit d6db21419c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
44 changed files with 253 additions and 264 deletions

View file

@ -18,21 +18,21 @@ class IJsonDeckParser
public: public:
virtual ~IJsonDeckParser() = default; virtual ~IJsonDeckParser() = default;
virtual DeckLoader *parse(const QJsonObject &obj) = 0; virtual DeckList parse(const QJsonObject &obj) = 0;
}; };
class ArchidektJsonParser : public IJsonDeckParser class ArchidektJsonParser : public IJsonDeckParser
{ {
public: public:
DeckLoader *parse(const QJsonObject &obj) override DeckList parse(const QJsonObject &obj) override
{ {
DeckLoader *loader = new DeckLoader(nullptr); DeckList deckList;
QString deckName = obj.value("name").toString(); QString deckName = obj.value("name").toString();
QString deckDescription = obj.value("description").toString(); QString deckDescription = obj.value("description").toString();
loader->getDeckList()->setName(deckName); deckList.setName(deckName);
loader->getDeckList()->setComments(deckDescription); deckList.setComments(deckDescription);
QString outputText; QString outputText;
QTextStream outStream(&outputText); QTextStream outStream(&outputText);
@ -49,25 +49,25 @@ public:
outStream << quantity << ' ' << cardName << " (" << setName << ") " << collectorNumber << '\n'; outStream << quantity << ' ' << cardName << " (" << setName << ") " << collectorNumber << '\n';
} }
loader->getDeckList()->loadFromStream_Plain(outStream, false); deckList.loadFromStream_Plain(outStream, false);
loader->getDeckList()->forEachCard(CardNodeFunction::ResolveProviderId()); deckList.forEachCard(CardNodeFunction::ResolveProviderId());
return loader; return deckList;
} }
}; };
class MoxfieldJsonParser : public IJsonDeckParser class MoxfieldJsonParser : public IJsonDeckParser
{ {
public: public:
DeckLoader *parse(const QJsonObject &obj) override DeckList parse(const QJsonObject &obj) override
{ {
DeckLoader *loader = new DeckLoader(nullptr); DeckList deckList;
QString deckName = obj.value("name").toString(); QString deckName = obj.value("name").toString();
QString deckDescription = obj.value("description").toString(); QString deckDescription = obj.value("description").toString();
loader->getDeckList()->setName(deckName); deckList.setName(deckName);
loader->getDeckList()->setComments(deckDescription); deckList.setComments(deckDescription);
QString outputText; QString outputText;
QTextStream outStream(&outputText); QTextStream outStream(&outputText);
@ -96,8 +96,8 @@ public:
outStream << quantity << ' ' << cardName << " (" << setName << ") " << collectorNumber << '\n'; outStream << quantity << ' ' << cardName << " (" << setName << ") " << collectorNumber << '\n';
} }
loader->getDeckList()->loadFromStream_Plain(outStream, false); deckList.loadFromStream_Plain(outStream, false);
loader->getDeckList()->forEachCard(CardNodeFunction::ResolveProviderId()); deckList.forEachCard(CardNodeFunction::ResolveProviderId());
QJsonObject commandersObj = obj.value("commanders").toObject(); QJsonObject commandersObj = obj.value("commanders").toObject();
if (!commandersObj.isEmpty()) { if (!commandersObj.isEmpty()) {
@ -108,12 +108,12 @@ public:
QString collectorNumber = cardData.value("cn").toString(); QString collectorNumber = cardData.value("cn").toString();
QString providerId = cardData.value("scryfall_id").toString(); QString providerId = cardData.value("scryfall_id").toString();
loader->getDeckList()->setBannerCard({commanderName, providerId}); deckList.setBannerCard({commanderName, providerId});
loader->getDeckList()->addCard(commanderName, DECK_ZONE_MAIN, -1, setName, collectorNumber, providerId); deckList.addCard(commanderName, DECK_ZONE_MAIN, -1, setName, collectorNumber, providerId);
} }
} }
return loader; return deckList;
} }
}; };

View file

@ -119,7 +119,7 @@ static void setupParserRules()
return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) -> bool { return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) -> bool {
int count = 0; int count = 0;
auto cardNodes = deck->deckLoader->getDeckList()->getCardNodes(); auto cardNodes = deck->deckLoader->getDeck().deckList.getCardNodes();
for (auto node : cardNodes) { for (auto node : cardNodes) {
auto cardInfoPtr = CardDatabaseManager::query()->getCardInfo(node->getName()); auto cardInfoPtr = CardDatabaseManager::query()->getCardInfo(node->getName());
if (!cardInfoPtr.isNull() && cardFilter.check(cardInfoPtr)) { if (!cardInfoPtr.isNull() && cardFilter.check(cardInfoPtr)) {
@ -139,7 +139,7 @@ static void setupParserRules()
search["DeckNameQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter { search["DeckNameQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter {
auto name = std::any_cast<QString>(sv[0]); auto name = std::any_cast<QString>(sv[0]);
return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) { return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) {
return deck->deckLoader->getDeckList()->getName().contains(name, Qt::CaseInsensitive); return deck->deckLoader->getDeck().deckList.getName().contains(name, Qt::CaseInsensitive);
}; };
}; };
@ -161,7 +161,7 @@ static void setupParserRules()
search["FormatQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter { search["FormatQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter {
auto format = std::any_cast<QString>(sv[0]); auto format = std::any_cast<QString>(sv[0]);
return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) { return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) {
auto gameFormat = deck->deckLoader->getDeckList()->getGameFormat(); auto gameFormat = deck->deckLoader->getDeck().deckList.getGameFormat();
return QString::compare(format, gameFormat, Qt::CaseInsensitive) == 0; return QString::compare(format, gameFormat, Qt::CaseInsensitive) == 0;
}; };
}; };

View file

@ -269,12 +269,12 @@ void DeckViewContainer::loadDeckFromFile(const QString &filePath)
return; return;
} }
loadDeckFromDeckLoader(&deck); loadDeckFromDeckList(deck.getDeck().deckList);
} }
void DeckViewContainer::loadDeckFromDeckLoader(DeckLoader *deck) void DeckViewContainer::loadDeckFromDeckList(const DeckList &deck)
{ {
QString deckString = deck->getDeckList()->writeToString_Native(); QString deckString = deck.writeToString_Native();
if (deckString.length() > MAX_FILE_LENGTH) { if (deckString.length() > MAX_FILE_LENGTH) {
QMessageBox::critical(this, tr("Error"), tr("Deck is greater than maximum file size.")); QMessageBox::critical(this, tr("Error"), tr("Deck is greater than maximum file size."));
@ -308,8 +308,8 @@ void DeckViewContainer::loadFromClipboard()
return; return;
} }
DeckLoader *deck = dlg.getDeckList(); DeckList deck = dlg.getDeckList();
loadDeckFromDeckLoader(deck); loadDeckFromDeckList(deck);
} }
void DeckViewContainer::loadFromWebsite() void DeckViewContainer::loadFromWebsite()
@ -320,16 +320,15 @@ void DeckViewContainer::loadFromWebsite()
return; return;
} }
DeckLoader *deck = dlg.getDeck(); DeckList deck = dlg.getDeck();
loadDeckFromDeckLoader(deck); loadDeckFromDeckList(deck);
} }
void DeckViewContainer::deckSelectFinished(const Response &r) void DeckViewContainer::deckSelectFinished(const Response &r)
{ {
const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext); const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext);
DeckLoader newDeck(this, new DeckList(QString::fromStdString(resp.deck()))); DeckList newDeck = DeckList(QString::fromStdString(resp.deck()));
CardPictureLoader::cacheCardPixmaps( CardPictureLoader::cacheCardPixmaps(CardDatabaseManager::query()->getCards(newDeck.getCardRefList()));
CardDatabaseManager::query()->getCards(newDeck.getDeckList()->getCardRefList()));
setDeck(newDeck); setDeck(newDeck);
switchToDeckLoadedView(); switchToDeckLoadedView();
} }
@ -410,8 +409,8 @@ void DeckViewContainer::setSideboardLocked(bool locked)
deckView->resetSideboardPlan(); deckView->resetSideboardPlan();
} }
void DeckViewContainer::setDeck(DeckLoader &deck) void DeckViewContainer::setDeck(const DeckList &deck)
{ {
deckView->setDeck(*deck.getDeckList()); deckView->setDeck(deck);
switchToDeckLoadedView(); switchToDeckLoadedView();
} }

View file

@ -85,12 +85,12 @@ public:
void setReadyStart(bool ready); void setReadyStart(bool ready);
void readyAndUpdate(); void readyAndUpdate();
void setSideboardLocked(bool locked); void setSideboardLocked(bool locked);
void setDeck(DeckLoader &deck); void setDeck(const DeckList &deck);
void setVisualDeckStorageExists(bool exists); void setVisualDeckStorageExists(bool exists);
public slots: public slots:
void loadDeckFromFile(const QString &filePath); void loadDeckFromFile(const QString &filePath);
void loadDeckFromDeckLoader(DeckLoader *deck); void loadDeckFromDeckList(const DeckList &deck);
}; };
#endif // DECK_VIEW_CONTAINER_H #endif // DECK_VIEW_CONTAINER_H

View file

@ -60,13 +60,13 @@ void UtilityMenu::populatePredefinedTokensMenu()
clear(); clear();
setEnabled(false); setEnabled(false);
predefinedTokens.clear(); predefinedTokens.clear();
DeckLoader *_deck = player->getDeck(); const DeckList &deckList = player->getDeck();
if (!_deck) { if (deckList.isEmpty()) {
return; return;
} }
auto tokenCardNodes = _deck->getDeckList()->getCardNodes({DECK_ZONE_TOKENS}); auto tokenCardNodes = deckList.getCardNodes({DECK_ZONE_TOKENS});
if (!tokenCardNodes.isEmpty()) { if (!tokenCardNodes.isEmpty()) {
setEnabled(true); setEnabled(true);

View file

@ -32,7 +32,7 @@
Player::Player(const ServerInfo_User &info, int _id, bool _local, bool _judge, AbstractGame *_parent) Player::Player(const ServerInfo_User &info, int _id, bool _local, bool _judge, AbstractGame *_parent)
: QObject(_parent), game(_parent), playerInfo(new PlayerInfo(info, _id, _local, _judge)), : QObject(_parent), game(_parent), playerInfo(new PlayerInfo(info, _id, _local, _judge)),
playerEventHandler(new PlayerEventHandler(this)), playerActions(new PlayerActions(this)), active(false), playerEventHandler(new PlayerEventHandler(this)), playerActions(new PlayerActions(this)), active(false),
conceded(false), deck(nullptr), zoneId(0), dialogSemaphore(false) conceded(false), zoneId(0), dialogSemaphore(false)
{ {
initializeZones(); initializeZones();
@ -263,10 +263,9 @@ void Player::deleteCard(CardItem *card)
} }
} }
//! \todo Does a player need a DeckLoader? void Player::setDeck(const DeckList &_deck)
void Player::setDeck(DeckLoader &_deck)
{ {
deck = new DeckLoader(this, _deck.getDeckList()); deck = _deck;
emit deckChanged(); emit deckChanged();
} }

View file

@ -9,6 +9,7 @@
#include "../../game_graphics/board/abstract_graphics_item.h" #include "../../game_graphics/board/abstract_graphics_item.h"
#include "../../interface/widgets/menus/tearoff_menu.h" #include "../../interface/widgets/menus/tearoff_menu.h"
#include "../interface/deck_loader/loaded_deck.h"
#include "../zones/logic/hand_zone_logic.h" #include "../zones/logic/hand_zone_logic.h"
#include "../zones/logic/pile_zone_logic.h" #include "../zones/logic/pile_zone_logic.h"
#include "../zones/logic/stack_zone_logic.h" #include "../zones/logic/stack_zone_logic.h"
@ -44,7 +45,6 @@ class ArrowTarget;
class CardDatabase; class CardDatabase;
class CardZone; class CardZone;
class CommandContainer; class CommandContainer;
class DeckLoader;
class GameCommand; class GameCommand;
class GameEvent; class GameEvent;
class PlayerInfo; class PlayerInfo;
@ -66,7 +66,7 @@ class Player : public QObject
Q_OBJECT Q_OBJECT
signals: signals:
void openDeckEditor(DeckLoader *deck); void openDeckEditor(const LoadedDeck &deck);
void deckChanged(); void deckChanged();
void newCardAdded(AbstractCardItem *card); void newCardAdded(AbstractCardItem *card);
void rearrangeCounters(); void rearrangeCounters();
@ -130,9 +130,9 @@ public:
return playerMenu; return playerMenu;
} }
void setDeck(DeckLoader &_deck); void setDeck(const DeckList &_deck);
[[nodiscard]] DeckLoader *getDeck() const [[nodiscard]] const DeckList &getDeck() const
{ {
return deck; return deck;
} }
@ -241,7 +241,7 @@ private:
bool active; bool active;
bool conceded; bool conceded;
DeckLoader *deck; DeckList deck;
int zoneId; int zoneId;
QMap<QString, CardZoneLogic *> zones; QMap<QString, CardZoneLogic *> zones;

View file

@ -218,7 +218,7 @@ void PlayerActions::actAlwaysLookAtTopCard()
void PlayerActions::actOpenDeckInDeckEditor() void PlayerActions::actOpenDeckInDeckEditor()
{ {
emit player->openDeckEditor(player->getDeck()); emit player->openDeckEditor({.deckList = player->getDeck()});
} }
void PlayerActions::actViewGraveyard() void PlayerActions::actViewGraveyard()

View file

@ -25,11 +25,7 @@ const QStringList DeckLoader::ACCEPTED_FILE_EXTENSIONS = {"*.cod", "*.dec", "*.d
const QStringList DeckLoader::FILE_NAME_FILTERS = { const QStringList DeckLoader::FILE_NAME_FILTERS = {
tr("Common deck formats (%1)").arg(ACCEPTED_FILE_EXTENSIONS.join(" ")), tr("All files (*.*)")}; tr("Common deck formats (%1)").arg(ACCEPTED_FILE_EXTENSIONS.join(" ")), tr("All files (*.*)")};
DeckLoader::DeckLoader(QObject *parent) : QObject(parent), deckList(new DeckList()) DeckLoader::DeckLoader(QObject *parent) : QObject(parent)
{
}
DeckLoader::DeckLoader(QObject *parent, DeckList *_deckList) : QObject(parent), deckList(_deckList)
{ {
} }
@ -41,17 +37,18 @@ bool DeckLoader::loadFromFile(const QString &fileName, DeckFileFormat::Format fm
} }
bool result = false; bool result = false;
DeckList deckList = DeckList();
switch (fmt) { switch (fmt) {
case DeckFileFormat::PlainText: case DeckFileFormat::PlainText:
result = deckList->loadFromFile_Plain(&file); result = deckList.loadFromFile_Plain(&file);
break; break;
case DeckFileFormat::Cockatrice: { case DeckFileFormat::Cockatrice: {
result = deckList->loadFromFile_Native(&file); result = deckList.loadFromFile_Native(&file);
qCInfo(DeckLoaderLog) << "Loaded from" << fileName << "-" << result; qCInfo(DeckLoaderLog) << "Loaded from" << fileName << "-" << result;
if (!result) { if (!result) {
qCInfo(DeckLoaderLog) << "Retrying as plain format"; qCInfo(DeckLoaderLog) << "Retrying as plain format";
file.seek(0); file.seek(0);
result = deckList->loadFromFile_Plain(&file); result = deckList.loadFromFile_Plain(&file);
fmt = DeckFileFormat::PlainText; fmt = DeckFileFormat::PlainText;
} }
break; break;
@ -62,7 +59,8 @@ bool DeckLoader::loadFromFile(const QString &fileName, DeckFileFormat::Format fm
} }
if (result) { if (result) {
lastLoadInfo = { loadedDeck.deckList = deckList;
loadedDeck.lastLoadInfo = {
.fileName = fileName, .fileName = fileName,
.fileFormat = fmt, .fileFormat = fmt,
}; };
@ -86,7 +84,7 @@ bool DeckLoader::loadFromFileAsync(const QString &fileName, DeckFileFormat::Form
watcher->deleteLater(); watcher->deleteLater();
if (result) { if (result) {
lastLoadInfo = { loadedDeck.lastLoadInfo = {
.fileName = fileName, .fileName = fileName,
.fileFormat = fmt, .fileFormat = fmt,
}; };
@ -107,13 +105,13 @@ bool DeckLoader::loadFromFileAsync(const QString &fileName, DeckFileFormat::Form
switch (fmt) { switch (fmt) {
case DeckFileFormat::PlainText: case DeckFileFormat::PlainText:
return deckList->loadFromFile_Plain(&file); return loadedDeck.deckList.loadFromFile_Plain(&file);
case DeckFileFormat::Cockatrice: { case DeckFileFormat::Cockatrice: {
bool result = false; bool result = false;
result = deckList->loadFromFile_Native(&file); result = loadedDeck.deckList.loadFromFile_Native(&file);
if (!result) { if (!result) {
file.seek(0); file.seek(0);
return deckList->loadFromFile_Plain(&file); return loadedDeck.deckList.loadFromFile_Plain(&file);
} }
return result; return result;
} }
@ -129,9 +127,9 @@ bool DeckLoader::loadFromFileAsync(const QString &fileName, DeckFileFormat::Form
bool DeckLoader::loadFromRemote(const QString &nativeString, int remoteDeckId) bool DeckLoader::loadFromRemote(const QString &nativeString, int remoteDeckId)
{ {
bool result = deckList->loadFromString_Native(nativeString); bool result = loadedDeck.deckList.loadFromString_Native(nativeString);
if (result) { if (result) {
lastLoadInfo = { loadedDeck.lastLoadInfo = {
.remoteDeckId = remoteDeckId, .remoteDeckId = remoteDeckId,
}; };
@ -150,16 +148,16 @@ bool DeckLoader::saveToFile(const QString &fileName, DeckFileFormat::Format fmt)
bool result = false; bool result = false;
switch (fmt) { switch (fmt) {
case DeckFileFormat::PlainText: case DeckFileFormat::PlainText:
result = deckList->saveToFile_Plain(&file); result = loadedDeck.deckList.saveToFile_Plain(&file);
break; break;
case DeckFileFormat::Cockatrice: case DeckFileFormat::Cockatrice:
result = deckList->saveToFile_Native(&file); result = loadedDeck.deckList.saveToFile_Native(&file);
qCInfo(DeckLoaderLog) << "Saving to " << fileName << "-" << result; qCInfo(DeckLoaderLog) << "Saving to " << fileName << "-" << result;
break; break;
} }
if (result) { if (result) {
lastLoadInfo = { loadedDeck.lastLoadInfo = {
.fileName = fileName, .fileName = fileName,
.fileFormat = fmt, .fileFormat = fmt,
}; };
@ -194,18 +192,18 @@ bool DeckLoader::updateLastLoadedTimestamp(const QString &fileName, DeckFileForm
// Perform file modifications // Perform file modifications
switch (fmt) { switch (fmt) {
case DeckFileFormat::PlainText: case DeckFileFormat::PlainText:
result = deckList->saveToFile_Plain(&file); result = loadedDeck.deckList.saveToFile_Plain(&file);
break; break;
case DeckFileFormat::Cockatrice: case DeckFileFormat::Cockatrice:
deckList->setLastLoadedTimestamp(QDateTime::currentDateTime().toString()); loadedDeck.deckList.setLastLoadedTimestamp(QDateTime::currentDateTime().toString());
result = deckList->saveToFile_Native(&file); result = loadedDeck.deckList.saveToFile_Native(&file);
break; break;
} }
file.close(); // Close the file to ensure changes are flushed file.close(); // Close the file to ensure changes are flushed
if (result) { if (result) {
lastLoadInfo = { loadedDeck.lastLoadInfo = {
.fileName = fileName, .fileName = fileName,
.fileFormat = fmt, .fileFormat = fmt,
}; };
@ -455,7 +453,7 @@ bool DeckLoader::convertToCockatriceFormat(QString fileName)
switch (DeckFileFormat::getFormatFromName(fileName)) { switch (DeckFileFormat::getFormatFromName(fileName)) {
case DeckFileFormat::PlainText: case DeckFileFormat::PlainText:
// Save in Cockatrice's native format // Save in Cockatrice's native format
result = deckList->saveToFile_Native(&file); result = loadedDeck.deckList.saveToFile_Native(&file);
break; break;
case DeckFileFormat::Cockatrice: case DeckFileFormat::Cockatrice:
qCInfo(DeckLoaderLog) << "File is already in Cockatrice format. No conversion needed."; qCInfo(DeckLoaderLog) << "File is already in Cockatrice format. No conversion needed.";
@ -476,7 +474,7 @@ bool DeckLoader::convertToCockatriceFormat(QString fileName)
} else { } else {
qCInfo(DeckLoaderLog) << "Original file deleted successfully:" << fileName; qCInfo(DeckLoaderLog) << "Original file deleted successfully:" << fileName;
} }
lastLoadInfo = { loadedDeck.lastLoadInfo = {
.fileName = newFileName, .fileName = newFileName,
.fileFormat = DeckFileFormat::Cockatrice, .fileFormat = DeckFileFormat::Cockatrice,
}; };

View file

@ -41,28 +41,16 @@ public:
}; };
private: private:
DeckList *deckList; LoadedDeck loadedDeck;
LoadedDeck::LoadInfo lastLoadInfo;
public: public:
DeckLoader(QObject *parent); DeckLoader(QObject *parent);
DeckLoader(QObject *parent, DeckList *_deckList);
DeckLoader(const DeckLoader &) = delete; DeckLoader(const DeckLoader &) = delete;
DeckLoader &operator=(const DeckLoader &) = delete; DeckLoader &operator=(const DeckLoader &) = delete;
const LoadedDeck::LoadInfo &getLastLoadInfo() const
{
return lastLoadInfo;
}
void setLastLoadInfo(const LoadedDeck::LoadInfo &info)
{
lastLoadInfo = info;
}
[[nodiscard]] bool hasNotBeenLoaded() const [[nodiscard]] bool hasNotBeenLoaded() const
{ {
return lastLoadInfo.isEmpty(); return loadedDeck.lastLoadInfo.isEmpty();
} }
bool loadFromFile(const QString &fileName, DeckFileFormat::Format fmt, bool userRequest = false); bool loadFromFile(const QString &fileName, DeckFileFormat::Format fmt, bool userRequest = false);
@ -88,9 +76,17 @@ public:
bool convertToCockatriceFormat(QString fileName); bool convertToCockatriceFormat(QString fileName);
DeckList *getDeckList() LoadedDeck &getDeck()
{ {
return deckList; return loadedDeck;
}
const LoadedDeck &getDeck() const
{
return loadedDeck;
}
void setDeck(const LoadedDeck &deck)
{
loadedDeck = deck;
} }
private: private:

View file

@ -30,8 +30,8 @@ struct LoadedDeck
bool isEmpty() const; bool isEmpty() const;
}; };
DeckList deckList; ///< The decklist itself DeckList deckList; ///< The decklist itself
LoadInfo lastLoadInfo; ///< info about where the deck was loaded from LoadInfo lastLoadInfo = {}; ///< info about where the deck was loaded from
bool isEmpty() const; bool isEmpty() const;
}; };

View file

@ -17,7 +17,6 @@
* @param outlineColor The color of the outline around the text. * @param outlineColor The color of the outline around the text.
* @param fontSize The font size of the overlay text. * @param fontSize The font size of the overlay text.
* @param alignment The alignment of the text within the overlay. * @param alignment The alignment of the text within the overlay.
* @param _deckLoader The Deck Loader holding the Deck associated with this preview.
* *
* Sets the widget's size policy and default border style. * Sets the widget's size policy and default border style.
*/ */

View file

@ -56,7 +56,7 @@ void DeckEditorDeckDockWidget::createDeckDock()
deckModel->setObjectName("deckModel"); deckModel->setObjectName("deckModel");
connect(deckModel, &DeckListModel::deckHashChanged, this, &DeckEditorDeckDockWidget::updateHash); connect(deckModel, &DeckListModel::deckHashChanged, this, &DeckEditorDeckDockWidget::updateHash);
deckLoader = new DeckLoader(this, deckModel->getDeckList()); deckLoader = new DeckLoader(this);
proxy = new DeckListStyleProxy(this); proxy = new DeckListStyleProxy(this);
proxy->setSourceModel(deckModel); proxy->setSourceModel(deckModel);
@ -347,7 +347,7 @@ void DeckEditorDeckDockWidget::updateCard(const QModelIndex /*&current*/, const
void DeckEditorDeckDockWidget::updateName(const QString &name) void DeckEditorDeckDockWidget::updateName(const QString &name)
{ {
emit requestDeckHistorySave( emit requestDeckHistorySave(
QString(tr("Rename deck to \"%1\" from \"%2\"")).arg(name).arg(deckLoader->getDeckList()->getName())); QString(tr("Rename deck to \"%1\" from \"%2\"")).arg(name).arg(deckLoader->getDeck().deckList.getName()));
deckModel->getDeckList()->setName(name); deckModel->getDeckList()->setName(name);
deckEditor->setModified(name.isEmpty()); deckEditor->setModified(name.isEmpty());
emit nameChanged(); emit nameChanged();
@ -357,7 +357,7 @@ void DeckEditorDeckDockWidget::updateName(const QString &name)
void DeckEditorDeckDockWidget::updateComments() void DeckEditorDeckDockWidget::updateComments()
{ {
emit requestDeckHistorySave(tr("Updated comments (was %1 chars, now %2 chars)") emit requestDeckHistorySave(tr("Updated comments (was %1 chars, now %2 chars)")
.arg(deckLoader->getDeckList()->getComments().size()) .arg(deckLoader->getDeck().deckList.getComments().size())
.arg(commentsEdit->toPlainText().size())); .arg(commentsEdit->toPlainText().size()));
deckModel->getDeckList()->setComments(commentsEdit->toPlainText()); deckModel->getDeckList()->setComments(commentsEdit->toPlainText());
@ -474,13 +474,12 @@ void DeckEditorDeckDockWidget::syncBannerCardComboBoxSelectionWithDeck()
/** /**
* Sets the currently active deck for this tab * Sets the currently active deck for this tab
* @param _deck The deck. Takes ownership of the object * @param _deck The deck.
*/ */
void DeckEditorDeckDockWidget::setDeck(DeckLoader *_deck) void DeckEditorDeckDockWidget::setDeck(const LoadedDeck &_deck)
{ {
deckLoader = _deck; deckLoader->setDeck(_deck);
deckLoader->setParent(this); deckModel->setDeckList(&deckLoader->getDeck().deckList);
deckModel->setDeckList(deckLoader->getDeckList());
connect(deckLoader, &DeckLoader::deckLoaded, deckModel, &DeckListModel::rebuildTree); connect(deckLoader, &DeckLoader::deckLoaded, deckModel, &DeckListModel::rebuildTree);
emit requestDeckHistoryClear(); emit requestDeckHistoryClear();

View file

@ -57,7 +57,7 @@ public:
public slots: public slots:
void cleanDeck(); void cleanDeck();
void updateBannerCardComboBox(); void updateBannerCardComboBox();
void setDeck(DeckLoader *_deck); void setDeck(const LoadedDeck &_deck);
void syncDisplayWidgetsToModel(); void syncDisplayWidgetsToModel();
void sortDeckModelToDeckView(); void sortDeckModelToDeckView();
DeckLoader *getDeckLoader(); DeckLoader *getDeckLoader();

View file

@ -66,26 +66,26 @@ void AbstractDlgDeckTextEdit::setText(const QString &text)
} }
/** /**
* Tries to load the current contents of the contentsEdit into the DeckLoader * Tries to load the current contents of the contentsEdit into the deckList
* *
* @param deckLoader The DeckLoader to load the deck into * @param deckList The deckList to load the deck into
* @return Whether the loading was successful * @return Whether the loading was successful
*/ */
bool AbstractDlgDeckTextEdit::loadIntoDeck(DeckLoader *deckLoader) const bool AbstractDlgDeckTextEdit::loadIntoDeck(DeckList &deckList) const
{ {
QString buffer = contentsEdit->toPlainText(); QString buffer = contentsEdit->toPlainText();
if (buffer.contains("<cockatrice_deck version=\"1\">")) { if (buffer.contains("<cockatrice_deck version=\"1\">")) {
return deckLoader->getDeckList()->loadFromString_Native(buffer); return deckList.loadFromString_Native(buffer);
} }
QTextStream stream(&buffer); QTextStream stream(&buffer);
if (deckLoader->getDeckList()->loadFromStream_Plain(stream, true)) { if (deckList.loadFromStream_Plain(stream, true)) {
if (loadSetNameAndNumberCheckBox->isChecked()) { if (loadSetNameAndNumberCheckBox->isChecked()) {
deckLoader->getDeckList()->forEachCard(CardNodeFunction::ResolveProviderId()); deckList.forEachCard(CardNodeFunction::ResolveProviderId());
} else { } else {
deckLoader->getDeckList()->forEachCard(CardNodeFunction::ClearPrintingData()); deckList.forEachCard(CardNodeFunction::ClearPrintingData());
} }
return true; return true;
} }
@ -108,7 +108,7 @@ void AbstractDlgDeckTextEdit::keyPressEvent(QKeyEvent *event)
* *
* @param parent The parent widget * @param parent The parent widget
*/ */
DlgLoadDeckFromClipboard::DlgLoadDeckFromClipboard(QWidget *parent) : AbstractDlgDeckTextEdit(parent), deckList(nullptr) DlgLoadDeckFromClipboard::DlgLoadDeckFromClipboard(QWidget *parent) : AbstractDlgDeckTextEdit(parent)
{ {
setWindowTitle(tr("Load deck from clipboard")); setWindowTitle(tr("Load deck from clipboard"));
@ -122,8 +122,6 @@ void DlgLoadDeckFromClipboard::actRefresh()
void DlgLoadDeckFromClipboard::actOK() void DlgLoadDeckFromClipboard::actOK()
{ {
deckList = new DeckLoader(this);
if (loadIntoDeck(deckList)) { if (loadIntoDeck(deckList)) {
accept(); accept();
} else { } else {
@ -134,18 +132,15 @@ void DlgLoadDeckFromClipboard::actOK()
/** /**
* Creates the dialog window for the "Edit deck in clipboard" action * Creates the dialog window for the "Edit deck in clipboard" action
* *
* @param _deckLoader The existing deck in the deck editor. Copies the instance * @param _deckList The existing deck in the deck editor.
* @param _annotated Whether to add annotations to the text that is loaded from the deck * @param _annotated Whether to add annotations to the text that is loaded from the deck
* @param parent The parent widget * @param parent The parent widget
*/ */
DlgEditDeckInClipboard::DlgEditDeckInClipboard(DeckLoader *_deckLoader, bool _annotated, QWidget *parent) DlgEditDeckInClipboard::DlgEditDeckInClipboard(const DeckList &_deckList, bool _annotated, QWidget *parent)
: AbstractDlgDeckTextEdit(parent), annotated(_annotated) : AbstractDlgDeckTextEdit(parent), deckList(_deckList), annotated(_annotated)
{ {
setWindowTitle(tr("Edit deck in clipboard")); setWindowTitle(tr("Edit deck in clipboard"));
deckLoader = new DeckLoader(this, _deckLoader->getDeckList());
deckLoader->setParent(this);
DlgEditDeckInClipboard::actRefresh(); DlgEditDeckInClipboard::actRefresh();
} }
@ -165,12 +160,12 @@ static QString deckListToString(const DeckList *deckList, bool addComments)
void DlgEditDeckInClipboard::actRefresh() void DlgEditDeckInClipboard::actRefresh()
{ {
setText(deckListToString(deckLoader->getDeckList(), annotated)); setText(deckListToString(&deckList, annotated));
} }
void DlgEditDeckInClipboard::actOK() void DlgEditDeckInClipboard::actOK()
{ {
if (loadIntoDeck(deckLoader)) { if (loadIntoDeck(deckList)) {
accept(); accept();
} else { } else {
QMessageBox::critical(this, tr("Error"), tr("Invalid deck list.")); QMessageBox::critical(this, tr("Error"), tr("Invalid deck list."));

View file

@ -8,10 +8,11 @@
#ifndef DLG_LOAD_DECK_FROM_CLIPBOARD_H #ifndef DLG_LOAD_DECK_FROM_CLIPBOARD_H
#define DLG_LOAD_DECK_FROM_CLIPBOARD_H #define DLG_LOAD_DECK_FROM_CLIPBOARD_H
#include "../../deck_loader/loaded_deck.h"
#include <QCheckBox> #include <QCheckBox>
#include <QDialog> #include <QDialog>
class DeckLoader;
class QPlainTextEdit; class QPlainTextEdit;
class QPushButton; class QPushButton;
@ -35,15 +36,13 @@ public:
/** /**
* Gets the loaded deck. Only call this method after this dialog window has been successfully exec'd. * Gets the loaded deck. Only call this method after this dialog window has been successfully exec'd.
* *
* The returned DeckLoader is parented to this object; make sure to take ownership of the DeckLoader if you intend * @return The loaded decklist
* to use it, since otherwise it will get destroyed once this dlg is destroyed
* @return The DeckLoader
*/ */
[[nodiscard]] virtual DeckLoader *getDeckList() const = 0; [[nodiscard]] virtual const DeckList &getDeckList() = 0;
protected: protected:
void setText(const QString &text); void setText(const QString &text);
bool loadIntoDeck(DeckLoader *deckLoader) const; bool loadIntoDeck(DeckList &deckList) const;
void keyPressEvent(QKeyEvent *event) override; void keyPressEvent(QKeyEvent *event) override;
protected slots: protected slots:
@ -62,12 +61,12 @@ protected slots:
void actRefresh() override; void actRefresh() override;
private: private:
DeckLoader *deckList; DeckList deckList;
public: public:
explicit DlgLoadDeckFromClipboard(QWidget *parent = nullptr); explicit DlgLoadDeckFromClipboard(QWidget *parent = nullptr);
[[nodiscard]] DeckLoader *getDeckList() const override [[nodiscard]] const DeckList &getDeckList() override
{ {
return deckList; return deckList;
} }
@ -84,15 +83,15 @@ protected slots:
void actRefresh() override; void actRefresh() override;
private: private:
DeckLoader *deckLoader; DeckList deckList;
bool annotated; bool annotated;
public: public:
explicit DlgEditDeckInClipboard(DeckLoader *_deckLoader, bool _annotated, QWidget *parent = nullptr); explicit DlgEditDeckInClipboard(const DeckList &_deckList, bool _annotated, QWidget *parent = nullptr);
[[nodiscard]] DeckLoader *getDeckList() const override [[nodiscard]] const DeckList &getDeckList() override
{ {
return deckLoader; return deckList;
} }
}; };

View file

@ -97,11 +97,11 @@ void DlgLoadDeckFromWebsite::accept()
} }
// Parse the plain text deck here // Parse the plain text deck here
DeckLoader *loader = new DeckLoader(this); DeckList deckList;
QTextStream stream(&deckText); QTextStream stream(&deckText);
loader->getDeckList()->loadFromStream_Plain(stream, false); deckList.loadFromStream_Plain(stream, false);
loader->getDeckList()->forEachCard(CardNodeFunction::ResolveProviderId()); deckList.forEachCard(CardNodeFunction::ResolveProviderId());
deck = loader; deck = deckList;
QDialog::accept(); QDialog::accept();
return; return;

View file

@ -26,9 +26,9 @@ public:
explicit DlgLoadDeckFromWebsite(QWidget *parent); explicit DlgLoadDeckFromWebsite(QWidget *parent);
void retranslateUi(); void retranslateUi();
bool testValidUrl(); bool testValidUrl();
DeckLoader *deck; DeckList deck;
DeckLoader *getDeck() const DeckList &getDeck() const
{ {
return deck; return deck;
} }

View file

@ -20,10 +20,6 @@ HomeWidget::HomeWidget(QWidget *parent, TabSupervisor *_tabSupervisor)
layout = new QGridLayout(this); layout = new QGridLayout(this);
backgroundSourceCard = new CardInfoPictureArtCropWidget(this); backgroundSourceCard = new CardInfoPictureArtCropWidget(this);
backgroundSourceDeck = new DeckLoader(this);
backgroundSourceDeck->loadFromFile(SettingsCache::instance().getDeckPath() + "background.cod",
DeckFileFormat::Cockatrice, false);
gradientColors = extractDominantColors(background); gradientColors = extractDominantColors(background);
@ -72,13 +68,20 @@ void HomeWidget::initializeBackgroundFromSource()
cardChangeTimer->start(SettingsCache::instance().getHomeTabBackgroundShuffleFrequency() * 1000); cardChangeTimer->start(SettingsCache::instance().getHomeTabBackgroundShuffleFrequency() * 1000);
break; break;
case BackgroundSources::DeckFileArt: case BackgroundSources::DeckFileArt:
backgroundSourceDeck->loadFromFile(SettingsCache::instance().getDeckPath() + "background.cod", loadBackgroundSourceDeck();
DeckFileFormat::Cockatrice, false);
cardChangeTimer->start(SettingsCache::instance().getHomeTabBackgroundShuffleFrequency() * 1000); cardChangeTimer->start(SettingsCache::instance().getHomeTabBackgroundShuffleFrequency() * 1000);
break; break;
} }
} }
void HomeWidget::loadBackgroundSourceDeck()
{
DeckLoader deckLoader = DeckLoader(this);
deckLoader.loadFromFile(SettingsCache::instance().getDeckPath() + "background.cod", DeckFileFormat::Cockatrice,
false);
backgroundSourceDeck = deckLoader.getDeck().deckList;
}
void HomeWidget::updateRandomCard() void HomeWidget::updateRandomCard()
{ {
auto backgroundSourceType = BackgroundSources::fromId(SettingsCache::instance().getHomeTabBackgroundSource()); auto backgroundSourceType = BackgroundSources::fromId(SettingsCache::instance().getHomeTabBackgroundSource());
@ -95,7 +98,7 @@ void HomeWidget::updateRandomCard()
newCard.getCardPtr()->getProperty("layout") != "normal"); newCard.getCardPtr()->getProperty("layout") != "normal");
break; break;
case BackgroundSources::DeckFileArt: case BackgroundSources::DeckFileArt:
QList<CardRef> cardRefs = backgroundSourceDeck->getDeckList()->getCardRefList(); QList<CardRef> cardRefs = backgroundSourceDeck.getCardRefList();
ExactCard oldCard = backgroundSourceCard->getCard(); ExactCard oldCard = backgroundSourceCard->getCard();
if (!cardRefs.empty()) { if (!cardRefs.empty()) {
@ -183,7 +186,7 @@ QGroupBox *HomeWidget::createButtons()
auto visualDeckEditorButton = new HomeStyledButton(tr("Create New Deck"), gradientColors); auto visualDeckEditorButton = new HomeStyledButton(tr("Create New Deck"), gradientColors);
connect(visualDeckEditorButton, &QPushButton::clicked, tabSupervisor, connect(visualDeckEditorButton, &QPushButton::clicked, tabSupervisor,
[this] { tabSupervisor->openDeckInNewTab(nullptr); }); [this] { tabSupervisor->openDeckInNewTab(LoadedDeck()); });
boxLayout->addWidget(visualDeckEditorButton); boxLayout->addWidget(visualDeckEditorButton);
auto visualDeckStorageButton = new HomeStyledButton(tr("Browse Decks"), gradientColors); auto visualDeckStorageButton = new HomeStyledButton(tr("Browse Decks"), gradientColors);
connect(visualDeckStorageButton, &QPushButton::clicked, tabSupervisor, connect(visualDeckStorageButton, &QPushButton::clicked, tabSupervisor,

View file

@ -40,10 +40,12 @@ private:
TabSupervisor *tabSupervisor; TabSupervisor *tabSupervisor;
QPixmap background; QPixmap background;
CardInfoPictureArtCropWidget *backgroundSourceCard = nullptr; CardInfoPictureArtCropWidget *backgroundSourceCard = nullptr;
DeckLoader *backgroundSourceDeck; DeckList backgroundSourceDeck;
QPixmap overlay; QPixmap overlay;
QPair<QColor, QColor> gradientColors; QPair<QColor, QColor> gradientColors;
HomeStyledButton *connectButton; HomeStyledButton *connectButton;
void loadBackgroundSourceDeck();
}; };
#endif // HOME_WIDGET_H #endif // HOME_WIDGET_H

View file

@ -213,22 +213,22 @@ void AbstractTabDeckEditor::actSwapCard(const ExactCard &card, const QString &zo
/** /**
* @brief Opens a deck in this tab. * @brief Opens a deck in this tab.
* @param deck DeckLoader object (takes ownership). * @param deck The deck
*/ */
void AbstractTabDeckEditor::openDeck(DeckLoader *deck) void AbstractTabDeckEditor::openDeck(const LoadedDeck &deck)
{ {
setDeck(deck); setDeck(deck);
if (!deck->getLastLoadInfo().fileName.isEmpty()) { if (!deck.lastLoadInfo.fileName.isEmpty()) {
SettingsCache::instance().recents().updateRecentlyOpenedDeckPaths(deck->getLastLoadInfo().fileName); SettingsCache::instance().recents().updateRecentlyOpenedDeckPaths(deck.lastLoadInfo.fileName);
} }
} }
/** /**
* @brief Sets the currently active deck. * @brief Sets the currently active deck.
* @param _deck DeckLoader object. * @param _deck The deck
*/ */
void AbstractTabDeckEditor::setDeck(DeckLoader *_deck) void AbstractTabDeckEditor::setDeck(const LoadedDeck &_deck)
{ {
deckDockWidget->setDeck(_deck); deckDockWidget->setDeck(_deck);
CardPictureLoader::cacheCardPixmaps(CardDatabaseManager::query()->getCards(getDeckList()->getCardRefList())); CardPictureLoader::cacheCardPixmaps(CardDatabaseManager::query()->getCards(getDeckList()->getCardRefList()));
@ -265,8 +265,8 @@ void AbstractTabDeckEditor::setModified(bool _modified)
*/ */
bool AbstractTabDeckEditor::isBlankNewDeck() const bool AbstractTabDeckEditor::isBlankNewDeck() const
{ {
DeckLoader *deck = deckDockWidget->getDeckLoader(); const LoadedDeck &loadedDeck = deckDockWidget->getDeckLoader()->getDeck();
return !modified && deck->getDeckList()->isBlankDeck() && deck->hasNotBeenLoaded(); return !modified && loadedDeck.isEmpty();
} }
/** @brief Creates a new deck. Handles opening in new tab if needed. */ /** @brief Creates a new deck. Handles opening in new tab if needed. */
@ -277,7 +277,7 @@ void AbstractTabDeckEditor::actNewDeck()
return; return;
if (deckOpenLocation == NEW_TAB) { if (deckOpenLocation == NEW_TAB) {
emit openDeckEditor(nullptr); emit openDeckEditor(LoadedDeck());
return; return;
} }
@ -382,17 +382,15 @@ void AbstractTabDeckEditor::openDeckFromFile(const QString &fileName, DeckOpenLo
{ {
DeckFileFormat::Format fmt = DeckFileFormat::getFormatFromName(fileName); DeckFileFormat::Format fmt = DeckFileFormat::getFormatFromName(fileName);
auto *l = new DeckLoader(this); auto l = DeckLoader(this);
if (l->loadFromFile(fileName, fmt, true)) { if (l.loadFromFile(fileName, fmt, true)) {
if (deckOpenLocation == NEW_TAB) { if (deckOpenLocation == NEW_TAB) {
emit openDeckEditor(l); emit openDeckEditor(l.getDeck());
l->deleteLater();
} else { } else {
deckMenu->setSaveStatus(false); deckMenu->setSaveStatus(false);
openDeck(l); openDeck(l.getDeck());
} }
} else { } else {
l->deleteLater();
QMessageBox::critical(this, tr("Error"), tr("Could not open deck at %1").arg(fileName)); QMessageBox::critical(this, tr("Error"), tr("Could not open deck at %1").arg(fileName));
} }
deckMenu->setSaveStatus(true); deckMenu->setSaveStatus(true);
@ -405,16 +403,16 @@ void AbstractTabDeckEditor::openDeckFromFile(const QString &fileName, DeckOpenLo
*/ */
bool AbstractTabDeckEditor::actSaveDeck() bool AbstractTabDeckEditor::actSaveDeck()
{ {
DeckLoader *const deck = getDeckLoader(); const LoadedDeck &loadedDeck = getDeckLoader()->getDeck();
if (deck->getLastLoadInfo().remoteDeckId != LoadedDeck::LoadInfo::NON_REMOTE_ID) { if (loadedDeck.lastLoadInfo.remoteDeckId != LoadedDeck::LoadInfo::NON_REMOTE_ID) {
QString deckString = deck->getDeckList()->writeToString_Native(); QString deckString = loadedDeck.deckList.writeToString_Native();
if (deckString.length() > MAX_FILE_LENGTH) { if (deckString.length() > MAX_FILE_LENGTH) {
QMessageBox::critical(this, tr("Error"), tr("Could not save remote deck")); QMessageBox::critical(this, tr("Error"), tr("Could not save remote deck"));
return false; return false;
} }
Command_DeckUpload cmd; Command_DeckUpload cmd;
cmd.set_deck_id(static_cast<google::protobuf::uint32>(deck->getLastLoadInfo().remoteDeckId)); cmd.set_deck_id(static_cast<google::protobuf::uint32>(loadedDeck.lastLoadInfo.remoteDeckId));
cmd.set_deck_list(deckString.toStdString()); cmd.set_deck_list(deckString.toStdString());
PendingCommand *pend = AbstractClient::prepareSessionCommand(cmd); PendingCommand *pend = AbstractClient::prepareSessionCommand(cmd);
@ -422,9 +420,11 @@ bool AbstractTabDeckEditor::actSaveDeck()
tabSupervisor->getClient()->sendCommand(pend); tabSupervisor->getClient()->sendCommand(pend);
return true; return true;
} else if (deck->getLastLoadInfo().fileName.isEmpty()) }
if (loadedDeck.lastLoadInfo.fileName.isEmpty())
return actSaveDeckAs(); return actSaveDeckAs();
else if (deck->saveToFile(deck->getLastLoadInfo().fileName, deck->getLastLoadInfo().fileFormat)) {
if (getDeckLoader()->saveToFile(loadedDeck.lastLoadInfo.fileName, loadedDeck.lastLoadInfo.fileFormat)) {
setModified(false); setModified(false);
return true; return true;
} }
@ -493,9 +493,9 @@ void AbstractTabDeckEditor::actLoadDeckFromClipboard()
return; return;
if (deckOpenLocation == NEW_TAB) { if (deckOpenLocation == NEW_TAB) {
emit openDeckEditor(dlg.getDeckList()); emit openDeckEditor({.deckList = dlg.getDeckList()});
} else { } else {
setDeck(dlg.getDeckList()); setDeck({.deckList = dlg.getDeckList()});
setModified(true); setModified(true);
} }
@ -508,11 +508,11 @@ void AbstractTabDeckEditor::actLoadDeckFromClipboard()
*/ */
void AbstractTabDeckEditor::editDeckInClipboard(bool annotated) void AbstractTabDeckEditor::editDeckInClipboard(bool annotated)
{ {
DlgEditDeckInClipboard dlg(getDeckLoader(), annotated, this); DlgEditDeckInClipboard dlg(getDeckLoader()->getDeck().deckList, annotated, this);
if (!dlg.exec()) if (!dlg.exec())
return; return;
setDeck(dlg.getDeckList()); setDeck({dlg.getDeckList(), getDeckLoader()->getDeck().lastLoadInfo});
setModified(true); setModified(true);
deckMenu->setSaveStatus(true); deckMenu->setSaveStatus(true);
} }
@ -576,9 +576,9 @@ void AbstractTabDeckEditor::actLoadDeckFromWebsite()
return; return;
if (deckOpenLocation == NEW_TAB) { if (deckOpenLocation == NEW_TAB) {
emit openDeckEditor(dlg.getDeck()); emit openDeckEditor({.deckList = dlg.getDeck()});
} else { } else {
setDeck(dlg.getDeck()); setDeck({.deckList = dlg.getDeck()});
setModified(true); setModified(true);
} }
@ -591,8 +591,8 @@ void AbstractTabDeckEditor::actLoadDeckFromWebsite()
*/ */
void AbstractTabDeckEditor::exportToDecklistWebsite(DeckLoader::DecklistWebsite website) void AbstractTabDeckEditor::exportToDecklistWebsite(DeckLoader::DecklistWebsite website)
{ {
if (DeckLoader *const deck = getDeckLoader()) { if (DeckList *deckList = getDeckList()) {
QString decklistUrlString = deck->exportDeckToDecklist(getDeckList(), website); QString decklistUrlString = DeckLoader::exportDeckToDecklist(deckList, website);
// Check to make sure the string isn't empty. // Check to make sure the string isn't empty.
if (decklistUrlString.isEmpty()) { if (decklistUrlString.isEmpty()) {
// Show an error if the deck is empty, and return. // Show an error if the deck is empty, and return.

View file

@ -114,9 +114,9 @@ public:
virtual void retranslateUi() override = 0; virtual void retranslateUi() override = 0;
/** @brief Opens a deck in this tab. /** @brief Opens a deck in this tab.
* @param deck Pointer to a DeckLoader object. * @param deck The deck to open
*/ */
void openDeck(DeckLoader *deck); void openDeck(const LoadedDeck &deck);
/** @brief Returns the currently active deck loader. */ /** @brief Returns the currently active deck loader. */
DeckLoader *getDeckLoader() const; DeckLoader *getDeckLoader() const;
@ -198,7 +198,7 @@ public slots:
signals: signals:
/** @brief Emitted when a deck should be opened in a new editor tab. */ /** @brief Emitted when a deck should be opened in a new editor tab. */
void openDeckEditor(DeckLoader *deckLoader); void openDeckEditor(const LoadedDeck &deck);
/** @brief Emitted before the tab is closed. */ /** @brief Emitted before the tab is closed. */
void deckEditorClosing(AbstractTabDeckEditor *tab); void deckEditorClosing(AbstractTabDeckEditor *tab);
@ -286,7 +286,7 @@ private:
/** @brief Sets the deck for this tab. /** @brief Sets the deck for this tab.
* @param _deck The deck object. * @param _deck The deck object.
*/ */
virtual void setDeck(DeckLoader *_deck); virtual void setDeck(const LoadedDeck &_deck);
/** @brief Helper for editing decks from the clipboard. */ /** @brief Helper for editing decks from the clipboard. */
void editDeckInClipboard(bool annotated); void editDeckInClipboard(bool annotated);

View file

@ -90,14 +90,14 @@ void ArchidektApiResponseDeckDisplayWidget::onGroupCriteriaChange(const QString
void ArchidektApiResponseDeckDisplayWidget::actOpenInDeckEditor() void ArchidektApiResponseDeckDisplayWidget::actOpenInDeckEditor()
{ {
auto loader = new DeckLoader(this); DeckList deckList(*model->getDeckList());
loader->getDeckList()->loadFromString_Native(model->getDeckList()->writeToString_Native()); deckList.setName(response.getDeckName());
deckList.setGameFormat(
loader->getDeckList()->setName(response.getDeckName());
loader->getDeckList()->setGameFormat(
ArchidektFormats::formatToCockatriceName(ArchidektFormats::DeckFormat(response.getDeckFormat() - 1))); ArchidektFormats::formatToCockatriceName(ArchidektFormats::DeckFormat(response.getDeckFormat() - 1)));
emit openInDeckEditor(loader); LoadedDeck loadedDeck = {deckList, {}};
emit openInDeckEditor(loadedDeck);
} }
void ArchidektApiResponseDeckDisplayWidget::clearAllDisplayWidgets() void ArchidektApiResponseDeckDisplayWidget::clearAllDisplayWidgets()

View file

@ -31,7 +31,7 @@
* *
* ### Signals * ### Signals
* - `requestNavigation(QString url)` triggered when navigation to a deck URL is requested. * - `requestNavigation(QString url)` triggered when navigation to a deck URL is requested.
* - `openInDeckEditor(DeckLoader *loader)` emitted when the user chooses to open the deck * - `openInDeckEditor(const LoadedDeck &deck)` emitted when the user chooses to open the deck
* in the deck editor. * in the deck editor.
* *
* ### Features * ### Features
@ -52,9 +52,9 @@ signals:
/** /**
* @brief Emitted when the deck should be opened in the deck editor. * @brief Emitted when the deck should be opened in the deck editor.
* @param loader Initialized DeckLoader containing the deck data. * @param deck LoadedDeck containing the deck data.
*/ */
void openInDeckEditor(DeckLoader *loader); void openInDeckEditor(const LoadedDeck &deck);
public: public:
/** /**
@ -75,7 +75,7 @@ public:
void retranslateUi(); void retranslateUi();
/** /**
* @brief Opens the deck in the deck editor via DeckLoader. * @brief Opens the deck in the deck editor.
*/ */
void actOpenInDeckEditor(); void actOpenInDeckEditor();

View file

@ -14,10 +14,8 @@ void EdhrecDeckApiResponse::fromJson(const QJsonArray &json)
deckList += cardlistValue.toString() + "\n"; deckList += cardlistValue.toString() + "\n";
} }
deckLoader = new DeckLoader(nullptr);
QTextStream stream(&deckList); QTextStream stream(&deckList);
deckLoader->getDeckList()->loadFromStream_Plain(stream, true); deck.loadFromStream_Plain(stream, true);
} }
void EdhrecDeckApiResponse::debugPrint() const void EdhrecDeckApiResponse::debugPrint() const

View file

@ -21,7 +21,7 @@ public:
// Debug method for logging // Debug method for logging
void debugPrint() const; void debugPrint() const;
DeckLoader *deckLoader; DeckList deck;
}; };
#endif // EDHREC_DECK_API_RESPONSE_H #endif // EDHREC_DECK_API_RESPONSE_H

View file

@ -363,7 +363,7 @@ void TabEdhRecMain::processAverageDeckResponse(QJsonObject reply)
{ {
EdhrecAverageDeckApiResponse deckData; EdhrecAverageDeckApiResponse deckData;
deckData.fromJson(reply); deckData.fromJson(reply);
tabSupervisor->openDeckInNewTab(deckData.deck.deckLoader); tabSupervisor->openDeckInNewTab({deckData.deck.deck, {}});
} }
void TabEdhRecMain::prettyPrintJson(const QJsonValue &value, int indentLevel) void TabEdhRecMain::prettyPrintJson(const QJsonValue &value, int indentLevel)

View file

@ -12,7 +12,6 @@ class CardDatabaseDisplayModel;
class DeckListModel; class DeckListModel;
class QLabel; class QLabel;
class DeckLoader;
/** /**
* @class TabDeckEditor * @class TabDeckEditor

View file

@ -245,7 +245,7 @@ void TabDeckStorage::actOpenLocalDeck()
if (!deckLoader->loadFromFile(filePath, DeckFileFormat::Cockatrice, true)) if (!deckLoader->loadFromFile(filePath, DeckFileFormat::Cockatrice, true))
continue; continue;
emit openDeckEditor(deckLoader); emit openDeckEditor(deckLoader->getDeck());
} }
} }
@ -307,13 +307,15 @@ void TabDeckStorage::uploadDeck(const QString &filePath, const QString &targetPa
QFile deckFile(filePath); QFile deckFile(filePath);
QFileInfo deckFileInfo(deckFile); QFileInfo deckFileInfo(deckFile);
DeckLoader deck(this); DeckLoader deckLoader(this);
if (!deck.loadFromFile(filePath, DeckFileFormat::Cockatrice)) { if (!deckLoader.loadFromFile(filePath, DeckFileFormat::Cockatrice)) {
QMessageBox::critical(this, tr("Error"), tr("Invalid deck file")); QMessageBox::critical(this, tr("Error"), tr("Invalid deck file"));
return; return;
} }
if (deck.getDeckList()->getName().isEmpty()) { DeckList deck = deckLoader.getDeck().deckList;
if (deck.getName().isEmpty()) {
bool ok; bool ok;
QString deckName = QString deckName =
getTextWithMax(this, tr("Enter deck name"), tr("This decklist does not have a name.\nPlease enter a name:"), getTextWithMax(this, tr("Enter deck name"), tr("This decklist does not have a name.\nPlease enter a name:"),
@ -322,12 +324,12 @@ void TabDeckStorage::uploadDeck(const QString &filePath, const QString &targetPa
return; return;
if (deckName.isEmpty()) if (deckName.isEmpty())
deckName = tr("Unnamed deck"); deckName = tr("Unnamed deck");
deck.getDeckList()->setName(deckName); deck.setName(deckName);
} else { } else {
deck.getDeckList()->setName(deck.getDeckList()->getName().left(MAX_NAME_LENGTH)); deck.setName(deck.getName().left(MAX_NAME_LENGTH));
} }
QString deckString = deck.getDeckList()->writeToString_Native(); QString deckString = deck.writeToString_Native();
if (deckString.length() > MAX_FILE_LENGTH) { if (deckString.length() > MAX_FILE_LENGTH) {
QMessageBox::critical(this, tr("Error"), tr("Invalid deck file")); QMessageBox::critical(this, tr("Error"), tr("Invalid deck file"));
return; return;
@ -436,7 +438,7 @@ void TabDeckStorage::openRemoteDeckFinished(const Response &r, const CommandCont
if (!loader.loadFromRemote(QString::fromStdString(resp.deck()), cmd.deck_id())) if (!loader.loadFromRemote(QString::fromStdString(resp.deck()), cmd.deck_id()))
return; return;
emit openDeckEditor(&loader); emit openDeckEditor(loader.getDeck());
} }
void TabDeckStorage::actDownload() void TabDeckStorage::actDownload()
@ -492,8 +494,12 @@ void TabDeckStorage::downloadFinished(const Response &r,
const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext); const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext);
QString filePath = extraData.toString(); QString filePath = extraData.toString();
DeckLoader deck(this, new DeckList(QString::fromStdString(resp.deck()))); DeckList deckList = DeckList(QString::fromStdString(resp.deck()));
deck.saveToFile(filePath, DeckFileFormat::Cockatrice);
DeckLoader deckLoader(this);
deckLoader.setDeck({deckList, {}});
deckLoader.saveToFile(filePath, DeckFileFormat::Cockatrice);
} }
void TabDeckStorage::actNewFolder() void TabDeckStorage::actNewFolder()

View file

@ -13,6 +13,7 @@
#include <libcockatrice/network/client/abstract/abstract_client.h> #include <libcockatrice/network/client/abstract/abstract_client.h>
struct LoadedDeck;
class ServerInfo_User; class ServerInfo_User;
class AbstractClient; class AbstractClient;
class QTreeView; class QTreeView;
@ -23,7 +24,6 @@ class QTreeWidgetItem;
class QGroupBox; class QGroupBox;
class CommandContainer; class CommandContainer;
class Response; class Response;
class DeckLoader;
class TabDeckStorage : public Tab class TabDeckStorage : public Tab
{ {
@ -87,7 +87,7 @@ public:
return tr("Deck Storage"); return tr("Deck Storage");
} }
signals: signals:
void openDeckEditor(DeckLoader *deckLoader); void openDeckEditor(const LoadedDeck &deck);
}; };
#endif #endif

View file

@ -749,11 +749,10 @@ void TabGame::loadDeckForLocalPlayer(Player *localPlayer, int playerId, ServerIn
{ {
TabbedDeckViewContainer *deckViewContainer = deckViewContainers.value(playerId); TabbedDeckViewContainer *deckViewContainer = deckViewContainers.value(playerId);
if (playerInfo.has_deck_list()) { if (playerInfo.has_deck_list()) {
DeckLoader newDeck(this, new DeckList(QString::fromStdString(playerInfo.deck_list()))); DeckList deckList = DeckList(QString::fromStdString(playerInfo.deck_list()));
CardPictureLoader::cacheCardPixmaps( CardPictureLoader::cacheCardPixmaps(CardDatabaseManager::query()->getCards(deckList.getCardRefList()));
CardDatabaseManager::query()->getCards(newDeck.getDeckList()->getCardRefList())); deckViewContainer->playerDeckView->setDeck(deckList);
deckViewContainer->playerDeckView->setDeck(newDeck); localPlayer->setDeck(deckList);
localPlayer->setDeck(newDeck);
} }
} }

View file

@ -45,7 +45,6 @@ class ReplayTimelineWidget;
class CardZone; class CardZone;
class AbstractCardItem; class AbstractCardItem;
class CardItem; class CardItem;
class DeckLoader;
class QVBoxLayout; class QVBoxLayout;
class QHBoxLayout; class QHBoxLayout;
class GameReplay; class GameReplay;
@ -119,7 +118,7 @@ signals:
void containerProcessingStarted(const GameEventContext &context); void containerProcessingStarted(const GameEventContext &context);
void containerProcessingDone(); void containerProcessingDone();
void openMessageDialog(const QString &userName, bool focus); void openMessageDialog(const QString &userName, bool focus);
void openDeckEditor(DeckLoader *deck); void openDeckEditor(const LoadedDeck &deck);
void notIdle(); void notIdle();
void phaseChanged(int phase); void phaseChanged(int phase);

View file

@ -133,10 +133,10 @@ TabSupervisor::TabSupervisor(AbstractClient *_client, QMenu *tabsMenu, QWidget *
// create tabs menu actions // create tabs menu actions
aTabDeckEditor = new QAction(this); aTabDeckEditor = new QAction(this);
connect(aTabDeckEditor, &QAction::triggered, this, [this] { addDeckEditorTab(nullptr); }); connect(aTabDeckEditor, &QAction::triggered, this, [this] { addDeckEditorTab(LoadedDeck()); });
aTabVisualDeckEditor = new QAction(this); aTabVisualDeckEditor = new QAction(this);
connect(aTabVisualDeckEditor, &QAction::triggered, this, [this] { addVisualDeckEditorTab(nullptr); }); connect(aTabVisualDeckEditor, &QAction::triggered, this, [this] { addVisualDeckEditorTab(LoadedDeck()); });
aTabEdhRec = new QAction(this); aTabEdhRec = new QAction(this);
connect(aTabEdhRec, &QAction::triggered, this, [this] { addEdhrecMainTab(); }); connect(aTabEdhRec, &QAction::triggered, this, [this] { addEdhrecMainTab(); });
@ -846,9 +846,9 @@ void TabSupervisor::talkLeft(TabMessage *tab)
/** /**
* Creates a new deck editor tab and loads the deck into it. * Creates a new deck editor tab and loads the deck into it.
* Creates either a classic or visual deck editor tab depending on settings * Creates either a classic or visual deck editor tab depending on settings
* @param deckToOpen The deck to open in the tab. Creates a copy of the DeckLoader instance. * @param deckToOpen The deck to open in the tab.
*/ */
void TabSupervisor::openDeckInNewTab(DeckLoader *deckToOpen) void TabSupervisor::openDeckInNewTab(const LoadedDeck &deckToOpen)
{ {
int type = SettingsCache::instance().getDefaultDeckEditorType(); int type = SettingsCache::instance().getDefaultDeckEditorType();
switch (type) { switch (type) {
@ -868,13 +868,12 @@ void TabSupervisor::openDeckInNewTab(DeckLoader *deckToOpen)
/** /**
* Creates a new deck editor tab * Creates a new deck editor tab
* @param deckToOpen The deck to open in the tab. Creates a copy of the DeckLoader instance. * @param deckToOpen The deck to open in the tab.
*/ */
TabDeckEditor *TabSupervisor::addDeckEditorTab(DeckLoader *deckToOpen) TabDeckEditor *TabSupervisor::addDeckEditorTab(const LoadedDeck &deckToOpen)
{ {
auto *tab = new TabDeckEditor(this); auto *tab = new TabDeckEditor(this);
if (deckToOpen) tab->openDeck(deckToOpen);
tab->openDeck(deckToOpen);
connect(tab, &AbstractTabDeckEditor::deckEditorClosing, this, &TabSupervisor::deckEditorClosed); connect(tab, &AbstractTabDeckEditor::deckEditorClosing, this, &TabSupervisor::deckEditorClosed);
connect(tab, &AbstractTabDeckEditor::openDeckEditor, this, &TabSupervisor::addDeckEditorTab); connect(tab, &AbstractTabDeckEditor::openDeckEditor, this, &TabSupervisor::addDeckEditorTab);
myAddTab(tab); myAddTab(tab);
@ -883,11 +882,10 @@ TabDeckEditor *TabSupervisor::addDeckEditorTab(DeckLoader *deckToOpen)
return tab; return tab;
} }
TabDeckEditorVisual *TabSupervisor::addVisualDeckEditorTab(DeckLoader *deckToOpen) TabDeckEditorVisual *TabSupervisor::addVisualDeckEditorTab(const LoadedDeck &deckToOpen)
{ {
auto *tab = new TabDeckEditorVisual(this); auto *tab = new TabDeckEditorVisual(this);
if (deckToOpen) tab->openDeck(deckToOpen);
tab->openDeck(deckToOpen);
connect(tab, &AbstractTabDeckEditor::deckEditorClosing, this, &TabSupervisor::deckEditorClosed); connect(tab, &AbstractTabDeckEditor::deckEditorClosing, this, &TabSupervisor::deckEditorClosed);
connect(tab, &AbstractTabDeckEditor::openDeckEditor, this, &TabSupervisor::addVisualDeckEditorTab); connect(tab, &AbstractTabDeckEditor::openDeckEditor, this, &TabSupervisor::addVisualDeckEditorTab);
myAddTab(tab); myAddTab(tab);

View file

@ -168,9 +168,9 @@ signals:
void showWindowIfHidden(); void showWindowIfHidden();
public slots: public slots:
void openDeckInNewTab(DeckLoader *deckToOpen); void openDeckInNewTab(const LoadedDeck &deckToOpen);
TabDeckEditor *addDeckEditorTab(DeckLoader *deckToOpen); TabDeckEditor *addDeckEditorTab(const LoadedDeck &deckToOpen);
TabDeckEditorVisual *addVisualDeckEditorTab(DeckLoader *deckToOpen); TabDeckEditorVisual *addVisualDeckEditorTab(const LoadedDeck &deckToOpen);
TabVisualDatabaseDisplay *addVisualDatabaseDisplayTab(); TabVisualDatabaseDisplay *addVisualDatabaseDisplayTab();
TabEdhRecMain *addEdhrecMainTab(); TabEdhRecMain *addEdhrecMainTab();
TabArchidekt *addArchidektTab(); TabArchidekt *addArchidektTab();

View file

@ -24,11 +24,11 @@ TabDeckStorageVisual::TabDeckStorageVisual(TabSupervisor *_tabSupervisor)
void TabDeckStorageVisual::actOpenLocalDeck(const QString &filePath) void TabDeckStorageVisual::actOpenLocalDeck(const QString &filePath)
{ {
auto deckLoader = new DeckLoader(this); auto deckLoader = DeckLoader(this);
if (!deckLoader->loadFromFile(filePath, DeckFileFormat::getFormatFromName(filePath), true)) { if (!deckLoader.loadFromFile(filePath, DeckFileFormat::getFormatFromName(filePath), true)) {
QMessageBox::critical(this, tr("Error"), tr("Could not open deck at %1").arg(filePath)); QMessageBox::critical(this, tr("Error"), tr("Could not open deck at %1").arg(filePath));
return; return;
} }
emit openDeckEditor(deckLoader); emit openDeckEditor(deckLoader.getDeck());
} }

View file

@ -9,9 +9,9 @@
#include "../tab.h" #include "../tab.h"
struct LoadedDeck;
class AbstractClient; class AbstractClient;
class CommandContainer; class CommandContainer;
class DeckLoader;
class DeckPreviewWidget; class DeckPreviewWidget;
class QFileSystemModel; class QFileSystemModel;
class QGroupBox; class QGroupBox;
@ -39,7 +39,7 @@ public slots:
void actOpenLocalDeck(const QString &filePath); void actOpenLocalDeck(const QString &filePath);
signals: signals:
void openDeckEditor(DeckLoader *deckLoader); void openDeckEditor(const LoadedDeck &deck);
private: private:
VisualDeckStorageWidget *visualDeckStorageWidget; VisualDeckStorageWidget *visualDeckStorageWidget;

View file

@ -79,7 +79,7 @@ void VisualDatabaseDisplayNameFilterWidget::actLoadFromClipboard()
if (!dlg.exec()) if (!dlg.exec())
return; return;
QStringList cardsInClipboard = dlg.getDeckList()->getDeckList()->getCardList(); QStringList cardsInClipboard = dlg.getDeckList().getCardList();
for (QString cardName : cardsInClipboard) { for (QString cardName : cardsInClipboard) {
createNameFilter(cardName); createNameFilter(cardName);
} }

View file

@ -80,7 +80,7 @@ static QStringList findAllKnownTags()
auto loader = DeckLoader(nullptr); auto loader = DeckLoader(nullptr);
for (const QString &file : allFiles) { for (const QString &file : allFiles) {
loader.loadFromFile(file, DeckFileFormat::getFormatFromName(file), false); loader.loadFromFile(file, DeckFileFormat::getFormatFromName(file), false);
QStringList tags = loader.getDeckList()->getTags(); QStringList tags = loader.getDeck().deckList.getTags();
knownTags.append(tags); knownTags.append(tags);
knownTags.removeDuplicates(); knownTags.removeDuplicates();
} }
@ -125,7 +125,7 @@ static bool confirmOverwriteIfExists(QWidget *parent, const QString &filePath)
static void convertFileToCockatriceFormat(DeckPreviewWidget *deckPreviewWidget) static void convertFileToCockatriceFormat(DeckPreviewWidget *deckPreviewWidget)
{ {
deckPreviewWidget->deckLoader->convertToCockatriceFormat(deckPreviewWidget->filePath); deckPreviewWidget->deckLoader->convertToCockatriceFormat(deckPreviewWidget->filePath);
deckPreviewWidget->filePath = deckPreviewWidget->deckLoader->getLastLoadInfo().fileName; deckPreviewWidget->filePath = deckPreviewWidget->deckLoader->getDeck().lastLoadInfo.fileName;
deckPreviewWidget->refreshBannerCardText(); deckPreviewWidget->refreshBannerCardText();
} }

View file

@ -74,16 +74,16 @@ void DeckPreviewWidget::initializeUi(const bool deckLoadSuccess)
if (!deckLoadSuccess) { if (!deckLoadSuccess) {
return; return;
} }
auto bannerCard = deckLoader->getDeckList()->getBannerCard().name.isEmpty() auto bannerCard = deckLoader->getDeck().deckList.getBannerCard().name.isEmpty()
? ExactCard() ? ExactCard()
: CardDatabaseManager::query()->getCard(deckLoader->getDeckList()->getBannerCard()); : CardDatabaseManager::query()->getCard(deckLoader->getDeck().deckList.getBannerCard());
bannerCardDisplayWidget->setCard(bannerCard); bannerCardDisplayWidget->setCard(bannerCard);
bannerCardDisplayWidget->setFontSize(24); bannerCardDisplayWidget->setFontSize(24);
setFilePath(deckLoader->getLastLoadInfo().fileName); setFilePath(deckLoader->getDeck().lastLoadInfo.fileName);
colorIdentityWidget = new ColorIdentityWidget(this, getColorIdentity()); colorIdentityWidget = new ColorIdentityWidget(this, getColorIdentity());
deckTagsDisplayWidget = new DeckPreviewDeckTagsDisplayWidget(this, deckLoader->getDeckList()->getTags()); deckTagsDisplayWidget = new DeckPreviewDeckTagsDisplayWidget(this, deckLoader->getDeck().deckList.getTags());
connect(deckTagsDisplayWidget, &DeckPreviewDeckTagsDisplayWidget::tagsChanged, this, &DeckPreviewWidget::setTags); connect(deckTagsDisplayWidget, &DeckPreviewDeckTagsDisplayWidget::tagsChanged, this, &DeckPreviewWidget::setTags);
bannerCardLabel = new QLabel(this); bannerCardLabel = new QLabel(this);
@ -91,7 +91,7 @@ void DeckPreviewWidget::initializeUi(const bool deckLoadSuccess)
bannerCardComboBox = new QComboBox(this); bannerCardComboBox = new QComboBox(this);
bannerCardComboBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); bannerCardComboBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
bannerCardComboBox->setObjectName("bannerCardComboBox"); bannerCardComboBox->setObjectName("bannerCardComboBox");
bannerCardComboBox->setCurrentText(deckLoader->getDeckList()->getBannerCard().name); bannerCardComboBox->setCurrentText(deckLoader->getDeck().deckList.getBannerCard().name);
bannerCardComboBox->installEventFilter(new NoScrollFilter()); bannerCardComboBox->installEventFilter(new NoScrollFilter());
connect(bannerCardComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, connect(bannerCardComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&DeckPreviewWidget::setBannerCard); &DeckPreviewWidget::setBannerCard);
@ -153,7 +153,7 @@ void DeckPreviewWidget::updateTagsVisibility(bool visible)
QString DeckPreviewWidget::getColorIdentity() QString DeckPreviewWidget::getColorIdentity()
{ {
QStringList cardList = deckLoader->getDeckList()->getCardList(); QStringList cardList = deckLoader->getDeck().deckList.getCardList();
if (cardList.isEmpty()) { if (cardList.isEmpty()) {
return {}; return {};
} }
@ -187,8 +187,8 @@ QString DeckPreviewWidget::getColorIdentity()
*/ */
QString DeckPreviewWidget::getDisplayName() const QString DeckPreviewWidget::getDisplayName() const
{ {
return deckLoader->getDeckList()->getName().isEmpty() ? QFileInfo(deckLoader->getLastLoadInfo().fileName).fileName() QString deckName = deckLoader->getDeck().deckList.getName();
: deckLoader->getDeckList()->getName(); return !deckName.isEmpty() ? deckName : QFileInfo(deckLoader->getDeck().lastLoadInfo.fileName).fileName();
} }
void DeckPreviewWidget::setFilePath(const QString &_filePath) void DeckPreviewWidget::setFilePath(const QString &_filePath)
@ -235,7 +235,7 @@ void DeckPreviewWidget::updateBannerCardComboBox()
// Prepare the new items with deduplication // Prepare the new items with deduplication
QSet<QPair<QString, QString>> bannerCardSet; QSet<QPair<QString, QString>> bannerCardSet;
QList<const DecklistCardNode *> cardsInDeck = deckLoader->getDeckList()->getCardNodes(); QList<const DecklistCardNode *> cardsInDeck = deckLoader->getDeck().deckList.getCardNodes();
for (auto currentCard : cardsInDeck) { for (auto currentCard : cardsInDeck) {
for (int k = 0; k < currentCard->getNumber(); ++k) { for (int k = 0; k < currentCard->getNumber(); ++k) {
@ -269,7 +269,7 @@ void DeckPreviewWidget::updateBannerCardComboBox()
bannerCardComboBox->setCurrentIndex(restoredIndex); bannerCardComboBox->setCurrentIndex(restoredIndex);
} else { } else {
// Add a placeholder "-" and set it as the current selection // Add a placeholder "-" and set it as the current selection
int bannerIndex = bannerCardComboBox->findText(deckLoader->getDeckList()->getBannerCard().name); int bannerIndex = bannerCardComboBox->findText(deckLoader->getDeck().deckList.getBannerCard().name);
if (bannerIndex != -1) { if (bannerIndex != -1) {
bannerCardComboBox->setCurrentIndex(bannerIndex); bannerCardComboBox->setCurrentIndex(bannerIndex);
} else { } else {
@ -287,7 +287,7 @@ void DeckPreviewWidget::setBannerCard(int /* changedIndex */)
{ {
auto [name, id] = bannerCardComboBox->currentData().value<QPair<QString, QString>>(); auto [name, id] = bannerCardComboBox->currentData().value<QPair<QString, QString>>();
CardRef cardRef = {name, id}; CardRef cardRef = {name, id};
deckLoader->getDeckList()->setBannerCard(cardRef); deckLoader->getDeck().deckList.setBannerCard(cardRef);
deckLoader->saveToFile(filePath, DeckFileFormat::getFormatFromName(filePath)); deckLoader->saveToFile(filePath, DeckFileFormat::getFormatFromName(filePath));
bannerCardDisplayWidget->setCard(CardDatabaseManager::query()->getCard(cardRef)); bannerCardDisplayWidget->setCard(CardDatabaseManager::query()->getCard(cardRef));
} }
@ -310,7 +310,7 @@ void DeckPreviewWidget::imageDoubleClickedEvent(QMouseEvent *event, DeckPreviewC
void DeckPreviewWidget::setTags(const QStringList &tags) void DeckPreviewWidget::setTags(const QStringList &tags)
{ {
deckLoader->getDeckList()->setTags(tags); deckLoader->getDeck().deckList.setTags(tags);
deckLoader->saveToFile(filePath, DeckFileFormat::Cockatrice); deckLoader->saveToFile(filePath, DeckFileFormat::Cockatrice);
} }
@ -320,7 +320,7 @@ QMenu *DeckPreviewWidget::createRightClickMenu()
menu->setAttribute(Qt::WA_DeleteOnClose); menu->setAttribute(Qt::WA_DeleteOnClose);
connect(menu->addAction(tr("Open in deck editor")), &QAction::triggered, this, connect(menu->addAction(tr("Open in deck editor")), &QAction::triggered, this,
[this] { emit openDeckEditor(deckLoader); }); [this] { emit openDeckEditor(deckLoader->getDeck()); });
connect(menu->addAction(tr("Edit Tags")), &QAction::triggered, deckTagsDisplayWidget, connect(menu->addAction(tr("Edit Tags")), &QAction::triggered, deckTagsDisplayWidget,
&DeckPreviewDeckTagsDisplayWidget::openTagEditDlg); &DeckPreviewDeckTagsDisplayWidget::openTagEditDlg);
@ -334,13 +334,13 @@ QMenu *DeckPreviewWidget::createRightClickMenu()
auto saveToClipboardMenu = menu->addMenu(tr("Save Deck to Clipboard")); auto saveToClipboardMenu = menu->addMenu(tr("Save Deck to Clipboard"));
connect(saveToClipboardMenu->addAction(tr("Annotated")), &QAction::triggered, this, connect(saveToClipboardMenu->addAction(tr("Annotated")), &QAction::triggered, this,
[this] { DeckLoader::saveToClipboard(deckLoader->getDeckList(), true, true); }); [this] { DeckLoader::saveToClipboard(&deckLoader->getDeck().deckList, true, true); });
connect(saveToClipboardMenu->addAction(tr("Annotated (No set info)")), &QAction::triggered, this, connect(saveToClipboardMenu->addAction(tr("Annotated (No set info)")), &QAction::triggered, this,
[this] { DeckLoader::saveToClipboard(deckLoader->getDeckList(), true, false); }); [this] { DeckLoader::saveToClipboard(&deckLoader->getDeck().deckList, true, false); });
connect(saveToClipboardMenu->addAction(tr("Not Annotated")), &QAction::triggered, this, connect(saveToClipboardMenu->addAction(tr("Not Annotated")), &QAction::triggered, this,
[this] { DeckLoader::saveToClipboard(deckLoader->getDeckList(), false, true); }); [this] { DeckLoader::saveToClipboard(&deckLoader->getDeck().deckList, false, true); });
connect(saveToClipboardMenu->addAction(tr("Not Annotated (No set info)")), &QAction::triggered, this, connect(saveToClipboardMenu->addAction(tr("Not Annotated (No set info)")), &QAction::triggered, this,
[this] { DeckLoader::saveToClipboard(deckLoader->getDeckList(), false, false); }); [this] { DeckLoader::saveToClipboard(&deckLoader->getDeck().deckList, false, false); });
menu->addSeparator(); menu->addSeparator();
@ -376,7 +376,7 @@ void DeckPreviewWidget::addSetBannerCardMenu(QMenu *menu)
void DeckPreviewWidget::actRenameDeck() void DeckPreviewWidget::actRenameDeck()
{ {
// read input // read input
const QString oldName = deckLoader->getDeckList()->getName(); const QString oldName = deckLoader->getDeck().deckList.getName();
bool ok; bool ok;
QString newName = QInputDialog::getText(this, "Rename deck", tr("New name:"), QLineEdit::Normal, oldName, &ok); QString newName = QInputDialog::getText(this, "Rename deck", tr("New name:"), QLineEdit::Normal, oldName, &ok);
@ -385,7 +385,7 @@ void DeckPreviewWidget::actRenameDeck()
} }
// write change // write change
deckLoader->getDeckList()->setName(newName); deckLoader->getDeck().deckList.setName(newName);
deckLoader->saveToFile(filePath, DeckFileFormat::getFormatFromName(filePath)); deckLoader->saveToFile(filePath, DeckFileFormat::getFormatFromName(filePath));
// update VDS // update VDS
@ -416,9 +416,7 @@ void DeckPreviewWidget::actRenameFile()
return; return;
} }
LoadedDeck::LoadInfo lastLoadInfo = deckLoader->getLastLoadInfo(); deckLoader->getDeck().lastLoadInfo.fileName = newFilePath;
lastLoadInfo.fileName = newFilePath;
deckLoader->setLastLoadInfo(lastLoadInfo);
// update VDS // update VDS
setFilePath(newFilePath); setFilePath(newFilePath);

View file

@ -51,7 +51,7 @@ public:
signals: signals:
void deckLoadRequested(const QString &filePath); void deckLoadRequested(const QString &filePath);
void openDeckEditor(DeckLoader *deck); void openDeckEditor(const LoadedDeck &deck);
public slots: public slots:
void setFilePath(const QString &filePath); void setFilePath(const QString &filePath);

View file

@ -211,7 +211,7 @@ QStringList VisualDeckStorageFolderDisplayWidget::gatherAllTagsFromFlowWidget()
// Iterate through all DeckPreviewWidgets // Iterate through all DeckPreviewWidgets
for (DeckPreviewWidget *display : flowWidget->findChildren<DeckPreviewWidget *>()) { for (DeckPreviewWidget *display : flowWidget->findChildren<DeckPreviewWidget *>()) {
// Get tags from each DeckPreviewWidget // Get tags from each DeckPreviewWidget
QStringList tags = display->deckLoader->getDeckList()->getTags(); QStringList tags = display->deckLoader->getDeck().deckList.getTags();
// Add tags to the list while avoiding duplicates // Add tags to the list while avoiding duplicates
allTags.append(tags); allTags.append(tags);

View file

@ -95,14 +95,17 @@ QList<DeckPreviewWidget *> VisualDeckStorageSortWidget::filterFiles(QList<DeckPr
switch (sortOrder) { switch (sortOrder) {
case ByName: case ByName:
return widget1->deckLoader->getDeckList()->getName() < widget2->deckLoader->getDeckList()->getName(); return widget1->deckLoader->getDeck().deckList.getName() <
widget2->deckLoader->getDeck().deckList.getName();
case Alphabetical: case Alphabetical:
return QString::localeAwareCompare(info1.fileName(), info2.fileName()) <= 0; return QString::localeAwareCompare(info1.fileName(), info2.fileName()) <= 0;
case ByLastModified: case ByLastModified:
return info1.lastModified() > info2.lastModified(); return info1.lastModified() > info2.lastModified();
case ByLastLoaded: { case ByLastLoaded: {
QDateTime time1 = QDateTime::fromString(widget1->deckLoader->getDeckList()->getLastLoadedTimestamp()); QDateTime time1 =
QDateTime time2 = QDateTime::fromString(widget2->deckLoader->getDeckList()->getLastLoadedTimestamp()); QDateTime::fromString(widget1->deckLoader->getDeck().deckList.getLastLoadedTimestamp());
QDateTime time2 =
QDateTime::fromString(widget2->deckLoader->getDeck().deckList.getLastLoadedTimestamp());
return time1 > time2; return time1 > time2;
} }
} }

View file

@ -57,7 +57,7 @@ void VisualDeckStorageTagFilterWidget::filterDecksBySelectedTags(const QList<Dec
} }
for (DeckPreviewWidget *deckPreview : deckPreviews) { for (DeckPreviewWidget *deckPreview : deckPreviews) {
QStringList deckTags = deckPreview->deckLoader->getDeckList()->getTags(); QStringList deckTags = deckPreview->deckLoader->getDeck().deckList.getTags();
bool hasAllSelected = std::all_of(selectedTags.begin(), selectedTags.end(), bool hasAllSelected = std::all_of(selectedTags.begin(), selectedTags.end(),
[&deckTags](const QString &tag) { return deckTags.contains(tag); }); [&deckTags](const QString &tag) { return deckTags.contains(tag); });
@ -153,7 +153,7 @@ QSet<QString> VisualDeckStorageTagFilterWidget::gatherAllTags() const
for (DeckPreviewWidget *widget : deckWidgets) { for (DeckPreviewWidget *widget : deckWidgets) {
if (widget->checkVisibility()) { if (widget->checkVisibility()) {
for (const QString &tag : widget->deckLoader->getDeckList()->getTags()) { for (const QString &tag : widget->deckLoader->getDeck().deckList.getTags()) {
allTags.insert(tag); allTags.insert(tag);
} }
} }

View file

@ -53,7 +53,7 @@ public slots:
signals: signals:
void bannerCardsRefreshed(); void bannerCardsRefreshed();
void deckLoadRequested(const QString &filePath); void deckLoadRequested(const QString &filePath);
void openDeckEditor(DeckLoader *deck); void openDeckEditor(const LoadedDeck &deck);
private: private:
QVBoxLayout *layout; QVBoxLayout *layout;