Misc startup improvement (#3740)

* Misc startup improvement

* fix paths

* clangiftw

* reworked save sets dialog

* Unified load and save steps for tokens and spoilers; added "finished" page

* linting1

* linting2

* wording

* undo layout change

* wording

* fix spoiler path again

* simplify phrase

* lint

* lint fix

Signed-off-by: Zach Halpern <ZaHalpern+github@gmail.com>
This commit is contained in:
ctrlaltca 2019-06-03 03:47:37 +02:00 committed by Zach H
parent e084bd18a9
commit 1d8fb79e11
11 changed files with 402 additions and 504 deletions

View file

@ -275,8 +275,8 @@ SettingsCache::SettingsCache()
spectatorsCanTalk = settings->value("game/spectatorscantalk", false).toBool(); spectatorsCanTalk = settings->value("game/spectatorscantalk", false).toBool();
spectatorsCanSeeEverything = settings->value("game/spectatorscanseeeverything", false).toBool(); spectatorsCanSeeEverything = settings->value("game/spectatorscanseeeverything", false).toBool();
rememberGameSettings = settings->value("game/remembergamesettings", true).toBool(); rememberGameSettings = settings->value("game/remembergamesettings", true).toBool();
clientID = settings->value("personal/clientid", "notset").toString(); clientID = settings->value("personal/clientid", CLIENT_INFO_NOT_SET).toString();
clientVersion = settings->value("personal/clientversion", "notset").toString(); clientVersion = settings->value("personal/clientversion", CLIENT_INFO_NOT_SET).toString();
knownMissingFeatures = settings->value("interface/knownmissingfeatures", "").toString(); knownMissingFeatures = settings->value("interface/knownmissingfeatures", "").toString();
} }

View file

@ -21,6 +21,7 @@ class ReleaseChannel;
#define DEFAULT_LANG_CODE "en" #define DEFAULT_LANG_CODE "en"
#define DEFAULT_LANG_NAME "English" #define DEFAULT_LANG_NAME "English"
#define CLIENT_INFO_NOT_SET "notset"
#define DEFAULT_FONT_SIZE 12 #define DEFAULT_FONT_SIZE 12

View file

@ -24,9 +24,9 @@ SpoilerBackgroundUpdater::SpoilerBackgroundUpdater(QObject *apParent) : QObject(
if (isSpoilerDownloadEnabled) { if (isSpoilerDownloadEnabled) {
// Start the process of checking if we're in spoiler season // Start the process of checking if we're in spoiler season
// File exists means we're in spoiler season // File exists means we're in spoiler season
// We will load the database before attempting to download spoilers, incase they fail
QtConcurrent::run(db, &CardDatabase::loadCardDatabases);
startSpoilerDownloadProcess(SPOILERS_STATUS_URL, false); startSpoilerDownloadProcess(SPOILERS_STATUS_URL, false);
} else {
qDebug() << "Spoilers Disabled";
} }
} }

View file

@ -30,6 +30,7 @@
#include <QPixmapCache> #include <QPixmapCache>
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
#include <QThread> #include <QThread>
#include <QTimer>
#include <QtConcurrent> #include <QtConcurrent>
#include <QtNetwork> #include <QtNetwork>
@ -838,31 +839,54 @@ MainWindow::MainWindow(QWidget *parent)
SLOT(cardDatabaseNewSetsFound(int, QStringList))); SLOT(cardDatabaseNewSetsFound(int, QStringList)));
connect(db, SIGNAL(cardDatabaseAllNewSetsEnabled()), this, SLOT(cardDatabaseAllNewSetsEnabled())); connect(db, SIGNAL(cardDatabaseAllNewSetsEnabled()), this, SLOT(cardDatabaseAllNewSetsEnabled()));
if (!settingsCache->getDownloadSpoilersStatus()) {
qDebug() << "Spoilers Disabled";
QtConcurrent::run(db, &CardDatabase::loadCardDatabases);
}
tip = new DlgTipOfTheDay(); tip = new DlgTipOfTheDay();
if (tip->successfulInit && settingsCache->getShowTipsOnStartup() && tip->newTipsAvailable) {
tip->show();
}
// Only run the check updater if the user wants it (defaults to on) // run startup check async
if (settingsCache->getNotifyAboutNewVersion()) { QTimer::singleShot(0, this, &MainWindow::startupConfigCheck);
auto versionUpdater = new MainUpdateHelper(); }
connect(versionUpdater, SIGNAL(newVersionDetected(QString)), this, SLOT(alertForcedOracleRun(QString)));
QtConcurrent::run(versionUpdater, &MainUpdateHelper::testForNewVersion); void MainWindow::startupConfigCheck()
{
if (settingsCache->getClientVersion() == CLIENT_INFO_NOT_SET) {
// no config found, 99% new clean install
qDebug() << "Startup: old client version empty, assuming first start after clean install";
alertForcedOracleRun(VERSION_STRING, false);
} else if (settingsCache->getClientVersion() != VERSION_STRING) {
// config found, from another (presumably older) version
qDebug() << "Startup: old client version" << settingsCache->getClientVersion()
<< "differs, assuming first start after update";
if (settingsCache->getNotifyAboutNewVersion()) {
alertForcedOracleRun(VERSION_STRING, true);
}
} else {
// previous config from this version found
qDebug() << "Startup: found config with current version";
QtConcurrent::run(db, &CardDatabase::loadCardDatabases);
// Run the tips dialog only on subsequent startups.
// On the first run after an install/update the startup is already crowded enough
if (tip->successfulInit && settingsCache->getShowTipsOnStartup() && tip->newTipsAvailable) {
tip->raise();
tip->show();
}
} }
} }
void MainWindow::alertForcedOracleRun(const QString &newVersion) void MainWindow::alertForcedOracleRun(const QString &version, bool isUpdate)
{ {
settingsCache->setClientVersion(newVersion); settingsCache->setClientVersion(version);
QMessageBox::information(this, tr("New Version"), if (isUpdate) {
tr("Congratulations on updating to Cockatrice %1!\n" QMessageBox::information(this, tr("New Version"),
"Oracle will now launch to update your card database.") tr("Congratulations on updating to Cockatrice %1!\n"
.arg(newVersion)); "Oracle will now launch to update your card database.")
.arg(version));
} else {
QMessageBox::information(this, tr("Cockatrice installed"),
tr("Congratulations on installing Cockatrice %1!\n"
"Oracle will now launch to install the initial card database.")
.arg(version));
}
actCheckCardUpdates(); actCheckCardUpdates();
actCheckServerUpdates(); actCheckServerUpdates();
} }
@ -1123,8 +1147,6 @@ void MainWindow::cardUpdateFinished(int, QProcess::ExitStatus)
cardUpdateProcess->deleteLater(); cardUpdateProcess->deleteLater();
cardUpdateProcess = nullptr; cardUpdateProcess = nullptr;
QMessageBox::information(this, tr("Information"),
tr("Update completed successfully.\nCockatrice will now reload the card database."));
QtConcurrent::run(db, &CardDatabase::loadCardDatabases); QtConcurrent::run(db, &CardDatabase::loadCardDatabases);
} }
@ -1317,10 +1339,3 @@ void MainWindow::promptForgotPasswordReset()
dlg.getPlayerName(), dlg.getToken(), dlg.getPassword()); dlg.getPlayerName(), dlg.getToken(), dlg.getPassword());
} }
} }
void MainUpdateHelper::testForNewVersion()
{
if (settingsCache->getClientVersion() != VERSION_STRING) {
emit newVersionDetected(VERSION_STRING);
}
}

View file

@ -102,7 +102,8 @@ private slots:
void actManageSets(); void actManageSets();
void actEditTokens(); void actEditTokens();
void alertForcedOracleRun(const QString &); void startupConfigCheck();
void alertForcedOracleRun(const QString &version, bool isUpdate);
private: private:
static const QString appName; static const QString appName;
@ -154,17 +155,4 @@ protected:
QString extractInvalidUsernameMessage(QString &in); QString extractInvalidUsernameMessage(QString &in);
}; };
class MainUpdateHelper : public QObject
{
Q_OBJECT
signals:
void newVersionDetected(QString);
public:
explicit MainUpdateHelper() = default;
~MainUpdateHelper() override = default;
void testForNewVersion();
};
#endif #endif

View file

@ -214,7 +214,6 @@ void WndSets::actSave()
{ {
model->save(db); model->save(db);
PictureLoader::clearPixmapCache(); PictureLoader::clearPixmapCache();
QMessageBox::information(this, tr("Success"), tr("The sets database has been saved successfully."));
close(); close();
} }

View file

@ -11,6 +11,7 @@ SET(oracle_SOURCES
src/main.cpp src/main.cpp
src/oraclewizard.cpp src/oraclewizard.cpp
src/oracleimporter.cpp src/oracleimporter.cpp
src/pagetemplates.cpp
src/qt-json/json.cpp src/qt-json/json.cpp
../cockatrice/src/carddatabase.cpp ../cockatrice/src/carddatabase.cpp
../cockatrice/src/pictureloader.cpp ../cockatrice/src/pictureloader.cpp

View file

@ -57,15 +57,17 @@ OracleWizard::OracleWizard(QWidget *parent) : QWizard(parent)
importer = new OracleImporter(settingsCache->getDataPath(), this); importer = new OracleImporter(settingsCache->getDataPath(), this);
nam = new QNetworkAccessManager(this);
if (!isSpoilersOnly) { if (!isSpoilersOnly) {
addPage(new IntroPage); addPage(new IntroPage);
addPage(new LoadSetsPage); addPage(new LoadSetsPage);
addPage(new SaveSetsPage); addPage(new SaveSetsPage);
addPage(new LoadTokensPage); addPage(new LoadTokensPage);
addPage(new SaveTokensPage); addPage(new OutroPage);
} else { } else {
addPage(new LoadSpoilersPage); addPage(new LoadSpoilersPage);
addPage(new SaveSpoilersPage); addPage(new OutroPage);
} }
retranslateUi(); retranslateUi();
@ -89,8 +91,6 @@ void OracleWizard::changeEvent(QEvent *event)
void OracleWizard::retranslateUi() void OracleWizard::retranslateUi()
{ {
setWindowTitle(tr("Oracle Importer")); setWindowTitle(tr("Oracle Importer"));
QWizard::setButtonText(QWizard::FinishButton, tr("Save"));
for (int i = 0; i < pageIds().count(); i++) { for (int i = 0; i < pageIds().count(); i++) {
dynamic_cast<OracleWizardPage *>(page(i))->retranslateUi(); dynamic_cast<OracleWizardPage *>(page(i))->retranslateUi();
} }
@ -195,7 +195,15 @@ void IntroPage::retranslateUi()
versionLabel->setText(tr("Version:") + QString(" %1").arg(VERSION_STRING)); versionLabel->setText(tr("Version:") + QString(" %1").arg(VERSION_STRING));
} }
LoadSetsPage::LoadSetsPage(QWidget *parent) : OracleWizardPage(parent), nam(nullptr) void OutroPage::retranslateUi()
{
setTitle(tr("Finished"));
setSubTitle(tr("The wizard has finished.") + "<br>" +
tr("You can now start using Cockatrice with the newly updated cards.") + "<br><br>" +
tr("If the card databases don't reload automatically, restart the Cockatrice client."));
}
LoadSetsPage::LoadSetsPage(QWidget *parent) : OracleWizardPage(parent)
{ {
urlRadioButton = new QRadioButton(this); urlRadioButton = new QRadioButton(this);
fileRadioButton = new QRadioButton(this); fileRadioButton = new QRadioButton(this);
@ -240,7 +248,7 @@ void LoadSetsPage::initializePage()
void LoadSetsPage::retranslateUi() void LoadSetsPage::retranslateUi()
{ {
setTitle(tr("Source selection")); setTitle(tr("Source selection"));
setSubTitle(tr("Please specify a source for the list of sets and cards. " setSubTitle(tr("Please specify a compatible source for the list of sets and cards. "
"You can specify a URL address that will be downloaded or " "You can specify a URL address that will be downloaded or "
"use an existing file from your computer.")); "use an existing file from your computer."));
@ -330,10 +338,7 @@ bool LoadSetsPage::validatePage()
void LoadSetsPage::downloadSetsFile(QUrl url) void LoadSetsPage::downloadSetsFile(QUrl url)
{ {
if (!nam) { QNetworkReply *reply = wizard()->nam->get(QNetworkRequest(url));
nam = new QNetworkAccessManager(this);
}
QNetworkReply *reply = nam->get(QNetworkRequest(url));
connect(reply, SIGNAL(finished()), this, SLOT(actDownloadFinishedSetsFile())); connect(reply, SIGNAL(finished()), this, SLOT(actDownloadFinishedSetsFile()));
connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(actDownloadProgressSetsFile(qint64, qint64))); connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(actDownloadProgressSetsFile(qint64, qint64)));
@ -478,8 +483,7 @@ void LoadSetsPage::zipDownloadFailed(const QString &message)
QMessageBox::StandardButton reply; QMessageBox::StandardButton reply;
reply = static_cast<QMessageBox::StandardButton>(QMessageBox::question( reply = static_cast<QMessageBox::StandardButton>(QMessageBox::question(
this, tr("Error"), this, tr("Error"), message + "<br>" + tr("Do you want to download the uncompressed file instead?"),
message + "<br/>" + tr("Do you want to try to download a fresh copy of the uncompressed file instead?"),
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)); QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes));
if (reply == QMessageBox::Yes) { if (reply == QMessageBox::Yes) {
@ -507,15 +511,19 @@ void LoadSetsPage::importFinished()
SaveSetsPage::SaveSetsPage(QWidget *parent) : OracleWizardPage(parent) SaveSetsPage::SaveSetsPage(QWidget *parent) : OracleWizardPage(parent)
{ {
pathLabel = new QLabel(this);
saveLabel = new QLabel(this);
defaultPathCheckBox = new QCheckBox(this); defaultPathCheckBox = new QCheckBox(this);
defaultPathCheckBox->setChecked(true);
messageLog = new QTextEdit(this); messageLog = new QTextEdit(this);
messageLog->setReadOnly(true); messageLog->setReadOnly(true);
auto *layout = new QGridLayout(this); auto *layout = new QGridLayout(this);
layout->addWidget(defaultPathCheckBox, 0, 0); layout->addWidget(messageLog, 0, 0);
layout->addWidget(messageLog, 1, 0); layout->addWidget(saveLabel, 1, 0);
layout->addWidget(pathLabel, 2, 0);
layout->addWidget(defaultPathCheckBox, 3, 0);
setLayout(layout); setLayout(layout);
} }
@ -540,10 +548,13 @@ void SaveSetsPage::initializePage()
void SaveSetsPage::retranslateUi() void SaveSetsPage::retranslateUi()
{ {
setTitle(tr("Sets imported")); setTitle(tr("Sets imported"));
setSubTitle(tr("The following sets has been imported. " setSubTitle(tr("The following sets have been found:"));
"Press \"Save\" to save the imported cards to the Cockatrice database."));
saveLabel->setText(tr("Press \"Save\" to store the imported cards in the Cockatrice database."));
pathLabel->setText(tr("The card database will be saved at the following location:") + "<br>" +
settingsCache->getCardDatabasePath());
defaultPathCheckBox->setText(tr("Save to a custom path (not recommended)"));
defaultPathCheckBox->setText(tr("Save to the default path (recommended)"));
setButtonText(QWizard::NextButton, tr("&Save")); setButtonText(QWizard::NextButton, tr("&Save"));
} }
@ -569,9 +580,9 @@ bool SaveSetsPage::validatePage()
do { do {
QString fileName; QString fileName;
if (defaultPathCheckBox->isChecked()) { if (defaultPathCheckBox->isChecked()) {
fileName = defaultPath;
} else {
fileName = QFileDialog::getSaveFileName(this, windowName, defaultPath, fileType); fileName = QFileDialog::getSaveFileName(this, windowName, defaultPath, fileType);
} else {
fileName = defaultPath;
} }
if (fileName.isEmpty()) { if (fileName.isEmpty()) {
@ -586,409 +597,84 @@ bool SaveSetsPage::validatePage()
if (wizard()->importer->saveToFile(fileName)) { if (wizard()->importer->saveToFile(fileName)) {
ok = true; ok = true;
QMessageBox::information(this, tr("Success"),
tr("The card database has been saved successfully to\n%1").arg(fileName));
} else { } else {
QMessageBox::critical(this, tr("Error"), tr("The file could not be saved to %1").arg(fileName)); QMessageBox::critical(this, tr("Error"), tr("The file could not be saved to %1").arg(fileName));
;
if (defaultPathCheckBox->isChecked()) {
defaultPathCheckBox->setChecked(false);
}
} }
} while (!ok); } while (!ok);
return true; return true;
} }
LoadSpoilersPage::LoadSpoilersPage(QWidget *parent) : OracleWizardPage(parent), nam(nullptr) QString LoadTokensPage::getDefaultUrl()
{ {
urlLabel = new QLabel(this); return TOKENS_URL;
urlLineEdit = new QLineEdit(this);
progressLabel = new QLabel(this);
progressBar = new QProgressBar(this);
urlButton = new QPushButton(this);
connect(urlButton, SIGNAL(clicked()), this, SLOT(actRestoreDefaultUrl()));
auto *layout = new QGridLayout(this);
layout->addWidget(urlLabel, 0, 0);
layout->addWidget(urlLineEdit, 0, 1);
layout->addWidget(urlButton, 1, 1, Qt::AlignRight);
layout->addWidget(progressLabel, 2, 0);
layout->addWidget(progressBar, 2, 1);
} }
void LoadSpoilersPage::actRestoreDefaultUrl() QString LoadTokensPage::getCustomUrlSettingsKey()
{ {
urlLineEdit->setText(SPOILERS_URL); return "tokensurl";
} }
void LoadSpoilersPage::initializePage() QString LoadTokensPage::getDefaultSavePath()
{ {
urlLineEdit->setText(wizard()->settings->value("spoilersurl", SPOILERS_URL).toString()); return settingsCache->getTokenDatabasePath();
progressLabel->hide();
progressBar->hide();
} }
void LoadSpoilersPage::actDownloadProgressSpoilersFile(qint64 received, qint64 total) QString LoadTokensPage::getWindowTitle()
{ {
if (total > 0) { return tr("Save token database");
progressBar->setMaximum(static_cast<int>(total));
progressBar->setValue(static_cast<int>(received));
}
progressLabel->setText(tr("Downloading (%1MB)").arg((int)received / (1024 * 1024)));
} }
void LoadSpoilersPage::actDownloadFinishedSpoilersFile() QString LoadTokensPage::getFileType()
{ {
// Check for server reply return tr("XML; token database (*.xml)");
auto *reply = dynamic_cast<QNetworkReply *>(sender());
QNetworkReply::NetworkError errorCode = reply->error();
if (errorCode != QNetworkReply::NoError) {
QMessageBox::critical(this, tr("Error"), tr("Network error: %1.").arg(reply->errorString()));
wizard()->enableButtons();
setEnabled(true);
reply->deleteLater();
return;
}
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (statusCode == 301 || statusCode == 302) {
QUrl redirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
qDebug() << "following redirect url:" << redirectUrl.toString();
downloadSpoilersFile(redirectUrl);
reply->deleteLater();
return;
}
progressLabel->hide();
progressBar->hide();
// save spoiler.xml url, but only if the user customized it and download was successful
if (urlLineEdit->text() != QString(SPOILERS_URL)) {
wizard()->settings->setValue("spoilersurl", urlLineEdit->text());
} else {
wizard()->settings->remove("spoilersurl");
}
wizard()->setTokensData(reply->readAll());
reply->deleteLater();
wizard()->enableButtons();
setEnabled(true);
progressLabel->hide();
progressBar->hide();
wizard()->next();
}
void LoadSpoilersPage::downloadSpoilersFile(QUrl url)
{
if (!nam) {
nam = new QNetworkAccessManager(this);
}
QNetworkReply *reply = nam->get(QNetworkRequest(url));
connect(reply, SIGNAL(finished()), this, SLOT(actDownloadFinishedSpoilersFile()));
connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this,
SLOT(actDownloadProgressSpoilersFile(qint64, qint64)));
}
bool LoadSpoilersPage::validatePage()
{
// once the import is finished, we call next(); skip validation
if (wizard()->hasTokensData()) {
return true;
}
QUrl url = QUrl::fromUserInput(urlLineEdit->text());
if (!url.isValid()) {
QMessageBox::critical(this, tr("Error"), tr("The provided URL is not valid."));
return false;
}
progressLabel->setText(tr("Downloading (0MB)"));
// show an infinite progressbar
progressBar->setMaximum(0);
progressBar->setMinimum(0);
progressBar->setValue(0);
progressLabel->show();
progressBar->show();
wizard()->disableButtons();
setEnabled(false);
downloadSpoilersFile(url);
return false;
}
void LoadSpoilersPage::retranslateUi()
{
setTitle(tr("Spoilers source selection"));
setSubTitle(tr("Please specify a spoiler source."));
urlLabel->setText(tr("Download URL:"));
urlButton->setText(tr("Restore default URL"));
}
LoadTokensPage::LoadTokensPage(QWidget *parent) : OracleWizardPage(parent), nam(nullptr)
{
urlLabel = new QLabel(this);
urlLineEdit = new QLineEdit(this);
progressLabel = new QLabel(this);
progressBar = new QProgressBar(this);
urlButton = new QPushButton(this);
connect(urlButton, SIGNAL(clicked()), this, SLOT(actRestoreDefaultUrl()));
auto *layout = new QGridLayout(this);
layout->addWidget(urlLabel, 0, 0);
layout->addWidget(urlLineEdit, 0, 1);
layout->addWidget(urlButton, 1, 1, Qt::AlignRight);
layout->addWidget(progressLabel, 2, 0);
layout->addWidget(progressBar, 2, 1);
setLayout(layout);
}
void LoadTokensPage::initializePage()
{
urlLineEdit->setText(wizard()->settings->value("tokensurl", TOKENS_URL).toString());
progressLabel->hide();
progressBar->hide();
} }
void LoadTokensPage::retranslateUi() void LoadTokensPage::retranslateUi()
{ {
setTitle(tr("Tokens source selection")); setTitle(tr("Tokens import"));
setSubTitle(tr("Please specify a source for the list of tokens.")); setSubTitle(tr("Please specify a compatible source for token data."));
urlLabel->setText(tr("Download URL:")); urlLabel->setText(tr("Download URL:"));
urlButton->setText(tr("Restore default URL")); urlButton->setText(tr("Restore default URL"));
pathLabel->setText(tr("The token database will be saved at the following location:") + "<br>" +
settingsCache->getTokenDatabasePath());
defaultPathCheckBox->setText(tr("Save to a custom path (not recommended)"));
} }
void LoadTokensPage::actRestoreDefaultUrl() QString LoadSpoilersPage::getDefaultUrl()
{ {
urlLineEdit->setText(TOKENS_URL); return SPOILERS_URL;
} }
bool LoadTokensPage::validatePage() QString LoadSpoilersPage::getCustomUrlSettingsKey()
{ {
// once the import is finished, we call next(); skip validation return "spoilersurl";
if (wizard()->hasTokensData()) {
return true;
}
QUrl url = QUrl::fromUserInput(urlLineEdit->text());
if (!url.isValid()) {
QMessageBox::critical(this, tr("Error"), tr("The provided URL is not valid."));
return false;
}
progressLabel->setText(tr("Downloading (0MB)"));
// show an infinite progressbar
progressBar->setMaximum(0);
progressBar->setMinimum(0);
progressBar->setValue(0);
progressLabel->show();
progressBar->show();
wizard()->disableButtons();
setEnabled(false);
downloadTokensFile(url);
return false;
} }
void LoadTokensPage::downloadTokensFile(QUrl url) QString LoadSpoilersPage::getDefaultSavePath()
{ {
if (!nam) { return settingsCache->getTokenDatabasePath();
nam = new QNetworkAccessManager(this);
}
QNetworkReply *reply = nam->get(QNetworkRequest(url));
connect(reply, SIGNAL(finished()), this, SLOT(actDownloadFinishedTokensFile()));
connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(actDownloadProgressTokensFile(qint64, qint64)));
} }
void LoadTokensPage::actDownloadProgressTokensFile(qint64 received, qint64 total) QString LoadSpoilersPage::getWindowTitle()
{ {
if (total > 0) { return tr("Save spoiler database");
progressBar->setMaximum(static_cast<int>(total));
progressBar->setValue(static_cast<int>(received));
}
progressLabel->setText(tr("Downloading (%1MB)").arg((int)received / (1024 * 1024)));
} }
void LoadTokensPage::actDownloadFinishedTokensFile() QString LoadSpoilersPage::getFileType()
{ {
// check for a reply return tr("XML; spoiler database (*.xml)");
auto *reply = dynamic_cast<QNetworkReply *>(sender());
QNetworkReply::NetworkError errorCode = reply->error();
if (errorCode != QNetworkReply::NoError) {
QMessageBox::critical(this, tr("Error"), tr("Network error: %1.").arg(reply->errorString()));
wizard()->enableButtons();
setEnabled(true);
reply->deleteLater();
return;
}
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (statusCode == 301 || statusCode == 302) {
QUrl redirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
qDebug() << "following redirect url:" << redirectUrl.toString();
downloadTokensFile(redirectUrl);
reply->deleteLater();
return;
}
progressLabel->hide();
progressBar->hide();
// save tokens.xml url, but only if the user customized it and download was successfull
if (urlLineEdit->text() != QString(TOKENS_URL)) {
wizard()->settings->setValue("tokensurl", urlLineEdit->text());
} else {
wizard()->settings->remove("tokensurl");
}
wizard()->setTokensData(reply->readAll());
reply->deleteLater();
wizard()->enableButtons();
setEnabled(true);
progressLabel->hide();
progressBar->hide();
wizard()->next();
} }
SaveSpoilersPage::SaveSpoilersPage(QWidget *parent) : OracleWizardPage(parent) void LoadSpoilersPage::retranslateUi()
{ {
defaultPathCheckBox = new QCheckBox(this); setTitle(tr("Spoilers import"));
defaultPathCheckBox->setChecked(true); setSubTitle(tr("Please specify a compatible source for spoiler data."));
auto *layout = new QGridLayout(this); urlLabel->setText(tr("Download URL:"));
layout->addWidget(defaultPathCheckBox, 0, 0); urlButton->setText(tr("Restore default URL"));
pathLabel->setText(tr("The spoiler database will be saved at the following location:") + "<br>" +
setLayout(layout); settingsCache->getSpoilerCardDatabasePath());
defaultPathCheckBox->setText(tr("Save to a custom path (not recommended)"));
} }
void SaveSpoilersPage::retranslateUi()
{
setTitle(tr("Spoilers imported"));
setSubTitle(tr("The spoilers file has been imported. "
"Press \"Save\" to save the imported spoilers to the Cockatrice card database."));
defaultPathCheckBox->setText(tr("Save to the default path (recommended)"));
}
bool SaveSpoilersPage::validatePage()
{
bool ok = false;
QString defaultPath = settingsCache->getSpoilerCardDatabasePath();
QString windowName = tr("Save spoiler database");
QString fileType = tr("XML; card database (*.xml)");
do {
QString fileName;
if (defaultPathCheckBox->isChecked()) {
fileName = defaultPath;
} else {
fileName = QFileDialog::getSaveFileName(this, windowName, defaultPath, fileType);
}
if (fileName.isEmpty()) {
return false;
}
QFileInfo fi(fileName);
QDir fileDir(fi.path());
if (!fileDir.exists() && !fileDir.mkpath(fileDir.absolutePath())) {
return false;
}
if (wizard()->saveTokensToFile(fileName)) {
ok = true;
} else {
QMessageBox::critical(this, tr("Error"), tr("The file could not be saved to %1").arg(fileName));
;
if (defaultPathCheckBox->isChecked()) {
defaultPathCheckBox->setChecked(false);
}
}
} while (!ok);
return true;
}
SaveTokensPage::SaveTokensPage(QWidget *parent) : OracleWizardPage(parent)
{
defaultPathCheckBox = new QCheckBox(this);
defaultPathCheckBox->setChecked(true);
auto *layout = new QGridLayout(this);
layout->addWidget(defaultPathCheckBox, 0, 0);
setLayout(layout);
}
void SaveTokensPage::retranslateUi()
{
setTitle(tr("Tokens imported"));
setSubTitle(tr("The tokens has been imported. "
"Press \"Save\" to save the imported tokens to the Cockatrice tokens database."));
defaultPathCheckBox->setText(tr("Save to the default path (recommended)"));
}
bool SaveTokensPage::validatePage()
{
bool ok = false;
QString defaultPath = settingsCache->getTokenDatabasePath();
QString windowName = tr("Save token database");
QString fileType = tr("XML; token database (*.xml)");
do {
QString fileName;
if (defaultPathCheckBox->isChecked()) {
fileName = defaultPath;
} else {
fileName = QFileDialog::getSaveFileName(this, windowName, defaultPath, fileType);
}
if (fileName.isEmpty()) {
return false;
}
QFileInfo fi(fileName);
QDir fileDir(fi.path());
if (!fileDir.exists() && !fileDir.mkpath(fileDir.absolutePath())) {
return false;
}
if (wizard()->saveTokensToFile(fileName)) {
ok = true;
QMessageBox::information(this, tr("Success"),
tr("The token database has been saved successfully to\n%1").arg(fileName));
} else {
QMessageBox::critical(this, tr("Error"), tr("The file could not be saved to %1").arg(fileName));
;
if (defaultPathCheckBox->isChecked()) {
defaultPathCheckBox->setChecked(false);
}
}
} while (!ok);
return true;
}

View file

@ -19,6 +19,8 @@ class QVBoxLayout;
class OracleImporter; class OracleImporter;
class QSettings; class QSettings;
#include "pagetemplates.h"
class OracleWizard : public QWizard class OracleWizard : public QWizard
{ {
Q_OBJECT Q_OBJECT
@ -41,6 +43,7 @@ public:
public: public:
OracleImporter *importer; OracleImporter *importer;
QSettings *settings; QSettings *settings;
QNetworkAccessManager *nam;
private slots: private slots:
void updateLanguage(); void updateLanguage();
@ -52,20 +55,6 @@ protected:
void changeEvent(QEvent *event) override; void changeEvent(QEvent *event) override;
}; };
class OracleWizardPage : public QWizardPage
{
Q_OBJECT
public:
explicit OracleWizardPage(QWidget *parent = nullptr) : QWizardPage(parent){};
virtual void retranslateUi() = 0;
protected:
inline OracleWizard *wizard()
{
return (OracleWizard *)QWizardPage::wizard();
};
};
class IntroPage : public OracleWizardPage class IntroPage : public OracleWizardPage
{ {
Q_OBJECT Q_OBJECT
@ -85,6 +74,16 @@ private slots:
void languageBoxChanged(int index); void languageBoxChanged(int index);
}; };
class OutroPage : public OracleWizardPage
{
Q_OBJECT
public:
explicit OutroPage(QWidget * = nullptr)
{
}
void retranslateUi() override;
};
class LoadSetsPage : public OracleWizardPage class LoadSetsPage : public OracleWizardPage
{ {
Q_OBJECT Q_OBJECT
@ -108,7 +107,6 @@ private:
QLabel *progressLabel; QLabel *progressLabel;
QProgressBar *progressBar; QProgressBar *progressBar;
QNetworkAccessManager *nam;
QFutureWatcher<bool> watcher; QFutureWatcher<bool> watcher;
QFuture<bool> future; QFuture<bool> future;
@ -131,6 +129,8 @@ public:
private: private:
QTextEdit *messageLog; QTextEdit *messageLog;
QCheckBox *defaultPathCheckBox; QCheckBox *defaultPathCheckBox;
QLabel *pathLabel;
QLabel *saveLabel;
protected: protected:
void initializePage() override; void initializePage() override;
@ -141,84 +141,34 @@ private slots:
void updateTotalProgress(int cardsImported, int setIndex, const QString &setName); void updateTotalProgress(int cardsImported, int setIndex, const QString &setName);
}; };
class LoadSpoilersPage : public OracleWizardPage class LoadSpoilersPage : public SimpleDownloadFilePage
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit LoadSpoilersPage(QWidget *parent = nullptr); explicit LoadSpoilersPage(QWidget * = nullptr){};
void retranslateUi() override; void retranslateUi() override;
private:
QLabel *urlLabel;
QLineEdit *urlLineEdit;
QPushButton *urlButton;
QLabel *progressLabel;
QProgressBar *progressBar;
QNetworkAccessManager *nam;
private slots:
void actRestoreDefaultUrl();
void actDownloadProgressSpoilersFile(qint64 received, qint64 total);
void actDownloadFinishedSpoilersFile();
protected: protected:
void initializePage() override; QString getDefaultUrl() override;
bool validatePage() override; QString getCustomUrlSettingsKey() override;
void downloadSpoilersFile(QUrl url); QString getDefaultSavePath() override;
QString getWindowTitle() override;
QString getFileType() override;
}; };
class SaveSpoilersPage : public OracleWizardPage class LoadTokensPage : public SimpleDownloadFilePage
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit SaveSpoilersPage(QWidget *parent = nullptr); explicit LoadTokensPage(QWidget * = nullptr){};
void retranslateUi() override;
private:
QCheckBox *defaultPathCheckBox;
protected:
bool validatePage() override;
};
class LoadTokensPage : public OracleWizardPage
{
Q_OBJECT
public:
explicit LoadTokensPage(QWidget *parent = nullptr);
void retranslateUi() override; void retranslateUi() override;
protected: protected:
void initializePage() override; QString getDefaultUrl() override;
bool validatePage() override; QString getCustomUrlSettingsKey() override;
void downloadTokensFile(QUrl url); QString getDefaultSavePath() override;
QString getWindowTitle() override;
private: QString getFileType() override;
QLabel *urlLabel;
QLineEdit *urlLineEdit;
QPushButton *urlButton;
QLabel *progressLabel;
QProgressBar *progressBar;
QNetworkAccessManager *nam;
private slots:
void actRestoreDefaultUrl();
void actDownloadProgressTokensFile(qint64 received, qint64 total);
void actDownloadFinishedTokensFile();
};
class SaveTokensPage : public OracleWizardPage
{
Q_OBJECT
public:
explicit SaveTokensPage(QWidget *parent = nullptr);
void retranslateUi() override;
private:
QCheckBox *defaultPathCheckBox;
protected:
bool validatePage() override;
}; };
#endif #endif

View file

@ -0,0 +1,196 @@
#include <QCheckBox>
#include <QDir>
#include <QFileDialog>
#include <QGridLayout>
#include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QNetworkReply>
#include <QProgressBar>
#include <QPushButton>
#include <QtGui>
#include "oraclewizard.h"
#include "pagetemplates.h"
SimpleDownloadFilePage::SimpleDownloadFilePage(QWidget *parent) : OracleWizardPage(parent)
{
urlLabel = new QLabel(this);
urlLineEdit = new QLineEdit(this);
progressLabel = new QLabel(this);
progressBar = new QProgressBar(this);
urlButton = new QPushButton(this);
connect(urlButton, SIGNAL(clicked()), this, SLOT(actRestoreDefaultUrl()));
defaultPathCheckBox = new QCheckBox(this);
pathLabel = new QLabel(this);
pathLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
auto *layout = new QGridLayout(this);
layout->addWidget(urlLabel, 0, 0);
layout->addWidget(urlLineEdit, 0, 1);
layout->addWidget(urlButton, 1, 1, Qt::AlignRight);
layout->addWidget(pathLabel, 2, 0, 1, 2);
layout->addWidget(defaultPathCheckBox, 3, 0, 1, 2);
layout->addWidget(progressLabel, 4, 0);
layout->addWidget(progressBar, 4, 1);
setLayout(layout);
}
void SimpleDownloadFilePage::initializePage()
{
// get custom url from settings if any; otherwise use default url
urlLineEdit->setText(wizard()->settings->value(getCustomUrlSettingsKey(), getDefaultUrl()).toString());
progressLabel->hide();
progressBar->hide();
}
void SimpleDownloadFilePage::actRestoreDefaultUrl()
{
urlLineEdit->setText(getDefaultUrl());
}
bool SimpleDownloadFilePage::validatePage()
{
// if data has already been downloaded, pass directly to the "save" step
if (!downloadData.isEmpty()) {
if (saveToFile()) {
return true;
} else {
wizard()->enableButtons();
return false;
}
}
QUrl url = QUrl::fromUserInput(urlLineEdit->text());
if (!url.isValid()) {
QMessageBox::critical(this, tr("Error"), tr("The provided URL is not valid."));
return false;
}
progressLabel->setText(tr("Downloading (0MB)"));
// show an infinite progressbar
progressBar->setMaximum(0);
progressBar->setMinimum(0);
progressBar->setValue(0);
progressLabel->show();
progressBar->show();
wizard()->disableButtons();
downloadFile(url);
return false;
}
void SimpleDownloadFilePage::downloadFile(QUrl url)
{
QNetworkReply *reply = wizard()->nam->get(QNetworkRequest(url));
connect(reply, SIGNAL(finished()), this, SLOT(actDownloadFinished()));
connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(actDownloadProgress(qint64, qint64)));
}
void SimpleDownloadFilePage::actDownloadProgress(qint64 received, qint64 total)
{
if (total > 0) {
progressBar->setMaximum(static_cast<int>(total));
progressBar->setValue(static_cast<int>(received));
}
progressLabel->setText(tr("Downloading (%1MB)").arg((int)received / (1024 * 1024)));
}
void SimpleDownloadFilePage::actDownloadFinished()
{
// check for a reply
auto *reply = dynamic_cast<QNetworkReply *>(sender());
QNetworkReply::NetworkError errorCode = reply->error();
if (errorCode != QNetworkReply::NoError) {
QMessageBox::critical(this, tr("Error"), tr("Network error: %1.").arg(reply->errorString()));
wizard()->enableButtons();
reply->deleteLater();
return;
}
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (statusCode == 301 || statusCode == 302) {
QUrl redirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
qDebug() << "following redirect url:" << redirectUrl.toString();
downloadFile(redirectUrl);
reply->deleteLater();
return;
}
// save downlaoded file url, but only if the user customized it and download was successfull
if (urlLineEdit->text() != getDefaultUrl()) {
wizard()->settings->setValue(getCustomUrlSettingsKey(), urlLineEdit->text());
} else {
wizard()->settings->remove(getCustomUrlSettingsKey());
}
downloadData = reply->readAll();
reply->deleteLater();
wizard()->enableButtons();
progressLabel->hide();
progressBar->hide();
wizard()->next();
}
bool SimpleDownloadFilePage::saveToFile()
{
bool ok = false;
QString defaultPath = getDefaultSavePath();
QString windowName = getWindowTitle();
QString fileType = getFileType();
do {
QString fileName;
if (defaultPathCheckBox->isChecked()) {
fileName = QFileDialog::getSaveFileName(this, windowName, defaultPath, fileType);
} else {
fileName = defaultPath;
}
if (fileName.isEmpty()) {
return false;
}
QFileInfo fi(fileName);
QDir fileDir(fi.path());
if (!fileDir.exists() && !fileDir.mkpath(fileDir.absolutePath())) {
return false;
}
if (internalSaveToFile(fileName)) {
ok = true;
} else {
QMessageBox::critical(this, tr("Error"), tr("The file could not be saved to %1").arg(fileName));
}
} while (!ok);
// clean saved downloadData
downloadData = QByteArray();
return true;
}
bool SimpleDownloadFilePage::internalSaveToFile(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
qDebug() << "File open (w) failed for" << fileName;
return false;
}
if (file.write(downloadData) == -1) {
qDebug() << "File write (w) failed for" << fileName;
return false;
}
file.close();
return true;
}

View file

@ -0,0 +1,62 @@
#ifndef PAGETEMPLATES_H
#define PAGETEMPLATES_H
#include <QWizardPage>
class OracleWizard;
class QCheckBox;
class QLabel;
class QLineEdit;
class QProgressBar;
class OracleWizardPage : public QWizardPage
{
Q_OBJECT
public:
explicit OracleWizardPage(QWidget *parent = nullptr) : QWizardPage(parent){};
virtual void retranslateUi() = 0;
protected:
inline OracleWizard *wizard()
{
return (OracleWizard *)QWizardPage::wizard();
};
};
class SimpleDownloadFilePage : public OracleWizardPage
{
Q_OBJECT
public:
explicit SimpleDownloadFilePage(QWidget *parent = nullptr);
protected:
void initializePage() override;
bool validatePage() override;
void downloadFile(QUrl url);
virtual QString getDefaultUrl() = 0;
virtual QString getCustomUrlSettingsKey() = 0;
virtual QString getDefaultSavePath() = 0;
virtual QString getWindowTitle() = 0;
virtual QString getFileType() = 0;
bool saveToFile();
bool internalSaveToFile(const QString &fileName);
protected:
QByteArray downloadData;
QLabel *urlLabel;
QLabel *pathLabel;
QLineEdit *urlLineEdit;
QPushButton *urlButton;
QLabel *progressLabel;
QProgressBar *progressBar;
QCheckBox *defaultPathCheckBox;
signals:
void parsedDataReady();
private slots:
void actRestoreDefaultUrl();
void actDownloadProgress(qint64 received, qint64 total);
void actDownloadFinished();
};
#endif // PAGETEMPLATES_H