deck editor...

This commit is contained in:
Max-Wilhelm Bruker 2009-05-24 01:41:25 +02:00
parent 3ae865178b
commit d9e51e58a3
7 changed files with 225 additions and 80 deletions

View file

@ -7,9 +7,20 @@
#include "decklist.h"
#include "carddatabase.h"
QString DecklistZone::getVisibleName() const
{
if (name == "main")
return QObject::tr("Maindeck");
else if (name == "side")
return QObject::tr("Sideboard");
else
return QString();
}
DeckList::DeckList(CardDatabase *_db, QObject *parent)
: QObject(parent), db(_db)
{
initZones();
}
DeckList::~DeckList()
@ -31,15 +42,16 @@ bool DeckList::loadFromFile_Native(QIODevice *device)
name = xml.readElementText();
else if (xml.name() == "comments")
comments = xml.readElementText();
else if (xml.name() == "decklist") {
else if (xml.name() == "zone") {
DecklistZone *zone = new DecklistZone(xml.attributes().value("name").toString());
zones.append(zone);
while (!xml.atEnd()) {
if (xml.readNext() == QXmlStreamReader::EndElement)
break;
if (xml.name() == "card") {
const int number = xml.attributes().value("number").toString().toInt();
const QString card = xml.attributes().value("name").toString();
const bool sb = xml.attributes().value("zone") == "side";
append(new DecklistRow(number, card, sb));
zone->append(new DecklistRow(number, card));
while (!xml.atEnd())
if (xml.readNext() == QXmlStreamReader::EndElement)
break;
@ -63,18 +75,17 @@ bool DeckList::saveToFile_Native(QIODevice *device)
xml.writeTextElement("deckname", name);
xml.writeTextElement("comments", comments);
xml.writeStartElement("decklist");
for (int i = 0; i < size(); i++) {
DecklistRow *r = at(i);
xml.writeEmptyElement("card");
if (r->isSideboard())
xml.writeAttribute("zone", "side");
else
xml.writeAttribute("zone", "main");
xml.writeAttribute("number", QString::number(r->getNumber()));
xml.writeAttribute("name", r->getCard());
for (int i = 0; i < zones.size(); i++) {
xml.writeStartElement("zone");
xml.writeAttribute("name", zones[i]->getName());
for (int j = 0; j < zones[i]->size(); j++) {
DecklistRow *r = zones[i]->at(j);
xml.writeEmptyElement("card");
xml.writeAttribute("number", QString::number(r->getNumber()));
xml.writeAttribute("name", r->getCard());
}
xml.writeEndElement(); // zone
}
xml.writeEndElement(); // decklist
xml.writeEndElement(); // cockatrice_deck
@ -84,17 +95,20 @@ bool DeckList::saveToFile_Native(QIODevice *device)
bool DeckList::loadFromFile_Plain(QIODevice *device)
{
initZones();
QTextStream in(device);
while (!in.atEnd()) {
QString line = in.readLine().simplified();
if (line.startsWith("//"))
continue;
bool isSideboard = false;
DecklistZone *zone;
if (line.startsWith("SB:", Qt::CaseInsensitive)) {
line = line.mid(3).trimmed();
isSideboard = true;
}
zone = zones[1];
} else
zone = zones[0];
// Filter out MWS edition symbols and basic land extras
QRegExp rx("\\[.*\\]");
@ -108,7 +122,7 @@ bool DeckList::loadFromFile_Plain(QIODevice *device)
int number = line.left(i).toInt(&ok);
if (!ok)
continue;
append(new DecklistRow(number, line.mid(i + 1), isSideboard));
zone->append(new DecklistRow(number, line.mid(i + 1)));
}
return true;
}
@ -116,10 +130,11 @@ bool DeckList::loadFromFile_Plain(QIODevice *device)
bool DeckList::saveToFile_Plain(QIODevice *device)
{
QTextStream out(device);
for (int i = 0; i < size(); i++) {
DecklistRow *r = at(i);
out << QString("%1%2 %3\n").arg(r->isSideboard() ? "SB: " : "").arg(r->getNumber()).arg(r->getCard());
}
for (int i = 0; i < zones.size(); i++)
for (int j = 0; j < zones[i]->size(); j++) {
DecklistRow *r = zones[i]->at(j);
out << QString("%1%2 %3\n").arg(zones[i]->getName() == "side" ? "SB: " : "").arg(r->getNumber()).arg(r->getCard());
}
return true;
}
@ -212,18 +227,37 @@ bool DeckList::saveDialog(QWidget *parent)
void DeckList::cacheCardPictures(QWidget *parent)
{
QProgressDialog progress(tr("Caching card pictures..."), QString(), 0, size(), parent);
int totalCards = 0;
for (int i = 0; i < zones.size(); i++)
totalCards += zones[i]->size();
QProgressDialog progress(tr("Caching card pictures..."), QString(), 0, totalCards, parent);
progress.setMinimumDuration(1000);
progress.setWindowModality(Qt::WindowModal);
for (int i = 0; i < size(); i++) {
db->getCard(at(i)->getCard())->getPixmap();
progress.setValue(i + 1);
}
for (int i = 0; i < zones.size(); i++)
for (int j = 0; j < zones[i]->size(); j++) {
db->getCard(zones[i]->at(j)->getCard())->getPixmap();
progress.setValue(progress.value() + 1);
}
}
void DeckList::cleanList()
{
for (int i = 0; i < size(); i++)
delete at(i);
clear();
for (int i = 0; i < zones.size(); i++) {
for (int j = 0; j < zones[i]->size(); j++)
delete zones[i]->at(j);
zones[i]->clear();
delete zones[i];
}
zones.clear();
setName();
setComments();
}
void DeckList::initZones()
{
// possibly Magic specific
zones.append(new DecklistZone("main"));
zones.append(new DecklistZone("side"));
}

View file

@ -11,17 +11,24 @@ class DecklistRow {
private:
int number;
QString card;
bool sideboard;
public:
DecklistRow(int _number = 1, const QString &_card = QString(), bool _sideboard = false) : number(_number), card(_card), sideboard(_sideboard) { }
DecklistRow(int _number = 1, const QString &_card = QString()) : number(_number), card(_card) { }
int getNumber() const { return number; }
void setNumber(int _number) { number = _number; }
QString getCard() const { return card; }
void setCard(const QString &_card) { card = _card; }
bool isSideboard() const { return sideboard; }
};
class DeckList : public QObject, public QList<DecklistRow *> {
class DecklistZone : public QList<DecklistRow *> {
private:
QString name;
public:
DecklistZone(const QString &_name) : name(_name) { }
QString getName() const { return name; }
QString getVisibleName() const;
};
class DeckList : public QObject {
Q_OBJECT
public:
enum FileFormat { PlainTextFormat, CockatriceFormat };
@ -32,11 +39,12 @@ private:
QString name, comments;
QString lastFileName;
FileFormat lastFileFormat;
QList<DecklistZone *> zones;
signals:
void deckLoaded();
public slots:
void setName(const QString &_name) { name = _name; }
void setComments(const QString &_comments) { comments = _comments; }
void setName(const QString &_name = QString()) { name = _name; }
void setComments(const QString &_comments = QString()) { comments = _comments; }
public:
DeckList(CardDatabase *_db, QObject *parent = 0);
~DeckList();
@ -55,6 +63,10 @@ public:
bool saveDialog(QWidget *parent = 0);
void cleanList();
void initZones();
int zoneCount() const { return zones.size(); }
DecklistZone *getZoneByIndex(int index) const { return zones[index]; }
};
#endif

View file

@ -1,10 +1,12 @@
#include <QFile>
#include <QTextStream>
#include <QFont>
#include <QBrush>
#include "decklistmodel.h"
#include "carddatabase.h"
DeckListModel::DeckListModel(CardDatabase *_db, QObject *parent)
: QAbstractListModel(parent), db(_db)
: QAbstractItemModel(parent), db(_db)
{
deckList = new DeckList(db, this);
connect(deckList, SIGNAL(deckLoaded()), this, SLOT(resetModel()));
@ -19,10 +21,19 @@ void DeckListModel::resetModel()
reset();
}
int DeckListModel::rowCount(const QModelIndex &/*parent*/) const
int DeckListModel::rowCount(const QModelIndex &parent) const
{
// qDebug(QString("rowCount = %1").arg(deckList->size()).toLatin1());
return deckList->size();
if (!parent.isValid()) // parent = root
return deckList->zoneCount();
else if (!parent.parent().isValid()) // parent = zone root
return deckList->getZoneByIndex(parent.row())->size();
else // parent = card
return 0;
}
bool DeckListModel::hasChildren(const QModelIndex &parent) const
{
return !parent.parent().isValid();
}
int DeckListModel::columnCount(const QModelIndex &/*parent*/) const
@ -32,26 +43,58 @@ int DeckListModel::columnCount(const QModelIndex &/*parent*/) const
QVariant DeckListModel::data(const QModelIndex &index, int role) const
{
// qDebug(QString("data() called: index.row = %1, column = %2, role = %3").arg(index.row()).arg(index.column()).arg(role).toLatin1());
if (!index.isValid())
return QVariant();
if ((index.row() >= deckList->size()) || (index.column() >= 2))
if (index.column() >= 2)
return QVariant();
if ((role != Qt::DisplayRole) && (role != Qt::EditRole))
return QVariant();
DecklistRow *r = deckList->at(index.row());
switch (index.column()) {
case 0: return r->getNumber();
case 1: return r->getCard();
default: return QVariant();
if (!index.parent().isValid()) {
if (index.row() >= deckList->zoneCount())
return QVariant();
switch (role) {
case Qt::FontRole: {
QFont f;
f.setBold(true);
return f;
}
case Qt::DisplayRole:
case Qt::EditRole: {
DecklistZone *zone = deckList->getZoneByIndex(index.row());
switch (index.column()) {
case 0: return zone->getVisibleName();
case 1: return QVariant();
default: return QVariant();
}
}
case Qt::BackgroundRole:
return QBrush(QColor(200, 255, 200));
default: return QVariant();
}
} else {
DecklistZone *zone = deckList->getZoneByIndex(index.parent().row());
if (index.row() >= zone->size())
return QVariant();
switch (role) {
case Qt::DisplayRole:
case Qt::EditRole: {
DecklistRow *r = zone->at(index.row());
switch (index.column()) {
case 0: return r->getNumber();
case 1: return r->getCard();
default: return QVariant();
}
}
case Qt::BackgroundRole: {
int color = 255 - (index.row() % 2) * 30;
return QBrush(QColor(color, color, color));
}
default: return QVariant();
}
}
}
QVariant DeckListModel::headerData(int section, Qt::Orientation orientation, int role) const
{
// qDebug(QString("headerData() called: section = %1, orientation = %2, role = %3").arg(section).arg(orientation).arg(role).toLatin1());
if (role != Qt::DisplayRole)
return QVariant();
if (orientation != Qt::Horizontal)
@ -63,22 +106,43 @@ QVariant DeckListModel::headerData(int section, Qt::Orientation orientation, int
}
}
QModelIndex DeckListModel::index(int row, int column, const QModelIndex &parent) const
{
int id;
if (!parent.isValid())
id = -((row + 1) * 1000 + column);
else
id = parent.row() * 1000000 + row * 1000 + column;
return createIndex(row, column, id);
}
QModelIndex DeckListModel::parent(const QModelIndex &ind) const
{
if ((int) ind.internalId() < 0)
return QModelIndex();
else
return index(ind.internalId() / 1000000, 0);
}
Qt::ItemFlags DeckListModel::flags(const QModelIndex &index) const
{
if (index.column() == 0)
return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
else
return QAbstractItemModel::flags(index);
Qt::ItemFlags result = Qt::ItemIsEnabled;
if (index.parent().isValid()) {
result |= Qt::ItemIsSelectable;
if (index.column() == 0)
result |= Qt::ItemIsEditable;
}
return result;
}
bool DeckListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid() || role != Qt::EditRole)
if (!index.isValid() || !index.parent().isValid() || role != Qt::EditRole)
return false;
switch (index.column()) {
case 0: deckList->at(index.row())->setNumber(value.toInt()); break;
case 1: deckList->at(index.row())->setCard(value.toString()); break;
case 0: deckList->getZoneByIndex(index.parent().row())->at(index.row())->setNumber(value.toInt()); break;
case 1: deckList->getZoneByIndex(index.parent().row())->at(index.row())->setCard(value.toString()); break;
default: return false;
}
emit dataChanged(index, index);
@ -87,10 +151,14 @@ bool DeckListModel::setData(const QModelIndex &index, const QVariant &value, int
bool DeckListModel::removeRows(int row, int count, const QModelIndex &parent)
{
// Inserting zones is not supported.
if (!parent.isValid())
return false;
beginRemoveRows(parent, row, row + count - 1);
for (int i = 0; i < count; i++)
deckList->removeAt(row);
deckList->getZoneByIndex(parent.row())->removeAt(row);
endRemoveRows();
return true;
@ -98,10 +166,14 @@ bool DeckListModel::removeRows(int row, int count, const QModelIndex &parent)
bool DeckListModel::insertRows(int row, int count, const QModelIndex &parent)
{
// Inserting zones is not supported.
if (!parent.isValid())
return false;
beginInsertRows(parent, row, row + count - 1);
for (int i = 0; i < count; i++)
deckList->insert(row, new DecklistRow);
deckList->getZoneByIndex(parent.row())->insert(row, new DecklistRow);
endInsertRows();
return true;

View file

@ -1,13 +1,13 @@
#ifndef DECKLISTMODEL_H
#define DECKLISTMODEL_H
#include <QAbstractListModel>
#include <QAbstractItemModel>
#include <QList>
#include "decklist.h"
class CardDatabase;
class DeckListModel : public QAbstractListModel {
class DeckListModel : public QAbstractItemModel {
Q_OBJECT
private slots:
void resetModel();
@ -15,9 +15,12 @@ public:
DeckListModel(CardDatabase *_db, QObject *parent = 0);
~DeckListModel();
int rowCount(const QModelIndex &parent = QModelIndex()) const;
bool hasChildren(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &index) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
bool setData(const QModelIndex &index, const QVariant &value, int role);
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());

View file

@ -46,10 +46,13 @@ QStringList DlgStartGame::getDeckList() const
{
QStringList result;
DeckList *deckList = tableModel->getDeckList();
for (int i = 0; i < deckList->size(); i++) {
DecklistRow *temp = deckList->at(i);
for (int j = 0; j < temp->getNumber(); j++)
result << QString("%1%2").arg(temp->isSideboard() ? "SB:" : "").arg(temp->getCard());
for (int i = 0; i < deckList->zoneCount(); i++) {
DecklistZone *zone = deckList->getZoneByIndex(i);
for (int j = 0; j < zone->size(); j++) {
DecklistRow *r = zone->at(j);
for (int k = 0; k < r->getNumber(); k++)
result << QString("%1%2").arg(zone->getName() == "side" ? "SB:" : "").arg(r->getCard());
}
}
return result;
}

View file

@ -11,6 +11,7 @@ WndDeckEditor::WndDeckEditor(CardDatabase *_db, QWidget *parent)
databaseModel = new CardDatabaseModel(db);
databaseView = new QTreeView();
databaseView->setModel(databaseModel);
databaseView->setUniformRowHeights(true);
databaseView->setSortingEnabled(true);
connect(databaseView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(updateCardInfoLeft(const QModelIndex &, const QModelIndex &)));
@ -35,6 +36,8 @@ WndDeckEditor::WndDeckEditor(CardDatabase *_db, QWidget *parent)
deckModel = new DeckListModel(db, this);
deckView = new QTreeView();
deckView->setModel(deckModel);
deckView->setUniformRowHeights(true);
deckView->setRootIsDecorated(false);
connect(deckView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(updateCardInfoRight(const QModelIndex &, const QModelIndex &)));
QLabel *nameLabel = new QLabel(tr("Deck &name:"));
@ -83,9 +86,11 @@ WndDeckEditor::WndDeckEditor(CardDatabase *_db, QWidget *parent)
deckMenu->addAction(aSaveDeck);
deckMenu->addAction(aSaveDeckAs);
aAddCard = new QAction(tr("&Add card"), this);
aAddCard = new QAction(tr("&Add card to maindeck"), this);
connect(aAddCard, SIGNAL(triggered()), this, SLOT(actAddCard()));
aRemoveCard = new QAction(tr("&Remove card"), this);
aAddCardToSideboard = new QAction(tr("&Add card to sideboard"), this);
connect(aAddCardToSideboard, SIGNAL(triggered()), this, SLOT(actAddCardToSideboard()));
aRemoveCard = new QAction(tr("&Remove row"), this);
connect(aRemoveCard, SIGNAL(triggered()), this, SLOT(actRemoveCard()));
aIncrement = new QAction(tr("&Increment number"), this);
connect(aIncrement, SIGNAL(triggered()), this, SLOT(actIncrement()));
@ -93,6 +98,7 @@ WndDeckEditor::WndDeckEditor(CardDatabase *_db, QWidget *parent)
connect(aDecrement, SIGNAL(triggered()), this, SLOT(actDecrement()));
verticalToolBar->addAction(aAddCard);
verticalToolBar->addAction(aAddCardToSideboard);
verticalToolBar->addAction(aRemoveCard);
verticalToolBar->addAction(aIncrement);
verticalToolBar->addAction(aDecrement);
@ -125,9 +131,9 @@ void WndDeckEditor::actLoadDeck()
if (l->loadDialog(this)) {
lastFileName = l->getLastFileName();
lastFileFormat = l->getLastFileFormat();
// deckView->reset();
nameEdit->setText(l->getName());
commentsEdit->setText(l->getComments());
deckView->expandAll();
}
}
@ -149,30 +155,42 @@ void WndDeckEditor::actSaveDeckAs()
}
}
void WndDeckEditor::actAddCard()
void WndDeckEditor::addCardHelper(int baseRow)
{
const QModelIndex currentIndex = databaseView->selectionModel()->currentIndex();
if (!currentIndex.isValid())
return;
const QString cardName = databaseModel->index(currentIndex.row(), 0).data().toString();
QModelIndexList matches = deckModel->match(deckModel->index(0, 1), Qt::EditRole, cardName);
QModelIndex zoneRoot = deckModel->index(baseRow, 0);
deckView->expand(zoneRoot);
QModelIndexList matches = deckModel->match(deckModel->index(0, 1, zoneRoot), Qt::EditRole, cardName);
if (matches.isEmpty()) {
int row = deckModel->rowCount();
deckModel->insertRow(row);
deckModel->setData(deckModel->index(row, 1), cardName, Qt::EditRole);
int row = deckModel->rowCount(zoneRoot);
deckModel->insertRow(row, zoneRoot);
deckModel->setData(deckModel->index(row, 1, zoneRoot), cardName, Qt::EditRole);
} else {
const QModelIndex numberIndex = deckModel->index(matches[0].row(), 0);
const QModelIndex numberIndex = deckModel->index(matches[0].row(), 0, zoneRoot);
const int count = deckModel->data(numberIndex, Qt::EditRole).toInt();
deckModel->setData(numberIndex, count + 1, Qt::EditRole);
}
}
void WndDeckEditor::actAddCard()
{
addCardHelper(0);
}
void WndDeckEditor::actAddCardToSideboard()
{
addCardHelper(1);
}
void WndDeckEditor::actRemoveCard()
{
const QModelIndex currentIndex = deckView->selectionModel()->currentIndex();
if (!currentIndex.isValid())
return;
deckModel->removeRow(currentIndex.row());
deckModel->removeRow(currentIndex.row(), currentIndex.parent());
}
void WndDeckEditor::actIncrement()
@ -180,7 +198,7 @@ void WndDeckEditor::actIncrement()
const QModelIndex currentIndex = deckView->selectionModel()->currentIndex();
if (!currentIndex.isValid())
return;
const QModelIndex numberIndex = deckModel->index(currentIndex.row(), 0);
const QModelIndex numberIndex = currentIndex.sibling(currentIndex.row(), 0);
const int count = deckModel->data(numberIndex, Qt::EditRole).toInt();
deckModel->setData(numberIndex, count + 1, Qt::EditRole);
}
@ -190,10 +208,10 @@ void WndDeckEditor::actDecrement()
const QModelIndex currentIndex = deckView->selectionModel()->currentIndex();
if (!currentIndex.isValid())
return;
const QModelIndex numberIndex = deckModel->index(currentIndex.row(), 0);
const QModelIndex numberIndex = currentIndex.sibling(currentIndex.row(), 0);
const int count = deckModel->data(numberIndex, Qt::EditRole).toInt();
if (count == 1)
deckModel->removeRow(currentIndex.row());
deckModel->removeRow(currentIndex.row(), currentIndex.parent());
else
deckModel->setData(numberIndex, count - 1, Qt::EditRole);
}

View file

@ -25,10 +25,13 @@ private slots:
void actSaveDeckAs();
void actAddCard();
void actAddCardToSideboard();
void actRemoveCard();
void actIncrement();
void actDecrement();
private:
void addCardHelper(int baseRow);
QString lastFileName;
DeckList::FileFormat lastFileFormat;
CardDatabase *db;
@ -42,7 +45,7 @@ private:
QMenu *deckMenu;
QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs;
QAction *aAddCard, *aRemoveCard, *aIncrement, *aDecrement;
QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement;
public:
WndDeckEditor(CardDatabase *_db, QWidget *parent = 0);
~WndDeckEditor();