diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 84450e85..a36ce0c7 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -62,6 +62,7 @@ SET(cockatrice_SOURCES src/tab_userlists.cpp src/tab_deck_editor.cpp src/replay_timeline_widget.cpp + src/deckstats_interface.cpp src/chatview.cpp src/userlist.cpp src/userinfobox.cpp @@ -137,6 +138,7 @@ SET(cockatrice_HEADERS src/tab_userlists.h src/tab_deck_editor.h src/replay_timeline_widget.h + src/deckstats_interface.h src/chatview.h src/userlist.h src/userinfobox.h diff --git a/cockatrice/src/deckstats_interface.cpp b/cockatrice/src/deckstats_interface.cpp new file mode 100644 index 00000000..65cb101c --- /dev/null +++ b/cockatrice/src/deckstats_interface.cpp @@ -0,0 +1,53 @@ +#include "deckstats_interface.h" +#include "decklist.h" +#include +#include +#include +#include +#include +#include + +DeckStatsInterface::DeckStatsInterface(QObject *parent) + : QObject(parent) +{ + manager = new QNetworkAccessManager(this); + connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(queryFinished(QNetworkReply *))); +} + +void DeckStatsInterface::queryFinished(QNetworkReply *reply) +{ + if (reply->error() != QNetworkReply::NoError) { + QMessageBox::critical(0, tr("Error"), reply->errorString()); + reply->deleteLater(); + deleteLater(); + return; + } + + QString data(reply->readAll()); + reply->deleteLater(); + + QRegExp rx("id=\"deckstats_deck_url\" value=\"([^\"]+)\""); + if (!rx.indexIn(data)) { + QMessageBox::critical(0, tr("Error"), tr("The reply from the server could not be parsed.")); + deleteLater(); + return; + } + + QString deckUrl = rx.cap(1); + QDesktopServices::openUrl(deckUrl); + + deleteLater(); +} + +void DeckStatsInterface::analyzeDeck(DeckList *deck) +{ + QUrl params; + params.addQueryItem("deck", deck->writeToString_Plain()); + QByteArray data; + data.append(params.encodedQuery()); + + QNetworkRequest request(QUrl("http://deckstats.net/index.php")); + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); + + manager->post(request, data); +} diff --git a/cockatrice/src/deckstats_interface.h b/cockatrice/src/deckstats_interface.h new file mode 100644 index 00000000..89361b2d --- /dev/null +++ b/cockatrice/src/deckstats_interface.h @@ -0,0 +1,21 @@ +#ifndef DECKSTATS_INTERFACE_H +#define DECKSTATS_INTERFACE_H + +#include + +class QNetworkAccessManager; +class QNetworkReply; +class DeckList; + +class DeckStatsInterface : public QObject { + Q_OBJECT +private: + QNetworkAccessManager *manager; +private slots: + void queryFinished(QNetworkReply *reply); +public: + DeckStatsInterface(QObject *parent = 0); + void analyzeDeck(DeckList *deck); +}; + +#endif diff --git a/cockatrice/src/tab_deck_editor.cpp b/cockatrice/src/tab_deck_editor.cpp index f7abd9a9..9b8b58ce 100644 --- a/cockatrice/src/tab_deck_editor.cpp +++ b/cockatrice/src/tab_deck_editor.cpp @@ -29,6 +29,7 @@ #include "settingscache.h" #include "priceupdater.h" #include "tab_supervisor.h" +#include "deckstats_interface.h" #include "abstractclient.h" #include "pending_command.h" #include "pb/response.pb.h" @@ -183,6 +184,8 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent) aPrintDeck = new QAction(QString(), this); aPrintDeck->setShortcuts(QKeySequence::Print); connect(aPrintDeck, SIGNAL(triggered()), this, SLOT(actPrintDeck())); + aAnalyzeDeck = new QAction(QString(), this); + connect(aAnalyzeDeck, SIGNAL(triggered()), this, SLOT(actAnalyzeDeck())); aClose = new QAction(QString(), this); connect(aClose, SIGNAL(triggered()), this, SLOT(closeRequest())); @@ -202,6 +205,8 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent) deckMenu->addSeparator(); deckMenu->addAction(aPrintDeck); deckMenu->addSeparator(); + deckMenu->addAction(aAnalyzeDeck); + deckMenu->addSeparator(); deckMenu->addAction(aClose); addTabMenu(deckMenu); @@ -268,6 +273,7 @@ void TabDeckEditor::retranslateUi() aLoadDeckFromClipboard->setText(tr("Load deck from cl&ipboard...")); aSaveDeckToClipboard->setText(tr("Save deck to clip&board")); aPrintDeck->setText(tr("&Print deck...")); + aAnalyzeDeck->setText(tr("&Analyze deck on deckstats.net")); aClose->setText(tr("&Close")); aClose->setShortcut(tr("Ctrl+Q")); @@ -471,6 +477,12 @@ void TabDeckEditor::actPrintDeck() dlg->exec(); } +void TabDeckEditor::actAnalyzeDeck() +{ + DeckStatsInterface *interface = new DeckStatsInterface(this); // it deletes itself when done + interface->analyzeDeck(deckModel->getDeckList()); +} + void TabDeckEditor::actEditSets() { WndSets *w = new WndSets; diff --git a/cockatrice/src/tab_deck_editor.h b/cockatrice/src/tab_deck_editor.h index 826825d3..73ee8a14 100644 --- a/cockatrice/src/tab_deck_editor.h +++ b/cockatrice/src/tab_deck_editor.h @@ -44,6 +44,7 @@ private slots: void actLoadDeckFromClipboard(); void actSaveDeckToClipboard(); void actPrintDeck(); + void actAnalyzeDeck(); void actEditSets(); void actEditTokens(); @@ -82,7 +83,7 @@ private: DlgCardSearch *dlgCardSearch; QMenu *deckMenu, *dbMenu; - QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, *aSaveDeckToClipboard, *aPrintDeck, *aClose; + QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, *aSaveDeckToClipboard, *aPrintDeck, *aAnalyzeDeck, *aClose; QAction *aEditSets, *aEditTokens, *aSearch, *aClearSearch; QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement, *aUpdatePrices; diff --git a/common/decklist.cpp b/common/decklist.cpp index 4612ec69..088cae5b 100644 --- a/common/decklist.cpp +++ b/common/decklist.cpp @@ -480,6 +480,14 @@ bool DeckList::saveToFile_Plain(QIODevice *device) return saveToStream_Plain(out); } +QString DeckList::writeToString_Plain() +{ + QString result; + QTextStream out(&result); + saveToStream_Plain(out); + return result; +} + void DeckList::cleanList() { root->clearTree(); diff --git a/common/decklist.h b/common/decklist.h index e4532b27..c5535c2d 100644 --- a/common/decklist.h +++ b/common/decklist.h @@ -144,6 +144,7 @@ public: bool loadFromFile_Plain(QIODevice *device); bool saveToStream_Plain(QTextStream &stream); bool saveToFile_Plain(QIODevice *device); + QString writeToString_Plain(); void cleanList(); bool isEmpty() const { return root->isEmpty() && name.isEmpty() && comments.isEmpty() && sideboardPlans.isEmpty(); }