Fix deck loader with spaces (#3007)
This commit is contained in:
parent
dcc632e0d4
commit
34bec90193
6 changed files with 561 additions and 330 deletions
|
@ -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,71 +69,99 @@ 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
|
||||||
{
|
{
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
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()) {
|
{
|
||||||
case 0: return card->getNumber();
|
switch (index.column())
|
||||||
case 1: return card->getName();
|
{
|
||||||
|
case 0: return card->getNumber();
|
||||||
|
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,33 +169,42 @@ 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) {
|
}
|
||||||
case 0: return tr("Number");
|
|
||||||
case 1: return tr("Card");
|
switch (section)
|
||||||
|
{
|
||||||
|
case 0: return tr("Number");
|
||||||
|
case 1: return tr("Card");
|
||||||
default: return QVariant();
|
default: return QVariant();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 1: node->setName(value.toString()); break;
|
case 0: node->setNumber(value.toInt()); 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,10 +438,13 @@ 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,16 +455,18 @@ void DeckListModel::sort(int column, Qt::SortOrder order)
|
||||||
|
|
||||||
emit layoutAboutToBeChanged();
|
emit layoutAboutToBeChanged();
|
||||||
DeckSortMethod sortMethod;
|
DeckSortMethod sortMethod;
|
||||||
switch(column) {
|
switch(column)
|
||||||
case 0:
|
{
|
||||||
sortMethod = ByNumber;
|
case 0:
|
||||||
break;
|
sortMethod = ByNumber;
|
||||||
case 1:
|
break;
|
||||||
sortMethod = ByName;
|
case 1:
|
||||||
break;
|
sortMethod = ByName;
|
||||||
default:
|
break;
|
||||||
sortMethod = ByName;
|
default:
|
||||||
|
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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
|
||||||
DeckLoader *deckList;
|
private:
|
||||||
public:
|
DeckLoader *deckList;
|
||||||
DlgLoadDeckFromClipboard(QWidget *parent = 0);
|
QPlainTextEdit *contentsEdit;
|
||||||
DeckLoader *getDeckList() const { return deckList; }
|
QPushButton *refreshButton;
|
||||||
private:
|
|
||||||
QPlainTextEdit *contentsEdit;
|
public:
|
||||||
QPushButton *refreshButton;
|
explicit DlgLoadDeckFromClipboard(QWidget *parent = nullptr);
|
||||||
|
DeckLoader *getDeckList() const { return deckList; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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,40 +50,50 @@ 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 the count ends with an 'x', ignore it. For example,
|
if (i > 0)
|
||||||
// "4x Storm Crow" will count 4 correctly.
|
{
|
||||||
if (i > 0 && line[i - 1] == 'x')
|
// If the count ends with an 'x', ignore it. For example,
|
||||||
i--;
|
// "4x Storm Crow" will count 4 correctly.
|
||||||
|
if (line.at(i-1) == 'x')
|
||||||
|
{
|
||||||
|
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,10 +684,13 @@ 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,12 +764,18 @@ 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,14 +883,16 @@ 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?
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,170 +25,183 @@ 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:
|
{
|
||||||
QString name;
|
private:
|
||||||
QList<MoveCard_ToZone> moveList;
|
QString name;
|
||||||
public:
|
QList<MoveCard_ToZone> moveList;
|
||||||
SideboardPlan(const QString &_name = QString(), const QList<MoveCard_ToZone> &_moveList = QList<MoveCard_ToZone>());
|
|
||||||
bool readElement(QXmlStreamReader *xml);
|
|
||||||
void write(QXmlStreamWriter *xml);
|
|
||||||
|
|
||||||
QString getName() const { return name; }
|
public:
|
||||||
const QList<MoveCard_ToZone> &getMoveList() const { return moveList; }
|
explicit SideboardPlan(const QString &_name = QString(), const QList<MoveCard_ToZone> &_moveList = QList<MoveCard_ToZone>());
|
||||||
void setMoveList(const QList<MoveCard_ToZone> &_moveList);
|
bool readElement(QXmlStreamReader *xml);
|
||||||
|
void write(QXmlStreamWriter *xml);
|
||||||
|
|
||||||
|
QString getName() const { return name; }
|
||||||
|
const QList<MoveCard_ToZone> &getMoveList() const { return moveList; }
|
||||||
|
void setMoveList(const QList<MoveCard_ToZone> &_moveList);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DeckSortMethod { ByNumber, ByName };
|
enum DeckSortMethod { ByNumber, ByName, Default };
|
||||||
|
|
||||||
class AbstractDecklistNode {
|
class AbstractDecklistNode
|
||||||
protected:
|
{
|
||||||
InnerDecklistNode *parent;
|
protected:
|
||||||
DeckSortMethod sortMethod;
|
InnerDecklistNode *parent;
|
||||||
public:
|
DeckSortMethod sortMethod;
|
||||||
AbstractDecklistNode(InnerDecklistNode *_parent = 0);
|
|
||||||
virtual ~AbstractDecklistNode() { }
|
|
||||||
virtual void setSortMethod(DeckSortMethod method) { sortMethod = method; }
|
|
||||||
virtual QString getName() const = 0;
|
|
||||||
InnerDecklistNode *getParent() const { return parent; }
|
|
||||||
int depth() const;
|
|
||||||
virtual int height() const = 0;
|
|
||||||
virtual bool compare(AbstractDecklistNode *other) const = 0;
|
|
||||||
|
|
||||||
virtual bool readElement(QXmlStreamReader *xml) = 0;
|
public:
|
||||||
virtual void writeElement(QXmlStreamWriter *xml) = 0;
|
explicit AbstractDecklistNode(InnerDecklistNode *_parent = nullptr);
|
||||||
|
virtual ~AbstractDecklistNode() = default;
|
||||||
|
virtual void setSortMethod(DeckSortMethod method) { sortMethod = method; }
|
||||||
|
virtual QString getName() const = 0;
|
||||||
|
InnerDecklistNode *getParent() const { return parent; }
|
||||||
|
int depth() const;
|
||||||
|
virtual int height() const = 0;
|
||||||
|
virtual bool compare(AbstractDecklistNode *other) const = 0;
|
||||||
|
|
||||||
|
virtual bool readElement(QXmlStreamReader *xml) = 0;
|
||||||
|
virtual void writeElement(QXmlStreamWriter *xml) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class InnerDecklistNode : public AbstractDecklistNode, public QList<AbstractDecklistNode *> {
|
class InnerDecklistNode : public AbstractDecklistNode, public QList<AbstractDecklistNode *>
|
||||||
private:
|
{
|
||||||
QString name;
|
private:
|
||||||
class compareFunctor;
|
QString name;
|
||||||
public:
|
class compareFunctor;
|
||||||
InnerDecklistNode(const QString &_name = QString(), InnerDecklistNode *_parent = 0) : AbstractDecklistNode(_parent), name(_name) { }
|
|
||||||
InnerDecklistNode(InnerDecklistNode *other, InnerDecklistNode *_parent = 0);
|
|
||||||
virtual ~InnerDecklistNode();
|
|
||||||
void setSortMethod(DeckSortMethod method);
|
|
||||||
QString getName() const { return name; }
|
|
||||||
void setName(const QString &_name) { name = _name; }
|
|
||||||
static QString visibleNameFromName(const QString &_name);
|
|
||||||
virtual QString getVisibleName() const;
|
|
||||||
void clearTree();
|
|
||||||
AbstractDecklistNode *findChild(const QString &name);
|
|
||||||
int height() const;
|
|
||||||
int recursiveCount(bool countTotalCards = false) const;
|
|
||||||
bool compare(AbstractDecklistNode *other) const;
|
|
||||||
bool compareNumber(AbstractDecklistNode *other) const;
|
|
||||||
bool compareName(AbstractDecklistNode *other) const;
|
|
||||||
QVector<QPair<int, int> > sort(Qt::SortOrder order = Qt::AscendingOrder);
|
|
||||||
|
|
||||||
bool readElement(QXmlStreamReader *xml);
|
public:
|
||||||
void writeElement(QXmlStreamWriter *xml);
|
explicit InnerDecklistNode(QString _name = QString(), InnerDecklistNode *_parent = nullptr) : AbstractDecklistNode(_parent), name(std::move(_name)) { }
|
||||||
|
explicit InnerDecklistNode(InnerDecklistNode *other, InnerDecklistNode *_parent = nullptr);
|
||||||
|
~InnerDecklistNode() override;
|
||||||
|
void setSortMethod(DeckSortMethod method) override;
|
||||||
|
QString getName() const override { return name; }
|
||||||
|
void setName(const QString &_name) { name = _name; }
|
||||||
|
static QString visibleNameFromName(const QString &_name);
|
||||||
|
virtual QString getVisibleName() const;
|
||||||
|
void clearTree();
|
||||||
|
AbstractDecklistNode *findChild(const QString &name);
|
||||||
|
int height() const override;
|
||||||
|
int recursiveCount(bool countTotalCards = false) const;
|
||||||
|
bool compare(AbstractDecklistNode *other) const override;
|
||||||
|
bool compareNumber(AbstractDecklistNode *other) const;
|
||||||
|
bool compareName(AbstractDecklistNode *other) const;
|
||||||
|
QVector<QPair<int, int> > sort(Qt::SortOrder order = Qt::AscendingOrder);
|
||||||
|
|
||||||
|
bool readElement(QXmlStreamReader *xml) override;
|
||||||
|
void writeElement(QXmlStreamWriter *xml) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AbstractDecklistCardNode : public AbstractDecklistNode {
|
class AbstractDecklistCardNode : public AbstractDecklistNode
|
||||||
public:
|
{
|
||||||
AbstractDecklistCardNode(InnerDecklistNode *_parent = 0) : AbstractDecklistNode(_parent) { }
|
public:
|
||||||
virtual int getNumber() const = 0;
|
explicit AbstractDecklistCardNode(InnerDecklistNode *_parent = nullptr) : AbstractDecklistNode(_parent) { }
|
||||||
virtual void setNumber(int _number) = 0;
|
virtual int getNumber() const = 0;
|
||||||
virtual QString getName() const = 0;
|
virtual void setNumber(int _number) = 0;
|
||||||
virtual void setName(const QString &_name) = 0;
|
QString getName() const override = 0;
|
||||||
int height() const { return 0; }
|
virtual void setName(const QString &_name) = 0;
|
||||||
bool compare(AbstractDecklistNode *other) const;
|
int height() const override { return 0; }
|
||||||
bool compareNumber(AbstractDecklistNode *other) const;
|
bool compare(AbstractDecklistNode *other) const override;
|
||||||
bool compareName(AbstractDecklistNode *other) const;
|
bool compareNumber(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:
|
{
|
||||||
QString name;
|
private:
|
||||||
int number;
|
QString name;
|
||||||
public:
|
int number;
|
||||||
DecklistCardNode(const QString &_name = QString(), int _number = 1, InnerDecklistNode *_parent = 0) : AbstractDecklistCardNode(_parent), name(_name), number(_number) { }
|
public:
|
||||||
DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent);
|
explicit DecklistCardNode(QString _name = QString(), int _number = 1, InnerDecklistNode *_parent = nullptr) : AbstractDecklistCardNode(_parent), name(std::move(_name)), number(_number) { }
|
||||||
int getNumber() const { return number; }
|
explicit DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent);
|
||||||
void setNumber(int _number) { number = _number; }
|
int getNumber() const override { return number; }
|
||||||
QString getName() const { return name; }
|
void setNumber(int _number) override { number = _number; }
|
||||||
void setName(const QString &_name) { name = _name; }
|
QString getName() const override { return 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; };
|
|
||||||
virtual QString getCompleteCardName(const QString cardName) const { return cardName; };
|
|
||||||
signals:
|
|
||||||
void deckHashChanged();
|
|
||||||
public slots:
|
|
||||||
void setName(const QString &_name = QString()) { name = _name; }
|
|
||||||
void setComments(const QString &_comments = QString()) { comments = _comments; }
|
|
||||||
public:
|
|
||||||
DeckList();
|
|
||||||
DeckList(const DeckList &other);
|
|
||||||
DeckList(const QString &nativeString);
|
|
||||||
~DeckList();
|
|
||||||
QString getName() const { return name; }
|
|
||||||
QString getComments() const { return comments; }
|
|
||||||
QList<MoveCard_ToZone> getCurrentSideboardPlan();
|
|
||||||
void setCurrentSideboardPlan(const QList<MoveCard_ToZone> &plan);
|
|
||||||
const QMap<QString, SideboardPlan *> &getSideboardPlans() const { return sideboardPlans; }
|
|
||||||
|
|
||||||
bool readElement(QXmlStreamReader *xml);
|
protected:
|
||||||
void write(QXmlStreamWriter *xml);
|
virtual QString getCardZoneFromName(const QString /*cardName*/, QString currentZoneName) { return currentZoneName; };
|
||||||
bool loadFromXml(QXmlStreamReader *xml);
|
virtual QString getCompleteCardName(const QString cardName) const { return cardName; };
|
||||||
bool loadFromString_Native(const QString &nativeString);
|
|
||||||
QString writeToString_Native();
|
|
||||||
bool loadFromFile_Native(QIODevice *device);
|
|
||||||
bool saveToFile_Native(QIODevice *device);
|
|
||||||
bool loadFromStream_Plain(QTextStream &stream);
|
|
||||||
bool loadFromFile_Plain(QIODevice *device);
|
|
||||||
bool saveToStream_Plain(QTextStream &stream, bool prefixSideboardCards, bool slashTappedOutSplitCards);
|
|
||||||
bool saveToFile_Plain(QIODevice *device, bool prefixSideboardCards=true, bool slashTappedOutSplitCards=false);
|
|
||||||
QString writeToString_Plain(bool prefixSideboardCards=true, bool slashTappedOutSplitCards=false);
|
|
||||||
|
|
||||||
void cleanList();
|
signals:
|
||||||
bool isEmpty() const { return root->isEmpty() && name.isEmpty() && comments.isEmpty() && sideboardPlans.isEmpty(); }
|
void deckHashChanged();
|
||||||
QStringList getCardList() const;
|
|
||||||
|
|
||||||
int getSideboardSize() const;
|
public slots:
|
||||||
|
void setName(const QString &_name = QString()) { name = _name; }
|
||||||
|
void setComments(const QString &_comments = QString()) { comments = _comments; }
|
||||||
|
|
||||||
QString getDeckHash() const { return deckHash; }
|
public:
|
||||||
void updateDeckHash();
|
explicit DeckList();
|
||||||
|
DeckList(const DeckList &other);
|
||||||
|
explicit DeckList(const QString &nativeString);
|
||||||
|
~DeckList() override;
|
||||||
|
QString getName() const { return name; }
|
||||||
|
QString getComments() const { return comments; }
|
||||||
|
QList<MoveCard_ToZone> getCurrentSideboardPlan();
|
||||||
|
void setCurrentSideboardPlan(const QList<MoveCard_ToZone> &plan);
|
||||||
|
const QMap<QString, SideboardPlan *> &getSideboardPlans() const { return sideboardPlans; }
|
||||||
|
|
||||||
InnerDecklistNode *getRoot() const { return root; }
|
bool readElement(QXmlStreamReader *xml);
|
||||||
DecklistCardNode *addCard(const QString &cardName, const QString &zoneName);
|
void write(QXmlStreamWriter *xml);
|
||||||
bool deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode = 0);
|
bool loadFromXml(QXmlStreamReader *xml);
|
||||||
|
bool loadFromString_Native(const QString &nativeString);
|
||||||
|
QString writeToString_Native();
|
||||||
|
bool loadFromFile_Native(QIODevice *device);
|
||||||
|
bool saveToFile_Native(QIODevice *device);
|
||||||
|
bool loadFromStream_Plain(QTextStream &stream);
|
||||||
|
bool loadFromFile_Plain(QIODevice *device);
|
||||||
|
bool saveToStream_Plain(QTextStream &stream, bool prefixSideboardCards, bool slashTappedOutSplitCards);
|
||||||
|
bool saveToFile_Plain(QIODevice *device, bool prefixSideboardCards=true, bool slashTappedOutSplitCards=false);
|
||||||
|
QString writeToString_Plain(bool prefixSideboardCards=true, bool slashTappedOutSplitCards=false);
|
||||||
|
|
||||||
/**
|
void cleanList();
|
||||||
* Calls a given function object for each card in the deck. It must
|
bool isEmpty() const { return root->isEmpty() && name.isEmpty() && comments.isEmpty() && sideboardPlans.isEmpty(); }
|
||||||
* take a InnerDecklistNode* as its first argument and a
|
QStringList getCardList() const;
|
||||||
* DecklistCardNode* as its second.
|
|
||||||
*/
|
int getSideboardSize() const;
|
||||||
template <typename Callback>
|
|
||||||
void forEachCard(Callback &callback) const {
|
QString getDeckHash() const { return deckHash; }
|
||||||
// Support for this is only possible if the internal structure
|
void updateDeckHash();
|
||||||
// doesn't get more complicated.
|
|
||||||
for (int i = 0; i < root->size(); i++) {
|
InnerDecklistNode *getRoot() const { return root; }
|
||||||
const InnerDecklistNode *node =
|
DecklistCardNode *addCard(const QString &cardName, const QString &zoneName);
|
||||||
dynamic_cast<InnerDecklistNode *>(root->at(i));
|
bool deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode = nullptr);
|
||||||
for (int j = 0; j < node->size(); j++) {
|
|
||||||
const DecklistCardNode *card =
|
/**
|
||||||
dynamic_cast<DecklistCardNode *>(
|
* Calls a given function object for each card in the deck. It must
|
||||||
node->at(j)
|
* take a InnerDecklistNode* as its first argument and a
|
||||||
);
|
* DecklistCardNode* as its second.
|
||||||
callback(node, card);
|
*/
|
||||||
|
template <typename Callback>
|
||||||
|
void forEachCard(Callback &callback) const {
|
||||||
|
// Support for this is only possible if the internal structure
|
||||||
|
// doesn't get more complicated.
|
||||||
|
for (int i = 0; i < root->size(); i++) {
|
||||||
|
const InnerDecklistNode *node =
|
||||||
|
dynamic_cast<InnerDecklistNode *>(root->at(i));
|
||||||
|
for (int j = 0; j < node->size(); j++) {
|
||||||
|
const DecklistCardNode *card =
|
||||||
|
dynamic_cast<DecklistCardNode *>(
|
||||||
|
node->at(j)
|
||||||
|
);
|
||||||
|
callback(node, card);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue