Add the option to background the oracle wizard, add an option to automatically launch oracle wizard in background every X days since last launch.

This commit is contained in:
Lukas Brübach 2025-06-24 21:23:27 +02:00
parent 208f8349a6
commit deb60b1bc2
11 changed files with 190 additions and 20 deletions

View file

@ -691,6 +691,7 @@ void MainWindow::retranslateUi()
aTips->setText(tr("&Tip of the Day"));
aUpdate->setText(tr("Check for Client Updates"));
aCheckCardUpdates->setText(tr("Check for Card Updates..."));
aCheckCardUpdatesBackground->setText(tr("Check for Card Updates (Automatic)"));
aStatusBar->setText(tr("Show Status Bar"));
aViewLog->setText(tr("View &Debug Log"));
aOpenSettingsFolder->setText(tr("Open Settings Folder"));
@ -744,6 +745,8 @@ void MainWindow::createActions()
connect(aUpdate, &QAction::triggered, this, &MainWindow::actUpdate);
aCheckCardUpdates = new QAction(this);
connect(aCheckCardUpdates, &QAction::triggered, this, &MainWindow::actCheckCardUpdates);
aCheckCardUpdatesBackground = new QAction(this);
connect(aCheckCardUpdatesBackground, &QAction::triggered, this, &MainWindow::actCheckCardUpdatesBackground);
aStatusBar = new QAction(this);
aStatusBar->setCheckable(true);
aStatusBar->setChecked(SettingsCache::instance().getShowStatusBar());
@ -825,6 +828,7 @@ void MainWindow::createMenus()
helpMenu->addSeparator();
helpMenu->addAction(aUpdate);
helpMenu->addAction(aCheckCardUpdates);
helpMenu->addAction(aCheckCardUpdatesBackground);
helpMenu->addSeparator();
helpMenu->addAction(aStatusBar);
helpMenu->addAction(aViewLog);
@ -943,6 +947,11 @@ void MainWindow::startupConfigCheck()
} else {
// previous config from this version found
qCInfo(WindowMainStartupVersionLog) << "Startup: found config with current version";
if (SettingsCache::instance().getCardUpdateCheckRequired()) {
actCheckCardUpdatesBackground();
}
const auto reloadOk1 = QtConcurrent::run([] { CardDatabaseManager::getInstance()->loadCardDatabases(); });
// Run the tips dialog only on subsequent startups.
@ -1151,6 +1160,16 @@ void MainWindow::cardDatabaseAllNewSetsEnabled()
/* CARD UPDATER */
void MainWindow::actCheckCardUpdates()
{
createCardUpdateProcess();
}
void MainWindow::actCheckCardUpdatesBackground()
{
createCardUpdateProcess(true);
}
void MainWindow::createCardUpdateProcess(bool background)
{
if (cardUpdateProcess) {
QMessageBox::information(this, tr("Information"), tr("A card database update is already running."));
@ -1213,13 +1232,19 @@ void MainWindow::actCheckCardUpdates()
return;
}
cardUpdateProcess->start(updaterCmd, QStringList());
if (!background) {
cardUpdateProcess->start(updaterCmd, QStringList());
} else {
cardUpdateProcess->start(updaterCmd, QStringList("-b"));
statusBar()->showMessage(tr("Card database update running."));
}
}
void MainWindow::exitCardDatabaseUpdate()
{
cardUpdateProcess->deleteLater();
cardUpdateProcess = nullptr;
statusBar()->clearMessage();
const auto reloadOk1 = QtConcurrent::run([] { CardDatabaseManager::getInstance()->loadCardDatabases(); });
}
@ -1256,8 +1281,11 @@ void MainWindow::cardUpdateError(QProcess::ProcessError err)
QMessageBox::warning(this, tr("Error"), tr("The card database updater exited with an error:\n%1").arg(error));
}
void MainWindow::cardUpdateFinished(int, QProcess::ExitStatus)
void MainWindow::cardUpdateFinished(int, QProcess::ExitStatus exitStatus)
{
if (exitStatus == QProcess::NormalExit) {
SettingsCache::instance().setLastCardUpdateCheck(QDateTime::currentDateTime().date());
}
exitCardDatabaseUpdate();
}

View file

@ -56,6 +56,7 @@ class MainWindow : public QMainWindow
Q_OBJECT
public slots:
void actCheckCardUpdates();
void actCheckCardUpdatesBackground();
void actCheckServerUpdates();
void actCheckClientUpdates();
private slots:
@ -131,6 +132,7 @@ private:
{
return "oracle";
};
void createCardUpdateProcess(bool background = false);
void exitCardDatabaseUpdate();
void startLocalGame(int numberPlayers);
@ -141,7 +143,8 @@ private:
QAction *aConnect, *aDisconnect, *aRegister, *aForgotPassword, *aSinglePlayer, *aWatchReplay, *aFullScreen;
QAction *aManageSets, *aEditTokens, *aOpenCustomFolder, *aOpenCustomsetsFolder, *aAddCustomSet,
*aReloadCardDatabase;
QAction *aTips, *aUpdate, *aCheckCardUpdates, *aStatusBar, *aViewLog, *aOpenSettingsFolder;
QAction *aTips, *aUpdate, *aCheckCardUpdates, *aCheckCardUpdatesBackground, *aStatusBar, *aViewLog,
*aOpenSettingsFolder;
TabSupervisor *tabSupervisor;
WndSets *wndSets;

View file

@ -71,6 +71,10 @@ GeneralSettingsPage::GeneralSettingsPage()
// updates
SettingsCache &settings = SettingsCache::instance();
startupUpdateCheckCheckBox.setChecked(settings.getCheckUpdatesOnStartup());
startupCardUpdateCheckCheckBox.setChecked(settings.getCheckCardUpdatesOnStartup());
cardUpdateCheckIntervalSpinBox.setMinimum(1);
cardUpdateCheckIntervalSpinBox.setMaximum(30);
cardUpdateCheckIntervalSpinBox.setValue(settings.getCardUpdateCheckInterval());
updateNotificationCheckBox.setChecked(settings.getNotifyAboutUpdates());
newVersionOracleCheckBox.setChecked(settings.getNotifyAboutNewVersion());
@ -83,6 +87,10 @@ GeneralSettingsPage::GeneralSettingsPage()
&GeneralSettingsPage::languageBoxChanged);
connect(&startupUpdateCheckCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings,
&SettingsCache::setCheckUpdatesOnStartup);
connect(&startupCardUpdateCheckCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings,
&SettingsCache::setCheckCardUpdatesOnStartup);
connect(&cardUpdateCheckIntervalSpinBox, &QSpinBox::valueChanged, &settings,
&SettingsCache::setCardUpdateCheckInterval);
connect(&updateNotificationCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, &SettingsCache::setNotifyAboutUpdate);
connect(&newVersionOracleCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings,
&SettingsCache::setNotifyAboutNewVersion);
@ -95,9 +103,13 @@ GeneralSettingsPage::GeneralSettingsPage()
personalGrid->addWidget(&updateReleaseChannelLabel, 2, 0);
personalGrid->addWidget(&updateReleaseChannelBox, 2, 1);
personalGrid->addWidget(&startupUpdateCheckCheckBox, 4, 0, 1, 2);
personalGrid->addWidget(&updateNotificationCheckBox, 5, 0, 1, 2);
personalGrid->addWidget(&newVersionOracleCheckBox, 6, 0, 1, 2);
personalGrid->addWidget(&showTipsOnStartup, 7, 0, 1, 2);
personalGrid->addWidget(&startupCardUpdateCheckCheckBox, 5, 0, 1, 2);
personalGrid->addWidget(&cardUpdateCheckIntervalLabel, 6, 0);
personalGrid->addWidget(&cardUpdateCheckIntervalSpinBox, 6, 1);
personalGrid->addWidget(&lastCardUpdateCheckDateLabel, 7, 1);
personalGrid->addWidget(&updateNotificationCheckBox, 8, 0, 1, 2);
personalGrid->addWidget(&newVersionOracleCheckBox, 9, 0, 1, 2);
personalGrid->addWidget(&showTipsOnStartup, 10, 0, 1, 2);
personalGroupBox = new QGroupBox;
personalGroupBox->setLayout(personalGrid);
@ -341,6 +353,9 @@ void GeneralSettingsPage::retranslateUi()
tokenDatabasePathLabel.setText(tr("Token database:"));
updateReleaseChannelLabel.setText(tr("Update channel"));
startupUpdateCheckCheckBox.setText(tr("Check for client updates on startup"));
startupCardUpdateCheckCheckBox.setText(tr("Automatically update card database in the background on startup."));
cardUpdateCheckIntervalLabel.setText(tr("Check for card database updates every"));
cardUpdateCheckIntervalSpinBox.setSuffix(tr(" days"));
updateNotificationCheckBox.setText(tr("Notify if a feature supported by the server is missing in my client"));
newVersionOracleCheckBox.setText(tr("Automatically run Oracle when running a new version of Cockatrice"));
showTipsOnStartup.setText(tr("Show tips on startup"));
@ -348,6 +363,12 @@ void GeneralSettingsPage::retranslateUi()
const auto &settings = SettingsCache::instance();
QDate lastCheckDate = settings.getLastCardUpdateCheck();
int daysAgo = lastCheckDate.daysTo(QDate::currentDate());
lastCardUpdateCheckDateLabel.setText(
tr("Last update check on %1 (%2 days ago)").arg(lastCheckDate.toString()).arg(daysAgo));
// We can't change the strings after they're put into the QComboBox, so this is our workaround
int oldIndex = updateReleaseChannelBox.currentIndex();
updateReleaseChannelBox.clear();

View file

@ -71,6 +71,10 @@ private:
QGroupBox *pathsGroupBox;
QComboBox languageBox;
QCheckBox startupUpdateCheckCheckBox;
QCheckBox startupCardUpdateCheckCheckBox;
QLabel cardUpdateCheckIntervalLabel;
QSpinBox cardUpdateCheckIntervalSpinBox;
QLabel lastCardUpdateCheckDateLabel;
QCheckBox updateNotificationCheckBox;
QCheckBox newVersionOracleCheckBox;
QComboBox updateReleaseChannelBox;

View file

@ -194,6 +194,9 @@ SettingsCache::SettingsCache()
mbDownloadSpoilers = settings->value("personal/downloadspoilers", false).toBool();
checkUpdatesOnStartup = settings->value("personal/startupUpdateCheck", true).toBool();
checkCardUpdatesOnStartup = settings->value("personal/startupCardUpdateCheck", true).toBool();
cardUpdateCheckInterval = settings->value("personal/cardUpdateCheckInterval", 7).toInt();
lastCardUpdateCheck = settings->value("personal/lastCardUpdateCheck", QDateTime::currentDateTime().date()).toDate();
notifyAboutUpdates = settings->value("personal/updatenotification", true).toBool();
notifyAboutNewVersion = settings->value("personal/newversionnotification", true).toBool();
updateReleaseChannel = settings->value("personal/updatereleasechannel", 0).toInt();
@ -1363,6 +1366,24 @@ void SettingsCache::setCheckUpdatesOnStartup(QT_STATE_CHANGED_T value)
settings->setValue("personal/startupUpdateCheck", checkUpdatesOnStartup);
}
void SettingsCache::setCheckCardUpdatesOnStartup(QT_STATE_CHANGED_T value)
{
checkCardUpdatesOnStartup = static_cast<bool>(value);
settings->setValue("personal/startupCardUpdateCheck", checkCardUpdatesOnStartup);
}
void SettingsCache::setCardUpdateCheckInterval(int value)
{
cardUpdateCheckInterval = value;
settings->setValue("personal/cardUpdateCheckInterval", cardUpdateCheckInterval);
}
void SettingsCache::setLastCardUpdateCheck(QDate value)
{
lastCardUpdateCheck = value;
settings->setValue("personal/lastCardUpdateCheck", lastCardUpdateCheck);
}
void SettingsCache::setRememberGameSettings(const bool _rememberGameSettings)
{
rememberGameSettings = _rememberGameSettings;

View file

@ -13,6 +13,7 @@
#include "servers_settings.h"
#include "shortcuts_settings.h"
#include <QDate>
#include <QLoggingCategory>
#include <QObject>
#include <QSize>
@ -198,6 +199,9 @@ private:
bool tabVisualDeckStorageOpen, tabServerOpen, tabAccountOpen, tabDeckStorageOpen, tabReplaysOpen, tabAdminOpen,
tabLogOpen;
bool checkUpdatesOnStartup;
bool checkCardUpdatesOnStartup;
int cardUpdateCheckInterval;
QDate lastCardUpdateCheck;
bool notifyAboutUpdates;
bool notifyAboutNewVersion;
bool showTipsOnStartup;
@ -438,6 +442,23 @@ public:
{
return checkUpdatesOnStartup;
}
bool getCheckCardUpdatesOnStartup() const
{
return checkCardUpdatesOnStartup;
}
int getCardUpdateCheckInterval() const
{
return cardUpdateCheckInterval;
}
QDate getLastCardUpdateCheck() const
{
return lastCardUpdateCheck;
}
bool getCardUpdateCheckRequired() const
{
return getLastCardUpdateCheck().daysTo(QDateTime::currentDateTime().date()) >= getCardUpdateCheckInterval() &&
getLastCardUpdateCheck() != QDateTime::currentDateTime().date();
}
bool getNotifyAboutUpdates() const
{
return notifyAboutUpdates;
@ -1007,6 +1028,9 @@ public slots:
void setDefaultStartingLifeTotal(const int _defaultStartingLifeTotal);
void setRememberGameSettings(const bool _rememberGameSettings);
void setCheckUpdatesOnStartup(QT_STATE_CHANGED_T value);
void setCheckCardUpdatesOnStartup(QT_STATE_CHANGED_T value);
void setCardUpdateCheckInterval(int value);
void setLastCardUpdateCheck(QDate value);
void setNotifyAboutUpdate(QT_STATE_CHANGED_T _notifyaboutupdate);
void setNotifyAboutNewVersion(QT_STATE_CHANGED_T _notifyaboutnewversion);
void setUpdateReleaseChannelIndex(int value);

View file

@ -8,6 +8,7 @@
#include <QCommandLineParser>
#include <QIcon>
#include <QLibraryInfo>
#include <QTimer>
#include <QTranslator>
QTranslator *translator, *qtTranslator;
@ -16,6 +17,7 @@ ThemeManager *themeManager;
const QString translationPrefix = "oracle";
QString translationPath;
bool isSpoilersOnly;
bool isBackgrounded;
void installNewTranslator()
{
@ -57,10 +59,13 @@ int main(int argc, char *argv[])
// If the program is opened with the -s flag, it will only do spoilers. Otherwise it will do MTGJSON/Tokens
QCommandLineParser parser;
QCommandLineOption showProgressOption("s", QCoreApplication::translate("main", "Only run in spoiler mode"));
parser.addOption(showProgressOption);
QCommandLineOption spoilersOnlyOption("s", QCoreApplication::translate("main", "Only run in spoiler mode"));
QCommandLineOption backgroundOption("b", QCoreApplication::translate("main", "Run in no-confirm background mode"));
parser.addOption(spoilersOnlyOption);
parser.addOption(backgroundOption);
parser.process(app);
isSpoilersOnly = parser.isSet(showProgressOption);
isSpoilersOnly = parser.isSet(spoilersOnlyOption);
isBackgrounded = parser.isSet(backgroundOption);
#ifdef Q_OS_MAC
translationPath = qApp->applicationDirPath() + "/../Resources/translations";
@ -85,5 +90,9 @@ int main(int argc, char *argv[])
wizard.show();
if (isBackgrounded) {
QTimer::singleShot(0, &wizard, [&wizard]() { wizard.runInBackground(); });
}
return app.exec();
}

View file

@ -64,15 +64,23 @@ OracleWizard::OracleWizard(QWidget *parent) : QWizard(parent)
nam = new QNetworkAccessManager(this);
QList<OracleWizardPage *> pages;
if (!isSpoilersOnly) {
addPage(new IntroPage);
addPage(new LoadSetsPage);
addPage(new SaveSetsPage);
addPage(new LoadTokensPage);
addPage(new OutroPage);
pages << new IntroPage << new LoadSetsPage << new SaveSetsPage << new LoadTokensPage << new OutroPage;
} else {
addPage(new LoadSpoilersPage);
addPage(new OutroPage);
pages << new LoadSpoilersPage << new OutroPage;
}
for (OracleWizardPage *page : pages) {
addPage(page);
// Connect background auto-advance
connect(page, &OracleWizardPage::readyToContinue, this, [this]() {
if (backgroundMode) {
next();
}
});
}
retranslateUi();
@ -169,6 +177,13 @@ IntroPage::IntroPage(QWidget *parent) : OracleWizardPage(parent)
setLayout(layout);
}
void IntroPage::initializePage()
{
if (wizard()->backgroundMode) {
emit readyToContinue();
}
}
QStringList IntroPage::findQmFiles()
{
QDir dir(translationPath);
@ -212,6 +227,14 @@ void OutroPage::retranslateUi()
tr("If the card databases don't reload automatically, restart the Cockatrice client."));
}
void OutroPage::initializePage()
{
if (wizard()->backgroundMode) {
wizard()->accept();
exit(0);
}
}
LoadSetsPage::LoadSetsPage(QWidget *parent) : OracleWizardPage(parent)
{
urlRadioButton = new QRadioButton(this);
@ -252,6 +275,12 @@ void LoadSetsPage::initializePage()
progressLabel->hide();
progressBar->hide();
if (wizard()->backgroundMode) {
if (isEnabled()) {
validatePage();
}
}
}
void LoadSetsPage::retranslateUi()
@ -616,6 +645,10 @@ void SaveSetsPage::initializePage()
if (!wizard()->importer->startImport()) {
QMessageBox::critical(this, tr("Error"), tr("No set has been imported."));
}
if (wizard()->backgroundMode) {
emit readyToContinue();
}
}
void SaveSetsPage::retranslateUi()
@ -691,6 +724,15 @@ bool SaveSetsPage::validatePage()
return true;
}
void LoadTokensPage::initializePage()
{
SimpleDownloadFilePage::initializePage();
if (wizard()->backgroundMode) {
emit readyToContinue();
}
}
QString LoadTokensPage::getDefaultUrl()
{
return TOKENS_URL;

View file

@ -3,6 +3,7 @@
#include <QFuture>
#include <QFutureWatcher>
#include <QTimer>
#include <QWizard>
#include <utility>
@ -56,12 +57,20 @@ public:
}
bool saveTokensToFile(const QString &fileName);
void runInBackground()
{
backgroundMode = true;
hide();
currentPage()->initializePage();
}
public:
OracleImporter *importer;
QSettings *settings;
QNetworkAccessManager *nam;
bool downloadedPlainXml = false;
QByteArray xmlData;
bool backgroundMode = false;
private slots:
void updateLanguage();
@ -92,6 +101,9 @@ private:
private slots:
void languageBoxChanged(int index);
protected slots:
void initializePage() override;
};
class OutroPage : public OracleWizardPage
@ -102,6 +114,8 @@ public:
{
}
void retranslateUi() override;
protected:
void initializePage() override;
};
class LoadSetsPage : public OracleWizardPage
@ -167,7 +181,7 @@ class LoadSpoilersPage : public SimpleDownloadFilePage
{
Q_OBJECT
public:
explicit LoadSpoilersPage(QWidget * = nullptr){};
explicit LoadSpoilersPage(QWidget * = nullptr) {};
void retranslateUi() override;
protected:
@ -182,7 +196,7 @@ class LoadTokensPage : public SimpleDownloadFilePage
{
Q_OBJECT
public:
explicit LoadTokensPage(QWidget * = nullptr){};
explicit LoadTokensPage(QWidget * = nullptr) {};
void retranslateUi() override;
protected:
@ -191,6 +205,7 @@ protected:
QString getDefaultSavePath() override;
QString getWindowTitle() override;
QString getFileType() override;
void initializePage() override;
};
#endif

View file

@ -70,7 +70,7 @@ bool SimpleDownloadFilePage::validatePage()
QUrl url = QUrl::fromUserInput(urlLineEdit->text());
if (!url.isValid()) {
QMessageBox::critical(this, tr("Error"), tr("The provided URL is not valid."));
QMessageBox::critical(this, tr("Error"), tr("The provided URL is not valid: ") + url.toString());
return false;
}

View file

@ -13,9 +13,12 @@ class OracleWizardPage : public QWizardPage
{
Q_OBJECT
public:
explicit OracleWizardPage(QWidget *parent = nullptr) : QWizardPage(parent){};
explicit OracleWizardPage(QWidget *parent = nullptr) : QWizardPage(parent) {};
virtual void retranslateUi() = 0;
signals:
void readyToContinue();
protected:
inline OracleWizard *wizard()
{