diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index a3cba262..c9d5f600 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -6,11 +6,13 @@ TEMPLATE = app TARGET = DEPENDPATH += . src INCLUDEPATH += . src +MOC_DIR = build +OBJECTS_DIR = build QT += network #QT += opengl #QTPLUGIN += qjpeg # Input -HEADERS += src/counter.h src/dlg_games.h src/dlg_creategame.h src/dlg_connect.h src/gamesmodel.h src/client.h src/window_main.h src/servergame.h src/servereventdata.h src/serverresponse.h src/pendingcommand.h src/zonelist.h src/cardzone.h src/player.h src/cardlist.h src/carditem.h src/tablezone.h src/handzone.h src/playerlist.h src/game.h src/carddatabase.h src/gameview.h src/decklistmodel.h src/dlg_startgame.h src/cardinfowidget.h src/messagelogwidget.h src/serverzonecard.h src/zoneviewzone.h src/zoneviewwidget.h src/libraryzone.h src/gravezone.h src/rfgzone.h src/sideboardzone.h src/carddragitem.h src/zoneviewlayout.h src/playerarea.h src/carddatabasemodel.h src/window_deckeditor.h -SOURCES += src/counter.cpp src/dlg_games.cpp src/dlg_creategame.cpp src/dlg_connect.cpp src/client.cpp src/main.cpp src/window_main.cpp src/servereventdata.cpp src/gamesmodel.cpp src/player.cpp src/cardzone.cpp src/zonelist.cpp src/cardlist.cpp src/carditem.cpp src/tablezone.cpp src/handzone.cpp src/playerlist.cpp src/game.cpp src/carddatabase.cpp src/gameview.cpp src/decklistmodel.cpp src/dlg_startgame.cpp src/cardinfowidget.cpp src/messagelogwidget.cpp src/zoneviewzone.cpp src/zoneviewwidget.cpp src/libraryzone.cpp src/gravezone.cpp src/rfgzone.cpp src/sideboardzone.cpp src/carddragitem.cpp src/zoneviewlayout.cpp src/playerarea.cpp src/carddatabasemodel.cpp src/window_deckeditor.cpp +HEADERS += src/counter.h src/dlg_games.h src/dlg_creategame.h src/dlg_connect.h src/gamesmodel.h src/client.h src/window_main.h src/servergame.h src/servereventdata.h src/serverresponse.h src/pendingcommand.h src/zonelist.h src/cardzone.h src/player.h src/cardlist.h src/carditem.h src/tablezone.h src/handzone.h src/playerlist.h src/game.h src/carddatabase.h src/gameview.h src/decklistmodel.h src/dlg_startgame.h src/cardinfowidget.h src/messagelogwidget.h src/serverzonecard.h src/zoneviewzone.h src/zoneviewwidget.h src/libraryzone.h src/gravezone.h src/rfgzone.h src/sideboardzone.h src/carddragitem.h src/zoneviewlayout.h src/playerarea.h src/carddatabasemodel.h src/window_deckeditor.h src/decklist.h +SOURCES += src/counter.cpp src/dlg_games.cpp src/dlg_creategame.cpp src/dlg_connect.cpp src/client.cpp src/main.cpp src/window_main.cpp src/servereventdata.cpp src/gamesmodel.cpp src/player.cpp src/cardzone.cpp src/zonelist.cpp src/cardlist.cpp src/carditem.cpp src/tablezone.cpp src/handzone.cpp src/playerlist.cpp src/game.cpp src/carddatabase.cpp src/gameview.cpp src/decklistmodel.cpp src/dlg_startgame.cpp src/cardinfowidget.cpp src/messagelogwidget.cpp src/zoneviewzone.cpp src/zoneviewwidget.cpp src/libraryzone.cpp src/gravezone.cpp src/rfgzone.cpp src/sideboardzone.cpp src/carddragitem.cpp src/zoneviewlayout.cpp src/playerarea.cpp src/carddatabasemodel.cpp src/window_deckeditor.cpp src/decklist.cpp diff --git a/cockatrice/src/decklist.cpp b/cockatrice/src/decklist.cpp new file mode 100644 index 00000000..14e28185 --- /dev/null +++ b/cockatrice/src/decklist.cpp @@ -0,0 +1,222 @@ +#include +#include +#include +#include +#include +#include "decklist.h" +#include "carddatabase.h" + +DeckList::DeckList(CardDatabase *_db) + : db(_db) +{ + +} + +DeckList::~DeckList() +{ + cleanList(); +} + +bool DeckList::loadFromFile_Native(QIODevice *device) +{ + QXmlStreamReader xml(device); + while (!xml.atEnd()) { + if (xml.readNext() == QXmlStreamReader::StartElement) { + if (xml.name() != "cockatrice_deck") + return false; + while (!xml.atEnd()) { + if (xml.readNext() == QXmlStreamReader::EndElement) + break; + if (xml.name() == "deckname") + name = xml.readElementText(); + else if (xml.name() == "comments") + comments = xml.readElementText(); + else if (xml.name() == "decklist") { + 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)); + while (!xml.atEnd()) + if (xml.readNext() == QXmlStreamReader::EndElement) + break; + } + } + } + } + } + } + return true; +} + +bool DeckList::saveToFile_Native(QIODevice *device) +{ + QXmlStreamWriter xml(device); + xml.setAutoFormatting(true); + xml.writeStartDocument(); + + xml.writeStartElement("cockatrice_deck"); + xml.writeAttribute("version", "1"); + 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()); + } + xml.writeEndElement(); // decklist + + xml.writeEndElement(); // cockatrice_deck + + xml.writeEndDocument(); + return true; +} + +bool DeckList::loadFromFile_Plain(QIODevice *device) +{ + QTextStream in(device); + while (!in.atEnd()) { + QString line = in.readLine().simplified(); + if (line.startsWith("//")) + continue; + + bool isSideboard = false; + if (line.startsWith("SB:", Qt::CaseInsensitive)) { + line = line.mid(3).trimmed(); + isSideboard = true; + } + + // Filter out MWS edition symbols and basic land extras + QRegExp rx("\\[.*\\]"); + line.remove(rx); + rx.setPattern("\\(.*\\)"); + line.remove(rx); + line = line.simplified(); + + int i = line.indexOf(' '); + bool ok; + int number = line.left(i).toInt(&ok); + if (!ok) + continue; + append(new DecklistRow(number, line.mid(i + 1), isSideboard)); + } + return true; +} + +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()); + } + return true; +} + +bool DeckList::loadFromFile(const QString &fileName, FileFormat fmt) +{ + QFile file(fileName); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + return false; + cleanList(); + + bool result = false; + switch (fmt) { + case PlainTextFormat: result = loadFromFile_Plain(&file); break; + case CockatriceFormat: result = loadFromFile_Native(&file); break; + } + if (result) + cacheCardPictures(); + return result; +} + +const QStringList DeckList::fileNameFilters = QStringList() + << QObject::tr("Cockatrice decks (*.cod)") + << QObject::tr("Plain text decks (*.dec *.mwDeck)") + << QObject::tr("All files (*.*)"); + +bool DeckList::saveToFile(const QString &fileName, FileFormat fmt) +{ + QFile file(fileName); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) + return false; + + bool result = false; + switch (fmt) { + case PlainTextFormat: result = saveToFile_Plain(&file); break; + case CockatriceFormat: result = saveToFile_Native(&file); break; + } + return result; +} + +bool DeckList::loadDialog(QWidget *parent) +{ + QFileDialog dialog(parent); + dialog.setNameFilters(fileNameFilters); + if (!dialog.exec()) + return false; + + QString fileName = dialog.selectedFiles().at(0); + FileFormat fmt; + switch (fileNameFilters.indexOf(dialog.selectedNameFilter())) { + case 0: fmt = CockatriceFormat; break; + case 1: fmt = PlainTextFormat; break; + default: fmt = PlainTextFormat; break; + } + + if (loadFromFile(fileName, fmt)) { + lastFileName = fileName; + lastFileFormat = fmt; + return true; + } + return false; +} + +bool DeckList::saveDialog(QWidget *parent) +{ + QFileDialog dialog(parent); + dialog.setAcceptMode(QFileDialog::AcceptSave); + dialog.setConfirmOverwrite(true); + dialog.setDefaultSuffix("cod"); + dialog.setNameFilters(fileNameFilters); + if (!dialog.exec()) + return false; + + QString fileName = dialog.selectedFiles().at(0); + DeckList::FileFormat fmt; + switch (fileNameFilters.indexOf(dialog.selectedNameFilter())) { + case 0: fmt = DeckList::CockatriceFormat; break; + case 1: fmt = DeckList::PlainTextFormat; break; + default: fmt = DeckList::PlainTextFormat; break; + } + + if (saveToFile(fileName, fmt)) { + lastFileName = fileName; + lastFileFormat = fmt; + return true; + } + return false; +} + +void DeckList::cacheCardPictures() +{ + for (int i = 0; i < size(); i++) + db->getCard(at(i)->getCard())->getPixmap(); +} + +void DeckList::cleanList() +{ + for (int i = 0; i < size(); i++) + delete at(i); + clear(); +} diff --git a/cockatrice/src/decklist.h b/cockatrice/src/decklist.h new file mode 100644 index 00000000..c9fa5985 --- /dev/null +++ b/cockatrice/src/decklist.h @@ -0,0 +1,55 @@ +#ifndef DECKLIST_H +#define DECKLIST_H + +#include +#include + +class CardDatabase; +class QIODevice; + +class DecklistRow { +private: + int number; + QString card; + bool sideboard; +public: + DecklistRow(int _number, const QString &_card, bool _sideboard) : number(_number), card(_card), sideboard(_sideboard) { } + int getNumber() const { return number; } + QString getCard() const { return card; } + bool isSideboard() const { return sideboard; } +}; + +class DeckList : public QList { +public: + enum FileFormat { PlainTextFormat, CockatriceFormat }; +private: + static const QStringList fileNameFilters; + void cacheCardPictures(); + CardDatabase *db; + QString name, comments; + QString lastFileName; + FileFormat lastFileFormat; +public: + + DeckList(CardDatabase *_db); + ~DeckList(); + void setName(const QString &_name) { name = _name; } + QString getName() const { return name; } + void setComments(const QString &_comments) { comments = _comments; } + QString getComments() const { return comments; } + QString getLastFileName() const { return lastFileName; } + FileFormat getLastFileFormat() const { return lastFileFormat; } + + bool loadFromFile_Native(QIODevice *device); + bool saveToFile_Native(QIODevice *device); + bool loadFromFile_Plain(QIODevice *device); + bool saveToFile_Plain(QIODevice *device); + bool loadFromFile(const QString &fileName, FileFormat fmt); + bool saveToFile(const QString &fileName, FileFormat fmt); + bool loadDialog(QWidget *parent = 0); + bool saveDialog(QWidget *parent = 0); + + void cleanList(); +}; + +#endif diff --git a/cockatrice/src/decklistmodel.cpp b/cockatrice/src/decklistmodel.cpp index 83de1ba2..437d7e40 100644 --- a/cockatrice/src/decklistmodel.cpp +++ b/cockatrice/src/decklistmodel.cpp @@ -6,19 +6,18 @@ DeckListModel::DeckListModel(CardDatabase *_db, QObject *parent) : QAbstractListModel(parent), db(_db) { - + deckList = new DeckList(db); } DeckListModel::~DeckListModel() { - qDebug("DeckListModel destructor"); - cleanList(); + delete deckList; } int DeckListModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); - return deckList.size(); + return deckList->size(); } int DeckListModel::columnCount(const QModelIndex &parent) const @@ -31,13 +30,13 @@ QVariant DeckListModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); - if ((index.row() >= deckList.size()) || (index.column() >= 2)) + if ((index.row() >= deckList->size()) || (index.column() >= 2)) return QVariant(); if (role != Qt::DisplayRole) return QVariant(); - DecklistRow *r = deckList.at(index.row()); + DecklistRow *r = deckList->at(index.row()); switch (index.column()) { case 0: return r->getNumber(); case 1: return r->getCard(); @@ -60,66 +59,13 @@ QVariant DeckListModel::headerData(int section, Qt::Orientation orientation, int void DeckListModel::cleanList() { - QListIterator i(deckList); - while (i.hasNext()) - delete i.next(); - deckList.clear(); + deckList->cleanList(); reset(); } -bool DeckListModel::loadFromFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) - return false; - QTextStream in(&file); - cleanList(); - while (!in.atEnd()) { - QString line = in.readLine().simplified(); - bool isSideboard = false; - if (line.startsWith("SB:", Qt::CaseInsensitive)) { - line = line.mid(3).trimmed(); - isSideboard = true; - } - int i = line.indexOf(' '); - bool ok; - int number = line.left(i).toInt(&ok); - if (!ok) - continue; - DecklistRow *row = new DecklistRow(number, line.mid(i + 1), isSideboard); - deckList << row; - } - cacheCardPictures(); - reset(); - return true; -} - -bool DeckListModel::saveToFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) - return false; - QTextStream out(&file); - QListIterator i(deckList); - while (i.hasNext()) { - DecklistRow *r = i.next(); - out << QString("%1%2 %3\n").arg(r->isSideboard() ? "SB: " : "").arg(r->getNumber()).arg(r->getCard()); - } - return true; -} - DecklistRow *DeckListModel::getRow(int row) const { - if (row >= deckList.size()) + if (row >= deckList->size()) return 0; - return deckList.at(row); -} - -void DeckListModel::cacheCardPictures() -{ - QListIterator i(deckList); - while (i.hasNext()) { - DecklistRow *r = i.next(); - db->getCard(r->getCard())->getPixmap(); - } + return deckList->at(row); } diff --git a/cockatrice/src/decklistmodel.h b/cockatrice/src/decklistmodel.h index b5a7320a..9d7eea49 100644 --- a/cockatrice/src/decklistmodel.h +++ b/cockatrice/src/decklistmodel.h @@ -3,21 +3,10 @@ #include #include +#include "decklist.h" class CardDatabase; -class DecklistRow { -private: - int number; - QString card; - bool sideboard; -public: - DecklistRow(int _number, const QString &_card, bool _sideboard) : number(_number), card(_card), sideboard(_sideboard) { } - int getNumber() const { return number; } - QString getCard() const { return card; } - bool isSideboard() const { return sideboard; } -}; - class DeckListModel : public QAbstractListModel { Q_OBJECT public: @@ -27,14 +16,14 @@ public: 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; - bool loadFromFile(const QString &fileName); - bool saveToFile(const QString &fileName); DecklistRow *getRow(int row) const; void cleanList(); + DeckList *getDeckList() const { return deckList; } + bool loadFromFile(const QString &fileName, DeckList::FileFormat fmt); + bool saveToFile(const QString &fileName, DeckList::FileFormat fmt); private: CardDatabase *db; - QList deckList; - void cacheCardPictures(); + DeckList *deckList; }; #endif diff --git a/cockatrice/src/dlg_startgame.cpp b/cockatrice/src/dlg_startgame.cpp index 2edad699..7113cb6e 100644 --- a/cockatrice/src/dlg_startgame.cpp +++ b/cockatrice/src/dlg_startgame.cpp @@ -35,11 +35,10 @@ DlgStartGame::DlgStartGame(CardDatabase *_db, QWidget *parent) void DlgStartGame::actLoad() { - QString fileName = QFileDialog::getOpenFileName(this, tr("Load deck"), QString(), tr("Deck files (*.dec)")); - if (fileName.isEmpty()) + if (!tableModel->getDeckList()->loadDialog(this)) return; - tableModel->loadFromFile(fileName); + tableView->reset(); emit newDeckLoaded(getDeckList()); } diff --git a/cockatrice/src/window_deckeditor.cpp b/cockatrice/src/window_deckeditor.cpp index 2acb8340..bd6ff81e 100644 --- a/cockatrice/src/window_deckeditor.cpp +++ b/cockatrice/src/window_deckeditor.cpp @@ -79,12 +79,12 @@ void WndDeckEditor::actNewDeck() void WndDeckEditor::actLoadDeck() { - QString fileName = QFileDialog::getOpenFileName(this, tr("Load deck"), QString(), tr("Deck files (*.dec)")); - if (fileName.isEmpty()) - return; - - if (deckModel->loadFromFile(fileName)) - lastFileName = fileName; + DeckList *l = deckModel->getDeckList(); + if (l->loadDialog(this)) { + lastFileName = l->getLastFileName(); + lastFileFormat = l->getLastFileFormat(); + deckView->reset(); + } } void WndDeckEditor::actSaveDeck() @@ -92,16 +92,15 @@ void WndDeckEditor::actSaveDeck() if (lastFileName.isEmpty()) actSaveDeckAs(); else - deckModel->saveToFile(lastFileName); + deckModel->getDeckList()->saveToFile(lastFileName, lastFileFormat); +; } void WndDeckEditor::actSaveDeckAs() { - QString fileName = QFileDialog::getSaveFileName(this, tr("Save deck as"), QString(), tr("Deck files (*.dec)")); - if (fileName.isEmpty()) - return; - if (!fileName.endsWith(".dec")) - fileName.append(".dec"); - if (deckModel->saveToFile(fileName)) - lastFileName = fileName; + DeckList *l = deckModel->getDeckList(); + if (l->saveDialog(this)) { + lastFileName = l->getLastFileName(); + lastFileFormat = l->getLastFileFormat(); + } } diff --git a/cockatrice/src/window_deckeditor.h b/cockatrice/src/window_deckeditor.h index 60765991..82f32dd1 100644 --- a/cockatrice/src/window_deckeditor.h +++ b/cockatrice/src/window_deckeditor.h @@ -3,6 +3,7 @@ #include #include +#include "decklist.h" class CardDatabase; class CardDatabaseModel; @@ -22,6 +23,7 @@ private slots: void actSaveDeckAs(); private: QString lastFileName; + DeckList::FileFormat lastFileFormat; CardDatabase *db; CardDatabaseModel *databaseModel;