Merge branch 'master' into mergingCheckout

This commit is contained in:
Lily 2025-04-18 11:49:56 -04:00
commit 0879bc3430
No known key found for this signature in database
GPG key ID: 57E5B0E79E93B05C
290 changed files with 50236 additions and 34560 deletions

View file

@ -4,24 +4,30 @@
git push -d origin --REPLACE-WITH-BETA-LIST-- git push -d origin --REPLACE-WITH-BETA-LIST--
--> -->
<!-- This list of binaries should be updated every time the CI is changed to <!-- This list of binaries should be updated every time the CI is changed to include all targets -->
include different targets -->
<pre> <pre>
<b>Pre-compiled binaries we serve:</b> Available pre-compiled binaries for installation:
- <kbd>Windows 10+</kbd>
- <kbd>Windows 7+</kbd> <b>Windows</b>
- <kbd>macOS 14+</kbd> ("Sonoma") / Apple M <kbd>Windows 10+</kbd>
- <kbd>macOS 13+</kbd> ("Ventura") / Intel <kbd>Windows 7+</kbd>
- <kbd>Ubuntu 24.04 LTS</kbd> ("Noble Numbat")
- <kbd>Ubuntu 22.04 LTS</kbd> ("Jammy Jellyfish") <b>macOS</b>
- <kbd>Ubuntu 20.04 LTS</kbd> ("Focal Fossa") <kbd>macOS 15+</kbd> <sub><i>Sequoia</i></sub> <sub>Apple M</sub>
- <kbd>Debian 12</kbd> ("Bookworm") <kbd>macOS 14+</kbd> <sub><i>Sonoma</i></sub> <sub>Apple M</sub>
- <kbd>Debian 11</kbd> ("Bullseye") <kbd>macOS 13+</kbd> <sub><i>Ventura</i></sub> <sub>Intel</sub>
- <kbd>Fedora 41</kbd>
- <kbd>Fedora 40</kbd> <b>Linux</b>
<kbd>Ubuntu 24.04 LTS</kbd> <sub><i>Noble Numbat</i></sub>
<i>We are also packaged in <kbd>Arch Linux</kbd>'s official "extra" repository, courtesy of @FFY00</i> <kbd>Ubuntu 22.04 LTS</kbd> <sub><i>Jammy Jellyfish</i></sub>
<i>General Linux support is available via a <kbd>flatpak</kbd> package (Flathub)</i> <kbd>Ubuntu 20.04 LTS</kbd> <sub><i>Focal Fossa</i></sub>
<kbd>Debian 12</kbd> <sub><i>Bookworm</i></sub>
<kbd>Debian 11</kbd> <sub><i>Bullseye</i></sub>
<kbd>Fedora 41</kbd>
<kbd>Fedora 40</kbd>
<sub>We are also packaged in <kbd>Arch Linux</kbd>'s <a href="https://archlinux.org/packages/extra/x86_64/cockatrice">official extra repository</a>, courtesy of @FFY00.</sub>
<sub>General Linux support is available via a <kbd>flatpak</kbd> package at <a href="https://flathub.org/apps/io.github.Cockatrice.cockatrice">Flathub</a>!</sub>
</pre> </pre>

View file

@ -74,7 +74,7 @@ endif()
# A project name is needed for CPack # A project name is needed for CPack
# Version can be overriden by git tags, see cmake/getversion.cmake # Version can be overriden by git tags, see cmake/getversion.cmake
project("Cockatrice" VERSION 2.10.1) project("Cockatrice" VERSION 2.11.0)
# Set release name if not provided via env/cmake var # Set release name if not provided via env/cmake var
if(NOT DEFINED GIT_TAG_RELEASENAME) if(NOT DEFINED GIT_TAG_RELEASENAME)

View file

@ -4,9 +4,243 @@
project(Cockatrice VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") project(Cockatrice VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
file(GLOB_RECURSE cockatrice_CPP_FILES CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/cockatrice/src/*.cpp) set(cockatrice_SOURCES
${VERSION_STRING_CPP}
set(cockatrice_SOURCES ${cockatrice_CPP_FILES} ${VERSION_STRING_CPP}) # sort by alphabetical order, so that there is no debate about where to add new sources to the list
src/client/game_logic/abstract_client.cpp
src/client/game_logic/key_signals.cpp
src/client/get_text_with_max.cpp
src/client/menus/deck_editor/deck_editor_menu.cpp
src/client/network/client_update_checker.cpp
src/client/network/release_channel.cpp
src/client/network/replay_timeline_widget.cpp
src/client/network/sets_model.cpp
src/client/network/spoiler_background_updater.cpp
src/client/sound_engine.cpp
src/client/tabs/abstract_tab_deck_editor.cpp
src/client/tabs/api/edhrec/tab_edhrec.cpp
src/client/tabs/api/edhrec/tab_edhrec_main.cpp
src/client/tabs/api/edhrec/display/commander/edhrec_commander_api_response_display_widget.cpp
src/client/tabs/api/edhrec/display/commander/edhrec_commander_api_response_card_details_display_widget.cpp
src/client/tabs/api/edhrec/display/commander/edhrec_commander_api_response_card_list_display_widget.cpp
src/client/tabs/api/edhrec/display/commander/edhrec_commander_api_response_commander_details_display_widget.cpp
src/client/tabs/api/edhrec/display/top_cards/edhrec_top_cards_api_response_display_widget.cpp
src/client/tabs/api/edhrec/display/top_commander/edhrec_top_commanders_api_response_display_widget.cpp
src/client/tabs/api/edhrec/display/top_tags/edhrec_top_tags_api_response_display_widget.cpp
src/client/tabs/api/edhrec/api_response/commander/edhrec_commander_api_response_archidekt_links.cpp
src/client/tabs/api/edhrec/api_response/commander/edhrec_commander_api_response_average_deck_statistics.cpp
src/client/tabs/api/edhrec/api_response/commander/edhrec_commander_api_response_card_details.cpp
src/client/tabs/api/edhrec/api_response/commander/edhrec_commander_api_response_card_list.cpp
src/client/tabs/api/edhrec/api_response/commander/edhrec_commander_api_response_card_container.cpp
src/client/tabs/api/edhrec/api_response/commander/edhrec_commander_api_response_card_prices.cpp
src/client/tabs/api/edhrec/api_response/commander/edhrec_commander_api_response_commander_details.cpp
src/client/tabs/api/edhrec/api_response/commander/edhrec_commander_api_response.cpp
src/client/tabs/api/edhrec/api_response/average_deck/edhrec_average_deck_api_response.cpp
src/client/tabs/api/edhrec/api_response/average_deck/edhrec_deck_api_response.cpp
src/client/tabs/api/edhrec/api_response/top_cards/edhrec_top_cards_api_response.cpp
src/client/tabs/api/edhrec/api_response/top_commanders/edhrec_top_commanders_api_response.cpp
src/client/tabs/api/edhrec/api_response/top_tags/edhrec_top_tags_api_response.cpp
src/client/tabs/tab.cpp
src/client/tabs/tab_account.cpp
src/client/tabs/tab_admin.cpp
src/client/tabs/tab_deck_editor.cpp
src/client/tabs/tab_deck_storage.cpp
src/client/tabs/tab_game.cpp
src/client/tabs/tab_logs.cpp
src/client/tabs/tab_message.cpp
src/client/tabs/tab_replays.cpp
src/client/tabs/tab_room.cpp
src/client/tabs/tab_server.cpp
src/client/tabs/tab_supervisor.cpp
src/client/tabs/tab_visual_database_display.cpp
src/client/tabs/visual_deck_editor/tab_deck_editor_visual.cpp
src/client/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.cpp
src/client/tabs/visual_deck_storage/tab_deck_storage_visual.cpp
src/client/tapped_out_interface.cpp
src/client/translate_counter_name.cpp
src/client/ui/layouts/flow_layout.cpp
src/client/ui/layouts/overlap_layout.cpp
src/client/ui/line_edit_completer.cpp
src/client/ui/phases_toolbar.cpp
src/client/ui/picture_loader/picture_loader.cpp
src/client/ui/picture_loader/picture_loader_worker.cpp
src/client/ui/picture_loader/picture_to_load.cpp
src/client/ui/pixel_map_generator.cpp
src/client/ui/theme_manager.cpp
src/client/ui/tip_of_the_day.cpp
src/client/ui/widgets/cards/additional_info/color_identity_widget.cpp
src/client/ui/widgets/cards/additional_info/mana_cost_widget.cpp
src/client/ui/widgets/cards/additional_info/mana_symbol_widget.cpp
src/client/ui/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp
src/client/ui/widgets/cards/card_group_display_widgets/flat_card_group_display_widget.cpp
src/client/ui/widgets/cards/card_group_display_widgets/overlapped_card_group_display_widget.cpp
src/client/ui/widgets/cards/card_info_display_widget.cpp
src/client/ui/widgets/cards/card_info_frame_widget.cpp
src/client/ui/widgets/cards/card_info_picture_enlarged_widget.cpp
src/client/ui/widgets/cards/card_info_picture_widget.cpp
src/client/ui/widgets/cards/card_info_picture_with_text_overlay_widget.cpp
src/client/ui/widgets/cards/card_info_text_widget.cpp
src/client/ui/widgets/cards/card_size_widget.cpp
src/client/ui/widgets/cards/deck_card_zone_display_widget.cpp
src/client/ui/widgets/cards/deck_preview_card_picture_widget.cpp
src/client/ui/widgets/deck_analytics/deck_analytics_widget.cpp
src/client/ui/widgets/deck_analytics/mana_base_widget.cpp
src/client/ui/widgets/deck_analytics/mana_curve_widget.cpp
src/client/ui/widgets/deck_analytics/mana_devotion_widget.cpp
src/client/ui/widgets/deck_editor/deck_editor_card_info_dock_widget.cpp
src/client/ui/widgets/deck_editor/deck_editor_database_display_widget.cpp
src/client/ui/widgets/deck_editor/deck_editor_deck_dock_widget.cpp
src/client/ui/widgets/deck_editor/deck_editor_filter_dock_widget.cpp
src/client/ui/widgets/deck_editor/deck_editor_printing_selector_dock_widget.cpp
src/client/ui/widgets/general/display/banner_widget.cpp
src/client/ui/widgets/general/display/bar_widget.cpp
src/client/ui/widgets/general/display/dynamic_font_size_label.cpp
src/client/ui/widgets/general/display/dynamic_font_size_push_button.cpp
src/client/ui/widgets/general/display/labeled_input.cpp
src/client/ui/widgets/general/display/shadow_background_label.cpp
src/client/ui/widgets/general/layout_containers/flow_widget.cpp
src/client/ui/widgets/general/layout_containers/overlap_control_widget.cpp
src/client/ui/widgets/general/layout_containers/overlap_widget.cpp
src/client/ui/widgets/printing_selector/all_zones_card_amount_widget.cpp
src/client/ui/widgets/printing_selector/card_amount_widget.cpp
src/client/ui/widgets/printing_selector/printing_selector.cpp
src/client/ui/widgets/printing_selector/printing_selector_card_display_widget.cpp
src/client/ui/widgets/printing_selector/printing_selector_card_overlay_widget.cpp
src/client/ui/widgets/printing_selector/printing_selector_card_search_widget.cpp
src/client/ui/widgets/printing_selector/printing_selector_card_selection_widget.cpp
src/client/ui/widgets/printing_selector/printing_selector_card_sorting_widget.cpp
src/client/ui/widgets/printing_selector/set_name_and_collectors_number_display_widget.cpp
src/client/ui/widgets/quick_settings/settings_button_widget.cpp
src/client/ui/widgets/quick_settings/settings_popup_widget.cpp
src/client/ui/widgets/visual_database_display/visual_database_display_widget.cpp
src/client/ui/widgets/visual_database_display/visual_database_display_color_filter_widget.cpp
src/client/ui/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.cpp
src/client/ui/widgets/visual_database_display/visual_database_display_name_filter_widget.cpp
src/client/ui/widgets/visual_database_display/visual_database_display_main_type_filter_widget.cpp
src/client/ui/widgets/visual_database_display/visual_database_display_set_filter_widget.cpp
src/client/ui/widgets/visual_database_display/visual_database_display_filter_save_load_widget.cpp
src/client/ui/widgets/visual_database_display/visual_database_filter_display_widget.cpp
src/client/ui/widgets/visual_deck_editor/visual_deck_editor_widget.cpp
src/client/ui/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_dialog.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_item_widget.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.cpp
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_search_widget.cpp
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_sort_widget.cpp
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.cpp
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_widget.cpp
src/client/ui/window_main.cpp
src/client/update_downloader.cpp
src/deck/custom_line_edit.cpp
src/deck/deck_list_model.cpp
src/deck/deck_loader.cpp
src/deck/deck_stats_interface.cpp
src/dialogs/dlg_connect.cpp
src/dialogs/dlg_convert_deck_to_cod_format.cpp
src/dialogs/dlg_create_game.cpp
src/dialogs/dlg_create_token.cpp
src/dialogs/dlg_edit_avatar.cpp
src/dialogs/dlg_edit_password.cpp
src/dialogs/dlg_edit_tokens.cpp
src/dialogs/dlg_edit_user.cpp
src/dialogs/dlg_filter_games.cpp
src/dialogs/dlg_forgot_password_challenge.cpp
src/dialogs/dlg_forgot_password_request.cpp
src/dialogs/dlg_forgot_password_reset.cpp
src/dialogs/dlg_load_deck.cpp
src/dialogs/dlg_load_deck_from_clipboard.cpp
src/dialogs/dlg_load_remote_deck.cpp
src/dialogs/dlg_manage_sets.cpp
src/dialogs/dlg_move_top_cards_until.cpp
src/dialogs/dlg_register.cpp
src/dialogs/dlg_roll_dice.cpp
src/dialogs/dlg_settings.cpp
src/dialogs/dlg_tip_of_the_day.cpp
src/dialogs/dlg_update.cpp
src/dialogs/dlg_view_log.cpp
src/game/board/abstract_counter.cpp
src/game/board/abstract_graphics_item.cpp
src/game/board/arrow_item.cpp
src/game/board/arrow_target.cpp
src/game/board/counter_general.cpp
src/game/cards/abstract_card_drag_item.cpp
src/game/cards/abstract_card_item.cpp
src/game/cards/card_completer_proxy_model.cpp
src/game/cards/card_database.cpp
src/game/cards/card_database_manager.cpp
src/game/cards/card_database_model.cpp
src/game/cards/card_database_parser/card_database_parser.cpp
src/game/cards/card_database_parser/cockatrice_xml_3.cpp
src/game/cards/card_database_parser/cockatrice_xml_4.cpp
src/game/cards/card_drag_item.cpp
src/game/cards/card_info.cpp
src/game/cards/card_item.cpp
src/game/cards/card_list.cpp
src/game/cards/card_search_model.cpp
src/game/deckview/deck_view.cpp
src/game/deckview/deck_view_container.cpp
src/game/filters/filter_builder.cpp
src/game/filters/filter_card.cpp
src/game/filters/filter_string.cpp
src/game/filters/filter_tree.cpp
src/game/filters/filter_tree_model.cpp
src/game/filters/syntax_help.cpp
src/game/game_scene.cpp
src/game/game_selector.cpp
src/game/game_view.cpp
src/game/games_model.cpp
src/game/hand_counter.cpp
src/game/phase.cpp
src/game/player/player.cpp
src/game/player/player_list_widget.cpp
src/game/player/player_target.cpp
src/game/zones/card_zone.cpp
src/game/zones/hand_zone.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/main.cpp
src/server/chat_view/chat_view.cpp
src/server/handle_public_servers.cpp
src/server/local_client.cpp
src/server/local_server.cpp
src/server/local_server_interface.cpp
src/server/message_log_widget.cpp
src/server/pending_command.cpp
src/server/remote/remote_client.cpp
src/server/remote/remote_decklist_tree_widget.cpp
src/server/remote/remote_replay_list_tree_widget.cpp
src/server/user/user_context_menu.cpp
src/server/user/user_info_box.cpp
src/server/user/user_info_connection.cpp
src/server/user/user_list_manager.cpp
src/server/user/user_list_widget.cpp
src/settings/cache_settings.cpp
src/settings/card_database_settings.cpp
src/settings/card_override_settings.cpp
src/settings/debug_settings.cpp
src/settings/download_settings.cpp
src/settings/game_filters_settings.cpp
src/settings/layouts_settings.cpp
src/settings/message_settings.cpp
src/settings/recents_settings.cpp
src/settings/servers_settings.cpp
src/settings/settings_manager.cpp
src/settings/shortcut_treeview.cpp
src/settings/shortcuts_settings.cpp
src/utility/card_info_comparator.cpp
src/utility/levenshtein.cpp
src/utility/logger.cpp
src/utility/sequence_edit.cpp
)
add_subdirectory(sounds) add_subdirectory(sounds)
add_subdirectory(themes) add_subdirectory(themes)

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,9 @@
[Rules] [Rules]
# Uncomment a rule to disable logging for that category # The default log level is info
*.debug = false
# Uncomment a rule to disable logging for that category,
# or set .debug = true for that category to see debug level logs
# main = false # main = false
# qt_translator = false # qt_translator = false
@ -23,6 +27,7 @@
# servers_settings = false # servers_settings = false
# shortcuts_settings = false # shortcuts_settings = false
# local_client = false
# remote_client = false # remote_client = false
# player = false # player = false
@ -47,9 +52,11 @@
# card_info = false # card_info = false
# card_list = false # card_list = false
flow_layout.debug = false #flow_layout = false
flow_widget.debug = false #flow_widget = false
flow_widget.size.debug = false #flow_widget.size = false
# card_info_picture_widget = false
# pixel_map_generator = false # pixel_map_generator = false

View file

@ -3,14 +3,13 @@
#include "../../../settings/cache_settings.h" #include "../../../settings/cache_settings.h"
#include "../../../settings/shortcuts_settings.h" #include "../../../settings/shortcuts_settings.h"
DeckEditorMenu::DeckEditorMenu(QWidget *parent, AbstractTabDeckEditor *_deckEditor) DeckEditorMenu::DeckEditorMenu(AbstractTabDeckEditor *parent) : QMenu(parent), deckEditor(parent)
: QMenu(parent), deckEditor(_deckEditor)
{ {
aNewDeck = new QAction(QString(), this); aNewDeck = new QAction(QString(), this);
connect(aNewDeck, SIGNAL(triggered()), deckEditor, SLOT(actNewDeck())); connect(aNewDeck, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actNewDeck);
aLoadDeck = new QAction(QString(), this); aLoadDeck = new QAction(QString(), this);
connect(aLoadDeck, SIGNAL(triggered()), deckEditor, SLOT(actLoadDeck())); connect(aLoadDeck, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actLoadDeck);
loadRecentDeckMenu = new QMenu(this); loadRecentDeckMenu = new QMenu(this);
connect(&SettingsCache::instance().recents(), &RecentsSettings::recentlyOpenedDeckPathsChanged, this, connect(&SettingsCache::instance().recents(), &RecentsSettings::recentlyOpenedDeckPathsChanged, this,
@ -22,47 +21,50 @@ DeckEditorMenu::DeckEditorMenu(QWidget *parent, AbstractTabDeckEditor *_deckEdit
updateRecentlyOpened(); updateRecentlyOpened();
aSaveDeck = new QAction(QString(), this); aSaveDeck = new QAction(QString(), this);
connect(aSaveDeck, SIGNAL(triggered()), deckEditor, SLOT(actSaveDeck())); connect(aSaveDeck, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actSaveDeck);
aSaveDeckAs = new QAction(QString(), this); aSaveDeckAs = new QAction(QString(), this);
connect(aSaveDeckAs, SIGNAL(triggered()), deckEditor, SLOT(actSaveDeckAs())); connect(aSaveDeckAs, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actSaveDeckAs);
aLoadDeckFromClipboard = new QAction(QString(), this); aLoadDeckFromClipboard = new QAction(QString(), this);
connect(aLoadDeckFromClipboard, SIGNAL(triggered()), deckEditor, SLOT(actLoadDeckFromClipboard())); connect(aLoadDeckFromClipboard, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actLoadDeckFromClipboard);
aEditDeckInClipboard = new QAction(QString(), this); aEditDeckInClipboard = new QAction(QString(), this);
connect(aEditDeckInClipboard, SIGNAL(triggered()), deckEditor, SLOT(actEditDeckInClipboard())); connect(aEditDeckInClipboard, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actEditDeckInClipboard);
aEditDeckInClipboardRaw = new QAction(QString(), this); aEditDeckInClipboardRaw = new QAction(QString(), this);
connect(aEditDeckInClipboardRaw, SIGNAL(triggered()), deckEditor, SLOT(actEditDeckInClipboardRaw())); connect(aEditDeckInClipboardRaw, &QAction::triggered, deckEditor,
&AbstractTabDeckEditor::actEditDeckInClipboardRaw);
aSaveDeckToClipboard = new QAction(QString(), this); aSaveDeckToClipboard = new QAction(QString(), this);
connect(aSaveDeckToClipboard, SIGNAL(triggered()), deckEditor, SLOT(actSaveDeckToClipboard())); connect(aSaveDeckToClipboard, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actSaveDeckToClipboard);
aSaveDeckToClipboardNoSetInfo = new QAction(QString(), this); aSaveDeckToClipboardNoSetInfo = new QAction(QString(), this);
connect(aSaveDeckToClipboardNoSetInfo, SIGNAL(triggered()), deckEditor, SLOT(actSaveDeckToClipboardNoSetInfo())); connect(aSaveDeckToClipboardNoSetInfo, &QAction::triggered, deckEditor,
&AbstractTabDeckEditor::actSaveDeckToClipboardNoSetInfo);
aSaveDeckToClipboardRaw = new QAction(QString(), this); aSaveDeckToClipboardRaw = new QAction(QString(), this);
connect(aSaveDeckToClipboardRaw, SIGNAL(triggered()), deckEditor, SLOT(actSaveDeckToClipboardRaw())); connect(aSaveDeckToClipboardRaw, &QAction::triggered, deckEditor,
&AbstractTabDeckEditor::actSaveDeckToClipboardRaw);
aSaveDeckToClipboardRawNoSetInfo = new QAction(QString(), this); aSaveDeckToClipboardRawNoSetInfo = new QAction(QString(), this);
connect(aSaveDeckToClipboardRawNoSetInfo, SIGNAL(triggered()), deckEditor, connect(aSaveDeckToClipboardRawNoSetInfo, &QAction::triggered, deckEditor,
SLOT(actSaveDeckToClipboardRawNoSetInfo())); &AbstractTabDeckEditor::actSaveDeckToClipboardRawNoSetInfo);
aPrintDeck = new QAction(QString(), this); aPrintDeck = new QAction(QString(), this);
connect(aPrintDeck, SIGNAL(triggered()), deckEditor, SLOT(actPrintDeck())); connect(aPrintDeck, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actPrintDeck);
aExportDeckDecklist = new QAction(QString(), this); aExportDeckDecklist = new QAction(QString(), this);
connect(aExportDeckDecklist, SIGNAL(triggered()), deckEditor, SLOT(actExportDeckDecklist())); connect(aExportDeckDecklist, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actExportDeckDecklist);
aExportDeckDecklistXyz = new QAction(QString(), this); aExportDeckDecklistXyz = new QAction(QString(), this);
connect(aExportDeckDecklistXyz, SIGNAL(triggered()), deckEditor, SLOT(actExportDeckDecklistXyz())); connect(aExportDeckDecklistXyz, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actExportDeckDecklistXyz);
aAnalyzeDeckDeckstats = new QAction(QString(), this); aAnalyzeDeckDeckstats = new QAction(QString(), this);
connect(aAnalyzeDeckDeckstats, SIGNAL(triggered()), deckEditor, SLOT(actAnalyzeDeckDeckstats())); connect(aAnalyzeDeckDeckstats, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actAnalyzeDeckDeckstats);
aAnalyzeDeckTappedout = new QAction(QString(), this); aAnalyzeDeckTappedout = new QAction(QString(), this);
connect(aAnalyzeDeckTappedout, SIGNAL(triggered()), deckEditor, SLOT(actAnalyzeDeckTappedout())); connect(aAnalyzeDeckTappedout, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actAnalyzeDeckTappedout);
analyzeDeckMenu = new QMenu(this); analyzeDeckMenu = new QMenu(this);
analyzeDeckMenu->addAction(aExportDeckDecklist); analyzeDeckMenu->addAction(aExportDeckDecklist);
@ -103,7 +105,8 @@ DeckEditorMenu::DeckEditorMenu(QWidget *parent, AbstractTabDeckEditor *_deckEdit
addAction(aClose); addAction(aClose);
retranslateUi(); retranslateUi();
connect(&SettingsCache::instance().shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts())); connect(&SettingsCache::instance().shortcuts(), &ShortcutsSettings::shortCutChanged, this,
&DeckEditorMenu::refreshShortcuts);
refreshShortcuts(); refreshShortcuts();
} }

View file

@ -10,7 +10,7 @@ class DeckEditorMenu : public QMenu
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit DeckEditorMenu(QWidget *parent, AbstractTabDeckEditor *deckEditor); explicit DeckEditorMenu(AbstractTabDeckEditor *parent);
AbstractTabDeckEditor *deckEditor; AbstractTabDeckEditor *deckEditor;

View file

@ -38,7 +38,7 @@ ReleaseChannel::~ReleaseChannel()
void ReleaseChannel::checkForUpdates() void ReleaseChannel::checkForUpdates()
{ {
QString releaseChannelUrl = getReleaseChannelUrl(); QString releaseChannelUrl = getReleaseChannelUrl();
qCDebug(ReleaseChannelLog) << "Searching for updates on the channel: " << releaseChannelUrl; qCInfo(ReleaseChannelLog) << "Searching for updates on the channel: " << releaseChannelUrl;
response = netMan->get(QNetworkRequest(releaseChannelUrl)); response = netMan->get(QNetworkRequest(releaseChannelUrl));
connect(response, &QNetworkReply::finished, this, &ReleaseChannel::releaseListFinished); connect(response, &QNetworkReply::finished, this, &ReleaseChannel::releaseListFinished);
} }
@ -152,15 +152,15 @@ void StableReleaseChannel::releaseListFinished()
QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN); QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN);
QString myHash = QString(VERSION_COMMIT); QString myHash = QString(VERSION_COMMIT);
qCDebug(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash; qCInfo(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash;
qCDebug(ReleaseChannelLog) << "Got reply from release server, name=" << lastRelease->getName() qCInfo(ReleaseChannelLog) << "Got reply from release server, name=" << lastRelease->getName()
<< "desc=" << lastRelease->getDescriptionUrl() << "desc=" << lastRelease->getDescriptionUrl() << "date=" << lastRelease->getPublishDate()
<< "date=" << lastRelease->getPublishDate() << "url=" << lastRelease->getDownloadUrl(); << "url=" << lastRelease->getDownloadUrl();
const QString &tagName = resultMap["tag_name"].toString(); const QString &tagName = resultMap["tag_name"].toString();
QString url = QString(STABLETAG_URL) + tagName; QString url = QString(STABLETAG_URL) + tagName;
qCDebug(ReleaseChannelLog) << "Searching for commit hash corresponding to stable channel tag: " << tagName; qCInfo(ReleaseChannelLog) << "Searching for commit hash corresponding to stable channel tag: " << tagName;
response = netMan->get(QNetworkRequest(url)); response = netMan->get(QNetworkRequest(url));
connect(response, &QNetworkReply::finished, this, &StableReleaseChannel::tagListFinished); connect(response, &QNetworkReply::finished, this, &StableReleaseChannel::tagListFinished);
} }
@ -185,11 +185,11 @@ void StableReleaseChannel::tagListFinished()
} }
lastRelease->setCommitHash(resultMap["object"].toMap()["sha"].toString()); lastRelease->setCommitHash(resultMap["object"].toMap()["sha"].toString());
qCDebug(ReleaseChannelLog) << "Got reply from tag server, commit=" << lastRelease->getCommitHash(); qCInfo(ReleaseChannelLog) << "Got reply from tag server, commit=" << lastRelease->getCommitHash();
QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN); QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN);
QString myHash = QString(VERSION_COMMIT); QString myHash = QString(VERSION_COMMIT);
qCDebug(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash; qCInfo(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash;
const bool needToUpdate = (QString::compare(shortHash, myHash, Qt::CaseInsensitive) != 0); const bool needToUpdate = (QString::compare(shortHash, myHash, Qt::CaseInsensitive) != 0);
emit finishedCheck(needToUpdate, lastRelease->isCompatibleVersionFound(), lastRelease); emit finishedCheck(needToUpdate, lastRelease->isCompatibleVersionFound(), lastRelease);
@ -256,13 +256,13 @@ void BetaReleaseChannel::releaseListFinished()
lastRelease->setName(QString("%1 (%2)").arg(resultMap["tag_name"].toString()).arg(shortHash)); lastRelease->setName(QString("%1 (%2)").arg(resultMap["tag_name"].toString()).arg(shortHash));
lastRelease->setDescriptionUrl(QString(BETARELEASE_CHANGESURL).arg(VERSION_COMMIT, shortHash)); lastRelease->setDescriptionUrl(QString(BETARELEASE_CHANGESURL).arg(VERSION_COMMIT, shortHash));
qCDebug(ReleaseChannelLog) << "Got reply from release server, size=" << resultMap.size() qCInfo(ReleaseChannelLog) << "Got reply from release server, size=" << resultMap.size()
<< "name=" << lastRelease->getName() << "desc=" << lastRelease->getDescriptionUrl() << "name=" << lastRelease->getName() << "desc=" << lastRelease->getDescriptionUrl()
<< "commit=" << lastRelease->getCommitHash() << "date=" << lastRelease->getPublishDate(); << "commit=" << lastRelease->getCommitHash() << "date=" << lastRelease->getPublishDate();
QString betaBuildDownloadUrl = resultMap["assets_url"].toString(); QString betaBuildDownloadUrl = resultMap["assets_url"].toString();
qCDebug(ReleaseChannelLog) << "Searching for a corresponding file on the beta channel: " << betaBuildDownloadUrl; qCInfo(ReleaseChannelLog) << "Searching for a corresponding file on the beta channel: " << betaBuildDownloadUrl;
response = netMan->get(QNetworkRequest(betaBuildDownloadUrl)); response = netMan->get(QNetworkRequest(betaBuildDownloadUrl));
connect(response, &QNetworkReply::finished, this, &BetaReleaseChannel::fileListFinished); connect(response, &QNetworkReply::finished, this, &BetaReleaseChannel::fileListFinished);
} }
@ -282,7 +282,7 @@ void BetaReleaseChannel::fileListFinished()
QVariantList resultList = jsonResponse.toVariant().toList(); QVariantList resultList = jsonResponse.toVariant().toList();
QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN); QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN);
QString myHash = QString(VERSION_COMMIT); QString myHash = QString(VERSION_COMMIT);
qCDebug(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash; qCInfo(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash;
bool needToUpdate = (QString::compare(shortHash, myHash, Qt::CaseInsensitive) != 0); bool needToUpdate = (QString::compare(shortHash, myHash, Qt::CaseInsensitive) != 0);
bool compatibleVersion = false; bool compatibleVersion = false;
@ -299,7 +299,7 @@ void BetaReleaseChannel::fileListFinished()
if (downloadMatchesCurrentOS(*url)) { if (downloadMatchesCurrentOS(*url)) {
compatibleVersion = true; compatibleVersion = true;
lastRelease->setDownloadUrl(*url); lastRelease->setDownloadUrl(*url);
qCDebug(ReleaseChannelLog) << "Found compatible version url=" << *url; qCInfo(ReleaseChannelLog) << "Found compatible version url=" << *url;
break; break;
} }
} }

View file

@ -28,7 +28,7 @@ SpoilerBackgroundUpdater::SpoilerBackgroundUpdater(QObject *apParent) : QObject(
// File exists means we're in spoiler season // File exists means we're in spoiler season
startSpoilerDownloadProcess(SPOILERS_STATUS_URL, false); startSpoilerDownloadProcess(SPOILERS_STATUS_URL, false);
} else { } else {
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoilers Disabled"; qCInfo(SpoilerBackgroundUpdaterLog) << "Spoilers Disabled";
} }
} }
@ -67,7 +67,7 @@ void SpoilerBackgroundUpdater::actDownloadFinishedSpoilersFile()
reply->deleteLater(); reply->deleteLater();
emit spoilerCheckerDone(); emit spoilerCheckerDone();
} else { } else {
qCDebug(SpoilerBackgroundUpdaterLog) << "Error downloading spoilers file" << errorCode; qCWarning(SpoilerBackgroundUpdaterLog) << "Error downloading spoilers file" << errorCode;
emit spoilerCheckerDone(); emit spoilerCheckerDone();
} }
} }
@ -81,11 +81,11 @@ bool SpoilerBackgroundUpdater::deleteSpoilerFile()
// Delete the spoiler.xml file // Delete the spoiler.xml file
if (file.exists() && file.remove()) { if (file.exists() && file.remove()) {
qCDebug(SpoilerBackgroundUpdaterLog) << "Deleting spoiler.xml"; qCInfo(SpoilerBackgroundUpdaterLog) << "Deleting spoiler.xml";
return true; return true;
} }
qCDebug(SpoilerBackgroundUpdaterLog) << "Error: Spoiler.xml not found or not deleted"; qCInfo(SpoilerBackgroundUpdaterLog) << "Error: Spoiler.xml not found or not deleted";
return false; return false;
} }
@ -101,24 +101,24 @@ void SpoilerBackgroundUpdater::actCheckIfSpoilerSeasonEnabled()
trayIcon->showMessage(tr("Spoilers season has ended"), tr("Deleting spoiler.xml. Please run Oracle")); trayIcon->showMessage(tr("Spoilers season has ended"), tr("Deleting spoiler.xml. Please run Oracle"));
} }
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler Season Offline"; qCInfo(SpoilerBackgroundUpdaterLog) << "Spoiler Season Offline";
emit spoilerCheckerDone(); emit spoilerCheckerDone();
} else if (errorCode == QNetworkReply::NoError) { } else if (errorCode == QNetworkReply::NoError) {
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler Service Online"; qCInfo(SpoilerBackgroundUpdaterLog) << "Spoiler Service Online";
startSpoilerDownloadProcess(SPOILERS_URL, true); startSpoilerDownloadProcess(SPOILERS_URL, true);
} else if (errorCode == QNetworkReply::HostNotFoundError) { } else if (errorCode == QNetworkReply::HostNotFoundError) {
if (trayIcon) { if (trayIcon) {
trayIcon->showMessage(tr("Spoilers download failed"), tr("No internet connection")); trayIcon->showMessage(tr("Spoilers download failed"), tr("No internet connection"));
} }
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler download failed due to no internet connection"; qCWarning(SpoilerBackgroundUpdaterLog) << "Spoiler download failed due to no internet connection";
emit spoilerCheckerDone(); emit spoilerCheckerDone();
} else { } else {
if (trayIcon) { if (trayIcon) {
trayIcon->showMessage(tr("Spoilers download failed"), tr("Error") + " " + (short)errorCode); trayIcon->showMessage(tr("Spoilers download failed"), tr("Error") + " " + (short)errorCode);
} }
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler download failed with reason" << errorCode; qCWarning(SpoilerBackgroundUpdaterLog) << "Spoiler download failed with reason" << errorCode;
emit spoilerCheckerDone(); emit spoilerCheckerDone();
} }
} }
@ -139,19 +139,19 @@ bool SpoilerBackgroundUpdater::saveDownloadedFile(QByteArray data)
trayIcon->showMessage(tr("Spoilers already up to date"), tr("No new spoilers added")); trayIcon->showMessage(tr("Spoilers already up to date"), tr("No new spoilers added"));
} }
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoilers Up to Date"; qCInfo(SpoilerBackgroundUpdaterLog) << "Spoilers Up to Date";
return false; return false;
} }
QFile file(fileName); QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) { if (!file.open(QIODevice::WriteOnly)) {
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler Service Error: File open (w) failed for" << fileName; qCWarning(SpoilerBackgroundUpdaterLog) << "Spoiler Service Error: File open (w) failed for" << fileName;
file.close(); file.close();
return false; return false;
} }
if (file.write(data) == -1) { if (file.write(data) == -1) {
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler Service Error: File write (w) failed for" << fileName; qCWarning(SpoilerBackgroundUpdaterLog) << "Spoiler Service Error: File write (w) failed for" << fileName;
file.close(); file.close();
return false; return false;
} }
@ -159,7 +159,7 @@ bool SpoilerBackgroundUpdater::saveDownloadedFile(QByteArray data)
file.close(); file.close();
// Data written, so reload the card database // Data written, so reload the card database
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler Service Data Written"; qCInfo(SpoilerBackgroundUpdaterLog) << "Spoiler Service Data Written";
const auto reloadOk = QtConcurrent::run([] { CardDatabaseManager::getInstance()->loadCardDatabases(); }); const auto reloadOk = QtConcurrent::run([] { CardDatabaseManager::getInstance()->loadCardDatabases(); });
// If the user has notifications enabled, let them know // If the user has notifications enabled, let them know
@ -202,12 +202,12 @@ QByteArray SpoilerBackgroundUpdater::getHash(const QString fileName)
QCryptographicHash hash(QCryptographicHash::Algorithm::Md5); QCryptographicHash hash(QCryptographicHash::Algorithm::Md5);
hash.addData(bytes); hash.addData(bytes);
qCDebug(SpoilerBackgroundUpdaterLog) << "File Hash =" << hash.result(); qCInfo(SpoilerBackgroundUpdaterLog) << "File Hash =" << hash.result();
file.close(); file.close();
return hash.result(); return hash.result();
} else { } else {
qCDebug(SpoilerBackgroundUpdaterLog) << "getHash ReadOnly failed!"; qCWarning(SpoilerBackgroundUpdaterLog) << "getHash ReadOnly failed!";
file.close(); file.close();
return QByteArray(); return QByteArray();
} }
@ -221,7 +221,7 @@ QByteArray SpoilerBackgroundUpdater::getHash(QByteArray data)
QCryptographicHash hash(QCryptographicHash::Algorithm::Md5); QCryptographicHash hash(QCryptographicHash::Algorithm::Md5);
hash.addData(bytes); hash.addData(bytes);
qCDebug(SpoilerBackgroundUpdaterLog) << "Data Hash =" << hash.result(); qCInfo(SpoilerBackgroundUpdaterLog) << "Data Hash =" << hash.result();
return hash.result(); return hash.result();
} }

View file

@ -37,7 +37,7 @@ SoundEngine::~SoundEngine()
void SoundEngine::soundEnabledChanged() void SoundEngine::soundEnabledChanged()
{ {
if (SettingsCache::instance().getSoundEnabled()) { if (SettingsCache::instance().getSoundEnabled()) {
qCDebug(SoundEngineLog) << "SoundEngine: enabling sound with" << audioData.size() << "sounds"; qCInfo(SoundEngineLog) << "SoundEngine: enabling sound with" << audioData.size() << "sounds";
if (!player) { if (!player) {
player = new QMediaPlayer; player = new QMediaPlayer;
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
@ -46,7 +46,7 @@ void SoundEngine::soundEnabledChanged()
#endif #endif
} }
} else { } else {
qCDebug(SoundEngineLog) << "SoundEngine: disabling sound"; qCInfo(SoundEngineLog) << "SoundEngine: disabling sound";
if (player) { if (player) {
player->stop(); player->stop();
player->deleteLater(); player->deleteLater();
@ -90,7 +90,7 @@ void SoundEngine::ensureThemeDirectoryExists()
{ {
if (SettingsCache::instance().getSoundThemeName().isEmpty() || if (SettingsCache::instance().getSoundThemeName().isEmpty() ||
!getAvailableThemes().contains(SettingsCache::instance().getSoundThemeName())) { !getAvailableThemes().contains(SettingsCache::instance().getSoundThemeName())) {
qCDebug(SoundEngineLog) << "Sounds theme name not set, setting default value"; qCInfo(SoundEngineLog) << "Sounds theme name not set, setting default value";
SettingsCache::instance().setSoundThemeName(DEFAULT_THEME_NAME); SettingsCache::instance().setSoundThemeName(DEFAULT_THEME_NAME);
} }
} }
@ -131,7 +131,7 @@ QStringMap &SoundEngine::getAvailableThemes()
void SoundEngine::themeChangedSlot() void SoundEngine::themeChangedSlot()
{ {
QString themeName = SettingsCache::instance().getSoundThemeName(); QString themeName = SettingsCache::instance().getSoundThemeName();
qCDebug(SoundEngineLog) << "Sound theme changed:" << themeName; qCInfo(SoundEngineLog) << "Sound theme changed:" << themeName;
QDir dir = getAvailableThemes().value(themeName); QDir dir = getAvailableThemes().value(themeName);

View file

@ -30,6 +30,7 @@
#include <QMenuBar> #include <QMenuBar>
#include <QMessageBox> #include <QMessageBox>
#include <QPrintPreviewDialog> #include <QPrintPreviewDialog>
#include <QPrinter>
#include <QProcessEnvironment> #include <QProcessEnvironment>
#include <QPushButton> #include <QPushButton>
#include <QRegularExpression> #include <QRegularExpression>
@ -65,7 +66,8 @@ AbstractTabDeckEditor::AbstractTabDeckEditor(TabSupervisor *_tabSupervisor) : Ta
connect(filterDockWidget, &DeckEditorFilterDockWidget::clearAllDatabaseFilters, databaseDisplayDockWidget, connect(filterDockWidget, &DeckEditorFilterDockWidget::clearAllDatabaseFilters, databaseDisplayDockWidget,
&DeckEditorDatabaseDisplayWidget::clearAllDatabaseFilters); &DeckEditorDatabaseDisplayWidget::clearAllDatabaseFilters);
connect(&SettingsCache::instance().shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts())); connect(&SettingsCache::instance().shortcuts(), &ShortcutsSettings::shortCutChanged, this,
&AbstractTabDeckEditor::refreshShortcuts);
} }
void AbstractTabDeckEditor::updateCard(CardInfoPtr _card) void AbstractTabDeckEditor::updateCard(CardInfoPtr _card)
@ -124,8 +126,13 @@ void AbstractTabDeckEditor::actSwapCard(CardInfoPtr info, QString zoneName)
{ {
QString providerId = CardDatabaseManager::getInstance()->getSetInfoForCard(info).getProperty("uuid"); QString providerId = CardDatabaseManager::getInstance()->getSetInfoForCard(info).getProperty("uuid");
QString collectorNumber = CardDatabaseManager::getInstance()->getSetInfoForCard(info).getProperty("num"); QString collectorNumber = CardDatabaseManager::getInstance()->getSetInfoForCard(info).getProperty("num");
deckDockWidget->swapCard(
deckDockWidget->deckModel->findCard(info->getName(), zoneName, providerId, collectorNumber)); QModelIndex foundCard = deckDockWidget->deckModel->findCard(info->getName(), zoneName, providerId, collectorNumber);
if (!foundCard.isValid()) {
foundCard = deckDockWidget->deckModel->findCard(info->getName(), zoneName);
}
deckDockWidget->swapCard(foundCard);
} }
/** /**
@ -332,8 +339,7 @@ bool AbstractTabDeckEditor::actSaveDeck()
cmd.set_deck_list(deckString.toStdString()); cmd.set_deck_list(deckString.toStdString());
PendingCommand *pend = AbstractClient::prepareSessionCommand(cmd); PendingCommand *pend = AbstractClient::prepareSessionCommand(cmd);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, connect(pend, &PendingCommand::finished, this, &AbstractTabDeckEditor::saveDeckRemoteFinished);
SLOT(saveDeckRemoteFinished(Response)));
tabSupervisor->getClient()->sendCommand(pend); tabSupervisor->getClient()->sendCommand(pend);
return true; return true;
@ -357,6 +363,7 @@ bool AbstractTabDeckEditor::actSaveDeckAs()
dialog.setDefaultSuffix("cod"); dialog.setDefaultSuffix("cod");
dialog.setNameFilters(DeckLoader::FILE_NAME_FILTERS); dialog.setNameFilters(DeckLoader::FILE_NAME_FILTERS);
dialog.selectFile(getDeckList()->getName().trimmed()); dialog.selectFile(getDeckList()->getName().trimmed());
if (!dialog.exec()) if (!dialog.exec())
return false; return false;
@ -451,7 +458,7 @@ void AbstractTabDeckEditor::actSaveDeckToClipboardRawNoSetInfo()
void AbstractTabDeckEditor::actPrintDeck() void AbstractTabDeckEditor::actPrintDeck()
{ {
auto *dlg = new QPrintPreviewDialog(this); auto *dlg = new QPrintPreviewDialog(this);
connect(dlg, SIGNAL(paintRequested(QPrinter *)), deckDockWidget->deckModel, SLOT(printDeckList(QPrinter *))); connect(dlg, &QPrintPreviewDialog::paintRequested, deckDockWidget->deckModel, &DeckListModel::printDeckList);
dlg->exec(); dlg->exec();
} }

View file

@ -1,7 +1,7 @@
#ifndef TAB_GENERIC_DECK_EDITOR_H #ifndef TAB_GENERIC_DECK_EDITOR_H
#define TAB_GENERIC_DECK_EDITOR_H #define TAB_GENERIC_DECK_EDITOR_H
#include "../../game/cards/card_database.h" #include "../../game/cards/card_info.h"
#include "../menus/deck_editor/deck_editor_menu.h" #include "../menus/deck_editor/deck_editor_menu.h"
#include "../ui/widgets/deck_editor/deck_editor_card_info_dock_widget.h" #include "../ui/widgets/deck_editor/deck_editor_card_info_dock_widget.h"
#include "../ui/widgets/deck_editor/deck_editor_database_display_widget.h" #include "../ui/widgets/deck_editor/deck_editor_database_display_widget.h"
@ -44,6 +44,8 @@ class AbstractTabDeckEditor : public Tab
{ {
Q_OBJECT Q_OBJECT
friend class DeckEditorMenu;
public: public:
explicit AbstractTabDeckEditor(TabSupervisor *_tabSupervisor); explicit AbstractTabDeckEditor(TabSupervisor *_tabSupervisor);
@ -67,7 +69,7 @@ public:
DeckEditorPrintingSelectorDockWidget *printingSelectorDockWidget; DeckEditorPrintingSelectorDockWidget *printingSelectorDockWidget;
public slots: public slots:
void onDeckChanged(); virtual void onDeckChanged();
void updateCard(CardInfoPtr _card); void updateCard(CardInfoPtr _card);
void actAddCard(CardInfoPtr info); void actAddCard(CardInfoPtr info);
void actAddCardToSideboard(CardInfoPtr info); void actAddCardToSideboard(CardInfoPtr info);
@ -90,7 +92,7 @@ protected slots:
void cleanDeckAndResetModified(); void cleanDeckAndResetModified();
virtual void actLoadDeck(); virtual void actLoadDeck();
bool actSaveDeck(); bool actSaveDeck();
bool actSaveDeckAs(); virtual bool actSaveDeckAs();
virtual void actLoadDeckFromClipboard(); virtual void actLoadDeckFromClipboard();
void actEditDeckInClipboard(); void actEditDeckInClipboard();
void actEditDeckInClipboardRaw(); void actEditDeckInClipboardRaw();

View file

@ -0,0 +1,47 @@
#include "edhrec_average_deck_api_response.h"
#include <QDebug>
#include <QJsonArray>
void EdhrecAverageDeckApiResponse::fromJson(const QJsonObject &json)
{
// Parse the collapsed DeckStatistics
deckStats.fromJson(json);
// Parse Archidekt section
QJsonArray archidektJson = json.value("archidekt").toArray();
archidekt.fromJson(archidektJson);
// Parse other fields
similar = json.value("similar").toObject();
header = json.value("header").toString();
panels = json.value("panels").toObject();
description = json.value("description").toString();
QJsonObject containerJson = json.value("container").toObject();
container.fromJson(containerJson);
QJsonArray cardsJson = json.value("deck").toArray();
deck.fromJson(cardsJson);
}
void EdhrecAverageDeckApiResponse::debugPrint() const
{
qDebug() << "Deck Statistics:";
qDebug() << " Creature:" << deckStats.creature;
qDebug() << " Instant:" << deckStats.instant;
qDebug() << " Sorcery:" << deckStats.sorcery;
qDebug() << " Artifact:" << deckStats.artifact;
qDebug() << " Enchantment:" << deckStats.enchantment;
qDebug() << " Battle:" << deckStats.battle;
qDebug() << " Planeswalker:" << deckStats.planeswalker;
qDebug() << " Land:" << deckStats.land;
qDebug() << " Basic:" << deckStats.basic;
qDebug() << " Nonbasic:" << deckStats.nonbasic;
archidekt.debugPrint();
qDebug() << "Similar:" << similar;
qDebug() << "Header:" << header;
qDebug() << "Panels:" << panels;
qDebug() << "Description:" << description;
container.debugPrint();
}

View file

@ -0,0 +1,30 @@
#ifndef EDHREC_AVERAGE_DECK_API_RESPONSE_H
#define EDHREC_AVERAGE_DECK_API_RESPONSE_H
#include "../commander/edhrec_commander_api_response_archidekt_links.h"
#include "../commander/edhrec_commander_api_response_average_deck_statistics.h"
#include "../commander/edhrec_commander_api_response_card_container.h"
#include "edhrec_deck_api_response.h"
#include <QDebug>
#include <QJsonObject>
#include <QString>
// Represents the main structure of the JSON
class EdhrecAverageDeckApiResponse
{
public:
EdhrecCommanderApiResponseAverageDeckStatistics deckStats;
EdhrecCommanderApiResponseArchidektLinks archidekt;
QJsonObject similar;
QString header;
QJsonObject panels;
QString description;
EdhrecCommanderApiResponseCardContainer container;
EdhrecDeckApiResponse deck;
void fromJson(const QJsonObject &json);
void debugPrint() const;
};
#endif // EDHREC_AVERAGE_DECK_API_RESPONSE_H

View file

@ -0,0 +1,27 @@
#include "edhrec_deck_api_response.h"
#include "../../../../../../deck/deck_loader.h"
#include <QApplication>
#include <QDebug>
#include <QJsonArray>
#include <QJsonObject>
#include <QMainWindow>
void EdhrecDeckApiResponse::fromJson(const QJsonArray &json)
{
QString deckList;
for (const QJsonValue &cardlistValue : json) {
deckList += cardlistValue.toString() + "\n";
}
deckLoader = new DeckLoader();
QTextStream stream(&deckList);
deckLoader->loadFromStream_Plain(stream, true);
}
void EdhrecDeckApiResponse::debugPrint() const
{
qDebug() << "Breadcrumb:";
}

View file

@ -0,0 +1,27 @@
#ifndef EDHREC_DECK_API_RESPONSE_H
#define EDHREC_DECK_API_RESPONSE_H
#include "../../../../../../deck/deck_loader.h"
#include <QDebug>
#include <QJsonArray>
#include <QJsonObject>
#include <QString>
#include <QVector>
class EdhrecDeckApiResponse
{
public:
// Constructor
EdhrecDeckApiResponse() = default;
// Parse deck-related data from JSON
void fromJson(const QJsonArray &json);
// Debug method for logging
void debugPrint() const;
DeckLoader *deckLoader;
};
#endif // EDHREC_DECK_API_RESPONSE_H

View file

@ -0,0 +1,19 @@
#include "edhrec_top_cards_api_response.h"
#include <QDebug>
#include <QJsonArray>
void EdhrecTopCardsApiResponse::fromJson(const QJsonObject &json)
{
header = json.value("header").toString();
description = json.value("description").toString();
QJsonObject containerJson = json.value("container").toObject();
container.fromJson(containerJson);
}
void EdhrecTopCardsApiResponse::debugPrint() const
{
qDebug() << "Header:" << header;
qDebug() << "Description:" << description;
container.debugPrint();
}

View file

@ -0,0 +1,22 @@
#ifndef EDHREC_TOP_CARDS_API_RESPONSE_H
#define EDHREC_TOP_CARDS_API_RESPONSE_H
#include "../commander/edhrec_commander_api_response_card_container.h"
#include <QDebug>
#include <QJsonObject>
#include <QString>
// Represents the main structure of the JSON
class EdhrecTopCardsApiResponse
{
public:
QString header;
QString description;
EdhrecCommanderApiResponseCardContainer container;
void fromJson(const QJsonObject &json);
void debugPrint() const;
};
#endif // EDHREC_TOP_CARDS_API_RESPONSE_H

View file

@ -0,0 +1,19 @@
#include "edhrec_top_commanders_api_response.h"
#include <QDebug>
#include <QJsonArray>
void EdhrecTopCommandersApiResponse::fromJson(const QJsonObject &json)
{
header = json.value("header").toString();
description = json.value("description").toString();
QJsonObject containerJson = json.value("container").toObject();
container.fromJson(containerJson);
}
void EdhrecTopCommandersApiResponse::debugPrint() const
{
qDebug() << "Header:" << header;
qDebug() << "Description:" << description;
container.debugPrint();
}

View file

@ -0,0 +1,22 @@
#ifndef EDHREC_TOP_COMMANDERS_API_RESPONSE_H
#define EDHREC_TOP_COMMANDERS_API_RESPONSE_H
#include "../commander/edhrec_commander_api_response_card_container.h"
#include <QDebug>
#include <QJsonObject>
#include <QString>
// Represents the main structure of the JSON
class EdhrecTopCommandersApiResponse
{
public:
QString header;
QString description;
EdhrecCommanderApiResponseCardContainer container;
void fromJson(const QJsonObject &json);
void debugPrint() const;
};
#endif // EDHREC_TOP_COMMANDERS_API_RESPONSE_H

View file

@ -0,0 +1,19 @@
#include "edhrec_top_tags_api_response.h"
#include <QDebug>
#include <QJsonArray>
void EdhrecTopTagsApiResponse::fromJson(const QJsonObject &json)
{
header = json.value("header").toString();
description = json.value("description").toString();
QJsonObject containerJson = json.value("container").toObject();
container.fromJson(containerJson);
}
void EdhrecTopTagsApiResponse::debugPrint() const
{
qDebug() << "Header:" << header;
qDebug() << "Description:" << description;
container.debugPrint();
}

View file

@ -0,0 +1,22 @@
#ifndef EDHREC_TOP_TAGS_API_RESPONSE_H
#define EDHREC_TOP_TAGS_API_RESPONSE_H
#include "../commander/edhrec_commander_api_response_card_container.h"
#include <QDebug>
#include <QJsonObject>
#include <QString>
// Represents the main structure of the JSON
class EdhrecTopTagsApiResponse
{
public:
QString header;
QString description;
EdhrecCommanderApiResponseCardContainer container;
void fromJson(const QJsonObject &json);
void debugPrint() const;
};
#endif // EDHREC_TOP_TAGS_API_RESPONSE_H

View file

@ -1,6 +1,7 @@
#include "edhrec_commander_api_response_card_details_display_widget.h" #include "edhrec_commander_api_response_card_details_display_widget.h"
#include "../../../../game/cards/card_database_manager.h" #include "../../../../../../game/cards/card_database_manager.h"
#include "../../tab_edhrec_main.h"
EdhrecCommanderApiResponseCardDetailsDisplayWidget::EdhrecCommanderApiResponseCardDetailsDisplayWidget( EdhrecCommanderApiResponseCardDetailsDisplayWidget::EdhrecCommanderApiResponseCardDetailsDisplayWidget(
QWidget *parent, QWidget *parent,
@ -11,14 +12,17 @@ EdhrecCommanderApiResponseCardDetailsDisplayWidget::EdhrecCommanderApiResponseCa
setLayout(layout); setLayout(layout);
cardPictureWidget = new CardInfoPictureWidget(this); cardPictureWidget = new CardInfoPictureWidget(this);
cardPictureWidget->setCard(CardDatabaseManager::getInstance()->getCard(toDisplay.name)); cardPictureWidget->setCard(CardDatabaseManager::getInstance()->guessCard(toDisplay.sanitized));
label = new QLabel(this); label = new QLabel(this);
label->setText(toDisplay.name + "\n" + toDisplay.label); label->setText(toDisplay.name + "\n" + toDisplay.label);
label->setAlignment(Qt::AlignHCenter); label->setAlignment(Qt::AlignHCenter);
int inclusionRate = 0;
// Set label color based on inclusion rate // Set label color based on inclusion rate
int inclusionRate = (toDisplay.numDecks * 100) / toDisplay.potentialDecks; if (toDisplay.potentialDecks != 0) {
inclusionRate = (toDisplay.numDecks * 100) / toDisplay.potentialDecks;
}
QColor labelColor; QColor labelColor;
if (inclusionRate <= 30) { if (inclusionRate <= 30) {
@ -38,4 +42,26 @@ EdhrecCommanderApiResponseCardDetailsDisplayWidget::EdhrecCommanderApiResponseCa
layout->addWidget(cardPictureWidget); layout->addWidget(cardPictureWidget);
layout->addWidget(label); layout->addWidget(label);
QWidget *currentParent = parentWidget();
TabEdhRecMain *parentTab = nullptr;
while (currentParent) {
if ((parentTab = qobject_cast<TabEdhRecMain *>(currentParent))) {
break;
}
currentParent = currentParent->parentWidget();
}
if (parentTab) {
connect(cardPictureWidget, &CardInfoPictureWidget::cardClicked, this,
&EdhrecCommanderApiResponseCardDetailsDisplayWidget::actRequestPageNavigation);
connect(this, &EdhrecCommanderApiResponseCardDetailsDisplayWidget::requestUrl, parentTab,
&TabEdhRecMain::actNavigatePage);
}
}
void EdhrecCommanderApiResponseCardDetailsDisplayWidget::actRequestPageNavigation()
{
emit requestUrl(toDisplay.url);
} }

View file

@ -1,8 +1,8 @@
#ifndef EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H #ifndef EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H
#define EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H #define EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H
#include "../../../ui/widgets/cards/card_info_picture_widget.h" #include "../../../../../ui/widgets/cards/card_info_picture_widget.h"
#include "api_response/edhrec_commander_api_response_card_details.h" #include "../../api_response/commander/edhrec_commander_api_response_card_details.h"
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QLabel> #include <QLabel>
@ -15,6 +15,10 @@ public:
explicit EdhrecCommanderApiResponseCardDetailsDisplayWidget( explicit EdhrecCommanderApiResponseCardDetailsDisplayWidget(
QWidget *parent, QWidget *parent,
const EdhrecCommanderApiResponseCardDetails &_toDisplay); const EdhrecCommanderApiResponseCardDetails &_toDisplay);
public slots:
void actRequestPageNavigation();
signals:
void requestUrl(QString url);
private: private:
EdhrecCommanderApiResponseCardDetails toDisplay; EdhrecCommanderApiResponseCardDetails toDisplay;

View file

@ -1,6 +1,6 @@
#include "edhrec_commander_api_response_card_list_display_widget.h" #include "edhrec_commander_api_response_card_list_display_widget.h"
#include "../../../ui/widgets/general/display/banner_widget.h" #include "../../../../../ui/widgets/general/display/banner_widget.h"
#include "edhrec_commander_api_response_card_details_display_widget.h" #include "edhrec_commander_api_response_card_details_display_widget.h"
#include <QLabel> #include <QLabel>

View file

@ -1,9 +1,9 @@
#ifndef EDHREC_COMMANDER_API_RESPONSE_CARD_LIST_DISPLAY_WIDGET_H #ifndef EDHREC_COMMANDER_API_RESPONSE_CARD_LIST_DISPLAY_WIDGET_H
#define EDHREC_COMMANDER_API_RESPONSE_CARD_LIST_DISPLAY_WIDGET_H #define EDHREC_COMMANDER_API_RESPONSE_CARD_LIST_DISPLAY_WIDGET_H
#include "../../../ui/widgets/general/display/banner_widget.h" #include "../../../../../ui/widgets/general/display/banner_widget.h"
#include "../../../ui/widgets/general/layout_containers/flow_widget.h" #include "../../../../../ui/widgets/general/layout_containers/flow_widget.h"
#include "api_response/edhrec_commander_api_response_card_list.h" #include "../../api_response/commander/edhrec_commander_api_response_card_list.h"
#include <QResizeEvent> #include <QResizeEvent>
#include <QVBoxLayout> #include <QVBoxLayout>

View file

@ -0,0 +1,75 @@
#include "edhrec_commander_api_response_commander_details_display_widget.h"
#include "../../../../../../game/cards/card_database_manager.h"
#include "../../../../../ui/widgets/cards/card_info_picture_widget.h"
#include "../../tab_edhrec_main.h"
#include <QLabel>
#include <QPushButton>
EdhrecCommanderResponseCommanderDetailsDisplayWidget::EdhrecCommanderResponseCommanderDetailsDisplayWidget(
QWidget *parent,
const EdhrecCommanderApiResponseCommanderDetails &_commanderDetails)
: QWidget(parent), commanderDetails(_commanderDetails)
{
layout = new QVBoxLayout(this);
setLayout(layout);
commanderPicture = new CardInfoPictureWidget(this);
commanderPicture->setCard(CardDatabaseManager::getInstance()->getCard(commanderDetails.getName()));
commanderDetails.debugPrint();
label = new QLabel(this);
label->setAlignment(Qt::AlignCenter);
salt = new QLabel(this);
salt->setAlignment(Qt::AlignCenter);
comboPushButton = new QPushButton(this);
averageDeckPushButton = new QPushButton(this);
layout->addWidget(commanderPicture);
layout->addWidget(label);
layout->addWidget(salt);
layout->addWidget(comboPushButton);
layout->addWidget(averageDeckPushButton);
QWidget *currentParent = parentWidget();
TabEdhRecMain *parentTab = nullptr;
while (currentParent) {
if ((parentTab = qobject_cast<TabEdhRecMain *>(currentParent))) {
break;
}
currentParent = currentParent->parentWidget();
}
if (parentTab) {
connect(comboPushButton, &QPushButton::clicked, this,
&EdhrecCommanderResponseCommanderDetailsDisplayWidget::actRequestComboNavigation);
connect(averageDeckPushButton, &QPushButton::clicked, this,
&EdhrecCommanderResponseCommanderDetailsDisplayWidget::actRequestAverageDeckNavigation);
connect(this, &EdhrecCommanderResponseCommanderDetailsDisplayWidget::requestUrl, parentTab,
&TabEdhRecMain::actNavigatePage);
}
retranslateUi();
}
void EdhrecCommanderResponseCommanderDetailsDisplayWidget::retranslateUi()
{
label->setText(commanderDetails.getLabel());
salt->setText(tr("Salt: ") + QString::number(commanderDetails.getSalt()));
comboPushButton->setText(tr("Combos"));
averageDeckPushButton->setText(tr("Average Deck"));
}
void EdhrecCommanderResponseCommanderDetailsDisplayWidget::actRequestComboNavigation()
{
emit requestUrl("/combos/" + commanderDetails.getSanitized());
}
void EdhrecCommanderResponseCommanderDetailsDisplayWidget::actRequestAverageDeckNavigation()
{
emit requestUrl("/average-decks/" + commanderDetails.getSanitized());
}

View file

@ -1,10 +1,11 @@
#ifndef EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_DISPLAY_WIDGET_H #ifndef EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_DISPLAY_WIDGET_H
#define EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_DISPLAY_WIDGET_H #define EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_DISPLAY_WIDGET_H
#include "../../../ui/widgets/cards/card_info_picture_widget.h" #include "../../../../../ui/widgets/cards/card_info_picture_widget.h"
#include "api_response/edhrec_commander_api_response_commander_details.h" #include "../../api_response/commander/edhrec_commander_api_response_commander_details.h"
#include <QLabel> #include <QLabel>
#include <QPushButton>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QWidget> #include <QWidget>
@ -17,9 +18,17 @@ public:
const EdhrecCommanderApiResponseCommanderDetails &_commanderDetails); const EdhrecCommanderApiResponseCommanderDetails &_commanderDetails);
void retranslateUi(); void retranslateUi();
public slots:
void actRequestComboNavigation();
void actRequestAverageDeckNavigation();
signals:
void requestUrl(QString url);
private: private:
QLabel *label; QLabel *label;
QLabel *salt; QLabel *salt;
QPushButton *comboPushButton;
QPushButton *averageDeckPushButton;
QVBoxLayout *layout; QVBoxLayout *layout;
CardInfoPictureWidget *commanderPicture; CardInfoPictureWidget *commanderPicture;
EdhrecCommanderApiResponseCommanderDetails commanderDetails; EdhrecCommanderApiResponseCommanderDetails commanderDetails;

View file

@ -1,7 +1,7 @@
#include "edhrec_commander_api_response_display_widget.h" #include "edhrec_commander_api_response_display_widget.h"
#include "../../../ui/widgets/cards/card_info_picture_widget.h" #include "../../../../../ui/widgets/cards/card_info_picture_widget.h"
#include "api_response/edhrec_commander_api_response.h" #include "../../api_response/commander/edhrec_commander_api_response.h"
#include "edhrec_commander_api_response_card_list_display_widget.h" #include "edhrec_commander_api_response_card_list_display_widget.h"
#include "edhrec_commander_api_response_commander_details_display_widget.h" #include "edhrec_commander_api_response_commander_details_display_widget.h"

View file

@ -1,7 +1,7 @@
#ifndef EDHREC_COMMANDER_API_RESPONSE_DISPLAY_WIDGET_H #ifndef EDHREC_COMMANDER_API_RESPONSE_DISPLAY_WIDGET_H
#define EDHREC_COMMANDER_API_RESPONSE_DISPLAY_WIDGET_H #define EDHREC_COMMANDER_API_RESPONSE_DISPLAY_WIDGET_H
#include "api_response/edhrec_commander_api_response.h" #include "../../api_response/commander/edhrec_commander_api_response.h"
#include <QScrollArea> #include <QScrollArea>
#include <QVBoxLayout> #include <QVBoxLayout>

View file

@ -0,0 +1,45 @@
#include "edhrec_top_cards_api_response_display_widget.h"
#include "../../api_response/top_cards/edhrec_top_cards_api_response.h"
#include "../commander/edhrec_commander_api_response_card_list_display_widget.h"
EdhrecTopCardsApiResponseDisplayWidget::EdhrecTopCardsApiResponseDisplayWidget(QWidget *parent,
EdhrecTopCardsApiResponse response)
: QWidget(parent)
{
layout = new QHBoxLayout(this);
setLayout(layout);
cardDisplayLayout = new QVBoxLayout(this);
// Add card list widgets
auto edhrec_commander_api_response_card_lists = response.container.getCardlists();
for (const EdhrecCommanderApiResponseCardList &card_list : edhrec_commander_api_response_card_lists) {
auto cardListDisplayWidget = new EdhrecCommanderApiResponseCardListDisplayWidget(this, card_list);
cardDisplayLayout->addWidget(cardListDisplayWidget);
}
// Create a QScrollArea to hold the card display widgets
scrollArea = new QScrollArea(this);
scrollArea->setWidgetResizable(true);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// Set the cardDisplayLayout inside the scroll area
auto scrollWidget = new QWidget(scrollArea);
scrollWidget->setLayout(cardDisplayLayout);
scrollArea->setWidget(scrollWidget);
layout->addWidget(scrollArea);
}
void EdhrecTopCardsApiResponseDisplayWidget::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
layout->invalidate();
layout->activate();
layout->update();
if (scrollArea && scrollArea->widget()) {
scrollArea->widget()->resize(event->size());
}
}

View file

@ -0,0 +1,25 @@
#ifndef EDHREC_TOP_CARDS_API_RESPONSE_DISPLAY_WIDGET_H
#define EDHREC_TOP_CARDS_API_RESPONSE_DISPLAY_WIDGET_H
#include "../../api_response/top_cards/edhrec_top_cards_api_response.h"
#include <QResizeEvent>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QWidget>
class EdhrecTopCardsApiResponseDisplayWidget : public QWidget
{
Q_OBJECT
public:
explicit EdhrecTopCardsApiResponseDisplayWidget(QWidget *parent, EdhrecTopCardsApiResponse response);
void resizeEvent(QResizeEvent *event) override;
private:
QHBoxLayout *layout;
QVBoxLayout *cardDisplayLayout;
QScrollArea *scrollArea;
};
#endif // EDHREC_TOP_CARDS_API_RESPONSE_DISPLAY_WIDGET_H

View file

@ -0,0 +1,47 @@
#include "edhrec_top_commanders_api_response_display_widget.h"
#include "../../api_response/top_commanders/edhrec_top_commanders_api_response.h"
#include "../commander/edhrec_commander_api_response_card_list_display_widget.h"
EdhrecTopCommandersApiResponseDisplayWidget::EdhrecTopCommandersApiResponseDisplayWidget(
QWidget *parent,
EdhrecTopCommandersApiResponse response)
: QWidget(parent)
{
layout = new QHBoxLayout(this);
setLayout(layout);
cardDisplayLayout = new QVBoxLayout(this);
// Add card list widgets
auto edhrec_commander_api_response_card_lists = response.container.getCardlists();
for (const EdhrecCommanderApiResponseCardList &card_list : edhrec_commander_api_response_card_lists) {
auto cardListDisplayWidget = new EdhrecCommanderApiResponseCardListDisplayWidget(this, card_list);
cardDisplayLayout->addWidget(cardListDisplayWidget);
}
// Create a QScrollArea to hold the card display widgets
scrollArea = new QScrollArea(this);
scrollArea->setWidgetResizable(true);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// Set the cardDisplayLayout inside the scroll area
auto scrollWidget = new QWidget(scrollArea);
scrollWidget->setLayout(cardDisplayLayout);
scrollArea->setWidget(scrollWidget);
layout->addWidget(scrollArea);
}
void EdhrecTopCommandersApiResponseDisplayWidget::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
qDebug() << event->size();
layout->invalidate();
layout->activate();
layout->update();
if (scrollArea && scrollArea->widget()) {
scrollArea->widget()->resize(event->size());
}
}

View file

@ -0,0 +1,25 @@
#ifndef EDHREC_TOP_COMMANDERS_API_RESPONSE_DISPLAY_WIDGET_H
#define EDHREC_TOP_COMMANDERS_API_RESPONSE_DISPLAY_WIDGET_H
#include "../../api_response/top_commanders/edhrec_top_commanders_api_response.h"
#include <QResizeEvent>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QWidget>
class EdhrecTopCommandersApiResponseDisplayWidget : public QWidget
{
Q_OBJECT
public:
explicit EdhrecTopCommandersApiResponseDisplayWidget(QWidget *parent, EdhrecTopCommandersApiResponse response);
void resizeEvent(QResizeEvent *event) override;
private:
QHBoxLayout *layout;
QVBoxLayout *cardDisplayLayout;
QScrollArea *scrollArea;
};
#endif // EDHREC_TOP_COMMANDERS_API_RESPONSE_DISPLAY_WIDGET_H

View file

@ -0,0 +1,45 @@
#include "edhrec_top_tags_api_response_display_widget.h"
#include "../../api_response/top_tags/edhrec_top_tags_api_response.h"
#include "../commander/edhrec_commander_api_response_card_list_display_widget.h"
EdhrecTopTagsApiResponseDisplayWidget::EdhrecTopTagsApiResponseDisplayWidget(QWidget *parent,
EdhrecTopTagsApiResponse response)
: QWidget(parent)
{
layout = new QHBoxLayout(this);
setLayout(layout);
cardDisplayLayout = new QVBoxLayout(this);
// Add card list widgets
auto edhrec_commander_api_response_card_lists = response.container.getCardlists();
for (const EdhrecCommanderApiResponseCardList &card_list : edhrec_commander_api_response_card_lists) {
auto cardListDisplayWidget = new EdhrecCommanderApiResponseCardListDisplayWidget(this, card_list);
cardDisplayLayout->addWidget(cardListDisplayWidget);
}
// Create a QScrollArea to hold the card display widgets
scrollArea = new QScrollArea(this);
scrollArea->setWidgetResizable(true);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// Set the cardDisplayLayout inside the scroll area
auto scrollWidget = new QWidget(scrollArea);
scrollWidget->setLayout(cardDisplayLayout);
scrollArea->setWidget(scrollWidget);
layout->addWidget(scrollArea);
}
void EdhrecTopTagsApiResponseDisplayWidget::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
layout->invalidate();
layout->activate();
layout->update();
if (scrollArea && scrollArea->widget()) {
scrollArea->widget()->resize(event->size());
}
}

View file

@ -0,0 +1,25 @@
#ifndef EDHREC_TOP_TAGS_API_RESPONSE_DISPLAY_WIDGET_H
#define EDHREC_TOP_TAGS_API_RESPONSE_DISPLAY_WIDGET_H
#include "../../api_response/top_tags/edhrec_top_tags_api_response.h"
#include <QResizeEvent>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QWidget>
class EdhrecTopTagsApiResponseDisplayWidget : public QWidget
{
Q_OBJECT
public:
explicit EdhrecTopTagsApiResponseDisplayWidget(QWidget *parent, EdhrecTopTagsApiResponse response);
void resizeEvent(QResizeEvent *event) override;
private:
QHBoxLayout *layout;
QVBoxLayout *cardDisplayLayout;
QScrollArea *scrollArea;
};
#endif // EDHREC_TOP_TAGS_API_RESPONSE_DISPLAY_WIDGET_H

View file

@ -1,36 +0,0 @@
#include "edhrec_commander_api_response_commander_details_display_widget.h"
#include "../../../../game/cards/card_database_manager.h"
#include "../../../ui/widgets/cards/card_info_picture_widget.h"
#include <QLabel>
EdhrecCommanderResponseCommanderDetailsDisplayWidget::EdhrecCommanderResponseCommanderDetailsDisplayWidget(
QWidget *parent,
const EdhrecCommanderApiResponseCommanderDetails &_commanderDetails)
: QWidget(parent), commanderDetails(_commanderDetails)
{
layout = new QVBoxLayout(this);
setLayout(layout);
commanderPicture = new CardInfoPictureWidget(this);
commanderPicture->setCard(CardDatabaseManager::getInstance()->getCard(commanderDetails.getName()));
commanderDetails.debugPrint();
label = new QLabel(this);
label->setAlignment(Qt::AlignCenter);
salt = new QLabel(this);
salt->setAlignment(Qt::AlignCenter);
layout->addWidget(commanderPicture);
layout->addWidget(label);
layout->addWidget(salt);
retranslateUi();
}
void EdhrecCommanderResponseCommanderDetailsDisplayWidget::retranslateUi()
{
label->setText(commanderDetails.getLabel());
salt->setText(tr("Salt: ") + QString::number(commanderDetails.getSalt()));
}

View file

@ -1,7 +1,7 @@
#include "tab_edhrec.h" #include "tab_edhrec.h"
#include "api_response/edhrec_commander_api_response.h" #include "api_response/commander/edhrec_commander_api_response.h"
#include "edhrec_commander_api_response_display_widget.h" #include "display/commander/edhrec_commander_api_response_display_widget.h"
#include <QDebug> #include <QDebug>
#include <QHBoxLayout> #include <QHBoxLayout>
@ -21,7 +21,7 @@ TabEdhRec::TabEdhRec(TabSupervisor *_tabSupervisor) : Tab(_tabSupervisor)
#endif #endif
networkManager->setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy); networkManager->setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy);
connect(networkManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(processApiJson(QNetworkReply *))); connect(networkManager, &QNetworkAccessManager::finished, this, &TabEdhRec::processApiJson);
} }
void TabEdhRec::retranslateUi() void TabEdhRec::retranslateUi()

View file

@ -1,12 +1,11 @@
#ifndef TAB_EDHREC_H #ifndef TAB_EDHREC_H
#define TAB_EDHREC_H #define TAB_EDHREC_H
#include "../../../../game/cards/card_database.h" #include "../../../../game/cards/card_info.h"
#include "../../../ui/widgets/general/layout_containers/flow_widget.h" #include "../../../ui/widgets/general/layout_containers/flow_widget.h"
#include "../../tab.h" #include "../../tab.h"
#include "edhrec_commander_api_response_display_widget.h" #include "display/commander/edhrec_commander_api_response_display_widget.h"
#include <QHBoxLayout>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
class TabEdhRec : public Tab class TabEdhRec : public Tab

View file

@ -0,0 +1,378 @@
#include "tab_edhrec_main.h"
#include "../../../../game/cards/card_completer_proxy_model.h"
#include "../../../../game/cards/card_database_manager.h"
#include "../../../../game/cards/card_search_model.h"
#include "../../tab_supervisor.h"
#include "api_response/average_deck/edhrec_average_deck_api_response.h"
#include "api_response/commander/edhrec_commander_api_response.h"
#include "api_response/top_cards/edhrec_top_cards_api_response.h"
#include "api_response/top_commanders/edhrec_top_commanders_api_response.h"
#include "api_response/top_tags/edhrec_top_tags_api_response.h"
#include "display/commander/edhrec_commander_api_response_display_widget.h"
#include "display/top_cards/edhrec_top_cards_api_response_display_widget.h"
#include "display/top_commander/edhrec_top_commanders_api_response_display_widget.h"
#include "display/top_tags/edhrec_top_tags_api_response_display_widget.h"
#include <QCompleter>
#include <QDebug>
#include <QHBoxLayout>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QPushButton>
#include <QRegularExpression>
#include <QResizeEvent>
static bool canBeCommander(const CardInfoPtr &cardInfo)
{
return ((cardInfo->getCardType().contains("Legendary", Qt::CaseInsensitive) &&
cardInfo->getCardType().contains("Creature", Qt::CaseInsensitive))) ||
cardInfo->getText().contains("can be your commander", Qt::CaseInsensitive);
}
TabEdhRecMain::TabEdhRecMain(TabSupervisor *_tabSupervisor) : Tab(_tabSupervisor)
{
networkManager = new QNetworkAccessManager(this);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
networkManager->setTransferTimeout(); // Use Qt's default timeout
#endif
networkManager->setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy);
connect(networkManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(processApiJson(QNetworkReply *)));
container = new QWidget(this);
mainLayout = new QVBoxLayout(container);
container->setLayout(mainLayout);
navigationContainer = new QWidget(container);
navigationContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
navigationLayout = new QHBoxLayout(navigationContainer);
navigationLayout->setSpacing(5);
navigationContainer->setLayout(navigationLayout);
cardsPushButton = new QPushButton(navigationContainer);
connect(cardsPushButton, &QPushButton::clicked, this, &TabEdhRecMain::getTopCards);
topCommandersPushButton = new QPushButton(navigationContainer);
connect(topCommandersPushButton, &QPushButton::clicked, this, &TabEdhRecMain::getTopCommanders);
tagsPushButton = new QPushButton(navigationContainer);
connect(tagsPushButton, &QPushButton::clicked, this, &TabEdhRecMain::getTopTags);
searchBar = new QLineEdit(this);
auto cardDatabaseModel = new CardDatabaseModel(CardDatabaseManager::getInstance(), false, this);
auto displayModel = new CardDatabaseDisplayModel(this);
displayModel->setSourceModel(cardDatabaseModel);
CardSearchModel *searchModel = new CardSearchModel(displayModel, this);
CardCompleterProxyModel *proxyModel = new CardCompleterProxyModel(this);
proxyModel->setSourceModel(searchModel);
proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
proxyModel->setFilterRole(Qt::DisplayRole);
QCompleter *completer = new QCompleter(proxyModel, this);
completer->setCompletionRole(Qt::DisplayRole);
completer->setCompletionMode(QCompleter::PopupCompletion);
completer->setCaseSensitivity(Qt::CaseInsensitive);
completer->setFilterMode(Qt::MatchContains);
completer->setMaxVisibleItems(10);
searchBar->setCompleter(completer);
// Update suggestions dynamically
connect(searchBar, &QLineEdit::textChanged, searchModel, &CardSearchModel::updateSearchResults);
connect(searchBar, &QLineEdit::textChanged, this, [=](const QString &text) {
// Ensure substring matching
QString pattern = ".*" + QRegularExpression::escape(text) + ".*";
proxyModel->setFilterRegularExpression(QRegularExpression(pattern, QRegularExpression::CaseInsensitiveOption));
if (!text.isEmpty()) {
completer->complete(); // Force the dropdown to appear
}
});
searchPushButton = new QPushButton(navigationContainer);
connect(searchPushButton, &QPushButton::clicked, this, [=, this]() { doSearch(); });
navigationLayout->addWidget(cardsPushButton);
navigationLayout->addWidget(topCommandersPushButton);
navigationLayout->addWidget(tagsPushButton);
navigationLayout->addWidget(searchBar);
navigationLayout->addWidget(searchPushButton);
currentPageDisplay = new QWidget(container);
currentPageLayout = new QVBoxLayout(currentPageDisplay);
currentPageDisplay->setLayout(currentPageLayout);
mainLayout->addWidget(navigationContainer);
mainLayout->addWidget(currentPageDisplay);
// Ensure navigation stays at the top and currentPageDisplay takes remaining space
mainLayout->setStretch(0, 0); // navigationContainer gets minimum space
mainLayout->setStretch(1, 1); // currentPageDisplay expands as much as possible
setCentralWidget(container);
TabEdhRecMain::retranslateUi();
getTopCards();
}
void TabEdhRecMain::retranslateUi()
{
cardsPushButton->setText(tr("&Cards"));
topCommandersPushButton->setText(tr("Top Commanders"));
tagsPushButton->setText(tr("Tags"));
searchBar->setPlaceholderText(tr("Search for a card ..."));
searchPushButton->setText(tr("Search"));
}
void TabEdhRecMain::doSearch()
{
CardInfoPtr searchedCard = CardDatabaseManager::getInstance()->getCard(searchBar->text());
if (!searchedCard) {
return;
}
setCard(searchedCard, canBeCommander(searchedCard));
}
void TabEdhRecMain::setCard(CardInfoPtr _cardToQuery, bool isCommander)
{
cardToQuery = _cardToQuery;
if (!cardToQuery) {
qDebug() << "Invalid card information provided.";
return;
}
QString cardName = cardToQuery->getName();
QString formattedName = cardName.toLower().replace(" ", "-").remove(QRegularExpression("[^a-z0-9\\-]"));
QString url;
if (isCommander) {
url = QString("https://json.edhrec.com/pages/commanders/%1.json").arg(formattedName);
} else {
url = QString("https://json.edhrec.com/pages/cards/%1.json").arg(formattedName);
}
QNetworkRequest request{QUrl(url)};
networkManager->get(request);
}
void TabEdhRecMain::actNavigatePage(QString url)
{
QNetworkRequest request{QUrl("https://json.edhrec.com/pages" + url + ".json")};
networkManager->get(request);
}
void TabEdhRecMain::getTopCards()
{
QNetworkRequest request{QUrl("https://json.edhrec.com/pages/top/year.json")};
networkManager->get(request);
}
void TabEdhRecMain::getTopCommanders()
{
QNetworkRequest request{QUrl("https://json.edhrec.com/pages/commanders/year.json")};
networkManager->get(request);
}
void TabEdhRecMain::getTopTags()
{
QNetworkRequest request{QUrl("https://json.edhrec.com/pages/tags.json")};
networkManager->get(request);
}
void TabEdhRecMain::processApiJson(QNetworkReply *reply)
{
if (reply->error() != QNetworkReply::NoError) {
qDebug() << "Network error occurred:" << reply->errorString();
reply->deleteLater();
return;
}
QByteArray responseData = reply->readAll();
QJsonDocument jsonDoc = QJsonDocument::fromJson(responseData);
if (!jsonDoc.isObject()) {
qDebug() << "Invalid JSON response received.";
reply->deleteLater();
return;
}
QJsonObject jsonObj = jsonDoc.object();
// Get the actual URL from the reply
QString responseUrl = reply->url().toString();
// Check if the response URL matches a commander request
if (responseUrl.startsWith("https://json.edhrec.com/pages/commanders/year.json")) {
processTopCommandersResponse(jsonObj);
} else if (responseUrl.startsWith("https://json.edhrec.com/pages/commanders/")) {
processCommanderResponse(jsonObj);
} else if (responseUrl.startsWith("https://json.edhrec.com/pages/cards/")) {
processCommanderResponse(jsonObj);
} else if (responseUrl.startsWith("https://json.edhrec.com/pages/tags/")) {
processCommanderResponse(jsonObj);
} else if (responseUrl.startsWith("https://json.edhrec.com/pages/tags.json")) {
processTopTagsResponse(jsonObj);
} else if (responseUrl.startsWith("https://json.edhrec.com/pages/top/year.json")) {
processTopCardsResponse(jsonObj);
} else if (responseUrl.startsWith("https://json.edhrec.com/pages/combos/")) {
processCommanderResponse(jsonObj);
} else if (responseUrl.startsWith("https://json.edhrec.com/pages/average-decks/")) {
processAverageDeckResponse(jsonObj);
} else {
prettyPrintJson(jsonObj, 4);
}
reply->deleteLater();
}
void TabEdhRecMain::processTopCardsResponse(QJsonObject reply)
{
EdhrecTopCardsApiResponse deckData;
deckData.fromJson(reply);
// **Remove previous page display to prevent stacking**
if (currentPageDisplay) {
mainLayout->removeWidget(currentPageDisplay);
delete currentPageDisplay;
currentPageDisplay = nullptr;
}
// **Create new currentPageDisplay**
currentPageDisplay = new QWidget(container);
currentPageLayout = new QVBoxLayout(currentPageDisplay);
currentPageDisplay->setLayout(currentPageLayout);
auto display = new EdhrecTopCardsApiResponseDisplayWidget(currentPageDisplay, deckData);
currentPageLayout->addWidget(display);
mainLayout->addWidget(currentPageDisplay);
// **Ensure layout stays correct**
mainLayout->setStretch(0, 0); // Keep navigationContainer at the top
mainLayout->setStretch(1, 1); // Make sure currentPageDisplay takes remaining space
}
void TabEdhRecMain::processTopTagsResponse(QJsonObject reply)
{
EdhrecTopTagsApiResponse deckData;
deckData.fromJson(reply);
// **Remove previous page display to prevent stacking**
if (currentPageDisplay) {
mainLayout->removeWidget(currentPageDisplay);
delete currentPageDisplay;
currentPageDisplay = nullptr;
}
// **Create new currentPageDisplay**
currentPageDisplay = new QWidget(container);
currentPageLayout = new QVBoxLayout(currentPageDisplay);
currentPageDisplay->setLayout(currentPageLayout);
auto display = new EdhrecTopTagsApiResponseDisplayWidget(currentPageDisplay, deckData);
currentPageLayout->addWidget(display);
mainLayout->addWidget(currentPageDisplay);
// **Ensure layout stays correct**
mainLayout->setStretch(0, 0); // Keep navigationContainer at the top
mainLayout->setStretch(1, 1); // Make sure currentPageDisplay takes remaining space
}
void TabEdhRecMain::processTopCommandersResponse(QJsonObject reply)
{
EdhrecTopCommandersApiResponse deckData;
deckData.fromJson(reply);
// **Remove previous page display to prevent stacking**
if (currentPageDisplay) {
mainLayout->removeWidget(currentPageDisplay);
delete currentPageDisplay;
currentPageDisplay = nullptr;
}
// **Create new currentPageDisplay**
currentPageDisplay = new QWidget(container);
currentPageLayout = new QVBoxLayout(currentPageDisplay);
currentPageDisplay->setLayout(currentPageLayout);
auto display = new EdhrecTopCommandersApiResponseDisplayWidget(currentPageDisplay, deckData);
currentPageLayout->addWidget(display);
mainLayout->addWidget(currentPageDisplay);
// **Ensure layout stays correct**
mainLayout->setStretch(0, 0); // Keep navigationContainer at the top
mainLayout->setStretch(1, 1); // Make sure currentPageDisplay takes remaining space
}
void TabEdhRecMain::processCommanderResponse(QJsonObject reply)
{
EdhrecCommanderApiResponse deckData;
deckData.fromJson(reply);
// **Remove previous page display to prevent stacking**
if (currentPageDisplay) {
mainLayout->removeWidget(currentPageDisplay);
delete currentPageDisplay;
currentPageDisplay = nullptr;
}
// **Create new currentPageDisplay**
currentPageDisplay = new QWidget(container);
currentPageLayout = new QVBoxLayout(currentPageDisplay);
currentPageDisplay->setLayout(currentPageLayout);
auto display = new EdhrecCommanderApiResponseDisplayWidget(currentPageDisplay, deckData);
currentPageLayout->addWidget(display);
mainLayout->addWidget(currentPageDisplay);
// **Ensure layout stays correct**
mainLayout->setStretch(0, 0); // Keep navigationContainer at the top
mainLayout->setStretch(1, 1); // Make sure currentPageDisplay takes remaining space
}
void TabEdhRecMain::processAverageDeckResponse(QJsonObject reply)
{
EdhrecAverageDeckApiResponse deckData;
deckData.fromJson(reply);
tabSupervisor->addVisualDeckEditorTab(deckData.deck.deckLoader);
}
void TabEdhRecMain::prettyPrintJson(const QJsonValue &value, int indentLevel)
{
const QString indent(indentLevel * 2, ' '); // Adjust spacing as needed for pretty printing
if (value.isObject()) {
QJsonObject obj = value.toObject();
for (auto it = obj.begin(); it != obj.end(); ++it) {
qDebug().noquote() << indent + it.key() + ":";
prettyPrintJson(it.value(), indentLevel + 1);
}
} else if (value.isArray()) {
QJsonArray array = value.toArray();
for (int i = 0; i < array.size(); ++i) {
qDebug().noquote() << indent + QString("[%1]:").arg(i);
prettyPrintJson(array[i], indentLevel + 1);
}
} else if (value.isString()) {
qDebug().noquote() << indent + "\"" + value.toString() + "\"";
} else if (value.isDouble()) {
qDebug().noquote() << indent + QString::number(value.toDouble());
} else if (value.isBool()) {
qDebug().noquote() << indent + (value.toBool() ? "true" : "false");
} else if (value.isNull()) {
qDebug().noquote() << indent + "null";
}
}

View file

@ -0,0 +1,61 @@
#ifndef TAB_EDHREC_MAIN_H
#define TAB_EDHREC_MAIN_H
#include "../../../../game/cards/card_database.h"
#include "../../../ui/widgets/general/layout_containers/flow_widget.h"
#include "../../tab.h"
#include "display/commander/edhrec_commander_api_response_display_widget.h"
#include <QHBoxLayout>
#include <QLineEdit>
#include <QNetworkAccessManager>
#include <QPushButton>
class TabEdhRecMain : public Tab
{
Q_OBJECT
public:
explicit TabEdhRecMain(TabSupervisor *_tabSupervisor);
void retranslateUi() override;
void doSearch();
QString getTabText() const override
{
auto cardName = cardToQuery.isNull() ? QString() : cardToQuery->getName();
return tr("EDHREC: ") + cardName;
}
QNetworkAccessManager *networkManager;
public slots:
void processApiJson(QNetworkReply *reply);
void processTopCardsResponse(QJsonObject reply);
void processTopTagsResponse(QJsonObject reply);
void processTopCommandersResponse(QJsonObject reply);
void processAverageDeckResponse(QJsonObject reply);
void prettyPrintJson(const QJsonValue &value, int indentLevel);
void setCard(CardInfoPtr _cardToQuery, bool isCommander = false);
void actNavigatePage(QString url);
void getTopCards();
void getTopCommanders();
void getTopTags();
private:
QWidget *container;
QWidget *navigationContainer;
QWidget *currentPageDisplay;
QVBoxLayout *mainLayout;
QHBoxLayout *navigationLayout;
QVBoxLayout *currentPageLayout;
QPushButton *cardsPushButton;
QPushButton *topCommandersPushButton;
QPushButton *tagsPushButton;
QLineEdit *searchBar;
QPushButton *searchPushButton;
CardInfoPtr cardToQuery;
EdhrecCommanderApiResponseDisplayWidget *displayWidget;
void processCommanderResponse(QJsonObject reply);
};
#endif // TAB_EDHREC_MAIN_H

View file

@ -55,7 +55,7 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor) : AbstractTabDeckEdi
void TabDeckEditor::createMenus() void TabDeckEditor::createMenus()
{ {
deckMenu = new DeckEditorMenu(this, this); deckMenu = new DeckEditorMenu(this);
addTabMenu(deckMenu); addTabMenu(deckMenu);
viewMenu = new QMenu(this); viewMenu = new QMenu(this);
@ -67,36 +67,36 @@ void TabDeckEditor::createMenus()
aCardInfoDockVisible = cardInfoDockMenu->addAction(QString()); aCardInfoDockVisible = cardInfoDockMenu->addAction(QString());
aCardInfoDockVisible->setCheckable(true); aCardInfoDockVisible->setCheckable(true);
connect(aCardInfoDockVisible, SIGNAL(triggered()), this, SLOT(dockVisibleTriggered())); connect(aCardInfoDockVisible, &QAction::triggered, this, &TabDeckEditor::dockVisibleTriggered);
aCardInfoDockFloating = cardInfoDockMenu->addAction(QString()); aCardInfoDockFloating = cardInfoDockMenu->addAction(QString());
aCardInfoDockFloating->setCheckable(true); aCardInfoDockFloating->setCheckable(true);
connect(aCardInfoDockFloating, SIGNAL(triggered()), this, SLOT(dockFloatingTriggered())); connect(aCardInfoDockFloating, &QAction::triggered, this, &TabDeckEditor::dockFloatingTriggered);
aDeckDockVisible = deckDockMenu->addAction(QString()); aDeckDockVisible = deckDockMenu->addAction(QString());
aDeckDockVisible->setCheckable(true); aDeckDockVisible->setCheckable(true);
connect(aDeckDockVisible, SIGNAL(triggered()), this, SLOT(dockVisibleTriggered())); connect(aDeckDockVisible, &QAction::triggered, this, &TabDeckEditor::dockVisibleTriggered);
aDeckDockFloating = deckDockMenu->addAction(QString()); aDeckDockFloating = deckDockMenu->addAction(QString());
aDeckDockFloating->setCheckable(true); aDeckDockFloating->setCheckable(true);
connect(aDeckDockFloating, SIGNAL(triggered()), this, SLOT(dockFloatingTriggered())); connect(aDeckDockFloating, &QAction::triggered, this, &TabDeckEditor::dockFloatingTriggered);
aFilterDockVisible = filterDockMenu->addAction(QString()); aFilterDockVisible = filterDockMenu->addAction(QString());
aFilterDockVisible->setCheckable(true); aFilterDockVisible->setCheckable(true);
connect(aFilterDockVisible, SIGNAL(triggered()), this, SLOT(dockVisibleTriggered())); connect(aFilterDockVisible, &QAction::triggered, this, &TabDeckEditor::dockVisibleTriggered);
aFilterDockFloating = filterDockMenu->addAction(QString()); aFilterDockFloating = filterDockMenu->addAction(QString());
aFilterDockFloating->setCheckable(true); aFilterDockFloating->setCheckable(true);
connect(aFilterDockFloating, SIGNAL(triggered()), this, SLOT(dockFloatingTriggered())); connect(aFilterDockFloating, &QAction::triggered, this, &TabDeckEditor::dockFloatingTriggered);
aPrintingSelectorDockVisible = printingSelectorDockMenu->addAction(QString()); aPrintingSelectorDockVisible = printingSelectorDockMenu->addAction(QString());
aPrintingSelectorDockVisible->setCheckable(true); aPrintingSelectorDockVisible->setCheckable(true);
connect(aPrintingSelectorDockVisible, SIGNAL(triggered()), this, SLOT(dockVisibleTriggered())); connect(aPrintingSelectorDockVisible, &QAction::triggered, this, &TabDeckEditor::dockVisibleTriggered);
aPrintingSelectorDockFloating = printingSelectorDockMenu->addAction(QString()); aPrintingSelectorDockFloating = printingSelectorDockMenu->addAction(QString());
aPrintingSelectorDockFloating->setCheckable(true); aPrintingSelectorDockFloating->setCheckable(true);
connect(aPrintingSelectorDockFloating, SIGNAL(triggered()), this, SLOT(dockFloatingTriggered())); connect(aPrintingSelectorDockFloating, &QAction::triggered, this, &TabDeckEditor::dockFloatingTriggered);
viewMenu->addSeparator(); viewMenu->addSeparator();
aResetLayout = viewMenu->addAction(QString()); aResetLayout = viewMenu->addAction(QString());
connect(aResetLayout, SIGNAL(triggered()), this, SLOT(restartLayout())); connect(aResetLayout, &QAction::triggered, this, &TabDeckEditor::restartLayout);
viewMenu->addAction(aResetLayout); viewMenu->addAction(aResetLayout);
deckMenu->setSaveStatus(false); deckMenu->setSaveStatus(false);
@ -200,7 +200,7 @@ void TabDeckEditor::loadLayout()
databaseDisplayDockWidget->setMinimumSize(100, 100); databaseDisplayDockWidget->setMinimumSize(100, 100);
databaseDisplayDockWidget->setMaximumSize(1400, 5000); databaseDisplayDockWidget->setMaximumSize(1400, 5000);
QTimer::singleShot(100, this, SLOT(freeDocksSize())); QTimer::singleShot(100, this, &TabDeckEditor::freeDocksSize);
} }
void TabDeckEditor::restartLayout() void TabDeckEditor::restartLayout()
@ -236,7 +236,7 @@ void TabDeckEditor::restartLayout()
splitDockWidget(cardInfoDockWidget, printingSelectorDockWidget, Qt::Horizontal); splitDockWidget(cardInfoDockWidget, printingSelectorDockWidget, Qt::Horizontal);
splitDockWidget(cardInfoDockWidget, filterDockWidget, Qt::Vertical); splitDockWidget(cardInfoDockWidget, filterDockWidget, Qt::Vertical);
QTimer::singleShot(100, this, SLOT(freeDocksSize())); QTimer::singleShot(100, this, &TabDeckEditor::freeDocksSize);
} }
void TabDeckEditor::freeDocksSize() void TabDeckEditor::freeDocksSize()

View file

@ -1,7 +1,7 @@
#ifndef WINDOW_DECKEDITOR_H #ifndef WINDOW_DECKEDITOR_H
#define WINDOW_DECKEDITOR_H #define WINDOW_DECKEDITOR_H
#include "../../game/cards/card_database.h" #include "../../game/cards/card_info.h"
#include "../game_logic/key_signals.h" #include "../game_logic/key_signals.h"
#include "../ui/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h" #include "../ui/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h"
#include "abstract_tab_deck_editor.h" #include "abstract_tab_deck_editor.h"

View file

@ -105,19 +105,19 @@ TabDeckStorage::TabDeckStorage(TabSupervisor *_tabSupervisor,
// Left side actions // Left side actions
aOpenLocalDeck = new QAction(this); aOpenLocalDeck = new QAction(this);
aOpenLocalDeck->setIcon(QPixmap("theme:icons/pencil")); aOpenLocalDeck->setIcon(QPixmap("theme:icons/pencil"));
connect(aOpenLocalDeck, SIGNAL(triggered()), this, SLOT(actOpenLocalDeck())); connect(aOpenLocalDeck, &QAction::triggered, this, &TabDeckStorage::actOpenLocalDeck);
aRenameLocal = new QAction(this); aRenameLocal = new QAction(this);
aRenameLocal->setIcon(QPixmap("theme:icons/rename")); aRenameLocal->setIcon(QPixmap("theme:icons/rename"));
connect(aRenameLocal, &QAction::triggered, this, &TabDeckStorage::actRenameLocal); connect(aRenameLocal, &QAction::triggered, this, &TabDeckStorage::actRenameLocal);
aUpload = new QAction(this); aUpload = new QAction(this);
aUpload->setIcon(QPixmap("theme:icons/arrow_right_green")); aUpload->setIcon(QPixmap("theme:icons/arrow_right_green"));
connect(aUpload, SIGNAL(triggered()), this, SLOT(actUpload())); connect(aUpload, &QAction::triggered, this, &TabDeckStorage::actUpload);
aNewLocalFolder = new QAction(this); aNewLocalFolder = new QAction(this);
aNewLocalFolder->setIcon(qApp->style()->standardIcon(QStyle::SP_FileDialogNewFolder)); aNewLocalFolder->setIcon(qApp->style()->standardIcon(QStyle::SP_FileDialogNewFolder));
connect(aNewLocalFolder, &QAction::triggered, this, &TabDeckStorage::actNewLocalFolder); connect(aNewLocalFolder, &QAction::triggered, this, &TabDeckStorage::actNewLocalFolder);
aDeleteLocalDeck = new QAction(this); aDeleteLocalDeck = new QAction(this);
aDeleteLocalDeck->setIcon(QPixmap("theme:icons/remove_row")); aDeleteLocalDeck->setIcon(QPixmap("theme:icons/remove_row"));
connect(aDeleteLocalDeck, SIGNAL(triggered()), this, SLOT(actDeleteLocalDeck())); connect(aDeleteLocalDeck, &QAction::triggered, this, &TabDeckStorage::actDeleteLocalDeck);
aOpenDecksFolder = new QAction(this); aOpenDecksFolder = new QAction(this);
aOpenDecksFolder->setIcon(qApp->style()->standardIcon(QStyle::SP_DirOpenIcon)); aOpenDecksFolder->setIcon(qApp->style()->standardIcon(QStyle::SP_DirOpenIcon));
@ -126,16 +126,16 @@ TabDeckStorage::TabDeckStorage(TabSupervisor *_tabSupervisor,
// Right side actions // Right side actions
aOpenRemoteDeck = new QAction(this); aOpenRemoteDeck = new QAction(this);
aOpenRemoteDeck->setIcon(QPixmap("theme:icons/pencil")); aOpenRemoteDeck->setIcon(QPixmap("theme:icons/pencil"));
connect(aOpenRemoteDeck, SIGNAL(triggered()), this, SLOT(actOpenRemoteDeck())); connect(aOpenRemoteDeck, &QAction::triggered, this, &TabDeckStorage::actOpenRemoteDeck);
aDownload = new QAction(this); aDownload = new QAction(this);
aDownload->setIcon(QPixmap("theme:icons/arrow_left_green")); aDownload->setIcon(QPixmap("theme:icons/arrow_left_green"));
connect(aDownload, SIGNAL(triggered()), this, SLOT(actDownload())); connect(aDownload, &QAction::triggered, this, &TabDeckStorage::actDownload);
aNewFolder = new QAction(this); aNewFolder = new QAction(this);
aNewFolder->setIcon(qApp->style()->standardIcon(QStyle::SP_FileDialogNewFolder)); aNewFolder->setIcon(qApp->style()->standardIcon(QStyle::SP_FileDialogNewFolder));
connect(aNewFolder, SIGNAL(triggered()), this, SLOT(actNewFolder())); connect(aNewFolder, &QAction::triggered, this, &TabDeckStorage::actNewFolder);
aDeleteRemoteDeck = new QAction(this); aDeleteRemoteDeck = new QAction(this);
aDeleteRemoteDeck->setIcon(QPixmap("theme:icons/remove_row")); aDeleteRemoteDeck->setIcon(QPixmap("theme:icons/remove_row"));
connect(aDeleteRemoteDeck, SIGNAL(triggered()), this, SLOT(actDeleteRemoteDeck())); connect(aDeleteRemoteDeck, &QAction::triggered, this, &TabDeckStorage::actDeleteRemoteDeck);
// Add actions to toolbars // Add actions to toolbars
leftToolBar->addAction(aOpenLocalDeck); leftToolBar->addAction(aOpenLocalDeck);
@ -339,8 +339,7 @@ void TabDeckStorage::uploadDeck(const QString &filePath, const QString &targetPa
cmd.set_deck_list(deckString.toStdString()); cmd.set_deck_list(deckString.toStdString());
PendingCommand *pend = client->prepareSessionCommand(cmd); PendingCommand *pend = client->prepareSessionCommand(cmd);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, connect(pend, &PendingCommand::finished, this, &TabDeckStorage::uploadFinished);
SLOT(uploadFinished(Response, CommandContainer)));
client->sendCommand(pend); client->sendCommand(pend);
} }
@ -421,8 +420,7 @@ void TabDeckStorage::actOpenRemoteDeck()
cmd.set_deck_id(node->getId()); cmd.set_deck_id(node->getId());
PendingCommand *pend = client->prepareSessionCommand(cmd); PendingCommand *pend = client->prepareSessionCommand(cmd);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, connect(pend, &PendingCommand::finished, this, &TabDeckStorage::openRemoteDeckFinished);
SLOT(openRemoteDeckFinished(Response, CommandContainer)));
client->sendCommand(pend); client->sendCommand(pend);
} }
} }
@ -479,8 +477,7 @@ void TabDeckStorage::downloadNodeAtIndex(const QModelIndex &curLeft, const QMode
PendingCommand *pend = client->prepareSessionCommand(cmd); PendingCommand *pend = client->prepareSessionCommand(cmd);
pend->setExtraData(filePath); pend->setExtraData(filePath);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, connect(pend, &PendingCommand::finished, this, &TabDeckStorage::downloadFinished);
SLOT(downloadFinished(Response, CommandContainer, QVariant)));
client->sendCommand(pend); client->sendCommand(pend);
} }
// node at index is invalid // node at index is invalid
@ -522,8 +519,7 @@ void TabDeckStorage::actNewFolder()
cmd.set_dir_name(folder); cmd.set_dir_name(folder);
PendingCommand *pend = client->prepareSessionCommand(cmd); PendingCommand *pend = client->prepareSessionCommand(cmd);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, connect(pend, &PendingCommand::finished, this, &TabDeckStorage::newFolderFinished);
SLOT(newFolderFinished(Response, CommandContainer)));
client->sendCommand(pend); client->sendCommand(pend);
} }
@ -573,15 +569,13 @@ void TabDeckStorage::deleteRemoteDeck(const RemoteDeckList_TreeModel::Node *curR
Command_DeckDelDir cmd; Command_DeckDelDir cmd;
cmd.set_path(targetPath.toStdString()); cmd.set_path(targetPath.toStdString());
pend = client->prepareSessionCommand(cmd); pend = client->prepareSessionCommand(cmd);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, connect(pend, &PendingCommand::finished, this, &TabDeckStorage::deleteFolderFinished);
SLOT(deleteFolderFinished(Response, CommandContainer)));
} else { } else {
const auto *deckNode = dynamic_cast<const RemoteDeckList_TreeModel::FileNode *>(curRight); const auto *deckNode = dynamic_cast<const RemoteDeckList_TreeModel::FileNode *>(curRight);
Command_DeckDel cmd; Command_DeckDel cmd;
cmd.set_deck_id(deckNode->getId()); cmd.set_deck_id(deckNode->getId());
pend = client->prepareSessionCommand(cmd); pend = client->prepareSessionCommand(cmd);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, connect(pend, &PendingCommand::finished, this, &TabDeckStorage::deleteDeckFinished);
SLOT(deleteDeckFinished(Response, CommandContainer)));
} }
client->sendCommand(pend); client->sendCommand(pend);

View file

@ -115,11 +115,12 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, GameReplay *_replay)
createReplayMenuItems(); createReplayMenuItems();
createViewMenuItems(); createViewMenuItems();
retranslateUi(); retranslateUi();
connect(&SettingsCache::instance().shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts())); connect(&SettingsCache::instance().shortcuts(), &ShortcutsSettings::shortCutChanged, this,
&TabGame::refreshShortcuts);
refreshShortcuts(); refreshShortcuts();
messageLog->logReplayStarted(gameInfo.game_id()); messageLog->logReplayStarted(gameInfo.game_id());
QTimer::singleShot(0, this, SLOT(loadLayout())); QTimer::singleShot(0, this, &TabGame::loadLayout);
} }
TabGame::TabGame(TabSupervisor *_tabSupervisor, TabGame::TabGame(TabSupervisor *_tabSupervisor,
@ -156,14 +157,15 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor,
createMenuItems(); createMenuItems();
createViewMenuItems(); createViewMenuItems();
retranslateUi(); retranslateUi();
connect(&SettingsCache::instance().shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts())); connect(&SettingsCache::instance().shortcuts(), &ShortcutsSettings::shortCutChanged, this,
&TabGame::refreshShortcuts);
refreshShortcuts(); refreshShortcuts();
// append game to rooms game list for others to see // append game to rooms game list for others to see
for (int i = gameInfo.game_types_size() - 1; i >= 0; i--) for (int i = gameInfo.game_types_size() - 1; i >= 0; i--)
gameTypes.append(roomGameTypes.find(gameInfo.game_types(i)).value()); gameTypes.append(roomGameTypes.find(gameInfo.game_types(i)).value());
QTimer::singleShot(0, this, SLOT(loadLayout())); QTimer::singleShot(0, this, &TabGame::loadLayout);
} }
void TabGame::addMentionTag(const QString &value) void TabGame::addMentionTag(const QString &value)
@ -626,7 +628,7 @@ Player *TabGame::addPlayer(int playerId, const ServerInfo_User &info)
} }
scene->addPlayer(newPlayer); scene->addPlayer(newPlayer);
connect(newPlayer, SIGNAL(newCardAdded(AbstractCardItem *)), this, SLOT(newCardAdded(AbstractCardItem *))); connect(newPlayer, &Player::newCardAdded, this, &TabGame::newCardAdded);
messageLog->connectToPlayer(newPlayer); messageLog->connectToPlayer(newPlayer);
if (local && !spectator) { if (local && !spectator) {
@ -634,7 +636,7 @@ Player *TabGame::addPlayer(int playerId, const ServerInfo_User &info)
newPlayer->setShortcutsActive(); newPlayer->setShortcutsActive();
auto *deckView = new DeckViewContainer(playerId, this); auto *deckView = new DeckViewContainer(playerId, this);
connect(deckView, SIGNAL(newCardAdded(AbstractCardItem *)), this, SLOT(newCardAdded(AbstractCardItem *))); connect(deckView, &DeckViewContainer::newCardAdded, this, &TabGame::newCardAdded);
deckViewContainers.insert(playerId, deckView); deckViewContainers.insert(playerId, deckView);
deckViewContainerLayout->addWidget(deckView); deckViewContainerLayout->addWidget(deckView);
@ -751,7 +753,7 @@ void TabGame::processGameEventContainer(const GameEventContainer &cont,
default: { default: {
Player *player = players.value(playerId, 0); Player *player = players.value(playerId, 0);
if (!player) { if (!player) {
qCDebug(TabGameLog) << "unhandled game event: invalid player id"; qCWarning(TabGameLog) << "unhandled game event: invalid player id";
break; break;
} }
player->processGameEvent(eventType, event, context, options); player->processGameEvent(eventType, event, context, options);
@ -782,8 +784,7 @@ void TabGame::sendGameCommand(PendingCommand *pend, int playerId)
if (!client) if (!client)
return; return;
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, connect(pend, &PendingCommand::finished, this, &TabGame::commandFinished);
SLOT(commandFinished(const Response &)));
client->sendCommand(pend); client->sendCommand(pend);
} }
@ -794,8 +795,7 @@ void TabGame::sendGameCommand(const google::protobuf::Message &command, int play
return; return;
PendingCommand *pend = prepareGameCommand(command); PendingCommand *pend = prepareGameCommand(command);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, connect(pend, &PendingCommand::finished, this, &TabGame::commandFinished);
SLOT(commandFinished(const Response &)));
client->sendCommand(pend); client->sendCommand(pend);
} }
@ -1196,10 +1196,11 @@ void TabGame::eventSetActivePhase(const Event_SetActivePhase &event,
void TabGame::newCardAdded(AbstractCardItem *card) void TabGame::newCardAdded(AbstractCardItem *card)
{ {
connect(card, SIGNAL(hovered(AbstractCardItem *)), cardInfoFrameWidget, SLOT(setCard(AbstractCardItem *))); connect(card, &AbstractCardItem::hovered, cardInfoFrameWidget,
qOverload<AbstractCardItem *>(&CardInfoFrameWidget::setCard));
connect(card, &AbstractCardItem::showCardInfoPopup, this, &TabGame::showCardInfoPopup); connect(card, &AbstractCardItem::showCardInfoPopup, this, &TabGame::showCardInfoPopup);
connect(card, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString))); connect(card, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString)));
connect(card, SIGNAL(cardShiftClicked(QString)), this, SLOT(linkCardToChat(QString))); connect(card, &AbstractCardItem::cardShiftClicked, this, &TabGame::linkCardToChat);
} }
CardItem *TabGame::getCard(int playerId, const QString &zoneName, int cardId) const CardItem *TabGame::getCard(int playerId, const QString &zoneName, int cardId) const
@ -1287,34 +1288,34 @@ void TabGame::updateCardMenu(AbstractCardItem *card)
void TabGame::createMenuItems() void TabGame::createMenuItems()
{ {
aNextPhase = new QAction(this); aNextPhase = new QAction(this);
connect(aNextPhase, SIGNAL(triggered()), this, SLOT(actNextPhase())); connect(aNextPhase, &QAction::triggered, this, &TabGame::actNextPhase);
aNextPhaseAction = new QAction(this); aNextPhaseAction = new QAction(this);
connect(aNextPhaseAction, SIGNAL(triggered()), this, SLOT(actNextPhaseAction())); connect(aNextPhaseAction, &QAction::triggered, this, &TabGame::actNextPhaseAction);
aNextTurn = new QAction(this); aNextTurn = new QAction(this);
connect(aNextTurn, SIGNAL(triggered()), this, SLOT(actNextTurn())); connect(aNextTurn, &QAction::triggered, this, &TabGame::actNextTurn);
aReverseTurn = new QAction(this); aReverseTurn = new QAction(this);
connect(aReverseTurn, SIGNAL(triggered()), this, SLOT(actReverseTurn())); connect(aReverseTurn, &QAction::triggered, this, &TabGame::actReverseTurn);
aRemoveLocalArrows = new QAction(this); aRemoveLocalArrows = new QAction(this);
connect(aRemoveLocalArrows, SIGNAL(triggered()), this, SLOT(actRemoveLocalArrows())); connect(aRemoveLocalArrows, &QAction::triggered, this, &TabGame::actRemoveLocalArrows);
aRotateViewCW = new QAction(this); aRotateViewCW = new QAction(this);
connect(aRotateViewCW, SIGNAL(triggered()), this, SLOT(actRotateViewCW())); connect(aRotateViewCW, &QAction::triggered, this, &TabGame::actRotateViewCW);
aRotateViewCCW = new QAction(this); aRotateViewCCW = new QAction(this);
connect(aRotateViewCCW, SIGNAL(triggered()), this, SLOT(actRotateViewCCW())); connect(aRotateViewCCW, &QAction::triggered, this, &TabGame::actRotateViewCCW);
aGameInfo = new QAction(this); aGameInfo = new QAction(this);
connect(aGameInfo, SIGNAL(triggered()), this, SLOT(actGameInfo())); connect(aGameInfo, &QAction::triggered, this, &TabGame::actGameInfo);
aConcede = new QAction(this); aConcede = new QAction(this);
connect(aConcede, SIGNAL(triggered()), this, SLOT(actConcede())); connect(aConcede, &QAction::triggered, this, &TabGame::actConcede);
aLeaveGame = new QAction(this); aLeaveGame = new QAction(this);
connect(aLeaveGame, &QAction::triggered, this, [this] { closeRequest(); }); connect(aLeaveGame, &QAction::triggered, this, [this] { closeRequest(); });
aFocusChat = new QAction(this); aFocusChat = new QAction(this);
connect(aFocusChat, SIGNAL(triggered()), sayEdit, SLOT(setFocus())); connect(aFocusChat, &QAction::triggered, sayEdit, qOverload<>(&LineEditCompleter::setFocus));
aCloseReplay = nullptr; aCloseReplay = nullptr;
phasesMenu = new TearOffMenu(this); phasesMenu = new TearOffMenu(this);
for (int i = 0; i < phasesToolbar->phaseCount(); ++i) { for (int i = 0; i < phasesToolbar->phaseCount(); ++i) {
QAction *temp = new QAction(QString(), this); QAction *temp = new QAction(QString(), this);
connect(temp, SIGNAL(triggered()), this, SLOT(actPhaseAction())); connect(temp, &QAction::triggered, this, &TabGame::actPhaseAction);
phasesMenu->addAction(temp); phasesMenu->addAction(temp);
phaseActions.append(temp); phaseActions.append(temp);
} }
@ -1373,40 +1374,40 @@ void TabGame::createViewMenuItems()
aCardInfoDockVisible = cardInfoDockMenu->addAction(QString()); aCardInfoDockVisible = cardInfoDockMenu->addAction(QString());
aCardInfoDockVisible->setCheckable(true); aCardInfoDockVisible->setCheckable(true);
connect(aCardInfoDockVisible, SIGNAL(triggered()), this, SLOT(dockVisibleTriggered())); connect(aCardInfoDockVisible, &QAction::triggered, this, &TabGame::dockVisibleTriggered);
aCardInfoDockFloating = cardInfoDockMenu->addAction(QString()); aCardInfoDockFloating = cardInfoDockMenu->addAction(QString());
aCardInfoDockFloating->setCheckable(true); aCardInfoDockFloating->setCheckable(true);
connect(aCardInfoDockFloating, SIGNAL(triggered()), this, SLOT(dockFloatingTriggered())); connect(aCardInfoDockFloating, &QAction::triggered, this, &TabGame::dockFloatingTriggered);
aMessageLayoutDockVisible = messageLayoutDockMenu->addAction(QString()); aMessageLayoutDockVisible = messageLayoutDockMenu->addAction(QString());
aMessageLayoutDockVisible->setCheckable(true); aMessageLayoutDockVisible->setCheckable(true);
connect(aMessageLayoutDockVisible, SIGNAL(triggered()), this, SLOT(dockVisibleTriggered())); connect(aMessageLayoutDockVisible, &QAction::triggered, this, &TabGame::dockVisibleTriggered);
aMessageLayoutDockFloating = messageLayoutDockMenu->addAction(QString()); aMessageLayoutDockFloating = messageLayoutDockMenu->addAction(QString());
aMessageLayoutDockFloating->setCheckable(true); aMessageLayoutDockFloating->setCheckable(true);
connect(aMessageLayoutDockFloating, SIGNAL(triggered()), this, SLOT(dockFloatingTriggered())); connect(aMessageLayoutDockFloating, &QAction::triggered, this, &TabGame::dockFloatingTriggered);
aPlayerListDockVisible = playerListDockMenu->addAction(QString()); aPlayerListDockVisible = playerListDockMenu->addAction(QString());
aPlayerListDockVisible->setCheckable(true); aPlayerListDockVisible->setCheckable(true);
connect(aPlayerListDockVisible, SIGNAL(triggered()), this, SLOT(dockVisibleTriggered())); connect(aPlayerListDockVisible, &QAction::triggered, this, &TabGame::dockVisibleTriggered);
aPlayerListDockFloating = playerListDockMenu->addAction(QString()); aPlayerListDockFloating = playerListDockMenu->addAction(QString());
aPlayerListDockFloating->setCheckable(true); aPlayerListDockFloating->setCheckable(true);
connect(aPlayerListDockFloating, SIGNAL(triggered()), this, SLOT(dockFloatingTriggered())); connect(aPlayerListDockFloating, &QAction::triggered, this, &TabGame::dockFloatingTriggered);
if (replayDock) { if (replayDock) {
replayDockMenu = viewMenu->addMenu(QString()); replayDockMenu = viewMenu->addMenu(QString());
aReplayDockVisible = replayDockMenu->addAction(QString()); aReplayDockVisible = replayDockMenu->addAction(QString());
aReplayDockVisible->setCheckable(true); aReplayDockVisible->setCheckable(true);
connect(aReplayDockVisible, SIGNAL(triggered()), this, SLOT(dockVisibleTriggered())); connect(aReplayDockVisible, &QAction::triggered, this, &TabGame::dockVisibleTriggered);
aReplayDockFloating = replayDockMenu->addAction(QString()); aReplayDockFloating = replayDockMenu->addAction(QString());
aReplayDockFloating->setCheckable(true); aReplayDockFloating->setCheckable(true);
connect(aReplayDockFloating, SIGNAL(triggered()), this, SLOT(dockFloatingTriggered())); connect(aReplayDockFloating, &QAction::triggered, this, &TabGame::dockFloatingTriggered);
} }
viewMenu->addSeparator(); viewMenu->addSeparator();
aResetLayout = viewMenu->addAction(QString()); aResetLayout = viewMenu->addAction(QString());
connect(aResetLayout, SIGNAL(triggered()), this, SLOT(actResetLayout())); connect(aResetLayout, &QAction::triggered, this, &TabGame::actResetLayout);
viewMenu->addAction(aResetLayout); viewMenu->addAction(aResetLayout);
addTabMenu(viewMenu); addTabMenu(viewMenu);
@ -1457,7 +1458,7 @@ void TabGame::loadLayout()
aReplayDockFloating->setChecked(replayDock->isFloating()); aReplayDockFloating->setChecked(replayDock->isFloating());
} }
QTimer::singleShot(100, this, SLOT(freeDocksSize())); QTimer::singleShot(100, this, &TabGame::freeDocksSize);
} }
void TabGame::freeDocksSize() void TabGame::freeDocksSize()
@ -1523,15 +1524,15 @@ void TabGame::actResetLayout()
playerListDock->setMaximumSize(250, 50); playerListDock->setMaximumSize(250, 50);
} }
QTimer::singleShot(100, this, SLOT(freeDocksSize())); QTimer::singleShot(100, this, &TabGame::freeDocksSize);
} }
void TabGame::createPlayAreaWidget(bool bReplay) void TabGame::createPlayAreaWidget(bool bReplay)
{ {
phasesToolbar = new PhasesToolbar; phasesToolbar = new PhasesToolbar;
if (!bReplay) if (!bReplay)
connect(phasesToolbar, SIGNAL(sendGameCommand(const ::google::protobuf::Message &, int)), this, connect(phasesToolbar, &PhasesToolbar::sendGameCommand, this,
SLOT(sendGameCommand(const ::google::protobuf::Message &, int))); qOverload<const ::google::protobuf::Message &, int>(&TabGame::sendGameCommand));
scene = new GameScene(phasesToolbar, this); scene = new GameScene(phasesToolbar, this);
gameView = new GameView(scene); gameView = new GameView(scene);
@ -1549,9 +1550,8 @@ void TabGame::createReplayDock()
// timeline widget // timeline widget
timelineWidget = new ReplayTimelineWidget; timelineWidget = new ReplayTimelineWidget;
timelineWidget->setTimeline(replayTimeline); timelineWidget->setTimeline(replayTimeline);
connect(timelineWidget, SIGNAL(processNextEvent(Player::EventProcessingOptions)), this, connect(timelineWidget, &ReplayTimelineWidget::processNextEvent, this, &TabGame::replayNextEvent);
SLOT(replayNextEvent(Player::EventProcessingOptions))); connect(timelineWidget, &ReplayTimelineWidget::replayFinished, this, &TabGame::replayFinished);
connect(timelineWidget, SIGNAL(replayFinished()), this, SLOT(replayFinished()));
connect(timelineWidget, &ReplayTimelineWidget::rewound, this, &TabGame::replayRewind); connect(timelineWidget, &ReplayTimelineWidget::rewound, this, &TabGame::replayRewind);
// timeline skip shortcuts // timeline skip shortcuts
@ -1583,13 +1583,13 @@ void TabGame::createReplayDock()
playButtonIcon.addPixmap(QPixmap("theme:replay/pause"), QIcon::Normal, QIcon::On); playButtonIcon.addPixmap(QPixmap("theme:replay/pause"), QIcon::Normal, QIcon::On);
replayPlayButton->setIcon(playButtonIcon); replayPlayButton->setIcon(playButtonIcon);
replayPlayButton->setCheckable(true); replayPlayButton->setCheckable(true);
connect(replayPlayButton, SIGNAL(toggled(bool)), this, SLOT(replayPlayButtonToggled(bool))); connect(replayPlayButton, &QToolButton::toggled, this, &TabGame::replayPlayButtonToggled);
replayFastForwardButton = new QToolButton; replayFastForwardButton = new QToolButton;
replayFastForwardButton->setIconSize(QSize(32, 32)); replayFastForwardButton->setIconSize(QSize(32, 32));
replayFastForwardButton->setIcon(QPixmap("theme:replay/fastforward")); replayFastForwardButton->setIcon(QPixmap("theme:replay/fastforward"));
replayFastForwardButton->setCheckable(true); replayFastForwardButton->setCheckable(true);
connect(replayFastForwardButton, SIGNAL(toggled(bool)), this, SLOT(replayFastForwardButtonToggled(bool))); connect(replayFastForwardButton, &QToolButton::toggled, this, &TabGame::replayFastForwardButtonToggled);
// putting everything together // putting everything together
replayControlLayout = new QHBoxLayout; replayControlLayout = new QHBoxLayout;
@ -1609,7 +1609,7 @@ void TabGame::createReplayDock()
replayDock->setFloating(false); replayDock->setFloating(false);
replayDock->installEventFilter(this); replayDock->installEventFilter(this);
connect(replayDock, SIGNAL(topLevelChanged(bool)), this, SLOT(dockTopLevelChanged(bool))); connect(replayDock, &QDockWidget::topLevelChanged, this, &TabGame::dockTopLevelChanged);
} }
void TabGame::createDeckViewContainerWidget(bool bReplay) void TabGame::createDeckViewContainerWidget(bool bReplay)
@ -1650,7 +1650,7 @@ void TabGame::createCardInfoDock(bool bReplay)
cardInfoDock->setFloating(false); cardInfoDock->setFloating(false);
cardInfoDock->installEventFilter(this); cardInfoDock->installEventFilter(this);
connect(cardInfoDock, SIGNAL(topLevelChanged(bool)), this, SLOT(dockTopLevelChanged(bool))); connect(cardInfoDock, &QDockWidget::topLevelChanged, this, &TabGame::dockTopLevelChanged);
} }
void TabGame::createPlayerListDock(bool bReplay) void TabGame::createPlayerListDock(bool bReplay)
@ -1672,26 +1672,28 @@ void TabGame::createPlayerListDock(bool bReplay)
playerListDock->setFloating(false); playerListDock->setFloating(false);
playerListDock->installEventFilter(this); playerListDock->installEventFilter(this);
connect(playerListDock, SIGNAL(topLevelChanged(bool)), this, SLOT(dockTopLevelChanged(bool))); connect(playerListDock, &QDockWidget::topLevelChanged, this, &TabGame::dockTopLevelChanged);
} }
void TabGame::createMessageDock(bool bReplay) void TabGame::createMessageDock(bool bReplay)
{ {
messageLog = new MessageLogWidget(tabSupervisor, this); messageLog = new MessageLogWidget(tabSupervisor, this);
connect(messageLog, SIGNAL(cardNameHovered(QString)), cardInfoFrameWidget, SLOT(setCard(QString))); connect(messageLog, &MessageLogWidget::cardNameHovered, cardInfoFrameWidget,
qOverload<const QString &>(&CardInfoFrameWidget::setCard));
connect(messageLog, &MessageLogWidget::showCardInfoPopup, this, &TabGame::showCardInfoPopup); connect(messageLog, &MessageLogWidget::showCardInfoPopup, this, &TabGame::showCardInfoPopup);
connect(messageLog, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString))); connect(messageLog, &MessageLogWidget::deleteCardInfoPopup, this, &TabGame::deleteCardInfoPopup);
if (!bReplay) { if (!bReplay) {
connect(messageLog, SIGNAL(openMessageDialog(QString, bool)), this, SIGNAL(openMessageDialog(QString, bool))); connect(messageLog, &MessageLogWidget::openMessageDialog, this, &TabGame::openMessageDialog);
connect(messageLog, SIGNAL(addMentionTag(QString)), this, SLOT(addMentionTag(QString))); connect(messageLog, &MessageLogWidget::addMentionTag, this, &TabGame::addMentionTag);
connect(&SettingsCache::instance(), SIGNAL(chatMentionCompleterChanged()), this, SLOT(actCompleterChanged())); connect(&SettingsCache::instance(), &SettingsCache::chatMentionCompleterChanged, this,
&TabGame::actCompleterChanged);
timeElapsedLabel = new QLabel; timeElapsedLabel = new QLabel;
timeElapsedLabel->setAlignment(Qt::AlignCenter); timeElapsedLabel->setAlignment(Qt::AlignCenter);
gameTimer = new QTimer(this); gameTimer = new QTimer(this);
gameTimer->setInterval(1000); gameTimer->setInterval(1000);
connect(gameTimer, SIGNAL(timeout()), this, SLOT(incrementGameTime())); connect(gameTimer, &QTimer::timeout, this, &TabGame::incrementGameTime);
gameTimer->start(); gameTimer->start();
sayLabel = new QLabel; sayLabel = new QLabel;
@ -1719,8 +1721,8 @@ void TabGame::createMessageDock(bool bReplay)
} }
} }
connect(tabSupervisor, SIGNAL(adminLockChanged(bool)), this, SLOT(adminLockChanged(bool))); connect(tabSupervisor, &TabSupervisor::adminLockChanged, this, &TabGame::adminLockChanged);
connect(sayEdit, SIGNAL(returnPressed()), this, SLOT(actSay())); connect(sayEdit, &LineEditCompleter::returnPressed, this, &TabGame::actSay);
sayHLayout = new QHBoxLayout; sayHLayout = new QHBoxLayout;
sayHLayout->addWidget(sayLabel); sayHLayout->addWidget(sayLabel);
@ -1746,7 +1748,7 @@ void TabGame::createMessageDock(bool bReplay)
messageLayoutDock->setFloating(false); messageLayoutDock->setFloating(false);
messageLayoutDock->installEventFilter(this); messageLayoutDock->installEventFilter(this);
connect(messageLayoutDock, SIGNAL(topLevelChanged(bool)), this, SLOT(dockTopLevelChanged(bool))); connect(messageLayoutDock, &QDockWidget::topLevelChanged, this, &TabGame::dockTopLevelChanged);
} }
void TabGame::hideEvent(QHideEvent *event) void TabGame::hideEvent(QHideEvent *event)

View file

@ -116,8 +116,7 @@ void TabLog::getClicked()
cmd.set_date_range(dateRange); cmd.set_date_range(dateRange);
cmd.set_maximum_results(maximumResults->value()); cmd.set_maximum_results(maximumResults->value());
PendingCommand *pend = client->prepareModeratorCommand(cmd); PendingCommand *pend = client->prepareModeratorCommand(cmd);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, connect(pend, &PendingCommand::finished, this, &TabLog::viewLogHistory_processResponse);
SLOT(viewLogHistory_processResponse(Response)));
client->sendCommand(pend); client->sendCommand(pend);
} }
@ -186,11 +185,11 @@ void TabLog::createDock()
getButton = new QPushButton(tr("Get User Logs")); getButton = new QPushButton(tr("Get User Logs"));
getButton->setAutoDefault(true); getButton->setAutoDefault(true);
connect(getButton, SIGNAL(clicked()), this, SLOT(getClicked())); connect(getButton, &QPushButton::clicked, this, &TabLog::getClicked);
clearButton = new QPushButton(tr("Clear Filters")); clearButton = new QPushButton(tr("Clear Filters"));
clearButton->setAutoDefault(true); clearButton->setAutoDefault(true);
connect(clearButton, SIGNAL(clicked()), this, SLOT(clearClicked())); connect(clearButton, &QPushButton::clicked, this, &TabLog::clearClicked);
criteriaGrid = new QGridLayout; criteriaGrid = new QGridLayout;
criteriaGrid->addWidget(labelFindUserName, 0, 0); criteriaGrid->addWidget(labelFindUserName, 0, 0);

View file

@ -28,11 +28,11 @@ TabMessage::TabMessage(TabSupervisor *_tabSupervisor,
{ {
chatView = new ChatView(tabSupervisor, 0, true); chatView = new ChatView(tabSupervisor, 0, true);
connect(chatView, &ChatView::showCardInfoPopup, this, &TabMessage::showCardInfoPopup); connect(chatView, &ChatView::showCardInfoPopup, this, &TabMessage::showCardInfoPopup);
connect(chatView, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString))); connect(chatView, &ChatView::deleteCardInfoPopup, this, &TabMessage::deleteCardInfoPopup);
connect(chatView, SIGNAL(addMentionTag(QString)), this, SLOT(addMentionTag(QString))); connect(chatView, &ChatView::addMentionTag, this, &TabMessage::addMentionTag);
sayEdit = new LineEditUnfocusable; sayEdit = new LineEditUnfocusable;
sayEdit->setMaxLength(MAX_TEXT_LENGTH); sayEdit->setMaxLength(MAX_TEXT_LENGTH);
connect(sayEdit, SIGNAL(returnPressed()), this, SLOT(sendMessage())); connect(sayEdit, &LineEditUnfocusable::returnPressed, this, &TabMessage::sendMessage);
QVBoxLayout *vbox = new QVBoxLayout; QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(chatView); vbox->addWidget(chatView);
@ -102,7 +102,7 @@ void TabMessage::sendMessage()
cmd.set_message(sayEdit->text().toStdString()); cmd.set_message(sayEdit->text().toStdString());
PendingCommand *pend = client->prepareSessionCommand(cmd); PendingCommand *pend = client->prepareSessionCommand(cmd);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(messageSent(const Response &))); connect(pend, &PendingCommand::finished, this, &TabMessage::messageSent);
client->sendCommand(pend); client->sendCommand(pend);
sayEdit->clear(); sayEdit->clear();
@ -140,12 +140,12 @@ bool TabMessage::shouldShowSystemPopup(const Event_UserMessage &event)
void TabMessage::showSystemPopup(const Event_UserMessage &event) void TabMessage::showSystemPopup(const Event_UserMessage &event)
{ {
if (trayIcon) { if (trayIcon) {
disconnect(trayIcon, SIGNAL(messageClicked()), 0, 0); disconnect(trayIcon, &QSystemTrayIcon::messageClicked, 0, 0);
trayIcon->showMessage(tr("Private message from") + " " + otherUserInfo->name().c_str(), trayIcon->showMessage(tr("Private message from") + " " + otherUserInfo->name().c_str(),
event.message().c_str()); event.message().c_str());
connect(trayIcon, SIGNAL(messageClicked()), this, SLOT(messageClicked())); connect(trayIcon, &QSystemTrayIcon::messageClicked, this, &TabMessage::messageClicked);
} else { } else {
qCDebug(TabMessageLog) << "Error: trayIcon is NULL. TabMessage::showSystemPopup failed"; qCWarning(TabMessageLog) << "Error: trayIcon is NULL. TabMessage::showSystemPopup failed";
} }
} }

View file

@ -96,8 +96,8 @@ TabReplays::TabReplays(TabSupervisor *_tabSupervisor, AbstractClient *_client, c
// Left side actions // Left side actions
aOpenLocalReplay = new QAction(this); aOpenLocalReplay = new QAction(this);
aOpenLocalReplay->setIcon(QPixmap("theme:icons/view")); aOpenLocalReplay->setIcon(QPixmap("theme:icons/view"));
connect(aOpenLocalReplay, SIGNAL(triggered()), this, SLOT(actOpenLocalReplay())); connect(aOpenLocalReplay, &QAction::triggered, this, &TabReplays::actOpenLocalReplay);
connect(localDirView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(actOpenLocalReplay())); connect(localDirView, &QTreeView::doubleClicked, this, &TabReplays::actOpenLocalReplay);
aRenameLocal = new QAction(this); aRenameLocal = new QAction(this);
aRenameLocal->setIcon(QPixmap("theme:icons/rename")); aRenameLocal->setIcon(QPixmap("theme:icons/rename"));
connect(aRenameLocal, &QAction::triggered, this, &TabReplays::actRenameLocal); connect(aRenameLocal, &QAction::triggered, this, &TabReplays::actRenameLocal);
@ -106,7 +106,7 @@ TabReplays::TabReplays(TabSupervisor *_tabSupervisor, AbstractClient *_client, c
connect(aNewLocalFolder, &QAction::triggered, this, &TabReplays::actNewLocalFolder); connect(aNewLocalFolder, &QAction::triggered, this, &TabReplays::actNewLocalFolder);
aDeleteLocalReplay = new QAction(this); aDeleteLocalReplay = new QAction(this);
aDeleteLocalReplay->setIcon(QPixmap("theme:icons/remove_row")); aDeleteLocalReplay->setIcon(QPixmap("theme:icons/remove_row"));
connect(aDeleteLocalReplay, SIGNAL(triggered()), this, SLOT(actDeleteLocalReplay())); connect(aDeleteLocalReplay, &QAction::triggered, this, &TabReplays::actDeleteLocalReplay);
aOpenReplaysFolder = new QAction(this); aOpenReplaysFolder = new QAction(this);
aOpenReplaysFolder->setIcon(qApp->style()->standardIcon(QStyle::SP_DirOpenIcon)); aOpenReplaysFolder->setIcon(qApp->style()->standardIcon(QStyle::SP_DirOpenIcon));
@ -115,17 +115,17 @@ TabReplays::TabReplays(TabSupervisor *_tabSupervisor, AbstractClient *_client, c
// Right side actions // Right side actions
aOpenRemoteReplay = new QAction(this); aOpenRemoteReplay = new QAction(this);
aOpenRemoteReplay->setIcon(QPixmap("theme:icons/view")); aOpenRemoteReplay->setIcon(QPixmap("theme:icons/view"));
connect(aOpenRemoteReplay, SIGNAL(triggered()), this, SLOT(actOpenRemoteReplay())); connect(aOpenRemoteReplay, &QAction::triggered, this, &TabReplays::actOpenRemoteReplay);
connect(serverDirView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(actOpenRemoteReplay())); connect(serverDirView, &QTreeView::doubleClicked, this, &TabReplays::actOpenRemoteReplay);
aDownload = new QAction(this); aDownload = new QAction(this);
aDownload->setIcon(QPixmap("theme:icons/arrow_left_green")); aDownload->setIcon(QPixmap("theme:icons/arrow_left_green"));
connect(aDownload, SIGNAL(triggered()), this, SLOT(actDownload())); connect(aDownload, &QAction::triggered, this, &TabReplays::actDownload);
aKeep = new QAction(this); aKeep = new QAction(this);
aKeep->setIcon(QPixmap("theme:icons/lock")); aKeep->setIcon(QPixmap("theme:icons/lock"));
connect(aKeep, SIGNAL(triggered()), this, SLOT(actKeepRemoteReplay())); connect(aKeep, &QAction::triggered, this, &TabReplays::actKeepRemoteReplay);
aDeleteRemoteReplay = new QAction(this); aDeleteRemoteReplay = new QAction(this);
aDeleteRemoteReplay->setIcon(QPixmap("theme:icons/remove_row")); aDeleteRemoteReplay->setIcon(QPixmap("theme:icons/remove_row"));
connect(aDeleteRemoteReplay, SIGNAL(triggered()), this, SLOT(actDeleteRemoteReplay())); connect(aDeleteRemoteReplay, &QAction::triggered, this, &TabReplays::actDeleteRemoteReplay);
// Add actions to toolbars // Add actions to toolbars
leftToolBar->addAction(aOpenLocalReplay); leftToolBar->addAction(aOpenLocalReplay);
@ -146,8 +146,7 @@ TabReplays::TabReplays(TabSupervisor *_tabSupervisor, AbstractClient *_client, c
mainWidget->setLayout(hbox); mainWidget->setLayout(hbox);
setCentralWidget(mainWidget); setCentralWidget(mainWidget);
connect(client, SIGNAL(replayAddedEventReceived(const Event_ReplayAdded &)), this, connect(client, &AbstractClient::replayAddedEventReceived, this, &TabReplays::replayAddedEventReceived);
SLOT(replayAddedEventReceived(const Event_ReplayAdded &)));
connect(client, &AbstractClient::userInfoChanged, this, &TabReplays::handleConnected); connect(client, &AbstractClient::userInfoChanged, this, &TabReplays::handleConnected);
connect(client, &AbstractClient::statusChanged, this, &TabReplays::handleConnectionChanged); connect(client, &AbstractClient::statusChanged, this, &TabReplays::handleConnectionChanged);
@ -323,8 +322,7 @@ void TabReplays::actOpenRemoteReplay()
cmd.set_replay_id(curRight->replay_id()); cmd.set_replay_id(curRight->replay_id());
PendingCommand *pend = client->prepareSessionCommand(cmd); PendingCommand *pend = client->prepareSessionCommand(cmd);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, connect(pend, &PendingCommand::finished, this, &TabReplays::openRemoteReplayFinished);
SLOT(openRemoteReplayFinished(const Response &)));
client->sendCommand(pend); client->sendCommand(pend);
} }
} }
@ -378,8 +376,7 @@ void TabReplays::downloadNodeAtIndex(const QModelIndex &curLeft, const QModelInd
PendingCommand *pend = client->prepareSessionCommand(cmd); PendingCommand *pend = client->prepareSessionCommand(cmd);
pend->setExtraData(filePath); pend->setExtraData(filePath);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, connect(pend, &PendingCommand::finished, this, &TabReplays::downloadFinished);
SLOT(downloadFinished(Response, CommandContainer, QVariant)));
client->sendCommand(pend); client->sendCommand(pend);
} }
// node at index was invalid // node at index was invalid
@ -416,8 +413,7 @@ void TabReplays::actKeepRemoteReplay()
cmd.set_do_not_hide(!curRight->do_not_hide()); cmd.set_do_not_hide(!curRight->do_not_hide());
PendingCommand *pend = client->prepareSessionCommand(cmd); PendingCommand *pend = client->prepareSessionCommand(cmd);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, connect(pend, &PendingCommand::finished, this, &TabReplays::keepRemoteReplayFinished);
SLOT(keepRemoteReplayFinished(Response, CommandContainer)));
client->sendCommand(pend); client->sendCommand(pend);
} }
} }
@ -455,8 +451,7 @@ void TabReplays::actDeleteRemoteReplay()
cmd.set_game_id(curRight->game_id()); cmd.set_game_id(curRight->game_id());
PendingCommand *pend = client->prepareSessionCommand(cmd); PendingCommand *pend = client->prepareSessionCommand(cmd);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, connect(pend, &PendingCommand::finished, this, &TabReplays::deleteRemoteReplayFinished);
SLOT(deleteRemoteReplayFinished(Response, CommandContainer)));
client->sendCommand(pend); client->sendCommand(pend);
} }
} }

View file

@ -53,28 +53,29 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor,
SIGNAL(openMessageDialog(const QString &, bool))); SIGNAL(openMessageDialog(const QString &, bool)));
chatView = new ChatView(tabSupervisor, nullptr, true, this); chatView = new ChatView(tabSupervisor, nullptr, true, this);
connect(chatView, SIGNAL(showMentionPopup(const QString &)), this, SLOT(actShowMentionPopup(const QString &))); connect(chatView, &ChatView::showMentionPopup, this, &TabRoom::actShowMentionPopup);
connect(chatView, SIGNAL(messageClickedSignal()), this, SLOT(focusTab())); connect(chatView, &ChatView::messageClickedSignal, this, &TabRoom::focusTab);
connect(chatView, SIGNAL(openMessageDialog(QString, bool)), this, SIGNAL(openMessageDialog(QString, bool))); connect(chatView, &ChatView::openMessageDialog, this, &TabRoom::openMessageDialog);
connect(chatView, &ChatView::showCardInfoPopup, this, &TabRoom::showCardInfoPopup); connect(chatView, &ChatView::showCardInfoPopup, this, &TabRoom::showCardInfoPopup);
connect(chatView, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString))); connect(chatView, &ChatView::deleteCardInfoPopup, this, &TabRoom::deleteCardInfoPopup);
connect(chatView, SIGNAL(addMentionTag(QString)), this, SLOT(addMentionTag(QString))); connect(chatView, &ChatView::addMentionTag, this, &TabRoom::addMentionTag);
connect(&SettingsCache::instance(), SIGNAL(chatMentionCompleterChanged()), this, SLOT(actCompleterChanged())); connect(&SettingsCache::instance(), &SettingsCache::chatMentionCompleterChanged, this,
&TabRoom::actCompleterChanged);
sayLabel = new QLabel; sayLabel = new QLabel;
sayEdit = new LineEditCompleter; sayEdit = new LineEditCompleter;
sayEdit->setMaxLength(MAX_TEXT_LENGTH); sayEdit->setMaxLength(MAX_TEXT_LENGTH);
sayLabel->setBuddy(sayEdit); sayLabel->setBuddy(sayEdit);
connect(sayEdit, SIGNAL(returnPressed()), this, SLOT(sendMessage())); connect(sayEdit, &LineEditCompleter::returnPressed, this, &TabRoom::sendMessage);
QMenu *chatSettingsMenu = new QMenu(this); QMenu *chatSettingsMenu = new QMenu(this);
aClearChat = chatSettingsMenu->addAction(QString()); aClearChat = chatSettingsMenu->addAction(QString());
connect(aClearChat, SIGNAL(triggered()), this, SLOT(actClearChat())); connect(aClearChat, &QAction::triggered, this, &TabRoom::actClearChat);
chatSettingsMenu->addSeparator(); chatSettingsMenu->addSeparator();
aOpenChatSettings = chatSettingsMenu->addAction(QString()); aOpenChatSettings = chatSettingsMenu->addAction(QString());
connect(aOpenChatSettings, SIGNAL(triggered()), this, SLOT(actOpenChatSettings())); connect(aOpenChatSettings, &QAction::triggered, this, &TabRoom::actOpenChatSettings);
QToolButton *chatSettingsButton = new QToolButton; QToolButton *chatSettingsButton = new QToolButton;
chatSettingsButton->setIcon(QPixmap("theme:icons/settings")); chatSettingsButton->setIcon(QPixmap("theme:icons/settings"));
@ -126,7 +127,8 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor,
sayEdit->setCompleter(completer); sayEdit->setCompleter(completer);
actCompleterChanged(); actCompleterChanged();
connect(&SettingsCache::instance().shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts())); connect(&SettingsCache::instance().shortcuts(), &ShortcutsSettings::shortCutChanged, this,
&TabRoom::refreshShortcuts);
refreshShortcuts(); refreshShortcuts();
retranslateUi(); retranslateUi();
@ -165,9 +167,9 @@ void TabRoom::actShowPopup(const QString &message)
{ {
if (trayIcon && (tabSupervisor->currentIndex() != tabSupervisor->indexOf(this) || if (trayIcon && (tabSupervisor->currentIndex() != tabSupervisor->indexOf(this) ||
QApplication::activeWindow() == nullptr || QApplication::focusWidget() == nullptr)) { QApplication::activeWindow() == nullptr || QApplication::focusWidget() == nullptr)) {
disconnect(trayIcon, SIGNAL(messageClicked()), nullptr, nullptr); disconnect(trayIcon, &QSystemTrayIcon::messageClicked, nullptr, nullptr);
trayIcon->showMessage(message, tr("Click to view")); trayIcon->showMessage(message, tr("Click to view"));
connect(trayIcon, SIGNAL(messageClicked()), chatView, SLOT(actMessageClicked())); connect(trayIcon, &QSystemTrayIcon::messageClicked, chatView, &ChatView::messageClickedSignal);
} }
} }
@ -201,8 +203,7 @@ void TabRoom::sendMessage()
cmd.set_message(sayEdit->text().toStdString()); cmd.set_message(sayEdit->text().toStdString());
PendingCommand *pend = prepareRoomCommand(cmd); PendingCommand *pend = prepareRoomCommand(cmd);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, connect(pend, &PendingCommand::finished, this, &TabRoom::sayFinished);
SLOT(sayFinished(const Response &)));
sendRoomCommand(pend); sendRoomCommand(pend);
sayEdit->clear(); sayEdit->clear();
} }

View file

@ -33,7 +33,7 @@ RoomSelector::RoomSelector(AbstractClient *_client, QWidget *parent) : QGroupBox
roomList->header()->setSectionResizeMode(3, QHeaderView::ResizeToContents); roomList->header()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
joinButton = new QPushButton; joinButton = new QPushButton;
connect(joinButton, SIGNAL(clicked()), this, SLOT(joinClicked())); connect(joinButton, &QPushButton::clicked, this, &RoomSelector::joinClicked);
QHBoxLayout *buttonLayout = new QHBoxLayout; QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addStretch(); buttonLayout->addStretch();
buttonLayout->addWidget(joinButton); buttonLayout->addWidget(joinButton);
@ -44,9 +44,8 @@ RoomSelector::RoomSelector(AbstractClient *_client, QWidget *parent) : QGroupBox
retranslateUi(); retranslateUi();
setLayout(vbox); setLayout(vbox);
connect(client, SIGNAL(listRoomsEventReceived(const Event_ListRooms &)), this, connect(client, &AbstractClient::listRoomsEventReceived, this, &RoomSelector::processListRoomsEvent);
SLOT(processListRoomsEvent(const Event_ListRooms &))); connect(roomList, &QTreeWidget::activated, this, &RoomSelector::joinClicked);
connect(roomList, SIGNAL(activated(const QModelIndex &)), this, SLOT(joinClicked()));
client->sendCommand(client->prepareSessionCommand(Command_ListRooms())); client->sendCommand(client->prepareSessionCommand(Command_ListRooms()));
} }
@ -144,10 +143,9 @@ TabServer::TabServer(TabSupervisor *_tabSupervisor, AbstractClient *_client) : T
serverInfoBox = new QTextBrowser; serverInfoBox = new QTextBrowser;
serverInfoBox->setOpenExternalLinks(true); serverInfoBox->setOpenExternalLinks(true);
connect(roomSelector, SIGNAL(joinRoomRequest(int, bool)), this, SLOT(joinRoom(int, bool))); connect(roomSelector, &RoomSelector::joinRoomRequest, this, &TabServer::joinRoom);
connect(client, SIGNAL(serverMessageEventReceived(const Event_ServerMessage &)), this, connect(client, &AbstractClient::serverMessageEventReceived, this, &TabServer::processServerMessageEvent);
SLOT(processServerMessageEvent(const Event_ServerMessage &)));
QVBoxLayout *vbox = new QVBoxLayout; QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(roomSelector); vbox->addWidget(roomSelector);
@ -185,8 +183,7 @@ void TabServer::joinRoom(int id, bool setCurrent)
PendingCommand *pend = client->prepareSessionCommand(cmd); PendingCommand *pend = client->prepareSessionCommand(cmd);
pend->setExtraData(setCurrent); pend->setExtraData(setCurrent);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, connect(pend, &PendingCommand::finished, this, &TabServer::joinRoomFinished);
SLOT(joinRoomFinished(Response, CommandContainer, QVariant)));
client->sendCommand(pend); client->sendCommand(pend);

View file

@ -6,6 +6,7 @@
#include "../../server/user/user_list_widget.h" #include "../../server/user/user_list_widget.h"
#include "../../settings/cache_settings.h" #include "../../settings/cache_settings.h"
#include "../ui/pixel_map_generator.h" #include "../ui/pixel_map_generator.h"
#include "api/edhrec/tab_edhrec_main.h"
#include "pb/event_game_joined.pb.h" #include "pb/event_game_joined.pb.h"
#include "pb/event_notify_user.pb.h" #include "pb/event_notify_user.pb.h"
#include "pb/event_user_message.pb.h" #include "pb/event_user_message.pb.h"
@ -25,6 +26,9 @@
#include "tab_replays.h" #include "tab_replays.h"
#include "tab_room.h" #include "tab_room.h"
#include "tab_server.h" #include "tab_server.h"
#include "tab_visual_database_display.h"
#include "visual_deck_editor/tab_deck_editor_visual.h"
#include "visual_deck_editor/tab_deck_editor_visual_tab_widget.h"
#include "visual_deck_storage/tab_deck_storage_visual.h" #include "visual_deck_storage/tab_deck_storage_visual.h"
#include <QApplication> #include <QApplication>
@ -130,10 +134,19 @@ TabSupervisor::TabSupervisor(AbstractClient *_client, QMenu *tabsMenu, QWidget *
aTabDeckEditor = new QAction(this); aTabDeckEditor = new QAction(this);
connect(aTabDeckEditor, &QAction::triggered, this, [this] { addDeckEditorTab(nullptr); }); connect(aTabDeckEditor, &QAction::triggered, this, [this] { addDeckEditorTab(nullptr); });
aTabVisualDeckEditor = new QAction(this);
connect(aTabVisualDeckEditor, &QAction::triggered, this, [this] { addVisualDeckEditorTab(nullptr); });
aTabEdhRec = new QAction(this);
connect(aTabEdhRec, &QAction::triggered, this, [this] { addEdhrecMainTab(); });
aTabVisualDeckStorage = new QAction(this); aTabVisualDeckStorage = new QAction(this);
aTabVisualDeckStorage->setCheckable(true); aTabVisualDeckStorage->setCheckable(true);
connect(aTabVisualDeckStorage, &QAction::triggered, this, &TabSupervisor::actTabVisualDeckStorage); connect(aTabVisualDeckStorage, &QAction::triggered, this, &TabSupervisor::actTabVisualDeckStorage);
aTabVisualDatabaseDisplay = new QAction(this);
connect(aTabVisualDatabaseDisplay, &QAction::triggered, this, [this] { addVisualDatabaseDisplayTab(); });
aTabServer = new QAction(this); aTabServer = new QAction(this);
aTabServer->setCheckable(true); aTabServer->setCheckable(true);
connect(aTabServer, &QAction::triggered, this, &TabSupervisor::actTabServer); connect(aTabServer, &QAction::triggered, this, &TabSupervisor::actTabServer);
@ -176,7 +189,10 @@ void TabSupervisor::retranslateUi()
{ {
// tab menu actions // tab menu actions
aTabDeckEditor->setText(tr("Deck Editor")); aTabDeckEditor->setText(tr("Deck Editor"));
aTabVisualDeckEditor->setText(tr("Visual Deck Editor"));
aTabEdhRec->setText(tr("EDHRec"));
aTabVisualDeckStorage->setText(tr("&Visual Deck Storage")); aTabVisualDeckStorage->setText(tr("&Visual Deck Storage"));
aTabVisualDatabaseDisplay->setText(tr("Visual Database Display"));
aTabServer->setText(tr("Server")); aTabServer->setText(tr("Server"));
aTabAccount->setText(tr("Account")); aTabAccount->setText(tr("Account"));
aTabDeckStorage->setText(tr("Deck Storage")); aTabDeckStorage->setText(tr("Deck Storage"));
@ -223,6 +239,7 @@ void TabSupervisor::refreshShortcuts()
{ {
ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts();
aTabDeckEditor->setShortcuts(shortcuts.getShortcut("Tabs/aTabDeckEditor")); aTabDeckEditor->setShortcuts(shortcuts.getShortcut("Tabs/aTabDeckEditor"));
aTabVisualDeckEditor->setShortcuts(shortcuts.getShortcut("Tabs/aTabVisualDeckEditor"));
aTabVisualDeckStorage->setShortcuts(shortcuts.getShortcut("Tabs/aTabVisualDeckStorage")); aTabVisualDeckStorage->setShortcuts(shortcuts.getShortcut("Tabs/aTabVisualDeckStorage"));
aTabServer->setShortcuts(shortcuts.getShortcut("Tabs/aTabServer")); aTabServer->setShortcuts(shortcuts.getShortcut("Tabs/aTabServer"));
aTabAccount->setShortcuts(shortcuts.getShortcut("Tabs/aTabAccount")); aTabAccount->setShortcuts(shortcuts.getShortcut("Tabs/aTabAccount"));
@ -370,8 +387,11 @@ void TabSupervisor::resetTabsMenu()
{ {
tabsMenu->clear(); tabsMenu->clear();
tabsMenu->addAction(aTabDeckEditor); tabsMenu->addAction(aTabDeckEditor);
tabsMenu->addAction(aTabVisualDeckEditor);
tabsMenu->addAction(aTabEdhRec);
tabsMenu->addSeparator(); tabsMenu->addSeparator();
tabsMenu->addAction(aTabVisualDeckStorage); tabsMenu->addAction(aTabVisualDeckStorage);
tabsMenu->addAction(aTabVisualDatabaseDisplay);
tabsMenu->addAction(aTabDeckStorage); tabsMenu->addAction(aTabDeckStorage);
tabsMenu->addAction(aTabReplays); tabsMenu->addAction(aTabReplays);
} }
@ -804,6 +824,36 @@ TabDeckEditor *TabSupervisor::addDeckEditorTab(const DeckLoader *deckToOpen)
return tab; return tab;
} }
TabDeckEditorVisual *TabSupervisor::addVisualDeckEditorTab(const DeckLoader *deckToOpen)
{
auto *tab = new TabDeckEditorVisual(this);
if (deckToOpen)
tab->openDeck(new DeckLoader(*deckToOpen));
connect(tab, &AbstractTabDeckEditor::deckEditorClosing, this, &TabSupervisor::deckEditorClosed);
connect(tab, &AbstractTabDeckEditor::openDeckEditor, this, &TabSupervisor::addVisualDeckEditorTab);
myAddTab(tab);
deckEditorTabs.append(tab);
setCurrentWidget(tab);
return tab;
}
TabEdhRecMain *TabSupervisor::addEdhrecMainTab()
{
auto *tab = new TabEdhRecMain(this);
myAddTab(tab);
setCurrentWidget(tab);
return tab;
}
TabVisualDatabaseDisplay *TabSupervisor::addVisualDatabaseDisplayTab()
{
auto *tab = new TabVisualDatabaseDisplay(this);
myAddTab(tab);
setCurrentWidget(tab);
return tab;
}
TabEdhRec *TabSupervisor::addEdhrecTab(const CardInfoPtr &cardToQuery, bool isCommander) TabEdhRec *TabSupervisor::addEdhrecTab(const CardInfoPtr &cardToQuery, bool isCommander)
{ {
auto *tab = new TabEdhRec(this); auto *tab = new TabEdhRec(this);
@ -856,7 +906,7 @@ void TabSupervisor::processGameEventContainer(const GameEventContainer &cont)
if (tab) if (tab)
tab->processGameEventContainer(cont, qobject_cast<AbstractClient *>(sender()), {}); tab->processGameEventContainer(cont, qobject_cast<AbstractClient *>(sender()), {});
else else
qCDebug(TabSupervisorLog) << "gameEvent: invalid gameId"; qCInfo(TabSupervisorLog) << "gameEvent: invalid gameId" << cont.game_id();
} }
void TabSupervisor::processUserMessageEvent(const Event_UserMessage &event) void TabSupervisor::processUserMessageEvent(const Event_UserMessage &event)

View file

@ -5,6 +5,10 @@
#include "../../server/user/user_list_proxy.h" #include "../../server/user/user_list_proxy.h"
#include "abstract_tab_deck_editor.h" #include "abstract_tab_deck_editor.h"
#include "api/edhrec/tab_edhrec.h" #include "api/edhrec/tab_edhrec.h"
#include "api/edhrec/tab_edhrec_main.h"
#include "tab_visual_database_display.h"
#include "visual_deck_editor/tab_deck_editor_visual.h"
#include "visual_deck_editor/tab_deck_editor_visual_tab_widget.h"
#include "visual_deck_storage/tab_deck_storage_visual.h" #include "visual_deck_storage/tab_deck_storage_visual.h"
#include <QAbstractButton> #include <QAbstractButton>
@ -91,8 +95,8 @@ private:
QList<AbstractTabDeckEditor *> deckEditorTabs; QList<AbstractTabDeckEditor *> deckEditorTabs;
bool isLocalGame; bool isLocalGame;
QAction *aTabDeckEditor, *aTabVisualDeckStorage, *aTabServer, *aTabAccount, *aTabDeckStorage, *aTabReplays, QAction *aTabDeckEditor, *aTabVisualDeckEditor, *aTabEdhRec, *aTabVisualDeckStorage, *aTabVisualDatabaseDisplay,
*aTabAdmin, *aTabLog; *aTabServer, *aTabAccount, *aTabDeckStorage, *aTabReplays, *aTabAdmin, *aTabLog;
int myAddTab(Tab *tab, QAction *manager = nullptr); int myAddTab(Tab *tab, QAction *manager = nullptr);
void addCloseButtonToTab(Tab *tab, int tabIndex, QAction *manager); void addCloseButtonToTab(Tab *tab, int tabIndex, QAction *manager);
@ -149,6 +153,9 @@ signals:
public slots: public slots:
TabDeckEditor *addDeckEditorTab(const DeckLoader *deckToOpen); TabDeckEditor *addDeckEditorTab(const DeckLoader *deckToOpen);
TabDeckEditorVisual *addVisualDeckEditorTab(const DeckLoader *deckToOpen);
TabVisualDatabaseDisplay *addVisualDatabaseDisplayTab();
TabEdhRecMain *addEdhrecMainTab();
TabEdhRec *addEdhrecTab(const CardInfoPtr &cardToQuery, bool isCommander = false); TabEdhRec *addEdhrecTab(const CardInfoPtr &cardToQuery, bool isCommander = false);
void openReplay(GameReplay *replay); void openReplay(GameReplay *replay);
void maximizeMainWindow(); void maximizeMainWindow();

View file

@ -0,0 +1,20 @@
#include "tab_visual_database_display.h"
#include "tab_deck_editor.h"
TabVisualDatabaseDisplay::TabVisualDatabaseDisplay(TabSupervisor *_tabSupervisor) : Tab(_tabSupervisor)
{
deckEditor = new TabDeckEditor(_tabSupervisor);
deckEditor->setHidden(true);
visualDatabaseDisplayWidget =
new VisualDatabaseDisplayWidget(this, deckEditor, deckEditor->databaseDisplayDockWidget->databaseModel,
deckEditor->databaseDisplayDockWidget->databaseDisplayModel);
setCentralWidget(visualDatabaseDisplayWidget);
TabVisualDatabaseDisplay::retranslateUi();
}
void TabVisualDatabaseDisplay::retranslateUi()
{
}

View file

@ -0,0 +1,26 @@
#ifndef TAB_VISUAL_DATABASE_DISPLAY_H
#define TAB_VISUAL_DATABASE_DISPLAY_H
#include "../ui/widgets/visual_database_display/visual_database_display_widget.h"
#include "tab.h"
#include <QVBoxLayout>
class TabVisualDatabaseDisplay : public Tab
{
Q_OBJECT
private:
TabDeckEditor *deckEditor;
VisualDatabaseDisplayWidget *visualDatabaseDisplayWidget;
public:
TabVisualDatabaseDisplay(TabSupervisor *_tabSupervisor);
void retranslateUi() override;
QString getTabText() const override
{
return tr("Visual Database Display");
}
};
#endif // TAB_VISUAL_DATABASE_DISPLAY_H

View file

@ -0,0 +1,470 @@
#include "tab_deck_editor_visual.h"
#include "../../../deck/deck_list_model.h"
#include "../../../deck/deck_stats_interface.h"
#include "../../../game/cards/card_database_model.h"
#include "../../../game/filters/filter_builder.h"
#include "../../../server/pending_command.h"
#include "../../../settings/cache_settings.h"
#include "../../ui/pixel_map_generator.h"
#include "../../ui/widgets/cards/card_info_frame_widget.h"
#include "../../ui/widgets/deck_analytics/deck_analytics_widget.h"
#include "../../ui/widgets/visual_deck_editor/visual_deck_editor_widget.h"
#include "../tab_deck_editor.h"
#include "../tab_supervisor.h"
#include "pb/command_deck_upload.pb.h"
#include "tab_deck_editor_visual_tab_widget.h"
#include "trice_limits.h"
#include <QAction>
#include <QApplication>
#include <QCloseEvent>
#include <QCompleter>
#include <QDir>
#include <QDockWidget>
#include <QFileDialog>
#include <QHeaderView>
#include <QLineEdit>
#include <QMenu>
#include <QPrintPreviewDialog>
#include <QProcessEnvironment>
#include <QSplitter>
#include <QTextStream>
#include <QTimer>
#include <QTreeView>
#include <QVBoxLayout>
TabDeckEditorVisual::TabDeckEditorVisual(TabSupervisor *_tabSupervisor) : AbstractTabDeckEditor(_tabSupervisor)
{
setObjectName("TabDeckEditorVisual");
createCentralFrame();
TabDeckEditorVisual::createMenus();
installEventFilter(this);
TabDeckEditorVisual::retranslateUi();
connect(&SettingsCache::instance().shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts()));
TabDeckEditorVisual::refreshShortcuts();
TabDeckEditorVisual::loadLayout();
databaseDisplayDockWidget->setHidden(true);
}
void TabDeckEditorVisual::createCentralFrame()
{
centralWidget = new QWidget(this);
centralWidget->setObjectName("centralWidget");
centralFrame = new QVBoxLayout;
centralWidget->setLayout(centralFrame);
tabContainer = new TabDeckEditorVisualTabWidget(centralWidget, this, deckDockWidget->deckModel,
databaseDisplayDockWidget->databaseModel,
databaseDisplayDockWidget->databaseDisplayModel);
connect(tabContainer, &TabDeckEditorVisualTabWidget::cardChanged, this,
&TabDeckEditorVisual::changeModelIndexAndCardInfo);
connect(tabContainer, &TabDeckEditorVisualTabWidget::cardChangedDatabaseDisplay, this,
&AbstractTabDeckEditor::updateCard);
connect(tabContainer, &TabDeckEditorVisualTabWidget::cardClicked, this,
&TabDeckEditorVisual::processMainboardCardClick);
connect(tabContainer, &TabDeckEditorVisualTabWidget::cardClickedDatabaseDisplay, this,
&TabDeckEditorVisual::processCardClickDatabaseDisplay);
centralFrame->addWidget(tabContainer);
setCentralWidget(centralWidget);
setDockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks);
}
void TabDeckEditorVisual::onDeckChanged()
{
AbstractTabDeckEditor::onDeckChanged();
tabContainer->visualDeckView->decklistDataChanged(QModelIndex(), QModelIndex());
tabContainer->deckAnalytics->refreshDisplays(deckDockWidget->deckModel);
tabContainer->sampleHandWidget->setDeckModel(deckDockWidget->deckModel);
}
void TabDeckEditorVisual::createMenus()
{
deckMenu = new DeckEditorMenu(this);
addTabMenu(deckMenu);
viewMenu = new QMenu(this);
cardInfoDockMenu = viewMenu->addMenu(QString());
deckDockMenu = viewMenu->addMenu(QString());
deckAnalyticsMenu = viewMenu->addMenu(QString());
filterDockMenu = viewMenu->addMenu(QString());
printingSelectorDockMenu = viewMenu->addMenu(QString());
aCardInfoDockVisible = cardInfoDockMenu->addAction(QString());
aCardInfoDockVisible->setCheckable(true);
connect(aCardInfoDockVisible, SIGNAL(triggered()), this, SLOT(dockVisibleTriggered()));
aCardInfoDockFloating = cardInfoDockMenu->addAction(QString());
aCardInfoDockFloating->setCheckable(true);
connect(aCardInfoDockFloating, SIGNAL(triggered()), this, SLOT(dockFloatingTriggered()));
aDeckDockVisible = deckDockMenu->addAction(QString());
aDeckDockVisible->setCheckable(true);
connect(aDeckDockVisible, SIGNAL(triggered()), this, SLOT(dockVisibleTriggered()));
aDeckDockFloating = deckDockMenu->addAction(QString());
aDeckDockFloating->setCheckable(true);
connect(aDeckDockFloating, SIGNAL(triggered()), this, SLOT(dockFloatingTriggered()));
aDeckAnalyticsDockVisible = deckAnalyticsMenu->addAction(QString());
aDeckAnalyticsDockVisible->setCheckable(true);
connect(aDeckAnalyticsDockVisible, SIGNAL(triggered()), this, SLOT(dockVisibleTriggered()));
aDeckAnalyticsDockFloating = deckAnalyticsMenu->addAction(QString());
aDeckAnalyticsDockFloating->setCheckable(true);
connect(aDeckAnalyticsDockFloating, SIGNAL(triggered()), this, SLOT(dockFloatingTriggered()));
aFilterDockVisible = filterDockMenu->addAction(QString());
aFilterDockVisible->setCheckable(true);
connect(aFilterDockVisible, SIGNAL(triggered()), this, SLOT(dockVisibleTriggered()));
aFilterDockFloating = filterDockMenu->addAction(QString());
aFilterDockFloating->setCheckable(true);
connect(aFilterDockFloating, SIGNAL(triggered()), this, SLOT(dockFloatingTriggered()));
aPrintingSelectorDockVisible = printingSelectorDockMenu->addAction(QString());
aPrintingSelectorDockVisible->setCheckable(true);
connect(aPrintingSelectorDockVisible, SIGNAL(triggered()), this, SLOT(dockVisibleTriggered()));
aPrintingSelectorDockFloating = printingSelectorDockMenu->addAction(QString());
aPrintingSelectorDockFloating->setCheckable(true);
connect(aPrintingSelectorDockFloating, SIGNAL(triggered()), this, SLOT(dockFloatingTriggered()));
viewMenu->addSeparator();
aResetLayout = viewMenu->addAction(QString());
connect(aResetLayout, SIGNAL(triggered()), this, SLOT(restartLayout()));
viewMenu->addAction(aResetLayout);
deckMenu->setSaveStatus(false);
addTabMenu(viewMenu);
}
QString TabDeckEditorVisual::getTabText() const
{
QString result = tr("Visual Deck: %1").arg(deckDockWidget->getSimpleDeckName());
if (modified)
result.prepend("* ");
return result;
}
void TabDeckEditorVisual::changeModelIndexAndCardInfo(const CardInfoPtr &activeCard)
{
updateCard(activeCard);
changeModelIndexToCard(activeCard);
}
void TabDeckEditorVisual::changeModelIndexToCard(const CardInfoPtr &activeCard)
{
QString cardName = activeCard->getName();
QModelIndex index = deckDockWidget->deckModel->findCard(cardName, DECK_ZONE_MAIN);
if (!index.isValid()) {
index = deckDockWidget->deckModel->findCard(cardName, DECK_ZONE_SIDE);
}
deckDockWidget->deckView->setCurrentIndex(index);
}
void TabDeckEditorVisual::processMainboardCardClick(QMouseEvent *event,
CardInfoPictureWithTextOverlayWidget *instance,
QString zoneName)
{
if (event->button() == Qt::LeftButton) {
actSwapCard(instance->getInfo(), zoneName);
} else if (event->button() == Qt::RightButton) {
actDecrementCard(instance->getInfo());
} else if (event->button() == Qt::MiddleButton) {
deckDockWidget->actRemoveCard();
}
}
void TabDeckEditorVisual::processCardClickDatabaseDisplay(QMouseEvent *event,
CardInfoPictureWithTextOverlayWidget *instance)
{
if (event->button() == Qt::LeftButton) {
actAddCard(instance->getInfo());
} else if (event->button() == Qt::RightButton) {
actDecrementCard(instance->getInfo());
} else if (event->button() == Qt::MiddleButton) {
deckDockWidget->actRemoveCard();
}
}
bool TabDeckEditorVisual::actSaveDeckAs()
{
// We have to disable the quick-add search bar or else it'll steal focus after dialog creation.
tabContainer->visualDeckView->searchBar->setEnabled(false);
auto result = AbstractTabDeckEditor::actSaveDeckAs();
tabContainer->visualDeckView->searchBar->setEnabled(true);
return result;
}
void TabDeckEditorVisual::showPrintingSelector()
{
printingSelectorDockWidget->printingSelector->setCard(cardInfoDockWidget->cardInfo->getInfo(), DECK_ZONE_MAIN);
printingSelectorDockWidget->printingSelector->updateDisplay();
aPrintingSelectorDockVisible->setChecked(true);
printingSelectorDockWidget->setVisible(true);
}
void TabDeckEditorVisual::restartLayout()
{
deckDockWidget->setVisible(true);
cardInfoDockWidget->setVisible(true);
filterDockWidget->setVisible(true);
deckDockWidget->setFloating(false);
cardInfoDockWidget->setFloating(false);
filterDockWidget->setFloating(false);
aCardInfoDockVisible->setChecked(true);
aDeckDockVisible->setChecked(true);
aFilterDockVisible->setChecked(true);
aCardInfoDockFloating->setChecked(false);
aDeckDockFloating->setChecked(false);
aFilterDockFloating->setChecked(false);
addDockWidget(static_cast<Qt::DockWidgetArea>(2), deckDockWidget);
addDockWidget(static_cast<Qt::DockWidgetArea>(2), cardInfoDockWidget);
addDockWidget(static_cast<Qt::DockWidgetArea>(1), deckAnalyticsDock);
addDockWidget(static_cast<Qt::DockWidgetArea>(2), filterDockWidget);
splitDockWidget(cardInfoDockWidget, deckDockWidget, Qt::Horizontal);
splitDockWidget(cardInfoDockWidget, filterDockWidget, Qt::Vertical);
splitDockWidget(searchAndDatabaseDock, deckAnalyticsDock, Qt::Vertical);
deckDockWidget->setMinimumWidth(360);
deckDockWidget->setMaximumWidth(360);
cardInfoDockWidget->setMinimumSize(250, 360);
cardInfoDockWidget->setMaximumSize(250, 360);
QTimer::singleShot(100, this, SLOT(freeDocksSize()));
}
void TabDeckEditorVisual::freeDocksSize()
{
deckDockWidget->setMinimumSize(100, 100);
deckDockWidget->setMaximumSize(5000, 5000);
cardInfoDockWidget->setMinimumSize(100, 100);
cardInfoDockWidget->setMaximumSize(5000, 5000);
filterDockWidget->setMinimumSize(100, 100);
filterDockWidget->setMaximumSize(5000, 5000);
databaseDisplayDockWidget->setMinimumSize(100, 100);
databaseDisplayDockWidget->setMaximumSize(1400, 5000);
}
void TabDeckEditorVisual::refreshShortcuts()
{
ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts();
aResetLayout->setShortcuts(shortcuts.getShortcut("TabDeckEditorVisual/aResetLayout"));
}
void TabDeckEditorVisual::loadLayout()
{
LayoutsSettings &layouts = SettingsCache::instance().layouts();
auto &layoutState = layouts.getDeckEditorLayoutState();
if (layoutState.isNull()) {
restartLayout();
} else {
restoreState(layoutState);
restoreGeometry(layouts.getDeckEditorGeometry());
}
aCardInfoDockVisible->setChecked(!cardInfoDockWidget->isHidden());
aFilterDockVisible->setChecked(!filterDockWidget->isHidden());
aDeckDockVisible->setChecked(!deckDockWidget->isHidden());
aPrintingSelectorDockVisible->setChecked(!printingSelectorDockWidget->isHidden());
aCardInfoDockFloating->setEnabled(aCardInfoDockVisible->isChecked());
aDeckDockFloating->setEnabled(aDeckDockVisible->isChecked());
aFilterDockFloating->setEnabled(aFilterDockVisible->isChecked());
aPrintingSelectorDockFloating->setEnabled(aPrintingSelectorDockVisible->isChecked());
aCardInfoDockFloating->setChecked(cardInfoDockWidget->isFloating());
aFilterDockFloating->setChecked(filterDockWidget->isFloating());
aDeckDockFloating->setChecked(deckDockWidget->isFloating());
aPrintingSelectorDockFloating->setChecked(printingSelectorDockWidget->isFloating());
cardInfoDockWidget->setMinimumSize(layouts.getDeckEditorCardSize());
cardInfoDockWidget->setMaximumSize(layouts.getDeckEditorCardSize());
filterDockWidget->setMinimumSize(layouts.getDeckEditorFilterSize());
filterDockWidget->setMaximumSize(layouts.getDeckEditorFilterSize());
deckDockWidget->setMinimumSize(layouts.getDeckEditorDeckSize());
deckDockWidget->setMaximumSize(layouts.getDeckEditorDeckSize());
printingSelectorDockWidget->setMinimumSize(layouts.getDeckEditorPrintingSelectorSize());
printingSelectorDockWidget->setMaximumSize(layouts.getDeckEditorPrintingSelectorSize());
databaseDisplayDockWidget->setMinimumSize(100, 100);
databaseDisplayDockWidget->setMaximumSize(1400, 5000);
QTimer::singleShot(100, this, &TabDeckEditorVisual::freeDocksSize);
}
void TabDeckEditorVisual::retranslateUi()
{
deckMenu->setTitle(tr("&Visual Deck Editor"));
cardInfoDockWidget->setWindowTitle(tr("Card Info"));
deckDockWidget->setWindowTitle(tr("Deck"));
filterDockWidget->setWindowTitle(tr("Filters"));
viewMenu->setTitle(tr("&View"));
cardInfoDockMenu->setTitle(tr("Card Info"));
deckDockMenu->setTitle(tr("Deck"));
deckAnalyticsMenu->setTitle(tr("Deck Analytics"));
filterDockMenu->setTitle(tr("Filters"));
printingSelectorDockMenu->setTitle(tr("Printing"));
aCardInfoDockVisible->setText(tr("Visible"));
aCardInfoDockFloating->setText(tr("Floating"));
aDeckDockVisible->setText(tr("Visible"));
aDeckDockFloating->setText(tr("Floating"));
aDeckAnalyticsDockVisible->setText(tr("Visible"));
aDeckAnalyticsDockFloating->setText(tr("Floating"));
aFilterDockVisible->setText(tr("Visible"));
aFilterDockFloating->setText(tr("Floating"));
aPrintingSelectorDockVisible->setText(tr("Visible"));
aPrintingSelectorDockFloating->setText(tr("Floating"));
aResetLayout->setText(tr("Reset layout"));
}
// Method uses to sync docks state with menu items state
bool TabDeckEditorVisual::eventFilter(QObject *o, QEvent *e)
{
if (e->type() == QEvent::Close) {
if (o == cardInfoDockWidget) {
aCardInfoDockVisible->setChecked(false);
aCardInfoDockFloating->setEnabled(false);
} else if (o == deckDockWidget) {
aDeckDockVisible->setChecked(false);
aDeckDockFloating->setEnabled(false);
} else if (o == deckAnalyticsDock) {
aDeckAnalyticsDockVisible->setChecked(false);
aDeckAnalyticsDockFloating->setEnabled(false);
} else if (o == filterDockWidget) {
aFilterDockVisible->setChecked(false);
aFilterDockFloating->setEnabled(false);
} else if (o == printingSelectorDockWidget) {
aPrintingSelectorDockVisible->setChecked(false);
aPrintingSelectorDockFloating->setEnabled(false);
}
}
if (o == this && e->type() == QEvent::Hide) {
LayoutsSettings &layouts = SettingsCache::instance().layouts();
layouts.setDeckEditorLayoutState(saveState());
layouts.setDeckEditorGeometry(saveGeometry());
layouts.setDeckEditorCardSize(cardInfoDockWidget->size());
layouts.setDeckEditorFilterSize(filterDockWidget->size());
layouts.setDeckEditorDeckSize(deckDockWidget->size());
layouts.setDeckEditorPrintingSelectorSize(printingSelectorDockWidget->size());
}
return false;
}
void TabDeckEditorVisual::dockVisibleTriggered()
{
QObject *o = sender();
if (o == aCardInfoDockVisible) {
cardInfoDockWidget->setHidden(!aCardInfoDockVisible->isChecked());
aCardInfoDockFloating->setEnabled(aCardInfoDockVisible->isChecked());
return;
}
if (o == aDeckDockVisible) {
deckDockWidget->setHidden(!aDeckDockVisible->isChecked());
aDeckDockFloating->setEnabled(aDeckDockVisible->isChecked());
return;
}
if (o == aDeckAnalyticsDockVisible) {
deckAnalyticsDock->setHidden(!aDeckAnalyticsDockVisible->isChecked());
aDeckAnalyticsDockFloating->setEnabled(aDeckAnalyticsDockVisible->isChecked());
return;
}
if (o == aFilterDockVisible) {
filterDockWidget->setHidden(!aFilterDockVisible->isChecked());
aFilterDockFloating->setEnabled(aFilterDockVisible->isChecked());
return;
}
if (o == aPrintingSelectorDockVisible) {
printingSelectorDockWidget->setHidden(!aPrintingSelectorDockVisible->isChecked());
aPrintingSelectorDockFloating->setEnabled(aPrintingSelectorDockVisible->isChecked());
return;
}
}
void TabDeckEditorVisual::dockFloatingTriggered()
{
QObject *o = sender();
if (o == aCardInfoDockFloating) {
cardInfoDockWidget->setFloating(aCardInfoDockFloating->isChecked());
return;
}
if (o == aDeckDockFloating) {
deckDockWidget->setFloating(aDeckDockFloating->isChecked());
return;
}
if (o == aDeckAnalyticsDockFloating) {
deckAnalyticsDock->setFloating(aDeckAnalyticsDockFloating->isChecked());
return;
}
if (o == aFilterDockFloating) {
filterDockWidget->setFloating(aFilterDockFloating->isChecked());
return;
}
if (o == aPrintingSelectorDockFloating) {
printingSelectorDockWidget->setFloating(aPrintingSelectorDockFloating->isChecked());
return;
}
}
void TabDeckEditorVisual::dockTopLevelChanged(bool topLevel)
{
QObject *o = sender();
if (o == cardInfoDockWidget) {
aCardInfoDockFloating->setChecked(topLevel);
return;
}
if (o == deckDockWidget) {
aDeckDockFloating->setChecked(topLevel);
return;
}
if (o == filterDockWidget) {
aFilterDockFloating->setChecked(topLevel);
return;
}
if (o == deckAnalyticsDock) {
aDeckAnalyticsDockFloating->setChecked(topLevel);
return;
}
if (o == printingSelectorDockWidget) {
aPrintingSelectorDockFloating->setChecked(topLevel);
return;
}
}

View file

@ -0,0 +1,53 @@
#ifndef WINDOW_DECKEDITORVISUAL_H
#define WINDOW_DECKEDITORVISUAL_H
#include "../tab.h"
#include "tab_deck_editor_visual_tab_widget.h"
class TabDeckEditorVisual : public AbstractTabDeckEditor
{
Q_OBJECT
protected slots:
void loadLayout() override;
void restartLayout() override;
void freeDocksSize() override;
void refreshShortcuts() override;
bool eventFilter(QObject *o, QEvent *e) override;
void dockVisibleTriggered() override;
void dockFloatingTriggered() override;
void dockTopLevelChanged(bool topLevel) override;
protected:
TabDeckEditorVisualTabWidget *tabContainer;
QVBoxLayout *centralFrame;
QVBoxLayout *searchAndDatabaseFrame;
QHBoxLayout *searchLayout;
QDockWidget *searchAndDatabaseDock;
QDockWidget *deckAnalyticsDock;
QWidget *centralWidget;
QMenu *deckAnalyticsMenu;
QAction *aDeckAnalyticsDockVisible, *aDeckAnalyticsDockFloating;
public:
explicit TabDeckEditorVisual(TabSupervisor *_tabSupervisor);
void retranslateUi() override;
QString getTabText() const override;
void changeModelIndexAndCardInfo(const CardInfoPtr &activeCard);
void changeModelIndexToCard(const CardInfoPtr &activeCard);
void createDeckAnalyticsDock();
void createMenus() override;
void createSearchAndDatabaseFrame();
void createCentralFrame();
public slots:
void onDeckChanged() override;
void showPrintingSelector() override;
void
processMainboardCardClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance, QString zoneName);
void processCardClickDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance);
bool actSaveDeckAs() override;
};
#endif

View file

@ -0,0 +1,113 @@
#include "tab_deck_editor_visual_tab_widget.h"
#include "../../ui/widgets/visual_database_display/visual_database_display_widget.h"
#include "../abstract_tab_deck_editor.h"
TabDeckEditorVisualTabWidget::TabDeckEditorVisualTabWidget(QWidget *parent,
AbstractTabDeckEditor *_deckEditor,
DeckListModel *_deckModel,
CardDatabaseModel *_cardDatabaseModel,
CardDatabaseDisplayModel *_cardDatabaseDisplayModel)
: QTabWidget(parent), deckEditor(_deckEditor), deckModel(_deckModel), cardDatabaseModel(_cardDatabaseModel),
cardDatabaseDisplayModel(_cardDatabaseDisplayModel)
{
this->setTabsClosable(true); // Enable tab closing
connect(this, &QTabWidget::tabCloseRequested, this, &TabDeckEditorVisualTabWidget::handleTabClose);
// Set up the layout and add tab widget
layout = new QVBoxLayout(this);
setLayout(layout);
visualDeckView = new VisualDeckEditorWidget(this, deckModel);
visualDeckView->setObjectName("visualDeckView");
connect(visualDeckView, &VisualDeckEditorWidget::activeCardChanged, this,
&TabDeckEditorVisualTabWidget::onCardChanged);
connect(visualDeckView, &VisualDeckEditorWidget::cardClicked, this,
&TabDeckEditorVisualTabWidget::onCardClickedDeckEditor);
connect(visualDeckView, &VisualDeckEditorWidget::cardAdditionRequested, deckEditor,
&AbstractTabDeckEditor::actAddCard);
visualDatabaseDisplay =
new VisualDatabaseDisplayWidget(this, deckEditor, _cardDatabaseModel, _cardDatabaseDisplayModel);
visualDatabaseDisplay->setObjectName("visualDatabaseView");
connect(visualDatabaseDisplay, &VisualDatabaseDisplayWidget::cardHoveredDatabaseDisplay, this,
&TabDeckEditorVisualTabWidget::onCardChangedDatabaseDisplay);
connect(visualDatabaseDisplay, &VisualDatabaseDisplayWidget::cardClickedDatabaseDisplay, this,
&TabDeckEditorVisualTabWidget::onCardClickedDatabaseDisplay);
deckAnalytics = new DeckAnalyticsWidget(this, deckModel);
deckAnalytics->setObjectName("deckAnalytics");
sampleHandWidget = new VisualDeckEditorSampleHandWidget(this, deckModel);
this->addNewTab(visualDeckView, tr("Visual Deck View"));
this->addNewTab(visualDatabaseDisplay, tr("Visual Database Display"));
this->addNewTab(deckAnalytics, tr("Deck Analytics"));
this->addNewTab(sampleHandWidget, tr("Sample Hand"));
}
void TabDeckEditorVisualTabWidget::onCardChanged(CardInfoPtr activeCard)
{
emit cardChanged(activeCard);
}
void TabDeckEditorVisualTabWidget::onCardChangedDatabaseDisplay(CardInfoPtr activeCard)
{
emit cardChangedDatabaseDisplay(activeCard);
}
void TabDeckEditorVisualTabWidget::onCardClickedDeckEditor(QMouseEvent *event,
CardInfoPictureWithTextOverlayWidget *instance,
QString zoneName)
{
emit cardClicked(event, instance, zoneName);
}
void TabDeckEditorVisualTabWidget::onCardClickedDatabaseDisplay(QMouseEvent *event,
CardInfoPictureWithTextOverlayWidget *instance)
{
emit cardClickedDatabaseDisplay(event, instance);
}
void TabDeckEditorVisualTabWidget::addNewTab(QWidget *widget, const QString &title)
{
// Add new tab to the tab widget
this->addTab(widget, title);
}
void TabDeckEditorVisualTabWidget::removeCurrentTab()
{
// Remove the currently selected tab
int currentIndex = this->currentIndex();
if (currentIndex != -1) {
this->removeTab(currentIndex);
}
}
void TabDeckEditorVisualTabWidget::setTabTitle(int index, const QString &title)
{
// Set the title of the tab at the given index
if (index >= 0 && index < this->count()) {
this->setTabText(index, title);
}
}
QWidget *TabDeckEditorVisualTabWidget::getCurrentTab() const
{
// Return the currently selected tab widget
return this->currentWidget();
}
int TabDeckEditorVisualTabWidget::getTabCount() const
{
// Return the number of tabs
return this->count();
}
void TabDeckEditorVisualTabWidget::handleTabClose(int index)
{
// Handle closing of the tab at the given index
QWidget *tab = this->widget(index);
this->removeTab(index);
delete tab; // Delete the tab's widget to free memory
}

View file

@ -0,0 +1,62 @@
#ifndef TAB_DECK_EDITOR_VISUAL_TAB_WIDGET_H
#define TAB_DECK_EDITOR_VISUAL_TAB_WIDGET_H
#include "../../ui/widgets/deck_analytics/deck_analytics_widget.h"
#include "../../ui/widgets/printing_selector/printing_selector.h"
#include "../../ui/widgets/visual_database_display/visual_database_display_widget.h"
#include "../../ui/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.h"
#include "../../ui/widgets/visual_deck_editor/visual_deck_editor_widget.h"
#include "../abstract_tab_deck_editor.h"
#include <QTabWidget>
#include <QVBoxLayout>
#include <QWidget>
class TabDeckEditorVisualTabWidget : public QTabWidget
{
Q_OBJECT
public:
explicit TabDeckEditorVisualTabWidget(QWidget *parent,
AbstractTabDeckEditor *_deckEditor,
DeckListModel *_deckModel,
CardDatabaseModel *_cardDatabaseModel,
CardDatabaseDisplayModel *_cardDatabaseDisplayModel);
// Utility functions
void addNewTab(QWidget *widget, const QString &title);
void removeCurrentTab();
void setTabTitle(int index, const QString &title);
QWidget *getCurrentTab() const;
int getTabCount() const;
VisualDeckEditorWidget *visualDeckView;
DeckAnalyticsWidget *deckAnalytics;
VisualDatabaseDisplayWidget *visualDatabaseDisplay;
PrintingSelector *printingSelector;
VisualDeckEditorSampleHandWidget *sampleHandWidget;
public slots:
void onCardChanged(CardInfoPtr activeCard);
void onCardChangedDatabaseDisplay(CardInfoPtr activeCard);
void onCardClickedDeckEditor(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance, QString zoneName);
void onCardClickedDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance);
signals:
void cardChanged(CardInfoPtr activeCard);
void cardChangedDatabaseDisplay(CardInfoPtr activeCard);
void cardClicked(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance, QString zoneName);
void cardClickedDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance);
private:
QVBoxLayout *layout; // Layout for the tab widget and other controls
AbstractTabDeckEditor *deckEditor;
DeckListModel *deckModel;
CardDatabaseModel *cardDatabaseModel;
CardDatabaseDisplayModel *cardDatabaseDisplayModel;
private slots:
void handleTabClose(int index); // Slot for closing a tab
};
#endif // TAB_DECK_EDITOR_VISUAL_TAB_WIDGET_H

View file

@ -12,7 +12,7 @@
TabDeckStorageVisual::TabDeckStorageVisual(TabSupervisor *_tabSupervisor) TabDeckStorageVisual::TabDeckStorageVisual(TabSupervisor *_tabSupervisor)
: Tab(_tabSupervisor), visualDeckStorageWidget(new VisualDeckStorageWidget(this)) : Tab(_tabSupervisor), visualDeckStorageWidget(new VisualDeckStorageWidget(this))
{ {
connect(this, &TabDeckStorageVisual::openDeckEditor, tabSupervisor, &TabSupervisor::addDeckEditorTab); connect(this, &TabDeckStorageVisual::openDeckEditor, tabSupervisor, &TabSupervisor::addVisualDeckEditorTab);
connect(visualDeckStorageWidget, &VisualDeckStorageWidget::deckLoadRequested, this, connect(visualDeckStorageWidget, &VisualDeckStorageWidget::deckLoadRequested, this,
&TabDeckStorageVisual::actOpenLocalDeck); &TabDeckStorageVisual::actOpenLocalDeck);
connect(visualDeckStorageWidget, &VisualDeckStorageWidget::openDeckEditor, this, connect(visualDeckStorageWidget, &VisualDeckStorageWidget::openDeckEditor, this,

View file

@ -33,7 +33,7 @@ void TappedOutInterface::queryFinished(QNetworkReply *reply)
* can be extracted from the header. The http status is a 302 "redirect". * can be extracted from the header. The http status is a 302 "redirect".
*/ */
QString deckUrl = reply->rawHeader("Location"); QString deckUrl = reply->rawHeader("Location");
qCDebug(TappedOutInterfaceLog) << "Tappedout: good reply, http status" << httpStatus << "location" << deckUrl; qCInfo(TappedOutInterfaceLog) << "Tappedout: good reply, http status" << httpStatus << "location" << deckUrl;
QDesktopServices::openUrl("https://tappedout.net" + deckUrl); QDesktopServices::openUrl("https://tappedout.net" + deckUrl);
} else { } else {
/* /*
@ -57,8 +57,8 @@ void TappedOutInterface::queryFinished(QNetworkReply *reply)
} }
QString errorMessage = errorMessageList.join("\n"); QString errorMessage = errorMessageList.join("\n");
qCDebug(TappedOutInterfaceLog) << "Tappedout: bad reply, http status" << httpStatus << "size" << data.size() qCWarning(TappedOutInterfaceLog) << "Tappedout: bad reply, http status" << httpStatus << "size" << data.size()
<< "message" << errorMessage; << "message" << errorMessage;
QMessageBox::critical(nullptr, tr("Error"), errorMessage); QMessageBox::critical(nullptr, tr("Error"), errorMessage);
} }

View file

@ -7,7 +7,7 @@
#include <QWidget> #include <QWidget>
#include <qstyle.h> #include <qstyle.h>
inline Q_LOGGING_CATEGORY(FlowLayoutLog, "flow_layout"); inline Q_LOGGING_CATEGORY(FlowLayoutLog, "flow_layout", QtInfoMsg);
class FlowLayout : public QLayout class FlowLayout : public QLayout
{ {

View file

@ -1,5 +1,6 @@
#include "overlap_layout.h" #include "overlap_layout.h"
#include <QDebug>
#include <QtMath> #include <QtMath>
/** /**
@ -32,9 +33,10 @@ OverlapLayout::OverlapLayout(QWidget *parent,
const int overlapPercentage, const int overlapPercentage,
const int maxColumns, const int maxColumns,
const int maxRows, const int maxRows,
const Qt::Orientation direction) const Qt::Orientation _overlapDirection,
const Qt::Orientation _flowDirection)
: QLayout(parent), overlapPercentage(overlapPercentage), maxColumns(maxColumns), maxRows(maxRows), : QLayout(parent), overlapPercentage(overlapPercentage), maxColumns(maxColumns), maxRows(maxRows),
direction(direction) overlapDirection(_overlapDirection), flowDirection(_flowDirection)
{ {
} }
@ -148,17 +150,21 @@ void OverlapLayout::setGeometry(const QRect &rect)
} }
// Calculate the overlap offsets based on the layout direction and overlap percentage. // Calculate the overlap offsets based on the layout direction and overlap percentage.
const int overlapOffsetWidth = (direction == Qt::Horizontal) ? (maxItemWidth * overlapPercentage / 100) : 0; const int overlapOffsetWidth = (overlapDirection == Qt::Horizontal) ? (maxItemWidth * overlapPercentage / 100) : 0;
const int overlapOffsetHeight = (direction == Qt::Vertical) ? (maxItemHeight * overlapPercentage / 100) : 0; const int overlapOffsetHeight = (overlapDirection == Qt::Vertical) ? (maxItemHeight * overlapPercentage / 100) : 0;
// Determine the number of columns based on layout constraints and available space. // Determine the number of columns based on layout constraints and available space.
int columns; int columns;
if (direction == Qt::Horizontal) { if (flowDirection == Qt::Horizontal) {
if (maxColumns > 0) { if (maxColumns > 0) {
// Calculate the maximum possible columns given the available width and overlap. // Calculate the maximum possible columns given the available width and overlap.
const int availableColumns = (availableWidth + overlapOffsetWidth) / (maxItemWidth - overlapOffsetWidth); const int availableColumns = (availableWidth + overlapOffsetWidth) / (maxItemWidth - overlapOffsetWidth);
// Use the smaller of maxColumns and availableColumns. // Use the smaller of maxColumns and availableColumns.
qCDebug(OverlapLayoutLog) << " Max Columns " << maxColumns << " available columns " << availableColumns;
columns = qMin(maxColumns, availableColumns); columns = qMin(maxColumns, availableColumns);
if (columns < 1) {
columns = 1;
}
} else { } else {
// If no maxColumns constraint, allow as many columns as possible. // If no maxColumns constraint, allow as many columns as possible.
columns = INT_MAX; columns = INT_MAX;
@ -170,12 +176,16 @@ void OverlapLayout::setGeometry(const QRect &rect)
// Determine the number of rows based on layout constraints and available space. // Determine the number of rows based on layout constraints and available space.
int rows; int rows;
if (direction == Qt::Vertical) { if (flowDirection == Qt::Vertical) {
if (maxRows > 0) { if (maxRows > 0) {
// Calculate the maximum possible rows given the available height and overlap. // Calculate the maximum possible rows given the available height and overlap.
const int availableRows = (availableHeight + overlapOffsetHeight) / (maxItemHeight - overlapOffsetHeight); const int availableRows = (availableHeight + overlapOffsetHeight) / (maxItemHeight - overlapOffsetHeight);
// Use the smaller of maxRows and availableRows. // Use the smaller of maxRows and availableRows.
qCDebug(OverlapLayoutLog) << " Max Rows " << maxRows << " available rows " << availableRows;
rows = qMin(maxRows, availableRows); rows = qMin(maxRows, availableRows);
if (rows < 1) {
rows = 1;
}
} else { } else {
// If no maxRows constraint, allow as many rows as possible. // If no maxRows constraint, allow as many rows as possible.
rows = INT_MAX; rows = INT_MAX;
@ -200,16 +210,17 @@ void OverlapLayout::setGeometry(const QRect &rect)
const int yPos = rect.top() + currentRow * (maxItemHeight - overlapOffsetHeight); const int yPos = rect.top() + currentRow * (maxItemHeight - overlapOffsetHeight);
item->setGeometry(QRect(xPos, yPos, maxItemWidth, maxItemHeight)); item->setGeometry(QRect(xPos, yPos, maxItemWidth, maxItemHeight));
// TODO: Figure this out properly or maybe adjust size hint to account for this?
// Update row and column indices based on the layout direction. // Update row and column indices based on the layout direction.
if (direction == Qt::Horizontal) { if (overlapDirection == Qt::Horizontal) {
currentColumn++; currentColumn++;
if (currentColumn >= columns) { if (currentColumn > qCeil(itemList.size() / rows)) {
currentColumn = 0; currentColumn = 0;
currentRow++; currentRow++;
} }
} else { } else {
currentRow++; currentRow++;
if (currentRow >= rows) { if (currentRow > qCeil(itemList.size() / columns)) {
currentRow = 0; currentRow = 0;
currentColumn++; currentColumn++;
} }
@ -223,88 +234,86 @@ void OverlapLayout::setGeometry(const QRect &rect)
*/ */
QSize OverlapLayout::calculatePreferredSize() const QSize OverlapLayout::calculatePreferredSize() const
{ {
// Get the parent widget for size and margin calculations.
const QWidget *parentWidget = this->parentWidget();
if (!parentWidget) {
return QSize(0, 0);
}
// Determine the maximum item dimensions. if (itemList.isEmpty()) {
return QSize(0, 0);
}
int availableWidth = parentWidget->width();
int availableHeight = parentWidget->height();
const QMargins margins = parentWidget->contentsMargins();
availableWidth -= margins.left() + margins.right();
availableHeight -= margins.top() + margins.bottom();
// Determine the maximum item width and height among all layout items.
int maxItemWidth = 0; int maxItemWidth = 0;
int maxItemHeight = 0; int maxItemHeight = 0;
for (QLayoutItem *item : itemList) { for (QLayoutItem *item : itemList) {
if (item == nullptr) { if (item != nullptr && item->widget()) {
continue; QSize itemSize = item->widget()->sizeHint();
maxItemWidth = qMax(maxItemWidth, itemSize.width());
maxItemHeight = qMax(maxItemHeight, itemSize.height());
} }
if (!item->widget()) {
continue;
}
QSize itemSize = item->widget()->sizeHint();
maxItemWidth = qMax(maxItemWidth, itemSize.width());
maxItemHeight = qMax(maxItemHeight, itemSize.height());
} }
// Calculate the overlap offsets. // Calculate the overlap offsets based on the layout direction and overlap percentage.
const int extra_for_overlap = (100 - overlapPercentage); const int overlapOffsetWidth = (overlapDirection == Qt::Horizontal) ? (maxItemWidth * overlapPercentage / 100) : 0;
const int overlapOffsetWidth = const int overlapOffsetHeight = (overlapDirection == Qt::Vertical) ? (maxItemHeight * overlapPercentage / 100) : 0;
(direction == Qt::Horizontal) ? qRound((maxItemWidth / 100.0) * extra_for_overlap) : 0;
const int overlapOffsetHeight =
(direction == Qt::Vertical) ? qRound((maxItemHeight / 100.0) * extra_for_overlap) : 0;
// Variables to hold the total dimensions based on layout orientation. // Determine the number of columns based on layout constraints and available space.
int totalWidth = 0; int columns;
int totalHeight = 0; if (flowDirection == Qt::Horizontal) {
if (maxColumns > 0) {
// Calculate the total size based on the layout direction and constraints. // Calculate the maximum possible columns given the available width and overlap.
if (direction == Qt::Horizontal) { const int availableColumns = (availableWidth + overlapOffsetWidth) / (maxItemWidth - overlapOffsetWidth);
// Determine the number of columns: // Use the smaller of maxColumns and availableColumns.
// - Use maxColumns if it is greater than 0 (constraint set by the user). qCDebug(OverlapLayoutLog) << " Max Columns " << maxColumns << " available columns " << availableColumns;
// - Otherwise, set the number of columns to the total number of items in the layout. columns = qMin(maxColumns, availableColumns);
const int numColumns = (maxColumns > 0) ? static_cast<int>(maxColumns) : static_cast<int>(itemList.size()); if (columns < 1) {
columns = 1;
// Calculate the extra space required for overlaps between columns: }
// - Each overlap reduces the effective width of subsequent items. } else {
const int extra_space_for_overlaps = overlapOffsetWidth * (numColumns - 1); // If no maxColumns constraint, allow as many columns as possible.
columns = INT_MAX;
// Total width: }
// - The first item's width is fully included (maxItemWidth). } else {
// - Add the space for all overlaps between adjacent items. // If not a horizontal layout, column count is irrelevant.
totalWidth = maxItemWidth + extra_space_for_overlaps; columns = INT_MAX;
// Determine the number of rows:
// - Use maxRows if maxColumns is set (to constrain the number of rows).
// - Otherwise, assume a single row.
const int numRows =
(maxColumns > 0) ? qCeil(static_cast<double>(itemList.size()) / static_cast<double>(numColumns)) : 1;
// Total height:
// - Multiply the number of rows by the item height (maxItemHeight).
// - Subtract the height overlap between rows to avoid double-counting.
totalHeight = maxItemHeight * numRows - (numRows - 1) * overlapOffsetHeight;
} else if (direction == Qt::Vertical) {
// Determine the number of columns:
// - Use maxRows to calculate how many columns are needed if a row constraint exists.
// - Otherwise, assume a single column.
const int numColumns =
(maxRows != 0) ? qCeil(static_cast<double>(itemList.size()) / static_cast<double>(maxRows)) : 1;
// Total width:
// - Multiply the number of columns by the item width (maxItemWidth).
// - Subtract the width overlap between columns to avoid double-counting.
totalWidth = maxItemWidth * numColumns - (numColumns - 1) * overlapOffsetWidth;
// Determine the number of rows:
// - Use maxRows if it is greater than 0 (constraint set by the user).
// - Otherwise, set the number of rows to the total number of items in the layout.
const int numRows = (maxRows > 0) ? static_cast<int>(maxRows) : static_cast<int>(itemList.size());
// Calculate the extra space required for overlaps between rows:
// - Each overlap reduces the effective height of subsequent items.
const int extraSpaceForOverlaps = overlapOffsetHeight * (numRows - 1);
// Total height:
// - The first item's height is fully included (maxItemHeight).
// - Add the space for all overlaps between adjacent items.
totalHeight = maxItemHeight + extraSpaceForOverlaps;
} }
return {totalWidth, totalHeight}; // Determine the number of rows based on layout constraints and available space.
int rows;
if (flowDirection == Qt::Vertical) {
if (maxRows > 0) {
// Calculate the maximum possible rows given the available height and overlap.
const int availableRows = (availableHeight + overlapOffsetHeight) / (maxItemHeight - overlapOffsetHeight);
// Use the smaller of maxRows and availableRows.
qCDebug(OverlapLayoutLog) << " Max Rows " << maxRows << " available rows " << availableRows;
rows = qMin(maxRows, availableRows);
if (rows < 1) {
rows = 1;
}
} else {
// If no maxRows constraint, allow as many rows as possible.
rows = INT_MAX;
}
} else {
// If not a vertical layout, row count is irrelevant.
rows = INT_MAX;
}
if (overlapDirection == Qt::Horizontal) {
return QSize(maxItemWidth + ((qCeil(itemList.size() / rows)) * (maxItemWidth - overlapOffsetWidth)),
rows * maxItemHeight);
} else {
return QSize(columns * maxItemWidth,
maxItemHeight + ((qCeil(itemList.size() / columns)) * (maxItemHeight - overlapOffsetHeight)));
}
} }
/** /**
@ -341,7 +350,7 @@ QSize OverlapLayout::minimumSize() const
*/ */
void OverlapLayout::setDirection(const Qt::Orientation _direction) void OverlapLayout::setDirection(const Qt::Orientation _direction)
{ {
direction = _direction; overlapDirection = _direction;
} }
/** /**
@ -378,7 +387,7 @@ void OverlapLayout::setMaxRows(const int _maxRows)
*/ */
int OverlapLayout::calculateMaxColumns() const int OverlapLayout::calculateMaxColumns() const
{ {
if (direction != Qt::Vertical || itemList.isEmpty()) { if (overlapDirection != Qt::Vertical || itemList.isEmpty()) {
return 1; // Only relevant if the layout direction is vertical return 1; // Only relevant if the layout direction is vertical
} }
@ -410,7 +419,7 @@ int OverlapLayout::calculateMaxColumns() const
*/ */
int OverlapLayout::calculateRowsForColumns(const int columns) const int OverlapLayout::calculateRowsForColumns(const int columns) const
{ {
if (direction != Qt::Vertical || itemList.isEmpty() || columns <= 0) { if (overlapDirection != Qt::Vertical || itemList.isEmpty() || columns <= 0) {
return 1; // Only relevant if the layout direction is vertical and there are items return 1; // Only relevant if the layout direction is vertical and there are items
} }
@ -429,7 +438,7 @@ int OverlapLayout::calculateRowsForColumns(const int columns) const
*/ */
int OverlapLayout::calculateMaxRows() const int OverlapLayout::calculateMaxRows() const
{ {
if (direction != Qt::Horizontal || itemList.isEmpty()) { if (overlapDirection != Qt::Horizontal || itemList.isEmpty()) {
return 1; // Only relevant if the layout direction is horizontal return 1; // Only relevant if the layout direction is horizontal
} }
@ -464,7 +473,7 @@ int OverlapLayout::calculateMaxRows() const
*/ */
int OverlapLayout::calculateColumnsForRows(const int rows) const int OverlapLayout::calculateColumnsForRows(const int rows) const
{ {
if (direction != Qt::Horizontal || itemList.isEmpty() || rows <= 0) { if (overlapDirection != Qt::Horizontal || itemList.isEmpty() || rows <= 0) {
return 1; // Only relevant if the layout direction is horizontal and there are items return 1; // Only relevant if the layout direction is horizontal and there are items
} }

View file

@ -3,8 +3,11 @@
#include <QLayout> #include <QLayout>
#include <QList> #include <QList>
#include <QLoggingCategory>
#include <QWidget> #include <QWidget>
inline Q_LOGGING_CATEGORY(OverlapLayoutLog, "overlap_layout");
class OverlapLayout : public QLayout class OverlapLayout : public QLayout
{ {
public: public:
@ -12,7 +15,8 @@ public:
int overlapPercentage = 10, int overlapPercentage = 10,
int maxColumns = 2, int maxColumns = 2,
int maxRows = 2, int maxRows = 2,
Qt::Orientation direction = Qt::Horizontal); Qt::Orientation overlapDirection = Qt::Vertical,
Qt::Orientation flowDirection = Qt::Horizontal);
~OverlapLayout(); ~OverlapLayout();
void addItem(QLayoutItem *item) override; void addItem(QLayoutItem *item) override;
@ -35,7 +39,8 @@ private:
int overlapPercentage; int overlapPercentage;
int maxColumns; int maxColumns;
int maxRows; int maxRows;
Qt::Orientation direction; Qt::Orientation overlapDirection;
Qt::Orientation flowDirection;
// Calculate the preferred size of the layout // Calculate the preferred size of the layout
QSize calculatePreferredSize() const; QSize calculatePreferredSize() const;

View file

@ -117,7 +117,7 @@ void LineEditCompleter::setCompleter(QCompleter *completer)
{ {
c = completer; c = completer;
c->setWidget(this); c->setWidget(this);
connect(c, SIGNAL(activated(QString)), this, SLOT(insertCompletion(QString))); connect(c, qOverload<const QString &>(&QCompleter::activated), this, &LineEditCompleter::insertCompletion);
} }
void LineEditCompleter::setCompletionList(QStringList completionList) void LineEditCompleter::setCompletionList(QStringList completionList)

View file

@ -18,7 +18,7 @@ PhaseButton::PhaseButton(const QString &_name, QGraphicsItem *parent, QAction *_
{ {
if (highlightable) { if (highlightable) {
activeAnimationTimer = new QTimer(this); activeAnimationTimer = new QTimer(this);
connect(activeAnimationTimer, SIGNAL(timeout()), this, SLOT(updateAnimation())); connect(activeAnimationTimer, &QTimer::timeout, this, &PhaseButton::updateAnimation);
activeAnimationTimer->setSingleShot(false); activeAnimationTimer->setSingleShot(false);
} else } else
activeAnimationCounter = 9; activeAnimationCounter = 9;
@ -106,9 +106,9 @@ PhasesToolbar::PhasesToolbar(QGraphicsItem *parent)
: QGraphicsItem(parent), width(100), height(100), ySpacing(1), symbolSize(8) : QGraphicsItem(parent), width(100), height(100), ySpacing(1), symbolSize(8)
{ {
auto *aUntapAll = new QAction(this); auto *aUntapAll = new QAction(this);
connect(aUntapAll, SIGNAL(triggered()), this, SLOT(actUntapAll())); connect(aUntapAll, &QAction::triggered, this, &PhasesToolbar::actUntapAll);
auto *aDrawCard = new QAction(this); auto *aDrawCard = new QAction(this);
connect(aDrawCard, SIGNAL(triggered()), this, SLOT(actDrawCard())); connect(aDrawCard, &QAction::triggered, this, &PhasesToolbar::actDrawCard);
PhaseButton *untapButton = new PhaseButton("untap", this, aUntapAll); PhaseButton *untapButton = new PhaseButton("untap", this, aUntapAll);
PhaseButton *upkeepButton = new PhaseButton("upkeep", this); PhaseButton *upkeepButton = new PhaseButton("upkeep", this);
@ -126,10 +126,10 @@ PhasesToolbar::PhasesToolbar(QGraphicsItem *parent)
<< combatBlockersButton << combatDamageButton << combatEndButton << main2Button << cleanupButton; << combatBlockersButton << combatDamageButton << combatEndButton << main2Button << cleanupButton;
for (auto &i : buttonList) for (auto &i : buttonList)
connect(i, SIGNAL(clicked()), this, SLOT(phaseButtonClicked())); connect(i, &PhaseButton::clicked, this, &PhasesToolbar::phaseButtonClicked);
nextTurnButton = new PhaseButton("nextturn", this, nullptr, false); nextTurnButton = new PhaseButton("nextturn", this, nullptr, false);
connect(nextTurnButton, SIGNAL(clicked()), this, SLOT(actNextTurn())); connect(nextTurnButton, &PhaseButton::clicked, this, &PhasesToolbar::actNextTurn);
rearrangeButtons(); rearrangeButtons();

View file

@ -23,11 +23,10 @@
PictureLoader::PictureLoader() : QObject(nullptr) PictureLoader::PictureLoader() : QObject(nullptr)
{ {
worker = new PictureLoaderWorker; worker = new PictureLoaderWorker;
connect(&SettingsCache::instance(), SIGNAL(picsPathChanged()), this, SLOT(picsPathChanged())); connect(&SettingsCache::instance(), &SettingsCache::picsPathChanged, this, &PictureLoader::picsPathChanged);
connect(&SettingsCache::instance(), SIGNAL(picDownloadChanged()), this, SLOT(picDownloadChanged())); connect(&SettingsCache::instance(), &SettingsCache::picDownloadChanged, this, &PictureLoader::picDownloadChanged);
connect(worker, SIGNAL(imageLoaded(CardInfoPtr, const QImage &)), this, connect(worker, &PictureLoaderWorker::imageLoaded, this, &PictureLoader::imageLoaded);
SLOT(imageLoaded(CardInfoPtr, const QImage &)));
} }
PictureLoader::~PictureLoader() PictureLoader::~PictureLoader()
@ -115,7 +114,7 @@ void PictureLoader::getPixmap(QPixmap &pixmap, CardInfoPtr card, QSize size)
QPixmap bigPixmap; QPixmap bigPixmap;
if (QPixmapCache::find(key, &bigPixmap)) { if (QPixmapCache::find(key, &bigPixmap)) {
if (bigPixmap.isNull()) { if (bigPixmap.isNull()) {
qCWarning(PictureLoaderLog) << "Cached pixmap for key" << key << "is NULL!"; qCDebug(PictureLoaderLog) << "Cached pixmap for key" << key << "is NULL!";
return; return;
} }
@ -140,7 +139,11 @@ void PictureLoader::imageLoaded(CardInfoPtr card, const QImage &image)
QPixmapCache::insert(card->getPixmapCacheKey(), QPixmap()); QPixmapCache::insert(card->getPixmapCacheKey(), QPixmap());
} else { } else {
if (card->getUpsideDownArt()) { if (card->getUpsideDownArt()) {
#if (QT_VERSION >= QT_VERSION_CHECK(6, 9, 0))
QImage mirrorImage = image.flipped(Qt::Horizontal | Qt::Vertical);
#else
QImage mirrorImage = image.mirrored(true, true); QImage mirrorImage = image.mirrored(true, true);
#endif
QPixmapCache::insert(card->getPixmapCacheKey(), QPixmap::fromImage(mirrorImage)); QPixmapCache::insert(card->getPixmapCacheKey(), QPixmap::fromImage(mirrorImage));
} else { } else {
QPixmapCache::insert(card->getPixmapCacheKey(), QPixmap::fromImage(image)); QPixmapCache::insert(card->getPixmapCacheKey(), QPixmap::fromImage(image));
@ -195,3 +198,31 @@ void PictureLoader::picsPathChanged()
{ {
QPixmapCache::clear(); QPixmapCache::clear();
} }
bool PictureLoader::hasCustomArt()
{
auto picsPath = SettingsCache::instance().getPicsPath();
QDirIterator it(picsPath, QDir::Dirs | QDir::NoDotAndDotDot);
// Check if there is at least one non-directory file in the pics path, other
// than in the "downloadedPics" subdirectory.
while (it.hasNext()) {
#if (QT_VERSION >= QT_VERSION_CHECK(6, 3, 0))
QFileInfo dir(it.nextFileInfo());
#else
// nextFileInfo() is only available in Qt 6.3+, for previous versions, we build
// the QFileInfo from a QString which requires more system calls.
QFileInfo dir(it.next());
#endif
if (it.fileName() == "downloadedPics")
continue;
QDirIterator subIt(it.filePath(), QDir::Files, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
if (subIt.hasNext()) {
return true;
}
}
return false;
}

View file

@ -1,7 +1,7 @@
#ifndef PICTURELOADER_H #ifndef PICTURELOADER_H
#define PICTURELOADER_H #define PICTURELOADER_H
#include "../../../game/cards/card_database.h" #include "../../../game/cards/card_info.h"
#include "picture_loader_worker.h" #include "picture_loader_worker.h"
#include <QLoggingCategory> #include <QLoggingCategory>
@ -36,6 +36,7 @@ public:
static void clearPixmapCache(CardInfoPtr card); static void clearPixmapCache(CardInfoPtr card);
static void clearPixmapCache(); static void clearPixmapCache();
static void cacheCardPixmaps(QList<CardInfoPtr> cards); static void cacheCardPixmaps(QList<CardInfoPtr> cards);
static bool hasCustomArt();
public slots: public slots:
static void clearNetworkCache(); static void clearNetworkCache();

View file

@ -16,11 +16,16 @@ QStringList PictureLoaderWorker::md5Blacklist = QStringList() << "db0c48db407a90
PictureLoaderWorker::PictureLoaderWorker() PictureLoaderWorker::PictureLoaderWorker()
: QObject(nullptr), picsPath(SettingsCache::instance().getPicsPath()), : QObject(nullptr), picsPath(SettingsCache::instance().getPicsPath()),
customPicsPath(SettingsCache::instance().getCustomPicsPath()), customPicsPath(SettingsCache::instance().getCustomPicsPath()),
picDownload(SettingsCache::instance().getPicDownload()), downloadRunning(false), loadQueueRunning(false) picDownload(SettingsCache::instance().getPicDownload()), downloadRunning(false), loadQueueRunning(false),
overrideAllCardArtWithPersonalPreference(SettingsCache::instance().getOverrideAllCardArtWithPersonalPreference())
{ {
connect(this, SIGNAL(startLoadQueue()), this, SLOT(processLoadQueue()), Qt::QueuedConnection); connect(this, &PictureLoaderWorker::startLoadQueue, this, &PictureLoaderWorker::processLoadQueue,
connect(&SettingsCache::instance(), SIGNAL(picsPathChanged()), this, SLOT(picsPathChanged())); Qt::QueuedConnection);
connect(&SettingsCache::instance(), SIGNAL(picDownloadChanged()), this, SLOT(picDownloadChanged())); connect(&SettingsCache::instance(), &SettingsCache::picsPathChanged, this, &PictureLoaderWorker::picsPathChanged);
connect(&SettingsCache::instance(), &SettingsCache::picDownloadChanged, this,
&PictureLoaderWorker::picDownloadChanged);
connect(&SettingsCache::instance(), &SettingsCache::overrideAllCardArtWithPersonalPreferenceChanged, this,
&PictureLoaderWorker::setOverrideAllCardArtWithPersonalPreference);
networkManager = new QNetworkAccessManager(this); networkManager = new QNetworkAccessManager(this);
// We need a timeout to ensure requests don't hang indefinitely in case of // We need a timeout to ensure requests don't hang indefinitely in case of
@ -40,7 +45,7 @@ PictureLoaderWorker::PictureLoaderWorker()
// Use a ManualRedirectPolicy since we keep track of redirects in picDownloadFinished // Use a ManualRedirectPolicy since we keep track of redirects in picDownloadFinished
// We can't use NoLessSafeRedirectPolicy because it is not applied with AlwaysCache // We can't use NoLessSafeRedirectPolicy because it is not applied with AlwaysCache
networkManager->setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy); networkManager->setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy);
connect(networkManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(picDownloadFinished(QNetworkReply *))); connect(networkManager, &QNetworkAccessManager::finished, this, &PictureLoaderWorker::picDownloadFinished);
cacheFilePath = SettingsCache::instance().getRedirectCachePath() + REDIRECT_CACHE_FILENAME; cacheFilePath = SettingsCache::instance().getRedirectCachePath() + REDIRECT_CACHE_FILENAME;
loadRedirectCache(); loadRedirectCache();
@ -83,11 +88,24 @@ void PictureLoaderWorker::processLoadQueue()
qCDebug(PictureLoaderWorkerLog).nospace() qCDebug(PictureLoaderWorkerLog).nospace()
<< "[card: " << cardName << " set: " << setName << "]: Trying to load picture"; << "[card: " << cardName << " set: " << setName << "]: Trying to load picture";
if (CardDatabaseManager::getInstance()->isProviderIdForPreferredPrinting( // FIXME: This is a hack so that to keep old Cockatrice behavior
cardName, cardBeingLoaded.getCard()->getPixmapCacheKey())) { // (ignoring provider ID) when the "override all card art with personal
if (cardImageExistsOnDisk(setName, correctedCardName)) { // preference" is set.
continue; //
} // Figure out a proper way to integrate the two systems at some point.
//
// Note: need to go through a member for
// overrideAllCardArtWithPersonalPreference as reading from the
// SettingsCache instance from the PictureLoaderWorker thread could
// cause race conditions.
//
// XXX: Reading from the CardDatabaseManager instance from the
// PictureLoaderWorker thread might not be safe either
bool searchCustomPics = overrideAllCardArtWithPersonalPreference ||
CardDatabaseManager::getInstance()->isProviderIdForPreferredPrinting(
cardName, cardBeingLoaded.getCard()->getPixmapCacheKey());
if (searchCustomPics && cardImageExistsOnDisk(setName, correctedCardName, searchCustomPics)) {
continue;
} }
qCDebug(PictureLoaderWorkerLog).nospace() qCDebug(PictureLoaderWorkerLog).nospace()
@ -100,23 +118,26 @@ void PictureLoaderWorker::processLoadQueue()
} }
} }
bool PictureLoaderWorker::cardImageExistsOnDisk(QString &setName, QString &correctedCardname) bool PictureLoaderWorker::cardImageExistsOnDisk(QString &setName, QString &correctedCardname, bool searchCustomPics)
{ {
QImage image; QImage image;
QImageReader imgReader; QImageReader imgReader;
imgReader.setDecideFormatFromContent(true); imgReader.setDecideFormatFromContent(true);
QList<QString> picsPaths = QList<QString>(); QList<QString> picsPaths = QList<QString>();
QDirIterator it(customPicsPath, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
// Recursively check all subdirectories of the CUSTOM folder if (searchCustomPics) {
while (it.hasNext()) { QDirIterator it(customPicsPath, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
QString thisPath(it.next());
QFileInfo thisFileInfo(thisPath);
if (thisFileInfo.isFile() && // Recursively check all subdirectories of the CUSTOM folder
(thisFileInfo.fileName() == correctedCardname || thisFileInfo.completeBaseName() == correctedCardname || while (it.hasNext()) {
thisFileInfo.baseName() == correctedCardname)) { QString thisPath(it.next());
picsPaths << thisPath; // Card found in the CUSTOM directory, somewhere QFileInfo thisFileInfo(thisPath);
if (thisFileInfo.isFile() &&
(thisFileInfo.fileName() == correctedCardname || thisFileInfo.completeBaseName() == correctedCardname ||
thisFileInfo.baseName() == correctedCardname)) {
picsPaths << thisPath; // Card found in the CUSTOM directory, somewhere
}
} }
} }
@ -194,7 +215,7 @@ void PictureLoaderWorker::picDownloadFailed()
loadQueue.prepend(cardBeingDownloaded); loadQueue.prepend(cardBeingDownloaded);
mutex.unlock(); mutex.unlock();
} else { } else {
qCDebug(PictureLoaderWorkerLog).nospace() qCWarning(PictureLoaderWorkerLog).nospace()
<< "[card: " << cardBeingDownloaded.getCard()->getCorrectedName() << "[card: " << cardBeingDownloaded.getCard()->getCorrectedName()
<< " set: " << cardBeingDownloaded.getSetName() << "]: Picture NOT found, " << " set: " << cardBeingDownloaded.getSetName() << "]: Picture NOT found, "
<< (picDownload ? "download failed" : "downloads disabled") << (picDownload ? "download failed" : "downloads disabled")
@ -225,6 +246,23 @@ QNetworkReply *PictureLoaderWorker::makeRequest(const QUrl &url)
QNetworkRequest req(url); QNetworkRequest req(url);
// QNetworkDiskCache leaks file descriptors when downloading compressed
// files, see https://bugreports.qt.io/browse/QTBUG-135641
//
// We can set the Accept-Encoding header manually to disable Qt's automatic
// response decompression, but then we would have to deal with decompression
// ourselves.
//
// Since we are dowloading images that are usually stored in a
// compressed format (e.g. jpeg or webp), it's not clear compression at the
// HTTP level helps; in fact, images are typically returned without
// compression. Redirects, on the other hand, are compressed and cause file
// descriptor leaks -- but since redirects have no payload, we don't really
// care either.
//
// In the end, just do the simple thing and disable HTTP compression.
req.setRawHeader("accept-encoding", "identity");
if (!picDownload) { if (!picDownload) {
req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysCache); req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysCache);
} }
@ -405,7 +443,7 @@ void PictureLoaderWorker::picDownloadFinished(QNetworkReply *reply)
} }
if (logSuccessMessage) { if (logSuccessMessage) {
qCDebug(PictureLoaderWorkerLog).nospace() qCInfo(PictureLoaderWorkerLog).nospace()
<< "[card: " << cardBeingDownloaded.getCard()->getName() << " set: " << cardBeingDownloaded.getSetName() << "[card: " << cardBeingDownloaded.getCard()->getName() << " set: " << cardBeingDownloaded.getSetName()
<< "]: Image successfully " << (isFromCache ? "loaded from cached" : "downloaded from") << " url " << "]: Image successfully " << (isFromCache ? "loaded from cached" : "downloaded from") << " url "
<< reply->url().toDisplayString(); << reply->url().toDisplayString();
@ -451,7 +489,12 @@ void PictureLoaderWorker::picsPathChanged()
customPicsPath = SettingsCache::instance().getCustomPicsPath(); customPicsPath = SettingsCache::instance().getCustomPicsPath();
} }
void PictureLoaderWorker::setOverrideAllCardArtWithPersonalPreference(bool _overrideAllCardArtWithPersonalPreference)
{
overrideAllCardArtWithPersonalPreference = _overrideAllCardArtWithPersonalPreference;
}
void PictureLoaderWorker::clearNetworkCache() void PictureLoaderWorker::clearNetworkCache()
{ {
networkManager->cache()->clear(); networkManager->cache()->clear();
} }

View file

@ -1,7 +1,7 @@
#ifndef PICTURE_LOADER_WORKER_H #ifndef PICTURE_LOADER_WORKER_H
#define PICTURE_LOADER_WORKER_H #define PICTURE_LOADER_WORKER_H
#include "../../../game/cards/card_database.h" #include "../../../game/cards/card_info.h"
#include "picture_to_load.h" #include "picture_to_load.h"
#include <QLoggingCategory> #include <QLoggingCategory>
@ -42,8 +42,16 @@ private:
PictureToLoad cardBeingLoaded; PictureToLoad cardBeingLoaded;
PictureToLoad cardBeingDownloaded; PictureToLoad cardBeingDownloaded;
bool picDownload, downloadRunning, loadQueueRunning; bool picDownload, downloadRunning, loadQueueRunning;
bool overrideAllCardArtWithPersonalPreference;
void startNextPicDownload(); void startNextPicDownload();
bool cardImageExistsOnDisk(QString &setName, QString &correctedCardName);
/** Emit the `imageLoaded` signal and return `true` if a picture is found on
disk, return `false` otherwise.
If `searchCustomPics` is `true`, the CUSTOM folder is searched for a
matching image first; otherwise, only the set-based folders are used. */
bool cardImageExistsOnDisk(QString &setName, QString &correctedCardName, bool searchCustomPics);
bool imageIsBlackListed(const QByteArray &); bool imageIsBlackListed(const QByteArray &);
QNetworkReply *makeRequest(const QUrl &url); QNetworkReply *makeRequest(const QUrl &url);
void cacheRedirect(const QUrl &originalUrl, const QUrl &redirectUrl); void cacheRedirect(const QUrl &originalUrl, const QUrl &redirectUrl);
@ -58,6 +66,7 @@ private slots:
void picDownloadChanged(); void picDownloadChanged();
void picsPathChanged(); void picsPathChanged();
void setOverrideAllCardArtWithPersonalPreference(bool _overrideAllCardArtWithPersonalPreference);
public slots: public slots:
void processLoadQueue(); void processLoadQueue();

View file

@ -1,7 +1,7 @@
#ifndef PICTURE_TO_LOAD_H #ifndef PICTURE_TO_LOAD_H
#define PICTURE_TO_LOAD_H #define PICTURE_TO_LOAD_H
#include "../../../game/cards/card_database.h" #include "../../../game/cards/card_info.h"
#include <QLoggingCategory> #include <QLoggingCategory>

View file

@ -24,7 +24,7 @@ static const QStringList DEFAULT_RESOURCE_PATHS = {":/resources"};
ThemeManager::ThemeManager(QObject *parent) : QObject(parent) ThemeManager::ThemeManager(QObject *parent) : QObject(parent)
{ {
ensureThemeDirectoryExists(); ensureThemeDirectoryExists();
connect(&SettingsCache::instance(), SIGNAL(themeChanged()), this, SLOT(themeChangedSlot())); connect(&SettingsCache::instance(), &SettingsCache::themeChanged, this, &ThemeManager::themeChangedSlot);
themeChangedSlot(); themeChangedSlot();
} }
@ -32,7 +32,7 @@ void ThemeManager::ensureThemeDirectoryExists()
{ {
if (SettingsCache::instance().getThemeName().isEmpty() || if (SettingsCache::instance().getThemeName().isEmpty() ||
!getAvailableThemes().contains(SettingsCache::instance().getThemeName())) { !getAvailableThemes().contains(SettingsCache::instance().getThemeName())) {
qCDebug(ThemeManagerLog) << "Theme name not set, setting default value"; qCInfo(ThemeManagerLog) << "Theme name not set, setting default value";
SettingsCache::instance().setThemeName(NONE_THEME_NAME); SettingsCache::instance().setThemeName(NONE_THEME_NAME);
} }
} }
@ -105,7 +105,7 @@ QBrush ThemeManager::loadExtraBrush(QString fileName, QBrush &fallbackBrush)
void ThemeManager::themeChangedSlot() void ThemeManager::themeChangedSlot()
{ {
QString themeName = SettingsCache::instance().getThemeName(); QString themeName = SettingsCache::instance().getThemeName();
qCDebug(ThemeManagerLog) << "Theme changed:" << themeName; qCInfo(ThemeManagerLog) << "Theme changed:" << themeName;
QString dirPath = getAvailableThemes().value(themeName); QString dirPath = getAvailableThemes().value(themeName);
QDir dir = dirPath; QDir dir = dirPath;

View file

@ -1,7 +1,7 @@
#ifndef COLOR_IDENTITY_WIDGET_H #ifndef COLOR_IDENTITY_WIDGET_H
#define COLOR_IDENTITY_WIDGET_H #define COLOR_IDENTITY_WIDGET_H
#include "../../../../../game/cards/card_database.h" #include "../../../../../game/cards/card_info.h"
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QWidget> #include <QWidget>

View file

@ -1,7 +1,7 @@
#ifndef MANA_COST_WIDGET_H #ifndef MANA_COST_WIDGET_H
#define MANA_COST_WIDGET_H #define MANA_COST_WIDGET_H
#include "../../../../../game/cards/card_database.h" #include "../../../../../game/cards/card_info.h"
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QWidget> #include <QWidget>

View file

@ -0,0 +1,81 @@
#include "card_group_display_widget.h"
#include "../../../../../deck/deck_list_model.h"
#include "../../../../../game/cards/card_database_manager.h"
#include "../../../../../utility/card_info_comparator.h"
#include "../card_info_picture_with_text_overlay_widget.h"
#include <QResizeEvent>
CardGroupDisplayWidget::CardGroupDisplayWidget(QWidget *parent,
DeckListModel *_deckListModel,
QString _zoneName,
QString _cardGroupCategory,
QString _activeGroupCriteria,
QStringList _activeSortCriteria,
int bannerOpacity,
CardSizeWidget *_cardSizeWidget)
: QWidget(parent), deckListModel(_deckListModel), zoneName(_zoneName), cardGroupCategory(_cardGroupCategory),
activeGroupCriteria(_activeGroupCriteria), activeSortCriteria(_activeSortCriteria),
cardSizeWidget(_cardSizeWidget)
{
layout = new QVBoxLayout(this);
setLayout(layout);
setMinimumSize(QSize(0, 0));
banner = new BannerWidget(this, cardGroupCategory, Qt::Orientation::Vertical, bannerOpacity);
layout->addWidget(banner);
updateCardDisplays();
}
void CardGroupDisplayWidget::updateCardDisplays()
{
}
QList<CardInfoPtr> CardGroupDisplayWidget::getCardsMatchingGroup(QList<CardInfoPtr> cardsToSort)
{
cardsToSort = sortCardList(cardsToSort, activeSortCriteria, Qt::SortOrder::AscendingOrder);
QList<CardInfoPtr> activeList;
for (const CardInfoPtr &info : cardsToSort) {
if (info && info->getProperty(activeGroupCriteria) == cardGroupCategory) {
activeList.append(info);
}
}
return activeList;
}
QList<CardInfoPtr> CardGroupDisplayWidget::sortCardList(QList<CardInfoPtr> cardsToSort,
const QStringList properties,
Qt::SortOrder order = Qt::AscendingOrder)
{
CardInfoComparator comparator(properties, order);
std::sort(cardsToSort.begin(), cardsToSort.end(), comparator);
return cardsToSort;
}
void CardGroupDisplayWidget::onActiveSortCriteriaChanged(QStringList _activeSortCriteria)
{
if (activeSortCriteria != _activeSortCriteria) {
activeSortCriteria = _activeSortCriteria;
updateCardDisplays(); // Refresh display with new sorting
}
}
void CardGroupDisplayWidget::onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card)
{
emit cardClicked(event, card);
}
void CardGroupDisplayWidget::onHover(CardInfoPtr card)
{
emit cardHovered(card);
}
void CardGroupDisplayWidget::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
}

View file

@ -0,0 +1,53 @@
#ifndef CARD_GROUP_DISPLAY_WIDGET_H
#define CARD_GROUP_DISPLAY_WIDGET_H
#include "../../../../../deck/deck_list_model.h"
#include "../../../../../game/cards/card_info.h"
#include "../../general/display/banner_widget.h"
#include "../card_info_picture_with_text_overlay_widget.h"
#include "../card_size_widget.h"
#include <QLabel>
#include <QVBoxLayout>
#include <QWidget>
class CardGroupDisplayWidget : public QWidget
{
Q_OBJECT
public:
CardGroupDisplayWidget(QWidget *parent,
DeckListModel *deckListModel,
QString zoneName,
QString cardGroupCategory,
QString activeGroupCriteria,
QStringList activeSortCriteria,
int bannerOpacity,
CardSizeWidget *cardSizeWidget);
QList<CardInfoPtr> getCardsMatchingGroup(QList<CardInfoPtr> cardsToSort);
void resizeEvent(QResizeEvent *event) override;
DeckListModel *deckListModel;
QString zoneName;
QString cardGroupCategory;
QString activeGroupCriteria;
QStringList activeSortCriteria;
CardSizeWidget *cardSizeWidget;
public slots:
QList<CardInfoPtr> sortCardList(QList<CardInfoPtr> cardsToSort, QStringList properties, Qt::SortOrder order);
void onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card);
void onHover(CardInfoPtr card);
virtual void updateCardDisplays();
void onActiveSortCriteriaChanged(QStringList activeSortCriteria);
signals:
void cardClicked(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card);
void cardHovered(CardInfoPtr card);
protected:
QVBoxLayout *layout;
BannerWidget *banner;
};
#endif // CARD_GROUP_DISPLAY_WIDGET_H

View file

@ -0,0 +1,107 @@
#include "flat_card_group_display_widget.h"
#include "../../../../../deck/deck_list_model.h"
#include "../../../../../game/cards/card_database_manager.h"
#include "../../../../../utility/card_info_comparator.h"
#include "../card_info_picture_with_text_overlay_widget.h"
#include <QResizeEvent>
FlatCardGroupDisplayWidget::FlatCardGroupDisplayWidget(QWidget *parent,
DeckListModel *_deckListModel,
QString _zoneName,
QString _cardGroupCategory,
QString _activeGroupCriteria,
QStringList _activeSortCriteria,
int bannerOpacity,
CardSizeWidget *_cardSizeWidget)
: CardGroupDisplayWidget(parent,
_deckListModel,
_zoneName,
_cardGroupCategory,
_activeGroupCriteria,
_activeSortCriteria,
bannerOpacity,
_cardSizeWidget)
{
flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAlwaysOff);
banner->setBuddy(flowWidget);
layout->addWidget(flowWidget);
FlatCardGroupDisplayWidget::updateCardDisplays();
connect(deckListModel, &DeckListModel::dataChanged, this, &FlatCardGroupDisplayWidget::updateCardDisplays);
}
void FlatCardGroupDisplayWidget::updateCardDisplays()
{
// Retrieve and sort cards
QList<CardInfoPtr> cardsInZone = getCardsMatchingGroup(deckListModel->getCardsAsCardInfoPtrsForZone(zoneName));
// Show or hide widget
bool shouldBeVisible = !cardsInZone.isEmpty();
if (shouldBeVisible != isVisible()) {
setVisible(shouldBeVisible);
}
// Retrieve existing widgets
QList<CardInfoPictureWithTextOverlayWidget *> existingWidgets =
flowWidget->findChildren<CardInfoPictureWithTextOverlayWidget *>();
QHash<QString, QList<CardInfoPictureWithTextOverlayWidget *>> widgetMap;
for (CardInfoPictureWithTextOverlayWidget *widget : existingWidgets) {
widgetMap[widget->getInfo()->getName()].append(widget);
}
QList<CardInfoPictureWithTextOverlayWidget *> sortedWidgets;
QSet<CardInfoPictureWithTextOverlayWidget *> usedWidgets;
// Ensure widgets are ordered to match the sorted cards
for (const CardInfoPtr &card : cardsInZone) {
QString name = card->getName();
CardInfoPictureWithTextOverlayWidget *widget = nullptr;
if (!widgetMap[name].isEmpty()) {
// Reuse an existing widget
widget = widgetMap[name].takeFirst();
} else {
// Create a new widget if needed
widget = new CardInfoPictureWithTextOverlayWidget(flowWidget, true);
widget->setScaleFactor(cardSizeWidget->getSlider()->value());
widget->setCard(card);
connect(widget, &CardInfoPictureWithTextOverlayWidget::imageClicked, this,
&FlatCardGroupDisplayWidget::onClick);
connect(widget, &CardInfoPictureWithTextOverlayWidget::hoveredOnCard, this,
&FlatCardGroupDisplayWidget::onHover);
connect(cardSizeWidget->getSlider(), &QSlider::valueChanged, widget,
&CardInfoPictureWidget::setScaleFactor);
flowWidget->addWidget(widget);
}
// Store in sorted order
sortedWidgets.append(widget);
usedWidgets.insert(widget);
}
// Remove extra widgets
for (CardInfoPictureWithTextOverlayWidget *widget : existingWidgets) {
if (!usedWidgets.contains(widget)) {
flowWidget->layout()->removeWidget(widget);
widget->deleteLater();
}
}
// **Reorder widgets in place**
for (int i = 0; i < sortedWidgets.size(); ++i) {
sortedWidgets[i]->setParent(nullptr); // Temporarily detach
}
for (int i = 0; i < sortedWidgets.size(); ++i) {
flowWidget->addWidget(sortedWidgets[i]); // Reattach in correct order
}
}
void FlatCardGroupDisplayWidget::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
}

View file

@ -0,0 +1,30 @@
#ifndef FLAT_CARD_GROUP_DISPLAY_WIDGET_H
#define FLAT_CARD_GROUP_DISPLAY_WIDGET_H
#include "../../general/layout_containers/flow_widget.h"
#include "card_group_display_widget.h"
class FlatCardGroupDisplayWidget : public CardGroupDisplayWidget
{
Q_OBJECT
public:
FlatCardGroupDisplayWidget(QWidget *parent,
DeckListModel *deckListModel,
QString zoneName,
QString cardGroupCategory,
QString activeGroupCriteria,
QStringList activeSortCriteria,
int bannerOpacity,
CardSizeWidget *cardSizeWidget);
void resizeEvent(QResizeEvent *event) override;
public slots:
void updateCardDisplays() override;
private:
FlowWidget *flowWidget;
};
#endif // FLAT_CARD_GROUP_DISPLAY_WIDGET_H

View file

@ -0,0 +1,122 @@
#include "overlapped_card_group_display_widget.h"
#include "../../../../../deck/deck_list_model.h"
#include "../../../../../game/cards/card_database_manager.h"
#include "../../../../../utility/card_info_comparator.h"
#include "../card_info_picture_with_text_overlay_widget.h"
#include <QResizeEvent>
OverlappedCardGroupDisplayWidget::OverlappedCardGroupDisplayWidget(QWidget *parent,
DeckListModel *_deckListModel,
QString _zoneName,
QString _cardGroupCategory,
QString _activeGroupCriteria,
QStringList _activeSortCriteria,
int bannerOpacity,
CardSizeWidget *_cardSizeWidget)
: CardGroupDisplayWidget(parent,
_deckListModel,
_zoneName,
_cardGroupCategory,
_activeGroupCriteria,
_activeSortCriteria,
bannerOpacity,
_cardSizeWidget)
{
overlapWidget = new OverlapWidget(this, 80, 1, 1, Qt::Vertical, true);
banner->setBuddy(overlapWidget);
layout->addWidget(overlapWidget);
OverlappedCardGroupDisplayWidget::updateCardDisplays();
connect(deckListModel, &DeckListModel::dataChanged, this, &OverlappedCardGroupDisplayWidget::updateCardDisplays);
connect(cardSizeWidget->getSlider(), &QSlider::valueChanged, this,
[this]() { overlapWidget->adjustMaxColumnsAndRows(); });
}
void OverlappedCardGroupDisplayWidget::updateCardDisplays()
{
overlapWidget->setUpdatesEnabled(false);
// Retrieve and sort cards
QList<CardInfoPtr> cardsInZone = getCardsMatchingGroup(deckListModel->getCardsAsCardInfoPtrsForZone(zoneName));
// Show or hide widget
bool shouldBeVisible = !cardsInZone.isEmpty();
if (shouldBeVisible != isVisible()) {
setVisible(shouldBeVisible);
}
// Retrieve existing widgets
QList<CardInfoPictureWithTextOverlayWidget *> existingWidgets =
overlapWidget->findChildren<CardInfoPictureWithTextOverlayWidget *>();
QHash<QString, QList<CardInfoPictureWithTextOverlayWidget *>> widgetMap;
for (CardInfoPictureWithTextOverlayWidget *widget : existingWidgets) {
widgetMap[widget->getInfo()->getName()].append(widget);
}
QList<CardInfoPictureWithTextOverlayWidget *> sortedWidgets;
QSet<CardInfoPictureWithTextOverlayWidget *> usedWidgets;
// Ensure widgets are ordered to match the sorted cards
for (const CardInfoPtr &card : cardsInZone) {
QString name = card->getName();
CardInfoPictureWithTextOverlayWidget *widget = nullptr;
if (!widgetMap[name].isEmpty()) {
// Reuse an existing widget
widget = widgetMap[name].takeFirst();
} else {
// Create a new widget if needed
widget = new CardInfoPictureWithTextOverlayWidget(overlapWidget, true);
widget->setScaleFactor(cardSizeWidget->getSlider()->value());
widget->setCard(card);
connect(widget, &CardInfoPictureWithTextOverlayWidget::imageClicked, this,
&OverlappedCardGroupDisplayWidget::onClick);
connect(widget, &CardInfoPictureWithTextOverlayWidget::hoveredOnCard, this,
&OverlappedCardGroupDisplayWidget::onHover);
connect(cardSizeWidget->getSlider(), &QSlider::valueChanged, widget,
&CardInfoPictureWidget::setScaleFactor);
overlapWidget->addWidget(widget);
}
// Store in sorted order
sortedWidgets.append(widget);
usedWidgets.insert(widget);
}
// Remove extra widgets
for (CardInfoPictureWithTextOverlayWidget *widget : existingWidgets) {
if (!usedWidgets.contains(widget)) {
overlapWidget->layout()->removeWidget(widget);
delete widget;
}
}
// **Reorder widgets in place**
for (int i = 0; i < sortedWidgets.size(); ++i) {
sortedWidgets[i]->setParent(nullptr); // Temporarily detach
}
for (int i = 0; i < sortedWidgets.size(); ++i) {
overlapWidget->addWidget(sortedWidgets[i]); // Reattach in correct order
}
// Ensure proper layering
for (CardInfoPictureWithTextOverlayWidget *widget : sortedWidgets) {
widget->raise();
}
overlapWidget->adjustMaxColumnsAndRows();
overlapWidget->setUpdatesEnabled(true);
overlapWidget->update();
}
void OverlappedCardGroupDisplayWidget::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
overlapWidget->resize(event->size());
overlapWidget->adjustMaxColumnsAndRows();
}

View file

@ -0,0 +1,30 @@
#ifndef OVERLAPPED_CARD_GROUP_DISPLAY_WIDGET_H
#define OVERLAPPED_CARD_GROUP_DISPLAY_WIDGET_H
#include "../../general/layout_containers/overlap_widget.h"
#include "card_group_display_widget.h"
class OverlappedCardGroupDisplayWidget : public CardGroupDisplayWidget
{
Q_OBJECT
public:
OverlappedCardGroupDisplayWidget(QWidget *parent,
DeckListModel *deckListModel,
QString zoneName,
QString cardGroupCategory,
QString activeGroupCriteria,
QStringList activeSortCriteria,
int bannerOpacity,
CardSizeWidget *cardSizeWidget);
void resizeEvent(QResizeEvent *event) override;
public slots:
void updateCardDisplays() override;
private:
OverlapWidget *overlapWidget;
};
#endif // OVERLAPPED_CARD_GROUP_DISPLAY_WIDGET_H

View file

@ -22,7 +22,7 @@ CardInfoDisplayWidget::CardInfoDisplayWidget(const QString &cardName,
pic->setObjectName("pic"); pic->setObjectName("pic");
text = new CardInfoTextWidget(); text = new CardInfoTextWidget();
text->setObjectName("text"); text->setObjectName("text");
connect(text, SIGNAL(linkActivated(const QString &)), this, SLOT(setCard(const QString &))); connect(text, &CardInfoTextWidget::linkActivated, this, [this](const QString &card) { setCard(card); });
auto *layout = new QVBoxLayout(); auto *layout = new QVBoxLayout();
layout->setObjectName("layout"); layout->setObjectName("layout");
@ -52,7 +52,7 @@ void CardInfoDisplayWidget::setCard(CardInfoPtr card)
disconnect(info.data(), nullptr, this, nullptr); disconnect(info.data(), nullptr, this, nullptr);
info = std::move(card); info = std::move(card);
if (info) if (info)
connect(info.data(), SIGNAL(destroyed()), this, SLOT(clear())); connect(info.data(), &QObject::destroyed, this, &CardInfoDisplayWidget::clear);
text->setCard(info); text->setCard(info);
pic->setCard(info); pic->setCard(info);

View file

@ -1,7 +1,7 @@
#ifndef CARDINFOWIDGET_H #ifndef CARDINFOWIDGET_H
#define CARDINFOWIDGET_H #define CARDINFOWIDGET_H
#include "../../../../game/cards/card_database.h" #include "../../../../game/cards/card_info.h"
#include <QComboBox> #include <QComboBox>
#include <QFrame> #include <QFrame>

View file

@ -21,7 +21,7 @@ CardInfoFrameWidget::CardInfoFrameWidget(const QString &cardName, QWidget *paren
text = new CardInfoTextWidget(); text = new CardInfoTextWidget();
text->setObjectName("text"); text->setObjectName("text");
connect(text, SIGNAL(linkActivated(const QString &)), this, SLOT(setCard(const QString &))); connect(text, &CardInfoTextWidget::linkActivated, this, qOverload<const QString &>(&CardInfoFrameWidget::setCard));
tab1 = new QWidget(this); tab1 = new QWidget(this);
tab2 = new QWidget(this); tab2 = new QWidget(this);
@ -34,7 +34,7 @@ CardInfoFrameWidget::CardInfoFrameWidget(const QString &cardName, QWidget *paren
insertTab(ImageOnlyView, tab1, QString()); insertTab(ImageOnlyView, tab1, QString());
insertTab(TextOnlyView, tab2, QString()); insertTab(TextOnlyView, tab2, QString());
insertTab(ImageAndTextView, tab3, QString()); insertTab(ImageAndTextView, tab3, QString());
connect(this, SIGNAL(currentChanged(int)), this, SLOT(setViewMode(int))); connect(this, &CardInfoFrameWidget::currentChanged, this, &CardInfoFrameWidget::setViewMode);
tab1Layout = new QVBoxLayout(); tab1Layout = new QVBoxLayout();
tab1Layout->setObjectName("tab1Layout"); tab1Layout->setObjectName("tab1Layout");
@ -61,6 +61,7 @@ CardInfoFrameWidget::CardInfoFrameWidget(const QString &cardName, QWidget *paren
setViewMode(SettingsCache::instance().getCardInfoViewMode()); setViewMode(SettingsCache::instance().getCardInfoViewMode());
// TODO: Change this to be by UUID
setCard(CardDatabaseManager::getInstance()->getCard(cardName)); setCard(CardDatabaseManager::getInstance()->getCard(cardName));
} }
@ -154,7 +155,7 @@ void CardInfoFrameWidget::setCard(CardInfoPtr card)
info = std::move(card); info = std::move(card);
if (info) { if (info) {
connect(info.data(), SIGNAL(destroyed()), this, SLOT(clearCard())); connect(info.data(), &QObject::destroyed, this, &CardInfoFrameWidget::clearCard);
} }
setViewTransformationButtonVisibility(hasTransformation(info)); setViewTransformationButtonVisibility(hasTransformation(info));

View file

@ -1,7 +1,7 @@
#ifndef CARDFRAME_H #ifndef CARDFRAME_H
#define CARDFRAME_H #define CARDFRAME_H
#include "../../../../game/cards/card_database.h" #include "../../../../game/cards/card_info.h"
#include <QPushButton> #include <QPushButton>
#include <QTabWidget> #include <QTabWidget>

View file

@ -1,7 +1,7 @@
#ifndef CARD_PICTURE_ENLARGED_WIDGET_H #ifndef CARD_PICTURE_ENLARGED_WIDGET_H
#define CARD_PICTURE_ENLARGED_WIDGET_H #define CARD_PICTURE_ENLARGED_WIDGET_H
#include "../../../../game/cards/card_database.h" #include "../../../../game/cards/card_info.h"
#include <QPixmap> #include <QPixmap>
#include <QWidget> #include <QWidget>

Some files were not shown because too many files have changed in this diff Show more