mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-11 16:44:48 -07:00
Merge remote-tracking branch 'upstream/master' into cmake_qt5
This commit is contained in:
commit
5c13c06982
34 changed files with 1505 additions and 1221 deletions
|
|
@ -1,6 +1,6 @@
|
|||
#include <QApplication>
|
||||
#include <QTextCodec>
|
||||
#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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,330 +1,246 @@
|
|||
#include "oracleimporter.h"
|
||||
#if QT_VERSION < 0x050000
|
||||
#include <QtGui>
|
||||
#include <QtGui>
|
||||
#else
|
||||
#include <QtWidgets>
|
||||
#include <QtWidgets>
|
||||
#endif
|
||||
|
||||
#include <QtNetwork>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QDomDocument>
|
||||
#include <QDebug>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
QXmlStreamReader xml(&setsFile);
|
||||
return readSetsFromXml(xml);
|
||||
}
|
||||
|
||||
bool OracleImporter::readSetsFromByteArray(const QByteArray &data)
|
||||
{
|
||||
QXmlStreamReader xml(data);
|
||||
return readSetsFromXml(xml);
|
||||
}
|
||||
QList<SetToDownload> newSetList;
|
||||
|
||||
bool ok;
|
||||
setsMap = QtJson::Json::parse(QString(data), ok).toMap();
|
||||
if (!ok) {
|
||||
qDebug() << "error: QtJson::Json::parse()";
|
||||
return 0;
|
||||
}
|
||||
|
||||
QListIterator<QVariant> it(setsMap.values());
|
||||
QVariantMap map;
|
||||
|
||||
bool OracleImporter::readSetsFromXml(QXmlStreamReader &xml)
|
||||
{
|
||||
QList<SetToDownload> 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;
|
||||
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));
|
||||
}
|
||||
|
||||
qSort(newSetList);
|
||||
|
||||
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 cardName,
|
||||
bool isToken,
|
||||
int cardId,
|
||||
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("’", "'");
|
||||
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;
|
||||
// Remove {} around mana costs
|
||||
cardCost.remove(QChar('{'));
|
||||
cardCost.remove(QChar('}'));
|
||||
|
||||
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 QByteArray &data)
|
||||
int OracleImporter::importTextSpoiler(CardSet *set, const QVariant &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;
|
||||
int cards = 0;
|
||||
|
||||
QListIterator<QVariant> it(data.toList());
|
||||
QVariantMap map;
|
||||
QString cardName;
|
||||
QString cardCost;
|
||||
QString cardType;
|
||||
QString cardPT;
|
||||
QString cardText;
|
||||
int cardId;
|
||||
int cardLoyalty;
|
||||
QMap<int, QVariantMap> splitCards;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
return cards;
|
||||
while (it.hasNext()) {
|
||||
map = it.next().toMap();
|
||||
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;
|
||||
|
||||
// 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 = ↦
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
QString OracleImporter::getPictureUrl(QString url, int cardId, QString name, const QString &setName) const
|
||||
int OracleImporter::startImport()
|
||||
{
|
||||
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()
|
||||
{
|
||||
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("!longname!", setsToDownload[setIndex].getLongName());
|
||||
|
||||
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<SetToDownload> it(allSets);
|
||||
const SetToDownload * curSet;
|
||||
|
||||
while (it.hasNext())
|
||||
{
|
||||
curSet = & it.next();
|
||||
if(!curSet->getImport())
|
||||
continue;
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,53 +1,42 @@
|
|||
#ifndef ORACLEIMPORTER_H
|
||||
#define ORACLEIMPORTER_H
|
||||
|
||||
#include <carddatabase.h>
|
||||
#include <QHttp>
|
||||
#include <QMap>
|
||||
|
||||
class QBuffer;
|
||||
class QXmlStreamReader;
|
||||
#include <carddatabase.h>
|
||||
|
||||
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) { }
|
||||
bool operator<(const SetToDownload &set) const { return longName.compare(set.longName, Qt::CaseInsensitive) < 0; }
|
||||
};
|
||||
|
||||
class OracleImporter : public CardDatabase {
|
||||
Q_OBJECT
|
||||
private:
|
||||
QList<SetToDownload> allSets, setsToDownload;
|
||||
QString pictureUrl, pictureUrlHq, pictureUrlSt, setUrl;
|
||||
QList<SetToDownload> 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);
|
||||
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 &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 startDownload();
|
||||
int importTextSpoiler(CardSet *set, const QByteArray &data);
|
||||
int startImport();
|
||||
int importTextSpoiler(CardSet *set, const QVariant &data);
|
||||
QList<SetToDownload> &getSets() { return allSets; }
|
||||
const QString &getDataDir() const { return dataDir; }
|
||||
};
|
||||
|
|
|
|||
398
oracle/src/oraclewizard.cpp
Normal file
398
oracle/src/oraclewizard.cpp
Normal file
|
|
@ -0,0 +1,398 @@
|
|||
#include <QtGui>
|
||||
#include <QGridLayout>
|
||||
#include <QDesktopServices>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
|
||||
#include "oraclewizard.h"
|
||||
#include "oracleimporter.h"
|
||||
|
||||
#define ALLSETS_URL "http://mtgjson.com/json/AllSets.json"
|
||||
|
||||
OracleWizard::OracleWizard(QWidget *parent)
|
||||
: QWizard(parent)
|
||||
{
|
||||
settings = new QSettings(this);
|
||||
importer = new OracleImporter(QDesktopServices::storageLocation(QDesktopServices::DataLocation), this);
|
||||
|
||||
addPage(new IntroPage);
|
||||
addPage(new LoadSetsPage);
|
||||
addPage(new ChooseSetsPage);
|
||||
addPage(new SaveSetsPage);
|
||||
|
||||
setWindowTitle(tr("Oracle Importer"));
|
||||
QWizard::setButtonText(QWizard::FinishButton, tr("Save"));
|
||||
}
|
||||
|
||||
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"));
|
||||
|
||||
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."));
|
||||
|
||||
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);
|
||||
|
||||
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()
|
||||
{
|
||||
urlLineEdit->setText(wizard()->settings->value("allsetsurl", ALLSETS_URL).toString());
|
||||
|
||||
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<QNetworkReply *>(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;
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
wizard()->enableButtons();
|
||||
setEnabled(true);
|
||||
progressLabel->hide();
|
||||
progressBar->hide();
|
||||
|
||||
if(watcher.future().result())
|
||||
{
|
||||
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<SetToDownload> &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<QCheckBox *>(sender());
|
||||
QList<SetToDownload> &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 \"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(defaultPathCheckBox, 0, 0);
|
||||
layout->addWidget(messageLog, 1, 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("<b>" + tr("Import finished: %1 cards.").arg(wizard()->importer->getCardList().size()) + "</b>");
|
||||
} 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() || !defaultPathCheckBox->isChecked())
|
||||
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;
|
||||
}
|
||||
114
oracle/src/oraclewizard.h
Normal file
114
oracle/src/oraclewizard.h
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
#ifndef ORACLEWIZARD_H
|
||||
#define ORACLEWIZARD_H
|
||||
|
||||
#include <QWizard>
|
||||
#include <QFutureWatcher>
|
||||
#include <QFuture>
|
||||
|
||||
class QCheckBox;
|
||||
class QGroupBox;
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
class QRadioButton;
|
||||
class QProgressBar;
|
||||
class QNetworkAccessManager;
|
||||
class QTextEdit;
|
||||
class QVBoxLayout;
|
||||
class OracleImporter;
|
||||
class QSettings;
|
||||
|
||||
class OracleWizard : public QWizard
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
OracleWizard(QWidget *parent = 0);
|
||||
void accept();
|
||||
void enableButtons();
|
||||
void disableButtons();
|
||||
public:
|
||||
OracleImporter *importer;
|
||||
QSettings * settings;
|
||||
};
|
||||
|
||||
|
||||
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<bool> watcher;
|
||||
QFuture<bool> 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<QCheckBox *> 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;
|
||||
QCheckBox * defaultPathCheckBox;
|
||||
protected:
|
||||
void initializePage();
|
||||
void cleanupPage();
|
||||
bool validatePage();
|
||||
private slots:
|
||||
void updateTotalProgress(int cardsImported, int setIndex, const QString &setName);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,256 +0,0 @@
|
|||
#include <QApplication>
|
||||
#include <QMenu>
|
||||
#include <QMenuBar>
|
||||
#include <QStatusBar>
|
||||
#include <QLineEdit>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QScrollArea>
|
||||
#include <QTextEdit>
|
||||
#include <QInputDialog>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QCheckBox>
|
||||
#include <QProgressBar>
|
||||
#include <QVBoxLayout>
|
||||
#include <QDesktopServices>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include "window_main.h"
|
||||
#include "oracleimporter.h"
|
||||
|
||||
const QString WindowMain::defaultSetsUrl = QString("http://www.woogerworks.com/files/sets.xml");
|
||||
|
||||
WindowMain::WindowMain(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
{
|
||||
#if QT_VERSION < 0x050000
|
||||
importer = new OracleImporter(QDesktopServices::storageLocation(QDesktopServices::DataLocation), this);
|
||||
#else
|
||||
importer = new OracleImporter(QStandardPaths::standardLocations(QStandardPaths::DataLocation)).toString(), this);
|
||||
#endif
|
||||
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 download"));
|
||||
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<SetToDownload> &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 XML file (*.xml)");
|
||||
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<QNetworkReply *>(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;
|
||||
#if QT_VERSION < 0x050000
|
||||
const QString dataDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
|
||||
#else
|
||||
const QString dataDir = QStandardPaths::standardLocations(QStandardPaths::DataLocation)).toString();
|
||||
#endif
|
||||
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->startDownload();
|
||||
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<QCheckBox *>(sender());
|
||||
QList<SetToDownload> &sets = importer->getSets();
|
||||
for (int i = 0; i < sets.size(); ++i)
|
||||
if (sets[i].getLongName() == checkBox->text()) {
|
||||
sets[i].setImport(state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
#ifndef WINDOW_MAIN_H
|
||||
#define WINDOW_MAIN_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QList>
|
||||
|
||||
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<QCheckBox *> 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue