From 57e6c91689d7b7b86485621985449c908e5a90a3 Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Thu, 15 Jan 2026 18:05:19 -0800 Subject: [PATCH] [TabDeckEditor] Automatically sync view menu actions (#6522) --- .../deck_editor_card_database_dock_widget.cpp | 1 - .../deck_editor_card_info_dock_widget.cpp | 1 - .../deck_editor_deck_dock_widget.cpp | 1 - .../deck_editor_filter_dock_widget.cpp | 1 - ...k_editor_printing_selector_dock_widget.cpp | 1 - .../widgets/tabs/abstract_tab_deck_editor.cpp | 41 ++++++++- .../widgets/tabs/abstract_tab_deck_editor.h | 26 +++--- .../widgets/tabs/tab_deck_editor.cpp | 89 ++----------------- .../interface/widgets/tabs/tab_deck_editor.h | 3 - .../tab_deck_editor_visual.cpp | 84 ++--------------- .../tab_deck_editor_visual.h | 16 ---- 11 files changed, 65 insertions(+), 199 deletions(-) diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.cpp index 5abc6e619..bacebe385 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.cpp @@ -25,7 +25,6 @@ void DeckEditorCardDatabaseDockWidget::createDatabaseDisplayDock(AbstractTabDeck setWidget(dockContents); installEventFilter(deckEditor); - connect(this, &QDockWidget::topLevelChanged, deckEditor, &AbstractTabDeckEditor::dockTopLevelChanged); // connect signals connect(databaseDisplayWidget, &DeckEditorDatabaseDisplayWidget::cardChanged, deckEditor, diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_info_dock_widget.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_info_dock_widget.cpp index 3f12636a8..a78a9c9c5 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_info_dock_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_info_dock_widget.cpp @@ -31,7 +31,6 @@ void DeckEditorCardInfoDockWidget::createCardInfoDock() setWidget(cardInfoDockContents); installEventFilter(deckEditor); - connect(this, &QDockWidget::topLevelChanged, deckEditor, &AbstractTabDeckEditor::dockTopLevelChanged); } void DeckEditorCardInfoDockWidget::updateCard(const ExactCard &_card) diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp index 73bafe54f..2ecb4f46a 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp @@ -46,7 +46,6 @@ DeckEditorDeckDockWidget::DeckEditorDeckDockWidget(AbstractTabDeckEditor *parent setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); installEventFilter(deckEditor); - connect(this, &DeckEditorDeckDockWidget::topLevelChanged, deckEditor, &AbstractTabDeckEditor::dockTopLevelChanged); createDeckDock(); } diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.cpp index 5790131c5..8a9a6cdaa 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.cpp @@ -80,7 +80,6 @@ void DeckEditorFilterDockWidget::createFiltersDock() setWidget(filterDockContents); installEventFilter(deckEditor); - connect(this, &QDockWidget::topLevelChanged, deckEditor, &AbstractTabDeckEditor::dockTopLevelChanged); } void DeckEditorFilterDockWidget::filterViewCustomContextMenu(const QPoint &point) diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_printing_selector_dock_widget.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_editor_printing_selector_dock_widget.cpp index 03760c22d..7c4e0de18 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_printing_selector_dock_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_printing_selector_dock_widget.cpp @@ -32,7 +32,6 @@ void DeckEditorPrintingSelectorDockWidget::createPrintingSelectorDock() setWidget(printingSelectorDockContents); installEventFilter(deckEditor); - connect(this, &QDockWidget::topLevelChanged, deckEditor, &AbstractTabDeckEditor::dockTopLevelChanged); connect(printingSelector, &PrintingSelector::prevCardRequested, deckEditor->getDeckDockWidget(), &DeckEditorDeckDockWidget::selectPrevCard); connect(printingSelector, &PrintingSelector::nextCardRequested, deckEditor->getDeckDockWidget(), diff --git a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp index e41feb0c1..5e6db71f3 100644 --- a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp +++ b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp @@ -77,16 +77,30 @@ AbstractTabDeckEditor::AbstractTabDeckEditor(TabSupervisor *_tabSupervisor) : Ta &AbstractTabDeckEditor::refreshShortcuts); } -void AbstractTabDeckEditor::registerDockWidget(QDockWidget *widget) +void AbstractTabDeckEditor::registerDockWidget(QMenu *_viewMenu, QDockWidget *widget) { - QMenu *menu = viewMenu->addMenu(QString()); + QMenu *menu = _viewMenu->addMenu(QString()); QAction *aVisible = menu->addAction(QString()); aVisible->setCheckable(true); - connect(aVisible, &QAction::triggered, this, &AbstractTabDeckEditor::dockVisibleTriggered); + QAction *aFloating = menu->addAction(QString()); aFloating->setCheckable(true); - connect(aFloating, &QAction::triggered, this, &AbstractTabDeckEditor::dockFloatingTriggered); + aFloating->setEnabled(false); + + // user interaction + connect(aVisible, &QAction::triggered, widget, [widget](bool checked) { widget->setVisible(checked); }); + connect(aFloating, &QAction::triggered, this, [widget](bool checked) { widget->setFloating(checked); }); + + // sync aFloating's enabled state with aVisible's checked state + connect(aVisible, &QAction::toggled, aFloating, [aFloating](bool checked) { aFloating->setEnabled(checked); }); + + // sync aFloating with dockWidget's floating state + connect(widget, &QDockWidget::topLevelChanged, aFloating, + [aFloating](bool topLevel) { aFloating->setChecked(topLevel); }); + + // sync aVisible with dockWidget's visible state + widget->installEventFilter(new DockWidgetVisibilityFilter(widget, aVisible)); dockToActions.insert(widget, {menu, aVisible, aFloating}); } @@ -594,3 +608,22 @@ bool AbstractTabDeckEditor::closeRequest() return false; return close(); } + +DockWidgetVisibilityFilter::DockWidgetVisibilityFilter(QDockWidget *dockWidget, QAction *aVisible) + : QObject(dockWidget), dockWidget(dockWidget), aVisible(aVisible) +{ +} + +bool DockWidgetVisibilityFilter::eventFilter(QObject *o, QEvent *e) +{ + if (o == dockWidget && !e->spontaneous()) { + if (e->type() == QEvent::Show) { + aVisible->setChecked(true); + } + + if (e->type() == QEvent::Hide) { + aVisible->setChecked(false); + } + } + return false; +} \ No newline at end of file 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 66a56f39b..eb0b3755c 100644 --- a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.h +++ b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.h @@ -169,9 +169,6 @@ public slots: /** @brief Shows the printing selector dock. Pure virtual. */ virtual void showPrintingSelector() = 0; - /** @brief Slot for when a dock's top-level state changes. Pure virtual. */ - virtual void dockTopLevelChanged(bool topLevel) = 0; - signals: /** @brief Emitted when a deck should be opened in a new editor tab. */ void openDeckEditor(const LoadedDeck &deck); @@ -246,12 +243,6 @@ protected slots: /** @brief Handles dock close events. */ void closeEvent(QCloseEvent *event) override; - /** @brief Slot triggered when a dock visibility changes. Pure virtual. */ - virtual void dockVisibleTriggered() = 0; - - /** @brief Slot triggered when a dock floating state changes. Pure virtual. */ - virtual void dockFloatingTriggered() = 0; - private: /** @brief Sets the deck for this tab. * @param _deck The deck object. @@ -289,7 +280,7 @@ protected: * @brief registers a QDockWidget as a managed dock widget. Creates the associated actions and menu, adds them to * the viewMenu, and connects those actions to the tab's slots. */ - void registerDockWidget(QDockWidget *widget); + void registerDockWidget(QMenu *_viewMenu, QDockWidget *widget); /** @brief Confirms deck open action based on settings and modified state. * @param openInSameTabIfBlank Whether to reuse same tab if blank. @@ -316,4 +307,19 @@ protected: QMap dockToActions; }; +/** + * This filter syncs the dock widget's visibility with the viewMenu visibility action's check state. + */ +class DockWidgetVisibilityFilter : public QObject +{ + Q_OBJECT + + QDockWidget *dockWidget; + QAction *aVisible; + +public: + explicit DockWidgetVisibilityFilter(QDockWidget *dockWidget, QAction *aVisible); + bool eventFilter(QObject *o, QEvent *e) override; +}; + #endif // TAB_GENERIC_DECK_EDITOR_H diff --git a/cockatrice/src/interface/widgets/tabs/tab_deck_editor.cpp b/cockatrice/src/interface/widgets/tabs/tab_deck_editor.cpp index 9c7cc0a84..4625decd8 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_deck_editor.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_deck_editor.cpp @@ -54,11 +54,11 @@ void TabDeckEditor::createMenus() viewMenu = new QMenu(this); - registerDockWidget(cardInfoDockWidget); - registerDockWidget(cardDatabaseDockWidget); - registerDockWidget(deckDockWidget); - registerDockWidget(filterDockWidget); - registerDockWidget(printingSelectorDockWidget); + registerDockWidget(viewMenu, cardInfoDockWidget); + registerDockWidget(viewMenu, cardDatabaseDockWidget); + registerDockWidget(viewMenu, deckDockWidget); + registerDockWidget(viewMenu, filterDockWidget); + registerDockWidget(viewMenu, printingSelectorDockWidget); if (SettingsCache::instance().getOverrideAllCardArtWithPersonalPreference()) { dockToActions[printingSelectorDockWidget].menu->setEnabled(false); @@ -130,7 +130,6 @@ void TabDeckEditor::showPrintingSelector() { printingSelectorDockWidget->printingSelector->setCard(cardInfoDockWidget->cardInfo->getCard().getCardPtr()); printingSelectorDockWidget->printingSelector->updateDisplay(); - dockToActions[printingSelectorDockWidget].aVisible->setChecked(true); printingSelectorDockWidget->setVisible(true); } @@ -152,19 +151,9 @@ void TabDeckEditor::loadLayout() if (SettingsCache::instance().getOverrideAllCardArtWithPersonalPreference()) { if (!printingSelectorDockWidget->isHidden()) { printingSelectorDockWidget->setHidden(true); - dockToActions[printingSelectorDockWidget].aVisible->setChecked(true); } } - for (auto it = dockToActions.begin(); it != dockToActions.end(); ++it) { - QDockWidget *dockWidget = it.key(); - const DockActions &actions = it.value(); - - actions.aVisible->setChecked(!dockWidget->isHidden()); - actions.aFloating->setEnabled(actions.aVisible->isChecked()); - actions.aFloating->setChecked(dockWidget->isFloating()); - } - cardInfoDockWidget->setMinimumSize(layouts.getDeckEditorCardSize()); cardInfoDockWidget->setMaximumSize(layouts.getDeckEditorCardSize()); @@ -185,23 +174,13 @@ void TabDeckEditor::loadLayout() */ void TabDeckEditor::restartLayout() { - - // Update menu checkboxes - for (auto it = dockToActions.begin(); it != dockToActions.end(); ++it) { - QDockWidget *dockWidget = it.key(); - const DockActions &actions = it.value(); - - actions.aVisible->setEnabled(true); - actions.aFloating->setEnabled(false); - - // Show/hide and reset floating + // Show/hide and reset floating + for (auto dockWidget : dockToActions.keys()) { dockWidget->setVisible(true); dockWidget->setFloating(false); } // Printing selector special case - dockToActions[printingSelectorDockWidget].aVisible->setChecked( - !SettingsCache::instance().getOverrideAllCardArtWithPersonalPreference()); printingSelectorDockWidget->setVisible(!SettingsCache::instance().getOverrideAllCardArtWithPersonalPreference()); addDockWidget(Qt::LeftDockWidgetArea, cardDatabaseDockWidget); @@ -230,51 +209,6 @@ void TabDeckEditor::freeDocksSize() } } -/** @brief Handles dock visibility toggling from menu actions. */ -void TabDeckEditor::dockVisibleTriggered() -{ - QObject *o = sender(); - - for (auto it = dockToActions.begin(); it != dockToActions.end(); ++it) { - QDockWidget *dockWidget = it.key(); - const DockActions &actions = it.value(); - - if (o == actions.aVisible) { - dockWidget->setHidden(!actions.aVisible->isChecked()); - actions.aFloating->setEnabled(actions.aVisible->isChecked()); - return; - } - } -} - -/** @brief Handles dock floating toggling from menu actions. */ -void TabDeckEditor::dockFloatingTriggered() -{ - QObject *o = sender(); - - for (auto it = dockToActions.begin(); it != dockToActions.end(); ++it) { - QDockWidget *dockWidget = it.key(); - const DockActions &actions = it.value(); - - if (o == actions.aFloating) { - dockWidget->setFloating(actions.aFloating->isChecked()); - return; - } - } -} - -/** @brief Syncs menu state with dock floating changes. */ -void TabDeckEditor::dockTopLevelChanged(bool topLevel) -{ - QObject *o = sender(); - - auto dockWidget = qobject_cast(o); - if (dockToActions.contains(dockWidget)) { - DockActions actions = dockToActions.value(dockWidget); - actions.aFloating->setChecked(topLevel); - } -} - /** * @brief Handles close/hide events to update menu state and save layout. * @param o Object sending the event. @@ -283,15 +217,6 @@ void TabDeckEditor::dockTopLevelChanged(bool topLevel) */ bool TabDeckEditor::eventFilter(QObject *o, QEvent *e) { - if (e->type() == QEvent::Close) { - auto dockWidget = qobject_cast(o); - if (dockToActions.contains(dockWidget)) { - DockActions actions = dockToActions.value(dockWidget); - actions.aVisible->setChecked(false); - actions.aFloating->setEnabled(false); - } - } - if (o == this && e->type() == QEvent::Hide) { LayoutsSettings &layouts = SettingsCache::instance().layouts(); layouts.setDeckEditorLayoutState(saveState()); diff --git a/cockatrice/src/interface/widgets/tabs/tab_deck_editor.h b/cockatrice/src/interface/widgets/tabs/tab_deck_editor.h index b3ffb8d90..285d241d2 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_deck_editor.h +++ b/cockatrice/src/interface/widgets/tabs/tab_deck_editor.h @@ -70,9 +70,6 @@ protected slots: /** @brief Handles dock visibility, floating, and top-level changes. */ bool eventFilter(QObject *o, QEvent *e) override; - void dockVisibleTriggered() override; - void dockFloatingTriggered() override; - void dockTopLevelChanged(bool topLevel) override; public: /** 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 a3c18da7c..745ec22a8 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 @@ -97,10 +97,10 @@ void TabDeckEditorVisual::createMenus() viewMenu = new QMenu(this); - registerDockWidget(cardInfoDockWidget); - registerDockWidget(deckDockWidget); - registerDockWidget(filterDockWidget); - registerDockWidget(printingSelectorDockWidget); + registerDockWidget(viewMenu, cardInfoDockWidget); + registerDockWidget(viewMenu, deckDockWidget); + registerDockWidget(viewMenu, filterDockWidget); + registerDockWidget(viewMenu, printingSelectorDockWidget); if (SettingsCache::instance().getOverrideAllCardArtWithPersonalPreference()) { dockToActions[printingSelectorDockWidget].menu->setEnabled(false); @@ -241,7 +241,6 @@ void TabDeckEditorVisual::showPrintingSelector() { printingSelectorDockWidget->printingSelector->setCard(cardInfoDockWidget->cardInfo->getCard().getCardPtr()); printingSelectorDockWidget->printingSelector->updateDisplay(); - dockToActions[printingSelectorDockWidget].aVisible->setChecked(true); printingSelectorDockWidget->setVisible(true); } @@ -283,19 +282,9 @@ void TabDeckEditorVisual::loadLayout() if (SettingsCache::instance().getOverrideAllCardArtWithPersonalPreference()) { if (!printingSelectorDockWidget->isHidden()) { printingSelectorDockWidget->setHidden(true); - dockToActions[printingSelectorDockWidget].aVisible->setChecked(false); } } - for (auto it = dockToActions.begin(); it != dockToActions.end(); ++it) { - QDockWidget *dockWidget = it.key(); - const DockActions &actions = it.value(); - - actions.aVisible->setChecked(dockWidget->isHidden()); - actions.aFloating->setEnabled(actions.aVisible->isChecked()); - actions.aFloating->setChecked(dockWidget->isFloating()); - } - cardInfoDockWidget->setMinimumSize(layouts.getDeckEditorCardSize()); cardInfoDockWidget->setMaximumSize(layouts.getDeckEditorCardSize()); @@ -314,20 +303,10 @@ void TabDeckEditorVisual::loadLayout() /** @brief Resets the layout to default positions and dock states. */ void TabDeckEditorVisual::restartLayout() { - for (auto it = dockToActions.begin(); it != dockToActions.end(); ++it) { - QDockWidget *dockWidget = it.key(); - const DockActions &actions = it.value(); - - actions.aFloating->setEnabled(false); + for (auto dockWidget : dockToActions.keys()) { dockWidget->setFloating(false); } - dockToActions[cardInfoDockWidget].aVisible->setChecked(true); - dockToActions[deckDockWidget].aVisible->setChecked(true); - dockToActions[filterDockWidget].aVisible->setChecked(false); - dockToActions[printingSelectorDockWidget].aVisible->setChecked( - !SettingsCache::instance().getOverrideAllCardArtWithPersonalPreference()); - deckDockWidget->setVisible(true); cardInfoDockWidget->setVisible(true); filterDockWidget->setVisible(false); @@ -377,15 +356,6 @@ void TabDeckEditorVisual::retranslateUi() */ bool TabDeckEditorVisual::eventFilter(QObject *o, QEvent *e) { - if (e->type() == QEvent::Close) { - auto dockWidget = qobject_cast(o); - if (dockToActions.contains(dockWidget)) { - DockActions actions = dockToActions.value(dockWidget); - actions.aVisible->setChecked(false); - actions.aFloating->setEnabled(false); - } - } - if (o == this && e->type() == QEvent::Hide) { LayoutsSettings &layouts = SettingsCache::instance().layouts(); layouts.setDeckEditorLayoutState(saveState()); @@ -397,47 +367,3 @@ bool TabDeckEditorVisual::eventFilter(QObject *o, QEvent *e) } return false; } - -/** @brief Toggles dock visibility based on the corresponding menu action. */ -void TabDeckEditorVisual::dockVisibleTriggered() -{ - QObject *o = sender(); - for (auto it = dockToActions.begin(); it != dockToActions.end(); ++it) { - QDockWidget *dockWidget = it.key(); - const DockActions &actions = it.value(); - - if (o == actions.aVisible) { - dockWidget->setHidden(!actions.aVisible->isChecked()); - actions.aFloating->setEnabled(actions.aVisible->isChecked()); - return; - } - } -} - -/** @brief Toggles dock floating state based on the corresponding menu action. */ -void TabDeckEditorVisual::dockFloatingTriggered() -{ - QObject *o = sender(); - - for (auto it = dockToActions.begin(); it != dockToActions.end(); ++it) { - QDockWidget *dockWidget = it.key(); - const DockActions &actions = it.value(); - - if (o == actions.aFloating) { - dockWidget->setFloating(actions.aFloating->isChecked()); - return; - } - } -} - -/** @brief Updates menu checkboxes when a dock's top-level/floating state changes. */ -void TabDeckEditorVisual::dockTopLevelChanged(bool topLevel) -{ - QObject *o = sender(); - - auto dockWidget = qobject_cast(o); - if (dockToActions.contains(dockWidget)) { - DockActions actions = dockToActions.value(dockWidget); - actions.aFloating->setChecked(topLevel); - } -} 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 2f1d11d82..371699c4d 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 @@ -84,22 +84,6 @@ protected slots: */ bool eventFilter(QObject *o, QEvent *e) override; - /** - * @brief Triggered when a dock visibility menu item is clicked. - */ - void dockVisibleTriggered() override; - - /** - * @brief Triggered when a dock floating menu item is clicked. - */ - void dockFloatingTriggered() override; - - /** - * @brief Triggered when a dock top-level state changes. - * @param topLevel True if the dock became floating. - */ - void dockTopLevelChanged(bool topLevel) override; - protected: TabDeckEditorVisualTabWidget *tabContainer; ///< Tab container holding different visual widgets.