diff --git a/.ci/prep_release.sh b/.ci/prep_release.sh
index cddf49aa6..7f4f7d961 100755
--- a/.ci/prep_release.sh
+++ b/.ci/prep_release.sh
@@ -89,6 +89,8 @@ else
echo "'$previous' to '$TAG' ($count commits)"
# --> is the markdown comment escape sequence, emojis are way better
generated_list="${generated_list//-->/→}"
+ # Escape & to preserve it from commit message into markdown output
+ generated_list="${generated_list//&/\\&}"
body="${body//--REPLACE-WITH-GENERATED-LIST--/$generated_list}"
body="${body//--REPLACE-WITH-COMMIT-COUNT--/$count}"
body="${body//--REPLACE-WITH-PREVIOUS-RELEASE-TAG--/$previous}"
diff --git a/.clang-format b/.clang-format
index 1ef3ca6db..1db97481a 100644
--- a/.clang-format
+++ b/.clang-format
@@ -3,7 +3,9 @@ AccessModifierOffset: -4
ColumnLimit: 120
---
Language: Cpp
-BreakBeforeBraces: Custom
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortFunctionsOnASingleLine: None
+BinPackParameters: false
BraceWrapping:
AfterClass: true
AfterControlStatement: false
@@ -18,16 +20,14 @@ BraceWrapping:
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
-AllowShortFunctionsOnASingleLine: None
-BinPackParameters: false
-AllowAllParametersOfDeclarationOnNextLine: false
-IndentCaseLabels: true
-PointerAlignment: Right
-SortIncludes: true
+BreakBeforeBraces: Custom
IncludeBlocks: Regroup
+IndentCaseLabels: true
+InsertBraces: true
+PointerAlignment: Right
+RemoveSemicolon: true
+SortIncludes: true
StatementAttributeLikeMacros: [emit]
-# requires clang-format 16
-# RemoveSemicolon: true
---
Language: Proto
AllowShortFunctionsOnASingleLine: None
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index b293b3937..56ad64283 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -209,6 +209,16 @@ nowadays and clean it up for you.
Lines should be 120 characters or less. Please break up lines that are too long
into smaller parts, for example at spaces or after opening a brace.
+### Documentation Comments ###
+
+Use [Doxygen](https://www.doxygen.nl/) for code documentation:
+
+- **Doc blocks**: Use `/** @brief Description */` (Javadoc-style), not `///`
+- **Member comments**: Use trailing `///<` for inline member documentation
+- **TODOs**: Use `//! \todo Description` (Qt-style), Doxygen collects them into a Todo List
+ (uses [Qt-style comments](https://www.doxygen.nl/manual/docblocks.html) with
+ Doxygen's [\todo command](https://www.doxygen.nl/manual/commands.html#cmdtodo))
+
### Memory Management ###
New code should be written using references over pointers and stack allocation
diff --git a/.github/workflows/documentation-build.yml b/.github/workflows/documentation-build.yml
index 7306c726a..b0093d6b1 100644
--- a/.github/workflows/documentation-build.yml
+++ b/.github/workflows/documentation-build.yml
@@ -1,9 +1,9 @@
name: Generate Docs
on:
- push:
- tags:
- - '*' # Only re-generate docs when a new tagged version is pushed
+ release:
+ types:
+ - published # publishing of stable releases and pre-releases
pull_request:
paths:
- 'doc/doxygen/**'
@@ -53,11 +53,11 @@ jobs:
run: doxygen Doxyfile
- name: Deploy to cockatrice.github.io
- if: github.event_name != 'pull_request'
+ if: github.event_name == 'release' || github.event_name == 'workflow_dispatch'
uses: peaceiris/actions-gh-pages@v4
with:
deploy_key: ${{ secrets.DOCS_DEPLOY_KEY }}
external_repository: Cockatrice/cockatrice.github.io
publish_branch: master
publish_dir: ./docs/html
- destination_dir: docs # Docs will live under https://cockatrice.github.io/docs/
+ destination_dir: docs # Docs will live under https://cockatrice.github.io/docs/
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 853369115..92a1be373 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -72,7 +72,7 @@ endif()
# A project name is needed for CPack
# Version can be overriden by git tags, see cmake/getversion.cmake
-project("Cockatrice" VERSION 3.0.1)
+project("Cockatrice" VERSION 3.1.0)
# Set release name if not provided via env/cmake var
if(NOT DEFINED GIT_TAG_RELEASENAME)
diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt
index 5212ef3c2..7ec717315 100644
--- a/cockatrice/CMakeLists.txt
+++ b/cockatrice/CMakeLists.txt
@@ -59,12 +59,15 @@ set(cockatrice_SOURCES
src/game/board/abstract_card_drag_item.cpp
src/game/board/abstract_card_item.cpp
src/game/board/abstract_counter.cpp
+ src/game/board/arrow_data.cpp
src/game/board/arrow_item.cpp
src/game/board/arrow_target.cpp
src/game/board/card_drag_item.cpp
src/game/board/card_item.cpp
src/game/board/card_list.cpp
+ src/game/board/card_state.cpp
src/game/board/counter_general.cpp
+ src/game/board/counter_state.cpp
src/game/board/translate_counter_name.cpp
src/game/deckview/deck_view.cpp
src/game/deckview/deck_view_container.cpp
@@ -94,30 +97,30 @@ set(cockatrice_SOURCES
src/game/player/menu/say_menu.cpp
src/game/player/menu/sideboard_menu.cpp
src/game/player/menu/utility_menu.cpp
- src/game/player/player.cpp
src/game/player/player_actions.cpp
src/game/player/player_area.cpp
src/game/player/player_event_handler.cpp
src/game/player/player_graphics_item.cpp
src/game/player/player_info.cpp
src/game/player/player_list_widget.cpp
+ src/game/player/player_logic.cpp
src/game/player/player_manager.cpp
src/game/player/player_target.cpp
src/game/replay.cpp
- src/game/zones/card_zone.cpp
- src/game/zones/hand_zone.cpp
- src/game/zones/logic/card_zone_logic.cpp
- src/game/zones/logic/hand_zone_logic.cpp
- src/game/zones/logic/pile_zone_logic.cpp
- src/game/zones/logic/stack_zone_logic.cpp
- src/game/zones/logic/table_zone_logic.cpp
- src/game/zones/logic/view_zone_logic.cpp
- src/game/zones/pile_zone.cpp
- src/game/zones/select_zone.cpp
- src/game/zones/stack_zone.cpp
- src/game/zones/table_zone.cpp
- src/game/zones/view_zone.cpp
- src/game/zones/view_zone_widget.cpp
+ src/game/zones/card_zone_logic.cpp
+ src/game/zones/hand_zone_logic.cpp
+ src/game/zones/pile_zone_logic.cpp
+ src/game/zones/stack_zone_logic.cpp
+ src/game/zones/table_zone_logic.cpp
+ src/game/zones/view_zone_logic.cpp
+ src/game_graphics/zones/card_zone.cpp
+ src/game_graphics/zones/hand_zone.cpp
+ src/game_graphics/zones/pile_zone.cpp
+ src/game_graphics/zones/select_zone.cpp
+ src/game_graphics/zones/stack_zone.cpp
+ src/game_graphics/zones/table_zone.cpp
+ src/game_graphics/zones/view_zone.cpp
+ src/game_graphics/zones/view_zone_widget.cpp
src/game_graphics/board/abstract_graphics_item.cpp
src/interface/card_picture_loader/card_picture_loader.cpp
src/interface/card_picture_loader/card_picture_loader_local.cpp
@@ -130,7 +133,13 @@ set(cockatrice_SOURCES
src/interface/layouts/overlap_layout.cpp
src/interface/widgets/utility/line_edit_completer.cpp
src/interface/pixel_map_generator.cpp
+ src/interface/theme_config.cpp
src/interface/theme_manager.cpp
+ src/interface/palette_editor/color_button.cpp
+ src/interface/palette_editor/palette_generator.cpp
+ src/interface/palette_editor/quick_setup_panel.cpp
+ src/interface/palette_editor/palette_grid_widget.cpp
+ src/interface/palette_editor/palette_editor_dialog.cpp
src/interface/widgets/cards/additional_info/color_identity_widget.cpp
src/interface/widgets/cards/additional_info/mana_cost_widget.cpp
src/interface/widgets/cards/additional_info/mana_symbol_widget.cpp
@@ -229,6 +238,14 @@ set(cockatrice_SOURCES
src/interface/widgets/server/user/user_info_connection.cpp
src/interface/widgets/server/user/user_list_manager.cpp
src/interface/widgets/server/user/user_list_widget.cpp
+ src/interface/widgets/settings_page/appearance_settings_page.cpp
+ src/interface/widgets/settings_page/deck_editor_settings_page.cpp
+ src/interface/widgets/settings_page/general_settings_page.cpp
+ src/interface/widgets/settings_page/messages_settings_page.cpp
+ src/interface/widgets/settings_page/shortcut_settings_page.cpp
+ src/interface/widgets/settings_page/sound_settings_page.cpp
+ src/interface/widgets/settings_page/storage_settings_page.cpp
+ src/interface/widgets/settings_page/user_interface_settings_page.cpp
src/interface/widgets/utility/custom_line_edit.cpp
src/interface/widgets/utility/get_text_with_max.cpp
src/interface/widgets/utility/sequence_edit.cpp
@@ -327,6 +344,8 @@ set(cockatrice_SOURCES
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_bracket_navigation_widget.h
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_budget_navigation_widget.cpp
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_budget_navigation_widget.h
+ src/interface/widgets/utility/compact_push_button.cpp
+ src/interface/widgets/utility/compact_push_button.h
)
add_subdirectory(sounds)
diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc
index 37fb145f0..9c34929b7 100644
--- a/cockatrice/cockatrice.qrc
+++ b/cockatrice/cockatrice.qrc
@@ -55,6 +55,7 @@
resources/icons/view.svg
resources/icons/mana/B.svg
+ resources/icons/mana/C.svg
resources/icons/mana/G.svg
resources/icons/mana/R.svg
resources/icons/mana/U.svg
@@ -69,6 +70,7 @@
resources/config/interface.svg
resources/config/messages.svg
resources/config/deckeditor.svg
+ resources/config/storage.svg
resources/config/shorcuts.svg
resources/config/sound.svg
resources/config/debug.ini
diff --git a/cockatrice/resources/config/qtlogging.ini b/cockatrice/resources/config/qtlogging.ini
index 20aa206ce..7ac0d9ca4 100644
--- a/cockatrice/resources/config/qtlogging.ini
+++ b/cockatrice/resources/config/qtlogging.ini
@@ -28,6 +28,8 @@
#dlg_tip_of_the_day = true
#dlg_update = true
+#general_settings_page = true
+
#settings_cache = true
#servers_settings = true
#shortcuts_settings = true
diff --git a/cockatrice/resources/config/storage.svg b/cockatrice/resources/config/storage.svg
new file mode 100644
index 000000000..de85228dc
--- /dev/null
+++ b/cockatrice/resources/config/storage.svg
@@ -0,0 +1,799 @@
+
+
+
+
diff --git a/cockatrice/resources/icons/mana/C.svg b/cockatrice/resources/icons/mana/C.svg
new file mode 100644
index 000000000..eb09fb872
--- /dev/null
+++ b/cockatrice/resources/icons/mana/C.svg
@@ -0,0 +1,72 @@
+
+
+
+
diff --git a/cockatrice/src/client/network/connection_controller/remote_connection_controller.cpp b/cockatrice/src/client/network/connection_controller/remote_connection_controller.cpp
index f517acdc4..75cedcafc 100644
--- a/cockatrice/src/client/network/connection_controller/remote_connection_controller.cpp
+++ b/cockatrice/src/client/network/connection_controller/remote_connection_controller.cpp
@@ -140,13 +140,15 @@ void ConnectionController::onConnectionClosedEvent(const Event_ConnectionClosed
}
case Event_ConnectionClosed::BANNED: {
reasonStr = tr("Banned by moderator");
- if (event.has_end_time())
+ if (event.has_end_time()) {
reasonStr.append(
"\n" + tr("Expected end time: %1").arg(QDateTime::fromSecsSinceEpoch(event.end_time()).toString()));
- else
+ } else {
reasonStr.append("\n" + tr("This ban lasts indefinitely."));
- if (event.has_reason_str())
+ }
+ if (event.has_reason_str()) {
reasonStr.append("\n\n" + QString::fromStdString(event.reason_str()));
+ }
break;
}
case Event_ConnectionClosed::SERVER_SHUTDOWN: {
@@ -240,8 +242,9 @@ void ConnectionController::onLoginError(int r,
QString bannedStr =
endTime ? tr("You are banned until %1.").arg(QDateTime::fromSecsSinceEpoch(endTime).toString())
: tr("You are banned indefinitely.");
- if (!reasonStr.isEmpty())
+ if (!reasonStr.isEmpty()) {
bannedStr.append("\n\n" + reasonStr);
+ }
QMessageBox::critical(dialogParent, tr("Error"), bannedStr);
break;
}
@@ -354,8 +357,9 @@ void ConnectionController::onRegisterError(int r, QString reasonStr, quint32 end
QString bannedStr =
endTime ? tr("You are banned until %1.").arg(QDateTime::fromSecsSinceEpoch(endTime).toString())
: tr("You are banned indefinitely.");
- if (!reasonStr.isEmpty())
+ if (!reasonStr.isEmpty()) {
bannedStr.append("\n\n" + reasonStr);
+ }
QMessageBox::critical(dialogParent, tr("Error"), bannedStr);
break;
}
@@ -545,8 +549,9 @@ QString ConnectionController::extractInvalidUsernameMessage(QString &in)
out +=
"
" + tr("can %1 contain numeric characters").arg((rules.at(4).toInt() > 0) ? "" : tr("NOT")) + "";
- if (rules.at(6).size() > 0)
+ if (rules.at(6).size() > 0) {
out += "" + tr("can contain the following punctuation: %1").arg(rules.at(6).toHtmlEscaped()) + "";
+ }
out += "" +
tr("first character can %1 be a punctuation mark").arg((rules.at(5).toInt() > 0) ? "" : tr("NOT")) +
@@ -566,10 +571,11 @@ QString ConnectionController::extractInvalidUsernameMessage(QString &in)
}
}
- if (rules.at(8).size() > 0)
+ if (rules.at(8).size() > 0) {
out += "" +
tr("can not match any of the following expressions: %1").arg(rules.at(8).toHtmlEscaped()) +
"";
+ }
}
out += "";
diff --git a/cockatrice/src/client/network/interfaces/deck_stats_interface.h b/cockatrice/src/client/network/interfaces/deck_stats_interface.h
index 7dc841027..2ec67a5a7 100644
--- a/cockatrice/src/client/network/interfaces/deck_stats_interface.h
+++ b/cockatrice/src/client/network/interfaces/deck_stats_interface.h
@@ -1,8 +1,8 @@
/**
* @file deck_stats_interface.h
* @ingroup ApiInterfaces
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef DECKSTATS_INTERFACE_H
#define DECKSTATS_INTERFACE_H
diff --git a/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp b/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp
index af377d176..cd39ea251 100644
--- a/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp
+++ b/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp
@@ -99,14 +99,16 @@ void TappedOutInterface::copyDeckSplitMainAndSide(const DeckList &source, DeckLi
{
auto copyMainOrSide = [this, &mainboard, &sideboard](const auto node, const auto card) {
CardInfoPtr dbCard = cardDatabase.query()->getCardInfo(card->getName());
- if (!dbCard || dbCard->getIsToken())
+ if (!dbCard || dbCard->getIsToken()) {
return;
+ }
DecklistCardNode *addedCard;
- if (node->getName() == DECK_ZONE_SIDE)
+ if (node->getName() == DECK_ZONE_SIDE) {
addedCard = sideboard.addCard(card->getName(), node->getName(), -1);
- else
+ } else {
addedCard = mainboard.addCard(card->getName(), node->getName(), -1);
+ }
addedCard->setNumber(card->getNumber());
};
diff --git a/cockatrice/src/client/network/interfaces/tapped_out_interface.h b/cockatrice/src/client/network/interfaces/tapped_out_interface.h
index 0ea9c8358..f1cc1cbeb 100644
--- a/cockatrice/src/client/network/interfaces/tapped_out_interface.h
+++ b/cockatrice/src/client/network/interfaces/tapped_out_interface.h
@@ -1,8 +1,8 @@
/**
* @file tapped_out_interface.h
* @ingroup ApiInterfaces
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef TAPPEDOUT_INTERFACE_H
#define TAPPEDOUT_INTERFACE_H
diff --git a/cockatrice/src/client/network/parsers/deck_link_to_api_transformer.h b/cockatrice/src/client/network/parsers/deck_link_to_api_transformer.h
index 1e2372fd1..bbdd70c97 100644
--- a/cockatrice/src/client/network/parsers/deck_link_to_api_transformer.h
+++ b/cockatrice/src/client/network/parsers/deck_link_to_api_transformer.h
@@ -1,8 +1,8 @@
/**
* @file deck_link_to_api_transformer.h
* @ingroup ApiInterfaces
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef DECK_LINK_TO_API_TRANSFORMER_H
#define DECK_LINK_TO_API_TRANSFORMER_H
diff --git a/cockatrice/src/client/network/parsers/interface_json_deck_parser.h b/cockatrice/src/client/network/parsers/interface_json_deck_parser.h
index 1818aa35c..87fde4d54 100644
--- a/cockatrice/src/client/network/parsers/interface_json_deck_parser.h
+++ b/cockatrice/src/client/network/parsers/interface_json_deck_parser.h
@@ -1,8 +1,8 @@
/**
* @file interface_json_deck_parser.h
* @ingroup ApiInterfaces
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef INTERFACE_JSON_DECK_PARSER_H
#define INTERFACE_JSON_DECK_PARSER_H
diff --git a/cockatrice/src/client/network/update/card_spoiler/spoiler_background_updater.h b/cockatrice/src/client/network/update/card_spoiler/spoiler_background_updater.h
index a2feb5ccf..03d4897a2 100644
--- a/cockatrice/src/client/network/update/card_spoiler/spoiler_background_updater.h
+++ b/cockatrice/src/client/network/update/card_spoiler/spoiler_background_updater.h
@@ -1,8 +1,8 @@
/**
* @file spoiler_background_updater.h
* @ingroup Client
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef COCKATRICE_SPOILER_DOWNLOADER_H
#define COCKATRICE_SPOILER_DOWNLOADER_H
diff --git a/cockatrice/src/client/network/update/client/client_update_checker.h b/cockatrice/src/client/network/update/client/client_update_checker.h
index 4e6f279c3..1a89de533 100644
--- a/cockatrice/src/client/network/update/client/client_update_checker.h
+++ b/cockatrice/src/client/network/update/client/client_update_checker.h
@@ -1,8 +1,8 @@
/**
* @file client_update_checker.h
* @ingroup ClientUpdate
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef CLIENT_UPDATE_CHECKER_H
#define CLIENT_UPDATE_CHECKER_H
diff --git a/cockatrice/src/client/network/update/client/release_channel.cpp b/cockatrice/src/client/network/update/client/release_channel.cpp
index 9edfe7caf..260167bc8 100644
--- a/cockatrice/src/client/network/update/client/release_channel.cpp
+++ b/cockatrice/src/client/network/update/client/release_channel.cpp
@@ -129,8 +129,9 @@ void StableReleaseChannel::releaseListFinished()
return;
}
- if (!lastRelease)
+ if (!lastRelease) {
lastRelease = new Release;
+ }
lastRelease->setName(resultMap["name"].toString());
lastRelease->setDescriptionUrl(resultMap["html_url"].toString());
@@ -246,8 +247,9 @@ void BetaReleaseChannel::releaseListFinished()
return;
}
- if (lastRelease == nullptr)
+ if (lastRelease == nullptr) {
lastRelease = new Release;
+ }
lastRelease->setCommitHash(resultMap["target_commitish"].toString());
lastRelease->setPublishDate(resultMap["published_at"].toDate());
diff --git a/cockatrice/src/client/network/update/client/release_channel.h b/cockatrice/src/client/network/update/client/release_channel.h
index 93e6b985d..c56d0cfce 100644
--- a/cockatrice/src/client/network/update/client/release_channel.h
+++ b/cockatrice/src/client/network/update/client/release_channel.h
@@ -1,8 +1,8 @@
/**
* @file release_channel.h
* @ingroup ClientUpdate
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef RELEASECHANNEL_H
#define RELEASECHANNEL_H
diff --git a/cockatrice/src/client/network/update/client/update_downloader.cpp b/cockatrice/src/client/network/update/client/update_downloader.cpp
index c0f3e945c..a71bcf8f8 100644
--- a/cockatrice/src/client/network/update/client/update_downloader.cpp
+++ b/cockatrice/src/client/network/update/client/update_downloader.cpp
@@ -10,8 +10,9 @@ UpdateDownloader::UpdateDownloader(QObject *parent) : QObject(parent), response(
void UpdateDownloader::beginDownload(QUrl downloadUrl)
{
// Save the original URL because we need it for the filename
- if (originalUrl.isEmpty())
+ if (originalUrl.isEmpty()) {
originalUrl = downloadUrl;
+ }
response = netMan->get(QNetworkRequest(downloadUrl));
connect(response, &QNetworkReply::finished, this, &UpdateDownloader::fileFinished);
@@ -21,8 +22,9 @@ void UpdateDownloader::beginDownload(QUrl downloadUrl)
void UpdateDownloader::downloadError(QNetworkReply::NetworkError)
{
- if (response == nullptr)
+ if (response == nullptr) {
return;
+ }
emit error(response->errorString().toUtf8());
}
diff --git a/cockatrice/src/client/network/update/client/update_downloader.h b/cockatrice/src/client/network/update/client/update_downloader.h
index d70759038..9a0caccbc 100644
--- a/cockatrice/src/client/network/update/client/update_downloader.h
+++ b/cockatrice/src/client/network/update/client/update_downloader.h
@@ -1,8 +1,8 @@
/**
* @file update_downloader.h
* @ingroup ClientUpdate
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef COCKATRICE_UPDATEDOWNLOADER_H
#define COCKATRICE_UPDATEDOWNLOADER_H
diff --git a/cockatrice/src/client/settings/cache_settings.cpp b/cockatrice/src/client/settings/cache_settings.cpp
index 9a46c6426..64416e5ee 100644
--- a/cockatrice/src/client/settings/cache_settings.cpp
+++ b/cockatrice/src/client/settings/cache_settings.cpp
@@ -1,5 +1,7 @@
#include "cache_settings.h"
+#include "../../interface/card_picture_loader/card_picture_loader_cache_method.h"
+#include "../../interface/card_picture_loader/card_picture_loader_local_schemes.h"
#include "../network/update/client/release_channel.h"
#include "card_counter_settings.h"
#include "version_string.h"
@@ -24,10 +26,11 @@ SettingsCache &SettingsCache::instance()
QString SettingsCache::getDataPath()
{
- if (isPortableBuild)
+ if (isPortableBuild) {
return qApp->applicationDirPath() + "/data";
- else
+ } else {
return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
+ }
}
QString SettingsCache::getSettingsPath()
@@ -37,10 +40,11 @@ QString SettingsCache::getSettingsPath()
QString SettingsCache::getCachePath() const
{
- if (isPortableBuild)
+ if (isPortableBuild) {
return qApp->applicationDirPath() + "/cache";
- else
+ } else {
return QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
+ }
}
QString SettingsCache::getNetworkCachePath() const
@@ -50,14 +54,17 @@ QString SettingsCache::getNetworkCachePath() const
void SettingsCache::translateLegacySettings()
{
- if (isPortableBuild)
+ if (isPortableBuild) {
return;
+ }
// Layouts
QFile layoutFile(getSettingsPath() + "layouts/deckLayout.ini");
- if (layoutFile.exists())
- if (layoutFile.copy(getSettingsPath() + "layouts.ini"))
+ if (layoutFile.exists()) {
+ if (layoutFile.copy(getSettingsPath() + "layouts.ini")) {
layoutFile.remove();
+ }
+ }
QStringList usedKeys;
QSettings legacySetting;
@@ -116,10 +123,11 @@ void SettingsCache::translateLegacySettings()
gameFilters().setHideIgnoredUserGames(legacySetting.value("hide_ignored_user_games").toBool());
gameFilters().setMinPlayers(legacySetting.value("min_players").toInt());
- if (legacySetting.value("max_players").toInt() > 1)
+ if (legacySetting.value("max_players").toInt() > 1) {
gameFilters().setMaxPlayers(legacySetting.value("max_players").toInt());
- else
+ } else {
gameFilters().setMaxPlayers(99); // This prevents a bug where no games will show if max was not set before
+ }
QStringList allFilters = legacySetting.allKeys();
for (int i = 0; i < allFilters.size(); ++i) {
@@ -135,8 +143,9 @@ void SettingsCache::translateLegacySettings()
QStringList allLegacyKeys = legacySetting.allKeys();
for (int i = 0; i < allLegacyKeys.size(); ++i) {
- if (usedKeys.contains(allLegacyKeys.at(i)))
+ if (usedKeys.contains(allLegacyKeys.at(i))) {
continue;
+ }
settings->setValue(allLegacyKeys.at(i), legacySetting.value(allLegacyKeys.at(i)));
}
}
@@ -147,8 +156,9 @@ QString SettingsCache::getSafeConfigPath(QString configEntry, QString defaultPat
// if the config settings is empty or refers to a not-existing folder,
// ensure that the defaut path exists and return it
if (tmp.isEmpty() || !QDir(tmp).exists()) {
- if (!QDir().mkpath(defaultPath))
+ if (!QDir().mkpath(defaultPath)) {
qCInfo(SettingsCacheLog) << "[SettingsCache] Could not create folder:" << defaultPath;
+ }
tmp = defaultPath;
}
return tmp;
@@ -159,8 +169,9 @@ QString SettingsCache::getSafeConfigFilePath(QString configEntry, QString defaul
QString tmp = settings->value(configEntry).toString();
// if the config settings is empty or refers to a not-existing file,
// return the default Path
- if (!QFile::exists(tmp) || tmp.isEmpty())
+ if (!QFile::exists(tmp) || tmp.isEmpty()) {
tmp = std::move(defaultPath);
+ }
return tmp;
}
@@ -168,8 +179,9 @@ SettingsCache::SettingsCache()
{
// first, figure out if we are running in portable mode
isPortableBuild = QFile::exists(qApp->applicationDirPath() + "/portable.dat");
- if (isPortableBuild)
+ if (isPortableBuild) {
qCInfo(SettingsCacheLog) << "Portable mode enabled";
+ }
// define a dummy context that will be used where needed
QString dummy = QT_TRANSLATE_NOOP("i18n", "English");
@@ -189,8 +201,9 @@ SettingsCache::SettingsCache()
cardCounterSettings = new CardCounterSettings(settingsPath, this);
- if (!QFile(settingsPath + "global.ini").exists())
+ if (!QFile(settingsPath + "global.ini").exists()) {
translateLegacySettings();
+ }
// updates - don't reorder them or their index in the settings won't match
// append channels one by one, or msvc will add them in the wrong order.
@@ -257,14 +270,26 @@ SettingsCache::SettingsCache()
settings->setValue("personal/pixmapCacheSize", pixmapCacheSize);
settings->setValue("personal/picturedownloadhq", false);
settings->setValue("revert/pixmapCacheSize", true);
- } else
+ } else {
pixmapCacheSize = settings->value("personal/pixmapCacheSize", PIXMAPCACHE_SIZE_DEFAULT).toInt();
+ }
// sanity check
- if (pixmapCacheSize < PIXMAPCACHE_SIZE_MIN || pixmapCacheSize > PIXMAPCACHE_SIZE_MAX)
+ if (pixmapCacheSize < PIXMAPCACHE_SIZE_MIN || pixmapCacheSize > PIXMAPCACHE_SIZE_MAX) {
pixmapCacheSize = PIXMAPCACHE_SIZE_DEFAULT;
+ }
networkCacheSize = settings->value("personal/networkCacheSize", NETWORK_CACHE_SIZE_DEFAULT).toInt();
redirectCacheTtl = settings->value("personal/redirectCacheTtl", NETWORK_REDIRECT_CACHE_TTL_DEFAULT).toInt();
+ cardPictureLoaderCacheMethod =
+ settings
+ ->value("personal/cardPictureLoaderCacheMethod",
+ static_cast(CardPictureLoaderCacheMethod::CacheMethod::NETWORK_CACHE))
+ .toInt();
+ localCardImageStorageNamingScheme =
+ settings
+ ->value("personal/localCardImageStorageNamingScheme",
+ static_cast(CardPictureLoaderLocalSchemes::NamingScheme::Set_Folder_Name_Set_Collector))
+ .toInt();
picDownload = settings->value("personal/picturedownload", true).toBool();
showStatusBar = settings->value("personal/showStatusBar", false).toBool();
@@ -770,8 +795,9 @@ void SettingsCache::setPrintingSelectorCardSize(int _printingSelectorCardSize)
void SettingsCache::setIncludeRebalancedCards(bool _includeRebalancedCards)
{
- if (includeRebalancedCards == _includeRebalancedCards)
+ if (includeRebalancedCards == _includeRebalancedCards) {
return;
+ }
includeRebalancedCards = _includeRebalancedCards;
settings->setValue("cards/includerebalancedcards", includeRebalancedCards);
@@ -1098,6 +1124,13 @@ void SettingsCache::setPixmapCacheSize(const int _pixmapCacheSize)
emit pixmapCacheSizeChanged(pixmapCacheSize);
}
+void SettingsCache::setCardImageCacheMethod(const CardPictureLoaderCacheMethod::CacheMethod _cardImageCachingMethod)
+{
+ cardPictureLoaderCacheMethod = static_cast(_cardImageCachingMethod);
+ settings->setValue("personal/cardPictureLoaderCacheMethod", cardPictureLoaderCacheMethod);
+ emit cardPictureLoaderCacheMethodChanged(cardPictureLoaderCacheMethod);
+}
+
void SettingsCache::setNetworkCacheSizeInMB(const int _networkCacheSize)
{
networkCacheSize = _networkCacheSize;
@@ -1112,6 +1145,14 @@ void SettingsCache::setNetworkRedirectCacheTtl(const int _redirectCacheTtl)
emit redirectCacheTtlChanged(redirectCacheTtl);
}
+void SettingsCache::setLocalCardImageStorageNamingScheme(
+ const CardPictureLoaderLocalSchemes::NamingScheme _localCardImageStorageNamingScheme)
+{
+ localCardImageStorageNamingScheme = static_cast(_localCardImageStorageNamingScheme);
+ settings->setValue("personal/localCardImageStorageNamingScheme", localCardImageStorageNamingScheme);
+ emit localCardImageStorageNamingSchemeChanged(localCardImageStorageNamingScheme);
+}
+
void SettingsCache::setClientID(const QString &_clientID)
{
clientID = _clientID;
@@ -1310,8 +1351,9 @@ void SettingsCache::setMaxFontSize(int _max)
void SettingsCache::setRoundCardCorners(bool _roundCardCorners)
{
- if (_roundCardCorners == roundCardCorners)
+ if (_roundCardCorners == roundCardCorners) {
return;
+ }
roundCardCorners = _roundCardCorners;
settings->setValue("cards/roundcardcorners", _roundCardCorners);
diff --git a/cockatrice/src/client/settings/cache_settings.h b/cockatrice/src/client/settings/cache_settings.h
index 0cd5ceb68..b1197e267 100644
--- a/cockatrice/src/client/settings/cache_settings.h
+++ b/cockatrice/src/client/settings/cache_settings.h
@@ -1,12 +1,14 @@
/**
* @file cache_settings.h
* @ingroup Settings
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef SETTINGSCACHE_H
#define SETTINGSCACHE_H
+#include "../../interface/card_picture_loader/card_picture_loader_cache_method.h"
+#include "../../interface/card_picture_loader/card_picture_loader_local_schemes.h"
#include "shortcuts_settings.h"
#include
@@ -184,6 +186,8 @@ signals:
void pixmapCacheSizeChanged(int newSizeInMBs);
void networkCacheSizeChanged(int newSizeInMBs);
void redirectCacheTtlChanged(int newTtl);
+ void cardPictureLoaderCacheMethodChanged(int cardPictureLoaderCacheMethod);
+ void localCardImageStorageNamingSchemeChanged(int localCardImageStorageNamingScheme);
void masterVolumeChanged(int value);
void chatMentionCompleterChanged();
void downloadSpoilerTimeIndexChanged();
@@ -303,6 +307,8 @@ private:
int pixmapCacheSize;
int networkCacheSize;
int redirectCacheTtl;
+ int cardPictureLoaderCacheMethod;
+ int localCardImageStorageNamingScheme;
bool scaleCards;
int verticalCardOverlapPercent;
bool showMessagePopups;
@@ -786,6 +792,10 @@ public:
{
return pixmapCacheSize;
}
+ [[nodiscard]] CardPictureLoaderCacheMethod::CacheMethod getCardPictureLoaderCacheMethod() const
+ {
+ return static_cast(cardPictureLoaderCacheMethod);
+ }
[[nodiscard]] int getNetworkCacheSizeInMB() const
{
return networkCacheSize;
@@ -794,6 +804,10 @@ public:
{
return redirectCacheTtl;
}
+ [[nodiscard]] CardPictureLoaderLocalSchemes::NamingScheme getLocalCardImageStorageNamingScheme() const
+ {
+ return static_cast(localCardImageStorageNamingScheme);
+ }
[[nodiscard]] bool getScaleCards() const
{
return scaleCards;
@@ -1098,8 +1112,11 @@ public slots:
void setIgnoreUnregisteredUsers(QT_STATE_CHANGED_T _ignoreUnregisteredUsers);
void setIgnoreUnregisteredUserMessages(QT_STATE_CHANGED_T _ignoreUnregisteredUserMessages);
void setPixmapCacheSize(const int _pixmapCacheSize);
+ void setCardImageCacheMethod(CardPictureLoaderCacheMethod::CacheMethod _cardImageCachingMethod);
void setNetworkCacheSizeInMB(const int _networkCacheSize);
void setNetworkRedirectCacheTtl(const int _redirectCacheTtl);
+ void setLocalCardImageStorageNamingScheme(
+ const CardPictureLoaderLocalSchemes::NamingScheme _localCardImageStorageNamingScheme);
void setCardScaling(const QT_STATE_CHANGED_T _scaleCards);
void setStackCardOverlapPercent(const int _verticalCardOverlapPercent);
void setShowMessagePopups(const QT_STATE_CHANGED_T _showMessagePopups);
diff --git a/cockatrice/src/client/settings/card_counter_settings.cpp b/cockatrice/src/client/settings/card_counter_settings.cpp
index 399365c99..662ae0c7d 100644
--- a/cockatrice/src/client/settings/card_counter_settings.cpp
+++ b/cockatrice/src/client/settings/card_counter_settings.cpp
@@ -15,8 +15,9 @@ void CardCounterSettings::setColor(int counterId, const QColor &color)
QString key = QString("cards/counters/%1/color").arg(counterId);
- if (settings.value(key).value() == color)
+ if (settings.value(key).value() == color) {
return;
+ }
settings.setValue(key, color);
emit colorChanged(counterId, color);
diff --git a/cockatrice/src/client/settings/card_counter_settings.h b/cockatrice/src/client/settings/card_counter_settings.h
index b1d467d67..2ac658177 100644
--- a/cockatrice/src/client/settings/card_counter_settings.h
+++ b/cockatrice/src/client/settings/card_counter_settings.h
@@ -1,8 +1,8 @@
/**
* @file card_counter_settings.h
* @ingroup GameSettings
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef CARD_COUNTER_SETTINGS_H
#define CARD_COUNTER_SETTINGS_H
diff --git a/cockatrice/src/client/settings/shortcut_treeview.h b/cockatrice/src/client/settings/shortcut_treeview.h
index 8d74a6f1e..afaf7e7ed 100644
--- a/cockatrice/src/client/settings/shortcut_treeview.h
+++ b/cockatrice/src/client/settings/shortcut_treeview.h
@@ -1,8 +1,8 @@
/**
* @file shortcut_treeview.h
* @ingroup CoreSettings
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef SHORTCUT_TREEVIEW_H
#define SHORTCUT_TREEVIEW_H
diff --git a/cockatrice/src/client/settings/shortcuts_settings.cpp b/cockatrice/src/client/settings/shortcuts_settings.cpp
index 53c6f6a23..2ff65ab6f 100644
--- a/cockatrice/src/client/settings/shortcuts_settings.cpp
+++ b/cockatrice/src/client/settings/shortcuts_settings.cpp
@@ -64,8 +64,13 @@ ShortcutsSettings::ShortcutsSettings(const QString &settingsPath, QObject *paren
}
}
-/// PR 5079 changes Textbox/unfocusTextBox to Player/unfocusTextBox and tab_game/aFocusChat to Player/aFocusChat.
-/// A migration is necessary to let players keep their already configured shortcuts.
+/**
+ * @brief Migrates legacy shortcut key names to current naming scheme.
+ *
+ * PR 5079 changed Textbox/unfocusTextBox to Player/unfocusTextBox and
+ * tab_game/aFocusChat to Player/aFocusChat. This migration allows players
+ * to keep their already configured shortcuts.
+ */
void ShortcutsSettings::migrateShortcuts()
{
if (QFile(settingsFilePath).exists()) {
@@ -236,9 +241,7 @@ bool ShortcutsSettings::isValid(const QString &name, const QString &sequences) c
return findOverlaps(name, sequences).isEmpty();
}
-/**
- * Checks if the shortcut is a shortcut that is active in all windows
- */
+/** @brief Checks if the shortcut is a shortcut that is active in all windows. */
static bool isAlwaysActiveShortcut(const QString &shortcutName)
{
return shortcutName.startsWith("MainWindow") || shortcutName.startsWith("Tabs");
diff --git a/cockatrice/src/client/settings/shortcuts_settings.h b/cockatrice/src/client/settings/shortcuts_settings.h
index d9ea494dc..45e2c4fca 100644
--- a/cockatrice/src/client/settings/shortcuts_settings.h
+++ b/cockatrice/src/client/settings/shortcuts_settings.h
@@ -1,8 +1,8 @@
/**
* @file shortcuts_settings.h
* @ingroup CoreSettings
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef SHORTCUTSSETTINGS_H
#define SHORTCUTSSETTINGS_H
@@ -537,6 +537,9 @@ private:
{"Player/aSetAnnotation", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Annotation..."),
parseSequenceString("Alt+N"),
ShortcutGroup::Playing_Area)},
+ {"Player/aReduceLifeByPower", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Reduce Life by Power"),
+ parseSequenceString("Ctrl+Shift+L"),
+ ShortcutGroup::Playing_Area)},
{"Player/aSelectAll", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Select All Cards in Zone"),
parseSequenceString("Ctrl+A"),
ShortcutGroup::Playing_Area)},
diff --git a/cockatrice/src/client/sound_engine.cpp b/cockatrice/src/client/sound_engine.cpp
index b4991813c..7a4a4f7d2 100644
--- a/cockatrice/src/client/sound_engine.cpp
+++ b/cockatrice/src/client/sound_engine.cpp
@@ -95,8 +95,9 @@ QStringMap &SoundEngine::getAvailableThemes()
dir.setPath(SettingsCache::instance().getDataPath() + "/sounds");
for (const QString &themeName : dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name)) {
- if (!availableThemes.contains(themeName))
+ if (!availableThemes.contains(themeName)) {
availableThemes.insert(themeName, dir.absoluteFilePath(themeName));
+ }
}
// load themes from cockatrice system dir
@@ -111,8 +112,9 @@ QStringMap &SoundEngine::getAvailableThemes()
);
for (const QString &themeName : dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name)) {
- if (!availableThemes.contains(themeName))
+ if (!availableThemes.contains(themeName)) {
availableThemes.insert(themeName, dir.absoluteFilePath(themeName));
+ }
}
return availableThemes;
diff --git a/cockatrice/src/client/sound_engine.h b/cockatrice/src/client/sound_engine.h
index f45cccf7d..0c201523a 100644
--- a/cockatrice/src/client/sound_engine.h
+++ b/cockatrice/src/client/sound_engine.h
@@ -1,8 +1,8 @@
/**
* @file sound_engine.h
* @ingroup Core
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef SOUNDENGINE_H
#define SOUNDENGINE_H
diff --git a/cockatrice/src/filters/deck_filter_string.cpp b/cockatrice/src/filters/deck_filter_string.cpp
index 6b671831d..dd873cfa5 100644
--- a/cockatrice/src/filters/deck_filter_string.cpp
+++ b/cockatrice/src/filters/deck_filter_string.cpp
@@ -88,20 +88,27 @@ static void setupParserRules()
const auto arg = std::any_cast(sv[1]);
const auto op = std::any_cast(sv[0]);
- if (op == ">")
+ if (op == ">") {
return [=](const int s) { return s > arg; };
- if (op == ">=")
+ }
+ if (op == ">=") {
return [=](const int s) { return s >= arg; };
- if (op == "<")
+ }
+ if (op == "<") {
return [=](const int s) { return s < arg; };
- if (op == "<=")
+ }
+ if (op == "<=") {
return [=](const int s) { return s <= arg; };
- if (op == "=")
+ }
+ if (op == "=") {
return [=](const int s) { return s == arg; };
- if (op == ":")
+ }
+ if (op == ":") {
return [=](const int s) { return s == arg; };
- if (op == "!=")
+ }
+ if (op == "!=") {
return [=](const int s) { return s != arg; };
+ }
return [](int) { return false; };
};
diff --git a/cockatrice/src/filters/deck_filter_string.h b/cockatrice/src/filters/deck_filter_string.h
index 1b43d770d..916b629ee 100644
--- a/cockatrice/src/filters/deck_filter_string.h
+++ b/cockatrice/src/filters/deck_filter_string.h
@@ -1,8 +1,8 @@
/**
* @file deck_filter_string.h
* @ingroup DeckStorageWidgets
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef DECK_FILTER_STRING_H
#define DECK_FILTER_STRING_H
diff --git a/cockatrice/src/filters/filter_builder.cpp b/cockatrice/src/filters/filter_builder.cpp
index 7178ce95a..785f753e7 100644
--- a/cockatrice/src/filters/filter_builder.cpp
+++ b/cockatrice/src/filters/filter_builder.cpp
@@ -11,13 +11,15 @@ FilterBuilder::FilterBuilder(QWidget *parent) : QWidget(parent)
{
filterCombo = new QComboBox;
filterCombo->setObjectName("filterCombo");
- for (int i = 0; i < CardFilter::AttrEnd; i++)
+ for (int i = 0; i < CardFilter::AttrEnd; i++) {
filterCombo->addItem(CardFilter::attrName(static_cast(i)), QVariant(i));
+ }
typeCombo = new QComboBox;
typeCombo->setObjectName("typeCombo");
- for (int i = 0; i < CardFilter::TypeEnd; i++)
+ for (int i = 0; i < CardFilter::TypeEnd; i++) {
typeCombo->addItem(CardFilter::typeName(static_cast(i)), QVariant(i));
+ }
QPushButton *ok = new QPushButton(QPixmap("theme:icons/increment"), QString());
ok->setObjectName("ok");
@@ -53,8 +55,9 @@ FilterBuilder::~FilterBuilder()
void FilterBuilder::destroyFilter()
{
- if (fltr)
+ if (fltr) {
delete fltr;
+ }
}
static int comboCurrentIntData(const QComboBox *combo)
@@ -67,8 +70,9 @@ void FilterBuilder::emit_add()
QString txt;
txt = edit->text();
- if (txt.length() < 1)
+ if (txt.length() < 1) {
return;
+ }
destroyFilter();
fltr = new CardFilter(txt, static_cast(comboCurrentIntData(typeCombo)),
diff --git a/cockatrice/src/filters/filter_builder.h b/cockatrice/src/filters/filter_builder.h
index 74872e3cd..98fe3fd02 100644
--- a/cockatrice/src/filters/filter_builder.h
+++ b/cockatrice/src/filters/filter_builder.h
@@ -1,8 +1,8 @@
/**
* @file filter_builder.h
* @ingroup CardDatabaseModelFilters
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef FILTERBUILDER_H
#define FILTERBUILDER_H
diff --git a/cockatrice/src/filters/filter_tree_model.cpp b/cockatrice/src/filters/filter_tree_model.cpp
index f0a02ec79..33b54530e 100644
--- a/cockatrice/src/filters/filter_tree_model.cpp
+++ b/cockatrice/src/filters/filter_tree_model.cpp
@@ -23,8 +23,9 @@ void FilterTreeModel::proxyBeginInsertRow(const FilterTreeNode *node, int i)
int idx;
idx = node->index();
- if (idx >= 0)
+ if (idx >= 0) {
beginInsertRows(createIndex(idx, 0, (void *)node), i, i);
+ }
}
void FilterTreeModel::proxyEndInsertRow(const FilterTreeNode *node, int)
@@ -32,8 +33,9 @@ void FilterTreeModel::proxyEndInsertRow(const FilterTreeNode *node, int)
int idx;
idx = node->index();
- if (idx >= 0)
+ if (idx >= 0) {
endInsertRows();
+ }
}
void FilterTreeModel::proxyBeginRemoveRow(const FilterTreeNode *node, int i)
@@ -41,8 +43,9 @@ void FilterTreeModel::proxyBeginRemoveRow(const FilterTreeNode *node, int i)
int idx;
idx = node->index();
- if (idx >= 0)
+ if (idx >= 0) {
beginRemoveRows(createIndex(idx, 0, (void *)node), i, i);
+ }
}
void FilterTreeModel::proxyEndRemoveRow(const FilterTreeNode *node, int)
@@ -50,8 +53,9 @@ void FilterTreeModel::proxyEndRemoveRow(const FilterTreeNode *node, int)
int idx;
idx = node->index();
- if (idx >= 0)
+ if (idx >= 0) {
endRemoveRows();
+ }
}
FilterTreeNode *FilterTreeModel::indexToNode(const QModelIndex &idx) const
@@ -59,12 +63,14 @@ FilterTreeNode *FilterTreeModel::indexToNode(const QModelIndex &idx) const
void *ip;
FilterTreeNode *node;
- if (!idx.isValid())
+ if (!idx.isValid()) {
return fTree;
+ }
ip = idx.internalPointer();
- if (ip == NULL)
+ if (ip == NULL) {
return fTree;
+ }
node = static_cast(ip);
return node;
@@ -145,14 +151,16 @@ int FilterTreeModel::rowCount(const QModelIndex &parent) const
const FilterTreeNode *node;
int result;
- if (parent.column() > 0)
+ if (parent.column() > 0) {
return 0;
+ }
node = indexToNode(parent);
- if (node)
+ if (node) {
result = node->childCount();
- else
+ } else {
result = 0;
+ }
return result;
}
@@ -166,14 +174,17 @@ QVariant FilterTreeModel::data(const QModelIndex &index, int role) const
{
const FilterTreeNode *node;
- if (!index.isValid())
+ if (!index.isValid()) {
return QVariant();
- if (index.column() >= columnCount())
+ }
+ if (index.column() >= columnCount()) {
return QVariant();
+ }
node = indexToNode(index);
- if (node == NULL)
+ if (node == NULL) {
return QVariant();
+ }
switch (role) {
case Qt::FontRole:
@@ -190,10 +201,11 @@ QVariant FilterTreeModel::data(const QModelIndex &index, int role) const
case Qt::WhatsThisRole:
return node->text();
case Qt::CheckStateRole:
- if (node->isEnabled())
+ if (node->isEnabled()) {
return Qt::Checked;
- else
+ } else {
return Qt::Unchecked;
+ }
default:
return QVariant();
}
@@ -205,22 +217,27 @@ bool FilterTreeModel::setData(const QModelIndex &index, const QVariant &value, i
{
FilterTreeNode *node;
- if (!index.isValid())
+ if (!index.isValid()) {
return false;
- if (index.column() >= columnCount())
+ }
+ if (index.column() >= columnCount()) {
return false;
- if (role != Qt::CheckStateRole)
+ }
+ if (role != Qt::CheckStateRole) {
return false;
+ }
node = indexToNode(index);
- if (node == NULL || node == fTree)
+ if (node == NULL || node == fTree) {
return false;
+ }
Qt::CheckState state = static_cast(value.toInt());
- if (state == Qt::Checked)
+ if (state == Qt::Checked) {
node->enable();
- else
+ } else {
node->disable();
+ }
emit dataChanged(index, index);
return true;
@@ -231,16 +248,19 @@ Qt::ItemFlags FilterTreeModel::flags(const QModelIndex &index) const
const FilterTreeNode *node;
Qt::ItemFlags result;
- if (!index.isValid())
+ if (!index.isValid()) {
return Qt::NoItemFlags;
+ }
node = indexToNode(index);
- if (node == NULL)
+ if (node == NULL) {
return Qt::NoItemFlags;
+ }
result = Qt::ItemIsEnabled;
- if (node == fTree)
+ if (node == fTree) {
return result;
+ }
result |= Qt::ItemIsSelectable;
result |= Qt::ItemIsUserCheckable;
@@ -252,8 +272,9 @@ QModelIndex FilterTreeModel::nodeIndex(const FilterTreeNode *node, int row, int
{
FilterTreeNode *child;
- if (column > 0 || row >= node->childCount())
+ if (column > 0 || row >= node->childCount()) {
return QModelIndex();
+ }
child = node->nodeAt(row);
return createIndex(row, column, child);
@@ -263,12 +284,14 @@ QModelIndex FilterTreeModel::index(int row, int column, const QModelIndex &paren
{
const FilterTreeNode *node;
- if (!hasIndex(row, column, parent))
+ if (!hasIndex(row, column, parent)) {
return QModelIndex();
+ }
node = indexToNode(parent);
- if (node == NULL)
+ if (node == NULL) {
return QModelIndex();
+ }
return nodeIndex(node, row, column);
}
@@ -279,18 +302,21 @@ QModelIndex FilterTreeModel::parent(const QModelIndex &ind) const
FilterTreeNode *parent;
QModelIndex idx;
- if (!ind.isValid())
+ if (!ind.isValid()) {
return QModelIndex();
+ }
node = indexToNode(ind);
- if (node == NULL || node == fTree)
+ if (node == NULL || node == fTree) {
return QModelIndex();
+ }
parent = node->parent();
if (parent) {
int row = parent->index();
- if (row < 0)
+ if (row < 0) {
return QModelIndex();
+ }
idx = createIndex(row, 0, parent);
return idx;
}
@@ -304,18 +330,22 @@ bool FilterTreeModel::removeRows(int row, int count, const QModelIndex &parent)
int i, last;
last = row + count - 1;
- if (!parent.isValid() || count < 1 || row < 0)
+ if (!parent.isValid() || count < 1 || row < 0) {
return false;
+ }
node = indexToNode(parent);
- if (node == NULL || last >= node->childCount())
+ if (node == NULL || last >= node->childCount()) {
return false;
+ }
- for (i = 0; i < count; i++)
+ for (i = 0; i < count; i++) {
node->deleteAt(row);
+ }
- if (node != fTree && node->childCount() < 1)
+ if (node != fTree && node->childCount() < 1) {
return removeRow(parent.row(), parent.parent());
+ }
return true;
}
diff --git a/cockatrice/src/filters/filter_tree_model.h b/cockatrice/src/filters/filter_tree_model.h
index c6666a838..7452f7a61 100644
--- a/cockatrice/src/filters/filter_tree_model.h
+++ b/cockatrice/src/filters/filter_tree_model.h
@@ -1,8 +1,8 @@
/**
* @file filter_tree_model.h
* @ingroup CardDatabaseModelFilters
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef FILTERTREEMODEL_H
#define FILTERTREEMODEL_H
diff --git a/cockatrice/src/filters/syntax_help.h b/cockatrice/src/filters/syntax_help.h
index 7e5ef3e0e..d06fe03e5 100644
--- a/cockatrice/src/filters/syntax_help.h
+++ b/cockatrice/src/filters/syntax_help.h
@@ -2,8 +2,8 @@
* @file syntax_help.h
* @ingroup CardDatabaseModelFilters
* @ingroup DeckStorageWidgets
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef SEARCH_SYNTAX_HELP_H
#define SEARCH_SYNTAX_HELP_H
diff --git a/cockatrice/src/game/abstract_game.cpp b/cockatrice/src/game/abstract_game.cpp
index 9216f9174..5b1b4bff2 100644
--- a/cockatrice/src/game/abstract_game.cpp
+++ b/cockatrice/src/game/abstract_game.cpp
@@ -1,7 +1,7 @@
#include "abstract_game.h"
#include "../interface/widgets/tabs/tab_game.h"
-#include "player/player.h"
+#include "player/player_logic.h"
AbstractGame::AbstractGame(TabGame *_tab) : QObject(_tab), tab(_tab)
{
@@ -24,10 +24,11 @@ AbstractClient *AbstractGame::getClientForPlayer(int playerId) const
}
return gameState->getClients().at(playerId);
- } else if (gameState->getClients().isEmpty())
+ } else if (gameState->getClients().isEmpty()) {
return nullptr;
- else
+ } else {
return gameState->getClients().first();
+ }
}
void AbstractGame::loadReplay(GameReplay *replay)
@@ -43,13 +44,15 @@ void AbstractGame::setActiveCard(CardItem *card)
CardItem *AbstractGame::getCard(int playerId, const QString &zoneName, int cardId) const
{
- Player *player = playerManager->getPlayer(playerId);
- if (!player)
+ PlayerLogic *player = playerManager->getPlayer(playerId);
+ if (!player) {
return nullptr;
+ }
CardZoneLogic *zone = player->getZones().value(zoneName, 0);
- if (!zone)
+ if (!zone) {
return nullptr;
+ }
return zone->getCard(cardId);
}
\ No newline at end of file
diff --git a/cockatrice/src/game/abstract_game.h b/cockatrice/src/game/abstract_game.h
index cb4dbac2a..2441bac2d 100644
--- a/cockatrice/src/game/abstract_game.h
+++ b/cockatrice/src/game/abstract_game.h
@@ -1,8 +1,8 @@
/**
* @file abstract_game.h
* @ingroup GameLogic
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef COCKATRICE_ABSTRACT_GAME_H
#define COCKATRICE_ABSTRACT_GAME_H
diff --git a/cockatrice/src/game/board/abstract_card_drag_item.cpp b/cockatrice/src/game/board/abstract_card_drag_item.cpp
index 8e3def4ca..026efd60d 100644
--- a/cockatrice/src/game/board/abstract_card_drag_item.cpp
+++ b/cockatrice/src/game/board/abstract_card_drag_item.cpp
@@ -25,11 +25,12 @@ AbstractCardDragItem::AbstractCardDragItem(AbstractCardItem *_item,
setCursor(Qt::ClosedHandCursor);
setZValue(ZValues::DRAG_ITEM);
}
- if (item->getTapped())
+ if (item->getTapped()) {
setTransform(QTransform()
.translate(CardDimensions::WIDTH_HALF_F, CardDimensions::HEIGHT_HALF_F)
.rotate(90)
.translate(-CardDimensions::WIDTH_HALF_F, -CardDimensions::HEIGHT_HALF_F));
+ }
setCacheMode(DeviceCoordinateCache);
diff --git a/cockatrice/src/game/board/abstract_card_drag_item.h b/cockatrice/src/game/board/abstract_card_drag_item.h
index fe3b87983..1cbeb4fe7 100644
--- a/cockatrice/src/game/board/abstract_card_drag_item.h
+++ b/cockatrice/src/game/board/abstract_card_drag_item.h
@@ -1,8 +1,8 @@
/**
* @file abstract_card_drag_item.h
* @ingroup GameGraphicsCards
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef ABSTRACTCARDDRAGITEM_H
#define ABSTRACTCARDDRAGITEM_H
diff --git a/cockatrice/src/game/board/abstract_card_item.cpp b/cockatrice/src/game/board/abstract_card_item.cpp
index 9ec6ada9a..86b3e27c8 100644
--- a/cockatrice/src/game/board/abstract_card_item.cpp
+++ b/cockatrice/src/game/board/abstract_card_item.cpp
@@ -13,7 +13,7 @@
#include
#include
-AbstractCardItem::AbstractCardItem(QGraphicsItem *parent, const CardRef &cardRef, Player *_owner, int _id)
+AbstractCardItem::AbstractCardItem(QGraphicsItem *parent, const CardRef &cardRef, PlayerLogic *_owner, int _id)
: ArrowTarget(_owner, parent), id(_id), cardRef(cardRef), tapped(false), facedown(false), tapAngle(0),
bgColor(Qt::transparent), isHovered(false), realZValue(0)
{
@@ -85,7 +85,12 @@ const CardInfo &AbstractCardItem::getCardInfo() const
void AbstractCardItem::setRealZValue(qreal _zValue)
{
realZValue = _zValue;
- setZValue(_zValue);
+ // During hover, zValue is overridden to HOVERED_CARD. Layout operations
+ // like reorganizeCards() call setRealZValue() on all cards including the
+ // hovered one — skip setZValue() here to avoid clobbering the override.
+ if (!isHovered) {
+ setZValue(_zValue);
+ }
}
QSizeF AbstractCardItem::getTranslatedSize(QPainter *painter) const
@@ -126,8 +131,9 @@ void AbstractCardItem::paintPicture(QPainter *painter, const QSizeF &translatedS
// don't even spend time trying to load the picture if our size is too small
if (translatedSize.width() > 10) {
CardPictureLoader::getPixmap(translatedPixmap, exactCard, translatedSize.toSize());
- if (translatedPixmap.isNull())
+ if (translatedPixmap.isNull()) {
paintImage = false;
+ }
} else {
paintImage = false;
}
@@ -152,9 +158,9 @@ void AbstractCardItem::paintPicture(QPainter *painter, const QSizeF &translatedS
painter->setBackground(Qt::black);
painter->setBackgroundMode(Qt::OpaqueMode);
QString nameStr;
- if (facedown)
+ if (facedown) {
nameStr = "# " + QString::number(id);
- else {
+ } else {
QString prefix = "";
if (SettingsCache::instance().debug().getShowCardId()) {
prefix = "#" + QString::number(id) + " ";
@@ -181,10 +187,12 @@ void AbstractCardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *
if (isSelected() || isHovered) {
QPen pen;
- if (isHovered)
+ if (isHovered) {
pen.setColor(Qt::yellow);
- if (isSelected())
+ }
+ if (isSelected()) {
pen.setColor(Qt::red);
+ }
pen.setWidth(0); // Cosmetic pen
painter->setPen(pen);
painter->drawPath(shape());
@@ -210,11 +218,20 @@ void AbstractCardItem::setCardRef(const CardRef &_cardRef)
void AbstractCardItem::setHovered(bool _hovered)
{
- if (isHovered == _hovered)
+ if (isHovered == _hovered) {
return;
+ }
- if (_hovered)
+ if (_hovered) {
processHoverEvent();
+ } else {
+ // Mark the hovered card's current scene footprint dirty so overlapped
+ // sibling zones (e.g. StackZone) repaint after the card moves away.
+ if (scene()) {
+ scene()->update(sceneBoundingRect());
+ }
+ }
+
isHovered = _hovered;
setZValue(_hovered ? ZValues::HOVERED_CARD : realZValue);
setScale(_hovered && SettingsCache::instance().getScaleCards() ? 1.1 : 1);
@@ -265,13 +282,14 @@ void AbstractCardItem::cacheBgColor()
void AbstractCardItem::setTapped(bool _tapped, bool canAnimate)
{
- if (tapped == _tapped)
+ if (tapped == _tapped) {
return;
+ }
tapped = _tapped;
- if (SettingsCache::instance().getTapAnimation() && canAnimate)
+ if (SettingsCache::instance().getTapAnimation() && canAnimate) {
static_cast(scene())->registerAnimationItem(this);
- else {
+ } else {
tapAngle = tapped ? 90 : 0;
setTransform(QTransform()
.translate(CardDimensions::WIDTH_HALF_F, CardDimensions::HEIGHT_HALF_F)
@@ -297,17 +315,19 @@ void AbstractCardItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
scene()->clearSelection();
setSelected(true);
}
- if (event->button() == Qt::LeftButton)
+ if (event->button() == Qt::LeftButton) {
setCursor(Qt::ClosedHandCursor);
- else if (event->button() == Qt::MiddleButton)
+ } else if (event->button() == Qt::MiddleButton) {
emit showCardInfoPopup(event->screenPos(), cardRef);
+ }
event->accept();
}
void AbstractCardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
- if (event->button() == Qt::MiddleButton)
+ if (event->button() == Qt::MiddleButton) {
emit deleteCardInfoPopup(cardRef.name);
+ }
// This function ensures the parent function doesn't mess around with our selection.
event->accept();
@@ -323,6 +343,7 @@ QVariant AbstractCardItem::itemChange(QGraphicsItem::GraphicsItemChange change,
if (change == ItemSelectedHasChanged) {
update();
return value;
- } else
+ } else {
return ArrowTarget::itemChange(change, value);
+ }
}
diff --git a/cockatrice/src/game/board/abstract_card_item.h b/cockatrice/src/game/board/abstract_card_item.h
index 7d2c29cae..ed545e1ab 100644
--- a/cockatrice/src/game/board/abstract_card_item.h
+++ b/cockatrice/src/game/board/abstract_card_item.h
@@ -1,7 +1,7 @@
/**
* @file abstract_card_item.h
* @ingroup GameGraphicsCards
- * @brief TODO: Document this.
+ * @brief Base class for graphical card items, providing shared rendering, identity, and interaction logic.
*/
#ifndef ABSTRACTCARDITEM_H
@@ -14,7 +14,7 @@
#include
#include
-class Player;
+class PlayerLogic;
class AbstractCardItem : public ArrowTarget
{
@@ -56,7 +56,7 @@ public:
}
explicit AbstractCardItem(QGraphicsItem *parent = nullptr,
const CardRef &cardRef = {},
- Player *_owner = nullptr,
+ PlayerLogic *_owner = nullptr,
int _id = -1);
~AbstractCardItem() override;
QRectF boundingRect() const override;
@@ -96,6 +96,10 @@ public:
}
void setRealZValue(qreal _zValue);
void setHovered(bool _hovered);
+ bool getIsHovered() const
+ {
+ return isHovered;
+ }
QString getColor() const
{
return color;
diff --git a/cockatrice/src/game/board/abstract_counter.cpp b/cockatrice/src/game/board/abstract_counter.cpp
index 08d19ec8a..18787a0bc 100644
--- a/cockatrice/src/game/board/abstract_counter.cpp
+++ b/cockatrice/src/game/board/abstract_counter.cpp
@@ -2,13 +2,14 @@
#include "../../client/settings/cache_settings.h"
#include "../../interface/widgets/tabs/tab_game.h"
-#include "../player/player.h"
#include "../player/player_actions.h"
+#include "../player/player_logic.h"
#include "translate_counter_name.h"
#include
#include
#include
+#include
#include
#include
#include
@@ -16,24 +17,24 @@
#include
#include
-AbstractCounter::AbstractCounter(Player *_player,
- int _id,
- const QString &_name,
+AbstractCounter::AbstractCounter(CounterState *state,
+ PlayerLogic *_player,
bool _shownInCounterArea,
- int _value,
bool _useNameForShortcut,
QGraphicsItem *parent)
- : QGraphicsItem(parent), player(_player), id(_id), name(_name), value(_value),
- useNameForShortcut(_useNameForShortcut), hovered(false), aDec(nullptr), aInc(nullptr), dialogSemaphore(false),
- deleteAfterDialog(false), shownInCounterArea(_shownInCounterArea)
+ : QGraphicsItem(parent), player(_player), id(state->getId()), name(state->getName()), value(state->getValue()),
+ color(state->getColor()), radius(state->getRadius()), useNameForShortcut(_useNameForShortcut),
+ shownInCounterArea(_shownInCounterArea)
{
setAcceptHoverEvents(true);
- shortcutActive = false;
+ connect(state, &CounterState::valueChanged, this, [this](int, int newValue) {
+ value = newValue;
+ update();
+ });
if (player->getPlayerInfo()->getLocalOrJudge()) {
- QString displayName = TranslateCounterName::getDisplayName(_name);
- menu = new TearOffMenu(displayName);
+ menu = new TearOffMenu(TranslateCounterName::getDisplayName(state->getName()));
aSet = new QAction(this);
connect(aSet, &QAction::triggered, this, &AbstractCounter::setCounter);
menu->addAction(aSet);
@@ -41,16 +42,18 @@ AbstractCounter::AbstractCounter(Player *_player,
for (int i = 10; i >= -10; --i) {
if (i == 0) {
menu->addSeparator();
- } else {
- QAction *aIncrement = new QAction(QString(i < 0 ? "%1" : "+%1").arg(i), this);
- if (i == -1)
- aDec = aIncrement;
- else if (i == 1)
- aInc = aIncrement;
- aIncrement->setData(i);
- connect(aIncrement, &QAction::triggered, this, &AbstractCounter::incrementCounter);
- menu->addAction(aIncrement);
+ continue;
}
+ auto *a = new QAction(QString(i < 0 ? "%1" : "+%1").arg(i), this);
+ if (i == -1) {
+ aDec = a;
+ }
+ if (i == 1) {
+ aInc = a;
+ }
+ a->setData(i);
+ connect(a, &QAction::triggered, this, &AbstractCounter::incrementCounter);
+ menu->addAction(a);
}
} else {
menu = nullptr;
@@ -69,39 +72,35 @@ AbstractCounter::~AbstractCounter()
void AbstractCounter::delCounter()
{
- if (dialogSemaphore)
+ if (dialogSemaphore) {
deleteAfterDialog = true;
- else
+ } else {
deleteLater();
+ }
}
void AbstractCounter::retranslateUi()
{
- if (menu) {
+ if (aSet) {
aSet->setText(tr("&Set counter..."));
}
}
void AbstractCounter::setShortcutsActive()
{
- if (!menu) {
+ if (!menu || !player->getPlayerInfo()->getLocal()) {
return;
}
- if (!player->getPlayerInfo()->getLocal()) {
- return;
- }
-
- ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts();
+ ShortcutsSettings &sc = SettingsCache::instance().shortcuts();
+ shortcutActive = true;
if (name == "life") {
- shortcutActive = true;
- aSet->setShortcuts(shortcuts.getShortcut("Player/aSet"));
- aDec->setShortcuts(shortcuts.getShortcut("Player/aDec"));
- aInc->setShortcuts(shortcuts.getShortcut("Player/aInc"));
+ aSet->setShortcuts(sc.getShortcut("Player/aSet"));
+ aDec->setShortcuts(sc.getShortcut("Player/aDec"));
+ aInc->setShortcuts(sc.getShortcut("Player/aInc"));
} else if (useNameForShortcut) {
- shortcutActive = true;
- aSet->setShortcuts(shortcuts.getShortcut("Player/aSetCounter_" + name));
- aDec->setShortcuts(shortcuts.getShortcut("Player/aDecCounter_" + name));
- aInc->setShortcuts(shortcuts.getShortcut("Player/aIncCounter_" + name));
+ aSet->setShortcuts(sc.getShortcut("Player/aSetCounter_" + name));
+ aDec->setShortcuts(sc.getShortcut("Player/aDecCounter_" + name));
+ aInc->setShortcuts(sc.getShortcut("Player/aIncCounter_" + name));
}
}
@@ -126,43 +125,32 @@ void AbstractCounter::refreshShortcuts()
}
}
-void AbstractCounter::setValue(int _value)
-{
- value = _value;
- update();
-}
-
void AbstractCounter::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
- if (isUnderMouse() && player->getPlayerInfo()->getLocalOrJudge()) {
- if (event->button() == Qt::MiddleButton || (QApplication::keyboardModifiers() & Qt::ShiftModifier)) {
- if (menu)
- menu->exec(event->screenPos());
- event->accept();
- } else if (event->button() == Qt::LeftButton) {
- Command_IncCounter cmd;
- cmd.set_counter_id(id);
- cmd.set_delta(1);
- player->getPlayerActions()->sendGameCommand(cmd);
- event->accept();
- } else if (event->button() == Qt::RightButton) {
- Command_IncCounter cmd;
- cmd.set_counter_id(id);
- cmd.set_delta(-1);
- player->getPlayerActions()->sendGameCommand(cmd);
- event->accept();
- }
- } else
+ if (!isUnderMouse() || !player->getPlayerInfo()->getLocalOrJudge()) {
event->ignore();
+ return;
+ }
+
+ if (event->button() == Qt::MiddleButton || QApplication::keyboardModifiers() & Qt::ShiftModifier) {
+ if (menu) {
+ menu->exec(event->screenPos());
+ }
+ } else {
+ Command_IncCounter cmd;
+ cmd.set_counter_id(id);
+ cmd.set_delta(event->button() == Qt::LeftButton ? 1 : -1);
+ player->getPlayerActions()->sendGameCommand(cmd);
+ }
+ event->accept();
}
-void AbstractCounter::hoverEnterEvent(QGraphicsSceneHoverEvent * /*event*/)
+void AbstractCounter::hoverEnterEvent(QGraphicsSceneHoverEvent *)
{
hovered = true;
update();
}
-
-void AbstractCounter::hoverLeaveEvent(QGraphicsSceneHoverEvent * /*event*/)
+void AbstractCounter::hoverLeaveEvent(QGraphicsSceneHoverEvent *)
{
hovered = false;
update();
@@ -170,34 +158,36 @@ void AbstractCounter::hoverLeaveEvent(QGraphicsSceneHoverEvent * /*event*/)
void AbstractCounter::incrementCounter()
{
- const int delta = static_cast(sender())->data().toInt();
Command_IncCounter cmd;
cmd.set_counter_id(id);
- cmd.set_delta(delta);
+ cmd.set_delta(static_cast(sender())->data().toInt());
player->getPlayerActions()->sendGameCommand(cmd);
}
void AbstractCounter::setCounter()
{
+ QWidget *parent = nullptr;
+ if (auto *view = scene() ? scene()->views().value(0) : nullptr) {
+ parent = view->window();
+ }
+
dialogSemaphore = true;
- AbstractCounterDialog dialog(name, QString::number(value), player->getGame()->getTab());
- const int ok = dialog.exec();
+ AbstractCounterDialog dlg(name, QString::number(value), parent);
+ const int ok = dlg.exec();
+ dialogSemaphore = false;
if (deleteAfterDialog) {
deleteLater();
return;
}
- dialogSemaphore = false;
-
- if (!ok)
+ if (!ok) {
return;
+ }
Expression exp(value);
- int newValue = static_cast(exp.parse(dialog.textValue()));
-
Command_SetCounter cmd;
cmd.set_counter_id(id);
- cmd.set_value(newValue);
+ cmd.set_value(static_cast(exp.parse(dlg.textValue())));
player->getPlayerActions()->sendGameCommand(cmd);
}
@@ -231,8 +221,9 @@ void AbstractCounterDialog::changeValue(int diff)
{
bool ok;
int curValue = textValue().toInt(&ok);
- if (!ok)
+ if (!ok) {
return;
+ }
curValue += diff;
setTextValue(QString::number(curValue));
}
diff --git a/cockatrice/src/game/board/abstract_counter.h b/cockatrice/src/game/board/abstract_counter.h
index 074650d54..b31bd1aa3 100644
--- a/cockatrice/src/game/board/abstract_counter.h
+++ b/cockatrice/src/game/board/abstract_counter.h
@@ -1,19 +1,20 @@
/**
* @file abstract_counter.h
* @ingroup GameGraphicsPlayers
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef COUNTER_H
#define COUNTER_H
#include "../../interface/widgets/menus/tearoff_menu.h"
#include "../player/menu/abstract_player_component.h"
+#include "counter_state.h"
#include
#include
-class Player;
+class PlayerLogic;
class QAction;
class QKeyEvent;
class QMenu;
@@ -25,22 +26,26 @@ class AbstractCounter : public QObject, public QGraphicsItem, public AbstractPla
Q_INTERFACES(QGraphicsItem)
protected:
- Player *player;
+ PlayerLogic *player;
int id;
QString name;
int value;
- bool useNameForShortcut, hovered;
+ QColor color;
+ int radius;
+ bool hovered = false;
+ bool useNameForShortcut;
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
private:
- QAction *aSet, *aDec, *aInc;
- TearOffMenu *menu;
- bool dialogSemaphore, deleteAfterDialog;
+ QAction *aSet = nullptr, *aDec = nullptr, *aInc = nullptr;
+ TearOffMenu *menu = nullptr;
+ bool dialogSemaphore = false;
+ bool deleteAfterDialog = false;
bool shownInCounterArea;
- bool shortcutActive;
+ bool shortcutActive = false;
private slots:
void refreshShortcuts();
@@ -48,17 +53,14 @@ private slots:
void setCounter();
public:
- AbstractCounter(Player *_player,
- int _id,
- const QString &_name,
- bool _shownInCounterArea,
- int _value,
- bool _useNameForShortcut = false,
+ AbstractCounter(CounterState *state,
+ PlayerLogic *player,
+ bool shownInCounterArea,
+ bool useNameForShortcut = false,
QGraphicsItem *parent = nullptr);
~AbstractCounter() override;
void retranslateUi() override;
- void setValue(int _value);
void setShortcutsActive() override;
void setShortcutsInactive() override;
void delCounter();
@@ -67,7 +69,6 @@ public:
{
return menu;
}
-
int getId() const
{
return id;
@@ -76,14 +77,22 @@ public:
{
return name;
}
- bool getShownInCounterArea() const
+ QColor getColor() const
{
- return shownInCounterArea;
+ return color;
+ }
+ int getRadius() const
+ {
+ return radius;
}
int getValue() const
{
return value;
}
+ bool getShownInCounterArea() const
+ {
+ return shownInCounterArea;
+ }
};
class AbstractCounterDialog : public QInputDialog
diff --git a/cockatrice/src/game/board/arrow_data.cpp b/cockatrice/src/game/board/arrow_data.cpp
new file mode 100644
index 000000000..bbb70f474
--- /dev/null
+++ b/cockatrice/src/game/board/arrow_data.cpp
@@ -0,0 +1,19 @@
+#include "arrow_data.h"
+
+ArrowData ArrowData::fromProto(const ServerInfo_Arrow &arrow)
+{
+ ArrowData data;
+ data.id = arrow.id();
+ data.startPlayerId = arrow.start_player_id();
+ data.startZone = QString::fromStdString(arrow.start_zone());
+ data.startCardId = arrow.start_card_id();
+ data.targetPlayerId = arrow.target_player_id();
+ data.color = convertColorToQColor(arrow.arrow_color());
+
+ if (arrow.has_target_zone()) {
+ data.targetZone = QString::fromStdString(arrow.target_zone());
+ data.targetCardId = arrow.target_card_id();
+ }
+
+ return data;
+}
\ No newline at end of file
diff --git a/cockatrice/src/game/board/arrow_data.h b/cockatrice/src/game/board/arrow_data.h
new file mode 100644
index 000000000..a8b35dad6
--- /dev/null
+++ b/cockatrice/src/game/board/arrow_data.h
@@ -0,0 +1,28 @@
+#ifndef COCKATRICE_ARROW_DATA_H
+#define COCKATRICE_ARROW_DATA_H
+
+#include
+#include
+#include
+#include
+
+struct ArrowData
+{
+ int id;
+ int startPlayerId;
+ QString startZone;
+ int startCardId;
+ int targetPlayerId;
+ QString targetZone; // empty = targeting a player
+ int targetCardId = -1; // -1 = targeting a player
+ QColor color;
+
+ static ArrowData fromProto(const ServerInfo_Arrow &arrow);
+
+ bool isPlayerTargeted() const
+ {
+ return targetZone.isEmpty();
+ }
+};
+
+#endif // COCKATRICE_ARROW_DATA_H
diff --git a/cockatrice/src/game/board/arrow_item.cpp b/cockatrice/src/game/board/arrow_item.cpp
index 60585a774..430477d76 100644
--- a/cockatrice/src/game/board/arrow_item.cpp
+++ b/cockatrice/src/game/board/arrow_item.cpp
@@ -2,11 +2,11 @@
#include "arrow_item.h"
#include "../../client/settings/cache_settings.h"
-#include "../player/player.h"
+#include "../../game_graphics/zones/card_zone.h"
#include "../player/player_actions.h"
+#include "../player/player_logic.h"
#include "../player/player_target.h"
#include "../z_values.h"
-#include "../zones/card_zone.h"
#include "card_item.h"
#include
@@ -21,46 +21,53 @@
#include
#include
-ArrowItem::ArrowItem(Player *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &_color)
- : QGraphicsItem(), player(_player), id(_id), startItem(_startItem), targetItem(_targetItem), targetLocked(false),
- color(_color), fullColor(true)
+ArrowItem::ArrowItem(PlayerLogic *_player,
+ int _id,
+ ArrowTarget *_startItem,
+ ArrowTarget *_targetItem,
+ const QColor &_color)
+ : player(_player), id(_id), startItem(_startItem), targetItem(_targetItem), color(_color)
{
setZValue(ZValues::ARROWS);
- if (startItem)
- startItem->addArrowFrom(this);
- if (targetItem)
- targetItem->addArrowTo(this);
+ auto doUpdate = [this]() {
+ if (startItem && targetItem) {
+ updatePath();
+ }
+ };
- if (startItem && targetItem)
+ if (startItem) {
+ connect(startItem, &ArrowTarget::scenePositionChanged, this, doUpdate);
+ connect(startItem, &QObject::destroyed, this, &ArrowItem::onTargetDestroyed);
+ }
+ if (targetItem) {
+ connect(targetItem, &ArrowTarget::scenePositionChanged, this, doUpdate);
+ connect(targetItem, &QObject::destroyed, this, &ArrowItem::onTargetDestroyed);
+ }
+
+ if (startItem && targetItem) {
updatePath();
+ }
}
-ArrowItem::~ArrowItem()
+void ArrowItem::onTargetDestroyed()
{
+ emit requestDeletion(id);
}
void ArrowItem::delArrow()
{
- if (startItem) {
- startItem->removeArrowFrom(this);
- startItem = 0;
- }
-
if (targetItem) {
targetItem->setBeingPointedAt(false);
- targetItem->removeArrowTo(this);
- targetItem = 0;
}
-
- player->removeArrow(this);
deleteLater();
}
void ArrowItem::updatePath()
{
- if (!targetItem)
+ if (!targetItem) {
return;
+ }
QPointF endPoint = targetItem->mapToScene(
QPointF(targetItem->boundingRect().width() / 2, targetItem->boundingRect().height() / 2));
@@ -75,8 +82,9 @@ void ArrowItem::updatePath(const QPointF &endPoint)
headWidth / qPow(2, 0.5); // aka headWidth / sqrt (2) but this produces a compile error with MSVC++
const double phi = 15;
- if (!startItem)
+ if (!startItem) {
return;
+ }
QPointF startPoint =
startItem->mapToScene(QPointF(startItem->boundingRect().width() / 2, startItem->boundingRect().height() / 2));
@@ -84,9 +92,9 @@ void ArrowItem::updatePath(const QPointF &endPoint)
qreal lineLength = line.length();
prepareGeometryChange();
- if (lineLength < 30)
+ if (lineLength < 30) {
path = QPainterPath();
- else {
+ } else {
QPointF c(lineLength / 2, qTan(phi * M_PI / 180) * lineLength);
QPainterPath centerLine;
@@ -123,10 +131,11 @@ void ArrowItem::updatePath(const QPointF &endPoint)
void ArrowItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
{
QColor paintColor(color);
- if (fullColor)
+ if (fullColor) {
paintColor.setAlpha(200);
- else
+ } else {
paintColor.setAlpha(150);
+ }
painter->setBrush(paintColor);
painter->drawPath(path);
}
@@ -138,8 +147,7 @@ void ArrowItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
return;
}
- QList colliding = scene()->items(event->scenePos());
- for (QGraphicsItem *item : colliding) {
+ for (auto *item : scene()->items(event->scenePos())) {
if (qgraphicsitem_cast(item)) {
event->ignore();
return;
@@ -148,80 +156,86 @@ void ArrowItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
event->accept();
if (event->button() == Qt::RightButton) {
- Command_DeleteArrow cmd;
- cmd.set_arrow_id(id);
- player->getPlayerActions()->sendGameCommand(cmd);
+ emit requestDeletion(id);
}
}
-ArrowDragItem::ArrowDragItem(Player *_owner, ArrowTarget *_startItem, const QColor &_color, int _deleteInPhase)
- : ArrowItem(_owner, -1, _startItem, 0, _color), deleteInPhase(_deleteInPhase)
+// ArrowDragItem
+
+ArrowDragItem::ArrowDragItem(PlayerLogic *_owner, ArrowTarget *_startItem, const QColor &_color, int _deleteInPhase)
+ : ArrowItem(_owner, -1, _startItem, nullptr, _color), deleteInPhase(_deleteInPhase)
{
}
-void ArrowDragItem::addChildArrow(ArrowDragItem *childArrow)
+void ArrowDragItem::addChildArrow(ArrowDragItem *child)
{
- childArrows.append(childArrow);
+ childArrows.append(child);
}
void ArrowDragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
- // This ensures that if a mouse move event happens after a call to delArrow(),
- // the event will be discarded as it would create some stray pointers.
- if (targetLocked || !startItem)
+ if (targetLocked || !startItem) {
return;
+ }
- QPointF endPos = event->scenePos();
+ const QPointF endPos = event->scenePos();
- QList colliding = scene()->items(endPos);
- ArrowTarget *cursorItem = 0;
+ ArrowTarget *cursorItem = nullptr;
qreal cursorItemZ = -1;
- for (int i = colliding.size() - 1; i >= 0; i--) {
- if (qgraphicsitem_cast(colliding.at(i)) || qgraphicsitem_cast(colliding.at(i))) {
- if (colliding.at(i)->zValue() > cursorItemZ) {
- cursorItem = static_cast(colliding.at(i));
- cursorItemZ = cursorItem->zValue();
- }
+ for (auto *item : scene()->items(endPos)) {
+ ArrowTarget *candidate = nullptr;
+ if (auto *card = qgraphicsitem_cast(item)) {
+ candidate = card;
+ } else if (auto *pt = qgraphicsitem_cast(item)) {
+ candidate = pt;
+ }
+
+ if (candidate && candidate->zValue() > cursorItemZ) {
+ cursorItem = candidate;
+ cursorItemZ = candidate->zValue();
}
}
- if ((cursorItem != targetItem) && targetItem) {
- targetItem->setBeingPointedAt(false);
- targetItem->removeArrowTo(this);
- }
- if (!cursorItem) {
- fullColor = false;
- targetItem = 0;
- updatePath(endPos);
- } else {
- if (cursorItem != targetItem) {
- fullColor = true;
- if (cursorItem != startItem) {
- cursorItem->setBeingPointedAt(true);
- cursorItem->addArrowTo(this);
- }
- targetItem = cursorItem;
+ if (cursorItem != targetItem) {
+ if (targetItem) {
+ disconnect(positionConnection);
+ targetItem->setBeingPointedAt(false);
+ }
+
+ targetItem = cursorItem;
+ fullColor = (cursorItem != nullptr);
+
+ if (cursorItem && cursorItem != startItem) {
+ cursorItem->setBeingPointedAt(true);
+ positionConnection =
+ connect(cursorItem, &ArrowTarget::scenePositionChanged, this, [this]() { updatePath(); });
}
- updatePath();
}
+
+ targetItem ? updatePath() : updatePath(endPos);
update();
- for (ArrowDragItem *child : childArrows) {
+ for (auto *child : childArrows) {
child->mouseMoveEvent(event);
}
}
void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
- if (!startItem)
+ if (!startItem) {
return;
+ }
- if (targetItem && (targetItem != startItem)) {
- CardZoneLogic *startZone = static_cast(startItem)->getZone();
+ if (targetItem && targetItem != startItem) {
+ CardItem *startCard = qgraphicsitem_cast(startItem);
// For now, we can safely assume that the start item is always a card.
// The target item can be a player as well.
- CardItem *startCard = qgraphicsitem_cast(startItem);
- CardItem *targetCard = qgraphicsitem_cast(targetItem);
+ if (!startCard) {
+ delArrow();
+ return;
+ }
+
+ CardZoneLogic *startZone = startCard->getZone();
Command_CreateArrow cmd;
cmd.mutable_arrow_color()->CopyFrom(convertQColorToColor(color));
@@ -229,14 +243,16 @@ void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
cmd.set_start_zone(startZone->getName().toStdString());
cmd.set_start_card_id(startCard->getId());
- if (targetCard) {
+ if (auto *targetCard = qgraphicsitem_cast(targetItem)) {
CardZoneLogic *targetZone = targetCard->getZone();
cmd.set_target_player_id(targetZone->getPlayer()->getPlayerInfo()->getId());
cmd.set_target_zone(targetZone->getName().toStdString());
cmd.set_target_card_id(targetCard->getId());
- } else { // failed to cast target to card, this means it's a player
- PlayerTarget *targetPlayer = qgraphicsitem_cast(targetItem);
+ } else if (auto *targetPlayer = qgraphicsitem_cast(targetItem)) {
cmd.set_target_player_id(targetPlayer->getOwner()->getPlayerInfo()->getId());
+ } else {
+ delArrow();
+ return;
}
// if the card is in hand then we will move the card to stack or table as part of drawing the arrow
@@ -246,10 +262,11 @@ void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
bool playToStack = SettingsCache::instance().getPlayToStack();
if (ci && ((!playToStack && ci->getUiAttributes().tableRow == 3) ||
(playToStack && ci->getUiAttributes().tableRow != 0 &&
- startCard->getZone()->getName() != ZoneNames::STACK)))
+ startCard->getZone()->getName() != ZoneNames::STACK))) {
cmd.set_start_zone(ZoneNames::STACK);
- else
+ } else {
cmd.set_start_zone(playToStack ? ZoneNames::STACK : ZoneNames::TABLE);
+ }
}
if (deleteInPhase != 0) {
@@ -258,111 +275,109 @@ void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
player->getPlayerActions()->sendGameCommand(cmd);
}
- delArrow();
- for (ArrowDragItem *child : childArrows) {
+ delArrow();
+ for (auto *child : childArrows) {
child->mouseReleaseEvent(event);
}
}
+// ArrowAttachItem
ArrowAttachItem::ArrowAttachItem(ArrowTarget *_startItem)
- : ArrowItem(_startItem->getOwner(), -1, _startItem, 0, Qt::green)
+ : ArrowItem(_startItem->getOwner(), -1, _startItem, nullptr, Qt::green)
{
}
-void ArrowAttachItem::addChildArrow(ArrowAttachItem *childArrow)
+void ArrowAttachItem::addChildArrow(ArrowAttachItem *child)
{
- childArrows.append(childArrow);
+ childArrows.append(child);
}
void ArrowAttachItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
- if (targetLocked || !startItem)
+ if (targetLocked || !startItem) {
return;
+ }
- QPointF endPos = event->scenePos();
+ const QPointF endPos = event->scenePos();
- QList colliding = scene()->items(endPos);
- ArrowTarget *cursorItem = 0;
+ ArrowTarget *cursorItem = nullptr;
qreal cursorItemZ = -1;
- for (int i = colliding.size() - 1; i >= 0; i--) {
- if (qgraphicsitem_cast(colliding.at(i))) {
- if (colliding.at(i)->zValue() > cursorItemZ) {
- cursorItem = static_cast(colliding.at(i));
- cursorItemZ = cursorItem->zValue();
+ for (auto *item : scene()->items(endPos)) {
+ if (auto *card = qgraphicsitem_cast(item)) {
+ if (card->zValue() > cursorItemZ) {
+ cursorItem = card;
+ cursorItemZ = card->zValue();
}
}
}
- if ((cursorItem != targetItem) && targetItem) {
- targetItem->setBeingPointedAt(false);
- }
- if (!cursorItem) {
- fullColor = false;
- targetItem = 0;
- updatePath(endPos);
- } else {
- fullColor = true;
- if (cursorItem != startItem) {
- cursorItem->setBeingPointedAt(true);
+ if (cursorItem != targetItem) {
+ if (targetItem) {
+ disconnect(positionConnection);
+ targetItem->setBeingPointedAt(false);
}
+
targetItem = cursorItem;
- updatePath();
+ fullColor = (cursorItem != nullptr);
+
+ if (cursorItem && cursorItem != startItem) {
+ cursorItem->setBeingPointedAt(true);
+ positionConnection =
+ connect(cursorItem, &ArrowTarget::scenePositionChanged, this, [this]() { updatePath(); });
+ }
}
+
+ targetItem ? updatePath() : updatePath(endPos);
update();
- for (ArrowAttachItem *child : childArrows) {
+ for (auto *child : childArrows) {
child->mouseMoveEvent(event);
}
}
-void ArrowAttachItem::attachCards(CardItem *startCard, const CardItem *targetCard)
-{
- // do nothing if target is already attached to another card or is not in play
- if (targetCard->getAttachedTo() || targetCard->getZone()->getName() != ZoneNames::TABLE) {
- return;
- }
-
- CardZoneLogic *startZone = startCard->getZone();
- CardZoneLogic *targetZone = targetCard->getZone();
-
- // move card onto table first if attaching from some other zone
- if (startZone->getName() != ZoneNames::TABLE) {
- player->getPlayerActions()->playCardToTable(startCard, false);
- }
-
- Command_AttachCard cmd;
- cmd.set_start_zone(ZoneNames::TABLE);
- cmd.set_card_id(startCard->getId());
- cmd.set_target_player_id(targetZone->getPlayer()->getPlayerInfo()->getId());
- cmd.set_target_zone(targetZone->getName().toStdString());
- cmd.set_target_card_id(targetCard->getId());
-
- player->getPlayerActions()->sendGameCommand(cmd);
-}
-
void ArrowAttachItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
- if (!startItem)
+ if (!startItem) {
return;
+ }
// Attaching could move startItem under the current cursor position, causing all children to retarget to it right
// before they are processed. Prevent that.
- for (ArrowAttachItem *child : childArrows) {
+ for (auto *child : childArrows) {
child->setTargetLocked(true);
}
- if (targetItem && (targetItem != startItem)) {
- auto startCard = qgraphicsitem_cast(startItem);
- auto targetCard = qgraphicsitem_cast(targetItem);
+ if (targetItem && targetItem != startItem) {
+ auto *startCard = qgraphicsitem_cast(startItem);
+ auto *targetCard = qgraphicsitem_cast(targetItem);
if (startCard && targetCard) {
attachCards(startCard, targetCard);
}
}
delArrow();
-
- for (ArrowAttachItem *child : childArrows) {
+ for (auto *child : childArrows) {
child->mouseReleaseEvent(event);
}
}
+
+void ArrowAttachItem::attachCards(CardItem *startCard, const CardItem *targetCard)
+{
+ if (targetCard->getAttachedTo() || targetCard->getZone()->getName() != ZoneNames::TABLE) {
+ return;
+ }
+
+ // move card onto table first if attaching from some other zone
+ if (startCard->getZone()->getName() != ZoneNames::TABLE) {
+ player->getPlayerActions()->playCardToTable(startCard, false);
+ }
+
+ Command_AttachCard cmd;
+ cmd.set_start_zone(ZoneNames::TABLE);
+ cmd.set_card_id(startCard->getId());
+ cmd.set_target_player_id(targetCard->getZone()->getPlayer()->getPlayerInfo()->getId());
+ cmd.set_target_zone(targetCard->getZone()->getName().toStdString());
+ cmd.set_target_card_id(targetCard->getId());
+ player->getPlayerActions()->sendGameCommand(cmd);
+}
\ No newline at end of file
diff --git a/cockatrice/src/game/board/arrow_item.h b/cockatrice/src/game/board/arrow_item.h
index cb78ee066..7dc0f9477 100644
--- a/cockatrice/src/game/board/arrow_item.h
+++ b/cockatrice/src/game/board/arrow_item.h
@@ -1,40 +1,47 @@
/**
* @file arrow_item.h
* @ingroup GameGraphics
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef ARROWITEM_H
#define ARROWITEM_H
+#include "arrow_target.h"
+
#include
+#include
class CardItem;
class QGraphicsSceneMouseEvent;
class QMenu;
-class Player;
-class ArrowTarget;
+class PlayerLogic;
class ArrowItem : public QObject, public QGraphicsItem
{
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
+signals:
+ void requestDeletion(int id);
+
private:
QPainterPath path;
- QMenu *menu;
protected:
- Player *player;
+ PlayerLogic *player;
int id;
- ArrowTarget *startItem, *targetItem;
- bool targetLocked;
+ QPointer startItem;
+ QPointer targetItem;
+ bool targetLocked = false;
QColor color;
- bool fullColor;
+ bool fullColor = true;
+
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
public:
- ArrowItem(Player *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &color);
- ~ArrowItem() override;
+ ArrowItem(PlayerLogic *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &_color);
+ void onTargetDestroyed();
+
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
[[nodiscard]] QRectF boundingRect() const override
{
@@ -44,6 +51,7 @@ public:
{
return path;
}
+
void updatePath();
void updatePath(const QPointF &endPoint);
@@ -51,18 +59,10 @@ public:
{
return id;
}
- [[nodiscard]] Player *getPlayer() const
+ [[nodiscard]] PlayerLogic *getPlayer() const
{
return player;
}
- void setStartItem(ArrowTarget *_item)
- {
- startItem = _item;
- }
- void setTargetItem(ArrowTarget *_item)
- {
- targetItem = _item;
- }
[[nodiscard]] ArrowTarget *getStartItem() const
{
return startItem;
@@ -75,6 +75,7 @@ public:
{
targetLocked = _targetLocked;
}
+
void delArrow();
};
@@ -84,10 +85,11 @@ class ArrowDragItem : public ArrowItem
private:
int deleteInPhase;
QList childArrows;
+ QMetaObject::Connection positionConnection;
public:
- ArrowDragItem(Player *_owner, ArrowTarget *_startItem, const QColor &_color, int _deleteInPhase);
- void addChildArrow(ArrowDragItem *childArrow);
+ ArrowDragItem(PlayerLogic *_owner, ArrowTarget *_startItem, const QColor &_color, int _deleteInPhase);
+ void addChildArrow(ArrowDragItem *child);
protected:
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
@@ -99,12 +101,12 @@ class ArrowAttachItem : public ArrowItem
Q_OBJECT
private:
QList childArrows;
-
+ QMetaObject::Connection positionConnection;
void attachCards(CardItem *startCard, const CardItem *targetCard);
public:
explicit ArrowAttachItem(ArrowTarget *_startItem);
- void addChildArrow(ArrowAttachItem *childArrow);
+ void addChildArrow(ArrowAttachItem *child);
protected:
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
diff --git a/cockatrice/src/game/board/arrow_target.cpp b/cockatrice/src/game/board/arrow_target.cpp
index 2dbd913fa..edf526e4e 100644
--- a/cockatrice/src/game/board/arrow_target.cpp
+++ b/cockatrice/src/game/board/arrow_target.cpp
@@ -1,41 +1,23 @@
#include "arrow_target.h"
-#include "../player/player.h"
+#include "../player/player_logic.h"
#include "arrow_item.h"
-ArrowTarget::ArrowTarget(Player *_owner, QGraphicsItem *parent)
- : AbstractGraphicsItem(parent), owner(_owner), beingPointedAt(false)
+ArrowTarget::ArrowTarget(PlayerLogic *_owner, QGraphicsItem *parent) : AbstractGraphicsItem(parent), owner(_owner)
{
setFlag(ItemSendsScenePositionChanges);
}
-ArrowTarget::~ArrowTarget()
-{
- for (int i = 0; i < arrowsFrom.size(); ++i) {
- arrowsFrom[i]->setStartItem(0);
- arrowsFrom[i]->delArrow();
- }
- for (int i = 0; i < arrowsTo.size(); ++i) {
- arrowsTo[i]->setTargetItem(0);
- arrowsTo[i]->delArrow();
- }
-}
-
void ArrowTarget::setBeingPointedAt(bool _beingPointedAt)
{
beingPointedAt = _beingPointedAt;
update();
}
-QVariant ArrowTarget::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
+QVariant ArrowTarget::itemChange(GraphicsItemChange change, const QVariant &value)
{
- if (change == ItemScenePositionHasChanged && scene()) {
- for (auto *arrow : arrowsFrom)
- arrow->updatePath();
-
- for (auto *arrow : arrowsTo)
- arrow->updatePath();
+ if (change == ItemScenePositionHasChanged) {
+ emit scenePositionChanged();
}
-
- return QGraphicsItem::itemChange(change, value);
-}
+ return AbstractGraphicsItem::itemChange(change, value);
+}
\ No newline at end of file
diff --git a/cockatrice/src/game/board/arrow_target.h b/cockatrice/src/game/board/arrow_target.h
index 55f4ef678..664572705 100644
--- a/cockatrice/src/game/board/arrow_target.h
+++ b/cockatrice/src/game/board/arrow_target.h
@@ -1,8 +1,8 @@
/**
* @file arrow_target.h
* @ingroup GameGraphics
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef ARROWTARGET_H
#define ARROWTARGET_H
@@ -11,24 +11,26 @@
#include
-class Player;
+class PlayerLogic;
class ArrowItem;
class ArrowTarget : public AbstractGraphicsItem
{
Q_OBJECT
protected:
- Player *owner;
+ PlayerLogic *owner;
private:
- bool beingPointedAt;
- QList arrowsFrom, arrowsTo;
+ bool beingPointedAt = false;
+
+signals:
+ void scenePositionChanged();
public:
- explicit ArrowTarget(Player *_owner, QGraphicsItem *parent = nullptr);
- ~ArrowTarget() override;
+ explicit ArrowTarget(PlayerLogic *_owner, QGraphicsItem *parent = nullptr);
+ ~ArrowTarget() override = default;
- [[nodiscard]] Player *getOwner() const
+ [[nodiscard]] PlayerLogic *getOwner() const
{
return owner;
}
@@ -39,32 +41,7 @@ public:
return beingPointedAt;
}
- [[nodiscard]] const QList &getArrowsFrom() const
- {
- return arrowsFrom;
- }
- void addArrowFrom(ArrowItem *arrow)
- {
- arrowsFrom.append(arrow);
- }
- void removeArrowFrom(ArrowItem *arrow)
- {
- arrowsFrom.removeOne(arrow);
- }
- [[nodiscard]] const QList &getArrowsTo() const
- {
- return arrowsTo;
- }
- void addArrowTo(ArrowItem *arrow)
- {
- arrowsTo.append(arrow);
- }
- void removeArrowTo(ArrowItem *arrow)
- {
- arrowsTo.removeOne(arrow);
- }
-
protected:
- QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override;
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
};
#endif
diff --git a/cockatrice/src/game/board/card_drag_item.cpp b/cockatrice/src/game/board/card_drag_item.cpp
index 5ae56ccba..39fb9a390 100644
--- a/cockatrice/src/game/board/card_drag_item.cpp
+++ b/cockatrice/src/game/board/card_drag_item.cpp
@@ -1,9 +1,9 @@
#include "card_drag_item.h"
+#include "../../game_graphics/zones/card_zone.h"
+#include "../../game_graphics/zones/table_zone.h"
+#include "../../game_graphics/zones/view_zone.h"
#include "../game_scene.h"
-#include "../zones/card_zone.h"
-#include "../zones/table_zone.h"
-#include "../zones/view_zone.h"
#include "card_item.h"
#include
@@ -24,8 +24,9 @@ void CardDragItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
{
AbstractCardDragItem::paint(painter, option, widget);
- if (occupied)
+ if (occupied) {
painter->fillPath(shape(), QColor(200, 0, 0, 100));
+ }
}
void CardDragItem::updatePosition(const QPointF &cursorScenePos)
@@ -38,16 +39,19 @@ void CardDragItem::updatePosition(const QPointF &cursorScenePos)
ZoneViewZone *zoneViewZone = 0;
for (int i = colliding.size() - 1; i >= 0; i--) {
CardZone *temp = qgraphicsitem_cast(colliding.at(i));
- if (!cardZone)
+ if (!cardZone) {
cardZone = temp;
- if (!zoneViewZone)
+ }
+ if (!zoneViewZone) {
zoneViewZone = qobject_cast(temp);
+ }
}
CardZone *cursorZone = 0;
- if (zoneViewZone)
+ if (zoneViewZone) {
cursorZone = zoneViewZone;
- else if (cardZone)
+ } else if (cardZone) {
cursorZone = cardZone;
+ }
// Always update the current zone, even if its null, to cancel the drag
// instead of dropping cards into an non-intuitive location.
@@ -59,8 +63,9 @@ void CardDragItem::updatePosition(const QPointF &cursorScenePos)
QPointF newPos = cursorScenePos - hotSpot;
if (newPos != pos()) {
- for (int i = 0; i < childDrags.size(); i++)
+ for (int i = 0; i < childDrags.size(); i++) {
childDrags[i]->setPos(newPos + childDrags[i]->getHotSpot());
+ }
setPos(newPos);
}
@@ -78,23 +83,27 @@ void CardDragItem::updatePosition(const QPointF &cursorScenePos)
// position.
TableZone *tableZone = qobject_cast(cursorZone);
QPointF closestGridPoint;
- if (tableZone)
+ if (tableZone) {
closestGridPoint = tableZone->closestGridPoint(cursorPosInZone);
- else
+ } else {
closestGridPoint = cursorPosInZone - hotSpot;
+ }
QPointF newPos = zonePos + closestGridPoint;
if (newPos != pos()) {
- for (int i = 0; i < childDrags.size(); i++)
+ for (int i = 0; i < childDrags.size(); i++) {
childDrags[i]->setPos(newPos + childDrags[i]->getHotSpot());
+ }
setPos(newPos);
bool newOccupied = false;
TableZone *table = qobject_cast(cursorZone);
- if (table)
- if (table->getCardFromCoords(closestGridPoint))
+ if (table) {
+ if (table->getCardFromCoords(closestGridPoint)) {
newOccupied = true;
+ }
+ }
if (newOccupied != occupied) {
occupied = newOccupied;
update();
diff --git a/cockatrice/src/game/board/card_drag_item.h b/cockatrice/src/game/board/card_drag_item.h
index 930c6be6f..74d25ad04 100644
--- a/cockatrice/src/game/board/card_drag_item.h
+++ b/cockatrice/src/game/board/card_drag_item.h
@@ -1,8 +1,8 @@
/**
* @file card_drag_item.h
* @ingroup GameGraphicsCards
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef CARDDRAGITEM_H
#define CARDDRAGITEM_H
diff --git a/cockatrice/src/game/board/card_item.cpp b/cockatrice/src/game/board/card_item.cpp
index 072c1a231..a08194540 100644
--- a/cockatrice/src/game/board/card_item.cpp
+++ b/cockatrice/src/game/board/card_item.cpp
@@ -1,14 +1,14 @@
#include "card_item.h"
#include "../../client/settings/cache_settings.h"
+#include "../../game_graphics/zones/table_zone.h"
+#include "../../game_graphics/zones/view_zone.h"
#include "../../interface/widgets/tabs/tab_game.h"
#include "../game_scene.h"
#include "../phase.h"
-#include "../player/player.h"
#include "../player/player_actions.h"
-#include "../zones/logic/view_zone_logic.h"
-#include "../zones/table_zone.h"
-#include "../zones/view_zone.h"
+#include "../player/player_logic.h"
+#include "../zones/view_zone_logic.h"
#include "arrow_item.h"
#include "card_drag_item.h"
@@ -20,15 +20,19 @@
#include
#include
-CardItem::CardItem(Player *_owner, QGraphicsItem *parent, const CardRef &cardRef, int _cardid, CardZoneLogic *_zone)
- : AbstractCardItem(parent, cardRef, _owner, _cardid), zone(_zone), attacking(false), destroyOnZoneChange(false),
- doesntUntap(false), dragItem(nullptr), attachedTo(nullptr)
+CardItem::CardItem(PlayerLogic *_owner,
+ QGraphicsItem *parent,
+ const CardRef &cardRef,
+ int _cardid,
+ CardZoneLogic *_zone)
+ : AbstractCardItem(parent, cardRef, _owner, _cardid), state(new CardState(this, _zone)), dragItem(nullptr)
{
owner->addCard(this);
connect(&SettingsCache::instance().cardCounters(), &CardCounterSettings::colorChanged, this, [this](int counterId) {
- if (counters.contains(counterId))
+ if (state->getCounters().contains(counterId)) {
update();
+ }
});
}
@@ -47,23 +51,24 @@ void CardItem::prepareDelete()
attachedCards.first()->setAttachedTo(nullptr);
}
- if (attachedTo != nullptr) {
- attachedTo->removeAttachedCard(this);
- attachedTo = nullptr;
+ if (state->getAttachedTo() != nullptr) {
+ state->getAttachedTo()->removeAttachedCard(this);
+ state->setAttachedTo(nullptr);
}
}
void CardItem::deleteLater()
{
prepareDelete();
- if (scene())
+ if (scene()) {
static_cast(scene())->unregisterAnimationItem(this);
+ }
AbstractCardItem::deleteLater();
}
void CardItem::setZone(CardZoneLogic *_zone)
{
- zone = _zone;
+ state->setZone(_zone);
}
void CardItem::retranslateUi()
@@ -78,23 +83,23 @@ void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
AbstractCardItem::paint(painter, option, widget);
int i = 0;
- QMapIterator counterIterator(counters);
+ QMapIterator counterIterator(state->getCounters());
while (counterIterator.hasNext()) {
counterIterator.next();
QColor _color = cardCounterSettings.color(counterIterator.key());
- paintNumberEllipse(counterIterator.value(), 14, _color, i, counters.size(), painter);
+ paintNumberEllipse(counterIterator.value(), 14, _color, i, state->getCounters().size(), painter);
++i;
}
QSizeF translatedSize = getTranslatedSize(painter);
qreal scaleFactor = translatedSize.width() / boundingRect().width();
- if (!pt.isEmpty()) {
+ if (!state->getPT().isEmpty()) {
painter->save();
transformPainter(painter, translatedSize, tapAngle);
- if (!getFaceDown() && pt == exactCard.getInfo().getPowTough()) {
+ if (!getFaceDown() && state->getPT() == exactCard.getInfo().getPowTough()) {
painter->setPen(Qt::white);
} else {
painter->setPen(QColor(255, 150, 0)); // dark orange
@@ -105,11 +110,11 @@ void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
painter->drawText(QRectF(4 * scaleFactor, 4 * scaleFactor, translatedSize.width() - 10 * scaleFactor,
translatedSize.height() - 8 * scaleFactor),
- Qt::AlignRight | Qt::AlignBottom, pt);
+ Qt::AlignRight | Qt::AlignBottom, state->getPT());
painter->restore();
}
- if (!annotation.isEmpty()) {
+ if (!state->getAnnotation().isEmpty()) {
painter->save();
transformPainter(painter, translatedSize, tapAngle);
@@ -119,7 +124,7 @@ void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
painter->drawText(QRectF(4 * scaleFactor, 4 * scaleFactor, translatedSize.width() - 8 * scaleFactor,
translatedSize.height() - 8 * scaleFactor),
- Qt::AlignCenter | Qt::TextWrapAnywhere, annotation);
+ Qt::AlignCenter | Qt::TextWrapAnywhere, state->getAnnotation());
painter->restore();
}
@@ -127,7 +132,7 @@ void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
painter->fillPath(shape(), QBrush(QColor(255, 0, 0, 100)));
}
- if (doesntUntap) {
+ if (state->getDoesntUntap()) {
painter->save();
painter->setRenderHint(QPainter::Antialiasing, false);
@@ -146,69 +151,66 @@ void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
void CardItem::setAttacking(bool _attacking)
{
- attacking = _attacking;
+ state->setAttacking(_attacking);
update();
}
void CardItem::setCounter(int _id, int _value)
{
- if (_value)
- counters.insert(_id, _value);
- else
- counters.remove(_id);
+ state->setCounter(_id, _value);
update();
}
void CardItem::setAnnotation(const QString &_annotation)
{
- annotation = _annotation;
+ state->setAnnotation(_annotation);
update();
}
void CardItem::setDoesntUntap(bool _doesntUntap)
{
- doesntUntap = _doesntUntap;
+ state->setDoesntUntap(_doesntUntap);
update();
}
void CardItem::setPT(const QString &_pt)
{
- pt = _pt;
+ state->setPT(_pt);
update();
}
void CardItem::setAttachedTo(CardItem *_attachedTo)
{
- if (attachedTo != nullptr) {
- attachedTo->removeAttachedCard(this);
+ if (state->getAttachedTo() != nullptr) {
+ state->getAttachedTo()->removeAttachedCard(this);
}
gridPoint.setX(-1);
- attachedTo = _attachedTo;
- if (attachedTo != nullptr) {
+ state->setAttachedTo(_attachedTo);
+ if (state->getAttachedTo() != nullptr) {
// If the zone is being torn down, it might already be null by the time a card tries to un-attach all its
// attached cards
- if (attachedTo->zone == nullptr) {
+ if (state->getAttachedTo()->getZone() == nullptr) {
deleteLater();
} else {
- emit attachedTo->zone->cardAdded(this);
- attachedTo->addAttachedCard(this);
- if (zone != attachedTo->getZone()) {
- attachedTo->getZone()->reorganizeCards();
+ emit state->getAttachedTo()->getZone()->cardAdded(this);
+ state->getAttachedTo()->addAttachedCard(this);
+ if (state->getZone() != state->getAttachedTo()->getZone()) {
+ state->getAttachedTo()->getZone()->reorganizeCards();
}
}
} else {
// If the zone is being torn down, it might already be null by the time a card tries to un-attach all its
// attached cards
- if (zone == nullptr) {
+ if (state->getZone() == nullptr) {
deleteLater();
} else {
- emit zone->cardAdded(this);
+ emit state->getZone()->cardAdded(this);
}
}
- if (zone != nullptr) {
- zone->reorganizeCards();
+ if (state->getZone() != nullptr) {
+ state->getZone()->reorganizeCards();
}
}
@@ -217,28 +219,23 @@ void CardItem::setAttachedTo(CardItem *_attachedTo)
*/
void CardItem::resetState(bool keepAnnotations)
{
- attacking = false;
- counters.clear();
- pt.clear();
- if (!keepAnnotations) {
- annotation.clear();
- }
- attachedTo = 0;
+ state->resetState(keepAnnotations);
attachedCards.clear();
setTapped(false, false);
setDoesntUntap(false);
- if (scene())
+ if (scene()) {
static_cast(scene())->unregisterAnimationItem(this);
+ }
update();
}
void CardItem::processCardInfo(const ServerInfo_Card &_info)
{
- counters.clear();
+ state->clearCounters();
const int counterListSize = _info.counter_list_size();
for (int i = 0; i < counterListSize; ++i) {
const ServerInfo_CardCounter &counterInfo = _info.counter_list(i);
- counters.insert(counterInfo.id(), counterInfo.value());
+ state->insertCounter(counterInfo.id(), counterInfo.value());
}
setId(_info.id());
@@ -275,11 +272,12 @@ void CardItem::deleteDragItem()
void CardItem::drawArrow(const QColor &arrowColor)
{
- if (owner->getGame()->getPlayerManager()->isSpectator())
+ if (owner->getGame()->getPlayerManager()->isSpectator()) {
return;
+ }
auto *game = owner->getGame();
- Player *arrowOwner = game->getPlayerManager()->getActiveLocalPlayer(game->getGameState()->getActivePlayer());
+ PlayerLogic *arrowOwner = game->getPlayerManager()->getActiveLocalPlayer(game->getGameState()->getActivePlayer());
int phase = 0; // 0 means to not set the phase
if (SettingsCache::instance().getDoNotDeleteArrowsInSubPhases()) {
int currentPhase = game->getGameState()->getCurrentPhase();
@@ -291,10 +289,12 @@ void CardItem::drawArrow(const QColor &arrowColor)
for (const auto &item : scene()->selectedItems()) {
CardItem *card = qgraphicsitem_cast(item);
- if (card == nullptr || card == this)
+ if (card == nullptr || card == this) {
continue;
- if (card->getZone() != zone)
+ }
+ if (card->getZone() != state->getZone()) {
continue;
+ }
ArrowDragItem *childArrow = new ArrowDragItem(arrowOwner, card, arrowColor, phase);
scene()->addItem(childArrow);
@@ -304,8 +304,9 @@ void CardItem::drawArrow(const QColor &arrowColor)
void CardItem::drawAttachArrow()
{
- if (owner->getGame()->getPlayerManager()->isSpectator())
+ if (owner->getGame()->getPlayerManager()->isSpectator()) {
return;
+ }
auto *arrow = new ArrowAttachItem(this);
scene()->addItem(arrow);
@@ -313,10 +314,12 @@ void CardItem::drawAttachArrow()
for (const auto &item : scene()->selectedItems()) {
CardItem *card = qgraphicsitem_cast(item);
- if (card == nullptr)
+ if (card == nullptr) {
continue;
- if (card->getZone() != zone)
+ }
+ if (card->getZone() != state->getZone()) {
continue;
+ }
ArrowAttachItem *childArrow = new ArrowAttachItem(card);
scene()->addItem(childArrow);
@@ -328,27 +331,32 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (event->buttons().testFlag(Qt::RightButton)) {
if ((event->screenPos() - event->buttonDownScreenPos(Qt::RightButton)).manhattanLength() <
- 2 * QApplication::startDragDistance())
+ 2 * QApplication::startDragDistance()) {
return;
+ }
QColor arrowColor = Qt::red;
- if (event->modifiers().testFlag(Qt::ControlModifier))
+ if (event->modifiers().testFlag(Qt::ControlModifier)) {
arrowColor = Qt::yellow;
- else if (event->modifiers().testFlag(Qt::AltModifier))
+ } else if (event->modifiers().testFlag(Qt::AltModifier)) {
arrowColor = Qt::blue;
- else if (event->modifiers().testFlag(Qt::ShiftModifier))
+ } else if (event->modifiers().testFlag(Qt::ShiftModifier)) {
arrowColor = Qt::green;
+ }
drawArrow(arrowColor);
} else if (event->buttons().testFlag(Qt::LeftButton)) {
if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() <
- 2 * QApplication::startDragDistance())
+ 2 * QApplication::startDragDistance()) {
return;
- if (const ZoneViewZoneLogic *view = qobject_cast(zone)) {
- if (view->getRevealZone() && !view->getWriteableRevealZone())
+ }
+ if (const ZoneViewZoneLogic *view = qobject_cast(state->getZone())) {
+ if (view->getRevealZone() && !view->getWriteableRevealZone()) {
return;
- } else if (!owner->getPlayerInfo()->getLocalOrJudge())
+ }
+ } else if (!owner->getPlayerInfo()->getLocalOrJudge()) {
return;
+ }
bool forceFaceDown = event->modifiers().testFlag(Qt::ShiftModifier);
@@ -360,14 +368,16 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
int childIndex = 0;
for (const auto &item : scene()->selectedItems()) {
CardItem *card = static_cast(item);
- if ((card == this) || (card->getZone() != zone))
+ if ((card == this) || (card->getZone() != state->getZone())) {
continue;
+ }
++childIndex;
QPointF childPos;
- if (zone->getHasCardAttr())
+ if (state->getZone()->getHasCardAttr()) {
childPos = card->pos() - pos();
- else
+ } else {
childPos = QPointF(childIndex * CardDimensions::WIDTH_HALF_F, 0);
+ }
CardDragItem *drag =
new CardDragItem(card, card->getId(), childPos, card->getFaceDown() || forceFaceDown, dragItem);
drag->setPos(dragItem->pos() + childPos);
@@ -380,18 +390,19 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
void CardItem::playCard(bool faceDown)
{
// Do nothing if the card belongs to another player
- if (!owner->getPlayerInfo()->getLocalOrJudge())
+ if (!owner->getPlayerInfo()->getLocalOrJudge()) {
return;
+ }
- TableZoneLogic *tz = qobject_cast(zone);
- if (tz)
+ TableZoneLogic *tz = qobject_cast(state->getZone());
+ if (tz) {
emit tz->toggleTapped();
- else {
+ } else {
if (SettingsCache::instance().getClickPlaysAllSelected()) {
- faceDown ? zone->getPlayer()->getPlayerActions()->actPlayFacedown()
- : zone->getPlayer()->getPlayerActions()->actPlay();
+ faceDown ? state->getZone()->getPlayer()->getPlayerActions()->actPlayFacedown()
+ : state->getZone()->getPlayer()->getPlayerActions()->actPlay();
} else {
- zone->getPlayer()->getPlayerActions()->playCard(this, faceDown);
+ state->getZone()->getPlayer()->getPlayerActions()->playCard(this, faceDown);
}
}
}
@@ -447,11 +458,11 @@ static bool isUnwritableRevealZone(CardZoneLogic *zone)
*/
void CardItem::handleClickedToPlay(bool shiftHeld)
{
- if (isUnwritableRevealZone(zone)) {
+ if (isUnwritableRevealZone(state->getZone())) {
if (SettingsCache::instance().getClickPlaysAllSelected()) {
- zone->getPlayer()->getPlayerActions()->actHide();
+ state->getZone()->getPlayer()->getPlayerActions()->actHide();
} else {
- zone->removeCard(this);
+ state->getZone()->removeCard(this);
}
} else {
playCard(shiftHeld);
@@ -493,8 +504,9 @@ bool CardItem::animationEvent()
{
int rotation = ROTATION_DEGREES_PER_FRAME;
bool animationIncomplete = true;
- if (!tapped)
+ if (!tapped) {
rotation *= -1;
+ }
tapAngle += rotation;
if (tapped && (tapAngle > 90)) {
diff --git a/cockatrice/src/game/board/card_item.h b/cockatrice/src/game/board/card_item.h
index 9799b5067..87f9667de 100644
--- a/cockatrice/src/game/board/card_item.h
+++ b/cockatrice/src/game/board/card_item.h
@@ -1,42 +1,37 @@
/**
* @file card_item.h
* @ingroup GameGraphicsCards
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef CARDITEM_H
#define CARDITEM_H
-#include "../zones/logic/card_zone_logic.h"
+#include "../zones/card_zone_logic.h"
#include "abstract_card_item.h"
+#include "card_state.h"
#include
+#include
class CardDatabase;
class CardDragItem;
class CardZone;
class ServerInfo_Card;
-class Player;
+class PlayerLogic;
class QAction;
class QColor;
-const int MAX_COUNTERS_ON_CARD = 999;
const int ROTATION_DEGREES_PER_FRAME = 10;
class CardItem : public AbstractCardItem
{
Q_OBJECT
private:
- CardZoneLogic *zone;
- bool attacking;
- QMap counters;
- QString annotation;
- QString pt;
- bool destroyOnZoneChange;
- bool doesntUntap;
+ CardState *state;
+
QPoint gridPoint;
CardDragItem *dragItem;
- CardItem *attachedTo;
QList attachedCards;
void prepareDelete();
@@ -53,16 +48,20 @@ public:
{
return Type;
}
- explicit CardItem(Player *_owner,
+ explicit CardItem(PlayerLogic *_owner,
QGraphicsItem *parent = nullptr,
const CardRef &cardRef = {},
int _cardid = -1,
CardZoneLogic *_zone = nullptr);
void retranslateUi();
+ [[nodiscard]] CardState *getState() const
+ {
+ return state;
+ }
[[nodiscard]] CardZoneLogic *getZone() const
{
- return zone;
+ return state->getZone();
}
void setZone(CardZoneLogic *_zone);
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
@@ -78,50 +77,50 @@ public:
{
return gridPoint;
}
- [[nodiscard]] Player *getOwner() const
+ [[nodiscard]] PlayerLogic *getOwner() const
{
return owner;
}
- void setOwner(Player *_owner)
+ void setOwner(PlayerLogic *_owner)
{
owner = _owner;
}
[[nodiscard]] bool getAttacking() const
{
- return attacking;
+ return state->getAttacking();
}
void setAttacking(bool _attacking);
[[nodiscard]] const QMap &getCounters() const
{
- return counters;
+ return state->getCounters();
}
void setCounter(int _id, int _value);
[[nodiscard]] QString getAnnotation() const
{
- return annotation;
+ return state->getAnnotation();
}
void setAnnotation(const QString &_annotation);
[[nodiscard]] bool getDoesntUntap() const
{
- return doesntUntap;
+ return state->getDoesntUntap();
}
void setDoesntUntap(bool _doesntUntap);
[[nodiscard]] QString getPT() const
{
- return pt;
+ return state->getPT();
}
void setPT(const QString &_pt);
[[nodiscard]] bool getDestroyOnZoneChange() const
{
- return destroyOnZoneChange;
+ return state->getDestroyOnZoneChange();
}
void setDestroyOnZoneChange(bool _destroy)
{
- destroyOnZoneChange = _destroy;
+ state->setDestroyOnZoneChange(_destroy);
}
[[nodiscard]] CardItem *getAttachedTo() const
{
- return attachedTo;
+ return state->getAttachedTo();
}
void setAttachedTo(CardItem *_attachedTo);
void addAttachedCard(CardItem *card)
diff --git a/cockatrice/src/game/board/card_list.h b/cockatrice/src/game/board/card_list.h
index 07be33b32..85a6848b7 100644
--- a/cockatrice/src/game/board/card_list.h
+++ b/cockatrice/src/game/board/card_list.h
@@ -1,8 +1,8 @@
/**
* @file card_list.h
* @ingroup GameLogicCards
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef CARDLIST_H
#define CARDLIST_H
diff --git a/cockatrice/src/game/board/card_state.cpp b/cockatrice/src/game/board/card_state.cpp
new file mode 100644
index 000000000..4319400d7
--- /dev/null
+++ b/cockatrice/src/game/board/card_state.cpp
@@ -0,0 +1,111 @@
+#include "card_state.h"
+
+void CardState::resetState(bool keepAnnotations)
+{
+ attacking = false;
+ counters.clear();
+ pt.clear();
+ if (!keepAnnotations) {
+ annotation.clear();
+ }
+ attachedTo = nullptr;
+}
+
+void CardState::setZone(CardZoneLogic *_zone)
+{
+ if (zone == _zone) {
+ return;
+ }
+
+ zone = _zone;
+ emit zoneChanged(this, zone);
+ emit stateChanged();
+}
+
+void CardState::setAttacking(bool _attacking)
+{
+ if (attacking == _attacking) {
+ return;
+ }
+ attacking = _attacking;
+ emit attackingChanged(_attacking);
+ emit stateChanged();
+}
+
+void CardState::insertCounter(int id, int value)
+{
+ counters.insert(id, value);
+
+ emit countersChanged(counters);
+ emit stateChanged();
+}
+
+void CardState::setCounter(int id, int value)
+{
+ if (value) {
+ counters[id] = value;
+ } else {
+ counters.remove(id);
+ }
+
+ emit countersChanged(counters);
+ emit stateChanged();
+}
+
+void CardState::clearCounters()
+{
+ counters.clear();
+ emit countersChanged(counters);
+ emit stateChanged();
+}
+
+void CardState::setAnnotation(const QString &_annotation)
+{
+ if (annotation == _annotation) {
+ return;
+ }
+ annotation = _annotation;
+ emit annotationChanged(annotation);
+ emit stateChanged();
+}
+
+void CardState::setPT(const QString &_pt)
+{
+ if (pt == _pt) {
+ return;
+ }
+ pt = _pt;
+ emit ptChanged(pt);
+ emit stateChanged();
+}
+
+void CardState::setDoesntUntap(bool _doesntUntap)
+{
+ if (doesntUntap == _doesntUntap) {
+ return;
+ }
+ doesntUntap = _doesntUntap;
+ emit doesntUntapChanged(_doesntUntap);
+ emit stateChanged();
+}
+
+void CardState::setDestroyOnZoneChange(bool _destroyOnZoneChange)
+{
+ if (destroyOnZoneChange == _destroyOnZoneChange) {
+ return;
+ }
+
+ destroyOnZoneChange = _destroyOnZoneChange;
+ emit destroyOnZoneChangeChanged(_destroyOnZoneChange);
+ emit stateChanged();
+}
+
+void CardState::setAttachedTo(CardItem *_attachedTo)
+{
+ if (attachedTo == _attachedTo) {
+ return;
+ }
+ attachedTo = _attachedTo;
+ emit attachedToChanged(_attachedTo);
+ emit stateChanged();
+}
\ No newline at end of file
diff --git a/cockatrice/src/game/board/card_state.h b/cockatrice/src/game/board/card_state.h
new file mode 100644
index 000000000..0498b1aa2
--- /dev/null
+++ b/cockatrice/src/game/board/card_state.h
@@ -0,0 +1,103 @@
+#ifndef COCKATRICE_CARD_STATE_H
+#define COCKATRICE_CARD_STATE_H
+
+#include
+#include
+
+class CardZoneLogic;
+class CardItem;
+class CardState : public QObject
+{
+ Q_OBJECT
+
+private:
+ bool attacking = false;
+ QMap counters;
+ QString annotation;
+ QString pt;
+ bool doesntUntap = false;
+ bool destroyOnZoneChange = false;
+
+ CardItem *attachedTo = nullptr;
+ CardZoneLogic *zone = nullptr;
+
+signals:
+ void stateChanged();
+
+ void attackingChanged(bool newValue);
+ void countersChanged(const QMap &newCounters);
+ void annotationChanged(const QString &newAnnotation);
+ void ptChanged(const QString &newPt);
+ void doesntUntapChanged(bool newValue);
+ void destroyOnZoneChangeChanged(bool newValue);
+ void attachedToChanged(CardItem *newAttachedTo);
+ void zoneChanged(CardState *changedCard, CardZoneLogic *newZone);
+
+public:
+ explicit CardState(QObject *parent, CardZoneLogic *_zone) : QObject(parent), zone(_zone)
+ {
+ }
+
+ void resetState(bool keepAnnotations);
+
+ CardZoneLogic *getZone() const
+ {
+ return zone;
+ }
+
+ void setZone(CardZoneLogic *_zone);
+
+ bool getAttacking() const
+ {
+ return attacking;
+ }
+ void setAttacking(bool _attacking);
+
+ const QMap &getCounters() const
+ {
+ return counters;
+ }
+
+ void insertCounter(int id, int value);
+
+ void setCounter(int id, int value);
+
+ void clearCounters();
+
+ QString getAnnotation() const
+ {
+ return annotation;
+ }
+
+ void setAnnotation(const QString &_annotation);
+
+ QString getPT() const
+ {
+ return pt;
+ }
+
+ void setPT(const QString &_pt);
+
+ bool getDoesntUntap() const
+ {
+ return doesntUntap;
+ }
+
+ void setDoesntUntap(bool _doesntUntap);
+
+ bool getDestroyOnZoneChange() const
+ {
+ return destroyOnZoneChange;
+ }
+
+ void setDestroyOnZoneChange(bool _destroyOnZoneChange);
+
+ CardItem *getAttachedTo() const
+ {
+ return attachedTo;
+ }
+
+ void setAttachedTo(CardItem *_attachedTo);
+};
+
+#endif // COCKATRICE_CARD_STATE_H
diff --git a/cockatrice/src/game/board/counter_general.cpp b/cockatrice/src/game/board/counter_general.cpp
index d68486a1b..5147ede6b 100644
--- a/cockatrice/src/game/board/counter_general.cpp
+++ b/cockatrice/src/game/board/counter_general.cpp
@@ -5,15 +5,8 @@
#include
-GeneralCounter::GeneralCounter(Player *_player,
- int _id,
- const QString &_name,
- const QColor &_color,
- int _radius,
- int _value,
- bool useNameForShortcut,
- QGraphicsItem *parent)
- : AbstractCounter(_player, _id, _name, true, _value, useNameForShortcut, parent), color(_color), radius(_radius)
+GeneralCounter::GeneralCounter(CounterState *state, PlayerLogic *player, bool useNameForShortcut, QGraphicsItem *parent)
+ : AbstractCounter(state, player, true, useNameForShortcut, parent)
{
setCacheMode(DeviceCoordinateCache);
}
diff --git a/cockatrice/src/game/board/counter_general.h b/cockatrice/src/game/board/counter_general.h
index 3db1d7bb4..0a2e882ce 100644
--- a/cockatrice/src/game/board/counter_general.h
+++ b/cockatrice/src/game/board/counter_general.h
@@ -1,8 +1,8 @@
/**
* @file counter_general.h
* @ingroup GameGraphicsPlayers
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef COUNTER_GENERAL_H
#define COUNTER_GENERAL_H
@@ -12,17 +12,10 @@
class GeneralCounter : public AbstractCounter
{
Q_OBJECT
-private:
- QColor color;
- int radius;
public:
- GeneralCounter(Player *_player,
- int _id,
- const QString &_name,
- const QColor &_color,
- int _radius,
- int _value,
+ GeneralCounter(CounterState *state,
+ PlayerLogic *player,
bool useNameForShortcut = false,
QGraphicsItem *parent = nullptr);
QRectF boundingRect() const override;
diff --git a/cockatrice/src/game/board/counter_state.cpp b/cockatrice/src/game/board/counter_state.cpp
new file mode 100644
index 000000000..6da18b662
--- /dev/null
+++ b/cockatrice/src/game/board/counter_state.cpp
@@ -0,0 +1,24 @@
+#include "counter_state.h"
+
+#include
+
+CounterState::CounterState(int id, const QString &name, const QColor &color, int radius, int value, QObject *parent)
+ : QObject(parent), id(id), name(name), color(color), radius(radius), value(value)
+{
+}
+
+CounterState *CounterState::fromProto(const ServerInfo_Counter &counter, QObject *parent)
+{
+ return new CounterState(counter.id(), QString::fromStdString(counter.name()),
+ convertColorToQColor(counter.counter_color()), counter.radius(), counter.count(), parent);
+}
+
+void CounterState::setValue(int newValue)
+{
+ if (newValue == value) {
+ return;
+ }
+ int old = value;
+ value = newValue;
+ emit valueChanged(old, newValue);
+}
\ No newline at end of file
diff --git a/cockatrice/src/game/board/counter_state.h b/cockatrice/src/game/board/counter_state.h
new file mode 100644
index 000000000..0f2f16b55
--- /dev/null
+++ b/cockatrice/src/game/board/counter_state.h
@@ -0,0 +1,51 @@
+#ifndef COCKATRICE_COUNTER_STATE_H
+#define COCKATRICE_COUNTER_STATE_H
+
+#include
+#include
+#include
+#include
+
+class CounterState : public QObject
+{
+ Q_OBJECT
+public:
+ CounterState(int id, const QString &name, const QColor &color, int radius, int value, QObject *parent = nullptr);
+
+ static CounterState *fromProto(const ServerInfo_Counter &counter, QObject *parent = nullptr);
+
+ int getId() const
+ {
+ return id;
+ }
+ QString getName() const
+ {
+ return name;
+ }
+ QColor getColor() const
+ {
+ return color;
+ }
+ int getRadius() const
+ {
+ return radius;
+ }
+ int getValue() const
+ {
+ return value;
+ }
+
+ void setValue(int newValue);
+
+signals:
+ void valueChanged(int oldValue, int newValue);
+
+private:
+ int id;
+ QString name;
+ QColor color;
+ int radius;
+ int value;
+};
+
+#endif // COCKATRICE_COUNTER_STATE_H
diff --git a/cockatrice/src/game/board/translate_counter_name.h b/cockatrice/src/game/board/translate_counter_name.h
index fdb277c11..ba3a94fa5 100644
--- a/cockatrice/src/game/board/translate_counter_name.h
+++ b/cockatrice/src/game/board/translate_counter_name.h
@@ -1,8 +1,8 @@
/**
* @file translate_counter_name.h
* @ingroup GameGraphicsPlayers
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef TRANSLATECOUNTERNAME_H
#define TRANSLATECOUNTERNAME_H
diff --git a/cockatrice/src/game/card_dimensions.h b/cockatrice/src/game/card_dimensions.h
index 255d0bc04..c59a01b48 100644
--- a/cockatrice/src/game/card_dimensions.h
+++ b/cockatrice/src/game/card_dimensions.h
@@ -12,16 +12,16 @@
*/
namespace CardDimensions
{
-/// Card width in pixels
+/** @brief Card width in pixels. */
constexpr int WIDTH = 72;
-/// Card height in pixels
+/** @brief Card height in pixels. */
constexpr int HEIGHT = 102;
-/// Pre-converted for floating-point contexts (Z-value calculations)
+/** @brief Pre-converted for floating-point contexts (Z-value calculations). */
constexpr qreal WIDTH_F = static_cast(WIDTH);
constexpr qreal HEIGHT_F = static_cast(HEIGHT);
-/// Half-dimensions for centering and rotation transforms
+/** @brief Half-dimensions for centering and rotation transforms. */
constexpr qreal WIDTH_HALF_F = WIDTH_F / 2;
constexpr qreal HEIGHT_HALF_F = HEIGHT_F / 2;
} // namespace CardDimensions
diff --git a/cockatrice/src/game/deckview/deck_view.cpp b/cockatrice/src/game/deckview/deck_view.cpp
index 620dfaa5f..ced02c8db 100644
--- a/cockatrice/src/game/deckview/deck_view.cpp
+++ b/cockatrice/src/game/deckview/deck_view.cpp
@@ -24,17 +24,21 @@ void DeckViewCardDragItem::updatePosition(const QPointF &cursorScenePos)
QList colliding = scene()->items(cursorScenePos);
DeckViewCardContainer *cursorZone = 0;
- for (int i = colliding.size() - 1; i >= 0; i--)
- if ((cursorZone = qgraphicsitem_cast(colliding.at(i))))
+ for (int i = colliding.size() - 1; i >= 0; i--) {
+ if ((cursorZone = qgraphicsitem_cast(colliding.at(i)))) {
break;
- if (!cursorZone)
+ }
+ }
+ if (!cursorZone) {
return;
+ }
currentZone = cursorZone;
QPointF newPos = cursorScenePos;
if (newPos != pos()) {
- for (int i = 0; i < childDrags.size(); i++)
+ for (int i = 0; i < childDrags.size(); i++) {
childDrags[i]->setPos(newPos + childDrags[i]->getHotSpot());
+ }
setPos(newPos);
}
}
@@ -104,11 +108,13 @@ void DeckViewCard::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
void DeckViewCard::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() <
- 2 * QApplication::startDragDistance())
+ 2 * QApplication::startDragDistance()) {
return;
+ }
- if (static_cast(scene())->getLocked())
+ if (static_cast(scene())->getLocked()) {
return;
+ }
delete dragItem;
dragItem = new DeckViewCardDragItem(this, event->pos());
@@ -120,8 +126,9 @@ void DeckViewCard::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
int j = 0;
for (int i = 0; i < sel.size(); i++) {
auto *c = static_cast(sel.at(i));
- if (c == this)
+ if (c == this) {
continue;
+ }
++j;
auto childPos = QPointF(j * CardDimensions::WIDTH_HALF_F, 0);
auto *drag = new DeckViewCardDragItem(c, childPos, dragItem);
@@ -133,8 +140,9 @@ void DeckViewCard::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
void DeckView::mouseDoubleClickEvent(QMouseEvent *event)
{
- if (static_cast(scene())->getLocked())
+ if (static_cast(scene())->getLocked()) {
return;
+ }
if (event->button() == Qt::LeftButton) {
QList result;
@@ -147,12 +155,13 @@ void DeckView::mouseDoubleClickEvent(QMouseEvent *event)
m.set_card_name(c->getName().toStdString());
m.set_start_zone(zone->getName().toStdString());
- if (zone->getName() == DECK_ZONE_MAIN)
+ if (zone->getName() == DECK_ZONE_MAIN) {
m.set_target_zone(DECK_ZONE_SIDE);
- else if (zone->getName() == DECK_ZONE_SIDE)
+ } else if (zone->getName() == DECK_ZONE_SIDE) {
m.set_target_zone(DECK_ZONE_MAIN);
- else // Trying to move from another zone
+ } else { // Trying to move from another zone
m.set_target_zone(zone->getName().toStdString());
+ }
result.append(m);
}
@@ -232,8 +241,9 @@ QList> DeckViewCardContainer::getRowsAndCols() const
{
QList> result;
QList cardTypeList = cardsByType.uniqueKeys();
- for (int i = 0; i < cardTypeList.size(); ++i)
+ for (int i = 0; i < cardTypeList.size(); ++i) {
result.append(QPair(1, cardsByType.count(cardTypeList[i])));
+ }
return result;
}
@@ -262,8 +272,9 @@ QSizeF DeckViewCardContainer::calculateBoundingRect(const QList>
// Calculate space needed for cards
for (int i = 0; i < rowsAndCols.size(); ++i) {
totalHeight += CardDimensions::HEIGHT_F * rowsAndCols[i].first + paddingY;
- if (CardDimensions::WIDTH_F * rowsAndCols[i].second > totalWidth)
+ if (CardDimensions::WIDTH_F * rowsAndCols[i].second > totalWidth) {
totalWidth = CardDimensions::WIDTH_F * rowsAndCols[i].second;
+ }
}
return QSizeF(getCardTypeTextWidth() + totalWidth, totalHeight + separatorY + paddingY);
@@ -271,8 +282,9 @@ QSizeF DeckViewCardContainer::calculateBoundingRect(const QList>
bool DeckViewCardContainer::sortCardsByName(DeckViewCard *c1, DeckViewCard *c2)
{
- if (c1 && c2)
+ if (c1 && c2) {
return c1->getName() < c2->getName();
+ }
return false;
}
@@ -322,15 +334,17 @@ DeckViewScene::~DeckViewScene()
void DeckViewScene::clearContents()
{
QMapIterator i(cardContainers);
- while (i.hasNext())
+ while (i.hasNext()) {
delete i.next().value();
+ }
cardContainers.clear();
}
void DeckViewScene::setDeck(const DeckList &_deck)
{
- if (deck)
+ if (deck) {
delete deck;
+ }
deck = new DeckList(_deck.writeToString_Native());
rebuildTree();
@@ -342,8 +356,9 @@ void DeckViewScene::rebuildTree()
{
clearContents();
- if (!deck)
+ if (!deck) {
return;
+ }
for (auto *currentZone : deck->getZoneNodes()) {
DeckViewCardContainer *container = cardContainers.value(currentZone->getName(), 0);
@@ -355,8 +370,9 @@ void DeckViewScene::rebuildTree()
for (int j = 0; j < currentZone->size(); j++) {
auto *currentCard = dynamic_cast(currentZone->at(j));
- if (!currentCard)
+ if (!currentCard) {
continue;
+ }
for (int k = 0; k < currentCard->getNumber(); ++k) {
auto *newCard = new DeckViewCard(container, currentCard->toCardRef(), currentZone->getName());
@@ -373,18 +389,21 @@ void DeckViewScene::applySideboardPlan(const QList &plan)
const MoveCard_ToZone &m = plan[i];
DeckViewCardContainer *start = cardContainers.value(QString::fromStdString(m.start_zone()));
DeckViewCardContainer *target = cardContainers.value(QString::fromStdString(m.target_zone()));
- if (!start || !target)
+ if (!start || !target) {
continue;
+ }
DeckViewCard *card = 0;
const QList &cardList = start->getCards();
- for (int j = 0; j < cardList.size(); ++j)
+ for (int j = 0; j < cardList.size(); ++j) {
if (cardList[j]->getName() == QString::fromStdString(m.card_name())) {
card = cardList[j];
break;
}
- if (!card)
+ }
+ if (!card) {
continue;
+ }
start->removeCard(card);
target->addCard(card);
@@ -405,8 +424,9 @@ void DeckViewScene::rearrangeItems()
rowsAndColsList.append(rowsAndCols);
cardCountList.append(QList());
- for (int j = 0; j < rowsAndCols.size(); ++j)
+ for (int j = 0; j < rowsAndCols.size(); ++j) {
cardCountList[i].append(rowsAndCols[j].second);
+ }
}
qreal totalHeight, totalWidth;
@@ -417,23 +437,27 @@ void DeckViewScene::rearrangeItems()
for (int i = 0; i < contList.size(); ++i) {
QSizeF contSize = contList[i]->calculateBoundingRect(rowsAndColsList[i]);
totalHeight += contSize.height() + spacing;
- if (contSize.width() > totalWidth)
+ if (contSize.width() > totalWidth) {
totalWidth = contSize.width();
+ }
}
// We're done when the aspect ratio shifts from too high to too low.
- if (totalWidth / totalHeight <= optimalAspectRatio)
+ if (totalWidth / totalHeight <= optimalAspectRatio) {
break;
+ }
// Find category with highest column count
int maxIndex1 = -1, maxIndex2 = -1, maxCols = 0;
- for (int i = 0; i < rowsAndColsList.size(); ++i)
- for (int j = 0; j < rowsAndColsList[i].size(); ++j)
+ for (int i = 0; i < rowsAndColsList.size(); ++i) {
+ for (int j = 0; j < rowsAndColsList[i].size(); ++j) {
if (rowsAndColsList[i][j].second > maxCols) {
maxIndex1 = i;
maxIndex2 = j;
maxCols = rowsAndColsList[i][j].second;
}
+ }
+ }
// Add row to category
const int maxRows = rowsAndColsList[maxIndex1][maxIndex2].first;
@@ -451,8 +475,9 @@ void DeckViewScene::rearrangeItems()
}
totalWidth = totalHeight * optimalAspectRatio;
- for (int i = 0; i < contList.size(); ++i)
+ for (int i = 0; i < contList.size(); ++i) {
contList[i]->setWidth(totalWidth);
+ }
setSceneRect(QRectF(0, 0, totalWidth, totalHeight));
}
@@ -470,7 +495,7 @@ QList DeckViewScene::getSideboardPlan() const
while (containerIterator.hasNext()) {
DeckViewCardContainer *cont = containerIterator.next().value();
const QList cardList = cont->getCards();
- for (int i = 0; i < cardList.size(); ++i)
+ for (int i = 0; i < cardList.size(); ++i) {
if (cardList[i]->getOriginZone() != cont->getName()) {
MoveCard_ToZone m;
m.set_card_name(cardList[i]->getName().toStdString());
@@ -478,6 +503,7 @@ QList DeckViewScene::getSideboardPlan() const
m.set_target_zone(cont->getName().toStdString());
result.append(m);
}
+ }
}
return result;
}
diff --git a/cockatrice/src/game/deckview/deck_view.h b/cockatrice/src/game/deckview/deck_view.h
index 5abc558bd..f996fd4da 100644
--- a/cockatrice/src/game/deckview/deck_view.h
+++ b/cockatrice/src/game/deckview/deck_view.h
@@ -1,8 +1,8 @@
/**
* @file deck_view.h
* @ingroup Lobby
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef DECKVIEW_H
#define DECKVIEW_H
diff --git a/cockatrice/src/game/deckview/deck_view_container.cpp b/cockatrice/src/game/deckview/deck_view_container.cpp
index 44b2be6d1..cbd6c2bad 100644
--- a/cockatrice/src/game/deckview/deck_view_container.cpp
+++ b/cockatrice/src/game/deckview/deck_view_container.cpp
@@ -251,8 +251,9 @@ void DeckViewContainer::unloadDeck()
void DeckViewContainer::loadLocalDeck()
{
DlgLoadDeck dialog(this);
- if (!dialog.exec())
+ if (!dialog.exec()) {
return;
+ }
loadDeckFromFile(dialog.selectedFiles().at(0));
}
@@ -364,8 +365,9 @@ void DeckViewContainer::sideboardPlanChanged()
{
Command_SetSideboardPlan cmd;
const QList &newPlan = deckView->getSideboardPlan();
- for (const auto &i : newPlan)
+ for (const auto &i : newPlan) {
cmd.add_move_list()->CopyFrom(i);
+ }
parentGame->getGame()->getGameEventHandler()->sendGameCommand(cmd, playerId);
}
@@ -404,8 +406,9 @@ void DeckViewContainer::setSideboardLocked(bool locked)
{
sideboardLockButton->setState(!locked);
deckView->setLocked(readyStartButton->getState() || !sideboardLockButton->getState());
- if (locked)
+ if (locked) {
deckView->resetSideboardPlan();
+ }
}
void DeckViewContainer::setDeck(const DeckList &deck)
diff --git a/cockatrice/src/game/deckview/deck_view_container.h b/cockatrice/src/game/deckview/deck_view_container.h
index 6d685cd79..ec024bace 100644
--- a/cockatrice/src/game/deckview/deck_view_container.h
+++ b/cockatrice/src/game/deckview/deck_view_container.h
@@ -1,8 +1,8 @@
/**
* @file deck_view_container.h
* @ingroup Lobby
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef DECK_VIEW_CONTAINER_H
#define DECK_VIEW_CONTAINER_H
diff --git a/cockatrice/src/game/deckview/tabbed_deck_view_container.h b/cockatrice/src/game/deckview/tabbed_deck_view_container.h
index c34eef1ef..7cfa8c9aa 100644
--- a/cockatrice/src/game/deckview/tabbed_deck_view_container.h
+++ b/cockatrice/src/game/deckview/tabbed_deck_view_container.h
@@ -1,8 +1,8 @@
/**
* @file tabbed_deck_view_container.h
* @ingroup Lobby
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef TABBED_DECK_VIEW_CONTAINER_H
#define TABBED_DECK_VIEW_CONTAINER_H
diff --git a/cockatrice/src/game/dialogs/dlg_create_token.cpp b/cockatrice/src/game/dialogs/dlg_create_token.cpp
index df264f065..11c24b72e 100644
--- a/cockatrice/src/game/dialogs/dlg_create_token.cpp
+++ b/cockatrice/src/game/dialogs/dlg_create_token.cpp
@@ -101,8 +101,9 @@ DlgCreateToken::DlgCreateToken(const QStringList &_predefinedTokens, QWidget *pa
chooseTokenView->resizeColumnToContents(0);
chooseTokenView->setWordWrap(true);
- if (!deckHeaderState.isNull())
+ if (!deckHeaderState.isNull()) {
chooseTokenView->header()->restoreState(deckHeaderState);
+ }
chooseTokenView->header()->setStretchLastSection(false);
chooseTokenView->header()->hideSection(1); // Sets
@@ -185,8 +186,9 @@ void DlgCreateToken::tokenSelectionChanged(const QModelIndex ¤t, const QMo
const QChar cardColor = cardInfo->getColorChar();
colorEdit->setCurrentIndex(colorEdit->findData(cardColor, Qt::UserRole, Qt::MatchFixedString));
ptEdit->setText(cardInfo->getPowTough());
- if (SettingsCache::instance().getAnnotateTokens())
+ if (SettingsCache::instance().getAnnotateTokens()) {
annotationEdit->setText(cardInfo->getText());
+ }
} else {
nameEdit->setText("");
colorEdit->setCurrentIndex(colorEdit->findData(QString(), Qt::UserRole, Qt::MatchFixedString));
diff --git a/cockatrice/src/game/dialogs/dlg_create_token.h b/cockatrice/src/game/dialogs/dlg_create_token.h
index 9a18f1a57..281e161fc 100644
--- a/cockatrice/src/game/dialogs/dlg_create_token.h
+++ b/cockatrice/src/game/dialogs/dlg_create_token.h
@@ -1,8 +1,8 @@
/**
* @file dlg_create_token.h
* @ingroup GameDialogs
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef DLG_CREATETOKEN_H
#define DLG_CREATETOKEN_H
diff --git a/cockatrice/src/game/dialogs/dlg_move_top_cards_until.h b/cockatrice/src/game/dialogs/dlg_move_top_cards_until.h
index 20ba11c5c..ac9d41a94 100644
--- a/cockatrice/src/game/dialogs/dlg_move_top_cards_until.h
+++ b/cockatrice/src/game/dialogs/dlg_move_top_cards_until.h
@@ -1,8 +1,8 @@
/**
* @file dlg_move_top_cards_until.h
* @ingroup GameDialogs
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef DLG_MOVE_TOP_CARDS_UNTIL_H
#define DLG_MOVE_TOP_CARDS_UNTIL_H
diff --git a/cockatrice/src/game/dialogs/dlg_roll_dice.h b/cockatrice/src/game/dialogs/dlg_roll_dice.h
index 69edd0757..15f7dc1ba 100644
--- a/cockatrice/src/game/dialogs/dlg_roll_dice.h
+++ b/cockatrice/src/game/dialogs/dlg_roll_dice.h
@@ -1,8 +1,8 @@
/**
* @file dlg_roll_dice.h
* @ingroup GameDialogs
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef DLG_ROLL_DICE_H
#define DLG_ROLL_DICE_H
diff --git a/cockatrice/src/game/game.h b/cockatrice/src/game/game.h
index 96ebbae4d..ccdb679df 100644
--- a/cockatrice/src/game/game.h
+++ b/cockatrice/src/game/game.h
@@ -1,8 +1,8 @@
/**
* @file game.h
* @ingroup GameLogic
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef COCKATRICE_GAME_H
#define COCKATRICE_GAME_H
diff --git a/cockatrice/src/game/game_event_handler.cpp b/cockatrice/src/game/game_event_handler.cpp
index 42dd49458..cff80a1ec 100644
--- a/cockatrice/src/game/game_event_handler.cpp
+++ b/cockatrice/src/game/game_event_handler.cpp
@@ -36,8 +36,9 @@ GameEventHandler::GameEventHandler(AbstractGame *_game) : QObject(_game), game(_
void GameEventHandler::sendGameCommand(PendingCommand *pend, int playerId)
{
AbstractClient *client = game->getClientForPlayer(playerId);
- if (!client)
+ if (!client) {
return;
+ }
connect(pend, &PendingCommand::finished, this, &GameEventHandler::commandFinished);
client->sendCommand(pend);
@@ -46,8 +47,9 @@ void GameEventHandler::sendGameCommand(PendingCommand *pend, int playerId)
void GameEventHandler::sendGameCommand(const google::protobuf::Message &command, int playerId)
{
AbstractClient *client = game->getClientForPlayer(playerId);
- if (!client)
+ if (!client) {
return;
+ }
PendingCommand *pend = prepareGameCommand(command);
connect(pend, &PendingCommand::finished, this, &GameEventHandler::commandFinished);
@@ -56,8 +58,9 @@ void GameEventHandler::sendGameCommand(const google::protobuf::Message &command,
void GameEventHandler::commandFinished(const Response &response)
{
- if (response.response_code() == Response::RespChatFlood)
+ if (response.response_code() == Response::RespChatFlood) {
emit gameFlooded();
+ }
}
PendingCommand *GameEventHandler::prepareGameCommand(const ::google::protobuf::Message &cmd)
@@ -96,7 +99,7 @@ void GameEventHandler::processGameEventContainer(const GameEventContainer &cont,
if (cont.has_forced_by_judge()) {
auto id = cont.forced_by_judge();
- Player *judgep = game->getPlayerManager()->getPlayers().value(id, nullptr);
+ PlayerLogic *judgep = game->getPlayerManager()->getPlayers().value(id, nullptr);
if (judgep) {
emit setContextJudgeName(judgep->getPlayerInfo()->getName());
} else if (game->getPlayerManager()->getSpectators().contains(id)) {
@@ -117,9 +120,11 @@ void GameEventHandler::processGameEventContainer(const GameEventContainer &cont,
break;
}
} else {
- if ((game->getGameState()->getClients().size() > 1) && (playerId != -1))
- if (game->getGameState()->getClients().at(playerId) != client)
+ if ((game->getGameState()->getClients().size() > 1) && (playerId != -1)) {
+ if (game->getGameState()->getClients().at(playerId) != client) {
continue;
+ }
+ }
switch (eventType) {
case GameEvent::GAME_STATE_CHANGED:
@@ -155,7 +160,7 @@ void GameEventHandler::processGameEventContainer(const GameEventContainer &cont,
break;
default: {
- Player *player = game->getPlayerManager()->getPlayers().value(playerId, 0);
+ PlayerLogic *player = game->getPlayerManager()->getPlayers().value(playerId, 0);
if (!player) {
qCWarning(GameEventHandlerLog) << "unhandled game event: invalid player id";
break;
@@ -212,7 +217,20 @@ void GameEventHandler::handleArrowDeletion(int arrowId)
{
Command_DeleteArrow cmd;
cmd.set_arrow_id(arrowId);
- sendGameCommand(cmd);
+
+ auto preparedCommand = prepareGameCommand(cmd);
+
+ connect(preparedCommand, &PendingCommand::finished, this,
+ [arrowId, this](const Response &response) { handleArrowDeletionFinished(response, arrowId); });
+
+ sendGameCommand(preparedCommand);
+}
+
+void GameEventHandler::handleArrowDeletionFinished(const Response &response, int arrowId)
+{
+ if (response.response_code() == Response::RespNameNotFound) {
+ emit arrowDeleted(arrowId);
+ }
}
void GameEventHandler::eventSpectatorSay(const Event_GameSay &event,
@@ -256,7 +274,7 @@ void GameEventHandler::eventGameStateChanged(const Event_GameStateChanged &event
emit spectatorJoined(prop);
}
} else {
- Player *player = game->getPlayerManager()->getPlayers().value(playerId, 0);
+ PlayerLogic *player = game->getPlayerManager()->getPlayers().value(playerId, 0);
if (!player) {
player = game->getPlayerManager()->addPlayer(playerId, prop.user_info());
emit playerJoined(prop);
@@ -284,8 +302,9 @@ void GameEventHandler::eventGameStateChanged(const Event_GameStateChanged &event
if (event.game_started() && !game->getGameMetaInfo()->started()) {
game->getGameState()->setResuming(!game->getGameState()->isGameStateKnown());
game->getGameMetaInfo()->setStarted(event.game_started());
- if (game->getGameState()->isGameStateKnown())
+ if (game->getGameState()->isGameStateKnown()) {
emit logGameStart();
+ }
game->getGameState()->setActivePlayer(event.active_player_id());
game->getGameState()->setCurrentPhase(event.active_phase());
} else if (!event.game_started() && game->getGameMetaInfo()->started()) {
@@ -304,9 +323,10 @@ void GameEventHandler::processCardAttachmentsForPlayers(const Event_GameStateCha
const ServerInfo_Player &playerInfo = event.player_list(i);
const ServerInfo_PlayerProperties &prop = playerInfo.properties();
if (!prop.spectator()) {
- Player *player = game->getPlayerManager()->getPlayers().value(prop.player_id(), 0);
- if (!player)
+ PlayerLogic *player = game->getPlayerManager()->getPlayers().value(prop.player_id(), 0);
+ if (!player) {
continue;
+ }
player->processCardAttachment(playerInfo);
}
}
@@ -316,9 +336,10 @@ void GameEventHandler::eventPlayerPropertiesChanged(const Event_PlayerProperties
int eventPlayerId,
const GameEventContext &context)
{
- Player *player = game->getPlayerManager()->getPlayers().value(eventPlayerId, 0);
- if (!player)
+ PlayerLogic *player = game->getPlayerManager()->getPlayers().value(eventPlayerId, 0);
+ if (!player) {
return;
+ }
const ServerInfo_PlayerProperties &prop = event.player_properties();
emit playerPropertiesChanged(prop, eventPlayerId);
@@ -326,8 +347,9 @@ void GameEventHandler::eventPlayerPropertiesChanged(const Event_PlayerProperties
switch (contextType) {
case GameEventContext::READY_START: {
bool ready = prop.ready_start();
- if (player->getPlayerInfo()->getLocal())
+ if (player->getPlayerInfo()->getLocal()) {
emit localPlayerReadyStateChanged(player->getPlayerInfo()->getId(), ready);
+ }
if (ready) {
emit logReadyStart(player);
} else {
@@ -338,9 +360,10 @@ void GameEventHandler::eventPlayerPropertiesChanged(const Event_PlayerProperties
case GameEventContext::CONCEDE: {
player->setConceded(true);
- QMapIterator playerIterator(game->getPlayerManager()->getPlayers());
- while (playerIterator.hasNext())
+ QMapIterator playerIterator(game->getPlayerManager()->getPlayers());
+ while (playerIterator.hasNext()) {
playerIterator.next().value()->updateZones();
+ }
emit logConcede(eventPlayerId);
@@ -349,9 +372,10 @@ void GameEventHandler::eventPlayerPropertiesChanged(const Event_PlayerProperties
case GameEventContext::UNCONCEDE: {
player->setConceded(false);
- QMapIterator playerIterator(game->getPlayerManager()->getPlayers());
- while (playerIterator.hasNext())
+ QMapIterator playerIterator(game->getPlayerManager()->getPlayers());
+ while (playerIterator.hasNext()) {
playerIterator.next().value()->updateZones();
+ }
emit logUnconcede(eventPlayerId);
@@ -389,15 +413,16 @@ void GameEventHandler::eventJoin(const Event_Join &event, int /*eventPlayerId*/,
QString playerName = QString::fromStdString(playerInfo.user_info().name());
emit addPlayerToAutoCompleteList(playerName);
- if (game->getPlayerManager()->getPlayers().contains(playerId))
+ if (game->getPlayerManager()->getPlayers().contains(playerId)) {
return;
+ }
if (playerInfo.spectator()) {
game->getPlayerManager()->addSpectator(playerId, playerInfo);
emit logJoinSpectator(playerName);
emit spectatorJoined(playerInfo);
} else {
- Player *newPlayer = game->getPlayerManager()->addPlayer(playerId, playerInfo.user_info());
+ PlayerLogic *newPlayer = game->getPlayerManager()->addPlayer(playerId, playerInfo.user_info());
emit logJoinPlayer(newPlayer);
emit playerJoined(playerInfo);
}
@@ -425,9 +450,10 @@ QString GameEventHandler::getLeaveReason(Event_Leave::LeaveReason reason)
}
void GameEventHandler::eventLeave(const Event_Leave &event, int eventPlayerId, const GameEventContext & /*context*/)
{
- Player *player = game->getPlayerManager()->getPlayers().value(eventPlayerId, 0);
- if (!player)
+ PlayerLogic *player = game->getPlayerManager()->getPlayers().value(eventPlayerId, 0);
+ if (!player) {
return;
+ }
player->clear();
emit playerLeft(eventPlayerId);
@@ -439,9 +465,10 @@ void GameEventHandler::eventLeave(const Event_Leave &event, int eventPlayerId, c
player->deleteLater();
// Rearrange all remaining zones so that attachment relationship updates take place
- QMapIterator playerIterator(game->getPlayerManager()->getPlayers());
- while (playerIterator.hasNext())
+ QMapIterator playerIterator(game->getPlayerManager()->getPlayers());
+ while (playerIterator.hasNext()) {
playerIterator.next().value()->updateZones();
+ }
emitUserEvent();
}
@@ -460,9 +487,10 @@ void GameEventHandler::eventReverseTurn(const Event_ReverseTurn &event,
int eventPlayerId,
const GameEventContext & /*context*/)
{
- Player *player = game->getPlayerManager()->getPlayers().value(eventPlayerId, 0);
- if (!player)
+ PlayerLogic *player = game->getPlayerManager()->getPlayers().value(eventPlayerId, 0);
+ if (!player) {
return;
+ }
emit logTurnReversed(player, event.reversed());
}
@@ -490,9 +518,10 @@ void GameEventHandler::eventSetActivePlayer(const Event_SetActivePlayer &event,
const GameEventContext & /*context*/)
{
game->getGameState()->setActivePlayer(event.active_player_id());
- Player *player = game->getPlayerManager()->getPlayer(event.active_player_id());
- if (!player)
+ PlayerLogic *player = game->getPlayerManager()->getPlayer(event.active_player_id());
+ if (!player) {
return;
+ }
emit logActivePlayer(player);
emitUserEvent();
}
diff --git a/cockatrice/src/game/game_event_handler.h b/cockatrice/src/game/game_event_handler.h
index 302e7a6ff..bc4812aa4 100644
--- a/cockatrice/src/game/game_event_handler.h
+++ b/cockatrice/src/game/game_event_handler.h
@@ -1,8 +1,8 @@
/**
* @file game_event_handler.h
* @ingroup GameLogic
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef COCKATRICE_GAME_EVENT_HANDLER_H
#define COCKATRICE_GAME_EVENT_HANDLER_H
@@ -38,7 +38,7 @@ class Event_Kicked;
class Event_ReverseTurn;
class AbstractGame;
class PendingCommand;
-class Player;
+class PlayerLogic;
inline Q_LOGGING_CATEGORY(GameEventHandlerLog, "game_event_handler");
@@ -61,6 +61,7 @@ public:
void handleGameLeft();
void handleChatMessageSent(const QString &chatMessage);
void handleArrowDeletion(int arrowId);
+ void handleArrowDeletionFinished(const Response &response, int arrowId);
void eventSpectatorSay(const Event_GameSay &event, int eventPlayerId, const GameEventContext &context);
void eventSpectatorLeave(const Event_Leave &event, int eventPlayerId, const GameEventContext &context);
@@ -95,7 +96,7 @@ public slots:
signals:
void emitUserEvent();
void addPlayerToAutoCompleteList(QString playerName);
- void localPlayerDeckSelected(Player *localPlayer, int playerId, ServerInfo_Player playerInfo);
+ void localPlayerDeckSelected(PlayerLogic *localPlayer, int playerId, ServerInfo_Player playerInfo);
void remotePlayerDeckSelected(QString deckList, int playerId, QString playerName);
void remotePlayersDecksSelected(QVector>> opponentDecks);
void localPlayerSideboardLocked(int playerId, bool sideboardLocked);
@@ -112,21 +113,22 @@ signals:
void containerProcessingStarted(GameEventContext context);
void setContextJudgeName(QString judgeName);
void containerProcessingDone();
+ void arrowDeleted(int arrowId);
void logSpectatorSay(ServerInfo_User userInfo, QString message);
void logSpectatorLeave(QString name, QString reason);
void logGameStart();
- void logReadyStart(Player *player);
- void logNotReadyStart(Player *player);
- void logDeckSelect(Player *player, QString deckHash, int sideboardSize);
- void logSideboardLockSet(Player *player, bool sideboardLocked);
- void logConnectionStateChanged(Player *player, bool connected);
+ void logReadyStart(PlayerLogic *player);
+ void logNotReadyStart(PlayerLogic *player);
+ void logDeckSelect(PlayerLogic *player, QString deckHash, int sideboardSize);
+ void logSideboardLockSet(PlayerLogic *player, bool sideboardLocked);
+ void logConnectionStateChanged(PlayerLogic *player, bool connected);
void logJoinSpectator(QString spectatorName);
- void logJoinPlayer(Player *player);
- void logLeave(Player *player, QString reason);
+ void logJoinPlayer(PlayerLogic *player);
+ void logLeave(PlayerLogic *player, QString reason);
void logKicked();
- void logTurnReversed(Player *player, bool reversed);
+ void logTurnReversed(PlayerLogic *player, bool reversed);
void logGameClosed();
- void logActivePlayer(Player *activePlayer);
+ void logActivePlayer(PlayerLogic *activePlayer);
void logActivePhaseChanged(int activePhase);
void logConcede(int playerId);
void logUnconcede(int playerId);
diff --git a/cockatrice/src/game/game_meta_info.h b/cockatrice/src/game/game_meta_info.h
index b5f5bfe4f..cdba1605f 100644
--- a/cockatrice/src/game/game_meta_info.h
+++ b/cockatrice/src/game/game_meta_info.h
@@ -1,8 +1,8 @@
/**
* @file game_meta_info.h
* @ingroup GameLogic
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef GAME_META_INFO_H
#define GAME_META_INFO_H
@@ -87,15 +87,17 @@ public:
public slots:
void setStarted(bool s)
{
- if (gameInfo_.started() == s)
+ if (gameInfo_.started() == s) {
return;
+ }
gameInfo_.set_started(s);
emit startedChanged(s);
}
void setSpectatorsOmniscient(bool v)
{
- if (gameInfo_.spectators_omniscient() == v)
+ if (gameInfo_.spectators_omniscient() == v) {
return;
+ }
gameInfo_.set_spectators_omniscient(v);
emit spectatorsOmniscienceChanged(v);
}
diff --git a/cockatrice/src/game/game_scene.cpp b/cockatrice/src/game/game_scene.cpp
index 323adda38..1b4f0d461 100644
--- a/cockatrice/src/game/game_scene.cpp
+++ b/cockatrice/src/game/game_scene.cpp
@@ -1,12 +1,13 @@
#include "game_scene.h"
#include "../client/settings/cache_settings.h"
+#include "../game_graphics/zones/select_zone.h"
+#include "../game_graphics/zones/view_zone.h"
+#include "../game_graphics/zones/view_zone_widget.h"
#include "board/card_item.h"
#include "phases_toolbar.h"
-#include "player/player.h"
#include "player/player_graphics_item.h"
-#include "zones/view_zone.h"
-#include "zones/view_zone_widget.h"
+#include "player/player_logic.h"
#include
#include
@@ -54,8 +55,9 @@ GameScene::~GameScene()
*/
void GameScene::retranslateUi()
{
- for (ZoneViewWidget *view : zoneViews)
+ for (ZoneViewWidget *view : zoneViews) {
view->retranslateUi();
+ }
}
QList GameScene::selectedCards() const
@@ -76,13 +78,30 @@ QList GameScene::selectedCards() const
*
* Connects to the player's sizeChanged signal to recompute layout on resize.
*/
-void GameScene::addPlayer(Player *player)
+void GameScene::addPlayer(PlayerLogic *player)
{
qCInfo(GameScenePlayerAdditionRemovalLog) << "GameScene::addPlayer name=" << player->getPlayerInfo()->getName();
- players << player->getGraphicsItem();
+ playerViews.insert(player->getPlayerInfo()->getId(), player->getGraphicsItem());
addItem(player->getGraphicsItem());
connect(player->getGraphicsItem(), &PlayerGraphicsItem::sizeChanged, this, &GameScene::rearrange);
+
+ connect(player, &PlayerLogic::concededChanged, this, [this](int id, bool conceded) {
+ if (conceded) {
+ clearArrowsForPlayer(id);
+ }
+ rearrange();
+ });
+
+ connect(player, &PlayerLogic::arrowDeleted, this, &GameScene::deleteArrow);
+ connect(player, &PlayerLogic::arrowCreateRequested, this, &GameScene::addArrow);
+ connect(player, &PlayerLogic::arrowDeleteRequested, this, &GameScene::requestArrowDeletion);
+ connect(player, &PlayerLogic::arrowsCleared, this,
+ [this, id = player->getPlayerInfo()->getId()]() { clearArrowsForPlayer(id); });
+
+ connect(player->getPlayerEventHandler(), &PlayerEventHandler::cardZoneChanged, this, &GameScene::onCardZoneChanged);
+
+ rearrange();
}
/**
@@ -91,17 +110,19 @@ void GameScene::addPlayer(Player *player)
*
* Closes any zone views associated with the player and recomputes layout.
*/
-void GameScene::removePlayer(Player *player)
+void GameScene::removePlayer(PlayerLogic *player)
{
qCInfo(GameScenePlayerAdditionRemovalLog) << "GameScene::removePlayer name=" << player->getPlayerInfo()->getName();
+ clearArrowsForPlayer(player->getPlayerInfo()->getId());
+
for (ZoneViewWidget *zone : zoneViews) {
if (zone->getPlayer() == player) {
zone->close();
}
}
- players.removeOne(player->getGraphicsItem());
- removeItem(player->getGraphicsItem());
+ auto *view = playerViews.take(player->getPlayerInfo()->getId());
+ removeItem(view);
rearrange();
}
@@ -176,14 +197,14 @@ void GameScene::processViewSizeChange(const QSize &newSize)
*
* Used to determine rotation and layout order.
*/
-QList GameScene::collectActivePlayers(int &firstPlayerIndex) const
+QList GameScene::collectActivePlayers(int &firstPlayerIndex) const
{
- QList activePlayers;
+ QList activePlayers;
firstPlayerIndex = 0;
bool firstPlayerFound = false;
- for (auto *pgItem : players) {
- Player *p = pgItem->getPlayer();
+ for (auto *pgItem : playerViews.values()) {
+ PlayerLogic *p = pgItem->getPlayer();
if (p && !p->getConceded()) {
activePlayers.append(p);
if (!firstPlayerFound && p->getPlayerInfo()->getLocal()) {
@@ -203,15 +224,17 @@ QList GameScene::collectActivePlayers(int &firstPlayerIndex) const
*
* Applies rotation offset and ensures the list wraps correctly.
*/
-QList GameScene::rotatePlayers(const QList &activePlayers, int firstPlayerIndex) const
+QList GameScene::rotatePlayers(const QList &activePlayers, int firstPlayerIndex) const
{
- QList rotated = activePlayers;
+ QList rotated = activePlayers;
if (!rotated.isEmpty()) {
int totalRotation = firstPlayerIndex + playerRotation;
- while (totalRotation < 0)
+ while (totalRotation < 0) {
totalRotation += rotated.size();
- for (int i = 0; i < totalRotation; ++i)
+ }
+ for (int i = 0; i < totalRotation; ++i) {
rotated.append(rotated.takeFirst());
+ }
}
return rotated;
}
@@ -234,7 +257,7 @@ int GameScene::determineColumnCount(int playerCount)
* - Position players in columns with spacing.
* - Mirror graphics for visual balance.
*/
-QSizeF GameScene::computeSceneSizeAndPlayerLayout(const QList &playersPlaying, int columns)
+QSizeF GameScene::computeSceneSizeAndPlayerLayout(const QList &playersPlaying, int columns)
{
playersByColumn.clear();
@@ -242,7 +265,7 @@ QSizeF GameScene::computeSceneSizeAndPlayerLayout(const QList &players
qreal sceneHeight = 0, sceneWidth = -playerAreaSpacing;
QList columnWidth;
- QListIterator playersIter(playersPlaying);
+ QListIterator playersIter(playersPlaying);
for (int col = 0; col < columns; ++col) {
playersByColumn.append(QList());
columnWidth.append(0);
@@ -250,11 +273,12 @@ QSizeF GameScene::computeSceneSizeAndPlayerLayout(const QList &players
int rowsInColumn = rows - (playersPlaying.size() % columns) * col; // Adjust rows for uneven columns
for (int j = 0; j < rowsInColumn; ++j) {
- Player *player = playersIter.next();
- if (col == 0)
+ PlayerLogic *player = playersIter.next();
+ if (col == 0) {
playersByColumn[col].prepend(player->getGraphicsItem());
- else
+ } else {
playersByColumn[col].append(player->getGraphicsItem());
+ }
auto *pgItem = player->getGraphicsItem();
thisColumnHeight += pgItem->boundingRect().height() + playerAreaSpacing;
@@ -293,8 +317,9 @@ QList GameScene::calculateMinWidthByColumn() const
QList minWidthByColumn;
for (const auto &col : playersByColumn) {
qreal maxWidth = 0;
- for (PlayerGraphicsItem *player : col)
+ for (PlayerGraphicsItem *player : col) {
maxWidth = std::max(maxWidth, player->getMinimumWidth());
+ }
minWidthByColumn.append(maxWidth);
}
return minWidthByColumn;
@@ -342,6 +367,99 @@ void GameScene::resizeColumnsAndPlayers(const QList &minWidthByColumn, qr
}
}
+void GameScene::addArrow(const ArrowData &data)
+{
+ auto *startView = playerViews.value(data.startPlayerId);
+ auto *targetView = playerViews.value(data.targetPlayerId);
+ if (!startView || !targetView) {
+ return;
+ }
+
+ PlayerLogic *startLogic = startView->getPlayer();
+ auto *startZone = startLogic->getZones().value(data.startZone);
+ if (!startZone) {
+ return;
+ }
+
+ CardItem *startCard = startZone->getCard(data.startCardId);
+ if (!startCard) {
+ return;
+ }
+
+ ArrowTarget *targetItem = nullptr;
+ if (data.isPlayerTargeted()) {
+ targetItem = targetView->getPlayerTarget();
+ } else {
+ auto *zone = targetView->getPlayer()->getZones().value(data.targetZone);
+ if (zone) {
+ targetItem = zone->getCard(data.targetCardId);
+ }
+ }
+ if (!targetItem) {
+ return;
+ }
+
+ auto *arrow = new ArrowItem(startView->getPlayer(), data.id, startCard, targetItem, data.color);
+ addItem(arrow);
+ arrowRegistry.insert(data.id, arrow);
+ connect(arrow, &ArrowItem::requestDeletion, this, &GameScene::requestArrowDeletion);
+}
+
+void GameScene::deleteArrow(int arrowId)
+{
+ if (arrowRegistry.contains(arrowId)) {
+ arrowRegistry.take(arrowId)->delArrow();
+ }
+}
+
+void GameScene::clearArrowsForPlayer(int playerId)
+{
+ QList toDelete;
+ for (auto i = arrowRegistry.cbegin(); i != arrowRegistry.cend(); ++i) {
+ auto *arrow = i.value();
+ if (arrow->getPlayer()->getPlayerInfo()->getId() == playerId) {
+ toDelete.append(i.key());
+ }
+ }
+
+ for (int arrowId : toDelete) {
+ arrowRegistry.take(arrowId)->delArrow();
+ }
+}
+
+void GameScene::requestArrowDeletion(int arrowId)
+{
+ if (arrowRegistry.contains(arrowId)) {
+ emit arrowDeletionRequested(arrowId);
+ }
+}
+
+void GameScene::requestClearArrowsForPlayer(int playerId)
+{
+ for (auto *arrow : arrowRegistry.values()) {
+ if (arrow->getPlayer()->getPlayerInfo()->getId() == playerId) {
+ emit requestArrowDeletion(arrow->getId());
+ }
+ }
+}
+
+void GameScene::onCardZoneChanged(CardItem *card, bool sameZone)
+{
+ QList toDelete;
+ for (auto *arrow : arrowRegistry.values()) {
+ if (arrow->getStartItem() == card || arrow->getTargetItem() == card) {
+ if (sameZone) {
+ arrow->updatePath();
+ } else {
+ toDelete.append(arrow);
+ }
+ }
+ }
+ for (auto *arrow : toDelete) {
+ deleteArrow(arrow->getId());
+ }
+}
+
// ---------- Hover Handling ----------
void GameScene::updateHover(const QPointF &scenePos)
@@ -355,18 +473,38 @@ void GameScene::updateHover(const QPointF &scenePos)
void GameScene::updateHoveredCard(CardItem *newCard)
{
- if (hoveredCard && (newCard != hoveredCard))
- hoveredCard->setHovered(false);
- if (newCard && (newCard != hoveredCard))
- newCard->setHovered(true);
+ if (hoveredCard && (newCard != hoveredCard)) {
+ endCardHover(hoveredCard);
+ }
+ if (newCard && (newCard != hoveredCard)) {
+ beginCardHover(newCard);
+ }
hoveredCard = newCard;
}
+void GameScene::beginCardHover(CardItem *card)
+{
+ card->setHovered(true);
+ if (auto *zone = SelectZone::findOwningSelectZone(card)) {
+ zone->escapeClipForHover(card);
+ }
+}
+
+void GameScene::endCardHover(CardItem *card)
+{
+ if (auto *zone = SelectZone::findOwningSelectZone(card)) {
+ zone->restoreClipAfterHover(card);
+ }
+ card->setHovered(false);
+}
+
CardZone *GameScene::findTopmostZone(const QList &items)
{
- for (QGraphicsItem *item : items)
- if (auto *zone = qgraphicsitem_cast(item))
+ for (QGraphicsItem *item : items) {
+ if (auto *zone = qgraphicsitem_cast(item)) {
return zone;
+ }
+ }
return nullptr;
}
@@ -377,14 +515,17 @@ CardItem *GameScene::findTopmostCardInZone(const QList &items,
for (QGraphicsItem *item : items) {
CardItem *card = qgraphicsitem_cast(item);
- if (!card)
+ if (!card) {
continue;
+ }
if (card->getAttachedTo()) {
- if (card->getAttachedTo()->getZone() != zone->getLogic())
+ if (card->getAttachedTo()->getZone() != zone->getLogic()) {
continue;
- } else if (card->getZone() != zone->getLogic())
+ }
+ } else if (card->getZone() != zone->getLogic()) {
continue;
+ }
if (card->getRealZValue() > maxZ) {
maxZ = card->getRealZValue();
@@ -406,7 +547,7 @@ CardItem *GameScene::findTopmostCardInZone(const QList &items,
* If an identical view exists, it is closed. Otherwise, a new ZoneViewWidget is created
* and positioned based on zone type.
*/
-void GameScene::toggleZoneView(Player *player, const QString &zoneName, int numberCards, bool isReversed)
+void GameScene::toggleZoneView(PlayerLogic *player, const QString &zoneName, int numberCards, bool isReversed)
{
for (auto &view : zoneViews) {
ZoneViewZone *temp = view->getZone();
@@ -423,12 +564,13 @@ void GameScene::toggleZoneView(Player *player, const QString &zoneName, int numb
connect(item, &ZoneViewWidget::closePressed, this, &GameScene::removeZoneView);
addItem(item);
- if (zoneName == ZoneNames::GRAVE)
+ if (zoneName == ZoneNames::GRAVE) {
item->setPos(360, 100);
- else if (zoneName == ZoneNames::EXILE)
+ } else if (zoneName == ZoneNames::EXILE) {
item->setPos(380, 120);
- else
+ } else {
item->setPos(340, 80);
+ }
}
/**
@@ -438,7 +580,7 @@ void GameScene::toggleZoneView(Player *player, const QString &zoneName, int numb
* @param cardList List of cards to show.
* @param withWritePermission Whether edits are allowed.
*/
-void GameScene::addRevealedZoneView(Player *player,
+void GameScene::addRevealedZoneView(PlayerLogic *player,
CardZoneLogic *zone,
const QList &cardList,
bool withWritePermission)
@@ -465,8 +607,9 @@ void GameScene::removeZoneView(ZoneViewWidget *item)
*/
void GameScene::clearViews()
{
- while (!zoneViews.isEmpty())
+ while (!zoneViews.isEmpty()) {
zoneViews.first()->close();
+ }
}
/**
@@ -474,8 +617,9 @@ void GameScene::clearViews()
*/
void GameScene::closeMostRecentZoneView()
{
- if (!zoneViews.isEmpty())
+ if (!zoneViews.isEmpty()) {
zoneViews.last()->close();
+ }
}
// ---------- View Transforms ----------
@@ -494,8 +638,11 @@ QTransform GameScene::getViewportTransform() const
bool GameScene::event(QEvent *event)
{
- if (event->type() == QEvent::GraphicsSceneMouseMove)
+ if (event->type() == QEvent::GraphicsSceneMouseMove) {
updateHover(static_cast(event)->scenePos());
+ } else if (event->type() == QEvent::Leave) {
+ updateHoveredCard(nullptr);
+ }
return QGraphicsScene::event(event);
}
@@ -505,25 +652,29 @@ void GameScene::timerEvent(QTimerEvent * /*event*/)
QMutableSetIterator i(cardsToAnimate);
while (i.hasNext()) {
i.next();
- if (!i.value()->animationEvent())
+ if (!i.value()->animationEvent()) {
i.remove();
+ }
}
- if (cardsToAnimate.isEmpty())
+ if (cardsToAnimate.isEmpty()) {
animationTimer->stop();
+ }
}
void GameScene::registerAnimationItem(AbstractCardItem *card)
{
cardsToAnimate.insert(static_cast(card));
- if (!animationTimer->isActive())
+ if (!animationTimer->isActive()) {
animationTimer->start(10, this);
+ }
}
void GameScene::unregisterAnimationItem(AbstractCardItem *card)
{
cardsToAnimate.remove(static_cast(card));
- if (cardsToAnimate.isEmpty())
+ if (cardsToAnimate.isEmpty()) {
animationTimer->stop();
+ }
}
// ---------- Rubber Band ----------
diff --git a/cockatrice/src/game/game_scene.h b/cockatrice/src/game/game_scene.h
index 2ce92b775..1551c8365 100644
--- a/cockatrice/src/game/game_scene.h
+++ b/cockatrice/src/game/game_scene.h
@@ -1,7 +1,9 @@
#ifndef GAMESCENE_H
#define GAMESCENE_H
-#include "zones/logic/card_zone_logic.h"
+#include "board/arrow_data.h"
+#include "board/arrow_item.h"
+#include "zones/card_zone_logic.h"
#include
#include
@@ -12,7 +14,7 @@
inline Q_LOGGING_CATEGORY(GameSceneLog, "game_scene");
inline Q_LOGGING_CATEGORY(GameScenePlayerAdditionRemovalLog, "game_scene.player_addition_removal");
-class Player;
+class PlayerLogic;
class PlayerGraphicsItem;
class ZoneViewWidget;
class CardZone;
@@ -41,8 +43,9 @@ private:
static const int playerAreaSpacing = 5; ///< Space between player areas
PhasesToolbar *phasesToolbar; ///< Toolbar showing game phases
- QList players; ///< All player graphics items
+ QMap playerViews; ///< ID lookup for player graphics items
QList> playersByColumn; ///< Players organized by column
+ QMap arrowRegistry; ///< ID registry for arrow graphics items
QList zoneViews; ///< Active zone view widgets
QSize viewSize; ///< Current view size
QPointer hoveredCard; ///< Currently hovered card
@@ -56,6 +59,14 @@ private:
*/
void updateHover(const QPointF &scenePos);
+ /**
+ * @brief Activates hover state and escapes the card from its clip container
+ * so hover scaling is visible beyond zone bounds.
+ */
+ void beginCardHover(CardItem *card);
+ /** @brief Deactivates hover state and restores the card to its clip container. */
+ void endCardHover(CardItem *card);
+
public:
/**
* @brief Constructs the GameScene.
@@ -64,26 +75,26 @@ public:
*/
explicit GameScene(PhasesToolbar *_phasesToolbar, QObject *parent = nullptr);
- /** Destructor, cleans up timer and zone views. */
+ /** @brief Destructor, cleans up timer and zone views. */
~GameScene() override;
- /** Updates UI text for all zone views. */
+ /** @brief Updates UI text for all zone views. */
void retranslateUi();
- /** Gets all selected CardItems */
+ /** @brief Gets all selected CardItems. */
QList selectedCards() const;
/**
* @brief Adds a player to the scene and stores their graphics item.
* @param player Player to add.
*/
- void addPlayer(Player *player);
+ void addPlayer(PlayerLogic *player);
/**
* @brief Removes a player from the scene.
* @param player Player to remove.
*/
- void removePlayer(Player *player);
+ void removePlayer(PlayerLogic *player);
/**
* @brief Adjusts the global rotation offset for player layout.
@@ -91,7 +102,7 @@ public:
*/
void adjustPlayerRotation(int rotationAdjustment);
- /** Recomputes the layout of players and the scene size. */
+ /** @brief Recomputes the layout of players and the scene size. */
void rearrange();
/**
@@ -105,7 +116,7 @@ public:
* @param firstPlayerIndex Output index of first local player.
* @return List of active players.
*/
- QList collectActivePlayers(int &firstPlayerIndex) const;
+ QList collectActivePlayers(int &firstPlayerIndex) const;
/**
* @brief Rotates the list of players for layout.
@@ -113,7 +124,7 @@ public:
* @param firstPlayerIndex Index of first local player.
* @return Rotated list.
*/
- QList rotatePlayers(const QList &players, int firstPlayerIndex) const;
+ QList rotatePlayers(const QList &players, int firstPlayerIndex) const;
/**
* @brief Determines the number of columns to display players in.
@@ -128,7 +139,7 @@ public:
* @param columns Number of columns to split into.
* @return Calculated scene size.
*/
- QSizeF computeSceneSizeAndPlayerLayout(const QList &playersPlaying, int columns);
+ QSizeF computeSceneSizeAndPlayerLayout(const QList &playersPlaying, int columns);
/**
* @brief Computes the minimum width for each column based on player minimum widths.
@@ -151,56 +162,68 @@ public:
*/
void resizeColumnsAndPlayers(const QList &minWidthByColumn, qreal newWidth);
- /** Finds the topmost card zone under the cursor. */
+ /** @brief Finds the topmost card zone under the cursor. */
static CardZone *findTopmostZone(const QList &items);
- /** Finds the topmost card in a given zone, considering attachments and Z-order. */
+ /** @brief Finds the topmost card in a given zone, considering attachments and Z-order. */
static CardItem *findTopmostCardInZone(const QList &items, CardZone *zone);
- /** Updates hovered card highlighting. */
+ /** @brief Updates hovered card highlighting. */
void updateHoveredCard(CardItem *newCard);
- /** Registers a card for animation updates. */
+ /** @brief Registers a card for animation updates. */
void registerAnimationItem(AbstractCardItem *card);
- /** Unregisters a card from animation updates. */
+ /** @brief Unregisters a card from animation updates. */
void unregisterAnimationItem(AbstractCardItem *card);
void startRubberBand(const QPointF &selectionOrigin);
void resizeRubberBand(const QPointF &cursorPoint, int selectedCount);
void stopRubberBand();
public slots:
- /** Toggles a zone view for a player. */
- void toggleZoneView(Player *player, const QString &zoneName, int numberCards, bool isReversed = false);
+ /** @brief Toggles a zone view for a player. */
+ void toggleZoneView(PlayerLogic *player, const QString &zoneName, int numberCards, bool isReversed = false);
- /** Adds a revealed zone view (for shown cards). */
- void addRevealedZoneView(Player *player,
+ /** @brief Adds a revealed zone view (for shown cards). */
+ void addRevealedZoneView(PlayerLogic *player,
CardZoneLogic *zone,
const QList &cardList,
bool withWritePermission);
- /** Removes a zone view widget from the scene. */
+ /** @brief Removes a zone view widget from the scene. */
void removeZoneView(ZoneViewWidget *item);
- /** Closes all zone views. */
+ /** @brief Closes all zone views. */
void clearViews();
- /** Closes the most recently added zone view. */
+ /** @brief Closes the most recently added zone view. */
void closeMostRecentZoneView();
QTransform getViewTransform() const;
QTransform getViewportTransform() const;
+ /// Directly modifies the scene
+ void addArrow(const ArrowData &data);
+ void deleteArrow(int arrowId);
+ void clearArrowsForPlayer(int playerId);
+
+ /// Queues up arrow deletion but doesn't directly modify the scene
+ void requestArrowDeletion(int arrowId);
+ void requestClearArrowsForPlayer(int playerId);
+
+ void onCardZoneChanged(CardItem *card, bool sameZone);
+
protected:
- /** Handles hover updates. */
+ /** @brief Handles hover updates. */
bool event(QEvent *event) override;
- /** Handles animation timer updates. */
+ /** @brief Handles animation timer updates. */
void timerEvent(QTimerEvent *event) override;
signals:
void sigStartRubberBand(const QPointF &selectionOrigin);
void sigResizeRubberBand(const QPointF &cursorPoint, int selectedCount);
void sigStopRubberBand();
+ void arrowDeletionRequested(int arrowId);
};
#endif
diff --git a/cockatrice/src/game/game_state.h b/cockatrice/src/game/game_state.h
index 54f6d9276..5a57d4321 100644
--- a/cockatrice/src/game/game_state.h
+++ b/cockatrice/src/game/game_state.h
@@ -1,8 +1,8 @@
/**
* @file game_state.h
* @ingroup GameLogic
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef COCKATRICE_GAME_STATE_H
#define COCKATRICE_GAME_STATE_H
diff --git a/cockatrice/src/game/game_view.cpp b/cockatrice/src/game/game_view.cpp
index ce53828a7..4ba41cffb 100644
--- a/cockatrice/src/game/game_view.cpp
+++ b/cockatrice/src/game/game_view.cpp
@@ -75,8 +75,9 @@ void GameView::resizeEvent(QResizeEvent *event)
QGraphicsView::resizeEvent(event);
GameScene *s = dynamic_cast(scene());
- if (s)
+ if (s) {
s->processViewSizeChange(event->size());
+ }
updateSceneRect(scene()->sceneRect());
updateTotalSelectionCount(event->size());
@@ -89,8 +90,9 @@ void GameView::updateSceneRect(const QRectF &rect)
void GameView::startRubberBand(const QPointF &_selectionOrigin)
{
- if (!rubberBand)
+ if (!rubberBand) {
return;
+ }
selectionOrigin = _selectionOrigin;
rubberBand->setGeometry(QRect(mapFromScene(selectionOrigin), QSize(0, 0)));
@@ -99,8 +101,9 @@ void GameView::startRubberBand(const QPointF &_selectionOrigin)
void GameView::resizeRubberBand(const QPointF &cursorPoint, int selectedCount)
{
- if (!rubberBand)
+ if (!rubberBand) {
return;
+ }
constexpr int kLabelPaddingInPixels = 4;
@@ -145,8 +148,9 @@ void GameView::resizeRubberBand(const QPointF &cursorPoint, int selectedCount)
void GameView::stopRubberBand()
{
- if (!rubberBand)
+ if (!rubberBand) {
return;
+ }
rubberBand->hide();
dragCountLabel->hide();
diff --git a/cockatrice/src/game/game_view.h b/cockatrice/src/game/game_view.h
index a77ab9257..15abad9af 100644
--- a/cockatrice/src/game/game_view.h
+++ b/cockatrice/src/game/game_view.h
@@ -1,8 +1,8 @@
/**
* @file game_view.h
* @ingroup GameGraphics
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef GAMEVIEW_H
#define GAMEVIEW_H
diff --git a/cockatrice/src/game/hand_counter.cpp b/cockatrice/src/game/hand_counter.cpp
index 35989ff38..a853ae2de 100644
--- a/cockatrice/src/game/hand_counter.cpp
+++ b/cockatrice/src/game/hand_counter.cpp
@@ -1,6 +1,6 @@
#include "hand_counter.h"
-#include "zones/card_zone.h"
+#include "../game_graphics/zones/card_zone.h"
#include
#include
diff --git a/cockatrice/src/game/hand_counter.h b/cockatrice/src/game/hand_counter.h
index 2c0175ecc..41ab3b5b2 100644
--- a/cockatrice/src/game/hand_counter.h
+++ b/cockatrice/src/game/hand_counter.h
@@ -1,8 +1,8 @@
/**
* @file hand_counter.h
* @ingroup GameGraphicsPlayers
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef HANDCOUNTER_H
#define HANDCOUNTER_H
diff --git a/cockatrice/src/game/log/message_log_widget.cpp b/cockatrice/src/game/log/message_log_widget.cpp
index 09f6e656b..906f15c2e 100644
--- a/cockatrice/src/game/log/message_log_widget.cpp
+++ b/cockatrice/src/game/log/message_log_widget.cpp
@@ -5,7 +5,7 @@
#include "../board/card_item.h"
#include "../board/translate_counter_name.h"
#include "../phase.h"
-#include "../player/player.h"
+#include "../player/player_logic.h"
#include <../../client/settings/card_counter_settings.h>
#include
@@ -105,7 +105,7 @@ void MessageLogWidget::containerProcessingStarted(const GameEventContext &contex
}
}
-void MessageLogWidget::logAlwaysRevealTopCard(Player *player, CardZoneLogic *zone, bool reveal)
+void MessageLogWidget::logAlwaysRevealTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal)
{
appendHtmlServerMessage((reveal ? tr("%1 is now keeping the top card %2 revealed.")
: tr("%1 is not revealing the top card %2 any longer."))
@@ -113,7 +113,7 @@ void MessageLogWidget::logAlwaysRevealTopCard(Player *player, CardZoneLogic *zon
.arg(zone->getTranslatedName(true, CaseTopCardsOfZone)));
}
-void MessageLogWidget::logAlwaysLookAtTopCard(Player *player, CardZoneLogic *zone, bool reveal)
+void MessageLogWidget::logAlwaysLookAtTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal)
{
appendHtmlServerMessage((reveal ? tr("%1 can now look at top card %2 at any time.")
: tr("%1 no longer can look at top card %2 at any time."))
@@ -121,7 +121,10 @@ void MessageLogWidget::logAlwaysLookAtTopCard(Player *player, CardZoneLogic *zon
.arg(zone->getTranslatedName(true, CaseTopCardsOfZone)));
}
-void MessageLogWidget::logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName)
+void MessageLogWidget::logAttachCard(PlayerLogic *player,
+ QString cardName,
+ PlayerLogic *targetPlayer,
+ QString targetCardName)
{
appendHtmlServerMessage(tr("%1 attaches %2 to %3's %4.")
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
@@ -148,7 +151,7 @@ void MessageLogWidget::logUnconcede(int playerId)
true);
}
-void MessageLogWidget::logConnectionStateChanged(Player *player, bool connectionState)
+void MessageLogWidget::logConnectionStateChanged(PlayerLogic *player, bool connectionState)
{
if (connectionState) {
soundEngine->playSound("player_reconnect");
@@ -161,10 +164,10 @@ void MessageLogWidget::logConnectionStateChanged(Player *player, bool connection
}
}
-void MessageLogWidget::logCreateArrow(Player *player,
- Player *startPlayer,
+void MessageLogWidget::logCreateArrow(PlayerLogic *player,
+ PlayerLogic *startPlayer,
QString startCard,
- Player *targetPlayer,
+ PlayerLogic *targetPlayer,
QString targetCard,
bool playerTarget)
{
@@ -220,7 +223,7 @@ void MessageLogWidget::logCreateArrow(Player *player,
}
}
-void MessageLogWidget::logCreateToken(Player *player, QString cardName, QString pt, bool faceDown)
+void MessageLogWidget::logCreateToken(PlayerLogic *player, QString cardName, QString pt, bool faceDown)
{
if (faceDown) {
appendHtmlServerMessage(
@@ -233,7 +236,7 @@ void MessageLogWidget::logCreateToken(Player *player, QString cardName, QString
}
}
-void MessageLogWidget::logDeckSelect(Player *player, QString deckHash, int sideboardSize)
+void MessageLogWidget::logDeckSelect(PlayerLogic *player, QString deckHash, int sideboardSize)
{
if (sideboardSize < 0) {
appendHtmlServerMessage(
@@ -246,13 +249,13 @@ void MessageLogWidget::logDeckSelect(Player *player, QString deckHash, int sideb
}
}
-void MessageLogWidget::logDestroyCard(Player *player, QString cardName)
+void MessageLogWidget::logDestroyCard(PlayerLogic *player, QString cardName)
{
appendHtmlServerMessage(
tr("%1 destroys %2.").arg(sanitizeHtml(player->getPlayerInfo()->getName())).arg(cardLink(std::move(cardName))));
}
-void MessageLogWidget::logMoveCard(Player *player,
+void MessageLogWidget::logMoveCard(PlayerLogic *player,
CardItem *card,
CardZoneLogic *startZone,
int oldX,
@@ -359,7 +362,7 @@ void MessageLogWidget::logMoveCard(Player *player,
appendHtmlServerMessage(message);
}
-void MessageLogWidget::logDrawCards(Player *player, int number, bool deckIsEmpty)
+void MessageLogWidget::logDrawCards(PlayerLogic *player, int number, bool deckIsEmpty)
{
soundEngine->playSound("draw_card");
if (currentContext == MessageContext_Mulligan) {
@@ -376,7 +379,7 @@ void MessageLogWidget::logDrawCards(Player *player, int number, bool deckIsEmpty
}
}
-void MessageLogWidget::logDumpZone(Player *player, CardZoneLogic *zone, int numberCards, bool isReversed)
+void MessageLogWidget::logDumpZone(PlayerLogic *player, CardZoneLogic *zone, int numberCards, bool isReversed)
{
if (numberCards == -1) {
appendHtmlServerMessage(tr("%1 is looking at %2.")
@@ -392,7 +395,7 @@ void MessageLogWidget::logDumpZone(Player *player, CardZoneLogic *zone, int numb
}
}
-void MessageLogWidget::logFlipCard(Player *player, QString cardName, bool faceDown)
+void MessageLogWidget::logFlipCard(PlayerLogic *player, QString cardName, bool faceDown)
{
if (faceDown) {
appendHtmlServerMessage(
@@ -418,7 +421,7 @@ void MessageLogWidget::logGameFlooded()
appendMessage(tr("You are flooding the game. Please wait a couple of seconds."));
}
-void MessageLogWidget::logJoin(Player *player)
+void MessageLogWidget::logJoin(PlayerLogic *player)
{
soundEngine->playSound("player_join");
appendHtmlServerMessage(tr("%1 has joined the game.").arg(sanitizeHtml(player->getPlayerInfo()->getName())));
@@ -435,7 +438,7 @@ void MessageLogWidget::logKicked()
appendHtmlServerMessage(tr("You have been kicked out of the game."), true);
}
-void MessageLogWidget::logLeave(Player *player, QString reason)
+void MessageLogWidget::logLeave(PlayerLogic *player, QString reason)
{
soundEngine->playSound("player_leave");
appendHtmlServerMessage(tr("%1 has left the game (%2).")
@@ -450,13 +453,13 @@ void MessageLogWidget::logLeaveSpectator(QString name, QString reason)
.arg(sanitizeHtml(std::move(name)), sanitizeHtml(std::move(reason))));
}
-void MessageLogWidget::logNotReadyStart(Player *player)
+void MessageLogWidget::logNotReadyStart(PlayerLogic *player)
{
appendHtmlServerMessage(
tr("%1 is not ready to start the game any more.").arg(sanitizeHtml(player->getPlayerInfo()->getName())));
}
-void MessageLogWidget::logMulligan(Player *player, int number)
+void MessageLogWidget::logMulligan(PlayerLogic *player, int number)
{
if (!player) {
return;
@@ -476,16 +479,16 @@ void MessageLogWidget::logReplayStarted(int gameId)
appendHtmlServerMessage(tr("You are watching a replay of game #%1.").arg(gameId));
}
-void MessageLogWidget::logReadyStart(Player *player)
+void MessageLogWidget::logReadyStart(PlayerLogic *player)
{
appendHtmlServerMessage(tr("%1 is ready to start the game.").arg(sanitizeHtml(player->getPlayerInfo()->getName())));
}
-void MessageLogWidget::logRevealCards(Player *player,
+void MessageLogWidget::logRevealCards(PlayerLogic *player,
CardZoneLogic *zone,
int cardId,
QString cardName,
- Player *otherPlayer,
+ PlayerLogic *otherPlayer,
bool faceDown,
int amount,
bool isLentToAnotherPlayer)
@@ -568,14 +571,14 @@ void MessageLogWidget::logRevealCards(Player *player,
}
}
-void MessageLogWidget::logReverseTurn(Player *player, bool reversed)
+void MessageLogWidget::logReverseTurn(PlayerLogic *player, bool reversed)
{
appendHtmlServerMessage(tr("%1 reversed turn order, now it's %2.")
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
.arg(reversed ? tr("reversed") : tr("normal")));
}
-void MessageLogWidget::logRollDie(Player *player, int sides, const QList &rolls)
+void MessageLogWidget::logRollDie(PlayerLogic *player, int sides, const QList &rolls)
{
if (rolls.length() == 1) {
const auto roll = rolls.at(0);
@@ -612,7 +615,7 @@ void MessageLogWidget::logRollDie(Player *player, int sides, const QList &
soundEngine->playSound("roll_dice");
}
-void MessageLogWidget::logSay(Player *player, QString message)
+void MessageLogWidget::logSay(PlayerLogic *player, QString message)
{
appendMessage(std::move(message), {}, *player->getPlayerInfo()->getUserInfo(), true);
}
@@ -627,13 +630,13 @@ void MessageLogWidget::logSetActivePhase(int phaseNumber)
phase.getName() + "");
}
-void MessageLogWidget::logSetActivePlayer(Player *player)
+void MessageLogWidget::logSetActivePlayer(PlayerLogic *player)
{
appendHtml("
" + QDateTime::currentDateTime().toString("[hh:mm:ss] ") +
QString(tr("%1's turn.")).arg(player->getPlayerInfo()->getName()) + "
");
}
-void MessageLogWidget::logSetAnnotation(Player *player, CardItem *card, QString newAnnotation)
+void MessageLogWidget::logSetAnnotation(PlayerLogic *player, CardItem *card, QString newAnnotation)
{
appendHtmlServerMessage(
QString(tr("%1 sets annotation of %2 to %3."))
@@ -642,25 +645,27 @@ void MessageLogWidget::logSetAnnotation(Player *player, CardItem *card, QString
.arg(QString(""%1"").arg(sanitizeHtml(std::move(newAnnotation)))));
}
-void MessageLogWidget::logSetCardCounter(Player *player, QString cardName, int counterId, int value, int oldValue)
+void MessageLogWidget::logSetCardCounter(PlayerLogic *player, QString cardName, int counterId, int value, int oldValue)
{
QString finalStr;
int delta = abs(oldValue - value);
if (value > oldValue) {
- finalStr = tr("%1 places %2 \"%3\" counter(s) on %4 (now %5).", "", delta);
+ finalStr = tr("%1 places %2 %3%4 counter(s) on %5 (now %6).", "", delta);
} else {
- finalStr = tr("%1 removes %2 \"%3\" counter(s) from %4 (now %5).", "", delta);
+ finalStr = tr("%1 removes %2 %3%4 counter(s) from %5 (now %6).", "", delta);
}
auto &cardCounterSettings = SettingsCache::instance().cardCounters();
+ QString hex = cardCounterSettings.color(counterId).name();
appendHtmlServerMessage(finalStr.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
.arg("" + QString::number(delta) + "")
+ .arg("●")
.arg(cardCounterSettings.displayName(counterId))
.arg(cardLink(std::move(cardName)))
.arg(value));
}
-void MessageLogWidget::logSetCounter(Player *player, QString counterName, int value, int oldValue)
+void MessageLogWidget::logSetCounter(PlayerLogic *player, QString counterName, int value, int oldValue)
{
if (counterName == "life") {
soundEngine->playSound("life_change");
@@ -675,7 +680,7 @@ void MessageLogWidget::logSetCounter(Player *player, QString counterName, int va
.arg(value - oldValue));
}
-void MessageLogWidget::logSetDoesntUntap(Player *player, CardItem *card, bool doesntUntap)
+void MessageLogWidget::logSetDoesntUntap(PlayerLogic *player, CardItem *card, bool doesntUntap)
{
QString str;
if (doesntUntap) {
@@ -686,7 +691,7 @@ void MessageLogWidget::logSetDoesntUntap(Player *player, CardItem *card, bool do
appendHtmlServerMessage(str.arg(sanitizeHtml(player->getPlayerInfo()->getName())).arg(cardLink(card->getName())));
}
-void MessageLogWidget::logSetPT(Player *player, CardItem *card, QString newPT)
+void MessageLogWidget::logSetPT(PlayerLogic *player, CardItem *card, QString newPT)
{
if (currentContext == MessageContext_MoveCard) {
return;
@@ -713,7 +718,7 @@ void MessageLogWidget::logSetPT(Player *player, CardItem *card, QString newPT)
}
}
-void MessageLogWidget::logSetSideboardLock(Player *player, bool locked)
+void MessageLogWidget::logSetSideboardLock(PlayerLogic *player, bool locked)
{
if (locked) {
appendHtmlServerMessage(
@@ -724,7 +729,7 @@ void MessageLogWidget::logSetSideboardLock(Player *player, bool locked)
}
}
-void MessageLogWidget::logSetTapped(Player *player, CardItem *card, bool tapped)
+void MessageLogWidget::logSetTapped(PlayerLogic *player, CardItem *card, bool tapped)
{
if (currentContext == MessageContext_MoveCard) {
return;
@@ -747,7 +752,7 @@ void MessageLogWidget::logSetTapped(Player *player, CardItem *card, bool tapped)
}
}
-void MessageLogWidget::logShuffle(Player *player, CardZoneLogic *zone, int start, int end)
+void MessageLogWidget::logShuffle(PlayerLogic *player, CardZoneLogic *zone, int start, int end)
{
if (currentContext == MessageContext_Mulligan) {
return;
@@ -784,14 +789,14 @@ void MessageLogWidget::logSpectatorSay(const ServerInfo_User &spectator, QString
appendMessage(std::move(message), {}, spectator, false);
}
-void MessageLogWidget::logUnattachCard(Player *player, QString cardName)
+void MessageLogWidget::logUnattachCard(PlayerLogic *player, QString cardName)
{
appendHtmlServerMessage(tr("%1 unattaches %2.")
.arg(sanitizeHtml(player->getPlayerInfo()->getName()))
.arg(cardLink(std::move(cardName))));
}
-void MessageLogWidget::logUndoDraw(Player *player, QString cardName)
+void MessageLogWidget::logUndoDraw(PlayerLogic *player, QString cardName)
{
if (cardName.isEmpty()) {
appendHtmlServerMessage(tr("%1 undoes their last draw.").arg(sanitizeHtml(player->getPlayerInfo()->getName())));
@@ -803,6 +808,12 @@ void MessageLogWidget::logUndoDraw(Player *player, QString cardName)
}
}
+void MessageLogWidget::logUndoDrawFailed(PlayerLogic *player)
+{
+ appendHtmlServerMessage(
+ tr("%1 failed to undo their last draw.").arg(sanitizeHtml(player->getPlayerInfo()->getName())));
+}
+
void MessageLogWidget::setContextJudgeName(QString name)
{
messagePrefix = QString("");
@@ -836,6 +847,7 @@ void MessageLogWidget::connectToPlayerEventHandler(PlayerEventHandler *playerEve
connect(playerEventHandler, &PlayerEventHandler::logDumpZone, this, &MessageLogWidget::logDumpZone);
connect(playerEventHandler, &PlayerEventHandler::logDrawCards, this, &MessageLogWidget::logDrawCards);
connect(playerEventHandler, &PlayerEventHandler::logUndoDraw, this, &MessageLogWidget::logUndoDraw);
+ connect(playerEventHandler, &PlayerEventHandler::logUndoDrawFailed, this, &MessageLogWidget::logUndoDrawFailed);
connect(playerEventHandler, &PlayerEventHandler::logRevealCards, this, &MessageLogWidget::logRevealCards);
connect(playerEventHandler, &PlayerEventHandler::logAlwaysRevealTopCard, this,
&MessageLogWidget::logAlwaysRevealTopCard);
diff --git a/cockatrice/src/game/log/message_log_widget.h b/cockatrice/src/game/log/message_log_widget.h
index 369debd33..9f1990ac4 100644
--- a/cockatrice/src/game/log/message_log_widget.h
+++ b/cockatrice/src/game/log/message_log_widget.h
@@ -1,19 +1,19 @@
/**
* @file message_log_widget.h
* @ingroup GameWidgets
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef MESSAGELOGWIDGET_H
#define MESSAGELOGWIDGET_H
#include "../../interface/widgets/server/chat_view/chat_view.h"
-#include "../zones/logic/card_zone_logic.h"
+#include "../zones/card_zone_logic.h"
class AbstractGame;
class CardItem;
class GameEventContext;
-class Player;
+class PlayerLogic;
class PlayerEventHandler;
class MessageLogWidget : public ChatView
@@ -39,66 +39,67 @@ public:
public slots:
void containerProcessingDone();
void containerProcessingStarted(const GameEventContext &context);
- void logAlwaysRevealTopCard(Player *player, CardZoneLogic *zone, bool reveal);
- void logAlwaysLookAtTopCard(Player *player, CardZoneLogic *zone, bool reveal);
- void logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName);
+ void logAlwaysRevealTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal);
+ void logAlwaysLookAtTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal);
+ void logAttachCard(PlayerLogic *player, QString cardName, PlayerLogic *targetPlayer, QString targetCardName);
void logConcede(int playerId);
void logUnconcede(int playerId);
- void logConnectionStateChanged(Player *player, bool connectionState);
- void logCreateArrow(Player *player,
- Player *startPlayer,
+ void logConnectionStateChanged(PlayerLogic *player, bool connectionState);
+ void logCreateArrow(PlayerLogic *player,
+ PlayerLogic *startPlayer,
QString startCard,
- Player *targetPlayer,
+ PlayerLogic *targetPlayer,
QString targetCard,
bool playerTarget);
- void logCreateToken(Player *player, QString cardName, QString pt, bool faceDown);
- void logDeckSelect(Player *player, QString deckHash, int sideboardSize);
- void logDestroyCard(Player *player, QString cardName);
- void logDrawCards(Player *player, int number, bool deckIsEmpty);
- void logDumpZone(Player *player, CardZoneLogic *zone, int numberCards, bool isReversed = false);
- void logFlipCard(Player *player, QString cardName, bool faceDown);
+ void logCreateToken(PlayerLogic *player, QString cardName, QString pt, bool faceDown);
+ void logDeckSelect(PlayerLogic *player, QString deckHash, int sideboardSize);
+ void logDestroyCard(PlayerLogic *player, QString cardName);
+ void logDrawCards(PlayerLogic *player, int number, bool deckIsEmpty);
+ void logDumpZone(PlayerLogic *player, CardZoneLogic *zone, int numberCards, bool isReversed = false);
+ void logFlipCard(PlayerLogic *player, QString cardName, bool faceDown);
void logGameClosed();
void logGameStart();
void logGameFlooded();
- void logJoin(Player *player);
+ void logJoin(PlayerLogic *player);
void logJoinSpectator(QString name);
void logKicked();
- void logLeave(Player *player, QString reason);
+ void logLeave(PlayerLogic *player, QString reason);
void logLeaveSpectator(QString name, QString reason);
- void logNotReadyStart(Player *player);
- void logMoveCard(Player *player,
+ void logNotReadyStart(PlayerLogic *player);
+ void logMoveCard(PlayerLogic *player,
CardItem *card,
CardZoneLogic *startZone,
int oldX,
CardZoneLogic *targetZone,
int newX);
- void logMulligan(Player *player, int number);
+ void logMulligan(PlayerLogic *player, int number);
void logReplayStarted(int gameId);
- void logReadyStart(Player *player);
- void logRevealCards(Player *player,
+ void logReadyStart(PlayerLogic *player);
+ void logRevealCards(PlayerLogic *player,
CardZoneLogic *zone,
int cardId,
QString cardName,
- Player *otherPlayer,
+ PlayerLogic *otherPlayer,
bool faceDown,
int amount,
bool isLentToAnotherPlayer);
- void logReverseTurn(Player *player, bool reversed);
- void logRollDie(Player *player, int sides, const QList &rolls);
- void logSay(Player *player, QString message);
+ void logReverseTurn(PlayerLogic *player, bool reversed);
+ void logRollDie(PlayerLogic *player, int sides, const QList &rolls);
+ void logSay(PlayerLogic *player, QString message);
void logSetActivePhase(int phase);
- void logSetActivePlayer(Player *player);
- void logSetAnnotation(Player *player, CardItem *card, QString newAnnotation);
- void logSetCardCounter(Player *player, QString cardName, int counterId, int value, int oldValue);
- void logSetCounter(Player *player, QString counterName, int value, int oldValue);
- void logSetDoesntUntap(Player *player, CardItem *card, bool doesntUntap);
- void logSetPT(Player *player, CardItem *card, QString newPT);
- void logSetSideboardLock(Player *player, bool locked);
- void logSetTapped(Player *player, CardItem *card, bool tapped);
- void logShuffle(Player *player, CardZoneLogic *zone, int start, int end);
+ void logSetActivePlayer(PlayerLogic *player);
+ void logSetAnnotation(PlayerLogic *player, CardItem *card, QString newAnnotation);
+ void logSetCardCounter(PlayerLogic *player, QString cardName, int counterId, int value, int oldValue);
+ void logSetCounter(PlayerLogic *player, QString counterName, int value, int oldValue);
+ void logSetDoesntUntap(PlayerLogic *player, CardItem *card, bool doesntUntap);
+ void logSetPT(PlayerLogic *player, CardItem *card, QString newPT);
+ void logSetSideboardLock(PlayerLogic *player, bool locked);
+ void logSetTapped(PlayerLogic *player, CardItem *card, bool tapped);
+ void logShuffle(PlayerLogic *player, CardZoneLogic *zone, int start, int end);
void logSpectatorSay(const ServerInfo_User &spectator, QString message);
- void logUnattachCard(Player *player, QString cardName);
- void logUndoDraw(Player *player, QString cardName);
+ void logUnattachCard(PlayerLogic *player, QString cardName);
+ void logUndoDraw(PlayerLogic *player, QString cardName);
+ void logUndoDrawFailed(PlayerLogic *player);
void setContextJudgeName(QString player);
void appendHtmlServerMessage(const QString &html,
bool optionalIsBold = false,
diff --git a/cockatrice/src/game/phase.h b/cockatrice/src/game/phase.h
index 2e712932f..a888ad43b 100644
--- a/cockatrice/src/game/phase.h
+++ b/cockatrice/src/game/phase.h
@@ -1,8 +1,8 @@
/**
* @file phase.h
* @ingroup GameLogic
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef PHASE_H
#define PHASE_H
diff --git a/cockatrice/src/game/phases_toolbar.cpp b/cockatrice/src/game/phases_toolbar.cpp
index 2341a1d7f..3361f9d55 100644
--- a/cockatrice/src/game/phases_toolbar.cpp
+++ b/cockatrice/src/game/phases_toolbar.cpp
@@ -21,8 +21,9 @@ PhaseButton::PhaseButton(const QString &_name, QGraphicsItem *parent, QAction *_
activeAnimationTimer = new QTimer(this);
connect(activeAnimationTimer, &QTimer::timeout, this, &PhaseButton::updateAnimation);
activeAnimationTimer->setSingleShot(false);
- } else
+ } else {
activeAnimationCounter = 9;
+ }
setCacheMode(DeviceCoordinateCache);
}
@@ -63,8 +64,9 @@ void PhaseButton::setWidth(double _width)
void PhaseButton::setActive(bool _active)
{
- if ((active == _active) || !highlightable)
+ if ((active == _active) || !highlightable) {
return;
+ }
active = _active;
activeAnimationTimer->start(25);
@@ -72,8 +74,9 @@ void PhaseButton::setActive(bool _active)
void PhaseButton::updateAnimation()
{
- if (!highlightable)
+ if (!highlightable) {
return;
+ }
// the counter ticks up to 10 when active and down to 0 when inactive
if (active && activeAnimationCounter < 10) {
@@ -99,8 +102,9 @@ void PhaseButton::mouseDoubleClickEvent(QGraphicsSceneMouseEvent * /*event*/)
void PhaseButton::triggerDoubleClickAction()
{
- if (doubleClickAction)
+ if (doubleClickAction) {
doubleClickAction->trigger();
+ }
}
PhasesToolbar::PhasesToolbar(QGraphicsItem *parent)
@@ -126,8 +130,9 @@ PhasesToolbar::PhasesToolbar(QGraphicsItem *parent)
buttonList << untapButton << upkeepButton << drawButton << main1Button << combatStartButton << combatAttackersButton
<< combatBlockersButton << combatDamageButton << combatEndButton << main2Button << cleanupButton;
- for (auto &i : buttonList)
+ for (auto &i : buttonList) {
connect(i, &PhaseButton::clicked, this, &PhasesToolbar::phaseButtonClicked);
+ }
nextTurnButton = new PhaseButton("nextturn", this, nullptr, false);
connect(nextTurnButton, &PhaseButton::clicked, this, &PhasesToolbar::actNextTurn);
@@ -144,8 +149,9 @@ QRectF PhasesToolbar::boundingRect() const
void PhasesToolbar::retranslateUi()
{
- for (int i = 0; i < buttonList.size(); ++i)
+ for (int i = 0; i < buttonList.size(); ++i) {
buttonList[i]->setToolTip(getLongPhaseName(i));
+ }
}
QString PhasesToolbar::getLongPhaseName(int phase) const
@@ -187,8 +193,9 @@ const double PhasesToolbar::marginSize = 3;
void PhasesToolbar::rearrangeButtons()
{
- for (auto &i : buttonList)
+ for (auto &i : buttonList) {
i->setWidth(symbolSize);
+ }
nextTurnButton->setWidth(symbolSize);
double y = marginSize;
@@ -226,11 +233,13 @@ void PhasesToolbar::setHeight(double _height)
void PhasesToolbar::setActivePhase(int phase)
{
- if (phase >= buttonList.size())
+ if (phase >= buttonList.size()) {
return;
+ }
- for (int i = 0; i < buttonList.size(); ++i)
+ for (int i = 0; i < buttonList.size(); ++i) {
buttonList[i]->setActive(i == phase);
+ }
}
void PhasesToolbar::triggerPhaseAction(int phase)
@@ -243,8 +252,9 @@ void PhasesToolbar::triggerPhaseAction(int phase)
void PhasesToolbar::phaseButtonClicked()
{
auto *button = qobject_cast(sender());
- if (button->getActive())
+ if (button->getActive()) {
button->triggerDoubleClickAction();
+ }
Command_SetActivePhase cmd;
cmd.set_phase(static_cast(buttonList.indexOf(button)));
diff --git a/cockatrice/src/game/phases_toolbar.h b/cockatrice/src/game/phases_toolbar.h
index 215a97dd1..6f0931d61 100644
--- a/cockatrice/src/game/phases_toolbar.h
+++ b/cockatrice/src/game/phases_toolbar.h
@@ -2,8 +2,8 @@
* @file phases_toolbar.h
* @ingroup GameGraphics
* @ingroup GameWidgets
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef PHASESTOOLBAR_H
#define PHASESTOOLBAR_H
@@ -21,7 +21,7 @@ namespace protobuf
class Message;
}
} // namespace google
-class Player;
+class PlayerLogic;
class GameCommand;
class PhaseButton : public QObject, public QGraphicsItem
diff --git a/cockatrice/src/game/player/card_menu_action_type.h b/cockatrice/src/game/player/card_menu_action_type.h
index 1b63674fa..4cae22716 100644
--- a/cockatrice/src/game/player/card_menu_action_type.h
+++ b/cockatrice/src/game/player/card_menu_action_type.h
@@ -1,8 +1,8 @@
/**
* @file card_menu_action_type.h
* @ingroup GameMenusPlayers
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef COCKATRICE_CARD_MENU_ACTION_TYPE_H
#define COCKATRICE_CARD_MENU_ACTION_TYPE_H
diff --git a/cockatrice/src/game/player/event_processing_options.h b/cockatrice/src/game/player/event_processing_options.h
index 3e743bdb3..4c7663789 100644
--- a/cockatrice/src/game/player/event_processing_options.h
+++ b/cockatrice/src/game/player/event_processing_options.h
@@ -1,8 +1,8 @@
/**
* @file event_processing_options.h
* @ingroup GameLogicPlayers
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef COCKATRICE_EVENT_PROCESSING_OPTIONS_H
#define COCKATRICE_EVENT_PROCESSING_OPTIONS_H
diff --git a/cockatrice/src/game/player/menu/abstract_player_component.h b/cockatrice/src/game/player/menu/abstract_player_component.h
index 989300d41..ee310c428 100644
--- a/cockatrice/src/game/player/menu/abstract_player_component.h
+++ b/cockatrice/src/game/player/menu/abstract_player_component.h
@@ -19,13 +19,13 @@ class AbstractPlayerComponent
public:
virtual ~AbstractPlayerComponent() = default;
- /// Bind keyboard shortcuts. Called when this player gains focus.
+ /** @brief Bind keyboard shortcuts. Called when this player gains focus. */
virtual void setShortcutsActive() = 0;
- /// Unbind keyboard shortcuts. Called when this player loses focus.
+ /** @brief Unbind keyboard shortcuts. Called when this player loses focus. */
virtual void setShortcutsInactive() = 0;
- /// Retranslate all user-visible strings. Called on language change.
+ /** @brief Retranslate all user-visible strings. Called on language change. */
virtual void retranslateUi() = 0;
};
diff --git a/cockatrice/src/game/player/menu/card_menu.cpp b/cockatrice/src/game/player/menu/card_menu.cpp
index 34ed254fb..3b866d4e0 100644
--- a/cockatrice/src/game/player/menu/card_menu.cpp
+++ b/cockatrice/src/game/player/menu/card_menu.cpp
@@ -3,23 +3,40 @@
#include "../../../client/settings/card_counter_settings.h"
#include "../../../interface/widgets/tabs/tab_game.h"
#include "../../board/card_item.h"
-#include "../../zones/logic/view_zone_logic.h"
+#include "../../zones/view_zone_logic.h"
#include "../card_menu_action_type.h"
-#include "../player.h"
#include "../player_actions.h"
+#include "../player_logic.h"
#include "move_menu.h"
#include "pt_menu.h"
+#include
#include
#include
#include
-CardMenu::CardMenu(Player *_player, const CardItem *_card, bool _shortcutsActive)
+/**
+ * @brief Creates a circular icon filled with the specified color.
+ */
+static QIcon createCircleIcon(const QColor &color)
+{
+ QPixmap pixmap(32, 32);
+ pixmap.fill(Qt::transparent);
+ QPainter painter(&pixmap);
+ painter.setRenderHint(QPainter::Antialiasing);
+ painter.setPen(Qt::NoPen);
+ painter.setBrush(color);
+ painter.drawEllipse(pixmap.rect());
+
+ return QIcon(pixmap);
+}
+
+CardMenu::CardMenu(PlayerLogic *_player, const CardItem *_card, bool _shortcutsActive)
: player(_player), card(_card), shortcutsActive(_shortcutsActive)
{
auto playerActions = player->getPlayerActions();
- const QList &players = player->getGame()->getPlayerManager()->getPlayers().values();
+ const QList &players = player->getGame()->getPlayerManager()->getPlayers().values();
for (auto playerToAdd : players) {
if (playerToAdd == player) {
@@ -62,6 +79,9 @@ CardMenu::CardMenu(Player *_player, const CardItem *_card, bool _shortcutsActive
aSelectColumn = new QAction(this);
connect(aSelectColumn, &QAction::triggered, playerActions, &PlayerActions::actSelectColumn);
+ aReduceLifeByPower = new QAction(this);
+ connect(aReduceLifeByPower, &QAction::triggered, playerActions, &PlayerActions::actReduceLifeByPower);
+
aPlay = new QAction(this);
connect(aPlay, &QAction::triggered, playerActions, &PlayerActions::actPlay);
aHide = new QAction(this);
@@ -74,9 +94,21 @@ CardMenu::CardMenu(Player *_player, const CardItem *_card, bool _shortcutsActive
mCardCounters = new QMenu;
for (int i = 0; i < 6; ++i) {
+ QColor color = SettingsCache::instance().cardCounters().color(i);
+ QIcon circleIcon = createCircleIcon(color);
+
auto *tempAddCounter = new QAction(this);
+ tempAddCounter->setIconVisibleInMenu(true);
+ tempAddCounter->setIcon(circleIcon);
+
auto *tempRemoveCounter = new QAction(this);
+ tempRemoveCounter->setIconVisibleInMenu(true);
+ tempRemoveCounter->setIcon(circleIcon);
+
auto *tempSetCounter = new QAction(this);
+ tempSetCounter->setIconVisibleInMenu(true);
+ tempSetCounter->setIcon(circleIcon);
+
aAddCounter.append(tempAddCounter);
aRemoveCounter.append(tempRemoveCounter);
aSetCounter.append(tempSetCounter);
@@ -134,7 +166,7 @@ CardMenu::CardMenu(Player *_player, const CardItem *_card, bool _shortcutsActive
}
}
-void CardMenu::removePlayer(Player *playerToRemove)
+void CardMenu::removePlayer(PlayerLogic *playerToRemove)
{
for (auto it = playersInfo.begin(); it != playersInfo.end();) {
if (it->second == playerToRemove->getPlayerInfo()->getId()) {
@@ -153,6 +185,8 @@ void CardMenu::createTableMenu(bool canModifyCard)
addSeparator();
addAction(aClone);
addSeparator();
+ addAction(aReduceLifeByPower);
+ addSeparator();
addAction(aSelectAll);
addAction(aSelectRow);
addRelatedCardView();
@@ -179,6 +213,8 @@ void CardMenu::createTableMenu(bool canModifyCard)
addMenu(new PtMenu(player));
addAction(aSetAnnotation);
addSeparator();
+ addAction(aReduceLifeByPower);
+ addSeparator();
addAction(aSelectAll);
addAction(aSelectRow);
@@ -463,6 +499,7 @@ void CardMenu::retranslateUi()
aUnattach->setText(tr("Unattac&h"));
aDrawArrow->setText(tr("&Draw arrow..."));
aSetAnnotation->setText(tr("&Set annotation..."));
+ aReduceLifeByPower->setText(tr("Reduce life by power"));
mCardCounters->setTitle(tr("Ca&rd counters"));
@@ -497,6 +534,7 @@ void CardMenu::setShortcutsActive()
aUnattach->setShortcuts(shortcuts.getShortcut("Player/aUnattach"));
aDrawArrow->setShortcuts(shortcuts.getShortcut("Player/aDrawArrow"));
aSetAnnotation->setShortcuts(shortcuts.getShortcut("Player/aSetAnnotation"));
+ aReduceLifeByPower->setShortcuts(shortcuts.getShortcut("Player/aReduceLifeByPower"));
aSelectAll->setShortcuts(shortcuts.getShortcut("Player/aSelectAll"));
aSelectRow->setShortcuts(shortcuts.getShortcut("Player/aSelectRow"));
diff --git a/cockatrice/src/game/player/menu/card_menu.h b/cockatrice/src/game/player/menu/card_menu.h
index b7f2f8241..ad3962caf 100644
--- a/cockatrice/src/game/player/menu/card_menu.h
+++ b/cockatrice/src/game/player/menu/card_menu.h
@@ -1,8 +1,8 @@
/**
* @file card_menu.h
* @ingroup GameMenusCards
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef COCKATRICE_CARD_MENU_H
#define COCKATRICE_CARD_MENU_H
@@ -10,14 +10,14 @@
#include
class CardItem;
-class Player;
+class PlayerLogic;
class CardMenu : public QMenu
{
Q_OBJECT
public:
- explicit CardMenu(Player *player, const CardItem *card, bool shortcutsActive);
- void removePlayer(Player *playerToRemove);
+ explicit CardMenu(PlayerLogic *player, const CardItem *card, bool shortcutsActive);
+ void removePlayer(PlayerLogic *playerToRemove);
void createTableMenu(bool canModifyCard);
void createStackMenu(bool canModifyCard);
void createGraveyardOrExileMenu(bool canModifyCard);
@@ -36,11 +36,12 @@ public:
QAction *aFlip, *aPeek;
QAction *aAttach, *aUnattach;
QAction *aSetAnnotation;
+ QAction *aReduceLifeByPower;
QList aAddCounter, aSetCounter, aRemoveCounter;
private:
- Player *player;
+ PlayerLogic *player;
const CardItem *card;
QList> playersInfo;
bool shortcutsActive;
diff --git a/cockatrice/src/game/player/menu/custom_zone_menu.cpp b/cockatrice/src/game/player/menu/custom_zone_menu.cpp
index b0f3284c9..88b7f3710 100644
--- a/cockatrice/src/game/player/menu/custom_zone_menu.cpp
+++ b/cockatrice/src/game/player/menu/custom_zone_menu.cpp
@@ -1,13 +1,13 @@
#include "custom_zone_menu.h"
-#include "../player.h"
+#include "../player_logic.h"
-CustomZoneMenu::CustomZoneMenu(Player *_player) : player(_player)
+CustomZoneMenu::CustomZoneMenu(PlayerLogic *_player) : player(_player)
{
menuAction()->setVisible(false);
- connect(player, &Player::clearCustomZonesMenu, this, &CustomZoneMenu::clearCustomZonesMenu);
- connect(player, &Player::addViewCustomZoneActionToCustomZoneMenu, this,
+ connect(player, &PlayerLogic::clearCustomZonesMenu, this, &CustomZoneMenu::clearCustomZonesMenu);
+ connect(player, &PlayerLogic::addViewCustomZoneActionToCustomZoneMenu, this,
&CustomZoneMenu::addViewCustomZoneActionToCustomZoneMenu);
retranslateUi();
diff --git a/cockatrice/src/game/player/menu/custom_zone_menu.h b/cockatrice/src/game/player/menu/custom_zone_menu.h
index c4e66754e..e10f6a4f0 100644
--- a/cockatrice/src/game/player/menu/custom_zone_menu.h
+++ b/cockatrice/src/game/player/menu/custom_zone_menu.h
@@ -1,8 +1,8 @@
/**
* @file custom_zone_menu.h
* @ingroup GameMenusZones
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef COCKATRICE_CUSTOM_ZONE_MENU_H
#define COCKATRICE_CUSTOM_ZONE_MENU_H
@@ -11,12 +11,12 @@
#include
-class Player;
+class PlayerLogic;
class CustomZoneMenu : public QMenu, public AbstractPlayerComponent
{
Q_OBJECT
public:
- explicit CustomZoneMenu(Player *player);
+ explicit CustomZoneMenu(PlayerLogic *player);
void retranslateUi() override;
void setShortcutsActive() override
{
@@ -26,7 +26,7 @@ public:
}
private:
- Player *player;
+ PlayerLogic *player;
private slots:
void clearCustomZonesMenu();
void addViewCustomZoneActionToCustomZoneMenu(QString zoneName);
diff --git a/cockatrice/src/game/player/menu/grave_menu.cpp b/cockatrice/src/game/player/menu/grave_menu.cpp
index 2af62c08a..16a5858ca 100644
--- a/cockatrice/src/game/player/menu/grave_menu.cpp
+++ b/cockatrice/src/game/player/menu/grave_menu.cpp
@@ -1,14 +1,14 @@
#include "grave_menu.h"
#include "../../abstract_game.h"
-#include "../player.h"
#include "../player_actions.h"
+#include "../player_logic.h"
#include
#include
#include
-GraveyardMenu::GraveyardMenu(Player *_player, QWidget *parent) : TearOffMenu(parent), player(_player)
+GraveyardMenu::GraveyardMenu(PlayerLogic *_player, QWidget *parent) : TearOffMenu(parent), player(_player)
{
createMoveActions();
createViewActions();
@@ -78,8 +78,9 @@ void GraveyardMenu::populateRevealRandomMenuWithActivePlayers()
const auto &players = player->getGame()->getPlayerManager()->getPlayers().values();
for (auto *other : players) {
- if (other == player)
+ if (other == player) {
continue;
+ }
QAction *a = mRevealRandomGraveyardCard->addAction(other->getPlayerInfo()->getName());
a->setData(other->getPlayerInfo()->getId());
connect(a, &QAction::triggered, this, &GraveyardMenu::onRevealRandomTriggered);
diff --git a/cockatrice/src/game/player/menu/grave_menu.h b/cockatrice/src/game/player/menu/grave_menu.h
index 429173afa..d3d98802d 100644
--- a/cockatrice/src/game/player/menu/grave_menu.h
+++ b/cockatrice/src/game/player/menu/grave_menu.h
@@ -1,8 +1,8 @@
/**
* @file grave_menu.h
* @ingroup GameMenusZones
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef COCKATRICE_GRAVE_MENU_H
#define COCKATRICE_GRAVE_MENU_H
@@ -13,7 +13,7 @@
#include
#include
-class Player;
+class PlayerLogic;
class GraveyardMenu : public TearOffMenu, public AbstractPlayerComponent
{
Q_OBJECT
@@ -21,7 +21,7 @@ signals:
void newPlayerActionCreated(QAction *action);
public:
- explicit GraveyardMenu(Player *player, QWidget *parent = nullptr);
+ explicit GraveyardMenu(PlayerLogic *player, QWidget *parent = nullptr);
void createMoveActions();
void createViewActions();
void populateRevealRandomMenuWithActivePlayers();
@@ -40,7 +40,7 @@ public:
QAction *aMoveGraveToRfg = nullptr;
private:
- Player *player;
+ PlayerLogic *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
index d65c136bf..6ff177655 100644
--- a/cockatrice/src/game/player/menu/hand_menu.cpp
+++ b/cockatrice/src/game/player/menu/hand_menu.cpp
@@ -2,16 +2,16 @@
#include "../../../client/settings/cache_settings.h"
#include "../../../client/settings/shortcuts_settings.h"
+#include "../../../game_graphics/zones/hand_zone.h"
#include "../../abstract_game.h"
-#include "../../zones/hand_zone.h"
-#include "../player.h"
#include "../player_actions.h"
+#include "../player_logic.h"
#include
#include
#include
-HandMenu::HandMenu(Player *_player, PlayerActions *actions, QWidget *parent) : TearOffMenu(parent), player(_player)
+HandMenu::HandMenu(PlayerLogic *_player, PlayerActions *actions, QWidget *parent) : TearOffMenu(parent), player(_player)
{
if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) {
aViewHand = new QAction(this);
@@ -168,8 +168,9 @@ void HandMenu::populateRevealHandMenuWithActivePlayers()
const auto &players = player->getGame()->getPlayerManager()->getPlayers().values();
for (auto *other : players) {
- if (other == player)
+ if (other == player) {
continue;
+ }
QAction *a = mRevealHand->addAction(other->getPlayerInfo()->getName());
a->setData(other->getPlayerInfo()->getId());
connect(a, &QAction::triggered, this, &HandMenu::onRevealHandTriggered);
@@ -186,8 +187,9 @@ void HandMenu::populateRevealRandomHandCardMenuWithActivePlayers()
const auto &players = player->getGame()->getPlayerManager()->getPlayers().values();
for (auto *other : players) {
- if (other == player)
+ if (other == player) {
continue;
+ }
QAction *a = mRevealRandomHandCard->addAction(other->getPlayerInfo()->getName());
a->setData(other->getPlayerInfo()->getId());
connect(a, &QAction::triggered, this, &HandMenu::onRevealRandomHandCardTriggered);
@@ -197,8 +199,9 @@ void HandMenu::populateRevealRandomHandCardMenuWithActivePlayers()
void HandMenu::onRevealHandTriggered()
{
auto *action = qobject_cast(sender());
- if (!action)
+ if (!action) {
return;
+ }
const int targetId = action->data().toInt();
player->getPlayerActions()->actRevealHand(targetId);
@@ -207,8 +210,9 @@ void HandMenu::onRevealHandTriggered()
void HandMenu::onRevealRandomHandCardTriggered()
{
auto *action = qobject_cast(sender());
- if (!action)
+ if (!action) {
return;
+ }
const int targetId = action->data().toInt();
player->getPlayerActions()->actRevealRandomHandCard(targetId);
diff --git a/cockatrice/src/game/player/menu/hand_menu.h b/cockatrice/src/game/player/menu/hand_menu.h
index 76434cc98..1e2ddd95a 100644
--- a/cockatrice/src/game/player/menu/hand_menu.h
+++ b/cockatrice/src/game/player/menu/hand_menu.h
@@ -1,8 +1,8 @@
/**
* @file hand_menu.h
* @ingroup GameMenusZones
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef COCKATRICE_HAND_MENU_H
#define COCKATRICE_HAND_MENU_H
@@ -13,7 +13,7 @@
#include
#include
-class Player;
+class PlayerLogic;
class PlayerActions;
class HandMenu : public TearOffMenu, public AbstractPlayerComponent
@@ -21,7 +21,7 @@ class HandMenu : public TearOffMenu, public AbstractPlayerComponent
Q_OBJECT
public:
- HandMenu(Player *player, PlayerActions *actions, QWidget *parent = nullptr);
+ HandMenu(PlayerLogic *player, PlayerActions *actions, QWidget *parent = nullptr);
QMenu *revealHandMenu() const
{
@@ -43,7 +43,7 @@ private slots:
void onRevealRandomHandCardTriggered();
private:
- Player *player;
+ PlayerLogic *player;
QAction *aViewHand = nullptr;
QAction *aMulligan = nullptr;
diff --git a/cockatrice/src/game/player/menu/library_menu.cpp b/cockatrice/src/game/player/menu/library_menu.cpp
index 1bb647d06..8449af05a 100644
--- a/cockatrice/src/game/player/menu/library_menu.cpp
+++ b/cockatrice/src/game/player/menu/library_menu.cpp
@@ -4,13 +4,13 @@
#include "../../../client/settings/shortcuts_settings.h"
#include "../../../interface/widgets/tabs/tab_game.h"
#include "../../abstract_game.h"
-#include "../player.h"
#include "../player_actions.h"
+#include "../player_logic.h"
#include
#include
-LibraryMenu::LibraryMenu(Player *_player, QWidget *parent) : TearOffMenu(parent), player(_player)
+LibraryMenu::LibraryMenu(PlayerLogic *_player, QWidget *parent) : TearOffMenu(parent), player(_player)
{
createDrawActions();
createShuffleActions();
@@ -75,8 +75,8 @@ LibraryMenu::LibraryMenu(Player *_player, QWidget *parent) : TearOffMenu(parent)
bottomLibraryMenu->addSeparator();
bottomLibraryMenu->addAction(aShuffleBottomCards);
- connect(player, &Player::resetTopCardMenuActions, this, &LibraryMenu::resetTopCardMenuActions);
- connect(player, &Player::deckChanged, this, &LibraryMenu::enableOpenInDeckEditorAction);
+ connect(player, &PlayerLogic::resetTopCardMenuActions, this, &LibraryMenu::resetTopCardMenuActions);
+ connect(player, &PlayerLogic::deckChanged, this, &LibraryMenu::enableOpenInDeckEditorAction);
retranslateUi();
}
@@ -265,8 +265,9 @@ void LibraryMenu::populateRevealLibraryMenuWithActivePlayers()
const auto &players = player->getGame()->getPlayerManager()->getPlayers().values();
for (auto *other : players) {
- if (other == player)
+ if (other == player) {
continue;
+ }
QAction *a = mRevealLibrary->addAction(other->getPlayerInfo()->getName());
a->setData(other->getPlayerInfo()->getId());
connect(a, &QAction::triggered, this, &LibraryMenu::onRevealLibraryTriggered);
@@ -279,8 +280,9 @@ void LibraryMenu::populateLendLibraryMenuWithActivePlayers()
const auto &players = player->getGame()->getPlayerManager()->getPlayers().values();
for (auto *other : players) {
- if (other == player)
+ if (other == player) {
continue;
+ }
QAction *a = mLendLibrary->addAction(other->getPlayerInfo()->getName());
a->setData(other->getPlayerInfo()->getId());
connect(a, &QAction::triggered, this, &LibraryMenu::onLendLibraryTriggered);
@@ -299,8 +301,9 @@ void LibraryMenu::populateRevealTopCardMenuWithActivePlayers()
const auto &players = player->getGame()->getPlayerManager()->getPlayers().values();
for (auto *other : players) {
- if (other == player)
+ if (other == player) {
continue;
+ }
QAction *a = mRevealTopCard->addAction(other->getPlayerInfo()->getName());
a->setData(other->getPlayerInfo()->getId());
connect(a, &QAction::triggered, this, &LibraryMenu::onRevealTopCardTriggered);
diff --git a/cockatrice/src/game/player/menu/library_menu.h b/cockatrice/src/game/player/menu/library_menu.h
index 444e8f516..a941c54b1 100644
--- a/cockatrice/src/game/player/menu/library_menu.h
+++ b/cockatrice/src/game/player/menu/library_menu.h
@@ -1,8 +1,8 @@
/**
* @file library_menu.h
* @ingroup GameMenusZones
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef COCKATRICE_LIBRARY_MENU_H
#define COCKATRICE_LIBRARY_MENU_H
@@ -13,7 +13,7 @@
#include
#include
-class Player;
+class PlayerLogic;
class PlayerActions;
class LibraryMenu : public TearOffMenu, public AbstractPlayerComponent
@@ -24,7 +24,7 @@ public slots:
void resetTopCardMenuActions();
public:
- LibraryMenu(Player *player, QWidget *parent = nullptr);
+ LibraryMenu(PlayerLogic *player, QWidget *parent = nullptr);
void createDrawActions();
void createShuffleActions();
void createMoveActions();
@@ -111,7 +111,7 @@ public:
int defaultNumberTopCards = 1;
private:
- Player *player;
+ PlayerLogic *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
index 91e2d8d10..3a5ad4da3 100644
--- a/cockatrice/src/game/player/menu/move_menu.cpp
+++ b/cockatrice/src/game/player/menu/move_menu.cpp
@@ -1,10 +1,10 @@
#include "move_menu.h"
#include "../card_menu_action_type.h"
-#include "../player.h"
#include "../player_actions.h"
+#include "../player_logic.h"
-MoveMenu::MoveMenu(Player *player) : QMenu(tr("Move to"))
+MoveMenu::MoveMenu(PlayerLogic *player) : QMenu(tr("Move to"))
{
aMoveToTopLibrary = new QAction(this);
aMoveToTopLibrary->setData(cmMoveToTopLibrary);
diff --git a/cockatrice/src/game/player/menu/move_menu.h b/cockatrice/src/game/player/menu/move_menu.h
index dc39cb6a5..4e257b7fb 100644
--- a/cockatrice/src/game/player/menu/move_menu.h
+++ b/cockatrice/src/game/player/menu/move_menu.h
@@ -1,20 +1,20 @@
/**
* @file move_menu.h
* @ingroup GameMenusZones
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef COCKATRICE_MOVE_MENU_H
#define COCKATRICE_MOVE_MENU_H
#include
-class Player;
+class PlayerLogic;
class MoveMenu : public QMenu
{
Q_OBJECT
public:
- explicit MoveMenu(Player *player);
+ explicit MoveMenu(PlayerLogic *player);
void setShortcutsActive();
void retranslateUi();
diff --git a/cockatrice/src/game/player/menu/player_menu.cpp b/cockatrice/src/game/player/menu/player_menu.cpp
index 0dc381e28..9e7b91923 100644
--- a/cockatrice/src/game/player/menu/player_menu.cpp
+++ b/cockatrice/src/game/player/menu/player_menu.cpp
@@ -1,16 +1,16 @@
#include "player_menu.h"
+#include "../../../game_graphics/zones/hand_zone.h"
+#include "../../../game_graphics/zones/pile_zone.h"
+#include "../../../game_graphics/zones/table_zone.h"
#include "../../../interface/widgets/tabs/tab_game.h"
#include "../../board/card_item.h"
-#include "../../zones/hand_zone.h"
-#include "../../zones/pile_zone.h"
-#include "../../zones/table_zone.h"
#include "card_menu.h"
#include "hand_menu.h"
#include
-PlayerMenu::PlayerMenu(Player *_player) : QObject(_player), player(_player)
+PlayerMenu::PlayerMenu(PlayerLogic *_player) : QObject(_player), player(_player)
{
playerMenu = new TearOffMenu();
@@ -97,10 +97,7 @@ void PlayerMenu::retranslateUi()
countersMenu->setTitle(tr("&Counters"));
}
- QMapIterator counterIterator(player->getCounters());
- while (counterIterator.hasNext()) {
- counterIterator.next().value()->retranslateUi();
- }
+ emit retranslateRequested();
}
void PlayerMenu::refreshShortcuts()
@@ -120,30 +117,17 @@ void PlayerMenu::refreshShortcuts()
void PlayerMenu::setShortcutsActive()
{
shortcutsActive = true;
-
- for (auto *component : managedComponents) {
- component->setShortcutsActive();
- }
-
- // Counters implement AbstractPlayerComponent but are iterated via Player::counters
- // (the authoritative source) rather than managedComponents to avoid a redundant
- // list that must stay in sync with the map.
- QMapIterator counterIterator(player->getCounters());
- while (counterIterator.hasNext()) {
- counterIterator.next().value()->setShortcutsActive();
+ for (auto *c : managedComponents) {
+ c->setShortcutsActive();
}
+ emit shortcutsActivated();
}
void PlayerMenu::setShortcutsInactive()
{
shortcutsActive = false;
-
- for (auto *component : managedComponents) {
- component->setShortcutsInactive();
- }
-
- QMapIterator counterIterator(player->getCounters());
- while (counterIterator.hasNext()) {
- counterIterator.next().value()->setShortcutsInactive();
+ for (auto *c : managedComponents) {
+ c->setShortcutsInactive();
}
+ emit shortcutsDeactivated();
}
\ 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
index 104c5a930..d5c19df58 100644
--- a/cockatrice/src/game/player/menu/player_menu.h
+++ b/cockatrice/src/game/player/menu/player_menu.h
@@ -8,7 +8,7 @@
#define COCKATRICE_PLAYER_MENU_H
#include "../../../interface/widgets/menus/tearoff_menu.h"
-#include "../player.h"
+#include "../player_logic.h"
#include "custom_zone_menu.h"
#include "grave_menu.h"
#include "hand_menu.h"
@@ -29,6 +29,9 @@ class PlayerMenu : public QObject
signals:
void cardMenuUpdated(QMenu *cardMenu);
+ void shortcutsActivated();
+ void shortcutsDeactivated();
+ void retranslateRequested();
public slots:
void setMenusForGraphicItems();
@@ -37,8 +40,8 @@ private slots:
void refreshShortcuts();
public:
- explicit PlayerMenu(Player *player);
- /// Lifecycle methods: delegate to all managedComponents, plus counters separately via player->getCounters().
+ explicit PlayerMenu(PlayerLogic *player);
+ /** @brief Retranslate all user-visible strings. Called on language change. */
void retranslateUi();
QMenu *updateCardMenu(const CardItem *card);
@@ -68,13 +71,13 @@ public:
return shortcutsActive;
}
- /// Delegates to all managedComponents, plus counters separately.
+ /** @brief Bind keyboard shortcuts. Called when this player gains focus. */
void setShortcutsActive();
- /// Delegates to all managedComponents, plus counters separately.
+ /** @brief Unbind keyboard shortcuts. Called when this player loses focus. */
void setShortcutsInactive();
private:
- Player *player;
+ PlayerLogic *player;
TearOffMenu *playerMenu;
QMenu *countersMenu;
HandMenu *handMenu;
@@ -86,11 +89,13 @@ private:
SayMenu *sayMenu;
CustomZoneMenu *customZonesMenu;
- /// Drives AbstractPlayerComponent lifecycle delegation. Counters are iterated separately via player->getCounters().
+ /** @brief Drives AbstractPlayerComponent lifecycle delegation. Counters are iterated separately via
+ * player->getCounters().
+ */
QList managedComponents;
bool shortcutsActive = false;
- /// Creates component, adds it as a submenu of playerMenu, and registers in managedComponents.
+ /** @brief Creates component, adds it as a submenu of playerMenu, and registers in managedComponents. */
template MenuT *addManagedMenu(Args &&...args)
{
auto *menu = new MenuT(std::forward(args)...);
@@ -99,7 +104,7 @@ private:
return menu;
}
- /// Creates component and registers in managedComponents, but does NOT add it as a submenu.
+ /** @brief Creates component and registers in managedComponents, but does NOT add it as a submenu. */
template ComponentT *createManagedComponent(Args &&...args)
{
auto *component = new ComponentT(std::forward(args)...);
diff --git a/cockatrice/src/game/player/menu/pt_menu.cpp b/cockatrice/src/game/player/menu/pt_menu.cpp
index dae03e07f..7dc3035c1 100644
--- a/cockatrice/src/game/player/menu/pt_menu.cpp
+++ b/cockatrice/src/game/player/menu/pt_menu.cpp
@@ -1,9 +1,9 @@
#include "pt_menu.h"
-#include "../player.h"
#include "../player_actions.h"
+#include "../player_logic.h"
-PtMenu::PtMenu(Player *player) : QMenu(tr("Power / toughness"))
+PtMenu::PtMenu(PlayerLogic *player) : QMenu(tr("Power / toughness"))
{
PlayerActions *playerActions = player->getPlayerActions();
diff --git a/cockatrice/src/game/player/menu/pt_menu.h b/cockatrice/src/game/player/menu/pt_menu.h
index 44112e54f..645449586 100644
--- a/cockatrice/src/game/player/menu/pt_menu.h
+++ b/cockatrice/src/game/player/menu/pt_menu.h
@@ -1,21 +1,21 @@
/**
* @file pt_menu.h
* @ingroup GameMenusCards
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef COCKATRICE_PT_MENU_H
#define COCKATRICE_PT_MENU_H
#include
-class Player;
+class PlayerLogic;
class PtMenu : public QMenu
{
Q_OBJECT
public:
- explicit PtMenu(Player *player);
+ explicit PtMenu(PlayerLogic *player);
void retranslateUi();
void setShortcutsActive();
diff --git a/cockatrice/src/game/player/menu/rfg_menu.cpp b/cockatrice/src/game/player/menu/rfg_menu.cpp
index 8a101c04c..e8aca00cb 100644
--- a/cockatrice/src/game/player/menu/rfg_menu.cpp
+++ b/cockatrice/src/game/player/menu/rfg_menu.cpp
@@ -1,11 +1,11 @@
#include "rfg_menu.h"
-#include "../player.h"
#include "../player_actions.h"
+#include "../player_logic.h"
#include
-RfgMenu::RfgMenu(Player *_player, QWidget *parent) : TearOffMenu(parent), player(_player)
+RfgMenu::RfgMenu(PlayerLogic *_player, QWidget *parent) : TearOffMenu(parent), player(_player)
{
createMoveActions();
createViewActions();
diff --git a/cockatrice/src/game/player/menu/rfg_menu.h b/cockatrice/src/game/player/menu/rfg_menu.h
index 8f79b2f4a..9e179f8fd 100644
--- a/cockatrice/src/game/player/menu/rfg_menu.h
+++ b/cockatrice/src/game/player/menu/rfg_menu.h
@@ -1,8 +1,8 @@
/**
* @file rfg_menu.h
* @ingroup GameMenusZones
- * @brief TODO: Document this.
*/
+//! \todo Document this file.
#ifndef COCKATRICE_RFG_MENU_H
#define COCKATRICE_RFG_MENU_H
@@ -13,12 +13,12 @@
#include