From ed70099e36c9ebfb0f2de5e8aa87ac711a3ff228 Mon Sep 17 00:00:00 2001 From: ctrlaltca Date: Thu, 24 Jan 2019 00:17:10 +0100 Subject: [PATCH] Rework of the card database, xml format and oracle parser (#3511) * CardDB: merge all card properties in a new structure * Pre Json parser changes * Cockatrice: use qt's builtin json support * Move qt-json src dir from cockatrice to oracle * Add dummy cockatricexml4 parser (yet to be implemented) * Implement a new parser and xml format * cockatricexml4: new xml parser following the "generic properties hash" pattern; * oracleimporter: refactor the parsing code to better adapt to cockatricexml4; rewrote split cards parsing * carddb: change "colors" from a stringlist to a string * carddb: move the getMainCardType() method to the cockatricexml3 parser * * CardInfo: show all properties (stil missing: nice name + translation) * Rework the "add related card" feature so that it doesn't change the card name in the carddb Also, fix token count display * Picture loader: Added support for transform cards * Fix side information for flip cards Mtgjson uses side a/b for flip cards, while scryfall doesn't * Pictureloader: dynamic tag resolution from card properties Examples old => new * !cardid! => !set:muid! * !uuid! => !set:uuid! * !collectornumber! => !set:num! New examples: * !prop:type! * !prop:manacost! * Start moving mtg-related property names to a specific file * Clangify * Fix tests * Make gcc an happy puppy * Revert "Make gcc an happy puppy" This reverts commit 446ec5f27516c4d3b32dbfc79557f4827c5c5bdf. * Some gcc fixes * Share set list between different db parsers, so they won't overwrite one each other * All glory to the hypnoclangifier! * Fix test compilation * Cleanup edited files in the prior PR. (#3519) * Cleanup edited files in the prior PR. Signed-off-by: Zach Halpern * Fix includes Signed-off-by: Zach Halpern * Update carddatabase.h --- clangify.sh | 6 +- cockatrice/CMakeLists.txt | 3 +- cockatrice/src/carddatabase.cpp | 208 +++----- cockatrice/src/carddatabase.h | 285 +++++----- cockatrice/src/carddatabasemodel.cpp | 10 +- cockatrice/src/carddatabasemodel.h | 30 +- .../src/carddbparser/carddatabaseparser.cpp | 27 + .../src/carddbparser/carddatabaseparser.h | 20 +- .../src/carddbparser/cockatricexml3.cpp | 217 ++++---- cockatrice/src/carddbparser/cockatricexml3.h | 23 +- .../src/carddbparser/cockatricexml4.cpp | 362 +++++++++++++ cockatrice/src/carddbparser/cockatricexml4.h | 28 + cockatrice/src/cardframe.cpp | 9 +- cockatrice/src/cardframe.h | 2 +- cockatrice/src/cardinfotext.cpp | 160 ++---- cockatrice/src/cardinfotext.h | 12 +- cockatrice/src/cardinfowidget.cpp | 11 +- cockatrice/src/cardinfowidget.h | 2 +- cockatrice/src/decklistmodel.cpp | 4 +- cockatrice/src/decklistmodel.h | 33 +- cockatrice/src/dlg_edit_tokens.cpp | 19 +- cockatrice/src/dlg_edit_tokens.h | 2 +- cockatrice/src/filtertree.cpp | 19 +- cockatrice/src/filtertree.h | 100 ++-- cockatrice/src/game_specific_terms.h | 49 ++ cockatrice/src/handle_public_servers.cpp | 15 +- cockatrice/src/pictureloader.cpp | 52 +- cockatrice/src/player.cpp | 302 ++++++----- cockatrice/src/player.h | 19 +- cockatrice/src/releasechannel.cpp | 53 +- cockatrice/src/releasechannel.h | 51 +- cockatrice/src/settings/downloadsettings.cpp | 6 +- cockatrice/translations/cockatrice_en.ts | 452 +++++++++------- oracle/CMakeLists.txt | 4 +- oracle/src/oracleimporter.cpp | 498 +++++++++--------- oracle/src/oracleimporter.h | 73 ++- {cockatrice => oracle}/src/qt-json/AUTHORS | 0 {cockatrice => oracle}/src/qt-json/LICENSE | 0 {cockatrice => oracle}/src/qt-json/README | 0 {cockatrice => oracle}/src/qt-json/json.cpp | 0 {cockatrice => oracle}/src/qt-json/json.h | 0 oracle/translations/oracle_en.ts | 2 +- tests/carddatabase/CMakeLists.txt | 3 +- tests/carddatabase/carddatabase_test.cpp | 3 - 44 files changed, 1814 insertions(+), 1360 deletions(-) create mode 100644 cockatrice/src/carddbparser/carddatabaseparser.cpp create mode 100644 cockatrice/src/carddbparser/cockatricexml4.cpp create mode 100644 cockatrice/src/carddbparser/cockatricexml4.h create mode 100644 cockatrice/src/game_specific_terms.h rename {cockatrice => oracle}/src/qt-json/AUTHORS (100%) rename {cockatrice => oracle}/src/qt-json/LICENSE (100%) rename {cockatrice => oracle}/src/qt-json/README (100%) rename {cockatrice => oracle}/src/qt-json/json.cpp (100%) rename {cockatrice => oracle}/src/qt-json/json.h (100%) diff --git a/clangify.sh b/clangify.sh index ce81a114..9113952e 100755 --- a/clangify.sh +++ b/clangify.sh @@ -12,11 +12,11 @@ include=("common" \ "cockatrice/src" \ "oracle/src" \ "servatrice/src") -exclude=("cockatrice/src/qt-json" \ -"servatrice/src/smtp" \ +exclude=("servatrice/src/smtp" \ "common/sfmt" \ "oracle/src/zip" \ -"oracle/src/lzma") +"oracle/src/lzma" \ +"oracle/src/qt-json") exts=("cpp" "h") cf_cmd="clang-format" branch="origin/master" diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 38b4a331..3e7defbe 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -100,7 +100,6 @@ SET(cockatrice_SOURCES src/localserver.cpp src/localserverinterface.cpp src/localclient.cpp - src/qt-json/json.cpp src/soundengine.cpp src/pending_command.cpp src/pictureloader.cpp @@ -121,7 +120,9 @@ SET(cockatrice_SOURCES src/userconnection_information.cpp src/spoilerbackgroundupdater.cpp src/handle_public_servers.cpp + src/carddbparser/carddatabaseparser.cpp src/carddbparser/cockatricexml3.cpp + src/carddbparser/cockatricexml4.cpp ${VERSION_STRING_CPP} ) diff --git a/cockatrice/src/carddatabase.cpp b/cockatrice/src/carddatabase.cpp index f4995db5..a75f150c 100644 --- a/cockatrice/src/carddatabase.cpp +++ b/cockatrice/src/carddatabase.cpp @@ -1,5 +1,7 @@ #include "carddatabase.h" #include "carddbparser/cockatricexml3.h" +#include "carddbparser/cockatricexml4.h" +#include "game_specific_terms.h" #include "pictureloader.h" #include "settingscache.h" #include "spoilerbackgroundupdater.h" @@ -207,31 +209,23 @@ void SetList::guessSortKeys() } } +CardInfoPerSet::CardInfoPerSet(const CardSetPtr &_set) : set(_set) +{ +} + CardInfo::CardInfo(const QString &_name, - bool _isToken, - const QString &_manacost, - const QString &_cmc, - const QString &_cardtype, - const QString &_powtough, const QString &_text, - const QStringList &_colors, + bool _isToken, + QVariantHash _properties, const QList &_relatedCards, const QList &_reverseRelatedCards, - bool _upsideDownArt, - const QString &_loyalty, + CardInfoPerSetMap _sets, bool _cipt, int _tableRow, - const SetList &_sets, - const QStringMap &_customPicURLs, - MuidMap _muIds, - QStringMap _uuIds, - QStringMap _collectorNumbers, - QStringMap _rarities) - : name(_name), isToken(_isToken), sets(_sets), manacost(_manacost), cmc(_cmc), cardtype(_cardtype), - powtough(_powtough), text(_text), colors(_colors), relatedCards(_relatedCards), - reverseRelatedCards(_reverseRelatedCards), setsNames(), upsideDownArt(_upsideDownArt), loyalty(_loyalty), - customPicURLs(_customPicURLs), muIds(std::move(_muIds)), uuIds(std::move(_uuIds)), - collectorNumbers(std::move(_collectorNumbers)), rarities(std::move(_rarities)), cipt(_cipt), tableRow(_tableRow) + bool _upsideDownArt) + : name(_name), text(_text), isToken(_isToken), properties(std::move(_properties)), relatedCards(_relatedCards), + reverseRelatedCards(_reverseRelatedCards), sets(std::move(_sets)), cipt(_cipt), tableRow(_tableRow), + upsideDownArt(_upsideDownArt) { pixmapCacheKey = QLatin1String("card_") + name; simpleName = CardInfo::simplifyName(name); @@ -245,77 +239,27 @@ CardInfo::~CardInfo() } CardInfoPtr CardInfo::newInstance(const QString &_name, - bool _isToken, - const QString &_manacost, - const QString &_cmc, - const QString &_cardtype, - const QString &_powtough, const QString &_text, - const QStringList &_colors, + bool _isToken, + QVariantHash _properties, const QList &_relatedCards, const QList &_reverseRelatedCards, - bool _upsideDownArt, - const QString &_loyalty, + CardInfoPerSetMap _sets, bool _cipt, int _tableRow, - const SetList &_sets, - const QStringMap &_customPicURLs, - MuidMap _muIds, - QStringMap _uuIds, - QStringMap _collectorNumbers, - QStringMap _rarities) + bool _upsideDownArt) { - CardInfoPtr ptr(new CardInfo(_name, _isToken, _manacost, _cmc, _cardtype, _powtough, _text, _colors, _relatedCards, - _reverseRelatedCards, _upsideDownArt, _loyalty, _cipt, _tableRow, _sets, - _customPicURLs, std::move(_muIds), std::move(_uuIds), std::move(_collectorNumbers), - std::move(_rarities))); + CardInfoPtr ptr(new CardInfo(_name, _text, _isToken, std::move(_properties), _relatedCards, _reverseRelatedCards, + _sets, _cipt, _tableRow, _upsideDownArt)); ptr->setSmartPointer(ptr); - for (int i = 0; i < _sets.size(); i++) { - _sets[i]->append(ptr); + for (const CardInfoPerSet &set : _sets) { + set.getPtr()->append(ptr); } return ptr; } -QString CardInfo::getMainCardType() const -{ - QString result = getCardType(); - /* - Legendary Artifact Creature - Golem - Instant // Instant - */ - - int pos; - if ((pos = result.indexOf('-')) != -1) { - result.remove(pos, result.length()); - } - - if ((pos = result.indexOf("—")) != -1) { - result.remove(pos, result.length()); - } - - if ((pos = result.indexOf("//")) != -1) { - result.remove(pos, result.length()); - } - - result = result.simplified(); - /* - Legendary Artifact Creature - Instant - */ - - if ((pos = result.lastIndexOf(' ')) != -1) { - result = result.mid(pos + 1); - } - /* - Creature - Instant - */ - - return result; -} - QString CardInfo::getCorrectedName() const { QString result = name; @@ -323,26 +267,21 @@ QString CardInfo::getCorrectedName() const return result.remove(" // ").remove(':').remove('"').remove('?').replace('/', ' '); } -void CardInfo::addToSet(CardSetPtr set) +void CardInfo::addToSet(const CardSetPtr &_set, const CardInfoPerSet _info) { - if (set.isNull()) { - qDebug() << "addToSet(nullptr)"; - return; - } - - set->append(smartThis); - sets << set; + _set->append(smartThis); + sets.insert(_set->getShortName(), _info); refreshCachedSetNames(); } void CardInfo::refreshCachedSetNames() { - // update the cached list of set names QStringList setList; - for (int i = 0; i < sets.size(); i++) { - if (sets[i]->getEnabled()) { - setList << sets[i]->getShortName(); + // update the cached list of set names + for (const auto &set : sets) { + if (set.getPtr()->getEnabled()) { + setList << set.getPtr()->getShortName(); } } setsNames = setList.join(", "); @@ -371,11 +310,12 @@ QString CardInfo::simplifyName(const QString &name) const QChar CardInfo::getColorChar() const { + QString colors = getColors(); switch (colors.size()) { case 0: return QChar(); case 1: - return colors.first().isEmpty() ? QChar() : colors.first().at(0); + return colors.at(0); default: return QChar('m'); } @@ -388,6 +328,7 @@ CardDatabase::CardDatabase(QObject *parent) : QObject(parent), loadStatus(NotLoa // add new parsers here availableParsers << new CockatriceXml3Parser; + availableParsers << new CockatriceXml4Parser; for (auto &parser : availableParsers) { connect(parser, SIGNAL(addCard(CardInfoPtr)), this, SLOT(addCard(CardInfoPtr)), Qt::DirectConnection); @@ -419,9 +360,7 @@ void CardDatabase::clear() simpleNameCards.clear(); sets.clear(); - for (auto parser : availableParsers) { - parser->clearSetlist(); - } + ICardDatabaseParser::clearSetlist(); loadStatus = NotLoaded; @@ -438,13 +377,8 @@ void CardDatabase::addCard(CardInfoPtr card) // if card already exists just add the new set property if (cards.contains(card->getName())) { CardInfoPtr sameCard = cards[card->getName()]; - for (auto set : card->getSets()) { - QString setName = set->getCorrectedShortName(); - sameCard->setSet(set); - sameCard->setMuId(setName, card->getMuId(setName)); - sameCard->setUuId(setName, card->getUuId(setName)); - sameCard->setRarity(setName, card->getRarity(setName)); - sameCard->setSetNumber(setName, card->getCollectorNumber(setName)); + for (const CardInfoPerSet &set : card->getSets()) { + sameCard->addToSet(set.getPtr(), set); } return; } @@ -585,7 +519,7 @@ LoadStatus CardDatabase::loadCardDatabases() // load custom card databases QDir dir(settingsCache->getCustomCardDatabasePath()); - for (QString fileName : + for (const QString &fileName : dir.entryList(QStringList("*.xml"), QDir::Files | QDir::Readable, QDir::Name | QDir::IgnoreCase)) { loadCardDatabase(dir.absoluteFilePath(fileName)); } @@ -617,20 +551,13 @@ void CardDatabase::refreshCachedReverseRelatedCards() continue; } - QString relatedCardName; - if (card->getPowTough().size() > 0) { - relatedCardName = card->getPowTough() + " " + card->getName(); // "n/n name" - } else { - relatedCardName = card->getName(); // "name" - } - foreach (CardRelation *cardRelation, card->getReverseRelatedCards()) { const QString &targetCard = cardRelation->getName(); if (!cards.contains(targetCard)) { continue; } - auto *newCardRelation = new CardRelation(relatedCardName, cardRelation->getDoesAttach(), + auto *newCardRelation = new CardRelation(card->getName(), cardRelation->getDoesAttach(), cardRelation->getIsCreateAllExclusion(), cardRelation->getIsVariable(), cardRelation->getDefaultCount()); cards.value(targetCard)->addReverseRelatedCards2Me(newCardRelation); @@ -638,23 +565,6 @@ void CardDatabase::refreshCachedReverseRelatedCards() } } -QStringList CardDatabase::getAllColors() const -{ - QSet colors; - QHashIterator cardIterator(cards); - while (cardIterator.hasNext()) { - const QStringList &cardColors = cardIterator.next().value()->getColors(); - if (cardColors.isEmpty()) { - colors.insert("X"); - } else { - for (int i = 0; i < cardColors.size(); ++i) { - colors.insert(cardColors[i]); - } - } - } - return colors.toList(); -} - QStringList CardDatabase::getAllMainCardTypes() const { QSet types; @@ -720,8 +630,8 @@ bool CardDatabase::saveCustomTokensToFile() tmpSets.insert(CardDatabase::TOKENS_SETNAME, customTokensSet); CardNameMap tmpCards; - for (CardInfoPtr card : cards) { - if (card->getSets().contains(customTokensSet)) { + for (const CardInfoPtr &card : cards) { + if (card->getSets().contains(CardDatabase::TOKENS_SETNAME)) { tmpCards.insert(card->getName(), card); } } @@ -746,4 +656,46 @@ void CardInfo::resetReverseRelatedCards2Me() cardRelation->deleteLater(); } reverseRelatedCardsToMe = QList(); +} + +// Back-compatibility methods. Remove ASAP +const QString CardInfo::getCardType() const +{ + return getProperty(Mtg::CardType); +} +void CardInfo::setCardType(const QString &value) +{ + setProperty(Mtg::CardType, value); +} +const QString CardInfo::getCmc() const +{ + return getProperty(Mtg::ConvertedManaCost); +} +const QString CardInfo::getColors() const +{ + return getProperty(Mtg::Colors); +} +void CardInfo::setColors(const QString &value) +{ + setProperty(Mtg::Colors, value); +} +const QString CardInfo::getLoyalty() const +{ + return getProperty(Mtg::Loyalty); +} +const QString CardInfo::getMainCardType() const +{ + return getProperty(Mtg::MainCardType); +} +const QString CardInfo::getManaCost() const +{ + return getProperty(Mtg::ManaCost); +} +const QString CardInfo::getPowTough() const +{ + return getProperty(Mtg::PowTough); +} +void CardInfo::setPowTough(const QString &value) +{ + setProperty(Mtg::PowTough, value); } \ No newline at end of file diff --git a/cockatrice/src/carddatabase.h b/cockatrice/src/carddatabase.h index 8aa89e0b..c5cf0ea2 100644 --- a/cockatrice/src/carddatabase.h +++ b/cockatrice/src/carddatabase.h @@ -9,10 +9,13 @@ #include #include #include +#include #include +#include class CardDatabase; class CardInfo; +class CardInfoPerSet; class CardSet; class CardRelation; class ICardDatabaseParser; @@ -21,6 +24,7 @@ typedef QMap QStringMap; typedef QMap MuidMap; typedef QSharedPointer CardInfoPtr; typedef QSharedPointer CardSetPtr; +typedef QMap CardInfoPerSetMap; Q_DECLARE_METATYPE(CardInfoPtr) @@ -112,178 +116,162 @@ public: QStringList getUnknownSetsNames(); }; +class CardInfoPerSet +{ +public: + explicit CardInfoPerSet(const CardSetPtr &_set = QSharedPointer(nullptr)); + ~CardInfoPerSet() = default; + +private: + CardSetPtr set; + // per-set card properties; + QVariantHash properties; + +public: + const CardSetPtr getPtr() const + { + return set; + } + const QStringList getProperties() const + { + return properties.keys(); + } + const QString getProperty(const QString &propertyName) const + { + return properties.value(propertyName).toString(); + } + void setProperty(const QString &_name, const QString &_value) + { + properties.insert(_name, _value); + } +}; + class CardInfo : public QObject { Q_OBJECT private: CardInfoPtr smartThis; + // The card name QString name; - - /* - * The name without punctuation or capitalization, for better card tag name - * recognition. - */ + // The name without punctuation or capitalization, for better card name recognition. QString simpleName; - - bool isToken; - SetList sets; - QString manacost; - QString cmc; - QString cardtype; - QString powtough; + // The key used to identify this card in the cache + QString pixmapCacheKey; + // card text QString text; - QStringList colors; - + // whether this is not a "real" card but a token + bool isToken; + // basic card properties; common for all the sets + QVariantHash properties; // the cards i'm related to QList relatedCards; - // the card i'm reverse-related to QList reverseRelatedCards; - // the cards thare are reverse-related to me QList reverseRelatedCardsToMe; - + // card sets + CardInfoPerSetMap sets; + // cached set names QString setsNames; - - bool upsideDownArt; - QString loyalty; - QStringMap customPicURLs; - MuidMap muIds; - QStringMap uuIds; - QStringMap collectorNumbers; - QStringMap rarities; + // positioning properties; used by UI bool cipt; int tableRow; - QString pixmapCacheKey; + bool upsideDownArt; public: explicit CardInfo(const QString &_name = QString(), - bool _isToken = false, - const QString &_manacost = QString(), - const QString &_cmc = QString(), - const QString &_cardtype = QString(), - const QString &_powtough = QString(), const QString &_text = QString(), - const QStringList &_colors = QStringList(), + bool _isToken = false, + QVariantHash _properties = QVariantHash(), const QList &_relatedCards = QList(), const QList &_reverseRelatedCards = QList(), - bool _upsideDownArt = false, - const QString &_loyalty = QString(), + CardInfoPerSetMap _sets = CardInfoPerSetMap(), bool _cipt = false, int _tableRow = 0, - const SetList &_sets = SetList(), - const QStringMap &_customPicURLs = QStringMap(), - MuidMap _muids = MuidMap(), - QStringMap _uuIds = QStringMap(), - QStringMap _collectorNumbers = QStringMap(), - QStringMap _rarities = QStringMap()); + bool _upsideDownArt = false); ~CardInfo() override; static CardInfoPtr newInstance(const QString &_name = QString(), - bool _isToken = false, - const QString &_manacost = QString(), - const QString &_cmc = QString(), - const QString &_cardtype = QString(), - const QString &_powtough = QString(), const QString &_text = QString(), - const QStringList &_colors = QStringList(), + bool _isToken = false, + QVariantHash _properties = QVariantHash(), const QList &_relatedCards = QList(), const QList &_reverseRelatedCards = QList(), - bool _upsideDownArt = false, - const QString &_loyalty = QString(), + CardInfoPerSetMap _sets = CardInfoPerSetMap(), bool _cipt = false, int _tableRow = 0, - const SetList &_sets = SetList(), - const QStringMap &_customPicURLs = QStringMap(), - MuidMap _muids = MuidMap(), - QStringMap _uuIds = QStringMap(), - QStringMap _collectorNumbers = QStringMap(), - QStringMap _rarities = QStringMap()); + bool _upsideDownArt = false); void setSmartPointer(CardInfoPtr _ptr) { - smartThis = _ptr; + smartThis = std::move(_ptr); } + // basic properties inline const QString &getName() const { return name; } - inline const QString &getSetsNames() const - { - return setsNames; - } const QString &getSimpleName() const { return simpleName; } - bool getIsToken() const - { - return isToken; - } - const SetList &getSets() const - { - return sets; - } - inline const QString &getManaCost() const - { - return manacost; - } - inline const QString &getCmc() const - { - return cmc; - } - inline const QString &getCardType() const - { - return cardtype; - } - inline const QString &getPowTough() const - { - return powtough; - } - const QString &getText() const - { - return text; - } const QString &getPixmapCacheKey() const { return pixmapCacheKey; } - const QString &getLoyalty() const + + const QString &getText() const { - return loyalty; - } - bool getCipt() const - { - return cipt; - } - // void setManaCost(const QString &_manaCost) { manacost = _manaCost; emit cardInfoChanged(smartThis); } - // void setCmc(const QString &_cmc) { cmc = _cmc; emit cardInfoChanged(smartThis); } - void setCardType(const QString &_cardType) - { - cardtype = _cardType; - emit cardInfoChanged(smartThis); - } - void setPowTough(const QString &_powTough) - { - powtough = _powTough; - emit cardInfoChanged(smartThis); + return text; } void setText(const QString &_text) { text = _text; emit cardInfoChanged(smartThis); } - void setColors(const QStringList &_colors) + + bool getIsToken() const { - colors = _colors; + return isToken; + } + const QStringList getProperties() const + { + return properties.keys(); + } + const QString getProperty(const QString &propertyName) const + { + return properties.value(propertyName).toString(); + } + void setProperty(const QString &_name, const QString &_value) + { + properties.insert(_name, _value); emit cardInfoChanged(smartThis); } - const QChar getColorChar() const; - const QStringList &getColors() const + const CardInfoPerSetMap &getSets() const { - return colors; + return sets; } + const QString &getSetsNames() const + { + return setsNames; + } + const QString getSetProperty(const QString &setName, const QString &propertyName) const + { + if (!sets.contains(setName)) + return ""; + return sets[setName].getProperty(propertyName); + } + void setSetProperty(const QString &setName, const QString &_name, const QString &_value) + { + if (!sets.contains(setName)) + return; + + sets[setName].setProperty(_name, _value); + emit cardInfoChanged(smartThis); + } + + // related cards const QList &getRelatedCards() const { return relatedCards; @@ -301,36 +289,12 @@ public: { reverseRelatedCardsToMe.append(cardRelation); } - bool getUpsideDownArt() const + + // positioning + bool getCipt() const { - return upsideDownArt; + return cipt; } - QString getCustomPicURL(const QString &set) const - { - return customPicURLs.value(set); - } - int getMuId(const QString &set) const - { - return muIds.value(set); - } - QString getUuId(const QString &set) const - { - return uuIds.value(set); - } - QString getCollectorNumber(const QString &set) const - { - return collectorNumbers.value(set); - } - QString getRarity(const QString &set) const - { - return rarities.value(set); - } - QStringMap getRarities() const - { - return rarities; - } - QString getMainCardType() const; - QString getCorrectedName() const; int getTableRow() const { return tableRow; @@ -339,31 +303,31 @@ public: { tableRow = _tableRow; } - // void setLoyalty(int _loyalty) { loyalty = _loyalty; emit cardInfoChanged(smartThis); } - // void setCustomPicURL(const QString &_set, const QString &_customPicURL) { customPicURLs.insert(_set, - // _customPicURL); } - void setSet(const CardSetPtr &_set) + bool getUpsideDownArt() const { - sets.append(_set); - refreshCachedSetNames(); + return upsideDownArt; } - void setMuId(const QString &_set, const int &_muId) + const QChar getColorChar() const; + + // Back-compatibility methods. Remove ASAP + const QString getCardType() const; + void setCardType(const QString &value); + const QString getCmc() const; + const QString getColors() const; + void setColors(const QString &value); + const QString getLoyalty() const; + const QString getMainCardType() const; + const QString getManaCost() const; + const QString getPowTough() const; + void setPowTough(const QString &value); + + // methods using per-set properties + QString getCustomPicURL(const QString &set) const { - muIds.insert(_set, _muId); + return getSetProperty(set, "picurl"); } - void setUuId(const QString &_set, const QString &_uuId) - { - uuIds.insert(_set, _uuId); - } - void setSetNumber(const QString &_set, const QString &_setNumber) - { - collectorNumbers.insert(_set, _setNumber); - } - void setRarity(const QString &_set, const QString &_setNumber) - { - rarities.insert(_set, _setNumber); - } - void addToSet(CardSetPtr set); + QString getCorrectedName() const; + void addToSet(const CardSetPtr &_set, CardInfoPerSet _info = CardInfoPerSet()); void emitPixmapUpdated() { emit pixmapUpdated(); @@ -450,7 +414,6 @@ public: SetList getSetList() const; LoadStatus loadFromFile(const QString &fileName); bool saveCustomTokensToFile(); - QStringList getAllColors() const; QStringList getAllMainCardTypes() const; LoadStatus getLoadStatus() const { @@ -517,4 +480,4 @@ public: return defaultCount; } }; -#endif \ No newline at end of file +#endif diff --git a/cockatrice/src/carddatabasemodel.cpp b/cockatrice/src/carddatabasemodel.cpp index faa8c3a8..9ae85578 100644 --- a/cockatrice/src/carddatabasemodel.cpp +++ b/cockatrice/src/carddatabasemodel.cpp @@ -14,9 +14,7 @@ CardDatabaseModel::CardDatabaseModel(CardDatabase *_db, bool _showOnlyCardsFromE cardDatabaseEnabledSetsChanged(); } -CardDatabaseModel::~CardDatabaseModel() -{ -} +CardDatabaseModel::~CardDatabaseModel() = default; QMap CardDatabaseDisplayModel::characterTranslation = {{L'“', L'\"'}, {L'”', L'\"'}, @@ -53,7 +51,7 @@ QVariant CardDatabaseModel::data(const QModelIndex &index, int role) const case PTColumn: return card->getPowTough(); case ColorColumn: - return card->getColors().join(""); + return card->getColors(); default: return QVariant(); } @@ -97,8 +95,8 @@ bool CardDatabaseModel::checkCardHasAtLeastOneEnabledSet(CardInfoPtr card) if (!showOnlyCardsFromEnabledSets) return true; - for (CardSetPtr set : card->getSets()) { - if (set->getEnabled()) + for (const auto &set : card->getSets()) { + if (set.getPtr()->getEnabled()) return true; } diff --git a/cockatrice/src/carddatabasemodel.h b/cockatrice/src/carddatabasemodel.h index 5400c1f4..8e8cb67c 100644 --- a/cockatrice/src/carddatabasemodel.h +++ b/cockatrice/src/carddatabasemodel.h @@ -26,12 +26,12 @@ public: { SortRole = Qt::UserRole }; - CardDatabaseModel(CardDatabase *_db, bool _showOnlyCardsFromEnabledSets, QObject *parent = 0); - ~CardDatabaseModel(); - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - QVariant data(const QModelIndex &index, int role) const; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + CardDatabaseModel(CardDatabase *_db, bool _showOnlyCardsFromEnabledSets, QObject *parent = nullptr); + ~CardDatabaseModel() override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; CardDatabase *getDatabase() const { return db; @@ -77,7 +77,7 @@ private: static QMap characterTranslation; public: - CardDatabaseDisplayModel(QObject *parent = 0); + explicit CardDatabaseDisplayModel(QObject *parent = nullptr); void setFilterTree(FilterTree *filterTree); void setIsToken(FilterBool _isToken) { @@ -119,15 +119,15 @@ public: invalidate(); } void clearFilterAll(); - int rowCount(const QModelIndex &parent = QModelIndex()) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; protected: - bool lessThan(const QModelIndex &left, const QModelIndex &right) const; + bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; static int lessThanNumerically(const QString &left, const QString &right); - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; bool rowMatchesCardName(CardInfoPtr info) const; - bool canFetchMore(const QModelIndex &parent) const; - void fetchMore(const QModelIndex &parent); + bool canFetchMore(const QModelIndex &parent) const override; + void fetchMore(const QModelIndex &parent) override; private slots: void filterTreeChanged(); /** Will translate all undesirable characters in DIRTYNAME according to the TABLE. */ @@ -138,11 +138,11 @@ class TokenDisplayModel : public CardDatabaseDisplayModel { Q_OBJECT public: - TokenDisplayModel(QObject *parent = 0); - int rowCount(const QModelIndex &parent = QModelIndex()) const; + explicit TokenDisplayModel(QObject *parent = nullptr); + int rowCount(const QModelIndex &parent = QModelIndex()) const override; protected: - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; }; #endif diff --git a/cockatrice/src/carddbparser/carddatabaseparser.cpp b/cockatrice/src/carddbparser/carddatabaseparser.cpp new file mode 100644 index 00000000..0048c958 --- /dev/null +++ b/cockatrice/src/carddbparser/carddatabaseparser.cpp @@ -0,0 +1,27 @@ +#include "carddatabaseparser.h" + +SetNameMap ICardDatabaseParser::sets; + +void ICardDatabaseParser::clearSetlist() +{ + sets.clear(); +} + +CardSetPtr ICardDatabaseParser::internalAddSet(const QString &setName, + const QString &longName, + const QString &setType, + const QDate &releaseDate) +{ + if (sets.contains(setName)) { + return sets.value(setName); + } + + CardSetPtr newSet = CardSet::newInstance(setName); + newSet->setLongName(longName); + newSet->setSetType(setType); + newSet->setReleaseDate(releaseDate); + + sets.insert(setName, newSet); + emit addSet(newSet); + return newSet; +} \ No newline at end of file diff --git a/cockatrice/src/carddbparser/carddatabaseparser.h b/cockatrice/src/carddbparser/carddatabaseparser.h index d094b6d7..e8b46f95 100644 --- a/cockatrice/src/carddbparser/carddatabaseparser.h +++ b/cockatrice/src/carddbparser/carddatabaseparser.h @@ -9,15 +9,27 @@ class ICardDatabaseParser : public QObject { public: - virtual ~ICardDatabaseParser() - { - } + ~ICardDatabaseParser() override = default; + virtual bool getCanParseFile(const QString &name, QIODevice &device) = 0; virtual void parseFile(QIODevice &device) = 0; virtual bool saveToFile(SetNameMap sets, CardNameMap cards, const QString &fileName) = 0; - virtual void clearSetlist() = 0; + static void clearSetlist(); + +protected: + /* + * A cached list of the available sets, needed to cross-reference sets from cards. + * Shared between all parsers + */ + static SetNameMap sets; + + CardSetPtr internalAddSet(const QString &setName, + const QString &longName = "", + const QString &setType = "", + const QDate &releaseDate = QDate()); signals: virtual void addCard(CardInfoPtr card) = 0; + virtual void addSet(CardSetPtr set) = 0; }; Q_DECLARE_INTERFACE(ICardDatabaseParser, "ICardDatabaseParser") diff --git a/cockatrice/src/carddbparser/cockatricexml3.cpp b/cockatrice/src/carddbparser/cockatricexml3.cpp index 6a6300cf..b6335277 100644 --- a/cockatrice/src/carddbparser/cockatricexml3.cpp +++ b/cockatrice/src/carddbparser/cockatricexml3.cpp @@ -61,30 +61,6 @@ void CockatriceXml3Parser::parseFile(QIODevice &device) } } -CardSetPtr CockatriceXml3Parser::internalAddSet(const QString &setName, - const QString &longName, - const QString &setType, - const QDate &releaseDate) -{ - if (sets.contains(setName)) { - return sets.value(setName); - } - - CardSetPtr newSet = CardSet::newInstance(setName); - newSet->setLongName(longName); - newSet->setSetType(setType); - newSet->setReleaseDate(releaseDate); - - sets.insert(setName, newSet); - emit addSet(newSet); - return newSet; -} - -void CockatriceXml3Parser::clearSetlist() -{ - sets.clear(); -} - void CockatriceXml3Parser::loadSetsFromXml(QXmlStreamReader &xml) { while (!xml.atEnd()) { @@ -120,6 +96,44 @@ void CockatriceXml3Parser::loadSetsFromXml(QXmlStreamReader &xml) } } +QString CockatriceXml3Parser::getMainCardType(QString &type) +{ + QString result = type; + /* + Legendary Artifact Creature - Golem + Instant // Instant + */ + + int pos; + if ((pos = result.indexOf('-')) != -1) { + result.remove(pos, result.length()); + } + + if ((pos = result.indexOf("—")) != -1) { + result.remove(pos, result.length()); + } + + if ((pos = result.indexOf("//")) != -1) { + result.remove(pos, result.length()); + } + + result = result.simplified(); + /* + Legendary Artifact Creature + Instant + */ + + if ((pos = result.lastIndexOf(' ')) != -1) { + result = result.mid(pos + 1); + } + /* + Creature + Instant + */ + + return result; +} + void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml) { while (!xml.atEnd()) { @@ -128,59 +142,77 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml) } if (xml.name() == "card") { - QString name, manacost, cmc, type, pt, text, loyalty; - QStringList colors; + QString name = QString(""); + QString text = QString(""); + QVariantHash properties = QVariantHash(); + QString colors = QString(""); QList relatedCards, reverseRelatedCards; - QStringMap customPicURLs; - MuidMap muids; - QStringMap uuids, collectorNumbers, rarities; - SetList sets; + CardInfoPerSetMap sets = CardInfoPerSetMap(); int tableRow = 0; bool cipt = false; bool isToken = false; bool upsideDown = false; + while (!xml.atEnd()) { if (xml.readNext() == QXmlStreamReader::EndElement) { break; } - + // variable - assigned properties if (xml.name() == "name") { name = xml.readElementText(); - } else if (xml.name() == "manacost") { - manacost = xml.readElementText(); - } else if (xml.name() == "cmc") { - cmc = xml.readElementText(); - } else if (xml.name() == "type") { - type = xml.readElementText(); - } else if (xml.name() == "pt") { - pt = xml.readElementText(); } else if (xml.name() == "text") { text = xml.readElementText(); + } else if (xml.name() == "color") { + colors.append(xml.readElementText()); + } else if (xml.name() == "token") { + isToken = static_cast(xml.readElementText().toInt()); + // generic properties + } else if (xml.name() == "manacost") { + properties.insert("manacost", xml.readElementText()); + } else if (xml.name() == "cmc") { + properties.insert("cmc", xml.readElementText()); + } else if (xml.name() == "type") { + QString type = xml.readElementText(); + properties.insert("type", type); + properties.insert("maintype", getMainCardType(type)); + } else if (xml.name() == "pt") { + properties.insert("pt", xml.readElementText()); + } else if (xml.name() == "loyalty") { + properties.insert("loyalty", xml.readElementText()); + // positioning info + } else if (xml.name() == "tablerow") { + tableRow = xml.readElementText().toInt(); + } else if (xml.name() == "cipt") { + cipt = (xml.readElementText() == "1"); + } else if (xml.name() == "upsidedown") { + upsideDown = (xml.readElementText() == "1"); + // sets } else if (xml.name() == "set") { + // NOTE: attributes must be read before readElementText() QXmlStreamAttributes attrs = xml.attributes(); QString setName = xml.readElementText(); - sets.append(internalAddSet(setName)); + CardInfoPerSet setInfo(internalAddSet(setName)); if (attrs.hasAttribute("muId")) { - muids[setName] = attrs.value("muId").toString().toInt(); + setInfo.setProperty("muid", attrs.value("muId").toString()); } if (attrs.hasAttribute("muId")) { - uuids[setName] = attrs.value("uuId").toString(); + setInfo.setProperty("uuid", attrs.value("uuId").toString()); } if (attrs.hasAttribute("picURL")) { - customPicURLs[setName] = attrs.value("picURL").toString(); + setInfo.setProperty("picurl", attrs.value("picURL").toString()); } if (attrs.hasAttribute("num")) { - collectorNumbers[setName] = attrs.value("num").toString(); + setInfo.setProperty("num", attrs.value("num").toString()); } if (attrs.hasAttribute("rarity")) { - rarities[setName] = attrs.value("rarity").toString(); + setInfo.setProperty("rarity", attrs.value("rarity").toString()); } - } else if (xml.name() == "color") { - colors << xml.readElementText(); + sets.insert(setName, setInfo); + // relatd cards } else if (xml.name() == "related" || xml.name() == "reverse-related") { bool attach = false; bool exclude = false; @@ -217,16 +249,6 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml) } else { relatedCards << relation; } - } else if (xml.name() == "tablerow") { - tableRow = xml.readElementText().toInt(); - } else if (xml.name() == "cipt") { - cipt = (xml.readElementText() == "1"); - } else if (xml.name() == "upsidedown") { - upsideDown = (xml.readElementText() == "1"); - } else if (xml.name() == "loyalty") { - loyalty = xml.readElementText(); - } else if (xml.name() == "token") { - isToken = static_cast(xml.readElementText().toInt()); } else if (xml.name() != "") { qDebug() << "[CockatriceXml3Parser] Unknown card property" << xml.name() << ", trying to continue anyway"; @@ -234,9 +256,9 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml) } } - CardInfoPtr newCard = CardInfo::newInstance( - name, isToken, manacost, cmc, type, pt, text, colors, relatedCards, reverseRelatedCards, upsideDown, - loyalty, cipt, tableRow, sets, customPicURLs, muids, uuids, collectorNumbers, rarities); + properties.insert("colors", colors); + CardInfoPtr newCard = CardInfo::newInstance(name, text, isToken, properties, relatedCards, + reverseRelatedCards, sets, cipt, tableRow, upsideDown); emit addCard(newCard); } } @@ -266,38 +288,60 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfoPtr &in return xml; } - xml.writeStartElement("card"); - xml.writeTextElement("name", info->getName()); - - const SetList &sets = info->getSets(); QString tmpString; - QString tmpSet; - for (int i = 0; i < sets.size(); i++) { + + xml.writeStartElement("card"); + + // variable - assigned properties + xml.writeTextElement("name", info->getName()); + xml.writeTextElement("text", info->getText()); + if (info->getIsToken()) { + xml.writeTextElement("token", "1"); + } + + // generic properties + xml.writeTextElement("manacost", info->getProperty("manacost")); + xml.writeTextElement("cmc", info->getProperty("cmc")); + xml.writeTextElement("type", info->getProperty("type")); + + int colorSize = info->getColors().size(); + for (int i = 0; i < colorSize; ++i) { + xml.writeTextElement("color", info->getColors().at(i)); + } + + tmpString = info->getProperty("pt"); + if (!tmpString.isEmpty()) { + xml.writeTextElement("pt", tmpString); + } + + tmpString = info->getProperty("loyalty"); + if (!tmpString.isEmpty()) { + xml.writeTextElement("loyalty", tmpString); + } + + // sets + const CardInfoPerSetMap sets = info->getSets(); + for (CardInfoPerSet set : sets) { xml.writeStartElement("set"); + xml.writeAttribute("rarity", set.getProperty("rarity")); + xml.writeAttribute("muId", set.getProperty("muid")); + xml.writeAttribute("uuId", set.getProperty("uuid")); - tmpSet = sets[i]->getShortName(); - xml.writeAttribute("rarity", info->getRarity(tmpSet)); - xml.writeAttribute("muId", QString::number(info->getMuId(tmpSet))); - xml.writeAttribute("uuId", info->getUuId(tmpSet)); - - tmpString = info->getCollectorNumber(tmpSet); + tmpString = set.getProperty("num"); if (!tmpString.isEmpty()) { - xml.writeAttribute("num", info->getCollectorNumber(tmpSet)); + xml.writeAttribute("num", tmpString); } - tmpString = info->getCustomPicURL(tmpSet); + tmpString = set.getProperty("picurl"); if (!tmpString.isEmpty()) { xml.writeAttribute("picURL", tmpString); } - xml.writeCharacters(tmpSet); + xml.writeCharacters(set.getPtr()->getShortName()); xml.writeEndElement(); } - const QStringList &colors = info->getColors(); - for (int i = 0; i < colors.size(); i++) { - xml.writeTextElement("color", colors[i]); - } + // related cards const QList related = info->getRelatedCards(); for (auto i : related) { xml.writeStartElement("related"); @@ -343,23 +387,12 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfoPtr &in xml.writeCharacters(i->getName()); xml.writeEndElement(); } - xml.writeTextElement("manacost", info->getManaCost()); - xml.writeTextElement("cmc", info->getCmc()); - xml.writeTextElement("type", info->getCardType()); - if (!info->getPowTough().isEmpty()) { - xml.writeTextElement("pt", info->getPowTough()); - } + + // positioning xml.writeTextElement("tablerow", QString::number(info->getTableRow())); - xml.writeTextElement("text", info->getText()); - if (info->getMainCardType() == "Planeswalker") { - xml.writeTextElement("loyalty", info->getLoyalty()); - } if (info->getCipt()) { xml.writeTextElement("cipt", "1"); } - if (info->getIsToken()) { - xml.writeTextElement("token", "1"); - } if (info->getUpsideDownArt()) { xml.writeTextElement("upsidedown", "1"); } diff --git a/cockatrice/src/carddbparser/cockatricexml3.h b/cockatrice/src/carddbparser/cockatricexml3.h index 286ee3af..109832cf 100644 --- a/cockatrice/src/carddbparser/cockatricexml3.h +++ b/cockatrice/src/carddbparser/cockatricexml3.h @@ -11,27 +11,18 @@ class CockatriceXml3Parser : public ICardDatabaseParser Q_INTERFACES(ICardDatabaseParser) public: CockatriceXml3Parser() = default; - ~CockatriceXml3Parser() = default; - bool getCanParseFile(const QString &name, QIODevice &device); - void parseFile(QIODevice &device); - bool saveToFile(SetNameMap sets, CardNameMap cards, const QString &fileName); - void clearSetlist(); + ~CockatriceXml3Parser() override = default; + bool getCanParseFile(const QString &name, QIODevice &device) override; + void parseFile(QIODevice &device) override; + bool saveToFile(SetNameMap sets, CardNameMap cards, const QString &fileName) override; private: - /* - * A cached list of the available sets, needed to cross-reference sets from cards. - */ - SetNameMap sets; - - CardSetPtr internalAddSet(const QString &setName, - const QString &longName = "", - const QString &setType = "", - const QDate &releaseDate = QDate()); void loadCardsFromXml(QXmlStreamReader &xml); void loadSetsFromXml(QXmlStreamReader &xml); + QString getMainCardType(QString &type); signals: - void addCard(CardInfoPtr card); - void addSet(CardSetPtr set); + void addCard(CardInfoPtr card) override; + void addSet(CardSetPtr set) override; }; #endif \ No newline at end of file diff --git a/cockatrice/src/carddbparser/cockatricexml4.cpp b/cockatrice/src/carddbparser/cockatricexml4.cpp new file mode 100644 index 00000000..a3b2adf0 --- /dev/null +++ b/cockatrice/src/carddbparser/cockatricexml4.cpp @@ -0,0 +1,362 @@ +#include "cockatricexml4.h" + +#include +#include +#include + +#define COCKATRICE_XML4_TAGNAME "cockatrice_carddatabase" +#define COCKATRICE_XML4_TAGVER 4 + +bool CockatriceXml4Parser::getCanParseFile(const QString &fileName, QIODevice &device) +{ + qDebug() << "[CockatriceXml4Parser] Trying to parse: " << fileName; + + if (!fileName.endsWith(".xml", Qt::CaseInsensitive)) { + qDebug() << "[CockatriceXml4Parser] Parsing failed: wrong extension"; + return false; + } + + QXmlStreamReader xml(&device); + while (!xml.atEnd()) { + if (xml.readNext() == QXmlStreamReader::StartElement) { + if (xml.name() == COCKATRICE_XML4_TAGNAME) { + int version = xml.attributes().value("version").toString().toInt(); + if (version == COCKATRICE_XML4_TAGVER) { + return true; + } else { + qDebug() << "[CockatriceXml4Parser] Parsing failed: wrong version" << version; + return false; + } + + } else { + qDebug() << "[CockatriceXml4Parser] Parsing failed: wrong element tag" << xml.name(); + return false; + } + } + } + + return true; +} + +void CockatriceXml4Parser::parseFile(QIODevice &device) +{ + QXmlStreamReader xml(&device); + while (!xml.atEnd()) { + if (xml.readNext() == QXmlStreamReader::StartElement) { + while (!xml.atEnd()) { + if (xml.readNext() == QXmlStreamReader::EndElement) { + break; + } + + if (xml.name() == "sets") { + loadSetsFromXml(xml); + } else if (xml.name() == "cards") { + loadCardsFromXml(xml); + } else if (xml.name() != "") { + qDebug() << "[CockatriceXml4Parser] Unknown item" << xml.name() << ", trying to continue anyway"; + xml.skipCurrentElement(); + } + } + } + } +} + +void CockatriceXml4Parser::loadSetsFromXml(QXmlStreamReader &xml) +{ + while (!xml.atEnd()) { + if (xml.readNext() == QXmlStreamReader::EndElement) { + break; + } + + if (xml.name() == "set") { + QString shortName, longName, setType; + QDate releaseDate; + while (!xml.atEnd()) { + if (xml.readNext() == QXmlStreamReader::EndElement) { + break; + } + + if (xml.name() == "name") { + shortName = xml.readElementText(); + } else if (xml.name() == "longname") { + longName = xml.readElementText(); + } else if (xml.name() == "settype") { + setType = xml.readElementText(); + } else if (xml.name() == "releasedate") { + releaseDate = QDate::fromString(xml.readElementText(), Qt::ISODate); + } else if (xml.name() != "") { + qDebug() << "[CockatriceXml4Parser] Unknown set property" << xml.name() + << ", trying to continue anyway"; + xml.skipCurrentElement(); + } + } + + internalAddSet(shortName, longName, setType, releaseDate); + } + } +} + +QVariantHash CockatriceXml4Parser::loadCardPropertiesFromXml(QXmlStreamReader &xml) +{ + QVariantHash properties = QVariantHash(); + while (!xml.atEnd()) { + if (xml.readNext() == QXmlStreamReader::EndElement) { + break; + } + + if (xml.name() != "") { + properties.insert(xml.name().toString(), xml.readElementText()); + } + } + return properties; +} + +void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml) +{ + while (!xml.atEnd()) { + if (xml.readNext() == QXmlStreamReader::EndElement) { + break; + } + + if (xml.name() == "card") { + QString name = QString(""); + QString text = QString(""); + QVariantHash properties = QVariantHash(); + QList relatedCards, reverseRelatedCards; + CardInfoPerSetMap sets = CardInfoPerSetMap(); + int tableRow = 0; + bool cipt = false; + bool isToken = false; + bool upsideDown = false; + + while (!xml.atEnd()) { + if (xml.readNext() == QXmlStreamReader::EndElement) { + break; + } + // variable - assigned properties + if (xml.name() == "name") { + name = xml.readElementText(); + } else if (xml.name() == "text") { + text = xml.readElementText(); + } else if (xml.name() == "token") { + isToken = static_cast(xml.readElementText().toInt()); + // generic properties + } else if (xml.name() == "prop") { + properties = loadCardPropertiesFromXml(xml); + // positioning info + } else if (xml.name() == "tablerow") { + tableRow = xml.readElementText().toInt(); + } else if (xml.name() == "cipt") { + cipt = (xml.readElementText() == "1"); + } else if (xml.name() == "upsidedown") { + upsideDown = (xml.readElementText() == "1"); + // sets + } else if (xml.name() == "set") { + // NOTE: attributes but be read before readElementText() + QXmlStreamAttributes attrs = xml.attributes(); + QString setName = xml.readElementText(); + CardInfoPerSet setInfo(internalAddSet(setName)); + for (QXmlStreamAttribute attr : attrs) { + setInfo.setProperty(attr.name().toString(), attr.value().toString()); + } + sets.insert(setName, setInfo); + // relatd cards + } else if (xml.name() == "related" || xml.name() == "reverse-related") { + bool attach = false; + bool exclude = false; + bool variable = false; + int count = 1; + QXmlStreamAttributes attrs = xml.attributes(); + QString cardName = xml.readElementText(); + if (attrs.hasAttribute("count")) { + if (attrs.value("count").toString().indexOf("x=") == 0) { + variable = true; + count = attrs.value("count").toString().remove(0, 2).toInt(); + } else if (attrs.value("count").toString().indexOf("x") == 0) { + variable = true; + } else { + count = attrs.value("count").toString().toInt(); + } + + if (count < 1) { + count = 1; + } + } + + if (attrs.hasAttribute("attach")) { + attach = true; + } + + if (attrs.hasAttribute("exclude")) { + exclude = true; + } + + auto *relation = new CardRelation(cardName, attach, exclude, variable, count); + if (xml.name() == "reverse-related") { + reverseRelatedCards << relation; + } else { + relatedCards << relation; + } + } else if (xml.name() != "") { + qDebug() << "[CockatriceXml4Parser] Unknown card property" << xml.name() + << ", trying to continue anyway"; + xml.skipCurrentElement(); + } + } + + CardInfoPtr newCard = CardInfo::newInstance(name, text, isToken, properties, relatedCards, + reverseRelatedCards, sets, cipt, tableRow, upsideDown); + emit addCard(newCard); + } + } +} + +static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardSetPtr &set) +{ + if (set.isNull()) { + qDebug() << "&operator<< set is nullptr"; + return xml; + } + + xml.writeStartElement("set"); + xml.writeTextElement("name", set->getShortName()); + xml.writeTextElement("longname", set->getLongName()); + xml.writeTextElement("settype", set->getSetType()); + xml.writeTextElement("releasedate", set->getReleaseDate().toString(Qt::ISODate)); + xml.writeEndElement(); + + return xml; +} + +static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfoPtr &info) +{ + if (info.isNull()) { + qDebug() << "operator<< info is nullptr"; + return xml; + } + + QString tmpString; + + xml.writeStartElement("card"); + + // variable - assigned properties + xml.writeTextElement("name", info->getName()); + xml.writeTextElement("text", info->getText()); + if (info->getIsToken()) { + xml.writeTextElement("token", "1"); + } + + // generic properties + xml.writeStartElement("prop"); + for (QString propName : info->getProperties()) { + xml.writeTextElement(propName, info->getProperty(propName)); + } + xml.writeEndElement(); + + // sets + for (CardInfoPerSet set : info->getSets()) { + xml.writeStartElement("set"); + for (QString propName : set.getProperties()) { + xml.writeAttribute(propName, set.getProperty(propName)); + } + + xml.writeCharacters(set.getPtr()->getShortName()); + xml.writeEndElement(); + } + + // related cards + const QList related = info->getRelatedCards(); + for (auto i : related) { + xml.writeStartElement("related"); + if (i->getDoesAttach()) { + xml.writeAttribute("attach", "attach"); + } + if (i->getIsCreateAllExclusion()) { + xml.writeAttribute("exclude", "exclude"); + } + + if (i->getIsVariable()) { + if (1 == i->getDefaultCount()) { + xml.writeAttribute("count", "x"); + } else { + xml.writeAttribute("count", "x=" + QString::number(i->getDefaultCount())); + } + } else if (1 != i->getDefaultCount()) { + xml.writeAttribute("count", QString::number(i->getDefaultCount())); + } + xml.writeCharacters(i->getName()); + xml.writeEndElement(); + } + const QList reverseRelated = info->getReverseRelatedCards(); + for (auto i : reverseRelated) { + xml.writeStartElement("reverse-related"); + if (i->getDoesAttach()) { + xml.writeAttribute("attach", "attach"); + } + + if (i->getIsCreateAllExclusion()) { + xml.writeAttribute("exclude", "exclude"); + } + + if (i->getIsVariable()) { + if (1 == i->getDefaultCount()) { + xml.writeAttribute("count", "x"); + } else { + xml.writeAttribute("count", "x=" + QString::number(i->getDefaultCount())); + } + } else if (1 != i->getDefaultCount()) { + xml.writeAttribute("count", QString::number(i->getDefaultCount())); + } + xml.writeCharacters(i->getName()); + xml.writeEndElement(); + } + + // positioning + xml.writeTextElement("tablerow", QString::number(info->getTableRow())); + if (info->getCipt()) { + xml.writeTextElement("cipt", "1"); + } + if (info->getUpsideDownArt()) { + xml.writeTextElement("upsidedown", "1"); + } + + xml.writeEndElement(); // card + + return xml; +} + +bool CockatriceXml4Parser::saveToFile(SetNameMap sets, CardNameMap cards, const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QIODevice::WriteOnly)) { + return false; + } + + QXmlStreamWriter xml(&file); + + xml.setAutoFormatting(true); + xml.writeStartDocument(); + xml.writeStartElement(COCKATRICE_XML4_TAGNAME); + xml.writeAttribute("version", QString::number(COCKATRICE_XML4_TAGVER)); + + if (sets.count() > 0) { + xml.writeStartElement("sets"); + for (CardSetPtr set : sets) { + xml << set; + } + xml.writeEndElement(); + } + + if (cards.count() > 0) { + xml.writeStartElement("cards"); + for (CardInfoPtr card : cards) { + xml << card; + } + xml.writeEndElement(); + } + + xml.writeEndElement(); // cockatrice_carddatabase + xml.writeEndDocument(); + + return true; +} \ No newline at end of file diff --git a/cockatrice/src/carddbparser/cockatricexml4.h b/cockatrice/src/carddbparser/cockatricexml4.h new file mode 100644 index 00000000..cc37c4f3 --- /dev/null +++ b/cockatrice/src/carddbparser/cockatricexml4.h @@ -0,0 +1,28 @@ +#ifndef COCKATRICE_XML4_H +#define COCKATRICE_XML4_H + +#include + +#include "carddatabaseparser.h" + +class CockatriceXml4Parser : public ICardDatabaseParser +{ + Q_OBJECT + Q_INTERFACES(ICardDatabaseParser) +public: + CockatriceXml4Parser() = default; + ~CockatriceXml4Parser() override = default; + bool getCanParseFile(const QString &name, QIODevice &device) override; + void parseFile(QIODevice &device) override; + bool saveToFile(SetNameMap sets, CardNameMap cards, const QString &fileName) override; + +private: + QVariantHash loadCardPropertiesFromXml(QXmlStreamReader &xml); + void loadCardsFromXml(QXmlStreamReader &xml); + void loadSetsFromXml(QXmlStreamReader &xml); +signals: + void addCard(CardInfoPtr card) override; + void addSet(CardSetPtr set) override; +}; + +#endif \ No newline at end of file diff --git a/cockatrice/src/cardframe.cpp b/cockatrice/src/cardframe.cpp index eecbc328..fd1d0873 100644 --- a/cockatrice/src/cardframe.cpp +++ b/cockatrice/src/cardframe.cpp @@ -1,3 +1,5 @@ +#include + #include "cardframe.h" #include "cardinfopicture.h" @@ -16,6 +18,7 @@ CardFrame::CardFrame(const QString &cardName, QWidget *parent) : QTabWidget(pare pic->setObjectName("pic"); text = new CardInfoText(); text->setObjectName("text"); + connect(text, SIGNAL(linkActivated(const QString &)), this, SLOT(setCard(const QString &))); tab1 = new QWidget(this); tab2 = new QWidget(this); @@ -93,10 +96,10 @@ void CardFrame::setCard(CardInfoPtr card) disconnect(info.data(), nullptr, this, nullptr); } - info = card; + info = std::move(card); if (info) { - connect(info.data(), SIGNAL(destroyed()), this, SLOT(clear())); + connect(info.data(), SIGNAL(destroyed()), this, SLOT(clearCard())); } text->setCard(info); @@ -115,7 +118,7 @@ void CardFrame::setCard(AbstractCardItem *card) } } -void CardFrame::clear() +void CardFrame::clearCard() { setCard((CardInfoPtr) nullptr); } diff --git a/cockatrice/src/cardframe.h b/cockatrice/src/cardframe.h index cf8b2ad0..5023fd70 100644 --- a/cockatrice/src/cardframe.h +++ b/cockatrice/src/cardframe.h @@ -37,7 +37,7 @@ public slots: void setCard(CardInfoPtr card); void setCard(const QString &cardName); void setCard(AbstractCardItem *card); - void clear(); + void clearCard(); void setViewMode(int mode); }; diff --git a/cockatrice/src/cardinfotext.cpp b/cockatrice/src/cardinfotext.cpp index 9f315751..448b276b 100644 --- a/cockatrice/src/cardinfotext.cpp +++ b/cockatrice/src/cardinfotext.cpp @@ -1,137 +1,83 @@ #include "cardinfotext.h" - #include "carditem.h" +#include "game_specific_terms.h" #include "main.h" + #include #include #include CardInfoText::CardInfoText(QWidget *parent) : QFrame(parent), info(nullptr) { - nameLabel1 = new QLabel; - nameLabel2 = new QLabel; - nameLabel2->setWordWrap(true); - nameLabel2->setTextInteractionFlags(Qt::TextBrowserInteraction); - manacostLabel1 = new QLabel; - manacostLabel2 = new QLabel; - manacostLabel2->setWordWrap(true); - manacostLabel2->setTextInteractionFlags(Qt::TextBrowserInteraction); - colorLabel1 = new QLabel; - colorLabel2 = new QLabel; - colorLabel2->setWordWrap(true); - colorLabel2->setTextInteractionFlags(Qt::TextBrowserInteraction); - cardtypeLabel1 = new QLabel; - cardtypeLabel2 = new QLabel; - cardtypeLabel2->setWordWrap(true); - cardtypeLabel2->setTextInteractionFlags(Qt::TextBrowserInteraction); - powtoughLabel1 = new QLabel; - powtoughLabel2 = new QLabel; - powtoughLabel2->setTextInteractionFlags(Qt::TextBrowserInteraction); - loyaltyLabel1 = new QLabel; - loyaltyLabel2 = new QLabel; - loyaltyLabel1->setTextInteractionFlags(Qt::TextBrowserInteraction); + nameLabel = new QLabel; + nameLabel->setOpenExternalLinks(false); + connect(nameLabel, SIGNAL(linkActivated(const QString &)), this, SIGNAL(linkActivated(const QString &))); textLabel = new QTextEdit(); textLabel->setReadOnly(true); QGridLayout *grid = new QGridLayout(this); - int row = 0; - grid->addWidget(nameLabel1, row, 0); - grid->addWidget(nameLabel2, row++, 1); - grid->addWidget(manacostLabel1, row, 0); - grid->addWidget(manacostLabel2, row++, 1); - grid->addWidget(colorLabel1, row, 0); - grid->addWidget(colorLabel2, row++, 1); - grid->addWidget(cardtypeLabel1, row, 0); - grid->addWidget(cardtypeLabel2, row++, 1); - grid->addWidget(powtoughLabel1, row, 0); - grid->addWidget(powtoughLabel2, row++, 1); - grid->addWidget(loyaltyLabel1, row, 0); - grid->addWidget(loyaltyLabel2, row++, 1); - grid->addWidget(textLabel, row, 0, -1, 2); - grid->setRowStretch(row, 1); + grid->addWidget(nameLabel, 0, 0); + grid->addWidget(textLabel, 1, 0, -1, 2); + grid->setRowStretch(1, 1); grid->setColumnStretch(1, 1); retranslateUi(); } -// Reset every label which is optionally hidden -void CardInfoText::resetLabels() -{ - nameLabel1->show(); - nameLabel2->show(); - manacostLabel1->show(); - manacostLabel2->show(); - colorLabel1->show(); - colorLabel2->show(); - cardtypeLabel1->show(); - cardtypeLabel2->show(); - powtoughLabel1->show(); - powtoughLabel2->show(); - loyaltyLabel1->show(); - loyaltyLabel2->show(); - textLabel->show(); -} + void CardInfoText::setCard(CardInfoPtr card) { - if (card) { - resetLabels(); - nameLabel2->setText(card->getName()); - if (!card->getManaCost().isEmpty()) { - manacostLabel2->setText(card->getManaCost()); - } else { - manacostLabel1->hide(); - manacostLabel2->hide(); - } - if (!card->getColors().isEmpty()) { - colorLabel2->setText(card->getColors().join("")); - } else { - colorLabel2->setText("Colorless"); - } - cardtypeLabel2->setText(card->getCardType()); - if (!card->getPowTough().isEmpty()) { - powtoughLabel2->setText(card->getPowTough()); - } else { - powtoughLabel1->hide(); - powtoughLabel2->hide(); - } - if (!card->getLoyalty().isEmpty()) { - loyaltyLabel2->setText(card->getLoyalty()); - } else { - loyaltyLabel1->hide(); - loyaltyLabel2->hide(); - } - textLabel->setText(card->getText()); - } else { - nameLabel1->hide(); - nameLabel2->hide(); - manacostLabel1->hide(); - manacostLabel2->hide(); - colorLabel1->hide(); - colorLabel2->hide(); - cardtypeLabel1->hide(); - cardtypeLabel2->hide(); - powtoughLabel1->hide(); - powtoughLabel2->hide(); - loyaltyLabel1->hide(); - loyaltyLabel2->hide(); - textLabel->hide(); + if (card == nullptr) { + nameLabel->setText(""); + textLabel->setText(""); + return; } + + QString text = ""; + text += QString("") + .arg(tr("Name:"), card->getName().toHtmlEscaped()); + + QStringList cardProps = card->getProperties(); + foreach (QString key, cardProps) { + QString keyText = Mtg::getNicePropertyName(key).toHtmlEscaped() + ":"; + text += + QString("").arg(keyText, card->getProperty(key).toHtmlEscaped()); + } + + auto relatedCards = card->getRelatedCards(); + auto reverserelatedCards2Me = card->getReverseRelatedCards2Me(); + if (relatedCards.size() || reverserelatedCards2Me.size()) { + text += QString(""; + } + + text += "
%1%2
%1%2
%1").arg(tr("Related cards:")); + + for (int i = 0; i < relatedCards.size(); ++i) { + QString tmp = relatedCards.at(i)->getName().toHtmlEscaped(); + text += "" + tmp + "
"; + } + + for (int i = 0; i < reverserelatedCards2Me.size(); ++i) { + QString tmp = reverserelatedCards2Me.at(i)->getName().toHtmlEscaped(); + text += "" + tmp + "
"; + } + + text += "
"; + nameLabel->setText(text); + textLabel->setText(card->getText()); } void CardInfoText::setInvalidCardName(const QString &cardName) { - nameLabel1->setText(tr("Unknown card:")); - nameLabel1->show(); - nameLabel2->setText(cardName); - nameLabel2->show(); + nameLabel->setText(tr("Unknown card:") + " " + cardName); + textLabel->setText(""); } void CardInfoText::retranslateUi() { - nameLabel1->setText(tr("Name:")); - manacostLabel1->setText(tr("Mana cost:")); - colorLabel1->setText(tr("Color(s):")); - cardtypeLabel1->setText(tr("Card type:")); - powtoughLabel1->setText(tr("P / T:")); - loyaltyLabel1->setText(tr("Loyalty:")); + /* + * There's no way we can really translate the text currently being rendered. + * The best we can do is invalidate the current text. + */ + setInvalidCardName(""); } diff --git a/cockatrice/src/cardinfotext.h b/cockatrice/src/cardinfotext.h index 49445c09..7ee0a890 100644 --- a/cockatrice/src/cardinfotext.h +++ b/cockatrice/src/cardinfotext.h @@ -12,23 +12,17 @@ class CardInfoText : public QFrame Q_OBJECT private: - QLabel *nameLabel1, *nameLabel2; - QLabel *manacostLabel1, *manacostLabel2; - QLabel *colorLabel1, *colorLabel2; - QLabel *cardtypeLabel1, *cardtypeLabel2; - QLabel *powtoughLabel1, *powtoughLabel2; - QLabel *loyaltyLabel1, *loyaltyLabel2; + QLabel *nameLabel; QTextEdit *textLabel; - CardInfoPtr info; - void resetLabels(); - public: CardInfoText(QWidget *parent = 0); void retranslateUi(); void setInvalidCardName(const QString &cardName); +signals: + void linkActivated(const QString &link); public slots: void setCard(CardInfoPtr card); }; diff --git a/cockatrice/src/cardinfowidget.cpp b/cockatrice/src/cardinfowidget.cpp index 170540df..4bf8e94e 100644 --- a/cockatrice/src/cardinfowidget.cpp +++ b/cockatrice/src/cardinfowidget.cpp @@ -1,6 +1,8 @@ -#include "cardinfowidget.h" +#include + #include "cardinfopicture.h" #include "cardinfotext.h" +#include "cardinfowidget.h" #include "carditem.h" #include "main.h" #include @@ -14,8 +16,9 @@ CardInfoWidget::CardInfoWidget(const QString &cardName, QWidget *parent, Qt::Win pic->setObjectName("pic"); text = new CardInfoText(); text->setObjectName("text"); + connect(text, SIGNAL(linkActivated(const QString &)), this, SLOT(setCard(const QString &))); - QVBoxLayout *layout = new QVBoxLayout(); + auto *layout = new QVBoxLayout(); layout->setObjectName("layout"); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); @@ -26,7 +29,7 @@ CardInfoWidget::CardInfoWidget(const QString &cardName, QWidget *parent, Qt::Win setFrameStyle(QFrame::Panel | QFrame::Raised); QDesktopWidget desktopWidget; int pixmapHeight = desktopWidget.screenGeometry().height() / 3; - int pixmapWidth = pixmapHeight / aspectRatio; + int pixmapWidth = static_cast(pixmapHeight / aspectRatio); pic->setFixedWidth(pixmapWidth); pic->setFixedHeight(pixmapHeight); setFixedWidth(pixmapWidth + 150); @@ -41,7 +44,7 @@ void CardInfoWidget::setCard(CardInfoPtr card) { if (info) disconnect(info.data(), nullptr, this, nullptr); - info = card; + info = std::move(card); if (info) connect(info.data(), SIGNAL(destroyed()), this, SLOT(clear())); diff --git a/cockatrice/src/cardinfowidget.h b/cockatrice/src/cardinfowidget.h index f89ca504..7e986b75 100644 --- a/cockatrice/src/cardinfowidget.h +++ b/cockatrice/src/cardinfowidget.h @@ -22,7 +22,7 @@ private: CardInfoText *text; public: - CardInfoWidget(const QString &cardName, QWidget *parent = 0, Qt::WindowFlags f = 0); + explicit CardInfoWidget(const QString &cardName, QWidget *parent = nullptr, Qt::WindowFlags f = nullptr); public slots: void setCard(CardInfoPtr card); diff --git a/cockatrice/src/decklistmodel.cpp b/cockatrice/src/decklistmodel.cpp index 8b6e7bf5..7b66a927 100644 --- a/cockatrice/src/decklistmodel.cpp +++ b/cockatrice/src/decklistmodel.cpp @@ -322,9 +322,7 @@ QModelIndex DeckListModel::addCard(const QString &cardName, const QString &zoneN // This is usually called from tab_deck_editor // So we'll create a new CardInfo with the name // and default values for all fields - info = CardInfo::newInstance(cardName, false, nullptr, nullptr, "unknown", nullptr, nullptr, QStringList(), - QList(), QList(), false, 0, false, 0, - SetList(), QStringMap(), MuidMap(), QStringMap(), QStringMap(), QStringMap()); + info = CardInfo::newInstance(cardName); } else { return {}; } diff --git a/cockatrice/src/decklistmodel.h b/cockatrice/src/decklistmodel.h index 5e4f4dd3..19a0aeca 100644 --- a/cockatrice/src/decklistmodel.h +++ b/cockatrice/src/decklistmodel.h @@ -7,7 +7,6 @@ class DeckLoader; class CardDatabase; -class QProgressDialog; class QPrinter; class QTextCursor; @@ -21,19 +20,19 @@ public: : AbstractDecklistCardNode(_parent), dataNode(_dataNode) { } - int getNumber() const + int getNumber() const override { return dataNode->getNumber(); } - void setNumber(int _number) + void setNumber(int _number) override { dataNode->setNumber(_number); } - QString getName() const + QString getName() const override { return dataNode->getName(); } - void setName(const QString &_name) + void setName(const QString &_name) override { dataNode->setName(_name); } @@ -54,20 +53,20 @@ signals: void deckHashChanged(); public: - DeckListModel(QObject *parent = 0); - ~DeckListModel(); - int rowCount(const QModelIndex &parent) const; - int columnCount(const QModelIndex & /*parent*/ = QModelIndex()) const; - QVariant data(const QModelIndex &index, int role) const; - QVariant headerData(int section, Qt::Orientation orientation, int role) const; - QModelIndex index(int row, int column, const QModelIndex &parent) const; - QModelIndex parent(const QModelIndex &index) const; - Qt::ItemFlags flags(const QModelIndex &index) const; - bool setData(const QModelIndex &index, const QVariant &value, int role); - bool removeRows(int row, int count, const QModelIndex &parent); + explicit DeckListModel(QObject *parent = nullptr); + ~DeckListModel() override; + int rowCount(const QModelIndex &parent) const override; + int columnCount(const QModelIndex & /*parent*/ = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + QModelIndex index(int row, int column, const QModelIndex &parent) const override; + QModelIndex parent(const QModelIndex &index) const override; + 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; QModelIndex findCard(const QString &cardName, const QString &zoneName) const; QModelIndex addCard(const QString &cardName, const QString &zoneName, bool abAddAnyway = false); - void sort(int column, Qt::SortOrder order); + void sort(int column, Qt::SortOrder order) override; void cleanList(); DeckLoader *getDeckList() const { diff --git a/cockatrice/src/dlg_edit_tokens.cpp b/cockatrice/src/dlg_edit_tokens.cpp index be910ff9..81ce5875 100644 --- a/cockatrice/src/dlg_edit_tokens.cpp +++ b/cockatrice/src/dlg_edit_tokens.cpp @@ -17,7 +17,7 @@ #include #include -DlgEditTokens::DlgEditTokens(QWidget *parent) : QDialog(parent), currentCard(0) +DlgEditTokens::DlgEditTokens(QWidget *parent) : QDialog(parent), currentCard(nullptr) { nameLabel = new QLabel(tr("&Name:")); nameEdit = new QLineEdit; @@ -46,7 +46,7 @@ DlgEditTokens::DlgEditTokens(QWidget *parent) : QDialog(parent), currentCard(0) annotationLabel->setBuddy(annotationEdit); connect(annotationEdit, SIGNAL(textChanged(QString)), this, SLOT(annotationChanged(QString))); - QGridLayout *grid = new QGridLayout; + auto *grid = new QGridLayout; grid->addWidget(nameLabel, 0, 0); grid->addWidget(nameEdit, 0, 1); grid->addWidget(colorLabel, 1, 0); @@ -89,15 +89,15 @@ DlgEditTokens::DlgEditTokens(QWidget *parent) : QDialog(parent), currentCard(0) aRemoveToken->setIcon(QPixmap("theme:icons/decrement")); connect(aRemoveToken, SIGNAL(triggered()), this, SLOT(actRemoveToken())); - QToolBar *databaseToolBar = new QToolBar; + auto *databaseToolBar = new QToolBar; databaseToolBar->addAction(aAddToken); databaseToolBar->addAction(aRemoveToken); - QVBoxLayout *leftVBox = new QVBoxLayout; + auto *leftVBox = new QVBoxLayout; leftVBox->addWidget(chooseTokenView); leftVBox->addWidget(databaseToolBar); - QHBoxLayout *hbox = new QHBoxLayout; + auto *hbox = new QHBoxLayout; hbox->addLayout(leftVBox); hbox->addWidget(tokenDataGroupBox); @@ -105,7 +105,7 @@ DlgEditTokens::DlgEditTokens(QWidget *parent) : QDialog(parent), currentCard(0) connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); - QVBoxLayout *mainLayout = new QVBoxLayout; + auto *mainLayout = new QVBoxLayout; mainLayout->addLayout(hbox); mainLayout->addWidget(buttonBox); @@ -154,9 +154,10 @@ void DlgEditTokens::actAddToken() } } while (askAgain); - CardInfoPtr card = CardInfo::newInstance(name, true); - card->addToSet(databaseModel->getDatabase()->getSet(CardDatabase::TOKENS_SETNAME)); + CardInfoPtr card = CardInfo::newInstance(name, "", true); card->setCardType("Token"); + card->addToSet(databaseModel->getDatabase()->getSet(CardDatabase::TOKENS_SETNAME)); + databaseModel->getDatabase()->addCard(card); } @@ -172,7 +173,7 @@ void DlgEditTokens::actRemoveToken() void DlgEditTokens::colorChanged(int colorIndex) { if (currentCard) - currentCard->setColors(QStringList() << QString(colorEdit->itemData(colorIndex).toChar())); + currentCard->setColors(QString(colorEdit->itemData(colorIndex).toChar())); } void DlgEditTokens::ptChanged(const QString &_pt) diff --git a/cockatrice/src/dlg_edit_tokens.h b/cockatrice/src/dlg_edit_tokens.h index 6e9b3666..4f3f5eaf 100644 --- a/cockatrice/src/dlg_edit_tokens.h +++ b/cockatrice/src/dlg_edit_tokens.h @@ -35,7 +35,7 @@ private: QTreeView *chooseTokenView; public: - DlgEditTokens(QWidget *parent = nullptr); + explicit DlgEditTokens(QWidget *parent = nullptr); }; #endif diff --git a/cockatrice/src/filtertree.cpp b/cockatrice/src/filtertree.cpp index 93abf774..1dcb37cf 100644 --- a/cockatrice/src/filtertree.cpp +++ b/cockatrice/src/filtertree.cpp @@ -187,11 +187,8 @@ bool FilterItem::acceptColor(const CardInfoPtr info) const */ int match_count = 0; for (auto &it : converted_term) { - for (auto i = info->getColors().constBegin(); i != info->getColors().constEnd(); i++) { - if ((*i).contains(it, Qt::CaseInsensitive)) { - match_count++; - } - } + if (info->getColors().contains(it, Qt::CaseInsensitive)) + match_count++; } return match_count == converted_term.length(); @@ -205,9 +202,9 @@ bool FilterItem::acceptText(const CardInfoPtr info) const bool FilterItem::acceptSet(const CardInfoPtr info) const { bool status = false; - for (auto i = info->getSets().constBegin(); i != info->getSets().constEnd(); i++) { - if ((*i)->getShortName().compare(term, Qt::CaseInsensitive) == 0 || - (*i)->getLongName().compare(term, Qt::CaseInsensitive) == 0) { + for (const auto &set : info->getSets()) { + if (set.getPtr()->getShortName().compare(term, Qt::CaseInsensitive) == 0 || + set.getPtr()->getLongName().compare(term, Qt::CaseInsensitive) == 0) { status = true; break; } @@ -299,7 +296,7 @@ bool FilterItem::acceptRarity(const CardInfoPtr info) const /* * The purpose of this loop is to only apply one of the replacement - * policies and then escape. If we attempt to layer them ontop of + * policies and then escape. If we attempt to layer them on top of * each other, we will get awkward results (i.e. comythic rare mythic rareon) * Conditional statement will exit once a case is successful in * replacement OR we go through all possible cases. @@ -334,8 +331,8 @@ bool FilterItem::acceptRarity(const CardInfoPtr info) const } } - for (const QString &rareLevel : info->getRarities()) { - if (rareLevel.compare(converted_term, Qt::CaseInsensitive) == 0) { + for (const auto &set : info->getSets()) { + if (set.getProperty("rarity").compare(converted_term, Qt::CaseInsensitive) == 0) { return true; } } diff --git a/cockatrice/src/filtertree.h b/cockatrice/src/filtertree.h index 043bc95c..7227f944 100644 --- a/cockatrice/src/filtertree.h +++ b/cockatrice/src/filtertree.h @@ -1,12 +1,14 @@ + + #ifndef FILTERTREE_H #define FILTERTREE_H +#include "carddatabase.h" +#include "cardfilter.h" #include #include #include - -#include "carddatabase.h" -#include "cardfilter.h" +#include class FilterTreeNode { @@ -33,11 +35,11 @@ public: } virtual FilterTreeNode *parent() const { - return NULL; + return nullptr; } virtual FilterTreeNode *nodeAt(int /* i */) const { - return NULL; + return nullptr; } virtual void deleteAt(int /* i */) { @@ -52,7 +54,7 @@ public: } virtual int index() const { - return (parent() != NULL) ? parent()->childIndex(this) : -1; + return (parent() != nullptr) ? parent()->childIndex(this) : -1; } virtual const QString text() const { @@ -64,27 +66,27 @@ public: } virtual void nodeChanged() const { - if (parent() != NULL) + if (parent() != nullptr) parent()->nodeChanged(); } virtual void preInsertChild(const FilterTreeNode *p, int i) const { - if (parent() != NULL) + if (parent() != nullptr) parent()->preInsertChild(p, i); } virtual void postInsertChild(const FilterTreeNode *p, int i) const { - if (parent() != NULL) + if (parent() != nullptr) parent()->postInsertChild(p, i); } virtual void preRemoveChild(const FilterTreeNode *p, int i) const { - if (parent() != NULL) + if (parent() != nullptr) parent()->preRemoveChild(p, i); } virtual void postRemoveChild(const FilterTreeNode *p, int i) const { - if (parent() != NULL) + if (parent() != nullptr) parent()->postRemoveChild(p, i); } }; @@ -96,13 +98,13 @@ protected: public: virtual ~FilterTreeBranch(); - FilterTreeNode *nodeAt(int i) const; - void deleteAt(int i); - int childCount() const + FilterTreeNode *nodeAt(int i) const override; + void deleteAt(int i) override; + int childCount() const override { return childNodes.size(); } - int childIndex(const FilterTreeNode *node) const; + int childIndex(const FilterTreeNode *node) const override; }; class FilterItemList; @@ -121,8 +123,8 @@ public: } const FilterItemList *findTypeList(CardFilter::Type type) const; FilterItemList *typeList(CardFilter::Type type); - FilterTreeNode *parent() const; - const QString text() const + FilterTreeNode *parent() const override; + const QString text() const override { return CardFilter::attrName(attr); } @@ -144,21 +146,21 @@ public: { return p->attr; } - FilterTreeNode *parent() const + FilterTreeNode *parent() const override { return p; } int termIndex(const QString &term) const; FilterTreeNode *termNode(const QString &term); - const QString text() const + const QString text() const override { return CardFilter::typeName(type); } - bool testTypeAnd(const CardInfoPtr info, CardFilter::Attr attr) const; - bool testTypeAndNot(const CardInfoPtr info, CardFilter::Attr attr) const; - bool testTypeOr(const CardInfoPtr info, CardFilter::Attr attr) const; - bool testTypeOrNot(const CardInfoPtr info, CardFilter::Attr attr) const; + bool testTypeAnd(CardInfoPtr info, CardFilter::Attr attr) const; + bool testTypeAndNot(CardInfoPtr info, CardFilter::Attr attr) const; + bool testTypeOr(CardInfoPtr info, CardFilter::Attr attr) const; + bool testTypeOrNot(CardInfoPtr info, CardFilter::Attr attr) const; }; class FilterItem : public FilterTreeNode @@ -169,10 +171,10 @@ private: public: const QString term; - FilterItem(QString trm, FilterItemList *parent) : p(parent), term(trm) + FilterItem(QString trm, FilterItemList *parent) : p(parent), term(std::move(trm)) { } - virtual ~FilterItem(){}; + virtual ~FilterItem() = default; CardFilter::Attr attr() const { @@ -182,30 +184,30 @@ public: { return p->type; } - FilterTreeNode *parent() const + FilterTreeNode *parent() const override { return p; } - const QString text() const + const QString text() const override { return term; } - bool isLeaf() const + bool isLeaf() const override { return true; } - bool acceptName(const CardInfoPtr info) const; - bool acceptType(const CardInfoPtr info) const; - bool acceptColor(const CardInfoPtr info) const; - bool acceptText(const CardInfoPtr info) const; - bool acceptSet(const CardInfoPtr info) const; - bool acceptManaCost(const CardInfoPtr info) const; - bool acceptCmc(const CardInfoPtr info) const; - bool acceptPowerToughness(const CardInfoPtr info, CardFilter::Attr attr) const; - bool acceptLoyalty(const CardInfoPtr info) const; - bool acceptRarity(const CardInfoPtr info) const; - bool acceptCardAttr(const CardInfoPtr info, CardFilter::Attr attr) const; + bool acceptName(CardInfoPtr info) const; + bool acceptType(CardInfoPtr info) const; + bool acceptColor(CardInfoPtr info) const; + bool acceptText(CardInfoPtr info) const; + bool acceptSet(CardInfoPtr info) const; + bool acceptManaCost(CardInfoPtr info) const; + bool acceptCmc(CardInfoPtr info) const; + bool acceptPowerToughness(CardInfoPtr info, CardFilter::Attr attr) const; + bool acceptLoyalty(CardInfoPtr info) const; + bool acceptRarity(CardInfoPtr info) const; + bool acceptCardAttr(CardInfoPtr info, CardFilter::Attr attr) const; bool relationCheck(int cardInfo) const; }; @@ -224,47 +226,47 @@ private: LogicMap *attrLogicMap(CardFilter::Attr attr); FilterItemList *attrTypeList(CardFilter::Attr attr, CardFilter::Type type); - bool testAttr(const CardInfoPtr info, const LogicMap *lm) const; + bool testAttr(CardInfoPtr info, const LogicMap *lm) const; - void nodeChanged() const + void nodeChanged() const override { emit changed(); } - void preInsertChild(const FilterTreeNode *p, int i) const + void preInsertChild(const FilterTreeNode *p, int i) const override { emit preInsertRow(p, i); } - void postInsertChild(const FilterTreeNode *p, int i) const + void postInsertChild(const FilterTreeNode *p, int i) const override { emit postInsertRow(p, i); } - void preRemoveChild(const FilterTreeNode *p, int i) const + void preRemoveChild(const FilterTreeNode *p, int i) const override { emit preRemoveRow(p, i); } - void postRemoveChild(const FilterTreeNode *p, int i) const + void postRemoveChild(const FilterTreeNode *p, int i) const override { emit postRemoveRow(p, i); } public: FilterTree(); - ~FilterTree(); + ~FilterTree() override; int findTermIndex(CardFilter::Attr attr, CardFilter::Type type, const QString &term); int findTermIndex(const CardFilter *f); FilterTreeNode *termNode(CardFilter::Attr attr, CardFilter::Type type, const QString &term); FilterTreeNode *termNode(const CardFilter *f); FilterTreeNode *attrTypeNode(CardFilter::Attr attr, CardFilter::Type type); - const QString text() const + const QString text() const override { return QString("root"); } - int index() const + int index() const override { return 0; } - bool acceptsCard(const CardInfoPtr info) const; + bool acceptsCard(CardInfoPtr info) const; void clear(); }; diff --git a/cockatrice/src/game_specific_terms.h b/cockatrice/src/game_specific_terms.h new file mode 100644 index 00000000..9e3d0386 --- /dev/null +++ b/cockatrice/src/game_specific_terms.h @@ -0,0 +1,49 @@ +#ifndef GAME_SPECIFIC_TERMS_H +#define GAME_SPECIFIC_TERMS_H + +#include +#include + +/* + * Collection of traslatable property names used in games, + * so we can use Game::Property instead of hardcoding strings. + * Note: Mtg = "Maybe that game" + */ + +namespace Mtg +{ +QString const CardType("type"); +QString const ConvertedManaCost("cmc"); +QString const Colors("colors"); +QString const Loyalty("loyalty"); +QString const MainCardType("maintype"); +QString const ManaCost("manacost"); +QString const PowTough("pt"); +QString const Side("side"); +QString const Layout("layout"); + +inline static const QString getNicePropertyName(QString key) +{ + if (key == CardType) + return QCoreApplication::translate("Mtg", "Card type"); + if (key == ConvertedManaCost) + return QCoreApplication::translate("Mtg", "Converted mana cost"); + if (key == Colors) + return QCoreApplication::translate("Mtg", "Color(s)"); + if (key == Loyalty) + return QCoreApplication::translate("Mtg", "Loyalty"); + if (key == MainCardType) + return QCoreApplication::translate("Mtg", "Main card type"); + if (key == ManaCost) + return QCoreApplication::translate("Mtg", "Mana cost"); + if (key == PowTough) + return QCoreApplication::translate("Mtg", "P / T"); + if (key == Side) + return QCoreApplication::translate("Mtg", "Side"); + if (key == Layout) + return QCoreApplication::translate("Mtg", "Layout"); + return key; +} +}; // namespace Mtg + +#endif \ No newline at end of file diff --git a/cockatrice/src/handle_public_servers.cpp b/cockatrice/src/handle_public_servers.cpp index 11411ccd..7bbbbeb2 100644 --- a/cockatrice/src/handle_public_servers.cpp +++ b/cockatrice/src/handle_public_servers.cpp @@ -1,6 +1,6 @@ #include "handle_public_servers.h" -#include "qt-json/json.h" #include "settingscache.h" +#include #include #include #include @@ -31,19 +31,16 @@ void HandlePublicServers::actFinishParsingDownloadedData() savedHostList = uci.getServerInfo(); // Downloaded data from GitHub - bool jsonSuccessful; - QString jsonData = QString(reply->readAll()); - - auto jsonMap = QtJson::Json::parse(jsonData, jsonSuccessful).toMap(); - - if (jsonSuccessful) { + QJsonParseError parseError{}; + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll(), &parseError); + if (parseError.error == QJsonParseError::NoError) { + QVariantMap jsonMap = jsonResponse.toVariant().toMap(); updateServerINISettings(jsonMap); } else { qDebug() << "[PUBLIC SERVER HANDLER]" - << "JSON Parsing Error"; + << "JSON Parsing Error:" << parseError.errorString(); emit sigPublicServersDownloadedUnsuccessfully(errorCode); } - } else { qDebug() << "[PUBLIC SERVER HANDLER]" << "Error Downloading Public Servers" << errorCode; diff --git a/cockatrice/src/pictureloader.cpp b/cockatrice/src/pictureloader.cpp index 252fab18..cecca1de 100644 --- a/cockatrice/src/pictureloader.cpp +++ b/cockatrice/src/pictureloader.cpp @@ -30,7 +30,9 @@ PictureToLoad::PictureToLoad(CardInfoPtr _card) : card(std::move(_card)) urlTemplates = settingsCache->downloads().getAllURLs(); if (card) { - sortedSets = card->getSets(); + for (const auto &set : card->getSets()) { + sortedSets << set.getPtr(); + } qSort(sortedSets.begin(), sortedSets.end(), SetDownloadPriorityComparator()); // The first time called, nextSet will also populate the Urls for the first set. nextSet(); @@ -240,28 +242,50 @@ QString PictureToLoad::transformUrl(const QString &urlTemplate) const CardSetPtr set = getCurrentSet(); QMap transformMap = QMap(); - + // name transformMap["!name!"] = card->getName(); transformMap["!name_lower!"] = card->getName().toLower(); transformMap["!corrected_name!"] = card->getCorrectedName(); transformMap["!corrected_name_lower!"] = card->getCorrectedName().toLower(); + // card properties + QRegExp rxCardProp("!prop:([^!]+)!"); + int pos = 0; + while ((pos = rxCardProp.indexIn(transformedUrl, pos)) != -1) { + QString propertyName = rxCardProp.cap(1); + pos += rxCardProp.matchedLength(); + QString propertyValue = card->getProperty(propertyName); + if (propertyValue.isEmpty()) { + qDebug() << "PictureLoader: [card: " << card->getName() << " set: " << getSetName() + << "]: Requested property (" << propertyName << ") for Url template (" << urlTemplate + << ") is not available"; + return QString(); + } else { + transformMap["!prop:" + propertyName + "!"] = propertyValue; + } + } + if (set) { - transformMap["!cardid!"] = QString::number(card->getMuId(set->getShortName())); - transformMap["!uuid!"] = card->getUuId(set->getShortName()); - transformMap["!collectornumber!"] = card->getCollectorNumber(set->getShortName()); transformMap["!setcode!"] = set->getShortName(); transformMap["!setcode_lower!"] = set->getShortName().toLower(); transformMap["!setname!"] = set->getLongName(); transformMap["!setname_lower!"] = set->getLongName().toLower(); - } else { - transformMap["!cardid!"] = QString(); - transformMap["!uuid!"] = QString(); - transformMap["!collectornumber!"] = QString(); - transformMap["!setcode!"] = QString(); - transformMap["!setcode_lower!"] = QString(); - transformMap["!setname!"] = QString(); - transformMap["!setname_lower!"] = QString(); + + QRegExp rxSetProp("!set:([^!]+)!"); + pos = 0; // Defined above + while ((pos = rxSetProp.indexIn(transformedUrl, pos)) != -1) { + QString propertyName = rxSetProp.cap(1); + pos += rxSetProp.matchedLength(); + QString propertyValue = card->getSetProperty(set->getShortName(), propertyName); + if (propertyValue.isEmpty()) { + qDebug() << "PictureLoader: [card: " << card->getName() << " set: " << getSetName() + << "]: Requested set property (" << propertyName << ") for Url template (" << urlTemplate + << ") is not available"; + return QString(); + } else { + transformMap["!set:" + propertyName + "!"] = propertyValue; + } + } } for (const QString &prop : transformMap.keys()) { @@ -483,7 +507,7 @@ void PictureLoader::getPixmap(QPixmap &pixmap, CardInfoPtr card, QSize size) return; } - // search for an exact size copy of the picure in cache + // search for an exact size copy of the picture in cache QString key = card->getPixmapCacheKey(); QString sizeKey = key + QLatin1Char('_') + QString::number(size.width()) + QString::number(size.height()); if (QPixmapCache::find(sizeKey, &pixmap)) diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index 1b1386b3..65cdda5f 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -94,7 +94,7 @@ void PlayerArea::setSize(qreal width, qreal height) Player::Player(const ServerInfo_User &info, int _id, bool _local, TabGame *_parent) : QObject(_parent), game(_parent), shortcutsActive(false), defaultNumberTopCards(1), defaultNumberTopCardsToPlaceBelow(1), lastTokenDestroy(true), lastTokenTableRow(0), id(_id), active(false), - local(_local), mirrored(false), handVisible(false), conceded(false), dialogSemaphore(false), deck(0) + local(_local), mirrored(false), handVisible(false), conceded(false), dialogSemaphore(false), deck(nullptr) { userInfo = new ServerInfo_User; userInfo->CopyFrom(info); @@ -115,7 +115,7 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, TabGame *_pare qreal h = deck->boundingRect().width() + 5; - HandCounter *handCounter = new HandCounter(playerArea); + auto *handCounter = new HandCounter(playerArea); handCounter->setPos(base + QPointF(0, h + 10)); qreal h2 = handCounter->boundingRect().height(); @@ -279,8 +279,8 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, TabGame *_pare libraryMenu->addAction(aOpenDeckInDeckEditor); deck->setMenu(libraryMenu, aDrawCard); } else { - handMenu = 0; - libraryMenu = 0; + handMenu = nullptr; + libraryMenu = nullptr; } graveMenu = playerMenu->addMenu(QString()); @@ -356,19 +356,19 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, TabGame *_pare playerMenu->addSeparator(); playerMenu->addAction(aCardMenu); - for (int i = 0; i < playerLists.size(); ++i) { - QAction *newAction = playerLists[i]->addAction(QString()); + for (auto &playerList : playerLists) { + QAction *newAction = playerList->addAction(QString()); newAction->setData(-1); connect(newAction, SIGNAL(triggered()), this, SLOT(playerListActionTriggered())); allPlayersActions.append(newAction); - playerLists[i]->addSeparator(); + playerList->addSeparator(); } } else { - countersMenu = 0; - sbMenu = 0; - aCreateAnotherToken = 0; - createPredefinedTokenMenu = 0; - aCardMenu = 0; + countersMenu = nullptr; + sbMenu = nullptr; + aCreateAnotherToken = nullptr; + createPredefinedTokenMenu = nullptr; + aCardMenu = nullptr; } aTap = new QAction(this); @@ -436,11 +436,11 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, TabGame *_pare connect(aPlayFacedown, SIGNAL(triggered()), this, SLOT(actPlayFacedown())); for (int i = 0; i < 3; ++i) { - QAction *tempAddCounter = new QAction(this); + auto *tempAddCounter = new QAction(this); tempAddCounter->setData(9 + i * 1000); - QAction *tempRemoveCounter = new QAction(this); + auto *tempRemoveCounter = new QAction(this); tempRemoveCounter->setData(10 + i * 1000); - QAction *tempSetCounter = new QAction(this); + auto *tempSetCounter = new QAction(this); tempSetCounter->setData(11 + i * 1000); aAddCounter.append(tempAddCounter); aRemoveCounter.append(tempRemoveCounter); @@ -451,8 +451,8 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, TabGame *_pare } const QList &players = game->getPlayers().values(); - for (int i = 0; i < players.size(); ++i) - addPlayer(players[i]); + for (auto player : players) + addPlayer(player); rearrangeZones(); retranslateUi(); @@ -494,8 +494,8 @@ void Player::addPlayer(Player *player) return; } - for (int i = 0; i < playerLists.size(); ++i) { - QAction *newAction = playerLists[i]->addAction(player->getName()); + for (auto &playerList : playerLists) { + QAction *newAction = playerList->addAction(player->getName()); newAction->setData(player->getId()); connect(newAction, SIGNAL(triggered()), this, SLOT(playerListActionTriggered())); } @@ -507,20 +507,20 @@ void Player::removePlayer(Player *player) return; } - for (int i = 0; i < playerLists.size(); ++i) { - QList actionList = playerLists[i]->actions(); - for (int j = 0; j < actionList.size(); ++j) - if (actionList[j]->data().toInt() == player->getId()) { - playerLists[i]->removeAction(actionList[j]); - actionList[j]->deleteLater(); + for (auto &playerList : playerLists) { + QList actionList = playerList->actions(); + for (auto &j : actionList) + if (j->data().toInt() == player->getId()) { + playerList->removeAction(j); + j->deleteLater(); } } } void Player::playerListActionTriggered() { - QAction *action = static_cast(sender()); - QMenu *menu = static_cast(action->parentWidget()); + auto *action = static_cast(sender()); + auto *menu = static_cast(action->parentWidget()); Command_RevealCards cmd; const int otherPlayerId = action->data().toInt(); @@ -533,9 +533,9 @@ void Player::playerListActionTriggered() } else if (menu == mRevealTopCard) { int decksize = zones.value("deck")->getCards().size(); bool ok; - int number = - QInputDialog::getInt(0, tr("Reveal top cards of library"), tr("Number of cards: (max. %1)").arg(decksize), - defaultNumberTopCards, 1, decksize, 1, &ok); + int number = QInputDialog::getInt(nullptr, tr("Reveal top cards of library"), + tr("Number of cards: (max. %1)").arg(decksize), defaultNumberTopCards, 1, + decksize, 1, &ok); if (ok) { cmd.set_zone_name("deck"); cmd.set_top_cards(number); @@ -692,8 +692,8 @@ void Player::retranslateUi() aCardMenu->setText(tr("C&ard")); - for (int i = 0; i < allPlayersActions.size(); ++i) - allPlayersActions[i]->setText(tr("&All players")); + for (auto &allPlayersAction : allPlayersActions) + allPlayersAction->setText(tr("&All players")); } aPlay->setText(tr("&Play")); @@ -904,8 +904,8 @@ void Player::actViewLibrary() void Player::actViewTopCards() { bool ok; - int number = QInputDialog::getInt(0, tr("View top cards of library"), tr("Number of cards:"), defaultNumberTopCards, - 1, 2000000000, 1, &ok); + int number = QInputDialog::getInt(nullptr, tr("View top cards of library"), tr("Number of cards:"), + defaultNumberTopCards, 1, 2000000000, 1, &ok); if (ok) { defaultNumberTopCards = number; static_cast(scene())->toggleZoneView(this, "deck", number); @@ -934,7 +934,7 @@ void Player::actViewGraveyard() void Player::actRevealRandomGraveyardCard() { Command_RevealCards cmd; - QAction *action = dynamic_cast(sender()); + auto *action = dynamic_cast(sender()); const int otherPlayerId = action->data().toInt(); if (otherPlayerId != -1) { cmd.set_player_id(otherPlayerId); @@ -973,10 +973,10 @@ void Player::actMulligan() void Player::actDrawCards() { - int number = QInputDialog::getInt(0, tr("Draw cards"), tr("Number:")); + int number = QInputDialog::getInt(nullptr, tr("Draw cards"), tr("Number:")); if (number) { Command_DrawCards cmd; - cmd.set_number(number); + cmd.set_number(static_cast(number)); sendGameCommand(cmd); } } @@ -988,7 +988,7 @@ void Player::actUndoDraw() void Player::actMoveTopCardToGrave() { - if (zones.value("deck")->getCards().size() == 0) { + if (zones.value("deck")->getCards().empty()) { return; } @@ -1005,7 +1005,7 @@ void Player::actMoveTopCardToGrave() void Player::actMoveTopCardToExile() { - if (zones.value("deck")->getCards().size() == 0) { + if (zones.value("deck")->getCards().empty()) { return; } @@ -1022,7 +1022,7 @@ void Player::actMoveTopCardToExile() void Player::actMoveTopCardsToGrave() { - int number = QInputDialog::getInt(0, tr("Move top cards to grave"), tr("Number:")); + int number = QInputDialog::getInt(nullptr, tr("Move top cards to grave"), tr("Number:")); if (!number) { return; } @@ -1048,7 +1048,7 @@ void Player::actMoveTopCardsToGrave() void Player::actMoveTopCardsToExile() { - int number = QInputDialog::getInt(0, tr("Move top cards to exile"), tr("Number:")); + int number = QInputDialog::getInt(nullptr, tr("Move top cards to exile"), tr("Number:")); if (!number) { return; } @@ -1131,7 +1131,7 @@ void Player::actRollDie() 1000, 1, &ok); if (ok) { Command_RollDie cmd; - cmd.set_sides(sides); + cmd.set_sides(static_cast(sides)); sendGameCommand(cmd); } } @@ -1148,7 +1148,7 @@ void Player::actCreateToken() CardInfoPtr correctedCard = db->getCardBySimpleName(lastTokenName); if (correctedCard) { lastTokenName = correctedCard->getName(); - lastTokenTableRow = table->clampValidTableRow(2 - correctedCard->getTableRow()); + lastTokenTableRow = TableZone::clampValidTableRow(2 - correctedCard->getTableRow()); if (lastTokenPT.isEmpty()) { lastTokenPT = correctedCard->getPowTough(); } @@ -1182,7 +1182,7 @@ void Player::actCreateAnotherToken() void Player::actCreatePredefinedToken() { - QAction *action = static_cast(sender()); + auto *action = static_cast(sender()); CardInfoPtr cardInfo = db->getCard(action->text()); if (!cardInfo) { return; @@ -1199,7 +1199,7 @@ void Player::actCreateRelatedCard() if (!sourceCard) { return; } - QAction *action = static_cast(sender()); + auto *action = static_cast(sender()); // If there is a better way of passing a CardRelation through a QAction, please add it here. QList relatedCards = QList(); relatedCards.append(sourceCard->getInfo()->getRelatedCards()); @@ -1211,7 +1211,7 @@ void Player::actCreateRelatedCard() * then let's allow it to be created via "create another token" */ if (createRelatedFromRelation(sourceCard, cardRelation) && cardRelation->getCanCreateAnother()) { - CardInfoPtr cardInfo = db->getCard(dbNameFromTokenDisplayName(cardRelation->getName())); + CardInfoPtr cardInfo = db->getCard(cardRelation->getName()); setLastToken(cardInfo); } } @@ -1257,7 +1257,7 @@ void Player::actCreateAllRelatedCards() case 0: // else if nonExcludedRelatedCards == 0 for (CardRelation *cardRelationAll : relatedCards) { if (!cardRelationAll->getDoesAttach() && !cardRelationAll->getIsVariable()) { - dbName = dbNameFromTokenDisplayName(cardRelationAll->getName()); + dbName = cardRelationAll->getName(); for (int i = 0; i < cardRelationAll->getDefaultCount(); ++i) { createCard(sourceCard, dbName); } @@ -1271,7 +1271,7 @@ void Player::actCreateAllRelatedCards() default: // else for (CardRelation *cardRelationNotExcluded : nonExcludedRelatedCards) { if (!cardRelationNotExcluded->getDoesAttach() && !cardRelationNotExcluded->getIsVariable()) { - dbName = dbNameFromTokenDisplayName(cardRelationNotExcluded->getName()); + dbName = cardRelationNotExcluded->getName(); for (int i = 0; i < cardRelationNotExcluded->getDefaultCount(); ++i) { createCard(sourceCard, dbName); } @@ -1290,7 +1290,7 @@ void Player::actCreateAllRelatedCards() * then assign the first to the "Create another" shortcut. */ if (cardRelation != nullptr && cardRelation->getCanCreateAnother()) { - CardInfoPtr cardInfo = db->getCard(dbNameFromTokenDisplayName(cardRelation->getName())); + CardInfoPtr cardInfo = db->getCard(cardRelation->getName()); setLastToken(cardInfo); } } @@ -1300,12 +1300,12 @@ bool Player::createRelatedFromRelation(const CardItem *sourceCard, const CardRel if (sourceCard == nullptr || cardRelation == nullptr) { return false; } - QString dbName = dbNameFromTokenDisplayName(cardRelation->getName()); + QString dbName = cardRelation->getName(); if (cardRelation->getIsVariable()) { bool ok; dialogSemaphore = true; - int count = QInputDialog::getInt(0, tr("Create tokens"), tr("Number:"), cardRelation->getDefaultCount(), 1, - MAX_TOKENS_PER_DIALOG, 1, &ok); + int count = QInputDialog::getInt(nullptr, tr("Create tokens"), tr("Number:"), cardRelation->getDefaultCount(), + 1, MAX_TOKENS_PER_DIALOG, 1, &ok); dialogSemaphore = false; if (!ok) { return false; @@ -1337,19 +1337,22 @@ void Player::createCard(const CardItem *sourceCard, const QString &dbCardName, b // get the target token's location // TODO: Define this QPoint into its own function along with the one below - QPoint gridPoint = QPoint(-1, table->clampValidTableRow(2 - cardInfo->getTableRow())); + QPoint gridPoint = QPoint(-1, TableZone::clampValidTableRow(2 - cardInfo->getTableRow())); // create the token for the related card Command_CreateToken cmd; cmd.set_zone("table"); cmd.set_card_name(cardInfo->getName().toStdString()); - if (cardInfo->getColors().length() > 1) // Multicoloured - { - cmd.set_color("m"); - } else if (cardInfo->getColors().isEmpty()) { - cmd.set_color(""); - } else { - cmd.set_color(cardInfo->getColors().first().toLower().toStdString()); + switch (cardInfo->getColors().size()) { + case 0: + cmd.set_color(""); + break; + case 1: + cmd.set_color("m"); + break; + default: + cmd.set_color(cardInfo->getColors().left(1).toLower().toStdString()); + break; } cmd.set_pt(cardInfo->getPowTough().toStdString()); @@ -1377,7 +1380,7 @@ void Player::createAttachedCard(const CardItem *sourceCard, const QString &dbCar void Player::actSayMessage() { - QAction *a = qobject_cast(sender()); + auto *a = qobject_cast(sender()); Command_GameSay cmd; cmd.set_message(a->text().toStdString()); sendGameCommand(cmd); @@ -1436,22 +1439,6 @@ void Player::setCardAttrHelper(const GameEventContext &context, } } -// token names take the form of " / " or " ". -// dbName for tokens should take the form of " ". -// trailing whitespace is significant; it is hacked on at the end as an additional identifier in our single key database -QString Player::dbNameFromTokenDisplayName(const QString &tokenName) -{ - QRegularExpression tokenNamePattern(".*/\\S+\\s+(.*)"); - QRegularExpressionMatch match = tokenNamePattern.match(tokenName); - if (match.hasMatch()) { - return match.captured(1); - } else if (tokenName.indexOf(tr("Token: ")) != -1) { - return tokenName.mid(tr("Token: ").length()); - } else { - return tokenName; - } -} - void Player::eventGameSay(const Event_GameSay &event) { emit logSay(this, QString::fromStdString(event.message())); @@ -1481,8 +1468,8 @@ void Player::eventCreateArrow(const Event_CreateArrow &event) return; } - CardItem *startCard = static_cast(arrow->getStartItem()); - CardItem *targetCard = qgraphicsitem_cast(arrow->getTargetItem()); + auto *startCard = static_cast(arrow->getStartItem()); + auto *targetCard = qgraphicsitem_cast(arrow->getTargetItem()); if (targetCard) { emit logCreateArrow(this, startCard->getOwner(), startCard->getName(), targetCard->getOwner(), targetCard->getName(), false); @@ -1536,7 +1523,7 @@ void Player::eventSetCardAttr(const Event_SetCardAttr &event, const GameEventCon true); } if (event.attribute() == AttrTapped) { - emit logSetTapped(this, 0, event.attr_value() == "1"); + emit logSetTapped(this, nullptr, event.attr_value() == "1"); } } else { CardItem *card = zone->getCard(event.card_id(), QString()); @@ -1654,7 +1641,7 @@ void Player::eventMoveCard(const Event_MoveCard &event, const GameEventContext & if (card->getAttachedTo() && (startZone != targetZone)) { CardItem *parentCard = card->getAttachedTo(); - card->setAttachedTo(0); + card->setAttachedTo(nullptr); parentCard->getZone()->reorganizeCards(); } @@ -1667,8 +1654,8 @@ void Player::eventMoveCard(const Event_MoveCard &event, const GameEventContext & card->setHovered(false); const QList &attachedCards = card->getAttachedCards(); - for (int i = 0; i < attachedCards.size(); ++i) { - attachedCards[i]->setParentItem(targetZone); + for (auto attachedCard : attachedCards) { + attachedCard->setParentItem(targetZone); } if (startZone->getPlayer() != targetZone->getPlayer()) { @@ -1704,8 +1691,8 @@ void Player::eventMoveCard(const Event_MoveCard &event, const GameEventContext & } } } - for (int i = 0; i < arrowsToDelete.size(); ++i) { - arrowsToDelete[i]->delArrow(); + for (auto &i : arrowsToDelete) { + i->delArrow(); } } } @@ -1738,8 +1725,8 @@ void Player::eventDestroyCard(const Event_DestroyCard &event) QList attachedCards = card->getAttachedCards(); // This list is always empty except for buggy server implementations. - for (int i = 0; i < attachedCards.size(); ++i) { - attachedCards[i]->setAttachedTo(0); + for (auto &attachedCard : attachedCards) { + attachedCard->setAttachedTo(0); } emit logDestroyCard(this, card->getName()); @@ -1750,9 +1737,9 @@ void Player::eventDestroyCard(const Event_DestroyCard &event) void Player::eventAttachCard(const Event_AttachCard &event) { const QMap &playerList = game->getPlayers(); - Player *targetPlayer = 0; - CardZone *targetZone = 0; - CardItem *targetCard = 0; + Player *targetPlayer = nullptr; + CardZone *targetZone = nullptr; + CardItem *targetCard = nullptr; if (event.has_target_player_id()) { targetPlayer = playerList.value(event.target_player_id(), 0); if (targetPlayer) { @@ -1823,7 +1810,7 @@ void Player::eventRevealCards(const Event_RevealCards &event) if (!zone) { return; } - Player *otherPlayer = 0; + Player *otherPlayer = nullptr; if (event.has_other_player_id()) { otherPlayer = game->getPlayers().value(event.other_player_id()); if (!otherPlayer) { @@ -1843,14 +1830,14 @@ void Player::eventRevealCards(const Event_RevealCards &event) } if (peeking) { - for (int i = 0; i < cardList.size(); ++i) { - QString cardName = QString::fromStdString(cardList.at(i)->name()); - CardItem *card = zone->getCard(cardList.at(i)->id(), QString()); + for (auto i : cardList) { + QString cardName = QString::fromStdString(i->name()); + CardItem *card = zone->getCard(i->id(), QString()); if (!card) { continue; } card->setName(cardName); - emit logRevealCards(this, zone, cardList.at(i)->id(), cardName, this, true); + emit logRevealCards(this, zone, i->id(), cardName, this, true); } } else { bool showZoneView = true; @@ -1953,7 +1940,7 @@ void Player::processGameEvent(GameEvent::GameEventType type, const GameEvent &ev } } -void Player::setActive(bool _active) +void Player::setActivePlayer(bool _active) { active = _active; table->setActive(active); @@ -2073,7 +2060,7 @@ void Player::playCard(CardItem *card, bool faceDown, bool tapped) cmd.set_y(0); } else { int tableRow = faceDown ? 2 : info->getTableRow(); - QPoint gridPoint = QPoint(-1, table->clampValidTableRow(2 - tableRow)); + QPoint gridPoint = QPoint(-1, TableZone::clampValidTableRow(2 - tableRow)); cardToMove->set_face_down(faceDown); cardToMove->set_pt(info->getPowTough().toStdString()); cardToMove->set_tapped(faceDown ? false : tapped); @@ -2116,7 +2103,7 @@ AbstractCounter *Player::addCounter(int counterId, const QString &name, QColor c { qDebug() << "addCounter:" << getName() << counterId << name; if (counters.contains(counterId)) { - return 0; + return nullptr; } AbstractCounter *ctr; @@ -2163,25 +2150,25 @@ ArrowItem *Player::addArrow(const ServerInfo_Arrow &arrow) Player *startPlayer = playerList.value(arrow.start_player_id(), 0); Player *targetPlayer = playerList.value(arrow.target_player_id(), 0); if (!startPlayer || !targetPlayer) { - return 0; + return nullptr; } CardZone *startZone = startPlayer->getZones().value(QString::fromStdString(arrow.start_zone()), 0); - CardZone *targetZone = 0; + CardZone *targetZone = nullptr; if (arrow.has_target_zone()) { targetZone = targetPlayer->getZones().value(QString::fromStdString(arrow.target_zone()), 0); } if (!startZone || (!targetZone && arrow.has_target_zone())) { - return 0; + return nullptr; } CardItem *startCard = startZone->getCard(arrow.start_card_id(), QString()); - CardItem *targetCard = 0; + CardItem *targetCard = nullptr; if (targetZone) { targetCard = targetZone->getCard(arrow.target_card_id(), QString()); } if (!startCard || (!targetCard && arrow.has_target_card_id())) { - return 0; + return nullptr; } if (targetCard) { @@ -2194,7 +2181,7 @@ ArrowItem *Player::addArrow(const ServerInfo_Arrow &arrow) ArrowItem *Player::addArrow(int arrowId, CardItem *startCard, ArrowTarget *targetItem, const QColor &color) { - ArrowItem *arrow = new ArrowItem(this, arrowId, startCard, targetItem, color); + auto *arrow = new ArrowItem(this, arrowId, startCard, targetItem, color); arrows.insert(arrowId, arrow); scene()->addItem(arrow); return arrow; @@ -2295,7 +2282,7 @@ bool Player::clearCardsToDelete() void Player::actMoveCardXCardsFromTop() { bool ok; - int number = QInputDialog::getInt(0, tr("Place card X cards from top of library"), + int number = QInputDialog::getInt(nullptr, tr("Place card X cards from top of library"), tr("How many cards from the top of the deck should this card be placed:"), defaultNumberTopCardsToPlaceBelow, 1, 2000000000, 1, &ok); number--; @@ -2325,7 +2312,7 @@ void Player::actMoveCardXCardsFromTop() int startPlayerId = cardList[0]->getZone()->getPlayer()->getId(); QString startZone = cardList[0]->getZone()->getName(); - Command_MoveCard *cmd = new Command_MoveCard; + auto *cmd = new Command_MoveCard; cmd->set_start_player_id(startPlayerId); cmd->set_start_zone(startZone.toStdString()); cmd->mutable_cards_to_move()->CopyFrom(idList); @@ -2344,7 +2331,7 @@ void Player::actMoveCardXCardsFromTop() void Player::cardMenuAction() { - QAction *a = dynamic_cast(sender()); + auto *a = dynamic_cast(sender()); QList sel = scene()->selectedItems(); QList cardList; while (!sel.isEmpty()) { @@ -2353,14 +2340,13 @@ void Player::cardMenuAction() QList commandList; if (a->data().toInt() <= (int)cmClone) { - for (int i = 0; i < cardList.size(); ++i) { - CardItem *card = cardList[i]; + for (auto card : cardList) { switch (static_cast(a->data().toInt())) { // Leaving both for compatibility with server case cmUntap: // fallthrough case cmTap: { - Command_SetCardAttr *cmd = new Command_SetCardAttr; + auto *cmd = new Command_SetCardAttr; cmd->set_zone(card->getZone()->getName().toStdString()); cmd->set_card_id(card->getId()); cmd->set_attribute(AttrTapped); @@ -2369,7 +2355,7 @@ void Player::cardMenuAction() break; } case cmDoesntUntap: { - Command_SetCardAttr *cmd = new Command_SetCardAttr; + auto *cmd = new Command_SetCardAttr; cmd->set_zone(card->getZone()->getName().toStdString()); cmd->set_card_id(card->getId()); cmd->set_attribute(AttrDoesntUntap); @@ -2378,7 +2364,7 @@ void Player::cardMenuAction() break; } case cmFlip: { - Command_FlipCard *cmd = new Command_FlipCard; + auto *cmd = new Command_FlipCard; cmd->set_zone(card->getZone()->getName().toStdString()); cmd->set_card_id(card->getId()); cmd->set_face_down(!card->getFaceDown()); @@ -2392,7 +2378,7 @@ void Player::cardMenuAction() break; } case cmPeek: { - Command_RevealCards *cmd = new Command_RevealCards; + auto *cmd = new Command_RevealCards; cmd->set_zone_name(card->getZone()->getName().toStdString()); cmd->set_card_id(card->getId()); cmd->set_player_id(id); @@ -2400,7 +2386,7 @@ void Player::cardMenuAction() break; } case cmClone: { - Command_CreateToken *cmd = new Command_CreateToken; + auto *cmd = new Command_CreateToken; cmd->set_zone("table"); cmd->set_card_name(card->getName().toStdString()); cmd->set_color(card->getColor().toStdString()); @@ -2418,15 +2404,15 @@ void Player::cardMenuAction() } } else { ListOfCardsToMove idList; - for (int i = 0; i < cardList.size(); ++i) { - idList.add_card()->set_card_id(cardList[i]->getId()); + for (auto &i : cardList) { + idList.add_card()->set_card_id(i->getId()); } int startPlayerId = cardList[0]->getZone()->getPlayer()->getId(); QString startZone = cardList[0]->getZone()->getName(); switch (static_cast(a->data().toInt())) { case cmMoveToTopLibrary: { - Command_MoveCard *cmd = new Command_MoveCard; + auto *cmd = new Command_MoveCard; cmd->set_start_player_id(startPlayerId); cmd->set_start_zone(startZone.toStdString()); cmd->mutable_cards_to_move()->CopyFrom(idList); @@ -2438,7 +2424,7 @@ void Player::cardMenuAction() break; } case cmMoveToBottomLibrary: { - Command_MoveCard *cmd = new Command_MoveCard; + auto *cmd = new Command_MoveCard; cmd->set_start_player_id(startPlayerId); cmd->set_start_zone(startZone.toStdString()); cmd->mutable_cards_to_move()->CopyFrom(idList); @@ -2450,7 +2436,7 @@ void Player::cardMenuAction() break; } case cmMoveToHand: { - Command_MoveCard *cmd = new Command_MoveCard; + auto *cmd = new Command_MoveCard; cmd->set_start_player_id(startPlayerId); cmd->set_start_zone(startZone.toStdString()); cmd->mutable_cards_to_move()->CopyFrom(idList); @@ -2462,7 +2448,7 @@ void Player::cardMenuAction() break; } case cmMoveToGraveyard: { - Command_MoveCard *cmd = new Command_MoveCard; + auto *cmd = new Command_MoveCard; cmd->set_start_player_id(startPlayerId); cmd->set_start_zone(startZone.toStdString()); cmd->mutable_cards_to_move()->CopyFrom(idList); @@ -2474,7 +2460,7 @@ void Player::cardMenuAction() break; } case cmMoveToExile: { - Command_MoveCard *cmd = new Command_MoveCard; + auto *cmd = new Command_MoveCard; cmd->set_start_player_id(startPlayerId); cmd->set_start_zone(startZone.toStdString()); cmd->mutable_cards_to_move()->CopyFrom(idList); @@ -2505,8 +2491,8 @@ void Player::actIncPT(int deltaP, int deltaT) QList commandList; QListIterator j(scene()->selectedItems()); while (j.hasNext()) { - CardItem *card = static_cast(j.next()); - Command_SetCardAttr *cmd = new Command_SetCardAttr; + auto *card = static_cast(j.next()); + auto *cmd = new Command_SetCardAttr; cmd->set_zone(card->getZone()->getName().toStdString()); cmd->set_card_id(card->getId()); cmd->set_attribute(AttrPT); @@ -2527,12 +2513,12 @@ void Player::actResetPT() QList commandList; QListIterator selected(scene()->selectedItems()); while (selected.hasNext()) { - CardItem *card = static_cast(selected.next()); + auto *card = static_cast(selected.next()); CardInfoPtr info = card->getInfo(); if (!info) { continue; } - Command_SetCardAttr *cmd = new Command_SetCardAttr; + auto *cmd = new Command_SetCardAttr; QString zoneName = card->getZone()->getName(); cmd->set_zone(zoneName.toStdString()); cmd->set_card_id(card->getId()); @@ -2556,15 +2542,15 @@ void Player::actSetPT() QListIterator i(scene()->selectedItems()); while (i.hasNext()) { - CardItem *card = static_cast(i.next()); + auto *card = static_cast(i.next()); if (!card->getPT().isEmpty()) { oldPT = card->getPT(); } } bool ok; dialogSemaphore = true; - QString pt = QInputDialog::getText(0, tr("Set power/toughness"), tr("Please enter the new PT:"), QLineEdit::Normal, - oldPT, &ok); + QString pt = QInputDialog::getText(nullptr, tr("Set power/toughness"), tr("Please enter the new PT:"), + QLineEdit::Normal, oldPT, &ok); dialogSemaphore = false; if (clearCardsToDelete()) { return; @@ -2576,8 +2562,8 @@ void Player::actSetPT() QList commandList; QListIterator j(scene()->selectedItems()); while (j.hasNext()) { - CardItem *card = static_cast(j.next()); - Command_SetCardAttr *cmd = new Command_SetCardAttr; + auto *card = static_cast(j.next()); + auto *cmd = new Command_SetCardAttr; cmd->set_zone(card->getZone()->getName().toStdString()); cmd->set_card_id(card->getId()); cmd->set_attribute(AttrPT); @@ -2636,7 +2622,7 @@ void Player::actSetAnnotation() QString oldAnnotation; QListIterator i(scene()->selectedItems()); while (i.hasNext()) { - CardItem *card = static_cast(i.next()); + auto *card = static_cast(i.next()); if (!card->getAnnotation().isEmpty()) { oldAnnotation = card->getAnnotation(); } @@ -2644,7 +2630,7 @@ void Player::actSetAnnotation() bool ok; dialogSemaphore = true; - QString annotation = QInputDialog::getText(0, tr("Set annotation"), tr("Please enter the new annotation:"), + QString annotation = QInputDialog::getText(nullptr, tr("Set annotation"), tr("Please enter the new annotation:"), QLineEdit::Normal, oldAnnotation, &ok); dialogSemaphore = false; if (clearCardsToDelete()) { @@ -2657,8 +2643,8 @@ void Player::actSetAnnotation() QList commandList; i.toFront(); while (i.hasNext()) { - CardItem *card = static_cast(i.next()); - Command_SetCardAttr *cmd = new Command_SetCardAttr; + auto *card = static_cast(i.next()); + auto *cmd = new Command_SetCardAttr; cmd->set_zone(card->getZone()->getName().toStdString()); cmd->set_card_id(card->getId()); cmd->set_attribute(AttrAnnotation); @@ -2674,7 +2660,7 @@ void Player::actAttach() return; } - ArrowAttachItem *arrow = new ArrowAttachItem(game->getActiveCard()); + auto *arrow = new ArrowAttachItem(game->getActiveCard()); scene()->addItem(arrow); arrow->grabMouse(); } @@ -2693,16 +2679,16 @@ void Player::actUnattach() void Player::actCardCounterTrigger() { - QAction *action = static_cast(sender()); + auto *action = static_cast(sender()); int counterId = action->data().toInt() / 1000; QList commandList; switch (action->data().toInt() % 1000) { // TODO: define case numbers case 9: { QListIterator i(scene()->selectedItems()); while (i.hasNext()) { - CardItem *card = static_cast(i.next()); + auto *card = static_cast(i.next()); if (card->getCounters().value(counterId, 0) < MAX_COUNTERS_ON_CARD) { - Command_SetCardCounter *cmd = new Command_SetCardCounter; + auto *cmd = new Command_SetCardCounter; cmd->set_zone(card->getZone()->getName().toStdString()); cmd->set_card_id(card->getId()); cmd->set_counter_id(counterId); @@ -2715,9 +2701,9 @@ void Player::actCardCounterTrigger() case 10: { QListIterator i(scene()->selectedItems()); while (i.hasNext()) { - CardItem *card = static_cast(i.next()); + auto *card = static_cast(i.next()); if (card->getCounters().value(counterId, 0)) { - Command_SetCardCounter *cmd = new Command_SetCardCounter; + auto *cmd = new Command_SetCardCounter; cmd->set_zone(card->getZone()->getName().toStdString()); cmd->set_card_id(card->getId()); cmd->set_counter_id(counterId); @@ -2730,7 +2716,8 @@ void Player::actCardCounterTrigger() case 11: { bool ok; dialogSemaphore = true; - int number = QInputDialog::getInt(0, tr("Set counters"), tr("Number:"), 0, 0, MAX_COUNTERS_ON_CARD, 1, &ok); + int number = + QInputDialog::getInt(nullptr, tr("Set counters"), tr("Number:"), 0, 0, MAX_COUNTERS_ON_CARD, 1, &ok); dialogSemaphore = false; if (clearCardsToDelete() || !ok) { return; @@ -2738,8 +2725,8 @@ void Player::actCardCounterTrigger() QListIterator i(scene()->selectedItems()); while (i.hasNext()) { - CardItem *card = static_cast(i.next()); - Command_SetCardCounter *cmd = new Command_SetCardCounter; + auto *card = static_cast(i.next()); + auto *cmd = new Command_SetCardCounter; cmd->set_zone(card->getZone()->getName().toStdString()); cmd->set_card_id(card->getId()); cmd->set_counter_id(counterId); @@ -2964,16 +2951,25 @@ void Player::addRelatedCardActions(const CardItem *card, QMenu *cardMenu) int index = 0; QAction *createRelatedCards = nullptr; for (const CardRelation *cardRelation : relatedCards) { - QString cardName = cardRelation->getName(); + CardInfoPtr relatedCard = db->getCard(cardRelation->getName()); + if (relatedCard == nullptr) + continue; + QString relatedCardName; + if (relatedCard->getPowTough().size() > 0) { + relatedCardName = relatedCard->getPowTough() + " " + relatedCard->getName(); // "n/n name" + } else { + relatedCardName = relatedCard->getName(); // "name" + } + QString text = tr("Token: "); if (cardRelation->getDoesAttach()) { - text += tr("Attach to ") + "\"" + cardName + "\""; + text += tr("Attach to ") + "\"" + relatedCardName + "\""; } else if (cardRelation->getIsVariable()) { - text += "X " + cardName; + text += "X " + relatedCardName; } else if (cardRelation->getDefaultCount() != 1) { - text += QString(cardRelation->getDefaultCount()) + "x " + cardName; + text += QString::number(cardRelation->getDefaultCount()) + "x " + relatedCardName; } else { - text += cardName; + text += relatedCardName; } if (createRelatedCards == nullptr) { @@ -2985,7 +2981,7 @@ void Player::addRelatedCardActions(const CardItem *card, QMenu *cardMenu) } } - QAction *createRelated = new QAction(text, this); + auto *createRelated = new QAction(text, this); createRelated->setData(QVariant(index++)); connect(createRelated, SIGNAL(triggered()), this, SLOT(actCreateRelatedCard())); cardMenu->addAction(createRelated); @@ -3010,7 +3006,7 @@ QMenu *Player::getCardMenu() const if (aCardMenu) { return aCardMenu->menu(); } - return 0; + return nullptr; } QString Player::getName() const @@ -3055,7 +3051,7 @@ void Player::setMirrored(bool _mirrored) void Player::processSceneSizeChange(int newPlayerWidth) { - // Extend table (and hand, if horizontal) to accomodate the new player width. + // Extend table (and hand, if horizontal) to accommodate the new player width. qreal tableWidth = newPlayerWidth - CARD_HEIGHT - 15 - counterAreaWidth - stack->boundingRect().width(); if (!settingsCache->getHorizontalHand()) { tableWidth -= hand->boundingRect().width(); @@ -3072,10 +3068,10 @@ void Player::setLastToken(CardInfoPtr cardInfo) } lastTokenName = cardInfo->getName(); - lastTokenColor = cardInfo->getColors().isEmpty() ? QString() : cardInfo->getColors().first().toLower(); + lastTokenColor = cardInfo->getColors().isEmpty() ? QString() : cardInfo->getColors().left(1).toLower(); lastTokenPT = cardInfo->getPowTough(); lastTokenAnnotation = settingsCache->getAnnotateTokens() ? cardInfo->getText() : ""; - lastTokenTableRow = table->clampValidTableRow(2 - cardInfo->getTableRow()); + lastTokenTableRow = TableZone::clampValidTableRow(2 - cardInfo->getTableRow()); lastTokenDestroy = true; aCreateAnotherToken->setText(tr("C&reate another %1 token").arg(lastTokenName)); aCreateAnotherToken->setEnabled(true); diff --git a/cockatrice/src/player.h b/cockatrice/src/player.h index c4f6ed00..4f1dc96d 100644 --- a/cockatrice/src/player.h +++ b/cockatrice/src/player.h @@ -79,17 +79,17 @@ public: { Type = typeOther }; - int type() const + int type() const override { return Type; } - PlayerArea(QGraphicsItem *parent = 0); - QRectF boundingRect() const + explicit PlayerArea(QGraphicsItem *parent = nullptr); + QRectF boundingRect() const override { return bRect; } - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; void setSize(qreal width, qreal height); }; @@ -251,7 +251,6 @@ private: void createCard(const CardItem *sourceCard, const QString &dbCardName, bool attach = false); void createAttachedCard(const CardItem *sourceCard, const QString &dbCardName); bool createRelatedFromRelation(const CardItem *sourceCard, const CardRelation *cardRelation); - QString dbNameFromTokenDisplayName(const QString &tokenName); QRectF bRect; @@ -308,12 +307,12 @@ public: { Type = typeOther }; - int type() const + int type() const override { return Type; } - QRectF boundingRect() const; - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + QRectF boundingRect() const override; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; void playCard(CardItem *c, bool faceDown, bool tapped); void addCard(CardItem *c); @@ -336,7 +335,7 @@ public: } Player(const ServerInfo_User &info, int _id, bool _local, TabGame *_parent); - ~Player(); + ~Player() override; void retranslateUi(); void clear(); TabGame *getGame() const @@ -380,7 +379,7 @@ public: { return active; } - void setActive(bool _active); + void setActivePlayer(bool _active); void setShortcutsActive(); void setShortcutsInactive(); void updateZones(); diff --git a/cockatrice/src/releasechannel.cpp b/cockatrice/src/releasechannel.cpp index 841f801a..aab2cd80 100644 --- a/cockatrice/src/releasechannel.cpp +++ b/cockatrice/src/releasechannel.cpp @@ -1,5 +1,4 @@ #include "releasechannel.h" -#include "qt-json/json.h" #include "version_string.h" #include @@ -93,21 +92,20 @@ QString StableReleaseChannel::getReleaseChannelUrl() const void StableReleaseChannel::releaseListFinished() { - QNetworkReply *reply = static_cast(sender()); - bool ok; - QString tmp = QString(reply->readAll()); + auto *reply = static_cast(sender()); + QJsonParseError parseError{}; + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll(), &parseError); reply->deleteLater(); - - QVariantMap resultMap = QtJson::Json::parse(tmp, ok).toMap(); - if (!ok) { - qWarning() << "No reply received from the release update server:" << tmp; + if (parseError.error != QJsonParseError::NoError) { + qWarning() << "No reply received from the release update server."; emit error(tr("No reply received from the release update server.")); return; } + QVariantMap resultMap = jsonResponse.toVariant().toMap(); if (!(resultMap.contains("name") && resultMap.contains("html_url") && resultMap.contains("tag_name") && resultMap.contains("published_at"))) { - qWarning() << "Invalid received from the release update server:" << tmp; + qWarning() << "Invalid received from the release update server."; emit error(tr("Invalid reply received from the release update server.")); return; } @@ -145,7 +143,7 @@ void StableReleaseChannel::releaseListFinished() QString myHash = QString(VERSION_COMMIT); qDebug() << "Current hash=" << myHash << "update hash=" << shortHash; - qDebug() << "Got reply from release server, size=" << tmp.size() << "name=" << lastRelease->getName() + qDebug() << "Got reply from release server, name=" << lastRelease->getName() << "desc=" << lastRelease->getDescriptionUrl() << "date=" << lastRelease->getPublishDate() << "url=" << lastRelease->getDownloadUrl(); @@ -158,26 +156,25 @@ void StableReleaseChannel::releaseListFinished() void StableReleaseChannel::tagListFinished() { - QNetworkReply *reply = static_cast(sender()); - bool ok; - QString tmp = QString(reply->readAll()); + auto *reply = static_cast(sender()); + QJsonParseError parseError{}; + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll(), &parseError); reply->deleteLater(); - - QVariantMap resultMap = QtJson::Json::parse(tmp, ok).toMap(); - if (!ok) { - qWarning() << "No reply received from the tag update server:" << tmp; + if (parseError.error != QJsonParseError::NoError) { + qWarning() << "No reply received from the tag update server."; emit error(tr("No reply received from the tag update server.")); return; } + QVariantMap resultMap = jsonResponse.toVariant().toMap(); if (!(resultMap.contains("object") && resultMap["object"].toMap().contains("sha"))) { - qWarning() << "Invalid received from the tag update server:" << tmp; + qWarning() << "Invalid received from the tag update server."; emit error(tr("Invalid reply received from the tag update server.")); return; } lastRelease->setCommitHash(resultMap["object"].toMap()["sha"].toString()); - qDebug() << "Got reply from tag server, size=" << tmp.size() << "commit=" << lastRelease->getCommitHash(); + qDebug() << "Got reply from tag server, commit=" << lastRelease->getCommitHash(); QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN); QString myHash = QString(VERSION_COMMIT); @@ -190,7 +187,6 @@ void StableReleaseChannel::tagListFinished() void StableReleaseChannel::fileListFinished() { // Only implemented to satisfy interface - return; } QString BetaReleaseChannel::getManualDownloadUrl() const @@ -210,7 +206,7 @@ QString BetaReleaseChannel::getReleaseChannelUrl() const void BetaReleaseChannel::releaseListFinished() { - QNetworkReply *reply = static_cast(sender()); + auto *reply = static_cast(sender()); QByteArray jsonData = reply->readAll(); reply->deleteLater(); @@ -224,7 +220,7 @@ void BetaReleaseChannel::releaseListFinished() */ QVariantMap resultMap = array.at(0).toObject().toVariantMap(); - if (array.size() == 0 || resultMap.size() == 0) { + if (array.empty() || resultMap.empty()) { qWarning() << "No reply received from the release update server:" << QString(jsonData); emit error(tr("No reply received from the release update server.")); return; @@ -262,18 +258,17 @@ void BetaReleaseChannel::releaseListFinished() void BetaReleaseChannel::fileListFinished() { - QNetworkReply *reply = static_cast(sender()); - QByteArray jsonData = reply->readAll(); + auto *reply = static_cast(sender()); + QJsonParseError parseError{}; + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll(), &parseError); reply->deleteLater(); - bool ok; - - QVariantList resultList = QtJson::Json::parse(jsonData, ok).toList(); - if (!ok) { - qWarning() << "No reply received from the file update server:" << QString(jsonData); + if (parseError.error != QJsonParseError::NoError) { + qWarning() << "No reply received from the file update server."; emit error(tr("No reply received from the file update server.")); return; } + QVariantList resultList = jsonResponse.toVariant().toList(); QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN); QString myHash = QString(VERSION_COMMIT); qDebug() << "Current hash=" << myHash << "update hash=" << shortHash; diff --git a/cockatrice/src/releasechannel.h b/cockatrice/src/releasechannel.h index c2b020dc..8ec4d04c 100644 --- a/cockatrice/src/releasechannel.h +++ b/cockatrice/src/releasechannel.h @@ -5,6 +5,7 @@ #include #include #include +#include class QNetworkReply; class QNetworkAccessManager; @@ -15,8 +16,8 @@ class Release friend class BetaReleaseChannel; public: - Release(){}; - ~Release(){}; + Release() = default; + ~Release() = default; private: QString name, descriptionUrl, downloadUrl, commitHash; @@ -26,20 +27,20 @@ private: protected: void setName(QString _name) { - name = _name; + name = std::move(_name); } void setDescriptionUrl(QString _descriptionUrl) { - descriptionUrl = _descriptionUrl; + descriptionUrl = std::move(_descriptionUrl); } void setDownloadUrl(QString _downloadUrl) { - downloadUrl = _downloadUrl; + downloadUrl = std::move(_downloadUrl); compatibleVersionFound = true; } void setCommitHash(QString _commitHash) { - commitHash = _commitHash; + commitHash = std::move(_commitHash); } void setPublishDate(QDate _publishDate) { @@ -78,7 +79,7 @@ class ReleaseChannel : public QObject Q_OBJECT public: ReleaseChannel(); - ~ReleaseChannel(); + ~ReleaseChannel() override; protected: // shared by all instances @@ -116,33 +117,41 @@ class StableReleaseChannel : public ReleaseChannel { Q_OBJECT public: - StableReleaseChannel(){}; - ~StableReleaseChannel(){}; - virtual QString getManualDownloadUrl() const; - virtual QString getName() const; + StableReleaseChannel() = default; + ~StableReleaseChannel() override = default; + + QString getManualDownloadUrl() const override; + + QString getName() const override; protected: - virtual QString getReleaseChannelUrl() const; + QString getReleaseChannelUrl() const override; protected slots: - virtual void releaseListFinished(); + + void releaseListFinished() override; void tagListFinished(); - virtual void fileListFinished(); + + void fileListFinished() override; }; class BetaReleaseChannel : public ReleaseChannel { Q_OBJECT public: - BetaReleaseChannel(){}; - ~BetaReleaseChannel(){}; - virtual QString getManualDownloadUrl() const; - virtual QString getName() const; + BetaReleaseChannel() = default; + ~BetaReleaseChannel() override = default; + + QString getManualDownloadUrl() const override; + + QString getName() const override; protected: - virtual QString getReleaseChannelUrl() const; + QString getReleaseChannelUrl() const override; protected slots: - virtual void releaseListFinished(); - virtual void fileListFinished(); + + void releaseListFinished() override; + + void fileListFinished() override; }; #endif \ No newline at end of file diff --git a/cockatrice/src/settings/downloadsettings.cpp b/cockatrice/src/settings/downloadsettings.cpp index 4591b680..239b3d6c 100644 --- a/cockatrice/src/settings/downloadsettings.cpp +++ b/cockatrice/src/settings/downloadsettings.cpp @@ -29,9 +29,9 @@ QStringList DownloadSettings::getAllURLs() void DownloadSettings::populateDefaultURLs() { downloadURLs.clear(); - downloadURLs.append("https://api.scryfall.com/cards/!uuid!?format=image"); - downloadURLs.append("https://api.scryfall.com/cards/multiverse/!cardid!?format=image"); - downloadURLs.append("http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=!cardid!&type=card"); + downloadURLs.append("https://api.scryfall.com/cards/!set:uuid!?format=image&face=!prop:side!"); + downloadURLs.append("https://api.scryfall.com/cards/multiverse/!set:muid!?format=image"); + downloadURLs.append("http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=!set:muid!&type=card"); downloadURLs.append("http://gatherer.wizards.com/Handlers/Image.ashx?name=!name!&type=card"); setValue(QVariant::fromValue(downloadURLs), "urls", "downloads"); } diff --git a/cockatrice/translations/cockatrice_en.ts b/cockatrice/translations/cockatrice_en.ts index 8c02bad7..bc74d9a1 100644 --- a/cockatrice/translations/cockatrice_en.ts +++ b/cockatrice/translations/cockatrice_en.ts @@ -22,62 +22,62 @@ AppearanceSettingsPage - + Theme settings - + Current theme: - + Card rendering - + Display card names on cards having a picture - + Scale cards on mouse over - + Hand layout - + Display hand horizontally (wastes space) - + Enable left justification - + Table grid layout - + Invert vertical coordinate - + Minimum player count for multi-column layout: - + Maximum font size for information displayed on cards: @@ -192,22 +192,22 @@ This is only saved for moderators and cannot be seen by the banned person. BetaReleaseChannel - + Beta Releases - + No reply received from the release update server. - + Invalid reply received from the release update server. - + No reply received from the file update server. @@ -330,17 +330,17 @@ This is only saved for moderators and cannot be seen by the banned person. CardFrame - + Image - + Description - + Both @@ -348,40 +348,20 @@ This is only saved for moderators and cannot be seen by the banned person. CardInfoText - + + Related cards: + + + + Unknown card: - + Name: - - - Mana cost: - - - - - Color(s): - - - - - Card type: - - - - - P / T: - - - - - Loyalty: - - CardItem @@ -522,58 +502,120 @@ This is only saved for moderators and cannot be seen by the banned person. DeckEditorSettingsPage - - + + Update Spoilers + + + + Success + + + + + Download URLs have been reset. + + + + + Downloaded card pictures have been reset. + + + Error + + + + + One or more downloaded card pictures could not be cleared. + + + + + Add URL + + + + + + URL: + + + + + Edit URL + + + + Updating... - + Choose path - + + URL Download Priority + + + + Spoilers - + Download Spoilers Automatically - + Spoiler Location: - - Hey, something's here finally! + + Download card pictures on the fly - + + How to add a custom URL + + + + + Delete Downloaded Images + + + + + Reset Download URLs + + + + Last Updated - + Spoilers download automatically on launch - + Press the button to manually update without relaunching - + Do not close settings until manual update complete @@ -1498,12 +1540,12 @@ Make sure to enable the 'Token' set in the "Manage sets" dia DlgSettings - + Unknown Error loading card database - + Your card database is invalid. Cockatrice may not function correctly with an invalid database @@ -1514,7 +1556,7 @@ Would you like to change your database location setting? - + Your card database version is too old. This can cause problems loading card information or images @@ -1525,7 +1567,7 @@ Would you like to change your database location setting? - + Your card database did not finish loading Please file a ticket at http://github.com/Cockatrice/Cockatrice/issues with your cards.xml attached @@ -1534,21 +1576,21 @@ Would you like to change your database location setting? - + File Error loading your card database. Would you like to change your database location setting? - + Your card database was loaded but contains no cards. Would you like to change your database location setting? - + Unknown card database load status Please file a ticket at http://github.com/Cockatrice/Cockatrice/issues @@ -1557,59 +1599,59 @@ Would you like to change your database location setting? - - - + + + Error - + The path to your deck directory is invalid. Would you like to go back and set the correct path? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? - + Settings - + General - + Appearance - + User Interface - - Deck Editor + + Card Sources - + Chat - + Sound - + Shortcuts @@ -2001,127 +2043,76 @@ You may have to build from source yourself. GeneralSettingsPage + + + + - - - - Choose path - - Success - - - - - Downloaded card pictures have been reset. - - - - - Error - - - - - One or more downloaded card pictures could not be cleared. - - - - + Personal settings - + Language: - - Download card pictures on the fly - - - - + Paths (editing disabled in portable mode) - + Paths - + Decks directory: - + Replays directory: - + Pictures directory: - + Card database: - + Token database: - + Picture cache size: - - Primary download URL: - - - - - Fallback download URL: - - - - - How to set a custom picture url - - - - - Reset/clear downloaded pictures - - - - + Update channel - + Notify if a feature supported by the server is missing in my client - - - Reset - - - - + Show tips on startup @@ -3443,94 +3434,157 @@ Cockatrice will now reload the card database. MessagesSettingsPage - + Word1 Word2 Word3 - + + Add New URL + + + + + Edit URL + + + + + Remove URL + + + + Add message - - + + Message: - + Edit message - + Chat settings - + Custom alert words - + Enable chat mentions - + Enable mention completer - + In-game message macros - + Ignore chat room messages sent by unregistered users - + Ignore private messages sent by unregistered users - - + + Invert text color - + Enable desktop notifications for private messages - + Enable desktop notification for mentions - + Enable room message history on join - - + + (Color is hexadecimal) - + Separate words with a space, alphanumeric characters only + + Mtg + + + Card type + + + + + Converted mana cost + + + + + Color(s) + + + + + Loyalty + + + + + Main card type + + + + + Mana cost + + + + + P / T + + + + + Side + + + + + Layout + + + PhasesToolbar @@ -3948,7 +4002,7 @@ Cockatrice will now reload the card database. - + C&reate another %1 token @@ -3958,34 +4012,32 @@ Cockatrice will now reload the card database. - - - + Token: - + Place card X cards from top of library - + How many cards from the top of the deck should this card be placed: - + View related cards - + Attach to - + All tokens @@ -4036,7 +4088,7 @@ Cockatrice will now reload the card database. - + Number: @@ -4061,27 +4113,27 @@ Cockatrice will now reload the card database. - + Set power/toughness - + Please enter the new PT: - + Set annotation - + Please enter the new annotation: - + Set counters @@ -4352,27 +4404,27 @@ Please check your shortcut settings! SoundSettingsPage - + Enable &sounds - + Current sounds theme: - + Test system sound engine - + Sound settings - + Master volume @@ -4429,27 +4481,27 @@ Please check your shortcut settings! StableReleaseChannel - + Stable Releases - + No reply received from the release update server. - + Invalid reply received from the release update server. - + No reply received from the tag update server. - + Invalid reply received from the tag update server. @@ -5788,42 +5840,42 @@ Please refrain from engaging in this activity or further actions may be taken ag UserInterfaceSettingsPage - + General interface settings - + Enable notifications in taskbar - + Notify in the taskbar for game events while you are spectating - + &Double-click cards to play them (instead of single-click) - + &Play all nonlands onto the stack (not the battlefield) by default - + Annotate card text on tokens - + Animation settings - + &Tap/untap animation diff --git a/oracle/CMakeLists.txt b/oracle/CMakeLists.txt index 82df556f..13156ed4 100644 --- a/oracle/CMakeLists.txt +++ b/oracle/CMakeLists.txt @@ -11,9 +11,12 @@ SET(oracle_SOURCES src/main.cpp src/oraclewizard.cpp src/oracleimporter.cpp + src/qt-json/json.cpp ../cockatrice/src/carddatabase.cpp ../cockatrice/src/pictureloader.cpp + ../cockatrice/src/carddbparser/carddatabaseparser.cpp ../cockatrice/src/carddbparser/cockatricexml3.cpp + ../cockatrice/src/carddbparser/cockatricexml4.cpp ../cockatrice/src/settingscache.cpp ../cockatrice/src/shortcutssettings.cpp ../cockatrice/src/settings/carddatabasesettings.cpp @@ -24,7 +27,6 @@ SET(oracle_SOURCES ../cockatrice/src/settings/layoutssettings.cpp ../cockatrice/src/settings/downloadsettings.cpp ../cockatrice/src/thememanager.cpp - ../cockatrice/src/qt-json/json.cpp ../cockatrice/src/releasechannel.cpp ${VERSION_STRING_CPP} ) diff --git a/oracle/src/oracleimporter.cpp b/oracle/src/oracleimporter.cpp index ec096f5c..1b652b00 100644 --- a/oracle/src/oracleimporter.cpp +++ b/oracle/src/oracleimporter.cpp @@ -1,5 +1,5 @@ #include "oracleimporter.h" -#include "carddbparser/cockatricexml3.h" +#include "carddbparser/cockatricexml4.h" #include #include @@ -7,6 +7,14 @@ #include "qt-json/json.h" +SplitCardPart::SplitCardPart(const int _index, + const QString &_text, + const QVariantHash &_properties, + const CardInfoPerSet _setInfo) + : index(_index), text(_text), properties(_properties), setInfo(_setInfo) +{ +} + OracleImporter::OracleImporter(const QString &_dataDir, QObject *parent) : CardDatabase(parent), dataDir(_dataDir) { } @@ -25,24 +33,23 @@ bool OracleImporter::readSetsFromByteArray(const QByteArray &data) QListIterator it(setsMap.values()); QVariantMap map; - QString edition; - QString editionLong; - QVariant editionCards; + QString shortName; + QString longName; + QList setCards; QString setType; QDate releaseDate; while (it.hasNext()) { map = it.next().toMap(); - edition = map.value("code").toString().toUpper(); - editionLong = map.value("name").toString(); - editionCards = map.value("cards"); + shortName = map.value("code").toString().toUpper(); + longName = map.value("name").toString(); + setCards = map.value("cards").toList(); setType = map.value("type").toString(); // capitalize set type if (setType.length() > 0) setType[0] = setType[0].toUpper(); releaseDate = map.value("releaseDate").toDate(); - - newSetList.append(SetToDownload(edition, editionLong, editionCards, setType, releaseDate)); + newSetList.append(SetToDownload(shortName, longName, setCards, setType, releaseDate)); } qSort(newSetList); @@ -53,37 +60,27 @@ bool OracleImporter::readSetsFromByteArray(const QByteArray &data) return true; } -CardInfoPtr OracleImporter::addCard(const QString &setName, - QString cardName, +CardInfoPtr OracleImporter::addCard(QString name, + QString text, bool isToken, - int cardId, - QString &cardUuId, - QString &setNumber, - QString &cardCost, - QString &cmc, - const QString &cardType, - const QString &cardPT, - const QString &cardLoyalty, - const QString &cardText, - const QStringList &colors, - const QList &relatedCards, - const QList &reverseRelatedCards, - bool upsideDown, - QString &rarity) + QVariantHash properties, + QList &relatedCards, + CardInfoPerSet setInfo) { - QStringList cardTextRows = cardText.split("\n"); - // Workaround for card name weirdness - cardName = cardName.replace("Æ", "AE"); - cardName = cardName.replace("’", "'"); + name = name.replace("Æ", "AE"); + name = name.replace("’", "'"); + if (cards.contains(name)) { + CardInfoPtr card = cards.value(name); + card->addToSet(setInfo.getPtr(), setInfo); + return card; + } - CardInfoPtr card; - if (cards.contains(cardName)) { - card = cards.value(cardName); - } else { - // Remove {} around mana costs, except if it's split cost - QStringList symbols = cardCost.split("}"); - QString formattedCardCost = QString(); + // Remove {} around mana costs, except if it's split cost + QString manacost = properties.value("manacost").toString(); + if (!manacost.isEmpty()) { + QStringList symbols = manacost.split("}"); + QString formattedCardCost; for (QString symbol : symbols) { if (symbol.contains(QRegExp("[0-9WUBGRP]/[0-9WUBGRP]"))) { symbol.append("}"); @@ -92,240 +89,251 @@ CardInfoPtr OracleImporter::addCard(const QString &setName, } formattedCardCost.append(symbol); } - - // detect mana generator artifacts - bool mArtifact = false; - if (cardType.endsWith("Artifact")) { - for (int i = 0; i < cardTextRows.size(); ++i) { - cardTextRows[i].remove(QRegularExpression(R"(\".*?\")")); - if (cardTextRows[i].contains("{T}") && cardTextRows[i].contains("to your mana pool")) { - mArtifact = true; - } - } - } - - // detect cards that enter the field tapped - bool cipt = - cardText.contains("Hideaway") || (cardText.contains(cardName + " enters the battlefield tapped") && - !cardText.contains(cardName + " enters the battlefield tapped unless")); - - // insert the card and its properties - card = CardInfo::newInstance(cardName, isToken, formattedCardCost, cmc, cardType, cardPT, cardText, colors, - relatedCards, reverseRelatedCards, upsideDown, cardLoyalty, cipt); - int tableRow = 1; - QString mainCardType = card->getMainCardType(); - if ((mainCardType == "Land") || mArtifact) - tableRow = 0; - else if ((mainCardType == "Sorcery") || (mainCardType == "Instant")) - tableRow = 3; - else if (mainCardType == "Creature") - tableRow = 2; - card->setTableRow(tableRow); - - cards.insert(cardName, card); + properties.insert("manacost", formattedCardCost); } - card->setMuId(setName, cardId); - card->setUuId(setName, cardUuId); - card->setSetNumber(setName, setNumber); - card->setRarity(setName, rarity); + // fix colors + QString allColors = properties.value("colors").toString(); + if (allColors.size() > 1) { + sortAndReduceColors(allColors); + properties.insert("colors", allColors); + } - return card; + // DETECT CARD POSITIONING INFO + + // cards that enter the field tapped + bool cipt = text.contains("Hideaway") || (text.contains(name + " enters the battlefield tapped") && + !text.contains(name + " enters the battlefield tapped unless")); + + // detect mana generator artifacts + QStringList cardTextRows = text.split("\n"); + bool mArtifact = false; + QString cardType = properties.value("type").toString(); + if (cardType.endsWith("Artifact")) { + for (int i = 0; i < cardTextRows.size(); ++i) { + cardTextRows[i].remove(QRegularExpression(R"(\".*?\")")); + if (cardTextRows[i].contains("{T}") && cardTextRows[i].contains("to your mana pool")) { + mArtifact = true; + } + } + } + + // table row + int tableRow = 1; + QString mainCardType = properties.value("maintype").toString(); + if ((mainCardType == "Land") || mArtifact) + tableRow = 0; + else if ((mainCardType == "Sorcery") || (mainCardType == "Instant")) + tableRow = 3; + else if (mainCardType == "Creature") + tableRow = 2; + + // card side + QString side = properties.value("side").toString() == "b" ? "back" : "front"; + properties.insert("side", side); + + // upsideDown (flip cards) + bool upsideDown = false; + QStringList additionalNames = properties.value("names").toStringList(); + QString layout = properties.value("layout").toString(); + if (layout == "flip") { + if (properties.value("side").toString() != "front") { + upsideDown = true; + } + // reset the side property, since the card has no back image + properties.insert("side", "front"); + } + + // insert the card and its properties + QList reverseRelatedCards; + CardInfoPerSetMap setsInfo; + setsInfo.insert(setInfo.getPtr()->getShortName(), setInfo); + CardInfoPtr newCard = CardInfo::newInstance(name, text, isToken, properties, relatedCards, reverseRelatedCards, + setsInfo, cipt, tableRow, upsideDown); + + cards.insert(name, newCard); + return newCard; } -int OracleImporter::importTextSpoiler(CardSetPtr set, const QVariant &data) +QString OracleImporter::getStringPropertyFromMap(QVariantMap card, QString propertyName) { - int cards = 0; + return card.contains(propertyName) ? card.value(propertyName).toString() : QString(""); +} - QListIterator it(data.toList()); - QVariantMap map; - QString cardName; - QString cardCost; - QString cmc; - QString cardType; - QString cardPT; - QString cardText; - QStringList colors; +int OracleImporter::importCardsFromSet(CardSetPtr currentSet, const QList &cardsList) +{ + static const QMap cardProperties{ + // mtgjson name => xml name + {"manaCost", "manacost"}, {"convertedManaCost", "cmc"}, {"type", "type"}, + {"loyalty", "loyalty"}, {"layout", "layout"}, {"side", "side"}, + }; + + static const QMap setInfoProperties{// mtgjson name => xml name + {"multiverseId", "muid"}, + {"scryfallId", "uuid"}, + {"number", "num"}, + {"rarity", "rarity"}}; + + int numCards = 0; + QMap splitCards; + QString ptSeparator("/"); + QVariantMap card; + QString layout, name, text, colors, maintype, power, toughness; + bool isToken; + QStringList additionalNames; + QVariantHash properties; + CardInfoPerSet setInfo; QList relatedCards; - QList reverseRelatedCards; // dummy - int cardId; - QString cardUuId; - QString setNumber; - QString rarity; - QString cardLoyalty; - bool upsideDown; - QMap splitCards; - while (it.hasNext()) { - map = it.next().toMap(); + for (const QVariant &cardVar : cardsList) { + card = cardVar.toMap(); /* Currently used layouts are: * augment, double_faced_token, flip, host, leveler, meld, normal, planar, * saga, scheme, split, token, transform, vanguard */ - QString layout = map.value("layout").toString(); + layout = getStringPropertyFromMap(card, "layout"); // don't import tokens from the json file + isToken = false; if (layout == "token") continue; - // Aftermath card layout seems to have been integrated in "split" - if (layout == "split") { - // Enqueue split card for later handling - cardId = map.contains("multiverseId") ? map.value("multiverseId").toInt() : 0; - if (cardId) - splitCards.insertMulti(cardId, map); - continue; - } - // normal cards handling - cardName = map.contains("name") ? map.value("name").toString() : QString(""); - cardCost = map.contains("manaCost") ? map.value("manaCost").toString() : QString(""); - cmc = map.contains("convertedManaCost") ? map.value("convertedManaCost").toString() : QString("0"); - cardType = map.contains("type") ? map.value("type").toString() : QString(""); - cardPT = map.contains("power") || map.contains("toughness") - ? map.value("power").toString() + QString('/') + map.value("toughness").toString() - : QString(""); - cardText = map.contains("text") ? map.value("text").toString() : QString(""); - cardId = map.contains("multiverseId") ? map.value("multiverseId").toInt() : 0; - cardUuId = map.contains("scryfallId") ? map.value("scryfallId").toString() : QString(""); - setNumber = map.contains("number") ? map.value("number").toString() : QString(""); - rarity = map.contains("rarity") ? map.value("rarity").toString() : QString(""); - cardLoyalty = map.contains("loyalty") ? map.value("loyalty").toString() : QString(""); - colors = map.contains("colors") ? map.value("colors").toStringList() : QStringList(); - relatedCards = QList(); - if (map.contains("names")) - for (const QString &name : map.value("names").toStringList()) { - if (name != cardName) - relatedCards.append(new CardRelation(name, true)); - } + name = getStringPropertyFromMap(card, "name"); + text = getStringPropertyFromMap(card, "text"); - if (0 == QString::compare(map.value("layout").toString(), QString("flip"), Qt::CaseInsensitive)) { - QStringList cardNames = map.contains("names") ? map.value("names").toStringList() : QStringList(); - upsideDown = (cardNames.indexOf(cardName) > 0); + // card properties + properties.clear(); + QMapIterator it(cardProperties); + while (it.hasNext()) { + it.next(); + QString mtgjsonProperty = it.key(); + QString xmlPropertyName = it.value(); + QString propertyValue = getStringPropertyFromMap(card, mtgjsonProperty); + if (!propertyValue.isEmpty()) + properties.insert(xmlPropertyName, propertyValue); + } + + // per-set properties + setInfo = CardInfoPerSet(currentSet); + QMapIterator it2(setInfoProperties); + while (it2.hasNext()) { + it2.next(); + QString mtgjsonProperty = it2.key(); + QString xmlPropertyName = it2.value(); + QString propertyValue = getStringPropertyFromMap(card, mtgjsonProperty); + if (!propertyValue.isEmpty()) + setInfo.setProperty(xmlPropertyName, propertyValue); + } + + // special handling properties + colors = card.value("colors").toStringList().join(""); + if (!colors.isEmpty()) + properties.insert("colors", colors); + + maintype = card.value("types").toStringList().first(); + if (!maintype.isEmpty()) + properties.insert("maintype", maintype); + + power = getStringPropertyFromMap(card, "power"); + toughness = getStringPropertyFromMap(card, "toughness"); + if (!(power.isEmpty() && toughness.isEmpty())) + properties.insert("pt", power + ptSeparator + toughness); + + additionalNames = card.value("names").toStringList(); + // split cards are considered a single card, enqueue for later merging + if (layout == "split") { + // get the position of this card part + int index = additionalNames.indexOf(name); + // construct full card name + name = additionalNames.join(QString(" // ")); + SplitCardPart split(index, text, properties, setInfo); + splitCards.insertMulti(name, split); } else { - upsideDown = false; - } + // relations + relatedCards.clear(); + if (additionalNames.size() > 1) { + for (const QString &additionalName : additionalNames) { + if (additionalName != name) + relatedCards.append(new CardRelation(additionalName, true)); + } + } - CardInfoPtr card = - addCard(set->getShortName(), cardName, false, cardId, cardUuId, setNumber, cardCost, cmc, cardType, cardPT, - cardLoyalty, cardText, colors, relatedCards, reverseRelatedCards, upsideDown, rarity); - - if (!set->contains(card)) { - card->addToSet(set); - cards++; + CardInfoPtr newCard = addCard(name, text, isToken, properties, relatedCards, setInfo); + numCards++; } } - // split cards handling - get all unique card muids - QList muids = splitCards.uniqueKeys(); - for (int muid : muids) { - // get all cards for this specific muid - QList maps = splitCards.values(muid); - QStringList names; - // now, reorder the cards using the ordered list of names - QMap orderedMaps; - for (const QVariantMap &inner_map : maps) { - if (names.isEmpty()) - names = inner_map.contains("names") ? inner_map.value("names").toStringList() : QStringList(); - QString name = inner_map.value("name").toString(); - int index = names.indexOf(name); - orderedMaps.insertMulti(index, inner_map); + // split cards handling + QString splitCardPropSeparator = QString(" // "); + QString splitCardTextSeparator = QString("\n\n---\n\n"); + for (const QString &nameSplit : splitCards.uniqueKeys()) { + // get all parts for this specific card + QList splitCardParts = splitCards.values(nameSplit); + // sort them by index (aka position) + qSort(splitCardParts.begin(), splitCardParts.end(), + [](const SplitCardPart &a, const SplitCardPart &b) -> bool { return a.getIndex() < b.getIndex(); }); + + text = QString(""); + isToken = false; + properties.clear(); + relatedCards.clear(); + + int lastIndex = -1; + for (const SplitCardPart &tmp : splitCardParts) { + // some sets have 2 different variations of the same split card, + // eg. Fire // Ice in WC02. Avoid adding duplicates. + if (lastIndex == tmp.getIndex()) + continue; + lastIndex = tmp.getIndex(); + + if (!text.isEmpty()) + text.append(splitCardTextSeparator); + text.append(tmp.getText()); + + if (properties.isEmpty()) { + properties = tmp.getProperties(); + setInfo = tmp.getSetInfo(); + } else { + const QVariantHash &props = tmp.getProperties(); + for (const QString &prop : props.keys()) { + QString originalPropertyValue = properties.value(prop).toString(); + QString thisCardPropertyValue = props.value(prop).toString(); + if (originalPropertyValue != thisCardPropertyValue) { + if (prop == "colors") { + properties.insert(prop, originalPropertyValue + thisCardPropertyValue); + } else { + properties.insert(prop, + originalPropertyValue + splitCardPropSeparator + thisCardPropertyValue); + } + } + } + } } - // clean variables - cardName = ""; - cardCost = ""; - cmc = ""; - cardType = ""; - cardPT = ""; - cardText = ""; - cardUuId = ""; - setNumber = ""; - rarity = ""; - cardLoyalty = ""; - colors.clear(); - - // loop cards and merge their contents - QString prefix = QString(" // "); - QString prefix2 = QString("\n\n---\n\n"); - for (const QVariantMap &inner_map : orderedMaps.values()) { - if (inner_map.contains("name")) { - if (!cardName.isEmpty()) - cardName += (orderedMaps.count() > 2) ? QString("/") : prefix; - cardName += inner_map.value("name").toString(); - } - if (inner_map.contains("manaCost")) { - if (!cardCost.isEmpty()) - cardCost += prefix; - cardCost += inner_map.value("manaCost").toString(); - } - if (inner_map.contains("convertedManaCost")) { - if (!cmc.isEmpty()) - cmc += prefix; - cmc += inner_map.value("convertedManaCost").toString(); - } - if (inner_map.contains("type")) { - if (!cardType.isEmpty()) - cardType += prefix; - cardType += inner_map.value("type").toString(); - } - if (inner_map.contains("power") || inner_map.contains("toughness")) { - if (!cardPT.isEmpty()) - cardPT += prefix; - cardPT += inner_map.value("power").toString() + QString('/') + inner_map.value("toughness").toString(); - } - if (inner_map.contains("text")) { - if (!cardText.isEmpty()) - cardText += prefix2; - cardText += inner_map.value("text").toString(); - } - if (inner_map.contains("uuid")) { - if (cardUuId.isEmpty()) - cardUuId = inner_map.value("uuid").toString(); - } - if (inner_map.contains("number")) { - if (setNumber.isEmpty()) - setNumber = inner_map.value("number").toString(); - } - if (inner_map.contains("rarity")) { - if (rarity.isEmpty()) - rarity = inner_map.value("rarity").toString(); - } - - colors << inner_map.value("colors").toStringList(); - } - - colors.removeDuplicates(); - if (colors.length() > 1) { - sortColors(colors); - } - - // Fortunately, there are no split cards that flip, transform or meld. - relatedCards = QList(); - reverseRelatedCards = QList(); - upsideDown = false; - - // add the card - CardInfoPtr card = - addCard(set->getShortName(), cardName, false, muid, cardUuId, setNumber, cardCost, cmc, cardType, cardPT, - cardLoyalty, cardText, colors, relatedCards, reverseRelatedCards, upsideDown, rarity); - - if (!set->contains(card)) { - card->addToSet(set); - cards++; - } + CardInfoPtr newCard = addCard(name, text, isToken, properties, relatedCards, setInfo); + numCards++; } - return cards; + return numCards; } -void OracleImporter::sortColors(QStringList &colors) +void OracleImporter::sortAndReduceColors(QString &colors) { - const QHash colorOrder{{"W", 0}, {"U", 1}, {"B", 2}, {"R", 3}, {"G", 4}}; - std::sort(colors.begin(), colors.end(), [&colorOrder](const QString a, const QString b) { + // sort + const QHash colorOrder{{'W', 0}, {'U', 1}, {'B', 2}, {'R', 3}, {'G', 4}}; + std::sort(colors.begin(), colors.end(), [&colorOrder](const QChar a, const QChar b) { return colorOrder.value(a, INT_MAX) < colorOrder.value(b, INT_MAX); }); + // reduce + QChar lastChar = '\0'; + for (int i = 0; i < colors.size(); ++i) { + if (colors.at(i) == lastChar) + colors.remove(i, 1); + else + lastChar = colors.at(i); + } } int OracleImporter::startImport() @@ -333,25 +341,21 @@ int OracleImporter::startImport() clear(); int setCards = 0, setIndex = 0; - QListIterator it(allSets); - const SetToDownload *curSet; - // add an empty set for tokens CardSetPtr tokenSet = CardSet::newInstance(TOKENS_SETNAME, tr("Dummy set containing tokens"), "Tokens"); sets.insert(TOKENS_SETNAME, tokenSet); - while (it.hasNext()) { - curSet = &it.next(); - CardSetPtr set = CardSet::newInstance(curSet->getShortName(), curSet->getLongName(), curSet->getSetType(), - curSet->getReleaseDate()); - if (!sets.contains(set->getShortName())) - sets.insert(set->getShortName(), set); + for (const SetToDownload &curSetToParse : allSets) { + CardSetPtr newSet = CardSet::newInstance(curSetToParse.getShortName(), curSetToParse.getLongName(), + curSetToParse.getSetType(), curSetToParse.getReleaseDate()); + if (!sets.contains(newSet->getShortName())) + sets.insert(newSet->getShortName(), newSet); - int setCardsHere = importTextSpoiler(set, curSet->getCards()); + int numCardsInSet = importCardsFromSet(newSet, curSetToParse.getCards()); ++setIndex; - emit setIndexChanged(setCardsHere, setIndex, curSet->getLongName()); + emit setIndexChanged(numCardsInSet, setIndex, curSetToParse.getLongName()); } emit setIndexChanged(setCards, setIndex, QString()); @@ -362,6 +366,6 @@ int OracleImporter::startImport() bool OracleImporter::saveToFile(const QString &fileName) { - CockatriceXml3Parser parser; + CockatriceXml4Parser parser; return parser.saveToFile(sets, cards, fileName); } \ No newline at end of file diff --git a/oracle/src/oracleimporter.h b/oracle/src/oracleimporter.h index 68a7b62b..d4228e09 100644 --- a/oracle/src/oracleimporter.h +++ b/oracle/src/oracleimporter.h @@ -3,14 +3,14 @@ #include #include - #include +#include class SetToDownload { private: QString shortName, longName; - QVariant cards; + QList cards; QDate releaseDate; QString setType; @@ -23,7 +23,7 @@ public: { return longName; } - const QVariant &getCards() const + const QList &getCards() const { return cards; } @@ -35,12 +35,13 @@ public: { return releaseDate; } - SetToDownload(const QString &_shortName, - const QString &_longName, - const QVariant &_cards, - const QString &_setType = QString(), + SetToDownload(QString _shortName, + QString _longName, + QList _cards, + QString _setType = QString(), const QDate &_releaseDate = QDate()) - : shortName(_shortName), longName(_longName), cards(_cards), releaseDate(_releaseDate), setType(_setType) + : shortName(std::move(_shortName)), longName(std::move(_longName)), cards(std::move(_cards)), + releaseDate(_releaseDate), setType(std::move(_setType)) { } bool operator<(const SetToDownload &set) const @@ -49,6 +50,34 @@ public: } }; +class SplitCardPart +{ +public: + SplitCardPart(int _index, const QString &_text, const QVariantHash &_properties, CardInfoPerSet setInfo); + inline const int &getIndex() const + { + return index; + } + inline const QString &getText() const + { + return text; + } + inline const QVariantHash &getProperties() const + { + return properties; + } + inline const CardInfoPerSet &getSetInfo() const + { + return setInfo; + } + +private: + int index; + QString text; + QVariantHash properties; + CardInfoPerSet setInfo; +}; + class OracleImporter : public CardDatabase { Q_OBJECT @@ -57,33 +86,22 @@ private: QVariantMap setsMap; QString dataDir; - CardInfoPtr addCard(const QString &setName, - QString cardName, + CardInfoPtr addCard(QString name, + QString text, bool isToken, - int cardId, - QString &cardUuId, - QString &setNumber, - QString &cardCost, - QString &cmc, - const QString &cardType, - const QString &cardPT, - const QString &cardLoyalty, - const QString &cardText, - const QStringList &colors, - const QList &relatedCards, - const QList &reverseRelatedCards, - bool upsideDown, - QString &rarity); + QVariantHash properties, + QList &relatedCards, + CardInfoPerSet setInfo); signals: void setIndexChanged(int cardsImported, int setIndex, const QString &setName); void dataReadProgress(int bytesRead, int totalBytes); public: - OracleImporter(const QString &_dataDir, QObject *parent = 0); + explicit OracleImporter(const QString &_dataDir, QObject *parent = nullptr); bool readSetsFromByteArray(const QByteArray &data); int startImport(); bool saveToFile(const QString &fileName); - int importTextSpoiler(CardSetPtr set, const QVariant &data); + int importCardsFromSet(CardSetPtr currentSet, const QList &cards); QList &getSets() { return allSets; @@ -94,7 +112,8 @@ public: } protected: - void sortColors(QStringList &colors); + inline QString getStringPropertyFromMap(QVariantMap card, QString propertyName); + void sortAndReduceColors(QString &colors); }; #endif diff --git a/cockatrice/src/qt-json/AUTHORS b/oracle/src/qt-json/AUTHORS similarity index 100% rename from cockatrice/src/qt-json/AUTHORS rename to oracle/src/qt-json/AUTHORS diff --git a/cockatrice/src/qt-json/LICENSE b/oracle/src/qt-json/LICENSE similarity index 100% rename from cockatrice/src/qt-json/LICENSE rename to oracle/src/qt-json/LICENSE diff --git a/cockatrice/src/qt-json/README b/oracle/src/qt-json/README similarity index 100% rename from cockatrice/src/qt-json/README rename to oracle/src/qt-json/README diff --git a/cockatrice/src/qt-json/json.cpp b/oracle/src/qt-json/json.cpp similarity index 100% rename from cockatrice/src/qt-json/json.cpp rename to oracle/src/qt-json/json.cpp diff --git a/cockatrice/src/qt-json/json.h b/oracle/src/qt-json/json.h similarity index 100% rename from cockatrice/src/qt-json/json.h rename to oracle/src/qt-json/json.h diff --git a/oracle/translations/oracle_en.ts b/oracle/translations/oracle_en.ts index a65be73a..3a793e74 100644 --- a/oracle/translations/oracle_en.ts +++ b/oracle/translations/oracle_en.ts @@ -253,7 +253,7 @@ OracleImporter - + Dummy set containing tokens diff --git a/tests/carddatabase/CMakeLists.txt b/tests/carddatabase/CMakeLists.txt index 5ea6d8ff..a592f053 100644 --- a/tests/carddatabase/CMakeLists.txt +++ b/tests/carddatabase/CMakeLists.txt @@ -2,8 +2,9 @@ ADD_DEFINITIONS("-DCARDDB_DATADIR=\"${CMAKE_CURRENT_SOURCE_DIR}/data/\"") add_executable(carddatabase_test carddatabase_test.cpp ../../cockatrice/src/carddatabase.cpp + ../../cockatrice/src/carddbparser/carddatabaseparser.cpp ../../cockatrice/src/carddbparser/cockatricexml3.cpp - + ../../cockatrice/src/carddbparser/cockatricexml4.cpp ) if(NOT GTEST_FOUND) add_dependencies(carddatabase_test gtest) diff --git a/tests/carddatabase/carddatabase_test.cpp b/tests/carddatabase/carddatabase_test.cpp index 795793df..0cff817b 100644 --- a/tests/carddatabase/carddatabase_test.cpp +++ b/tests/carddatabase/carddatabase_test.cpp @@ -64,7 +64,6 @@ TEST(CardDatabaseTest, LoadXml) // ensure the card database is empty at start ASSERT_EQ(0, db->getCardList().size()) << "Cards not empty at start"; ASSERT_EQ(0, db->getSetList().size()) << "Sets not empty at start"; - ASSERT_EQ(0, db->getAllColors().size()) << "Colors not empty at start"; ASSERT_EQ(0, db->getAllMainCardTypes().size()) << "Types not empty at start"; ASSERT_EQ(NotLoaded, db->getLoadStatus()) << "Incorrect status at start"; @@ -72,7 +71,6 @@ TEST(CardDatabaseTest, LoadXml) db->loadCardDatabases(); ASSERT_EQ(6, db->getCardList().size()) << "Wrong card count after load"; ASSERT_EQ(3, db->getSetList().size()) << "Wrong sets count after load"; - ASSERT_EQ(4, db->getAllColors().size()) << "Wrong colors count after load"; ASSERT_EQ(2, db->getAllMainCardTypes().size()) << "Wrong types count after load"; ASSERT_EQ(Ok, db->getLoadStatus()) << "Wrong status after load"; @@ -80,7 +78,6 @@ TEST(CardDatabaseTest, LoadXml) db->clear(); ASSERT_EQ(0, db->getCardList().size()) << "Cards not empty after clear"; ASSERT_EQ(0, db->getSetList().size()) << "Sets not empty after clear"; - ASSERT_EQ(0, db->getAllColors().size()) << "Colors not empty after clear"; ASSERT_EQ(0, db->getAllMainCardTypes().size()) << "Types not empty after clear"; ASSERT_EQ(NotLoaded, db->getLoadStatus()) << "Incorrect status after clear"; }