diff --git a/cockatrice/src/game_graphics/player/menu/card_menu.cpp b/cockatrice/src/game_graphics/player/menu/card_menu.cpp index 9f00c0cba..96835bcf5 100644 --- a/cockatrice/src/game_graphics/player/menu/card_menu.cpp +++ b/cockatrice/src/game_graphics/player/menu/card_menu.cpp @@ -123,7 +123,7 @@ CardMenu::CardMenu(PlayerGraphicsItem *_player, CardItem *_card, bool _shortcuts aRevealToAll = new QAction(this); - mCardCounters = new QMenu; + mCardCounters = new QMenu(this); // Card counters for (int i = 0; i < 6; ++i) { @@ -225,7 +225,7 @@ void CardMenu::createTableMenu(bool canModifyCard) } addSeparator(); addAction(aClone); - addMenu(new MoveMenu(player)); + addMenu(new MoveMenu(player, this)); addSeparator(); addAction(aAttach); if (card->getAttachedTo()) { @@ -233,7 +233,7 @@ void CardMenu::createTableMenu(bool canModifyCard) } addAction(aDrawArrow); addSeparator(); - addMenu(new PtMenu(player)); + addMenu(new PtMenu(player, this)); addAction(aSetAnnotation); addSeparator(); addAction(aReduceLifeByPower); @@ -275,7 +275,7 @@ void CardMenu::createStackMenu(bool canModifyCard) addAction(aPlayFacedown); addSeparator(); addAction(aClone); - addMenu(new MoveMenu(player)); + addMenu(new MoveMenu(player, this)); addSeparator(); addAction(aAttach); addAction(aDrawArrow); @@ -304,7 +304,7 @@ void CardMenu::createGraveyardOrExileMenu(bool canModifyCard) addAction(aPlayFacedown); addSeparator(); addAction(aClone); - addMenu(new MoveMenu(player)); + addMenu(new MoveMenu(player, this)); addSeparator(); addAction(aAttach); addAction(aDrawArrow); @@ -342,7 +342,7 @@ void CardMenu::createHandOrCustomZoneMenu(bool canModifyCard) addSeparator(); addAction(aClone); - addMenu(new MoveMenu(player)); + addMenu(new MoveMenu(player, this)); // actions that are really wonky when done from deck or sideboard if (card->getZone()->getName() == ZoneNames::HAND) { @@ -366,7 +366,7 @@ void CardMenu::createHandOrCustomZoneMenu(bool canModifyCard) void CardMenu::createZonelessMenu(bool canModifyCard) { if (canModifyCard) { - addMenu(new MoveMenu(player)); + addMenu(new MoveMenu(player, this)); } } @@ -415,7 +415,7 @@ void CardMenu::addRelatedCardView() } addSeparator(); - auto viewRelatedCards = new QMenu(tr("View related cards")); + auto viewRelatedCards = new QMenu(tr("View related cards"), this); addMenu(viewRelatedCards); for (const CardRelation *relatedCard : relatedCards) { QString relatedCardName = relatedCard->getName(); diff --git a/cockatrice/src/game_graphics/player/menu/move_menu.cpp b/cockatrice/src/game_graphics/player/menu/move_menu.cpp index b81c4619b..24bfa3b0c 100644 --- a/cockatrice/src/game_graphics/player/menu/move_menu.cpp +++ b/cockatrice/src/game_graphics/player/menu/move_menu.cpp @@ -10,7 +10,7 @@ #include #include -MoveMenu::MoveMenu(PlayerGraphicsItem *player) : QMenu(tr("Move to")) +MoveMenu::MoveMenu(PlayerGraphicsItem *player, QWidget *parent) : QMenu(tr("Move to"), parent) { aMoveToTopLibrary = new QAction(this); aMoveToTopLibrary->setData(cmMoveToTopLibrary); diff --git a/cockatrice/src/game_graphics/player/menu/move_menu.h b/cockatrice/src/game_graphics/player/menu/move_menu.h index f1f239abd..a2cb304aa 100644 --- a/cockatrice/src/game_graphics/player/menu/move_menu.h +++ b/cockatrice/src/game_graphics/player/menu/move_menu.h @@ -17,7 +17,7 @@ class MoveMenu : public QMenu Q_OBJECT public: - explicit MoveMenu(PlayerGraphicsItem *player); + explicit MoveMenu(PlayerGraphicsItem *player, QWidget *parent); void setShortcutsActive(); void retranslateUi(); diff --git a/cockatrice/src/game_graphics/player/menu/pt_menu.cpp b/cockatrice/src/game_graphics/player/menu/pt_menu.cpp index e6c65fcfb..67e98bd76 100644 --- a/cockatrice/src/game_graphics/player/menu/pt_menu.cpp +++ b/cockatrice/src/game_graphics/player/menu/pt_menu.cpp @@ -9,7 +9,7 @@ #include #include -PtMenu::PtMenu(PlayerGraphicsItem *player) : QMenu(tr("Power / toughness")) +PtMenu::PtMenu(PlayerGraphicsItem *player, QWidget *parent) : QMenu(tr("Power / toughness"), parent) { PlayerActions *playerActions = player->getLogic()->getPlayerActions(); diff --git a/cockatrice/src/game_graphics/player/menu/pt_menu.h b/cockatrice/src/game_graphics/player/menu/pt_menu.h index aaf17cead..987f033f8 100644 --- a/cockatrice/src/game_graphics/player/menu/pt_menu.h +++ b/cockatrice/src/game_graphics/player/menu/pt_menu.h @@ -18,7 +18,7 @@ class PtMenu : public QMenu Q_OBJECT public: - explicit PtMenu(PlayerGraphicsItem *player); + explicit PtMenu(PlayerGraphicsItem *player, QWidget *parent); void retranslateUi(); void setShortcutsActive(); diff --git a/cockatrice/src/interface/widgets/tabs/tab_game.cpp b/cockatrice/src/interface/widgets/tabs/tab_game.cpp index 01d021907..055ab321c 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_game.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_game.cpp @@ -330,6 +330,9 @@ void TabGame::emitUserEvent() TabGame::~TabGame() { + if (aCardMenu && aCardMenu->menu() && aCardMenu->menu() != emptyCardMenu) { + delete aCardMenu->menu(); + } for (auto &player : game->getPlayerManager()->getPlayers()) { player->clear(); } @@ -1158,10 +1161,16 @@ QString TabGame::getTabText() const /** * @param menu The menu to set. Pass in nullptr to set the menu to empty. + * + * The previous card menu is deleted here: QAction::setMenu() does not take ownership, so whoever installs the menu + * (this widget) has to dispose of the one it replaces. The empty placeholder menu is reused instead of deleted. */ void TabGame::setCardMenu(CardMenu *menu) { - if (!aCardMenu) { + if (!aCardMenu || !emptyCardMenu) { + if (menu) { + menu->deleteLater(); + } return; } @@ -1171,10 +1180,11 @@ void TabGame::setCardMenu(CardMenu *menu) gameView->viewport()->update(); } } - if (menu) { - aCardMenu->setMenu(menu); - } else { - aCardMenu->setMenu(new QMenu); + + QMenu *previousMenu = aCardMenu->menu(); + aCardMenu->setMenu(menu ? menu : emptyCardMenu); + if (previousMenu && previousMenu != emptyCardMenu && previousMenu != menu) { + previousMenu->deleteLater(); } } @@ -1258,7 +1268,8 @@ void TabGame::createMenuItems() gameMenu->addSeparator(); - aCardMenu = gameMenu->addMenu(new QMenu(this)); + emptyCardMenu = new QMenu(this); + aCardMenu = gameMenu->addMenu(emptyCardMenu); // Sync the new action with the same state the dock button already shows. updateInviteButtonState(); @@ -1290,6 +1301,7 @@ void TabGame::createReplayMenuItems() gameMenu->addAction(aLeaveGame); aCardMenu = nullptr; + emptyCardMenu = nullptr; addTabMenu(gameMenu); } diff --git a/cockatrice/src/interface/widgets/tabs/tab_game.h b/cockatrice/src/interface/widgets/tabs/tab_game.h index 142c02999..5c2af82b4 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_game.h +++ b/cockatrice/src/interface/widgets/tabs/tab_game.h @@ -101,6 +101,8 @@ private: QAction *aInviteToGame = nullptr; QList phaseActions; QAction *aCardMenu; + /** @brief Placeholder submenu shown when no card is selected; reused instead of reallocated. */ + QMenu *emptyCardMenu = nullptr; /** * @brief The actions associated with managing a QDockWidget