1 #ifndef DECKLIST_H 2 #define DECKLIST_H 3 4 #include <QList> 5 #include <QMap> 6 #include <QObject> 7 #include <QPair> 8 #include <QSet> 9 #include <QStringList> 10 #include <QVector> 11 12 // Required on Mac. Forward declaration doesn't work. Don't ask why. 13 #include <QtCore/QXmlStreamReader> 14 #include <QtCore/QXmlStreamWriter> 15 #include <common/pb/move_card_to_zone.pb.h> 16 17 class CardDatabase; 18 class QIODevice; 19 class QTextStream; 20 21 class InnerDecklistNode; 22 23 #define DECK_ZONE_MAIN "main" 24 #define DECK_ZONE_SIDE "side" 25 #define DECK_ZONE_TOKENS "tokens" 26 27 class SideboardPlan 28 { 29 private: 30 QString name; 31 QList<MoveCard_ToZone> moveList; 32 33 public: 34 explicit SideboardPlan(const QString &_name = QString(), 35 const QList<MoveCard_ToZone> &_moveList = QList<MoveCard_ToZone>()); 36 bool readElement(QXmlStreamReader *xml); 37 void write(QXmlStreamWriter *xml); 38 getName()39 QString getName() const 40 { 41 return name; 42 } getMoveList()43 const QList<MoveCard_ToZone> &getMoveList() const 44 { 45 return moveList; 46 } 47 void setMoveList(const QList<MoveCard_ToZone> &_moveList); 48 }; 49 50 enum DeckSortMethod 51 { 52 ByNumber, 53 ByName, 54 Default 55 }; 56 57 class AbstractDecklistNode 58 { 59 protected: 60 InnerDecklistNode *parent; 61 DeckSortMethod sortMethod; 62 63 public: 64 explicit AbstractDecklistNode(InnerDecklistNode *_parent = nullptr); 65 virtual ~AbstractDecklistNode() = default; setSortMethod(DeckSortMethod method)66 virtual void setSortMethod(DeckSortMethod method) 67 { 68 sortMethod = method; 69 } 70 virtual QString getName() const = 0; getParent()71 InnerDecklistNode *getParent() const 72 { 73 return parent; 74 } 75 int depth() const; 76 virtual int height() const = 0; 77 virtual bool compare(AbstractDecklistNode *other) const = 0; 78 79 virtual bool readElement(QXmlStreamReader *xml) = 0; 80 virtual void writeElement(QXmlStreamWriter *xml) = 0; 81 }; 82 83 class InnerDecklistNode : public AbstractDecklistNode, public QList<AbstractDecklistNode *> 84 { 85 private: 86 QString name; 87 class compareFunctor; 88 89 public: 90 explicit InnerDecklistNode(QString _name = QString(), InnerDecklistNode *_parent = nullptr) AbstractDecklistNode(_parent)91 : AbstractDecklistNode(_parent), name(std::move(_name)) 92 { 93 } 94 explicit InnerDecklistNode(InnerDecklistNode *other, InnerDecklistNode *_parent = nullptr); 95 ~InnerDecklistNode() override; 96 void setSortMethod(DeckSortMethod method) override; getName()97 QString getName() const override 98 { 99 return name; 100 } setName(const QString & _name)101 void setName(const QString &_name) 102 { 103 name = _name; 104 } 105 static QString visibleNameFromName(const QString &_name); 106 virtual QString getVisibleName() const; 107 void clearTree(); 108 AbstractDecklistNode *findChild(const QString &name); 109 int height() const override; 110 int recursiveCount(bool countTotalCards = false) const; 111 bool compare(AbstractDecklistNode *other) const override; 112 bool compareNumber(AbstractDecklistNode *other) const; 113 bool compareName(AbstractDecklistNode *other) const; 114 QVector<QPair<int, int>> sort(Qt::SortOrder order = Qt::AscendingOrder); 115 116 bool readElement(QXmlStreamReader *xml) override; 117 void writeElement(QXmlStreamWriter *xml) override; 118 }; 119 120 class AbstractDecklistCardNode : public AbstractDecklistNode 121 { 122 public: AbstractDecklistNode(_parent)123 explicit AbstractDecklistCardNode(InnerDecklistNode *_parent = nullptr) : AbstractDecklistNode(_parent) 124 { 125 } 126 virtual int getNumber() const = 0; 127 virtual void setNumber(int _number) = 0; 128 QString getName() const override = 0; 129 virtual void setName(const QString &_name) = 0; height()130 int height() const override 131 { 132 return 0; 133 } 134 bool compare(AbstractDecklistNode *other) const override; 135 bool compareNumber(AbstractDecklistNode *other) const; 136 bool compareName(AbstractDecklistNode *other) const; 137 138 bool readElement(QXmlStreamReader *xml) override; 139 void writeElement(QXmlStreamWriter *xml) override; 140 }; 141 142 class DecklistCardNode : public AbstractDecklistCardNode 143 { 144 private: 145 QString name; 146 int number; 147 148 public: 149 explicit DecklistCardNode(QString _name = QString(), int _number = 1, InnerDecklistNode *_parent = nullptr) AbstractDecklistCardNode(_parent)150 : AbstractDecklistCardNode(_parent), name(std::move(_name)), number(_number) 151 { 152 } 153 explicit DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent); getNumber()154 int getNumber() const override 155 { 156 return number; 157 } setNumber(int _number)158 void setNumber(int _number) override 159 { 160 number = _number; 161 } getName()162 QString getName() const override 163 { 164 return name; 165 } setName(const QString & _name)166 void setName(const QString &_name) override 167 { 168 name = _name; 169 } 170 }; 171 172 class DeckList : public QObject 173 { 174 Q_OBJECT 175 private: 176 QString name, comments; 177 QString deckHash; 178 QMap<QString, SideboardPlan *> sideboardPlans; 179 InnerDecklistNode *root; 180 void getCardListHelper(InnerDecklistNode *node, QSet<QString> &result) const; 181 InnerDecklistNode *getZoneObjFromName(QString zoneName); 182 183 protected: getCardZoneFromName(const QString,QString currentZoneName)184 virtual QString getCardZoneFromName(const QString /*cardName*/, QString currentZoneName) 185 { 186 return currentZoneName; 187 }; getCompleteCardName(const QString cardName)188 virtual QString getCompleteCardName(const QString cardName) const 189 { 190 return cardName; 191 }; 192 193 signals: 194 void deckHashChanged(); 195 196 public slots: 197 void setName(const QString &_name = QString()) 198 { 199 name = _name; 200 } 201 void setComments(const QString &_comments = QString()) 202 { 203 comments = _comments; 204 } 205 206 public: 207 explicit DeckList(); 208 DeckList(const DeckList &other); 209 explicit DeckList(const QString &nativeString); 210 ~DeckList() override; getName()211 QString getName() const 212 { 213 return name; 214 } getComments()215 QString getComments() const 216 { 217 return comments; 218 } 219 QList<MoveCard_ToZone> getCurrentSideboardPlan(); 220 void setCurrentSideboardPlan(const QList<MoveCard_ToZone> &plan); getSideboardPlans()221 const QMap<QString, SideboardPlan *> &getSideboardPlans() const 222 { 223 return sideboardPlans; 224 } 225 226 bool readElement(QXmlStreamReader *xml); 227 void write(QXmlStreamWriter *xml); 228 bool loadFromXml(QXmlStreamReader *xml); 229 bool loadFromString_Native(const QString &nativeString); 230 QString writeToString_Native(); 231 bool loadFromFile_Native(QIODevice *device); 232 bool saveToFile_Native(QIODevice *device); 233 bool loadFromStream_Plain(QTextStream &stream); 234 bool loadFromFile_Plain(QIODevice *device); 235 bool saveToStream_Plain(QTextStream &stream, bool prefixSideboardCards, bool slashTappedOutSplitCards); 236 bool saveToFile_Plain(QIODevice *device, bool prefixSideboardCards = true, bool slashTappedOutSplitCards = false); 237 QString writeToString_Plain(bool prefixSideboardCards = true, bool slashTappedOutSplitCards = false); 238 239 void cleanList(); isEmpty()240 bool isEmpty() const 241 { 242 return root->isEmpty() && name.isEmpty() && comments.isEmpty() && sideboardPlans.isEmpty(); 243 } 244 QStringList getCardList() const; 245 246 int getSideboardSize() const; 247 getDeckHash()248 QString getDeckHash() const 249 { 250 return deckHash; 251 } 252 void updateDeckHash(); 253 getRoot()254 InnerDecklistNode *getRoot() const 255 { 256 return root; 257 } 258 DecklistCardNode *addCard(const QString &cardName, const QString &zoneName); 259 bool deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode = nullptr); 260 261 /** 262 * Calls a given function object for each card in the deck. It must 263 * take a InnerDecklistNode* as its first argument and a 264 * DecklistCardNode* as its second. 265 */ forEachCard(Callback & callback)266 template <typename Callback> void forEachCard(Callback &callback) const 267 { 268 // Support for this is only possible if the internal structure 269 // doesn't get more complicated. 270 for (int i = 0; i < root->size(); i++) { 271 const InnerDecklistNode *node = dynamic_cast<InnerDecklistNode *>(root->at(i)); 272 for (int j = 0; j < node->size(); j++) { 273 const DecklistCardNode *card = dynamic_cast<DecklistCardNode *>(node->at(j)); 274 callback(node, card); 275 } 276 } 277 } 278 }; 279 280 #endif 281