diff --git a/cockatrice/src/client/tabs/tab_deck_storage.cpp b/cockatrice/src/client/tabs/tab_deck_storage.cpp index 426431c68..ee7e40671 100644 --- a/cockatrice/src/client/tabs/tab_deck_storage.cpp +++ b/cockatrice/src/client/tabs/tab_deck_storage.cpp @@ -5,7 +5,7 @@ #include "../../server/remote/remote_decklist_tree_widget.h" #include "../../settings/cache_settings.h" #include "../get_text_with_max.h" -#include "decklist.h" +#include "deck_list.h" #include "pb/command_deck_del.pb.h" #include "pb/command_deck_del_dir.pb.h" #include "pb/command_deck_download.pb.h" diff --git a/cockatrice/src/client/tapped_out_interface.cpp b/cockatrice/src/client/tapped_out_interface.cpp index 9b9a239d4..bea880b27 100644 --- a/cockatrice/src/client/tapped_out_interface.cpp +++ b/cockatrice/src/client/tapped_out_interface.cpp @@ -1,6 +1,7 @@ #include "tapped_out_interface.h" -#include "decklist.h" +#include "deck_list.h" +#include "deck_list_card_node.h" #include #include diff --git a/cockatrice/src/client/tapped_out_interface.h b/cockatrice/src/client/tapped_out_interface.h index a6a763d45..675901245 100644 --- a/cockatrice/src/client/tapped_out_interface.h +++ b/cockatrice/src/client/tapped_out_interface.h @@ -2,7 +2,7 @@ #define TAPPEDOUT_INTERFACE_H #include "../game/cards/card_database.h" -#include "decklist.h" +#include "deck_list.h" #include #include diff --git a/cockatrice/src/client/ui/widgets/deck_analytics/deck_analytics_widget.h b/cockatrice/src/client/ui/widgets/deck_analytics/deck_analytics_widget.h index b379b435c..59f37982e 100644 --- a/cockatrice/src/client/ui/widgets/deck_analytics/deck_analytics_widget.h +++ b/cockatrice/src/client/ui/widgets/deck_analytics/deck_analytics_widget.h @@ -11,7 +11,7 @@ #include #include #include -#include +#include class DeckAnalyticsWidget : public QWidget { diff --git a/cockatrice/src/client/ui/widgets/deck_analytics/mana_base_widget.cpp b/cockatrice/src/client/ui/widgets/deck_analytics/mana_base_widget.cpp index 98e56df66..20628581a 100644 --- a/cockatrice/src/client/ui/widgets/deck_analytics/mana_base_widget.cpp +++ b/cockatrice/src/client/ui/widgets/deck_analytics/mana_base_widget.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include ManaBaseWidget::ManaBaseWidget(QWidget *parent, DeckListModel *_deckListModel) : QWidget(parent), deckListModel(_deckListModel) diff --git a/cockatrice/src/client/ui/widgets/deck_analytics/mana_base_widget.h b/cockatrice/src/client/ui/widgets/deck_analytics/mana_base_widget.h index 66442f687..7b35bbfdc 100644 --- a/cockatrice/src/client/ui/widgets/deck_analytics/mana_base_widget.h +++ b/cockatrice/src/client/ui/widgets/deck_analytics/mana_base_widget.h @@ -6,7 +6,7 @@ #include #include -#include +#include #include class ManaBaseWidget : public QWidget diff --git a/cockatrice/src/client/ui/widgets/deck_analytics/mana_curve_widget.cpp b/cockatrice/src/client/ui/widgets/deck_analytics/mana_curve_widget.cpp index 0831ad655..abe1e17de 100644 --- a/cockatrice/src/client/ui/widgets/deck_analytics/mana_curve_widget.cpp +++ b/cockatrice/src/client/ui/widgets/deck_analytics/mana_curve_widget.cpp @@ -7,7 +7,7 @@ #include "../general/display/banner_widget.h" #include "../general/display/bar_widget.h" -#include +#include #include ManaCurveWidget::ManaCurveWidget(QWidget *parent, DeckListModel *_deckListModel) diff --git a/cockatrice/src/client/ui/widgets/deck_analytics/mana_devotion_widget.cpp b/cockatrice/src/client/ui/widgets/deck_analytics/mana_devotion_widget.cpp index 485afc475..5071ebd7d 100644 --- a/cockatrice/src/client/ui/widgets/deck_analytics/mana_devotion_widget.cpp +++ b/cockatrice/src/client/ui/widgets/deck_analytics/mana_devotion_widget.cpp @@ -7,7 +7,7 @@ #include "../general/display/banner_widget.h" #include "../general/display/bar_widget.h" -#include +#include #include #include #include diff --git a/cockatrice/src/client/ui/widgets/deck_analytics/mana_devotion_widget.h b/cockatrice/src/client/ui/widgets/deck_analytics/mana_devotion_widget.h index 551ecd82d..3edaa52ff 100644 --- a/cockatrice/src/client/ui/widgets/deck_analytics/mana_devotion_widget.h +++ b/cockatrice/src/client/ui/widgets/deck_analytics/mana_devotion_widget.h @@ -6,7 +6,7 @@ #include #include -#include +#include #include class ManaDevotionWidget : public QWidget diff --git a/cockatrice/src/deck/deck_list_model.h b/cockatrice/src/deck/deck_list_model.h index cb074a55c..dd9101626 100644 --- a/cockatrice/src/deck/deck_list_model.h +++ b/cockatrice/src/deck/deck_list_model.h @@ -2,7 +2,9 @@ #define DECKLISTMODEL_H #include "../game/cards/exact_card.h" -#include "decklist.h" +#include "abstract_deck_list_card_node.h" +#include "deck_list.h" +#include "deck_list_card_node.h" #include #include @@ -12,19 +14,35 @@ class CardDatabase; class QPrinter; class QTextCursor; +/** + * @brief Specifies the criteria used to group cards in the DeckListModel. + */ enum DeckListModelGroupCriteria { - MAIN_TYPE, - MANA_COST, - COLOR + MAIN_TYPE, /**< Group cards by their main type (e.g., creature, instant). */ + MANA_COST, /**< Group cards by their mana cost. */ + COLOR /**< Group cards by their color identity. */ }; +/** + * @brief Adapter node that wraps a DecklistCardNode for use in the DeckListModel tree. + * + * This class forwards all property accessors (name, number, provider ID, set info, etc.) + * to the underlying DecklistCardNode. It exists so the model can represent cards + * in the same hierarchy as InnerDecklistNode containers. + */ class DecklistModelCardNode : public AbstractDecklistCardNode { private: - DecklistCardNode *dataNode; + DecklistCardNode *dataNode; /**< Pointer to the underlying data node. */ public: + /** + * @brief Constructs a model node wrapping a DecklistCardNode. + * @param _dataNode The underlying DecklistCardNode to wrap. + * @param _parent The parent InnerDecklistNode in the model tree. + * @param position Optional position to insert in parent (-1 appends at end). + */ DecklistModelCardNode(DecklistCardNode *_dataNode, InnerDecklistNode *_parent, int position = -1) : AbstractDecklistCardNode(_parent, position), dataNode(_dataNode) { @@ -69,6 +87,11 @@ public: { dataNode->setCardCollectorNumber(_cardSetNumber); } + + /** + * @brief Returns the underlying data node. + * @return Pointer to the DecklistCardNode wrapped by this node. + */ DecklistCardNode *getDataNode() const { return dataNode; @@ -79,24 +102,68 @@ public: } }; +/** + * @brief Qt model representing a decklist for use in views (tree/table). + * + * DeckListModel is a QAbstractItemModel that exposes the structure of a deck + * (zones and cards) to Qt views. It organizes cards hierarchically under + * InnerDecklistNode containers and supports grouping, sorting, adding/removing + * cards, and printing decklists. + * + * Signals: + * - deckHashChanged(): emitted when the deck contents change in a way that + * affects its hash. + * + * Slots: + * - rebuildTree(): rebuilds the model structure from the underlying DeckLoader. + * - printDeckList(): renders the decklist to a QPrinter. + */ class DeckListModel : public QAbstractItemModel { Q_OBJECT private slots: + /** + * @brief Rebuilds the model tree from the underlying DeckLoader. + * + * This updates all indices and ensures the model reflects the current + * state of the deck. + */ void rebuildTree(); + public slots: + /** + * @brief Prints the decklist to the provided QPrinter. + * @param printer The printer to render the decklist to. + */ void printDeckList(QPrinter *printer); + signals: + /** + * @brief Emitted whenever the deck hash changes due to modifications in the model. + */ void deckHashChanged(); public: explicit DeckListModel(QObject *parent = nullptr); ~DeckListModel() override; + + /** + * @brief Returns the root index of the model. + * @return QModelIndex representing the root node. + */ QModelIndex getRoot() const { return nodeToIndex(root); }; + + /** + * @brief Returns the value of the grouping category for a card based on the current criteria. + * @param info Pointer to card information. + * @return String representing the value of the current grouping criteria for the card. + */ QString getGroupCriteriaForCard(CardInfoPtr info) const; + + // Qt model overrides int rowCount(const QModelIndex &parent) const override; int columnCount(const QModelIndex & /*parent*/ = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role) const override; @@ -106,31 +173,75 @@ public: Qt::ItemFlags flags(const QModelIndex &index) const override; bool setData(const QModelIndex &index, const QVariant &value, int role) override; bool removeRows(int row, int count, const QModelIndex &parent) override; + + /** + * @brief Finds a card by name, zone, and optional identifiers. + * @param cardName The card's name. + * @param zoneName The zone to search in (main/side/etc.). + * @param providerId Optional provider-specific ID. + * @param cardNumber Optional collector number. + * @return QModelIndex of the card, or invalid index if not found. + */ QModelIndex findCard(const QString &cardName, const QString &zoneName, const QString &providerId = "", const QString &cardNumber = "") const; + + /** + * @brief Adds a card using the preferred printing if available. + * + * @param cardName Name of the card to add. + * @param zoneName Zone to insert the card into. + * @param abAddAnyway Whether to add the card even if resolution fails. + * @return QModelIndex pointing to the newly inserted card node. + */ QModelIndex addPreferredPrintingCard(const QString &cardName, const QString &zoneName, bool abAddAnyway); + + /** + * @brief Adds an ExactCard to the specified zone. + * @param card The card to add. + * @param zoneName The zone to insert the card into. + * @return QModelIndex pointing to the newly inserted card node. + */ QModelIndex addCard(const ExactCard &card, const QString &zoneName); + + /** + * @brief Determines the sorted insertion row for a card. + * @param parent The parent node where the card will be inserted. + * @param cardInfo The card info to insert. + * @return Row index where the card should be inserted to maintain sort order. + */ int findSortedInsertRow(InnerDecklistNode *parent, CardInfoPtr cardInfo) const; + void sort(int column, Qt::SortOrder order) override; + + /** + * @brief Removes all cards and resets the model. + */ void cleanList(); DeckLoader *getDeckList() const { return deckList; } void setDeckList(DeckLoader *_deck); + QList getCards() const; QList getCardsForZone(const QString &zoneName) const; QList *getZones() const; + + /** + * @brief Sets the criteria used to group cards in the model. + * @param newCriteria The new grouping criteria. + */ void setActiveGroupCriteria(DeckListModelGroupCriteria newCriteria); private: - DeckLoader *deckList; - InnerDecklistNode *root; + DeckLoader *deckList; /**< Pointer to the deck loader providing the underlying data. */ + InnerDecklistNode *root; /**< Root node of the model tree. */ DeckListModelGroupCriteria activeGroupCriteria = DeckListModelGroupCriteria::MAIN_TYPE; - int lastKnownColumn; - Qt::SortOrder lastKnownOrder; + int lastKnownColumn; /**< Last column used for sorting. */ + Qt::SortOrder lastKnownOrder; /**< Last known sort order. */ + InnerDecklistNode *createNodeIfNeeded(const QString &name, InnerDecklistNode *parent); QModelIndex nodeToIndex(AbstractDecklistNode *node) const; DecklistModelCardNode *findCardNode(const QString &cardName, diff --git a/cockatrice/src/deck/deck_loader.cpp b/cockatrice/src/deck/deck_loader.cpp index eef8461bc..8eea89a63 100644 --- a/cockatrice/src/deck/deck_loader.cpp +++ b/cockatrice/src/deck/deck_loader.cpp @@ -3,7 +3,8 @@ #include "../game/cards/card_database.h" #include "../game/cards/card_database_manager.h" #include "../main.h" -#include "decklist.h" +#include "deck_list.h" +#include "deck_list_card_node.h" #include #include diff --git a/cockatrice/src/deck/deck_loader.h b/cockatrice/src/deck/deck_loader.h index cf83f24fb..16e14f3d2 100644 --- a/cockatrice/src/deck/deck_loader.h +++ b/cockatrice/src/deck/deck_loader.h @@ -1,7 +1,7 @@ #ifndef DECK_LOADER_H #define DECK_LOADER_H -#include "decklist.h" +#include "deck_list.h" #include diff --git a/cockatrice/src/deck/deck_stats_interface.cpp b/cockatrice/src/deck/deck_stats_interface.cpp index e95785fd6..389ec9a68 100644 --- a/cockatrice/src/deck/deck_stats_interface.cpp +++ b/cockatrice/src/deck/deck_stats_interface.cpp @@ -1,6 +1,7 @@ #include "deck_stats_interface.h" -#include "decklist.h" +#include "deck_list.h" +#include "deck_list_card_node.h" #include #include diff --git a/cockatrice/src/deck/deck_stats_interface.h b/cockatrice/src/deck/deck_stats_interface.h index c3611df81..4704b143e 100644 --- a/cockatrice/src/deck/deck_stats_interface.h +++ b/cockatrice/src/deck/deck_stats_interface.h @@ -2,7 +2,7 @@ #define DECKSTATS_INTERFACE_H #include "../game/cards/card_database.h" -#include "decklist.h" +#include "deck_list.h" #include diff --git a/cockatrice/src/dialogs/dlg_create_token.cpp b/cockatrice/src/dialogs/dlg_create_token.cpp index 064c77fa1..07d61908b 100644 --- a/cockatrice/src/dialogs/dlg_create_token.cpp +++ b/cockatrice/src/dialogs/dlg_create_token.cpp @@ -5,7 +5,7 @@ #include "../game/cards/card_database_model.h" #include "../main.h" #include "../settings/cache_settings.h" -#include "decklist.h" +#include "deck_list.h" #include "trice_limits.h" #include diff --git a/cockatrice/src/game/deckview/deck_view.cpp b/cockatrice/src/game/deckview/deck_view.cpp index 9be1c556e..afc35e77a 100644 --- a/cockatrice/src/game/deckview/deck_view.cpp +++ b/cockatrice/src/game/deckview/deck_view.cpp @@ -3,7 +3,8 @@ #include "../../client/ui/theme_manager.h" #include "../../game/cards/card_info.h" #include "../../settings/cache_settings.h" -#include "decklist.h" +#include "deck_list.h" +#include "deck_list_card_node.h" #include #include diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index ff84ff5b9..50d136f4f 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -5,11 +5,15 @@ add_subdirectory(pb) set(common_SOURCES + abstract_deck_list_card_node.cpp + abstract_deck_list_node.cpp debug_pb_message.cpp - decklist.cpp + deck_list_card_node.cpp + deck_list.cpp expression.cpp featureset.cpp get_pb_extension.cpp + inner_deck_list_node.cpp passwordhasher.cpp rng_abstract.cpp rng_sfmt.cpp diff --git a/common/abstract_deck_list_card_node.cpp b/common/abstract_deck_list_card_node.cpp new file mode 100644 index 000000000..b8a497c20 --- /dev/null +++ b/common/abstract_deck_list_card_node.cpp @@ -0,0 +1,62 @@ +#include "abstract_deck_list_card_node.h" + +bool AbstractDecklistCardNode::compare(AbstractDecklistNode *other) const +{ + switch (sortMethod) { + case ByNumber: + return compareNumber(other); + case ByName: + return compareName(other); + default: + return false; + } +} + +bool AbstractDecklistCardNode::compareNumber(AbstractDecklistNode *other) const +{ + auto *other2 = dynamic_cast(other); + if (other2) { + int n1 = getNumber(); + int n2 = other2->getNumber(); + return (n1 != n2) ? (n1 > n2) : compareName(other); + } else { + return true; + } +} + +bool AbstractDecklistCardNode::compareName(AbstractDecklistNode *other) const +{ + auto *other2 = dynamic_cast(other); + if (other2) { + return (getName() > other2->getName()); + } else { + return true; + } +} + +bool AbstractDecklistCardNode::readElement(QXmlStreamReader *xml) +{ + while (!xml->atEnd()) { + xml->readNext(); + if (xml->isEndElement() && xml->name().toString() == "card") + return false; + } + return true; +} + +void AbstractDecklistCardNode::writeElement(QXmlStreamWriter *xml) +{ + xml->writeEmptyElement("card"); + xml->writeAttribute("number", QString::number(getNumber())); + xml->writeAttribute("name", getName()); + + if (!getCardSetShortName().isEmpty()) { + xml->writeAttribute("setShortName", getCardSetShortName()); + } + if (!getCardCollectorNumber().isEmpty()) { + xml->writeAttribute("collectorNumber", getCardCollectorNumber()); + } + if (!getCardProviderId().isEmpty()) { + xml->writeAttribute("uuid", getCardProviderId()); + } +} \ No newline at end of file diff --git a/common/abstract_deck_list_card_node.h b/common/abstract_deck_list_card_node.h new file mode 100644 index 000000000..82d334db8 --- /dev/null +++ b/common/abstract_deck_list_card_node.h @@ -0,0 +1,148 @@ +/** + * @file abstract_deck_list_card_node.h + * @brief Defines the AbstractDecklistCardNode base class, which adds + * card-specific behavior on top of AbstractDecklistNode. + * + * This class is the intermediate abstract base between the generic + * AbstractDecklistNode and concrete card entries such as DecklistCardNode + * or DecklistModelCardNode. + */ + +#ifndef COCKATRICE_ABSTRACT_DECK_LIST_CARD_NODE_H +#define COCKATRICE_ABSTRACT_DECK_LIST_CARD_NODE_H + +#include "abstract_deck_list_node.h" + +/** + * @class AbstractDecklistCardNode + * @brief Abstract base class for all deck list nodes that represent + * actual card entries. + * + * While AbstractDecklistNode provides the general interface for all + * nodes in the deck tree (zones, groups, cards), this subclass refines + * the interface to cover properties specific to *cards*: + * - Quantity (number of copies). + * - Name. + * - Set code and collector number. + * - Provider ID. + * + * ### Role in the hierarchy: + * - Leaf-oriented abstract class; no children of its own. + * - Serves as the base for concrete implementations: + * - @c DecklistCardNode: Stores real card data in the deck tree. + * - @c DecklistModelCardNode: Wraps a DecklistCardNode for use + * in the Qt model layer. + * + * ### Responsibilities: + * - Defines getters/setters for all card-identifying attributes. + * - Provides comparison logic for sorting by name or number. + * - Implements XML serialization for saving/loading deck files. + * + * ### Ownership: + * - As with all nodes, owned by its parent InnerDecklistNode. + */ +class AbstractDecklistCardNode : public AbstractDecklistNode +{ +public: + /** + * @brief Construct a new AbstractDecklistCardNode. + * + * @param _parent Optional parent node. If provided, this node + * will be inserted into the parent’s children list. + * @param position Index at which to insert into parent’s children. + * If -1, the node is appended to the end. + */ + explicit AbstractDecklistCardNode(InnerDecklistNode *_parent = nullptr, int position = -1) + : AbstractDecklistNode(_parent, position) + { + } + + /// @return The number of copies of this card in the deck. + virtual int getNumber() const = 0; + + /// @param _number Set the number of copies of this card. + virtual void setNumber(int _number) = 0; + + /// @return The display name of this card. + QString getName() const override = 0; + + /// @param _name Set the display name of this card. + virtual void setName(const QString &_name) = 0; + + /// @return The provider identifier for this card (e.g., UUID). + virtual QString getCardProviderId() const override = 0; + + /// @param _cardProviderId Set the provider identifier for this card. + virtual void setCardProviderId(const QString &_cardProviderId) = 0; + + /// @return The abbreviated set code (e.g., "NEO"). + virtual QString getCardSetShortName() const override = 0; + + /// @param _cardSetShortName Set the abbreviated set code. + virtual void setCardSetShortName(const QString &_cardSetShortName) = 0; + + /// @return The collector number of the card within its set. + virtual QString getCardCollectorNumber() const override = 0; + + /// @param _cardSetNumber Set the collector number. + virtual void setCardCollectorNumber(const QString &_cardSetNumber) = 0; + + /** + * @brief Get the height of this node in the tree. + * + * For card nodes, height is always 0 because they are leaf nodes + * and do not contain children. + * + * @return 0 + */ + int height() const override + { + return 0; + } + + /** + * @brief Compare this card node against another for sorting. + * + * Uses the node’s current @c sortMethod to determine how to compare: + * - ByName: Alphabetical comparison. + * - ByNumber: Numerical comparison. + * - Default: Falls back to implementation-defined behavior. + * + * @param other Another node to compare against. + * @return true if this node should sort before @p other. + */ + bool compare(AbstractDecklistNode *other) const override; + + /** + * @brief Compare this card node to another by quantity. + * @param other Node to compare against. + * @return true if this node’s number < other’s number. + */ + bool compareNumber(AbstractDecklistNode *other) const; + + /** + * @brief Compare this card node to another by name. + * @param other Node to compare against. + * @return true if this node’s name comes before other’s name. + */ + bool compareName(AbstractDecklistNode *other) const; + + /** + * @brief Deserialize this node’s properties from XML. + * @param xml QXmlStreamReader positioned at the element. + * @return true if parsing succeeded. + * + * This supports loading deck files from Cockatrice’s XML format. + */ + bool readElement(QXmlStreamReader *xml) override; + + /** + * @brief Serialize this node’s properties to XML. + * @param xml Writer to append this node’s XML element. + * + * This supports saving deck files to Cockatrice’s XML format. + */ + void writeElement(QXmlStreamWriter *xml) override; +}; + +#endif // COCKATRICE_ABSTRACT_DECK_LIST_CARD_NODE_H diff --git a/common/abstract_deck_list_node.cpp b/common/abstract_deck_list_node.cpp new file mode 100644 index 000000000..0f39ce71a --- /dev/null +++ b/common/abstract_deck_list_node.cpp @@ -0,0 +1,24 @@ +#include "abstract_deck_list_node.h" + +#include "inner_deck_list_node.h" + +AbstractDecklistNode::AbstractDecklistNode(InnerDecklistNode *_parent, int position) + : parent(_parent), sortMethod(Default) +{ + if (parent) { + if (position == -1) { + parent->append(this); + } else { + parent->insert(position, this); + } + } +} + +int AbstractDecklistNode::depth() const +{ + if (parent) { + return parent->depth() + 1; + } else { + return 0; + } +} \ No newline at end of file diff --git a/common/abstract_deck_list_node.h b/common/abstract_deck_list_node.h new file mode 100644 index 000000000..6dcc2c7d6 --- /dev/null +++ b/common/abstract_deck_list_node.h @@ -0,0 +1,184 @@ +/** + * @file abstract_deck_list_node.h + * @brief Defines the AbstractDecklistNode base class used as the foundation + * for all nodes in the deck list tree (zones, groups, and cards). + * + * The deck list is modeled as a tree: + * - The invisible root node is managed by DeckListModel. + * - Top-level children are zones (e.g. Mainboard, Sideboard). + * - Zones contain grouping nodes (e.g. by type, color, or mana cost). + * - Grouping nodes contain card nodes. + * + * This abstract base class provides the interface and shared functionality + * for all node types. Concrete subclasses (InnerDecklistNode, + * DecklistCardNode, DecklistModelCardNode, etc.) implement the specifics. + */ + +#ifndef COCKATRICE_ABSTRACT_DECK_LIST_NODE_H +#define COCKATRICE_ABSTRACT_DECK_LIST_NODE_H + +#include +#include + +/** + * @enum DeckSortMethod + * @brief Defines the different sort strategies a node may use + * to order its children. + * + * Sorting behavior is typically set by the DeckListModel when the user + * requests sorting in the UI. + * + * - ByNumber: Sort numerically (often by collector number). + * - ByName: Sort alphabetically by card name. + * - Default: No explicit sorting; insertion order is preserved. + */ +enum DeckSortMethod +{ + ByNumber, ///< Sort by numeric properties (e.g. collector number). + ByName, ///< Sort by card name (locale-aware comparison). + Default ///< Leave in insertion order. +}; + +class InnerDecklistNode; + +/** + * @class AbstractDecklistNode + * @brief Base class for all nodes in the deck list tree. + * + * This class defines the common interface for every node in the + * deck representation: zones, groupings, and cards. + * + * Responsibilities: + * - Maintain a pointer to its parent (if any). + * - Track the sorting method to be used for child nodes. + * - Provide a consistent interface for retrieving basic identifying + * properties (name, set, collector number, provider ID). + * - Define abstract methods for XML serialization, used when saving + * or loading deck files. + * + * Lifetime / Ownership: + * - Nodes are arranged hierarchically under @c InnerDecklistNode parents. + * - The parent takes ownership of its children; destruction cascades. + * - The DeckListModel holds the invisible root node, which in turn + * owns the entire hierarchy. + * + * Extension: + * - @c InnerDecklistNode is the concrete subclass representing + * "folders" in the tree (zones, groups). + * - @c DecklistCardNode and @c DecklistModelCardNode represent + * actual card entries. + */ +class AbstractDecklistNode +{ +protected: + /** + * @brief Pointer to the parent node, or nullptr if this is the root. + * + * Ownership note: The parent is responsible for destroying this node + * when it is removed from the tree. + */ + InnerDecklistNode *parent; + + /** + * @brief Current sorting strategy for this node's children. + * + * Sorting is applied recursively by the DeckListModel when + * the view requests it. + */ + DeckSortMethod sortMethod; + +public: + /** + * @brief Construct a new AbstractDecklistNode and insert it into its parent. + * + * @param _parent Parent node. May be nullptr if this is the root. + * @param position Optional index at which to insert into the parent's + * children. If -1, the node is appended to the end. + * + * If a parent is provided, the constructor automatically appends + * or inserts this node into the parent’s child list. + */ + explicit AbstractDecklistNode(InnerDecklistNode *_parent = nullptr, int position = -1); + + /// Virtual destructor. Child classes must clean up their resources. + virtual ~AbstractDecklistNode() = default; + + /** + * @brief Set the sort method for this node’s children. + * @param method The sorting strategy to use. + * + * Subclasses may override if they need to apply additional logic. + */ + virtual void setSortMethod(DeckSortMethod method) + { + sortMethod = method; + } + + /** + * @name Core identification properties + * + * These methods provide a standard way for the model to retrieve + * identifying information about a node, regardless of type. + * @{ + */ + virtual QString getName() const = 0; + virtual QString getCardProviderId() const = 0; + virtual QString getCardSetShortName() const = 0; + virtual QString getCardCollectorNumber() const = 0; + /// @} + + /** + * @brief Whether this node is the "deck header" (deck metadata). + * + * This distinguishes special nodes that represent deck-level + * information rather than cards or groupings. + */ + [[nodiscard]] virtual bool isDeckHeader() const = 0; + + /// @return The parent node, or nullptr if this is the root. + InnerDecklistNode *getParent() const + { + return parent; + } + + /** + * @brief Compute the depth of this node in the tree. + * @return Distance from the root (root = 0, children = 1, etc.). + */ + int depth() const; + + /** + * @brief Compute the "height" of this node. + * + * Height is defined by subclasses; it usually represents how + * many levels of descendants this node spans. + * + * For example: + * - A card node has height 1. + * - A group node containing cards has height 2. + */ + virtual int height() const = 0; + + /** + * @brief Compare this node against another for sorting. + * + * The semantics of comparison depend on the node type and the + * current @c sortMethod. + * + * @param other The node to compare against. + * @return true if this node should come before @p other. + */ + virtual bool compare(AbstractDecklistNode *other) const = 0; + + /** + * @name XML serialization + * These methods support reading and writing decks from/to + * Cockatrice deck XML format. + * @{ + */ + virtual bool readElement(QXmlStreamReader *xml) = 0; + virtual void writeElement(QXmlStreamWriter *xml) = 0; + /// @} +}; + +#endif // COCKATRICE_ABSTRACT_DECK_LIST_NODE_H diff --git a/common/decklist.cpp b/common/deck_list.cpp similarity index 74% rename from common/decklist.cpp rename to common/deck_list.cpp index d040914c5..b2fbdb028 100644 --- a/common/decklist.cpp +++ b/common/deck_list.cpp @@ -1,4 +1,8 @@ -#include "decklist.h" +#include "deck_list.h" + +#include "abstract_deck_list_node.h" +#include "deck_list_card_node.h" +#include "inner_deck_list_node.h" #include #include @@ -71,291 +75,6 @@ void SideboardPlan::write(QXmlStreamWriter *xml) xml->writeEndElement(); } -AbstractDecklistNode::AbstractDecklistNode(InnerDecklistNode *_parent, int position) - : parent(_parent), sortMethod(Default) -{ - if (parent) { - if (position == -1) { - parent->append(this); - } else { - parent->insert(position, this); - } - } -} - -int AbstractDecklistNode::depth() const -{ - if (parent) { - return parent->depth() + 1; - } else { - return 0; - } -} - -InnerDecklistNode::InnerDecklistNode(InnerDecklistNode *other, InnerDecklistNode *_parent) - : AbstractDecklistNode(_parent), name(other->getName()) -{ - for (int i = 0; i < other->size(); ++i) { - auto *inner = dynamic_cast(other->at(i)); - if (inner) { - new InnerDecklistNode(inner, this); - } else { - new DecklistCardNode(dynamic_cast(other->at(i)), this); - } - } -} - -InnerDecklistNode::~InnerDecklistNode() -{ - clearTree(); -} - -QString InnerDecklistNode::visibleNameFromName(const QString &_name) -{ - if (_name == DECK_ZONE_MAIN) { - return QObject::tr("Maindeck"); - } else if (_name == DECK_ZONE_SIDE) { - return QObject::tr("Sideboard"); - } else if (_name == DECK_ZONE_TOKENS) { - return QObject::tr("Tokens"); - } else { - return _name; - } -} - -void InnerDecklistNode::setSortMethod(DeckSortMethod method) -{ - sortMethod = method; - for (int i = 0; i < size(); i++) { - at(i)->setSortMethod(method); - } -} - -QString InnerDecklistNode::getVisibleName() const -{ - return visibleNameFromName(name); -} - -void InnerDecklistNode::clearTree() -{ - for (int i = 0; i < size(); i++) - delete at(i); - clear(); -} - -DecklistCardNode::DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent) - : AbstractDecklistCardNode(_parent), name(other->getName()), number(other->getNumber()), - cardSetShortName(other->getCardSetShortName()), cardSetNumber(other->getCardCollectorNumber()), - cardProviderId(other->getCardProviderId()) -{ -} - -AbstractDecklistNode *InnerDecklistNode::findChild(const QString &_name) -{ - for (int i = 0; i < size(); i++) { - if (at(i)->getName() == _name) { - return at(i); - } - } - return nullptr; -} - -AbstractDecklistNode *InnerDecklistNode::findCardChildByNameProviderIdAndNumber(const QString &_name, - const QString &_providerId, - const QString &_cardNumber) -{ - for (const auto &i : *this) { - if (!i || i->getName() != _name) { - continue; - } - if (_cardNumber != "" && i->getCardCollectorNumber() != _cardNumber) { - continue; - } - if (_providerId != "" && i->getCardProviderId() != _providerId) { - continue; - } - return i; - } - return nullptr; -} - -int InnerDecklistNode::height() const -{ - return at(0)->height() + 1; -} - -int InnerDecklistNode::recursiveCount(bool countTotalCards) const -{ - int result = 0; - for (int i = 0; i < size(); i++) { - auto *node = dynamic_cast(at(i)); - - if (node) { - result += node->recursiveCount(countTotalCards); - } else if (countTotalCards) { - result += dynamic_cast(at(i))->getNumber(); - } else { - result++; - } - } - return result; -} - -bool InnerDecklistNode::compare(AbstractDecklistNode *other) const -{ - switch (sortMethod) { - case ByNumber: - return compareNumber(other); - case ByName: - return compareName(other); - default: - return false; - } -} - -bool InnerDecklistNode::compareNumber(AbstractDecklistNode *other) const -{ - auto *other2 = dynamic_cast(other); - if (other2) { - int n1 = recursiveCount(true); - int n2 = other2->recursiveCount(true); - return (n1 != n2) ? (n1 > n2) : compareName(other); - } else { - return false; - } -} - -bool InnerDecklistNode::compareName(AbstractDecklistNode *other) const -{ - auto *other2 = dynamic_cast(other); - if (other2) { - return (getName() > other2->getName()); - } else { - return false; - } -} - -bool AbstractDecklistCardNode::compare(AbstractDecklistNode *other) const -{ - switch (sortMethod) { - case ByNumber: - return compareNumber(other); - case ByName: - return compareName(other); - default: - return false; - } -} - -bool AbstractDecklistCardNode::compareNumber(AbstractDecklistNode *other) const -{ - auto *other2 = dynamic_cast(other); - if (other2) { - int n1 = getNumber(); - int n2 = other2->getNumber(); - return (n1 != n2) ? (n1 > n2) : compareName(other); - } else { - return true; - } -} - -bool AbstractDecklistCardNode::compareName(AbstractDecklistNode *other) const -{ - auto *other2 = dynamic_cast(other); - if (other2) { - return (getName() > other2->getName()); - } else { - return true; - } -} - -bool InnerDecklistNode::readElement(QXmlStreamReader *xml) -{ - while (!xml->atEnd()) { - xml->readNext(); - const QString childName = xml->name().toString(); - if (xml->isStartElement()) { - if (childName == "zone") { - InnerDecklistNode *newZone = new InnerDecklistNode(xml->attributes().value("name").toString(), this); - newZone->readElement(xml); - } else if (childName == "card") { - DecklistCardNode *newCard = new DecklistCardNode( - xml->attributes().value("name").toString(), xml->attributes().value("number").toString().toInt(), - this, -1, xml->attributes().value("setShortName").toString(), - xml->attributes().value("collectorNumber").toString(), xml->attributes().value("uuid").toString()); - newCard->readElement(xml); - } - } else if (xml->isEndElement() && (childName == "zone")) - return false; - } - return true; -} - -void InnerDecklistNode::writeElement(QXmlStreamWriter *xml) -{ - xml->writeStartElement("zone"); - xml->writeAttribute("name", name); - for (int i = 0; i < size(); i++) - at(i)->writeElement(xml); - xml->writeEndElement(); // zone -} - -bool AbstractDecklistCardNode::readElement(QXmlStreamReader *xml) -{ - while (!xml->atEnd()) { - xml->readNext(); - if (xml->isEndElement() && xml->name().toString() == "card") - return false; - } - return true; -} - -void AbstractDecklistCardNode::writeElement(QXmlStreamWriter *xml) -{ - xml->writeEmptyElement("card"); - xml->writeAttribute("number", QString::number(getNumber())); - xml->writeAttribute("name", getName()); - - if (!getCardSetShortName().isEmpty()) { - xml->writeAttribute("setShortName", getCardSetShortName()); - } - if (!getCardCollectorNumber().isEmpty()) { - xml->writeAttribute("collectorNumber", getCardCollectorNumber()); - } - if (!getCardProviderId().isEmpty()) { - xml->writeAttribute("uuid", getCardProviderId()); - } -} - -QVector> InnerDecklistNode::sort(Qt::SortOrder order) -{ - QVector> result(size()); - - // Initialize temporary list with contents of current list - QVector> tempList(size()); - for (int i = size() - 1; i >= 0; --i) { - tempList[i].first = i; - tempList[i].second = at(i); - } - - // Sort temporary list - auto cmp = [order](const auto &a, const auto &b) { - return (order == Qt::AscendingOrder) ? (b.second->compare(a.second)) : (a.second->compare(b.second)); - }; - - std::sort(tempList.begin(), tempList.end(), cmp); - - // Map old indexes to new indexes and - // copy temporary list to the current one - for (int i = size() - 1; i >= 0; --i) { - result[i].first = tempList[i].first; - result[i].second = i; - replace(i, tempList[i].second); - } - - return result; -} - DeckList::DeckList() { root = new InnerDecklistNode; diff --git a/common/deck_list.h b/common/deck_list.h new file mode 100644 index 000000000..87c826e09 --- /dev/null +++ b/common/deck_list.h @@ -0,0 +1,313 @@ +/** + * @file decklist.h + * @brief Defines the DeckList class and supporting types for managing a full + * deck structure including cards, zones, sideboard plans, and + * serialization to/from multiple formats. This is a logic class which + * does not care about Qt or user facing views. + * See @c DeckListModel for the actual Qt Model to be used for views + */ + +#ifndef DECKLIST_H +#define DECKLIST_H + +#include "card_ref.h" +#include "inner_deck_list_node.h" + +#include +#include +#include +#include +#include + +class AbstractDecklistNode; +class DecklistCardNode; +class CardDatabase; +class QIODevice; +class QTextStream; +class InnerDecklistNode; + +/** + * @class SideboardPlan + * @brief Represents a predefined sideboarding strategy for a deck. + * + * Sideboard plans store a named list of card movements that should be applied + * between the mainboard and sideboard for a specific matchup. Each movement + * is expressed using a `MoveCard_ToZone` protobuf message. + * + * ### Responsibilities: + * - Store the plan name and list of moves. + * - Support XML serialization/deserialization. + * + * ### Typical usage: + * A deck can contain multiple sideboard plans (e.g., "vs Aggro", "vs Control"), + * each describing how to transform the main deck into its intended configuration. + */ +class SideboardPlan +{ +private: + QString name; ///< Human-readable name of this plan. + QList moveList; ///< List of move instructions for this plan. + +public: + /** + * @brief Construct a new SideboardPlan. + * @param _name The plan name. + * @param _moveList Initial list of card move instructions. + */ + explicit SideboardPlan(const QString &_name = QString(), + const QList &_moveList = QList()); + + /** + * @brief Read a SideboardPlan from an XML stream. + * @param xml XML reader positioned at the plan element. + * @return true if parsing succeeded. + */ + bool readElement(QXmlStreamReader *xml); + + /** + * @brief Write this SideboardPlan to XML. + * @param xml Stream to append the serialized element to. + */ + void write(QXmlStreamWriter *xml); + + /// @return The plan name. + QString getName() const + { + return name; + } + + /// @return Const reference to the move list. + const QList &getMoveList() const + { + return moveList; + } + + /// @brief Replace the move list with a new one. + void setMoveList(const QList &_moveList); +}; + +/** + * @class DeckList + * @brief Represents a complete deck, including metadata, zones, cards, + * and sideboard plans. + * + * A DeckList is a QObject wrapper around an `InnerDecklistNode` tree, + * enriched with metadata like deck name, comments, tags, banner card, + * and multiple sideboard plans. + * + * ### Core responsibilities: + * - Store and manage the root node tree (zones → groups → cards). + * - Provide deck-level metadata (name, comments, tags, banner). + * - Support multiple sideboard plans (meta-game strategies). + * - Provide import/export in multiple formats: + * - Cockatrice native XML format. + * - Plain-text list format. + * - Provide hashing for deck identity (deck hash). + * + * ### Ownership: + * - Owns the root `InnerDecklistNode` tree. + * - Owns `SideboardPlan` instances stored in `sideboardPlans`. + * + * ### Signals: + * - @c deckHashChanged() — emitted when the deck contents change. + * - @c deckTagsChanged() — emitted when tags are added/removed. + * + * ### Example workflow: + * ``` + * DeckList deck; + * deck.setName("Mono Red Aggro"); + * deck.addCard("Lightning Bolt", "main", -1); + * deck.addTag("Aggro"); + * deck.saveToFile_Native(device); + * ``` + */ +class DeckList : public QObject +{ + Q_OBJECT +private: + QString name; ///< User-defined deck name. + QString comments; ///< Free-form comments or notes. + CardRef bannerCard; ///< Optional representative card for the deck. + QString lastLoadedTimestamp; ///< Timestamp string of last load. + QStringList tags; ///< User-defined tags for deck classification. + QMap sideboardPlans; ///< Named sideboard plans. + InnerDecklistNode *root; ///< Root of the deck tree (zones + cards). + + /** + * @brief Cached deck hash, recalculated lazily. + * An empty string indicates the cache is invalid. + */ + mutable QString cachedDeckHash; + + // Helpers for traversing the tree + static void getCardListHelper(InnerDecklistNode *node, QSet &result); + static void getCardRefListHelper(InnerDecklistNode *item, QList &result); + InnerDecklistNode *getZoneObjFromName(const QString &zoneName); + +protected: + /** + * @brief Map a card name to its zone. + * Override in subclasses for format-specific logic. + * @param cardName Card being placed. + * @param currentZoneName Zone candidate. + * @return Zone name to use. + */ + virtual QString getCardZoneFromName(const QString /*cardName*/, QString currentZoneName) + { + return currentZoneName; + }; + + /** + * @brief Produce the complete display name of a card. + * Override in subclasses to add set suffixes or annotations. + * @param cardName Base name. + * @return Full display name. + */ + virtual QString getCompleteCardName(const QString &cardName) const + { + return cardName; + }; + +signals: + /// Emitted when the deck hash changes. + void deckHashChanged(); + /// Emitted when the deck tags are modified. + void deckTagsChanged(); + +public slots: + /// @name Metadata setters + ///@{ + void setName(const QString &_name = QString()) + { + name = _name; + } + void setComments(const QString &_comments = QString()) + { + comments = _comments; + } + void setTags(const QStringList &_tags = QStringList()) + { + tags = _tags; + emit deckTagsChanged(); + } + void addTag(const QString &_tag) + { + tags.append(_tag); + emit deckTagsChanged(); + } + void clearTags() + { + tags.clear(); + emit deckTagsChanged(); + } + void setBannerCard(const CardRef &_bannerCard = {}) + { + bannerCard = _bannerCard; + } + void setLastLoadedTimestamp(const QString &_lastLoadedTimestamp = QString()) + { + lastLoadedTimestamp = _lastLoadedTimestamp; + } + ///@} + +public: + /// @brief Construct an empty deck. + explicit DeckList(); + /// @brief Deep-copy constructor. + DeckList(const DeckList &other); + /// @brief Construct from a serialized native-format string. + explicit DeckList(const QString &nativeString); + ~DeckList() override; + + /// @name Metadata getters + ///@{ + QString getName() const + { + return name; + } + QString getComments() const + { + return comments; + } + QStringList getTags() const + { + return tags; + } + CardRef getBannerCard() const + { + return bannerCard; + } + QString getLastLoadedTimestamp() const + { + return lastLoadedTimestamp; + } + ///@} + + /// @name Sideboard plans + ///@{ + QList getCurrentSideboardPlan(); + void setCurrentSideboardPlan(const QList &plan); + const QMap &getSideboardPlans() const + { + return sideboardPlans; + } + ///@} + + /// @name Serialization (XML) + ///@{ + bool readElement(QXmlStreamReader *xml); + void write(QXmlStreamWriter *xml) const; + bool loadFromXml(QXmlStreamReader *xml); + bool loadFromString_Native(const QString &nativeString); + QString writeToString_Native() const; + bool loadFromFile_Native(QIODevice *device); + bool saveToFile_Native(QIODevice *device); + ///@} + + /// @name Serialization (Plain text) + ///@{ + bool loadFromStream_Plain(QTextStream &stream, bool preserveMetadata); + bool loadFromFile_Plain(QIODevice *device); + bool saveToStream_Plain(QTextStream &stream, bool prefixSideboardCards, bool slashTappedOutSplitCards); + bool saveToFile_Plain(QIODevice *device, bool prefixSideboardCards = true, bool slashTappedOutSplitCards = false); + QString writeToString_Plain(bool prefixSideboardCards = true, bool slashTappedOutSplitCards = false); + ///@} + + /// @name Deck manipulation + ///@{ + void cleanList(bool preserveMetadata = false); + bool isEmpty() const + { + return root->isEmpty() && name.isEmpty() && comments.isEmpty() && sideboardPlans.isEmpty(); + } + QStringList getCardList() const; + QList getCardRefList() const; + int getSideboardSize() const; + InnerDecklistNode *getRoot() const + { + return root; + } + DecklistCardNode *addCard(const QString &cardName, + const QString &zoneName, + int position, + const QString &cardSetName = QString(), + const QString &cardSetCollectorNumber = QString(), + const QString &cardProviderId = QString()); + bool deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode = nullptr); + ///@} + + /// @name Deck identity + ///@{ + QString getDeckHash() const; + void refreshDeckHash(); + ///@} + + /** + * @brief Apply a function to every card in the deck tree. + * + * @param func Function taking (zone node, card node). + */ + void forEachCard(const std::function &func); +}; + +#endif diff --git a/common/deck_list_card_node.cpp b/common/deck_list_card_node.cpp new file mode 100644 index 000000000..1791c09a6 --- /dev/null +++ b/common/deck_list_card_node.cpp @@ -0,0 +1,8 @@ +#include "deck_list_card_node.h" + +DecklistCardNode::DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent) + : AbstractDecklistCardNode(_parent), name(other->getName()), number(other->getNumber()), + cardSetShortName(other->getCardSetShortName()), cardSetNumber(other->getCardCollectorNumber()), + cardProviderId(other->getCardProviderId()) +{ +} \ No newline at end of file diff --git a/common/deck_list_card_node.h b/common/deck_list_card_node.h new file mode 100644 index 000000000..3ccb8e062 --- /dev/null +++ b/common/deck_list_card_node.h @@ -0,0 +1,169 @@ +/** + * @file deck_list_card_node.h + * @brief Defines the DecklistCardNode class, representing a single card entry + * in the deck list tree. + * + * DecklistCardNode is the concrete data-bearing node that corresponds to + * an individual card entry in a deck. It stores the card’s name, quantity, + * set information, and provider ID. These nodes live inside an + * InnerDecklistNode (e.g., under Mainboard → Group → Card). + */ + +#ifndef COCKATRICE_DECK_LIST_CARD_NODE_H +#define COCKATRICE_DECK_LIST_CARD_NODE_H + +#include "abstract_deck_list_card_node.h" +#include "card_ref.h" + +/** + * @class DecklistCardNode + * @brief Concrete node type representing an actual card entry in the deck. + * + * This class extends AbstractDecklistCardNode to hold all information + * needed to uniquely identify a card printing within the deck. + * + * ### Role in the hierarchy: + * - Child of an InnerDecklistNode (which groups cards by zone or criteria). + * - Leaf node in the deck tree; it does not contain further children. + * + * ### Data stored: + * - @c name: Card’s display name. + * - @c number: Quantity of this card in the deck. + * - @c cardSetShortName: Abbreviation of the set (e.g., "NEO" for Neon Dynasty). + * - @c cardSetNumber: Collector number within the set. + * - @c cardProviderId: External provider identifier (e.g., UUID or MTGJSON ID). + * + * ### Usage: + * - Constructed directly when building a deck list from user input or file. + * - Used by DeckListModel to present cards in Qt views. + * - Convertible to @c CardRef for database lookups or cross-references. + * + * ### Ownership: + * - Owned by its parent InnerDecklistNode. + * - Destroyed automatically when its parent is destroyed. + */ +class DecklistCardNode : public AbstractDecklistCardNode +{ + QString name; ///< Display name of the card. + int number; ///< Quantity of this card in the deck. + QString cardSetShortName; ///< Short set code (e.g., "NEO"). + QString cardSetNumber; ///< Collector number within the set. + QString cardProviderId; ///< External provider identifier (e.g., UUID). + +public: + /** + * @brief Construct a new DecklistCardNode. + * + * @param _name Display name of the card. + * @param _number Quantity of this card (default = 1). + * @param _parent Parent node in the tree (zone or group). May be nullptr. + * @param position Index to insert into parent’s children. -1 = append. + * @param _cardSetShortName Short set code (e.g., "NEO"). + * @param _cardSetNumber Collector number within the set. + * @param _cardProviderId External provider ID (e.g., UUID). + * + * On construction, if a parent is provided, this node is inserted into + * the parent’s children list automatically. + */ + explicit DecklistCardNode(QString _name = QString(), + int _number = 1, + InnerDecklistNode *_parent = nullptr, + int position = -1, + QString _cardSetShortName = QString(), + QString _cardSetNumber = QString(), + QString _cardProviderId = QString()) + : AbstractDecklistCardNode(_parent, position), name(std::move(_name)), number(_number), + cardSetShortName(std::move(_cardSetShortName)), cardSetNumber(std::move(_cardSetNumber)), + cardProviderId(std::move(_cardProviderId)) + { + } + + /** + * @brief Copy constructor with new parent assignment. + * @param other Existing DecklistCardNode to copy. + * @param _parent Parent node for the copy. + * + * Creates a deep copy of the card node’s properties, but attaches + * the new instance to a different parent in the tree. + */ + explicit DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent); + + /// @return The quantity of this card. + int getNumber() const override + { + return number; + } + + /// @param _number Set the quantity of this card. + void setNumber(int _number) override + { + number = _number; + } + + /// @return The display name of this card. + QString getName() const override + { + return name; + } + + /// @param _name Set the display name of this card. + void setName(const QString &_name) override + { + name = _name; + } + + /// @return The provider identifier for this card. + QString getCardProviderId() const override + { + return cardProviderId; + } + + /// @param _providerId Set the provider identifier for this card. + void setCardProviderId(const QString &_providerId) override + { + cardProviderId = _providerId; + } + + /// @return The short set code (e.g., "NEO"). + QString getCardSetShortName() const override + { + return cardSetShortName; + } + + /// @param _cardSetShortName Set the short set code. + void setCardSetShortName(const QString &_cardSetShortName) override + { + cardSetShortName = _cardSetShortName; + } + + /// @return The collector number of this card within its set. + QString getCardCollectorNumber() const override + { + return cardSetNumber; + } + + /// @param _cardSetNumber Set the collector number. + void setCardCollectorNumber(const QString &_cardSetNumber) override + { + cardSetNumber = _cardSetNumber; + } + + /// @return Always false; card nodes are not deck headers. + [[nodiscard]] bool isDeckHeader() const override + { + return false; + } + + /** + * @brief Convert this node to a CardRef. + * + * @return A CardRef with the card’s name and provider ID, suitable + * for database lookups or comparison with other card sources. + */ + CardRef toCardRef() const + { + return {name, cardProviderId}; + } +}; + +#endif // COCKATRICE_DECK_LIST_CARD_NODE_H diff --git a/common/decklist.h b/common/decklist.h deleted file mode 100644 index e5f2753cd..000000000 --- a/common/decklist.h +++ /dev/null @@ -1,380 +0,0 @@ -#ifndef DECKLIST_H -#define DECKLIST_H - -#include "card_ref.h" - -#include -#include - -// Required on Mac. Forward declaration doesn't work. Don't ask why. -#include -#include -#include - -class CardDatabase; -class QIODevice; -class QTextStream; - -class InnerDecklistNode; - -#define DECK_ZONE_MAIN "main" -#define DECK_ZONE_SIDE "side" -#define DECK_ZONE_TOKENS "tokens" - -class SideboardPlan -{ -private: - QString name; - QList moveList; - -public: - explicit SideboardPlan(const QString &_name = QString(), - const QList &_moveList = QList()); - bool readElement(QXmlStreamReader *xml); - void write(QXmlStreamWriter *xml); - - QString getName() const - { - return name; - } - const QList &getMoveList() const - { - return moveList; - } - void setMoveList(const QList &_moveList); -}; - -enum DeckSortMethod -{ - ByNumber, - ByName, - Default -}; - -class AbstractDecklistNode -{ -protected: - InnerDecklistNode *parent; - DeckSortMethod sortMethod; - -public: - explicit AbstractDecklistNode(InnerDecklistNode *_parent = nullptr, int position = -1); - virtual ~AbstractDecklistNode() = default; - virtual void setSortMethod(DeckSortMethod method) - { - sortMethod = method; - } - virtual QString getName() const = 0; - virtual QString getCardProviderId() const = 0; - virtual QString getCardSetShortName() const = 0; - virtual QString getCardCollectorNumber() const = 0; - [[nodiscard]] virtual bool isDeckHeader() const = 0; - InnerDecklistNode *getParent() const - { - return parent; - } - int depth() const; - virtual int height() const = 0; - virtual bool compare(AbstractDecklistNode *other) const = 0; - - virtual bool readElement(QXmlStreamReader *xml) = 0; - virtual void writeElement(QXmlStreamWriter *xml) = 0; -}; - -class InnerDecklistNode : public AbstractDecklistNode, public QList -{ - QString name; - -public: - explicit InnerDecklistNode(QString _name = QString(), InnerDecklistNode *_parent = nullptr, int position = -1) - : AbstractDecklistNode(_parent, position), name(std::move(_name)) - { - } - explicit InnerDecklistNode(InnerDecklistNode *other, InnerDecklistNode *_parent = nullptr); - ~InnerDecklistNode() override; - void setSortMethod(DeckSortMethod method) override; - [[nodiscard]] QString getName() const override - { - return name; - } - void setName(const QString &_name) - { - name = _name; - } - static QString visibleNameFromName(const QString &_name); - [[nodiscard]] virtual QString getVisibleName() const; - [[nodiscard]] QString getCardProviderId() const override - { - return ""; - } - [[nodiscard]] QString getCardSetShortName() const override - { - return ""; - } - [[nodiscard]] QString getCardCollectorNumber() const override - { - return ""; - } - [[nodiscard]] bool isDeckHeader() const override - { - return true; - } - - void clearTree(); - AbstractDecklistNode *findChild(const QString &_name); - AbstractDecklistNode *findCardChildByNameProviderIdAndNumber(const QString &_name, - const QString &_providerId = "", - const QString &_cardNumber = ""); - int height() const override; - int recursiveCount(bool countTotalCards = false) const; - bool compare(AbstractDecklistNode *other) const override; - bool compareNumber(AbstractDecklistNode *other) const; - bool compareName(AbstractDecklistNode *other) const; - QVector> sort(Qt::SortOrder order = Qt::AscendingOrder); - - bool readElement(QXmlStreamReader *xml) override; - void writeElement(QXmlStreamWriter *xml) override; -}; - -class AbstractDecklistCardNode : public AbstractDecklistNode -{ -public: - explicit AbstractDecklistCardNode(InnerDecklistNode *_parent = nullptr, int position = -1) - : AbstractDecklistNode(_parent, position) - { - } - virtual int getNumber() const = 0; - virtual void setNumber(int _number) = 0; - QString getName() const override = 0; - virtual void setName(const QString &_name) = 0; - virtual QString getCardProviderId() const override = 0; - virtual void setCardProviderId(const QString &_cardProviderId) = 0; - virtual QString getCardSetShortName() const override = 0; - virtual void setCardSetShortName(const QString &_cardSetShortName) = 0; - virtual QString getCardCollectorNumber() const override = 0; - virtual void setCardCollectorNumber(const QString &_cardSetNumber) = 0; - int height() const override - { - return 0; - } - bool compare(AbstractDecklistNode *other) const override; - bool compareNumber(AbstractDecklistNode *other) const; - bool compareName(AbstractDecklistNode *other) const; - - bool readElement(QXmlStreamReader *xml) override; - void writeElement(QXmlStreamWriter *xml) override; -}; - -class DecklistCardNode : public AbstractDecklistCardNode -{ - QString name; - int number; - QString cardSetShortName; - QString cardSetNumber; - QString cardProviderId; - -public: - explicit DecklistCardNode(QString _name = QString(), - int _number = 1, - InnerDecklistNode *_parent = nullptr, - int position = -1, - QString _cardSetShortName = QString(), - QString _cardSetNumber = QString(), - QString _cardProviderId = QString()) - : AbstractDecklistCardNode(_parent, position), name(std::move(_name)), number(_number), - cardSetShortName(std::move(_cardSetShortName)), cardSetNumber(std::move(_cardSetNumber)), - cardProviderId(std::move(_cardProviderId)) - { - } - explicit DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent); - int getNumber() const override - { - return number; - } - void setNumber(int _number) override - { - number = _number; - } - QString getName() const override - { - return name; - } - void setName(const QString &_name) override - { - name = _name; - } - QString getCardProviderId() const override - { - return cardProviderId; - } - void setCardProviderId(const QString &_providerId) override - { - cardProviderId = _providerId; - } - - QString getCardSetShortName() const override - { - return cardSetShortName; - } - void setCardSetShortName(const QString &_cardSetShortName) override - { - cardSetShortName = _cardSetShortName; - } - QString getCardCollectorNumber() const override - { - return cardSetNumber; - } - void setCardCollectorNumber(const QString &_cardSetNumber) override - { - cardSetNumber = _cardSetNumber; - } - [[nodiscard]] bool isDeckHeader() const override - { - return false; - } - CardRef toCardRef() const - { - return {name, cardProviderId}; - } -}; - -class DeckList : public QObject -{ - Q_OBJECT -private: - QString name, comments; - CardRef bannerCard; - QString lastLoadedTimestamp; - QStringList tags; - QMap sideboardPlans; - InnerDecklistNode *root; - static void getCardListHelper(InnerDecklistNode *node, QSet &result); - static void getCardRefListHelper(InnerDecklistNode *item, QList &result); - InnerDecklistNode *getZoneObjFromName(const QString &zoneName); - - /** - * Empty string indicates invalidated cache. - */ - mutable QString cachedDeckHash; - -protected: - virtual QString getCardZoneFromName(const QString /*cardName*/, QString currentZoneName) - { - return currentZoneName; - }; - virtual QString getCompleteCardName(const QString &cardName) const - { - return cardName; - }; - -signals: - void deckHashChanged(); - void deckTagsChanged(); - -public slots: - void setName(const QString &_name = QString()) - { - name = _name; - } - void setComments(const QString &_comments = QString()) - { - comments = _comments; - } - void setTags(const QStringList &_tags = QStringList()) - { - tags = _tags; - emit deckTagsChanged(); - } - void addTag(const QString &_tag) - { - tags.append(_tag); - emit deckTagsChanged(); - } - void clearTags() - { - tags.clear(); - emit deckTagsChanged(); - } - void setBannerCard(const CardRef &_bannerCard = {}) - { - bannerCard = _bannerCard; - } - void setLastLoadedTimestamp(const QString &_lastLoadedTimestamp = QString()) - { - lastLoadedTimestamp = _lastLoadedTimestamp; - } - -public: - explicit DeckList(); - DeckList(const DeckList &other); - explicit DeckList(const QString &nativeString); - ~DeckList() override; - QString getName() const - { - return name; - } - QString getComments() const - { - return comments; - } - QStringList getTags() const - { - return tags; - } - CardRef getBannerCard() const - { - return bannerCard; - } - QString getLastLoadedTimestamp() const - { - return lastLoadedTimestamp; - } - QList getCurrentSideboardPlan(); - void setCurrentSideboardPlan(const QList &plan); - const QMap &getSideboardPlans() const - { - return sideboardPlans; - } - - bool readElement(QXmlStreamReader *xml); - void write(QXmlStreamWriter *xml) const; - bool loadFromXml(QXmlStreamReader *xml); - bool loadFromString_Native(const QString &nativeString); - QString writeToString_Native() const; - bool loadFromFile_Native(QIODevice *device); - bool saveToFile_Native(QIODevice *device); - bool loadFromStream_Plain(QTextStream &stream, bool preserveMetadata); - bool loadFromFile_Plain(QIODevice *device); - bool saveToStream_Plain(QTextStream &stream, bool prefixSideboardCards, bool slashTappedOutSplitCards); - bool saveToFile_Plain(QIODevice *device, bool prefixSideboardCards = true, bool slashTappedOutSplitCards = false); - QString writeToString_Plain(bool prefixSideboardCards = true, bool slashTappedOutSplitCards = false); - - void cleanList(bool preserveMetadata = false); - bool isEmpty() const - { - return root->isEmpty() && name.isEmpty() && comments.isEmpty() && sideboardPlans.isEmpty(); - } - QStringList getCardList() const; - QList getCardRefList() const; - - int getSideboardSize() const; - - InnerDecklistNode *getRoot() const - { - return root; - } - DecklistCardNode *addCard(const QString &cardName, - const QString &zoneName, - int position, - const QString &cardSetName = QString(), - const QString &cardSetCollectorNumber = QString(), - const QString &cardProviderId = QString()); - bool deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode = nullptr); - - QString getDeckHash() const; - void refreshDeckHash(); - - void forEachCard(const std::function &func); -}; - -#endif \ No newline at end of file diff --git a/common/inner_deck_list_node.cpp b/common/inner_deck_list_node.cpp new file mode 100644 index 000000000..c91b3ea14 --- /dev/null +++ b/common/inner_deck_list_node.cpp @@ -0,0 +1,199 @@ +#include "inner_deck_list_node.h" + +#include "deck_list_card_node.h" + +InnerDecklistNode::InnerDecklistNode(InnerDecklistNode *other, InnerDecklistNode *_parent) + : AbstractDecklistNode(_parent), name(other->getName()) +{ + for (int i = 0; i < other->size(); ++i) { + auto *inner = dynamic_cast(other->at(i)); + if (inner) { + new InnerDecklistNode(inner, this); + } else { + new DecklistCardNode(dynamic_cast(other->at(i)), this); + } + } +} + +InnerDecklistNode::~InnerDecklistNode() +{ + clearTree(); +} + +QString InnerDecklistNode::visibleNameFromName(const QString &_name) +{ + if (_name == DECK_ZONE_MAIN) { + return QObject::tr("Maindeck"); + } else if (_name == DECK_ZONE_SIDE) { + return QObject::tr("Sideboard"); + } else if (_name == DECK_ZONE_TOKENS) { + return QObject::tr("Tokens"); + } else { + return _name; + } +} + +void InnerDecklistNode::setSortMethod(DeckSortMethod method) +{ + sortMethod = method; + for (int i = 0; i < size(); i++) { + at(i)->setSortMethod(method); + } +} + +QString InnerDecklistNode::getVisibleName() const +{ + return visibleNameFromName(name); +} + +void InnerDecklistNode::clearTree() +{ + for (int i = 0; i < size(); i++) + delete at(i); + clear(); +} + +AbstractDecklistNode *InnerDecklistNode::findChild(const QString &_name) +{ + for (int i = 0; i < size(); i++) { + if (at(i)->getName() == _name) { + return at(i); + } + } + return nullptr; +} + +AbstractDecklistNode *InnerDecklistNode::findCardChildByNameProviderIdAndNumber(const QString &_name, + const QString &_providerId, + const QString &_cardNumber) +{ + for (const auto &i : *this) { + if (!i || i->getName() != _name) { + continue; + } + if (_cardNumber != "" && i->getCardCollectorNumber() != _cardNumber) { + continue; + } + if (_providerId != "" && i->getCardProviderId() != _providerId) { + continue; + } + return i; + } + return nullptr; +} + +int InnerDecklistNode::height() const +{ + return at(0)->height() + 1; +} + +int InnerDecklistNode::recursiveCount(bool countTotalCards) const +{ + int result = 0; + for (int i = 0; i < size(); i++) { + auto *node = dynamic_cast(at(i)); + + if (node) { + result += node->recursiveCount(countTotalCards); + } else if (countTotalCards) { + result += dynamic_cast(at(i))->getNumber(); + } else { + result++; + } + } + return result; +} + +bool InnerDecklistNode::compare(AbstractDecklistNode *other) const +{ + switch (sortMethod) { + case ByNumber: + return compareNumber(other); + case ByName: + return compareName(other); + default: + return false; + } +} + +bool InnerDecklistNode::compareNumber(AbstractDecklistNode *other) const +{ + auto *other2 = dynamic_cast(other); + if (other2) { + int n1 = recursiveCount(true); + int n2 = other2->recursiveCount(true); + return (n1 != n2) ? (n1 > n2) : compareName(other); + } else { + return false; + } +} + +bool InnerDecklistNode::compareName(AbstractDecklistNode *other) const +{ + auto *other2 = dynamic_cast(other); + if (other2) { + return (getName() > other2->getName()); + } else { + return false; + } +} + +bool InnerDecklistNode::readElement(QXmlStreamReader *xml) +{ + while (!xml->atEnd()) { + xml->readNext(); + const QString childName = xml->name().toString(); + if (xml->isStartElement()) { + if (childName == "zone") { + InnerDecklistNode *newZone = new InnerDecklistNode(xml->attributes().value("name").toString(), this); + newZone->readElement(xml); + } else if (childName == "card") { + DecklistCardNode *newCard = new DecklistCardNode( + xml->attributes().value("name").toString(), xml->attributes().value("number").toString().toInt(), + this, -1, xml->attributes().value("setShortName").toString(), + xml->attributes().value("collectorNumber").toString(), xml->attributes().value("uuid").toString()); + newCard->readElement(xml); + } + } else if (xml->isEndElement() && (childName == "zone")) + return false; + } + return true; +} + +void InnerDecklistNode::writeElement(QXmlStreamWriter *xml) +{ + xml->writeStartElement("zone"); + xml->writeAttribute("name", name); + for (int i = 0; i < size(); i++) + at(i)->writeElement(xml); + xml->writeEndElement(); // zone +} + +QVector> InnerDecklistNode::sort(Qt::SortOrder order) +{ + QVector> result(size()); + + // Initialize temporary list with contents of current list + QVector> tempList(size()); + for (int i = size() - 1; i >= 0; --i) { + tempList[i].first = i; + tempList[i].second = at(i); + } + + // Sort temporary list + auto cmp = [order](const auto &a, const auto &b) { + return (order == Qt::AscendingOrder) ? (b.second->compare(a.second)) : (a.second->compare(b.second)); + }; + + std::sort(tempList.begin(), tempList.end(), cmp); + + // Map old indexes to new indexes and + // copy temporary list to the current one + for (int i = size() - 1; i >= 0; --i) { + result[i].first = tempList[i].first; + result[i].second = i; + replace(i, tempList[i].second); + } + + return result; +} \ No newline at end of file diff --git a/common/inner_deck_list_node.h b/common/inner_deck_list_node.h new file mode 100644 index 000000000..07bb4203f --- /dev/null +++ b/common/inner_deck_list_node.h @@ -0,0 +1,228 @@ +/** + * @file inner_deck_list_node.h + * @brief Defines the InnerDecklistNode class, which represents + * structural nodes (zones and groups) in the deck tree. + * + * The deck tree consists of: + * - A root node (invisible). + * - Zones (Main, Sideboard, Tokens). + * - Optional grouping nodes (e.g., by type, color, or mana cost). + * - Card nodes as leaves. + * + * InnerDecklistNode implements the zone/group nodes and provides + * storage and management of child nodes. + */ + +#ifndef COCKATRICE_INNER_DECK_LIST_NODE_H +#define COCKATRICE_INNER_DECK_LIST_NODE_H + +#include "abstract_deck_list_node.h" + +/// Constant for the "main" deck zone name. +#define DECK_ZONE_MAIN "main" +/// Constant for the "sideboard" zone name. +#define DECK_ZONE_SIDE "side" +/// Constant for the "tokens" zone name. +#define DECK_ZONE_TOKENS "tokens" + +/** + * @class InnerDecklistNode + * @brief Represents a container node in the deck list hierarchy + * (zones and groupings). + * + * Unlike DecklistCardNode, which holds leaf card data, this class + * manages collections of child nodes, which may themselves be + * InnerDecklistNode or DecklistCardNode objects. + * + * ### Role in the hierarchy: + * - Root node (invisible): Holds zones. + * - Zone nodes: "main", "side", "tokens". + * - Grouping nodes: Created dynamically when grouping by type, + * color, or mana cost. + * - Card nodes: Always children of an InnerDecklistNode. + * + * ### Design notes: + * - Inherits from AbstractDecklistNode (tree interface) and + * QList (storage of children). + * This allows direct QList-style manipulation of children while + * still presenting a polymorphic node interface. + * + * ### Responsibilities: + * - Store a display name. + * - Own and manage child nodes (insert, clear, find). + * - Provide recursive operations such as counting cards or computing height. + * - Implement sorting logic for reordering children. + * - Implement XML serialization for persistence. + * + * ### Ownership: + * - Owns all child nodes stored in the QList. The destructor + * recursively deletes children. + */ +class InnerDecklistNode : public AbstractDecklistNode, public QList +{ + QString name; ///< Internal identifier for this node (zone or group name). + +public: + /** + * @brief Construct a new InnerDecklistNode. + * + * @param _name Internal name (e.g., "main", "side", "tokens", or group label). + * @param _parent Parent node (may be nullptr for the root). + * @param position Optional index for insertion into parent. -1 = append. + */ + explicit InnerDecklistNode(QString _name = QString(), InnerDecklistNode *_parent = nullptr, int position = -1) + : AbstractDecklistNode(_parent, position), name(std::move(_name)) + { + } + + /** + * @brief Copy constructor with parent reassignment. + * @param other Node to copy from (deep copy of children). + * @param _parent Parent node for the copy. + */ + explicit InnerDecklistNode(InnerDecklistNode *other, InnerDecklistNode *_parent = nullptr); + + /** + * @brief Destructor. Recursively deletes all child nodes. + */ + ~InnerDecklistNode() override; + + /** + * @brief Set the sorting method for this node and all children. + * @param method Sort method to apply recursively. + */ + void setSortMethod(DeckSortMethod method) override; + + /// @return The internal name of this node. + [[nodiscard]] QString getName() const override + { + return name; + } + + /// @param _name Set the internal name of this node. + void setName(const QString &_name) + { + name = _name; + } + + /** + * @brief Translate an internal name into a user-visible name. + * + * For example, the internal string "main" is presented as + * "Mainboard" in the UI. + * + * @param _name Internal identifier. + * @return Display-friendly string. + */ + static QString visibleNameFromName(const QString &_name); + + /** + * @brief Get this node’s display-friendly name. + * @return Human-readable name (zone/group name). + */ + [[nodiscard]] virtual QString getVisibleName() const; + + /// @return Always empty for container nodes. + [[nodiscard]] QString getCardProviderId() const override + { + return ""; + } + + /// @return Always empty for container nodes. + [[nodiscard]] QString getCardSetShortName() const override + { + return ""; + } + + /// @return Always empty for container nodes. + [[nodiscard]] QString getCardCollectorNumber() const override + { + return ""; + } + + /// @return Always true; InnerDecklistNode represents deck structure. + [[nodiscard]] bool isDeckHeader() const override + { + return true; + } + + /** + * @brief Delete all children of this node, recursively. + */ + void clearTree(); + + /** + * @brief Find a direct child node by name. + * @param _name Name to match. + * @return Pointer to child node, or nullptr if not found. + */ + AbstractDecklistNode *findChild(const QString &_name); + + /** + * @brief Find a child card node by name, provider ID, and collector number. + * + * Searches immediate children only. + * + * @param _name Card name to match. + * @param _providerId Optional provider ID to match. + * @param _cardNumber Optional collector number to match. + * @return Pointer to child node if found, nullptr otherwise. + */ + AbstractDecklistNode *findCardChildByNameProviderIdAndNumber(const QString &_name, + const QString &_providerId = "", + const QString &_cardNumber = ""); + + /** + * @brief Compute the height of this node. + * @return Maximum depth of descendants + 1. + */ + int height() const override; + + /** + * @brief Count cards recursively under this node. + * @param countTotalCards If true, sums up quantities of cards. + * If false, counts unique card nodes. + * @return Total count. + */ + int recursiveCount(bool countTotalCards = false) const; + + /** + * @brief Compare this node against another for sorting. + * + * Uses current @c sortMethod to determine the comparison. + * + * @param other Node to compare. + * @return true if this node should sort before @p other. + */ + bool compare(AbstractDecklistNode *other) const override; + + /// @copydoc compare(AbstractDecklistNode*) const + bool compareNumber(AbstractDecklistNode *other) const; + + /// @copydoc compare(AbstractDecklistNode*) const + bool compareName(AbstractDecklistNode *other) const; + + /** + * @brief Sort this node’s children recursively. + * + * @param order Ascending or descending. + * @return A QVector of (oldIndex, newIndex) pairs indicating + * how children were reordered. + */ + QVector> sort(Qt::SortOrder order = Qt::AscendingOrder); + + /** + * @brief Deserialize this node and its children from XML. + * @param xml Reader positioned at this element. + * @return true if parsing succeeded. + */ + bool readElement(QXmlStreamReader *xml) override; + + /** + * @brief Serialize this node and its children to XML. + * @param xml Writer to append elements to. + */ + void writeElement(QXmlStreamWriter *xml) override; +}; + +#endif // COCKATRICE_INNER_DECK_LIST_NODE_H diff --git a/common/server_game.cpp b/common/server_game.cpp index 95d97f1da..83c39c1ef 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -19,7 +19,7 @@ ***************************************************************************/ #include "server_game.h" -#include "decklist.h" +#include "deck_list.h" #include "pb/context_connection_state_changed.pb.h" #include "pb/context_deck_select.pb.h" #include "pb/context_ping_changed.pb.h" diff --git a/common/server_player.cpp b/common/server_player.cpp index 67c5ef34c..b49f3c0e7 100644 --- a/common/server_player.cpp +++ b/common/server_player.cpp @@ -1,7 +1,8 @@ #include "server_player.h" #include "color.h" -#include "decklist.h" +#include "deck_list.h" +#include "deck_list_card_node.h" #include "get_pb_extension.h" #include "pb/command_attach_card.pb.h" #include "pb/command_change_zone_properties.pb.h" diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 619586dad..99a8f7c41 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -19,7 +19,7 @@ ***************************************************************************/ #include "servatrice.h" -#include "decklist.h" +#include "deck_list.h" #include "email_parser.h" #include "featureset.h" #include "isl_interface.h" diff --git a/servatrice/src/servatrice_database_interface.cpp b/servatrice/src/servatrice_database_interface.cpp index 2a8b9d675..289059846 100644 --- a/servatrice/src/servatrice_database_interface.cpp +++ b/servatrice/src/servatrice_database_interface.cpp @@ -1,6 +1,6 @@ #include "servatrice_database_interface.h" -#include "decklist.h" +#include "deck_list.h" #include "passwordhasher.h" #include "pb/game_replay.pb.h" #include "servatrice.h" diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index f0d4771a7..5f765574f 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -20,7 +20,7 @@ #include "serversocketinterface.h" -#include "decklist.h" +#include "deck_list.h" #include "email_parser.h" #include "main.h" #include "pb/command_deck_del.pb.h" diff --git a/tests/loading_from_clipboard/CMakeLists.txt b/tests/loading_from_clipboard/CMakeLists.txt index 7b635a12d..be8ac6374 100644 --- a/tests/loading_from_clipboard/CMakeLists.txt +++ b/tests/loading_from_clipboard/CMakeLists.txt @@ -1,6 +1,6 @@ add_definitions("-DCARDDB_DATADIR=\"${CMAKE_CURRENT_SOURCE_DIR}/data/\"") add_executable( - loading_from_clipboard_test ../../common/decklist.cpp clipboard_testing.cpp loading_from_clipboard_test.cpp + loading_from_clipboard_test ../../common/deck_list.cpp clipboard_testing.cpp loading_from_clipboard_test.cpp ) if(NOT GTEST_FOUND) diff --git a/tests/loading_from_clipboard/clipboard_testing.cpp b/tests/loading_from_clipboard/clipboard_testing.cpp index b2021bde5..943c6a05d 100644 --- a/tests/loading_from_clipboard/clipboard_testing.cpp +++ b/tests/loading_from_clipboard/clipboard_testing.cpp @@ -1,5 +1,7 @@ #include "clipboard_testing.h" +#include "../../common/deck_list_card_node.h" + #include void testEmpty(const QString &clipboard) diff --git a/tests/loading_from_clipboard/clipboard_testing.h b/tests/loading_from_clipboard/clipboard_testing.h index 00d73b636..8f1b215b8 100644 --- a/tests/loading_from_clipboard/clipboard_testing.h +++ b/tests/loading_from_clipboard/clipboard_testing.h @@ -1,7 +1,7 @@ #ifndef CLIPBOARD_TESTING_H #define CLIPBOARD_TESTING_H -#include "../../common/decklist.h" +#include "../../common/deck_list.h" #include "gtest/gtest.h"