From fb23cc8c7a3ca97dcbd865901cfbc69e4d54b872 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Fri, 12 Sep 2025 19:52:05 +0200 Subject: [PATCH] Refactor player menus into helper classes (#6121) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Refactor player menus into helper classes. Took 2 hours 6 minutes Took 11 minutes * Lint. Took 6 minutes Took 22 seconds * Refactor card and move menu. Took 1 hour 6 minutes Took 36 seconds Took 52 seconds * Set active shortcuts, move player info stuff to card menu. Took 25 minutes Took 18 seconds * Refactor say and utility menu. Took 54 minutes Took 2 minutes Took 5 minutes Took 11 minutes * Rename folder. Took 24 minutes Took 6 minutes * Refactor sideboard menu. Took 26 minutes * Remove unused variable in constructor. Took 42 seconds * Lint. Took 11 minutes * Nullptr check Took 8 minutes * Use localOrJudge check Took 6 minutes * Fix the build. Took 7 minutes Took 35 seconds * PlayerList things. Took 16 minutes * Retranslate and set shortcuts for everything. Took 10 minutes * Correctly nullptr out sayMenu if not local Took 3 minutes * Don't check playerInfo in sbMenu shortcutsActive Took 3 minutes --------- Co-authored-by: Lukas BrĂ¼bach --- cockatrice/CMakeLists.txt | 13 +- cockatrice/src/game/player/menu/card_menu.cpp | 498 ++++++ cockatrice/src/game/player/menu/card_menu.h | 47 + .../src/game/player/menu/custom_zone_menu.cpp | 41 + .../src/game/player/menu/custom_zone_menu.h | 21 + .../src/game/player/menu/grave_menu.cpp | 90 ++ cockatrice/src/game/player/menu/grave_menu.h | 37 + cockatrice/src/game/player/menu/hand_menu.cpp | 92 ++ cockatrice/src/game/player/menu/hand_menu.h | 52 + .../src/game/player/menu/library_menu.cpp | 283 ++++ .../src/game/player/menu/library_menu.h | 98 ++ cockatrice/src/game/player/menu/move_menu.cpp | 63 + cockatrice/src/game/player/menu/move_menu.h | 24 + .../src/game/player/menu/player_menu.cpp | 312 ++++ cockatrice/src/game/player/menu/player_menu.h | 93 ++ cockatrice/src/game/player/menu/pt_menu.cpp | 78 + cockatrice/src/game/player/menu/pt_menu.h | 29 + cockatrice/src/game/player/menu/rfg_menu.cpp | 69 + cockatrice/src/game/player/menu/rfg_menu.h | 31 + cockatrice/src/game/player/menu/say_menu.cpp | 28 + cockatrice/src/game/player/menu/say_menu.h | 18 + .../src/game/player/menu/sideboard_menu.cpp | 33 + .../src/game/player/menu/sideboard_menu.h | 23 + .../src/game/player/menu/utility_menu.cpp | 117 ++ .../src/game/player/menu/utility_menu.h | 46 + cockatrice/src/game/player/player.cpp | 3 - cockatrice/src/game/player/player.h | 2 +- cockatrice/src/game/player/player_actions.cpp | 12 +- cockatrice/src/game/player/player_menu.cpp | 1394 ----------------- cockatrice/src/game/player/player_menu.h | 131 -- 30 files changed, 2242 insertions(+), 1536 deletions(-) create mode 100644 cockatrice/src/game/player/menu/card_menu.cpp create mode 100644 cockatrice/src/game/player/menu/card_menu.h create mode 100644 cockatrice/src/game/player/menu/custom_zone_menu.cpp create mode 100644 cockatrice/src/game/player/menu/custom_zone_menu.h create mode 100644 cockatrice/src/game/player/menu/grave_menu.cpp create mode 100644 cockatrice/src/game/player/menu/grave_menu.h create mode 100644 cockatrice/src/game/player/menu/hand_menu.cpp create mode 100644 cockatrice/src/game/player/menu/hand_menu.h create mode 100644 cockatrice/src/game/player/menu/library_menu.cpp create mode 100644 cockatrice/src/game/player/menu/library_menu.h create mode 100644 cockatrice/src/game/player/menu/move_menu.cpp create mode 100644 cockatrice/src/game/player/menu/move_menu.h create mode 100644 cockatrice/src/game/player/menu/player_menu.cpp create mode 100644 cockatrice/src/game/player/menu/player_menu.h create mode 100644 cockatrice/src/game/player/menu/pt_menu.cpp create mode 100644 cockatrice/src/game/player/menu/pt_menu.h create mode 100644 cockatrice/src/game/player/menu/rfg_menu.cpp create mode 100644 cockatrice/src/game/player/menu/rfg_menu.h create mode 100644 cockatrice/src/game/player/menu/say_menu.cpp create mode 100644 cockatrice/src/game/player/menu/say_menu.h create mode 100644 cockatrice/src/game/player/menu/sideboard_menu.cpp create mode 100644 cockatrice/src/game/player/menu/sideboard_menu.h create mode 100644 cockatrice/src/game/player/menu/utility_menu.cpp create mode 100644 cockatrice/src/game/player/menu/utility_menu.h delete mode 100644 cockatrice/src/game/player/player_menu.cpp delete mode 100644 cockatrice/src/game/player/player_menu.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index dfe40b03d..b34a41410 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -232,8 +232,19 @@ set(cockatrice_SOURCES src/game/player/player_info.cpp src/game/player/player_list_widget.cpp src/game/player/player_manager.cpp - src/game/player/player_menu.cpp src/game/player/player_target.cpp + src/game/player/menu/card_menu.cpp + src/game/player/menu/custom_zone_menu.cpp + src/game/player/menu/grave_menu.cpp + src/game/player/menu/hand_menu.cpp + src/game/player/menu/library_menu.cpp + src/game/player/menu/move_menu.cpp + src/game/player/menu/player_menu.cpp + src/game/player/menu/pt_menu.cpp + src/game/player/menu/rfg_menu.cpp + src/game/player/menu/say_menu.cpp + src/game/player/menu/sideboard_menu.cpp + src/game/player/menu/utility_menu.cpp src/game/replay.cpp src/game/zones/card_zone.cpp src/game/zones/hand_zone.cpp diff --git a/cockatrice/src/game/player/menu/card_menu.cpp b/cockatrice/src/game/player/menu/card_menu.cpp new file mode 100644 index 000000000..4b45fce7d --- /dev/null +++ b/cockatrice/src/game/player/menu/card_menu.cpp @@ -0,0 +1,498 @@ +#include "card_menu.h" + +#include "../../../client/tabs/tab_game.h" +#include "../../../settings/card_counter_settings.h" +#include "../../board/card_item.h" +#include "../../cards/card_database_manager.h" +#include "../../zones/logic/view_zone_logic.h" +#include "../card_menu_action_type.h" +#include "../player.h" +#include "../player_actions.h" +#include "move_menu.h" +#include "pt_menu.h" + +CardMenu::CardMenu(Player *_player, const CardItem *_card, bool _shortcutsActive) + : player(_player), card(_card), shortcutsActive(_shortcutsActive) +{ + auto playerActions = player->getPlayerActions(); + + const QList &players = player->getGame()->getPlayerManager()->getPlayers().values(); + + for (auto playerToAdd : players) { + if (playerToAdd == player) { + continue; + } + playersInfo.append(qMakePair(playerToAdd->getPlayerInfo()->getName(), playerToAdd->getPlayerInfo()->getId())); + } + + connect(player->getGame()->getPlayerManager(), &PlayerManager::playerRemoved, this, &CardMenu::removePlayer); + + aTap = new QAction(this); + aTap->setData(cmTap); + connect(aTap, &QAction::triggered, playerActions, &PlayerActions::cardMenuAction); + aDoesntUntap = new QAction(this); + aDoesntUntap->setData(cmDoesntUntap); + connect(aDoesntUntap, &QAction::triggered, playerActions, &PlayerActions::cardMenuAction); + aAttach = new QAction(this); + connect(aAttach, &QAction::triggered, playerActions, &PlayerActions::actAttach); + aUnattach = new QAction(this); + connect(aUnattach, &QAction::triggered, playerActions, &PlayerActions::actUnattach); + aDrawArrow = new QAction(this); + connect(aDrawArrow, &QAction::triggered, playerActions, &PlayerActions::actDrawArrow); + aSetAnnotation = new QAction(this); + connect(aSetAnnotation, &QAction::triggered, playerActions, &PlayerActions::actSetAnnotation); + aFlip = new QAction(this); + aFlip->setData(cmFlip); + connect(aFlip, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); + aPeek = new QAction(this); + aPeek->setData(cmPeek); + connect(aPeek, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); + aClone = new QAction(this); + aClone->setData(cmClone); + connect(aClone, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); + aSelectAll = new QAction(this); + connect(aSelectAll, &QAction::triggered, playerActions, &PlayerActions::actSelectAll); + aSelectRow = new QAction(this); + connect(aSelectRow, &QAction::triggered, playerActions, &PlayerActions::actSelectRow); + aSelectColumn = new QAction(this); + connect(aSelectColumn, &QAction::triggered, playerActions, &PlayerActions::actSelectColumn); + + aPlay = new QAction(this); + connect(aPlay, &QAction::triggered, playerActions, &PlayerActions::actPlay); + aHide = new QAction(this); + connect(aHide, &QAction::triggered, playerActions, &PlayerActions::actHide); + aPlayFacedown = new QAction(this); + connect(aPlayFacedown, &QAction::triggered, playerActions, &PlayerActions::actPlayFacedown); + + mCardCounters = new QMenu; + + for (int i = 0; i < 6; ++i) { + auto *tempAddCounter = new QAction(this); + tempAddCounter->setData(9 + i * 1000); + auto *tempRemoveCounter = new QAction(this); + tempRemoveCounter->setData(10 + i * 1000); + auto *tempSetCounter = new QAction(this); + tempSetCounter->setData(11 + i * 1000); + aAddCounter.append(tempAddCounter); + aRemoveCounter.append(tempRemoveCounter); + aSetCounter.append(tempSetCounter); + connect(tempAddCounter, &QAction::triggered, playerActions, &PlayerActions::actCardCounterTrigger); + connect(tempRemoveCounter, &QAction::triggered, playerActions, &PlayerActions::actCardCounterTrigger); + connect(tempSetCounter, &QAction::triggered, playerActions, &PlayerActions::actCardCounterTrigger); + } + + setShortcutsActive(); + + retranslateUi(); + + if (card == nullptr) { + return; + } + + bool revealedCard = false; + bool writeableCard = player->getPlayerInfo()->getLocalOrJudge(); + if (auto *view = qobject_cast(card->getZone())) { + if (view->getRevealZone()) { + if (view->getWriteableRevealZone()) { + writeableCard = true; + } else { + revealedCard = true; + } + } + } + + if (revealedCard) { + addAction(aHide); + addAction(aClone); + addSeparator(); + addAction(aSelectAll); + addAction(aSelectColumn); + addRelatedCardView(); + } else if (writeableCard) { + + if (card->getZone()) { + if (card->getZone()->getName() == "table") { + createTableMenu(); + } else if (card->getZone()->getName() == "stack") { + createStackMenu(); + } else if (card->getZone()->getName() == "rfg" || card->getZone()->getName() == "grave") { + createGraveyardOrExileMenu(); + } else { + createHandOrCustomZoneMenu(); + } + } else { + addMenu(new MoveMenu(player)); + } + } else { + if (card->getZone() && card->getZone()->getName() != "hand") { + addAction(aDrawArrow); + addSeparator(); + addRelatedCardView(); + addRelatedCardActions(); + addSeparator(); + addAction(aClone); + addSeparator(); + addAction(aSelectAll); + } + } +} + +void CardMenu::removePlayer(Player *playerToRemove) +{ + for (auto it = playersInfo.begin(); it != playersInfo.end();) { + if (it->second == playerToRemove->getPlayerInfo()->getId()) { + it = playersInfo.erase(it); + } else { + ++it; + } + } +} + +void CardMenu::createTableMenu() +{ + // Card is on the battlefield + bool canModifyCard = player->getPlayerInfo()->judge || card->getOwner() == player; + + if (!canModifyCard) { + addRelatedCardView(); + addRelatedCardActions(); + + addSeparator(); + addAction(aDrawArrow); + addSeparator(); + addAction(aClone); + addSeparator(); + addAction(aSelectAll); + addAction(aSelectRow); + return; + } + + addAction(aTap); + addAction(aDoesntUntap); + addAction(aFlip); + if (card->getFaceDown()) { + addAction(aPeek); + } + + addRelatedCardView(); + addRelatedCardActions(); + + addSeparator(); + addAction(aAttach); + if (card->getAttachedTo()) { + addAction(aUnattach); + } + addAction(aDrawArrow); + addSeparator(); + addMenu(new PtMenu(player)); + addAction(aSetAnnotation); + addSeparator(); + addAction(aClone); + addMenu(new MoveMenu(player)); + addSeparator(); + addAction(aSelectAll); + addAction(aSelectRow); + + addSeparator(); + mCardCounters->clear(); + for (int i = 0; i < aAddCounter.size(); ++i) { + mCardCounters->addSeparator(); + mCardCounters->addAction(aAddCounter[i]); + if (card->getCounters().contains(i)) { + mCardCounters->addAction(aRemoveCounter[i]); + } + mCardCounters->addAction(aSetCounter[i]); + } + addSeparator(); + addMenu(mCardCounters); +} + +void CardMenu::createStackMenu() +{ + bool canModifyCard = player->getPlayerInfo()->judge || card->getOwner() == player; + + // Card is on the stack + if (canModifyCard) { + addAction(aAttach); + addAction(aDrawArrow); + addSeparator(); + addAction(aClone); + addMenu(new MoveMenu(player)); + addSeparator(); + addAction(aSelectAll); + } else { + addAction(aDrawArrow); + addSeparator(); + addAction(aClone); + addSeparator(); + addAction(aSelectAll); + } + + addRelatedCardView(); + addRelatedCardActions(); +} + +void CardMenu::createGraveyardOrExileMenu() +{ + bool canModifyCard = player->getPlayerInfo()->judge || card->getOwner() == player; + + // Card is in the graveyard or exile + if (canModifyCard) { + addAction(aPlay); + addAction(aPlayFacedown); + + addSeparator(); + addAction(aClone); + addMenu(new MoveMenu(player)); + addSeparator(); + addAction(aSelectAll); + addAction(aSelectColumn); + + addSeparator(); + addAction(aAttach); + addAction(aDrawArrow); + } else { + addAction(aClone); + addSeparator(); + addAction(aSelectAll); + addAction(aSelectColumn); + addSeparator(); + addAction(aDrawArrow); + } + + addRelatedCardView(); + addRelatedCardActions(); +} + +void CardMenu::createHandOrCustomZoneMenu() +{ + // Card is in hand or a custom zone specified by server + addAction(aPlay); + addAction(aPlayFacedown); + + QMenu *revealMenu = addMenu(tr("Re&veal to...")); + + initContextualPlayersMenu(revealMenu); + + connect(revealMenu, &QMenu::triggered, player->getPlayerActions(), &PlayerActions::actReveal); + + addSeparator(); + addAction(aClone); + addMenu(new MoveMenu(player)); + + // actions that are really wonky when done from deck or sideboard + if (card->getZone()->getName() == "hand") { + addSeparator(); + addAction(aAttach); + addAction(aDrawArrow); + } + + addSeparator(); + addAction(aSelectAll); + if (qobject_cast(card->getZone())) { + addAction(aSelectColumn); + } + + addRelatedCardView(); + if (card->getZone()->getName() == "hand") { + addRelatedCardActions(); + } +} + +void CardMenu::initContextualPlayersMenu(QMenu *menu) +{ + menu->addAction(tr("&All players"))->setData(-1); + menu->addSeparator(); + + for (const auto &playerInfo : playersInfo) { + menu->addAction(playerInfo.first)->setData(playerInfo.second); + } +} + +void CardMenu::addRelatedCardView() +{ + if (!card) { + return; + } + auto exactCard = card->getCard(); + if (!exactCard) { + return; + } + + bool atLeastOneGoodRelationFound = false; + QList relatedCards = exactCard.getInfo().getAllRelatedCards(); + for (const CardRelation *cardRelation : relatedCards) { + CardInfoPtr relatedCard = CardDatabaseManager::getInstance()->getCardInfo(cardRelation->getName()); + if (relatedCard != nullptr) { + atLeastOneGoodRelationFound = true; + break; + } + } + + if (!atLeastOneGoodRelationFound) { + return; + } + + addSeparator(); + auto viewRelatedCards = new QMenu(tr("View related cards")); + addMenu(viewRelatedCards); + for (const CardRelation *relatedCard : relatedCards) { + QString relatedCardName = relatedCard->getName(); + CardRef cardRef = {relatedCardName, exactCard.getPrinting().getUuid()}; + QAction *viewCard = viewRelatedCards->addAction(relatedCardName); + Q_UNUSED(viewCard); + + connect(viewCard, &QAction::triggered, player->getGame(), + [this, cardRef] { player->getGame()->getTab()->viewCardInfo(cardRef); }); + } +} + +void CardMenu::addRelatedCardActions() +{ + if (!card) { + return; + } + auto exactCard = card->getCard(); + if (!exactCard) { + return; + } + + QList relatedCards = exactCard.getInfo().getAllRelatedCards(); + if (relatedCards.isEmpty()) { + return; + } + + addSeparator(); + int index = 0; + QAction *createRelatedCards = nullptr; + for (const CardRelation *cardRelation : relatedCards) { + ExactCard relatedCard = CardDatabaseManager::getInstance()->getCardFromSameSet(cardRelation->getName(), + card->getCard().getPrinting()); + if (!relatedCard) { + relatedCard = CardDatabaseManager::getInstance()->getCard({cardRelation->getName()}); + } + if (!relatedCard) { + continue; + } + + QString relatedCardName; + if (relatedCard.getInfo().getPowTough().size() > 0) { + relatedCardName = relatedCard.getInfo().getPowTough() + " " + relatedCard.getName(); // "n/n name" + } else { + relatedCardName = relatedCard.getName(); // "name" + } + + QString text = tr("Token: "); + if (cardRelation->getDoesAttach()) { + text += + tr(cardRelation->getDoesTransform() ? "Transform into " : "Attach to ") + "\"" + relatedCardName + "\""; + } else if (cardRelation->getIsVariable()) { + text += "X " + relatedCardName; + } else if (cardRelation->getDefaultCount() != 1) { + text += QString::number(cardRelation->getDefaultCount()) + "x " + relatedCardName; + } else { + text += relatedCardName; + } + + if (createRelatedCards == nullptr) { + if (relatedCards.length() == 1) { + createRelatedCards = new QAction(text, this); // set actCreateAllRelatedCards with this text + break; // do not set an individual entry as there is only one entry + } else { + createRelatedCards = new QAction(tr("All tokens"), this); + } + } + + auto *createRelated = new QAction(text, this); + createRelated->setData(QVariant(index++)); + connect(createRelated, &QAction::triggered, player->getPlayerActions(), &PlayerActions::actCreateRelatedCard); + addAction(createRelated); + } + + if (createRelatedCards) { + if (shortcutsActive) { + createRelatedCards->setShortcuts( + SettingsCache::instance().shortcuts().getShortcut("Player/aCreateRelatedTokens")); + } + connect(createRelatedCards, &QAction::triggered, player->getPlayerActions(), + &PlayerActions::actCreateAllRelatedCards); + addAction(createRelatedCards); + } +} + +void CardMenu::retranslateUi() +{ + aSelectAll->setText(tr("&Select All")); + aSelectRow->setText(tr("S&elect Row")); + aSelectColumn->setText(tr("S&elect Column")); + + aPlay->setText(tr("&Play")); + aHide->setText(tr("&Hide")); + aPlayFacedown->setText(tr("Play &Face Down")); + //: Turn sideways or back again + aTap->setText(tr("&Tap / Untap")); + aDoesntUntap->setText(tr("Toggle &normal untapping")); + //: Turn face up/face down + aFlip->setText(tr("T&urn Over")); // Only the user facing names in client got renamed to "turn over" + // All code and proto bits are still unchanged (flip) for compatibility reasons + // A protocol rewrite with v3 could incorporate that, see #3100 + aPeek->setText(tr("&Peek at card face")); + aClone->setText(tr("&Clone")); + aAttach->setText(tr("Attac&h to card...")); + aUnattach->setText(tr("Unattac&h")); + aDrawArrow->setText(tr("&Draw arrow...")); + aSetAnnotation->setText(tr("&Set annotation...")); + + mCardCounters->setTitle(tr("Ca&rd counters")); + + auto &cardCounterSettings = SettingsCache::instance().cardCounters(); + + for (int i = 0; i < aAddCounter.size(); ++i) { + aAddCounter[i]->setText(tr("&Add counter (%1)").arg(cardCounterSettings.displayName(i))); + } + for (int i = 0; i < aRemoveCounter.size(); ++i) { + aRemoveCounter[i]->setText(tr("&Remove counter (%1)").arg(cardCounterSettings.displayName(i))); + } + for (int i = 0; i < aSetCounter.size(); ++i) { + aSetCounter[i]->setText(tr("&Set counters (%1)...").arg(cardCounterSettings.displayName(i))); + } +} + +void CardMenu::setShortcutsActive() +{ + ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); + + aHide->setShortcuts(shortcuts.getShortcut("Player/aHide")); + aPlay->setShortcuts(shortcuts.getShortcut("Player/aPlay")); + aTap->setShortcuts(shortcuts.getShortcut("Player/aTap")); + aDoesntUntap->setShortcuts(shortcuts.getShortcut("Player/aDoesntUntap")); + aFlip->setShortcuts(shortcuts.getShortcut("Player/aFlip")); + aPeek->setShortcuts(shortcuts.getShortcut("Player/aPeek")); + aClone->setShortcuts(shortcuts.getShortcut("Player/aClone")); + aAttach->setShortcuts(shortcuts.getShortcut("Player/aAttach")); + aUnattach->setShortcuts(shortcuts.getShortcut("Player/aUnattach")); + aDrawArrow->setShortcuts(shortcuts.getShortcut("Player/aDrawArrow")); + aSetAnnotation->setShortcuts(shortcuts.getShortcut("Player/aSetAnnotation")); + + aSelectAll->setShortcuts(shortcuts.getShortcut("Player/aSelectAll")); + aSelectRow->setShortcuts(shortcuts.getShortcut("Player/aSelectRow")); + aSelectColumn->setShortcuts(shortcuts.getShortcut("Player/aSelectColumn")); + + aPlayFacedown->setShortcuts(shortcuts.getShortcut("Player/aPlayFacedown")); + aPlay->setShortcuts(shortcuts.getShortcut("Player/aPlay")); + + static const QStringList colorWords = {"Red", "Yellow", "Green", "Cyan", "Purple", "Magenta"}; + for (int i = 0; i < aAddCounter.size(); i++) { + aAddCounter[i]->setShortcuts(shortcuts.getShortcut("Player/aCC" + colorWords[i])); + aRemoveCounter[i]->setShortcuts(shortcuts.getShortcut("Player/aRC" + colorWords[i])); + aSetCounter[i]->setShortcuts(shortcuts.getShortcut("Player/aSC" + colorWords[i])); + } + + // Don't enable always-active shortcuts in local games, since it causes keyboard shortcuts to work inconsistently + // when there are more than 1 player. + if (!player->getGame()->getGameState()->getIsLocalGame()) { + // unattach action is only active in card menu if the active card is attached. + // make unattach shortcut always active so that it consistently works when multiple cards are selected. + player->getGame()->getTab()->addAction(aUnattach); + } +} \ No newline at end of file diff --git a/cockatrice/src/game/player/menu/card_menu.h b/cockatrice/src/game/player/menu/card_menu.h new file mode 100644 index 000000000..931d0249f --- /dev/null +++ b/cockatrice/src/game/player/menu/card_menu.h @@ -0,0 +1,47 @@ +#ifndef COCKATRICE_CARD_MENU_H +#define COCKATRICE_CARD_MENU_H + +#include + +class CardItem; +class Player; +class CardMenu : public QMenu +{ + Q_OBJECT + +public: + explicit CardMenu(Player *player, const CardItem *card, bool shortcutsActive); + void removePlayer(Player *playerToRemove); + void createTableMenu(); + void createStackMenu(); + void createGraveyardOrExileMenu(); + void createHandOrCustomZoneMenu(); + + QMenu *mCardCounters; + + QAction *aPlay, *aPlayFacedown; + QAction *aHide; + QAction *aClone; + QAction *aSelectAll, *aSelectRow, *aSelectColumn; + QAction *aDrawArrow; + QAction *aTap, *aDoesntUntap; + QAction *aFlip, *aPeek; + QAction *aAttach, *aUnattach; + QAction *aSetAnnotation; + + QList aAddCounter, aSetCounter, aRemoveCounter; + +private: + Player *player; + const CardItem *card; + QList> playersInfo; + bool shortcutsActive; + + void addRelatedCardActions(); + void retranslateUi(); + void initContextualPlayersMenu(QMenu *menu); + void setShortcutsActive(); + void addRelatedCardView(); +}; + +#endif // COCKATRICE_CARD_MENU_H diff --git a/cockatrice/src/game/player/menu/custom_zone_menu.cpp b/cockatrice/src/game/player/menu/custom_zone_menu.cpp new file mode 100644 index 000000000..b0f3284c9 --- /dev/null +++ b/cockatrice/src/game/player/menu/custom_zone_menu.cpp @@ -0,0 +1,41 @@ +#include "custom_zone_menu.h" + +#include "../player.h" + +CustomZoneMenu::CustomZoneMenu(Player *_player) : player(_player) +{ + menuAction()->setVisible(false); + + connect(player, &Player::clearCustomZonesMenu, this, &CustomZoneMenu::clearCustomZonesMenu); + connect(player, &Player::addViewCustomZoneActionToCustomZoneMenu, this, + &CustomZoneMenu::addViewCustomZoneActionToCustomZoneMenu); + + retranslateUi(); +} + +void CustomZoneMenu::retranslateUi() +{ + setTitle(tr("C&ustom Zones")); + + if (player->getPlayerInfo()->getLocalOrJudge()) { + + for (auto aViewZone : actions()) { + aViewZone->setText(tr("View custom zone '%1'").arg(aViewZone->data().toString())); + } + } +} + +void CustomZoneMenu::clearCustomZonesMenu() +{ + clear(); + menuAction()->setVisible(false); +} + +void CustomZoneMenu::addViewCustomZoneActionToCustomZoneMenu(QString zoneName) +{ + menuAction()->setVisible(true); + QAction *aViewZone = addAction(tr("View custom zone '%1'").arg(zoneName)); + aViewZone->setData(zoneName); + connect(aViewZone, &QAction::triggered, this, + [zoneName, this]() { player->getGameScene()->toggleZoneView(player, zoneName, -1); }); +} \ No newline at end of file diff --git a/cockatrice/src/game/player/menu/custom_zone_menu.h b/cockatrice/src/game/player/menu/custom_zone_menu.h new file mode 100644 index 000000000..cf7b13f23 --- /dev/null +++ b/cockatrice/src/game/player/menu/custom_zone_menu.h @@ -0,0 +1,21 @@ +#ifndef COCKATRICE_CUSTOM_ZONE_MENU_H +#define COCKATRICE_CUSTOM_ZONE_MENU_H + +#include + +class Player; +class CustomZoneMenu : public QMenu +{ + Q_OBJECT +public: + explicit CustomZoneMenu(Player *player); + void retranslateUi(); + +private: + Player *player; +private slots: + void clearCustomZonesMenu(); + void addViewCustomZoneActionToCustomZoneMenu(QString zoneName); +}; + +#endif // COCKATRICE_CUSTOM_ZONE_MENU_H diff --git a/cockatrice/src/game/player/menu/grave_menu.cpp b/cockatrice/src/game/player/menu/grave_menu.cpp new file mode 100644 index 000000000..69cf537bf --- /dev/null +++ b/cockatrice/src/game/player/menu/grave_menu.cpp @@ -0,0 +1,90 @@ +#include "grave_menu.h" + +#include "../player.h" +#include "../player_actions.h" + +GraveyardMenu::GraveyardMenu(Player *_player, QWidget *parent) : TearOffMenu(parent), player(_player) +{ + createMoveActions(); + createViewActions(); + + addAction(aViewGraveyard); + + if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { + mRevealRandomGraveyardCard = addMenu(QString()); + QAction *newAction = mRevealRandomGraveyardCard->addAction(QString()); + newAction->setData(-1); + connect(newAction, &QAction::triggered, player->getPlayerActions(), + &PlayerActions::actRevealRandomGraveyardCard); + emit newPlayerActionCreated(newAction); + mRevealRandomGraveyardCard->addSeparator(); + + addSeparator(); + moveGraveMenu = addTearOffMenu(QString()); + moveGraveMenu->addAction(aMoveGraveToTopLibrary); + moveGraveMenu->addAction(aMoveGraveToBottomLibrary); + moveGraveMenu->addSeparator(); + moveGraveMenu->addAction(aMoveGraveToHand); + moveGraveMenu->addSeparator(); + moveGraveMenu->addAction(aMoveGraveToRfg); + } + + retranslateUi(); +} + +void GraveyardMenu::createMoveActions() +{ + auto grave = player->getGraveZone(); + + if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { + aMoveGraveToTopLibrary = new QAction(this); + aMoveGraveToTopLibrary->setData(QList() << "deck" << 0); + aMoveGraveToBottomLibrary = new QAction(this); + aMoveGraveToBottomLibrary->setData(QList() << "deck" << -1); + aMoveGraveToHand = new QAction(this); + aMoveGraveToHand->setData(QList() << "hand" << 0); + aMoveGraveToRfg = new QAction(this); + aMoveGraveToRfg->setData(QList() << "rfg" << 0); + + connect(aMoveGraveToTopLibrary, &QAction::triggered, grave, &PileZoneLogic::moveAllToZone); + connect(aMoveGraveToBottomLibrary, &QAction::triggered, grave, &PileZoneLogic::moveAllToZone); + connect(aMoveGraveToHand, &QAction::triggered, grave, &PileZoneLogic::moveAllToZone); + connect(aMoveGraveToRfg, &QAction::triggered, grave, &PileZoneLogic::moveAllToZone); + } +} + +void GraveyardMenu::createViewActions() +{ + PlayerActions *playerActions = player->getPlayerActions(); + + aViewGraveyard = new QAction(this); + connect(aViewGraveyard, &QAction::triggered, playerActions, &PlayerActions::actViewGraveyard); +} + +void GraveyardMenu::retranslateUi() +{ + setTitle(tr("&Graveyard")); + + aViewGraveyard->setText(tr("&View graveyard")); + + if (player->getPlayerInfo()->getLocalOrJudge()) { + moveGraveMenu->setTitle(tr("&Move graveyard to...")); + aMoveGraveToTopLibrary->setText(tr("&Top of library")); + aMoveGraveToBottomLibrary->setText(tr("&Bottom of library")); + aMoveGraveToHand->setText(tr("&Hand")); + aMoveGraveToRfg->setText(tr("&Exile")); + mRevealRandomGraveyardCard->setTitle(tr("Reveal random card to...")); + } +} + +void GraveyardMenu::setShortcutsActive() +{ + ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); + + aViewGraveyard->setShortcuts(shortcuts.getShortcut("Player/aViewGraveyard")); +} + +void GraveyardMenu::setShortcutsInactive() +{ + aViewGraveyard->setShortcut(QKeySequence()); +} \ No newline at end of file diff --git a/cockatrice/src/game/player/menu/grave_menu.h b/cockatrice/src/game/player/menu/grave_menu.h new file mode 100644 index 000000000..1e471aa6b --- /dev/null +++ b/cockatrice/src/game/player/menu/grave_menu.h @@ -0,0 +1,37 @@ +#ifndef COCKATRICE_GRAVE_MENU_H +#define COCKATRICE_GRAVE_MENU_H + +#include "../../../client/tearoff_menu.h" + +#include +#include + +class Player; +class GraveyardMenu : public TearOffMenu +{ + Q_OBJECT +signals: + void newPlayerActionCreated(QAction *action); + +public: + explicit GraveyardMenu(Player *player, QWidget *parent = nullptr); + void createMoveActions(); + void createViewActions(); + void retranslateUi(); + void setShortcutsActive(); + void setShortcutsInactive(); + + QMenu *mRevealRandomGraveyardCard = nullptr; + QMenu *moveGraveMenu = nullptr; + + QAction *aViewGraveyard = nullptr; + QAction *aMoveGraveToTopLibrary = nullptr; + QAction *aMoveGraveToBottomLibrary = nullptr; + QAction *aMoveGraveToHand = nullptr; + QAction *aMoveGraveToRfg = nullptr; + +private: + Player *player; +}; + +#endif // COCKATRICE_GRAVE_MENU_H diff --git a/cockatrice/src/game/player/menu/hand_menu.cpp b/cockatrice/src/game/player/menu/hand_menu.cpp new file mode 100644 index 000000000..77b1e3a27 --- /dev/null +++ b/cockatrice/src/game/player/menu/hand_menu.cpp @@ -0,0 +1,92 @@ +#include "hand_menu.h" + +#include "../player.h" +#include "../player_actions.h" + +HandMenu::HandMenu(Player *_player, PlayerActions *actions, QWidget *parent) : TearOffMenu(parent), player(_player) +{ + if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { + aViewHand = new QAction(this); + connect(aViewHand, &QAction::triggered, actions, &PlayerActions::actViewHand); + addAction(aViewHand); + + aSortHand = new QAction(this); + connect(aSortHand, &QAction::triggered, actions, &PlayerActions::actSortHand); + addAction(aSortHand); + } + + mRevealHand = addMenu(QString()); + mRevealRandomHandCard = addMenu(QString()); + addSeparator(); + + aMulligan = new QAction(this); + connect(aMulligan, &QAction::triggered, actions, &PlayerActions::actMulligan); + addAction(aMulligan); + + addSeparator(); + + mMoveHandMenu = addTearOffMenu(QString()); + + if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { + aMoveHandToTopLibrary = new QAction(this); + aMoveHandToTopLibrary->setData(QList() << "deck" << 0); + aMoveHandToBottomLibrary = new QAction(this); + aMoveHandToBottomLibrary->setData(QList() << "deck" << -1); + aMoveHandToGrave = new QAction(this); + aMoveHandToGrave->setData(QList() << "grave" << 0); + aMoveHandToRfg = new QAction(this); + aMoveHandToRfg->setData(QList() << "rfg" << 0); + + auto hand = player->getHandZone(); + + connect(aMoveHandToTopLibrary, &QAction::triggered, hand, &HandZoneLogic::moveAllToZone); + connect(aMoveHandToBottomLibrary, &QAction::triggered, hand, &HandZoneLogic::moveAllToZone); + connect(aMoveHandToGrave, &QAction::triggered, hand, &HandZoneLogic::moveAllToZone); + connect(aMoveHandToRfg, &QAction::triggered, hand, &HandZoneLogic::moveAllToZone); + + mMoveHandMenu->addAction(aMoveHandToTopLibrary); + mMoveHandMenu->addAction(aMoveHandToBottomLibrary); + mMoveHandMenu->addSeparator(); + mMoveHandMenu->addAction(aMoveHandToGrave); + mMoveHandMenu->addSeparator(); + mMoveHandMenu->addAction(aMoveHandToRfg); + } + + retranslateUi(); +} + +void HandMenu::retranslateUi() +{ + setTitle(tr("&Hand")); + + if (player->getPlayerInfo()->getLocalOrJudge()) { + aViewHand->setText(tr("&View hand")); + aSortHand->setText(tr("&Sort hand")); + aMulligan->setText(tr("Take &mulligan")); + + mMoveHandMenu->setTitle(tr("&Move hand to...")); + aMoveHandToTopLibrary->setText(tr("&Top of library")); + aMoveHandToBottomLibrary->setText(tr("&Bottom of library")); + aMoveHandToGrave->setText(tr("&Graveyard")); + aMoveHandToRfg->setText(tr("&Exile")); + + mRevealHand->setTitle(tr("&Reveal hand to...")); + mRevealRandomHandCard->setTitle(tr("Reveal r&andom card to...")); + } +} + +void HandMenu::setShortcutsActive() +{ + ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); + + aViewHand->setShortcuts(shortcuts.getShortcut("Player/aViewHand")); + aSortHand->setShortcuts(shortcuts.getShortcut("Player/aSortHand")); + aMulligan->setShortcuts(shortcuts.getShortcut("Player/aMulligan")); +} + +void HandMenu::setShortcutsInactive() +{ + aViewHand->setShortcut(QKeySequence()); + aSortHand->setShortcut(QKeySequence()); + aMulligan->setShortcut(QKeySequence()); +} diff --git a/cockatrice/src/game/player/menu/hand_menu.h b/cockatrice/src/game/player/menu/hand_menu.h new file mode 100644 index 000000000..d8aefb351 --- /dev/null +++ b/cockatrice/src/game/player/menu/hand_menu.h @@ -0,0 +1,52 @@ +#ifndef COCKATRICE_HAND_MENU_H +#define COCKATRICE_HAND_MENU_H + +#include "../../../client/tearoff_menu.h" + +#include +#include + +class Player; +class PlayerActions; + +class HandMenu : public TearOffMenu +{ + Q_OBJECT +public: + explicit HandMenu(Player *player, PlayerActions *actions, QWidget *parent = nullptr); + void retranslateUi(); + void setShortcutsActive(); + void setShortcutsInactive(); + + // expose useful actions/menus if PlayerMenu needs them + QMenu *revealHandMenu() const + { + return mRevealHand; + } + QMenu *revealRandomHandCardMenu() const + { + return mRevealRandomHandCard; + } + QMenu *moveHandMenu() const + { + return mMoveHandMenu; + } + +private: + Player *player; + + QAction *aViewHand = nullptr; + QAction *aSortHand = nullptr; + QAction *aMulligan = nullptr; + + QMenu *mRevealHand = nullptr; + QMenu *mRevealRandomHandCard = nullptr; + QMenu *mMoveHandMenu = nullptr; + + QAction *aMoveHandToTopLibrary = nullptr; + QAction *aMoveHandToBottomLibrary = nullptr; + QAction *aMoveHandToGrave = nullptr; + QAction *aMoveHandToRfg = nullptr; +}; + +#endif // COCKATRICE_HAND_MENU_H diff --git a/cockatrice/src/game/player/menu/library_menu.cpp b/cockatrice/src/game/player/menu/library_menu.cpp new file mode 100644 index 000000000..260ae09ab --- /dev/null +++ b/cockatrice/src/game/player/menu/library_menu.cpp @@ -0,0 +1,283 @@ +#include "library_menu.h" + +#include "../player.h" +#include "../player_actions.h" + +LibraryMenu::LibraryMenu(Player *_player, QWidget *parent) : TearOffMenu(parent), player(_player) +{ + createDrawActions(); + createShuffleActions(); + createMoveActions(); + createViewActions(); + + addAction(aDrawCard); + addAction(aDrawCards); + addAction(aUndoDraw); + addSeparator(); + addAction(aShuffle); + addSeparator(); + addAction(aViewLibrary); + addAction(aViewTopCards); + addAction(aViewBottomCards); + addSeparator(); + mRevealLibrary = addMenu(QString()); + mLendLibrary = addMenu(QString()); + mRevealTopCard = addMenu(QString()); + addAction(aAlwaysRevealTopCard); + addAction(aAlwaysLookAtTopCard); + addSeparator(); + topLibraryMenu = addTearOffMenu(QString()); + bottomLibraryMenu = addTearOffMenu(QString()); + addSeparator(); + addAction(aOpenDeckInDeckEditor); + topLibraryMenu->addAction(aMoveTopToPlay); + topLibraryMenu->addAction(aMoveTopToPlayFaceDown); + topLibraryMenu->addAction(aMoveTopCardToBottom); + topLibraryMenu->addSeparator(); + topLibraryMenu->addAction(aMoveTopCardToGraveyard); + topLibraryMenu->addAction(aMoveTopCardsToGraveyard); + topLibraryMenu->addAction(aMoveTopCardToExile); + topLibraryMenu->addAction(aMoveTopCardsToExile); + topLibraryMenu->addAction(aMoveTopCardsUntil); + topLibraryMenu->addSeparator(); + topLibraryMenu->addAction(aShuffleTopCards); + + bottomLibraryMenu->addAction(aDrawBottomCard); + bottomLibraryMenu->addAction(aDrawBottomCards); + bottomLibraryMenu->addSeparator(); + bottomLibraryMenu->addAction(aMoveBottomToPlay); + bottomLibraryMenu->addAction(aMoveBottomToPlayFaceDown); + bottomLibraryMenu->addAction(aMoveBottomCardToTop); + bottomLibraryMenu->addSeparator(); + bottomLibraryMenu->addAction(aMoveBottomCardToGraveyard); + bottomLibraryMenu->addAction(aMoveBottomCardsToGraveyard); + bottomLibraryMenu->addAction(aMoveBottomCardToExile); + bottomLibraryMenu->addAction(aMoveBottomCardsToExile); + bottomLibraryMenu->addSeparator(); + bottomLibraryMenu->addAction(aShuffleBottomCards); + + connect(player, &Player::resetTopCardMenuActions, this, &LibraryMenu::resetTopCardMenuActions); + connect(player, &Player::deckChanged, this, &LibraryMenu::enableOpenInDeckEditorAction); + + retranslateUi(); +} + +void LibraryMenu::enableOpenInDeckEditorAction() const +{ + aOpenDeckInDeckEditor->setEnabled(true); +} + +void LibraryMenu::resetTopCardMenuActions() +{ + aAlwaysRevealTopCard->setChecked(false); + aAlwaysLookAtTopCard->setChecked(false); +} + +void LibraryMenu::createDrawActions() +{ + PlayerActions *playerActions = player->getPlayerActions(); + + if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { + aDrawCard = new QAction(this); + connect(aDrawCard, &QAction::triggered, playerActions, &PlayerActions::actDrawCard); + aDrawCards = new QAction(this); + connect(aDrawCards, &QAction::triggered, playerActions, &PlayerActions::actDrawCards); + aUndoDraw = new QAction(this); + connect(aUndoDraw, &QAction::triggered, playerActions, &PlayerActions::actUndoDraw); + aDrawBottomCard = new QAction(this); + connect(aDrawBottomCard, &QAction::triggered, playerActions, &PlayerActions::actDrawBottomCard); + aDrawBottomCards = new QAction(this); + connect(aDrawBottomCards, &QAction::triggered, playerActions, &PlayerActions::actDrawBottomCards); + } +} + +void LibraryMenu::createShuffleActions() +{ + PlayerActions *playerActions = player->getPlayerActions(); + + if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { + aShuffle = new QAction(this); + connect(aShuffle, &QAction::triggered, playerActions, &PlayerActions::actShuffle); + aShuffleTopCards = new QAction(this); + connect(aShuffleTopCards, &QAction::triggered, playerActions, &PlayerActions::actShuffleTop); + aShuffleBottomCards = new QAction(this); + connect(aShuffleBottomCards, &QAction::triggered, playerActions, &PlayerActions::actShuffleBottom); + } +} + +void LibraryMenu::createMoveActions() +{ + PlayerActions *playerActions = player->getPlayerActions(); + + if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { + aMoveTopToPlay = new QAction(this); + connect(aMoveTopToPlay, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardToPlay); + aMoveTopToPlayFaceDown = new QAction(this); + connect(aMoveTopToPlayFaceDown, &QAction::triggered, playerActions, + &PlayerActions::actMoveTopCardToPlayFaceDown); + aMoveTopCardToGraveyard = new QAction(this); + connect(aMoveTopCardToGraveyard, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardToGrave); + aMoveTopCardToExile = new QAction(this); + connect(aMoveTopCardToExile, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardToExile); + aMoveTopCardsToGraveyard = new QAction(this); + connect(aMoveTopCardsToGraveyard, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardsToGrave); + aMoveTopCardsToExile = new QAction(this); + connect(aMoveTopCardsToExile, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardsToExile); + aMoveTopCardsUntil = new QAction(this); + connect(aMoveTopCardsUntil, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardsUntil); + aMoveTopCardToBottom = new QAction(this); + connect(aMoveTopCardToBottom, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardToBottom); + + aMoveBottomToPlay = new QAction(this); + connect(aMoveBottomToPlay, &QAction::triggered, playerActions, &PlayerActions::actMoveBottomCardToPlay); + aMoveBottomToPlayFaceDown = new QAction(this); + connect(aMoveBottomToPlayFaceDown, &QAction::triggered, playerActions, + &PlayerActions::actMoveBottomCardToPlayFaceDown); + aMoveBottomCardToGraveyard = new QAction(this); + connect(aMoveBottomCardToGraveyard, &QAction::triggered, playerActions, + &PlayerActions::actMoveBottomCardToGrave); + aMoveBottomCardToExile = new QAction(this); + connect(aMoveBottomCardToExile, &QAction::triggered, playerActions, &PlayerActions::actMoveBottomCardToExile); + aMoveBottomCardsToGraveyard = new QAction(this); + connect(aMoveBottomCardsToGraveyard, &QAction::triggered, playerActions, + &PlayerActions::actMoveBottomCardsToGrave); + aMoveBottomCardsToExile = new QAction(this); + connect(aMoveBottomCardsToExile, &QAction::triggered, playerActions, &PlayerActions::actMoveBottomCardsToExile); + aMoveBottomCardToTop = new QAction(this); + connect(aMoveBottomCardToTop, &QAction::triggered, playerActions, &PlayerActions::actMoveBottomCardToTop); + } +} + +void LibraryMenu::createViewActions() +{ + PlayerActions *playerActions = player->getPlayerActions(); + + if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { + aViewLibrary = new QAction(this); + connect(aViewLibrary, &QAction::triggered, playerActions, &PlayerActions::actViewLibrary); + + aViewTopCards = new QAction(this); + connect(aViewTopCards, &QAction::triggered, playerActions, &PlayerActions::actViewTopCards); + aViewBottomCards = new QAction(this); + connect(aViewBottomCards, &QAction::triggered, playerActions, &PlayerActions::actViewBottomCards); + aAlwaysRevealTopCard = new QAction(this); + aAlwaysRevealTopCard->setCheckable(true); + connect(aAlwaysRevealTopCard, &QAction::triggered, playerActions, &PlayerActions::actAlwaysRevealTopCard); + aAlwaysLookAtTopCard = new QAction(this); + aAlwaysLookAtTopCard->setCheckable(true); + connect(aAlwaysLookAtTopCard, &QAction::triggered, playerActions, &PlayerActions::actAlwaysLookAtTopCard); + aOpenDeckInDeckEditor = new QAction(this); + aOpenDeckInDeckEditor->setEnabled(false); + connect(aOpenDeckInDeckEditor, &QAction::triggered, playerActions, &PlayerActions::actOpenDeckInDeckEditor); + } +} + +void LibraryMenu::retranslateUi() +{ + setTitle(tr("&Library")); + + if (player->getPlayerInfo()->getLocalOrJudge()) { + aViewLibrary->setText(tr("&View library")); + aViewTopCards->setText(tr("View &top cards of library...")); + aViewBottomCards->setText(tr("View bottom cards of library...")); + mRevealLibrary->setTitle(tr("Reveal &library to...")); + mLendLibrary->setTitle(tr("Lend library to...")); + mRevealTopCard->setTitle(tr("Reveal &top cards to...")); + topLibraryMenu->setTitle(tr("&Top of library...")); + bottomLibraryMenu->setTitle(tr("&Bottom of library...")); + aAlwaysRevealTopCard->setText(tr("&Always reveal top card")); + aAlwaysLookAtTopCard->setText(tr("&Always look at top card")); + aOpenDeckInDeckEditor->setText(tr("&Open deck in deck editor")); + + aDrawCard->setText(tr("&Draw card")); + aDrawCards->setText(tr("D&raw cards...")); + aUndoDraw->setText(tr("&Undo last draw")); + + aShuffle->setText(tr("Shuffle")); + + aMoveTopToPlay->setText(tr("&Play top card")); + aMoveTopToPlayFaceDown->setText(tr("Play top card &face down")); + aMoveTopCardToBottom->setText(tr("Put top card on &bottom")); + aMoveTopCardToGraveyard->setText(tr("Move top card to grave&yard")); + aMoveTopCardToExile->setText(tr("Move top card to e&xile")); + aMoveTopCardsToGraveyard->setText(tr("Move top cards to &graveyard...")); + aMoveTopCardsToExile->setText(tr("Move top cards to &exile...")); + aMoveTopCardsUntil->setText(tr("Put top cards on stack &until...")); + aShuffleTopCards->setText(tr("Shuffle top cards...")); + + aDrawBottomCard->setText(tr("&Draw bottom card")); + aDrawBottomCards->setText(tr("D&raw bottom cards...")); + aMoveBottomToPlay->setText(tr("&Play bottom card")); + aMoveBottomToPlayFaceDown->setText(tr("Play bottom card &face down")); + aMoveBottomCardToGraveyard->setText(tr("Move bottom card to grave&yard")); + aMoveBottomCardToExile->setText(tr("Move bottom card to e&xile")); + aMoveBottomCardsToGraveyard->setText(tr("Move bottom cards to &graveyard...")); + aMoveBottomCardsToExile->setText(tr("Move bottom cards to &exile...")); + aMoveBottomCardToTop->setText(tr("Put bottom card on &top")); + aShuffleBottomCards->setText(tr("Shuffle bottom cards...")); + } +} + +void LibraryMenu::setShortcutsActive() +{ + ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); + + aViewLibrary->setShortcuts(shortcuts.getShortcut("Player/aViewLibrary")); + aViewTopCards->setShortcuts(shortcuts.getShortcut("Player/aViewTopCards")); + aViewBottomCards->setShortcuts(shortcuts.getShortcut("Player/aViewBottomCards")); + aDrawCard->setShortcuts(shortcuts.getShortcut("Player/aDrawCard")); + aDrawCards->setShortcuts(shortcuts.getShortcut("Player/aDrawCards")); + aUndoDraw->setShortcuts(shortcuts.getShortcut("Player/aUndoDraw")); + aShuffle->setShortcuts(shortcuts.getShortcut("Player/aShuffle")); + aShuffleTopCards->setShortcuts(shortcuts.getShortcut("Player/aShuffleTopCards")); + aShuffleBottomCards->setShortcuts(shortcuts.getShortcut("Player/aShuffleBottomCards")); + aAlwaysRevealTopCard->setShortcuts(shortcuts.getShortcut("Player/aAlwaysRevealTopCard")); + aAlwaysLookAtTopCard->setShortcuts(shortcuts.getShortcut("Player/aAlwaysLookAtTopCard")); + aMoveTopToPlay->setShortcuts(shortcuts.getShortcut("Player/aMoveTopToPlay")); + aMoveTopToPlayFaceDown->setShortcuts(shortcuts.getShortcut("Player/aMoveTopToPlayFaceDown")); + aMoveTopCardToGraveyard->setShortcuts(shortcuts.getShortcut("Player/aMoveTopCardToGraveyard")); + aMoveTopCardsToGraveyard->setShortcuts(shortcuts.getShortcut("Player/aMoveTopCardsToGraveyard")); + aMoveTopCardToExile->setShortcuts(shortcuts.getShortcut("Player/aMoveTopCardToExile")); + aMoveTopCardsToExile->setShortcuts(shortcuts.getShortcut("Player/aMoveTopCardsToExile")); + aMoveTopCardsUntil->setShortcuts(shortcuts.getShortcut("Player/aMoveTopCardsUntil")); + aMoveTopCardToBottom->setShortcuts(shortcuts.getShortcut("Player/aMoveTopCardToBottom")); + aDrawBottomCard->setShortcuts(shortcuts.getShortcut("Player/aDrawBottomCard")); + aDrawBottomCards->setShortcuts(shortcuts.getShortcut("Player/aDrawBottomCards")); + aMoveBottomToPlay->setShortcuts(shortcuts.getShortcut("Player/aMoveBottomToPlay")); + aMoveBottomToPlayFaceDown->setShortcuts(shortcuts.getShortcut("Player/aMoveBottomToPlayFaceDown")); + aMoveBottomCardToGraveyard->setShortcuts(shortcuts.getShortcut("Player/aMoveBottomCardToGrave")); + aMoveBottomCardsToGraveyard->setShortcuts(shortcuts.getShortcut("Player/aMoveBottomCardsToGrave")); + aMoveBottomCardToExile->setShortcuts(shortcuts.getShortcut("Player/aMoveBottomCardToExile")); + aMoveBottomCardsToExile->setShortcuts(shortcuts.getShortcut("Player/aMoveBottomCardsToExile")); + aMoveBottomCardToTop->setShortcuts(shortcuts.getShortcut("Player/aMoveBottomCardToTop")); +} + +void LibraryMenu::setShortcutsInactive() +{ + aViewLibrary->setShortcut(QKeySequence()); + aViewTopCards->setShortcut(QKeySequence()); + aViewBottomCards->setShortcut(QKeySequence()); + aDrawCard->setShortcut(QKeySequence()); + aDrawCards->setShortcut(QKeySequence()); + aUndoDraw->setShortcut(QKeySequence()); + aShuffle->setShortcut(QKeySequence()); + aShuffleTopCards->setShortcut(QKeySequence()); + aShuffleBottomCards->setShortcut(QKeySequence()); + aAlwaysRevealTopCard->setShortcut(QKeySequence()); + aAlwaysLookAtTopCard->setShortcut(QKeySequence()); + aMoveTopToPlay->setShortcut(QKeySequence()); + aMoveTopToPlayFaceDown->setShortcut(QKeySequence()); + aMoveTopCardToGraveyard->setShortcut(QKeySequence()); + aMoveTopCardsToGraveyard->setShortcut(QKeySequence()); + aMoveTopCardToExile->setShortcut(QKeySequence()); + aMoveTopCardsToExile->setShortcut(QKeySequence()); + aMoveTopCardsUntil->setShortcut(QKeySequence()); + aDrawBottomCard->setShortcut(QKeySequence()); + aDrawBottomCards->setShortcut(QKeySequence()); + aMoveBottomToPlay->setShortcut(QKeySequence()); + aMoveBottomToPlayFaceDown->setShortcut(QKeySequence()); + aMoveBottomCardToGraveyard->setShortcut(QKeySequence()); + aMoveBottomCardsToGraveyard->setShortcut(QKeySequence()); + aMoveBottomCardToExile->setShortcut(QKeySequence()); + aMoveBottomCardsToExile->setShortcut(QKeySequence()); +} \ No newline at end of file diff --git a/cockatrice/src/game/player/menu/library_menu.h b/cockatrice/src/game/player/menu/library_menu.h new file mode 100644 index 000000000..a91aebcdd --- /dev/null +++ b/cockatrice/src/game/player/menu/library_menu.h @@ -0,0 +1,98 @@ +#ifndef COCKATRICE_LIBRARY_MENU_H +#define COCKATRICE_LIBRARY_MENU_H + +#include "../../../client/tearoff_menu.h" + +#include +#include + +class Player; +class PlayerActions; + +class LibraryMenu : public TearOffMenu +{ + Q_OBJECT +public slots: + void enableOpenInDeckEditorAction() const; + void resetTopCardMenuActions(); + +public: + LibraryMenu(Player *player, QWidget *parent = nullptr); + void createDrawActions(); + void createShuffleActions(); + void createMoveActions(); + void createViewActions(); + void retranslateUi(); + void setShortcutsActive(); + void setShortcutsInactive(); + + [[nodiscard]] bool isAlwaysRevealTopCardChecked() const + { + return aAlwaysRevealTopCard->isChecked(); + } + + [[nodiscard]] bool isAlwaysLookAtTopCardChecked() const + { + return aAlwaysLookAtTopCard->isChecked(); + } + + // expose useful actions/menus if PlayerMenu needs them + QMenu *revealLibrary() const + { + return mRevealLibrary; + } + QMenu *lendLibraryMenu() const + { + return mLendLibrary; + } + QMenu *revealTopCardMenu() const + { + return mRevealTopCard; + } + + QMenu *topLibraryMenu = nullptr; + QMenu *bottomLibraryMenu = nullptr; + + // Expose submenus that PlayerMenu tracks in its lists + QMenu *mRevealLibrary = nullptr; + QMenu *mLendLibrary = nullptr; + QMenu *mRevealTopCard = nullptr; + + QAction *aDrawCard = nullptr; + QAction *aDrawCards = nullptr; + QAction *aUndoDraw = nullptr; + + QAction *aShuffle = nullptr; + QAction *aViewLibrary = nullptr; + QAction *aViewTopCards = nullptr; + QAction *aViewBottomCards = nullptr; + QAction *aAlwaysRevealTopCard = nullptr; + QAction *aAlwaysLookAtTopCard = nullptr; + QAction *aOpenDeckInDeckEditor = nullptr; + + QAction *aMoveTopToPlay = nullptr; + QAction *aMoveTopToPlayFaceDown = nullptr; + QAction *aMoveTopCardToBottom = nullptr; + QAction *aMoveTopCardToGraveyard = nullptr; + QAction *aMoveTopCardToExile = nullptr; + QAction *aMoveTopCardsToGraveyard = nullptr; + QAction *aMoveTopCardsToExile = nullptr; + QAction *aMoveTopCardsUntil = nullptr; + QAction *aShuffleTopCards = nullptr; + + QAction *aDrawBottomCard = nullptr; + QAction *aDrawBottomCards = nullptr; + QAction *aMoveBottomToPlay = nullptr; + QAction *aMoveBottomToPlayFaceDown = nullptr; + QAction *aMoveBottomCardToTop = nullptr; + QAction *aMoveBottomCardToGraveyard = nullptr; + QAction *aMoveBottomCardToExile = nullptr; + QAction *aMoveBottomCardsToGraveyard = nullptr; + QAction *aMoveBottomCardsToExile = nullptr; + QAction *aShuffleBottomCards = nullptr; + +private: + Player *player; +}; + +#endif // COCKATRICE_LIBRARY_MENU_H diff --git a/cockatrice/src/game/player/menu/move_menu.cpp b/cockatrice/src/game/player/menu/move_menu.cpp new file mode 100644 index 000000000..d27e16009 --- /dev/null +++ b/cockatrice/src/game/player/menu/move_menu.cpp @@ -0,0 +1,63 @@ +#include "move_menu.h" + +#include "../card_menu_action_type.h" +#include "../player.h" +#include "../player_actions.h" + +MoveMenu::MoveMenu(Player *player) : QMenu(tr("Move to")) +{ + aMoveToTopLibrary = new QAction(this); + aMoveToTopLibrary->setData(cmMoveToTopLibrary); + aMoveToBottomLibrary = new QAction(this); + aMoveToBottomLibrary->setData(cmMoveToBottomLibrary); + aMoveToXfromTopOfLibrary = new QAction(this); + aMoveToGraveyard = new QAction(this); + aMoveToHand = new QAction(this); + aMoveToHand->setData(cmMoveToHand); + aMoveToGraveyard->setData(cmMoveToGraveyard); + aMoveToExile = new QAction(this); + aMoveToExile->setData(cmMoveToExile); + + connect(aMoveToTopLibrary, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); + connect(aMoveToBottomLibrary, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); + connect(aMoveToXfromTopOfLibrary, &QAction::triggered, player->getPlayerActions(), + &PlayerActions::actMoveCardXCardsFromTop); + connect(aMoveToHand, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); + connect(aMoveToGraveyard, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); + connect(aMoveToExile, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); + + addAction(aMoveToTopLibrary); + addAction(aMoveToXfromTopOfLibrary); + addAction(aMoveToBottomLibrary); + addSeparator(); + addAction(aMoveToHand); + addSeparator(); + addAction(aMoveToGraveyard); + addSeparator(); + addAction(aMoveToExile); + + setShortcutsActive(); + + retranslateUi(); +} + +void MoveMenu::setShortcutsActive() +{ + ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); + + aMoveToTopLibrary->setShortcuts(shortcuts.getShortcut("Player/aMoveToTopLibrary")); + aMoveToBottomLibrary->setShortcuts(shortcuts.getShortcut("Player/aMoveToBottomLibrary")); + aMoveToHand->setShortcuts(shortcuts.getShortcut("Player/aMoveToHand")); + aMoveToGraveyard->setShortcuts(shortcuts.getShortcut("Player/aMoveToGraveyard")); + aMoveToExile->setShortcuts(shortcuts.getShortcut("Player/aMoveToExile")); +} + +void MoveMenu::retranslateUi() +{ + aMoveToTopLibrary->setText(tr("&Top of library in random order")); + aMoveToXfromTopOfLibrary->setText(tr("X cards from the top of library...")); + aMoveToBottomLibrary->setText(tr("&Bottom of library in random order")); + aMoveToHand->setText(tr("&Hand")); + aMoveToGraveyard->setText(tr("&Graveyard")); + aMoveToExile->setText(tr("&Exile")); +} \ No newline at end of file diff --git a/cockatrice/src/game/player/menu/move_menu.h b/cockatrice/src/game/player/menu/move_menu.h new file mode 100644 index 000000000..f7780d2e8 --- /dev/null +++ b/cockatrice/src/game/player/menu/move_menu.h @@ -0,0 +1,24 @@ +#ifndef COCKATRICE_MOVE_MENU_H +#define COCKATRICE_MOVE_MENU_H +#include + +class Player; +class MoveMenu : public QMenu +{ + Q_OBJECT + +public: + explicit MoveMenu(Player *player); + void setShortcutsActive(); + void retranslateUi(); + + QAction *aMoveToTopLibrary = nullptr; + QAction *aMoveToXfromTopOfLibrary = nullptr; + QAction *aMoveToBottomLibrary = nullptr; + + QAction *aMoveToHand = nullptr; + QAction *aMoveToGraveyard = nullptr; + QAction *aMoveToExile = nullptr; +}; + +#endif // COCKATRICE_MOVE_MENU_H diff --git a/cockatrice/src/game/player/menu/player_menu.cpp b/cockatrice/src/game/player/menu/player_menu.cpp new file mode 100644 index 000000000..0c13dddc2 --- /dev/null +++ b/cockatrice/src/game/player/menu/player_menu.cpp @@ -0,0 +1,312 @@ +#include "player_menu.h" + +#include "../../../client/tabs/tab_game.h" +#include "../../../common/pb/command_reveal_cards.pb.h" +#include "../../board/card_item.h" +#include "../../cards/card_database_manager.h" +#include "../../zones/hand_zone.h" +#include "../card_menu_action_type.h" +#include "../player_actions.h" +#include "card_menu.h" +#include "hand_menu.h" + +PlayerMenu::PlayerMenu(Player *_player) : player(_player) +{ + + if (player->getPlayerInfo()->getLocalOrJudge()) { + connect(player->getGame()->getPlayerManager(), &PlayerManager::playerAdded, this, &PlayerMenu::addPlayer); + connect(player->getGame()->getPlayerManager(), &PlayerManager::playerRemoved, this, &PlayerMenu::removePlayer); + } + + const QList &players = player->getGame()->getPlayerManager()->getPlayers().values(); + for (const auto playerToAdd : players) { + addPlayer(playerToAdd); + } + + playerMenu = new TearOffMenu(); + + if (player->getPlayerInfo()->getLocalOrJudge()) { + handMenu = new HandMenu(player, player->getPlayerActions(), playerMenu); + playerMenu->addMenu(handMenu); + playerLists.append(handMenu->revealHandMenu()); + playerLists.append(handMenu->revealRandomHandCardMenu()); + + libraryMenu = new LibraryMenu(player, playerMenu); + playerLists.append(libraryMenu->revealLibrary()); + playerLists.append(libraryMenu->lendLibraryMenu()); + playerLists.append(libraryMenu->revealTopCardMenu()); + playerMenu->addMenu(libraryMenu); + } else { + handMenu = nullptr; + libraryMenu = nullptr; + } + + graveMenu = new GraveyardMenu(player, playerMenu); + connect(graveMenu, &GraveyardMenu::newPlayerActionCreated, this, &PlayerMenu::onNewPlayerListActionCreated); + playerMenu->addMenu(graveMenu); + + rfgMenu = new RfgMenu(player, playerMenu); + playerMenu->addMenu(rfgMenu); + + if (player->getPlayerInfo()->getLocalOrJudge()) { + sideboardMenu = new SideboardMenu(player, playerMenu); + playerMenu->addMenu(sideboardMenu); + + customZonesMenu = new CustomZoneMenu(player); + playerMenu->addMenu(customZonesMenu); + playerMenu->addSeparator(); + + countersMenu = playerMenu->addMenu(QString()); + + utilityMenu = new UtilityMenu(player, playerMenu); + } else { + sideboardMenu = nullptr; + customZonesMenu = nullptr; + countersMenu = nullptr; + utilityMenu = nullptr; + } + + if (player->getPlayerInfo()->getLocal()) { + sayMenu = new SayMenu(player); + playerMenu->addMenu(sayMenu); + } else { + sayMenu = nullptr; + } + + if (player->getPlayerInfo()->getLocalOrJudge()) { + + for (auto &playerList : playerLists) { + QAction *newAction = playerList->addAction(QString()); + newAction->setData(-1); + connect(newAction, &QAction::triggered, this, &PlayerMenu::playerListActionTriggered); + allPlayersActions.append(newAction); + playerList->addSeparator(); + } + } + + connect(&SettingsCache::instance().shortcuts(), &ShortcutsSettings::shortCutChanged, this, + &PlayerMenu::refreshShortcuts); + refreshShortcuts(); + + retranslateUi(); +} + +void PlayerMenu::setMenusForGraphicItems() +{ + player->getGraphicsItem()->getTableZoneGraphicsItem()->setMenu(playerMenu); + player->getGraphicsItem()->getGraveyardZoneGraphicsItem()->setMenu(graveMenu, graveMenu->aViewGraveyard); + player->getGraphicsItem()->getRfgZoneGraphicsItem()->setMenu(rfgMenu, rfgMenu->aViewRfg); + if (player->getPlayerInfo()->getLocalOrJudge()) { + player->getGraphicsItem()->getHandZoneGraphicsItem()->setMenu(handMenu); + player->getGraphicsItem()->getDeckZoneGraphicsItem()->setMenu(libraryMenu, libraryMenu->aDrawCard); + player->getGraphicsItem()->getSideboardZoneGraphicsItem()->setMenu(sideboardMenu); + } +} + +void PlayerMenu::addPlayer(Player *playerToAdd) +{ + if (playerToAdd == nullptr || playerToAdd == player) { + return; + } + + for (auto &playerList : playerLists) { + addPlayerToList(playerList, playerToAdd); + } +} + +void PlayerMenu::addPlayerToList(QMenu *playerList, Player *playerToAdd) +{ + QAction *newAction = playerList->addAction(playerToAdd->getPlayerInfo()->getName()); + newAction->setData(playerToAdd->getPlayerInfo()->getId()); + connect(newAction, &QAction::triggered, this, &PlayerMenu::playerListActionTriggered); +} + +void PlayerMenu::removePlayer(Player *playerToRemove) +{ + if (playerToRemove == nullptr) { + return; + } + + for (auto &playerList : playerLists) { + removePlayerFromList(playerList, playerToRemove); + } +} + +void PlayerMenu::removePlayerFromList(QMenu *playerList, Player *player) +{ + QList actionList = playerList->actions(); + for (auto &j : actionList) + if (j->data().toInt() == player->getPlayerInfo()->getId()) { + playerList->removeAction(j); + j->deleteLater(); + } +} + +void PlayerMenu::playerListActionTriggered() +{ + auto *action = static_cast(sender()); + auto *menu = static_cast(action->parent()); + + Command_RevealCards cmd; + const int otherPlayerId = action->data().toInt(); + if (otherPlayerId != -1) { + cmd.set_player_id(otherPlayerId); + } + + if (menu == libraryMenu->revealLibrary() || menu == libraryMenu->lendLibraryMenu()) { + cmd.set_zone_name("deck"); + cmd.set_grant_write_access(menu == libraryMenu->lendLibraryMenu()); + } else if (menu == libraryMenu->revealTopCardMenu()) { + int deckSize = player->getDeckZone()->getCards().size(); + bool ok; + int number = QInputDialog::getInt(player->getGame()->getTab(), tr("Reveal top cards of library"), + tr("Number of cards: (max. %1)").arg(deckSize), /* defaultNumberTopCards */ 1, + 1, deckSize, 1, &ok); + if (ok) { + cmd.set_zone_name("deck"); + cmd.set_top_cards(number); + // backward compatibility: servers before #1051 only permits to reveal the first card + cmd.add_card_id(0); + // defaultNumberTopCards = number; + } + } else if (menu == handMenu->revealHandMenu()) { + cmd.set_zone_name("hand"); + } else if (menu == handMenu->revealRandomHandCardMenu()) { + cmd.set_zone_name("hand"); + cmd.add_card_id(PlayerActions::RANDOM_CARD_FROM_ZONE); + } else { + return; + } + + player->getPlayerActions()->sendGameCommand(cmd); +} + +void PlayerMenu::onNewPlayerListActionCreated(QAction *action) +{ + allPlayersActions.append(action); +} + +QMenu *PlayerMenu::updateCardMenu(const CardItem *card) +{ + if (!card) { + emit cardMenuUpdated(nullptr); + return nullptr; + } + + // If is spectator (as spectators don't need card menus), return + // only update the menu if the card is actually selected + if ((player->getGame()->getPlayerManager()->isSpectator() && !player->getGame()->getPlayerManager()->isJudge()) || + player->getGame()->getActiveCard() != card) { + return nullptr; + } + + QMenu *menu = new CardMenu(player, card, shortcutsActive); + emit cardMenuUpdated(menu); + + return menu; +} + +void PlayerMenu::retranslateUi() +{ + playerMenu->setTitle(tr("Player \"%1\"").arg(player->getPlayerInfo()->getName())); + + if (handMenu) { + handMenu->retranslateUi(); + } + if (libraryMenu) { + libraryMenu->retranslateUi(); + } + + graveMenu->retranslateUi(); + rfgMenu->retranslateUi(); + + if (sideboardMenu) { + sideboardMenu->retranslateUi(); + } + + if (countersMenu) { + countersMenu->setTitle(tr("&Counters")); + } + + if (customZonesMenu) { + customZonesMenu->retranslateUi(); + } + + QMapIterator counterIterator(player->getCounters()); + while (counterIterator.hasNext()) { + counterIterator.next().value()->retranslateUi(); + } + + if (utilityMenu) { + utilityMenu->retranslateUi(); + } + + for (auto &allPlayersAction : allPlayersActions) { + allPlayersAction->setText(tr("&All players")); + } + + if (sayMenu) { + sayMenu->setTitle(tr("S&ay")); + } +} + +void PlayerMenu::refreshShortcuts() +{ + if (shortcutsActive) { + setShortcutsActive(); + } +} + +void PlayerMenu::setShortcutsActive() +{ + shortcutsActive = true; + + if (handMenu) { + handMenu->setShortcutsActive(); + } + if (libraryMenu) { + libraryMenu->setShortcutsActive(); + } + graveMenu->setShortcutsActive(); + // No shortcuts for RfgMenu yet + + if (sideboardMenu) { + sideboardMenu->setShortcutsActive(); + } + + QMapIterator counterIterator(player->getCounters()); + while (counterIterator.hasNext()) { + counterIterator.next().value()->setShortcutsActive(); + } + + if (utilityMenu) { + utilityMenu->setShortcutsActive(); + } +} + +void PlayerMenu::setShortcutsInactive() +{ + shortcutsActive = false; + + if (handMenu) { + handMenu->setShortcutsInactive(); + } + if (libraryMenu) { + libraryMenu->setShortcutsInactive(); + } + graveMenu->setShortcutsInactive(); + // No shortcuts for RfgMenu yet + + if (sideboardMenu) { + sideboardMenu->setShortcutsInactive(); + } + + QMapIterator counterIterator(player->getCounters()); + while (counterIterator.hasNext()) { + counterIterator.next().value()->setShortcutsInactive(); + } + + if (utilityMenu) { + utilityMenu->setShortcutsInactive(); + } +} \ No newline at end of file diff --git a/cockatrice/src/game/player/menu/player_menu.h b/cockatrice/src/game/player/menu/player_menu.h new file mode 100644 index 000000000..b2059250d --- /dev/null +++ b/cockatrice/src/game/player/menu/player_menu.h @@ -0,0 +1,93 @@ +#ifndef COCKATRICE_PLAYER_MENU_H +#define COCKATRICE_PLAYER_MENU_H + +#include "../../../client/tearoff_menu.h" +#include "../player.h" +#include "custom_zone_menu.h" +#include "grave_menu.h" +#include "hand_menu.h" +#include "library_menu.h" +#include "rfg_menu.h" +#include "say_menu.h" +#include "sideboard_menu.h" +#include "utility_menu.h" + +#include +#include + +class CardItem; +class PlayerMenu : public QObject +{ + Q_OBJECT + +signals: + void cardMenuUpdated(QMenu *cardMenu); + +public slots: + void setMenusForGraphicItems(); + +private slots: + void addPlayer(Player *playerToAdd); + void removePlayer(Player *playerToRemove); + void playerListActionTriggered(); + void onNewPlayerListActionCreated(QAction *action); + void refreshShortcuts(); + +public: + PlayerMenu(Player *player); + void retranslateUi(); + + void addPlayerToList(QMenu *playerList, Player *playerToAdd); + static void removePlayerFromList(QMenu *playerList, Player *player); + + QMenu *updateCardMenu(const CardItem *card); + + [[nodiscard]] QMenu *getPlayerMenu() const + { + return playerMenu; + } + + [[nodiscard]] QMenu *getCountersMenu() + { + return countersMenu; + } + + [[nodiscard]] LibraryMenu *getLibraryMenu() const + { + return libraryMenu; + } + + [[nodiscard]] UtilityMenu *getUtilityMenu() const + { + return utilityMenu; + } + + bool getShortcutsActive() const + { + return shortcutsActive; + } + + void setShortcutsActive(); + void setShortcutsInactive(); + +private: + Player *player; + TearOffMenu *playerMenu; + QMenu *countersMenu; + HandMenu *handMenu; + LibraryMenu *libraryMenu; + SideboardMenu *sideboardMenu; + GraveyardMenu *graveMenu; + RfgMenu *rfgMenu; + UtilityMenu *utilityMenu; + SayMenu *sayMenu; + CustomZoneMenu *customZonesMenu; + QList playerLists; + QList allPlayersActions; + + bool shortcutsActive; + + void initSayMenu(); +}; + +#endif // COCKATRICE_PLAYER_MENU_H diff --git a/cockatrice/src/game/player/menu/pt_menu.cpp b/cockatrice/src/game/player/menu/pt_menu.cpp new file mode 100644 index 000000000..dae03e07f --- /dev/null +++ b/cockatrice/src/game/player/menu/pt_menu.cpp @@ -0,0 +1,78 @@ +#include "pt_menu.h" + +#include "../player.h" +#include "../player_actions.h" + +PtMenu::PtMenu(Player *player) : QMenu(tr("Power / toughness")) +{ + PlayerActions *playerActions = player->getPlayerActions(); + + aIncP = new QAction(this); + connect(aIncP, &QAction::triggered, playerActions, &PlayerActions::actIncP); + aDecP = new QAction(this); + connect(aDecP, &QAction::triggered, playerActions, &PlayerActions::actDecP); + aIncT = new QAction(this); + connect(aIncT, &QAction::triggered, playerActions, &PlayerActions::actIncT); + aDecT = new QAction(this); + connect(aDecT, &QAction::triggered, playerActions, &PlayerActions::actDecT); + aIncPT = new QAction(this); + connect(aIncPT, &QAction::triggered, playerActions, [playerActions] { playerActions->actIncPT(); }); + aDecPT = new QAction(this); + connect(aDecPT, &QAction::triggered, playerActions, &PlayerActions::actDecPT); + aFlowP = new QAction(this); + connect(aFlowP, &QAction::triggered, playerActions, &PlayerActions::actFlowP); + aFlowT = new QAction(this); + connect(aFlowT, &QAction::triggered, playerActions, &PlayerActions::actFlowT); + aSetPT = new QAction(this); + connect(aSetPT, &QAction::triggered, playerActions, &PlayerActions::actSetPT); + aResetPT = new QAction(this); + connect(aResetPT, &QAction::triggered, playerActions, &PlayerActions::actResetPT); + + addAction(aIncP); + addAction(aDecP); + addAction(aFlowP); + addSeparator(); + addAction(aIncT); + addAction(aDecT); + addAction(aFlowT); + addSeparator(); + addAction(aIncPT); + addAction(aDecPT); + addSeparator(); + addAction(aSetPT); + addAction(aResetPT); + + setShortcutsActive(); + + retranslateUi(); +} + +void PtMenu::retranslateUi() +{ + aIncP->setText(tr("&Increase power")); + aDecP->setText(tr("&Decrease power")); + aIncT->setText(tr("I&ncrease toughness")); + aDecT->setText(tr("D&ecrease toughness")); + aIncPT->setText(tr("In&crease power and toughness")); + aDecPT->setText(tr("Dec&rease power and toughness")); + aFlowP->setText(tr("Increase power and decrease toughness")); + aFlowT->setText(tr("Decrease power and increase toughness")); + aSetPT->setText(tr("Set &power and toughness...")); + aResetPT->setText(tr("Reset p&ower and toughness")); +} + +void PtMenu::setShortcutsActive() +{ + ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); + + aIncP->setShortcuts(shortcuts.getShortcut("Player/aIncP")); + aDecP->setShortcuts(shortcuts.getShortcut("Player/aDecP")); + aIncT->setShortcuts(shortcuts.getShortcut("Player/aIncT")); + aDecT->setShortcuts(shortcuts.getShortcut("Player/aDecT")); + aIncPT->setShortcuts(shortcuts.getShortcut("Player/aIncPT")); + aDecPT->setShortcuts(shortcuts.getShortcut("Player/aDecPT")); + aFlowP->setShortcuts(shortcuts.getShortcut("Player/aFlowP")); + aFlowT->setShortcuts(shortcuts.getShortcut("Player/aFlowT")); + aSetPT->setShortcuts(shortcuts.getShortcut("Player/aSetPT")); + aResetPT->setShortcuts(shortcuts.getShortcut("Player/aResetPT")); +} \ No newline at end of file diff --git a/cockatrice/src/game/player/menu/pt_menu.h b/cockatrice/src/game/player/menu/pt_menu.h new file mode 100644 index 000000000..f6ceab990 --- /dev/null +++ b/cockatrice/src/game/player/menu/pt_menu.h @@ -0,0 +1,29 @@ +#ifndef COCKATRICE_PT_MENU_H +#define COCKATRICE_PT_MENU_H +#include + +class Player; +class PtMenu : public QMenu +{ + + Q_OBJECT + +public: + explicit PtMenu(Player *player); + void retranslateUi(); + void setShortcutsActive(); + + QAction *aIncP = nullptr; + QAction *aDecP = nullptr; + QAction *aFlowP = nullptr; + QAction *aIncT = nullptr; + QAction *aDecT = nullptr; + QAction *aFlowT = nullptr; + + QAction *aIncPT = nullptr; + QAction *aDecPT = nullptr; + QAction *aSetPT = nullptr; + QAction *aResetPT = nullptr; +}; + +#endif // COCKATRICE_PT_MENU_H diff --git a/cockatrice/src/game/player/menu/rfg_menu.cpp b/cockatrice/src/game/player/menu/rfg_menu.cpp new file mode 100644 index 000000000..25e162581 --- /dev/null +++ b/cockatrice/src/game/player/menu/rfg_menu.cpp @@ -0,0 +1,69 @@ +#include "rfg_menu.h" + +#include "../player.h" +#include "../player_actions.h" + +RfgMenu::RfgMenu(Player *_player, QWidget *parent) : TearOffMenu(parent), player(_player) +{ + createMoveActions(); + createViewActions(); + + addAction(aViewRfg); + + if (player->getPlayerInfo()->getLocalOrJudge()) { + addSeparator(); + moveRfgMenu = addTearOffMenu(QString()); + moveRfgMenu->addAction(aMoveRfgToTopLibrary); + moveRfgMenu->addAction(aMoveRfgToBottomLibrary); + moveRfgMenu->addSeparator(); + moveRfgMenu->addAction(aMoveRfgToHand); + moveRfgMenu->addSeparator(); + moveRfgMenu->addAction(aMoveRfgToGrave); + } + + retranslateUi(); +} + +void RfgMenu::createMoveActions() +{ + if (player->getPlayerInfo()->getLocalOrJudge()) { + auto rfg = player->getRfgZone(); + + aMoveRfgToTopLibrary = new QAction(this); + aMoveRfgToTopLibrary->setData(QList() << "deck" << 0); + aMoveRfgToBottomLibrary = new QAction(this); + aMoveRfgToBottomLibrary->setData(QList() << "deck" << -1); + aMoveRfgToHand = new QAction(this); + aMoveRfgToHand->setData(QList() << "hand" << 0); + aMoveRfgToGrave = new QAction(this); + aMoveRfgToGrave->setData(QList() << "grave" << 0); + + connect(aMoveRfgToTopLibrary, &QAction::triggered, rfg, &PileZoneLogic::moveAllToZone); + connect(aMoveRfgToBottomLibrary, &QAction::triggered, rfg, &PileZoneLogic::moveAllToZone); + connect(aMoveRfgToHand, &QAction::triggered, rfg, &PileZoneLogic::moveAllToZone); + connect(aMoveRfgToGrave, &QAction::triggered, rfg, &PileZoneLogic::moveAllToZone); + } +} + +void RfgMenu::createViewActions() +{ + PlayerActions *playerActions = player->getPlayerActions(); + + aViewRfg = new QAction(this); + connect(aViewRfg, &QAction::triggered, playerActions, &PlayerActions::actViewRfg); +} + +void RfgMenu::retranslateUi() +{ + setTitle(tr("&Exile")); + + aViewRfg->setText(tr("&View exile")); + + if (player->getPlayerInfo()->getLocalOrJudge()) { + moveRfgMenu->setTitle(tr("&Move exile to...")); + aMoveRfgToTopLibrary->setText(tr("&Top of library")); + aMoveRfgToBottomLibrary->setText(tr("&Bottom of library")); + aMoveRfgToHand->setText(tr("&Hand")); + aMoveRfgToGrave->setText(tr("&Graveyard")); + } +} \ No newline at end of file diff --git a/cockatrice/src/game/player/menu/rfg_menu.h b/cockatrice/src/game/player/menu/rfg_menu.h new file mode 100644 index 000000000..506b3af61 --- /dev/null +++ b/cockatrice/src/game/player/menu/rfg_menu.h @@ -0,0 +1,31 @@ +#ifndef COCKATRICE_RFG_MENU_H +#define COCKATRICE_RFG_MENU_H + +#include "../../../client/tearoff_menu.h" + +#include +#include + +class Player; +class RfgMenu : public TearOffMenu +{ + Q_OBJECT +public: + explicit RfgMenu(Player *player, QWidget *parent = nullptr); + void createMoveActions(); + void createViewActions(); + void retranslateUi(); + + QMenu *moveRfgMenu = nullptr; + + QAction *aViewRfg = nullptr; + QAction *aMoveRfgToTopLibrary = nullptr; + QAction *aMoveRfgToBottomLibrary = nullptr; + QAction *aMoveRfgToHand = nullptr; + QAction *aMoveRfgToGrave = nullptr; + +private: + Player *player; +}; + +#endif // COCKATRICE_RFG_MENU_H diff --git a/cockatrice/src/game/player/menu/say_menu.cpp b/cockatrice/src/game/player/menu/say_menu.cpp new file mode 100644 index 000000000..3598a1c66 --- /dev/null +++ b/cockatrice/src/game/player/menu/say_menu.cpp @@ -0,0 +1,28 @@ +#include "say_menu.h" + +#include "../../../settings/cache_settings.h" +#include "../player.h" +#include "../player_actions.h" + +SayMenu::SayMenu(Player *_player) : player(_player) +{ + connect(&SettingsCache::instance().messages(), &MessageSettings::messageMacrosChanged, this, &SayMenu::initSayMenu); + initSayMenu(); +} + +void SayMenu::initSayMenu() +{ + clear(); + + int count = SettingsCache::instance().messages().getCount(); + setEnabled(count > 0); + + for (int i = 0; i < count; ++i) { + auto *newAction = new QAction(SettingsCache::instance().messages().getMessageAt(i), this); + if (i < 10) { + newAction->setShortcut(QKeySequence("Ctrl+" + QString::number((i + 1) % 10))); + } + connect(newAction, &QAction::triggered, player->getPlayerActions(), &PlayerActions::actSayMessage); + addAction(newAction); + } +} \ No newline at end of file diff --git a/cockatrice/src/game/player/menu/say_menu.h b/cockatrice/src/game/player/menu/say_menu.h new file mode 100644 index 000000000..2df84e78a --- /dev/null +++ b/cockatrice/src/game/player/menu/say_menu.h @@ -0,0 +1,18 @@ +#ifndef COCKATRICE_SAY_MENU_H +#define COCKATRICE_SAY_MENU_H + +#include + +class Player; +class SayMenu : public QMenu +{ + Q_OBJECT +public: + explicit SayMenu(Player *player); + void initSayMenu(); + +private: + Player *player; +}; + +#endif // COCKATRICE_SAY_MENU_H diff --git a/cockatrice/src/game/player/menu/sideboard_menu.cpp b/cockatrice/src/game/player/menu/sideboard_menu.cpp new file mode 100644 index 000000000..bfc40cfd3 --- /dev/null +++ b/cockatrice/src/game/player/menu/sideboard_menu.cpp @@ -0,0 +1,33 @@ +#include "sideboard_menu.h" + +#include "../player.h" + +SideboardMenu::SideboardMenu(Player *player, QMenu *playerMenu) : QMenu(playerMenu) +{ + aViewSideboard = new QAction(this); + connect(aViewSideboard, &QAction::triggered, player->getPlayerActions(), &PlayerActions::actViewSideboard); + + if (player->getPlayerInfo()->getLocalOrJudge()) { + addAction(aViewSideboard); + } + + retranslateUi(); +} + +void SideboardMenu::retranslateUi() +{ + setTitle(tr("&Sideboard")); + aViewSideboard->setText(tr("&View sideboard")); +} + +void SideboardMenu::setShortcutsActive() +{ + ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); + + aViewSideboard->setShortcuts(shortcuts.getShortcut("Player/aViewSideboard")); +} + +void SideboardMenu::setShortcutsInactive() +{ + aViewSideboard->setShortcut(QKeySequence()); +} \ No newline at end of file diff --git a/cockatrice/src/game/player/menu/sideboard_menu.h b/cockatrice/src/game/player/menu/sideboard_menu.h new file mode 100644 index 000000000..a2e85776e --- /dev/null +++ b/cockatrice/src/game/player/menu/sideboard_menu.h @@ -0,0 +1,23 @@ +#ifndef COCKATRICE_SIDEBOARD_MENU_H +#define COCKATRICE_SIDEBOARD_MENU_H + +#include + +class Player; +class SideboardMenu : public QMenu +{ + Q_OBJECT + +public: + explicit SideboardMenu(Player *player, QMenu *playerMenu); + void retranslateUi(); + void setShortcutsActive(); + void setShortcutsInactive(); + +private: + Player *player; + + QAction *aViewSideboard; +}; + +#endif // COCKATRICE_SIDEBOARD_MENU_H diff --git a/cockatrice/src/game/player/menu/utility_menu.cpp b/cockatrice/src/game/player/menu/utility_menu.cpp new file mode 100644 index 000000000..fa41579a5 --- /dev/null +++ b/cockatrice/src/game/player/menu/utility_menu.cpp @@ -0,0 +1,117 @@ +#include "utility_menu.h" + +#include "../player.h" +#include "../player_actions.h" +#include "player_menu.h" + +UtilityMenu::UtilityMenu(Player *_player, QMenu *playerMenu) : QMenu(playerMenu), player(_player) +{ + PlayerActions *playerActions = player->getPlayerActions(); + + if (player->getPlayerInfo()->getLocalOrJudge()) { + aUntapAll = new QAction(this); + connect(aUntapAll, &QAction::triggered, playerActions, &PlayerActions::actUntapAll); + + aRollDie = new QAction(this); + connect(aRollDie, &QAction::triggered, playerActions, &PlayerActions::actRollDie); + + aCreateToken = new QAction(this); + connect(aCreateToken, &QAction::triggered, playerActions, &PlayerActions::actCreateToken); + + aCreateAnotherToken = new QAction(this); + connect(aCreateAnotherToken, &QAction::triggered, playerActions, &PlayerActions::actCreateAnotherToken); + aCreateAnotherToken->setEnabled(false); + + aIncrementAllCardCounters = new QAction(this); + connect(aIncrementAllCardCounters, &QAction::triggered, player, &Player::incrementAllCardCounters); + + createPredefinedTokenMenu = new QMenu(QString()); + createPredefinedTokenMenu->setEnabled(false); + connect(player, &Player::deckChanged, this, &UtilityMenu::populatePredefinedTokensMenu); + + playerMenu->addAction(aIncrementAllCardCounters); + playerMenu->addSeparator(); + playerMenu->addAction(aUntapAll); + playerMenu->addSeparator(); + playerMenu->addAction(aRollDie); + playerMenu->addSeparator(); + playerMenu->addAction(aCreateToken); + playerMenu->addAction(aCreateAnotherToken); + playerMenu->addMenu(createPredefinedTokenMenu); + playerMenu->addSeparator(); + } else { + aCreateToken = nullptr; + aCreateAnotherToken = nullptr; + createPredefinedTokenMenu = nullptr; + aIncrementAllCardCounters = nullptr; + aUntapAll = nullptr; + aRollDie = nullptr; + } + + retranslateUi(); +} + +void UtilityMenu::populatePredefinedTokensMenu() +{ + clear(); + setEnabled(false); + predefinedTokens.clear(); + DeckLoader *_deck = player->getDeck(); + + if (!_deck) { + return; + } + + InnerDecklistNode *tokenZone = dynamic_cast(_deck->getRoot()->findChild(DECK_ZONE_TOKENS)); + + if (tokenZone) { + if (!tokenZone->empty()) + setEnabled(true); + + for (int i = 0; i < tokenZone->size(); ++i) { + const QString tokenName = tokenZone->at(i)->getName(); + predefinedTokens.append(tokenName); + QAction *a = addAction(tokenName); + if (i < 10) { + a->setShortcut(QKeySequence("Alt+" + QString::number((i + 1) % 10))); + } + connect(a, &QAction::triggered, player->getPlayerActions(), &PlayerActions::actCreatePredefinedToken); + } + } +} + +void UtilityMenu::retranslateUi() +{ + if (player->getPlayerInfo()->getLocalOrJudge()) { + aIncrementAllCardCounters->setText(tr("Increment all card counters")); + aUntapAll->setText(tr("&Untap all permanents")); + aRollDie->setText(tr("R&oll die...")); + aCreateToken->setText(tr("&Create token...")); + aCreateAnotherToken->setText(tr("C&reate another token")); + createPredefinedTokenMenu->setTitle(tr("Cr&eate predefined token")); + } +} + +void UtilityMenu::setShortcutsActive() +{ + ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); + + if (player->getPlayerInfo()->getLocalOrJudge()) { + aIncrementAllCardCounters->setShortcuts(shortcuts.getShortcut("Player/aIncrementAllCardCounters")); + aUntapAll->setShortcuts(shortcuts.getShortcut("Player/aUntapAll")); + aRollDie->setShortcuts(shortcuts.getShortcut("Player/aRollDie")); + aCreateToken->setShortcuts(shortcuts.getShortcut("Player/aCreateToken")); + aCreateAnotherToken->setShortcuts(shortcuts.getShortcut("Player/aCreateAnotherToken")); + } +} + +void UtilityMenu::setShortcutsInactive() +{ + if (player->getPlayerInfo()->getLocalOrJudge()) { + aUntapAll->setShortcut(QKeySequence()); + aRollDie->setShortcut(QKeySequence()); + aCreateToken->setShortcut(QKeySequence()); + aCreateAnotherToken->setShortcut(QKeySequence()); + aIncrementAllCardCounters->setShortcut(QKeySequence()); + } +} \ No newline at end of file diff --git a/cockatrice/src/game/player/menu/utility_menu.h b/cockatrice/src/game/player/menu/utility_menu.h new file mode 100644 index 000000000..ce5005180 --- /dev/null +++ b/cockatrice/src/game/player/menu/utility_menu.h @@ -0,0 +1,46 @@ +#ifndef COCKATRICE_UTILITY_MENU_H +#define COCKATRICE_UTILITY_MENU_H + +#include + +class Player; +class UtilityMenu : public QMenu +{ + Q_OBJECT +public slots: + void populatePredefinedTokensMenu(); + void retranslateUi(); + void setShortcutsActive(); + void setShortcutsInactive(); + +public: + explicit UtilityMenu(Player *player, QMenu *playerMenu); + + [[nodiscard]] bool createAnotherTokenActionExists() const + { + return aCreateAnotherToken != nullptr; + } + + void setAndEnableCreateAnotherTokenAction(QString text) + { + aCreateAnotherToken->setText(text); + aCreateAnotherToken->setEnabled(true); + } + + QStringList getPredefinedTokens() const + { + return predefinedTokens; + } + +private: + Player *player; + QStringList predefinedTokens; + + QMenu *createPredefinedTokenMenu; + + QAction *aIncrementAllCardCounters; + QAction *aUntapAll, *aRollDie; + QAction *aCreateToken, *aCreateAnotherToken; +}; + +#endif // COCKATRICE_UTILITY_MENU_H diff --git a/cockatrice/src/game/player/player.cpp b/cockatrice/src/game/player/player.cpp index 17cc27a26..2e5c247df 100644 --- a/cockatrice/src/game/player/player.cpp +++ b/cockatrice/src/game/player/player.cpp @@ -42,9 +42,6 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, bool _judge, A connect(this, &Player::activeChanged, graphicsItem, &PlayerGraphicsItem::onPlayerActiveChanged); - connect(this, &Player::deckChanged, playerMenu, &PlayerMenu::enableOpenInDeckEditorAction); - connect(this, &Player::deckChanged, playerMenu, &PlayerMenu::populatePredefinedTokensMenu); - connect(this, &Player::openDeckEditor, game->getTab(), &TabGame::openDeckEditor); } diff --git a/cockatrice/src/game/player/player.h b/cockatrice/src/game/player/player.h index cd7d3f818..14da854b2 100644 --- a/cockatrice/src/game/player/player.h +++ b/cockatrice/src/game/player/player.h @@ -6,6 +6,7 @@ #include "../board/abstract_graphics_item.h" #include "../cards/card_info.h" #include "../filters/filter_string.h" +#include "menu/player_menu.h" #include "pb/card_attributes.pb.h" #include "pb/game_event.pb.h" #include "player_actions.h" @@ -13,7 +14,6 @@ #include "player_event_handler.h" #include "player_graphics_item.h" #include "player_info.h" -#include "player_menu.h" #include #include diff --git a/cockatrice/src/game/player/player_actions.cpp b/cockatrice/src/game/player/player_actions.cpp index 6c723805f..2f1badfea 100644 --- a/cockatrice/src/game/player/player_actions.cpp +++ b/cockatrice/src/game/player/player_actions.cpp @@ -172,7 +172,7 @@ void PlayerActions::actAlwaysRevealTopCard() { Command_ChangeZoneProperties cmd; cmd.set_zone_name("deck"); - cmd.set_always_reveal_top_card(player->getPlayerMenu()->isAlwaysRevealTopCardChecked()); + cmd.set_always_reveal_top_card(player->getPlayerMenu()->getLibraryMenu()->isAlwaysRevealTopCardChecked()); sendGameCommand(cmd); } @@ -181,7 +181,7 @@ void PlayerActions::actAlwaysLookAtTopCard() { Command_ChangeZoneProperties cmd; cmd.set_zone_name("deck"); - cmd.set_always_look_at_top_card(player->getPlayerMenu()->isAlwaysLookAtTopCardChecked()); + cmd.set_always_look_at_top_card(player->getPlayerMenu()->getLibraryMenu()->isAlwaysLookAtTopCardChecked()); sendGameCommand(cmd); } @@ -833,7 +833,7 @@ void PlayerActions::actRollDie() void PlayerActions::actCreateToken() { - DlgCreateToken dlg(player->getPlayerMenu()->getPredefinedTokens(), player->getGame()->getTab()); + DlgCreateToken dlg(player->getPlayerMenu()->getUtilityMenu()->getPredefinedTokens(), player->getGame()->getTab()); if (!dlg.exec()) { return; } @@ -850,7 +850,7 @@ void PlayerActions::actCreateToken() } } - player->getPlayerMenu()->setAndEnableCreateAnotherTokenAction( + player->getPlayerMenu()->getUtilityMenu()->setAndEnableCreateAnotherTokenAction( tr("C&reate another %1 token").arg(lastTokenInfo.name)); actCreateAnotherToken(); } @@ -878,7 +878,7 @@ void PlayerActions::actCreateAnotherToken() void PlayerActions::setLastToken(CardInfoPtr cardInfo) { - if (cardInfo == nullptr || !player->getPlayerMenu()->createAnotherTokenActionExists()) { + if (cardInfo == nullptr || !player->getPlayerMenu()->getUtilityMenu()->createAnotherTokenActionExists()) { return; } @@ -892,7 +892,7 @@ void PlayerActions::setLastToken(CardInfoPtr cardInfo) lastTokenTableRow = TableZone::clampValidTableRow(2 - cardInfo->getTableRow()); - player->getPlayerMenu()->setAndEnableCreateAnotherTokenAction( + player->getPlayerMenu()->getUtilityMenu()->setAndEnableCreateAnotherTokenAction( tr("C&reate another %1 token").arg(lastTokenInfo.name)); } diff --git a/cockatrice/src/game/player/player_menu.cpp b/cockatrice/src/game/player/player_menu.cpp deleted file mode 100644 index 0c7588824..000000000 --- a/cockatrice/src/game/player/player_menu.cpp +++ /dev/null @@ -1,1394 +0,0 @@ -#include "player_menu.h" - -#include "../../../common/pb/command_reveal_cards.pb.h" -#include "../../client/tabs/tab_game.h" -#include "../../settings/card_counter_settings.h" -#include "../board/card_item.h" -#include "../cards/card_database_manager.h" -#include "../zones/hand_zone.h" -#include "../zones/logic/view_zone_logic.h" -#include "card_menu_action_type.h" -#include "player_actions.h" - -PlayerMenu::PlayerMenu(Player *_player) : player(_player) -{ - - if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { - connect(player->getGame()->getPlayerManager(), &PlayerManager::playerAdded, this, &PlayerMenu::addPlayer); - connect(player->getGame()->getPlayerManager(), &PlayerManager::playerRemoved, this, &PlayerMenu::removePlayer); - } - - const QList &players = player->getGame()->getPlayerManager()->getPlayers().values(); - for (const auto playerToAdd : players) { - addPlayer(playerToAdd); - } - - PlayerActions *playerActions = player->getPlayerActions(); - - createDrawActions(); - createShuffleActions(); - createMoveActions(); - createViewActions(); - - playerMenu = new TearOffMenu(); - - if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { - handMenu = playerMenu->addTearOffMenu(QString()); - handMenu->addAction(aViewHand); - handMenu->addAction(aSortHand); - playerLists.append(mRevealHand = handMenu->addMenu(QString())); - playerLists.append(mRevealRandomHandCard = handMenu->addMenu(QString())); - handMenu->addSeparator(); - handMenu->addAction(aMulligan); - handMenu->addSeparator(); - moveHandMenu = handMenu->addTearOffMenu(QString()); - moveHandMenu->addAction(aMoveHandToTopLibrary); - moveHandMenu->addAction(aMoveHandToBottomLibrary); - moveHandMenu->addSeparator(); - moveHandMenu->addAction(aMoveHandToGrave); - moveHandMenu->addSeparator(); - moveHandMenu->addAction(aMoveHandToRfg); - - libraryMenu = playerMenu->addTearOffMenu(QString()); - libraryMenu->addAction(aDrawCard); - libraryMenu->addAction(aDrawCards); - libraryMenu->addAction(aUndoDraw); - libraryMenu->addSeparator(); - libraryMenu->addAction(aShuffle); - libraryMenu->addSeparator(); - libraryMenu->addAction(aViewLibrary); - libraryMenu->addAction(aViewTopCards); - libraryMenu->addAction(aViewBottomCards); - libraryMenu->addSeparator(); - playerLists.append(mRevealLibrary = libraryMenu->addMenu(QString())); - singlePlayerLists.append(mLendLibrary = libraryMenu->addMenu(QString())); - playerLists.append(mRevealTopCard = libraryMenu->addMenu(QString())); - libraryMenu->addAction(aAlwaysRevealTopCard); - libraryMenu->addAction(aAlwaysLookAtTopCard); - libraryMenu->addSeparator(); - topLibraryMenu = libraryMenu->addTearOffMenu(QString()); - bottomLibraryMenu = libraryMenu->addTearOffMenu(QString()); - libraryMenu->addSeparator(); - libraryMenu->addAction(aOpenDeckInDeckEditor); - topLibraryMenu->addAction(aMoveTopToPlay); - topLibraryMenu->addAction(aMoveTopToPlayFaceDown); - topLibraryMenu->addAction(aMoveTopCardToBottom); - topLibraryMenu->addSeparator(); - topLibraryMenu->addAction(aMoveTopCardToGraveyard); - topLibraryMenu->addAction(aMoveTopCardsToGraveyard); - topLibraryMenu->addAction(aMoveTopCardToExile); - topLibraryMenu->addAction(aMoveTopCardsToExile); - topLibraryMenu->addAction(aMoveTopCardsUntil); - topLibraryMenu->addSeparator(); - topLibraryMenu->addAction(aShuffleTopCards); - - bottomLibraryMenu->addAction(aDrawBottomCard); - bottomLibraryMenu->addAction(aDrawBottomCards); - bottomLibraryMenu->addSeparator(); - bottomLibraryMenu->addAction(aMoveBottomToPlay); - bottomLibraryMenu->addAction(aMoveBottomToPlayFaceDown); - bottomLibraryMenu->addAction(aMoveBottomCardToTop); - bottomLibraryMenu->addSeparator(); - bottomLibraryMenu->addAction(aMoveBottomCardToGraveyard); - bottomLibraryMenu->addAction(aMoveBottomCardsToGraveyard); - bottomLibraryMenu->addAction(aMoveBottomCardToExile); - bottomLibraryMenu->addAction(aMoveBottomCardsToExile); - bottomLibraryMenu->addSeparator(); - bottomLibraryMenu->addAction(aShuffleBottomCards); - } - - graveMenu = playerMenu->addTearOffMenu(QString()); - graveMenu->addAction(aViewGraveyard); - - if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { - mRevealRandomGraveyardCard = graveMenu->addMenu(QString()); - QAction *newAction = mRevealRandomGraveyardCard->addAction(QString()); - newAction->setData(-1); - connect(newAction, &QAction::triggered, playerActions, &PlayerActions::actRevealRandomGraveyardCard); - allPlayersActions.append(newAction); - mRevealRandomGraveyardCard->addSeparator(); - } - - rfgMenu = playerMenu->addTearOffMenu(QString()); - rfgMenu->addAction(aViewRfg); - - if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { - graveMenu->addSeparator(); - moveGraveMenu = graveMenu->addTearOffMenu(QString()); - moveGraveMenu->addAction(aMoveGraveToTopLibrary); - moveGraveMenu->addAction(aMoveGraveToBottomLibrary); - moveGraveMenu->addSeparator(); - moveGraveMenu->addAction(aMoveGraveToHand); - moveGraveMenu->addSeparator(); - moveGraveMenu->addAction(aMoveGraveToRfg); - - rfgMenu->addSeparator(); - moveRfgMenu = rfgMenu->addTearOffMenu(QString()); - moveRfgMenu->addAction(aMoveRfgToTopLibrary); - moveRfgMenu->addAction(aMoveRfgToBottomLibrary); - moveRfgMenu->addSeparator(); - moveRfgMenu->addAction(aMoveRfgToHand); - moveRfgMenu->addSeparator(); - moveRfgMenu->addAction(aMoveRfgToGrave); - - sbMenu = playerMenu->addMenu(QString()); - sbMenu->addAction(aViewSideboard); - - mCustomZones = playerMenu->addMenu(QString()); - mCustomZones->menuAction()->setVisible(false); - - aUntapAll = new QAction(this); - connect(aUntapAll, &QAction::triggered, playerActions, &PlayerActions::actUntapAll); - - aRollDie = new QAction(this); - connect(aRollDie, &QAction::triggered, playerActions, &PlayerActions::actRollDie); - - aCreateToken = new QAction(this); - connect(aCreateToken, &QAction::triggered, playerActions, &PlayerActions::actCreateToken); - - aCreateAnotherToken = new QAction(this); - connect(aCreateAnotherToken, &QAction::triggered, playerActions, &PlayerActions::actCreateAnotherToken); - aCreateAnotherToken->setEnabled(false); - - aIncrementAllCardCounters = new QAction(this); - connect(aIncrementAllCardCounters, &QAction::triggered, player, &Player::incrementAllCardCounters); - - createPredefinedTokenMenu = new QMenu(QString()); - createPredefinedTokenMenu->setEnabled(false); - - mCardCounters = new QMenu; - - playerMenu->addSeparator(); - countersMenu = playerMenu->addMenu(QString()); - playerMenu->addAction(aIncrementAllCardCounters); - playerMenu->addSeparator(); - playerMenu->addAction(aUntapAll); - playerMenu->addSeparator(); - playerMenu->addAction(aRollDie); - playerMenu->addSeparator(); - playerMenu->addAction(aCreateToken); - playerMenu->addAction(aCreateAnotherToken); - playerMenu->addMenu(createPredefinedTokenMenu); - playerMenu->addSeparator(); - } - - if (player->getPlayerInfo()->local) { - sayMenu = playerMenu->addMenu(QString()); - connect(&SettingsCache::instance().messages(), &MessageSettings::messageMacrosChanged, this, - &PlayerMenu::initSayMenu); - initSayMenu(); - } - - if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { - - for (auto &playerList : playerLists) { - QAction *newAction = playerList->addAction(QString()); - newAction->setData(-1); - connect(newAction, &QAction::triggered, this, &PlayerMenu::playerListActionTriggered); - allPlayersActions.append(newAction); - playerList->addSeparator(); - } - } - - // We have to explicitly not-instantiate a bunch of things if we are not local or a judge or else we have to - // consider it everywhere instead of just null-checking - if (!player->getPlayerInfo()->local && !player->getPlayerInfo()->judge) { - countersMenu = nullptr; - sbMenu = nullptr; - mCustomZones = nullptr; - aCreateAnotherToken = nullptr; - createPredefinedTokenMenu = nullptr; - aIncrementAllCardCounters = nullptr; - mCardCounters = nullptr; - moveHandMenu = nullptr; - aMoveHandToTopLibrary = nullptr; - aMoveHandToBottomLibrary = nullptr; - aMoveHandToGrave = nullptr; - aMoveHandToRfg = nullptr; - - moveGraveMenu = nullptr; - aMoveGraveToTopLibrary = nullptr; - aMoveGraveToBottomLibrary = nullptr; - aMoveGraveToHand = nullptr; - aMoveGraveToRfg = nullptr; - - moveRfgMenu = nullptr; - aMoveRfgToTopLibrary = nullptr; - aMoveRfgToBottomLibrary = nullptr; - aMoveRfgToHand = nullptr; - aMoveRfgToGrave = nullptr; - - aViewLibrary = nullptr; - aViewHand = nullptr; - aSortHand = nullptr; - aViewTopCards = nullptr; - aViewBottomCards = nullptr; - mRevealLibrary = nullptr; - mLendLibrary = nullptr; - mRevealTopCard = nullptr; - topLibraryMenu = nullptr; - bottomLibraryMenu = nullptr; - aAlwaysRevealTopCard = nullptr; - aAlwaysLookAtTopCard = nullptr; - aOpenDeckInDeckEditor = nullptr; - aViewSideboard = nullptr; - aDrawCard = nullptr; - aDrawCards = nullptr; - aUndoDraw = nullptr; - aMulligan = nullptr; - - aShuffle = nullptr; - aMoveTopToPlay = nullptr; - aMoveTopToPlayFaceDown = nullptr; - aMoveTopCardToBottom = nullptr; - aMoveTopCardToGraveyard = nullptr; - aMoveTopCardToExile = nullptr; - aMoveTopCardsToGraveyard = nullptr; - aMoveTopCardsToExile = nullptr; - aMoveTopCardsUntil = nullptr; - aShuffleTopCards = nullptr; - - aDrawBottomCard = nullptr; - aDrawBottomCards = nullptr; - aMoveBottomToPlay = nullptr; - aMoveBottomToPlayFaceDown = nullptr; - aMoveBottomCardToGraveyard = nullptr; - aMoveBottomCardToExile = nullptr; - aMoveBottomCardsToGraveyard = nullptr; - aMoveBottomCardsToExile = nullptr; - aMoveBottomCardToTop = nullptr; - aShuffleBottomCards = nullptr; - - handMenu = nullptr; - mRevealHand = nullptr; - mRevealRandomHandCard = nullptr; - mRevealRandomGraveyardCard = nullptr; - sbMenu = nullptr; - libraryMenu = nullptr; - countersMenu = nullptr; - mCustomZones = nullptr; - } - - aTap = new QAction(this); - aTap->setData(cmTap); - connect(aTap, &QAction::triggered, playerActions, &PlayerActions::cardMenuAction); - aDoesntUntap = new QAction(this); - aDoesntUntap->setData(cmDoesntUntap); - connect(aDoesntUntap, &QAction::triggered, playerActions, &PlayerActions::cardMenuAction); - aAttach = new QAction(this); - connect(aAttach, &QAction::triggered, playerActions, &PlayerActions::actAttach); - aUnattach = new QAction(this); - connect(aUnattach, &QAction::triggered, playerActions, &PlayerActions::actUnattach); - aDrawArrow = new QAction(this); - connect(aDrawArrow, &QAction::triggered, playerActions, &PlayerActions::actDrawArrow); - aIncP = new QAction(this); - connect(aIncP, &QAction::triggered, playerActions, &PlayerActions::actIncP); - aDecP = new QAction(this); - connect(aDecP, &QAction::triggered, playerActions, &PlayerActions::actDecP); - aIncT = new QAction(this); - connect(aIncT, &QAction::triggered, playerActions, &PlayerActions::actIncT); - aDecT = new QAction(this); - connect(aDecT, &QAction::triggered, playerActions, &PlayerActions::actDecT); - aIncPT = new QAction(this); - connect(aIncPT, &QAction::triggered, playerActions, [playerActions] { playerActions->actIncPT(); }); - aDecPT = new QAction(this); - connect(aDecPT, &QAction::triggered, playerActions, &PlayerActions::actDecPT); - aFlowP = new QAction(this); - connect(aFlowP, &QAction::triggered, playerActions, &PlayerActions::actFlowP); - aFlowT = new QAction(this); - connect(aFlowT, &QAction::triggered, playerActions, &PlayerActions::actFlowT); - aSetPT = new QAction(this); - connect(aSetPT, &QAction::triggered, playerActions, &PlayerActions::actSetPT); - aResetPT = new QAction(this); - connect(aResetPT, &QAction::triggered, playerActions, &PlayerActions::actResetPT); - aSetAnnotation = new QAction(this); - connect(aSetAnnotation, &QAction::triggered, playerActions, &PlayerActions::actSetAnnotation); - aFlip = new QAction(this); - aFlip->setData(cmFlip); - connect(aFlip, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); - aPeek = new QAction(this); - aPeek->setData(cmPeek); - connect(aPeek, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); - aClone = new QAction(this); - aClone->setData(cmClone); - connect(aClone, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); - aMoveToTopLibrary = new QAction(this); - aMoveToTopLibrary->setData(cmMoveToTopLibrary); - aMoveToBottomLibrary = new QAction(this); - aMoveToBottomLibrary->setData(cmMoveToBottomLibrary); - aMoveToXfromTopOfLibrary = new QAction(this); - aMoveToGraveyard = new QAction(this); - aMoveToHand = new QAction(this); - aMoveToHand->setData(cmMoveToHand); - aMoveToGraveyard->setData(cmMoveToGraveyard); - aMoveToExile = new QAction(this); - aMoveToExile->setData(cmMoveToExile); - connect(aMoveToTopLibrary, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); - connect(aMoveToBottomLibrary, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); - connect(aMoveToXfromTopOfLibrary, &QAction::triggered, playerActions, &PlayerActions::actMoveCardXCardsFromTop); - connect(aMoveToHand, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); - connect(aMoveToGraveyard, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); - connect(aMoveToExile, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); - - aSelectAll = new QAction(this); - connect(aSelectAll, &QAction::triggered, playerActions, &PlayerActions::actSelectAll); - aSelectRow = new QAction(this); - connect(aSelectRow, &QAction::triggered, playerActions, &PlayerActions::actSelectRow); - aSelectColumn = new QAction(this); - connect(aSelectColumn, &QAction::triggered, playerActions, &PlayerActions::actSelectColumn); - - aPlay = new QAction(this); - connect(aPlay, &QAction::triggered, playerActions, &PlayerActions::actPlay); - aHide = new QAction(this); - connect(aHide, &QAction::triggered, playerActions, &PlayerActions::actHide); - aPlayFacedown = new QAction(this); - connect(aPlayFacedown, &QAction::triggered, playerActions, &PlayerActions::actPlayFacedown); - - for (int i = 0; i < 6; ++i) { - auto *tempAddCounter = new QAction(this); - tempAddCounter->setData(9 + i * 1000); - auto *tempRemoveCounter = new QAction(this); - tempRemoveCounter->setData(10 + i * 1000); - auto *tempSetCounter = new QAction(this); - tempSetCounter->setData(11 + i * 1000); - aAddCounter.append(tempAddCounter); - aRemoveCounter.append(tempRemoveCounter); - aSetCounter.append(tempSetCounter); - connect(tempAddCounter, &QAction::triggered, playerActions, &PlayerActions::actCardCounterTrigger); - connect(tempRemoveCounter, &QAction::triggered, playerActions, &PlayerActions::actCardCounterTrigger); - connect(tempSetCounter, &QAction::triggered, playerActions, &PlayerActions::actCardCounterTrigger); - } - - connect(&SettingsCache::instance().shortcuts(), &ShortcutsSettings::shortCutChanged, this, - &PlayerMenu::refreshShortcuts); - refreshShortcuts(); - - connect(player, &Player::clearCustomZonesMenu, this, &PlayerMenu::clearCustomZonesMenu); - connect(player, &Player::addViewCustomZoneActionToCustomZoneMenu, this, - &PlayerMenu::addViewCustomZoneActionToCustomZoneMenu); - connect(player, &Player::resetTopCardMenuActions, this, &PlayerMenu::resetTopCardMenuActions); - - retranslateUi(); -} - -void PlayerMenu::setMenusForGraphicItems() -{ - player->getGraphicsItem()->getTableZoneGraphicsItem()->setMenu(playerMenu); - player->getGraphicsItem()->getGraveyardZoneGraphicsItem()->setMenu(graveMenu, aViewGraveyard); - player->getGraphicsItem()->getRfgZoneGraphicsItem()->setMenu(rfgMenu, aViewRfg); - if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { - player->getGraphicsItem()->getHandZoneGraphicsItem()->setMenu(handMenu); - player->getGraphicsItem()->getDeckZoneGraphicsItem()->setMenu(libraryMenu, aDrawCard); - player->getGraphicsItem()->getSideboardZoneGraphicsItem()->setMenu(sbMenu); - } -} - -void PlayerMenu::createDrawActions() -{ - PlayerActions *playerActions = player->getPlayerActions(); - - if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { - aDrawCard = new QAction(this); - connect(aDrawCard, &QAction::triggered, playerActions, &PlayerActions::actDrawCard); - aDrawCards = new QAction(this); - connect(aDrawCards, &QAction::triggered, playerActions, &PlayerActions::actDrawCards); - aUndoDraw = new QAction(this); - connect(aUndoDraw, &QAction::triggered, playerActions, &PlayerActions::actUndoDraw); - aMulligan = new QAction(this); - connect(aMulligan, &QAction::triggered, playerActions, &PlayerActions::actMulligan); - aDrawBottomCard = new QAction(this); - connect(aDrawBottomCard, &QAction::triggered, playerActions, &PlayerActions::actDrawBottomCard); - aDrawBottomCards = new QAction(this); - connect(aDrawBottomCards, &QAction::triggered, playerActions, &PlayerActions::actDrawBottomCards); - } -} - -void PlayerMenu::createShuffleActions() -{ - PlayerActions *playerActions = player->getPlayerActions(); - - if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { - aShuffle = new QAction(this); - connect(aShuffle, &QAction::triggered, playerActions, &PlayerActions::actShuffle); - aShuffleTopCards = new QAction(this); - connect(aShuffleTopCards, &QAction::triggered, playerActions, &PlayerActions::actShuffleTop); - aShuffleBottomCards = new QAction(this); - connect(aShuffleBottomCards, &QAction::triggered, playerActions, &PlayerActions::actShuffleBottom); - } -} - -void PlayerMenu::createMoveActions() -{ - PlayerActions *playerActions = player->getPlayerActions(); - - if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { - aMoveHandToTopLibrary = new QAction(this); - aMoveHandToTopLibrary->setData(QList() << "deck" << 0); - aMoveHandToBottomLibrary = new QAction(this); - aMoveHandToBottomLibrary->setData(QList() << "deck" << -1); - aMoveHandToGrave = new QAction(this); - aMoveHandToGrave->setData(QList() << "grave" << 0); - aMoveHandToRfg = new QAction(this); - aMoveHandToRfg->setData(QList() << "rfg" << 0); - - auto hand = player->getHandZone(); - auto grave = player->getGraveZone(); - auto rfg = player->getRfgZone(); - - connect(aMoveHandToTopLibrary, &QAction::triggered, hand, &HandZoneLogic::moveAllToZone); - connect(aMoveHandToBottomLibrary, &QAction::triggered, hand, &HandZoneLogic::moveAllToZone); - connect(aMoveHandToGrave, &QAction::triggered, hand, &HandZoneLogic::moveAllToZone); - connect(aMoveHandToRfg, &QAction::triggered, hand, &HandZoneLogic::moveAllToZone); - - aMoveGraveToTopLibrary = new QAction(this); - aMoveGraveToTopLibrary->setData(QList() << "deck" << 0); - aMoveGraveToBottomLibrary = new QAction(this); - aMoveGraveToBottomLibrary->setData(QList() << "deck" << -1); - aMoveGraveToHand = new QAction(this); - aMoveGraveToHand->setData(QList() << "hand" << 0); - aMoveGraveToRfg = new QAction(this); - aMoveGraveToRfg->setData(QList() << "rfg" << 0); - - connect(aMoveGraveToTopLibrary, &QAction::triggered, grave, &PileZoneLogic::moveAllToZone); - connect(aMoveGraveToBottomLibrary, &QAction::triggered, grave, &PileZoneLogic::moveAllToZone); - connect(aMoveGraveToHand, &QAction::triggered, grave, &PileZoneLogic::moveAllToZone); - connect(aMoveGraveToRfg, &QAction::triggered, grave, &PileZoneLogic::moveAllToZone); - - aMoveRfgToTopLibrary = new QAction(this); - aMoveRfgToTopLibrary->setData(QList() << "deck" << 0); - aMoveRfgToBottomLibrary = new QAction(this); - aMoveRfgToBottomLibrary->setData(QList() << "deck" << -1); - aMoveRfgToHand = new QAction(this); - aMoveRfgToHand->setData(QList() << "hand" << 0); - aMoveRfgToGrave = new QAction(this); - aMoveRfgToGrave->setData(QList() << "grave" << 0); - - connect(aMoveRfgToTopLibrary, &QAction::triggered, rfg, &PileZoneLogic::moveAllToZone); - connect(aMoveRfgToBottomLibrary, &QAction::triggered, rfg, &PileZoneLogic::moveAllToZone); - connect(aMoveRfgToHand, &QAction::triggered, rfg, &PileZoneLogic::moveAllToZone); - connect(aMoveRfgToGrave, &QAction::triggered, rfg, &PileZoneLogic::moveAllToZone); - - aMoveTopToPlay = new QAction(this); - connect(aMoveTopToPlay, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardToPlay); - aMoveTopToPlayFaceDown = new QAction(this); - connect(aMoveTopToPlayFaceDown, &QAction::triggered, playerActions, - &PlayerActions::actMoveTopCardToPlayFaceDown); - aMoveTopCardToGraveyard = new QAction(this); - connect(aMoveTopCardToGraveyard, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardToGrave); - aMoveTopCardToExile = new QAction(this); - connect(aMoveTopCardToExile, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardToExile); - aMoveTopCardsToGraveyard = new QAction(this); - connect(aMoveTopCardsToGraveyard, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardsToGrave); - aMoveTopCardsToExile = new QAction(this); - connect(aMoveTopCardsToExile, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardsToExile); - aMoveTopCardsUntil = new QAction(this); - connect(aMoveTopCardsUntil, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardsUntil); - aMoveTopCardToBottom = new QAction(this); - connect(aMoveTopCardToBottom, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardToBottom); - - aMoveBottomToPlay = new QAction(this); - connect(aMoveBottomToPlay, &QAction::triggered, playerActions, &PlayerActions::actMoveBottomCardToPlay); - aMoveBottomToPlayFaceDown = new QAction(this); - connect(aMoveBottomToPlayFaceDown, &QAction::triggered, playerActions, - &PlayerActions::actMoveBottomCardToPlayFaceDown); - aMoveBottomCardToGraveyard = new QAction(this); - connect(aMoveBottomCardToGraveyard, &QAction::triggered, playerActions, - &PlayerActions::actMoveBottomCardToGrave); - aMoveBottomCardToExile = new QAction(this); - connect(aMoveBottomCardToExile, &QAction::triggered, playerActions, &PlayerActions::actMoveBottomCardToExile); - aMoveBottomCardsToGraveyard = new QAction(this); - connect(aMoveBottomCardsToGraveyard, &QAction::triggered, playerActions, - &PlayerActions::actMoveBottomCardsToGrave); - aMoveBottomCardsToExile = new QAction(this); - connect(aMoveBottomCardsToExile, &QAction::triggered, playerActions, &PlayerActions::actMoveBottomCardsToExile); - aMoveBottomCardToTop = new QAction(this); - connect(aMoveBottomCardToTop, &QAction::triggered, playerActions, &PlayerActions::actMoveBottomCardToTop); - } -} - -void PlayerMenu::createViewActions() -{ - PlayerActions *playerActions = player->getPlayerActions(); - - aViewGraveyard = new QAction(this); - connect(aViewGraveyard, &QAction::triggered, playerActions, &PlayerActions::actViewGraveyard); - - aViewRfg = new QAction(this); - connect(aViewRfg, &QAction::triggered, playerActions, &PlayerActions::actViewRfg); - - if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { - aViewLibrary = new QAction(this); - connect(aViewLibrary, &QAction::triggered, playerActions, &PlayerActions::actViewLibrary); - aViewSideboard = new QAction(this); - connect(aViewSideboard, &QAction::triggered, playerActions, &PlayerActions::actViewSideboard); - - aViewHand = new QAction(this); - connect(aViewHand, &QAction::triggered, playerActions, &PlayerActions::actViewHand); - aSortHand = new QAction(this); - connect(aSortHand, &QAction::triggered, playerActions, &PlayerActions::actSortHand); - - aViewTopCards = new QAction(this); - connect(aViewTopCards, &QAction::triggered, playerActions, &PlayerActions::actViewTopCards); - aViewBottomCards = new QAction(this); - connect(aViewBottomCards, &QAction::triggered, playerActions, &PlayerActions::actViewBottomCards); - aAlwaysRevealTopCard = new QAction(this); - aAlwaysRevealTopCard->setCheckable(true); - connect(aAlwaysRevealTopCard, &QAction::triggered, playerActions, &PlayerActions::actAlwaysRevealTopCard); - aAlwaysLookAtTopCard = new QAction(this); - aAlwaysLookAtTopCard->setCheckable(true); - connect(aAlwaysLookAtTopCard, &QAction::triggered, playerActions, &PlayerActions::actAlwaysLookAtTopCard); - aOpenDeckInDeckEditor = new QAction(this); - aOpenDeckInDeckEditor->setEnabled(false); - connect(aOpenDeckInDeckEditor, &QAction::triggered, playerActions, &PlayerActions::actOpenDeckInDeckEditor); - } -} - -void PlayerMenu::refreshShortcuts() -{ - if (shortcutsActive) { - setShortcutsActive(); - } -} - -void PlayerMenu::addPlayer(Player *playerToAdd) -{ - if (playerToAdd == nullptr || playerToAdd == player) { - return; - } - - for (auto &playerList : playerLists) { - addPlayerToList(playerList, playerToAdd); - } - for (auto &playerList : singlePlayerLists) { - addPlayerToList(playerList, playerToAdd); - } - - playersInfo.append(qMakePair(playerToAdd->getPlayerInfo()->getName(), playerToAdd->getPlayerInfo()->getId())); -} - -void PlayerMenu::addPlayerToList(QMenu *playerList, Player *playerToAdd) -{ - QAction *newAction = playerList->addAction(playerToAdd->getPlayerInfo()->getName()); - newAction->setData(playerToAdd->getPlayerInfo()->getId()); - connect(newAction, &QAction::triggered, this, &PlayerMenu::playerListActionTriggered); -} - -void PlayerMenu::removePlayer(Player *playerToRemove) -{ - if (playerToRemove == nullptr) { - return; - } - - for (auto &playerList : playerLists) { - removePlayerFromList(playerList, playerToRemove); - } - for (auto &playerList : singlePlayerLists) { - removePlayerFromList(playerList, playerToRemove); - } - - for (auto it = playersInfo.begin(); it != playersInfo.end();) { - if (it->second == playerToRemove->getPlayerInfo()->getId()) { - it = playersInfo.erase(it); - } else { - ++it; - } - } -} - -void PlayerMenu::removePlayerFromList(QMenu *playerList, Player *player) -{ - QList actionList = playerList->actions(); - for (auto &j : actionList) - if (j->data().toInt() == player->getPlayerInfo()->getId()) { - playerList->removeAction(j); - j->deleteLater(); - } -} - -void PlayerMenu::playerListActionTriggered() -{ - auto *action = static_cast(sender()); - auto *menu = static_cast(action->parent()); - - Command_RevealCards cmd; - const int otherPlayerId = action->data().toInt(); - if (otherPlayerId != -1) { - cmd.set_player_id(otherPlayerId); - } - - if (menu == mRevealLibrary || menu == mLendLibrary) { - cmd.set_zone_name("deck"); - cmd.set_grant_write_access(menu == mLendLibrary); - } else if (menu == mRevealTopCard) { - int deckSize = player->getDeckZone()->getCards().size(); - bool ok; - int number = QInputDialog::getInt(player->getGame()->getTab(), tr("Reveal top cards of library"), - tr("Number of cards: (max. %1)").arg(deckSize), /* defaultNumberTopCards */ 1, - 1, deckSize, 1, &ok); - if (ok) { - cmd.set_zone_name("deck"); - cmd.set_top_cards(number); - // backward compatibility: servers before #1051 only permits to reveal the first card - cmd.add_card_id(0); - // defaultNumberTopCards = number; - } - } else if (menu == mRevealHand) { - cmd.set_zone_name("hand"); - } else if (menu == mRevealRandomHandCard) { - cmd.set_zone_name("hand"); - cmd.add_card_id(PlayerActions::RANDOM_CARD_FROM_ZONE); - } else { - return; - } - - player->getPlayerActions()->sendGameCommand(cmd); -} - -void PlayerMenu::initContextualPlayersMenu(QMenu *menu) -{ - menu->addAction(tr("&All players"))->setData(-1); - menu->addSeparator(); - - for (const auto &playerInfo : playersInfo) { - menu->addAction(playerInfo.first)->setData(playerInfo.second); - } -} - -QMenu *PlayerMenu::createCardMenu(const CardItem *card) -{ - if (card == nullptr) { - return nullptr; - } - - bool revealedCard = false; - bool writeableCard = player->getPlayerInfo()->getLocalOrJudge(); - if (auto *view = qobject_cast(card->getZone())) { - if (view->getRevealZone()) { - if (view->getWriteableRevealZone()) { - writeableCard = true; - } else { - revealedCard = true; - } - } - } - - QMenu *cardMenu = new QMenu; - - if (revealedCard) { - cardMenu->addAction(aHide); - cardMenu->addAction(aClone); - cardMenu->addSeparator(); - cardMenu->addAction(aSelectAll); - cardMenu->addAction(aSelectColumn); - addRelatedCardView(card, cardMenu); - } else if (writeableCard) { - bool canModifyCard = player->getPlayerInfo()->judge || card->getOwner() == player; - - if (card->getZone()) { - if (card->getZone()->getName() == "table") { - // Card is on the battlefield - - if (!canModifyCard) { - addRelatedCardView(card, cardMenu); - addRelatedCardActions(card, cardMenu); - - cardMenu->addSeparator(); - cardMenu->addAction(aDrawArrow); - cardMenu->addSeparator(); - cardMenu->addAction(aClone); - cardMenu->addSeparator(); - cardMenu->addAction(aSelectAll); - cardMenu->addAction(aSelectRow); - return cardMenu; - } - - cardMenu->addAction(aTap); - cardMenu->addAction(aDoesntUntap); - cardMenu->addAction(aFlip); - if (card->getFaceDown()) { - cardMenu->addAction(aPeek); - } - - addRelatedCardView(card, cardMenu); - addRelatedCardActions(card, cardMenu); - - cardMenu->addSeparator(); - cardMenu->addAction(aAttach); - if (card->getAttachedTo()) { - cardMenu->addAction(aUnattach); - } - cardMenu->addAction(aDrawArrow); - cardMenu->addSeparator(); - cardMenu->addMenu(createPtMenu()); - cardMenu->addAction(aSetAnnotation); - cardMenu->addSeparator(); - cardMenu->addAction(aClone); - cardMenu->addMenu(createMoveMenu()); - cardMenu->addSeparator(); - cardMenu->addAction(aSelectAll); - cardMenu->addAction(aSelectRow); - - cardMenu->addSeparator(); - mCardCounters->clear(); - for (int i = 0; i < aAddCounter.size(); ++i) { - mCardCounters->addSeparator(); - mCardCounters->addAction(aAddCounter[i]); - if (card->getCounters().contains(i)) { - mCardCounters->addAction(aRemoveCounter[i]); - } - mCardCounters->addAction(aSetCounter[i]); - } - cardMenu->addSeparator(); - cardMenu->addMenu(mCardCounters); - } else if (card->getZone()->getName() == "stack") { - // Card is on the stack - if (canModifyCard) { - cardMenu->addAction(aAttach); - cardMenu->addAction(aDrawArrow); - cardMenu->addSeparator(); - cardMenu->addAction(aClone); - cardMenu->addMenu(createMoveMenu()); - cardMenu->addSeparator(); - cardMenu->addAction(aSelectAll); - } else { - cardMenu->addAction(aDrawArrow); - cardMenu->addSeparator(); - cardMenu->addAction(aClone); - cardMenu->addSeparator(); - cardMenu->addAction(aSelectAll); - } - - addRelatedCardView(card, cardMenu); - addRelatedCardActions(card, cardMenu); - } else if (card->getZone()->getName() == "rfg" || card->getZone()->getName() == "grave") { - // Card is in the graveyard or exile - if (canModifyCard) { - cardMenu->addAction(aPlay); - cardMenu->addAction(aPlayFacedown); - - cardMenu->addSeparator(); - cardMenu->addAction(aClone); - cardMenu->addMenu(createMoveMenu()); - cardMenu->addSeparator(); - cardMenu->addAction(aSelectAll); - cardMenu->addAction(aSelectColumn); - - cardMenu->addSeparator(); - cardMenu->addAction(aAttach); - cardMenu->addAction(aDrawArrow); - } else { - cardMenu->addAction(aClone); - cardMenu->addSeparator(); - cardMenu->addAction(aSelectAll); - cardMenu->addAction(aSelectColumn); - cardMenu->addSeparator(); - cardMenu->addAction(aDrawArrow); - } - - addRelatedCardView(card, cardMenu); - addRelatedCardActions(card, cardMenu); - } else { - // Card is in hand or a custom zone specified by server - cardMenu->addAction(aPlay); - cardMenu->addAction(aPlayFacedown); - - QMenu *revealMenu = cardMenu->addMenu(tr("Re&veal to...")); - initContextualPlayersMenu(revealMenu); - - connect(revealMenu, &QMenu::triggered, player->getPlayerActions(), &PlayerActions::actReveal); - - cardMenu->addSeparator(); - cardMenu->addAction(aClone); - cardMenu->addMenu(createMoveMenu()); - - // actions that are really wonky when done from deck or sideboard - if (card->getZone()->getName() == "hand") { - cardMenu->addSeparator(); - cardMenu->addAction(aAttach); - cardMenu->addAction(aDrawArrow); - } - - cardMenu->addSeparator(); - cardMenu->addAction(aSelectAll); - if (qobject_cast(card->getZone())) { - cardMenu->addAction(aSelectColumn); - } - - addRelatedCardView(card, cardMenu); - if (card->getZone()->getName() == "hand") { - addRelatedCardActions(card, cardMenu); - } - } - } else { - cardMenu->addMenu(createMoveMenu()); - } - } else { - if (card->getZone() && card->getZone()->getName() != "hand") { - cardMenu->addAction(aDrawArrow); - cardMenu->addSeparator(); - addRelatedCardView(card, cardMenu); - addRelatedCardActions(card, cardMenu); - cardMenu->addSeparator(); - cardMenu->addAction(aClone); - cardMenu->addSeparator(); - cardMenu->addAction(aSelectAll); - } - } - - return cardMenu; -} - -/** - * Creates a card menu from the given card and sets it as the currently active card menu. - * Will first check if the card should have a card menu, and no-ops if not. - * - * @param card The card to create the menu for. Pass nullptr to disable the card menu. - * @return The new card menu, or nullptr if failed. - */ -QMenu *PlayerMenu::updateCardMenu(const CardItem *card) -{ - if (!card) { - emit cardMenuUpdated(nullptr); - return nullptr; - } - - // If is spectator (as spectators don't need card menus), return - // only update the menu if the card is actually selected - if ((player->getGame()->getPlayerManager()->isSpectator() && !player->getGame()->getPlayerManager()->isJudge()) || - player->getGame()->getActiveCard() != card) { - return nullptr; - } - - QMenu *menu = createCardMenu(card); - emit cardMenuUpdated(menu); - - return menu; -} - -QMenu *PlayerMenu::createPtMenu() const -{ - QMenu *ptMenu = new QMenu(tr("Power / toughness")); - ptMenu->addAction(aIncP); - ptMenu->addAction(aDecP); - ptMenu->addAction(aFlowP); - ptMenu->addSeparator(); - ptMenu->addAction(aIncT); - ptMenu->addAction(aDecT); - ptMenu->addAction(aFlowT); - ptMenu->addSeparator(); - ptMenu->addAction(aIncPT); - ptMenu->addAction(aDecPT); - ptMenu->addSeparator(); - ptMenu->addAction(aSetPT); - ptMenu->addAction(aResetPT); - return ptMenu; -} - -QMenu *PlayerMenu::createMoveMenu() const -{ - QMenu *moveMenu = new QMenu(tr("Move to")); - moveMenu->addAction(aMoveToTopLibrary); - moveMenu->addAction(aMoveToXfromTopOfLibrary); - moveMenu->addAction(aMoveToBottomLibrary); - moveMenu->addSeparator(); - moveMenu->addAction(aMoveToHand); - moveMenu->addSeparator(); - moveMenu->addAction(aMoveToGraveyard); - moveMenu->addSeparator(); - moveMenu->addAction(aMoveToExile); - return moveMenu; -} - -void PlayerMenu::addRelatedCardView(const CardItem *card, QMenu *cardMenu) -{ - if (!card || !cardMenu) { - return; - } - auto exactCard = card->getCard(); - if (!exactCard) { - return; - } - - bool atLeastOneGoodRelationFound = false; - QList relatedCards = exactCard.getInfo().getAllRelatedCards(); - for (const CardRelation *cardRelation : relatedCards) { - CardInfoPtr relatedCard = CardDatabaseManager::getInstance()->getCardInfo(cardRelation->getName()); - if (relatedCard != nullptr) { - atLeastOneGoodRelationFound = true; - break; - } - } - - if (!atLeastOneGoodRelationFound) { - return; - } - - cardMenu->addSeparator(); - auto viewRelatedCards = new QMenu(tr("View related cards")); - cardMenu->addMenu(viewRelatedCards); - for (const CardRelation *relatedCard : relatedCards) { - QString relatedCardName = relatedCard->getName(); - CardRef cardRef = {relatedCardName, exactCard.getPrinting().getUuid()}; - QAction *viewCard = viewRelatedCards->addAction(relatedCardName); - Q_UNUSED(viewCard); - - connect(viewCard, &QAction::triggered, player->getGame(), - [this, cardRef] { player->getGame()->getTab()->viewCardInfo(cardRef); }); - } -} - -void PlayerMenu::addRelatedCardActions(const CardItem *card, QMenu *cardMenu) -{ - if (!card || !cardMenu) { - return; - } - auto exactCard = card->getCard(); - if (!exactCard) { - return; - } - - QList relatedCards = exactCard.getInfo().getAllRelatedCards(); - if (relatedCards.isEmpty()) { - return; - } - - cardMenu->addSeparator(); - int index = 0; - QAction *createRelatedCards = nullptr; - for (const CardRelation *cardRelation : relatedCards) { - ExactCard relatedCard = CardDatabaseManager::getInstance()->getCardFromSameSet(cardRelation->getName(), - card->getCard().getPrinting()); - if (!relatedCard) { - relatedCard = CardDatabaseManager::getInstance()->getCard({cardRelation->getName()}); - } - if (!relatedCard) { - continue; - } - - QString relatedCardName; - if (relatedCard.getInfo().getPowTough().size() > 0) { - relatedCardName = relatedCard.getInfo().getPowTough() + " " + relatedCard.getName(); // "n/n name" - } else { - relatedCardName = relatedCard.getName(); // "name" - } - - QString text = tr("Token: "); - if (cardRelation->getDoesAttach()) { - text += - tr(cardRelation->getDoesTransform() ? "Transform into " : "Attach to ") + "\"" + relatedCardName + "\""; - } else if (cardRelation->getIsVariable()) { - text += "X " + relatedCardName; - } else if (cardRelation->getDefaultCount() != 1) { - text += QString::number(cardRelation->getDefaultCount()) + "x " + relatedCardName; - } else { - text += relatedCardName; - } - - if (createRelatedCards == nullptr) { - if (relatedCards.length() == 1) { - createRelatedCards = new QAction(text, this); // set actCreateAllRelatedCards with this text - break; // do not set an individual entry as there is only one entry - } else { - createRelatedCards = new QAction(tr("All tokens"), this); - } - } - - auto *createRelated = new QAction(text, this); - createRelated->setData(QVariant(index++)); - connect(createRelated, &QAction::triggered, player->getPlayerActions(), &PlayerActions::actCreateRelatedCard); - cardMenu->addAction(createRelated); - } - - if (createRelatedCards) { - if (shortcutsActive) { - createRelatedCards->setShortcuts( - SettingsCache::instance().shortcuts().getShortcut("Player/aCreateRelatedTokens")); - } - connect(createRelatedCards, &QAction::triggered, player->getPlayerActions(), - &PlayerActions::actCreateAllRelatedCards); - cardMenu->addAction(createRelatedCards); - } -} - -void PlayerMenu::clearCustomZonesMenu() -{ - // Can be null if we are not the local player! - if (mCustomZones) { - mCustomZones->clear(); - mCustomZones->menuAction()->setVisible(false); - } -} - -void PlayerMenu::addViewCustomZoneActionToCustomZoneMenu(QString zoneName) -{ - if (mCustomZones) { - mCustomZones->menuAction()->setVisible(true); - QAction *aViewZone = mCustomZones->addAction(tr("View custom zone '%1'").arg(zoneName)); - aViewZone->setData(zoneName); - connect(aViewZone, &QAction::triggered, this, - [zoneName, this]() { player->getGameScene()->toggleZoneView(player, zoneName, -1); }); - } -} - -void PlayerMenu::populatePredefinedTokensMenu() -{ - DeckLoader *_deck = player->getDeck(); - createPredefinedTokenMenu->clear(); - createPredefinedTokenMenu->setEnabled(false); - predefinedTokens.clear(); - InnerDecklistNode *tokenZone = dynamic_cast(_deck->getRoot()->findChild(DECK_ZONE_TOKENS)); - - if (tokenZone) { - if (!tokenZone->empty()) - createPredefinedTokenMenu->setEnabled(true); - - for (int i = 0; i < tokenZone->size(); ++i) { - const QString tokenName = tokenZone->at(i)->getName(); - predefinedTokens.append(tokenName); - QAction *a = createPredefinedTokenMenu->addAction(tokenName); - if (i < 10) { - a->setShortcut(QKeySequence("Alt+" + QString::number((i + 1) % 10))); - } - connect(a, &QAction::triggered, player->getPlayerActions(), &PlayerActions::actCreatePredefinedToken); - } - } -} - -void PlayerMenu::enableOpenInDeckEditorAction() const -{ - aOpenDeckInDeckEditor->setEnabled(true); -} - -void PlayerMenu::resetTopCardMenuActions() -{ - aAlwaysRevealTopCard->setChecked(false); - aAlwaysLookAtTopCard->setChecked(false); -} - -void PlayerMenu::retranslateUi() -{ - aViewGraveyard->setText(tr("&View graveyard")); - aViewRfg->setText(tr("&View exile")); - - playerMenu->setTitle(tr("Player \"%1\"").arg(player->getPlayerInfo()->getName())); - graveMenu->setTitle(tr("&Graveyard")); - rfgMenu->setTitle(tr("&Exile")); - - if (player->getPlayerInfo()->getLocalOrJudge()) { - moveHandMenu->setTitle(tr("&Move hand to...")); - aMoveHandToTopLibrary->setText(tr("&Top of library")); - aMoveHandToBottomLibrary->setText(tr("&Bottom of library")); - aMoveHandToGrave->setText(tr("&Graveyard")); - aMoveHandToRfg->setText(tr("&Exile")); - - moveGraveMenu->setTitle(tr("&Move graveyard to...")); - aMoveGraveToTopLibrary->setText(tr("&Top of library")); - aMoveGraveToBottomLibrary->setText(tr("&Bottom of library")); - aMoveGraveToHand->setText(tr("&Hand")); - aMoveGraveToRfg->setText(tr("&Exile")); - - moveRfgMenu->setTitle(tr("&Move exile to...")); - aMoveRfgToTopLibrary->setText(tr("&Top of library")); - aMoveRfgToBottomLibrary->setText(tr("&Bottom of library")); - aMoveRfgToHand->setText(tr("&Hand")); - aMoveRfgToGrave->setText(tr("&Graveyard")); - - aViewLibrary->setText(tr("&View library")); - aViewHand->setText(tr("&View hand")); - aSortHand->setText(tr("&Sort hand")); - aViewTopCards->setText(tr("View &top cards of library...")); - aViewBottomCards->setText(tr("View bottom cards of library...")); - mRevealLibrary->setTitle(tr("Reveal &library to...")); - mLendLibrary->setTitle(tr("Lend library to...")); - mRevealTopCard->setTitle(tr("Reveal &top cards to...")); - topLibraryMenu->setTitle(tr("&Top of library...")); - bottomLibraryMenu->setTitle(tr("&Bottom of library...")); - aAlwaysRevealTopCard->setText(tr("&Always reveal top card")); - aAlwaysLookAtTopCard->setText(tr("&Always look at top card")); - aOpenDeckInDeckEditor->setText(tr("&Open deck in deck editor")); - aViewSideboard->setText(tr("&View sideboard")); - aDrawCard->setText(tr("&Draw card")); - aDrawCards->setText(tr("D&raw cards...")); - aUndoDraw->setText(tr("&Undo last draw")); - aMulligan->setText(tr("Take &mulligan")); - - aShuffle->setText(tr("Shuffle")); - - aMoveTopToPlay->setText(tr("&Play top card")); - aMoveTopToPlayFaceDown->setText(tr("Play top card &face down")); - aMoveTopCardToBottom->setText(tr("Put top card on &bottom")); - aMoveTopCardToGraveyard->setText(tr("Move top card to grave&yard")); - aMoveTopCardToExile->setText(tr("Move top card to e&xile")); - aMoveTopCardsToGraveyard->setText(tr("Move top cards to &graveyard...")); - aMoveTopCardsToExile->setText(tr("Move top cards to &exile...")); - aMoveTopCardsUntil->setText(tr("Put top cards on stack &until...")); - aShuffleTopCards->setText(tr("Shuffle top cards...")); - - aDrawBottomCard->setText(tr("&Draw bottom card")); - aDrawBottomCards->setText(tr("D&raw bottom cards...")); - aMoveBottomToPlay->setText(tr("&Play bottom card")); - aMoveBottomToPlayFaceDown->setText(tr("Play bottom card &face down")); - aMoveBottomCardToGraveyard->setText(tr("Move bottom card to grave&yard")); - aMoveBottomCardToExile->setText(tr("Move bottom card to e&xile")); - aMoveBottomCardsToGraveyard->setText(tr("Move bottom cards to &graveyard...")); - aMoveBottomCardsToExile->setText(tr("Move bottom cards to &exile...")); - aMoveBottomCardToTop->setText(tr("Put bottom card on &top")); - aShuffleBottomCards->setText(tr("Shuffle bottom cards...")); - - handMenu->setTitle(tr("&Hand")); - mRevealHand->setTitle(tr("&Reveal hand to...")); - mRevealRandomHandCard->setTitle(tr("Reveal r&andom card to...")); - mRevealRandomGraveyardCard->setTitle(tr("Reveal random card to...")); - sbMenu->setTitle(tr("&Sideboard")); - libraryMenu->setTitle(tr("&Library")); - countersMenu->setTitle(tr("&Counters")); - mCustomZones->setTitle(tr("C&ustom Zones")); - - for (auto aViewZone : mCustomZones->actions()) { - aViewZone->setText(tr("View custom zone '%1'").arg(aViewZone->data().toString())); - } - - aIncrementAllCardCounters->setText(tr("Increment all card counters")); - aUntapAll->setText(tr("&Untap all permanents")); - aRollDie->setText(tr("R&oll die...")); - aCreateToken->setText(tr("&Create token...")); - aCreateAnotherToken->setText(tr("C&reate another token")); - createPredefinedTokenMenu->setTitle(tr("Cr&eate predefined token")); - - mCardCounters->setTitle(tr("Ca&rd counters")); - - for (auto &allPlayersAction : allPlayersActions) { - allPlayersAction->setText(tr("&All players")); - } - } - - if (player->getPlayerInfo()->getLocal()) { - sayMenu->setTitle(tr("S&ay")); - } - - aSelectAll->setText(tr("&Select All")); - aSelectRow->setText(tr("S&elect Row")); - aSelectColumn->setText(tr("S&elect Column")); - - aPlay->setText(tr("&Play")); - aHide->setText(tr("&Hide")); - aPlayFacedown->setText(tr("Play &Face Down")); - //: Turn sideways or back again - aTap->setText(tr("&Tap / Untap")); - aDoesntUntap->setText(tr("Toggle &normal untapping")); - //: Turn face up/face down - aFlip->setText(tr("T&urn Over")); // Only the user facing names in client got renamed to "turn over" - // All code and proto bits are still unchanged (flip) for compatibility reasons - // A protocol rewrite with v3 could incorporate that, see #3100 - aPeek->setText(tr("&Peek at card face")); - aClone->setText(tr("&Clone")); - aAttach->setText(tr("Attac&h to card...")); - aUnattach->setText(tr("Unattac&h")); - aDrawArrow->setText(tr("&Draw arrow...")); - aIncP->setText(tr("&Increase power")); - aDecP->setText(tr("&Decrease power")); - aIncT->setText(tr("I&ncrease toughness")); - aDecT->setText(tr("D&ecrease toughness")); - aIncPT->setText(tr("In&crease power and toughness")); - aDecPT->setText(tr("Dec&rease power and toughness")); - aFlowP->setText(tr("Increase power and decrease toughness")); - aFlowT->setText(tr("Decrease power and increase toughness")); - aSetPT->setText(tr("Set &power and toughness...")); - aResetPT->setText(tr("Reset p&ower and toughness")); - aSetAnnotation->setText(tr("&Set annotation...")); - - auto &cardCounterSettings = SettingsCache::instance().cardCounters(); - - for (int i = 0; i < aAddCounter.size(); ++i) { - aAddCounter[i]->setText(tr("&Add counter (%1)").arg(cardCounterSettings.displayName(i))); - } - for (int i = 0; i < aRemoveCounter.size(); ++i) { - aRemoveCounter[i]->setText(tr("&Remove counter (%1)").arg(cardCounterSettings.displayName(i))); - } - for (int i = 0; i < aSetCounter.size(); ++i) { - aSetCounter[i]->setText(tr("&Set counters (%1)...").arg(cardCounterSettings.displayName(i))); - } - - aMoveToTopLibrary->setText(tr("&Top of library in random order")); - aMoveToXfromTopOfLibrary->setText(tr("X cards from the top of library...")); - aMoveToBottomLibrary->setText(tr("&Bottom of library in random order")); - aMoveToHand->setText(tr("&Hand")); - aMoveToGraveyard->setText(tr("&Graveyard")); - aMoveToExile->setText(tr("&Exile")); -} - -void PlayerMenu::setShortcutIfItExists(QAction *action, ShortcutKey shortcut) -{ - if (action) { - action->setShortcuts(shortcut); - } -} - -void PlayerMenu::clearShortcutIfItExists(QAction *action) -{ - if (action) { - action->setShortcut(QKeySequence()); - } -} - -void PlayerMenu::setShortcutsActive() -{ - shortcutsActive = true; - ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); - - setShortcutIfItExists(aHide, shortcuts.getShortcut("Player/aHide")); - setShortcutIfItExists(aPlay, shortcuts.getShortcut("Player/aPlay")); - setShortcutIfItExists(aTap, shortcuts.getShortcut("Player/aTap")); - setShortcutIfItExists(aDoesntUntap, shortcuts.getShortcut("Player/aDoesntUntap")); - setShortcutIfItExists(aFlip, shortcuts.getShortcut("Player/aFlip")); - setShortcutIfItExists(aPeek, shortcuts.getShortcut("Player/aPeek")); - setShortcutIfItExists(aClone, shortcuts.getShortcut("Player/aClone")); - setShortcutIfItExists(aAttach, shortcuts.getShortcut("Player/aAttach")); - setShortcutIfItExists(aUnattach, shortcuts.getShortcut("Player/aUnattach")); - setShortcutIfItExists(aDrawArrow, shortcuts.getShortcut("Player/aDrawArrow")); - setShortcutIfItExists(aIncP, shortcuts.getShortcut("Player/aIncP")); - setShortcutIfItExists(aDecP, shortcuts.getShortcut("Player/aDecP")); - setShortcutIfItExists(aIncT, shortcuts.getShortcut("Player/aIncT")); - setShortcutIfItExists(aDecT, shortcuts.getShortcut("Player/aDecT")); - setShortcutIfItExists(aIncPT, shortcuts.getShortcut("Player/aIncPT")); - setShortcutIfItExists(aDecPT, shortcuts.getShortcut("Player/aDecPT")); - setShortcutIfItExists(aFlowP, shortcuts.getShortcut("Player/aFlowP")); - setShortcutIfItExists(aFlowT, shortcuts.getShortcut("Player/aFlowT")); - setShortcutIfItExists(aSetPT, shortcuts.getShortcut("Player/aSetPT")); - setShortcutIfItExists(aResetPT, shortcuts.getShortcut("Player/aResetPT")); - setShortcutIfItExists(aSetAnnotation, shortcuts.getShortcut("Player/aSetAnnotation")); - setShortcutIfItExists(aMoveToTopLibrary, shortcuts.getShortcut("Player/aMoveToTopLibrary")); - setShortcutIfItExists(aMoveToBottomLibrary, shortcuts.getShortcut("Player/aMoveToBottomLibrary")); - setShortcutIfItExists(aMoveToHand, shortcuts.getShortcut("Player/aMoveToHand")); - setShortcutIfItExists(aMoveToGraveyard, shortcuts.getShortcut("Player/aMoveToGraveyard")); - setShortcutIfItExists(aMoveToExile, shortcuts.getShortcut("Player/aMoveToExile")); - setShortcutIfItExists(aSortHand, shortcuts.getShortcut("Player/aSortHand")); - - setShortcutIfItExists(aSelectAll, shortcuts.getShortcut("Player/aSelectAll")); - setShortcutIfItExists(aSelectRow, shortcuts.getShortcut("Player/aSelectRow")); - setShortcutIfItExists(aSelectColumn, shortcuts.getShortcut("Player/aSelectColumn")); - - static const QStringList colorWords = {"Red", "Yellow", "Green", "Cyan", "Purple", "Magenta"}; - for (int i = 0; i < aAddCounter.size(); i++) { - setShortcutIfItExists(aAddCounter[i], shortcuts.getShortcut("Player/aCC" + colorWords[i])); - setShortcutIfItExists(aRemoveCounter[i], shortcuts.getShortcut("Player/aRC" + colorWords[i])); - setShortcutIfItExists(aSetCounter[i], shortcuts.getShortcut("Player/aSC" + colorWords[i])); - } - - QMapIterator counterIterator(player->getCounters()); - while (counterIterator.hasNext()) { - counterIterator.next().value()->setShortcutsActive(); - } - - setShortcutIfItExists(aIncrementAllCardCounters, shortcuts.getShortcut("Player/aIncrementAllCardCounters")); - setShortcutIfItExists(aViewSideboard, shortcuts.getShortcut("Player/aViewSideboard")); - setShortcutIfItExists(aViewLibrary, shortcuts.getShortcut("Player/aViewLibrary")); - setShortcutIfItExists(aViewHand, shortcuts.getShortcut("Player/aViewHand")); - setShortcutIfItExists(aViewTopCards, shortcuts.getShortcut("Player/aViewTopCards")); - setShortcutIfItExists(aViewBottomCards, shortcuts.getShortcut("Player/aViewBottomCards")); - setShortcutIfItExists(aViewGraveyard, shortcuts.getShortcut("Player/aViewGraveyard")); - setShortcutIfItExists(aDrawCard, shortcuts.getShortcut("Player/aDrawCard")); - setShortcutIfItExists(aDrawCards, shortcuts.getShortcut("Player/aDrawCards")); - setShortcutIfItExists(aUndoDraw, shortcuts.getShortcut("Player/aUndoDraw")); - setShortcutIfItExists(aMulligan, shortcuts.getShortcut("Player/aMulligan")); - setShortcutIfItExists(aShuffle, shortcuts.getShortcut("Player/aShuffle")); - setShortcutIfItExists(aShuffleTopCards, shortcuts.getShortcut("Player/aShuffleTopCards")); - setShortcutIfItExists(aShuffleBottomCards, shortcuts.getShortcut("Player/aShuffleBottomCards")); - setShortcutIfItExists(aUntapAll, shortcuts.getShortcut("Player/aUntapAll")); - setShortcutIfItExists(aRollDie, shortcuts.getShortcut("Player/aRollDie")); - setShortcutIfItExists(aCreateToken, shortcuts.getShortcut("Player/aCreateToken")); - setShortcutIfItExists(aCreateAnotherToken, shortcuts.getShortcut("Player/aCreateAnotherToken")); - setShortcutIfItExists(aAlwaysRevealTopCard, shortcuts.getShortcut("Player/aAlwaysRevealTopCard")); - setShortcutIfItExists(aAlwaysLookAtTopCard, shortcuts.getShortcut("Player/aAlwaysLookAtTopCard")); - setShortcutIfItExists(aMoveTopToPlay, shortcuts.getShortcut("Player/aMoveTopToPlay")); - setShortcutIfItExists(aMoveTopToPlayFaceDown, shortcuts.getShortcut("Player/aMoveTopToPlayFaceDown")); - setShortcutIfItExists(aMoveTopCardToGraveyard, shortcuts.getShortcut("Player/aMoveTopCardToGraveyard")); - setShortcutIfItExists(aMoveTopCardsToGraveyard, shortcuts.getShortcut("Player/aMoveTopCardsToGraveyard")); - setShortcutIfItExists(aMoveTopCardToExile, shortcuts.getShortcut("Player/aMoveTopCardToExile")); - setShortcutIfItExists(aMoveTopCardsToExile, shortcuts.getShortcut("Player/aMoveTopCardsToExile")); - setShortcutIfItExists(aMoveTopCardsUntil, shortcuts.getShortcut("Player/aMoveTopCardsUntil")); - setShortcutIfItExists(aMoveTopCardToBottom, shortcuts.getShortcut("Player/aMoveTopCardToBottom")); - setShortcutIfItExists(aDrawBottomCard, shortcuts.getShortcut("Player/aDrawBottomCard")); - setShortcutIfItExists(aDrawBottomCards, shortcuts.getShortcut("Player/aDrawBottomCards")); - setShortcutIfItExists(aMoveBottomToPlay, shortcuts.getShortcut("Player/aMoveBottomToPlay")); - setShortcutIfItExists(aMoveBottomToPlayFaceDown, shortcuts.getShortcut("Player/aMoveBottomToPlayFaceDown")); - setShortcutIfItExists(aMoveBottomCardToGraveyard, shortcuts.getShortcut("Player/aMoveBottomCardToGrave")); - setShortcutIfItExists(aMoveBottomCardsToGraveyard, shortcuts.getShortcut("Player/aMoveBottomCardsToGrave")); - setShortcutIfItExists(aMoveBottomCardToExile, shortcuts.getShortcut("Player/aMoveBottomCardToExile")); - setShortcutIfItExists(aMoveBottomCardsToExile, shortcuts.getShortcut("Player/aMoveBottomCardsToExile")); - setShortcutIfItExists(aMoveBottomCardToTop, shortcuts.getShortcut("Player/aMoveBottomCardToTop")); - setShortcutIfItExists(aPlayFacedown, shortcuts.getShortcut("Player/aPlayFacedown")); - setShortcutIfItExists(aPlay, shortcuts.getShortcut("Player/aPlay")); - - // Don't enable always-active shortcuts in local games, since it causes keyboard shortcuts to work inconsistently - // when there are more than 1 player. - if (!player->getGame()->getGameState()->getIsLocalGame()) { - // unattach action is only active in card menu if the active card is attached. - // make unattach shortcut always active so that it consistently works when multiple cards are selected. - player->getGame()->getTab()->addAction(aUnattach); - } -} - -void PlayerMenu::setShortcutsInactive() -{ - shortcutsActive = false; - - clearShortcutIfItExists(aViewSideboard); - clearShortcutIfItExists(aViewLibrary); - clearShortcutIfItExists(aViewHand); - clearShortcutIfItExists(aViewTopCards); - clearShortcutIfItExists(aViewBottomCards); - clearShortcutIfItExists(aViewGraveyard); - clearShortcutIfItExists(aDrawCard); - clearShortcutIfItExists(aDrawCards); - clearShortcutIfItExists(aUndoDraw); - clearShortcutIfItExists(aMulligan); - clearShortcutIfItExists(aShuffle); - clearShortcutIfItExists(aShuffleTopCards); - clearShortcutIfItExists(aShuffleBottomCards); - clearShortcutIfItExists(aUntapAll); - clearShortcutIfItExists(aRollDie); - clearShortcutIfItExists(aCreateToken); - clearShortcutIfItExists(aCreateAnotherToken); - clearShortcutIfItExists(aAlwaysRevealTopCard); - clearShortcutIfItExists(aAlwaysLookAtTopCard); - clearShortcutIfItExists(aMoveTopToPlay); - clearShortcutIfItExists(aMoveTopToPlayFaceDown); - clearShortcutIfItExists(aMoveTopCardToGraveyard); - clearShortcutIfItExists(aMoveTopCardsToGraveyard); - clearShortcutIfItExists(aMoveTopCardToExile); - clearShortcutIfItExists(aMoveTopCardsToExile); - clearShortcutIfItExists(aMoveTopCardsUntil); - clearShortcutIfItExists(aDrawBottomCard); - clearShortcutIfItExists(aDrawBottomCards); - clearShortcutIfItExists(aMoveBottomToPlay); - clearShortcutIfItExists(aMoveBottomToPlayFaceDown); - clearShortcutIfItExists(aMoveBottomCardToGraveyard); - clearShortcutIfItExists(aMoveBottomCardsToGraveyard); - clearShortcutIfItExists(aMoveBottomCardToExile); - clearShortcutIfItExists(aMoveBottomCardsToExile); - clearShortcutIfItExists(aIncrementAllCardCounters); - clearShortcutIfItExists(aSortHand); - - QMapIterator counterIterator(player->getCounters()); - while (counterIterator.hasNext()) { - counterIterator.next().value()->setShortcutsInactive(); - } -} - -void PlayerMenu::initSayMenu() -{ - sayMenu->clear(); - - int count = SettingsCache::instance().messages().getCount(); - sayMenu->setEnabled(count > 0); - - for (int i = 0; i < count; ++i) { - auto *newAction = new QAction(SettingsCache::instance().messages().getMessageAt(i), sayMenu); - if (i < 10) { - newAction->setShortcut(QKeySequence("Ctrl+" + QString::number((i + 1) % 10))); - } - connect(newAction, &QAction::triggered, player->getPlayerActions(), &PlayerActions::actSayMessage); - sayMenu->addAction(newAction); - } -} diff --git a/cockatrice/src/game/player/player_menu.h b/cockatrice/src/game/player/player_menu.h deleted file mode 100644 index 644fbc76e..000000000 --- a/cockatrice/src/game/player/player_menu.h +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef COCKATRICE_PLAYER_MENU_H -#define COCKATRICE_PLAYER_MENU_H - -#include "../../client/tearoff_menu.h" -#include "player.h" - -#include -#include - -class PlayerMenu : public QObject -{ - Q_OBJECT - -signals: - void cardMenuUpdated(QMenu *cardMenu); - -public slots: - QMenu *createPtMenu() const; - QMenu *createMoveMenu() const; - void enableOpenInDeckEditorAction() const; - void populatePredefinedTokensMenu(); - void setMenusForGraphicItems(); - -private slots: - void addPlayer(Player *playerToAdd); - void removePlayer(Player *playerToRemove); - void playerListActionTriggered(); - void refreshShortcuts(); - void clearCustomZonesMenu(); - void addViewCustomZoneActionToCustomZoneMenu(QString zoneName); - void resetTopCardMenuActions(); - -public: - PlayerMenu(Player *player); - void createDrawActions(); - void createShuffleActions(); - void createMoveActions(); - void createViewActions(); - void retranslateUi(); - - void addPlayerToList(QMenu *playerList, Player *playerToAdd); - static void removePlayerFromList(QMenu *playerList, Player *player); - - QMenu *updateCardMenu(const CardItem *card); - - [[nodiscard]] bool createAnotherTokenActionExists() const - { - return aCreateAnotherToken != nullptr; - } - - void setAndEnableCreateAnotherTokenAction(QString text) - { - aCreateAnotherToken->setText(text); - aCreateAnotherToken->setEnabled(true); - } - - QStringList getPredefinedTokens() const - { - return predefinedTokens; - } - - [[nodiscard]] bool isAlwaysRevealTopCardChecked() - { - return aAlwaysRevealTopCard->isChecked(); - } - - [[nodiscard]] bool isAlwaysLookAtTopCardChecked() - { - return aAlwaysLookAtTopCard->isChecked(); - } - - [[nodiscard]] QMenu *getPlayerMenu() const - { - return playerMenu; - } - - [[nodiscard]] QMenu *getCountersMenu() - { - return countersMenu; - } - - bool getShortcutsActive() const - { - return shortcutsActive; - } - - void setShortcutsActive(); - void setShortcutIfItExists(QAction *action, ShortcutKey shortcut); - void clearShortcutIfItExists(QAction *action); - void setShortcutsInactive(); - -private: - Player *player; - QMenu *sbMenu, *countersMenu, *sayMenu, *createPredefinedTokenMenu, *mRevealLibrary, *mLendLibrary, *mRevealTopCard, - *mRevealHand, *mRevealRandomHandCard, *mRevealRandomGraveyardCard, *mCustomZones, *mCardCounters; - TearOffMenu *moveGraveMenu, *moveRfgMenu, *graveMenu, *moveHandMenu, *handMenu, *libraryMenu, *topLibraryMenu, - *bottomLibraryMenu, *rfgMenu, *playerMenu; - QList playerLists; - QList singlePlayerLists; - QList allPlayersActions; - QList> playersInfo; - QAction *aMoveHandToTopLibrary, *aMoveHandToBottomLibrary, *aMoveHandToGrave, *aMoveHandToRfg, - *aMoveGraveToTopLibrary, *aMoveGraveToBottomLibrary, *aMoveGraveToHand, *aMoveGraveToRfg, *aMoveRfgToTopLibrary, - *aMoveRfgToBottomLibrary, *aMoveRfgToHand, *aMoveRfgToGrave, *aViewHand, *aViewLibrary, *aViewTopCards, - *aViewBottomCards, *aAlwaysRevealTopCard, *aAlwaysLookAtTopCard, *aOpenDeckInDeckEditor, - *aMoveTopCardToGraveyard, *aMoveTopCardToExile, *aMoveTopCardsToGraveyard, *aMoveTopCardsToExile, - *aMoveTopCardsUntil, *aMoveTopCardToBottom, *aViewGraveyard, *aViewRfg, *aViewSideboard, *aDrawCard, - *aDrawCards, *aUndoDraw, *aMulligan, *aShuffle, *aShuffleTopCards, *aShuffleBottomCards, *aMoveTopToPlay, - *aMoveTopToPlayFaceDown, *aUntapAll, *aRollDie, *aCreateToken, *aCreateAnotherToken, *aMoveBottomToPlay, - *aMoveBottomToPlayFaceDown, *aMoveBottomCardToTop, *aMoveBottomCardToGraveyard, *aMoveBottomCardToExile, - *aMoveBottomCardsToGraveyard, *aMoveBottomCardsToExile, *aDrawBottomCard, *aDrawBottomCards; - - QList aAddCounter, aSetCounter, aRemoveCounter; - QAction *aPlay, *aPlayFacedown, *aHide, *aTap, *aDoesntUntap, *aAttach, *aUnattach, *aDrawArrow, *aSetPT, *aResetPT, - *aIncP, *aDecP, *aIncT, *aDecT, *aIncPT, *aDecPT, *aFlowP, *aFlowT, *aSetAnnotation, *aFlip, *aPeek, *aClone, - *aMoveToTopLibrary, *aMoveToBottomLibrary, *aMoveToHand, *aMoveToGraveyard, *aMoveToExile, - *aMoveToXfromTopOfLibrary, *aSelectAll, *aSelectRow, *aSelectColumn, *aSortHand, *aIncrementAllCardCounters; - - bool shortcutsActive; - QStringList predefinedTokens; - - QMenu *createCardMenu(const CardItem *card); - - void addRelatedCardActions(const CardItem *card, QMenu *cardMenu); - void addRelatedCardView(const CardItem *card, QMenu *cardMenu); - - void initSayMenu(); - void initContextualPlayersMenu(QMenu *menu); -}; - -#endif // COCKATRICE_PLAYER_MENU_H