diff --git a/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.cpp b/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.cpp index a20d31652..182e75aac 100644 --- a/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.cpp +++ b/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.cpp @@ -183,6 +183,13 @@ UserInterfaceSettingsPage::UserInterfaceSettingsPage() connect(&defaultDeckEditorTypeSelector, QOverload::of(&QComboBox::currentIndexChanged), &SettingsCache::instance().deckEditor(), &DeckEditorSettings::setDefaultDeckEditorType); + vdeStartupTabSelector.addItem(""); // these will be set in retranslateUI + vdeStartupTabSelector.addItem(""); + vdeStartupTabSelector.addItem(""); + vdeStartupTabSelector.setCurrentIndex(SettingsCache::instance().deckEditor().getVdeStartupTab()); + connect(&vdeStartupTabSelector, QOverload::of(&QComboBox::currentIndexChanged), + &SettingsCache::instance().deckEditor(), &DeckEditorSettings::setVdeStartupTab); + commanderSpellbookIntegrationUseOfficialBracketNamesExplainer.setText("?"); commanderSpellbookIntegrationUseOfficialBracketNamesExplainer.setAutoRaise(true); commanderSpellbookIntegrationUseOfficialBracketNamesExplainer.setEnabled(false); @@ -242,10 +249,12 @@ UserInterfaceSettingsPage::UserInterfaceSettingsPage() deckEditorGrid->addWidget(&visualDeckStoragePromptForConversionSelector, 3, 1); deckEditorGrid->addWidget(&defaultDeckEditorTypeLabel, 4, 0); deckEditorGrid->addWidget(&defaultDeckEditorTypeSelector, 4, 1); - deckEditorGrid->addWidget(&commanderSpellbookIntegrationEnabledLabel, 5, 0); - deckEditorGrid->addWidget(&commanderSpellbookIntegrationEnabledSelector, 5, 1); - deckEditorGrid->addWidget(labelWidget, 6, 0); - deckEditorGrid->addWidget(&commanderSpellbookIntegrationBracketNamingSelector, 6, 1); + deckEditorGrid->addWidget(&vdeStartupTabLabel, 5, 0); + deckEditorGrid->addWidget(&vdeStartupTabSelector, 5, 1); + deckEditorGrid->addWidget(&commanderSpellbookIntegrationEnabledLabel, 6, 0); + deckEditorGrid->addWidget(&commanderSpellbookIntegrationEnabledSelector, 6, 1); + deckEditorGrid->addWidget(labelWidget, 7, 0); + deckEditorGrid->addWidget(&commanderSpellbookIntegrationBracketNamingSelector, 7, 1); deckEditorGroupBox = new QGroupBox; deckEditorGroupBox->setLayout(deckEditorGrid); @@ -368,6 +377,12 @@ void UserInterfaceSettingsPage::retranslateUi() defaultDeckEditorTypeLabel.setText(tr("Default deck editor type")); defaultDeckEditorTypeSelector.setItemText(TabSupervisor::ClassicDeckEditor, tr("Classic Deck Editor")); defaultDeckEditorTypeSelector.setItemText(TabSupervisor::VisualDeckEditor, tr("Visual Deck Editor")); + vdeStartupTabLabel.setText(tr("Visual deck editor startup tab")); + vdeStartupTabSelector.setItemText(VdeStartupTabContext, tr("Context")); + vdeStartupTabSelector.setItemText(VdeStartupTabDeckDisplay, tr("Deck display")); + vdeStartupTabSelector.setItemText(VdeStartupTabDatabaseDisplay, tr("Database display")); + vdeStartupTabSelector.setToolTip( + tr("Context mode: New decks open on the database display, existing decks open on the deck view.")); commanderSpellbookIntegrationEnabledLabel.setText( tr("CommanderSpellbook integration to estimate commander bracket")); diff --git a/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.h b/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.h index 2b9eba72c..0dc4cf4e8 100644 --- a/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.h +++ b/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.h @@ -50,6 +50,8 @@ private: QCheckBox visualDeckStorageSelectionAnimationCheckBox; QLabel defaultDeckEditorTypeLabel; QComboBox defaultDeckEditorTypeSelector; + QLabel vdeStartupTabLabel; + QComboBox vdeStartupTabSelector; QLabel commanderSpellbookIntegrationEnabledLabel; QComboBox commanderSpellbookIntegrationEnabledSelector; QLabel commanderSpellbookIntegrationUseOfficialBracketNamesLabel; diff --git a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.h b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.h index 34c585597..e1f255199 100644 --- a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.h +++ b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.h @@ -263,12 +263,12 @@ protected slots: /** @brief Handles dock close events. */ void closeEvent(QCloseEvent *event) override; -private: /** @brief Sets the deck for this tab. * @param _deck The deck object. */ virtual void setDeck(const LoadedDeck &_deck); +private: /** @brief Helper for editing decks from the clipboard. */ void editDeckInClipboard(bool annotated); diff --git a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp index c15f614d8..209a30642 100644 --- a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp +++ b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include /** @@ -98,6 +99,33 @@ void TabDeckEditorVisual::onDeckChanged() tabContainer->sampleHandWidget->setDeckModel(deckStateManager->getModel()); } +/** @brief Sets the deck and selects the startup sub-tab matching the context. */ +void TabDeckEditorVisual::setDeck(const LoadedDeck &_deck) +{ + AbstractTabDeckEditor::setDeck(_deck); + + int startupTab = SettingsCache::instance().deckEditor().getVdeStartupTab(); + if (startupTab == VdeStartupTabContext) { + // New (empty) decks open on the database display so cards can be added + // right away. Existing decks open on the deck view. + startupTab = _deck.isEmpty() ? VdeStartupTabDatabaseDisplay : VdeStartupTabDeckDisplay; + } + + switch (startupTab) { + case VdeStartupTabDatabaseDisplay: + tabContainer->setCurrentIndex(TabDeckEditorVisualTabWidget::TabIndex::VisualDatabaseDisplay); + break; + case VdeStartupTabDeckDisplay: + tabContainer->setCurrentIndex(TabDeckEditorVisualTabWidget::TabIndex::VisualDeckView); + break; + default: + qCWarning(TabSupervisorLog) << "Unknown VdeStartupTab [" << startupTab + << "]; falling back to the deck view"; + tabContainer->setCurrentIndex(TabDeckEditorVisualTabWidget::TabIndex::VisualDeckView); + break; + } +} + /** @brief Creates menus for deck editing and view options, including dock actions. */ void TabDeckEditorVisual::createMenus() { diff --git a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.h b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.h index 7d7a3f3a2..21335d2d0 100644 --- a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.h +++ b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.h @@ -164,6 +164,15 @@ public slots: * @return true if successful, false otherwise. */ bool actSaveDeckAs() override; + +private: + /** + * @brief Sets the deck for this tab and selects the sub-tab to open on + * startup, per the "Visual deck editor startup tab" setting (Context / + * Deck display / Database display). + * @param _deck The deck object. + */ + void setDeck(const LoadedDeck &_deck) override; }; #endif diff --git a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h index 2aabbb26a..4f04b51f6 100644 --- a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h +++ b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h @@ -49,6 +49,17 @@ class TabDeckEditorVisualTabWidget : public QTabWidget Q_OBJECT public: + /** + * @brief Sub-tab order in the container; addNewTab() is called in this order. + */ + enum TabIndex + { + VisualDeckView, + VisualDatabaseDisplay, + DeckAnalytics, + SampleHand, + }; + /** * @brief Construct the tab widget with required models. * @param parent Parent widget. diff --git a/libcockatrice_settings/libcockatrice/settings/deck_editor_settings.cpp b/libcockatrice_settings/libcockatrice/settings/deck_editor_settings.cpp index 65296a450..44cdcd86f 100644 --- a/libcockatrice_settings/libcockatrice/settings/deck_editor_settings.cpp +++ b/libcockatrice_settings/libcockatrice/settings/deck_editor_settings.cpp @@ -25,6 +25,11 @@ int DeckEditorSettings::getDefaultDeckEditorType() const return getValue("defaultDeckEditorType", QString(), QString(), 1).toInt(); } +int DeckEditorSettings::getVdeStartupTab() const +{ + return getValue("vdeStartupTab", QString(), QString(), VdeStartupTabContext).toInt(); +} + void DeckEditorSettings::setOpenDeckInNewTab(bool _openDeckInNewTab) { setValue(_openDeckInNewTab, "openDeckInNewTab"); @@ -47,6 +52,12 @@ void DeckEditorSettings::setDefaultDeckEditorType(int _defaultDeckEditorType) setValue(_defaultDeckEditorType, "defaultDeckEditorType"); } +void DeckEditorSettings::setVdeStartupTab(int _vdeStartupTab) +{ + setValue(_vdeStartupTab, "vdeStartupTab"); + emit vdeStartupTabChanged(_vdeStartupTab); +} + int DeckEditorSettings::getCommanderSpellbookIntegrationEnabled() const { return getValue("commanderspellbookintegrationenabled", QString(), QString(), diff --git a/libcockatrice_settings/libcockatrice/settings/deck_editor_settings.h b/libcockatrice_settings/libcockatrice/settings/deck_editor_settings.h index 70f91be9b..0c87a270a 100644 --- a/libcockatrice_settings/libcockatrice/settings/deck_editor_settings.h +++ b/libcockatrice_settings/libcockatrice/settings/deck_editor_settings.h @@ -13,6 +13,13 @@ enum commanderSpellbookIntegrationEnabledIndex commanderSpellbookIntegrationEnabledIndexUnprompted, }; +enum VdeStartupTab +{ + VdeStartupTabContext, ///< Match the opened deck: new decks show the database display, existing decks the deck view + VdeStartupTabDeckDisplay, ///< Always open the Visual Deck View + VdeStartupTabDatabaseDisplay, ///< Always open the Visual Database Display +}; + class DeckEditorSettings : public SettingsManager, public IDeckEditorSettingsProvider { Q_OBJECT @@ -23,6 +30,7 @@ public: [[nodiscard]] bool getBannerCardComboBoxVisible() const override; [[nodiscard]] bool getTagsWidgetVisible() const override; [[nodiscard]] int getDefaultDeckEditorType() const override; + [[nodiscard]] int getVdeStartupTab() const; [[nodiscard]] int getCommanderSpellbookIntegrationEnabled() const; [[nodiscard]] bool getCommanderSpellbookIntegrationUseOfficialBracketNames() const; @@ -30,6 +38,7 @@ public: void setBannerCardComboBoxVisible(bool _bannerCardComboBoxVisible); void setTagsWidgetVisible(bool _tagsWidgetVisible); void setDefaultDeckEditorType(int _defaultDeckEditorType); + void setVdeStartupTab(int _vdeStartupTab); void setCommanderSpellbookIntegrationEnabled(int _commanderSpellbookIntegrationEnabled); void setCommanderSpellbookIntegrationUseOfficialBracketNames(bool _useOfficialBracketNames); @@ -38,6 +47,7 @@ signals: void tagsWidgetVisibleChanged(bool visible); void commanderSpellbookIntegrationEnabledChanged(int enabled); void commanderSpellbookIntegrationUseOfficialBracketNamesChanged(bool useOfficialBracketNames); + void vdeStartupTabChanged(int vdeStartupTab); public: explicit DeckEditorSettings(const QString &settingPath, QObject *parent = nullptr); diff --git a/tests/settings/settings_defaults_test.cpp b/tests/settings/settings_defaults_test.cpp index 041a60d6f..4884fd80c 100644 --- a/tests/settings/settings_defaults_test.cpp +++ b/tests/settings/settings_defaults_test.cpp @@ -400,6 +400,23 @@ TEST_F(SettingsDefaultsTest, DeckEditor_DefaultDeckEditorType_Default) ASSERT_EQ(s.getDefaultDeckEditorType(), 1); } +TEST_F(SettingsDefaultsTest, DeckEditor_VdeStartupTab_Default) +{ + DeckEditorSettings s(settingsPath, nullptr); + ASSERT_EQ(s.getVdeStartupTab(), VdeStartupTabContext); +} + +TEST_F(SettingsDefaultsTest, DeckEditor_VdeStartupTab_SetAndGet) +{ + DeckEditorSettings s(settingsPath, nullptr); + s.setVdeStartupTab(VdeStartupTabDeckDisplay); + ASSERT_EQ(s.getVdeStartupTab(), VdeStartupTabDeckDisplay); + s.setVdeStartupTab(VdeStartupTabDatabaseDisplay); + ASSERT_EQ(s.getVdeStartupTab(), VdeStartupTabDatabaseDisplay); + s.setVdeStartupTab(VdeStartupTabContext); + ASSERT_EQ(s.getVdeStartupTab(), VdeStartupTabContext); +} + // --- NetworkSettings --- TEST_F(SettingsDefaultsTest, Network_ClientID_Default)