diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro
index 7d84a228..d4133d4a 100644
--- a/cockatrice/cockatrice.pro
+++ b/cockatrice/cockatrice.pro
@@ -5,7 +5,7 @@ INCLUDEPATH += . src ../common
MOC_DIR = build
OBJECTS_DIR = build
RESOURCES = cockatrice.qrc
-QT += network svg multimedia
+QT += network script svg multimedia
HEADERS += src/abstractcounter.h \
src/counter_general.h \
@@ -71,6 +71,7 @@ HEADERS += src/abstractcounter.h \
src/localserverinterface.h \
src/localclient.h \
src/translation.h \
+ src/priceupdater.h \
src/soundengine.h \
../common/color.h \
../common/serializable_item.h \
@@ -154,6 +155,7 @@ SOURCES += src/abstractcounter.cpp \
src/localserver.cpp \
src/localserverinterface.cpp \
src/localclient.cpp \
+ src/priceupdater.cpp \
src/soundengine.cpp \
../common/serializable_item.cpp \
../common/decklist.cpp \
diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc
index d57e461e..b7517dab 100644
--- a/cockatrice/cockatrice.qrc
+++ b/cockatrice/cockatrice.qrc
@@ -23,6 +23,7 @@
resources/pencil.svg
resources/icon_search.svg
resources/icon_clearsearch.svg
+ resources/icon_update.png
resources/hr.jpg
resources/appicon.svg
resources/add_to_sideboard.svg
diff --git a/cockatrice/src/decklistmodel.cpp b/cockatrice/src/decklistmodel.cpp
index 1084f345..82a44326 100644
--- a/cockatrice/src/decklistmodel.cpp
+++ b/cockatrice/src/decklistmodel.cpp
@@ -10,6 +10,7 @@
#include "main.h"
#include "decklistmodel.h"
#include "carddatabase.h"
+#include "settingscache.h"
DeckListModel::DeckListModel(QObject *parent)
: QAbstractItemModel(parent)
@@ -65,12 +66,20 @@ int DeckListModel::rowCount(const QModelIndex &parent) const
return 0;
}
+int DeckListModel::columnCount(const QModelIndex &/*parent*/) const
+{
+ if (settingsCache->getPriceTagFeature())
+ return 3;
+ else
+ return 2;
+}
+
QVariant DeckListModel::data(const QModelIndex &index, int role) const
{
// debugIndexInfo("data", index);
if (!index.isValid())
return QVariant();
- if (index.column() >= 2)
+ if (index.column() >= columnCount())
return QVariant();
AbstractDecklistNode *temp = static_cast(index.internalPointer());
@@ -86,8 +95,9 @@ QVariant DeckListModel::data(const QModelIndex &index, int role) const
case Qt::DisplayRole:
case Qt::EditRole:
switch (index.column()) {
- case 0: return node->recursiveCount(true);
- case 1: return node->getVisibleName();
+ case 0: return node->recursiveCount(true);
+ case 1: return node->getVisibleName();
+ case 2: return QString().sprintf("$%.2f", node->recursivePrice(true));
default: return QVariant();
}
case Qt::BackgroundRole: {
@@ -101,8 +111,9 @@ QVariant DeckListModel::data(const QModelIndex &index, int role) const
case Qt::DisplayRole:
case Qt::EditRole: {
switch (index.column()) {
- case 0: return card->getNumber();
- case 1: return card->getName();
+ case 0: return card->getNumber();
+ case 1: return card->getName();
+ case 2: return QString().sprintf("$%.2f", card->getTotalPrice());
default: return QVariant();
}
}
@@ -119,9 +130,12 @@ QVariant DeckListModel::headerData(int section, Qt::Orientation orientation, int
{
if ((role != Qt::DisplayRole) || (orientation != Qt::Horizontal))
return QVariant();
+ if (section >= columnCount())
+ return QVariant();
switch (section) {
- case 0: return tr("Number");
- case 1: return tr("Card");
+ case 0: return tr("Number");
+ case 1: return tr("Card");
+ case 2: return tr("Price");
default: return QVariant();
}
}
@@ -174,8 +188,9 @@ bool DeckListModel::setData(const QModelIndex &index, const QVariant &value, int
return false;
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;
+ case 2: node->setPrice(value.toFloat()); break;
default: return false;
}
emitRecursiveUpdates(index);
@@ -300,7 +315,7 @@ void DeckListModel::setDeckList(DeckList *_deck)
void DeckListModel::printDeckListNode(QTextCursor *cursor, InnerDecklistNode *node)
{
- static const int totalColumns = 3;
+ const int totalColumns = settingsCache->getPriceTagFeature() ? 3 : 2;
if (node->height() == 1) {
QTextBlockFormat blockFormat;
@@ -308,13 +323,16 @@ void DeckListModel::printDeckListNode(QTextCursor *cursor, InnerDecklistNode *no
charFormat.setFontPointSize(11);
charFormat.setFontWeight(QFont::Bold);
cursor->insertBlock(blockFormat, charFormat);
- cursor->insertText(QString("%1: %2").arg(node->getVisibleName()).arg(node->recursiveCount(true)));
+ QString priceStr;
+ if (settingsCache->getPriceTagFeature())
+ priceStr = QString().sprintf(": $%.2f", node->recursivePrice(true));
+ cursor->insertText(QString("%1: %2").arg(node->getVisibleName()).arg(node->recursiveCount(true)).append(priceStr));
QTextTableFormat tableFormat;
tableFormat.setCellPadding(0);
tableFormat.setCellSpacing(0);
tableFormat.setBorder(0);
- QTextTable *table = cursor->insertTable(node->size() + 1, 2, tableFormat);
+ QTextTable *table = cursor->insertTable(node->size() + 1, totalColumns, tableFormat);
for (int i = 0; i < node->size(); i++) {
AbstractDecklistCardNode *card = dynamic_cast(node->at(i));
@@ -330,6 +348,13 @@ void DeckListModel::printDeckListNode(QTextCursor *cursor, InnerDecklistNode *no
cell.setFormat(cellCharFormat);
cellCursor = cell.firstCursorPosition();
cellCursor.insertText(card->getName());
+
+ if (settingsCache->getPriceTagFeature()) {
+ cell = table->cellAt(i, 2);
+ cell.setFormat(cellCharFormat);
+ cellCursor = cell.firstCursorPosition();
+ cellCursor.insertText(QString().sprintf("$%.2f ", card->getTotalPrice()));
+ }
}
} else if (node->height() == 2) {
QTextBlockFormat blockFormat;
@@ -338,7 +363,10 @@ void DeckListModel::printDeckListNode(QTextCursor *cursor, InnerDecklistNode *no
charFormat.setFontWeight(QFont::Bold);
cursor->insertBlock(blockFormat, charFormat);
- cursor->insertText(QString("%1: %2").arg(node->getVisibleName()).arg(node->recursiveCount(true)));
+ QString priceStr;
+ if (settingsCache->getPriceTagFeature())
+ priceStr = QString().sprintf(": $%.2f", node->recursivePrice(true));
+ cursor->insertText(QString("%1: %2").arg(node->getVisibleName()).arg(node->recursiveCount(true)).append(priceStr));
QTextTableFormat tableFormat;
tableFormat.setCellPadding(10);
@@ -391,3 +419,14 @@ void DeckListModel::printDeckList(QPrinter *printer)
doc.print(printer);
}
+
+void DeckListModel::pricesUpdated(InnerDecklistNode *node)
+{
+ if (!node)
+ node = root;
+
+ if (node->isEmpty())
+ return;
+
+ emit dataChanged(createIndex(0, 2, node->at(0)), createIndex(node->size() - 1, 2, node->last()));
+}
diff --git a/cockatrice/src/decklistmodel.h b/cockatrice/src/decklistmodel.h
index f66f509d..a8a22c78 100644
--- a/cockatrice/src/decklistmodel.h
+++ b/cockatrice/src/decklistmodel.h
@@ -17,6 +17,8 @@ public:
DecklistModelCardNode(DecklistCardNode *_dataNode, InnerDecklistNode *_parent) : AbstractDecklistCardNode(_parent), dataNode(_dataNode) { }
int getNumber() const { return dataNode->getNumber(); }
void setNumber(int _number) { dataNode->setNumber(_number); }
+ float getPrice() const { return dataNode->getPrice(); }
+ void setPrice(float _price) { dataNode->setPrice(_price); }
QString getName() const { return dataNode->getName(); }
void setName(const QString &_name) { dataNode->setName(_name); }
DecklistCardNode *getDataNode() const { return dataNode; }
@@ -32,7 +34,7 @@ public:
DeckListModel(QObject *parent = 0);
~DeckListModel();
int rowCount(const QModelIndex &parent = QModelIndex()) const;
- int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const { return 2; }
+ 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;
@@ -45,6 +47,7 @@ public:
void cleanList();
DeckList *getDeckList() const { return deckList; }
void setDeckList(DeckList *_deck);
+ void pricesUpdated(InnerDecklistNode *node = 0);
private:
DeckList *deckList;
InnerDecklistNode *root;
diff --git a/cockatrice/src/dlg_settings.cpp b/cockatrice/src/dlg_settings.cpp
index a07fff6c..0f295af2 100644
--- a/cockatrice/src/dlg_settings.cpp
+++ b/cockatrice/src/dlg_settings.cpp
@@ -455,6 +455,30 @@ void UserInterfaceSettingsPage::soundPathButtonClicked()
settingsCache->setSoundPath(path);
}
+DeckEditorSettingsPage::DeckEditorSettingsPage()
+{
+ priceTagsCheckBox = new QCheckBox;
+ priceTagsCheckBox->setChecked(settingsCache->getPriceTagFeature());
+ connect(priceTagsCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPriceTagFeature(int)));
+
+ QGridLayout *generalGrid = new QGridLayout;
+ generalGrid->addWidget(priceTagsCheckBox, 0, 0);
+
+ generalGroupBox = new QGroupBox;
+ generalGroupBox->setLayout(generalGrid);
+
+ QVBoxLayout *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(generalGroupBox);
+
+ setLayout(mainLayout);
+}
+
+void DeckEditorSettingsPage::retranslateUi()
+{
+ priceTagsCheckBox->setText(tr("Enable &price tag feature (using data from blacklotusproject.com)"));
+ generalGroupBox->setTitle(tr("General"));
+}
+
MessagesSettingsPage::MessagesSettingsPage()
{
aAdd = new QAction(this);
@@ -533,6 +557,7 @@ DlgSettings::DlgSettings(QWidget *parent)
pagesWidget->addWidget(new GeneralSettingsPage);
pagesWidget->addWidget(new AppearanceSettingsPage);
pagesWidget->addWidget(new UserInterfaceSettingsPage);
+ pagesWidget->addWidget(new DeckEditorSettingsPage);
pagesWidget->addWidget(new MessagesSettingsPage);
closeButton = new QPushButton;
@@ -577,6 +602,11 @@ void DlgSettings::createIcons()
userInterfaceButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
userInterfaceButton->setIcon(QIcon(":/resources/icon_config_interface.svg"));
+ deckEditorButton = new QListWidgetItem(contentsWidget);
+ deckEditorButton->setTextAlignment(Qt::AlignHCenter);
+ deckEditorButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+ deckEditorButton->setIcon(QIcon(":/resources/icon_deckeditor.svg"));
+
messagesButton = new QListWidgetItem(contentsWidget);
messagesButton->setTextAlignment(Qt::AlignHCenter);
messagesButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
@@ -633,6 +663,7 @@ void DlgSettings::retranslateUi()
generalButton->setText(tr("General"));
appearanceButton->setText(tr("Appearance"));
userInterfaceButton->setText(tr("User interface"));
+ deckEditorButton->setText(tr("Deck editor"));
messagesButton->setText(tr("Messages"));
closeButton->setText(tr("&Close"));
diff --git a/cockatrice/src/dlg_settings.h b/cockatrice/src/dlg_settings.h
index 54648482..859376d6 100644
--- a/cockatrice/src/dlg_settings.h
+++ b/cockatrice/src/dlg_settings.h
@@ -93,6 +93,16 @@ public:
void retranslateUi();
};
+class DeckEditorSettingsPage : public AbstractSettingsPage {
+ Q_OBJECT
+public:
+ DeckEditorSettingsPage();
+ void retranslateUi();
+private:
+ QCheckBox *priceTagsCheckBox;
+ QGroupBox *generalGroupBox;
+};
+
class MessagesSettingsPage : public AbstractSettingsPage {
Q_OBJECT
public:
@@ -118,7 +128,7 @@ private slots:
private:
QListWidget *contentsWidget;
QStackedWidget *pagesWidget;
- QListWidgetItem *generalButton, *appearanceButton, *userInterfaceButton, *messagesButton;
+ QListWidgetItem *generalButton, *appearanceButton, *userInterfaceButton, *deckEditorButton, *messagesButton;
QPushButton *closeButton;
void createIcons();
void retranslateUi();
diff --git a/cockatrice/src/settingscache.cpp b/cockatrice/src/settingscache.cpp
index d3416fe6..f7494d76 100644
--- a/cockatrice/src/settingscache.cpp
+++ b/cockatrice/src/settingscache.cpp
@@ -31,6 +31,8 @@ SettingsCache::SettingsCache()
soundEnabled = settings->value("sound/enabled", false).toBool();
soundPath = settings->value("sound/path").toString();
+
+ priceTagFeature = settings->value("deckeditor/pricetags", false).toBool();
}
void SettingsCache::setLang(const QString &_lang)
@@ -171,3 +173,9 @@ void SettingsCache::setSoundPath(const QString &_soundPath)
settings->setValue("sound/path", soundPath);
emit soundPathChanged();
}
+
+void SettingsCache::setPriceTagFeature(int _priceTagFeature)
+{
+ priceTagFeature = _priceTagFeature;
+ settings->setValue("deckeditor/pricetags", priceTagFeature);
+}
diff --git a/cockatrice/src/settingscache.h b/cockatrice/src/settingscache.h
index a74e2a61..c834716a 100644
--- a/cockatrice/src/settingscache.h
+++ b/cockatrice/src/settingscache.h
@@ -38,6 +38,7 @@ private:
bool zoneViewSortByName, zoneViewSortByType;
bool soundEnabled;
QString soundPath;
+ bool priceTagFeature;
public:
SettingsCache();
QString getLang() const { return lang; }
@@ -61,6 +62,7 @@ public:
bool getZoneViewSortByType() const { return zoneViewSortByType; }
bool getSoundEnabled() const { return soundEnabled; }
QString getSoundPath() const { return soundPath; }
+ bool getPriceTagFeature() const { return priceTagFeature; }
public slots:
void setLang(const QString &_lang);
void setDeckPath(const QString &_deckPath);
@@ -83,6 +85,7 @@ public slots:
void setZoneViewSortByType(int _zoneViewSortByType);
void setSoundEnabled(int _soundEnabled);
void setSoundPath(const QString &_soundPath);
+ void setPriceTagFeature(int _priceTagFeature);
};
extern SettingsCache *settingsCache;
diff --git a/cockatrice/src/window_deckeditor.cpp b/cockatrice/src/window_deckeditor.cpp
index e540aad6..b3dfdc85 100644
--- a/cockatrice/src/window_deckeditor.cpp
+++ b/cockatrice/src/window_deckeditor.cpp
@@ -26,6 +26,7 @@
#include "dlg_load_deck_from_clipboard.h"
#include "main.h"
#include "settingscache.h"
+#include "priceupdater.h"
void SearchLineEdit::keyPressEvent(QKeyEvent *event)
{
@@ -113,15 +114,37 @@ WndDeckEditor::WndDeckEditor(QWidget *parent)
commentsEdit->setMaximumHeight(70);
commentsLabel->setBuddy(commentsEdit);
connect(commentsEdit, SIGNAL(textChanged()), this, SLOT(updateComments()));
+
QGridLayout *grid = new QGridLayout;
grid->addWidget(nameLabel, 0, 0);
grid->addWidget(nameEdit, 0, 1);
+
grid->addWidget(commentsLabel, 1, 0);
grid->addWidget(commentsEdit, 1, 1);
+ // Update price
+ aUpdatePrices = new QAction(tr("&Update prices"), this);
+ aUpdatePrices->setShortcut(tr("Ctrl+U"));
+ aUpdatePrices->setIcon(QIcon(":/resources/icon_update.png"));
+ connect(aUpdatePrices, SIGNAL(triggered()), this, SLOT(actUpdatePrices()));
+ if (!settingsCache->getPriceTagFeature())
+ aUpdatePrices->setVisible(false);
+
+ QToolBar *deckToolBar = new QToolBar;
+ deckToolBar->setOrientation(Qt::Vertical);
+ deckToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ deckToolBar->setIconSize(QSize(24, 24));
+ deckToolBar->addAction(aUpdatePrices);
+ QHBoxLayout *deckToolbarLayout = new QHBoxLayout;
+ deckToolbarLayout->addStretch();
+ deckToolbarLayout->addWidget(deckToolBar);
+ deckToolbarLayout->addStretch();
+
+
QVBoxLayout *rightFrame = new QVBoxLayout;
rightFrame->addLayout(grid);
rightFrame->addWidget(deckView);
+ rightFrame->addLayout(deckToolbarLayout);
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addLayout(leftFrame, 10);
@@ -456,6 +479,21 @@ void WndDeckEditor::actDecrement()
setWindowModified(true);
}
+void WndDeckEditor::actUpdatePrices()
+{
+ aUpdatePrices->setDisabled(true);
+ PriceUpdater *up = new PriceUpdater(deckModel->getDeckList());
+ connect(up, SIGNAL(finishedUpdate()), this, SLOT(finishedUpdatingPrices()));
+ up->updatePrices();
+}
+
+void WndDeckEditor::finishedUpdatingPrices()
+{
+ deckModel->pricesUpdated();
+ setWindowModified(true);
+ aUpdatePrices->setDisabled(false);
+}
+
void WndDeckEditor::setDeck(DeckList *_deck, const QString &_lastFileName, DeckList::FileFormat _lastFileFormat)
{
deckModel->setDeckList(_deck);
diff --git a/cockatrice/src/window_deckeditor.h b/cockatrice/src/window_deckeditor.h
index e14c1633..92a90bb9 100644
--- a/cockatrice/src/window_deckeditor.h
+++ b/cockatrice/src/window_deckeditor.h
@@ -52,6 +52,9 @@ private slots:
void actRemoveCard();
void actIncrement();
void actDecrement();
+ void actUpdatePrices();
+
+ void finishedUpdatingPrices();
private:
void addCardHelper(const QString &zoneName);
void recursiveExpand(const QModelIndex &index);
@@ -74,7 +77,7 @@ private:
QMenu *deckMenu, *dbMenu;
QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, *aSaveDeckToClipboard, *aPrintDeck, *aClose;
QAction *aEditSets, *aSearch, *aClearSearch;
- QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement;
+ QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement, *aUpdatePrices;
public:
WndDeckEditor(QWidget *parent = 0);
~WndDeckEditor();
diff --git a/common/decklist.cpp b/common/decklist.cpp
index 75a26514..6aed8f89 100644
--- a/common/decklist.cpp
+++ b/common/decklist.cpp
@@ -127,6 +127,19 @@ int InnerDecklistNode::recursiveCount(bool countTotalCards) const
return result;
}
+float InnerDecklistNode::recursivePrice(bool countTotalCards) const
+{
+ float result = 0;
+ for (int i = 0; i < size(); i++) {
+ InnerDecklistNode *node = dynamic_cast(at(i));
+ if (node)
+ result += node->recursivePrice(countTotalCards);
+ else if (countTotalCards)
+ result += dynamic_cast(at(i))->getTotalPrice();
+ }
+ return result;
+}
+
bool InnerDecklistNode::compare(AbstractDecklistNode *other) const
{
InnerDecklistNode *other2 = dynamic_cast(other);
@@ -165,11 +178,12 @@ bool InnerDecklistNode::readElement(QXmlStreamReader *xml)
}
if (xml->isStartElement() && (xml->name() == "zone"))
currentItem = new InnerDecklistNode(xml->attributes().value("name").toString(), this);
- else if (xml->isStartElement() && (xml->name() == "card"))
- currentItem = new DecklistCardNode(xml->attributes().value("name").toString(), xml->attributes().value("number").toString().toInt(), this);
- else if (xml->isEndElement() && (xml->name() == "zone"))
+ else if (xml->isStartElement() && (xml->name() == "card")) {
+ float price = (xml->attributes().value("price") != NULL) ? xml->attributes().value("price").toString().toFloat() : 0;
+ currentItem = new DecklistCardNode(xml->attributes().value("name").toString(), xml->attributes().value("number").toString().toInt(), price, this);
+ } else if (xml->isEndElement() && (xml->name() == "zone"))
return true;
-
+
return false;
}
@@ -194,6 +208,7 @@ void AbstractDecklistCardNode::writeElement(QXmlStreamWriter *xml)
{
xml->writeEmptyElement("card");
xml->writeAttribute("number", QString::number(getNumber()));
+ xml->writeAttribute("price", QString::number(getPrice()));
xml->writeAttribute("name", getName());
}
diff --git a/common/decklist.h b/common/decklist.h
index 37942174..d0f2b7cf 100644
--- a/common/decklist.h
+++ b/common/decklist.h
@@ -69,6 +69,7 @@ public:
AbstractDecklistNode *findChild(const QString &name);
int height() const;
int recursiveCount(bool countTotalCards = false) const;
+ float recursivePrice(bool countTotalCards = false) const;
bool compare(AbstractDecklistNode *other) const;
QVector > sort(Qt::SortOrder order = Qt::AscendingOrder);
@@ -83,6 +84,9 @@ public:
virtual void setNumber(int _number) = 0;
virtual QString getName() const = 0;
virtual void setName(const QString &_name) = 0;
+ virtual float getPrice() const = 0;
+ virtual void setPrice(float _price) = 0;
+ float getTotalPrice() const { return getNumber() * getPrice(); }
int height() const { return 0; }
bool compare(AbstractDecklistNode *other) const;
@@ -94,14 +98,18 @@ class DecklistCardNode : public AbstractDecklistCardNode {
private:
QString name;
int number;
+ float price;
public:
- DecklistCardNode(const QString &_name = QString(), int _number = 1, InnerDecklistNode *_parent = 0) : AbstractDecklistCardNode(_parent), name(_name), number(_number) { }
+ DecklistCardNode(const QString &_name = QString(), int _number = 1, float _price = 0, InnerDecklistNode *_parent = 0) : AbstractDecklistCardNode(_parent), name(_name), number(_number), price(_price) { }
+ DecklistCardNode(const QString &_name = QString(), int _number = 1, InnerDecklistNode *_parent = 0) : AbstractDecklistCardNode(_parent), name(_name), number(_number), price(0) { }
DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent);
int getNumber() const { return number; }
void setNumber(int _number) { number = _number; }
QString getName() const { return name; }
void setName(const QString &_name) { name = _name; }
-};
+ float getPrice() const { return price; }
+ void setPrice(const float _price) { price = _price; }
+ };
class DeckList : public SerializableItem {
Q_OBJECT