Merge pull request #111 from Daenyth/better-invalid-db-ux
Don't be a jerk when card database isn't usable.
This commit is contained in:
commit
1260ccc531
4 changed files with 109 additions and 41 deletions
|
@ -14,7 +14,7 @@
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
const int CardDatabase::versionNeeded = 2;
|
const int CardDatabase::versionNeeded = 3;
|
||||||
|
|
||||||
CardSet::CardSet(const QString &_shortName, const QString &_longName)
|
CardSet::CardSet(const QString &_shortName, const QString &_longName)
|
||||||
: shortName(_shortName), longName(_longName)
|
: shortName(_shortName), longName(_longName)
|
||||||
|
@ -457,7 +457,7 @@ QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info)
|
||||||
}
|
}
|
||||||
|
|
||||||
CardDatabase::CardDatabase(QObject *parent)
|
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(picsPathChanged()), this, SLOT(picsPathChanged()));
|
||||||
connect(settingsCache, SIGNAL(cardDatabasePathChanged()), this, SLOT(loadCardDatabase()));
|
connect(settingsCache, SIGNAL(cardDatabasePathChanged()), this, SLOT(loadCardDatabase()));
|
||||||
|
@ -636,13 +636,13 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CardDatabase::loadFromFile(const QString &fileName, bool tokens)
|
LoadStatus CardDatabase::loadFromFile(const QString &fileName, bool tokens)
|
||||||
{
|
{
|
||||||
QFile file(fileName);
|
QFile file(fileName);
|
||||||
file.open(QIODevice::ReadOnly);
|
file.open(QIODevice::ReadOnly);
|
||||||
if (!file.isOpen())
|
if (!file.isOpen())
|
||||||
return false;
|
return FileError;
|
||||||
|
|
||||||
if (tokens) {
|
if (tokens) {
|
||||||
QMutableHashIterator<QString, CardInfo *> i(cardHash);
|
QMutableHashIterator<QString, CardInfo *> i(cardHash);
|
||||||
while (i.hasNext()) {
|
while (i.hasNext()) {
|
||||||
|
@ -659,7 +659,7 @@ bool CardDatabase::loadFromFile(const QString &fileName, bool tokens)
|
||||||
delete setIt.value();
|
delete setIt.value();
|
||||||
}
|
}
|
||||||
setHash.clear();
|
setHash.clear();
|
||||||
|
|
||||||
QMutableHashIterator<QString, CardInfo *> i(cardHash);
|
QMutableHashIterator<QString, CardInfo *> i(cardHash);
|
||||||
while (i.hasNext()) {
|
while (i.hasNext()) {
|
||||||
i.next();
|
i.next();
|
||||||
|
@ -675,9 +675,12 @@ bool CardDatabase::loadFromFile(const QString &fileName, bool tokens)
|
||||||
while (!xml.atEnd()) {
|
while (!xml.atEnd()) {
|
||||||
if (xml.readNext() == QXmlStreamReader::StartElement) {
|
if (xml.readNext() == QXmlStreamReader::StartElement) {
|
||||||
if (xml.name() != "cockatrice_carddatabase")
|
if (xml.name() != "cockatrice_carddatabase")
|
||||||
return false;
|
return Invalid;
|
||||||
if (xml.attributes().value("version").toString().toInt() < versionNeeded)
|
int version = xml.attributes().value("version").toString().toInt();
|
||||||
return false;
|
if (version < versionNeeded) {
|
||||||
|
qDebug() << "loadFromFile(): Version too old: " << version;
|
||||||
|
return VersionTooOld;
|
||||||
|
}
|
||||||
while (!xml.atEnd()) {
|
while (!xml.atEnd()) {
|
||||||
if (xml.readNext() == QXmlStreamReader::EndElement)
|
if (xml.readNext() == QXmlStreamReader::EndElement)
|
||||||
break;
|
break;
|
||||||
|
@ -689,7 +692,10 @@ bool CardDatabase::loadFromFile(const QString &fileName, bool tokens)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qDebug() << cardHash.size() << "cards in" << setHash.size() << "sets loaded";
|
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)
|
bool CardDatabase::saveToFile(const QString &fileName, bool tokens)
|
||||||
|
@ -747,13 +753,13 @@ void CardDatabase::picDownloadHqChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CardDatabase::loadCardDatabase(const QString &path, bool tokens)
|
LoadStatus CardDatabase::loadCardDatabase(const QString &path, bool tokens)
|
||||||
{
|
{
|
||||||
bool tempLoadSuccess = false;
|
LoadStatus tempLoadStatus = NotLoaded;
|
||||||
if (!path.isEmpty())
|
if (!path.isEmpty())
|
||||||
tempLoadSuccess = loadFromFile(path, tokens);
|
tempLoadStatus = loadFromFile(path, tokens);
|
||||||
|
|
||||||
if (tempLoadSuccess) {
|
if (tempLoadStatus == Ok) {
|
||||||
SetList allSets;
|
SetList allSets;
|
||||||
QHashIterator<QString, CardSet *> setsIterator(setHash);
|
QHashIterator<QString, CardSet *> setsIterator(setHash);
|
||||||
while (setsIterator.hasNext())
|
while (setsIterator.hasNext())
|
||||||
|
@ -761,14 +767,17 @@ bool CardDatabase::loadCardDatabase(const QString &path, bool tokens)
|
||||||
allSets.sortByKey();
|
allSets.sortByKey();
|
||||||
for (int i = 0; i < allSets.size(); ++i)
|
for (int i = 0; i < allSets.size(); ++i)
|
||||||
allSets[i]->setSortKey(i);
|
allSets[i]->setSortKey(i);
|
||||||
|
|
||||||
emit cardListChanged();
|
emit cardListChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tokens)
|
if (!tokens) {
|
||||||
loadSuccess = tempLoadSuccess;
|
loadStatus = tempLoadStatus;
|
||||||
|
qDebug() << "loadCardDatabase(): Status = " << loadStatus;
|
||||||
return tempLoadSuccess;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return tempLoadStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardDatabase::loadCardDatabase()
|
void CardDatabase::loadCardDatabase()
|
||||||
|
|
|
@ -158,16 +158,18 @@ signals:
|
||||||
void cardInfoChanged(CardInfo *card);
|
void cardInfoChanged(CardInfo *card);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum LoadStatus { Ok, VersionTooOld, Invalid, NotLoaded, FileError, NoCards };
|
||||||
|
|
||||||
class CardDatabase : public QObject {
|
class CardDatabase : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
protected:
|
protected:
|
||||||
QHash<QString, CardInfo *> cardHash;
|
QHash<QString, CardInfo *> cardHash;
|
||||||
QHash<QString, CardSet *> setHash;
|
QHash<QString, CardSet *> setHash;
|
||||||
bool loadSuccess;
|
|
||||||
CardInfo *noCard;
|
CardInfo *noCard;
|
||||||
|
|
||||||
QThread *pictureLoaderThread;
|
QThread *pictureLoaderThread;
|
||||||
PictureLoader *pictureLoader;
|
PictureLoader *pictureLoader;
|
||||||
|
LoadStatus loadStatus;
|
||||||
private:
|
private:
|
||||||
static const int versionNeeded;
|
static const int versionNeeded;
|
||||||
void loadCardsFromXml(QXmlStreamReader &xml);
|
void loadCardsFromXml(QXmlStreamReader &xml);
|
||||||
|
@ -182,22 +184,23 @@ public:
|
||||||
CardSet *getSet(const QString &setName);
|
CardSet *getSet(const QString &setName);
|
||||||
QList<CardInfo *> getCardList() const { return cardHash.values(); }
|
QList<CardInfo *> getCardList() const { return cardHash.values(); }
|
||||||
SetList getSetList() const;
|
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);
|
bool saveToFile(const QString &fileName, bool tokens = false);
|
||||||
QStringList getAllColors() const;
|
QStringList getAllColors() const;
|
||||||
QStringList getAllMainCardTypes() 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 cacheCardPixmaps(const QStringList &cardNames);
|
||||||
void loadImage(CardInfo *card);
|
void loadImage(CardInfo *card);
|
||||||
public slots:
|
public slots:
|
||||||
void clearPixmapCache();
|
void clearPixmapCache();
|
||||||
bool loadCardDatabase(const QString &path, bool tokens = false);
|
LoadStatus loadCardDatabase(const QString &path, bool tokens = false);
|
||||||
private slots:
|
private slots:
|
||||||
void imageLoaded(CardInfo *card, QImage image);
|
void imageLoaded(CardInfo *card, QImage image);
|
||||||
void picDownloadChanged();
|
void picDownloadChanged();
|
||||||
void picDownloadHqChanged();
|
void picDownloadHqChanged();
|
||||||
void picsPathChanged();
|
void picsPathChanged();
|
||||||
|
|
||||||
void loadCardDatabase();
|
void loadCardDatabase();
|
||||||
void loadTokenDatabase();
|
void loadTokenDatabase();
|
||||||
signals:
|
signals:
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
|
#include <QDebug>
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
#include "dlg_settings.h"
|
#include "dlg_settings.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
@ -704,17 +705,65 @@ void DlgSettings::changeEvent(QEvent *event)
|
||||||
|
|
||||||
void DlgSettings::closeEvent(QCloseEvent *event)
|
void DlgSettings::closeEvent(QCloseEvent *event)
|
||||||
{
|
{
|
||||||
if (!db->getLoadSuccess())
|
bool showLoadError = true;
|
||||||
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) {
|
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();
|
event->ignore();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!QDir(settingsCache->getDeckPath()).exists() || settingsCache->getDeckPath().isEmpty())
|
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) {
|
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();
|
event->ignore();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!QDir(settingsCache->getPicsPath()).exists() || settingsCache->getPicsPath().isEmpty())
|
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) {
|
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();
|
event->ignore();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -74,10 +74,18 @@ void installNewTranslator()
|
||||||
qApp->installTranslator(translator);
|
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[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
if (app.arguments().contains("--debug-output"))
|
if (app.arguments().contains("--debug-output"))
|
||||||
qInstallMsgHandler(myMessageOutput);
|
qInstallMsgHandler(myMessageOutput);
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
|
@ -97,7 +105,7 @@ int main(int argc, char *argv[])
|
||||||
QCoreApplication::setOrganizationName("Cockatrice");
|
QCoreApplication::setOrganizationName("Cockatrice");
|
||||||
QCoreApplication::setOrganizationDomain("cockatrice.de");
|
QCoreApplication::setOrganizationDomain("cockatrice.de");
|
||||||
QCoreApplication::setApplicationName("Cockatrice");
|
QCoreApplication::setApplicationName("Cockatrice");
|
||||||
|
|
||||||
if (translationPath.isEmpty()) {
|
if (translationPath.isEmpty()) {
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
QDir translationsDir = baseDir;
|
QDir translationsDir = baseDir;
|
||||||
|
@ -108,7 +116,7 @@ int main(int argc, char *argv[])
|
||||||
translationPath = app.applicationDirPath() + "/translations";
|
translationPath = app.applicationDirPath() + "/translations";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
rng = new RNG_SFMT;
|
rng = new RNG_SFMT;
|
||||||
settingsCache = new SettingsCache;
|
settingsCache = new SettingsCache;
|
||||||
db = new CardDatabase;
|
db = new CardDatabase;
|
||||||
|
@ -119,7 +127,6 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
qsrand(QDateTime::currentDateTime().toTime_t());
|
qsrand(QDateTime::currentDateTime().toTime_t());
|
||||||
|
|
||||||
bool startMainProgram = true;
|
|
||||||
const QString dataDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
|
const QString dataDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
|
||||||
if (!db->getLoadSuccess())
|
if (!db->getLoadSuccess())
|
||||||
if (db->loadCardDatabase(dataDir + "/cards.xml"))
|
if (db->loadCardDatabase(dataDir + "/cards.xml"))
|
||||||
|
@ -138,30 +145,30 @@ int main(int argc, char *argv[])
|
||||||
QDir().mkpath(dataDir + "/pics");
|
QDir().mkpath(dataDir + "/pics");
|
||||||
settingsCache->setPicsPath(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 dlgSettings;
|
||||||
dlgSettings.show();
|
dlgSettings.show();
|
||||||
app.exec();
|
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");
|
qDebug("main(): starting main program");
|
||||||
soundEngine = new SoundEngine;
|
soundEngine = new SoundEngine;
|
||||||
qDebug("main(): SoundEngine constructor finished");
|
qDebug("main(): SoundEngine constructor finished");
|
||||||
|
|
||||||
MainWindow ui;
|
MainWindow ui;
|
||||||
qDebug("main(): MainWindow constructor finished");
|
qDebug("main(): MainWindow constructor finished");
|
||||||
|
|
||||||
QIcon icon(":/resources/appicon.svg");
|
QIcon icon(":/resources/appicon.svg");
|
||||||
ui.setWindowIcon(icon);
|
ui.setWindowIcon(icon);
|
||||||
|
|
||||||
ui.show();
|
ui.show();
|
||||||
qDebug("main(): ui.show() finished");
|
qDebug("main(): ui.show() finished");
|
||||||
|
|
||||||
app.exec();
|
app.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug("Event loop finished, terminating...");
|
qDebug("Event loop finished, terminating...");
|
||||||
delete db;
|
delete db;
|
||||||
delete settingsCache;
|
delete settingsCache;
|
||||||
|
@ -169,6 +176,6 @@ int main(int argc, char *argv[])
|
||||||
PingPixmapGenerator::clear();
|
PingPixmapGenerator::clear();
|
||||||
CountryPixmapGenerator::clear();
|
CountryPixmapGenerator::clear();
|
||||||
UserLevelPixmapGenerator::clear();
|
UserLevelPixmapGenerator::clear();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue