From e6d616242662cd322b8cab18799ec4ba802bffc8 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 4 Apr 2009 19:51:23 +0200 Subject: [PATCH] started implementing a simple deck editor --- cockatrice/cockatrice.pro | 4 +- cockatrice/src/carddatabase.cpp | 11 ++ cockatrice/src/carddatabase.h | 1 + cockatrice/src/carddatabasemodel.cpp | 87 ++++++++++++++ cockatrice/src/carddatabasemodel.h | 23 ++++ cockatrice/src/decklistmodel.cpp | 39 ++++++- cockatrice/src/decklistmodel.h | 14 ++- cockatrice/src/dlg_startgame.cpp | 18 +-- cockatrice/src/main.cpp | 2 +- cockatrice/src/window_deckeditor.cpp | 106 ++++++++++++++++++ cockatrice/src/window_deckeditor.h | 39 +++++++ .../src/{window.cpp => window_main.cpp} | 13 ++- cockatrice/src/{window.h => window_main.h} | 3 +- 13 files changed, 333 insertions(+), 27 deletions(-) create mode 100644 cockatrice/src/carddatabasemodel.cpp create mode 100644 cockatrice/src/carddatabasemodel.h create mode 100644 cockatrice/src/window_deckeditor.cpp create mode 100644 cockatrice/src/window_deckeditor.h rename cockatrice/src/{window.cpp => window_main.cpp} (95%) rename cockatrice/src/{window.h => window_main.h} (98%) diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index 3d98d672..5edf5941 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -12,5 +12,5 @@ QT += network #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.h src/servergame.h src/servereventdata.h src/serverresponse.h src/pendingcommand.h src/zonelist.h src/counterlist.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/zoneclosebutton.h src/zoneviewlayout.h src/playerarea.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.cpp src/servereventdata.cpp src/gamesmodel.cpp src/player.cpp src/cardzone.cpp src/zonelist.cpp src/counterlist.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/zoneclosebutton.cpp src/zoneviewlayout.cpp src/playerarea.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/counterlist.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/zoneclosebutton.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/counterlist.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/zoneclosebutton.cpp src/zoneviewlayout.cpp src/playerarea.cpp src/carddatabasemodel.cpp src/window_deckeditor.cpp diff --git a/cockatrice/src/carddatabase.cpp b/cockatrice/src/carddatabase.cpp index 8eb325c6..5d7062fe 100644 --- a/cockatrice/src/carddatabase.cpp +++ b/cockatrice/src/carddatabase.cpp @@ -97,6 +97,17 @@ CardInfo *CardDatabase::getCard(const QString &cardName) } } +QListCardDatabase::getCardList() +{ + QList cardList; + QHashIterator i(hash); + while (i.hasNext()) { + i.next(); + cardList.append(i.value()); + } + return cardList; +} + void CardDatabase::importOracle() { clear(); diff --git a/cockatrice/src/carddatabase.h b/cockatrice/src/carddatabase.h index 8ca624be..d078cdb5 100644 --- a/cockatrice/src/carddatabase.h +++ b/cockatrice/src/carddatabase.h @@ -43,6 +43,7 @@ public: ~CardDatabase(); void clear(); CardInfo *getCard(const QString &cardName = QString()); + QList getCardList(); void importOracle(); int loadFromFile(const QString &fileName); bool saveToFile(const QString &fileName); diff --git a/cockatrice/src/carddatabasemodel.cpp b/cockatrice/src/carddatabasemodel.cpp new file mode 100644 index 00000000..451b3d1a --- /dev/null +++ b/cockatrice/src/carddatabasemodel.cpp @@ -0,0 +1,87 @@ +#include "carddatabasemodel.h" + +CardDatabaseModel::CardDatabaseModel(CardDatabase *_db, QObject *parent) + : QAbstractListModel(parent), db(_db) +{ + cardList = db->getCardList(); +} + +CardDatabaseModel::~CardDatabaseModel() +{ + +} + +int CardDatabaseModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return cardList.size(); +} + +int CardDatabaseModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return 5; +} + +QVariant CardDatabaseModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + if ((index.row() >= cardList.size()) || (index.column() >= 5)) + return QVariant(); + if (role != Qt::DisplayRole) + return QVariant(); + + CardInfo *card = cardList.at(index.row()); + switch (index.column()){ + case 0: return card->getName(); + case 1: return card->getEditions().join(", "); + case 2: return card->getManacost(); + case 3: return card->getCardType(); + case 4: return card->getPowTough(); + default: return QVariant(); + } +} + +QVariant CardDatabaseModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role != Qt::DisplayRole) + return QVariant(); + if (orientation != Qt::Horizontal) + return QVariant(); + switch (section) { + case 0: return QString(tr("Name")); + case 1: return QString(tr("Sets")); + case 2: return QString(tr("Mana cost")); + case 3: return QString(tr("Card type")); + case 4: return QString(tr("P/T")); + default: return QVariant(); + } +} + +class CardInfoCompare { +private: + int column; + Qt::SortOrder order; +public: + CardInfoCompare(int _column, Qt::SortOrder _order) : column(_column), order(_order) { } + bool operator()(CardInfo *a, CardInfo *b) const + { + bool result; + switch (column) { + case 0: result = (a->getName() < b->getName()); break; + case 1: result = (a->getEditions().join("") < b->getEditions().join("")); break; + case 2: result = (a->getManacost() < b->getManacost()); break; + case 3: result = (a->getCardType() < b->getCardType()); break; + case 4: result = (a->getPowTough() < b->getPowTough()); break; + default: result = false; + } + return (order == Qt::AscendingOrder) ^ result; + } +}; + +void CardDatabaseModel::sort(int column, Qt::SortOrder order) +{ + CardInfoCompare cmp(column, order); + qSort(cardList.begin(), cardList.end(), cmp); +} diff --git a/cockatrice/src/carddatabasemodel.h b/cockatrice/src/carddatabasemodel.h new file mode 100644 index 00000000..5983291d --- /dev/null +++ b/cockatrice/src/carddatabasemodel.h @@ -0,0 +1,23 @@ +#ifndef CARDDATABASEMODEL_H +#define CARDDATABASEMODEL_H + +#include +#include +#include "carddatabase.h" + +class CardDatabaseModel : public QAbstractListModel { + Q_OBJECT +public: + CardDatabaseModel(CardDatabase *_db, QObject *parent = 0); + ~CardDatabaseModel(); + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + QVariant data(const QModelIndex &index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); +private: + QList cardList; + CardDatabase *db; +}; + +#endif diff --git a/cockatrice/src/decklistmodel.cpp b/cockatrice/src/decklistmodel.cpp index e88d5273..c9edaa4e 100644 --- a/cockatrice/src/decklistmodel.cpp +++ b/cockatrice/src/decklistmodel.cpp @@ -1,6 +1,13 @@ -#include "decklistmodel.h" #include #include +#include "decklistmodel.h" +#include "carddatabase.h" + +DeckListModel::DeckListModel(CardDatabase *_db, QObject *parent) + : QAbstractListModel(parent), db(_db) +{ + +} DeckListModel::~DeckListModel() { @@ -57,13 +64,14 @@ void DeckListModel::cleanList() while (i.hasNext()) delete i.next(); deckList.clear(); + reset(); } -void DeckListModel::loadFromFile(const QString &fileName) +bool DeckListModel::loadFromFile(const QString &fileName) { QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) - return; + return false; QTextStream in(&file); cleanList(); while (!in.atEnd()) { @@ -81,7 +89,23 @@ void DeckListModel::loadFromFile(const QString &fileName) 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 @@ -90,3 +114,12 @@ DecklistRow *DeckListModel::getRow(int row) const return 0; return deckList.at(row); } + +void DeckListModel::cacheCardPictures() +{ + QListIterator i(deckList); + while (i.hasNext()) { + DecklistRow *r = i.next(); + db->getCard(r->getCard())->getPixmap(); + } +} diff --git a/cockatrice/src/decklistmodel.h b/cockatrice/src/decklistmodel.h index 384fe6f6..b5a7320a 100644 --- a/cockatrice/src/decklistmodel.h +++ b/cockatrice/src/decklistmodel.h @@ -4,6 +4,8 @@ #include #include +class CardDatabase; + class DecklistRow { private: int number; @@ -19,18 +21,20 @@ public: class DeckListModel : public QAbstractListModel { Q_OBJECT public: - DeckListModel(QObject *parent = 0) - : QAbstractListModel(parent) { } + DeckListModel(CardDatabase *_db, QObject *parent = 0); ~DeckListModel(); int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; QVariant data(const QModelIndex &index, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - void loadFromFile(const QString &fileName); + bool loadFromFile(const QString &fileName); + bool saveToFile(const QString &fileName); DecklistRow *getRow(int row) const; -private: - QList deckList; void cleanList(); +private: + CardDatabase *db; + QList deckList; + void cacheCardPictures(); }; #endif diff --git a/cockatrice/src/dlg_startgame.cpp b/cockatrice/src/dlg_startgame.cpp index 0dce20ef..2edad699 100644 --- a/cockatrice/src/dlg_startgame.cpp +++ b/cockatrice/src/dlg_startgame.cpp @@ -8,7 +8,7 @@ DlgStartGame::DlgStartGame(CardDatabase *_db, QWidget *parent) : QDialog(parent), db(_db) { tableView = new QTreeView; - tableModel = new DeckListModel(this); + tableModel = new DeckListModel(db, this); tableView->setModel(tableModel); loadButton = new QPushButton(tr("&Load...")); @@ -36,19 +36,9 @@ 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()) - tableModel->loadFromFile(fileName); - - // Precache card pictures - for (int i = 0; i < tableModel->rowCount(); i++) { - QString cardName = tableModel->getRow(i)->getCard(); - CardInfo *card = db->getCard(cardName); - if (!card) { - qDebug(QString("Invalid card: %1").arg(cardName).toLatin1()); - continue; - } - card->getPixmap(); - } + if (fileName.isEmpty()) + return; + tableModel->loadFromFile(fileName); emit newDeckLoaded(getDeckList()); } diff --git a/cockatrice/src/main.cpp b/cockatrice/src/main.cpp index f750570c..4194032f 100644 --- a/cockatrice/src/main.cpp +++ b/cockatrice/src/main.cpp @@ -22,7 +22,7 @@ #include #include #include -#include "window.h" +#include "window_main.h" #include //Q_IMPORT_PLUGIN(qjpeg) diff --git a/cockatrice/src/window_deckeditor.cpp b/cockatrice/src/window_deckeditor.cpp new file mode 100644 index 00000000..827be55a --- /dev/null +++ b/cockatrice/src/window_deckeditor.cpp @@ -0,0 +1,106 @@ +#include +#include "window_deckeditor.h" +#include "carddatabase.h" +#include "carddatabasemodel.h" +#include "decklistmodel.h" +#include "cardinfowidget.h" + +WndDeckEditor::WndDeckEditor(CardDatabase *_db, QWidget *parent) + : QMainWindow(parent), db(_db) +{ + databaseModel = new CardDatabaseModel(db); + databaseView = new QTreeView(); + databaseView->setModel(databaseModel); + databaseView->setSortingEnabled(true); + connect(databaseView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(updateCardInfoLeft(const QModelIndex &, const QModelIndex &))); + + deckModel = new DeckListModel(db, this); + deckView = new QTreeView(); + deckView->setModel(deckModel); +// deckView->setSortingEnabled(true); + connect(deckView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(updateCardInfoRight(const QModelIndex &, const QModelIndex &))); + + cardInfo = new CardInfoWidget(db); + + QVBoxLayout *middleFrame = new QVBoxLayout; + middleFrame->addWidget(cardInfo); + middleFrame->addStretch(); + + QHBoxLayout *mainLayout = new QHBoxLayout; + mainLayout->addWidget(databaseView); + mainLayout->addLayout(middleFrame); + mainLayout->addWidget(deckView); + + QWidget *centralWidget = new QWidget; + centralWidget->setLayout(mainLayout); + setCentralWidget(centralWidget); + + setWindowTitle(tr("Card database")); + + aNewDeck = new QAction(tr("&New deck"), this); + connect(aNewDeck, SIGNAL(triggered()), this, SLOT(actNewDeck())); + aLoadDeck = new QAction(tr("&Load deck..."), this); + aLoadDeck->setShortcut(tr("Ctrl+L")); + connect(aLoadDeck, SIGNAL(triggered()), this, SLOT(actLoadDeck())); + aSaveDeck = new QAction(tr("&Save deck"), this); + aSaveDeck->setShortcut(tr("Ctrl+S")); + connect(aSaveDeck, SIGNAL(triggered()), this, SLOT(actSaveDeck())); + aSaveDeckAs = new QAction(tr("&Save deck as..."), this); + connect(aSaveDeckAs, SIGNAL(triggered()), this, SLOT(actSaveDeckAs())); + + deckMenu = menuBar()->addMenu(tr("Deck")); + deckMenu->addAction(aNewDeck); + deckMenu->addAction(aLoadDeck); + deckMenu->addAction(aSaveDeck); + deckMenu->addAction(aSaveDeckAs); +} + +WndDeckEditor::~WndDeckEditor() +{ + +} + +void WndDeckEditor::updateCardInfoLeft(const QModelIndex ¤t, const QModelIndex &previous) +{ + Q_UNUSED(previous); + cardInfo->setCard(current.sibling(current.row(), 0).data().toString()); +} + +void WndDeckEditor::updateCardInfoRight(const QModelIndex ¤t, const QModelIndex &previous) +{ + Q_UNUSED(previous); + cardInfo->setCard(current.sibling(current.row(), 1).data().toString()); +} + +void WndDeckEditor::actNewDeck() +{ + deckModel->cleanList(); + lastFileName = QString(); +} + +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; +} + +void WndDeckEditor::actSaveDeck() +{ + if (lastFileName.isEmpty()) + actSaveDeckAs(); + else + deckModel->saveToFile(lastFileName); +} + +void WndDeckEditor::actSaveDeckAs() +{ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save deck as"), QString(), tr("Deck files (*.dec)")); + if (!fileName.endsWith(".dec")) + fileName.append(".dec"); + if (deckModel->saveToFile(fileName)) + lastFileName = fileName; +} diff --git a/cockatrice/src/window_deckeditor.h b/cockatrice/src/window_deckeditor.h new file mode 100644 index 00000000..60765991 --- /dev/null +++ b/cockatrice/src/window_deckeditor.h @@ -0,0 +1,39 @@ +#ifndef WINDOW_DECKEDITOR_H +#define WINDOW_DECKEDITOR_H + +#include +#include + +class CardDatabase; +class CardDatabaseModel; +class DeckListModel; +class QTreeView; +class CardInfoWidget; + +class WndDeckEditor : public QMainWindow { + Q_OBJECT +private slots: + void updateCardInfoLeft(const QModelIndex ¤t, const QModelIndex &previous); + void updateCardInfoRight(const QModelIndex ¤t, const QModelIndex &previous); + + void actNewDeck(); + void actLoadDeck(); + void actSaveDeck(); + void actSaveDeckAs(); +private: + QString lastFileName; + CardDatabase *db; + + CardDatabaseModel *databaseModel; + DeckListModel *deckModel; + QTreeView *databaseView, *deckView; + CardInfoWidget *cardInfo; + + QMenu *deckMenu; + QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs; +public: + WndDeckEditor(CardDatabase *_db, QWidget *parent = 0); + ~WndDeckEditor(); +}; + +#endif diff --git a/cockatrice/src/window.cpp b/cockatrice/src/window_main.cpp similarity index 95% rename from cockatrice/src/window.cpp rename to cockatrice/src/window_main.cpp index d36b8e6c..9d628028 100644 --- a/cockatrice/src/window.cpp +++ b/cockatrice/src/window_main.cpp @@ -20,9 +20,10 @@ #include //#include -#include "window.h" +#include "window_main.h" #include "dlg_connect.h" #include "dlg_games.h" +#include "window_deckeditor.h" #include "cardinfowidget.h" #include "messagelogwidget.h" @@ -105,6 +106,12 @@ void MainWindow::actLeaveGame() aGames->setEnabled(true); } +void MainWindow::actDeckEditor() +{ + WndDeckEditor *deckEditor = new WndDeckEditor(db, this); + deckEditor->show(); +} + void MainWindow::actExit() { close(); @@ -170,6 +177,8 @@ void MainWindow::createActions() aLeaveGame = new QAction(tr("&Leave game"), this); aLeaveGame->setEnabled(false); connect(aLeaveGame, SIGNAL(triggered()), this, SLOT(actLeaveGame())); + aDeckEditor = new QAction(tr("&Deck editor"), this); + connect(aDeckEditor, SIGNAL(triggered()), this, SLOT(actDeckEditor())); aExit = new QAction(tr("&Exit"), this); connect(aExit, SIGNAL(triggered()), this, SLOT(actExit())); } @@ -184,6 +193,8 @@ void MainWindow::createMenus() gameMenu->addAction(aRestartGame); gameMenu->addAction(aLeaveGame); gameMenu->addSeparator(); + gameMenu->addAction(aDeckEditor); + gameMenu->addSeparator(); gameMenu->addAction(aExit); actionsMenu = menuBar()->addMenu(tr("&Actions")); diff --git a/cockatrice/src/window.h b/cockatrice/src/window_main.h similarity index 98% rename from cockatrice/src/window.h rename to cockatrice/src/window_main.h index 33650217..bd70121a 100644 --- a/cockatrice/src/window.h +++ b/cockatrice/src/window_main.h @@ -54,6 +54,7 @@ private slots: void actDisconnect(); void actGames(); void actLeaveGame(); + void actDeckEditor(); void actExit(); void updateSceneSize(); @@ -64,7 +65,7 @@ private: void createActions(); void createMenus(); QMenu *gameMenu, *actionsMenu, *cardMenu; - QAction *aConnect, *aDisconnect, *aGames, *aRestartGame, *aLeaveGame, *aExit; + QAction *aConnect, *aDisconnect, *aGames, *aRestartGame, *aLeaveGame, *aDeckEditor, *aExit; CardInfoWidget *cardInfo; MessageLogWidget *messageLog;