[TabGame] Automatically sync view menu actions (#6529)

This commit is contained in:
RickyRister 2026-01-16 17:22:48 -08:00 committed by GitHub
parent d579c82cb9
commit 9c07c7a963
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 58 additions and 193 deletions

View file

@ -20,6 +20,7 @@
#include "../interface/widgets/utility/line_edit_completer.h" #include "../interface/widgets/utility/line_edit_completer.h"
#include "../interface/window_main.h" #include "../interface/window_main.h"
#include "../main.h" #include "../main.h"
#include "../utility/visibility_change_listener.h"
#include "tab_supervisor.h" #include "tab_supervisor.h"
#include <QAction> #include <QAction>
@ -337,23 +338,18 @@ void TabGame::retranslateUi()
} }
viewMenu->setTitle(tr("&View")); viewMenu->setTitle(tr("&View"));
cardInfoDockMenu->setTitle(tr("Card Info"));
messageLayoutDockMenu->setTitle(tr("Messages"));
playerListDockMenu->setTitle(tr("Player List"));
aCardInfoDockVisible->setText(tr("Visible")); dockToActions[cardInfoDock].menu->setTitle(tr("Card Info"));
aCardInfoDockFloating->setText(tr("Floating")); dockToActions[messageLayoutDock].menu->setTitle(tr("Messages"));
dockToActions[playerListDock].menu->setTitle(tr("Player List"));
aMessageLayoutDockVisible->setText(tr("Visible"));
aMessageLayoutDockFloating->setText(tr("Floating"));
aPlayerListDockVisible->setText(tr("Visible"));
aPlayerListDockFloating->setText(tr("Floating"));
if (replayDock) { if (replayDock) {
replayDockMenu->setTitle(tr("Replay Timeline")); dockToActions[replayDock].menu->setTitle(tr("Replay Timeline"));
aReplayDockVisible->setText(tr("Visible")); }
aReplayDockFloating->setText(tr("Floating"));
for (auto &actions : dockToActions.values()) {
actions.aVisible->setText(tr("Visible"));
actions.aFloating->setText(tr("Floating"));
} }
aResetLayout->setText(tr("Reset layout")); aResetLayout->setText(tr("Reset layout"));
@ -1038,40 +1034,12 @@ void TabGame::createViewMenuItems()
{ {
viewMenu = new QMenu(this); viewMenu = new QMenu(this);
cardInfoDockMenu = viewMenu->addMenu(QString()); registerDockWidget(viewMenu, cardInfoDock);
messageLayoutDockMenu = viewMenu->addMenu(QString()); registerDockWidget(viewMenu, messageLayoutDock);
playerListDockMenu = viewMenu->addMenu(QString()); registerDockWidget(viewMenu, playerListDock);
aCardInfoDockVisible = cardInfoDockMenu->addAction(QString());
aCardInfoDockVisible->setCheckable(true);
connect(aCardInfoDockVisible, &QAction::triggered, this, &TabGame::dockVisibleTriggered);
aCardInfoDockFloating = cardInfoDockMenu->addAction(QString());
aCardInfoDockFloating->setCheckable(true);
connect(aCardInfoDockFloating, &QAction::triggered, this, &TabGame::dockFloatingTriggered);
aMessageLayoutDockVisible = messageLayoutDockMenu->addAction(QString());
aMessageLayoutDockVisible->setCheckable(true);
connect(aMessageLayoutDockVisible, &QAction::triggered, this, &TabGame::dockVisibleTriggered);
aMessageLayoutDockFloating = messageLayoutDockMenu->addAction(QString());
aMessageLayoutDockFloating->setCheckable(true);
connect(aMessageLayoutDockFloating, &QAction::triggered, this, &TabGame::dockFloatingTriggered);
aPlayerListDockVisible = playerListDockMenu->addAction(QString());
aPlayerListDockVisible->setCheckable(true);
connect(aPlayerListDockVisible, &QAction::triggered, this, &TabGame::dockVisibleTriggered);
aPlayerListDockFloating = playerListDockMenu->addAction(QString());
aPlayerListDockFloating->setCheckable(true);
connect(aPlayerListDockFloating, &QAction::triggered, this, &TabGame::dockFloatingTriggered);
if (replayDock) { if (replayDock) {
replayDockMenu = viewMenu->addMenu(QString()); registerDockWidget(viewMenu, replayDock);
aReplayDockVisible = replayDockMenu->addAction(QString());
aReplayDockVisible->setCheckable(true);
connect(aReplayDockVisible, &QAction::triggered, this, &TabGame::dockVisibleTriggered);
aReplayDockFloating = replayDockMenu->addAction(QString());
aReplayDockFloating->setCheckable(true);
connect(aReplayDockFloating, &QAction::triggered, this, &TabGame::dockFloatingTriggered);
} }
viewMenu->addSeparator(); viewMenu->addSeparator();
@ -1083,6 +1051,36 @@ void TabGame::createViewMenuItems()
addTabMenu(viewMenu); addTabMenu(viewMenu);
} }
void TabGame::registerDockWidget(QMenu *_viewMenu, QDockWidget *widget)
{
QMenu *menu = _viewMenu->addMenu(QString());
QAction *aVisible = menu->addAction(QString());
aVisible->setCheckable(true);
QAction *aFloating = menu->addAction(QString());
aFloating->setCheckable(true);
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
auto filter = new VisibilityChangeListener(widget);
connect(filter, &VisibilityChangeListener::visibilityChanged, aVisible,
[aVisible](bool visible) { aVisible->setChecked(visible); });
dockToActions.insert(widget, {menu, aVisible, aFloating});
}
void TabGame::loadLayout() void TabGame::loadLayout()
{ {
LayoutsSettings &layouts = SettingsCache::instance().layouts(); LayoutsSettings &layouts = SettingsCache::instance().layouts();
@ -1110,24 +1108,6 @@ void TabGame::loadLayout()
playerListDock->setMaximumSize(layouts.getGamePlayerListSize()); playerListDock->setMaximumSize(layouts.getGamePlayerListSize());
} }
aCardInfoDockVisible->setChecked(cardInfoDock->isVisible());
aMessageLayoutDockVisible->setChecked(messageLayoutDock->isVisible());
aPlayerListDockVisible->setChecked(playerListDock->isVisible());
aCardInfoDockFloating->setEnabled(aCardInfoDockVisible->isChecked());
aMessageLayoutDockFloating->setEnabled(aMessageLayoutDockVisible->isChecked());
aPlayerListDockFloating->setEnabled(aPlayerListDockVisible->isChecked());
aCardInfoDockFloating->setChecked(cardInfoDock->isFloating());
aMessageLayoutDockFloating->setChecked(messageLayoutDock->isFloating());
aPlayerListDockFloating->setChecked(playerListDock->isFloating());
if (replayDock) {
aReplayDockVisible->setChecked(replayDock->isVisible());
aReplayDockFloating->setEnabled(aReplayDockVisible->isChecked());
aReplayDockFloating->setChecked(replayDock->isFloating());
}
QTimer::singleShot(100, this, &TabGame::freeDocksSize); QTimer::singleShot(100, this, &TabGame::freeDocksSize);
} }
@ -1158,14 +1138,6 @@ void TabGame::actResetLayout()
playerListDock->setFloating(false); playerListDock->setFloating(false);
messageLayoutDock->setFloating(false); messageLayoutDock->setFloating(false);
aCardInfoDockVisible->setChecked(true);
aPlayerListDockVisible->setChecked(true);
aMessageLayoutDockVisible->setChecked(true);
aCardInfoDockFloating->setChecked(false);
aPlayerListDockFloating->setChecked(false);
aMessageLayoutDockFloating->setChecked(false);
addDockWidget(Qt::RightDockWidgetArea, cardInfoDock); addDockWidget(Qt::RightDockWidgetArea, cardInfoDock);
addDockWidget(Qt::RightDockWidgetArea, playerListDock); addDockWidget(Qt::RightDockWidgetArea, playerListDock);
addDockWidget(Qt::RightDockWidgetArea, messageLayoutDock); addDockWidget(Qt::RightDockWidgetArea, messageLayoutDock);
@ -1174,8 +1146,6 @@ void TabGame::actResetLayout()
replayDock->setVisible(true); replayDock->setVisible(true);
replayDock->setFloating(false); replayDock->setFloating(false);
addDockWidget(Qt::BottomDockWidgetArea, replayDock); addDockWidget(Qt::BottomDockWidgetArea, replayDock);
aReplayDockVisible->setChecked(true);
aReplayDockFloating->setChecked(false);
cardInfoDock->setMinimumSize(250, 360); cardInfoDock->setMinimumSize(250, 360);
cardInfoDock->setMaximumSize(250, 360); cardInfoDock->setMaximumSize(250, 360);
@ -1227,9 +1197,6 @@ void TabGame::createReplayDock(GameReplay *replay)
QDockWidget::DockWidgetMovable); QDockWidget::DockWidgetMovable);
replayDock->setWidget(replayManager); replayDock->setWidget(replayManager);
replayDock->setFloating(false); replayDock->setFloating(false);
replayDock->installEventFilter(this);
connect(replayDock, &QDockWidget::topLevelChanged, this, &TabGame::dockTopLevelChanged);
} }
void TabGame::createDeckViewContainerWidget(bool bReplay) void TabGame::createDeckViewContainerWidget(bool bReplay)
@ -1268,9 +1235,6 @@ void TabGame::createCardInfoDock(bool bReplay)
QDockWidget::DockWidgetMovable); QDockWidget::DockWidgetMovable);
cardInfoDock->setWidget(cardBoxLayoutWidget); cardInfoDock->setWidget(cardBoxLayoutWidget);
cardInfoDock->setFloating(false); cardInfoDock->setFloating(false);
cardInfoDock->installEventFilter(this);
connect(cardInfoDock, &QDockWidget::topLevelChanged, this, &TabGame::dockTopLevelChanged);
} }
void TabGame::createPlayerListDock(bool bReplay) void TabGame::createPlayerListDock(bool bReplay)
@ -1290,9 +1254,6 @@ void TabGame::createPlayerListDock(bool bReplay)
QDockWidget::DockWidgetMovable); QDockWidget::DockWidgetMovable);
playerListDock->setWidget(playerListWidget); playerListDock->setWidget(playerListWidget);
playerListDock->setFloating(false); playerListDock->setFloating(false);
playerListDock->installEventFilter(this);
connect(playerListDock, &QDockWidget::topLevelChanged, this, &TabGame::dockTopLevelChanged);
} }
void TabGame::createMessageDock(bool bReplay) void TabGame::createMessageDock(bool bReplay)
@ -1373,9 +1334,6 @@ void TabGame::createMessageDock(bool bReplay)
QDockWidget::DockWidgetMovable); QDockWidget::DockWidgetMovable);
messageLayoutDock->setWidget(messageLogLayoutWidget); messageLayoutDock->setWidget(messageLogLayoutWidget);
messageLayoutDock->setFloating(false); messageLayoutDock->setFloating(false);
messageLayoutDock->installEventFilter(this);
connect(messageLayoutDock, &QDockWidget::topLevelChanged, this, &TabGame::dockTopLevelChanged);
} }
void TabGame::hideEvent(QHideEvent *event) void TabGame::hideEvent(QHideEvent *event)
@ -1398,103 +1356,3 @@ void TabGame::hideEvent(QHideEvent *event)
Tab::hideEvent(event); Tab::hideEvent(event);
} }
// Method uses to sync docks state with menu items state
bool TabGame::eventFilter(QObject *o, QEvent *e)
{
if (e->type() == QEvent::Close) {
if (o == cardInfoDock) {
aCardInfoDockVisible->setChecked(false);
aCardInfoDockFloating->setEnabled(false);
} else if (o == messageLayoutDock) {
aMessageLayoutDockVisible->setChecked(false);
aMessageLayoutDockFloating->setEnabled(false);
} else if (o == playerListDock) {
aPlayerListDockVisible->setChecked(false);
aPlayerListDockFloating->setEnabled(false);
} else if (o == replayDock) {
aReplayDockVisible->setChecked(false);
aReplayDockFloating->setEnabled(false);
}
}
return false;
}
void TabGame::dockVisibleTriggered()
{
QObject *o = sender();
if (o == aCardInfoDockVisible) {
cardInfoDock->setVisible(aCardInfoDockVisible->isChecked());
aCardInfoDockFloating->setEnabled(aCardInfoDockVisible->isChecked());
return;
}
if (o == aMessageLayoutDockVisible) {
messageLayoutDock->setVisible(aMessageLayoutDockVisible->isChecked());
aMessageLayoutDockFloating->setEnabled(aMessageLayoutDockVisible->isChecked());
return;
}
if (o == aPlayerListDockVisible) {
playerListDock->setVisible(aPlayerListDockVisible->isChecked());
aPlayerListDockFloating->setEnabled(aPlayerListDockVisible->isChecked());
return;
}
if (o == aReplayDockVisible) {
replayDock->setVisible(aReplayDockVisible->isChecked());
aReplayDockFloating->setEnabled(aReplayDockVisible->isChecked());
return;
}
}
void TabGame::dockFloatingTriggered()
{
QObject *o = sender();
if (o == aCardInfoDockFloating) {
cardInfoDock->setFloating(aCardInfoDockFloating->isChecked());
return;
}
if (o == aMessageLayoutDockFloating) {
messageLayoutDock->setFloating(aMessageLayoutDockFloating->isChecked());
return;
}
if (o == aPlayerListDockFloating) {
playerListDock->setFloating(aPlayerListDockFloating->isChecked());
return;
}
if (o == aReplayDockFloating) {
replayDock->setFloating(aReplayDockFloating->isChecked());
return;
}
}
void TabGame::dockTopLevelChanged(bool topLevel)
{
retranslateUi();
QObject *o = sender();
if (o == cardInfoDock) {
aCardInfoDockFloating->setChecked(topLevel);
return;
}
if (o == messageLayoutDock) {
aMessageLayoutDockFloating->setChecked(topLevel);
return;
}
if (o == playerListDock) {
aPlayerListDockFloating->setChecked(topLevel);
return;
}
if (o == replayDock) {
aReplayDockFloating->setChecked(topLevel);
return;
}
}

View file

@ -78,16 +78,26 @@ private:
QWidget *gamePlayAreaWidget, *deckViewContainerWidget; QWidget *gamePlayAreaWidget, *deckViewContainerWidget;
QDockWidget *cardInfoDock, *messageLayoutDock, *playerListDock, *replayDock; QDockWidget *cardInfoDock, *messageLayoutDock, *playerListDock, *replayDock;
QAction *playersSeparator; QAction *playersSeparator;
QMenu *gameMenu, *viewMenu, *cardInfoDockMenu, *messageLayoutDockMenu, *playerListDockMenu, *replayDockMenu; QMenu *gameMenu, *viewMenu;
TearOffMenu *phasesMenu; TearOffMenu *phasesMenu;
QAction *aGameInfo, *aConcede, *aLeaveGame, *aNextPhase, *aNextPhaseAction, *aNextTurn, *aReverseTurn, QAction *aGameInfo, *aConcede, *aLeaveGame, *aNextPhase, *aNextPhaseAction, *aNextTurn, *aReverseTurn,
*aRemoveLocalArrows, *aRotateViewCW, *aRotateViewCCW, *aResetLayout, *aResetReplayLayout; *aRemoveLocalArrows, *aRotateViewCW, *aRotateViewCCW, *aResetLayout, *aResetReplayLayout;
QAction *aCardInfoDockVisible, *aCardInfoDockFloating, *aMessageLayoutDockVisible, *aMessageLayoutDockFloating,
*aPlayerListDockVisible, *aPlayerListDockFloating, *aReplayDockVisible, *aReplayDockFloating;
QAction *aFocusChat; QAction *aFocusChat;
QList<QAction *> phaseActions; QList<QAction *> phaseActions;
QAction *aCardMenu; QAction *aCardMenu;
/**
* @brief The actions associated with managing a QDockWidget
*/
struct DockActions
{
QMenu *menu;
QAction *aVisible;
QAction *aFloating;
};
QMap<QDockWidget *, DockActions> dockToActions;
Player *addPlayer(Player *newPlayer); Player *addPlayer(Player *newPlayer);
void addLocalPlayer(Player *newPlayer, int playerId); void addLocalPlayer(Player *newPlayer, int playerId);
void processRemotePlayerDeckSelect(QString deckList, int playerId, QString playerName); void processRemotePlayerDeckSelect(QString deckList, int playerId, QString playerName);
@ -107,6 +117,7 @@ private:
void createMenuItems(); void createMenuItems();
void createReplayMenuItems(); void createReplayMenuItems();
void createViewMenuItems(); void createViewMenuItems();
void registerDockWidget(QMenu *_viewMenu, QDockWidget *widget);
void createCardInfoDock(bool bReplay = false); void createCardInfoDock(bool bReplay = false);
void createPlayerListDock(bool bReplay = false); void createPlayerListDock(bool bReplay = false);
void createMessageDock(bool bReplay = false); void createMessageDock(bool bReplay = false);
@ -156,10 +167,6 @@ private slots:
void freeDocksSize(); void freeDocksSize();
void hideEvent(QHideEvent *event) override; void hideEvent(QHideEvent *event) override;
bool eventFilter(QObject *o, QEvent *e) override;
void dockVisibleTriggered();
void dockFloatingTriggered();
void dockTopLevelChanged(bool topLevel);
protected slots: protected slots:
void closeEvent(QCloseEvent *event) override; void closeEvent(QCloseEvent *event) override;