mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-10 08:14:47 -07:00
Rework "paths" settings loading and card database loading
* main.cpp: removed path checking and db loading * card database: merge card loading methods into a single one * settings cache: take care of returning safe paths for decks, replays, etc.. * main window: if db loading fails (eg. first run), propose to run oracle NSIS: propose to run cockatrice instead of oracle Rework card database loading * Move carddatabase-related method out of deckeditor tab * Load cards in another thread and render them progressively * Optimize database reload after enabled sets change Fix deck editor column width * removed the noCard hack. * getCard() no more creates cards instead of just returning existing ones * Fix the “edit tokens” dialog. * PictureLoader: avoid trying to download twice the same card * PictureLoader: correct return of card background * AbstractCardItem: avoid recalculating card color at every paint Use a different file to save custom tokens Misc required improvements * Use nullptr; * Refactor CardInfoWidget to use CardInfoPicture and CardInfoText instead of duplicating code; * Added CardInfo::getColorChar() * Fixed some potential crashes * removed dead code related to CardInfoWidget * Don't require a restart after adding a new custom sets file * Bump CMake requirements to 3.1
This commit is contained in:
parent
0b8f52e084
commit
1e3fb6c6e1
41 changed files with 855 additions and 1074 deletions
|
|
@ -287,6 +287,22 @@ QString CardInfo::simplifyName(const QString &name) {
|
|||
return simpleName;
|
||||
}
|
||||
|
||||
const QChar CardInfo::getColorChar() const
|
||||
{
|
||||
switch(colors.size())
|
||||
{
|
||||
case 0:
|
||||
return QChar();
|
||||
break;
|
||||
case 1:
|
||||
return colors.first().isEmpty() ? QChar() : colors.first().at(0);
|
||||
break;
|
||||
default:
|
||||
return QChar('m');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info)
|
||||
{
|
||||
xml.writeStartElement("card");
|
||||
|
|
@ -341,39 +357,35 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info)
|
|||
}
|
||||
|
||||
CardDatabase::CardDatabase(QObject *parent)
|
||||
: QObject(parent), noCard(0), loadStatus(NotLoaded)
|
||||
: QObject(parent), loadStatus(NotLoaded)
|
||||
{
|
||||
connect(settingsCache, SIGNAL(cardDatabasePathChanged()), this, SLOT(loadCardDatabase()));
|
||||
connect(settingsCache, SIGNAL(tokenDatabasePathChanged()), this, SLOT(loadTokenDatabase()));
|
||||
|
||||
noCard = new CardInfo();
|
||||
connect(settingsCache, SIGNAL(cardDatabasePathChanged()), this, SLOT(loadCardDatabases()));
|
||||
}
|
||||
|
||||
CardDatabase::~CardDatabase()
|
||||
{
|
||||
clear();
|
||||
delete noCard;
|
||||
}
|
||||
|
||||
void CardDatabase::clear()
|
||||
{
|
||||
QHashIterator<QString, CardInfo *> i(cards);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
removeCard(i.value());
|
||||
i.value()->deleteLater();
|
||||
}
|
||||
|
||||
// The pointers themselves were already deleted, so we don't delete them again.
|
||||
cards.clear();
|
||||
simpleNameCards.clear();
|
||||
|
||||
QHashIterator<QString, CardSet *> setIt(sets);
|
||||
while (setIt.hasNext()) {
|
||||
setIt.next();
|
||||
delete setIt.value();
|
||||
}
|
||||
sets.clear();
|
||||
|
||||
QHashIterator<QString, CardInfo *> i(cards);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
delete i.value();
|
||||
}
|
||||
cards.clear();
|
||||
|
||||
// The pointers themselves were already deleted, so we don't delete them
|
||||
// again.
|
||||
simpleNameCards.clear();
|
||||
}
|
||||
|
||||
void CardDatabase::addCard(CardInfo *card)
|
||||
|
|
@ -390,22 +402,23 @@ void CardDatabase::removeCard(CardInfo *card)
|
|||
emit cardRemoved(card);
|
||||
}
|
||||
|
||||
CardInfo *CardDatabase::getCard(const QString &cardName, bool createIfNotFound) {
|
||||
return getCardFromMap(cards, cardName, createIfNotFound);
|
||||
CardInfo *CardDatabase::getCard(const QString &cardName) const
|
||||
{
|
||||
return getCardFromMap(cards, cardName);
|
||||
}
|
||||
|
||||
QList<CardInfo *> CardDatabase::getCards(const QStringList &cardNames)
|
||||
QList<CardInfo *> CardDatabase::getCards(const QStringList &cardNames) const
|
||||
{
|
||||
QList<CardInfo *> cardInfos;
|
||||
foreach(QString cardName, cardNames)
|
||||
cardInfos.append(getCardFromMap(cards, cardName, false));
|
||||
cardInfos.append(getCardFromMap(cards, cardName));
|
||||
|
||||
return cardInfos;
|
||||
}
|
||||
|
||||
CardInfo *CardDatabase::getCardBySimpleName(const QString &cardName, bool createIfNotFound) {
|
||||
QString simpleName = CardInfo::simplifyName(cardName);
|
||||
return getCardFromMap(simpleNameCards, simpleName, createIfNotFound);
|
||||
CardInfo *CardDatabase::getCardBySimpleName(const QString &cardName) const
|
||||
{
|
||||
return getCardFromMap(simpleNameCards, CardInfo::simplifyName(cardName));
|
||||
}
|
||||
|
||||
CardSet *CardDatabase::getSet(const QString &setName)
|
||||
|
|
@ -459,7 +472,7 @@ void CardDatabase::loadSetsFromXml(QXmlStreamReader &xml)
|
|||
}
|
||||
}
|
||||
|
||||
void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml, bool tokens)
|
||||
void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml)
|
||||
{
|
||||
while (!xml.atEnd()) {
|
||||
if (xml.readNext() == QXmlStreamReader::EndElement)
|
||||
|
|
@ -518,28 +531,20 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml, bool tokens)
|
|||
isToken = xml.readElementText().toInt();
|
||||
}
|
||||
|
||||
if (isToken == tokens) {
|
||||
addCard(new CardInfo(name, isToken, manacost, cmc, type, pt, text, colors, relatedCards, reverseRelatedCards, upsideDown, loyalty, cipt, tableRow, sets, customPicURLs, muids));
|
||||
}
|
||||
addCard(new CardInfo(name, isToken, manacost, cmc, type, pt, text, colors, relatedCards, reverseRelatedCards, upsideDown, loyalty, cipt, tableRow, sets, customPicURLs, muids));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CardInfo *CardDatabase::getCardFromMap(CardNameMap &cardMap, const QString &cardName, bool createIfNotFound) {
|
||||
CardInfo *CardDatabase::getCardFromMap(const CardNameMap &cardMap, const QString &cardName) const
|
||||
{
|
||||
if (cardMap.contains(cardName))
|
||||
return cardMap.value(cardName);
|
||||
|
||||
if (createIfNotFound) {
|
||||
CardInfo *newCard = new CardInfo(cardName, true);
|
||||
newCard->addToSet(getSet(CardDatabase::TOKENS_SETNAME));
|
||||
cardMap.insert(cardName, newCard);
|
||||
return newCard;
|
||||
}
|
||||
|
||||
return noCard;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LoadStatus CardDatabase::loadFromFile(const QString &fileName, bool tokens)
|
||||
LoadStatus CardDatabase::loadFromFile(const QString &fileName)
|
||||
{
|
||||
QFile file(fileName);
|
||||
file.open(QIODevice::ReadOnly);
|
||||
|
|
@ -562,11 +567,10 @@ LoadStatus CardDatabase::loadFromFile(const QString &fileName, bool tokens)
|
|||
if (xml.name() == "sets")
|
||||
loadSetsFromXml(xml);
|
||||
else if (xml.name() == "cards")
|
||||
loadCardsFromXml(xml, tokens);
|
||||
loadCardsFromXml(xml);
|
||||
}
|
||||
}
|
||||
}
|
||||
qDebug() << cards.size() << "cards in" << sets.size() << "sets loaded";
|
||||
|
||||
if (cards.isEmpty()) return NoCards;
|
||||
|
||||
|
|
@ -609,57 +613,59 @@ bool CardDatabase::saveToFile(const QString &fileName, bool tokens)
|
|||
return true;
|
||||
}
|
||||
|
||||
void CardDatabase::emitCardListChanged()
|
||||
{
|
||||
emit cardListChanged();
|
||||
}
|
||||
|
||||
LoadStatus CardDatabase::loadCardDatabase(const QString &path, bool tokens)
|
||||
LoadStatus CardDatabase::loadCardDatabase(const QString &path)
|
||||
{
|
||||
LoadStatus tempLoadStatus = NotLoaded;
|
||||
if (!path.isEmpty())
|
||||
tempLoadStatus = loadFromFile(path, tokens);
|
||||
tempLoadStatus = loadFromFile(path);
|
||||
|
||||
if (tempLoadStatus == Ok) {
|
||||
SetList allSets;
|
||||
QHashIterator<QString, CardSet *> setsIterator(sets);
|
||||
while (setsIterator.hasNext())
|
||||
allSets.append(setsIterator.next().value());
|
||||
allSets.sortByKey();
|
||||
|
||||
if(!tokens)
|
||||
checkUnknownSets();
|
||||
emit cardListChanged();
|
||||
}
|
||||
|
||||
if (!tokens)
|
||||
loadStatus = tempLoadStatus;
|
||||
|
||||
qDebug() << "loadCardDatabase(): Path =" << path << "Tokens =" << tokens << "Status =" << loadStatus;
|
||||
qDebug() << "[CardDatabase] loadCardDatabase(): Path =" << path << "Status =" << tempLoadStatus << "Cards =" << cards.size() << "Sets=" << sets.size();
|
||||
|
||||
return tempLoadStatus;
|
||||
}
|
||||
|
||||
LoadStatus CardDatabase::loadCardDatabase()
|
||||
LoadStatus CardDatabase::loadCardDatabases()
|
||||
{
|
||||
return loadCardDatabase(settingsCache->getCardDatabasePath(), false);
|
||||
}
|
||||
|
||||
LoadStatus CardDatabase::loadTokenDatabase()
|
||||
{
|
||||
return loadCardDatabase(settingsCache->getTokenDatabasePath(), true);
|
||||
}
|
||||
|
||||
void CardDatabase::loadCustomCardDatabases(const QString &path)
|
||||
{
|
||||
QDir dir(path);
|
||||
if(!dir.exists())
|
||||
return;
|
||||
|
||||
qDebug() << "CardDatabase::loadCardDatabases start";
|
||||
// clean old db
|
||||
clear();
|
||||
// load main card database
|
||||
loadStatus = loadCardDatabase(settingsCache->getCardDatabasePath());
|
||||
// laod tokens database
|
||||
loadCardDatabase(settingsCache->getTokenDatabasePath());
|
||||
// load custom card databases
|
||||
QDir dir(settingsCache->getCustomCardDatabasePath());
|
||||
foreach(QString fileName, dir.entryList(QStringList("*.xml"), QDir::Files | QDir::Readable, QDir::Name | QDir::IgnoreCase))
|
||||
{
|
||||
loadCardDatabase(dir.absoluteFilePath(fileName), false);
|
||||
loadCardDatabase(dir.absoluteFilePath(fileName));
|
||||
}
|
||||
|
||||
// AFTER all the cards have been loaded
|
||||
|
||||
// reorder sets (TODO: refactor, this smells)
|
||||
SetList allSets;
|
||||
QHashIterator<QString, CardSet *> setsIterator(sets);
|
||||
while (setsIterator.hasNext())
|
||||
allSets.append(setsIterator.next().value());
|
||||
allSets.sortByKey();
|
||||
|
||||
// resolve the reverse-related tags
|
||||
refreshCachedReverseRelatedCards();
|
||||
|
||||
if(loadStatus == Ok)
|
||||
{
|
||||
// check for unknown sets
|
||||
checkUnknownSets();
|
||||
// update deck editors, etc
|
||||
qDebug() << "CardDatabase::loadCardDatabases success";
|
||||
} else {
|
||||
// bring up thr settings dialog
|
||||
qDebug() << "CardDatabase::loadCardDatabases failed";
|
||||
emit cardDatabaseLoadingFailed();
|
||||
}
|
||||
|
||||
// return the loadstatus of the main card database.
|
||||
return loadStatus;
|
||||
}
|
||||
|
||||
void CardDatabase::refreshCachedReverseRelatedCards()
|
||||
|
|
@ -716,48 +722,70 @@ void CardDatabase::checkUnknownSets()
|
|||
{
|
||||
SetList sets = getSetList();
|
||||
|
||||
// no set is enabled. Probably this is the first time running trice
|
||||
if(!sets.getEnabledSetsNum())
|
||||
if(sets.getEnabledSetsNum())
|
||||
{
|
||||
// if some sets are first found on thus run, ask the user
|
||||
int numUnknownSets = sets.getUnknownSetsNum();
|
||||
if(numUnknownSets > 0)
|
||||
emit cardDatabaseNewSetsFound(numUnknownSets);
|
||||
} else {
|
||||
// No set enabled. Probably this is the first time running trice
|
||||
sets.guessSortKeys();
|
||||
sets.sortByKey();
|
||||
sets.enableAll();
|
||||
notifyEnabledSetsChanged();
|
||||
|
||||
detectedFirstRun = true;
|
||||
return;
|
||||
emit cardDatabaseAllNewSetsEnabled();
|
||||
}
|
||||
|
||||
detectedFirstRun = false;
|
||||
|
||||
int numUnknownSets = sets.getUnknownSetsNum();
|
||||
// no unkown sets.
|
||||
if(!numUnknownSets)
|
||||
return;
|
||||
|
||||
QMessageBox msgbox(QMessageBox::Question, tr("New sets found"), tr("%1 new set(s) have been found in the card database. Do you want to enable them?").arg(numUnknownSets), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
|
||||
|
||||
switch(msgbox.exec())
|
||||
{
|
||||
case QMessageBox::No:
|
||||
sets.markAllAsKnown();
|
||||
break;
|
||||
case QMessageBox::Yes:
|
||||
sets.enableAllUnknown();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool CardDatabase::hasDetectedFirstRun()
|
||||
void CardDatabase::enableAllUnknownSets()
|
||||
{
|
||||
if(detectedFirstRun)
|
||||
{
|
||||
detectedFirstRun=false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
SetList sets = getSetList();
|
||||
sets.enableAllUnknown();
|
||||
}
|
||||
|
||||
void CardDatabase::markAllSetsAsKnown()
|
||||
{
|
||||
SetList sets = getSetList();
|
||||
sets.markAllAsKnown();
|
||||
}
|
||||
|
||||
void CardDatabase::notifyEnabledSetsChanged()
|
||||
{
|
||||
// refresh the list of cached set names
|
||||
foreach(CardInfo * card, cards)
|
||||
card->refreshCachedSetNames();
|
||||
|
||||
// inform the carddatabasemodels that they need to re-check their list of cards
|
||||
emit cardDatabaseEnabledSetsChanged();
|
||||
}
|
||||
|
||||
bool CardDatabase::saveCustomTokensToFile()
|
||||
{
|
||||
CardSet * customTokensSet = getSet(CardDatabase::TOKENS_SETNAME);
|
||||
QString fileName = settingsCache->getCustomCardDatabasePath() + "/" + CardDatabase::TOKENS_SETNAME + ".xml";
|
||||
QFile file(fileName);
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
return false;
|
||||
QXmlStreamWriter xml(&file);
|
||||
|
||||
xml.setAutoFormatting(true);
|
||||
xml.writeStartDocument();
|
||||
xml.writeStartElement("cockatrice_carddatabase");
|
||||
xml.writeAttribute("version", QString::number(versionNeeded));
|
||||
|
||||
xml.writeStartElement("cards");
|
||||
QHashIterator<QString, CardInfo *> cardIterator(cards);
|
||||
while (cardIterator.hasNext()) {
|
||||
CardInfo *card = cardIterator.next().value();
|
||||
if(card->getSets().contains(customTokensSet))
|
||||
xml << card;
|
||||
}
|
||||
xml.writeEndElement(); // cards
|
||||
|
||||
xml.writeEndElement(); // cockatrice_carddatabase
|
||||
xml.writeEndDocument();
|
||||
|
||||
return true;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue