Reorganize card context menus across table, stack, and graveyard/exile zones for better consistency: promote Draw Arrow and Clone actions, move related card entries to the bottom, add Play/Play Face Down to the stack menu, and flatten if/else blocks with early returns. Also fix playCard() ignoring the faceDown flag when routing instants/sorceries from the stack, which sent them to the graveyard instead of the table.
Adds a Table option to the Move menu, allowing cards to be moved directly to the battlefield from any zone. Extracts the repeated tableRow-to-grid-Y conversion logic into TableZone::tableRowToGridY(), consolidating five call sites and fixing a latent bug where cards with tableRow > 2 could land on the wrong row.
Non-QObject polymorphic interface with setShortcutsActive(), setShortcutsInactive(), and retranslateUi(). Uses regular multiple inheritance to avoid diamond inheritance with Qt's MOC.
All zone menus, SayMenu, and AbstractCounter implement this interface. PlayerMenu manages them via a managedComponents list with two template helpers (addManagedMenu/registerManagedComponent), replacing individual if-guarded lifecycle calls with a single polymorphic loop.
SayMenu now owns its shortcut and translation lifecycle instead of having PlayerMenu manage its title and shortcuts externally.
Counters are iterated via Player::getCounters() rather than managedComponents to avoid duplicating the authoritative owner's map.
* feat(game): add drag selection counter overlay
Display count of selected cards inside the lasso during drag selection.
Count appears near cursor, repositioning to stay within selection bounds.
Includes SelectionRubberBand subclass to allow label to appear above band.
QRubberBand calls raise() in showEvent/changeEvent to stay on top - this
subclass suppresses that behavior so dragCountLabel can be visible.
Adds user setting to enable/disable the drag count overlay.
* feat(game): add persistent selection counter overlay.
Display total count of selected cards in bottom-right corner when multiple cards are selected.
Updates on selection changes and window resize.
The counter connects to QGraphicsScene::selectionChanged to stay up-to-date without requiring manual refresh.
Adds user setting to enable/disable the total count overlay.
---------
Co-authored-by: RickyRister <42636155+RickyRister@users.noreply.github.com>
* fix(cmake): guard filter_string_test behind WITH_ORACLE or WITH_CLIENT. filter_string_test links against libcockatrice_filters, which is only built when WITH_ORACLE or WITH_CLIENT is enabled. Without this guard, test-only builds fail at configure time because the target doesn't exist. The guard condition mirrors the one in the root CMakeLists.txt that controls whether libcockatrice_filters is built.
* fix(cmake): centralize TEST_QT_MODULES in FindQtRuntime.cmake Each test CMakeLists.txt was independently defining TEST_QT_MODULES with its own subset of Qt modules. This duplicated knowledge that already lives in FindQtRuntime.cmake (which handles module discovery for all other targets: SERVATRICE, COCKATRICE, ORACLE). Consolidate into a single definition using the union of all test requirements (Concurrent Network Svg Widgets), matching the existing pattern for application-target modules. This ensures test-only builds (-DTEST=ON without application targets) discover all necessary Qt components.
* fix(cmake): guard libcockatrice_network behind application targets. libcockatrice_network is only needed by the client, server, and oracle targets. Other application-specific libraries (settings, models, filters) already have similar guards. This was an oversight that caused test-only builds to fail when network dependencies weren't available.
Hand and stack zones had near-identical addCardImpl() implementations, differing only in whether resetState() preserves annotations.
Extract the shared pattern into a template function (CardZoneAlgorithms::addCardToList) to eliminate duplication and enable isolated testing without Qt dependencies.
Pile, table, and zone-view logic are intentionally excluded — their post-add behavior (signals, coordinate placement, hidden cards) is materially different.
* Add local game options dialog. Introduces LocalGameOptions struct and DlgLocalGameOptions dialog to replace the previous QInputDialog for starting local games. Encapsulates game configuration with a simple interface that prevents parameter explosion as options are added. The dialog provides UI with settings persistence via SettingsCache
* integrate local game options into main window. Replaces QInputDialog with DlgLocalGameOptions in actSinglePlayer(). The startLocalGame() function now accepts LocalGameOptions, enabling configuration of starting life total and spectator visibility in addition to player count. Also adds user documentation for the local game options flow.
* Removed superfluous documentation file
* removed spectator option and moved structure definition
* Now remember settings separately and & shortcuts removed
* re-run checks
* Add ZoneNames constants for protocol zone identifiers. Introduce a centralized ZoneNames namespace providing constexpr constants for zone identifiers used in the client-server protocol. This establishes a single source of truth for zone names like TABLE, GRAVE, EXILE, HAND, DECK, SIDEBOARD, and STACK. The protocol values remain unchanged (e.g., EXILE maps to rfg for backwards compatibility) while providing meaningful constant names.
* refactor(server): use ZoneNames constants in server game logic
Replace hardcoded zone name strings with ZoneNames:: constants in:
- server_player.cpp: zone setup, draw, shuffle, mulligan operations
- server_abstract_player.cpp: card movement and token destruction
- server_game.cpp: returning cards when players leave
No functional changes - purely mechanical string literal replacement.
* refactor(client): use ZoneNames constants in core player/zone logic
Update the foundational player and zone classes to use ZoneNames::
constants instead of string literals. Changes include:
- player.h/cpp: zone initialization and builtinZones set
- card_zone_logic.cpp: zone name translation for UI display
- table_zone.cpp: table zone operations
No functional changes - purely mechanical string literal replacement.
* refactor(client): use ZoneNames constants in player actions and events
Replace zone name strings with ZoneNames:: constants in the player
action and event handling code. player_actions.cpp contains the most
extensive changes (~90+ replacements) covering all card movement
commands.
No functional changes - purely mechanical string literal replacement.
* refactor(client): use ZoneNames constants in zone menu handlers
Update all zone-specific menu files to use ZoneNames:: constants
for QAction data values and zone targeting. This covers context menus
for cards, graveyard, hand, and exile (RFG) zones.
No functional changes - purely mechanical string literal replacement.
* refactor(client): use ZoneNames constants in game scene components
Update remaining game scene components to use ZoneNames:: constants:
- arrow_item.cpp: arrow drawing between cards
- game_scene.cpp: zone view positioning
- message_log_widget.cpp: removes duplicate local static constants
that were previously defining zone names redundantly
- phases_toolbar.cpp: phase actions (untap all)
Notable: message_log_widget.cpp previously had its own local constants
(TABLE_ZONE_NAME, GRAVE_ZONE_NAME, etc.) which are now removed in favor
of the centralized ZoneNames:: constants.
* formatting fix
* [DeckList] Refactor load from plaintext to take normalizer as param
* update usages
* weaken unit test
* weaken unit test more
* revert unit test
* move CardNameNormalizer to libcockatrice_card
* update unit test
* formatting
* refactor: extract CARD_HEIGHT to shared CardDimensions header
Move duplicated CARD_WIDTH/CARD_HEIGHT constants to card_dimensions.h.
Fixed documentation in z_value_layer_manager.h.
* WIDTH_F used directly instead of casting
* Improved consistency and added missing newlines at end of files