Deck export (#2938)
* Added “export deck” option to export deck to decklist.org for viewing/printing. Implemented using a new menu item, added shortcut ability, and functionality to parse the deck correctly and add main/sideboard cards to decklist. Per issue #2931
This commit is contained in:
parent
4d641eb0e7
commit
6c038a91e4
6 changed files with 126 additions and 5 deletions
|
@ -103,6 +103,73 @@ bool DeckLoader::saveToFile(const QString &fileName, FileFormat fmt)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//This struct is here to support the forEachCard function call, defined in decklist. It
|
||||||
|
//requires a function to be called for each card, and passes an inner node and a card for
|
||||||
|
//each card in the decklist.
|
||||||
|
struct FormatDeckListForExport
|
||||||
|
{
|
||||||
|
//Create refrences for the strings that will be passed in.
|
||||||
|
QString &mainBoardCards;
|
||||||
|
QString &sideBoardCards;
|
||||||
|
//create main operator for struct, allowing the foreachcard to work.
|
||||||
|
FormatDeckListForExport(
|
||||||
|
QString &_mainBoardCards, QString &_sideBoardCards
|
||||||
|
) : mainBoardCards(_mainBoardCards),
|
||||||
|
sideBoardCards(_sideBoardCards){};
|
||||||
|
|
||||||
|
void operator()(const InnerDecklistNode *node, const DecklistCardNode *card) const{
|
||||||
|
//Get the card name
|
||||||
|
CardInfo * dbCard = db->getCard(card->getName());
|
||||||
|
if (!dbCard || dbCard->getIsToken()){
|
||||||
|
//If it's a token, we don't care about the card.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//Check if it's a sideboard card.
|
||||||
|
if(node->getName() == DECK_ZONE_SIDE){
|
||||||
|
//Get the number of cards and add the card name
|
||||||
|
sideBoardCards+=QString::number(card->getNumber());
|
||||||
|
//Add a space between card num and name
|
||||||
|
sideBoardCards+="%20";
|
||||||
|
//Add card name
|
||||||
|
sideBoardCards+=card->getName();
|
||||||
|
//Add a return at the end of the card
|
||||||
|
sideBoardCards+="%0A";
|
||||||
|
}
|
||||||
|
//If it's a mainboard card, do the same thing, but for the mainboard card string
|
||||||
|
else{
|
||||||
|
mainBoardCards+=QString::number(card->getNumber());
|
||||||
|
mainBoardCards+="%20";
|
||||||
|
mainBoardCards+=card->getName();
|
||||||
|
mainBoardCards+="%0A";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//Export deck to decklist function, called to format the deck in a way to be sent to a server
|
||||||
|
QString DeckLoader::exportDeckToDecklist()
|
||||||
|
{
|
||||||
|
//Add the base url
|
||||||
|
QString deckString = "https://www.decklist.org/?";
|
||||||
|
//Create two strings to pass to function
|
||||||
|
QString mainBoardCards, sideBoardCards;
|
||||||
|
//Set up the struct to call.
|
||||||
|
FormatDeckListForExport formatDeckListForExport(mainBoardCards, sideBoardCards);
|
||||||
|
//call our struct function for each card in the deck
|
||||||
|
forEachCard(formatDeckListForExport);
|
||||||
|
//Remove the extra return at the end of the last cards
|
||||||
|
mainBoardCards.chop(3);
|
||||||
|
sideBoardCards.chop(3);
|
||||||
|
//if after we've called it for each card, and the strings are empty, we know that
|
||||||
|
//there were no non-token cards in the deck, so show an error message.
|
||||||
|
if((QString::compare(mainBoardCards, "", Qt::CaseInsensitive) == 0) &&
|
||||||
|
(QString::compare(sideBoardCards, "", Qt::CaseInsensitive) == 0)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
//return a string with the url for decklist export
|
||||||
|
deckString+="deckmain="+mainBoardCards+"&deckside="+sideBoardCards;
|
||||||
|
return deckString;
|
||||||
|
}
|
||||||
|
|
||||||
DeckLoader::FileFormat DeckLoader::getFormatFromName(const QString &fileName)
|
DeckLoader::FileFormat DeckLoader::getFormatFromName(const QString &fileName)
|
||||||
{
|
{
|
||||||
if (fileName.endsWith(".cod", Qt::CaseInsensitive)) {
|
if (fileName.endsWith(".cod", Qt::CaseInsensitive)) {
|
||||||
|
@ -215,4 +282,4 @@ QString DeckLoader::getCompleteCardName(const QString cardName) const
|
||||||
}
|
}
|
||||||
|
|
||||||
return cardName;
|
return cardName;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ public:
|
||||||
bool loadFromFile(const QString &fileName, FileFormat fmt);
|
bool loadFromFile(const QString &fileName, FileFormat fmt);
|
||||||
bool loadFromRemote(const QString &nativeString, int remoteDeckId);
|
bool loadFromRemote(const QString &nativeString, int remoteDeckId);
|
||||||
bool saveToFile(const QString &fileName, FileFormat fmt);
|
bool saveToFile(const QString &fileName, FileFormat fmt);
|
||||||
|
QString exportDeckToDecklist();
|
||||||
|
|
||||||
// overload
|
// overload
|
||||||
bool saveToStream_Plain(QTextStream &out);
|
bool saveToStream_Plain(QTextStream &out);
|
||||||
|
|
|
@ -80,6 +80,8 @@ public:
|
||||||
SequenceEdit *TabDeckEditor_aIncrement;
|
SequenceEdit *TabDeckEditor_aIncrement;
|
||||||
QLabel *lbl_TabDeckEditor_aSaveDeck;
|
QLabel *lbl_TabDeckEditor_aSaveDeck;
|
||||||
SequenceEdit *TabDeckEditor_aSaveDeck;
|
SequenceEdit *TabDeckEditor_aSaveDeck;
|
||||||
|
QLabel *lbl_TabDeckEditor_aExportDeckDecklist;
|
||||||
|
SequenceEdit *TabDeckEditor_aExportDeckDecklist;
|
||||||
QLabel *lbl_TabDeckEditor_aDecrement;
|
QLabel *lbl_TabDeckEditor_aDecrement;
|
||||||
SequenceEdit *TabDeckEditor_aDecrement;
|
SequenceEdit *TabDeckEditor_aDecrement;
|
||||||
QLabel *lbl_TabDeckEditor_aSaveDeckAs;
|
QLabel *lbl_TabDeckEditor_aSaveDeckAs;
|
||||||
|
@ -642,6 +644,16 @@ public:
|
||||||
TabDeckEditor_aSaveDeckToClipboard->setObjectName("TabDeckEditor_aSaveDeckToClipboard");
|
TabDeckEditor_aSaveDeckToClipboard->setObjectName("TabDeckEditor_aSaveDeckToClipboard");
|
||||||
|
|
||||||
gridLayout->addWidget(TabDeckEditor_aSaveDeckToClipboard, 8, 3, 1, 1);
|
gridLayout->addWidget(TabDeckEditor_aSaveDeckToClipboard, 8, 3, 1, 1);
|
||||||
|
|
||||||
|
lbl_TabDeckEditor_aExportDeckDecklist = new QLabel(groupBox_2);
|
||||||
|
lbl_TabDeckEditor_aExportDeckDecklist->setObjectName("lbl_TabDeckEditor_aExportDeckDecklist");
|
||||||
|
|
||||||
|
gridLayout->addWidget(lbl_TabDeckEditor_aExportDeckDecklist, 9, 2, 1, 1);
|
||||||
|
|
||||||
|
TabDeckEditor_aExportDeckDecklist = new SequenceEdit("TabDeckEditor/aExportDeckDecklist",groupBox_2);
|
||||||
|
TabDeckEditor_aExportDeckDecklist->setObjectName("TabDeckEditor_aExportDeckDecklist");
|
||||||
|
|
||||||
|
gridLayout->addWidget(TabDeckEditor_aExportDeckDecklist, 9, 3, 1, 1);
|
||||||
|
|
||||||
gridLayout_3->addWidget(groupBox_2, 0, 1, 1, 1);
|
gridLayout_3->addWidget(groupBox_2, 0, 1, 1, 1);
|
||||||
|
|
||||||
|
@ -1749,6 +1761,7 @@ public:
|
||||||
lbl_TabDeckEditor_aResetLayout->setText(QApplication::translate("shortcutsTab", "Reset layout", 0));
|
lbl_TabDeckEditor_aResetLayout->setText(QApplication::translate("shortcutsTab", "Reset layout", 0));
|
||||||
lbl_TabDeckEditor_aIncrement->setText(QApplication::translate("shortcutsTab", "Add card", 0));
|
lbl_TabDeckEditor_aIncrement->setText(QApplication::translate("shortcutsTab", "Add card", 0));
|
||||||
lbl_TabDeckEditor_aSaveDeck->setText(QApplication::translate("shortcutsTab", "Save deck", 0));
|
lbl_TabDeckEditor_aSaveDeck->setText(QApplication::translate("shortcutsTab", "Save deck", 0));
|
||||||
|
lbl_TabDeckEditor_aExportDeckDecklist->setText(QApplication::translate("shortcutsTab", "Export deck", 0));
|
||||||
lbl_TabDeckEditor_aDecrement->setText(QApplication::translate("shortcutsTab", "Remove card", 0));
|
lbl_TabDeckEditor_aDecrement->setText(QApplication::translate("shortcutsTab", "Remove card", 0));
|
||||||
lbl_TabDeckEditor_aSaveDeckAs->setText(QApplication::translate("shortcutsTab", "Save deck as", 0));
|
lbl_TabDeckEditor_aSaveDeckAs->setText(QApplication::translate("shortcutsTab", "Save deck as", 0));
|
||||||
lbl_TabDeckEditor_aLoadDeck->setText(QApplication::translate("shortcutsTab", "Load deck", 0));
|
lbl_TabDeckEditor_aLoadDeck->setText(QApplication::translate("shortcutsTab", "Load deck", 0));
|
||||||
|
|
|
@ -157,6 +157,7 @@ void ShortcutsSettings::fillDefaultShorcuts()
|
||||||
defaultShortCuts["TabDeckEditor/aDecrement"] = parseSequenceString("-");
|
defaultShortCuts["TabDeckEditor/aDecrement"] = parseSequenceString("-");
|
||||||
defaultShortCuts["TabDeckEditor/aEditSets"] = parseSequenceString("");
|
defaultShortCuts["TabDeckEditor/aEditSets"] = parseSequenceString("");
|
||||||
defaultShortCuts["TabDeckEditor/aEditTokens"] = parseSequenceString("");
|
defaultShortCuts["TabDeckEditor/aEditTokens"] = parseSequenceString("");
|
||||||
|
defaultShortCuts["TabDeckEditor/aExportDeckDecklist"] = parseSequenceString("");
|
||||||
defaultShortCuts["TabDeckEditor/aIncrement"] = parseSequenceString("+");
|
defaultShortCuts["TabDeckEditor/aIncrement"] = parseSequenceString("+");
|
||||||
defaultShortCuts["TabDeckEditor/aLoadDeck"] = parseSequenceString("Ctrl+O");
|
defaultShortCuts["TabDeckEditor/aLoadDeck"] = parseSequenceString("Ctrl+O");
|
||||||
defaultShortCuts["TabDeckEditor/aLoadDeckFromClipboard"] = parseSequenceString("Ctrl+Shift+V");
|
defaultShortCuts["TabDeckEditor/aLoadDeckFromClipboard"] = parseSequenceString("Ctrl+Shift+V");
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
|
#include <QUrl>
|
||||||
#include "tab_deck_editor.h"
|
#include "tab_deck_editor.h"
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
#include "pictureloader.h"
|
#include "pictureloader.h"
|
||||||
|
@ -226,6 +227,9 @@ void TabDeckEditor::createMenus()
|
||||||
aPrintDeck = new QAction(QString(), this);
|
aPrintDeck = new QAction(QString(), this);
|
||||||
connect(aPrintDeck, SIGNAL(triggered()), this, SLOT(actPrintDeck()));
|
connect(aPrintDeck, SIGNAL(triggered()), this, SLOT(actPrintDeck()));
|
||||||
|
|
||||||
|
aExportDeckDecklist = new QAction(QString(), this);
|
||||||
|
connect(aExportDeckDecklist, SIGNAL(triggered()), this, SLOT(actExportDeckDecklist()));
|
||||||
|
|
||||||
aAnalyzeDeckDeckstats = new QAction(QString(), this);
|
aAnalyzeDeckDeckstats = new QAction(QString(), this);
|
||||||
connect(aAnalyzeDeckDeckstats, SIGNAL(triggered()), this, SLOT(actAnalyzeDeckDeckstats()));
|
connect(aAnalyzeDeckDeckstats, SIGNAL(triggered()), this, SLOT(actAnalyzeDeckDeckstats()));
|
||||||
|
|
||||||
|
@ -233,6 +237,7 @@ void TabDeckEditor::createMenus()
|
||||||
connect(aAnalyzeDeckTappedout, SIGNAL(triggered()), this, SLOT(actAnalyzeDeckTappedout()));
|
connect(aAnalyzeDeckTappedout, SIGNAL(triggered()), this, SLOT(actAnalyzeDeckTappedout()));
|
||||||
|
|
||||||
analyzeDeckMenu = new QMenu(this);
|
analyzeDeckMenu = new QMenu(this);
|
||||||
|
analyzeDeckMenu->addAction(aExportDeckDecklist);
|
||||||
analyzeDeckMenu->addAction(aAnalyzeDeckDeckstats);
|
analyzeDeckMenu->addAction(aAnalyzeDeckDeckstats);
|
||||||
analyzeDeckMenu->addAction(aAnalyzeDeckTappedout);
|
analyzeDeckMenu->addAction(aAnalyzeDeckTappedout);
|
||||||
|
|
||||||
|
@ -453,6 +458,7 @@ void TabDeckEditor::refreshShortcuts()
|
||||||
aNewDeck->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aNewDeck"));
|
aNewDeck->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aNewDeck"));
|
||||||
aLoadDeck->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aLoadDeck"));
|
aLoadDeck->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aLoadDeck"));
|
||||||
aSaveDeck->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aSaveDeck"));
|
aSaveDeck->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aSaveDeck"));
|
||||||
|
aExportDeckDecklist->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aExportDeckDecklist"));
|
||||||
aSaveDeckAs->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aSaveDeckAs"));
|
aSaveDeckAs->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aSaveDeckAs"));
|
||||||
aLoadDeckFromClipboard->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aLoadDeckFromClipboard"));
|
aLoadDeckFromClipboard->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aLoadDeckFromClipboard"));
|
||||||
aPrintDeck->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aPrintDeck"));
|
aPrintDeck->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aPrintDeck"));
|
||||||
|
@ -546,9 +552,10 @@ void TabDeckEditor::retranslateUi()
|
||||||
aSaveDeckToClipboard->setText(tr("Save deck to clip&board"));
|
aSaveDeckToClipboard->setText(tr("Save deck to clip&board"));
|
||||||
aPrintDeck->setText(tr("&Print deck..."));
|
aPrintDeck->setText(tr("&Print deck..."));
|
||||||
|
|
||||||
analyzeDeckMenu->setTitle(tr("&Analyze deck online"));
|
analyzeDeckMenu->setTitle(tr("&Send deck to online service"));
|
||||||
aAnalyzeDeckDeckstats->setText("deckstats.net");
|
aExportDeckDecklist->setText(tr("Create decklist (decklist.org)"));
|
||||||
aAnalyzeDeckTappedout->setText("tappedout.net");
|
aAnalyzeDeckDeckstats->setText(tr("Analyze deck (deckstats.net)"));
|
||||||
|
aAnalyzeDeckTappedout->setText(tr("Analyze deck (tappedout.net)"));
|
||||||
|
|
||||||
aClose->setText(tr("&Close"));
|
aClose->setText(tr("&Close"));
|
||||||
|
|
||||||
|
@ -764,6 +771,37 @@ void TabDeckEditor::actPrintDeck()
|
||||||
dlg->exec();
|
dlg->exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Action called when export deck to decklist menu item is pressed.
|
||||||
|
void TabDeckEditor::actExportDeckDecklist()
|
||||||
|
{
|
||||||
|
//Get the decklist class for the deck.
|
||||||
|
DeckLoader *const deck = deckModel->getDeckList();
|
||||||
|
//create a string to load the decklist url into.
|
||||||
|
QString decklistUrlString;
|
||||||
|
//check if deck is not null
|
||||||
|
if(deck){
|
||||||
|
//Get the decklist url string from the deck loader class.
|
||||||
|
decklistUrlString = deck->exportDeckToDecklist();
|
||||||
|
//Check to make sure the string isn't empty.
|
||||||
|
if(QString::compare(decklistUrlString, "", Qt::CaseInsensitive) == 0){
|
||||||
|
//Show an error if the deck is empty, and return.
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("There are no cards in your deck to be exported"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//Encode the string recieved from the model to make sure all characters are encoded.
|
||||||
|
//first we put it into a qurl object
|
||||||
|
QUrl decklistUrl = QUrl(decklistUrlString);
|
||||||
|
//we get the correctly encoded url.
|
||||||
|
decklistUrlString = decklistUrl.toEncoded();
|
||||||
|
//We open the url in the user's default browser
|
||||||
|
QDesktopServices::openUrl(decklistUrlString);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
//if there's no deck loader object, return an error
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("No deck was selected to be saved."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TabDeckEditor::actAnalyzeDeckDeckstats()
|
void TabDeckEditor::actAnalyzeDeckDeckstats()
|
||||||
{
|
{
|
||||||
DeckStatsInterface *interface = new DeckStatsInterface(
|
DeckStatsInterface *interface = new DeckStatsInterface(
|
||||||
|
|
|
@ -52,6 +52,7 @@ class TabDeckEditor : public Tab {
|
||||||
void actLoadDeckFromClipboard();
|
void actLoadDeckFromClipboard();
|
||||||
void actSaveDeckToClipboard();
|
void actSaveDeckToClipboard();
|
||||||
void actPrintDeck();
|
void actPrintDeck();
|
||||||
|
void actExportDeckDecklist();
|
||||||
void actAnalyzeDeckDeckstats();
|
void actAnalyzeDeckDeckstats();
|
||||||
void actAnalyzeDeckTappedout();
|
void actAnalyzeDeckTappedout();
|
||||||
|
|
||||||
|
@ -110,7 +111,7 @@ private:
|
||||||
QWidget *filterBox;
|
QWidget *filterBox;
|
||||||
|
|
||||||
QMenu *deckMenu, *viewMenu, *cardInfoDockMenu, *deckDockMenu, *filterDockMenu, *analyzeDeckMenu;
|
QMenu *deckMenu, *viewMenu, *cardInfoDockMenu, *deckDockMenu, *filterDockMenu, *analyzeDeckMenu;
|
||||||
QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, *aSaveDeckToClipboard, *aPrintDeck, *aAnalyzeDeckDeckstats, *aAnalyzeDeckTappedout, *aClose;
|
QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, *aSaveDeckToClipboard, *aPrintDeck, *aExportDeckDecklist, *aAnalyzeDeckDeckstats, *aAnalyzeDeckTappedout, *aClose;
|
||||||
QAction *aClearFilterAll, *aClearFilterOne;
|
QAction *aClearFilterAll, *aClearFilterOne;
|
||||||
QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement;
|
QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement;
|
||||||
QAction *aResetLayout;
|
QAction *aResetLayout;
|
||||||
|
|
Loading…
Reference in a new issue