A DeckLoader is not a DeckList. (#6306)

* A DeckLoader is not a DeckList.

Took 2 hours 39 minutes

* Explicitly initialize base class in copy constructor?

Took 3 minutes

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
BruebachL
2025-11-12 02:16:44 +01:00
committed by GitHub
parent 4c431e98a6
commit 8e88749078
32 changed files with 163 additions and 139 deletions

View File

@@ -24,13 +24,13 @@ class ArchidektJsonParser : public IJsonDeckParser
public:
DeckLoader *parse(const QJsonObject &obj) override
{
DeckLoader *list = new DeckLoader();
DeckLoader *loader = new DeckLoader(nullptr);
QString deckName = obj.value("name").toString();
QString deckDescription = obj.value("description").toString();
list->setName(deckName);
list->setComments(deckDescription);
loader->getDeckList()->setName(deckName);
loader->getDeckList()->setComments(deckDescription);
QString outputText;
QTextStream outStream(&outputText);
@@ -47,10 +47,10 @@ public:
outStream << quantity << ' ' << cardName << " (" << setName << ") " << collectorNumber << '\n';
}
list->loadFromStream_Plain(outStream, false);
list->resolveSetNameAndNumberToProviderID();
loader->getDeckList()->loadFromStream_Plain(outStream, false);
loader->resolveSetNameAndNumberToProviderID();
return list;
return loader;
}
};
@@ -59,13 +59,13 @@ class MoxfieldJsonParser : public IJsonDeckParser
public:
DeckLoader *parse(const QJsonObject &obj) override
{
DeckLoader *list = new DeckLoader();
DeckLoader *loader = new DeckLoader(nullptr);
QString deckName = obj.value("name").toString();
QString deckDescription = obj.value("description").toString();
list->setName(deckName);
list->setComments(deckDescription);
loader->getDeckList()->setName(deckName);
loader->getDeckList()->setComments(deckDescription);
QString outputText;
QTextStream outStream(&outputText);
@@ -94,8 +94,8 @@ public:
outStream << quantity << ' ' << cardName << " (" << setName << ") " << collectorNumber << '\n';
}
list->loadFromStream_Plain(outStream, false);
list->resolveSetNameAndNumberToProviderID();
loader->getDeckList()->loadFromStream_Plain(outStream, false);
loader->resolveSetNameAndNumberToProviderID();
QJsonObject commandersObj = obj.value("commanders").toObject();
if (!commandersObj.isEmpty()) {
@@ -106,12 +106,12 @@ public:
QString collectorNumber = cardData.value("cn").toString();
QString providerId = cardData.value("scryfall_id").toString();
list->setBannerCard({commanderName, providerId});
list->addCard(commanderName, DECK_ZONE_MAIN, -1, setName, collectorNumber, providerId);
loader->getDeckList()->setBannerCard({commanderName, providerId});
loader->getDeckList()->addCard(commanderName, DECK_ZONE_MAIN, -1, setName, collectorNumber, providerId);
}
}
return list;
return loader;
}
};

View File

@@ -117,7 +117,7 @@ static void setupParserRules()
return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) -> bool {
int count = 0;
deck->deckLoader->forEachCard([&](InnerDecklistNode *, const DecklistCardNode *node) {
deck->deckLoader->getDeckList()->forEachCard([&](InnerDecklistNode *, const DecklistCardNode *node) {
auto cardInfoPtr = CardDatabaseManager::query()->getCardInfo(node->getName());
if (!cardInfoPtr.isNull() && cardFilter.check(cardInfoPtr)) {
count += node->getNumber();
@@ -136,7 +136,7 @@ static void setupParserRules()
search["DeckNameQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter {
auto name = std::any_cast<QString>(sv[0]);
return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) {
return deck->deckLoader->getName().contains(name, Qt::CaseInsensitive);
return deck->deckLoader->getDeckList()->getName().contains(name, Qt::CaseInsensitive);
};
};

View File

@@ -264,7 +264,7 @@ void DeckViewContainer::loadLocalDeck()
void DeckViewContainer::loadDeckFromFile(const QString &filePath)
{
DeckLoader::FileFormat fmt = DeckLoader::getFormatFromName(filePath);
DeckLoader deck;
DeckLoader deck(this);
bool success = deck.loadFromFile(filePath, fmt, true);
@@ -276,9 +276,9 @@ void DeckViewContainer::loadDeckFromFile(const QString &filePath)
loadDeckFromDeckLoader(&deck);
}
void DeckViewContainer::loadDeckFromDeckLoader(const DeckLoader *deck)
void DeckViewContainer::loadDeckFromDeckLoader(DeckLoader *deck)
{
QString deckString = deck->writeToString_Native();
QString deckString = deck->getDeckList()->writeToString_Native();
if (deckString.length() > MAX_FILE_LENGTH) {
QMessageBox::critical(this, tr("Error"), tr("Deck is greater than maximum file size."));
@@ -331,8 +331,9 @@ void DeckViewContainer::loadFromWebsite()
void DeckViewContainer::deckSelectFinished(const Response &r)
{
const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext);
DeckLoader newDeck(QString::fromStdString(resp.deck()));
CardPictureLoader::cacheCardPixmaps(CardDatabaseManager::query()->getCards(newDeck.getCardRefList()));
DeckLoader newDeck(this, new DeckList(QString::fromStdString(resp.deck())));
CardPictureLoader::cacheCardPixmaps(
CardDatabaseManager::query()->getCards(newDeck.getDeckList()->getCardRefList()));
setDeck(newDeck);
switchToDeckLoadedView();
}
@@ -413,8 +414,8 @@ void DeckViewContainer::setSideboardLocked(bool locked)
deckView->resetSideboardPlan();
}
void DeckViewContainer::setDeck(const DeckLoader &deck)
void DeckViewContainer::setDeck(DeckLoader &deck)
{
deckView->setDeck(deck);
deckView->setDeck(*deck.getDeckList());
switchToDeckLoadedView();
}

View File

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

View File

@@ -62,7 +62,8 @@ void UtilityMenu::populatePredefinedTokensMenu()
return;
}
InnerDecklistNode *tokenZone = dynamic_cast<InnerDecklistNode *>(_deck->getRoot()->findChild(DECK_ZONE_TOKENS));
InnerDecklistNode *tokenZone =
dynamic_cast<InnerDecklistNode *>(_deck->getDeckList()->getRoot()->findChild(DECK_ZONE_TOKENS));
if (tokenZone) {
if (!tokenZone->empty())

View File

@@ -66,7 +66,7 @@ class Player : public QObject
Q_OBJECT
signals:
void openDeckEditor(const DeckLoader *deck);
void openDeckEditor(DeckLoader *deck);
void deckChanged();
void newCardAdded(AbstractCardItem *card);
void rearrangeCounters();

View File

@@ -25,26 +25,27 @@ const QStringList DeckLoader::ACCEPTED_FILE_EXTENSIONS = {"*.cod", "*.dec", "*.d
const QStringList DeckLoader::FILE_NAME_FILTERS = {
tr("Common deck formats (%1)").arg(ACCEPTED_FILE_EXTENSIONS.join(" ")), tr("All files (*.*)")};
DeckLoader::DeckLoader() : DeckList(), lastFileName(QString()), lastFileFormat(CockatriceFormat), lastRemoteDeckId(-1)
DeckLoader::DeckLoader(QObject *parent)
: QObject(parent), deckList(new DeckList()), lastFileFormat(CockatriceFormat), lastRemoteDeckId(-1)
{
}
DeckLoader::DeckLoader(const QString &nativeString)
: DeckList(nativeString), lastFileName(QString()), lastFileFormat(CockatriceFormat), lastRemoteDeckId(-1)
{
}
DeckLoader::DeckLoader(const DeckList &other)
: DeckList(other), lastFileName(QString()), lastFileFormat(CockatriceFormat), lastRemoteDeckId(-1)
DeckLoader::DeckLoader(QObject *parent, DeckList *_deckList)
: QObject(parent), deckList(_deckList), lastFileFormat(CockatriceFormat), lastRemoteDeckId(-1)
{
}
DeckLoader::DeckLoader(const DeckLoader &other)
: DeckList(other), lastFileName(other.lastFileName), lastFileFormat(other.lastFileFormat),
: QObject(), deckList(other.deckList), lastFileName(other.lastFileName), lastFileFormat(other.lastFileFormat),
lastRemoteDeckId(other.lastRemoteDeckId)
{
}
void DeckLoader::setDeckList(DeckList *_deckList)
{
deckList = _deckList;
}
bool DeckLoader::loadFromFile(const QString &fileName, FileFormat fmt, bool userRequest)
{
QFile file(fileName);
@@ -55,15 +56,15 @@ bool DeckLoader::loadFromFile(const QString &fileName, FileFormat fmt, bool user
bool result = false;
switch (fmt) {
case PlainTextFormat:
result = loadFromFile_Plain(&file);
result = deckList->loadFromFile_Plain(&file);
break;
case CockatriceFormat: {
result = loadFromFile_Native(&file);
result = deckList->loadFromFile_Native(&file);
qCInfo(DeckLoaderLog) << "Loaded from" << fileName << "-" << result;
if (!result) {
qCInfo(DeckLoaderLog) << "Retrying as plain format";
file.seek(0);
result = loadFromFile_Plain(&file);
result = deckList->loadFromFile_Plain(&file);
fmt = PlainTextFormat;
}
break;
@@ -115,13 +116,13 @@ bool DeckLoader::loadFromFileAsync(const QString &fileName, FileFormat fmt, bool
switch (fmt) {
case PlainTextFormat:
return loadFromFile_Plain(&file);
return deckList->loadFromFile_Plain(&file);
case CockatriceFormat: {
bool result = false;
result = loadFromFile_Native(&file);
result = deckList->loadFromFile_Native(&file);
if (!result) {
file.seek(0);
return loadFromFile_Plain(&file);
return deckList->loadFromFile_Plain(&file);
}
return result;
}
@@ -137,7 +138,7 @@ bool DeckLoader::loadFromFileAsync(const QString &fileName, FileFormat fmt, bool
bool DeckLoader::loadFromRemote(const QString &nativeString, int remoteDeckId)
{
bool result = loadFromString_Native(nativeString);
bool result = deckList->loadFromString_Native(nativeString);
if (result) {
lastFileName = QString();
lastFileFormat = CockatriceFormat;
@@ -158,10 +159,10 @@ bool DeckLoader::saveToFile(const QString &fileName, FileFormat fmt)
bool result = false;
switch (fmt) {
case PlainTextFormat:
result = saveToFile_Plain(&file);
result = deckList->saveToFile_Plain(&file);
break;
case CockatriceFormat:
result = saveToFile_Native(&file);
result = deckList->saveToFile_Native(&file);
break;
}
@@ -198,11 +199,11 @@ bool DeckLoader::updateLastLoadedTimestamp(const QString &fileName, FileFormat f
// Perform file modifications
switch (fmt) {
case PlainTextFormat:
result = saveToFile_Plain(&file);
result = deckList->saveToFile_Plain(&file);
break;
case CockatriceFormat:
setLastLoadedTimestamp(QDateTime::currentDateTime().toString());
result = saveToFile_Native(&file);
deckList->setLastLoadedTimestamp(QDateTime::currentDateTime().toString());
result = deckList->saveToFile_Native(&file);
break;
}
@@ -301,7 +302,7 @@ QString DeckLoader::exportDeckToDecklist(DecklistWebsite website)
};
// call our struct function for each card in the deck
forEachCard(formatDeckListForExport);
deckList->forEachCard(formatDeckListForExport);
// Remove the extra return at the end of the last cards
mainBoardCards.chop(3);
sideBoardCards.chop(3);
@@ -349,7 +350,7 @@ void DeckLoader::setProviderIdToPreferredPrinting()
SetProviderIdToPreferred setProviderIdToPreferred;
// Call the forEachCard method for each card in the deck
forEachCard(setProviderIdToPreferred);
deckList->forEachCard(setProviderIdToPreferred);
}
/**
@@ -370,7 +371,7 @@ void DeckLoader::resolveSetNameAndNumberToProviderID()
card->setCardProviderId(providerId);
};
forEachCard(setProviderId);
deckList->forEachCard(setProviderId);
}
// This struct is here to support the forEachCard function call, defined in decklist.
@@ -405,7 +406,7 @@ void DeckLoader::clearSetNamesAndNumbers()
card->setCardProviderId(nullptr);
};
forEachCard(clearSetNameAndNumber);
deckList->forEachCard(clearSetNameAndNumber);
}
DeckLoader::FileFormat DeckLoader::getFormatFromName(const QString &fileName)
@@ -432,8 +433,8 @@ bool DeckLoader::saveToStream_Plain(QTextStream &out, bool addComments, bool add
}
// loop zones
for (int i = 0; i < getRoot()->size(); i++) {
const auto *zoneNode = dynamic_cast<InnerDecklistNode *>(getRoot()->at(i));
for (int i = 0; i < deckList->getRoot()->size(); i++) {
const auto *zoneNode = dynamic_cast<InnerDecklistNode *>(deckList->getRoot()->at(i));
saveToStream_DeckZone(out, zoneNode, addComments, addSetNameAndNumber);
@@ -446,12 +447,12 @@ bool DeckLoader::saveToStream_Plain(QTextStream &out, bool addComments, bool add
void DeckLoader::saveToStream_DeckHeader(QTextStream &out) const
{
if (!getName().isEmpty()) {
out << "// " << getName() << "\n\n";
if (!deckList->getName().isEmpty()) {
out << "// " << deckList->getName() << "\n\n";
}
if (!getComments().isEmpty()) {
QStringList commentRows = getComments().split(QRegularExpression("\n|\r\n|\r"));
if (!deckList->getComments().isEmpty()) {
QStringList commentRows = deckList->getComments().split(QRegularExpression("\n|\r\n|\r"));
for (const QString &row : commentRows) {
out << "// " << row << "\n";
}
@@ -558,7 +559,7 @@ bool DeckLoader::convertToCockatriceFormat(QString fileName)
switch (getFormatFromName(fileName)) {
case PlainTextFormat:
// Save in Cockatrice's native format
result = saveToFile_Native(&file);
result = deckList->saveToFile_Native(&file);
break;
case CockatriceFormat:
qCInfo(DeckLoaderLog) << "File is already in Cockatrice format. No conversion needed.";
@@ -685,19 +686,19 @@ void DeckLoader::printDeckList(QPrinter *printer)
headerCharFormat.setFontWeight(QFont::Bold);
cursor.insertBlock(headerBlockFormat, headerCharFormat);
cursor.insertText(getName());
cursor.insertText(deckList->getName());
headerCharFormat.setFontPointSize(12);
cursor.insertBlock(headerBlockFormat, headerCharFormat);
cursor.insertText(getComments());
cursor.insertText(deckList->getComments());
cursor.insertBlock(headerBlockFormat, headerCharFormat);
for (int i = 0; i < getRoot()->size(); i++) {
for (int i = 0; i < deckList->getRoot()->size(); i++) {
cursor.insertHtml("<br><img src=theme:hr.jpg>");
// cursor.insertHtml("<hr>");
cursor.insertBlock(headerBlockFormat, headerCharFormat);
printDeckListNode(&cursor, dynamic_cast<InnerDecklistNode *>(getRoot()->at(i)));
printDeckListNode(&cursor, dynamic_cast<InnerDecklistNode *>(deckList->getRoot()->at(i)));
}
doc.print(printer);

View File

@@ -14,7 +14,7 @@
inline Q_LOGGING_CATEGORY(DeckLoaderLog, "deck_loader")
class DeckLoader : public DeckList
class DeckLoader : public QObject
{
Q_OBJECT
signals:
@@ -52,14 +52,15 @@ public:
};
private:
DeckList *deckList;
QString lastFileName;
FileFormat lastFileFormat;
int lastRemoteDeckId;
public:
DeckLoader();
explicit DeckLoader(const QString &nativeString);
explicit DeckLoader(const DeckList &other);
DeckLoader(QObject *parent);
DeckLoader(QObject *parent, DeckList *_deckList);
void setDeckList(DeckList *_deckList);
DeckLoader(const DeckLoader &other);
const QString &getLastFileName() const
{
@@ -102,6 +103,11 @@ public:
bool saveToStream_Plain(QTextStream &out, bool addComments = true, bool addSetNameAndNumber = true) const;
bool convertToCockatriceFormat(QString fileName);
DeckList *getDeckList()
{
return deckList;
}
private:
void printDeckListNode(QTextCursor *cursor, InnerDecklistNode *node);
@@ -116,8 +122,8 @@ protected:
QList<DecklistCardNode *> cards,
bool addComments = true,
bool addSetNameAndNumber = true) const;
[[nodiscard]] QString getCardZoneFromName(QString cardName, QString currentZoneName) override;
[[nodiscard]] QString getCompleteCardName(const QString &cardName) const override;
[[nodiscard]] QString getCardZoneFromName(QString cardName, QString currentZoneName);
[[nodiscard]] QString getCompleteCardName(const QString &cardName) const;
};
#endif

View File

@@ -32,6 +32,8 @@ void DeckEditorDeckDockWidget::createDeckDock()
deckModel->setObjectName("deckModel");
connect(deckModel, &DeckListModel::deckHashChanged, this, &DeckEditorDeckDockWidget::updateHash);
deckLoader = new DeckLoader(this, deckModel->getDeckList());
DeckListStyleProxy *proxy = new DeckListStyleProxy(this);
proxy->setSourceModel(deckModel);
@@ -373,10 +375,9 @@ void DeckEditorDeckDockWidget::syncBannerCardComboBoxSelectionWithDeck()
void DeckEditorDeckDockWidget::setDeck(DeckLoader *_deck)
{
deckLoader = _deck;
deckModel->setDeckList(_deck);
connect(_deck, &DeckLoader::deckLoaded, deckModel, &DeckListModel::rebuildTree);
connect(_deck, &DeckLoader::deckHashChanged, deckModel, &DeckListModel::deckHashChanged);
deckModel->setDeckList(deckLoader->getDeckList());
connect(deckLoader, &DeckLoader::deckLoaded, deckModel, &DeckListModel::rebuildTree);
connect(deckLoader->getDeckList(), &DeckList::deckHashChanged, deckModel, &DeckListModel::deckHashChanged);
nameEdit->setText(deckModel->getDeckList()->getName());
commentsEdit->setText(deckModel->getDeckList()->getComments());
@@ -398,6 +399,11 @@ DeckLoader *DeckEditorDeckDockWidget::getDeckLoader()
return deckLoader;
}
DeckList *DeckEditorDeckDockWidget::getDeckList()
{
return deckModel->getDeckList();
}
/**
* Resets the tab to the state for a blank new tab.
*/

View File

@@ -52,6 +52,7 @@ public slots:
void updateBannerCardComboBox();
void setDeck(DeckLoader *_deck);
DeckLoader *getDeckLoader();
DeckList *getDeckList();
void actIncrement();
bool swapCard(const QModelIndex &idx);
void actDecrementCard(const ExactCard &card, QString zoneName);

View File

@@ -75,12 +75,12 @@ bool AbstractDlgDeckTextEdit::loadIntoDeck(DeckLoader *deckLoader) const
QString buffer = contentsEdit->toPlainText();
if (buffer.contains("<cockatrice_deck version=\"1\">")) {
return deckLoader->loadFromString_Native(buffer);
return deckLoader->getDeckList()->loadFromString_Native(buffer);
}
QTextStream stream(&buffer);
if (deckLoader->loadFromStream_Plain(stream, true)) {
if (deckLoader->getDeckList()->loadFromStream_Plain(stream, true)) {
if (loadSetNameAndNumberCheckBox->isChecked()) {
deckLoader->resolveSetNameAndNumberToProviderID();
} else {
@@ -121,8 +121,7 @@ void DlgLoadDeckFromClipboard::actRefresh()
void DlgLoadDeckFromClipboard::actOK()
{
deckList = new DeckLoader;
deckList->setParent(this);
deckList = new DeckLoader(this);
if (loadIntoDeck(deckList)) {
accept();

View File

@@ -95,9 +95,9 @@ void DlgLoadDeckFromWebsite::accept()
}
// Parse the plain text deck here
DeckLoader *loader = new DeckLoader();
DeckLoader *loader = new DeckLoader(this);
QTextStream stream(&deckText);
loader->loadFromStream_Plain(stream, false);
loader->getDeckList()->loadFromStream_Plain(stream, false);
loader->resolveSetNameAndNumberToProviderID();
deck = loader;

View File

@@ -19,7 +19,7 @@ HomeWidget::HomeWidget(QWidget *parent, TabSupervisor *_tabSupervisor)
layout = new QGridLayout(this);
backgroundSourceCard = new CardInfoPictureArtCropWidget(this);
backgroundSourceDeck = new DeckLoader();
backgroundSourceDeck = new DeckLoader(this);
backgroundSourceDeck->loadFromFile(SettingsCache::instance().getDeckPath() + "background.cod",
DeckLoader::CockatriceFormat, false);
@@ -94,7 +94,7 @@ void HomeWidget::updateRandomCard()
newCard.getCardPtr()->getProperty("layout") != "normal");
break;
case BackgroundSources::DeckFileArt:
QList<CardRef> cardRefs = backgroundSourceDeck->getCardRefList();
QList<CardRef> cardRefs = backgroundSourceDeck->getDeckList()->getCardRefList();
ExactCard oldCard = backgroundSourceCard->getCard();
if (!cardRefs.empty()) {

View File

@@ -209,7 +209,7 @@ void AbstractTabDeckEditor::openDeck(DeckLoader *deck)
void AbstractTabDeckEditor::setDeck(DeckLoader *_deck)
{
deckDockWidget->setDeck(_deck);
CardPictureLoader::cacheCardPixmaps(CardDatabaseManager::query()->getCards(getDeckLoader()->getCardRefList()));
CardPictureLoader::cacheCardPixmaps(CardDatabaseManager::query()->getCards(getDeckList()->getCardRefList()));
setModified(false);
aDeckDockVisible->setChecked(true);
@@ -222,6 +222,12 @@ DeckLoader *AbstractTabDeckEditor::getDeckLoader() const
return deckDockWidget->getDeckLoader();
}
/** @brief Returns the currently loaded deck list. */
DeckList *AbstractTabDeckEditor::getDeckList() const
{
return deckDockWidget->getDeckList();
}
/**
* @brief Sets the modified state of the tab.
* @param _modified True if tab is modified, false otherwise.
@@ -238,7 +244,7 @@ void AbstractTabDeckEditor::setModified(bool _modified)
bool AbstractTabDeckEditor::isBlankNewDeck() const
{
DeckLoader *deck = deckDockWidget->getDeckLoader();
return !modified && deck->isBlankDeck() && deck->hasNotBeenLoaded();
return !modified && deck->getDeckList()->isBlankDeck() && deck->hasNotBeenLoaded();
}
/** @brief Creates a new deck. Handles opening in new tab if needed. */
@@ -354,7 +360,7 @@ void AbstractTabDeckEditor::openDeckFromFile(const QString &fileName, DeckOpenLo
{
DeckLoader::FileFormat fmt = DeckLoader::getFormatFromName(fileName);
auto *l = new DeckLoader;
auto *l = new DeckLoader(this);
if (l->loadFromFile(fileName, fmt, true)) {
if (deckOpenLocation == NEW_TAB) {
emit openDeckEditor(l);
@@ -379,7 +385,7 @@ bool AbstractTabDeckEditor::actSaveDeck()
{
DeckLoader *const deck = getDeckLoader();
if (deck->getLastRemoteDeckId() != -1) {
QString deckString = deck->writeToString_Native();
QString deckString = deck->getDeckList()->writeToString_Native();
if (deckString.length() > MAX_FILE_LENGTH) {
QMessageBox::critical(this, tr("Error"), tr("Could not save remote deck"));
return false;
@@ -418,7 +424,7 @@ bool AbstractTabDeckEditor::actSaveDeckAs()
dialog.setAcceptMode(QFileDialog::AcceptSave);
dialog.setDefaultSuffix("cod");
dialog.setNameFilters(DeckLoader::FILE_NAME_FILTERS);
dialog.selectFile(getDeckLoader()->getName().trimmed());
dialog.selectFile(getDeckList()->getName().trimmed());
if (!dialog.exec())
return false;
@@ -600,14 +606,14 @@ void AbstractTabDeckEditor::actExportDeckDecklistXyz()
void AbstractTabDeckEditor::actAnalyzeDeckDeckstats()
{
auto *interface = new DeckStatsInterface(*databaseDisplayDockWidget->databaseModel->getDatabase(), this);
interface->analyzeDeck(getDeckLoader());
interface->analyzeDeck(getDeckList());
}
/** @brief Analyzes the deck using TappedOut. */
void AbstractTabDeckEditor::actAnalyzeDeckTappedout()
{
auto *interface = new TappedOutInterface(*databaseDisplayDockWidget->databaseModel->getDatabase(), this);
interface->analyzeDeck(getDeckLoader());
interface->analyzeDeck(getDeckList());
}
/** @brief Applies a new filter tree to the database display. */

View File

@@ -116,9 +116,12 @@ public:
*/
void openDeck(DeckLoader *deck);
/** @brief Returns the currently active deck. */
/** @brief Returns the currently active deck loader. */
DeckLoader *getDeckLoader() const;
/** @brief Returns the currently active deck list. */
DeckList *getDeckList() const;
/** @brief Sets the modified state of the tab.
* @param _windowModified Whether the tab is modified.
*/
@@ -178,7 +181,7 @@ public slots:
signals:
/** @brief Emitted when a deck should be opened in a new editor tab. */
void openDeckEditor(const DeckLoader *deckLoader);
void openDeckEditor(DeckLoader *deckLoader);
/** @brief Emitted before the tab is closed. */
void deckEditorClosing(AbstractTabDeckEditor *tab);

View File

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

View File

@@ -242,7 +242,7 @@ void TabDeckStorage::actOpenLocalDeck()
continue;
QString filePath = localDirModel->filePath(curLeft);
DeckLoader deckLoader;
DeckLoader deckLoader(this);
if (!deckLoader.loadFromFile(filePath, DeckLoader::CockatriceFormat, true))
continue;
@@ -308,13 +308,13 @@ void TabDeckStorage::uploadDeck(const QString &filePath, const QString &targetPa
QFile deckFile(filePath);
QFileInfo deckFileInfo(deckFile);
DeckLoader deck;
DeckLoader deck(this);
if (!deck.loadFromFile(filePath, DeckLoader::CockatriceFormat)) {
QMessageBox::critical(this, tr("Error"), tr("Invalid deck file"));
return;
}
if (deck.getName().isEmpty()) {
if (deck.getDeckList()->getName().isEmpty()) {
bool ok;
QString deckName =
getTextWithMax(this, tr("Enter deck name"), tr("This decklist does not have a name.\nPlease enter a name:"),
@@ -323,12 +323,12 @@ void TabDeckStorage::uploadDeck(const QString &filePath, const QString &targetPa
return;
if (deckName.isEmpty())
deckName = tr("Unnamed deck");
deck.setName(deckName);
deck.getDeckList()->setName(deckName);
} else {
deck.setName(deck.getName().left(MAX_NAME_LENGTH));
deck.getDeckList()->setName(deck.getDeckList()->getName().left(MAX_NAME_LENGTH));
}
QString deckString = deck.writeToString_Native();
QString deckString = deck.getDeckList()->writeToString_Native();
if (deckString.length() > MAX_FILE_LENGTH) {
QMessageBox::critical(this, tr("Error"), tr("Invalid deck file"));
return;
@@ -433,7 +433,7 @@ void TabDeckStorage::openRemoteDeckFinished(const Response &r, const CommandCont
const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext);
const Command_DeckDownload &cmd = commandContainer.session_command(0).GetExtension(Command_DeckDownload::ext);
DeckLoader loader;
DeckLoader loader(this);
if (!loader.loadFromRemote(QString::fromStdString(resp.deck()), cmd.deck_id()))
return;
@@ -493,7 +493,7 @@ void TabDeckStorage::downloadFinished(const Response &r,
const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext);
QString filePath = extraData.toString();
DeckLoader deck(QString::fromStdString(resp.deck()));
DeckLoader deck(this, new DeckList(QString::fromStdString(resp.deck())));
deck.saveToFile(filePath, DeckLoader::CockatriceFormat);
}

View File

@@ -87,7 +87,7 @@ public:
return tr("Deck Storage");
}
signals:
void openDeckEditor(const DeckLoader *deckLoader);
void openDeckEditor(DeckLoader *deckLoader);
};
#endif

View File

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

View File

@@ -121,7 +121,7 @@ signals:
void containerProcessingStarted(const GameEventContext &context);
void containerProcessingDone();
void openMessageDialog(const QString &userName, bool focus);
void openDeckEditor(const DeckLoader *deck);
void openDeckEditor(DeckLoader *deck);
void notIdle();
void phaseChanged(int phase);

View File

@@ -843,7 +843,7 @@ void TabSupervisor::talkLeft(TabMessage *tab)
* 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.
*/
void TabSupervisor::openDeckInNewTab(const DeckLoader *deckToOpen)
void TabSupervisor::openDeckInNewTab(DeckLoader *deckToOpen)
{
int type = SettingsCache::instance().getDefaultDeckEditorType();
switch (type) {
@@ -865,11 +865,11 @@ void TabSupervisor::openDeckInNewTab(const DeckLoader *deckToOpen)
* Creates a new deck editor tab
* @param deckToOpen The deck to open in the tab. Creates a copy of the DeckLoader instance.
*/
TabDeckEditor *TabSupervisor::addDeckEditorTab(const DeckLoader *deckToOpen)
TabDeckEditor *TabSupervisor::addDeckEditorTab(DeckLoader *deckToOpen)
{
auto *tab = new TabDeckEditor(this);
if (deckToOpen)
tab->openDeck(new DeckLoader(*deckToOpen));
tab->openDeck(new DeckLoader(this, deckToOpen->getDeckList()));
connect(tab, &AbstractTabDeckEditor::deckEditorClosing, this, &TabSupervisor::deckEditorClosed);
connect(tab, &AbstractTabDeckEditor::openDeckEditor, this, &TabSupervisor::addDeckEditorTab);
myAddTab(tab);
@@ -878,11 +878,11 @@ TabDeckEditor *TabSupervisor::addDeckEditorTab(const DeckLoader *deckToOpen)
return tab;
}
TabDeckEditorVisual *TabSupervisor::addVisualDeckEditorTab(const DeckLoader *deckToOpen)
TabDeckEditorVisual *TabSupervisor::addVisualDeckEditorTab(DeckLoader *deckToOpen)
{
auto *tab = new TabDeckEditorVisual(this);
if (deckToOpen)
tab->openDeck(new DeckLoader(*deckToOpen));
tab->openDeck(new DeckLoader(this, deckToOpen->getDeckList()));
connect(tab, &AbstractTabDeckEditor::deckEditorClosing, this, &TabSupervisor::deckEditorClosed);
connect(tab, &AbstractTabDeckEditor::openDeckEditor, this, &TabSupervisor::addVisualDeckEditorTab);
myAddTab(tab);

View File

@@ -169,9 +169,9 @@ signals:
void showWindowIfHidden();
public slots:
void openDeckInNewTab(const DeckLoader *deckToOpen);
TabDeckEditor *addDeckEditorTab(const DeckLoader *deckToOpen);
TabDeckEditorVisual *addVisualDeckEditorTab(const DeckLoader *deckToOpen);
void openDeckInNewTab(DeckLoader *deckToOpen);
TabDeckEditor *addDeckEditorTab(DeckLoader *deckToOpen);
TabDeckEditorVisual *addVisualDeckEditorTab(DeckLoader *deckToOpen);
TabVisualDatabaseDisplay *addVisualDatabaseDisplayTab();
TabEdhRecMain *addEdhrecMainTab();
TabEdhRec *addEdhrecTab(const CardInfoPtr &cardToQuery, bool isCommander = false);

View File

@@ -27,7 +27,7 @@ TabDeckStorageVisual::TabDeckStorageVisual(TabSupervisor *_tabSupervisor)
void TabDeckStorageVisual::actOpenLocalDeck(const QString &filePath)
{
DeckLoader deckLoader;
DeckLoader deckLoader(this);
if (!deckLoader.loadFromFile(filePath, DeckLoader::getFormatFromName(filePath), true)) {
QMessageBox::critical(this, tr("Error"), tr("Could not open deck at %1").arg(filePath));
return;

View File

@@ -39,7 +39,7 @@ public slots:
void actOpenLocalDeck(const QString &filePath);
signals:
void openDeckEditor(const DeckLoader *deckLoader);
void openDeckEditor(DeckLoader *deckLoader);
private:
VisualDeckStorageWidget *visualDeckStorageWidget;

View File

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

View File

@@ -167,10 +167,10 @@ void DeckPreviewDeckTagsDisplayWidget::openTagEditDlg()
auto *deckEditor = qobject_cast<AbstractTabDeckEditor *>(currentParent);
QStringList knownTags;
QStringList allFiles = getAllFiles(SettingsCache::instance().getDeckPath());
DeckLoader loader;
DeckLoader loader(this);
for (const QString &file : allFiles) {
loader.loadFromFile(file, DeckLoader::getFormatFromName(file), false);
QStringList tags = loader.getTags();
QStringList tags = loader.getDeckList()->getTags();
knownTags.append(tags);
knownTags.removeDuplicates();
}

View File

@@ -25,8 +25,7 @@ DeckPreviewWidget::DeckPreviewWidget(QWidget *_parent,
layout = new QVBoxLayout(this);
setLayout(layout);
deckLoader = new DeckLoader();
deckLoader->setParent(this);
deckLoader = new DeckLoader(this);
connect(deckLoader, &DeckLoader::loadFinished, this, &DeckPreviewWidget::initializeUi);
/* TODO: We shouldn't update the tags on *every* deck load, since it's kinda expensive. We should instead count how
many deck loads have finished already and if we've loaded all decks and THEN load all the tags at once. */
@@ -74,23 +73,23 @@ void DeckPreviewWidget::initializeUi(const bool deckLoadSuccess)
if (!deckLoadSuccess) {
return;
}
auto bannerCard = deckLoader->getBannerCard().name.isEmpty()
auto bannerCard = deckLoader->getDeckList()->getBannerCard().name.isEmpty()
? ExactCard()
: CardDatabaseManager::query()->getCard(deckLoader->getBannerCard());
: CardDatabaseManager::query()->getCard(deckLoader->getDeckList()->getBannerCard());
bannerCardDisplayWidget->setCard(bannerCard);
bannerCardDisplayWidget->setFontSize(24);
setFilePath(deckLoader->getLastFileName());
colorIdentityWidget = new ColorIdentityWidget(this, getColorIdentity());
deckTagsDisplayWidget = new DeckPreviewDeckTagsDisplayWidget(this, deckLoader);
deckTagsDisplayWidget = new DeckPreviewDeckTagsDisplayWidget(this, deckLoader->getDeckList());
bannerCardLabel = new QLabel(this);
bannerCardLabel->setObjectName("bannerCardLabel");
bannerCardComboBox = new QComboBox(this);
bannerCardComboBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
bannerCardComboBox->setObjectName("bannerCardComboBox");
bannerCardComboBox->setCurrentText(deckLoader->getBannerCard().name);
bannerCardComboBox->setCurrentText(deckLoader->getDeckList()->getBannerCard().name);
bannerCardComboBox->installEventFilter(new NoScrollFilter());
connect(bannerCardComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&DeckPreviewWidget::setBannerCard);
@@ -152,7 +151,7 @@ void DeckPreviewWidget::updateTagsVisibility(bool visible)
QString DeckPreviewWidget::getColorIdentity()
{
QStringList cardList = deckLoader->getCardList();
QStringList cardList = deckLoader->getDeckList()->getCardList();
if (cardList.isEmpty()) {
return {};
}
@@ -186,8 +185,8 @@ QString DeckPreviewWidget::getColorIdentity()
*/
QString DeckPreviewWidget::getDisplayName() const
{
return deckLoader->getName().isEmpty() ? QFileInfo(deckLoader->getLastFileName()).fileName()
: deckLoader->getName();
return deckLoader->getDeckList()->getName().isEmpty() ? QFileInfo(deckLoader->getLastFileName()).fileName()
: deckLoader->getDeckList()->getName();
}
void DeckPreviewWidget::setFilePath(const QString &_filePath)
@@ -233,7 +232,7 @@ void DeckPreviewWidget::updateBannerCardComboBox()
// Prepare the new items with deduplication
QSet<QPair<QString, QString>> bannerCardSet;
InnerDecklistNode *listRoot = deckLoader->getRoot();
InnerDecklistNode *listRoot = deckLoader->getDeckList()->getRoot();
for (auto i : *listRoot) {
auto *currentZone = dynamic_cast<InnerDecklistNode *>(i);
for (auto j : *currentZone) {
@@ -273,7 +272,7 @@ void DeckPreviewWidget::updateBannerCardComboBox()
bannerCardComboBox->setCurrentIndex(restoredIndex);
} else {
// Add a placeholder "-" and set it as the current selection
int bannerIndex = bannerCardComboBox->findText(deckLoader->getBannerCard().name);
int bannerIndex = bannerCardComboBox->findText(deckLoader->getDeckList()->getBannerCard().name);
if (bannerIndex != -1) {
bannerCardComboBox->setCurrentIndex(bannerIndex);
} else {
@@ -291,7 +290,7 @@ void DeckPreviewWidget::setBannerCard(int /* changedIndex */)
{
auto [name, id] = bannerCardComboBox->currentData().value<QPair<QString, QString>>();
CardRef cardRef = {name, id};
deckLoader->setBannerCard(cardRef);
deckLoader->getDeckList()->setBannerCard(cardRef);
deckLoader->saveToFile(filePath, DeckLoader::getFormatFromName(filePath));
bannerCardDisplayWidget->setCard(CardDatabaseManager::query()->getCard(cardRef));
}
@@ -374,7 +373,7 @@ void DeckPreviewWidget::addSetBannerCardMenu(QMenu *menu)
void DeckPreviewWidget::actRenameDeck()
{
// read input
const QString oldName = deckLoader->getName();
const QString oldName = deckLoader->getDeckList()->getName();
bool ok;
QString newName = QInputDialog::getText(this, "Rename deck", tr("New name:"), QLineEdit::Normal, oldName, &ok);
@@ -383,7 +382,7 @@ void DeckPreviewWidget::actRenameDeck()
}
// write change
deckLoader->setName(newName);
deckLoader->getDeckList()->setName(newName);
deckLoader->saveToFile(filePath, DeckLoader::getFormatFromName(filePath));
// update VDS

View File

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

View File

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

View File

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

View File

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

View File

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