mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-07-13 14:02:15 -07:00
Merge branch 'master' into valgrind
This commit is contained in:
commit
954489e6c0
105 changed files with 5903 additions and 4729 deletions
|
|
@ -13,6 +13,7 @@
|
|||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QDebug>
|
||||
#include <QImageReader>
|
||||
|
||||
const int CardDatabase::versionNeeded = 3;
|
||||
|
||||
|
|
@ -92,6 +93,14 @@ bool PictureToLoad::nextSet()
|
|||
return true;
|
||||
}
|
||||
|
||||
QString PictureToLoad::getSetName() const
|
||||
{
|
||||
if (setIndex < sortedSets.size())
|
||||
return sortedSets[setIndex]->getCorrectedShortName();
|
||||
else
|
||||
return QString("");
|
||||
}
|
||||
|
||||
PictureLoader::PictureLoader(const QString &__picsPath, bool _picDownload, bool _picDownloadHq, QObject *parent)
|
||||
: QObject(parent),
|
||||
_picsPath(__picsPath), picDownload(_picDownload), picDownloadHq(_picDownloadHq),
|
||||
|
|
@ -124,41 +133,90 @@ void PictureLoader::processLoadQueue()
|
|||
}
|
||||
PictureToLoad ptl = loadQueue.takeFirst();
|
||||
mutex.unlock();
|
||||
QString correctedName = ptl.getCard()->getCorrectedName();
|
||||
QString picsPath = _picsPath;
|
||||
QString setName = ptl.getSetName();
|
||||
|
||||
//The list of paths to the folders in which to search for images
|
||||
QList<QString> picsPaths = QList<QString>() << _picsPath + "/CUSTOM/" + ptl.getCard()->getCorrectedName() + ".full";
|
||||
|
||||
|
||||
QString setName=ptl.getSetName();
|
||||
if(!setName.isEmpty())
|
||||
{
|
||||
picsPaths << _picsPath + "/" + setName + "/" + ptl.getCard()->getCorrectedName() + ".full"
|
||||
<< _picsPath + "/downloadedPics/" + setName + "/" + ptl.getCard()->getCorrectedName() + ".full";
|
||||
}
|
||||
|
||||
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)))
|
||||
if (!image.load(QString("%1/%2/%3/%4.full.jpg").arg(picsPath).arg("downloadedPics").arg(setName).arg(correctedName))) {
|
||||
if (picDownload) {
|
||||
cardsToDownload.append(ptl);
|
||||
if (!downloadRunning)
|
||||
startNextPicDownload();
|
||||
} else {
|
||||
if (ptl.nextSet())
|
||||
loadQueue.prepend(ptl);
|
||||
else
|
||||
emit imageLoaded(ptl.getCard(), QImage());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
QImageReader imgReader;
|
||||
imgReader.setDecideFormatFromContent(true);
|
||||
bool found = false;
|
||||
|
||||
emit imageLoaded(ptl.getCard(), image);
|
||||
//Iterates through the list of paths, searching for images with the desired name with any QImageReader-supported extension
|
||||
for (int i = 0; i < picsPaths.length() && !found; i ++) {
|
||||
imgReader.setFileName(picsPaths.at(i));
|
||||
if (imgReader.read(&image)) {
|
||||
emit imageLoaded(ptl.getCard(), image);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
if (picDownload) {
|
||||
cardsToDownload.append(ptl);
|
||||
if (!downloadRunning)
|
||||
startNextPicDownload();
|
||||
} else {
|
||||
if (ptl.nextSet())
|
||||
loadQueue.prepend(ptl);
|
||||
else
|
||||
emit imageLoaded(ptl.getCard(), QImage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString PictureLoader::getPicUrl(CardInfo *card)
|
||||
{
|
||||
if (!picDownload) return 0;
|
||||
if (!picDownload) return QString("");
|
||||
|
||||
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())));
|
||||
QString picUrl = QString("");
|
||||
|
||||
// if sets have been defined for the card, they can contain custom picUrls
|
||||
if(set)
|
||||
{
|
||||
// first check if Hq is enabled and a custom Hq card url exists in cards.xml
|
||||
if(picDownloadHq)
|
||||
{
|
||||
picUrl = card->getCustomPicURLHq(set->getShortName());
|
||||
if (!picUrl.isEmpty())
|
||||
return picUrl;
|
||||
}
|
||||
|
||||
// then, test for a custom, non-Hq card url in cards.xml
|
||||
picUrl = card->getCustomPicURL(set->getShortName());
|
||||
if (!picUrl.isEmpty())
|
||||
return picUrl;
|
||||
}
|
||||
|
||||
// otherwise, fallback to the default url
|
||||
picUrl = picDownloadHq ? settingsCache->getPicUrlHq() : settingsCache->getPicUrl();
|
||||
picUrl.replace("!name!", QUrl::toPercentEncoding(card->getCorrectedName()));
|
||||
|
||||
if (set) {
|
||||
picUrl.replace("!setcode!", QUrl::toPercentEncoding(set->getShortName()));
|
||||
picUrl.replace("!setname!", QUrl::toPercentEncoding(set->getLongName()));
|
||||
}
|
||||
int muid = card->getPreferredMuId();
|
||||
if (muid)
|
||||
picUrl.replace("!cardid!", QUrl::toPercentEncoding(QString::number(muid)));
|
||||
|
||||
if (picUrl.contains("!name!") ||
|
||||
picUrl.contains("!setcode!") ||
|
||||
picUrl.contains("!setname!") ||
|
||||
picUrl.contains("!cardid!")) {
|
||||
qDebug() << "Insufficient card data to download" << card->getName() << "Url:" << picUrl;
|
||||
return QString("");
|
||||
}
|
||||
|
||||
return picUrl;
|
||||
}
|
||||
|
|
@ -175,8 +233,13 @@ void PictureLoader::startNextPicDownload()
|
|||
|
||||
cardBeingDownloaded = cardsToDownload.takeFirst();
|
||||
|
||||
// TODO: Do something useful when picUrl is 0 or empty, etc
|
||||
QString picUrl = getPicUrl(cardBeingDownloaded.getCard());
|
||||
if (picUrl.isEmpty()) {
|
||||
qDebug() << "No url for" << cardBeingDownloaded.getCard()->getName();
|
||||
cardBeingDownloaded = 0;
|
||||
downloadRunning = false;
|
||||
return;
|
||||
}
|
||||
|
||||
QUrl url(picUrl);
|
||||
|
||||
|
|
@ -192,29 +255,35 @@ void PictureLoader::picDownloadFinished(QNetworkReply *reply)
|
|||
qDebug() << "Download failed:" << reply->errorString();
|
||||
}
|
||||
|
||||
const QByteArray &picData = reply->readAll();
|
||||
const QByteArray &picData = reply->peek(reply->size()); //peek is used to keep the data in the buffer for use by QImageReader
|
||||
QImage testImage;
|
||||
if (testImage.loadFromData(picData)) {
|
||||
if (!QDir(QString(picsPath + "/downloadedPics/")).exists()) {
|
||||
QDir dir(picsPath);
|
||||
if (!dir.exists())
|
||||
|
||||
QImageReader imgReader;
|
||||
imgReader.setDecideFormatFromContent(true);
|
||||
imgReader.setDevice(reply);
|
||||
QString extension = "." + imgReader.format(); //the format is determined prior to reading the QImageReader data into a QImage object, as that wipes the QImageReader buffer
|
||||
if (extension == ".jpeg")
|
||||
extension = ".jpg";
|
||||
|
||||
if (imgReader.read(&testImage)) {
|
||||
QString setName = cardBeingDownloaded.getSetName();
|
||||
if(!setName.isEmpty())
|
||||
{
|
||||
if (!QDir().mkpath(picsPath + "/downloadedPics/" + setName)) {
|
||||
qDebug() << picsPath + "/downloadedPics/" + setName + " could not be created.";
|
||||
return;
|
||||
dir.mkdir("downloadedPics");
|
||||
}
|
||||
if (!QDir(QString(picsPath + "/downloadedPics/" + cardBeingDownloaded.getSetName())).exists()) {
|
||||
QDir dir(QString(picsPath + "/downloadedPics"));
|
||||
dir.mkdir(cardBeingDownloaded.getSetName());
|
||||
}
|
||||
}
|
||||
|
||||
QString suffix;
|
||||
if (!cardBeingDownloaded.getStripped())
|
||||
suffix = ".full";
|
||||
QString suffix;
|
||||
if (!cardBeingDownloaded.getStripped())
|
||||
suffix = ".full";
|
||||
|
||||
QFile newPic(picsPath + "/downloadedPics/" + cardBeingDownloaded.getSetName() + "/" + cardBeingDownloaded.getCard()->getCorrectedName() + suffix + ".jpg");
|
||||
if (!newPic.open(QIODevice::WriteOnly))
|
||||
return;
|
||||
newPic.write(picData);
|
||||
newPic.close();
|
||||
QFile newPic(picsPath + "/downloadedPics/" + setName + "/" + cardBeingDownloaded.getCard()->getCorrectedName() + suffix + extension);
|
||||
if (!newPic.open(QIODevice::WriteOnly))
|
||||
return;
|
||||
newPic.write(picData);
|
||||
newPic.close();
|
||||
}
|
||||
|
||||
emit imageLoaded(cardBeingDownloaded.getCard(), testImage);
|
||||
} else if (cardBeingDownloaded.getHq()) {
|
||||
|
|
@ -275,6 +344,8 @@ CardInfo::CardInfo(CardDatabase *_db,
|
|||
bool _cipt,
|
||||
int _tableRow,
|
||||
const SetList &_sets,
|
||||
const QStringMap &_customPicURLs,
|
||||
const QStringMap &_customPicURLsHq,
|
||||
MuidMap _muIds)
|
||||
: db(_db),
|
||||
name(_name),
|
||||
|
|
@ -286,6 +357,8 @@ CardInfo::CardInfo(CardDatabase *_db,
|
|||
text(_text),
|
||||
colors(_colors),
|
||||
loyalty(_loyalty),
|
||||
customPicURLs(_customPicURLs),
|
||||
customPicURLsHq(_customPicURLsHq),
|
||||
muIds(_muIds),
|
||||
cipt(_cipt),
|
||||
tableRow(_tableRow),
|
||||
|
|
@ -424,6 +497,8 @@ void CardInfo::updatePixmapCache()
|
|||
|
||||
CardSet* CardInfo::getPreferredSet()
|
||||
{
|
||||
if(sets.isEmpty())
|
||||
return 0;
|
||||
SetList sortedSets = sets;
|
||||
sortedSets.sortByKey();
|
||||
return sortedSets.first();
|
||||
|
|
@ -431,7 +506,28 @@ CardSet* CardInfo::getPreferredSet()
|
|||
|
||||
int CardInfo::getPreferredMuId()
|
||||
{
|
||||
return muIds[getPreferredSet()->getShortName()];
|
||||
CardSet *set = getPreferredSet();
|
||||
return set ? muIds[set->getShortName()] : 0;
|
||||
}
|
||||
|
||||
QString CardInfo::simplifyName(const QString &name) {
|
||||
QString simpleName(name);
|
||||
|
||||
// So Aetherling would work, but not Ætherling since 'Æ' would get replaced
|
||||
// with nothing.
|
||||
simpleName.replace("æ", "ae");
|
||||
simpleName.replace("Æ", "AE");
|
||||
|
||||
// Replace Jötun Grunt with Jotun Grunt.
|
||||
simpleName = simpleName.normalized(QString::NormalizationForm_KD);
|
||||
|
||||
// Replace dashes with spaces so that we can say "garruk the veil cursed"
|
||||
// instead of the unintuitive "garruk the veilcursed".
|
||||
simpleName = simpleName.replace("-", " ");
|
||||
|
||||
simpleName.remove(QRegExp("[^a-zA-Z0-9 ]"));
|
||||
simpleName = simpleName.toLower();
|
||||
return simpleName;
|
||||
}
|
||||
|
||||
static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info)
|
||||
|
|
@ -448,6 +544,14 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info)
|
|||
tmpSet=sets[i]->getShortName();
|
||||
xml.writeAttribute("muId", QString::number(info->getMuId(tmpSet)));
|
||||
|
||||
tmpString = info->getCustomPicURL(tmpSet);
|
||||
if(!tmpString.isEmpty())
|
||||
xml.writeAttribute("picURL", tmpString);
|
||||
|
||||
tmpString = info->getCustomPicURLHq(tmpSet);
|
||||
if(!tmpString.isEmpty())
|
||||
xml.writeAttribute("picURLHq", tmpString);
|
||||
|
||||
xml.writeCharacters(tmpSet);
|
||||
xml.writeEndElement();
|
||||
}
|
||||
|
|
@ -507,55 +611,55 @@ CardDatabase::~CardDatabase()
|
|||
|
||||
void CardDatabase::clear()
|
||||
{
|
||||
QHashIterator<QString, CardSet *> setIt(setHash);
|
||||
QHashIterator<QString, CardSet *> setIt(sets);
|
||||
while (setIt.hasNext()) {
|
||||
setIt.next();
|
||||
delete setIt.value();
|
||||
}
|
||||
setHash.clear();
|
||||
sets.clear();
|
||||
|
||||
QHashIterator<QString, CardInfo *> i(cardHash);
|
||||
QHashIterator<QString, CardInfo *> i(cards);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
delete i.value();
|
||||
}
|
||||
cardHash.clear();
|
||||
cards.clear();
|
||||
|
||||
// The pointers themselves were already deleted, so we don't delete them
|
||||
// again.
|
||||
simpleNameCards.clear();
|
||||
}
|
||||
|
||||
void CardDatabase::addCard(CardInfo *card)
|
||||
{
|
||||
cardHash.insert(card->getName(), card);
|
||||
cards.insert(card->getName(), card);
|
||||
simpleNameCards.insert(CardInfo::simplifyName(card->getName()), card);
|
||||
emit cardAdded(card);
|
||||
}
|
||||
|
||||
void CardDatabase::removeCard(CardInfo *card)
|
||||
{
|
||||
cardHash.remove(card->getName());
|
||||
cards.remove(card->getName());
|
||||
simpleNameCards.remove(CardInfo::simplifyName(card->getName()));
|
||||
emit cardRemoved(card);
|
||||
}
|
||||
|
||||
CardInfo *CardDatabase::getCard(const QString &cardName, bool createIfNotFound)
|
||||
{
|
||||
if (cardName.isEmpty())
|
||||
return noCard;
|
||||
else if (cardHash.contains(cardName))
|
||||
return cardHash.value(cardName);
|
||||
else if (createIfNotFound) {
|
||||
CardInfo *newCard = new CardInfo(this, cardName, true);
|
||||
newCard->addToSet(getSet("TK"));
|
||||
cardHash.insert(cardName, newCard);
|
||||
return newCard;
|
||||
} else
|
||||
return 0;
|
||||
CardInfo *CardDatabase::getCard(const QString &cardName, bool createIfNotFound) {
|
||||
return getCardFromMap(cards, cardName, createIfNotFound);
|
||||
}
|
||||
|
||||
CardInfo *CardDatabase::getCardBySimpleName(const QString &cardName, bool createIfNotFound) {
|
||||
QString simpleName = CardInfo::simplifyName(cardName);
|
||||
return getCardFromMap(simpleNameCards, simpleName, createIfNotFound);
|
||||
}
|
||||
|
||||
CardSet *CardDatabase::getSet(const QString &setName)
|
||||
{
|
||||
if (setHash.contains(setName))
|
||||
return setHash.value(setName);
|
||||
if (sets.contains(setName))
|
||||
return sets.value(setName);
|
||||
else {
|
||||
CardSet *newSet = new CardSet(setName);
|
||||
setHash.insert(setName, newSet);
|
||||
sets.insert(setName, newSet);
|
||||
return newSet;
|
||||
}
|
||||
}
|
||||
|
|
@ -563,7 +667,7 @@ CardSet *CardDatabase::getSet(const QString &setName)
|
|||
SetList CardDatabase::getSetList() const
|
||||
{
|
||||
SetList result;
|
||||
QHashIterator<QString, CardSet *> i(setHash);
|
||||
QHashIterator<QString, CardSet *> i(sets);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
result << i.value();
|
||||
|
|
@ -573,7 +677,9 @@ SetList CardDatabase::getSetList() const
|
|||
|
||||
void CardDatabase::clearPixmapCache()
|
||||
{
|
||||
QHashIterator<QString, CardInfo *> i(cardHash);
|
||||
// This also clears the cards in simpleNameCards since they point to the
|
||||
// same object.
|
||||
QHashIterator<QString, CardInfo *> i(cards);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
i.value()->clearPixmapCache();
|
||||
|
|
@ -597,7 +703,7 @@ void CardDatabase::loadSetsFromXml(QXmlStreamReader &xml)
|
|||
else if (xml.name() == "longname")
|
||||
longName = xml.readElementText();
|
||||
}
|
||||
setHash.insert(shortName, new CardSet(shortName, longName));
|
||||
sets.insert(shortName, new CardSet(shortName, longName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -610,6 +716,7 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml)
|
|||
if (xml.name() == "card") {
|
||||
QString name, manacost, type, pt, text;
|
||||
QStringList colors;
|
||||
QStringMap customPicURLs, customPicURLsHq;
|
||||
MuidMap muids;
|
||||
SetList sets;
|
||||
int tableRow = 0;
|
||||
|
|
@ -636,6 +743,12 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml)
|
|||
if (attrs.hasAttribute("muId")) {
|
||||
muids[setName] = attrs.value("muId").toString().toInt();
|
||||
}
|
||||
if (attrs.hasAttribute("picURL")) {
|
||||
customPicURLs[setName] = attrs.value("picURL").toString();
|
||||
}
|
||||
if (attrs.hasAttribute("picURLHq")) {
|
||||
customPicURLsHq[setName] = attrs.value("picURLHq").toString();
|
||||
}
|
||||
} else if (xml.name() == "color")
|
||||
colors << xml.readElementText();
|
||||
else if (xml.name() == "tablerow")
|
||||
|
|
@ -647,46 +760,32 @@ 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, muids));
|
||||
addCard(new CardInfo(this, name, isToken, manacost, type, pt, text, colors, loyalty, cipt, tableRow, sets, customPicURLs, customPicURLsHq, muids));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LoadStatus CardDatabase::loadFromFile(const QString &fileName, bool tokens)
|
||||
CardInfo *CardDatabase::getCardFromMap(CardNameMap &cardMap, const QString &cardName, bool createIfNotFound) {
|
||||
if (cardName.isEmpty())
|
||||
return noCard;
|
||||
else if (cardMap.contains(cardName))
|
||||
return cardMap.value(cardName);
|
||||
else if (createIfNotFound) {
|
||||
CardInfo *newCard = new CardInfo(this, cardName, true);
|
||||
newCard->addToSet(getSet("TK"));
|
||||
cardMap.insert(cardName, newCard);
|
||||
return newCard;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
LoadStatus CardDatabase::loadFromFile(const QString &fileName)
|
||||
{
|
||||
QFile file(fileName);
|
||||
file.open(QIODevice::ReadOnly);
|
||||
if (!file.isOpen())
|
||||
return FileError;
|
||||
|
||||
if (tokens) {
|
||||
QMutableHashIterator<QString, CardInfo *> i(cardHash);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
if (i.value()->getIsToken()) {
|
||||
delete i.value();
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QHashIterator<QString, CardSet *> setIt(setHash);
|
||||
while (setIt.hasNext()) {
|
||||
setIt.next();
|
||||
delete setIt.value();
|
||||
}
|
||||
setHash.clear();
|
||||
|
||||
QMutableHashIterator<QString, CardInfo *> i(cardHash);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
if (!i.value()->getIsToken()) {
|
||||
delete i.value();
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
cardHash.clear();
|
||||
}
|
||||
|
||||
QXmlStreamReader xml(&file);
|
||||
while (!xml.atEnd()) {
|
||||
if (xml.readNext() == QXmlStreamReader::StartElement) {
|
||||
|
|
@ -707,9 +806,9 @@ LoadStatus CardDatabase::loadFromFile(const QString &fileName, bool tokens)
|
|||
}
|
||||
}
|
||||
}
|
||||
qDebug() << cardHash.size() << "cards in" << setHash.size() << "sets loaded";
|
||||
qDebug() << cards.size() << "cards in" << sets.size() << "sets loaded";
|
||||
|
||||
if (cardHash.isEmpty()) return NoCards;
|
||||
if (cards.isEmpty()) return NoCards;
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
|
@ -728,18 +827,17 @@ bool CardDatabase::saveToFile(const QString &fileName, bool tokens)
|
|||
|
||||
if (!tokens) {
|
||||
xml.writeStartElement("sets");
|
||||
QHashIterator<QString, CardSet *> setIterator(setHash);
|
||||
QHashIterator<QString, CardSet *> setIterator(sets);
|
||||
while (setIterator.hasNext())
|
||||
xml << setIterator.next().value();
|
||||
xml.writeEndElement(); // sets
|
||||
}
|
||||
|
||||
xml.writeStartElement("cards");
|
||||
QHashIterator<QString, CardInfo *> cardIterator(cardHash);
|
||||
QHashIterator<QString, CardInfo *> cardIterator(cards);
|
||||
while (cardIterator.hasNext()) {
|
||||
CardInfo *card = cardIterator.next().value();
|
||||
if (card->getIsToken() == tokens)
|
||||
xml << card;
|
||||
xml << card;
|
||||
}
|
||||
xml.writeEndElement(); // cards
|
||||
|
||||
|
|
@ -753,7 +851,7 @@ void CardDatabase::picDownloadChanged()
|
|||
{
|
||||
pictureLoader->setPicDownload(settingsCache->getPicDownload());
|
||||
if (settingsCache->getPicDownload()) {
|
||||
QHashIterator<QString, CardInfo *> cardIterator(cardHash);
|
||||
QHashIterator<QString, CardInfo *> cardIterator(cards);
|
||||
while (cardIterator.hasNext())
|
||||
cardIterator.next().value()->clearPixmapCacheMiss();
|
||||
}
|
||||
|
|
@ -763,7 +861,7 @@ void CardDatabase::picDownloadHqChanged()
|
|||
{
|
||||
pictureLoader->setPicDownloadHq(settingsCache->getPicDownloadHq());
|
||||
if (settingsCache->getPicDownloadHq()) {
|
||||
QHashIterator<QString, CardInfo *> cardIterator(cardHash);
|
||||
QHashIterator<QString, CardInfo *> cardIterator(cards);
|
||||
while (cardIterator.hasNext())
|
||||
cardIterator.next().value()->clearPixmapCacheMiss();
|
||||
}
|
||||
|
|
@ -773,11 +871,11 @@ LoadStatus CardDatabase::loadCardDatabase(const QString &path, bool tokens)
|
|||
{
|
||||
LoadStatus tempLoadStatus = NotLoaded;
|
||||
if (!path.isEmpty())
|
||||
tempLoadStatus = loadFromFile(path, tokens);
|
||||
tempLoadStatus = loadFromFile(path);
|
||||
|
||||
if (tempLoadStatus == Ok) {
|
||||
SetList allSets;
|
||||
QHashIterator<QString, CardSet *> setsIterator(setHash);
|
||||
QHashIterator<QString, CardSet *> setsIterator(sets);
|
||||
while (setsIterator.hasNext())
|
||||
allSets.append(setsIterator.next().value());
|
||||
allSets.sortByKey();
|
||||
|
|
@ -809,7 +907,7 @@ void CardDatabase::loadTokenDatabase()
|
|||
QStringList CardDatabase::getAllColors() const
|
||||
{
|
||||
QSet<QString> colors;
|
||||
QHashIterator<QString, CardInfo *> cardIterator(cardHash);
|
||||
QHashIterator<QString, CardInfo *> cardIterator(cards);
|
||||
while (cardIterator.hasNext()) {
|
||||
const QStringList &cardColors = cardIterator.next().value()->getColors();
|
||||
if (cardColors.isEmpty())
|
||||
|
|
@ -824,7 +922,7 @@ QStringList CardDatabase::getAllColors() const
|
|||
QStringList CardDatabase::getAllMainCardTypes() const
|
||||
{
|
||||
QSet<QString> types;
|
||||
QHashIterator<QString, CardInfo *> cardIterator(cardHash);
|
||||
QHashIterator<QString, CardInfo *> cardIterator(cards);
|
||||
while (cardIterator.hasNext())
|
||||
types.insert(cardIterator.next().value()->getMainCardType());
|
||||
return types.toList();
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ public:
|
|||
PictureToLoad(CardInfo *_card = 0, bool _stripped = false, bool _hq = true);
|
||||
CardInfo *getCard() const { return card; }
|
||||
bool getStripped() const { return stripped; }
|
||||
QString getSetName() const { return sortedSets[setIndex]->getCorrectedShortName(); }
|
||||
QString getSetName() const;
|
||||
bool nextSet();
|
||||
bool getHq() const { return hq; }
|
||||
void setHq(bool _hq) { hq = _hq; }
|
||||
|
|
@ -95,6 +95,13 @@ private:
|
|||
CardDatabase *db;
|
||||
|
||||
QString name;
|
||||
|
||||
/*
|
||||
* The name without punctuation or capitalization, for better card tag name
|
||||
* recognition.
|
||||
*/
|
||||
QString simpleName;
|
||||
|
||||
bool isToken;
|
||||
SetList sets;
|
||||
QString manacost;
|
||||
|
|
@ -103,6 +110,7 @@ private:
|
|||
QString text;
|
||||
QStringList colors;
|
||||
int loyalty;
|
||||
QStringMap customPicURLs, customPicURLsHq;
|
||||
MuidMap muIds;
|
||||
bool cipt;
|
||||
int tableRow;
|
||||
|
|
@ -121,6 +129,8 @@ public:
|
|||
bool _cipt = false,
|
||||
int _tableRow = 0,
|
||||
const SetList &_sets = SetList(),
|
||||
const QStringMap &_customPicURLs = QStringMap(),
|
||||
const QStringMap &_customPicURLsHq = QStringMap(),
|
||||
MuidMap muids = MuidMap());
|
||||
~CardInfo();
|
||||
const QString &getName() const { return name; }
|
||||
|
|
@ -138,12 +148,16 @@ 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 getCustomPicURL(const QString &set) const { return customPicURLs.value(set); }
|
||||
QString getCustomPicURLHq(const QString &set) const { return customPicURLsHq.value(set); }
|
||||
int getMuId(const QString &set) const { return muIds.value(set); }
|
||||
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 setCustomPicURL(const QString &_set, const QString &_customPicURL) { customPicURLs.insert(_set, _customPicURL); }
|
||||
void setCustomPicURLHq(const QString &_set, const QString &_customPicURL) { customPicURLsHq.insert(_set, _customPicURL); }
|
||||
void setMuId(const QString &_set, const int &_muId) { muIds.insert(_set, _muId); }
|
||||
void addToSet(CardSet *set);
|
||||
QPixmap *loadPixmap();
|
||||
|
|
@ -153,6 +167,12 @@ public:
|
|||
void imageLoaded(const QImage &image);
|
||||
CardSet *getPreferredSet();
|
||||
int getPreferredMuId();
|
||||
|
||||
/**
|
||||
* Simplify a name to have no punctuation and lowercase all letters, for
|
||||
* less strict name-matching.
|
||||
*/
|
||||
static QString simplifyName(const QString &name);
|
||||
public slots:
|
||||
void updatePixmapCache();
|
||||
signals:
|
||||
|
|
@ -162,11 +182,27 @@ signals:
|
|||
|
||||
enum LoadStatus { Ok, VersionTooOld, Invalid, NotLoaded, FileError, NoCards };
|
||||
|
||||
typedef QHash<QString, CardInfo *> CardNameMap;
|
||||
typedef QHash<QString, CardSet *> SetNameMap;
|
||||
|
||||
class CardDatabase : public QObject {
|
||||
Q_OBJECT
|
||||
protected:
|
||||
QHash<QString, CardInfo *> cardHash;
|
||||
QHash<QString, CardSet *> setHash;
|
||||
/*
|
||||
* The cards, indexed by name.
|
||||
*/
|
||||
CardNameMap cards;
|
||||
|
||||
/**
|
||||
* The cards, indexed by their simple name.
|
||||
*/
|
||||
CardNameMap simpleNameCards;
|
||||
|
||||
/*
|
||||
* The sets, indexed by short name.
|
||||
*/
|
||||
SetNameMap sets;
|
||||
|
||||
CardInfo *noCard;
|
||||
|
||||
QThread *pictureLoaderThread;
|
||||
|
|
@ -176,6 +212,8 @@ private:
|
|||
static const int versionNeeded;
|
||||
void loadCardsFromXml(QXmlStreamReader &xml);
|
||||
void loadSetsFromXml(QXmlStreamReader &xml);
|
||||
|
||||
CardInfo *getCardFromMap(CardNameMap &cardMap, const QString &cardName, bool createIfNotFound);
|
||||
public:
|
||||
CardDatabase(QObject *parent = 0);
|
||||
~CardDatabase();
|
||||
|
|
@ -183,10 +221,17 @@ public:
|
|||
void addCard(CardInfo *card);
|
||||
void removeCard(CardInfo *card);
|
||||
CardInfo *getCard(const QString &cardName = QString(), bool createIfNotFound = true);
|
||||
|
||||
/*
|
||||
* Get a card by its simple name. The name will be simplified in this
|
||||
* function, so you don't need to simplify it beforehand.
|
||||
*/
|
||||
CardInfo *getCardBySimpleName(const QString &cardName = QString(), bool createIfNotFound = true);
|
||||
|
||||
CardSet *getSet(const QString &setName);
|
||||
QList<CardInfo *> getCardList() const { return cardHash.values(); }
|
||||
QList<CardInfo *> getCardList() const { return cards.values(); }
|
||||
SetList getSetList() const;
|
||||
LoadStatus loadFromFile(const QString &fileName, bool tokens = false);
|
||||
LoadStatus loadFromFile(const QString &fileName);
|
||||
bool saveToFile(const QString &fileName, bool tokens = false);
|
||||
QStringList getAllColors() const;
|
||||
QStringList getAllMainCardTypes() const;
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ CardInfoWidget::CardInfoWidget(ResizeMode _mode, const QString &cardName, QWidge
|
|||
} else
|
||||
setFixedWidth(250);
|
||||
|
||||
setCard(db->getCard(cardName));
|
||||
setCard(getCard(cardName));
|
||||
setMinimized(settingsCache->getCardInfoMinimized());
|
||||
}
|
||||
|
||||
|
|
@ -166,7 +166,7 @@ void CardInfoWidget::setCard(CardInfo *card)
|
|||
|
||||
void CardInfoWidget::setCard(const QString &cardName)
|
||||
{
|
||||
setCard(db->getCard(cardName));
|
||||
setCard(getCard(cardName));
|
||||
}
|
||||
|
||||
void CardInfoWidget::setCard(AbstractCardItem *card)
|
||||
|
|
@ -176,7 +176,11 @@ void CardInfoWidget::setCard(AbstractCardItem *card)
|
|||
|
||||
void CardInfoWidget::clear()
|
||||
{
|
||||
setCard(db->getCard());
|
||||
setCard(getCard());
|
||||
}
|
||||
|
||||
CardInfo *CardInfoWidget::getCard(const QString &cardName) {
|
||||
return db->getCardBySimpleName(cardName);
|
||||
}
|
||||
|
||||
void CardInfoWidget::updatePixmap()
|
||||
|
|
@ -188,7 +192,7 @@ void CardInfoWidget::updatePixmap()
|
|||
if (resizedPixmap)
|
||||
cardPicture->setPixmap(*resizedPixmap);
|
||||
else
|
||||
cardPicture->setPixmap(*(db->getCard()->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio))));
|
||||
cardPicture->setPixmap(*(getCard()->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio))));
|
||||
}
|
||||
|
||||
void CardInfoWidget::retranslateUi()
|
||||
|
|
|
|||
|
|
@ -42,6 +42,11 @@ private:
|
|||
CardInfo *info;
|
||||
void setMinimized(int _minimized);
|
||||
|
||||
/*
|
||||
* Wrapper around db->getCardBySimpleName.
|
||||
*/
|
||||
CardInfo *getCard(const QString &cardName = QString());
|
||||
|
||||
public:
|
||||
CardInfoWidget(ResizeMode _mode, const QString &cardName = QString(), QWidget *parent = 0, Qt::WindowFlags f = 0);
|
||||
void retranslateUi();
|
||||
|
|
|
|||
|
|
@ -233,7 +233,8 @@ CardDragItem *CardItem::createDragItem(int _id, const QPointF &_pos, const QPoin
|
|||
|
||||
void CardItem::deleteDragItem()
|
||||
{
|
||||
dragItem->deleteLater();
|
||||
if(dragItem)
|
||||
dragItem->deleteLater();
|
||||
dragItem = NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -472,13 +472,7 @@ void DeckListModel::printDeckList(QPrinter *printer)
|
|||
doc.print(printer);
|
||||
}
|
||||
|
||||
void DeckListModel::pricesUpdated(InnerDecklistNode *node)
|
||||
void DeckListModel::pricesUpdated()
|
||||
{
|
||||
if (!node)
|
||||
node = root;
|
||||
|
||||
if (node->isEmpty())
|
||||
return;
|
||||
|
||||
emit dataChanged(createIndex(0, 2, node->at(0)), createIndex(node->size() - 1, 2, node->last()));
|
||||
emit layoutChanged();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public:
|
|||
void cleanList();
|
||||
DeckLoader *getDeckList() const { return deckList; }
|
||||
void setDeckList(DeckLoader *_deck);
|
||||
void pricesUpdated(InnerDecklistNode *node = 0);
|
||||
void pricesUpdated();
|
||||
private:
|
||||
DeckLoader *deckList;
|
||||
InnerDecklistNode *root;
|
||||
|
|
|
|||
|
|
@ -11,8 +11,10 @@
|
|||
#include <QUrlQuery>
|
||||
#endif
|
||||
|
||||
DeckStatsInterface::DeckStatsInterface(QObject *parent)
|
||||
: QObject(parent)
|
||||
DeckStatsInterface::DeckStatsInterface(
|
||||
CardDatabase &_cardDatabase,
|
||||
QObject *parent
|
||||
) : QObject(parent), cardDatabase(_cardDatabase)
|
||||
{
|
||||
manager = new QNetworkAccessManager(this);
|
||||
connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(queryFinished(QNetworkReply *)));
|
||||
|
|
@ -43,24 +45,23 @@ void DeckStatsInterface::queryFinished(QNetworkReply *reply)
|
|||
deleteLater();
|
||||
}
|
||||
|
||||
void DeckStatsInterface::getAnalyzeRequestData(DeckList *deck, QByteArray *data)
|
||||
{
|
||||
DeckList deckWithoutTokens;
|
||||
copyDeckWithoutTokens(*deck, deckWithoutTokens);
|
||||
|
||||
#if QT_VERSION < 0x050000
|
||||
void DeckStatsInterface::getAnalyzeRequestData(DeckList *deck, QByteArray *data)
|
||||
{
|
||||
QUrl params;
|
||||
params.addQueryItem("deck", deck->writeToString_Plain());
|
||||
params.addQueryItem("deck", deckWithoutTokens.writeToString_Plain());
|
||||
data->append(params.encodedQuery());
|
||||
}
|
||||
#else
|
||||
void DeckStatsInterface::getAnalyzeRequestData(DeckList *deck, QByteArray *data)
|
||||
{
|
||||
QUrl params;
|
||||
QUrlQuery urlQuery;
|
||||
urlQuery.addQueryItem("deck", deck->writeToString_Plain());
|
||||
urlQuery.addQueryItem("deck", deckWithoutTokens.writeToString_Plain());
|
||||
params.setQuery(urlQuery);
|
||||
data->append(params.query(QUrl::EncodeReserved));
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void DeckStatsInterface::analyzeDeck(DeckList *deck)
|
||||
{
|
||||
|
|
@ -72,3 +73,34 @@ void DeckStatsInterface::analyzeDeck(DeckList *deck)
|
|||
|
||||
manager->post(request, data);
|
||||
}
|
||||
|
||||
struct CopyIfNotAToken {
|
||||
CardDatabase &cardDatabase;
|
||||
DeckList &destination;
|
||||
|
||||
CopyIfNotAToken(
|
||||
CardDatabase &_cardDatabase,
|
||||
DeckList &_destination
|
||||
) : cardDatabase(_cardDatabase), destination(_destination) {};
|
||||
|
||||
void operator()(
|
||||
const InnerDecklistNode *node,
|
||||
const DecklistCardNode *card
|
||||
) const {
|
||||
if (!cardDatabase.getCard(card->getName())->getIsToken()) {
|
||||
DecklistCardNode *addedCard = destination.addCard(
|
||||
card->getName(),
|
||||
node->getName()
|
||||
);
|
||||
addedCard->setNumber(card->getNumber());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void DeckStatsInterface::copyDeckWithoutTokens(
|
||||
const DeckList &source,
|
||||
DeckList &destination
|
||||
) {
|
||||
CopyIfNotAToken copyIfNotAToken(cardDatabase, destination);
|
||||
source.forEachCard(copyIfNotAToken);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef DECKSTATS_INTERFACE_H
|
||||
#define DECKSTATS_INTERFACE_H
|
||||
|
||||
#include "carddatabase.h"
|
||||
#include "decklist.h"
|
||||
#include <QObject>
|
||||
|
||||
class QByteArray;
|
||||
|
|
@ -12,11 +14,21 @@ class DeckStatsInterface : public QObject {
|
|||
Q_OBJECT
|
||||
private:
|
||||
QNetworkAccessManager *manager;
|
||||
|
||||
CardDatabase &cardDatabase;
|
||||
|
||||
/**
|
||||
* Deckstats doesn't recognize token cards, and instead tries to find the
|
||||
* closest non-token card instead. So we construct a new deck which has no
|
||||
* tokens.
|
||||
*/
|
||||
void copyDeckWithoutTokens(const DeckList &source, DeckList& destination);
|
||||
|
||||
private slots:
|
||||
void queryFinished(QNetworkReply *reply);
|
||||
void getAnalyzeRequestData(DeckList *deck, QByteArray *data);
|
||||
public:
|
||||
DeckStatsInterface(QObject *parent = 0);
|
||||
DeckStatsInterface(CardDatabase &_cardDatabase, QObject *parent = 0);
|
||||
void analyzeDeck(DeckList *deck);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ DlgEditTokens::DlgEditTokens(CardDatabaseModel *_cardDatabaseModel, QWidget *par
|
|||
setWindowTitle(tr("Edit tokens"));
|
||||
}
|
||||
|
||||
void DlgEditTokens::tokenSelectionChanged(const QModelIndex ¤t, const QModelIndex &previous)
|
||||
void DlgEditTokens::tokenSelectionChanged(const QModelIndex ¤t, const QModelIndex & /* previous */)
|
||||
{
|
||||
const QModelIndex realIndex = cardDatabaseDisplayModel->mapToSource(current);
|
||||
CardInfo *cardInfo = current.row() >= 0 ? cardDatabaseModel->getCard(realIndex.row()) : cardDatabaseModel->getDatabase()->getCard();
|
||||
|
|
|
|||
|
|
@ -9,26 +9,53 @@
|
|||
#include <QVBoxLayout>
|
||||
#include <QGridLayout>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QSettings>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
DlgFilterGames::DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
DlgFilterGames::DlgFilterGames(const QMap<int, QString> &_allGameTypes, QWidget *parent)
|
||||
: QDialog(parent),
|
||||
allGameTypes(_allGameTypes)
|
||||
{
|
||||
QSettings settings;
|
||||
settings.beginGroup("filter_games");
|
||||
|
||||
unavailableGamesVisibleCheckBox = new QCheckBox(tr("Show &unavailable games"));
|
||||
unavailableGamesVisibleCheckBox->setChecked(
|
||||
settings.value("unavailable_games_visible", false).toBool()
|
||||
);
|
||||
|
||||
passwordProtectedGamesVisibleCheckBox = new QCheckBox(tr("Show &password protected games"));
|
||||
passwordProtectedGamesVisibleCheckBox->setChecked(
|
||||
settings.value("password_protected_games_visible", false).toBool()
|
||||
);
|
||||
|
||||
QLabel *gameNameFilterLabel = new QLabel(tr("Game &description:"));
|
||||
gameNameFilterEdit = new QLineEdit;
|
||||
gameNameFilterEdit->setText(
|
||||
settings.value("game_name_filter", "").toString()
|
||||
);
|
||||
QLabel *gameNameFilterLabel = new QLabel(tr("Game &description:"));
|
||||
gameNameFilterLabel->setBuddy(gameNameFilterEdit);
|
||||
|
||||
QLabel *creatorNameFilterLabel = new QLabel(tr("&Creator name:"));
|
||||
creatorNameFilterEdit = new QLineEdit;
|
||||
creatorNameFilterEdit->setText(
|
||||
settings.value("creator_name_filter", "").toString()
|
||||
);
|
||||
QLabel *creatorNameFilterLabel = new QLabel(tr("&Creator name:"));
|
||||
creatorNameFilterLabel->setBuddy(creatorNameFilterEdit);
|
||||
|
||||
QVBoxLayout *gameTypeFilterLayout = new QVBoxLayout;
|
||||
QMapIterator<int, QString> gameTypesIterator(allGameTypes);
|
||||
while (gameTypesIterator.hasNext()) {
|
||||
gameTypesIterator.next();
|
||||
|
||||
QCheckBox *temp = new QCheckBox(gameTypesIterator.value());
|
||||
temp->setChecked(
|
||||
settings.value(
|
||||
"game_type/" + hashGameType(gameTypesIterator.value()),
|
||||
false
|
||||
).toBool()
|
||||
);
|
||||
|
||||
gameTypeFilterCheckBoxes.insert(gameTypesIterator.key(), temp);
|
||||
gameTypeFilterLayout->addWidget(temp);
|
||||
}
|
||||
|
|
@ -43,14 +70,18 @@ DlgFilterGames::DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *
|
|||
maxPlayersFilterMinSpinBox = new QSpinBox;
|
||||
maxPlayersFilterMinSpinBox->setMinimum(1);
|
||||
maxPlayersFilterMinSpinBox->setMaximum(99);
|
||||
maxPlayersFilterMinSpinBox->setValue(1);
|
||||
maxPlayersFilterMinSpinBox->setValue(
|
||||
settings.value("min_players", 1).toInt()
|
||||
);
|
||||
maxPlayersFilterMinLabel->setBuddy(maxPlayersFilterMinSpinBox);
|
||||
|
||||
QLabel *maxPlayersFilterMaxLabel = new QLabel(tr("at &most:"));
|
||||
maxPlayersFilterMaxSpinBox = new QSpinBox;
|
||||
maxPlayersFilterMaxSpinBox->setMinimum(1);
|
||||
maxPlayersFilterMaxSpinBox->setMaximum(99);
|
||||
maxPlayersFilterMaxSpinBox->setValue(99);
|
||||
maxPlayersFilterMaxSpinBox->setValue(
|
||||
settings.value("max_players", 99).toInt()
|
||||
);
|
||||
maxPlayersFilterMaxLabel->setBuddy(maxPlayersFilterMaxSpinBox);
|
||||
|
||||
QGridLayout *maxPlayersFilterLayout = new QGridLayout;
|
||||
|
|
@ -83,7 +114,7 @@ DlgFilterGames::DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *
|
|||
hbox->addLayout(rightColumn);
|
||||
|
||||
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(actOk()));
|
||||
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
|
|
@ -94,6 +125,42 @@ DlgFilterGames::DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *
|
|||
setWindowTitle(tr("Filter games"));
|
||||
}
|
||||
|
||||
void DlgFilterGames::actOk() {
|
||||
QSettings settings;
|
||||
settings.beginGroup("filter_games");
|
||||
settings.setValue(
|
||||
"unavailable_games_visible",
|
||||
unavailableGamesVisibleCheckBox->isChecked()
|
||||
);
|
||||
settings.setValue(
|
||||
"password_protected_games_visible",
|
||||
passwordProtectedGamesVisibleCheckBox->isChecked()
|
||||
);
|
||||
settings.setValue("game_name_filter", gameNameFilterEdit->text());
|
||||
settings.setValue("creator_name_filter", creatorNameFilterEdit->text());
|
||||
|
||||
QMapIterator<int, QString> gameTypeIterator(allGameTypes);
|
||||
QMapIterator<int, QCheckBox *> checkboxIterator(gameTypeFilterCheckBoxes);
|
||||
while (gameTypeIterator.hasNext()) {
|
||||
gameTypeIterator.next();
|
||||
checkboxIterator.next();
|
||||
|
||||
settings.setValue(
|
||||
"game_type/" + hashGameType(gameTypeIterator.value()),
|
||||
checkboxIterator.value()->isChecked()
|
||||
);
|
||||
}
|
||||
|
||||
settings.setValue("min_players", maxPlayersFilterMinSpinBox->value());
|
||||
settings.setValue("max_players", maxPlayersFilterMaxSpinBox->value());
|
||||
|
||||
accept();
|
||||
}
|
||||
|
||||
QString DlgFilterGames::hashGameType(const QString &gameType) const {
|
||||
return QCryptographicHash::hash(gameType.toUtf8(), QCryptographicHash::Md5).toHex();
|
||||
}
|
||||
|
||||
bool DlgFilterGames::getUnavailableGamesVisible() const
|
||||
{
|
||||
return unavailableGamesVisibleCheckBox->isChecked();
|
||||
|
|
|
|||
|
|
@ -19,6 +19,16 @@ private:
|
|||
QMap<int, QCheckBox *> gameTypeFilterCheckBoxes;
|
||||
QSpinBox *maxPlayersFilterMinSpinBox;
|
||||
QSpinBox *maxPlayersFilterMaxSpinBox;
|
||||
|
||||
const QMap<int, QString> &allGameTypes;
|
||||
|
||||
/*
|
||||
* The game type might contain special characters, so to use it in
|
||||
* QSettings we just hash it.
|
||||
*/
|
||||
QString hashGameType(const QString &gameType) const;
|
||||
private slots:
|
||||
void actOk();
|
||||
public:
|
||||
DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *parent = 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -18,11 +18,13 @@
|
|||
#include <QInputDialog>
|
||||
#include <QSpinBox>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QRadioButton>
|
||||
#include <QDebug>
|
||||
#include "carddatabase.h"
|
||||
#include "dlg_settings.h"
|
||||
#include "main.h"
|
||||
#include "settingscache.h"
|
||||
#include "priceupdater.h"
|
||||
|
||||
GeneralSettingsPage::GeneralSettingsPage()
|
||||
{
|
||||
|
|
@ -531,9 +533,30 @@ DeckEditorSettingsPage::DeckEditorSettingsPage()
|
|||
priceTagsCheckBox = new QCheckBox;
|
||||
priceTagsCheckBox->setChecked(settingsCache->getPriceTagFeature());
|
||||
connect(priceTagsCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPriceTagFeature(int)));
|
||||
|
||||
|
||||
priceTagSource0 = new QRadioButton;
|
||||
priceTagSource1 = new QRadioButton;
|
||||
|
||||
switch(settingsCache->getPriceTagSource())
|
||||
{
|
||||
case AbstractPriceUpdater::DBPriceSource:
|
||||
priceTagSource1->setChecked(true);
|
||||
break;
|
||||
case AbstractPriceUpdater::BLPPriceSource:
|
||||
default:
|
||||
priceTagSource0->setChecked(true);
|
||||
break;
|
||||
}
|
||||
|
||||
connect(priceTagSource0, SIGNAL(toggled(bool)), this, SLOT(radioPriceTagSourceClicked(bool)));
|
||||
connect(priceTagSource1, SIGNAL(toggled(bool)), this, SLOT(radioPriceTagSourceClicked(bool)));
|
||||
|
||||
connect(this, SIGNAL(priceTagSourceChanged(int)), settingsCache, SLOT(setPriceTagSource(int)));
|
||||
|
||||
QGridLayout *generalGrid = new QGridLayout;
|
||||
generalGrid->addWidget(priceTagsCheckBox, 0, 0);
|
||||
generalGrid->addWidget(priceTagSource0, 1, 0);
|
||||
generalGrid->addWidget(priceTagSource1, 2, 0);
|
||||
|
||||
generalGroupBox = new QGroupBox;
|
||||
generalGroupBox->setLayout(generalGrid);
|
||||
|
|
@ -546,10 +569,26 @@ DeckEditorSettingsPage::DeckEditorSettingsPage()
|
|||
|
||||
void DeckEditorSettingsPage::retranslateUi()
|
||||
{
|
||||
priceTagsCheckBox->setText(tr("Enable &price tag feature (using data from blacklotusproject.com)"));
|
||||
priceTagsCheckBox->setText(tr("Enable &price tag feature"));
|
||||
priceTagSource0->setText(tr("using data from blacklotusproject.com"));
|
||||
priceTagSource1->setText(tr("using data from deckbrew.com"));
|
||||
generalGroupBox->setTitle(tr("General"));
|
||||
}
|
||||
|
||||
void DeckEditorSettingsPage::radioPriceTagSourceClicked(bool checked)
|
||||
{
|
||||
if(!checked)
|
||||
return;
|
||||
|
||||
int source=AbstractPriceUpdater::BLPPriceSource;
|
||||
if(priceTagSource0->isChecked())
|
||||
source=AbstractPriceUpdater::BLPPriceSource;
|
||||
if(priceTagSource1->isChecked())
|
||||
source=AbstractPriceUpdater::DBPriceSource;
|
||||
|
||||
emit priceTagSourceChanged(source);
|
||||
}
|
||||
|
||||
MessagesSettingsPage::MessagesSettingsPage()
|
||||
{
|
||||
aAdd = new QAction(this);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ class QCheckBox;
|
|||
class QLabel;
|
||||
class QCloseEvent;
|
||||
class QSpinBox;
|
||||
class QRadioButton;
|
||||
|
||||
class AbstractSettingsPage : public QWidget {
|
||||
public:
|
||||
|
|
@ -100,8 +101,13 @@ class DeckEditorSettingsPage : public AbstractSettingsPage {
|
|||
public:
|
||||
DeckEditorSettingsPage();
|
||||
void retranslateUi();
|
||||
private slots:
|
||||
void radioPriceTagSourceClicked(bool checked);
|
||||
signals:
|
||||
void priceTagSourceChanged(int _priceTagSource);
|
||||
private:
|
||||
QCheckBox *priceTagsCheckBox;
|
||||
QRadioButton *priceTagSource0, *priceTagSource1;
|
||||
QGroupBox *generalGroupBox;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -18,10 +18,10 @@ public:
|
|||
virtual void enable() { enabled = true; nodeChanged(); }
|
||||
virtual void disable() { enabled = false; nodeChanged(); }
|
||||
virtual FilterTreeNode *parent() const { return NULL; }
|
||||
virtual FilterTreeNode *nodeAt(int i) const { return NULL; }
|
||||
virtual void deleteAt(int i) {}
|
||||
virtual FilterTreeNode *nodeAt(int /* i */) const { return NULL; }
|
||||
virtual void deleteAt(int /* i */) {}
|
||||
virtual int childCount() const { return 0; }
|
||||
virtual int childIndex(const FilterTreeNode *node) const { return -1; }
|
||||
virtual int childIndex(const FilterTreeNode * /* node */) const { return -1; }
|
||||
virtual int index() const { return (parent() != NULL)? parent()->childIndex(this) : -1; }
|
||||
virtual QString text() const { return QString(textCStr()); }
|
||||
virtual bool isLeaf() const { return false; }
|
||||
|
|
@ -48,7 +48,7 @@ class FilterTreeBranch : public FilterTreeNode {
|
|||
protected:
|
||||
QList<T> childNodes;
|
||||
public:
|
||||
~FilterTreeBranch();
|
||||
virtual ~FilterTreeBranch();
|
||||
FilterTreeNode *nodeAt(int i) const;
|
||||
void deleteAt(int i);
|
||||
int childCount() const { return childNodes.size(); }
|
||||
|
|
@ -102,6 +102,7 @@ public:
|
|||
|
||||
FilterItem(QString trm, FilterItemList *parent)
|
||||
: p(parent), term(trm) {}
|
||||
virtual ~FilterItem() {};
|
||||
|
||||
CardFilter::Attr attr() const { return p->attr(); }
|
||||
CardFilter::Type type() const { return p->type; }
|
||||
|
|
|
|||
|
|
@ -84,12 +84,6 @@ void GameSelector::actSetFilter()
|
|||
if (room)
|
||||
gameTypeMap = gameListModel->getGameTypes().value(room->getRoomId());
|
||||
DlgFilterGames dlg(gameTypeMap, this);
|
||||
dlg.setUnavailableGamesVisible(gameListProxyModel->getUnavailableGamesVisible());
|
||||
dlg.setPasswordProtectedGamesVisible(gameListProxyModel->getPasswordProtectedGamesVisible());
|
||||
dlg.setGameNameFilter(gameListProxyModel->getGameNameFilter());
|
||||
dlg.setCreatorNameFilter(gameListProxyModel->getCreatorNameFilter());
|
||||
dlg.setGameTypeFilter(gameListProxyModel->getGameTypeFilter());
|
||||
dlg.setMaxPlayersFilter(gameListProxyModel->getMaxPlayersFilterMin(), gameListProxyModel->getMaxPlayersFilterMax());
|
||||
|
||||
if (!dlg.exec())
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ ServerInfo_User LocalServer_DatabaseInterface::getUserData(const QString &name,
|
|||
return result;
|
||||
}
|
||||
|
||||
AuthenticationResult LocalServer_DatabaseInterface::checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, QString &reasonStr, int &secondsLeft)
|
||||
AuthenticationResult LocalServer_DatabaseInterface::checkUserPassword(Server_ProtocolHandler * /* handler */, const QString & /* user */, const QString & /* password */, QString & /* reasonStr */, int & /* secondsLeft */)
|
||||
{
|
||||
return UnknownUser;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <QIcon>
|
||||
#include <QDir>
|
||||
#include <QDesktopServices>
|
||||
#include <QDebug>
|
||||
|
||||
#include "main.h"
|
||||
#include "window_main.h"
|
||||
|
|
@ -158,7 +159,9 @@ int main(int argc, char *argv[])
|
|||
QDir().mkpath(dataDir + "/pics");
|
||||
settingsCache->setPicsPath(dataDir + "/pics");
|
||||
}
|
||||
|
||||
if (!QDir().mkpath(settingsCache->getPicsPath() + "/CUSTOM"))
|
||||
qDebug() << "Could not create " + settingsCache->getPicsPath().toUtf8() + "/CUSTOM. Will fall back on default card images.";
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
if(settingsCache->getHandBgPath().isEmpty() &&
|
||||
settingsCache->getStackBgPath().isEmpty() &&
|
||||
|
|
|
|||
|
|
@ -959,6 +959,10 @@ void Player::actCreateToken()
|
|||
return;
|
||||
|
||||
lastTokenName = dlg.getName();
|
||||
if (CardInfo *correctedCard = db->getCardBySimpleName(lastTokenName, false)) {
|
||||
lastTokenName = correctedCard->getName();
|
||||
}
|
||||
|
||||
lastTokenColor = dlg.getColor();
|
||||
lastTokenPT = dlg.getPT();
|
||||
lastTokenAnnotation = dlg.getAnnotation();
|
||||
|
|
|
|||
|
|
@ -178,5 +178,5 @@ void PlayerListWidget::showContextMenu(const QPoint &pos, const QModelIndex &ind
|
|||
int playerId = index.sibling(index.row(), 4).data(Qt::UserRole + 1).toInt();
|
||||
UserLevelFlags userLevel(index.sibling(index.row(), 3).data(Qt::UserRole).toInt());
|
||||
|
||||
userContextMenu->showContextMenu(pos, userName, userLevel, playerId);
|
||||
userContextMenu->showContextMenu(pos, userName, userLevel, true, playerId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,25 +4,46 @@
|
|||
*/
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "qt-json/json.h"
|
||||
#include "priceupdater.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "carddatabase.h"
|
||||
|
||||
#if QT_VERSION < 0x050000
|
||||
// for Qt::escape()
|
||||
#include <QtGui/qtextdocument.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param _deck deck.
|
||||
*/
|
||||
PriceUpdater::PriceUpdater(const DeckList *_deck)
|
||||
AbstractPriceUpdater::AbstractPriceUpdater(const DeckList *_deck)
|
||||
{
|
||||
nam = new QNetworkAccessManager(this);
|
||||
deck = _deck;
|
||||
}
|
||||
|
||||
// blacklotusproject.com
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param _deck deck.
|
||||
*/
|
||||
BLPPriceUpdater::BLPPriceUpdater(const DeckList *_deck)
|
||||
: AbstractPriceUpdater(_deck)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the prices of the cards in deckList.
|
||||
*/
|
||||
void PriceUpdater::updatePrices()
|
||||
void BLPPriceUpdater::updatePrices()
|
||||
{
|
||||
QString q = "http://blacklotusproject.com/json/?cards=";
|
||||
QStringList cards = deck->getCardList();
|
||||
|
|
@ -38,7 +59,7 @@ void PriceUpdater::updatePrices()
|
|||
/**
|
||||
* Called when the download of the json file with the prices is finished.
|
||||
*/
|
||||
void PriceUpdater::downloadFinished()
|
||||
void BLPPriceUpdater::downloadFinished()
|
||||
{
|
||||
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
|
||||
bool ok;
|
||||
|
|
@ -82,3 +103,188 @@ void PriceUpdater::downloadFinished()
|
|||
deleteLater();
|
||||
emit finishedUpdate();
|
||||
}
|
||||
|
||||
// deckbrew.com
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param _deck deck.
|
||||
*/
|
||||
DBPriceUpdater::DBPriceUpdater(const DeckList *_deck)
|
||||
: AbstractPriceUpdater(_deck)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the prices of the cards in deckList.
|
||||
*/
|
||||
void DBPriceUpdater::updatePrices()
|
||||
{
|
||||
QString base = "https://api.deckbrew.com/mtg/cards", q = "";
|
||||
QStringList cards = deck->getCardList();
|
||||
muidMap.clear();
|
||||
urls.clear();
|
||||
CardInfo * card;
|
||||
int muid;
|
||||
SetList sets;
|
||||
bool bNotFirst=false;
|
||||
|
||||
for (int i = 0; i < cards.size(); ++i) {
|
||||
card = db->getCard(cards[i], false);
|
||||
sets = card->getSets();
|
||||
for(int j = 0; j < sets.size(); ++j)
|
||||
{
|
||||
muid=card->getMuId(sets[j]->getShortName());
|
||||
|
||||
if (!muid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//qDebug() << "muid " << muid << " card: " << cards[i] << endl;
|
||||
if(bNotFirst)
|
||||
{
|
||||
q += QString("&m=%1").arg(muid);
|
||||
} else {
|
||||
q += QString("?m=%1").arg(muid);
|
||||
bNotFirst = true;
|
||||
}
|
||||
muidMap.insert(muid, cards[i]);
|
||||
|
||||
if(q.length() > 240)
|
||||
{
|
||||
urls.append(base + q);
|
||||
bNotFirst=false;
|
||||
q = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
if(q.length() > 0)
|
||||
urls.append(base + q);
|
||||
|
||||
requestNext();
|
||||
}
|
||||
|
||||
void DBPriceUpdater::requestNext()
|
||||
{
|
||||
if(urls.empty())
|
||||
return;
|
||||
|
||||
QUrl url(urls.takeFirst(), QUrl::TolerantMode);
|
||||
//qDebug() << "request prices from: " << url.toString() << endl;
|
||||
QNetworkReply *reply = nam->get(QNetworkRequest(url));
|
||||
connect(reply, SIGNAL(finished()), this, SLOT(downloadFinished()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the download of the json file with the prices is finished.
|
||||
*/
|
||||
void DBPriceUpdater::downloadFinished()
|
||||
{
|
||||
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
|
||||
bool ok;
|
||||
QString tmp = QString(reply->readAll());
|
||||
|
||||
// Errors are incapsulated in an object, check for them first
|
||||
QVariantMap resultMap = QtJson::Json::parse(tmp, ok).toMap();
|
||||
if (!ok) {
|
||||
QMessageBox::critical(this, tr("Error"), tr("A problem has occured while fetching card prices."));
|
||||
reply->deleteLater();
|
||||
if(urls.isEmpty())
|
||||
{
|
||||
deleteLater();
|
||||
emit finishedUpdate();
|
||||
} else {
|
||||
requestNext();
|
||||
}
|
||||
}
|
||||
|
||||
if(resultMap.contains("errors"))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("A problem has occured while fetching card prices:") +
|
||||
"<br/>" +
|
||||
#if QT_VERSION < 0x050000
|
||||
Qt::escape(resultMap["errors"].toList().first().toString())
|
||||
#else
|
||||
resultMap["errors"].toList().first().toString().toHtmlEscaped()
|
||||
#endif
|
||||
);
|
||||
reply->deleteLater();
|
||||
if(urls.isEmpty())
|
||||
{
|
||||
deleteLater();
|
||||
emit finishedUpdate();
|
||||
} else {
|
||||
requestNext();
|
||||
}
|
||||
}
|
||||
|
||||
// Good results are a list
|
||||
QVariantList resultList = QtJson::Json::parse(tmp, ok).toList();
|
||||
if (!ok) {
|
||||
QMessageBox::critical(this, tr("Error"), tr("A problem has occured while fetching card prices."));
|
||||
reply->deleteLater();
|
||||
if(urls.isEmpty())
|
||||
{
|
||||
deleteLater();
|
||||
emit finishedUpdate();
|
||||
} else {
|
||||
requestNext();
|
||||
}
|
||||
}
|
||||
|
||||
QMap<QString, float> cardsPrice;
|
||||
QListIterator<QVariant> it(resultList);
|
||||
while (it.hasNext()) {
|
||||
QVariantMap cardMap = it.next().toMap();
|
||||
|
||||
|
||||
// get sets list
|
||||
QList<QVariant> editions = cardMap.value("editions").toList();
|
||||
foreach (QVariant ed, editions)
|
||||
{
|
||||
// retrieve card name "as we know it" from the muid
|
||||
QVariantMap edition = ed.toMap();
|
||||
QString set = edition.value("set_id").toString();
|
||||
|
||||
int muid = edition.value("multiverse_id").toString().toInt();
|
||||
if(!muidMap.contains(muid))
|
||||
continue;
|
||||
|
||||
QString name=muidMap.value(muid);
|
||||
// Prices are in USD cents
|
||||
float price = edition.value("price").toMap().value("median").toString().toFloat() / 100;
|
||||
//qDebug() << "card " << name << " set " << set << " price " << price << endl;
|
||||
|
||||
/**
|
||||
* Make sure Masters Edition (MED) isn't the set, as it doesn't
|
||||
* physically exist. Also check the price to see that the cheapest set
|
||||
* ends up as the final price.
|
||||
*/
|
||||
if (set != "MED" && price > 0 && (!cardsPrice.contains(name) || cardsPrice.value(name) > price))
|
||||
cardsPrice.insert(name, price);
|
||||
}
|
||||
}
|
||||
|
||||
InnerDecklistNode *listRoot = deck->getRoot();
|
||||
for (int i = 0; i < listRoot->size(); i++) {
|
||||
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
|
||||
for (int j = 0; j < currentZone->size(); j++) {
|
||||
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
|
||||
if (!currentCard)
|
||||
continue;
|
||||
float price = cardsPrice[currentCard->getName()];
|
||||
if(price > 0)
|
||||
currentCard->setPrice(price);
|
||||
}
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
if(urls.isEmpty())
|
||||
{
|
||||
deleteLater();
|
||||
emit finishedUpdate();
|
||||
} else {
|
||||
requestNext();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,57 @@
|
|||
#ifndef PRICEUPDATER_H
|
||||
#define PRICEUPDATER_H
|
||||
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkAccessManager>
|
||||
#include "decklist.h"
|
||||
|
||||
class QNetworkAccessManager;
|
||||
|
||||
// If we don't typedef this, won't compile on OS X < 10.9
|
||||
typedef QMap<int, QString> MuidStringMap;
|
||||
|
||||
/**
|
||||
* Price Updater.
|
||||
*
|
||||
* @author Marcio Ribeiro <mmr@b1n.org>
|
||||
*/
|
||||
class PriceUpdater : public QObject
|
||||
class AbstractPriceUpdater : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
public:
|
||||
enum PriceSource { BLPPriceSource, DBPriceSource };
|
||||
protected:
|
||||
const DeckList *deck;
|
||||
QNetworkAccessManager *nam;
|
||||
signals:
|
||||
void finishedUpdate();
|
||||
private slots:
|
||||
void downloadFinished();
|
||||
protected slots:
|
||||
virtual void downloadFinished() = 0;
|
||||
public:
|
||||
PriceUpdater(const DeckList *deck);
|
||||
void updatePrices();
|
||||
AbstractPriceUpdater(const DeckList *deck);
|
||||
virtual void updatePrices() = 0;
|
||||
};
|
||||
|
||||
class BLPPriceUpdater : public AbstractPriceUpdater
|
||||
{
|
||||
Q_OBJECT
|
||||
protected:
|
||||
virtual void downloadFinished();
|
||||
public:
|
||||
BLPPriceUpdater(const DeckList *deck);
|
||||
virtual void updatePrices();
|
||||
};
|
||||
|
||||
class DBPriceUpdater : public AbstractPriceUpdater
|
||||
{
|
||||
Q_OBJECT
|
||||
protected:
|
||||
MuidStringMap muidMap;
|
||||
QList<QString> urls;
|
||||
protected:
|
||||
virtual void downloadFinished();
|
||||
void requestNext();
|
||||
public:
|
||||
DBPriceUpdater(const DeckList *deck);
|
||||
virtual void updatePrices();
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ RemoteClient::RemoteClient(QObject *parent)
|
|||
connect(socket, SIGNAL(connected()), this, SLOT(slotConnected()));
|
||||
connect(socket, SIGNAL(readyRead()), this, SLOT(readData()));
|
||||
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(slotSocketError(QAbstractSocket::SocketError)));
|
||||
|
||||
|
||||
connect(this, SIGNAL(serverIdentificationEventReceived(const Event_ServerIdentification &)), this, SLOT(processServerIdentificationEvent(const Event_ServerIdentification &)));
|
||||
connect(this, SIGNAL(connectionClosedEventReceived(Event_ConnectionClosed)), this, SLOT(processConnectionClosedEvent(Event_ConnectionClosed)));
|
||||
connect(this, SIGNAL(sigConnectToServer(QString, unsigned int, QString, QString)), this, SLOT(doConnectToServer(QString, unsigned int, QString, QString)));
|
||||
|
|
@ -47,12 +47,12 @@ void RemoteClient::slotConnected()
|
|||
{
|
||||
timeRunning = lastDataReceived = 0;
|
||||
timer->start();
|
||||
|
||||
|
||||
// dirty hack to be compatible with v14 server
|
||||
sendCommandContainer(CommandContainer());
|
||||
getNewCmdId();
|
||||
// end of hack
|
||||
|
||||
|
||||
setStatus(StatusAwaitingWelcome);
|
||||
}
|
||||
|
||||
|
|
@ -208,7 +208,7 @@ void RemoteClient::ping()
|
|||
pend->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int maxTime = timeRunning - lastDataReceived;
|
||||
emit maxPingTime(maxTime, maxTimeout);
|
||||
if (maxTime >= maxTimeout) {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ void ReplayTimelineWidget::setTimeline(const QList<int> &_replayTimeline)
|
|||
update();
|
||||
}
|
||||
|
||||
void ReplayTimelineWidget::paintEvent(QPaintEvent *event)
|
||||
void ReplayTimelineWidget::paintEvent(QPaintEvent * /* event */)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.drawRect(0, 0, width() - 1, height() - 1);
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ SettingsCache::SettingsCache()
|
|||
soundPath = settings->value("sound/path").toString();
|
||||
|
||||
priceTagFeature = settings->value("deckeditor/pricetags", false).toBool();
|
||||
priceTagSource = settings->value("deckeditor/pricetagsource", 0).toInt();
|
||||
|
||||
ignoreUnregisteredUsers = settings->value("chat/ignore_unregistered", false).toBool();
|
||||
}
|
||||
|
|
@ -247,6 +248,12 @@ void SettingsCache::setPriceTagFeature(int _priceTagFeature)
|
|||
emit priceTagFeatureChanged(priceTagFeature);
|
||||
}
|
||||
|
||||
void SettingsCache::setPriceTagSource(int _priceTagSource)
|
||||
{
|
||||
priceTagSource = _priceTagSource;
|
||||
settings->setValue("deckeditor/pricetagsource", priceTagSource);
|
||||
}
|
||||
|
||||
void SettingsCache::setIgnoreUnregisteredUsers(bool _ignoreUnregisteredUsers)
|
||||
{
|
||||
ignoreUnregisteredUsers = _ignoreUnregisteredUsers;
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ private:
|
|||
bool soundEnabled;
|
||||
QString soundPath;
|
||||
bool priceTagFeature;
|
||||
int priceTagSource;
|
||||
bool ignoreUnregisteredUsers;
|
||||
QString picUrl;
|
||||
QString picUrlHq;
|
||||
|
|
@ -87,6 +88,7 @@ public:
|
|||
bool getSoundEnabled() const { return soundEnabled; }
|
||||
QString getSoundPath() const { return soundPath; }
|
||||
bool getPriceTagFeature() const { return priceTagFeature; }
|
||||
int getPriceTagSource() const { return priceTagSource; }
|
||||
bool getIgnoreUnregisteredUsers() const { return ignoreUnregisteredUsers; }
|
||||
QString getPicUrl() const { return picUrl; }
|
||||
QString getPicUrlHq() const { return picUrlHq; }
|
||||
|
|
@ -121,6 +123,7 @@ public slots:
|
|||
void setSoundEnabled(int _soundEnabled);
|
||||
void setSoundPath(const QString &_soundPath);
|
||||
void setPriceTagFeature(int _priceTagFeature);
|
||||
void setPriceTagSource(int _priceTagSource);
|
||||
void setIgnoreUnregisteredUsers(bool _ignoreUnregisteredUsers);
|
||||
void setPicUrl(const QString &_picUrl);
|
||||
void setPicUrlHq(const QString &_picUrlHq);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ public:
|
|||
virtual QString getTabText() const = 0;
|
||||
virtual void retranslateUi() = 0;
|
||||
virtual void closeRequest() { }
|
||||
virtual void tabActivated() { }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -512,7 +512,10 @@ void TabDeckEditor::actPrintDeck()
|
|||
|
||||
void TabDeckEditor::actAnalyzeDeck()
|
||||
{
|
||||
DeckStatsInterface *interface = new DeckStatsInterface(this); // it deletes itself when done
|
||||
DeckStatsInterface *interface = new DeckStatsInterface(
|
||||
*databaseModel->getDatabase(),
|
||||
this
|
||||
); // it deletes itself when done
|
||||
interface->analyzeDeck(deckModel->getDeckList());
|
||||
}
|
||||
|
||||
|
|
@ -643,12 +646,25 @@ void TabDeckEditor::actDecrement()
|
|||
void TabDeckEditor::setPriceTagFeatureEnabled(int enabled)
|
||||
{
|
||||
aUpdatePrices->setVisible(enabled);
|
||||
deckModel->pricesUpdated();
|
||||
}
|
||||
|
||||
void TabDeckEditor::actUpdatePrices()
|
||||
{
|
||||
aUpdatePrices->setDisabled(true);
|
||||
PriceUpdater *up = new PriceUpdater(deckModel->getDeckList());
|
||||
AbstractPriceUpdater *up;
|
||||
|
||||
switch(settingsCache->getPriceTagSource())
|
||||
{
|
||||
case AbstractPriceUpdater::DBPriceSource:
|
||||
up = new DBPriceUpdater(deckModel->getDeckList());
|
||||
break;
|
||||
case AbstractPriceUpdater::BLPPriceSource:
|
||||
default:
|
||||
up = new BLPPriceUpdater(deckModel->getDeckList());
|
||||
break;
|
||||
}
|
||||
|
||||
connect(up, SIGNAL(finishedUpdate()), this, SLOT(finishedUpdatingPrices()));
|
||||
up->updatePrices();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -255,7 +255,7 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, GameReplay *_replay)
|
|||
|
||||
// Create list: event number -> time [ms]
|
||||
// Distribute simultaneous events evenly across 1 second.
|
||||
int lastEventTimestamp = -1;
|
||||
unsigned int lastEventTimestamp = 0;
|
||||
const int eventCount = replay->event_list_size();
|
||||
for (int i = 0; i < eventCount; ++i) {
|
||||
int j = i + 1;
|
||||
|
|
|
|||
|
|
@ -49,6 +49,12 @@ void TabMessage::retranslateUi()
|
|||
aLeave->setText(tr("&Leave"));
|
||||
}
|
||||
|
||||
void TabMessage::tabActivated()
|
||||
{
|
||||
if(!sayEdit->hasFocus())
|
||||
sayEdit->setFocus();
|
||||
}
|
||||
|
||||
QString TabMessage::getUserName() const
|
||||
{
|
||||
return QString::fromStdString(otherUserInfo->name());
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ public:
|
|||
~TabMessage();
|
||||
void retranslateUi();
|
||||
void closeRequest();
|
||||
void tabActivated();
|
||||
QString getUserName() const;
|
||||
QString getTabText() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ void TabReplays::actDownload()
|
|||
client->sendCommand(pend);
|
||||
}
|
||||
|
||||
void TabReplays::downloadFinished(const Response &r, const CommandContainer &commandContainer, const QVariant &extraData)
|
||||
void TabReplays::downloadFinished(const Response &r, const CommandContainer & /* commandContainer */, const QVariant &extraData)
|
||||
{
|
||||
if (r.response_code() != Response::RespOk)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -121,6 +121,12 @@ void TabRoom::closeRequest()
|
|||
actLeaveRoom();
|
||||
}
|
||||
|
||||
void TabRoom::tabActivated()
|
||||
{
|
||||
if(!sayEdit->hasFocus())
|
||||
sayEdit->setFocus();
|
||||
}
|
||||
|
||||
QString TabRoom::sanitizeHtml(QString dirty) const
|
||||
{
|
||||
return dirty
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ public:
|
|||
~TabRoom();
|
||||
void retranslateUi();
|
||||
void closeRequest();
|
||||
void tabActivated();
|
||||
void processRoomEvent(const RoomEvent &event);
|
||||
int getRoomId() const { return roomId; }
|
||||
const QMap<int, QString> &getGameTypes() const { return gameTypes; }
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ void CloseButton::paintEvent(QPaintEvent * /*event*/)
|
|||
}
|
||||
|
||||
TabSupervisor::TabSupervisor(AbstractClient *_client, QWidget *parent)
|
||||
: QTabWidget(parent), userInfo(0), client(_client), tabUserLists(0), tabServer(0), tabDeckStorage(0), tabAdmin(0), tabReplays(0)
|
||||
: QTabWidget(parent), userInfo(0), client(_client), tabServer(0), tabUserLists(0), tabDeckStorage(0), tabReplays(0), tabAdmin(0)
|
||||
{
|
||||
tabChangedIcon = new QIcon(":/resources/icon_tab_changed.svg");
|
||||
setElideMode(Qt::ElideRight);
|
||||
|
|
@ -479,6 +479,7 @@ void TabSupervisor::updateCurrent(int index)
|
|||
tab->setContentsChanged(false);
|
||||
}
|
||||
emit setMenu(static_cast<Tab *>(widget(index))->getTabMenus());
|
||||
tab->tabActivated();
|
||||
} else
|
||||
emit setMenu();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ void UserContextMenu::banUser_dialogFinished()
|
|||
client->sendCommand(client->prepareModeratorCommand(cmd));
|
||||
}
|
||||
|
||||
void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName, UserLevelFlags userLevel, int playerId)
|
||||
void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName, UserLevelFlags userLevel, bool online, int playerId)
|
||||
{
|
||||
aUserName->setText(userName);
|
||||
|
||||
|
|
@ -132,7 +132,8 @@ void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName
|
|||
menu->addAction(aBan);
|
||||
}
|
||||
bool anotherUser = userName != QString::fromStdString(tabSupervisor->getUserInfo()->name());
|
||||
aChat->setEnabled(anotherUser);
|
||||
aDetails->setEnabled(online);
|
||||
aChat->setEnabled(anotherUser && online);
|
||||
aShowGames->setEnabled(anotherUser);
|
||||
aAddToBuddyList->setEnabled(anotherUser);
|
||||
aRemoveFromBuddyList->setEnabled(anotherUser);
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ private slots:
|
|||
public:
|
||||
UserContextMenu(const TabSupervisor *_tabSupervisor, QWidget *_parent, TabGame *_game = 0);
|
||||
void retranslateUi();
|
||||
void showContextMenu(const QPoint &pos, const QString &userName, UserLevelFlags userLevel, int playerId = -1);
|
||||
void showContextMenu(const QPoint &pos, const QString &userName, UserLevelFlags userLevel, bool online = true, int playerId = -1);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -311,8 +311,9 @@ void UserList::userClicked(QTreeWidgetItem *item, int /*column*/)
|
|||
void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index)
|
||||
{
|
||||
const ServerInfo_User &userInfo = static_cast<UserListTWI *>(userTree->topLevelItem(index.row()))->getUserInfo();
|
||||
|
||||
userContextMenu->showContextMenu(pos, QString::fromStdString(userInfo.name()), UserLevelFlags(userInfo.user_level()));
|
||||
bool online = index.sibling(index.row(), 0).data(Qt::UserRole + 1).toBool();
|
||||
|
||||
userContextMenu->showContextMenu(pos, QString::fromStdString(userInfo.name()), UserLevelFlags(userInfo.user_level()), online);
|
||||
}
|
||||
|
||||
void UserList::sortItems()
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ void MainWindow::loginError(Response::ResponseCode r, QString reasonStr, quint32
|
|||
{
|
||||
switch (r) {
|
||||
case Response::RespWrongPassword:
|
||||
QMessageBox::critical(this, tr("Error"), tr("Invalid login data."));
|
||||
QMessageBox::critical(this, tr("Error"), tr("Incorrect username or password. Please check your authentication information and try again."));
|
||||
break;
|
||||
case Response::RespWouldOverwriteOldSession:
|
||||
QMessageBox::critical(this, tr("Error"), tr("There is already an active session using this user name.\nPlease close that session first and re-login."));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue