From 94419b1e38d0d999c030ee19d35fcdadc335dfab Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 14 Jun 2014 11:29:00 +0200 Subject: [PATCH 01/24] Oracle: build with qtjson --- oracle/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oracle/CMakeLists.txt b/oracle/CMakeLists.txt index 6f4e18c9..c23dfc4e 100644 --- a/oracle/CMakeLists.txt +++ b/oracle/CMakeLists.txt @@ -4,7 +4,7 @@ PROJECT(oracle) # paths set(DESKTOPDIR share/applications CACHE STRING "path to .desktop files") -SET(oracle_SOURCES src/main.cpp src/oracleimporter.cpp src/window_main.cpp ../cockatrice/src/carddatabase.cpp ../cockatrice/src/settingscache.cpp) +SET(oracle_SOURCES src/main.cpp src/oracleimporter.cpp src/window_main.cpp ../cockatrice/src/carddatabase.cpp ../cockatrice/src/settingscache.cpp ../cockatrice/src/qt-json/json.cpp) SET(oracle_HEADERS src/oracleimporter.h src/window_main.h ../cockatrice/src/carddatabase.h ../cockatrice/src/settingscache.h) SET(QT_USE_QTNETWORK TRUE) From dbac97ee8957a7b3144e3d6a03084143624a6000 Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 14 Jun 2014 11:34:06 +0200 Subject: [PATCH 02/24] OracleImporter: use json to parse cards in sets Problem: Split card are imported as 2 different cards; need to find some way to join them --- oracle/src/oracleimporter.cpp | 94 +++++++++++------------------------ 1 file changed, 29 insertions(+), 65 deletions(-) diff --git a/oracle/src/oracleimporter.cpp b/oracle/src/oracleimporter.cpp index c244e56a..4d431e51 100644 --- a/oracle/src/oracleimporter.cpp +++ b/oracle/src/oracleimporter.cpp @@ -5,6 +5,8 @@ #include #include +#include "qt-json/json.h" + OracleImporter::OracleImporter(const QString &_dataDir, QObject *parent) : CardDatabase(parent), dataDir(_dataDir), setIndex(-1) { @@ -147,72 +149,34 @@ CardInfo *OracleImporter::addCard(const QString &setName, int OracleImporter::importTextSpoiler(CardSet *set, const QByteArray &data) { int cards = 0; - QString bufferContents(data); - - // Workaround for ampersand bug in text spoilers - int index = -1; - while ((index = bufferContents.indexOf('&', index + 1)) != -1) { - int semicolonIndex = bufferContents.indexOf(';', index); - if (semicolonIndex > 5) { - bufferContents.insert(index + 1, "amp;"); - index += 4; - } - } - - QDomDocument doc; - QString errorMsg; - int errorLine, errorColumn; - if (!doc.setContent(bufferContents, &errorMsg, &errorLine, &errorColumn)) - qDebug() << "error:" << errorMsg << "line:" << errorLine << "column:" << errorColumn; + bool ok; + QVariantMap resultMap = QtJson::Json::parse(QString(data), ok).toMap(); + if (!ok) { + qDebug() << "error: QtJson::Json::parse()"; + return 0; + } + + QListIterator it(resultMap.value("cards").toList()); + while (it.hasNext()) { + QVariantMap map = it.next().toMap(); + QString cardName = map.value("name").toString(); + QString cardCost = map.value("manaCost").toString(); + QString cardType = map.value("type").toString(); + QString cardPT = map.value("power").toString() + QString('/') + map.value("toughness").toString(); + QString cardText = map.value("text").toString(); + int cardId = map.value("multiverseid").toInt(); + int cardLoyalty = map.value("loyalty").toInt(); + QStringList cardTextSplit = cardText.split("\n"); - QDomNodeList divs = doc.elementsByTagName("div"); - for (int i = 0; i < divs.size(); ++i) { - QDomElement div = divs.at(i).toElement(); - QDomNode divClass = div.attributes().namedItem("class"); - if (divClass.nodeValue() == "textspoiler") { - QString cardName, cardCost, cardType, cardPT, cardText; - int cardId = 0; - int cardLoyalty = 0; - - QDomNodeList trs = div.elementsByTagName("tr"); - for (int j = 0; j < trs.size(); ++j) { - QDomElement tr = trs.at(j).toElement(); - QDomNodeList tds = tr.elementsByTagName("td"); - if (tds.size() != 2) { - QStringList cardTextSplit = cardText.split("\n"); - for (int i = 0; i < cardTextSplit.size(); ++i) - cardTextSplit[i] = cardTextSplit[i].trimmed(); - - CardInfo *card = addCard(set->getShortName(), cardName, false, cardId, cardCost, cardType, cardPT, cardLoyalty, cardTextSplit); - if (!set->contains(card)) { - card->addToSet(set); - cards++; - } - cardName = cardCost = cardType = cardPT = cardText = QString(); - } else { - QString v1 = tds.at(0).toElement().text().simplified(); - QString v2 = tds.at(1).toElement().text().replace(trUtf8("—"), "-"); - - if (v1 == "Name") { - QDomElement a = tds.at(1).toElement().elementsByTagName("a").at(0).toElement(); - QString href = a.attributes().namedItem("href").nodeValue(); - cardId = href.mid(href.indexOf("multiverseid=") + 13).toInt(); - cardName = v2.simplified(); - } else if (v1 == "Cost:") - cardCost = v2.simplified(); - else if (v1 == "Type:") - cardType = v2.simplified(); - else if (v1 == "Pow/Tgh:") - cardPT = v2.simplified().remove('(').remove(')'); - else if (v1 == "Rules Text:") - cardText = v2.trimmed(); - else if (v1 == "Loyalty:") - cardLoyalty = v2.trimmed().remove('(').remove(')').toInt(); - } - } - break; + CardInfo *card = addCard(set->getShortName(), cardName, false, cardId, cardCost, cardType, cardPT, cardLoyalty, cardTextSplit); + + if (!set->contains(card)) { + card->addToSet(set); + cards++; } - } + cardName = cardCost = cardType = cardPT = cardText = QString(); + } + return cards; } @@ -257,7 +221,7 @@ void OracleImporter::downloadNextFile() QString urlString = setsToDownload[setIndex].getUrl(); if (urlString.isEmpty()) urlString = setUrl; - urlString = urlString.replace("!longname!", setsToDownload[setIndex].getLongName()); + urlString = urlString.replace("!name!", setsToDownload[setIndex].getShortName()); if (urlString.startsWith("http://")) { QUrl url(urlString); From 6f8b2baad8f3b62130bc4c738df0f8a6e46aa603 Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 14 Jun 2014 11:34:52 +0200 Subject: [PATCH 03/24] Corrections to sets.xml for mtgjson.com MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Used http://www.woogerworks.com/files/sets.xml as a base * update version * use mtgjson.com as source * adapted some sets name (es: 6E => 6ED) Caveats: * Not all previous sets are present (e.g.: WOTC, WMCQ, WRL); they were not present in woogerworks’s sets.xml anyway --- doc/sets.xml | 688 ++++++++++++++++++++++----------------------------- 1 file changed, 290 insertions(+), 398 deletions(-) diff --git a/doc/sets.xml b/doc/sets.xml index 1afa3958..92bf1b21 100644 --- a/doc/sets.xml +++ b/doc/sets.xml @@ -1,333 +1,253 @@ - + http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=!cardid!&type=card -http://gatherer.wizards.com/Pages/Search/Default.aspx?output=spoiler&method=text&set=["!longname!"]&special=true - - 10E - Tenth Edition - - - 15ANN - 15th Anniversary - - - 4E - Fourth Edition - - - 5DN - Fifth Dawn - - - 5E - Fifth Edition - - - 6E - Classic Sixth Edition - - - 7E - Seventh Edition - - - 8EB - Eighth Edition Box Set - - - 8E - Eighth Edition - - - 9EB - Ninth Edition Box Set - - - 9E - Ninth Edition - - - AI - Alliances - - - ALA - Shards of Alara - - - AL - Limited Edition Alpha - - - AN - Arabian Nights - - - APAC - Asia Pacific Land Program - - - AP - Apocalypse - - - AQ - Antiquities - +http://mtgjson.com/json/!name!.json ARB Alara Reborn + ALL + Alliances + + + ATQ + Antiquities + + + APC + Apocalypse + + + ARN + Arabian Nights + + ARC Archenemy - - ARENA - Arena League - - - AT - Anthologies - AVR Avacyn Restored - - BD - Beatdown Box Set + + BRB + Battle Royale Box Set - - BE - Limited Edition Beta + + BTD + Beatdown Box Set BOK Betrayers of Kamigawa - BR - Battle Royale Box Set - - - CED - Collector's Edition - - - CEDI - International Collectors' Edition - - - CFX - Conflux - - - CH - Chronicles + BNG + Born of the Gods CHK Champions of Kamigawa - CMA - Commander's Arsenal + CHR + Chronicles - CMD - Commander + 6ED + Classic Sixth Edition - CP - Champs - - - CS + CSP Coldsnap - CSTD - Coldsnap Theme Decks + CON + Conflux + + + CMA + Commander's Arsenal + + ^M + C13^M + Commander 2013 Edition^M - DCILM - Legend Membership - - - DDF - Duel Decks: Elspeth vs. Tezzeret - - - DDG - Duel Decks: Knights vs. Dragons - - - DDH - Duel Decks: Ajani vs. Nicol Bolas - - - DDI - Duel Decks: Venser vs. Koth - - - DDJ - Duel Decks: Izzet vs. Golgari - - - DDK - Duel Decks: Sorin vs. Tibalt - - - DGM - Dragon's Maze - - - DI - Dissension + DST + Darksteel DKA Dark Ascension - DK - The Dark + DIS + Dissension - DM - Deckmasters + DGM + Dragon's Maze - - DPA - Duels of the Planeswalkers + + DDH + Duel Decks: Ajani vs. Nicol Bolas - - DRC - Dragon Con - - - DS - Darksteel - - - DVD + + DDC Duel Decks: Divine vs. Demonic + + DDF + Duel Decks: Elspeth vs. Tezzeret + + + EVG + Duel Decks: Elves vs. Goblins + + + DDD + Duel Decks: Garruk vs. Liliana + + + DDL + Duel Decks: Heroes vs. Monsters + + + DDJ + Duel Decks: Izzet vs. Golgari + + + DD2 + Duel Decks: Jace vs. Chandra + + + DDM + Duel Decks: Jace vs. Vraska + + + DDG + Duel Decks: Knights vs. Dragons + + + DDE + Duel Decks: Phyrexia vs. the Coalition + + + DDK + Duel Decks: Sorin vs. Tibalt + + + DDI + Duel Decks: Venser vs. Koth + - EURO - European Land Program + 8ED + Eighth Edition EVE Eventide - EVG - Duel Decks: Elves vs. Goblins - - - EX + EXO Exodus - FE + FEM Fallen Empires - FNMP - Friday Night Magic + 5DN + Fifth Dawn + + + 5ED + Fifth Edition + + + 4ED + Fourth Edition + + + DRB + From the Vault: Dragons + + + V09 + From the Vault: Exiled + + + V11 + From the Vault: Legends + + + V12 + From the Vault: Realms + + + V10 + From the Vault: Relics + + + V13 + From the Vault: Twenty FUT Future Sight - FVD - From the Vault: Dragons - - - FVE - From the Vault: Exiled - - - FVL - From the Vault: Legends - - - FVR - From the Vault: Relics - - - GP + GPT Guildpact - - GPX - Grand Prix - - - GRC - WPN/Gateway - GTC Gatecrash - GURU - Guru - - - GVL - Duel Decks: Garruk vs. Liliana - - - HHO - Happy Holidays - - - HL + HML Homelands - IA + ICE Ice Age - - IN - Invasion - ISD Innistrad - ITP - Introductory Two-Player Set + INV + Invasion - JR - Judge Gift Program + JOU + Journey into Nyx - JU + JUD Judgment - JVC - Duel Decks: Jace vs. Chandra - - - LE - Legions - - - LG + LEG Legends - LW + LGN + Legions + + + LEA + Limited Edition Alpha + + + LEB + Limited Edition Beta + + + LRW Lorwyn @@ -347,63 +267,59 @@ Magic 2013 - MBP - Media Inserts + M14 + Magic 2014 Core Set + + + CMD + Magic: The Gathering-Commander + + + CNS + Magic: The Gathering—Conspiracy + + + MED + Masters Edition + + + ME2 + Masters Edition II + + + ME3 + Masters Edition III + + + ME4 + Masters Edition IV + + + MMQ + Mercadian Masques + + + MIR + Mirage + + + MRD + Mirrodin MBS Mirrodin Besieged + ^M + MMA^M + Modern Masters^M + ^ - ME2 - MTGO Masters Edition II - - - ME3 - MTGO Masters Edition III - - - ME4 - MTGO Masters Edition IV - - - MED - MTGO Masters Edition - - - MGBC - Multiverse Gift Box Cards - - - MGDC - Magic Game Day Cards - - - MI - Mirrodin - - - MLP - Magic: The Gathering Launch Parties - - - MM - Mercadian Masques - - - MPRP - Magic Player Rewards - - - MR - Mirage - - - MT + MOR Morningtide - NE + NMS Nemesis @@ -411,104 +327,80 @@ New Phyrexia - OD + 9ED + Ninth Edition + + + ODY Odyssey - ON + ONS Onslaught - P3K - Portal Three Kingdoms + PLC + Planar Chaos - + + HOP + Planechase + + PC2 Planechase 2012 Edition - PC - Planar Chaos + PLS + Planeshift - PCH - Planechase - - - PD2 - Premium Deck Series: Fire and Lightning - - - PD3 - Premium Deck Series: Graveborn - - - PDS - Premium Deck Series: Slivers + POR + Portal PO2 Portal Second Age - PO - Portal + PTK + Portal Three Kingdoms + + + PD2 + Premium Deck Series: Fire and Lightning + + + PD3 + Premium Deck Series: Graveborn + + + H09 + Premium Deck Series: Slivers + + + PPR + Promo set for Gatherer - POT - Portal Demogame - - - PR + PCY Prophecy - - PRO - Pro Tour - - - PS - Planeshift - - - PTC - Prerelease Events - - - PVC - Duel Decks: Phyrexia vs. The Coalition - RAV Ravnica: City of Guilds - - REP - Release Events - - - ROE - Rise of the Eldrazi - RTR Return to Ravnica - RV + 3ED Revised Edition - SC - Scourge - - - SH - Stronghold - - - SHM - Shadowmoor + ROE + Rise of the Eldrazi SOK @@ -519,97 +411,97 @@ Scars of Mirrodin - ST2K - Starter 2000 + SCG + Scourge - ST + 7ED + Seventh Edition + + + SHM + Shadowmoor + + + ALA + Shards of Alara + + + S99 Starter 1999 - SUM - Summer of Magic + S00 + Starter 2000 - SUS - Super Series + STH + Stronghold - THGT - Two-Headed Giant Tournament - - - TP + TMP Tempest - TR - Torment + 10E + Tenth Edition - TS + DRK + The Dark + + + THS + Theros + + + TSP Time Spiral - TSTS + TSB Time Spiral "Timeshifted" - UD - Urza's Destiny + TOR + Torment - - UG + + UGL Unglued - - UHAA - Unhinged Alternate Foils - - - UH + + UNH Unhinged - UL - Urza's Legacy - - - UN + 2ED Unlimited Edition - UQC - Celebration Cards + UDS + Urza's Destiny - US + ULG + Urza's Legacy + + + USG Urza's Saga - - V12 - From the Vault: Realms + + VAN + Vanguard - VI + VIS Visions - WL + WTH Weatherlight - - WMCQ - World Magic Cup Qualifiers - - - WOTC - WotC Online Store - - - WRL - Worlds - WWK Worldwake From d58615df1a2c2bd02b3599d3fa62eccbe66f50d6 Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 14 Jun 2014 11:52:55 +0200 Subject: [PATCH 04/24] Fix import of P/T; misc optimizations --- oracle/src/oracleimporter.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/oracle/src/oracleimporter.cpp b/oracle/src/oracleimporter.cpp index 4d431e51..af310a46 100644 --- a/oracle/src/oracleimporter.cpp +++ b/oracle/src/oracleimporter.cpp @@ -157,15 +157,24 @@ int OracleImporter::importTextSpoiler(CardSet *set, const QByteArray &data) } QListIterator it(resultMap.value("cards").toList()); + QVariantMap map; + QString cardName; + QString cardCost; + QString cardType; + QString cardPT; + QString cardText; + int cardId; + int cardLoyalty; + while (it.hasNext()) { - QVariantMap map = it.next().toMap(); - QString cardName = map.value("name").toString(); - QString cardCost = map.value("manaCost").toString(); - QString cardType = map.value("type").toString(); - QString cardPT = map.value("power").toString() + QString('/') + map.value("toughness").toString(); - QString cardText = map.value("text").toString(); - int cardId = map.value("multiverseid").toInt(); - int cardLoyalty = map.value("loyalty").toInt(); + map = it.next().toMap(); + cardName = map.contains("name") ? map.value("name").toString() : QString(""); + cardCost = map.contains("manaCost") ? map.value("manaCost").toString() : QString(""); + cardType = map.contains("type") ? map.value("type").toString() : QString(""); + cardPT = map.contains("power") || map.contains("toughness") ? map.value("power").toString() + QString('/') + map.value("toughness").toString() : QString(""); + cardText = map.contains("text") ? map.value("text").toString() : QString(""); + cardId = map.contains("multiverseid") ? map.value("multiverseid").toInt() : 0; + cardLoyalty = map.contains("loyalty") ? map.value("loyalty").toInt() : 0; QStringList cardTextSplit = cardText.split("\n"); CardInfo *card = addCard(set->getShortName(), cardName, false, cardId, cardCost, cardType, cardPT, cardLoyalty, cardTextSplit); @@ -174,7 +183,6 @@ int OracleImporter::importTextSpoiler(CardSet *set, const QByteArray &data) card->addToSet(set); cards++; } - cardName = cardCost = cardType = cardPT = cardText = QString(); } return cards; From 2b1d7c4f740923a06f7880c3e25f3384d31733fc Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 14 Jun 2014 12:02:34 +0200 Subject: [PATCH 05/24] Use mtgimage.com for card images --- doc/sets.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sets.xml b/doc/sets.xml index 92bf1b21..639cbdfc 100644 --- a/doc/sets.xml +++ b/doc/sets.xml @@ -1,6 +1,6 @@ -http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=!cardid!&type=card +http://mtgimage.com/multiverseid/!cardid!.jpg http://mtgjson.com/json/!name!.json ARB From 827f448cde5c4fb584b969bf2cb8b1ed0842a0ec Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 14 Jun 2014 12:11:03 +0200 Subject: [PATCH 06/24] Keep gatherer as image source; mtgimage as a hq alternative --- doc/sets.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/sets.xml b/doc/sets.xml index 639cbdfc..bcc7c20e 100644 --- a/doc/sets.xml +++ b/doc/sets.xml @@ -1,6 +1,7 @@ -http://mtgimage.com/multiverseid/!cardid!.jpg +http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=!cardid!&type=card + http://mtgjson.com/json/!name!.json ARB From 89ab257d0bdc32212b5390e39192d961ac38dc4f Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 14 Jun 2014 11:29:00 +0200 Subject: [PATCH 07/24] Oracle: build with qtjson --- oracle/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/oracle/CMakeLists.txt b/oracle/CMakeLists.txt index 340ce16a..8e1f9b16 100644 --- a/oracle/CMakeLists.txt +++ b/oracle/CMakeLists.txt @@ -13,6 +13,7 @@ SET(oracle_SOURCES src/window_main.cpp ../cockatrice/src/carddatabase.cpp ../cockatrice/src/settingscache.cpp + ../cockatrice/src/qt-json/json.cpp ) SET(QT_USE_QTNETWORK TRUE) From dfbcace05b56074ffae5de3c575ce35722adb2aa Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 14 Jun 2014 11:34:06 +0200 Subject: [PATCH 08/24] OracleImporter: use json to parse cards in sets Problem: Split card are imported as 2 different cards; need to find some way to join them --- oracle/src/oracleimporter.cpp | 94 +++++++++++------------------------ 1 file changed, 29 insertions(+), 65 deletions(-) diff --git a/oracle/src/oracleimporter.cpp b/oracle/src/oracleimporter.cpp index c244e56a..4d431e51 100644 --- a/oracle/src/oracleimporter.cpp +++ b/oracle/src/oracleimporter.cpp @@ -5,6 +5,8 @@ #include #include +#include "qt-json/json.h" + OracleImporter::OracleImporter(const QString &_dataDir, QObject *parent) : CardDatabase(parent), dataDir(_dataDir), setIndex(-1) { @@ -147,72 +149,34 @@ CardInfo *OracleImporter::addCard(const QString &setName, int OracleImporter::importTextSpoiler(CardSet *set, const QByteArray &data) { int cards = 0; - QString bufferContents(data); - - // Workaround for ampersand bug in text spoilers - int index = -1; - while ((index = bufferContents.indexOf('&', index + 1)) != -1) { - int semicolonIndex = bufferContents.indexOf(';', index); - if (semicolonIndex > 5) { - bufferContents.insert(index + 1, "amp;"); - index += 4; - } - } - - QDomDocument doc; - QString errorMsg; - int errorLine, errorColumn; - if (!doc.setContent(bufferContents, &errorMsg, &errorLine, &errorColumn)) - qDebug() << "error:" << errorMsg << "line:" << errorLine << "column:" << errorColumn; + bool ok; + QVariantMap resultMap = QtJson::Json::parse(QString(data), ok).toMap(); + if (!ok) { + qDebug() << "error: QtJson::Json::parse()"; + return 0; + } + + QListIterator it(resultMap.value("cards").toList()); + while (it.hasNext()) { + QVariantMap map = it.next().toMap(); + QString cardName = map.value("name").toString(); + QString cardCost = map.value("manaCost").toString(); + QString cardType = map.value("type").toString(); + QString cardPT = map.value("power").toString() + QString('/') + map.value("toughness").toString(); + QString cardText = map.value("text").toString(); + int cardId = map.value("multiverseid").toInt(); + int cardLoyalty = map.value("loyalty").toInt(); + QStringList cardTextSplit = cardText.split("\n"); - QDomNodeList divs = doc.elementsByTagName("div"); - for (int i = 0; i < divs.size(); ++i) { - QDomElement div = divs.at(i).toElement(); - QDomNode divClass = div.attributes().namedItem("class"); - if (divClass.nodeValue() == "textspoiler") { - QString cardName, cardCost, cardType, cardPT, cardText; - int cardId = 0; - int cardLoyalty = 0; - - QDomNodeList trs = div.elementsByTagName("tr"); - for (int j = 0; j < trs.size(); ++j) { - QDomElement tr = trs.at(j).toElement(); - QDomNodeList tds = tr.elementsByTagName("td"); - if (tds.size() != 2) { - QStringList cardTextSplit = cardText.split("\n"); - for (int i = 0; i < cardTextSplit.size(); ++i) - cardTextSplit[i] = cardTextSplit[i].trimmed(); - - CardInfo *card = addCard(set->getShortName(), cardName, false, cardId, cardCost, cardType, cardPT, cardLoyalty, cardTextSplit); - if (!set->contains(card)) { - card->addToSet(set); - cards++; - } - cardName = cardCost = cardType = cardPT = cardText = QString(); - } else { - QString v1 = tds.at(0).toElement().text().simplified(); - QString v2 = tds.at(1).toElement().text().replace(trUtf8("—"), "-"); - - if (v1 == "Name") { - QDomElement a = tds.at(1).toElement().elementsByTagName("a").at(0).toElement(); - QString href = a.attributes().namedItem("href").nodeValue(); - cardId = href.mid(href.indexOf("multiverseid=") + 13).toInt(); - cardName = v2.simplified(); - } else if (v1 == "Cost:") - cardCost = v2.simplified(); - else if (v1 == "Type:") - cardType = v2.simplified(); - else if (v1 == "Pow/Tgh:") - cardPT = v2.simplified().remove('(').remove(')'); - else if (v1 == "Rules Text:") - cardText = v2.trimmed(); - else if (v1 == "Loyalty:") - cardLoyalty = v2.trimmed().remove('(').remove(')').toInt(); - } - } - break; + CardInfo *card = addCard(set->getShortName(), cardName, false, cardId, cardCost, cardType, cardPT, cardLoyalty, cardTextSplit); + + if (!set->contains(card)) { + card->addToSet(set); + cards++; } - } + cardName = cardCost = cardType = cardPT = cardText = QString(); + } + return cards; } @@ -257,7 +221,7 @@ void OracleImporter::downloadNextFile() QString urlString = setsToDownload[setIndex].getUrl(); if (urlString.isEmpty()) urlString = setUrl; - urlString = urlString.replace("!longname!", setsToDownload[setIndex].getLongName()); + urlString = urlString.replace("!name!", setsToDownload[setIndex].getShortName()); if (urlString.startsWith("http://")) { QUrl url(urlString); From f8a6f7421193d78534ccabc7206cafe44c7cb71a Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 14 Jun 2014 11:34:52 +0200 Subject: [PATCH 09/24] Corrections to sets.xml for mtgjson.com MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Used http://www.woogerworks.com/files/sets.xml as a base * update version * use mtgjson.com as source * adapted some sets name (es: 6E => 6ED) Caveats: * Not all previous sets are present (e.g.: WOTC, WMCQ, WRL); they were not present in woogerworks’s sets.xml anyway --- doc/sets.xml | 688 ++++++++++++++++++++++----------------------------- 1 file changed, 290 insertions(+), 398 deletions(-) diff --git a/doc/sets.xml b/doc/sets.xml index 1afa3958..92bf1b21 100644 --- a/doc/sets.xml +++ b/doc/sets.xml @@ -1,333 +1,253 @@ - + http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=!cardid!&type=card -http://gatherer.wizards.com/Pages/Search/Default.aspx?output=spoiler&method=text&set=["!longname!"]&special=true - - 10E - Tenth Edition - - - 15ANN - 15th Anniversary - - - 4E - Fourth Edition - - - 5DN - Fifth Dawn - - - 5E - Fifth Edition - - - 6E - Classic Sixth Edition - - - 7E - Seventh Edition - - - 8EB - Eighth Edition Box Set - - - 8E - Eighth Edition - - - 9EB - Ninth Edition Box Set - - - 9E - Ninth Edition - - - AI - Alliances - - - ALA - Shards of Alara - - - AL - Limited Edition Alpha - - - AN - Arabian Nights - - - APAC - Asia Pacific Land Program - - - AP - Apocalypse - - - AQ - Antiquities - +http://mtgjson.com/json/!name!.json ARB Alara Reborn + ALL + Alliances + + + ATQ + Antiquities + + + APC + Apocalypse + + + ARN + Arabian Nights + + ARC Archenemy - - ARENA - Arena League - - - AT - Anthologies - AVR Avacyn Restored - - BD - Beatdown Box Set + + BRB + Battle Royale Box Set - - BE - Limited Edition Beta + + BTD + Beatdown Box Set BOK Betrayers of Kamigawa - BR - Battle Royale Box Set - - - CED - Collector's Edition - - - CEDI - International Collectors' Edition - - - CFX - Conflux - - - CH - Chronicles + BNG + Born of the Gods CHK Champions of Kamigawa - CMA - Commander's Arsenal + CHR + Chronicles - CMD - Commander + 6ED + Classic Sixth Edition - CP - Champs - - - CS + CSP Coldsnap - CSTD - Coldsnap Theme Decks + CON + Conflux + + + CMA + Commander's Arsenal + + ^M + C13^M + Commander 2013 Edition^M - DCILM - Legend Membership - - - DDF - Duel Decks: Elspeth vs. Tezzeret - - - DDG - Duel Decks: Knights vs. Dragons - - - DDH - Duel Decks: Ajani vs. Nicol Bolas - - - DDI - Duel Decks: Venser vs. Koth - - - DDJ - Duel Decks: Izzet vs. Golgari - - - DDK - Duel Decks: Sorin vs. Tibalt - - - DGM - Dragon's Maze - - - DI - Dissension + DST + Darksteel DKA Dark Ascension - DK - The Dark + DIS + Dissension - DM - Deckmasters + DGM + Dragon's Maze - - DPA - Duels of the Planeswalkers + + DDH + Duel Decks: Ajani vs. Nicol Bolas - - DRC - Dragon Con - - - DS - Darksteel - - - DVD + + DDC Duel Decks: Divine vs. Demonic + + DDF + Duel Decks: Elspeth vs. Tezzeret + + + EVG + Duel Decks: Elves vs. Goblins + + + DDD + Duel Decks: Garruk vs. Liliana + + + DDL + Duel Decks: Heroes vs. Monsters + + + DDJ + Duel Decks: Izzet vs. Golgari + + + DD2 + Duel Decks: Jace vs. Chandra + + + DDM + Duel Decks: Jace vs. Vraska + + + DDG + Duel Decks: Knights vs. Dragons + + + DDE + Duel Decks: Phyrexia vs. the Coalition + + + DDK + Duel Decks: Sorin vs. Tibalt + + + DDI + Duel Decks: Venser vs. Koth + - EURO - European Land Program + 8ED + Eighth Edition EVE Eventide - EVG - Duel Decks: Elves vs. Goblins - - - EX + EXO Exodus - FE + FEM Fallen Empires - FNMP - Friday Night Magic + 5DN + Fifth Dawn + + + 5ED + Fifth Edition + + + 4ED + Fourth Edition + + + DRB + From the Vault: Dragons + + + V09 + From the Vault: Exiled + + + V11 + From the Vault: Legends + + + V12 + From the Vault: Realms + + + V10 + From the Vault: Relics + + + V13 + From the Vault: Twenty FUT Future Sight - FVD - From the Vault: Dragons - - - FVE - From the Vault: Exiled - - - FVL - From the Vault: Legends - - - FVR - From the Vault: Relics - - - GP + GPT Guildpact - - GPX - Grand Prix - - - GRC - WPN/Gateway - GTC Gatecrash - GURU - Guru - - - GVL - Duel Decks: Garruk vs. Liliana - - - HHO - Happy Holidays - - - HL + HML Homelands - IA + ICE Ice Age - - IN - Invasion - ISD Innistrad - ITP - Introductory Two-Player Set + INV + Invasion - JR - Judge Gift Program + JOU + Journey into Nyx - JU + JUD Judgment - JVC - Duel Decks: Jace vs. Chandra - - - LE - Legions - - - LG + LEG Legends - LW + LGN + Legions + + + LEA + Limited Edition Alpha + + + LEB + Limited Edition Beta + + + LRW Lorwyn @@ -347,63 +267,59 @@ Magic 2013 - MBP - Media Inserts + M14 + Magic 2014 Core Set + + + CMD + Magic: The Gathering-Commander + + + CNS + Magic: The Gathering—Conspiracy + + + MED + Masters Edition + + + ME2 + Masters Edition II + + + ME3 + Masters Edition III + + + ME4 + Masters Edition IV + + + MMQ + Mercadian Masques + + + MIR + Mirage + + + MRD + Mirrodin MBS Mirrodin Besieged + ^M + MMA^M + Modern Masters^M + ^ - ME2 - MTGO Masters Edition II - - - ME3 - MTGO Masters Edition III - - - ME4 - MTGO Masters Edition IV - - - MED - MTGO Masters Edition - - - MGBC - Multiverse Gift Box Cards - - - MGDC - Magic Game Day Cards - - - MI - Mirrodin - - - MLP - Magic: The Gathering Launch Parties - - - MM - Mercadian Masques - - - MPRP - Magic Player Rewards - - - MR - Mirage - - - MT + MOR Morningtide - NE + NMS Nemesis @@ -411,104 +327,80 @@ New Phyrexia - OD + 9ED + Ninth Edition + + + ODY Odyssey - ON + ONS Onslaught - P3K - Portal Three Kingdoms + PLC + Planar Chaos - + + HOP + Planechase + + PC2 Planechase 2012 Edition - PC - Planar Chaos + PLS + Planeshift - PCH - Planechase - - - PD2 - Premium Deck Series: Fire and Lightning - - - PD3 - Premium Deck Series: Graveborn - - - PDS - Premium Deck Series: Slivers + POR + Portal PO2 Portal Second Age - PO - Portal + PTK + Portal Three Kingdoms + + + PD2 + Premium Deck Series: Fire and Lightning + + + PD3 + Premium Deck Series: Graveborn + + + H09 + Premium Deck Series: Slivers + + + PPR + Promo set for Gatherer - POT - Portal Demogame - - - PR + PCY Prophecy - - PRO - Pro Tour - - - PS - Planeshift - - - PTC - Prerelease Events - - - PVC - Duel Decks: Phyrexia vs. The Coalition - RAV Ravnica: City of Guilds - - REP - Release Events - - - ROE - Rise of the Eldrazi - RTR Return to Ravnica - RV + 3ED Revised Edition - SC - Scourge - - - SH - Stronghold - - - SHM - Shadowmoor + ROE + Rise of the Eldrazi SOK @@ -519,97 +411,97 @@ Scars of Mirrodin - ST2K - Starter 2000 + SCG + Scourge - ST + 7ED + Seventh Edition + + + SHM + Shadowmoor + + + ALA + Shards of Alara + + + S99 Starter 1999 - SUM - Summer of Magic + S00 + Starter 2000 - SUS - Super Series + STH + Stronghold - THGT - Two-Headed Giant Tournament - - - TP + TMP Tempest - TR - Torment + 10E + Tenth Edition - TS + DRK + The Dark + + + THS + Theros + + + TSP Time Spiral - TSTS + TSB Time Spiral "Timeshifted" - UD - Urza's Destiny + TOR + Torment - - UG + + UGL Unglued - - UHAA - Unhinged Alternate Foils - - - UH + + UNH Unhinged - UL - Urza's Legacy - - - UN + 2ED Unlimited Edition - UQC - Celebration Cards + UDS + Urza's Destiny - US + ULG + Urza's Legacy + + + USG Urza's Saga - - V12 - From the Vault: Realms + + VAN + Vanguard - VI + VIS Visions - WL + WTH Weatherlight - - WMCQ - World Magic Cup Qualifiers - - - WOTC - WotC Online Store - - - WRL - Worlds - WWK Worldwake From 4ff225cc3b1e232597f354bb187ed13122178dcb Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 14 Jun 2014 11:52:55 +0200 Subject: [PATCH 10/24] Fix import of P/T; misc optimizations --- oracle/src/oracleimporter.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/oracle/src/oracleimporter.cpp b/oracle/src/oracleimporter.cpp index 4d431e51..af310a46 100644 --- a/oracle/src/oracleimporter.cpp +++ b/oracle/src/oracleimporter.cpp @@ -157,15 +157,24 @@ int OracleImporter::importTextSpoiler(CardSet *set, const QByteArray &data) } QListIterator it(resultMap.value("cards").toList()); + QVariantMap map; + QString cardName; + QString cardCost; + QString cardType; + QString cardPT; + QString cardText; + int cardId; + int cardLoyalty; + while (it.hasNext()) { - QVariantMap map = it.next().toMap(); - QString cardName = map.value("name").toString(); - QString cardCost = map.value("manaCost").toString(); - QString cardType = map.value("type").toString(); - QString cardPT = map.value("power").toString() + QString('/') + map.value("toughness").toString(); - QString cardText = map.value("text").toString(); - int cardId = map.value("multiverseid").toInt(); - int cardLoyalty = map.value("loyalty").toInt(); + map = it.next().toMap(); + cardName = map.contains("name") ? map.value("name").toString() : QString(""); + cardCost = map.contains("manaCost") ? map.value("manaCost").toString() : QString(""); + cardType = map.contains("type") ? map.value("type").toString() : QString(""); + cardPT = map.contains("power") || map.contains("toughness") ? map.value("power").toString() + QString('/') + map.value("toughness").toString() : QString(""); + cardText = map.contains("text") ? map.value("text").toString() : QString(""); + cardId = map.contains("multiverseid") ? map.value("multiverseid").toInt() : 0; + cardLoyalty = map.contains("loyalty") ? map.value("loyalty").toInt() : 0; QStringList cardTextSplit = cardText.split("\n"); CardInfo *card = addCard(set->getShortName(), cardName, false, cardId, cardCost, cardType, cardPT, cardLoyalty, cardTextSplit); @@ -174,7 +183,6 @@ int OracleImporter::importTextSpoiler(CardSet *set, const QByteArray &data) card->addToSet(set); cards++; } - cardName = cardCost = cardType = cardPT = cardText = QString(); } return cards; From f562f3ef06f6c7443a724cc62a66f10749019e0a Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 14 Jun 2014 12:02:34 +0200 Subject: [PATCH 11/24] Use mtgimage.com for card images --- doc/sets.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sets.xml b/doc/sets.xml index 92bf1b21..639cbdfc 100644 --- a/doc/sets.xml +++ b/doc/sets.xml @@ -1,6 +1,6 @@ -http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=!cardid!&type=card +http://mtgimage.com/multiverseid/!cardid!.jpg http://mtgjson.com/json/!name!.json ARB From 62cfa74d0899dca2d2a964d7f1b884ca8506f525 Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 14 Jun 2014 12:11:03 +0200 Subject: [PATCH 12/24] Keep gatherer as image source; mtgimage as a hq alternative --- doc/sets.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/sets.xml b/doc/sets.xml index 639cbdfc..bcc7c20e 100644 --- a/doc/sets.xml +++ b/doc/sets.xml @@ -1,6 +1,7 @@ -http://mtgimage.com/multiverseid/!cardid!.jpg +http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=!cardid!&type=card + http://mtgjson.com/json/!name!.json ARB From 0d3ec71e8fc57756be06fe14de3b3f29f5fb480d Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 14 Jun 2014 16:47:36 +0200 Subject: [PATCH 13/24] Merge splitter cards into a single card --- oracle/src/oracleimporter.cpp | 98 ++++++++++++++++++++++++++--------- 1 file changed, 74 insertions(+), 24 deletions(-) diff --git a/oracle/src/oracleimporter.cpp b/oracle/src/oracleimporter.cpp index af310a46..4adfb1a8 100644 --- a/oracle/src/oracleimporter.cpp +++ b/oracle/src/oracleimporter.cpp @@ -148,44 +148,94 @@ CardInfo *OracleImporter::addCard(const QString &setName, int OracleImporter::importTextSpoiler(CardSet *set, const QByteArray &data) { - int cards = 0; + int cards = 0; bool ok; QVariantMap resultMap = QtJson::Json::parse(QString(data), ok).toMap(); if (!ok) { - qDebug() << "error: QtJson::Json::parse()"; + qDebug() << "error: QtJson::Json::parse()"; return 0; } QListIterator it(resultMap.value("cards").toList()); QVariantMap map; - QString cardName; - QString cardCost; - QString cardType; - QString cardPT; - QString cardText; - int cardId; - int cardLoyalty; + QString cardName; + QString cardCost; + QString cardType; + QString cardPT; + QString cardText; + int cardId; + int cardLoyalty; + QMap splitCards; while (it.hasNext()) { map = it.next().toMap(); - cardName = map.contains("name") ? map.value("name").toString() : QString(""); - cardCost = map.contains("manaCost") ? map.value("manaCost").toString() : QString(""); - cardType = map.contains("type") ? map.value("type").toString() : QString(""); - cardPT = map.contains("power") || map.contains("toughness") ? map.value("power").toString() + QString('/') + map.value("toughness").toString() : QString(""); - cardText = map.contains("text") ? map.value("text").toString() : QString(""); - cardId = map.contains("multiverseid") ? map.value("multiverseid").toInt() : 0; - cardLoyalty = map.contains("loyalty") ? map.value("loyalty").toInt() : 0; - QStringList cardTextSplit = cardText.split("\n"); + if(0 == QString::compare(map.value("layout").toString(), QString("split"), Qt::CaseInsensitive)) + { + // Split card handling + cardId = map.contains("multiverseid") ? map.value("multiverseid").toInt() : 0; + if(splitCards.contains(cardId)) + { + // merge two split cards + QVariantMap tmpMap = splitCards.take(cardId); + QVariantMap * card1 = 0, * card2 = 0; + // same cardid + cardId = map.contains("multiverseid") ? map.value("multiverseid").toInt() : 0; + // this is currently an integer; can't accept 2 values + cardLoyalty = 0; - CardInfo *card = addCard(set->getShortName(), cardName, false, cardId, cardCost, cardType, cardPT, cardLoyalty, cardTextSplit); + // determine which subcard is the first one in the split + QStringList names=map.contains("names") ? map.value("names").toStringList() : QStringList(""); + if(names.count()>0 && + map.contains("name") && + 0 == QString::compare(map.value("name").toString(), names.at(0))) + { + // map is the left part of the split card, tmpMap is right part + card1 = ↦ + card2 = &tmpMap; + } else { + //tmpMap is the left part of the split card, map is right part + card1 = &tmpMap; + card2 = ↦ + } - if (!set->contains(card)) { - card->addToSet(set); - cards++; - } + // add first card's data + cardName = card1->contains("name") ? card1->value("name").toString() : QString(""); + cardCost = card1->contains("manaCost") ? card1->value("manaCost").toString() : QString(""); + cardType = card1->contains("type") ? card1->value("type").toString() : QString(""); + cardPT = card1->contains("power") || card1->contains("toughness") ? card1->value("power").toString() + QString('/') + card1->value("toughness").toString() : QString(""); + cardText = card1->contains("text") ? card1->value("text").toString() : QString(""); + + // add second card's data + cardName += card2->contains("name") ? QString(" // ") + card2->value("name").toString() : QString(""); + cardCost += card2->contains("manaCost") ? QString(" // ") + card2->value("manaCost").toString() : QString(""); + cardType += card2->contains("type") ? QString(" // ") + card2->value("type").toString() : QString(""); + cardPT += card2->contains("power") || card2->contains("toughness") ? QString(" // ") + card2->value("power").toString() + QString('/') + card2->value("toughness").toString() : QString(""); + cardText += card2->contains("text") ? QString("\n\n---\n\n") + card2->value("text").toString() : QString(""); + } else { + // first card od a pair; enqueue for later merging + splitCards.insert(cardId, map); + continue; + } + } else { + // normal cards handling + cardName = map.contains("name") ? map.value("name").toString() : QString(""); + cardCost = map.contains("manaCost") ? map.value("manaCost").toString() : QString(""); + cardType = map.contains("type") ? map.value("type").toString() : QString(""); + cardPT = map.contains("power") || map.contains("toughness") ? map.value("power").toString() + QString('/') + map.value("toughness").toString() : QString(""); + cardText = map.contains("text") ? map.value("text").toString() : QString(""); + cardId = map.contains("multiverseid") ? map.value("multiverseid").toInt() : 0; + cardLoyalty = map.contains("loyalty") ? map.value("loyalty").toInt() : 0; + } + + CardInfo *card = addCard(set->getShortName(), cardName, false, cardId, cardCost, cardType, cardPT, cardLoyalty, cardText.split("\n")); + + if (!set->contains(card)) { + card->addToSet(set); + cards++; + } } - - return cards; + + return cards; } QString OracleImporter::getPictureUrl(QString url, int cardId, QString name, const QString &setName) const From f3a57d5506cf4ea9a680c4f2bd8a48e32348295b Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Mon, 16 Jun 2014 00:27:33 +0200 Subject: [PATCH 14/24] Import data from mtgjson's allsets.xml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add multiverse id to cards.xml * remove pictures urls from cards.xml TBD: * fix/clean oracle’s gui * add support in cockatrice --- cockatrice/src/carddatabase.cpp | 23 +- cockatrice/src/carddatabase.h | 3 + oracle/src/oracleimporter.cpp | 395 +++++++++++++------------------- oracle/src/oracleimporter.h | 32 +-- oracle/src/window_main.cpp | 8 +- 5 files changed, 193 insertions(+), 268 deletions(-) diff --git a/cockatrice/src/carddatabase.cpp b/cockatrice/src/carddatabase.cpp index e5c60e52..748d8197 100644 --- a/cockatrice/src/carddatabase.cpp +++ b/cockatrice/src/carddatabase.cpp @@ -406,12 +406,27 @@ QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info) xml.writeTextElement("name", info->getName()); const SetList &sets = info->getSets(); + QString tmpString; + QString tmpSet; for (int i = 0; i < sets.size(); i++) { xml.writeStartElement("set"); - xml.writeAttribute("picURL", info->getPicURL(sets[i]->getShortName())); - xml.writeAttribute("picURLHq", info->getPicURLHq(sets[i]->getShortName())); - xml.writeAttribute("picURLSt", info->getPicURLSt(sets[i]->getShortName())); - xml.writeCharacters(sets[i]->getShortName()); + + tmpSet=sets[i]->getShortName(); + xml.writeAttribute("muId", QString::number(info->getMuId(tmpSet))); + + tmpString = info->getPicURL(tmpSet); + if(!tmpString.isEmpty()) + xml.writeAttribute("picURL", tmpString); + + tmpString = info->getPicURLHq(tmpSet); + if(!tmpString.isEmpty()) + xml.writeAttribute("picURLHq", tmpString); + + tmpString = info->getPicURLSt(tmpSet); + if(!tmpString.isEmpty()) + xml.writeAttribute("picURLSt", tmpString); + + xml.writeCharacters(tmpSet); xml.writeEndElement(); } const QStringList &colors = info->getColors(); diff --git a/cockatrice/src/carddatabase.h b/cockatrice/src/carddatabase.h index 9d3f33f3..987848d3 100644 --- a/cockatrice/src/carddatabase.h +++ b/cockatrice/src/carddatabase.h @@ -100,6 +100,7 @@ private: QStringList colors; int loyalty; QMap picURLs, picURLsHq, picURLsSt; + QMap muIds; bool cipt; int tableRow; QPixmap *pixmap; @@ -139,6 +140,7 @@ public: QString getPicURL(const QString &set) const { return picURLs.value(set); } QString getPicURLHq(const QString &set) const { return picURLsHq.value(set); } QString getPicURLSt(const QString &set) const { return picURLsSt.value(set); } + int getMuId(const QString &set) const { return muIds.value(set); } QString getPicURL() const; const QMap &getPicURLs() const { return picURLs; } QString getMainCardType() const; @@ -149,6 +151,7 @@ public: void setPicURL(const QString &_set, const QString &_picURL) { picURLs.insert(_set, _picURL); } void setPicURLHq(const QString &_set, const QString &_picURL) { picURLsHq.insert(_set, _picURL); } void setPicURLSt(const QString &_set, const QString &_picURL) { picURLsSt.insert(_set, _picURL); } + void setMuId(const QString &_set, const int &_muId) { muIds.insert(_set, _muId); } void addToSet(CardSet *set); QPixmap *loadPixmap(); QPixmap *getPixmap(QSize size); diff --git a/oracle/src/oracleimporter.cpp b/oracle/src/oracleimporter.cpp index 4adfb1a8..b3aa5e44 100644 --- a/oracle/src/oracleimporter.cpp +++ b/oracle/src/oracleimporter.cpp @@ -1,162 +1,138 @@ #include "oracleimporter.h" #include -#include -#include -#include #include #include "qt-json/json.h" OracleImporter::OracleImporter(const QString &_dataDir, QObject *parent) - : CardDatabase(parent), dataDir(_dataDir), setIndex(-1) + : CardDatabase(parent), dataDir(_dataDir) { - buffer = new QBuffer(this); - http = new QHttp(this); - connect(http, SIGNAL(requestFinished(int, bool)), this, SLOT(httpRequestFinished(int, bool))); - connect(http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)), this, SLOT(readResponseHeader(const QHttpResponseHeader &))); - connect(http, SIGNAL(dataReadProgress(int, int)), this, SIGNAL(dataReadProgress(int, int))); } bool OracleImporter::readSetsFromFile(const QString &fileName) { - QFile setsFile(fileName); - if (!setsFile.open(QIODevice::ReadOnly | QIODevice::Text)) { - QMessageBox::critical(0, tr("Error"), tr("Cannot open file '%1'.").arg(fileName)); - return false; - } + QFile setsFile(fileName); + if (!setsFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox::critical(0, tr("Error"), tr("Cannot open file '%1'.").arg(fileName)); + return false; + } - QXmlStreamReader xml(&setsFile); - return readSetsFromXml(xml); + return readSetsFromByteArray(setsFile.readAll()); } bool OracleImporter::readSetsFromByteArray(const QByteArray &data) { - QXmlStreamReader xml(data); - return readSetsFromXml(xml); -} - -bool OracleImporter::readSetsFromXml(QXmlStreamReader &xml) -{ - QList newSetList; - - QString edition; - QString editionLong; - QString editionURL; - while (!xml.atEnd()) { - if (xml.readNext() == QXmlStreamReader::EndElement) - break; - if (xml.name() == "set") { - bool import = xml.attributes().value("import").toString().toInt(); - while (!xml.atEnd()) { - if (xml.readNext() == QXmlStreamReader::EndElement) - break; - if (xml.name() == "name") - edition = xml.readElementText(); - else if (xml.name() == "longname") - editionLong = xml.readElementText(); - else if (xml.name() == "url") - editionURL = xml.readElementText(); - } - newSetList.append(SetToDownload(edition, editionLong, editionURL, import)); - edition = editionLong = editionURL = QString(); - } else if (xml.name() == "picture_url") - pictureUrl = xml.readElementText(); - else if (xml.name() == "picture_url_hq") - pictureUrlHq = xml.readElementText(); - else if (xml.name() == "picture_url_st") - pictureUrlSt = xml.readElementText(); - else if (xml.name() == "set_url") - setUrl = xml.readElementText(); - } - if (newSetList.isEmpty()) - return false; - allSets = newSetList; - return true; -} - -CardInfo *OracleImporter::addCard(const QString &setName, - QString cardName, - bool isToken, - int cardId, - const QString &cardCost, - const QString &cardType, - const QString &cardPT, - int cardLoyalty, - const QStringList &cardText) -{ - QString fullCardText = cardText.join("\n"); - bool splitCard = false; - if (cardName.contains('(')) { - cardName.remove(QRegExp(" \\(.*\\)")); - splitCard = true; - } - // Workaround for card name weirdness - if (cardName.contains("XX")) - cardName.remove("XX"); - cardName = cardName.replace("Æ", "AE"); - cardName = cardName.replace("’", "'"); - - CardInfo *card; - if (cardHash.contains(cardName)) { - card = cardHash.value(cardName); - if (splitCard && !card->getText().contains(fullCardText)) - card->setText(card->getText() + "\n---\n" + fullCardText); - } else { - bool mArtifact = false; - if (cardType.endsWith("Artifact")) - for (int i = 0; i < cardText.size(); ++i) - if (cardText[i].contains("{T}") && cardText[i].contains("to your mana pool")) - mArtifact = true; - - QStringList colors; - QStringList allColors = QStringList() << "W" << "U" << "B" << "R" << "G"; - for (int i = 0; i < allColors.size(); i++) - if (cardCost.contains(allColors[i])) - colors << allColors[i]; - - if (cardText.contains(cardName + " is white.")) - colors << "W"; - if (cardText.contains(cardName + " is blue.")) - colors << "U"; - if (cardText.contains(cardName + " is black.")) - colors << "B"; - if (cardText.contains(cardName + " is red.")) - colors << "R"; - if (cardText.contains(cardName + " is green.")) - colors << "G"; - - bool cipt = (cardText.contains(cardName + " enters the battlefield tapped.")); - - card = new CardInfo(this, cardName, isToken, cardCost, cardType, cardPT, fullCardText, colors, cardLoyalty, cipt); - int tableRow = 1; - QString mainCardType = card->getMainCardType(); - if ((mainCardType == "Land") || mArtifact) - tableRow = 0; - else if ((mainCardType == "Sorcery") || (mainCardType == "Instant")) - tableRow = 3; - else if (mainCardType == "Creature") - tableRow = 2; - card->setTableRow(tableRow); - - cardHash.insert(cardName, card); - } - card->setPicURL(setName, getPictureUrl(pictureUrl, cardId, cardName, setName)); - card->setPicURLHq(setName, getPictureUrl(pictureUrlHq, cardId, cardName, setName)); - card->setPicURLSt(setName, getPictureUrl(pictureUrlSt, cardId, cardName, setName)); - return card; -} - -int OracleImporter::importTextSpoiler(CardSet *set, const QByteArray &data) -{ - int cards = 0; + QList newSetList; + bool ok; - QVariantMap resultMap = QtJson::Json::parse(QString(data), ok).toMap(); + setsMap = QtJson::Json::parse(QString(data), ok).toMap(); if (!ok) { qDebug() << "error: QtJson::Json::parse()"; return 0; } - QListIterator it(resultMap.value("cards").toList()); + QListIterator it(setsMap.values()); + QVariantMap map; + + QString edition; + QString editionLong; + QVariant editionCards; + bool import; + + while (it.hasNext()) { + map = it.next().toMap(); + edition = map.value("code").toString(); + editionLong = map.value("name").toString(); + editionCards = map.value("cards"); + + // core and expansion sets are marked to be imported by default + import = (0 == QString::compare(map.value("type").toString(), QString("core"), Qt::CaseInsensitive) || + 0 == QString::compare(map.value("type").toString(), QString("expansion"), Qt::CaseInsensitive)); + + newSetList.append(SetToDownload(edition, editionLong, editionCards, import)); + } + if (newSetList.isEmpty()) + return false; + allSets = newSetList; + return true; +} + +CardInfo *OracleImporter::addCard(const QString &setName, + QString cardName, + bool isToken, + int cardId, + const QString &cardCost, + const QString &cardType, + const QString &cardPT, + int cardLoyalty, + const QStringList &cardText) +{ + QString fullCardText = cardText.join("\n"); + bool splitCard = false; + if (cardName.contains('(')) { + cardName.remove(QRegExp(" \\(.*\\)")); + splitCard = true; + } + // Workaround for card name weirdness + if (cardName.contains("XX")) + cardName.remove("XX"); + cardName = cardName.replace("Æ", "AE"); + cardName = cardName.replace("’", "'"); + + CardInfo *card; + if (cardHash.contains(cardName)) { + card = cardHash.value(cardName); + if (splitCard && !card->getText().contains(fullCardText)) + card->setText(card->getText() + "\n---\n" + fullCardText); + } else { + bool mArtifact = false; + if (cardType.endsWith("Artifact")) + for (int i = 0; i < cardText.size(); ++i) + if (cardText[i].contains("{T}") && cardText[i].contains("to your mana pool")) + mArtifact = true; + + QStringList colors; + QStringList allColors = QStringList() << "W" << "U" << "B" << "R" << "G"; + for (int i = 0; i < allColors.size(); i++) + if (cardCost.contains(allColors[i])) + colors << allColors[i]; + + if (cardText.contains(cardName + " is white.")) + colors << "W"; + if (cardText.contains(cardName + " is blue.")) + colors << "U"; + if (cardText.contains(cardName + " is black.")) + colors << "B"; + if (cardText.contains(cardName + " is red.")) + colors << "R"; + if (cardText.contains(cardName + " is green.")) + colors << "G"; + + bool cipt = (cardText.contains(cardName + " enters the battlefield tapped.")); + + card = new CardInfo(this, cardName, isToken, cardCost, cardType, cardPT, fullCardText, colors, cardLoyalty, cipt); + int tableRow = 1; + QString mainCardType = card->getMainCardType(); + if ((mainCardType == "Land") || mArtifact) + tableRow = 0; + else if ((mainCardType == "Sorcery") || (mainCardType == "Instant")) + tableRow = 3; + else if (mainCardType == "Creature") + tableRow = 2; + card->setTableRow(tableRow); + + cardHash.insert(cardName, card); + } + card->setMuId(setName, cardId); + + return card; +} + +int OracleImporter::importTextSpoiler(CardSet *set, const QVariant &data) +{ + int cards = 0; + + QListIterator it(data.toList()); QVariantMap map; QString cardName; QString cardCost; @@ -237,111 +213,52 @@ int OracleImporter::importTextSpoiler(CardSet *set, const QByteArray &data) return cards; } - +/* QString OracleImporter::getPictureUrl(QString url, int cardId, QString name, const QString &setName) const { - if ((name == "Island") || (name == "Swamp") || (name == "Mountain") || (name == "Plains") || (name == "Forest")) - name.append("1"); - return url.replace("!cardid!", QString::number(cardId)).replace("!set!", setName).replace("!name!", name - .replace("ö", "o") -// .remove('\'') - .remove(" // ") -// .remove(',') -// .remove(':') -// .remove('.') - .remove(QRegExp("\\(.*\\)")) - .simplified() -// .replace(' ', '_') -// .replace('-', '_') - ); + if ((name == "Island") || (name == "Swamp") || (name == "Mountain") || (name == "Plains") || (name == "Forest")) + name.append("1"); + return url.replace("!cardid!", QString::number(cardId)).replace("!set!", setName).replace("!name!", name + .replace("ö", "o") +// .remove('\'') + .remove(" // ") +// .remove(',') +// .remove(':') +// .remove('.') + .remove(QRegExp("\\(.*\\)")) + .simplified() +// .replace(' ', '_') +// .replace('-', '_') + ); } - -int OracleImporter::startDownload() +*/ +int OracleImporter::startImport() { - clear(); - - setsToDownload.clear(); - for (int i = 0; i < allSets.size(); ++i) - if (allSets[i].getImport()) - setsToDownload.append(allSets[i]); - - if (setsToDownload.isEmpty()) - return 0; - setIndex = 0; - emit setIndexChanged(0, 0, setsToDownload[0].getLongName()); - - downloadNextFile(); - return setsToDownload.size(); -} - -void OracleImporter::downloadNextFile() -{ - QString urlString = setsToDownload[setIndex].getUrl(); - if (urlString.isEmpty()) - urlString = setUrl; - urlString = urlString.replace("!name!", setsToDownload[setIndex].getShortName()); - - if (urlString.startsWith("http://")) { - QUrl url(urlString); - http->setHost(url.host(), QHttp::ConnectionModeHttp, url.port() == -1 ? 0 : url.port()); - QString path = QUrl::toPercentEncoding(urlString.mid(url.host().size() + 7).replace(' ', '+'), "?!$&'()*+,;=:@/"); - - buffer->close(); - buffer->setData(QByteArray()); - buffer->open(QIODevice::ReadWrite | QIODevice::Text); - reqId = http->get(path, buffer); - } else { - QFile file(dataDir + "/" + urlString); - file.open(QIODevice::ReadOnly | QIODevice::Text); - - buffer->close(); - buffer->setData(file.readAll()); - buffer->open(QIODevice::ReadWrite | QIODevice::Text); - reqId = 0; - httpRequestFinished(reqId, false); - } -} - -void OracleImporter::httpRequestFinished(int requestId, bool error) -{ - if (error) { - QMessageBox::information(0, tr("HTTP"), tr("Error.")); - return; - } - if (requestId != reqId) - return; - - CardSet *set = new CardSet(setsToDownload[setIndex].getShortName(), setsToDownload[setIndex].getLongName()); - if (!setHash.contains(set->getShortName())) - setHash.insert(set->getShortName(), set); - - buffer->seek(0); - buffer->close(); - int cards = importTextSpoiler(set, buffer->data()); - if (cards > 0) - ++setIndex; - - if (setIndex == setsToDownload.size()) { - emit setIndexChanged(cards, setIndex, QString()); - setIndex = -1; - } else { - downloadNextFile(); - emit setIndexChanged(cards, setIndex, setsToDownload[setIndex].getLongName()); - } -} - -void OracleImporter::readResponseHeader(const QHttpResponseHeader &responseHeader) -{ - switch (responseHeader.statusCode()) { - case 200: - case 301: - case 302: - case 303: - case 307: - break; - default: - QMessageBox::information(0, tr("HTTP"), tr("Download failed: %1.").arg(responseHeader.reasonPhrase())); - http->abort(); - deleteLater(); - } + clear(); + + int setCards = 0, setIndex= 0; + QListIterator it(allSets); + const SetToDownload * curSet; + + while (it.hasNext()) + { + curSet = & it.next(); + + emit setIndexChanged(0, 0, curSet->getLongName()); + + CardSet *set = new CardSet(curSet->getShortName(), curSet->getLongName()); + if (!setHash.contains(set->getShortName())) + setHash.insert(set->getShortName(), set); + + int setCards = importTextSpoiler(set, curSet->getCards()); + + ++setIndex; + + emit setIndexChanged(setCards, setIndex, curSet->getLongName()); + } + + emit setIndexChanged(setCards, setIndex, QString()); + + // total number of sets + return setIndex; } diff --git a/oracle/src/oracleimporter.h b/oracle/src/oracleimporter.h index 3e03586f..76989933 100644 --- a/oracle/src/oracleimporter.h +++ b/oracle/src/oracleimporter.h @@ -1,44 +1,34 @@ #ifndef ORACLEIMPORTER_H #define ORACLEIMPORTER_H -#include -#include +#include -class QBuffer; -class QXmlStreamReader; +#include class SetToDownload { private: - QString shortName, longName, url; + QString shortName, longName; bool import; + QVariant cards; public: const QString &getShortName() const { return shortName; } const QString &getLongName() const { return longName; } - const QString &getUrl() const { return url; } + const QVariant &getCards() const { return cards; } bool getImport() const { return import; } void setImport(bool _import) { import = _import; } - SetToDownload(const QString &_shortName, const QString &_longName, const QString &_url, bool _import) - : shortName(_shortName), longName(_longName), url(_url), import(_import) { } + SetToDownload(const QString &_shortName, const QString &_longName, const QVariant &_cards, bool _import) + : shortName(_shortName), longName(_longName), cards(_cards), import(_import) { } }; class OracleImporter : public CardDatabase { Q_OBJECT private: - QList allSets, setsToDownload; - QString pictureUrl, pictureUrlHq, pictureUrlSt, setUrl; + QList allSets; + QVariantMap setsMap; QString dataDir; - int setIndex; - int reqId; - QBuffer *buffer; - QHttp *http; - QString getPictureUrl(QString url, int cardId, QString name, const QString &setName) const; void downloadNextFile(); - bool readSetsFromXml(QXmlStreamReader &xml); CardInfo *addCard(const QString &setName, QString cardName, bool isToken, int cardId, const QString &cardCost, const QString &cardType, const QString &cardPT, int cardLoyalty, const QStringList &cardText); -private slots: - void httpRequestFinished(int requestId, bool error); - void readResponseHeader(const QHttpResponseHeader &responseHeader); signals: void setIndexChanged(int cardsImported, int setIndex, const QString &nextSetName); void dataReadProgress(int bytesRead, int totalBytes); @@ -46,8 +36,8 @@ public: OracleImporter(const QString &_dataDir, QObject *parent = 0); bool readSetsFromByteArray(const QByteArray &data); bool readSetsFromFile(const QString &fileName); - int startDownload(); - int importTextSpoiler(CardSet *set, const QByteArray &data); + int startImport(); + int importTextSpoiler(CardSet *set, const QVariant &data); QList &getSets() { return allSets; } const QString &getDataDir() const { return dataDir; } }; diff --git a/oracle/src/window_main.cpp b/oracle/src/window_main.cpp index 0283bded..24d79b4f 100644 --- a/oracle/src/window_main.cpp +++ b/oracle/src/window_main.cpp @@ -19,7 +19,7 @@ #include "window_main.h" #include "oracleimporter.h" -const QString WindowMain::defaultSetsUrl = QString("http://www.woogerworks.com/files/sets.xml"); +const QString WindowMain::defaultSetsUrl = QString("http://mtgjson.com/json/AllSets.json"); WindowMain::WindowMain(QWidget *parent) : QMainWindow(parent) @@ -45,7 +45,7 @@ WindowMain::WindowMain(QWidget *parent) checkAllButtonLayout->addWidget(checkAllButton); checkAllButtonLayout->addWidget(uncheckAllButton); - startButton = new QPushButton(tr("&Start download")); + startButton = new QPushButton(tr("&Start import")); connect(startButton, SIGNAL(clicked()), this, SLOT(actStart())); QVBoxLayout *settingsLayout = new QVBoxLayout; @@ -130,7 +130,7 @@ void WindowMain::actLoadSetsFile() { QFileDialog dialog(this, tr("Load sets file")); dialog.setFileMode(QFileDialog::ExistingFile); - dialog.setNameFilter("Sets XML file (*.xml)"); + dialog.setNameFilter("Sets JSON file (*.json)"); if (!dialog.exec()) return; @@ -224,7 +224,7 @@ void WindowMain::actUncheckAll() void WindowMain::actStart() { - int setsCount = importer->startDownload(); + int setsCount = importer->startImport(); if (!setsCount) { QMessageBox::critical(this, tr("Error"), tr("No sets to download selected.")); return; From 40f9536224c26c5e66d2885f2b86ba2424d2f2a0 Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Thu, 19 Jun 2014 16:49:38 +0200 Subject: [PATCH 15/24] Rewrite oracle as a wizard --- oracle/CMakeLists.txt | 2 +- oracle/src/main.cpp | 13 +- oracle/src/oracleimporter.cpp | 18 +- oracle/src/oracleimporter.h | 5 +- oracle/src/oraclewizard.cpp | 392 ++++++++++++++++++++++++++++++++++ oracle/src/oraclewizard.h | 111 ++++++++++ oracle/src/window_main.cpp | 248 --------------------- oracle/src/window_main.h | 52 ----- 8 files changed, 518 insertions(+), 323 deletions(-) create mode 100644 oracle/src/oraclewizard.cpp create mode 100644 oracle/src/oraclewizard.h delete mode 100644 oracle/src/window_main.cpp delete mode 100644 oracle/src/window_main.h diff --git a/oracle/CMakeLists.txt b/oracle/CMakeLists.txt index 8e1f9b16..031f38e4 100644 --- a/oracle/CMakeLists.txt +++ b/oracle/CMakeLists.txt @@ -9,8 +9,8 @@ set(DESKTOPDIR share/applications CACHE STRING "path to .desktop files") SET(oracle_SOURCES src/main.cpp + src/oraclewizard.cpp src/oracleimporter.cpp - src/window_main.cpp ../cockatrice/src/carddatabase.cpp ../cockatrice/src/settingscache.cpp ../cockatrice/src/qt-json/json.cpp diff --git a/oracle/src/main.cpp b/oracle/src/main.cpp index a84f4975..44b900f3 100644 --- a/oracle/src/main.cpp +++ b/oracle/src/main.cpp @@ -1,6 +1,6 @@ #include #include -#include "window_main.h" +#include "oraclewizard.h" #include "settingscache.h" SettingsCache *settingsCache; @@ -12,13 +12,14 @@ int main(int argc, char *argv[]) QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); QCoreApplication::setOrganizationName("Cockatrice"); - QCoreApplication::setOrganizationDomain("cockatrice.de"); + QCoreApplication::setOrganizationDomain("cockatrice"); + // this can't be changed, as it influences the default savepath for cards.xml QCoreApplication::setApplicationName("Cockatrice"); settingsCache = new SettingsCache; - - WindowMain wnd; - wnd.show(); - + + OracleWizard wizard; + wizard.show(); + return app.exec(); } diff --git a/oracle/src/oracleimporter.cpp b/oracle/src/oracleimporter.cpp index b3aa5e44..a95481e2 100644 --- a/oracle/src/oracleimporter.cpp +++ b/oracle/src/oracleimporter.cpp @@ -9,17 +9,6 @@ OracleImporter::OracleImporter(const QString &_dataDir, QObject *parent) { } -bool OracleImporter::readSetsFromFile(const QString &fileName) -{ - QFile setsFile(fileName); - if (!setsFile.open(QIODevice::ReadOnly | QIODevice::Text)) { - QMessageBox::critical(0, tr("Error"), tr("Cannot open file '%1'.").arg(fileName)); - return false; - } - - return readSetsFromByteArray(setsFile.readAll()); -} - bool OracleImporter::readSetsFromByteArray(const QByteArray &data) { QList newSetList; @@ -51,6 +40,9 @@ bool OracleImporter::readSetsFromByteArray(const QByteArray &data) newSetList.append(SetToDownload(edition, editionLong, editionCards, import)); } + + qSort(newSetList); + if (newSetList.isEmpty()) return false; allSets = newSetList; @@ -243,8 +235,8 @@ int OracleImporter::startImport() while (it.hasNext()) { curSet = & it.next(); - - emit setIndexChanged(0, 0, curSet->getLongName()); + if(!curSet->getImport()) + continue; CardSet *set = new CardSet(curSet->getShortName(), curSet->getLongName()); if (!setHash.contains(set->getShortName())) diff --git a/oracle/src/oracleimporter.h b/oracle/src/oracleimporter.h index 76989933..a320fd5a 100644 --- a/oracle/src/oracleimporter.h +++ b/oracle/src/oracleimporter.h @@ -18,6 +18,7 @@ public: void setImport(bool _import) { import = _import; } SetToDownload(const QString &_shortName, const QString &_longName, const QVariant &_cards, bool _import) : shortName(_shortName), longName(_longName), cards(_cards), import(_import) { } + bool operator<(const SetToDownload &set) const { return longName < set.longName; } }; class OracleImporter : public CardDatabase { @@ -27,15 +28,13 @@ private: QVariantMap setsMap; QString dataDir; - void downloadNextFile(); CardInfo *addCard(const QString &setName, QString cardName, bool isToken, int cardId, const QString &cardCost, const QString &cardType, const QString &cardPT, int cardLoyalty, const QStringList &cardText); signals: - void setIndexChanged(int cardsImported, int setIndex, const QString &nextSetName); + void setIndexChanged(int cardsImported, int setIndex, const QString &setName); void dataReadProgress(int bytesRead, int totalBytes); public: OracleImporter(const QString &_dataDir, QObject *parent = 0); bool readSetsFromByteArray(const QByteArray &data); - bool readSetsFromFile(const QString &fileName); int startImport(); int importTextSpoiler(CardSet *set, const QVariant &data); QList &getSets() { return allSets; } diff --git a/oracle/src/oraclewizard.cpp b/oracle/src/oraclewizard.cpp new file mode 100644 index 00000000..92bcaa4c --- /dev/null +++ b/oracle/src/oraclewizard.cpp @@ -0,0 +1,392 @@ +#include +#include +#include +#include +#include + +#include "oraclewizard.h" +#include "oracleimporter.h" + +#define ALLSETS_URL "http://mtgjson.com/json/AllSets.json" + +OracleWizard::OracleWizard(QWidget *parent) + : QWizard(parent) +{ + importer = new OracleImporter(QDesktopServices::storageLocation(QDesktopServices::DataLocation), this); + + addPage(new IntroPage); + addPage(new LoadSetsPage); + addPage(new ChooseSetsPage); + addPage(new SaveSetsPage); + +/* + setPixmap(QWizard::BannerPixmap, QPixmap(":/images/banner.png")); + setPixmap(QWizard::BackgroundPixmap, QPixmap(":/images/background.png")); +*/ + setWindowTitle(tr("Oracle Importer")); +} + +void OracleWizard::accept() +{ + QDialog::accept(); +} + +void OracleWizard::enableButtons() +{ + button(QWizard::NextButton)->setDisabled(false); + button(QWizard::BackButton)->setDisabled(false); +} + +void OracleWizard::disableButtons() +{ + button(QWizard::NextButton)->setDisabled(true); + button(QWizard::BackButton)->setDisabled(true); +} + +IntroPage::IntroPage(QWidget *parent) + : OracleWizardPage(parent) +{ + setTitle(tr("Introduction")); + //setPixmap(QWizard::WatermarkPixmap, QPixmap(":/images/watermark1.png")); + + label = new QLabel(tr("This wizard will import the list of sets and cards " + "that will be used by Cockatrice. You will need to " + "specify an url or a filename that will be used as a " + "source, and then choose the wanted sets from the list " + "of the available ones."), + this); + label->setWordWrap(true); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->addWidget(label); + setLayout(layout); +} + +LoadSetsPage::LoadSetsPage(QWidget *parent) + : OracleWizardPage(parent), nam(0) +{ + setTitle(tr("Source selection")); + setSubTitle(tr("Please specify a source for the list of sets and cards. " + "You can specify an url address that will be download or " + "use an existing file from your computer.")); + //setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo1.png")); + + urlRadioButton = new QRadioButton(tr("Download url:"), this); + fileRadioButton = new QRadioButton(tr("Local file:"), this); + + urlLineEdit = new QLineEdit(this); + fileLineEdit = new QLineEdit(this); + + progressLabel = new QLabel(this); + progressBar = new QProgressBar(this); + + urlRadioButton->setChecked(true); + urlLineEdit->setText(ALLSETS_URL); + + fileButton = new QPushButton(tr("Choose file..."), this); + connect(fileButton, SIGNAL(clicked()), this, SLOT(actLoadSetsFile())); + + QGridLayout *layout = new QGridLayout(this); + layout->addWidget(urlRadioButton, 0, 0); + layout->addWidget(urlLineEdit, 0, 1); + layout->addWidget(fileRadioButton, 1, 0); + layout->addWidget(fileLineEdit, 1, 1); + layout->addWidget(fileButton, 2, 1, Qt::AlignRight); + layout->addWidget(progressLabel, 3, 0); + layout->addWidget(progressBar, 3, 1); + + connect(&watcher, SIGNAL(finished()), this, SLOT(importFinished())); + + setLayout(layout); +} + +void LoadSetsPage::initializePage() +{ + progressLabel->hide(); + progressBar->hide(); +} + +void LoadSetsPage::actLoadSetsFile() +{ + QFileDialog dialog(this, tr("Load sets file")); + dialog.setFileMode(QFileDialog::ExistingFile); + dialog.setNameFilter("Sets JSON file (*.json)"); + + if(!fileLineEdit->text().isEmpty() && QFile::exists(fileLineEdit->text())) + dialog.selectFile(fileLineEdit->text()); + + if (!dialog.exec()) + return; + + fileLineEdit->setText(dialog.selectedFiles().at(0)); +} + +bool LoadSetsPage::validatePage() +{ + // once the import is finished, we call next(); skip validation + if(wizard()->importer->getSets().count() > 0) + return true; + + // else, try to import sets + if(urlRadioButton->isChecked()) + { + QUrl url = QUrl::fromUserInput(urlLineEdit->text()); + if(!url.isValid()) + { + QMessageBox::critical(this, tr("Error"), tr("The provided url is not valid.")); + return false; + } + + progressLabel->setText(tr("Downloading (0MB)")); + // show an infinite progressbar + progressBar->setMaximum(0); + progressBar->setMinimum(0); + progressBar->setValue(0); + progressLabel->show(); + progressBar->show(); + + wizard()->disableButtons(); + setEnabled(false); + + if(!nam) + nam = new QNetworkAccessManager(this); + QNetworkReply *reply = nam->get(QNetworkRequest(url)); + + connect(reply, SIGNAL(finished()), this, SLOT(actDownloadFinishedSetsFile())); + connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(actDownloadProgressSetsFile(qint64, qint64))); + + } else if(fileRadioButton->isChecked()) { + QFile setsFile(fileLineEdit->text()); + if(!setsFile.exists()) + { + QMessageBox::critical(this, tr("Error"), tr("Please choose a file.")); + return false; + } + + if (!setsFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox::critical(0, tr("Error"), tr("Cannot open file '%1'.").arg(fileLineEdit->text())); + return false; + } + + wizard()->disableButtons(); + setEnabled(false); + + readSetsFromByteArray(setsFile.readAll()); + + } + return false; +} + +void LoadSetsPage::actDownloadProgressSetsFile(qint64 received, qint64 total) +{ + if(total > 0 && progressBar->maximum()==0) + { + progressBar->setMaximum(total); + progressBar->setValue(received); + } + progressLabel->setText(tr("Downloading (%1MB)").arg((int) received / 1048576)); +} + +void LoadSetsPage::actDownloadFinishedSetsFile() +{ + progressLabel->hide(); + progressBar->hide(); + + // check for a reply + QNetworkReply *reply = static_cast(sender()); + QNetworkReply::NetworkError errorCode = reply->error(); + if (errorCode != QNetworkReply::NoError) { + QMessageBox::critical(this, tr("Error"), tr("Network error: %1.").arg(reply->errorString())); + + wizard()->enableButtons(); + setEnabled(true); + + reply->deleteLater(); + return; + } + + this->readSetsFromByteArray(reply->readAll()); + reply->deleteLater(); +} + +void LoadSetsPage::readSetsFromByteArray(QByteArray data) +{ + // show an infinite progressbar + progressBar->setMaximum(0); + progressBar->setMinimum(0); + progressBar->setValue(0); + progressLabel->setText(tr("Parsing file")); + progressLabel->show(); + progressBar->show(); + + // Start the computation. + future = QtConcurrent::run(wizard()->importer, &OracleImporter::readSetsFromByteArray, data); + watcher.setFuture(future); +} + +void LoadSetsPage::importFinished() +{ + if(watcher.future().result()) + { + wizard()->enableButtons(); + setEnabled(true); + progressLabel->hide(); + progressBar->hide(); + + wizard()->next(); + } else { + QMessageBox::critical(this, tr("Error"), tr("The file was retrieved successfully, but it does not contain any sets data.")); + } +} + +ChooseSetsPage::ChooseSetsPage(QWidget *parent) + : OracleWizardPage(parent) +{ + setTitle(tr("Sets selection")); + setSubTitle(tr("The following sets has been found in the source file. " + "Please mark the sets that will be imported.")); + + checkBoxLayout = new QVBoxLayout; + + QWidget *checkboxFrame = new QWidget(this); + checkboxFrame->setLayout(checkBoxLayout); + + QScrollArea *checkboxArea = new QScrollArea(this); + checkboxArea->setWidget(checkboxFrame); + checkboxArea->setWidgetResizable(true); + + checkAllButton = new QPushButton(tr("&Check all")); + connect(checkAllButton, SIGNAL(clicked()), this, SLOT(actCheckAll())); + uncheckAllButton = new QPushButton(tr("&Uncheck all")); + connect(uncheckAllButton, SIGNAL(clicked()), this, SLOT(actUncheckAll())); + + QGridLayout *layout = new QGridLayout(this); + layout->addWidget(checkboxArea, 0, 0, 1, 2); + layout->addWidget(checkAllButton, 1, 0); + layout->addWidget(uncheckAllButton, 1, 1); + + setLayout(layout); +} + +void ChooseSetsPage::initializePage() +{ + // populate checkbox list + for (int i = 0; i < checkBoxList.size(); ++i) + delete checkBoxList[i]; + checkBoxList.clear(); + + QList &sets = wizard()->importer->getSets(); + for (int i = 0; i < sets.size(); ++i) { + QCheckBox *checkBox = new QCheckBox(sets[i].getLongName()); + checkBox->setChecked(sets[i].getImport()); + connect(checkBox, SIGNAL(stateChanged(int)), this, SLOT(checkBoxChanged(int))); + checkBoxLayout->addWidget(checkBox); + checkBoxList << checkBox; + } +} + +void ChooseSetsPage::checkBoxChanged(int state) +{ + QCheckBox *checkBox = qobject_cast(sender()); + QList &sets = wizard()->importer->getSets(); + for (int i = 0; i < sets.size(); ++i) + if (sets[i].getLongName() == checkBox->text()) { + sets[i].setImport(state); + break; + } +} + +void ChooseSetsPage::actCheckAll() +{ + for (int i = 0; i < checkBoxList.size(); ++i) + checkBoxList[i]->setChecked(true); +} + +void ChooseSetsPage::actUncheckAll() +{ + for (int i = 0; i < checkBoxList.size(); ++i) + checkBoxList[i]->setChecked(false); +} + +bool ChooseSetsPage::validatePage() +{ + for (int i = 0; i < checkBoxList.size(); ++i) + { + if(checkBoxList[i]->isChecked()) + return true; + } + + QMessageBox::critical(this, tr("Error"), tr("Please mark at least one set.")); + return false; +} + +SaveSetsPage::SaveSetsPage(QWidget *parent) + : OracleWizardPage(parent) +{ + setTitle(tr("Sets imported")); + setSubTitle(tr("The following sets has been imported. " + "Press \"Done\" to save the imported cards to the Cockatrice database.")); + +// setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo3.png")); + + messageLog = new QTextEdit(this); + messageLog->setReadOnly(true); + + QGridLayout *layout = new QGridLayout(this); + layout->addWidget(messageLog, 0, 0); + + setLayout(layout); +} + +void SaveSetsPage::cleanupPage() +{ + disconnect(wizard()->importer, SIGNAL(setIndexChanged(int, int, const QString &)), 0, 0); +} + +void SaveSetsPage::initializePage() +{ + messageLog->clear(); + + connect(wizard()->importer, SIGNAL(setIndexChanged(int, int, const QString &)), this, SLOT(updateTotalProgress(int, int, const QString &))); + + if (!wizard()->importer->startImport()) + QMessageBox::critical(this, tr("Error"), tr("No set has been imported.")); +} + +void SaveSetsPage::updateTotalProgress(int cardsImported, int setIndex, const QString &setName) +{ + if (setName.isEmpty()) { + messageLog->append("" + tr("Import finished: %1 cards.").arg(wizard()->importer->getCardList().size()) + ""); + } else { + messageLog->append(tr("%1: %2 cards imported").arg(setName).arg(cardsImported)); + } + messageLog->verticalScrollBar()->setValue(messageLog->verticalScrollBar()->maximum()); +} + +bool SaveSetsPage::validatePage() +{ + bool ok = false; + const QString dataDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation); + QDir dir(dataDir); + if (!dir.exists()) + dir.mkpath(dataDir); + QString savePath = dataDir + "/cards.xml"; + do { + QString fileName; + if (savePath.isEmpty()) + fileName = QFileDialog::getSaveFileName(this, tr("Save card database"), dataDir + "/cards.xml", tr("XML card database (*.xml)")); + else { + fileName = savePath; + savePath.clear(); + } + if (fileName.isEmpty()) { + return false; + } + if (wizard()->importer->saveToFile(fileName)) + ok = true; + else + QMessageBox::critical(this, tr("Error"), tr("The file could not be saved to the desired location.")); + } while (!ok); + + return true; +} diff --git a/oracle/src/oraclewizard.h b/oracle/src/oraclewizard.h new file mode 100644 index 00000000..5514b9da --- /dev/null +++ b/oracle/src/oraclewizard.h @@ -0,0 +1,111 @@ +#ifndef ORACLEWIZARD_H +#define ORACLEWIZARD_H + +#include +#include +#include + +class QCheckBox; +class QGroupBox; +class QLabel; +class QLineEdit; +class QRadioButton; +class QProgressBar; +class QNetworkAccessManager; +class QTextEdit; +class QVBoxLayout; +class OracleImporter; + +class OracleWizard : public QWizard +{ + Q_OBJECT +public: + OracleWizard(QWidget *parent = 0); + void accept(); + void enableButtons(); + void disableButtons(); +public: + OracleImporter *importer; +}; + + +class OracleWizardPage : public QWizardPage +{ + Q_OBJECT +public: + OracleWizardPage(QWidget *parent = 0): QWizardPage(parent) {}; +protected: + inline OracleWizard *wizard() { return (OracleWizard*) QWizardPage::wizard(); }; +}; + +class IntroPage : public OracleWizardPage +{ + Q_OBJECT +public: + IntroPage(QWidget *parent = 0); +private: + QLabel *label; +}; + +class LoadSetsPage : public OracleWizardPage +{ + Q_OBJECT +public: + LoadSetsPage(QWidget *parent = 0); +protected: + void initializePage(); + bool validatePage(); + void readSetsFromByteArray(QByteArray data); +private: + QRadioButton *urlRadioButton; + QRadioButton *fileRadioButton; + QLineEdit *urlLineEdit; + QLineEdit *fileLineEdit; + QPushButton *fileButton; + QLabel *progressLabel; + QProgressBar * progressBar; + + QNetworkAccessManager *nam; + QFutureWatcher watcher; + QFuture future; +private slots: + void actLoadSetsFile(); + void actDownloadProgressSetsFile(qint64 received, qint64 total); + void actDownloadFinishedSetsFile(); + void importFinished(); +}; + +class ChooseSetsPage : public OracleWizardPage +{ + Q_OBJECT +public: + ChooseSetsPage(QWidget *parent = 0); +protected: + void initializePage(); + bool validatePage(); +private: + QPushButton *checkAllButton, *uncheckAllButton; + QVBoxLayout *checkBoxLayout; + QList checkBoxList; +private slots: + void actCheckAll(); + void actUncheckAll(); + void checkBoxChanged(int state); +}; + +class SaveSetsPage : public OracleWizardPage +{ + Q_OBJECT +public: + SaveSetsPage(QWidget *parent = 0); +private: + QTextEdit *messageLog; +protected: + void initializePage(); + void cleanupPage(); + bool validatePage(); +private slots: + void updateTotalProgress(int cardsImported, int setIndex, const QString &setName); +}; + +#endif \ No newline at end of file diff --git a/oracle/src/window_main.cpp b/oracle/src/window_main.cpp deleted file mode 100644 index 24d79b4f..00000000 --- a/oracle/src/window_main.cpp +++ /dev/null @@ -1,248 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "window_main.h" -#include "oracleimporter.h" - -const QString WindowMain::defaultSetsUrl = QString("http://mtgjson.com/json/AllSets.json"); - -WindowMain::WindowMain(QWidget *parent) - : QMainWindow(parent) -{ - importer = new OracleImporter(QDesktopServices::storageLocation(QDesktopServices::DataLocation), this); - nam = new QNetworkAccessManager(this); - - checkBoxLayout = new QVBoxLayout; - - QWidget *checkboxFrame = new QWidget; - checkboxFrame->setLayout(checkBoxLayout); - - QScrollArea *checkboxArea = new QScrollArea; - checkboxArea->setWidget(checkboxFrame); - checkboxArea->setWidgetResizable(true); - - checkAllButton = new QPushButton(tr("&Check all")); - connect(checkAllButton, SIGNAL(clicked()), this, SLOT(actCheckAll())); - uncheckAllButton = new QPushButton(tr("&Uncheck all")); - connect(uncheckAllButton, SIGNAL(clicked()), this, SLOT(actUncheckAll())); - - QHBoxLayout *checkAllButtonLayout = new QHBoxLayout; - checkAllButtonLayout->addWidget(checkAllButton); - checkAllButtonLayout->addWidget(uncheckAllButton); - - startButton = new QPushButton(tr("&Start import")); - connect(startButton, SIGNAL(clicked()), this, SLOT(actStart())); - - QVBoxLayout *settingsLayout = new QVBoxLayout; - settingsLayout->addWidget(checkboxArea); - settingsLayout->addLayout(checkAllButtonLayout); - settingsLayout->addWidget(startButton); - - totalLabel = new QLabel(tr("Total progress:")); - totalProgressBar = new QProgressBar; - nextSetLabel1 = new QLabel(tr("Current file:")); - nextSetLabel2 = new QLabel; - fileLabel = new QLabel(tr("Progress:")); - fileProgressBar = new QProgressBar; - - messageLog = new QTextEdit; - messageLog->setReadOnly(true); - - QGridLayout *grid = new QGridLayout; - grid->addWidget(totalLabel, 0, 0); - grid->addWidget(totalProgressBar, 0, 1); - grid->addWidget(nextSetLabel1, 1, 0); - grid->addWidget(nextSetLabel2, 1, 1); - grid->addWidget(fileLabel, 2, 0); - grid->addWidget(fileProgressBar, 2, 1); - grid->addWidget(messageLog, 3, 0, 1, 2); - - QHBoxLayout *mainLayout = new QHBoxLayout; - mainLayout->addLayout(settingsLayout, 6); - mainLayout->addSpacing(10); - mainLayout->addLayout(grid, 10); - - QWidget *centralWidget = new QWidget; - centralWidget->setLayout(mainLayout); - setCentralWidget(centralWidget); - - connect(importer, SIGNAL(setIndexChanged(int, int, const QString &)), this, SLOT(updateTotalProgress(int, int, const QString &))); - connect(importer, SIGNAL(dataReadProgress(int, int)), this, SLOT(updateFileProgress(int, int))); - - aLoadSetsFile = new QAction(tr("Load sets information from &file..."), this); - connect(aLoadSetsFile, SIGNAL(triggered()), this, SLOT(actLoadSetsFile())); - aDownloadSetsFile = new QAction(tr("&Download sets information..."), this); - connect(aDownloadSetsFile, SIGNAL(triggered()), this, SLOT(actDownloadSetsFile())); - aExit = new QAction(tr("E&xit"), this); - connect(aExit, SIGNAL(triggered()), this, SLOT(close())); - - fileMenu = menuBar()->addMenu(tr("&File")); - fileMenu->addAction(aLoadSetsFile); - fileMenu->addAction(aDownloadSetsFile); - fileMenu->addSeparator(); - fileMenu->addAction(aExit); - - setWindowTitle(tr("Oracle importer")); - setMinimumSize(750, 500); - - QStringList args = qApp->arguments(); - if (args.contains("-dlsets")) - downloadSetsFile(defaultSetsUrl); - - statusLabel = new QLabel; - statusBar()->addWidget(statusLabel); - statusLabel->setText(tr("Sets data not loaded.")); -} - -void WindowMain::updateSetList() -{ - for (int i = 0; i < checkBoxList.size(); ++i) - delete checkBoxList[i]; - checkBoxList.clear(); - - QList &sets = importer->getSets(); - for (int i = 0; i < sets.size(); ++i) { - QCheckBox *checkBox = new QCheckBox(sets[i].getLongName()); - checkBox->setChecked(sets[i].getImport()); - connect(checkBox, SIGNAL(stateChanged(int)), this, SLOT(checkBoxChanged(int))); - checkBoxLayout->addWidget(checkBox); - checkBoxList << checkBox; - } - statusLabel->setText(tr("Ready.")); -} - -void WindowMain::actLoadSetsFile() -{ - QFileDialog dialog(this, tr("Load sets file")); - dialog.setFileMode(QFileDialog::ExistingFile); - dialog.setNameFilter("Sets JSON file (*.json)"); - if (!dialog.exec()) - return; - - QString fileName = dialog.selectedFiles().at(0); - if (importer->readSetsFromFile(fileName)) - updateSetList(); - else - QMessageBox::critical(this, tr("Error"), tr("This file does not contain any sets data.")); -} - -void WindowMain::actDownloadSetsFile() -{ - QString url = QInputDialog::getText(this, tr("Load sets from URL"), tr("Please enter the URL of the sets file:"), QLineEdit::Normal, defaultSetsUrl); - if (!url.isEmpty()) - downloadSetsFile(url); -} - -void WindowMain::downloadSetsFile(const QString &url) -{ - QNetworkReply *reply = nam->get(QNetworkRequest(url)); - connect(reply, SIGNAL(finished()), this, SLOT(setsDownloadFinished())); -} - -void WindowMain::setsDownloadFinished() -{ - QNetworkReply *reply = static_cast(sender()); - QNetworkReply::NetworkError errorCode = reply->error(); - if (errorCode == QNetworkReply::NoError) { - if (importer->readSetsFromByteArray(reply->readAll())) - updateSetList(); - else - QMessageBox::critical(this, tr("Error"), tr("The file was retrieved successfully, but it does not contain any sets data.")); - } else - QMessageBox::critical(this, tr("Error"), tr("Network error: %1.").arg(reply->errorString())); - reply->deleteLater(); -} - -void WindowMain::updateTotalProgress(int cardsImported, int setIndex, const QString &nextSetName) -{ - if (setIndex != 0) - messageLog->append(QString("%1: %2 cards imported").arg(nextSetLabel2->text()).arg(cardsImported)); - totalProgressBar->setValue(setIndex); - if (nextSetName.isEmpty()) { - QMessageBox::information(this, tr("Oracle importer"), tr("Import finished: %1 cards.").arg(importer->getCardList().size())); - bool ok = false; - const QString dataDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation); - QDir dir(dataDir); - if (!dir.exists()) - dir.mkpath(dataDir); - QString savePath = dataDir + "/cards.xml"; - do { - QString fileName; - if (savePath.isEmpty()) - fileName = QFileDialog::getSaveFileName(this, tr("Save card database"), dataDir + "/cards.xml", tr("XML card database (*.xml)")); - else { - fileName = savePath; - savePath.clear(); - } - if (fileName.isEmpty()) { - qApp->quit(); - return; - } - if (importer->saveToFile(fileName)) - ok = true; - else - QMessageBox::critical(this, tr("Error"), tr("The file could not be saved to the desired location.")); - } while (!ok); - qApp->quit(); - } else { - nextSetLabel2->setText(nextSetName); - } -} - -void WindowMain::updateFileProgress(int bytesRead, int totalBytes) -{ - fileProgressBar->setMaximum(totalBytes); - fileProgressBar->setValue(bytesRead); -} - -void WindowMain::actCheckAll() -{ - for (int i = 0; i < checkBoxList.size(); ++i) - checkBoxList[i]->setChecked(true); -} - -void WindowMain::actUncheckAll() -{ - for (int i = 0; i < checkBoxList.size(); ++i) - checkBoxList[i]->setChecked(false); -} - -void WindowMain::actStart() -{ - int setsCount = importer->startImport(); - if (!setsCount) { - QMessageBox::critical(this, tr("Error"), tr("No sets to download selected.")); - return; - } - for (int i = 0; i < checkBoxList.size(); ++i) - checkBoxList[i]->setEnabled(false); - startButton->setEnabled(false); - totalProgressBar->setMaximum(setsCount); - statusLabel->setText(tr("Downloading card data...")); -} - -void WindowMain::checkBoxChanged(int state) -{ - QCheckBox *checkBox = qobject_cast(sender()); - QList &sets = importer->getSets(); - for (int i = 0; i < sets.size(); ++i) - if (sets[i].getLongName() == checkBox->text()) { - sets[i].setImport(state); - break; - } -} diff --git a/oracle/src/window_main.h b/oracle/src/window_main.h deleted file mode 100644 index 1fdba235..00000000 --- a/oracle/src/window_main.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef WINDOW_MAIN_H -#define WINDOW_MAIN_H - -#include -#include - -class OracleImporter; -class QLabel; -class QProgressBar; -class QTextEdit; -class QPushButton; -class QCheckBox; -class QVBoxLayout; -class QMenu; -class QAction; -class QNetworkAccessManager; - -class WindowMain : public QMainWindow { - Q_OBJECT -private: - static const QString defaultSetsUrl; - - OracleImporter *importer; - QNetworkAccessManager *nam; - - QMenu *fileMenu; - QAction *aLoadSetsFile, *aDownloadSetsFile, *aExit; - QPushButton *checkAllButton, *uncheckAllButton, *startButton; - QLabel *totalLabel, *fileLabel, *nextSetLabel1, *nextSetLabel2; - QProgressBar *totalProgressBar, *fileProgressBar; - QTextEdit *messageLog; - QVBoxLayout *checkBoxLayout; - QList checkBoxList; - QLabel *statusLabel; - - void downloadSetsFile(const QString &url); -private slots: - void updateTotalProgress(int cardsImported, int setIndex, const QString &nextSetName); - void updateFileProgress(int bytesRead, int totalBytes); - void updateSetList(); - void actCheckAll(); - void actUncheckAll(); - void actStart(); - void actLoadSetsFile(); - void actDownloadSetsFile(); - void setsDownloadFinished(); - void checkBoxChanged(int state); -public: - WindowMain(QWidget *parent = 0); -}; - -#endif From 8281f631342d92d5b54b99cb3b1a6b8d88fb831f Mon Sep 17 00:00:00 2001 From: Daenyth Date: Fri, 20 Jun 2014 22:10:26 -0400 Subject: [PATCH 16/24] Add settings fields for pic urls --- cockatrice/src/settingscache.cpp | 33 +++++++++++++++++++++++--------- cockatrice/src/settingscache.h | 9 +++++++++ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/cockatrice/src/settingscache.cpp b/cockatrice/src/settingscache.cpp index b73d6d86..3bcc4111 100644 --- a/cockatrice/src/settingscache.cpp +++ b/cockatrice/src/settingscache.cpp @@ -4,23 +4,26 @@ SettingsCache::SettingsCache() { settings = new QSettings(this); - + lang = settings->value("personal/lang").toString(); - + deckPath = settings->value("paths/decks").toString(); replaysPath = settings->value("paths/replays").toString(); picsPath = settings->value("paths/pics").toString(); cardDatabasePath = settings->value("paths/carddatabase").toString(); tokenDatabasePath = settings->value("paths/tokendatabase").toString(); - + handBgPath = settings->value("zonebg/hand").toString(); stackBgPath = settings->value("zonebg/stack").toString(); tableBgPath = settings->value("zonebg/table").toString(); playerBgPath = settings->value("zonebg/playerarea").toString(); cardBackPicturePath = settings->value("paths/cardbackpicture").toString(); - - mainWindowGeometry = settings->value("interface/main_window_geometry").toByteArray(); + picDownload = settings->value("personal/picturedownload", true).toBool(); + picUrl = settings->value("personal/picUrl", PIC_URL_DEFAULT).toString(); + picUrlHq = settings->value("personal/picUrlHq", PIC_URL_HQ_DEFAULT).toString(); + + mainWindowGeometry = settings->value("interface/main_window_geometry").toByteArray(); notificationsEnabled = settings->value("interface/notificationsenabled", true).toBool(); doubleClickToPlay = settings->value("interface/doubleclicktoplay", true).toBool(); playToStack = settings->value("interface/playtostack", false).toBool(); @@ -31,15 +34,15 @@ SettingsCache::SettingsCache() invertVerticalCoordinate = settings->value("table/invert_vertical", false).toBool(); minPlayersForMultiColumnLayout = settings->value("interface/min_players_multicolumn", 5).toInt(); tapAnimation = settings->value("cards/tapanimation", true).toBool(); - + zoneViewSortByName = settings->value("zoneview/sortbyname", true).toBool(); zoneViewSortByType = settings->value("zoneview/sortbytype", true).toBool(); - + soundEnabled = settings->value("sound/enabled", false).toBool(); soundPath = settings->value("sound/path").toString(); - + priceTagFeature = settings->value("deckeditor/pricetags", false).toBool(); - + ignoreUnregisteredUsers = settings->value("chat/ignore_unregistered", false).toBool(); } @@ -125,6 +128,18 @@ void SettingsCache::setPicDownload(int _picDownload) emit picDownloadChanged(); } +void SettingsCache::setPicUrl(const QString &_picUrl) +{ + picUrl = _picUrl; + settings->setValue("personal/picUrl", picUrl); +} + +void SettingsCache::setPicUrlHq(const QString &_picUrlHq) +{ + picUrlHq = _picUrlHq; + settings->setValue("personal/picUrlHq", picUrlHq); +} + void SettingsCache::setNotificationsEnabled(int _notificationsEnabled) { notificationsEnabled = _notificationsEnabled; diff --git a/cockatrice/src/settingscache.h b/cockatrice/src/settingscache.h index 6c28227a..ba3dbb00 100644 --- a/cockatrice/src/settingscache.h +++ b/cockatrice/src/settingscache.h @@ -3,6 +3,9 @@ #include +#define PIC_URL_DEFAULT "http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=!cardid!&type=card" +#define PIC_URL_HQ_DEFAULT "http://mtgimage.com/multiverseid/!cardid!.jpg" + class QSettings; class SettingsCache : public QObject { @@ -48,6 +51,8 @@ private: QString soundPath; bool priceTagFeature; bool ignoreUnregisteredUsers; + QString picUrl; + QString picUrlHq; public: SettingsCache(); const QByteArray &getMainWindowGeometry() const { return mainWindowGeometry; } @@ -79,6 +84,8 @@ public: QString getSoundPath() const { return soundPath; } bool getPriceTagFeature() const { return priceTagFeature; } bool getIgnoreUnregisteredUsers() const { return ignoreUnregisteredUsers; } + QString getPicUrl() const { return picUrl; } + QString getPicUrlHq() const { return picUrlHq; } public slots: void setMainWindowGeometry(const QByteArray &_mainWindowGeometry); void setLang(const QString &_lang); @@ -109,6 +116,8 @@ public slots: void setSoundPath(const QString &_soundPath); void setPriceTagFeature(int _priceTagFeature); void setIgnoreUnregisteredUsers(bool _ignoreUnregisteredUsers); + void setPicUrl(const QString &_picUrl); + void setPicUrlHq(const QString &_picUrlHq); }; extern SettingsCache *settingsCache; From 53d2b82e61471095b562f5251af3cc3b697f89af Mon Sep 17 00:00:00 2001 From: Daenyth Date: Sat, 21 Jun 2014 01:12:47 -0400 Subject: [PATCH 17/24] Use picUrl templates to download cards. Add HQ card option --- cockatrice/src/carddatabase.cpp | 125 +++++++++++++++++-------------- cockatrice/src/carddatabase.h | 24 +++--- cockatrice/src/dlg_settings.cpp | 20 +++-- cockatrice/src/dlg_settings.h | 1 + cockatrice/src/settingscache.cpp | 8 ++ cockatrice/src/settingscache.h | 6 +- 6 files changed, 105 insertions(+), 79 deletions(-) diff --git a/cockatrice/src/carddatabase.cpp b/cockatrice/src/carddatabase.cpp index 748d8197..2045f95e 100644 --- a/cockatrice/src/carddatabase.cpp +++ b/cockatrice/src/carddatabase.cpp @@ -80,11 +80,13 @@ bool PictureToLoad::nextSet() return true; } -PictureLoader::PictureLoader(const QString &__picsPath, bool _picDownload, QObject *parent) - : QObject(parent), _picsPath(__picsPath), picDownload(_picDownload), downloadRunning(false), loadQueueRunning(false) +PictureLoader::PictureLoader(const QString &__picsPath, bool _picDownload, bool _picDownloadHq, QObject *parent) + : QObject(parent), + _picsPath(__picsPath), picDownload(_picDownload), picDownloadHq(_picDownloadHq), + downloadRunning(false), loadQueueRunning(false) { connect(this, SIGNAL(startLoadQueue()), this, SLOT(processLoadQueue()), Qt::QueuedConnection); - + networkManager = new QNetworkAccessManager(this); connect(networkManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(picDownloadFinished(QNetworkReply *))); } @@ -99,7 +101,7 @@ void PictureLoader::processLoadQueue() { if (loadQueueRunning) return; - + loadQueueRunning = true; forever { mutex.lock(); @@ -113,7 +115,7 @@ void PictureLoader::processLoadQueue() QString correctedName = ptl.getCard()->getCorrectedName(); QString picsPath = _picsPath; QString setName = ptl.getSetName(); - + QImage image; if (!image.load(QString("%1/%2/%3.full.jpg").arg(picsPath).arg(setName).arg(correctedName))) if (!image.load(QString("%1/%2/%3%4.full.jpg").arg(picsPath).arg(setName).arg(correctedName).arg(1))) @@ -135,6 +137,20 @@ void PictureLoader::processLoadQueue() } } +QString PictureLoader::getPicUrl(CardInfo *card) +{ + if (!picDownload) return 0; + + QString picUrl = picDownloadHq ? settingsCache->getPicUrlHq() : settingsCache->getPicUrl(); + picUrl.replace("!name!", QUrl::toPercentEncoding(card->getCorrectedName())); + CardSet *set = card->getPreferredSet(); + picUrl.replace("!setcode!", QUrl::toPercentEncoding(set->getShortName())); + picUrl.replace("!setname!", QUrl::toPercentEncoding(set->getLongName())); + picUrl.replace("!cardid!", QUrl::toPercentEncoding(QString::number(card->getPreferredMuId()))); + + return picUrl; +} + void PictureLoader::startNextPicDownload() { if (cardsToDownload.isEmpty()) { @@ -142,23 +158,16 @@ void PictureLoader::startNextPicDownload() downloadRunning = false; return; } - + downloadRunning = true; - + cardBeingDownloaded = cardsToDownload.takeFirst(); - QString picUrl; - if (cardBeingDownloaded.getStripped()) - picUrl = cardBeingDownloaded.getCard()->getPicURLSt(cardBeingDownloaded.getSetName()); - else if (cardBeingDownloaded.getHq()) { - picUrl = cardBeingDownloaded.getCard()->getPicURLHq(cardBeingDownloaded.getSetName()); - if (picUrl.isEmpty()) { - picUrl = cardBeingDownloaded.getCard()->getPicURL(cardBeingDownloaded.getSetName()); - cardBeingDownloaded.setHq(false); - } - } else - picUrl = cardBeingDownloaded.getCard()->getPicURL(cardBeingDownloaded.getSetName()); + + // TODO: Do something useful when picUrl is 0 or empty, etc + QString picUrl = getPicUrl(cardBeingDownloaded.getCard()); + QUrl url(picUrl); - + QNetworkRequest req(url); qDebug() << "starting picture download:" << req.url(); networkManager->get(req); @@ -232,6 +241,12 @@ void PictureLoader::setPicDownload(bool _picDownload) picDownload = _picDownload; } +void PictureLoader::setPicDownloadHq(bool _picDownloadHq) +{ + QMutexLocker locker(&mutex); + picDownloadHq = _picDownloadHq; +} + CardInfo::CardInfo(CardDatabase *_db, const QString &_name, bool _isToken, @@ -244,22 +259,18 @@ CardInfo::CardInfo(CardDatabase *_db, bool _cipt, int _tableRow, const SetList &_sets, - const QMap &_picURLs, - const QMap &_picURLsHq, - const QMap &_picURLsSt) + QMap _muIds) : db(_db), name(_name), isToken(_isToken), sets(_sets), + muIds(_muIds), manacost(_manacost), cardtype(_cardtype), powtough(_powtough), text(_text), colors(_colors), loyalty(_loyalty), - picURLs(_picURLs), - picURLsHq(_picURLsHq), - picURLsSt(_picURLsSt), cipt(_cipt), tableRow(_tableRow), pixmap(NULL) @@ -315,19 +326,12 @@ void CardInfo::addToSet(CardSet *set) sets << set; } -QString CardInfo::getPicURL() const -{ - SetList sortedSets = sets; - sortedSets.sortByKey(); - return picURLs.value(sortedSets.first()->getShortName()); -} - QPixmap *CardInfo::loadPixmap() { if (pixmap) return pixmap; pixmap = new QPixmap(); - + if (getName().isEmpty()) { pixmap->load(settingsCache->getCardBackPicturePath()); return pixmap; @@ -400,6 +404,18 @@ void CardInfo::updatePixmapCache() emit pixmapUpdated(); } +CardSet* CardInfo::getPreferredSet() +{ + SetList sortedSets = sets; + sortedSets.sortByKey(); + return sortedSets.first(); +} + +int CardInfo::getPreferredMuId() +{ + return muIds[getPreferredSet()->getShortName()]; +} + QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info) { xml.writeStartElement("card"); @@ -414,18 +430,6 @@ QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info) tmpSet=sets[i]->getShortName(); xml.writeAttribute("muId", QString::number(info->getMuId(tmpSet))); - tmpString = info->getPicURL(tmpSet); - if(!tmpString.isEmpty()) - xml.writeAttribute("picURL", tmpString); - - tmpString = info->getPicURLHq(tmpSet); - if(!tmpString.isEmpty()) - xml.writeAttribute("picURLHq", tmpString); - - tmpString = info->getPicURLSt(tmpSet); - if(!tmpString.isEmpty()) - xml.writeAttribute("picURLSt", tmpString); - xml.writeCharacters(tmpSet); xml.writeEndElement(); } @@ -457,12 +461,13 @@ CardDatabase::CardDatabase(QObject *parent) connect(settingsCache, SIGNAL(cardDatabasePathChanged()), this, SLOT(loadCardDatabase())); connect(settingsCache, SIGNAL(tokenDatabasePathChanged()), this, SLOT(loadTokenDatabase())); connect(settingsCache, SIGNAL(picDownloadChanged()), this, SLOT(picDownloadChanged())); - + connect(settingsCache, SIGNAL(picDownloadHqChanged()), this, SLOT(picDownloadHqChanged())); + loadCardDatabase(); loadTokenDatabase(); - + pictureLoaderThread = new QThread; - pictureLoader = new PictureLoader(settingsCache->getPicsPath(), settingsCache->getPicDownload()); + pictureLoader = new PictureLoader(settingsCache->getPicsPath(), settingsCache->getPicDownload(), settingsCache->getPicDownloadHq()); pictureLoader->moveToThread(pictureLoaderThread); connect(pictureLoader, SIGNAL(imageLoaded(CardInfo *, const QImage &)), this, SLOT(imageLoaded(CardInfo *, const QImage &))); pictureLoaderThread->start(QThread::LowPriority); @@ -587,7 +592,7 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml) if (xml.name() == "card") { QString name, manacost, type, pt, text; QStringList colors; - QMap picURLs, picURLsHq, picURLsSt; + QMap muids; SetList sets; int tableRow = 0; int loyalty = 0; @@ -607,14 +612,12 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml) else if (xml.name() == "text") text = xml.readElementText(); else if (xml.name() == "set") { - QString picURL = xml.attributes().value("picURL").toString(); - QString picURLHq = xml.attributes().value("picURLHq").toString(); - QString picURLSt = xml.attributes().value("picURLSt").toString(); + QXmlStreamAttributes attrs = xml.attributes(); QString setName = xml.readElementText(); sets.append(getSet(setName)); - picURLs.insert(setName, picURL); - picURLsHq.insert(setName, picURLHq); - picURLsSt.insert(setName, picURLSt); + if (attrs.hasAttribute("muId")) { + muids[setName] = attrs.value("muId").toString().toInt(); + } } else if (xml.name() == "color") colors << xml.readElementText(); else if (xml.name() == "tablerow") @@ -626,7 +629,7 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml) else if (xml.name() == "token") isToken = xml.readElementText().toInt(); } - cardHash.insert(name, new CardInfo(this, name, isToken, manacost, type, pt, text, colors, loyalty, cipt, tableRow, sets, picURLs, picURLsHq, picURLsSt)); + cardHash.insert(name, new CardInfo(this, name, isToken, manacost, type, pt, text, colors, loyalty, cipt, tableRow, sets, muids)); } } } @@ -732,6 +735,16 @@ void CardDatabase::picDownloadChanged() } } +void CardDatabase::picDownloadHqChanged() +{ + pictureLoader->setPicDownloadHq(settingsCache->getPicDownloadHq()); + if (settingsCache->getPicDownloadHq()) { + QHashIterator cardIterator(cardHash); + while (cardIterator.hasNext()) + cardIterator.next().value()->clearPixmapCacheMiss(); + } +} + bool CardDatabase::loadCardDatabase(const QString &path, bool tokens) { bool tempLoadSuccess = false; diff --git a/cockatrice/src/carddatabase.h b/cockatrice/src/carddatabase.h index 987848d3..39d2faec 100644 --- a/cockatrice/src/carddatabase.h +++ b/cockatrice/src/carddatabase.h @@ -68,13 +68,15 @@ private: QNetworkAccessManager *networkManager; QList cardsToDownload; PictureToLoad cardBeingDownloaded; - bool picDownload, downloadRunning, loadQueueRunning; + bool picDownload, picDownloadHq, downloadRunning, loadQueueRunning; void startNextPicDownload(); + QString getPicUrl(CardInfo* card); public: - PictureLoader(const QString &__picsPath, bool _picDownload, QObject *parent = 0); + PictureLoader(const QString &__picsPath, bool _picDownload, bool _picDownloadHq, QObject *parent = 0); ~PictureLoader(); void setPicsPath(const QString &path); void setPicDownload(bool _picDownload); + void setPicDownloadHq(bool _picDownloadHq); void loadImage(CardInfo *card, bool stripped); private slots: void picDownloadFinished(QNetworkReply *reply); @@ -99,7 +101,6 @@ private: QString text; QStringList colors; int loyalty; - QMap picURLs, picURLsHq, picURLsSt; QMap muIds; bool cipt; int tableRow; @@ -118,9 +119,7 @@ public: bool _cipt = false, int _tableRow = 0, const SetList &_sets = SetList(), - const QStringMap &_picURLs = QStringMap(), - const QStringMap &_picURLsHq = QStringMap(), - const QStringMap &_picURLsSt = QStringMap()); + QMap muids = QMap()); ~CardInfo(); const QString &getName() const { return name; } bool getIsToken() const { return isToken; } @@ -137,20 +136,12 @@ public: void setText(const QString &_text) { text = _text; emit cardInfoChanged(this); } void setColors(const QStringList &_colors) { colors = _colors; emit cardInfoChanged(this); } const QStringList &getColors() const { return colors; } - QString getPicURL(const QString &set) const { return picURLs.value(set); } - QString getPicURLHq(const QString &set) const { return picURLsHq.value(set); } - QString getPicURLSt(const QString &set) const { return picURLsSt.value(set); } int getMuId(const QString &set) const { return muIds.value(set); } - QString getPicURL() const; - const QMap &getPicURLs() const { return picURLs; } QString getMainCardType() const; QString getCorrectedName() const; int getTableRow() const { return tableRow; } void setTableRow(int _tableRow) { tableRow = _tableRow; } void setLoyalty(int _loyalty) { loyalty = _loyalty; emit cardInfoChanged(this); } - void setPicURL(const QString &_set, const QString &_picURL) { picURLs.insert(_set, _picURL); } - void setPicURLHq(const QString &_set, const QString &_picURL) { picURLsHq.insert(_set, _picURL); } - void setPicURLSt(const QString &_set, const QString &_picURL) { picURLsSt.insert(_set, _picURL); } void setMuId(const QString &_set, const int &_muId) { muIds.insert(_set, _muId); } void addToSet(CardSet *set); QPixmap *loadPixmap(); @@ -158,6 +149,8 @@ public: void clearPixmapCache(); void clearPixmapCacheMiss(); void imageLoaded(const QImage &image); + CardSet *getPreferredSet(); + int getPreferredMuId(); public slots: void updatePixmapCache(); signals: @@ -172,7 +165,7 @@ protected: QHash setHash; bool loadSuccess; CardInfo *noCard; - + QThread *pictureLoaderThread; PictureLoader *pictureLoader; private: @@ -202,6 +195,7 @@ public slots: private slots: void imageLoaded(CardInfo *card, QImage image); void picDownloadChanged(); + void picDownloadHqChanged(); void picsPathChanged(); void loadCardDatabase(); diff --git a/cockatrice/src/dlg_settings.cpp b/cockatrice/src/dlg_settings.cpp index 32d4f1fb..f7293964 100644 --- a/cockatrice/src/dlg_settings.cpp +++ b/cockatrice/src/dlg_settings.cpp @@ -27,7 +27,7 @@ GeneralSettingsPage::GeneralSettingsPage() { languageLabel = new QLabel; languageBox = new QComboBox; - + QString setLanguage = settingsCache->getLang(); QStringList qmFiles = findQmFiles(); for (int i = 0; i < qmFiles.size(); i++) { @@ -36,27 +36,32 @@ GeneralSettingsPage::GeneralSettingsPage() if ((qmFiles[i] == setLanguage) || (setLanguage.isEmpty() && langName == tr("English"))) languageBox->setCurrentIndex(i); } - + picDownloadCheckBox = new QCheckBox; picDownloadCheckBox->setChecked(settingsCache->getPicDownload()); - + + picDownloadHqCheckBox = new QCheckBox; + picDownloadHqCheckBox->setChecked(settingsCache->getPicDownloadHq()); + connect(languageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(languageBoxChanged(int))); connect(picDownloadCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPicDownload(int))); - + connect(picDownloadHqCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPicDownloadHq(int))); + QGridLayout *personalGrid = new QGridLayout; personalGrid->addWidget(languageLabel, 0, 0); personalGrid->addWidget(languageBox, 0, 1); personalGrid->addWidget(picDownloadCheckBox, 1, 0, 1, 2); - + personalGrid->addWidget(picDownloadHqCheckBox, 2, 0, 1, 2); + personalGroupBox = new QGroupBox; personalGroupBox->setLayout(personalGrid); - + deckPathLabel = new QLabel; deckPathEdit = new QLineEdit(settingsCache->getDeckPath()); deckPathEdit->setReadOnly(true); QPushButton *deckPathButton = new QPushButton("..."); connect(deckPathButton, SIGNAL(clicked()), this, SLOT(deckPathButtonClicked())); - + replaysPathLabel = new QLabel; replaysPathEdit = new QLineEdit(settingsCache->getReplaysPath()); replaysPathEdit->setReadOnly(true); @@ -183,6 +188,7 @@ void GeneralSettingsPage::retranslateUi() personalGroupBox->setTitle(tr("Personal settings")); languageLabel->setText(tr("Language:")); picDownloadCheckBox->setText(tr("Download card pictures on the fly")); + picDownloadHqCheckBox->setText(tr("Download high-quality card pictures")); pathsGroupBox->setTitle(tr("Paths")); deckPathLabel->setText(tr("Decks directory:")); replaysPathLabel->setText(tr("Replays directory:")); diff --git a/cockatrice/src/dlg_settings.h b/cockatrice/src/dlg_settings.h index 5f87887c..8462f612 100644 --- a/cockatrice/src/dlg_settings.h +++ b/cockatrice/src/dlg_settings.h @@ -40,6 +40,7 @@ private: QGroupBox *personalGroupBox, *pathsGroupBox; QComboBox *languageBox; QCheckBox *picDownloadCheckBox; + QCheckBox *picDownloadHqCheckBox; QLabel *languageLabel, *deckPathLabel, *replaysPathLabel, *picsPathLabel, *cardDatabasePathLabel, *tokenDatabasePathLabel; }; diff --git a/cockatrice/src/settingscache.cpp b/cockatrice/src/settingscache.cpp index 3bcc4111..ac5c130f 100644 --- a/cockatrice/src/settingscache.cpp +++ b/cockatrice/src/settingscache.cpp @@ -20,6 +20,7 @@ SettingsCache::SettingsCache() cardBackPicturePath = settings->value("paths/cardbackpicture").toString(); picDownload = settings->value("personal/picturedownload", true).toBool(); + picDownloadHq = settings->value("personal/picturedownloadhq", false).toBool(); picUrl = settings->value("personal/picUrl", PIC_URL_DEFAULT).toString(); picUrlHq = settings->value("personal/picUrlHq", PIC_URL_HQ_DEFAULT).toString(); @@ -128,6 +129,13 @@ void SettingsCache::setPicDownload(int _picDownload) emit picDownloadChanged(); } +void SettingsCache::setPicDownloadHq(int _picDownloadHq) +{ + picDownloadHq = _picDownloadHq; + settings->setValue("personal/picturedownloadhq", picDownloadHq); + emit picDownloadHqChanged(); +} + void SettingsCache::setPicUrl(const QString &_picUrl) { picUrl = _picUrl; diff --git a/cockatrice/src/settingscache.h b/cockatrice/src/settingscache.h index ba3dbb00..5156772d 100644 --- a/cockatrice/src/settingscache.h +++ b/cockatrice/src/settingscache.h @@ -3,7 +3,7 @@ #include -#define PIC_URL_DEFAULT "http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=!cardid!&type=card" +#define PIC_URL_DEFAULT "http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=!cardid!&type=card" #define PIC_URL_HQ_DEFAULT "http://mtgimage.com/multiverseid/!cardid!.jpg" class QSettings; @@ -21,6 +21,7 @@ signals: void playerBgPathChanged(); void cardBackPicturePathChanged(); void picDownloadChanged(); + void picDownloadHqChanged(); void displayCardNamesChanged(); void horizontalHandChanged(); void invertVerticalCoordinateChanged(); @@ -36,6 +37,7 @@ private: QString deckPath, replaysPath, picsPath, cardDatabasePath, tokenDatabasePath; QString handBgPath, stackBgPath, tableBgPath, playerBgPath, cardBackPicturePath; bool picDownload; + bool picDownloadHq; bool notificationsEnabled; bool doubleClickToPlay; bool playToStack; @@ -68,6 +70,7 @@ public: QString getPlayerBgPath() const { return playerBgPath; } QString getCardBackPicturePath() const { return cardBackPicturePath; } bool getPicDownload() const { return picDownload; } + bool getPicDownloadHq() const { return picDownloadHq; } bool getNotificationsEnabled() const { return notificationsEnabled; } bool getDoubleClickToPlay() const { return doubleClickToPlay; } bool getPlayToStack() const { return playToStack; } @@ -100,6 +103,7 @@ public slots: void setPlayerBgPath(const QString &_playerBgPath); void setCardBackPicturePath(const QString &_cardBackPicturePath); void setPicDownload(int _picDownload); + void setPicDownloadHq(int _picDownloadHq); void setNotificationsEnabled(int _notificationsEnabled); void setDoubleClickToPlay(int _doubleClickToPlay); void setPlayToStack(int _playToStack); From 53de2db89c6da54895c3182a4001834263ac66fb Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 21 Jun 2014 11:04:52 +0200 Subject: [PATCH 18/24] Clean up code leftovers --- oracle/src/oracleimporter.cpp | 20 +------------------- oracle/src/oraclewizard.cpp | 8 -------- 2 files changed, 1 insertion(+), 27 deletions(-) diff --git a/oracle/src/oracleimporter.cpp b/oracle/src/oracleimporter.cpp index a95481e2..c531a036 100644 --- a/oracle/src/oracleimporter.cpp +++ b/oracle/src/oracleimporter.cpp @@ -205,25 +205,7 @@ int OracleImporter::importTextSpoiler(CardSet *set, const QVariant &data) return cards; } -/* -QString OracleImporter::getPictureUrl(QString url, int cardId, QString name, const QString &setName) const -{ - if ((name == "Island") || (name == "Swamp") || (name == "Mountain") || (name == "Plains") || (name == "Forest")) - name.append("1"); - return url.replace("!cardid!", QString::number(cardId)).replace("!set!", setName).replace("!name!", name - .replace("ö", "o") -// .remove('\'') - .remove(" // ") -// .remove(',') -// .remove(':') -// .remove('.') - .remove(QRegExp("\\(.*\\)")) - .simplified() -// .replace(' ', '_') -// .replace('-', '_') - ); -} -*/ + int OracleImporter::startImport() { clear(); diff --git a/oracle/src/oraclewizard.cpp b/oracle/src/oraclewizard.cpp index 92bcaa4c..5869b873 100644 --- a/oracle/src/oraclewizard.cpp +++ b/oracle/src/oraclewizard.cpp @@ -19,10 +19,6 @@ OracleWizard::OracleWizard(QWidget *parent) addPage(new ChooseSetsPage); addPage(new SaveSetsPage); -/* - setPixmap(QWizard::BannerPixmap, QPixmap(":/images/banner.png")); - setPixmap(QWizard::BackgroundPixmap, QPixmap(":/images/background.png")); -*/ setWindowTitle(tr("Oracle Importer")); } @@ -47,7 +43,6 @@ IntroPage::IntroPage(QWidget *parent) : OracleWizardPage(parent) { setTitle(tr("Introduction")); - //setPixmap(QWizard::WatermarkPixmap, QPixmap(":/images/watermark1.png")); label = new QLabel(tr("This wizard will import the list of sets and cards " "that will be used by Cockatrice. You will need to " @@ -69,7 +64,6 @@ LoadSetsPage::LoadSetsPage(QWidget *parent) setSubTitle(tr("Please specify a source for the list of sets and cards. " "You can specify an url address that will be download or " "use an existing file from your computer.")); - //setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo1.png")); urlRadioButton = new QRadioButton(tr("Download url:"), this); fileRadioButton = new QRadioButton(tr("Local file:"), this); @@ -327,8 +321,6 @@ SaveSetsPage::SaveSetsPage(QWidget *parent) setSubTitle(tr("The following sets has been imported. " "Press \"Done\" to save the imported cards to the Cockatrice database.")); -// setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo3.png")); - messageLog = new QTextEdit(this); messageLog->setReadOnly(true); From 075c743a17f33e9d195abfae71902176dd7b12d3 Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 21 Jun 2014 11:11:49 +0200 Subject: [PATCH 19/24] Sets: case insensitive sorting --- oracle/src/oracleimporter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oracle/src/oracleimporter.h b/oracle/src/oracleimporter.h index a320fd5a..dc5b45fc 100644 --- a/oracle/src/oracleimporter.h +++ b/oracle/src/oracleimporter.h @@ -18,7 +18,7 @@ public: void setImport(bool _import) { import = _import; } SetToDownload(const QString &_shortName, const QString &_longName, const QVariant &_cards, bool _import) : shortName(_shortName), longName(_longName), cards(_cards), import(_import) { } - bool operator<(const SetToDownload &set) const { return longName < set.longName; } + bool operator<(const SetToDownload &set) const { return longName.compare(set.longName, Qt::CaseInsensitive) < 0; } }; class OracleImporter : public CardDatabase { From c6078c384c693eef15afaf9786e12489c02f75d5 Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 21 Jun 2014 11:18:41 +0200 Subject: [PATCH 20/24] Strip { } around mana cost --- oracle/src/oracleimporter.cpp | 8 ++++++-- oracle/src/oracleimporter.h | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/oracle/src/oracleimporter.cpp b/oracle/src/oracleimporter.cpp index c531a036..70972d92 100644 --- a/oracle/src/oracleimporter.cpp +++ b/oracle/src/oracleimporter.cpp @@ -53,7 +53,7 @@ CardInfo *OracleImporter::addCard(const QString &setName, QString cardName, bool isToken, int cardId, - const QString &cardCost, + QString &cardCost, const QString &cardType, const QString &cardPT, int cardLoyalty, @@ -69,7 +69,11 @@ CardInfo *OracleImporter::addCard(const QString &setName, if (cardName.contains("XX")) cardName.remove("XX"); cardName = cardName.replace("Æ", "AE"); - cardName = cardName.replace("’", "'"); + cardName = cardName.replace("’", "'"); + + // Remove {} around mana costs + cardCost.remove(QChar('{')); + cardCost.remove(QChar('}')); CardInfo *card; if (cardHash.contains(cardName)) { diff --git a/oracle/src/oracleimporter.h b/oracle/src/oracleimporter.h index dc5b45fc..1f705eeb 100644 --- a/oracle/src/oracleimporter.h +++ b/oracle/src/oracleimporter.h @@ -28,7 +28,7 @@ private: QVariantMap setsMap; QString dataDir; - CardInfo *addCard(const QString &setName, QString cardName, bool isToken, int cardId, const QString &cardCost, const QString &cardType, const QString &cardPT, int cardLoyalty, const QStringList &cardText); + CardInfo *addCard(const QString &setName, QString cardName, bool isToken, int cardId, QString &cardCost, const QString &cardType, const QString &cardPT, int cardLoyalty, const QStringList &cardText); signals: void setIndexChanged(int cardsImported, int setIndex, const QString &setName); void dataReadProgress(int bytesRead, int totalBytes); From bb9a79f83b5253df1b2e4465b3d874c2fbd941a9 Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 21 Jun 2014 11:25:24 +0200 Subject: [PATCH 21/24] Rename the finish/done button as "Save" --- oracle/src/oraclewizard.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/oracle/src/oraclewizard.cpp b/oracle/src/oraclewizard.cpp index 5869b873..7b48b341 100644 --- a/oracle/src/oraclewizard.cpp +++ b/oracle/src/oraclewizard.cpp @@ -20,6 +20,7 @@ OracleWizard::OracleWizard(QWidget *parent) addPage(new SaveSetsPage); setWindowTitle(tr("Oracle Importer")); + QWizard::setButtonText(QWizard::FinishButton, tr("Save")); } void OracleWizard::accept() @@ -319,7 +320,7 @@ SaveSetsPage::SaveSetsPage(QWidget *parent) { setTitle(tr("Sets imported")); setSubTitle(tr("The following sets has been imported. " - "Press \"Done\" to save the imported cards to the Cockatrice database.")); + "Press \"Save\" to save the imported cards to the Cockatrice database.")); messageLog = new QTextEdit(this); messageLog->setReadOnly(true); From 1edc34f086a9e9bb99891800de7d27c3d03d1f6e Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 21 Jun 2014 11:37:46 +0200 Subject: [PATCH 22/24] Add an option to force selection of save path By default oracle saves cards.xml to the correct path, where cockatrice will be able to pick it up; if oracle is not able to determine the path or the user unchecks the option, oracle will ask for a save path --- oracle/src/oraclewizard.cpp | 9 +++++++-- oracle/src/oraclewizard.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/oracle/src/oraclewizard.cpp b/oracle/src/oraclewizard.cpp index 7b48b341..66417764 100644 --- a/oracle/src/oraclewizard.cpp +++ b/oracle/src/oraclewizard.cpp @@ -322,11 +322,16 @@ SaveSetsPage::SaveSetsPage(QWidget *parent) setSubTitle(tr("The following sets has been imported. " "Press \"Save\" to save the imported cards to the Cockatrice database.")); + defaultPathCheckBox = new QCheckBox(this); + defaultPathCheckBox->setText(tr("Save to the default path (recommended)")); + defaultPathCheckBox->setChecked(true); + messageLog = new QTextEdit(this); messageLog->setReadOnly(true); QGridLayout *layout = new QGridLayout(this); - layout->addWidget(messageLog, 0, 0); + layout->addWidget(defaultPathCheckBox, 0, 0); + layout->addWidget(messageLog, 1, 0); setLayout(layout); } @@ -366,7 +371,7 @@ bool SaveSetsPage::validatePage() QString savePath = dataDir + "/cards.xml"; do { QString fileName; - if (savePath.isEmpty()) + if (savePath.isEmpty() || !defaultPathCheckBox->isChecked()) fileName = QFileDialog::getSaveFileName(this, tr("Save card database"), dataDir + "/cards.xml", tr("XML card database (*.xml)")); else { fileName = savePath; diff --git a/oracle/src/oraclewizard.h b/oracle/src/oraclewizard.h index 5514b9da..152ce3ad 100644 --- a/oracle/src/oraclewizard.h +++ b/oracle/src/oraclewizard.h @@ -100,6 +100,7 @@ public: SaveSetsPage(QWidget *parent = 0); private: QTextEdit *messageLog; + QCheckBox * defaultPathCheckBox; protected: void initializePage(); void cleanupPage(); From 17f7fe7ad918b32e6a9472b25f367afc549ff952 Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 21 Jun 2014 11:41:31 +0200 Subject: [PATCH 23/24] Don't lock the UI if the loaded file was not readable --- oracle/src/oraclewizard.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/oracle/src/oraclewizard.cpp b/oracle/src/oraclewizard.cpp index 66417764..28a5c646 100644 --- a/oracle/src/oraclewizard.cpp +++ b/oracle/src/oraclewizard.cpp @@ -221,13 +221,13 @@ void LoadSetsPage::readSetsFromByteArray(QByteArray data) void LoadSetsPage::importFinished() { + wizard()->enableButtons(); + setEnabled(true); + progressLabel->hide(); + progressBar->hide(); + if(watcher.future().result()) { - wizard()->enableButtons(); - setEnabled(true); - progressLabel->hide(); - progressBar->hide(); - wizard()->next(); } else { QMessageBox::critical(this, tr("Error"), tr("The file was retrieved successfully, but it does not contain any sets data.")); From 0ec5842c3f4d134f837730368e4a3c0d7e518fcc Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Sat, 21 Jun 2014 12:10:04 +0200 Subject: [PATCH 24/24] Add an unexposed config value for the AllSets.json file url MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It will be saved only if: * it’s different than the default (the user used a custom url); * the download actually worked --- oracle/src/oraclewizard.cpp | 12 ++++++++++-- oracle/src/oraclewizard.h | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/oracle/src/oraclewizard.cpp b/oracle/src/oraclewizard.cpp index 28a5c646..75381b1d 100644 --- a/oracle/src/oraclewizard.cpp +++ b/oracle/src/oraclewizard.cpp @@ -12,6 +12,7 @@ OracleWizard::OracleWizard(QWidget *parent) : QWizard(parent) { + settings = new QSettings(this); importer = new OracleImporter(QDesktopServices::storageLocation(QDesktopServices::DataLocation), this); addPage(new IntroPage); @@ -76,7 +77,6 @@ LoadSetsPage::LoadSetsPage(QWidget *parent) progressBar = new QProgressBar(this); urlRadioButton->setChecked(true); - urlLineEdit->setText(ALLSETS_URL); fileButton = new QPushButton(tr("Choose file..."), this); connect(fileButton, SIGNAL(clicked()), this, SLOT(actLoadSetsFile())); @@ -97,6 +97,8 @@ LoadSetsPage::LoadSetsPage(QWidget *parent) void LoadSetsPage::initializePage() { + urlLineEdit->setText(wizard()->settings->value("allsetsurl", ALLSETS_URL).toString()); + progressLabel->hide(); progressBar->hide(); } @@ -200,7 +202,13 @@ void LoadSetsPage::actDownloadFinishedSetsFile() return; } - this->readSetsFromByteArray(reply->readAll()); + // save allsets.json url, but only if the user customized it and download was successfull + if(urlLineEdit->text() != QString(ALLSETS_URL)) + wizard()->settings->setValue("allsetsurl", urlLineEdit->text()); + else + wizard()->settings->remove("allsetsurl"); + + readSetsFromByteArray(reply->readAll()); reply->deleteLater(); } diff --git a/oracle/src/oraclewizard.h b/oracle/src/oraclewizard.h index 152ce3ad..6e6a6ea8 100644 --- a/oracle/src/oraclewizard.h +++ b/oracle/src/oraclewizard.h @@ -15,6 +15,7 @@ class QNetworkAccessManager; class QTextEdit; class QVBoxLayout; class OracleImporter; +class QSettings; class OracleWizard : public QWizard { @@ -26,6 +27,7 @@ public: void disableButtons(); public: OracleImporter *importer; + QSettings * settings; };