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 <ZaHalpern+github@gmail.com>

* Fix includes

Signed-off-by: Zach Halpern <ZaHalpern+github@gmail.com>

* Update carddatabase.h
This commit is contained in:
ctrlaltca 2019-01-24 00:17:10 +01:00 committed by Zach H
parent 19180243aa
commit ed70099e36
44 changed files with 1814 additions and 1360 deletions

View file

@ -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<CardRelation *> &_relatedCards,
const QList<CardRelation *> &_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<CardRelation *> &_relatedCards,
const QList<CardRelation *> &_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<QString> colors;
QHashIterator<QString, CardInfoPtr> 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<QString> 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<CardRelation *>();
}
// 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);
}

View file

@ -9,10 +9,13 @@
#include <QMetaType>
#include <QSharedPointer>
#include <QStringList>
#include <QVariant>
#include <QVector>
#include <utility>
class CardDatabase;
class CardInfo;
class CardInfoPerSet;
class CardSet;
class CardRelation;
class ICardDatabaseParser;
@ -21,6 +24,7 @@ typedef QMap<QString, QString> QStringMap;
typedef QMap<QString, int> MuidMap;
typedef QSharedPointer<CardInfo> CardInfoPtr;
typedef QSharedPointer<CardSet> CardSetPtr;
typedef QMap<QString, CardInfoPerSet> CardInfoPerSetMap;
Q_DECLARE_METATYPE(CardInfoPtr)
@ -112,178 +116,162 @@ public:
QStringList getUnknownSetsNames();
};
class CardInfoPerSet
{
public:
explicit CardInfoPerSet(const CardSetPtr &_set = QSharedPointer<CardSet>(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<CardRelation *> relatedCards;
// the card i'm reverse-related to
QList<CardRelation *> reverseRelatedCards;
// the cards thare are reverse-related to me
QList<CardRelation *> 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<CardRelation *> &_relatedCards = QList<CardRelation *>(),
const QList<CardRelation *> &_reverseRelatedCards = QList<CardRelation *>(),
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<CardRelation *> &_relatedCards = QList<CardRelation *>(),
const QList<CardRelation *> &_reverseRelatedCards = QList<CardRelation *>(),
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<CardRelation *> &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
#endif

View file

@ -14,9 +14,7 @@ CardDatabaseModel::CardDatabaseModel(CardDatabase *_db, bool _showOnlyCardsFromE
cardDatabaseEnabledSetsChanged();
}
CardDatabaseModel::~CardDatabaseModel()
{
}
CardDatabaseModel::~CardDatabaseModel() = default;
QMap<wchar_t, wchar_t> 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;
}

View file

@ -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<wchar_t, wchar_t> 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

View file

@ -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;
}

View file

@ -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")

View file

@ -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<CardRelation *> 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<bool>(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<bool>(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<CardRelation *> 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");
}

View file

@ -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

View file

@ -0,0 +1,362 @@
#include "cockatricexml4.h"
#include <QDebug>
#include <QFile>
#include <QXmlStreamReader>
#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<CardRelation *> 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<bool>(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<CardRelation *> 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<CardRelation *> 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;
}

View file

@ -0,0 +1,28 @@
#ifndef COCKATRICE_XML4_H
#define COCKATRICE_XML4_H
#include <QXmlStreamReader>
#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

View file

@ -1,3 +1,5 @@
#include <utility>
#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);
}

View file

@ -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);
};

View file

@ -1,137 +1,83 @@
#include "cardinfotext.h"
#include "carditem.h"
#include "game_specific_terms.h"
#include "main.h"
#include <QGridLayout>
#include <QLabel>
#include <QTextEdit>
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 = "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>";
text += QString("<tr><td>%1</td><td width=\"5\"></td><td>%2</td></tr>")
.arg(tr("Name:"), card->getName().toHtmlEscaped());
QStringList cardProps = card->getProperties();
foreach (QString key, cardProps) {
QString keyText = Mtg::getNicePropertyName(key).toHtmlEscaped() + ":";
text +=
QString("<tr><td>%1</td><td></td><td>%2</td></tr>").arg(keyText, card->getProperty(key).toHtmlEscaped());
}
auto relatedCards = card->getRelatedCards();
auto reverserelatedCards2Me = card->getReverseRelatedCards2Me();
if (relatedCards.size() || reverserelatedCards2Me.size()) {
text += QString("<tr><td>%1</td><td width=\"5\"></td><td>").arg(tr("Related cards:"));
for (int i = 0; i < relatedCards.size(); ++i) {
QString tmp = relatedCards.at(i)->getName().toHtmlEscaped();
text += "<a href=\"" + tmp + "\">" + tmp + "</a><br>";
}
for (int i = 0; i < reverserelatedCards2Me.size(); ++i) {
QString tmp = reverserelatedCards2Me.at(i)->getName().toHtmlEscaped();
text += "<a href=\"" + tmp + "\">" + tmp + "</a><br>";
}
text += "</td></tr>";
}
text += "</table>";
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("");
}

View file

@ -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);
};

View file

@ -1,6 +1,8 @@
#include "cardinfowidget.h"
#include <utility>
#include "cardinfopicture.h"
#include "cardinfotext.h"
#include "cardinfowidget.h"
#include "carditem.h"
#include "main.h"
#include <QDesktopWidget>
@ -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<int>(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()));

View file

@ -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);

View file

@ -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<CardRelation *>(), QList<CardRelation *>(), false, 0, false, 0,
SetList(), QStringMap(), MuidMap(), QStringMap(), QStringMap(), QStringMap());
info = CardInfo::newInstance(cardName);
} else {
return {};
}

View file

@ -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
{

View file

@ -17,7 +17,7 @@
#include <QTreeView>
#include <QVBoxLayout>
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)

View file

@ -35,7 +35,7 @@ private:
QTreeView *chooseTokenView;
public:
DlgEditTokens(QWidget *parent = nullptr);
explicit DlgEditTokens(QWidget *parent = nullptr);
};
#endif

View file

@ -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;
}
}

View file

@ -1,12 +1,14 @@
#ifndef FILTERTREE_H
#define FILTERTREE_H
#include "carddatabase.h"
#include "cardfilter.h"
#include <QList>
#include <QMap>
#include <QObject>
#include "carddatabase.h"
#include "cardfilter.h"
#include <utility>
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();
};

View file

@ -0,0 +1,49 @@
#ifndef GAME_SPECIFIC_TERMS_H
#define GAME_SPECIFIC_TERMS_H
#include <QCoreApplication>
#include <QString>
/*
* 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

View file

@ -1,6 +1,6 @@
#include "handle_public_servers.h"
#include "qt-json/json.h"
#include "settingscache.h"
#include <QJsonDocument>
#include <QMessageBox>
#include <QNetworkAccessManager>
#include <QNetworkReply>
@ -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;

View file

@ -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<QString, QString> transformMap = QMap<QString, QString>();
// 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))

View file

@ -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<Player *> &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<QAction *> 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<QAction *> 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<QAction *>(sender());
QMenu *menu = static_cast<QMenu *>(action->parentWidget());
auto *action = static_cast<QAction *>(sender());
auto *menu = static_cast<QMenu *>(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<GameScene *>(scene())->toggleZoneView(this, "deck", number);
@ -934,7 +934,7 @@ void Player::actViewGraveyard()
void Player::actRevealRandomGraveyardCard()
{
Command_RevealCards cmd;
QAction *action = dynamic_cast<QAction *>(sender());
auto *action = dynamic_cast<QAction *>(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<google::protobuf::uint32>(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<google::protobuf::uint32>(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<QAction *>(sender());
auto *action = static_cast<QAction *>(sender());
CardInfoPtr cardInfo = db->getCard(action->text());
if (!cardInfo) {
return;
@ -1199,7 +1199,7 @@ void Player::actCreateRelatedCard()
if (!sourceCard) {
return;
}
QAction *action = static_cast<QAction *>(sender());
auto *action = static_cast<QAction *>(sender());
// If there is a better way of passing a CardRelation through a QAction, please add it here.
QList<CardRelation *> relatedCards = QList<CardRelation *>();
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<QAction *>(sender());
auto *a = qobject_cast<QAction *>(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 "<Descriptors> <Power>/<Toughness> <Card Name> " or "<Card Name> ".
// dbName for tokens should take the form of "<Card Name> ".
// 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<CardItem *>(arrow->getStartItem());
CardItem *targetCard = qgraphicsitem_cast<CardItem *>(arrow->getTargetItem());
auto *startCard = static_cast<CardItem *>(arrow->getStartItem());
auto *targetCard = qgraphicsitem_cast<CardItem *>(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<CardItem *> &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<CardItem *> 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<int, Player *> &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<QAction *>(sender());
auto *a = dynamic_cast<QAction *>(sender());
QList<QGraphicsItem *> sel = scene()->selectedItems();
QList<CardItem *> cardList;
while (!sel.isEmpty()) {
@ -2353,14 +2340,13 @@ void Player::cardMenuAction()
QList<const ::google::protobuf::Message *> 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<CardMenuActionType>(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<CardMenuActionType>(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<const ::google::protobuf::Message *> commandList;
QListIterator<QGraphicsItem *> j(scene()->selectedItems());
while (j.hasNext()) {
CardItem *card = static_cast<CardItem *>(j.next());
Command_SetCardAttr *cmd = new Command_SetCardAttr;
auto *card = static_cast<CardItem *>(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<const ::google::protobuf::Message *> commandList;
QListIterator<QGraphicsItem *> selected(scene()->selectedItems());
while (selected.hasNext()) {
CardItem *card = static_cast<CardItem *>(selected.next());
auto *card = static_cast<CardItem *>(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<QGraphicsItem *> i(scene()->selectedItems());
while (i.hasNext()) {
CardItem *card = static_cast<CardItem *>(i.next());
auto *card = static_cast<CardItem *>(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<const ::google::protobuf::Message *> commandList;
QListIterator<QGraphicsItem *> j(scene()->selectedItems());
while (j.hasNext()) {
CardItem *card = static_cast<CardItem *>(j.next());
Command_SetCardAttr *cmd = new Command_SetCardAttr;
auto *card = static_cast<CardItem *>(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<QGraphicsItem *> i(scene()->selectedItems());
while (i.hasNext()) {
CardItem *card = static_cast<CardItem *>(i.next());
auto *card = static_cast<CardItem *>(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<const ::google::protobuf::Message *> commandList;
i.toFront();
while (i.hasNext()) {
CardItem *card = static_cast<CardItem *>(i.next());
Command_SetCardAttr *cmd = new Command_SetCardAttr;
auto *card = static_cast<CardItem *>(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<QAction *>(sender());
auto *action = static_cast<QAction *>(sender());
int counterId = action->data().toInt() / 1000;
QList<const ::google::protobuf::Message *> commandList;
switch (action->data().toInt() % 1000) { // TODO: define case numbers
case 9: {
QListIterator<QGraphicsItem *> i(scene()->selectedItems());
while (i.hasNext()) {
CardItem *card = static_cast<CardItem *>(i.next());
auto *card = static_cast<CardItem *>(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<QGraphicsItem *> i(scene()->selectedItems());
while (i.hasNext()) {
CardItem *card = static_cast<CardItem *>(i.next());
auto *card = static_cast<CardItem *>(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<QGraphicsItem *> i(scene()->selectedItems());
while (i.hasNext()) {
CardItem *card = static_cast<CardItem *>(i.next());
Command_SetCardCounter *cmd = new Command_SetCardCounter;
auto *card = static_cast<CardItem *>(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);

View file

@ -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();

View file

@ -1,3 +0,0 @@
Eeli Reilin <eeli@emicode.fi>
Luis Gustavo S. Barreto <gustavosbarreto@gmail.com>
Stephen Kockentiedt <Stephen@Kockentiedt.name>

View file

@ -1,27 +0,0 @@
Copyright 2011 Eeli Reilin. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL EELI REILIN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation
are those of the authors and should not be interpreted as representing
official policies, either expressed or implied, of Eeli Reilin.

View file

@ -1,96 +0,0 @@
########################################################################
1. INTRODUCTION
The Json class is a simple class for parsing JSON data into a QVariant
hierarchies. Now, we can also reverse the process and serialize
QVariant hierarchies into valid JSON data.
########################################################################
2. HOW TO USE
The parser is really easy to use. Let's say we have the following
QString of JSON data:
------------------------------------------------------------------------
{
"encoding" : "UTF-8",
"plug-ins" : [
"python",
"c++",
"ruby"
],
"indent" : {
"length" : 3,
"use_space" : true
}
}
------------------------------------------------------------------------
We would first call the parse-method:
------------------------------------------------------------------------
//Say that we're using the QtJson namespace
using namespace QtJson;
bool ok;
//json is a QString containing the JSON data
QVariantMap result = Json::parse(json, ok).toMap();
if(!ok) {
qFatal("An error occurred during parsing");
exit(1);
}
------------------------------------------------------------------------
Assuming the parsing process completed without errors, we would then
go through the hierarchy:
------------------------------------------------------------------------
qDebug() << "encoding:" << result["encoding"].toString();
qDebug() << "plugins:";
foreach(QVariant plugin, result["plug-ins"].toList()) {
qDebug() << "\t-" << plugin.toString();
}
QVariantMap nestedMap = result["indent"].toMap();
qDebug() << "length:" << nestedMap["length"].toInt();
qDebug() << "use_space:" << nestedMap["use_space"].toBool();
------------------------------------------------------------------------
The previous code would print out the following:
------------------------------------------------------------------------
encoding: "UTF-8"
plugins:
- "python"
- "c++"
- "ruby"
length: 3
use_space: true
------------------------------------------------------------------------
To write JSON data from Qt object is as simple as parsing:
------------------------------------------------------------------------
QVariantMap map;
map["name"] = "Name";
map["age"] = 22;
QByteArray data = Json::serialize(map);
------------------------------------------------------------------------
The byte array 'data' contains valid JSON data:
------------------------------------------------------------------------
{
name: "Luis Gustavo",
age: 22,
}
------------------------------------------------------------------------
########################################################################
4. CONTRIBUTING
The code is available to download at GitHub. Contribute if you dare!

View file

@ -1,614 +0,0 @@
/* Copyright 2011 Eeli Reilin. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL EELI REILIN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation
* are those of the authors and should not be interpreted as representing
* official policies, either expressed or implied, of Eeli Reilin.
*/
/**
* \file json.cpp
*/
#include "json.h"
#include <iostream>
namespace QtJson
{
static QString sanitizeString(QString str)
{
str.replace(QLatin1String("\\"), QLatin1String("\\\\"));
str.replace(QLatin1String("\""), QLatin1String("\\\""));
str.replace(QLatin1String("\b"), QLatin1String("\\b"));
str.replace(QLatin1String("\f"), QLatin1String("\\f"));
str.replace(QLatin1String("\n"), QLatin1String("\\n"));
str.replace(QLatin1String("\r"), QLatin1String("\\r"));
str.replace(QLatin1String("\t"), QLatin1String("\\t"));
return QString(QLatin1String("\"%1\"")).arg(str);
}
static QByteArray join(const QList<QByteArray> &list, const QByteArray &sep)
{
QByteArray res;
Q_FOREACH(const QByteArray &i, list)
{
if(!res.isEmpty())
{
res += sep;
}
res += i;
}
return res;
}
/**
* parse
*/
QVariant Json::parse(const QString &json)
{
bool success = true;
return Json::parse(json, success);
}
/**
* parse
*/
QVariant Json::parse(const QString &json, bool &success)
{
success = true;
//Return an empty QVariant if the JSON data is either null or empty
if(!json.isNull() || !json.isEmpty())
{
QString data = json;
//We'll start from index 0
int index = 0;
//Parse the first value
QVariant value = Json::parseValue(data, index, success);
//Return the parsed value
return value;
}
else
{
//Return the empty QVariant
return QVariant();
}
}
QByteArray Json::serialize(const QVariant &data)
{
bool success = true;
return Json::serialize(data, success);
}
QByteArray Json::serialize(const QVariant &data, bool &success)
{
QByteArray str;
success = true;
if(!data.isValid()) // invalid or null?
{
str = "null";
}
else if((data.type() == QVariant::List) || (data.type() == QVariant::StringList)) // variant is a list?
{
QList<QByteArray> values;
const QVariantList list = data.toList();
Q_FOREACH(const QVariant& v, list)
{
QByteArray serializedValue = serialize(v);
if(serializedValue.isNull())
{
success = false;
break;
}
values << serializedValue;
}
str = "[ " + join( values, ", " ) + " ]";
}
else if(data.type() == QVariant::Hash) // variant is a hash?
{
const QVariantHash vhash = data.toHash();
QHashIterator<QString, QVariant> it( vhash );
str = "{ ";
QList<QByteArray> pairs;
while(it.hasNext())
{
it.next();
QByteArray serializedValue = serialize(it.value());
if(serializedValue.isNull())
{
success = false;
break;
}
pairs << sanitizeString(it.key()).toUtf8() + " : " + serializedValue;
}
str += join(pairs, ", ");
str += " }";
}
else if(data.type() == QVariant::Map) // variant is a map?
{
const QVariantMap vmap = data.toMap();
QMapIterator<QString, QVariant> it( vmap );
str = "{ ";
QList<QByteArray> pairs;
while(it.hasNext())
{
it.next();
QByteArray serializedValue = serialize(it.value());
if(serializedValue.isNull())
{
success = false;
break;
}
pairs << sanitizeString(it.key()).toUtf8() + " : " + serializedValue;
}
str += join(pairs, ", ");
str += " }";
}
else if((data.type() == QVariant::String) || (data.type() == QVariant::ByteArray)) // a string or a byte array?
{
str = sanitizeString(data.toString()).toUtf8();
}
else if(data.type() == QVariant::Double) // double?
{
str = QByteArray::number(data.toDouble(), 'g', 20);
if(!str.contains(".") && ! str.contains("e"))
{
str += ".0";
}
}
else if (data.type() == QVariant::Bool) // boolean value?
{
str = data.toBool() ? "true" : "false";
}
else if (data.type() == QVariant::ULongLong) // large unsigned number?
{
str = QByteArray::number(data.value<qulonglong>());
}
else if ( data.canConvert<qlonglong>() ) // any signed number?
{
str = QByteArray::number(data.value<qlonglong>());
}
else if (data.canConvert<long>())
{
str = QString::number(data.value<long>()).toUtf8();
}
else if (data.canConvert<QString>()) // can value be converted to string?
{
// this will catch QDate, QDateTime, QUrl, ...
str = sanitizeString(data.toString()).toUtf8();
}
else
{
success = false;
}
if (success)
{
return str;
}
else
{
return QByteArray();
}
}
/**
* parseValue
*/
QVariant Json::parseValue(const QString &json, int &index, bool &success)
{
//Determine what kind of data we should parse by
//checking out the upcoming token
switch(Json::lookAhead(json, index))
{
case JsonTokenString:
return Json::parseString(json, index, success);
case JsonTokenNumber:
return Json::parseNumber(json, index);
case JsonTokenCurlyOpen:
return Json::parseObject(json, index, success);
case JsonTokenSquaredOpen:
return Json::parseArray(json, index, success);
case JsonTokenTrue:
Json::nextToken(json, index);
return QVariant(true);
case JsonTokenFalse:
Json::nextToken(json, index);
return QVariant(false);
case JsonTokenNull:
Json::nextToken(json, index);
return QVariant();
case JsonTokenNone:
break;
}
//If there were no tokens, flag the failure and return an empty QVariant
success = false;
return QVariant();
}
/**
* parseObject
*/
QVariant Json::parseObject(const QString &json, int &index, bool &success)
{
QVariantMap map;
int token;
//Get rid of the whitespace and increment index
Json::nextToken(json, index);
//Loop through all of the key/value pairs of the object
bool done = false;
while(!done)
{
//Get the upcoming token
token = Json::lookAhead(json, index);
if(token == JsonTokenNone)
{
success = false;
return QVariantMap();
}
else if(token == JsonTokenComma)
{
Json::nextToken(json, index);
}
else if(token == JsonTokenCurlyClose)
{
Json::nextToken(json, index);
return map;
}
else
{
//Parse the key/value pair's name
QString name = Json::parseString(json, index, success).toString();
if(!success)
{
return QVariantMap();
}
//Get the next token
token = Json::nextToken(json, index);
//If the next token is not a colon, flag the failure
//return an empty QVariant
if(token != JsonTokenColon)
{
success = false;
return QVariant(QVariantMap());
}
//Parse the key/value pair's value
QVariant value = Json::parseValue(json, index, success);
if(!success)
{
return QVariantMap();
}
//Assign the value to the key in the map
map[name] = value;
}
}
//Return the map successfully
return QVariant(map);
}
/**
* parseArray
*/
QVariant Json::parseArray(const QString &json, int &index, bool &success)
{
QVariantList list;
Json::nextToken(json, index);
bool done = false;
while(!done)
{
int token = Json::lookAhead(json, index);
if(token == JsonTokenNone)
{
success = false;
return QVariantList();
}
else if(token == JsonTokenComma)
{
Json::nextToken(json, index);
}
else if(token == JsonTokenSquaredClose)
{
Json::nextToken(json, index);
break;
}
else
{
QVariant value = Json::parseValue(json, index, success);
if(!success)
{
return QVariantList();
}
list.push_back(value);
}
}
return QVariant(list);
}
/**
* parseString
*/
QVariant Json::parseString(const QString &json, int &index, bool &success)
{
QString s;
QChar c;
Json::eatWhitespace(json, index);
c = json[index++];
bool complete = false;
while(!complete)
{
if(index == json.size())
{
break;
}
c = json[index++];
if(c == '\"')
{
complete = true;
break;
}
else if(c == '\\')
{
if(index == json.size())
{
break;
}
c = json[index++];
if(c == '\"')
{
s.append('\"');
}
else if(c == '\\')
{
s.append('\\');
}
else if(c == '/')
{
s.append('/');
}
else if(c == 'b')
{
s.append('\b');
}
else if(c == 'f')
{
s.append('\f');
}
else if(c == 'n')
{
s.append('\n');
}
else if(c == 'r')
{
s.append('\r');
}
else if(c == 't')
{
s.append('\t');
}
else if(c == 'u')
{
int remainingLength = json.size() - index;
if(remainingLength >= 4)
{
QString unicodeStr = json.mid(index, 4);
int symbol = unicodeStr.toInt(0, 16);
s.append(QChar(symbol));
index += 4;
}
else
{
break;
}
}
}
else
{
s.append(c);
}
}
if(!complete)
{
success = false;
return QVariant();
}
return QVariant(s);
}
/**
* parseNumber
*/
QVariant Json::parseNumber(const QString &json, int &index)
{
Json::eatWhitespace(json, index);
int lastIndex = Json::lastIndexOfNumber(json, index);
int charLength = (lastIndex - index) + 1;
QString numberStr;
numberStr = json.mid(index, charLength);
index = lastIndex + 1;
if (numberStr.contains('.')) {
return QVariant(numberStr.toDouble(NULL));
} else if (numberStr.startsWith('-')) {
return QVariant(numberStr.toLongLong(NULL));
} else {
return QVariant(numberStr.toULongLong(NULL));
}
}
/**
* lastIndexOfNumber
*/
int Json::lastIndexOfNumber(const QString &json, int index)
{
static const QString numericCharacters("0123456789+-.eE");
int lastIndex;
for(lastIndex = index; lastIndex < json.size(); lastIndex++)
{
if(numericCharacters.indexOf(json[lastIndex]) == -1)
{
break;
}
}
return lastIndex -1;
}
/**
* eatWhitespace
*/
void Json::eatWhitespace(const QString &json, int &index)
{
static const QString whitespaceChars(" \t\n\r");
for(; index < json.size(); index++)
{
if(whitespaceChars.indexOf(json[index]) == -1)
{
break;
}
}
}
/**
* lookAhead
*/
int Json::lookAhead(const QString &json, int index)
{
int saveIndex = index;
return Json::nextToken(json, saveIndex);
}
/**
* nextToken
*/
int Json::nextToken(const QString &json, int &index)
{
Json::eatWhitespace(json, index);
if(index == json.size())
{
return JsonTokenNone;
}
QChar c = json[index];
index++;
switch(c.toLatin1())
{
case '{': return JsonTokenCurlyOpen;
case '}': return JsonTokenCurlyClose;
case '[': return JsonTokenSquaredOpen;
case ']': return JsonTokenSquaredClose;
case ',': return JsonTokenComma;
case '"': return JsonTokenString;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '-': return JsonTokenNumber;
case ':': return JsonTokenColon;
}
index--;
int remainingLength = json.size() - index;
//True
if(remainingLength >= 4)
{
if (json[index] == 't' && json[index + 1] == 'r' &&
json[index + 2] == 'u' && json[index + 3] == 'e')
{
index += 4;
return JsonTokenTrue;
}
}
//False
if (remainingLength >= 5)
{
if (json[index] == 'f' && json[index + 1] == 'a' &&
json[index + 2] == 'l' && json[index + 3] == 's' &&
json[index + 4] == 'e')
{
index += 5;
return JsonTokenFalse;
}
}
//Null
if (remainingLength >= 4)
{
if (json[index] == 'n' && json[index + 1] == 'u' &&
json[index + 2] == 'l' && json[index + 3] == 'l')
{
index += 4;
return JsonTokenNull;
}
}
return JsonTokenNone;
}
} //end namespace

View file

@ -1,204 +0,0 @@
/* Copyright 2011 Eeli Reilin. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL EELI REILIN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation
* are those of the authors and should not be interpreted as representing
* official policies, either expressed or implied, of Eeli Reilin.
*/
/**
* \file json.h
*/
#ifndef JSON_H
#define JSON_H
#include <QVariant>
#include <QString>
namespace QtJson
{
/**
* \enum JsonToken
*/
enum JsonToken
{
JsonTokenNone = 0,
JsonTokenCurlyOpen = 1,
JsonTokenCurlyClose = 2,
JsonTokenSquaredOpen = 3,
JsonTokenSquaredClose = 4,
JsonTokenColon = 5,
JsonTokenComma = 6,
JsonTokenString = 7,
JsonTokenNumber = 8,
JsonTokenTrue = 9,
JsonTokenFalse = 10,
JsonTokenNull = 11
};
/**
* \class Json
* \brief A JSON data parser
*
* Json parses a JSON data into a QVariant hierarchy.
*/
class Json
{
public:
/**
* Parse a JSON string
*
* \param json The JSON data
*/
static QVariant parse(const QString &json);
/**
* Parse a JSON string
*
* \param json The JSON data
* \param success The success of the parsing
*/
static QVariant parse(const QString &json, bool &success);
/**
* This method generates a textual JSON representation
*
* \param data The JSON data generated by the parser.
* \param success The success of the serialization
*/
static QByteArray serialize(const QVariant &data);
/**
* This method generates a textual JSON representation
*
* \param data The JSON data generated by the parser.
* \param success The success of the serialization
*
* \return QByteArray Textual JSON representation
*/
static QByteArray serialize(const QVariant &data, bool &success);
private:
/**
* Parses a value starting from index
*
* \param json The JSON data
* \param index The start index
* \param success The success of the parse process
*
* \return QVariant The parsed value
*/
static QVariant parseValue(const QString &json, int &index,
bool &success);
/**
* Parses an object starting from index
*
* \param json The JSON data
* \param index The start index
* \param success The success of the object parse
*
* \return QVariant The parsed object map
*/
static QVariant parseObject(const QString &json, int &index,
bool &success);
/**
* Parses an array starting from index
*
* \param json The JSON data
* \param index The starting index
* \param success The success of the array parse
*
* \return QVariant The parsed variant array
*/
static QVariant parseArray(const QString &json, int &index,
bool &success);
/**
* Parses a string starting from index
*
* \param json The JSON data
* \param index The starting index
* \param success The success of the string parse
*
* \return QVariant The parsed string
*/
static QVariant parseString(const QString &json, int &index,
bool &success);
/**
* Parses a number starting from index
*
* \param json The JSON data
* \param index The starting index
*
* \return QVariant The parsed number
*/
static QVariant parseNumber(const QString &json, int &index);
/**
* Get the last index of a number starting from index
*
* \param json The JSON data
* \param index The starting index
*
* \return The last index of the number
*/
static int lastIndexOfNumber(const QString &json, int index);
/**
* Skip unwanted whitespace symbols starting from index
*
* \param json The JSON data
* \param index The start index
*/
static void eatWhitespace(const QString &json, int &index);
/**
* Check what token lies ahead
*
* \param json The JSON data
* \param index The starting index
*
* \return int The upcoming token
*/
static int lookAhead(const QString &json, int index);
/**
* Get the next JSON token
*
* \param json The JSON data
* \param index The starting index
*
* \return int The next JSON token
*/
static int nextToken(const QString &json, int &index);
};
} //end namespace
#endif //JSON_H

View file

@ -1,5 +1,4 @@
#include "releasechannel.h"
#include "qt-json/json.h"
#include "version_string.h"
#include <QJsonArray>
@ -93,21 +92,20 @@ QString StableReleaseChannel::getReleaseChannelUrl() const
void StableReleaseChannel::releaseListFinished()
{
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
bool ok;
QString tmp = QString(reply->readAll());
auto *reply = static_cast<QNetworkReply *>(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<QNetworkReply *>(sender());
bool ok;
QString tmp = QString(reply->readAll());
auto *reply = static_cast<QNetworkReply *>(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<QNetworkReply *>(sender());
auto *reply = static_cast<QNetworkReply *>(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<QNetworkReply *>(sender());
QByteArray jsonData = reply->readAll();
auto *reply = static_cast<QNetworkReply *>(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;

View file

@ -5,6 +5,7 @@
#include <QObject>
#include <QString>
#include <QVariantMap>
#include <utility>
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

View file

@ -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");
}