Fix deck loader with spaces (#3007)

This commit is contained in:
Zach H 2018-01-18 19:23:13 -05:00 committed by GitHub
parent dcc632e0d4
commit 34bec90193
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 561 additions and 330 deletions

View file

@ -31,23 +31,34 @@ DeckListModel::~DeckListModel()
void DeckListModel::rebuildTree() void DeckListModel::rebuildTree()
{ {
beginResetModel(); beginResetModel();
root->clearTree(); root->clearTree();
InnerDecklistNode *listRoot = deckList->getRoot(); InnerDecklistNode *listRoot = deckList->getRoot();
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i)); for (int i = 0; i < listRoot->size(); i++)
InnerDecklistNode *node = new InnerDecklistNode(currentZone->getName(), root); {
for (int j = 0; j < currentZone->size(); j++) { auto *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j)); auto *node = new InnerDecklistNode(currentZone->getName(), root);
// XXX better sanity checking
if (!currentCard) for (int j = 0; j < currentZone->size(); j++)
{
auto *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
// TODO: better sanity checking
if (currentCard == nullptr)
{
continue; continue;
}
CardInfo *info = db->getCard(currentCard->getName()); CardInfo *info = db->getCard(currentCard->getName());
QString cardType = info ? info->getMainCardType() : "unknown"; QString cardType = info ? info->getMainCardType() : "unknown";
InnerDecklistNode *cardTypeNode = dynamic_cast<InnerDecklistNode *>(node->findChild(cardType));
auto *cardTypeNode = dynamic_cast<InnerDecklistNode *>(node->findChild(cardType));
if (!cardTypeNode) if (!cardTypeNode)
{
cardTypeNode = new InnerDecklistNode(cardType, node); cardTypeNode = new InnerDecklistNode(cardType, node);
}
new DecklistModelCardNode(currentCard, cardTypeNode); new DecklistModelCardNode(currentCard, cardTypeNode);
} }
@ -58,12 +69,16 @@ void DeckListModel::rebuildTree()
int DeckListModel::rowCount(const QModelIndex &parent) const int DeckListModel::rowCount(const QModelIndex &parent) const
{ {
// debugIndexInfo("rowCount", parent); //debugIndexInfo("rowCount", parent);
InnerDecklistNode *node = getNode<InnerDecklistNode *>(parent); auto *node = getNode<InnerDecklistNode *>(parent);
if (node) if (node)
{
return node->size(); return node->size();
}
else else
{
return 0; return 0;
}
} }
int DeckListModel::columnCount(const QModelIndex &/*parent*/) const int DeckListModel::columnCount(const QModelIndex &/*parent*/) const
@ -73,56 +88,80 @@ int DeckListModel::columnCount(const QModelIndex &/*parent*/) const
QVariant DeckListModel::data(const QModelIndex &index, int role) const QVariant DeckListModel::data(const QModelIndex &index, int role) const
{ {
// debugIndexInfo("data", index); //debugIndexInfo("data", index);
if (!index.isValid()) if (!index.isValid())
{
return QVariant(); return QVariant();
if (index.column() >= columnCount()) }
return QVariant();
AbstractDecklistNode *temp = static_cast<AbstractDecklistNode *>(index.internalPointer()); if (index.column() >= columnCount())
DecklistModelCardNode *card = dynamic_cast<DecklistModelCardNode *>(temp); {
if (!card) { return QVariant();
InnerDecklistNode *node = dynamic_cast<InnerDecklistNode *>(temp); }
switch (role) {
case Qt::FontRole: { auto *temp = static_cast<AbstractDecklistNode *>(index.internalPointer());
auto *card = dynamic_cast<DecklistModelCardNode *>(temp);
if (card == nullptr)
{
auto *node = dynamic_cast<InnerDecklistNode *>(temp);
switch (role)
{
case Qt::FontRole:
{
QFont f; QFont f;
f.setBold(true); f.setBold(true);
return f; return f;
} }
case Qt::DisplayRole: case Qt::DisplayRole:
case Qt::EditRole: case Qt::EditRole:
switch (index.column()) { {
case 0: return node->recursiveCount(true); switch (index.column())
case 1: return node->getVisibleName(); {
default: return QVariant(); case 0:
return node->recursiveCount(true);
case 1:
return node->getVisibleName();
default:
return QVariant();
} }
case Qt::BackgroundRole: { }
case Qt::BackgroundRole:
{
int color = 90 + 60 * node->depth(); int color = 90 + 60 * node->depth();
return QBrush(QColor(color, 255, color)); return QBrush(QColor(color, 255, color));
} }
case Qt::ForegroundRole: { case Qt::ForegroundRole:
{
return QBrush(QColor(0 ,0 ,0)); return QBrush(QColor(0 ,0 ,0));
} }
default: return QVariant(); default: return QVariant();
} }
} else { }
switch (role) { else
{
switch (role)
{
case Qt::DisplayRole: case Qt::DisplayRole:
case Qt::EditRole: { case Qt::EditRole:
switch (index.column()) { {
switch (index.column())
{
case 0: return card->getNumber(); case 0: return card->getNumber();
case 1: return card->getName(); case 1: return card->getName();
default: return QVariant(); default: return QVariant();
} }
} }
case Qt::BackgroundRole: { case Qt::BackgroundRole:
{
int color = 255 - (index.row() % 2) * 30; int color = 255 - (index.row() % 2) * 30;
return QBrush(QColor(color, color, color)); return QBrush(QColor(color, color, color));
} }
case Qt::ForegroundRole: { case Qt::ForegroundRole:
{
return QBrush(QColor(0 ,0 ,0)); return QBrush(QColor(0 ,0 ,0));
} }
default: return QVariant(); default:
return QVariant();
} }
} }
} }
@ -130,10 +169,17 @@ QVariant DeckListModel::data(const QModelIndex &index, int role) const
QVariant DeckListModel::headerData(int section, Qt::Orientation orientation, int role) const QVariant DeckListModel::headerData(int section, Qt::Orientation orientation, int role) const
{ {
if ((role != Qt::DisplayRole) || (orientation != Qt::Horizontal)) if ((role != Qt::DisplayRole) || (orientation != Qt::Horizontal))
{
return QVariant(); return QVariant();
}
if (section >= columnCount()) if (section >= columnCount())
{
return QVariant(); return QVariant();
switch (section) { }
switch (section)
{
case 0: return tr("Number"); case 0: return tr("Number");
case 1: return tr("Card"); case 1: return tr("Card");
default: return QVariant(); default: return QVariant();
@ -142,21 +188,23 @@ QVariant DeckListModel::headerData(int section, Qt::Orientation orientation, int
QModelIndex DeckListModel::index(int row, int column, const QModelIndex &parent) const QModelIndex DeckListModel::index(int row, int column, const QModelIndex &parent) const
{ {
// debugIndexInfo("index", parent); //debugIndexInfo("index", parent);
if (!hasIndex(row, column, parent)) if (!hasIndex(row, column, parent))
return QModelIndex(); {
return {};
}
InnerDecklistNode *parentNode = getNode<InnerDecklistNode *>(parent); auto *parentNode = getNode<InnerDecklistNode *>(parent);
if (row >= parentNode->size()) return row >= parentNode->size() ? QModelIndex() : createIndex(row, column, parentNode->at(row));
return QModelIndex();
return createIndex(row, column, parentNode->at(row));
} }
QModelIndex DeckListModel::parent(const QModelIndex &ind) const QModelIndex DeckListModel::parent(const QModelIndex &ind) const
{ {
if (!ind.isValid()) if (!ind.isValid())
return QModelIndex(); {
return {};
}
return nodeToIndex(static_cast<AbstractDecklistNode *>(ind.internalPointer())->getParent()); return nodeToIndex(static_cast<AbstractDecklistNode *>(ind.internalPointer())->getParent());
} }
@ -164,7 +212,9 @@ QModelIndex DeckListModel::parent(const QModelIndex &ind) const
Qt::ItemFlags DeckListModel::flags(const QModelIndex &index) const Qt::ItemFlags DeckListModel::flags(const QModelIndex &index) const
{ {
if (!index.isValid()) if (!index.isValid())
return 0; {
return nullptr;
}
Qt::ItemFlags result = Qt::ItemIsEnabled; Qt::ItemFlags result = Qt::ItemIsEnabled;
result |= Qt::ItemIsSelectable; result |= Qt::ItemIsSelectable;
@ -175,22 +225,29 @@ Qt::ItemFlags DeckListModel::flags(const QModelIndex &index) const
void DeckListModel::emitRecursiveUpdates(const QModelIndex &index) void DeckListModel::emitRecursiveUpdates(const QModelIndex &index)
{ {
if (!index.isValid()) if (!index.isValid())
{
return; return;
}
emit dataChanged(index, index); emit dataChanged(index, index);
emitRecursiveUpdates(index.parent()); emitRecursiveUpdates(index.parent());
} }
bool DeckListModel::setData(const QModelIndex &index, const QVariant &value, int role) bool DeckListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{ {
DecklistModelCardNode *node = getNode<DecklistModelCardNode *>(index); auto *node = getNode<DecklistModelCardNode *>(index);
if (!node || (role != Qt::EditRole)) if (!node || (role != Qt::EditRole))
{
return false; return false;
}
switch (index.column()) { switch (index.column())
{
case 0: node->setNumber(value.toInt()); break; case 0: node->setNumber(value.toInt()); break;
case 1: node->setName(value.toString()); break; case 1: node->setName(value.toString()); break;
default: return false; default: return false;
} }
emitRecursiveUpdates(index); emitRecursiveUpdates(index);
deckList->updateDeckHash(); deckList->updateDeckHash();
return true; return true;
@ -198,33 +255,46 @@ bool DeckListModel::setData(const QModelIndex &index, const QVariant &value, int
bool DeckListModel::removeRows(int row, int count, const QModelIndex &parent) bool DeckListModel::removeRows(int row, int count, const QModelIndex &parent)
{ {
InnerDecklistNode *node = getNode<InnerDecklistNode *>(parent); auto *node = getNode<InnerDecklistNode *>(parent);
if (!node) if (!node)
{
return false; return false;
}
if (row + count > node->size()) if (row + count > node->size())
{
return false; return false;
}
beginRemoveRows(parent, row, row + count - 1); beginRemoveRows(parent, row, row + count - 1);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++)
{
AbstractDecklistNode *toDelete = node->takeAt(row); AbstractDecklistNode *toDelete = node->takeAt(row);
if (DecklistModelCardNode *temp = dynamic_cast<DecklistModelCardNode *>(toDelete)) if (auto *temp = dynamic_cast<DecklistModelCardNode *>(toDelete))
{
deckList->deleteNode(temp->getDataNode()); deckList->deleteNode(temp->getDataNode());
}
delete toDelete; delete toDelete;
} }
endRemoveRows(); endRemoveRows();
if (!node->size() && (node != root)) if (node->empty() && (node != root))
{
removeRows(parent.row(), 1, parent.parent()); removeRows(parent.row(), 1, parent.parent());
}
else else
{
emitRecursiveUpdates(parent); emitRecursiveUpdates(parent);
}
return true; return true;
} }
InnerDecklistNode *DeckListModel::createNodeIfNeeded(const QString &name, InnerDecklistNode *parent) InnerDecklistNode *DeckListModel::createNodeIfNeeded(const QString &name, InnerDecklistNode *parent)
{ {
InnerDecklistNode *newNode = dynamic_cast<InnerDecklistNode *>(parent->findChild(name)); auto *newNode = dynamic_cast<InnerDecklistNode *>(parent->findChild(name));
if (!newNode) { if (!newNode)
{
beginInsertRows(nodeToIndex(parent), parent->size(), parent->size()); beginInsertRows(nodeToIndex(parent), parent->size(), parent->size());
newNode = new InnerDecklistNode(name, parent); newNode = new InnerDecklistNode(name, parent);
endInsertRows(); endInsertRows();
@ -239,17 +309,23 @@ DecklistModelCardNode *DeckListModel::findCardNode(const QString &cardName, cons
QString cardType; QString cardType;
zoneNode = dynamic_cast<InnerDecklistNode *>(root->findChild(zoneName)); zoneNode = dynamic_cast<InnerDecklistNode *>(root->findChild(zoneName));
if(!zoneNode) if (!zoneNode)
return NULL; {
return nullptr;
}
info = db->getCard(cardName); info = db->getCard(cardName);
if(!info) if (!info)
return NULL; {
return nullptr;
}
cardType = info->getMainCardType(); cardType = info->getMainCardType();
typeNode = dynamic_cast<InnerDecklistNode *>(zoneNode->findChild(cardType)); typeNode = dynamic_cast<InnerDecklistNode *>(zoneNode->findChild(cardType));
if(!typeNode) if (!typeNode)
return NULL; {
return nullptr;
}
return dynamic_cast<DecklistModelCardNode *>(typeNode->findChild(cardName)); return dynamic_cast<DecklistModelCardNode *>(typeNode->findChild(cardName));
} }
@ -259,8 +335,11 @@ QModelIndex DeckListModel::findCard(const QString &cardName, const QString &zone
DecklistModelCardNode *cardNode; DecklistModelCardNode *cardNode;
cardNode = findCardNode(cardName, zoneName); cardNode = findCardNode(cardName, zoneName);
if(!cardNode) if (!cardNode)
return QModelIndex(); {
return {};
}
return nodeToIndex(cardNode); return nodeToIndex(cardNode);
} }
@ -299,7 +378,7 @@ QModelIndex DeckListModel::addCard(const QString &cardName, const QString &zoneN
} }
else else
{ {
return QModelIndex(); return {};
} }
} }
@ -309,13 +388,16 @@ QModelIndex DeckListModel::addCard(const QString &cardName, const QString &zoneN
InnerDecklistNode *cardTypeNode = createNodeIfNeeded(cardType, zoneNode); InnerDecklistNode *cardTypeNode = createNodeIfNeeded(cardType, zoneNode);
QModelIndex parentIndex = nodeToIndex(cardTypeNode); QModelIndex parentIndex = nodeToIndex(cardTypeNode);
DecklistModelCardNode *cardNode = dynamic_cast<DecklistModelCardNode *>(cardTypeNode->findChild(cardName)); auto *cardNode = dynamic_cast<DecklistModelCardNode *>(cardTypeNode->findChild(cardName));
if (!cardNode) { if (!cardNode)
{
DecklistCardNode *decklistCard = deckList->addCard(cardName, zoneName); DecklistCardNode *decklistCard = deckList->addCard(cardName, zoneName);
beginInsertRows(parentIndex, cardTypeNode->size(), cardTypeNode->size()); beginInsertRows(parentIndex, cardTypeNode->size(), cardTypeNode->size());
cardNode = new DecklistModelCardNode(decklistCard, cardTypeNode); cardNode = new DecklistModelCardNode(decklistCard, cardTypeNode);
endInsertRows(); endInsertRows();
} else { }
else
{
cardNode->setNumber(cardNode->getNumber() + 1); cardNode->setNumber(cardNode->getNumber() + 1);
deckList->updateDeckHash(); deckList->updateDeckHash();
} }
@ -327,7 +409,9 @@ QModelIndex DeckListModel::addCard(const QString &cardName, const QString &zoneN
QModelIndex DeckListModel::nodeToIndex(AbstractDecklistNode *node) const QModelIndex DeckListModel::nodeToIndex(AbstractDecklistNode *node) const
{ {
if (node == nullptr || node == root) if (node == nullptr || node == root)
return QModelIndex(); {
return {};
}
return createIndex(node->getParent()->indexOf(node), 0, node); return createIndex(node->getParent()->indexOf(node), 0, node);
} }
@ -340,11 +424,13 @@ void DeckListModel::sortHelper(InnerDecklistNode *node, Qt::SortOrder order)
QModelIndexList from, to; QModelIndexList from, to;
int columns = columnCount(); int columns = columnCount();
for (int i = sortResult.size() - 1; i >= 0; --i) { for (int i = sortResult.size() - 1; i >= 0; --i)
{
const int fromRow = sortResult[i].first; const int fromRow = sortResult[i].first;
const int toRow = sortResult[i].second; const int toRow = sortResult[i].second;
AbstractDecklistNode *temp = node->at(toRow); AbstractDecklistNode *temp = node->at(toRow);
for (int j = 0; j < columns; ++j) { for (int j = 0; j < columns; ++j)
{
from << createIndex(fromRow, j, temp); from << createIndex(fromRow, j, temp);
to << createIndex(toRow, j, temp); to << createIndex(toRow, j, temp);
} }
@ -352,11 +438,14 @@ void DeckListModel::sortHelper(InnerDecklistNode *node, Qt::SortOrder order)
changePersistentIndexList(from, to); changePersistentIndexList(from, to);
// Recursion // Recursion
for (int i = node->size() - 1; i >= 0; --i) { for (int i = node->size() - 1; i >= 0; --i)
InnerDecklistNode *subNode = dynamic_cast<InnerDecklistNode *>(node->at(i)); {
auto *subNode = dynamic_cast<InnerDecklistNode *>(node->at(i));
if (subNode) if (subNode)
{
sortHelper(subNode, order); sortHelper(subNode, order);
} }
}
} }
void DeckListModel::sort(int column, Qt::SortOrder order) void DeckListModel::sort(int column, Qt::SortOrder order)
@ -366,7 +455,8 @@ void DeckListModel::sort(int column, Qt::SortOrder order)
emit layoutAboutToBeChanged(); emit layoutAboutToBeChanged();
DeckSortMethod sortMethod; DeckSortMethod sortMethod;
switch(column) { switch(column)
{
case 0: case 0:
sortMethod = ByNumber; sortMethod = ByNumber;
break; break;
@ -376,6 +466,7 @@ void DeckListModel::sort(int column, Qt::SortOrder order)
default: default:
sortMethod = ByName; sortMethod = ByName;
} }
root->setSortMethod(sortMethod); root->setSortMethod(sortMethod);
sortHelper(root, order); sortHelper(root, order);
emit layoutChanged(); emit layoutChanged();
@ -399,7 +490,8 @@ void DeckListModel::printDeckListNode(QTextCursor *cursor, InnerDecklistNode *no
{ {
const int totalColumns = 2; const int totalColumns = 2;
if (node->height() == 1) { if (node->height() == 1)
{
QTextBlockFormat blockFormat; QTextBlockFormat blockFormat;
QTextCharFormat charFormat; QTextCharFormat charFormat;
charFormat.setFontPointSize(11); charFormat.setFontPointSize(11);
@ -411,8 +503,9 @@ void DeckListModel::printDeckListNode(QTextCursor *cursor, InnerDecklistNode *no
tableFormat.setCellSpacing(0); tableFormat.setCellSpacing(0);
tableFormat.setBorder(0); tableFormat.setBorder(0);
QTextTable *table = cursor->insertTable(node->size() + 1, totalColumns, tableFormat); QTextTable *table = cursor->insertTable(node->size() + 1, totalColumns, tableFormat);
for (int i = 0; i < node->size(); i++) { for (int i = 0; i < node->size(); i++)
AbstractDecklistCardNode *card = dynamic_cast<AbstractDecklistCardNode *>(node->at(i)); {
auto *card = dynamic_cast<AbstractDecklistCardNode *>(node->at(i));
QTextCharFormat cellCharFormat; QTextCharFormat cellCharFormat;
cellCharFormat.setFontPointSize(9); cellCharFormat.setFontPointSize(9);
@ -428,7 +521,9 @@ void DeckListModel::printDeckListNode(QTextCursor *cursor, InnerDecklistNode *no
cellCursor.insertText(card->getName()); cellCursor.insertText(card->getName());
} }
} else if (node->height() == 2) { }
else if (node->height() == 2)
{
QTextBlockFormat blockFormat; QTextBlockFormat blockFormat;
QTextCharFormat charFormat; QTextCharFormat charFormat;
charFormat.setFontPointSize(14); charFormat.setFontPointSize(14);
@ -442,15 +537,19 @@ void DeckListModel::printDeckListNode(QTextCursor *cursor, InnerDecklistNode *no
tableFormat.setBorder(0); tableFormat.setBorder(0);
QVector<QTextLength> constraints; QVector<QTextLength> constraints;
for (int i = 0; i < totalColumns; i++) for (int i = 0; i < totalColumns; i++)
{
constraints << QTextLength(QTextLength::PercentageLength, 100.0 / totalColumns); constraints << QTextLength(QTextLength::PercentageLength, 100.0 / totalColumns);
}
tableFormat.setColumnWidthConstraints(constraints); tableFormat.setColumnWidthConstraints(constraints);
QTextTable *table = cursor->insertTable(1, totalColumns, tableFormat); QTextTable *table = cursor->insertTable(1, totalColumns, tableFormat);
for (int i = 0; i < node->size(); i++) { for (int i = 0; i < node->size(); i++)
{
QTextCursor cellCursor = table->cellAt(0, (i * totalColumns) / node->size()).lastCursorPosition(); QTextCursor cellCursor = table->cellAt(0, (i * totalColumns) / node->size()).lastCursorPosition();
printDeckListNode(&cellCursor, dynamic_cast<InnerDecklistNode *>(node->at(i))); printDeckListNode(&cellCursor, dynamic_cast<InnerDecklistNode *>(node->at(i)));
} }
} }
cursor->movePosition(QTextCursor::End); cursor->movePosition(QTextCursor::End);
} }
@ -477,7 +576,8 @@ void DeckListModel::printDeckList(QPrinter *printer)
cursor.insertText(deckList->getComments()); cursor.insertText(deckList->getComments());
cursor.insertBlock(headerBlockFormat, headerCharFormat); cursor.insertBlock(headerBlockFormat, headerCharFormat);
for (int i = 0; i < root->size(); i++) { for (int i = 0; i < root->size(); i++)
{
cursor.insertHtml("<br><img src=theme:hr.jpg>"); cursor.insertHtml("<br><img src=theme:hr.jpg>");
//cursor.insertHtml("<hr>"); //cursor.insertHtml("<hr>");
cursor.insertBlock(headerBlockFormat, headerCharFormat); cursor.insertBlock(headerBlockFormat, headerCharFormat);

View file

@ -34,18 +34,18 @@ signals:
public: public:
DeckListModel(QObject *parent = 0); DeckListModel(QObject *parent = 0);
~DeckListModel(); ~DeckListModel();
int rowCount(const QModelIndex &parent = QModelIndex()) const; int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const; int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const; QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; QVariant headerData(int section, Qt::Orientation orientation, int role) const;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; QModelIndex index(int row, int column, const QModelIndex &parent) const;
QModelIndex parent(const QModelIndex &index) const; QModelIndex parent(const QModelIndex &index) const;
Qt::ItemFlags flags(const QModelIndex &index) const; Qt::ItemFlags flags(const QModelIndex &index) const;
bool setData(const QModelIndex &index, const QVariant &value, int role); bool setData(const QModelIndex &index, const QVariant &value, int role);
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); bool removeRows(int row, int count, const QModelIndex &parent);
QModelIndex findCard(const QString &cardName, const QString &zoneName) const; QModelIndex findCard(const QString &cardName, const QString &zoneName) const;
QModelIndex addCard(const QString &cardName, const QString &zoneName, bool abAddAnyway = false); QModelIndex addCard(const QString &cardName, const QString &zoneName, bool abAddAnyway = false);
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); void sort(int column, Qt::SortOrder order);
void cleanList(); void cleanList();
DeckLoader *getDeckList() const { return deckList; } DeckLoader *getDeckList() const { return deckList; }
void setDeckList(DeckLoader *_deck); void setDeckList(DeckLoader *_deck);

View file

@ -2,8 +2,6 @@
#include <QPlainTextEdit> #include <QPlainTextEdit>
#include <QPushButton> #include <QPushButton>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QHBoxLayout>
#include <QKeySequence>
#include <QApplication> #include <QApplication>
#include <QTextStream> #include <QTextStream>
#include <QDialogButtonBox> #include <QDialogButtonBox>
@ -12,8 +10,7 @@
#include "deck_loader.h" #include "deck_loader.h"
#include "settingscache.h" #include "settingscache.h"
DlgLoadDeckFromClipboard::DlgLoadDeckFromClipboard(QWidget *parent) DlgLoadDeckFromClipboard::DlgLoadDeckFromClipboard(QWidget *parent) : QDialog(parent), deckList(nullptr)
: QDialog(parent), deckList(0)
{ {
contentsEdit = new QPlainTextEdit; contentsEdit = new QPlainTextEdit;
@ -25,7 +22,7 @@ DlgLoadDeckFromClipboard::DlgLoadDeckFromClipboard(QWidget *parent)
connect(buttonBox, SIGNAL(accepted()), this, SLOT(actOK())); connect(buttonBox, SIGNAL(accepted()), this, SLOT(actOK()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
QVBoxLayout *mainLayout = new QVBoxLayout; auto *mainLayout = new QVBoxLayout;
mainLayout->addWidget(contentsEdit); mainLayout->addWidget(contentsEdit);
mainLayout->addWidget(buttonBox); mainLayout->addWidget(buttonBox);
@ -54,25 +51,28 @@ void DlgLoadDeckFromClipboard::actOK()
QString buffer = contentsEdit->toPlainText(); QString buffer = contentsEdit->toPlainText();
QTextStream stream(&buffer); QTextStream stream(&buffer);
DeckLoader *l = new DeckLoader; auto *deckLoader = new DeckLoader;
if (buffer.contains("<cockatrice_deck version=\"1\">")) if (buffer.contains("<cockatrice_deck version=\"1\">"))
{ {
if (l->loadFromString_Native(buffer)) if (deckLoader->loadFromString_Native(buffer))
{ {
deckList = l; deckList = deckLoader;
accept(); accept();
} }
else else
{ {
QMessageBox::critical(this, tr("Error"), tr("Invalid deck list.")); QMessageBox::critical(this, tr("Error"), tr("Invalid deck list."));
delete l; delete deckLoader;
} }
} }
else if (l->loadFromStream_Plain(stream)) { else if (deckLoader->loadFromStream_Plain(stream))
deckList = l; {
deckList = deckLoader;
accept(); accept();
} else { }
else
{
QMessageBox::critical(this, tr("Error"), tr("Invalid deck list.")); QMessageBox::critical(this, tr("Error"), tr("Invalid deck list."));
delete l; delete deckLoader;
} }
} }

View file

@ -7,20 +7,22 @@ class DeckLoader;
class QPlainTextEdit; class QPlainTextEdit;
class QPushButton; class QPushButton;
class DlgLoadDeckFromClipboard : public QDialog { class DlgLoadDeckFromClipboard : public QDialog
{
Q_OBJECT Q_OBJECT
private slots: private slots:
void actOK(); void actOK();
void actRefresh(); void actRefresh();
void refreshShortcuts(); void refreshShortcuts();
private:
private:
DeckLoader *deckList; DeckLoader *deckList;
public:
DlgLoadDeckFromClipboard(QWidget *parent = 0);
DeckLoader *getDeckList() const { return deckList; }
private:
QPlainTextEdit *contentsEdit; QPlainTextEdit *contentsEdit;
QPushButton *refreshButton; QPushButton *refreshButton;
public:
explicit DlgLoadDeckFromClipboard(QWidget *parent = nullptr);
DeckLoader *getDeckList() const { return deckList; }
}; };
#endif #endif

View file

@ -1,6 +1,5 @@
#include <QFile> #include <QFile>
#include <QTextStream> #include <QTextStream>
#include <QVariant>
#include <QCryptographicHash> #include <QCryptographicHash>
#include <QDebug> #include <QDebug>
#include "decklist.h" #include "decklist.h"
@ -51,41 +50,51 @@ void SideboardPlan::write(QXmlStreamWriter *xml)
{ {
xml->writeStartElement("sideboard_plan"); xml->writeStartElement("sideboard_plan");
xml->writeTextElement("name", name); xml->writeTextElement("name", name);
for (int i = 0; i < moveList.size(); ++i) { for (auto &i : moveList)
{
xml->writeStartElement("move_card_to_zone"); xml->writeStartElement("move_card_to_zone");
xml->writeTextElement("card_name", QString::fromStdString(moveList[i].card_name())); xml->writeTextElement("card_name", QString::fromStdString(i.card_name()));
xml->writeTextElement("start_zone", QString::fromStdString(moveList[i].start_zone())); xml->writeTextElement("start_zone", QString::fromStdString(i.start_zone()));
xml->writeTextElement("target_zone", QString::fromStdString(moveList[i].target_zone())); xml->writeTextElement("target_zone", QString::fromStdString(i.target_zone()));
xml->writeEndElement(); xml->writeEndElement();
} }
xml->writeEndElement(); xml->writeEndElement();
} }
AbstractDecklistNode::AbstractDecklistNode(InnerDecklistNode *_parent) AbstractDecklistNode::AbstractDecklistNode(InnerDecklistNode *_parent) : parent(_parent), sortMethod(Default)
: parent(_parent)
{ {
if (parent) if (parent)
{
parent->append(this); parent->append(this);
}
} }
int AbstractDecklistNode::depth() const int AbstractDecklistNode::depth() const
{ {
if (parent) if (parent)
{
return parent->depth() + 1; return parent->depth() + 1;
}
else else
{
return 0; return 0;
}
} }
InnerDecklistNode::InnerDecklistNode(InnerDecklistNode *other, InnerDecklistNode *_parent) InnerDecklistNode::InnerDecklistNode(InnerDecklistNode *other, InnerDecklistNode *_parent) : AbstractDecklistNode(_parent), name(other->getName())
: AbstractDecklistNode(_parent), name(other->getName())
{ {
for (int i = 0; i < other->size(); ++i) { for (int i = 0; i < other->size(); ++i)
InnerDecklistNode *inner = dynamic_cast<InnerDecklistNode *>(other->at(i)); {
auto *inner = dynamic_cast<InnerDecklistNode *>(other->at(i));
if (inner) if (inner)
{
new InnerDecklistNode(inner, this); new InnerDecklistNode(inner, this);
}
else else
{
new DecklistCardNode(dynamic_cast<DecklistCardNode *>(other->at(i)), this); new DecklistCardNode(dynamic_cast<DecklistCardNode *>(other->at(i)), this);
} }
}
} }
InnerDecklistNode::~InnerDecklistNode() InnerDecklistNode::~InnerDecklistNode()
@ -96,20 +105,30 @@ InnerDecklistNode::~InnerDecklistNode()
QString InnerDecklistNode::visibleNameFromName(const QString &_name) QString InnerDecklistNode::visibleNameFromName(const QString &_name)
{ {
if (_name == DECK_ZONE_MAIN) if (_name == DECK_ZONE_MAIN)
{
return QObject::tr("Maindeck"); return QObject::tr("Maindeck");
}
else if (_name == DECK_ZONE_SIDE) else if (_name == DECK_ZONE_SIDE)
{
return QObject::tr("Sideboard"); return QObject::tr("Sideboard");
}
else if (_name == DECK_ZONE_TOKENS) else if (_name == DECK_ZONE_TOKENS)
{
return QObject::tr("Tokens"); return QObject::tr("Tokens");
}
else else
{
return _name; return _name;
}
} }
void InnerDecklistNode::setSortMethod(DeckSortMethod method) void InnerDecklistNode::setSortMethod(DeckSortMethod method)
{ {
sortMethod = method; sortMethod = method;
for (int i = 0; i < size(); i++) for (int i = 0; i < size(); i++)
{
at(i)->setSortMethod(method); at(i)->setSortMethod(method);
}
} }
QString InnerDecklistNode::getVisibleName() const QString InnerDecklistNode::getVisibleName() const
@ -124,17 +143,21 @@ void InnerDecklistNode::clearTree()
clear(); clear();
} }
DecklistCardNode::DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent) DecklistCardNode::DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent) : AbstractDecklistCardNode(_parent), name(other->getName()), number(other->getNumber())
: AbstractDecklistCardNode(_parent), name(other->getName()), number(other->getNumber())
{ {
} }
AbstractDecklistNode *InnerDecklistNode::findChild(const QString &name) AbstractDecklistNode *InnerDecklistNode::findChild(const QString &name)
{ {
for (int i = 0; i < size(); i++) for (int i = 0; i < size(); i++)
{
if (at(i)->getName() == name) if (at(i)->getName() == name)
{
return at(i); return at(i);
return 0; }
}
return nullptr;
} }
int InnerDecklistNode::height() const int InnerDecklistNode::height() const
@ -145,32 +168,42 @@ int InnerDecklistNode::height() const
int InnerDecklistNode::recursiveCount(bool countTotalCards) const int InnerDecklistNode::recursiveCount(bool countTotalCards) const
{ {
int result = 0; int result = 0;
for (int i = 0; i < size(); i++) { for (int i = 0; i < size(); i++)
InnerDecklistNode *node = dynamic_cast<InnerDecklistNode *>(at(i)); {
auto *node = dynamic_cast<InnerDecklistNode *>(at(i));
if (node) if (node)
{
result += node->recursiveCount(countTotalCards); result += node->recursiveCount(countTotalCards);
}
else if (countTotalCards) else if (countTotalCards)
{
result += dynamic_cast<AbstractDecklistCardNode *>(at(i))->getNumber(); result += dynamic_cast<AbstractDecklistCardNode *>(at(i))->getNumber();
}
else else
result += 1; {
result++;
}
} }
return result; return result;
} }
bool InnerDecklistNode::compare(AbstractDecklistNode *other) const bool InnerDecklistNode::compare(AbstractDecklistNode *other) const
{ {
switch (sortMethod) { switch (sortMethod)
{
case ByNumber: case ByNumber:
return compareNumber(other); return compareNumber(other);
case ByName: case ByName:
return compareName(other); return compareName(other);
default:
return false;
} }
return 0;
} }
bool InnerDecklistNode::compareNumber(AbstractDecklistNode *other) const bool InnerDecklistNode::compareNumber(AbstractDecklistNode *other) const
{ {
InnerDecklistNode *other2 = dynamic_cast<InnerDecklistNode *>(other); auto *other2 = dynamic_cast<InnerDecklistNode *>(other);
if (other2) { if (other2) {
int n1 = recursiveCount(true); int n1 = recursiveCount(true);
int n2 = other2->recursiveCount(true); int n2 = other2->recursiveCount(true);
@ -182,43 +215,54 @@ bool InnerDecklistNode::compareNumber(AbstractDecklistNode *other) const
bool InnerDecklistNode::compareName(AbstractDecklistNode *other) const bool InnerDecklistNode::compareName(AbstractDecklistNode *other) const
{ {
InnerDecklistNode *other2 = dynamic_cast<InnerDecklistNode *>(other); auto *other2 = dynamic_cast<InnerDecklistNode *>(other);
if (other2) { if (other2)
{
return (getName() > other2->getName()); return (getName() > other2->getName());
} else { }
else
{
return false; return false;
} }
} }
bool AbstractDecklistCardNode::compare(AbstractDecklistNode *other) const bool AbstractDecklistCardNode::compare(AbstractDecklistNode *other) const
{ {
switch (sortMethod) { switch (sortMethod)
{
case ByNumber: case ByNumber:
return compareNumber(other); return compareNumber(other);
case ByName: case ByName:
return compareName(other); return compareName(other);
default:
return false;
} }
return 0;
} }
bool AbstractDecklistCardNode::compareNumber(AbstractDecklistNode *other) const bool AbstractDecklistCardNode::compareNumber(AbstractDecklistNode *other) const
{ {
AbstractDecklistCardNode *other2 = dynamic_cast<AbstractDecklistCardNode *>(other); auto *other2 = dynamic_cast<AbstractDecklistCardNode *>(other);
if (other2) { if (other2)
{
int n1 = getNumber(); int n1 = getNumber();
int n2 = other2->getNumber(); int n2 = other2->getNumber();
return (n1 != n2) ? (n1 > n2) : compareName(other); return (n1 != n2) ? (n1 > n2) : compareName(other);
} else { }
else
{
return true; return true;
} }
} }
bool AbstractDecklistCardNode::compareName(AbstractDecklistNode *other) const bool AbstractDecklistCardNode::compareName(AbstractDecklistNode *other) const
{ {
AbstractDecklistCardNode *other2 = dynamic_cast<AbstractDecklistCardNode *>(other); auto *other2 = dynamic_cast<AbstractDecklistCardNode *>(other);
if (other2) { if (other2)
{
return (getName() > other2->getName()); return (getName() > other2->getName());
} else { }
else
{
return true; return true;
} }
} }
@ -227,7 +271,7 @@ class InnerDecklistNode::compareFunctor {
private: private:
Qt::SortOrder order; Qt::SortOrder order;
public: public:
compareFunctor(Qt::SortOrder _order) : order(_order) { } explicit compareFunctor(Qt::SortOrder _order) : order(_order) { }
inline bool operator()(QPair<int, AbstractDecklistNode *> a, QPair<int, AbstractDecklistNode *> b) const inline bool operator()(QPair<int, AbstractDecklistNode *> a, QPair<int, AbstractDecklistNode *> b) const
{ {
return (order == Qt::AscendingOrder) ^ (a.second->compare(b.second)); return (order == Qt::AscendingOrder) ^ (a.second->compare(b.second));
@ -311,16 +355,13 @@ DeckList::DeckList()
} }
// TODO: http://qt-project.org/doc/qt-4.8/qobject.html#no-copy-constructor-or-assignment-operator // TODO: http://qt-project.org/doc/qt-4.8/qobject.html#no-copy-constructor-or-assignment-operator
DeckList::DeckList(const DeckList &other) DeckList::DeckList(const DeckList &other) : QObject(), name(other.name), comments(other.comments), deckHash(other.deckHash)
: QObject(),
name(other.name),
comments(other.comments),
deckHash(other.deckHash)
{ {
root = new InnerDecklistNode(other.getRoot()); root = new InnerDecklistNode(other.getRoot());
QMapIterator<QString, SideboardPlan *> spIterator(other.getSideboardPlans()); QMapIterator<QString, SideboardPlan *> spIterator(other.getSideboardPlans());
while (spIterator.hasNext()) { while (spIterator.hasNext())
{
spIterator.next(); spIterator.next();
sideboardPlans.insert(spIterator.key(), new SideboardPlan(spIterator.key(), spIterator.value()->getMoveList())); sideboardPlans.insert(spIterator.key(), new SideboardPlan(spIterator.key(), spIterator.value()->getMoveList()));
} }
@ -481,13 +522,18 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
* This will also concise multiple blank lines in a row to just one blank * This will also concise multiple blank lines in a row to just one blank
* Ex: ("Card1", "Card2", "", "", "", "Card3") => ("Card1", "Card2", "", "Card3") * Ex: ("Card1", "Card2", "", "", "", "Card3") => ("Card1", "Card2", "", "Card3")
*/ */
if (line.isEmpty()) { if (line.isEmpty())
{
if (priorEntryIsBlank || isAtBeginning) if (priorEntryIsBlank || isAtBeginning)
{
continue; continue;
}
priorEntryIsBlank = true; priorEntryIsBlank = true;
blankLines++; blankLines++;
} else { }
else
{
isAtBeginning = false; isAtBeginning = false;
priorEntryIsBlank = false; priorEntryIsBlank = false;
} }
@ -501,7 +547,7 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
* NOTE: Any duplicates were taken care of above, so there can be * NOTE: Any duplicates were taken care of above, so there can be
* at most one blank line at the very end * at most one blank line at the very end
*/ */
if (inputs.size() && inputs.last().isEmpty()) if (!inputs.empty() && inputs.last().isEmpty())
{ {
blankLines--; blankLines--;
inputs.erase(inputs.end() - 1); inputs.erase(inputs.end() - 1);
@ -509,20 +555,28 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
// If "Sideboard" line appears in inputs, then blank lines mean nothing // If "Sideboard" line appears in inputs, then blank lines mean nothing
if (inputs.contains("sideboard")) if (inputs.contains("sideboard"))
{
blankLines = 2; blankLines = 2;
}
bool inSideboard = false, titleFound = false, isSideboard; bool inSideboard = false, titleFound = false, isSideboard;
int okRows = 0; int okRows = 0;
foreach(QString line, inputs) {
foreach(QString line, inputs)
{
// This is a comment line, ignore it // This is a comment line, ignore it
if (line.startsWith("//")) if (line.startsWith("//"))
{ {
if (!titleFound) { // Set the title to the first comment if (!titleFound) // Set the title to the first comment
{
name = line.mid(2).trimmed(); name = line.mid(2).trimmed();
titleFound = true; titleFound = true;
} else if (okRows == 0) { // We haven't processed any cards yet }
else if (okRows == 0) // We haven't processed any cards yet
{
comments += line.mid(2).trimmed() + "\n"; comments += line.mid(2).trimmed() + "\n";
} }
continue; continue;
} }
@ -530,20 +584,24 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
// Then we assume it means to start the sideboard section of the paste. // Then we assume it means to start the sideboard section of the paste.
// If we have the word "Sideboard" appear on any line, then that will // If we have the word "Sideboard" appear on any line, then that will
// also indicate the start of the sideboard. // also indicate the start of the sideboard.
if ((line.isEmpty() && blankLines == 1) || line.startsWith("sideboard")) { if ((line.isEmpty() && blankLines == 1) || line.startsWith("sideboard"))
{
inSideboard = true; inSideboard = true;
continue; // The line isn't actually a card continue; // The line isn't actually a card
} }
isSideboard = inSideboard; isSideboard = inSideboard;
if (line.startsWith("sb:")) { if (line.startsWith("sb:"))
{
line = line.mid(3).trimmed(); line = line.mid(3).trimmed();
isSideboard = true; isSideboard = true;
} }
if (line.trimmed().isEmpty()) if (line.trimmed().isEmpty())
{
continue; // The line was " " instead of "\n" continue; // The line was " " instead of "\n"
}
// Filter out MWS edition symbols and basic land extras // Filter out MWS edition symbols and basic land extras
QRegExp rx("\\[.*\\]"); QRegExp rx("\\[.*\\]");
@ -555,21 +613,37 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
rx.setPattern("\\|.*$"); rx.setPattern("\\|.*$");
line.remove(rx); line.remove(rx);
// If the user inputs "Quicksilver Elemental" then it will cut it off
// 1x Squishy Treaker
int i = line.indexOf(' '); int i = line.indexOf(' ');
int cardNameStart = i + 1; int cardNameStart = i + 1;
if (i > 0)
{
// If the count ends with an 'x', ignore it. For example, // If the count ends with an 'x', ignore it. For example,
// "4x Storm Crow" will count 4 correctly. // "4x Storm Crow" will count 4 correctly.
if (i > 0 && line[i - 1] == 'x') if (line.at(i-1) == 'x')
{
i--; i--;
}
else if (! line.at(i-1).isDigit())
{
// If the user inputs "Quicksilver Elemental" then it will work as 1x of that card
cardNameStart = 0;
}
}
bool ok; bool ok;
int number = line.left(i).toInt(&ok); int number = line.left(i).toInt(&ok);
if (!ok) if (!ok)
{
number = 1; // If input is "cardName" assume it's "1x cardName" number = 1; // If input is "cardName" assume it's "1x cardName"
}
QString cardName = line.mid(cardNameStart); QString cardName = line.mid(cardNameStart);
// Common differences between Cockatrice's card names // Common differences between Cockatrice's card names
// and what's commonly used in decklists // and what's commonly used in decklists
rx.setPattern(""); rx.setPattern("");
@ -585,7 +659,9 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
// Qt regexes don't support lookbehind so we capture and replace instead. // Qt regexes don't support lookbehind so we capture and replace instead.
rx.setPattern("([^A-Z])\\s*&\\s*"); rx.setPattern("([^A-Z])\\s*&\\s*");
if (rx.indexIn(cardName) != -1) if (rx.indexIn(cardName) != -1)
{
cardName.replace(rx, QString("%1 // ").arg(rx.cap(1))); cardName.replace(rx, QString("%1 // ").arg(rx.cap(1)));
}
// We need to get the name of the card from the database, // We need to get the name of the card from the database,
// but we can't do that until we get the "real" name // but we can't do that until we get the "real" name
@ -608,11 +684,14 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
InnerDecklistNode * DeckList::getZoneObjFromName(const QString zoneName) InnerDecklistNode * DeckList::getZoneObjFromName(const QString zoneName)
{ {
for (int i = 0; i < root->size(); i++) { for (int i = 0; i < root->size(); i++)
InnerDecklistNode *node = dynamic_cast<InnerDecklistNode *>(root->at(i)); {
if(node->getName() == zoneName) auto *node = dynamic_cast<InnerDecklistNode *>(root->at(i));
if (node->getName() == zoneName)
{
return node; return node;
} }
}
return new InnerDecklistNode(zoneName, root); return new InnerDecklistNode(zoneName, root);
} }
@ -685,13 +764,19 @@ void DeckList::cleanList()
void DeckList::getCardListHelper(InnerDecklistNode *item, QSet<QString> &result) const void DeckList::getCardListHelper(InnerDecklistNode *item, QSet<QString> &result) const
{ {
for (int i = 0; i < item->size(); ++i) { for (int i = 0; i < item->size(); ++i)
DecklistCardNode *node = dynamic_cast<DecklistCardNode *>(item->at(i)); {
auto *node = dynamic_cast<DecklistCardNode *>(item->at(i));
if (node) if (node)
{
result.insert(node->getName()); result.insert(node->getName());
}
else else
{
getCardListHelper(dynamic_cast<InnerDecklistNode *>(item->at(i)), result); getCardListHelper(dynamic_cast<InnerDecklistNode *>(item->at(i)), result);
} }
}
} }
QStringList DeckList::getCardList() const QStringList DeckList::getCardList() const
@ -704,12 +789,17 @@ QStringList DeckList::getCardList() const
int DeckList::getSideboardSize() const int DeckList::getSideboardSize() const
{ {
int size = 0; int size = 0;
for (int i = 0; i < root->size(); ++i) { for (int i = 0; i < root->size(); ++i)
InnerDecklistNode *node = dynamic_cast<InnerDecklistNode *>(root->at(i)); {
auto *node = dynamic_cast<InnerDecklistNode *>(root->at(i));
if (node->getName() != DECK_ZONE_SIDE) if (node->getName() != DECK_ZONE_SIDE)
{
continue; continue;
for (int j = 0; j < node->size(); j++) { }
DecklistCardNode *card = dynamic_cast<DecklistCardNode *>(node->at(j));
for (int j = 0; j < node->size(); j++)
{
auto *card = dynamic_cast<DecklistCardNode *>(node->at(j));
size += card->getNumber(); size += card->getNumber();
} }
} }
@ -718,43 +808,67 @@ int DeckList::getSideboardSize() const
DecklistCardNode *DeckList::addCard(const QString &cardName, const QString &zoneName) DecklistCardNode *DeckList::addCard(const QString &cardName, const QString &zoneName)
{ {
InnerDecklistNode *zoneNode = dynamic_cast<InnerDecklistNode *>(root->findChild(zoneName)); auto *zoneNode = dynamic_cast<InnerDecklistNode *>(root->findChild(zoneName));
if (!zoneNode) if (zoneNode == nullptr)
{
zoneNode = new InnerDecklistNode(zoneName, root); zoneNode = new InnerDecklistNode(zoneName, root);
}
DecklistCardNode *node = new DecklistCardNode(cardName, 1, zoneNode); auto *node = new DecklistCardNode(cardName, 1, zoneNode);
updateDeckHash(); updateDeckHash();
return node; return node;
} }
bool DeckList::deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode) bool DeckList::deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode)
{ {
if (node == root) if (node == root)
{
return true; return true;
}
bool updateHash = false; bool updateHash = false;
if (!rootNode) { if (rootNode == nullptr)
{
rootNode = root; rootNode = root;
updateHash = true; updateHash = true;
} }
int index = rootNode->indexOf(node); int index = rootNode->indexOf(node);
if (index != -1) { if (index != -1)
{
delete rootNode->takeAt(index); delete rootNode->takeAt(index);
if (!rootNode->size())
if (rootNode->empty())
{
deleteNode(rootNode, rootNode->getParent()); deleteNode(rootNode, rootNode->getParent());
}
if (updateHash) if (updateHash)
{
updateDeckHash(); updateDeckHash();
}
return true; return true;
} }
for (int i = 0; i < rootNode->size(); i++) {
InnerDecklistNode *inner = dynamic_cast<InnerDecklistNode *>(rootNode->at(i)); for (int i = 0; i < rootNode->size(); i++)
{
auto *inner = dynamic_cast<InnerDecklistNode *>(rootNode->at(i));
if (inner) if (inner)
if (deleteNode(node, inner)) { {
if (deleteNode(node, inner))
{
if (updateHash) if (updateHash)
{
updateDeckHash(); updateDeckHash();
}
return true; return true;
} }
} }
}
return false; return false;
} }
@ -769,15 +883,17 @@ void DeckList::updateDeckHash()
for (int i = 0; i < root->size(); i++) for (int i = 0; i < root->size(); i++)
{ {
InnerDecklistNode *node = dynamic_cast<InnerDecklistNode *>(root->at(i)); auto *node = dynamic_cast<InnerDecklistNode *>(root->at(i));
for (int j = 0; j < node->size(); j++) for (int j = 0; j < node->size(); j++)
{ {
if (hashZones.contains(node->getName())) // Mainboard or Sideboard if (hashZones.contains(node->getName())) // Mainboard or Sideboard
{ {
DecklistCardNode *card = dynamic_cast<DecklistCardNode *>(node->at(j)); auto *card = dynamic_cast<DecklistCardNode *>(node->at(j));
for (int k = 0; k < card->getNumber(); ++k) for (int k = 0; k < card->getNumber(); ++k)
{
cardList.append((node->getName() == DECK_ZONE_SIDE ? "SB:" : "") + card->getName().toLower()); cardList.append((node->getName() == DECK_ZONE_SIDE ? "SB:" : "") + card->getName().toLower());
} }
}
else if (!optionalZones.contains(node->getName())) // Not a valid zone -> cheater? else if (!optionalZones.contains(node->getName())) // Not a valid zone -> cheater?
{ {
isValidDeckList = false; // Deck is invalid isValidDeckList = false; // Deck is invalid

View file

@ -25,12 +25,14 @@ class InnerDecklistNode;
#define DECK_ZONE_SIDE "side" #define DECK_ZONE_SIDE "side"
#define DECK_ZONE_TOKENS "tokens" #define DECK_ZONE_TOKENS "tokens"
class SideboardPlan { class SideboardPlan
private: {
private:
QString name; QString name;
QList<MoveCard_ToZone> moveList; QList<MoveCard_ToZone> moveList;
public:
SideboardPlan(const QString &_name = QString(), const QList<MoveCard_ToZone> &_moveList = QList<MoveCard_ToZone>()); public:
explicit SideboardPlan(const QString &_name = QString(), const QList<MoveCard_ToZone> &_moveList = QList<MoveCard_ToZone>());
bool readElement(QXmlStreamReader *xml); bool readElement(QXmlStreamReader *xml);
void write(QXmlStreamWriter *xml); void write(QXmlStreamWriter *xml);
@ -39,15 +41,17 @@ public:
void setMoveList(const QList<MoveCard_ToZone> &_moveList); void setMoveList(const QList<MoveCard_ToZone> &_moveList);
}; };
enum DeckSortMethod { ByNumber, ByName }; enum DeckSortMethod { ByNumber, ByName, Default };
class AbstractDecklistNode { class AbstractDecklistNode
protected: {
protected:
InnerDecklistNode *parent; InnerDecklistNode *parent;
DeckSortMethod sortMethod; DeckSortMethod sortMethod;
public:
AbstractDecklistNode(InnerDecklistNode *_parent = 0); public:
virtual ~AbstractDecklistNode() { } explicit AbstractDecklistNode(InnerDecklistNode *_parent = nullptr);
virtual ~AbstractDecklistNode() = default;
virtual void setSortMethod(DeckSortMethod method) { sortMethod = method; } virtual void setSortMethod(DeckSortMethod method) { sortMethod = method; }
virtual QString getName() const = 0; virtual QString getName() const = 0;
InnerDecklistNode *getParent() const { return parent; } InnerDecklistNode *getParent() const { return parent; }
@ -59,83 +63,92 @@ public:
virtual void writeElement(QXmlStreamWriter *xml) = 0; virtual void writeElement(QXmlStreamWriter *xml) = 0;
}; };
class InnerDecklistNode : public AbstractDecklistNode, public QList<AbstractDecklistNode *> { class InnerDecklistNode : public AbstractDecklistNode, public QList<AbstractDecklistNode *>
private: {
private:
QString name; QString name;
class compareFunctor; class compareFunctor;
public:
InnerDecklistNode(const QString &_name = QString(), InnerDecklistNode *_parent = 0) : AbstractDecklistNode(_parent), name(_name) { } public:
InnerDecklistNode(InnerDecklistNode *other, InnerDecklistNode *_parent = 0); explicit InnerDecklistNode(QString _name = QString(), InnerDecklistNode *_parent = nullptr) : AbstractDecklistNode(_parent), name(std::move(_name)) { }
virtual ~InnerDecklistNode(); explicit InnerDecklistNode(InnerDecklistNode *other, InnerDecklistNode *_parent = nullptr);
void setSortMethod(DeckSortMethod method); ~InnerDecklistNode() override;
QString getName() const { return name; } void setSortMethod(DeckSortMethod method) override;
QString getName() const override { return name; }
void setName(const QString &_name) { name = _name; } void setName(const QString &_name) { name = _name; }
static QString visibleNameFromName(const QString &_name); static QString visibleNameFromName(const QString &_name);
virtual QString getVisibleName() const; virtual QString getVisibleName() const;
void clearTree(); void clearTree();
AbstractDecklistNode *findChild(const QString &name); AbstractDecklistNode *findChild(const QString &name);
int height() const; int height() const override;
int recursiveCount(bool countTotalCards = false) const; int recursiveCount(bool countTotalCards = false) const;
bool compare(AbstractDecklistNode *other) const; bool compare(AbstractDecklistNode *other) const override;
bool compareNumber(AbstractDecklistNode *other) const; bool compareNumber(AbstractDecklistNode *other) const;
bool compareName(AbstractDecklistNode *other) const; bool compareName(AbstractDecklistNode *other) const;
QVector<QPair<int, int> > sort(Qt::SortOrder order = Qt::AscendingOrder); QVector<QPair<int, int> > sort(Qt::SortOrder order = Qt::AscendingOrder);
bool readElement(QXmlStreamReader *xml); bool readElement(QXmlStreamReader *xml) override;
void writeElement(QXmlStreamWriter *xml); void writeElement(QXmlStreamWriter *xml) override;
}; };
class AbstractDecklistCardNode : public AbstractDecklistNode { class AbstractDecklistCardNode : public AbstractDecklistNode
public: {
AbstractDecklistCardNode(InnerDecklistNode *_parent = 0) : AbstractDecklistNode(_parent) { } public:
explicit AbstractDecklistCardNode(InnerDecklistNode *_parent = nullptr) : AbstractDecklistNode(_parent) { }
virtual int getNumber() const = 0; virtual int getNumber() const = 0;
virtual void setNumber(int _number) = 0; virtual void setNumber(int _number) = 0;
virtual QString getName() const = 0; QString getName() const override = 0;
virtual void setName(const QString &_name) = 0; virtual void setName(const QString &_name) = 0;
int height() const { return 0; } int height() const override { return 0; }
bool compare(AbstractDecklistNode *other) const; bool compare(AbstractDecklistNode *other) const override;
bool compareNumber(AbstractDecklistNode *other) const; bool compareNumber(AbstractDecklistNode *other) const;
bool compareName(AbstractDecklistNode *other) const; bool compareName(AbstractDecklistNode *other) const;
bool readElement(QXmlStreamReader *xml); bool readElement(QXmlStreamReader *xml) override;
void writeElement(QXmlStreamWriter *xml); void writeElement(QXmlStreamWriter *xml) override;
}; };
class DecklistCardNode : public AbstractDecklistCardNode { class DecklistCardNode : public AbstractDecklistCardNode
private: {
private:
QString name; QString name;
int number; int number;
public: public:
DecklistCardNode(const QString &_name = QString(), int _number = 1, InnerDecklistNode *_parent = 0) : AbstractDecklistCardNode(_parent), name(_name), number(_number) { } explicit DecklistCardNode(QString _name = QString(), int _number = 1, InnerDecklistNode *_parent = nullptr) : AbstractDecklistCardNode(_parent), name(std::move(_name)), number(_number) { }
DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent); explicit DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent);
int getNumber() const { return number; } int getNumber() const override { return number; }
void setNumber(int _number) { number = _number; } void setNumber(int _number) override { number = _number; }
QString getName() const { return name; } QString getName() const override { return name; }
void setName(const QString &_name) { name = _name; } void setName(const QString &_name) override { name = _name; }
}; };
class DeckList : public QObject { class DeckList : public QObject
{
Q_OBJECT Q_OBJECT
private: private:
QString name, comments; QString name, comments;
QString deckHash; QString deckHash;
QMap<QString, SideboardPlan *> sideboardPlans; QMap<QString, SideboardPlan *> sideboardPlans;
InnerDecklistNode *root; InnerDecklistNode *root;
void getCardListHelper(InnerDecklistNode *node, QSet<QString> &result) const; void getCardListHelper(InnerDecklistNode *node, QSet<QString> &result) const;
InnerDecklistNode *getZoneObjFromName(const QString zoneName); InnerDecklistNode *getZoneObjFromName(QString zoneName);
protected:
virtual QString getCardZoneFromName(QString /* cardName */, QString currentZoneName) { return currentZoneName; }; protected:
virtual QString getCardZoneFromName(const QString /*cardName*/, QString currentZoneName) { return currentZoneName; };
virtual QString getCompleteCardName(const QString cardName) const { return cardName; }; virtual QString getCompleteCardName(const QString cardName) const { return cardName; };
signals:
signals:
void deckHashChanged(); void deckHashChanged();
public slots:
public slots:
void setName(const QString &_name = QString()) { name = _name; } void setName(const QString &_name = QString()) { name = _name; }
void setComments(const QString &_comments = QString()) { comments = _comments; } void setComments(const QString &_comments = QString()) { comments = _comments; }
public:
DeckList(); public:
explicit DeckList();
DeckList(const DeckList &other); DeckList(const DeckList &other);
DeckList(const QString &nativeString); explicit DeckList(const QString &nativeString);
~DeckList(); ~DeckList() override;
QString getName() const { return name; } QString getName() const { return name; }
QString getComments() const { return comments; } QString getComments() const { return comments; }
QList<MoveCard_ToZone> getCurrentSideboardPlan(); QList<MoveCard_ToZone> getCurrentSideboardPlan();
@ -166,7 +179,7 @@ public:
InnerDecklistNode *getRoot() const { return root; } InnerDecklistNode *getRoot() const { return root; }
DecklistCardNode *addCard(const QString &cardName, const QString &zoneName); DecklistCardNode *addCard(const QString &cardName, const QString &zoneName);
bool deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode = 0); bool deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode = nullptr);
/** /**
* Calls a given function object for each card in the deck. It must * Calls a given function object for each card in the deck. It must