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;
|
||||
}
|
||||
|
||||
//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)
|
||||
{
|
||||
if (fileName.endsWith(".cod", Qt::CaseInsensitive)) {
|
||||
|
@ -215,4 +282,4 @@ QString DeckLoader::getCompleteCardName(const QString cardName) const
|
|||
}
|
||||
|
||||
return cardName;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ public:
|
|||
bool loadFromFile(const QString &fileName, FileFormat fmt);
|
||||
bool loadFromRemote(const QString &nativeString, int remoteDeckId);
|
||||
bool saveToFile(const QString &fileName, FileFormat fmt);
|
||||
QString exportDeckToDecklist();
|
||||
|
||||
// overload
|
||||
bool saveToStream_Plain(QTextStream &out);
|
||||
|
|
|
@ -80,6 +80,8 @@ public:
|
|||
SequenceEdit *TabDeckEditor_aIncrement;
|
||||
QLabel *lbl_TabDeckEditor_aSaveDeck;
|
||||
SequenceEdit *TabDeckEditor_aSaveDeck;
|
||||
QLabel *lbl_TabDeckEditor_aExportDeckDecklist;
|
||||
SequenceEdit *TabDeckEditor_aExportDeckDecklist;
|
||||
QLabel *lbl_TabDeckEditor_aDecrement;
|
||||
SequenceEdit *TabDeckEditor_aDecrement;
|
||||
QLabel *lbl_TabDeckEditor_aSaveDeckAs;
|
||||
|
@ -642,6 +644,16 @@ public:
|
|||
TabDeckEditor_aSaveDeckToClipboard->setObjectName("TabDeckEditor_aSaveDeckToClipboard");
|
||||
|
||||
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);
|
||||
|
||||
|
@ -1749,6 +1761,7 @@ public:
|
|||
lbl_TabDeckEditor_aResetLayout->setText(QApplication::translate("shortcutsTab", "Reset layout", 0));
|
||||
lbl_TabDeckEditor_aIncrement->setText(QApplication::translate("shortcutsTab", "Add card", 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_aSaveDeckAs->setText(QApplication::translate("shortcutsTab", "Save deck as", 0));
|
||||
lbl_TabDeckEditor_aLoadDeck->setText(QApplication::translate("shortcutsTab", "Load deck", 0));
|
||||
|
|
|
@ -157,6 +157,7 @@ void ShortcutsSettings::fillDefaultShorcuts()
|
|||
defaultShortCuts["TabDeckEditor/aDecrement"] = parseSequenceString("-");
|
||||
defaultShortCuts["TabDeckEditor/aEditSets"] = parseSequenceString("");
|
||||
defaultShortCuts["TabDeckEditor/aEditTokens"] = parseSequenceString("");
|
||||
defaultShortCuts["TabDeckEditor/aExportDeckDecklist"] = parseSequenceString("");
|
||||
defaultShortCuts["TabDeckEditor/aIncrement"] = parseSequenceString("+");
|
||||
defaultShortCuts["TabDeckEditor/aLoadDeck"] = parseSequenceString("Ctrl+O");
|
||||
defaultShortCuts["TabDeckEditor/aLoadDeckFromClipboard"] = parseSequenceString("Ctrl+Shift+V");
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <QPushButton>
|
||||
#include <QDir>
|
||||
#include <QDesktopServices>
|
||||
#include <QUrl>
|
||||
#include "tab_deck_editor.h"
|
||||
#include "carddatabase.h"
|
||||
#include "pictureloader.h"
|
||||
|
@ -226,6 +227,9 @@ void TabDeckEditor::createMenus()
|
|||
aPrintDeck = new QAction(QString(), this);
|
||||
connect(aPrintDeck, SIGNAL(triggered()), this, SLOT(actPrintDeck()));
|
||||
|
||||
aExportDeckDecklist = new QAction(QString(), this);
|
||||
connect(aExportDeckDecklist, SIGNAL(triggered()), this, SLOT(actExportDeckDecklist()));
|
||||
|
||||
aAnalyzeDeckDeckstats = new QAction(QString(), this);
|
||||
connect(aAnalyzeDeckDeckstats, SIGNAL(triggered()), this, SLOT(actAnalyzeDeckDeckstats()));
|
||||
|
||||
|
@ -233,6 +237,7 @@ void TabDeckEditor::createMenus()
|
|||
connect(aAnalyzeDeckTappedout, SIGNAL(triggered()), this, SLOT(actAnalyzeDeckTappedout()));
|
||||
|
||||
analyzeDeckMenu = new QMenu(this);
|
||||
analyzeDeckMenu->addAction(aExportDeckDecklist);
|
||||
analyzeDeckMenu->addAction(aAnalyzeDeckDeckstats);
|
||||
analyzeDeckMenu->addAction(aAnalyzeDeckTappedout);
|
||||
|
||||
|
@ -453,6 +458,7 @@ void TabDeckEditor::refreshShortcuts()
|
|||
aNewDeck->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aNewDeck"));
|
||||
aLoadDeck->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aLoadDeck"));
|
||||
aSaveDeck->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aSaveDeck"));
|
||||
aExportDeckDecklist->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aExportDeckDecklist"));
|
||||
aSaveDeckAs->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aSaveDeckAs"));
|
||||
aLoadDeckFromClipboard->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aLoadDeckFromClipboard"));
|
||||
aPrintDeck->setShortcuts(settingsCache->shortcuts().getShortcut("TabDeckEditor/aPrintDeck"));
|
||||
|
@ -546,9 +552,10 @@ void TabDeckEditor::retranslateUi()
|
|||
aSaveDeckToClipboard->setText(tr("Save deck to clip&board"));
|
||||
aPrintDeck->setText(tr("&Print deck..."));
|
||||
|
||||
analyzeDeckMenu->setTitle(tr("&Analyze deck online"));
|
||||
aAnalyzeDeckDeckstats->setText("deckstats.net");
|
||||
aAnalyzeDeckTappedout->setText("tappedout.net");
|
||||
analyzeDeckMenu->setTitle(tr("&Send deck to online service"));
|
||||
aExportDeckDecklist->setText(tr("Create decklist (decklist.org)"));
|
||||
aAnalyzeDeckDeckstats->setText(tr("Analyze deck (deckstats.net)"));
|
||||
aAnalyzeDeckTappedout->setText(tr("Analyze deck (tappedout.net)"));
|
||||
|
||||
aClose->setText(tr("&Close"));
|
||||
|
||||
|
@ -764,6 +771,37 @@ void TabDeckEditor::actPrintDeck()
|
|||
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()
|
||||
{
|
||||
DeckStatsInterface *interface = new DeckStatsInterface(
|
||||
|
|
|
@ -52,6 +52,7 @@ class TabDeckEditor : public Tab {
|
|||
void actLoadDeckFromClipboard();
|
||||
void actSaveDeckToClipboard();
|
||||
void actPrintDeck();
|
||||
void actExportDeckDecklist();
|
||||
void actAnalyzeDeckDeckstats();
|
||||
void actAnalyzeDeckTappedout();
|
||||
|
||||
|
@ -110,7 +111,7 @@ private:
|
|||
QWidget *filterBox;
|
||||
|
||||
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 *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement;
|
||||
QAction *aResetLayout;
|
||||
|
|
Loading…
Reference in a new issue