Merge remote-tracking branch 'upstream/master' into cmake_qt5

This commit is contained in:
Fabio Bas 2014-06-24 18:13:26 +02:00
commit 5c13c06982
34 changed files with 1505 additions and 1221 deletions

View file

@ -9,6 +9,7 @@ class CardInfo;
class AbstractCardDragItem : public QObject, public QGraphicsItem {
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
protected:
AbstractCardItem *item;
QPointF hotSpot;

View file

@ -9,6 +9,7 @@ class QAction;
class AbstractCounter : public QObject, public QGraphicsItem {
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
protected:
Player *player;
int id;

View file

@ -11,6 +11,7 @@ class ArrowTarget;
class ArrowItem : public QObject, public QGraphicsItem {
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
private:
QPainterPath path;
QMenu *menu;

View file

@ -14,7 +14,7 @@
#include <QNetworkRequest>
#include <QDebug>
const int CardDatabase::versionNeeded = 2;
const int CardDatabase::versionNeeded = 3;
CardSet::CardSet(const QString &_shortName, const QString &_longName)
: shortName(_shortName), longName(_longName)
@ -80,11 +80,13 @@ bool PictureToLoad::nextSet()
return true;
}
PictureLoader::PictureLoader(const QString &__picsPath, bool _picDownload, QObject *parent)
: QObject(parent), _picsPath(__picsPath), picDownload(_picDownload), downloadRunning(false), loadQueueRunning(false)
PictureLoader::PictureLoader(const QString &__picsPath, bool _picDownload, bool _picDownloadHq, QObject *parent)
: QObject(parent),
_picsPath(__picsPath), picDownload(_picDownload), picDownloadHq(_picDownloadHq),
downloadRunning(false), loadQueueRunning(false)
{
connect(this, SIGNAL(startLoadQueue()), this, SLOT(processLoadQueue()), Qt::QueuedConnection);
networkManager = new QNetworkAccessManager(this);
connect(networkManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(picDownloadFinished(QNetworkReply *)));
}
@ -99,7 +101,7 @@ void PictureLoader::processLoadQueue()
{
if (loadQueueRunning)
return;
loadQueueRunning = true;
forever {
mutex.lock();
@ -113,7 +115,7 @@ void PictureLoader::processLoadQueue()
QString correctedName = ptl.getCard()->getCorrectedName();
QString picsPath = _picsPath;
QString setName = ptl.getSetName();
QImage image;
if (!image.load(QString("%1/%2/%3.full.jpg").arg(picsPath).arg(setName).arg(correctedName)))
if (!image.load(QString("%1/%2/%3%4.full.jpg").arg(picsPath).arg(setName).arg(correctedName).arg(1)))
@ -130,11 +132,25 @@ void PictureLoader::processLoadQueue()
}
continue;
}
emit imageLoaded(ptl.getCard(), image);
}
}
QString PictureLoader::getPicUrl(CardInfo *card)
{
if (!picDownload) return 0;
QString picUrl = picDownloadHq ? settingsCache->getPicUrlHq() : settingsCache->getPicUrl();
picUrl.replace("!name!", QUrl::toPercentEncoding(card->getCorrectedName()));
CardSet *set = card->getPreferredSet();
picUrl.replace("!setcode!", QUrl::toPercentEncoding(set->getShortName()));
picUrl.replace("!setname!", QUrl::toPercentEncoding(set->getLongName()));
picUrl.replace("!cardid!", QUrl::toPercentEncoding(QString::number(card->getPreferredMuId())));
return picUrl;
}
void PictureLoader::startNextPicDownload()
{
if (cardsToDownload.isEmpty()) {
@ -142,31 +158,28 @@ void PictureLoader::startNextPicDownload()
downloadRunning = false;
return;
}
downloadRunning = true;
cardBeingDownloaded = cardsToDownload.takeFirst();
QString picUrl;
if (cardBeingDownloaded.getStripped())
picUrl = cardBeingDownloaded.getCard()->getPicURLSt(cardBeingDownloaded.getSetName());
else if (cardBeingDownloaded.getHq()) {
picUrl = cardBeingDownloaded.getCard()->getPicURLHq(cardBeingDownloaded.getSetName());
if (picUrl.isEmpty()) {
picUrl = cardBeingDownloaded.getCard()->getPicURL(cardBeingDownloaded.getSetName());
cardBeingDownloaded.setHq(false);
}
} else
picUrl = cardBeingDownloaded.getCard()->getPicURL(cardBeingDownloaded.getSetName());
// TODO: Do something useful when picUrl is 0 or empty, etc
QString picUrl = getPicUrl(cardBeingDownloaded.getCard());
QUrl url(picUrl);
QNetworkRequest req(url);
qDebug() << "starting picture download:" << req.url();
qDebug() << "starting picture download:" << cardBeingDownloaded.getCard()->getName() << "Url:" << req.url();
networkManager->get(req);
}
void PictureLoader::picDownloadFinished(QNetworkReply *reply)
{
QString picsPath = _picsPath;
if (reply->error()) {
qDebug() << "Download failed:" << reply->errorString();
}
const QByteArray &picData = reply->readAll();
QImage testImage;
if (testImage.loadFromData(picData)) {
@ -180,17 +193,17 @@ void PictureLoader::picDownloadFinished(QNetworkReply *reply)
QDir dir(QString(picsPath + "/downloadedPics"));
dir.mkdir(cardBeingDownloaded.getSetName());
}
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();
emit imageLoaded(cardBeingDownloaded.getCard(), testImage);
} else if (cardBeingDownloaded.getHq()) {
qDebug() << "HQ: received invalid picture. URL:" << reply->request().url();
@ -207,7 +220,7 @@ void PictureLoader::picDownloadFinished(QNetworkReply *reply)
} else
emit imageLoaded(cardBeingDownloaded.getCard(), QImage());
}
reply->deleteLater();
startNextPicDownload();
}
@ -215,7 +228,7 @@ void PictureLoader::picDownloadFinished(QNetworkReply *reply)
void PictureLoader::loadImage(CardInfo *card, bool stripped)
{
QMutexLocker locker(&mutex);
loadQueue.append(PictureToLoad(card, stripped));
emit startLoadQueue();
}
@ -232,6 +245,12 @@ void PictureLoader::setPicDownload(bool _picDownload)
picDownload = _picDownload;
}
void PictureLoader::setPicDownloadHq(bool _picDownloadHq)
{
QMutexLocker locker(&mutex);
picDownloadHq = _picDownloadHq;
}
CardInfo::CardInfo(CardDatabase *_db,
const QString &_name,
bool _isToken,
@ -244,22 +263,18 @@ CardInfo::CardInfo(CardDatabase *_db,
bool _cipt,
int _tableRow,
const SetList &_sets,
const QMap<QString, QString> &_picURLs,
const QMap<QString, QString> &_picURLsHq,
const QMap<QString, QString> &_picURLsSt)
QMap<QString, int> _muIds)
: db(_db),
name(_name),
isToken(_isToken),
sets(_sets),
muIds(_muIds),
manacost(_manacost),
cardtype(_cardtype),
powtough(_powtough),
text(_text),
colors(_colors),
loyalty(_loyalty),
picURLs(_picURLs),
picURLsHq(_picURLsHq),
picURLsSt(_picURLsSt),
cipt(_cipt),
tableRow(_tableRow),
pixmap(NULL)
@ -284,6 +299,8 @@ QString CardInfo::getMainCardType() const
int pos;
if ((pos = result.indexOf('-')) != -1)
result.remove(pos, result.length());
if ((pos = result.indexOf("")) != -1)
result.remove(pos, result.length());
if ((pos = result.indexOf("//")) != -1)
result.remove(pos, result.length());
result = result.simplified();
@ -315,19 +332,12 @@ void CardInfo::addToSet(CardSet *set)
sets << set;
}
QString CardInfo::getPicURL() const
{
SetList sortedSets = sets;
sortedSets.sortByKey();
return picURLs.value(sortedSets.first()->getShortName());
}
QPixmap *CardInfo::loadPixmap()
{
if (pixmap)
return pixmap;
pixmap = new QPixmap();
if (getName().isEmpty()) {
pixmap->load(settingsCache->getCardBackPicturePath());
return pixmap;
@ -400,18 +410,33 @@ void CardInfo::updatePixmapCache()
emit pixmapUpdated();
}
CardSet* CardInfo::getPreferredSet()
{
SetList sortedSets = sets;
sortedSets.sortByKey();
return sortedSets.first();
}
int CardInfo::getPreferredMuId()
{
return muIds[getPreferredSet()->getShortName()];
}
QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info)
{
xml.writeStartElement("card");
xml.writeTextElement("name", info->getName());
const SetList &sets = info->getSets();
QString tmpString;
QString tmpSet;
for (int i = 0; i < sets.size(); i++) {
xml.writeStartElement("set");
xml.writeAttribute("picURL", info->getPicURL(sets[i]->getShortName()));
xml.writeAttribute("picURLHq", info->getPicURLHq(sets[i]->getShortName()));
xml.writeAttribute("picURLSt", info->getPicURLSt(sets[i]->getShortName()));
xml.writeCharacters(sets[i]->getShortName());
tmpSet=sets[i]->getShortName();
xml.writeAttribute("muId", QString::number(info->getMuId(tmpSet)));
xml.writeCharacters(tmpSet);
xml.writeEndElement();
}
const QStringList &colors = info->getColors();
@ -436,18 +461,19 @@ QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info)
}
CardDatabase::CardDatabase(QObject *parent)
: QObject(parent), loadSuccess(false), noCard(0)
: QObject(parent), loadStatus(NotLoaded), noCard(0)
{
connect(settingsCache, SIGNAL(picsPathChanged()), this, SLOT(picsPathChanged()));
connect(settingsCache, SIGNAL(cardDatabasePathChanged()), this, SLOT(loadCardDatabase()));
connect(settingsCache, SIGNAL(tokenDatabasePathChanged()), this, SLOT(loadTokenDatabase()));
connect(settingsCache, SIGNAL(picDownloadChanged()), this, SLOT(picDownloadChanged()));
connect(settingsCache, SIGNAL(picDownloadHqChanged()), this, SLOT(picDownloadHqChanged()));
loadCardDatabase();
loadTokenDatabase();
pictureLoaderThread = new QThread;
pictureLoader = new PictureLoader(settingsCache->getPicsPath(), settingsCache->getPicDownload());
pictureLoader = new PictureLoader(settingsCache->getPicsPath(), settingsCache->getPicDownload(), settingsCache->getPicDownloadHq());
pictureLoader->moveToThread(pictureLoaderThread);
connect(pictureLoader, SIGNAL(imageLoaded(CardInfo *, const QImage &)), this, SLOT(imageLoaded(CardInfo *, const QImage &)));
pictureLoaderThread->start(QThread::LowPriority);
@ -572,7 +598,7 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml)
if (xml.name() == "card") {
QString name, manacost, type, pt, text;
QStringList colors;
QMap<QString, QString> picURLs, picURLsHq, picURLsSt;
QMap<QString, int> muids;
SetList sets;
int tableRow = 0;
int loyalty = 0;
@ -592,14 +618,12 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml)
else if (xml.name() == "text")
text = xml.readElementText();
else if (xml.name() == "set") {
QString picURL = xml.attributes().value("picURL").toString();
QString picURLHq = xml.attributes().value("picURLHq").toString();
QString picURLSt = xml.attributes().value("picURLSt").toString();
QXmlStreamAttributes attrs = xml.attributes();
QString setName = xml.readElementText();
sets.append(getSet(setName));
picURLs.insert(setName, picURL);
picURLsHq.insert(setName, picURLHq);
picURLsSt.insert(setName, picURLSt);
if (attrs.hasAttribute("muId")) {
muids[setName] = attrs.value("muId").toString().toInt();
}
} else if (xml.name() == "color")
colors << xml.readElementText();
else if (xml.name() == "tablerow")
@ -611,18 +635,18 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml)
else if (xml.name() == "token")
isToken = xml.readElementText().toInt();
}
cardHash.insert(name, new CardInfo(this, name, isToken, manacost, type, pt, text, colors, loyalty, cipt, tableRow, sets, picURLs, picURLsHq, picURLsSt));
cardHash.insert(name, new CardInfo(this, name, isToken, manacost, type, pt, text, colors, loyalty, cipt, tableRow, sets, muids));
}
}
}
bool CardDatabase::loadFromFile(const QString &fileName, bool tokens)
LoadStatus CardDatabase::loadFromFile(const QString &fileName, bool tokens)
{
QFile file(fileName);
file.open(QIODevice::ReadOnly);
if (!file.isOpen())
return false;
return FileError;
if (tokens) {
QMutableHashIterator<QString, CardInfo *> i(cardHash);
while (i.hasNext()) {
@ -639,7 +663,7 @@ bool CardDatabase::loadFromFile(const QString &fileName, bool tokens)
delete setIt.value();
}
setHash.clear();
QMutableHashIterator<QString, CardInfo *> i(cardHash);
while (i.hasNext()) {
i.next();
@ -655,9 +679,12 @@ bool CardDatabase::loadFromFile(const QString &fileName, bool tokens)
while (!xml.atEnd()) {
if (xml.readNext() == QXmlStreamReader::StartElement) {
if (xml.name() != "cockatrice_carddatabase")
return false;
if (xml.attributes().value("version").toString().toInt() < versionNeeded)
return false;
return Invalid;
int version = xml.attributes().value("version").toString().toInt();
if (version < versionNeeded) {
qDebug() << "loadFromFile(): Version too old: " << version;
return VersionTooOld;
}
while (!xml.atEnd()) {
if (xml.readNext() == QXmlStreamReader::EndElement)
break;
@ -669,7 +696,10 @@ bool CardDatabase::loadFromFile(const QString &fileName, bool tokens)
}
}
qDebug() << cardHash.size() << "cards in" << setHash.size() << "sets loaded";
return !cardHash.isEmpty();
if (cardHash.isEmpty()) return NoCards;
return Ok;
}
bool CardDatabase::saveToFile(const QString &fileName, bool tokens)
@ -717,13 +747,23 @@ void CardDatabase::picDownloadChanged()
}
}
bool CardDatabase::loadCardDatabase(const QString &path, bool tokens)
void CardDatabase::picDownloadHqChanged()
{
bool tempLoadSuccess = false;
pictureLoader->setPicDownloadHq(settingsCache->getPicDownloadHq());
if (settingsCache->getPicDownloadHq()) {
QHashIterator<QString, CardInfo *> cardIterator(cardHash);
while (cardIterator.hasNext())
cardIterator.next().value()->clearPixmapCacheMiss();
}
}
LoadStatus CardDatabase::loadCardDatabase(const QString &path, bool tokens)
{
LoadStatus tempLoadStatus = NotLoaded;
if (!path.isEmpty())
tempLoadSuccess = loadFromFile(path, tokens);
if (tempLoadSuccess) {
tempLoadStatus = loadFromFile(path, tokens);
if (tempLoadStatus == Ok) {
SetList allSets;
QHashIterator<QString, CardSet *> setsIterator(setHash);
while (setsIterator.hasNext())
@ -731,14 +771,17 @@ bool CardDatabase::loadCardDatabase(const QString &path, bool tokens)
allSets.sortByKey();
for (int i = 0; i < allSets.size(); ++i)
allSets[i]->setSortKey(i);
emit cardListChanged();
}
if (!tokens)
loadSuccess = tempLoadSuccess;
return tempLoadSuccess;
if (!tokens) {
loadStatus = tempLoadStatus;
qDebug() << "loadCardDatabase(): Status = " << loadStatus;
}
return tempLoadStatus;
}
void CardDatabase::loadCardDatabase()

View file

@ -53,10 +53,8 @@ public:
bool getStripped() const { return stripped; }
QString getSetName() const { return sortedSets[setIndex]->getShortName(); }
bool nextSet();
bool getHq() const { return hq; }
void setHq(bool _hq) { hq = _hq; }
};
class PictureLoader : public QObject {
@ -68,13 +66,15 @@ private:
QNetworkAccessManager *networkManager;
QList<PictureToLoad> cardsToDownload;
PictureToLoad cardBeingDownloaded;
bool picDownload, downloadRunning, loadQueueRunning;
bool picDownload, picDownloadHq, downloadRunning, loadQueueRunning;
void startNextPicDownload();
QString getPicUrl(CardInfo* card);
public:
PictureLoader(const QString &__picsPath, bool _picDownload, QObject *parent = 0);
PictureLoader(const QString &__picsPath, bool _picDownload, bool _picDownloadHq, QObject *parent = 0);
~PictureLoader();
void setPicsPath(const QString &path);
void setPicDownload(bool _picDownload);
void setPicDownloadHq(bool _picDownloadHq);
void loadImage(CardInfo *card, bool stripped);
private slots:
void picDownloadFinished(QNetworkReply *reply);
@ -99,7 +99,7 @@ private:
QString text;
QStringList colors;
int loyalty;
QMap<QString, QString> picURLs, picURLsHq, picURLsSt;
QMap<QString, int> muIds;
bool cipt;
int tableRow;
QPixmap *pixmap;
@ -117,9 +117,7 @@ public:
bool _cipt = false,
int _tableRow = 0,
const SetList &_sets = SetList(),
const QStringMap &_picURLs = QStringMap(),
const QStringMap &_picURLsHq = QStringMap(),
const QStringMap &_picURLsSt = QStringMap());
QMap<QString, int> muids = QMap<QString, int>());
~CardInfo();
const QString &getName() const { return name; }
bool getIsToken() const { return isToken; }
@ -136,25 +134,21 @@ public:
void setText(const QString &_text) { text = _text; emit cardInfoChanged(this); }
void setColors(const QStringList &_colors) { colors = _colors; emit cardInfoChanged(this); }
const QStringList &getColors() const { return colors; }
QString getPicURL(const QString &set) const { return picURLs.value(set); }
QString getPicURLHq(const QString &set) const { return picURLsHq.value(set); }
QString getPicURLSt(const QString &set) const { return picURLsSt.value(set); }
QString getPicURL() const;
const QMap<QString, QString> &getPicURLs() const { return picURLs; }
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 setPicURL(const QString &_set, const QString &_picURL) { picURLs.insert(_set, _picURL); }
void setPicURLHq(const QString &_set, const QString &_picURL) { picURLsHq.insert(_set, _picURL); }
void setPicURLSt(const QString &_set, const QString &_picURL) { picURLsSt.insert(_set, _picURL); }
void setMuId(const QString &_set, const int &_muId) { muIds.insert(_set, _muId); }
void addToSet(CardSet *set);
QPixmap *loadPixmap();
QPixmap *getPixmap(QSize size);
void clearPixmapCache();
void clearPixmapCacheMiss();
void imageLoaded(const QImage &image);
CardSet *getPreferredSet();
int getPreferredMuId();
public slots:
void updatePixmapCache();
signals:
@ -162,16 +156,18 @@ signals:
void cardInfoChanged(CardInfo *card);
};
enum LoadStatus { Ok, VersionTooOld, Invalid, NotLoaded, FileError, NoCards };
class CardDatabase : public QObject {
Q_OBJECT
protected:
QHash<QString, CardInfo *> cardHash;
QHash<QString, CardSet *> setHash;
bool loadSuccess;
CardInfo *noCard;
QThread *pictureLoaderThread;
PictureLoader *pictureLoader;
LoadStatus loadStatus;
private:
static const int versionNeeded;
void loadCardsFromXml(QXmlStreamReader &xml);
@ -186,21 +182,23 @@ public:
CardSet *getSet(const QString &setName);
QList<CardInfo *> getCardList() const { return cardHash.values(); }
SetList getSetList() const;
bool loadFromFile(const QString &fileName, bool tokens = false);
LoadStatus loadFromFile(const QString &fileName, bool tokens = false);
bool saveToFile(const QString &fileName, bool tokens = false);
QStringList getAllColors() const;
QStringList getAllMainCardTypes() const;
bool getLoadSuccess() const { return loadSuccess; }
LoadStatus getLoadStatus() const { return loadStatus; }
bool getLoadSuccess() const { return loadStatus == Ok; }
void cacheCardPixmaps(const QStringList &cardNames);
void loadImage(CardInfo *card);
public slots:
void clearPixmapCache();
bool loadCardDatabase(const QString &path, bool tokens = false);
LoadStatus loadCardDatabase(const QString &path, bool tokens = false);
private slots:
void imageLoaded(CardInfo *card, QImage image);
void picDownloadChanged();
void picDownloadHqChanged();
void picsPathChanged();
void loadCardDatabase();
void loadTokenDatabase();
signals:

View file

@ -1,5 +1,6 @@
#include <QStringList>
#include <QFile>
#include <QDebug>
#include "deck_loader.h"
#include "decklist.h"
@ -44,18 +45,28 @@ bool DeckLoader::loadFromFile(const QString &fileName, FileFormat fmt)
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return false;
bool result = false;
switch (fmt) {
case PlainTextFormat: result = loadFromFile_Plain(&file); break;
case CockatriceFormat: result = loadFromFile_Native(&file); break;
case CockatriceFormat:
result = loadFromFile_Native(&file);
qDebug() << "Loaded from" << fileName << "-" << result;
if (!result) {
qDebug() << "Retying as plain format";
file.seek(0);
result = loadFromFile_Plain(&file);
fmt = PlainTextFormat;
}
break;
}
if (result) {
lastFileName = fileName;
lastFileFormat = fmt;
emit deckLoaded();
}
qDebug() << "Deck was loaded -" << result;
return result;
}
@ -66,7 +77,7 @@ bool DeckLoader::loadFromRemote(const QString &nativeString, int remoteDeckId)
lastFileName = QString();
lastFileFormat = CockatriceFormat;
lastRemoteDeckId = remoteDeckId;
emit deckLoaded();
}
return result;

View file

@ -14,7 +14,7 @@
#include "deck_loader.h"
DeckListModel::DeckListModel(QObject *parent)
: QAbstractItemModel(parent)
: QAbstractItemModel(parent), lastKnownColumn(1), lastKnownOrder(Qt::AscendingOrder)
{
deckList = new DeckLoader;
connect(deckList, SIGNAL(deckLoaded()), this, SLOT(rebuildTree()));
@ -275,23 +275,20 @@ QModelIndex DeckListModel::addCard(const QString &cardName, const QString &zoneN
QString cardType = info->getMainCardType();
InnerDecklistNode *cardTypeNode = createNodeIfNeeded(cardType, zoneNode);
QModelIndex parentIndex = nodeToIndex(cardTypeNode);
DecklistModelCardNode *cardNode = dynamic_cast<DecklistModelCardNode *>(cardTypeNode->findChild(cardName));
if (!cardNode) {
DecklistCardNode *decklistCard = deckList->addCard(cardName, zoneName);
QModelIndex parentIndex = nodeToIndex(cardTypeNode);
beginInsertRows(parentIndex, cardTypeNode->size(), cardTypeNode->size());
cardNode = new DecklistModelCardNode(decklistCard, cardTypeNode);
endInsertRows();
sort(1);
emitRecursiveUpdates(parentIndex);
return nodeToIndex(cardNode);
} else {
cardNode->setNumber(cardNode->getNumber() + 1);
QModelIndex ind = nodeToIndex(cardNode);
emitRecursiveUpdates(ind);
deckList->updateDeckHash();
return ind;
}
sort(lastKnownColumn, lastKnownOrder);
emitRecursiveUpdates(parentIndex);
return nodeToIndex(cardNode);
}
QModelIndex DeckListModel::nodeToIndex(AbstractDecklistNode *node) const
@ -318,7 +315,7 @@ void DeckListModel::sortHelper(InnerDecklistNode *node, Qt::SortOrder order)
}
}
changePersistentIndexList(from, to);
// Recursion
for (int i = node->size() - 1; i >= 0; --i) {
InnerDecklistNode *subNode = dynamic_cast<InnerDecklistNode *>(node->at(i));
@ -327,9 +324,24 @@ void DeckListModel::sortHelper(InnerDecklistNode *node, Qt::SortOrder order)
}
}
void DeckListModel::sort(int /*column*/, Qt::SortOrder order)
void DeckListModel::sort(int column, Qt::SortOrder order)
{
lastKnownColumn = column;
lastKnownOrder = order;
emit layoutAboutToBeChanged();
DeckSortMethod sortMethod;
switch(column) {
case 0:
sortMethod = ByNumber;
break;
case 1:
sortMethod = ByName;
break;
case 2:
sortMethod = ByPrice;
}
root->setSortMethod(sortMethod);
sortHelper(root, order);
emit layoutChanged();
}

View file

@ -55,6 +55,8 @@ public:
private:
DeckLoader *deckList;
InnerDecklistNode *root;
int lastKnownColumn;
Qt::SortOrder lastKnownOrder;
InnerDecklistNode *createNodeIfNeeded(const QString &name, InnerDecklistNode *parent);
QModelIndex nodeToIndex(AbstractDecklistNode *node) const;
DecklistModelCardNode *findCardNode(const QString &cardName, const QString &zoneName) const;

View file

@ -18,6 +18,7 @@
#include <QInputDialog>
#include <QSpinBox>
#include <QDialogButtonBox>
#include <QDebug>
#include "carddatabase.h"
#include "dlg_settings.h"
#include "main.h"
@ -27,7 +28,7 @@ GeneralSettingsPage::GeneralSettingsPage()
{
languageLabel = new QLabel;
languageBox = new QComboBox;
QString setLanguage = settingsCache->getLang();
QStringList qmFiles = findQmFiles();
for (int i = 0; i < qmFiles.size(); i++) {
@ -36,27 +37,32 @@ GeneralSettingsPage::GeneralSettingsPage()
if ((qmFiles[i] == setLanguage) || (setLanguage.isEmpty() && langName == tr("English")))
languageBox->setCurrentIndex(i);
}
picDownloadCheckBox = new QCheckBox;
picDownloadCheckBox->setChecked(settingsCache->getPicDownload());
picDownloadHqCheckBox = new QCheckBox;
picDownloadHqCheckBox->setChecked(settingsCache->getPicDownloadHq());
connect(languageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(languageBoxChanged(int)));
connect(picDownloadCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPicDownload(int)));
connect(picDownloadHqCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPicDownloadHq(int)));
QGridLayout *personalGrid = new QGridLayout;
personalGrid->addWidget(languageLabel, 0, 0);
personalGrid->addWidget(languageBox, 0, 1);
personalGrid->addWidget(picDownloadCheckBox, 1, 0, 1, 2);
personalGrid->addWidget(picDownloadHqCheckBox, 2, 0, 1, 2);
personalGroupBox = new QGroupBox;
personalGroupBox->setLayout(personalGrid);
deckPathLabel = new QLabel;
deckPathEdit = new QLineEdit(settingsCache->getDeckPath());
deckPathEdit->setReadOnly(true);
QPushButton *deckPathButton = new QPushButton("...");
connect(deckPathButton, SIGNAL(clicked()), this, SLOT(deckPathButtonClicked()));
replaysPathLabel = new QLabel;
replaysPathEdit = new QLineEdit(settingsCache->getReplaysPath());
replaysPathEdit->setReadOnly(true);
@ -183,6 +189,7 @@ void GeneralSettingsPage::retranslateUi()
personalGroupBox->setTitle(tr("Personal settings"));
languageLabel->setText(tr("Language:"));
picDownloadCheckBox->setText(tr("Download card pictures on the fly"));
picDownloadHqCheckBox->setText(tr("Download high-quality card pictures"));
pathsGroupBox->setTitle(tr("Paths"));
deckPathLabel->setText(tr("Decks directory:"));
replaysPathLabel->setText(tr("Replays directory:"));
@ -698,17 +705,65 @@ void DlgSettings::changeEvent(QEvent *event)
void DlgSettings::closeEvent(QCloseEvent *event)
{
if (!db->getLoadSuccess())
if (QMessageBox::critical(this, tr("Error"), tr("Your card database is invalid. Would you like to go back and set the correct path?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
bool showLoadError = true;
QString loadErrorMessage = tr("Unknown Error loading card database");
LoadStatus loadStatus = db->getLoadStatus();
qDebug() << "Card Database load status: " << loadStatus;
switch(loadStatus) {
case Ok:
showLoadError = false;
break;
case Invalid:
loadErrorMessage =
tr("Your card database is invalid.\n\n"
"Cockatrice may not function correctly with an invalid database\n\n"
"You may need to rerun oracle to update your card database.\n\n"
"Would you like to change your database location setting?");
break;
case VersionTooOld:
loadErrorMessage =
tr("Your card database version is too old.\n\n"
"This can cause problems loading card information or images\n\n"
"Usually this can be fixed by rerunning oracle to to update your card database.\n\n"
"Would you like to change your database location setting?");
break;
case NotLoaded:
loadErrorMessage =
tr("Your card database did not finish loading\n\n"
"Please file a ticket at http://github.com/Daenyth/Cockatrice/issues with your cards.xml attached\n\n"
"Would you like to change your database location setting?");
break;
case FileError:
loadErrorMessage =
tr("File Error loading your card database.\n\n"
"Would you like to change your database location setting?");
break;
case NoCards:
loadErrorMessage =
tr("Your card database was loaded but contains no cards.\n\n"
"Would you like to change your database location setting?");
break;
default:
loadErrorMessage =
tr("Unknown card database load status\n\n"
"Please file a ticket at http://github.com/Daenyth/Cockatrice/issues\n\n"
"Would you like to change your database location setting?");
break;
}
if (showLoadError)
if (QMessageBox::critical(this, tr("Error"), loadErrorMessage, QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
event->ignore();
return;
}
if (!QDir(settingsCache->getDeckPath()).exists() || settingsCache->getDeckPath().isEmpty())
// TODO: Prompt to create it
if (QMessageBox::critical(this, tr("Error"), tr("The path to your deck directory is invalid. Would you like to go back and set the correct path?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
event->ignore();
return;
}
if (!QDir(settingsCache->getPicsPath()).exists() || settingsCache->getPicsPath().isEmpty())
// TODO: Prompt to create it
if (QMessageBox::critical(this, tr("Error"), tr("The path to your card pictures directory is invalid. Would you like to go back and set the correct path?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
event->ignore();
return;

View file

@ -40,6 +40,7 @@ private:
QGroupBox *personalGroupBox, *pathsGroupBox;
QComboBox *languageBox;
QCheckBox *picDownloadCheckBox;
QCheckBox *picDownloadHqCheckBox;
QLabel *languageLabel, *deckPathLabel, *replaysPathLabel, *picsPathLabel, *cardDatabasePathLabel, *tokenDatabasePathLabel;
};

View file

@ -74,10 +74,18 @@ void installNewTranslator()
qApp->installTranslator(translator);
}
bool settingsValid()
{
return QDir(settingsCache->getDeckPath()).exists() &&
!settingsCache->getDeckPath().isEmpty() &&
QDir(settingsCache->getPicsPath()).exists() &&
!settingsCache->getPicsPath().isEmpty();
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
if (app.arguments().contains("--debug-output"))
qInstallMsgHandler(myMessageOutput);
#ifdef Q_OS_MAC
@ -97,7 +105,7 @@ int main(int argc, char *argv[])
QCoreApplication::setOrganizationName("Cockatrice");
QCoreApplication::setOrganizationDomain("cockatrice.de");
QCoreApplication::setApplicationName("Cockatrice");
if (translationPath.isEmpty()) {
#ifdef Q_OS_MAC
QDir translationsDir = baseDir;
@ -108,7 +116,7 @@ int main(int argc, char *argv[])
translationPath = app.applicationDirPath() + "/translations";
#endif
}
rng = new RNG_SFMT;
settingsCache = new SettingsCache;
db = new CardDatabase;
@ -116,7 +124,7 @@ int main(int argc, char *argv[])
qtTranslator = new QTranslator;
translator = new QTranslator;
installNewTranslator();
qsrand(QDateTime::currentDateTime().toTime_t());
bool startMainProgram = true;
@ -142,30 +150,30 @@ int main(int argc, char *argv[])
QDir().mkpath(dataDir + "/pics");
settingsCache->setPicsPath(dataDir + "/pics");
}
if (!db->getLoadSuccess() || !QDir(settingsCache->getDeckPath()).exists() || settingsCache->getDeckPath().isEmpty() || settingsCache->getPicsPath().isEmpty() || !QDir(settingsCache->getPicsPath()).exists()) {
if (!settingsValid() || db->getLoadStatus() != Ok) {
qDebug("main(): invalid settings or load status");
DlgSettings dlgSettings;
dlgSettings.show();
app.exec();
startMainProgram = (db->getLoadSuccess() && QDir(settingsCache->getDeckPath()).exists() && !settingsCache->getDeckPath().isEmpty() && QDir(settingsCache->getPicsPath()).exists() && !settingsCache->getPicsPath().isEmpty());
}
if (startMainProgram) {
if (settingsValid()) {
qDebug("main(): starting main program");
soundEngine = new SoundEngine;
qDebug("main(): SoundEngine constructor finished");
MainWindow ui;
qDebug("main(): MainWindow constructor finished");
QIcon icon(":/resources/appicon.svg");
ui.setWindowIcon(icon);
ui.show();
qDebug("main(): ui.show() finished");
app.exec();
}
qDebug("Event loop finished, terminating...");
delete db;
delete settingsCache;
@ -173,6 +181,6 @@ int main(int argc, char *argv[])
PingPixmapGenerator::clear();
CountryPixmapGenerator::clear();
UserLevelPixmapGenerator::clear();
return 0;
}

View file

@ -11,6 +11,7 @@ class GameCommand;
class PhaseButton : public QObject, public QGraphicsItem {
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
private:
QString name;
bool active, highlightable;
@ -39,6 +40,7 @@ protected:
class PhasesToolbar : public QObject, public QGraphicsItem {
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
private:
QList<PhaseButton *> buttonList;
PhaseButton *nextTurnButton;

View file

@ -58,7 +58,8 @@ class PendingCommand;
class PlayerArea : public QObject, public QGraphicsItem {
Q_OBJECT
private:
Q_INTERFACES(QGraphicsItem)
private:
QBrush bgPixmapBrush;
QRectF bRect;
private slots:
@ -76,6 +77,7 @@ public:
class Player : public QObject, public QGraphicsItem {
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
signals:
void openDeckEditor(const DeckLoader *deck);
void newCardAdded(AbstractCardItem *card);

View file

@ -27,7 +27,7 @@ void PriceUpdater::updatePrices()
QString q = "http://blacklotusproject.com/json/?cards=";
QStringList cards = deck->getCardList();
for (int i = 0; i < cards.size(); ++i) {
q += cards[i] + "|";
q += cards[i].toLower() + "|";
}
QUrl url(q.replace(' ', '+'));

View file

@ -4,23 +4,27 @@
SettingsCache::SettingsCache()
{
settings = new QSettings(this);
lang = settings->value("personal/lang").toString();
deckPath = settings->value("paths/decks").toString();
replaysPath = settings->value("paths/replays").toString();
picsPath = settings->value("paths/pics").toString();
cardDatabasePath = settings->value("paths/carddatabase").toString();
tokenDatabasePath = settings->value("paths/tokendatabase").toString();
handBgPath = settings->value("zonebg/hand").toString();
stackBgPath = settings->value("zonebg/stack").toString();
tableBgPath = settings->value("zonebg/table").toString();
playerBgPath = settings->value("zonebg/playerarea").toString();
cardBackPicturePath = settings->value("paths/cardbackpicture").toString();
mainWindowGeometry = settings->value("interface/main_window_geometry").toByteArray();
picDownload = settings->value("personal/picturedownload", true).toBool();
picDownloadHq = settings->value("personal/picturedownloadhq", false).toBool();
picUrl = settings->value("personal/picUrl", PIC_URL_DEFAULT).toString();
picUrlHq = settings->value("personal/picUrlHq", PIC_URL_HQ_DEFAULT).toString();
mainWindowGeometry = settings->value("interface/main_window_geometry").toByteArray();
notificationsEnabled = settings->value("interface/notificationsenabled", true).toBool();
doubleClickToPlay = settings->value("interface/doubleclicktoplay", true).toBool();
playToStack = settings->value("interface/playtostack", false).toBool();
@ -31,15 +35,15 @@ SettingsCache::SettingsCache()
invertVerticalCoordinate = settings->value("table/invert_vertical", false).toBool();
minPlayersForMultiColumnLayout = settings->value("interface/min_players_multicolumn", 5).toInt();
tapAnimation = settings->value("cards/tapanimation", true).toBool();
zoneViewSortByName = settings->value("zoneview/sortbyname", true).toBool();
zoneViewSortByType = settings->value("zoneview/sortbytype", true).toBool();
soundEnabled = settings->value("sound/enabled", false).toBool();
soundPath = settings->value("sound/path").toString();
priceTagFeature = settings->value("deckeditor/pricetags", false).toBool();
ignoreUnregisteredUsers = settings->value("chat/ignore_unregistered", false).toBool();
}
@ -125,6 +129,25 @@ void SettingsCache::setPicDownload(int _picDownload)
emit picDownloadChanged();
}
void SettingsCache::setPicDownloadHq(int _picDownloadHq)
{
picDownloadHq = _picDownloadHq;
settings->setValue("personal/picturedownloadhq", picDownloadHq);
emit picDownloadHqChanged();
}
void SettingsCache::setPicUrl(const QString &_picUrl)
{
picUrl = _picUrl;
settings->setValue("personal/picUrl", picUrl);
}
void SettingsCache::setPicUrlHq(const QString &_picUrlHq)
{
picUrlHq = _picUrlHq;
settings->setValue("personal/picUrlHq", picUrlHq);
}
void SettingsCache::setNotificationsEnabled(int _notificationsEnabled)
{
notificationsEnabled = _notificationsEnabled;
@ -219,6 +242,7 @@ void SettingsCache::setPriceTagFeature(int _priceTagFeature)
{
priceTagFeature = _priceTagFeature;
settings->setValue("deckeditor/pricetags", priceTagFeature);
emit priceTagFeatureChanged(priceTagFeature);
}
void SettingsCache::setIgnoreUnregisteredUsers(bool _ignoreUnregisteredUsers)

View file

@ -3,6 +3,9 @@
#include <QObject>
#define PIC_URL_DEFAULT "http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=!cardid!&type=card"
#define PIC_URL_HQ_DEFAULT "http://mtgimage.com/multiverseid/!cardid!.jpg"
class QSettings;
class SettingsCache : public QObject {
@ -18,21 +21,24 @@ signals:
void playerBgPathChanged();
void cardBackPicturePathChanged();
void picDownloadChanged();
void picDownloadHqChanged();
void displayCardNamesChanged();
void horizontalHandChanged();
void invertVerticalCoordinateChanged();
void minPlayersForMultiColumnLayoutChanged();
void soundEnabledChanged();
void soundPathChanged();
void priceTagFeatureChanged(int enabled);
void ignoreUnregisteredUsersChanged();
private:
QSettings *settings;
QByteArray mainWindowGeometry;
QString lang;
QString deckPath, replaysPath, picsPath, cardDatabasePath, tokenDatabasePath;
QString handBgPath, stackBgPath, tableBgPath, playerBgPath, cardBackPicturePath;
bool picDownload;
bool picDownloadHq;
bool notificationsEnabled;
bool doubleClickToPlay;
bool playToStack;
@ -48,6 +54,8 @@ private:
QString soundPath;
bool priceTagFeature;
bool ignoreUnregisteredUsers;
QString picUrl;
QString picUrlHq;
public:
SettingsCache();
const QByteArray &getMainWindowGeometry() const { return mainWindowGeometry; }
@ -63,6 +71,7 @@ public:
QString getPlayerBgPath() const { return playerBgPath; }
QString getCardBackPicturePath() const { return cardBackPicturePath; }
bool getPicDownload() const { return picDownload; }
bool getPicDownloadHq() const { return picDownloadHq; }
bool getNotificationsEnabled() const { return notificationsEnabled; }
bool getDoubleClickToPlay() const { return doubleClickToPlay; }
bool getPlayToStack() const { return playToStack; }
@ -79,6 +88,8 @@ public:
QString getSoundPath() const { return soundPath; }
bool getPriceTagFeature() const { return priceTagFeature; }
bool getIgnoreUnregisteredUsers() const { return ignoreUnregisteredUsers; }
QString getPicUrl() const { return picUrl; }
QString getPicUrlHq() const { return picUrlHq; }
public slots:
void setMainWindowGeometry(const QByteArray &_mainWindowGeometry);
void setLang(const QString &_lang);
@ -93,6 +104,7 @@ public slots:
void setPlayerBgPath(const QString &_playerBgPath);
void setCardBackPicturePath(const QString &_cardBackPicturePath);
void setPicDownload(int _picDownload);
void setPicDownloadHq(int _picDownloadHq);
void setNotificationsEnabled(int _notificationsEnabled);
void setDoubleClickToPlay(int _doubleClickToPlay);
void setPlayToStack(int _playToStack);
@ -109,6 +121,8 @@ public slots:
void setSoundPath(const QString &_soundPath);
void setPriceTagFeature(int _priceTagFeature);
void setIgnoreUnregisteredUsers(bool _ignoreUnregisteredUsers);
void setPicUrl(const QString &_picUrl);
void setPicUrlHq(const QString &_picUrlHq);
};
extern SettingsCache *settingsCache;

View file

@ -132,6 +132,8 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
deckView = new QTreeView();
deckView->setModel(deckModel);
deckView->setUniformRowHeights(true);
deckView->setSortingEnabled(true);
deckView->sortByColumn(1, Qt::AscendingOrder);
deckView->header()->setResizeMode(QHeaderView::ResizeToContents);
deckView->installEventFilter(&deckViewKeySignals);
connect(deckView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(updateCardInfoRight(const QModelIndex &, const QModelIndex &)));
@ -170,6 +172,7 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
connect(aUpdatePrices, SIGNAL(triggered()), this, SLOT(actUpdatePrices()));
if (!settingsCache->getPriceTagFeature())
aUpdatePrices->setVisible(false);
connect(settingsCache, SIGNAL(priceTagFeatureChanged(int)), this, SLOT(setPriceTagFeatureEnabled(int)));
QToolBar *deckToolBar = new QToolBar;
deckToolBar->setOrientation(Qt::Vertical);
@ -180,7 +183,7 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
deckToolbarLayout->addStretch();
deckToolbarLayout->addWidget(deckToolBar);
deckToolbarLayout->addStretch();
QVBoxLayout *rightFrame = new QVBoxLayout;
rightFrame->addLayout(grid);
rightFrame->addWidget(deckView, 10);
@ -191,7 +194,7 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
mainLayout->addLayout(middleFrame);
mainLayout->addLayout(rightFrame);
setLayout(mainLayout);
aNewDeck = new QAction(QString(), this);
aNewDeck->setShortcuts(QKeySequence::New);
connect(aNewDeck, SIGNAL(triggered()), this, SLOT(actNewDeck()));
@ -633,6 +636,11 @@ void TabDeckEditor::actDecrement()
offsetCountAtIndex(currentIndex, -1);
}
void TabDeckEditor::setPriceTagFeatureEnabled(int enabled)
{
aUpdatePrices->setVisible(enabled);
}
void TabDeckEditor::actUpdatePrices()
{
aUpdatePrices->setDisabled(true);
@ -655,10 +663,10 @@ void TabDeckEditor::setDeck(DeckLoader *_deck)
nameEdit->setText(deckModel->getDeckList()->getName());
commentsEdit->setText(deckModel->getDeckList()->getComments());
updateHash();
deckModel->sort(1);
deckModel->sort(deckView->header()->sortIndicatorSection(), deckView->header()->sortIndicatorOrder());
deckView->expandAll();
setModified(false);
db->cacheCardPixmaps(deckModel->getDeckList()->getCardList());
deckView->expandAll();
setModified(false);

View file

@ -50,7 +50,7 @@ private slots:
void actEditSets();
void actEditTokens();
void actClearSearch();
void actAddCard();
@ -67,6 +67,7 @@ private slots:
void saveDeckRemoteFinished(const Response &r);
void filterViewCustomContextMenu(const QPoint &point);
void filterRemove(QAction *action);
void setPriceTagFeatureEnabled(int enabled);
private:
CardInfo *currentCardInfo() const;
void addCardHelper(QString zoneName);

View file

@ -11,6 +11,7 @@ class QGraphicsSceneWheelEvent;
class ZoneViewZone : public SelectZone, public QGraphicsLayoutItem {
Q_OBJECT
Q_INTERFACES(QGraphicsLayoutItem)
private:
QRectF bRect, optimumRect;
int minRows, numberCards;