From f3913949b2f1d68db378494bee6d4e02eb47413e Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Mon, 30 Jun 2025 04:21:52 +0200 Subject: [PATCH] Automatic Card Database Updates (#6004) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add the option to background the oracle wizard, add an option to automatically launch oracle wizard in background every X days since last launch. * Mocks and a typo. * Lint. * Lint? * qOverload the spinBox. * Change to a prompt instead. * An Label. * Update window_main.cpp --------- Co-authored-by: Lukas BrĂ¼bach Co-authored-by: Zach H --- cockatrice/CMakeLists.txt | 1 + cockatrice/src/client/ui/window_main.cpp | 61 ++++++++++++++++++- cockatrice/src/client/ui/window_main.h | 5 +- cockatrice/src/dialogs/dlg_settings.cpp | 56 ++++++++++++++++- cockatrice/src/dialogs/dlg_settings.h | 5 ++ .../src/dialogs/dlg_startup_card_check.cpp | 50 +++++++++++++++ .../src/dialogs/dlg_startup_card_check.h | 24 ++++++++ cockatrice/src/settings/cache_settings.cpp | 28 +++++++++ cockatrice/src/settings/cache_settings.h | 31 ++++++++++ dbconverter/src/mocks.cpp | 12 ++++ oracle/src/main.cpp | 15 ++++- oracle/src/oraclewizard.cpp | 56 ++++++++++++++--- oracle/src/oraclewizard.h | 16 +++++ oracle/src/pagetemplates.cpp | 2 +- oracle/src/pagetemplates.h | 3 + tests/carddatabase/mocks.cpp | 12 ++++ 16 files changed, 360 insertions(+), 17 deletions(-) create mode 100644 cockatrice/src/dialogs/dlg_startup_card_check.cpp create mode 100644 cockatrice/src/dialogs/dlg_startup_card_check.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 26cc72aca..612181bca 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -172,6 +172,7 @@ set(cockatrice_SOURCES src/dialogs/dlg_roll_dice.cpp src/dialogs/dlg_select_set_for_cards.cpp src/dialogs/dlg_settings.cpp + src/dialogs/dlg_startup_card_check.cpp src/dialogs/dlg_tip_of_the_day.cpp src/dialogs/dlg_update.cpp src/dialogs/dlg_view_log.cpp diff --git a/cockatrice/src/client/ui/window_main.cpp b/cockatrice/src/client/ui/window_main.cpp index 883d54dc1..e3b0066e9 100644 --- a/cockatrice/src/client/ui/window_main.cpp +++ b/cockatrice/src/client/ui/window_main.cpp @@ -27,6 +27,7 @@ #include "../../dialogs/dlg_manage_sets.h" #include "../../dialogs/dlg_register.h" #include "../../dialogs/dlg_settings.h" +#include "../../dialogs/dlg_startup_card_check.h" #include "../../dialogs/dlg_tip_of_the_day.h" #include "../../dialogs/dlg_update.h" #include "../../dialogs/dlg_view_log.h" @@ -52,6 +53,7 @@ #include #include +#include #include #include #include @@ -62,6 +64,7 @@ #include #include #include +#include #include #include #include @@ -691,6 +694,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 +748,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 +831,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 +950,37 @@ void MainWindow::startupConfigCheck() } else { // previous config from this version found qCInfo(WindowMainStartupVersionLog) << "Startup: found config with current version"; + + if (SettingsCache::instance().getCardUpdateCheckRequired()) { + if (SettingsCache::instance().getStartupCardUpdateCheckPromptForUpdate()) { + auto startupCardCheckDialog = new DlgStartupCardCheck(this); + + if (startupCardCheckDialog->exec() == QDialog::Accepted) { + switch (startupCardCheckDialog->group->checkedId()) { + case 0: // foreground + actCheckCardUpdates(); + break; + case 1: // background + actCheckCardUpdatesBackground(); + break; + case 2: // background + always + SettingsCache::instance().setStartupCardUpdateCheckPromptForUpdate(false); + SettingsCache::instance().setStartupCardUpdateCheckAlwaysUpdate(true); + actCheckCardUpdatesBackground(); + break; + case 3: // don't prompt again + don't run + SettingsCache::instance().setStartupCardUpdateCheckPromptForUpdate(false); + SettingsCache::instance().setStartupCardUpdateCheckAlwaysUpdate(false); + break; + default: + break; + } + } + } else if (SettingsCache::instance().getStartupCardUpdateCheckAlwaysUpdate()) { + actCheckCardUpdatesBackground(); + } + } + const auto reloadOk1 = QtConcurrent::run([] { CardDatabaseManager::getInstance()->loadCardDatabases(); }); // Run the tips dialog only on subsequent startups. @@ -1151,6 +1189,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 +1261,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 +1310,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(); } diff --git a/cockatrice/src/client/ui/window_main.h b/cockatrice/src/client/ui/window_main.h index a5bc1f20b..420aac214 100644 --- a/cockatrice/src/client/ui/window_main.h +++ b/cockatrice/src/client/ui/window_main.h @@ -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; diff --git a/cockatrice/src/dialogs/dlg_settings.cpp b/cockatrice/src/dialogs/dlg_settings.cpp index 0b0b86260..0de11aa48 100644 --- a/cockatrice/src/dialogs/dlg_settings.cpp +++ b/cockatrice/src/dialogs/dlg_settings.cpp @@ -52,6 +52,13 @@ #define WIKI_CUSTOM_SHORTCUTS "https://github.com/Cockatrice/Cockatrice/wiki/Custom-Keyboard-Shortcuts" #define WIKI_TRANSLATION_FAQ "https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ" +enum startupCardUpdateCheckBehaviorIndex +{ + startupCardUpdateCheckBehaviorIndexNone, + startupCardUpdateCheckBehaviorIndexPrompt, + startupCardUpdateCheckBehaviorIndexAlways +}; + GeneralSettingsPage::GeneralSettingsPage() { QStringList languageCodes = findQmFiles(); @@ -71,6 +78,21 @@ GeneralSettingsPage::GeneralSettingsPage() // updates SettingsCache &settings = SettingsCache::instance(); startupUpdateCheckCheckBox.setChecked(settings.getCheckUpdatesOnStartup()); + + startupCardUpdateCheckBehaviorSelector.addItem(""); // these will be set in retranslateUI + startupCardUpdateCheckBehaviorSelector.addItem(""); + startupCardUpdateCheckBehaviorSelector.addItem(""); + if (SettingsCache::instance().getStartupCardUpdateCheckPromptForUpdate()) { + startupCardUpdateCheckBehaviorSelector.setCurrentIndex(startupCardUpdateCheckBehaviorIndexPrompt); + } else if (SettingsCache::instance().getStartupCardUpdateCheckAlwaysUpdate()) { + startupCardUpdateCheckBehaviorSelector.setCurrentIndex(startupCardUpdateCheckBehaviorIndexAlways); + } else { + startupCardUpdateCheckBehaviorSelector.setCurrentIndex(startupCardUpdateCheckBehaviorIndexNone); + } + + cardUpdateCheckIntervalSpinBox.setMinimum(1); + cardUpdateCheckIntervalSpinBox.setMaximum(30); + cardUpdateCheckIntervalSpinBox.setValue(settings.getCardUpdateCheckInterval()); updateNotificationCheckBox.setChecked(settings.getNotifyAboutUpdates()); newVersionOracleCheckBox.setChecked(settings.getNotifyAboutNewVersion()); @@ -83,6 +105,15 @@ GeneralSettingsPage::GeneralSettingsPage() &GeneralSettingsPage::languageBoxChanged); connect(&startupUpdateCheckCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, &SettingsCache::setCheckUpdatesOnStartup); + connect(&startupCardUpdateCheckBehaviorSelector, QOverload::of(&QComboBox::currentIndexChanged), this, + [](int index) { + SettingsCache::instance().setStartupCardUpdateCheckPromptForUpdate( + index == startupCardUpdateCheckBehaviorIndexPrompt); + SettingsCache::instance().setStartupCardUpdateCheckAlwaysUpdate( + index == startupCardUpdateCheckBehaviorIndexAlways); + }); + connect(&cardUpdateCheckIntervalSpinBox, qOverload(&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 +126,14 @@ 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(&startupCardUpdateCheckBehaviorLabel, 5, 0); + personalGrid->addWidget(&startupCardUpdateCheckBehaviorSelector, 5, 1); + 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 +377,14 @@ void GeneralSettingsPage::retranslateUi() tokenDatabasePathLabel.setText(tr("Token database:")); updateReleaseChannelLabel.setText(tr("Update channel")); startupUpdateCheckCheckBox.setText(tr("Check for client updates on startup")); + startupCardUpdateCheckBehaviorLabel.setText(tr("Check for card database updates on startup")); + startupCardUpdateCheckBehaviorSelector.setItemText(startupCardUpdateCheckBehaviorIndexNone, tr("Don't check")); + startupCardUpdateCheckBehaviorSelector.setItemText(startupCardUpdateCheckBehaviorIndexPrompt, + tr("Prompt for update")); + startupCardUpdateCheckBehaviorSelector.setItemText(startupCardUpdateCheckBehaviorIndexAlways, + tr("Always update in the background")); + 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 +392,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(); diff --git a/cockatrice/src/dialogs/dlg_settings.h b/cockatrice/src/dialogs/dlg_settings.h index f0b9c62c9..19677c790 100644 --- a/cockatrice/src/dialogs/dlg_settings.h +++ b/cockatrice/src/dialogs/dlg_settings.h @@ -71,6 +71,11 @@ private: QGroupBox *pathsGroupBox; QComboBox languageBox; QCheckBox startupUpdateCheckCheckBox; + QLabel startupCardUpdateCheckBehaviorLabel; + QComboBox startupCardUpdateCheckBehaviorSelector; + QLabel cardUpdateCheckIntervalLabel; + QSpinBox cardUpdateCheckIntervalSpinBox; + QLabel lastCardUpdateCheckDateLabel; QCheckBox updateNotificationCheckBox; QCheckBox newVersionOracleCheckBox; QComboBox updateReleaseChannelBox; diff --git a/cockatrice/src/dialogs/dlg_startup_card_check.cpp b/cockatrice/src/dialogs/dlg_startup_card_check.cpp new file mode 100644 index 000000000..5d76bc253 --- /dev/null +++ b/cockatrice/src/dialogs/dlg_startup_card_check.cpp @@ -0,0 +1,50 @@ +#include "dlg_startup_card_check.h" + +#include "../settings/cache_settings.h" + +#include + +DlgStartupCardCheck::DlgStartupCardCheck(QWidget *parent) : QDialog(parent) +{ + setWindowTitle(tr("Card Update Check")); + + layout = new QVBoxLayout(this); + + QDate lastCheckDate = SettingsCache::instance().getLastCardUpdateCheck(); + int daysAgo = lastCheckDate.daysTo(QDate::currentDate()); + + instructionLabel = new QLabel( + tr("It has been more than %2 days since you last checked your card database for updates.\nChoose how you would " + "like to run the card database updater.\nYou can always change this behavior in the 'General' settings tab.") + .arg(daysAgo)); + + layout->addWidget(instructionLabel); + + group = new QButtonGroup(this); + + foregroundBtn = new QRadioButton(tr("Run in foreground")); + backgroundBtn = new QRadioButton(tr("Run in background")); + backgroundAlwaysBtn = new QRadioButton(tr("Run in background and always from now on")); + dontPromptBtn = new QRadioButton(tr("Don't prompt again and don't run")); + dontRunBtn = new QRadioButton(tr("Don't run this time")); + + group->addButton(foregroundBtn, 0); + group->addButton(backgroundBtn, 1); + group->addButton(backgroundAlwaysBtn, 2); + group->addButton(dontPromptBtn, 3); + group->addButton(dontRunBtn, 4); + + foregroundBtn->setChecked(true); // default + + layout->addWidget(foregroundBtn); + layout->addWidget(backgroundBtn); + layout->addWidget(backgroundAlwaysBtn); + layout->addWidget(dontPromptBtn); + layout->addWidget(dontRunBtn); + + buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + layout->addWidget(buttonBox); + + connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); +} diff --git a/cockatrice/src/dialogs/dlg_startup_card_check.h b/cockatrice/src/dialogs/dlg_startup_card_check.h new file mode 100644 index 000000000..cb7acd280 --- /dev/null +++ b/cockatrice/src/dialogs/dlg_startup_card_check.h @@ -0,0 +1,24 @@ +#ifndef DLG_STARTUP_CARD_CHECK_H +#define DLG_STARTUP_CARD_CHECK_H + +#include +#include +#include +#include +#include +#include + +class DlgStartupCardCheck : public QDialog +{ + Q_OBJECT +public: + explicit DlgStartupCardCheck(QWidget *parent); + + QVBoxLayout *layout; + QLabel *instructionLabel; + QButtonGroup *group; + QRadioButton *foregroundBtn, *backgroundBtn, *backgroundAlwaysBtn, *dontPromptBtn, *dontRunBtn; + QDialogButtonBox *buttonBox; +}; + +#endif // DLG_STARTUP_CARD_CHECK_H diff --git a/cockatrice/src/settings/cache_settings.cpp b/cockatrice/src/settings/cache_settings.cpp index 4b2e854d7..2ad735128 100644 --- a/cockatrice/src/settings/cache_settings.cpp +++ b/cockatrice/src/settings/cache_settings.cpp @@ -194,6 +194,11 @@ SettingsCache::SettingsCache() mbDownloadSpoilers = settings->value("personal/downloadspoilers", false).toBool(); checkUpdatesOnStartup = settings->value("personal/startupUpdateCheck", true).toBool(); + startupCardUpdateCheckPromptForUpdate = + settings->value("personal/startupCardUpdateCheckPromptForUpdate", true).toBool(); + startupCardUpdateCheckAlwaysUpdate = settings->value("personal/startupCardUpdateCheckAlwaysUpdate", false).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 +1368,29 @@ void SettingsCache::setCheckUpdatesOnStartup(QT_STATE_CHANGED_T value) settings->setValue("personal/startupUpdateCheck", checkUpdatesOnStartup); } +void SettingsCache::setStartupCardUpdateCheckPromptForUpdate(bool value) +{ + startupCardUpdateCheckPromptForUpdate = value; + settings->setValue("personal/startupCardUpdateCheckPromptForUpdate", startupCardUpdateCheckPromptForUpdate); +} +void SettingsCache::setStartupCardUpdateCheckAlwaysUpdate(bool value) +{ + startupCardUpdateCheckAlwaysUpdate = value; + settings->setValue("personal/startupCardUpdateCheckAlwaysUpdate", startupCardUpdateCheckAlwaysUpdate); +} + +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; diff --git a/cockatrice/src/settings/cache_settings.h b/cockatrice/src/settings/cache_settings.h index aaf40edf8..16822d755 100644 --- a/cockatrice/src/settings/cache_settings.h +++ b/cockatrice/src/settings/cache_settings.h @@ -13,6 +13,7 @@ #include "servers_settings.h" #include "shortcuts_settings.h" +#include #include #include #include @@ -198,6 +199,11 @@ private: bool tabVisualDeckStorageOpen, tabServerOpen, tabAccountOpen, tabDeckStorageOpen, tabReplaysOpen, tabAdminOpen, tabLogOpen; bool checkUpdatesOnStartup; + bool startupCardUpdateCheckPromptForUpdate; + bool startupCardUpdateCheckAlwaysUpdate; + bool checkCardUpdatesOnStartup; + int cardUpdateCheckInterval; + QDate lastCardUpdateCheck; bool notifyAboutUpdates; bool notifyAboutNewVersion; bool showTipsOnStartup; @@ -438,6 +444,27 @@ public: { return checkUpdatesOnStartup; } + bool getStartupCardUpdateCheckPromptForUpdate() + { + return startupCardUpdateCheckPromptForUpdate; + } + bool getStartupCardUpdateCheckAlwaysUpdate() + { + return startupCardUpdateCheckAlwaysUpdate; + } + 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 +1034,10 @@ public slots: void setDefaultStartingLifeTotal(const int _defaultStartingLifeTotal); void setRememberGameSettings(const bool _rememberGameSettings); void setCheckUpdatesOnStartup(QT_STATE_CHANGED_T value); + void setStartupCardUpdateCheckPromptForUpdate(bool value); + void setStartupCardUpdateCheckAlwaysUpdate(bool 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); diff --git a/dbconverter/src/mocks.cpp b/dbconverter/src/mocks.cpp index 150660d31..738a17695 100644 --- a/dbconverter/src/mocks.cpp +++ b/dbconverter/src/mocks.cpp @@ -408,6 +408,18 @@ void SettingsCache::setRememberGameSettings(const bool /* _rememberGameSettings void SettingsCache::setCheckUpdatesOnStartup(QT_STATE_CHANGED_T /* value */) { } +void SettingsCache::setStartupCardUpdateCheckPromptForUpdate(bool /* value */) +{ +} +void SettingsCache::setStartupCardUpdateCheckAlwaysUpdate(bool /* value */) +{ +} +void SettingsCache::setCardUpdateCheckInterval(int /* value */) +{ +} +void SettingsCache::setLastCardUpdateCheck(QDate /* value */) +{ +} void SettingsCache::setNotifyAboutUpdate(QT_STATE_CHANGED_T /* _notifyaboutupdate */) { } diff --git a/oracle/src/main.cpp b/oracle/src/main.cpp index 009a099ac..19007a3ca 100644 --- a/oracle/src/main.cpp +++ b/oracle/src/main.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include 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(); } diff --git a/oracle/src/oraclewizard.cpp b/oracle/src/oraclewizard.cpp index bea87dde2..0fdd4b8f1 100644 --- a/oracle/src/oraclewizard.cpp +++ b/oracle/src/oraclewizard.cpp @@ -64,15 +64,23 @@ OracleWizard::OracleWizard(QWidget *parent) : QWizard(parent) nam = new QNetworkAccessManager(this); + QList 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; diff --git a/oracle/src/oraclewizard.h b/oracle/src/oraclewizard.h index 35f1a233e..2733bf1ad 100644 --- a/oracle/src/oraclewizard.h +++ b/oracle/src/oraclewizard.h @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -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,9 @@ public: { } void retranslateUi() override; + +protected: + void initializePage() override; }; class LoadSetsPage : public OracleWizardPage @@ -191,6 +206,7 @@ protected: QString getDefaultSavePath() override; QString getWindowTitle() override; QString getFileType() override; + void initializePage() override; }; #endif diff --git a/oracle/src/pagetemplates.cpp b/oracle/src/pagetemplates.cpp index 858fd8022..d9ce3300f 100644 --- a/oracle/src/pagetemplates.cpp +++ b/oracle/src/pagetemplates.cpp @@ -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; } diff --git a/oracle/src/pagetemplates.h b/oracle/src/pagetemplates.h index a65559ae0..874652d17 100644 --- a/oracle/src/pagetemplates.h +++ b/oracle/src/pagetemplates.h @@ -16,6 +16,9 @@ public: explicit OracleWizardPage(QWidget *parent = nullptr) : QWizardPage(parent){}; virtual void retranslateUi() = 0; +signals: + void readyToContinue(); + protected: inline OracleWizard *wizard() { diff --git a/tests/carddatabase/mocks.cpp b/tests/carddatabase/mocks.cpp index 9d1573856..9d158217e 100644 --- a/tests/carddatabase/mocks.cpp +++ b/tests/carddatabase/mocks.cpp @@ -412,6 +412,18 @@ void SettingsCache::setRememberGameSettings(const bool /* _rememberGameSettings void SettingsCache::setCheckUpdatesOnStartup(QT_STATE_CHANGED_T /* value */) { } +void SettingsCache::setStartupCardUpdateCheckPromptForUpdate(bool /* value */) +{ +} +void SettingsCache::setStartupCardUpdateCheckAlwaysUpdate(bool /* value */) +{ +} +void SettingsCache::setCardUpdateCheckInterval(int /* value */) +{ +} +void SettingsCache::setLastCardUpdateCheck(QDate /* value */) +{ +} void SettingsCache::setNotifyAboutUpdate(QT_STATE_CHANGED_T /* _notifyaboutupdate */) { }