From 6226e381de8f14251db6aa49bf5de62a563c8a8c Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Thu, 16 Jun 2011 16:43:01 +0200 Subject: [PATCH] price tag feature by Marcio Ribeiro --- cockatrice/cockatrice.pro | 4 +- cockatrice/cockatrice.qrc | 1 + cockatrice/src/decklistmodel.cpp | 65 ++++++++++++++++++++++------ cockatrice/src/decklistmodel.h | 5 ++- cockatrice/src/dlg_settings.cpp | 31 +++++++++++++ cockatrice/src/dlg_settings.h | 12 ++++- cockatrice/src/settingscache.cpp | 8 ++++ cockatrice/src/settingscache.h | 3 ++ cockatrice/src/window_deckeditor.cpp | 38 ++++++++++++++++ cockatrice/src/window_deckeditor.h | 5 ++- common/decklist.cpp | 23 ++++++++-- common/decklist.h | 12 ++++- 12 files changed, 184 insertions(+), 23 deletions(-) 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