mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-07-06 05:23:56 -07:00
Revert UI.
Took 25 minutes Took 5 seconds
This commit is contained in:
parent
fe12f4cbb9
commit
135beab531
174 changed files with 14 additions and 15702 deletions
|
|
@ -51,7 +51,6 @@ set(cockatrice_SOURCES
|
||||||
src/interface/widgets/dialogs/dlg_view_log.cpp
|
src/interface/widgets/dialogs/dlg_view_log.cpp
|
||||||
src/interface/widgets/dialogs/override_printing_warning.cpp
|
src/interface/widgets/dialogs/override_printing_warning.cpp
|
||||||
src/interface/widgets/dialogs/tip_of_the_day.cpp
|
src/interface/widgets/dialogs/tip_of_the_day.cpp
|
||||||
src/filters/deck_filter_string.cpp
|
|
||||||
src/filters/filter_builder.cpp
|
src/filters/filter_builder.cpp
|
||||||
src/filters/filter_tree_model.cpp
|
src/filters/filter_tree_model.cpp
|
||||||
src/filters/syntax_help.cpp
|
src/filters/syntax_help.cpp
|
||||||
|
|
@ -145,33 +144,6 @@ set(cockatrice_SOURCES
|
||||||
src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.cpp
|
src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.cpp
|
||||||
src/interface/widgets/cards/card_info_text_widget.cpp
|
src/interface/widgets/cards/card_info_text_widget.cpp
|
||||||
src/interface/widgets/cards/card_size_widget.cpp
|
src/interface/widgets/cards/card_size_widget.cpp
|
||||||
src/interface/widgets/cards/deck_card_zone_display_widget.cpp
|
|
||||||
src/interface/widgets/cards/deck_preview_card_picture_widget.cpp
|
|
||||||
src/interface/widgets/deck_analytics/abstract_analytics_panel_widget.cpp
|
|
||||||
src/interface/widgets/deck_analytics/add_analytics_panel_dialog.cpp
|
|
||||||
src/interface/widgets/deck_analytics/analytics_panel_widget_factory.cpp
|
|
||||||
src/interface/widgets/deck_analytics/analytics_panel_widget_registrar.cpp
|
|
||||||
src/interface/widgets/deck_analytics/deck_analytics_widget.cpp
|
|
||||||
src/interface/widgets/deck_analytics/deck_list_statistics_analyzer.cpp
|
|
||||||
src/interface/widgets/deck_analytics/resizable_panel.cpp
|
|
||||||
src/interface/widgets/deck_analytics/analyzer_modules/draw_probability/draw_probability_config.cpp
|
|
||||||
src/interface/widgets/deck_analytics/analyzer_modules/draw_probability/draw_probability_config_dialog.cpp
|
|
||||||
src/interface/widgets/deck_analytics/analyzer_modules/draw_probability/draw_probability_widget.cpp
|
|
||||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_base/mana_base_config.cpp
|
|
||||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_base/mana_base_config_dialog.cpp
|
|
||||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_base/mana_base_widget.cpp
|
|
||||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_config.cpp
|
|
||||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_config_dialog.cpp
|
|
||||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_widget.cpp
|
|
||||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_devotion/mana_devotion_config.cpp
|
|
||||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_devotion/mana_devotion_config_dialog.cpp
|
|
||||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_devotion/mana_devotion_widget.cpp
|
|
||||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_distribution/mana_distribution_config.cpp
|
|
||||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_distribution/mana_distribution_config_dialog.cpp
|
|
||||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_distribution/mana_distribution_widget.cpp
|
|
||||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_distribution/mana_distribution_single_display_widget.cpp
|
|
||||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_total_widget.cpp
|
|
||||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_category_widget.cpp
|
|
||||||
src/interface/widgets/deck_editor/deck_list_history_manager_widget.cpp
|
src/interface/widgets/deck_editor/deck_list_history_manager_widget.cpp
|
||||||
src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.cpp
|
src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.cpp
|
||||||
src/interface/widgets/deck_editor/deck_editor_card_info_dock_widget.cpp
|
src/interface/widgets/deck_editor/deck_editor_card_info_dock_widget.cpp
|
||||||
|
|
@ -182,7 +154,6 @@ set(cockatrice_SOURCES
|
||||||
src/interface/widgets/deck_editor/deck_list_style_proxy.cpp
|
src/interface/widgets/deck_editor/deck_list_style_proxy.cpp
|
||||||
src/interface/widgets/deck_editor/deck_state_manager.cpp
|
src/interface/widgets/deck_editor/deck_state_manager.cpp
|
||||||
src/interface/widgets/deck_editor/printing_disabled_info_widget.cpp
|
src/interface/widgets/deck_editor/printing_disabled_info_widget.cpp
|
||||||
src/interface/widgets/general/background_sources.cpp
|
|
||||||
src/interface/widgets/general/display/background_plate_widget.cpp
|
src/interface/widgets/general/display/background_plate_widget.cpp
|
||||||
src/interface/widgets/general/display/banner_widget.cpp
|
src/interface/widgets/general/display/banner_widget.cpp
|
||||||
src/interface/widgets/general/display/dynamic_font_size_label.cpp
|
src/interface/widgets/general/display/dynamic_font_size_label.cpp
|
||||||
|
|
@ -196,8 +167,6 @@ set(cockatrice_SOURCES
|
||||||
src/interface/widgets/general/display/charts/bars/bar_chart_background_widget.cpp
|
src/interface/widgets/general/display/charts/bars/bar_chart_background_widget.cpp
|
||||||
src/interface/widgets/general/display/charts/bars/segmented_bar_widget.cpp
|
src/interface/widgets/general/display/charts/bars/segmented_bar_widget.cpp
|
||||||
src/interface/widgets/general/display/charts/pies/color_pie.cpp
|
src/interface/widgets/general/display/charts/pies/color_pie.cpp
|
||||||
src/interface/widgets/general/home_styled_button.cpp
|
|
||||||
src/interface/widgets/general/home_widget.cpp
|
|
||||||
src/interface/widgets/general/layout_containers/flow_widget.cpp
|
src/interface/widgets/general/layout_containers/flow_widget.cpp
|
||||||
src/interface/widgets/general/layout_containers/overlap_control_widget.cpp
|
src/interface/widgets/general/layout_containers/overlap_control_widget.cpp
|
||||||
src/interface/widgets/general/layout_containers/overlap_widget.cpp
|
src/interface/widgets/general/layout_containers/overlap_widget.cpp
|
||||||
|
|
@ -234,99 +203,23 @@ set(cockatrice_SOURCES
|
||||||
src/interface/widgets/utility/sequence_edit.cpp
|
src/interface/widgets/utility/sequence_edit.cpp
|
||||||
src/interface/widgets/utility/visibility_change_listener.cpp
|
src/interface/widgets/utility/visibility_change_listener.cpp
|
||||||
src/interface/widgets/utility/visibility_change_listener.h
|
src/interface/widgets/utility/visibility_change_listener.h
|
||||||
src/interface/widgets/visual_database_display/visual_database_display_color_filter_widget.cpp
|
|
||||||
src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.cpp
|
|
||||||
src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.cpp
|
|
||||||
src/interface/widgets/visual_database_display/visual_database_display_format_legality_filter_widget.cpp
|
|
||||||
src/interface/widgets/visual_database_display/visual_database_display_main_type_filter_widget.cpp
|
|
||||||
src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.cpp
|
|
||||||
src/interface/widgets/visual_database_display/visual_database_display_set_filter_widget.cpp
|
|
||||||
src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.cpp
|
|
||||||
src/interface/widgets/visual_database_display/visual_database_display_widget.cpp
|
|
||||||
src/interface/widgets/visual_database_display/visual_database_filter_display_widget.cpp
|
|
||||||
src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.cpp
|
|
||||||
src/interface/widgets/visual_deck_editor/visual_deck_editor_placeholder_widget.cpp
|
|
||||||
src/interface/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp
|
|
||||||
src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp
|
|
||||||
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.cpp
|
|
||||||
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.cpp
|
|
||||||
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.cpp
|
|
||||||
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_dialog.cpp
|
|
||||||
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.cpp
|
|
||||||
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_item_widget.cpp
|
|
||||||
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp
|
|
||||||
src/interface/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.cpp
|
|
||||||
src/interface/widgets/visual_deck_storage/visual_deck_storage_quick_settings_widget.cpp
|
|
||||||
src/interface/widgets/visual_deck_storage/visual_deck_storage_search_widget.cpp
|
|
||||||
src/interface/widgets/visual_deck_storage/visual_deck_storage_sort_widget.cpp
|
|
||||||
src/interface/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.cpp
|
|
||||||
src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.cpp
|
|
||||||
src/interface/window_main.cpp
|
src/interface/window_main.cpp
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
src/interface/widgets/tabs/abstract_tab_deck_editor.cpp
|
src/interface/widgets/tabs/abstract_tab_deck_editor.cpp
|
||||||
src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp
|
|
||||||
src/interface/widgets/tabs/api/archidekt/api_response/archidekt_deck_listing_api_response.cpp
|
|
||||||
src/interface/widgets/tabs/api/archidekt/api_response/archidekt_formats.h
|
|
||||||
src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.cpp
|
|
||||||
src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card_entry.cpp
|
|
||||||
src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_edition.cpp
|
|
||||||
src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.cpp
|
|
||||||
src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck_category.cpp
|
|
||||||
src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_listing_container.cpp
|
|
||||||
src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_owner.cpp
|
|
||||||
src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_display_widget.cpp
|
|
||||||
src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.cpp
|
|
||||||
src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_listings_display_widget.cpp
|
|
||||||
src/interface/widgets/tabs/api/archidekt/display/archidekt_deck_preview_image_display_widget.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/api_response/archidekt_links/edhrec_api_response_archidekt_links.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_average_deck_api_response.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_deck_api_response.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/api_response/card_prices/edhrec_api_response_card_prices.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_container.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_details.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_list.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_commander_api_response_commander_details.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/api_response/commander/edhrec_commander_api_response.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/api_response/commander/edhrec_commander_api_response_average_deck_statistics.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/api_response/top_cards/edhrec_top_cards_api_response.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/api_response/top_commanders/edhrec_top_commanders_api_response.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/api_response/top_tags/edhrec_top_tags_api_response.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/display/card_prices/edhrec_api_response_card_prices_display_widget.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_inclusion_display_widget.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_list_display_widget.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_synergy_display_widget.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_api_response_commander_details_display_widget.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_display_widget.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_navigation_widget.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/display/top_cards/edhrec_top_cards_api_response_display_widget.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/display/top_commander/edhrec_top_commanders_api_response_display_widget.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/display/top_tags/edhrec_top_tags_api_response_display_widget.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/tab_edhrec.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.cpp
|
|
||||||
src/interface/widgets/tabs/tab.cpp
|
src/interface/widgets/tabs/tab.cpp
|
||||||
src/interface/widgets/tabs/tab_account.cpp
|
src/interface/widgets/tabs/tab_account.cpp
|
||||||
src/interface/widgets/tabs/tab_admin.cpp
|
src/interface/widgets/tabs/tab_admin.cpp
|
||||||
src/interface/widgets/tabs/tab_deck_editor.cpp
|
src/interface/widgets/tabs/tab_deck_editor.cpp
|
||||||
src/interface/widgets/tabs/tab_deck_storage.cpp
|
src/interface/widgets/tabs/tab_deck_storage.cpp
|
||||||
src/interface/widgets/tabs/tab_game.cpp
|
src/interface/widgets/tabs/tab_game.cpp
|
||||||
src/interface/widgets/tabs/tab_home.cpp
|
|
||||||
src/interface/widgets/tabs/tab_logs.cpp
|
src/interface/widgets/tabs/tab_logs.cpp
|
||||||
src/interface/widgets/tabs/tab_message.cpp
|
src/interface/widgets/tabs/tab_message.cpp
|
||||||
src/interface/widgets/tabs/tab_replays.cpp
|
src/interface/widgets/tabs/tab_replays.cpp
|
||||||
src/interface/widgets/tabs/tab_room.cpp
|
src/interface/widgets/tabs/tab_room.cpp
|
||||||
src/interface/widgets/tabs/tab_server.cpp
|
src/interface/widgets/tabs/tab_server.cpp
|
||||||
src/interface/widgets/tabs/tab_supervisor.cpp
|
src/interface/widgets/tabs/tab_supervisor.cpp
|
||||||
src/interface/widgets/tabs/tab_visual_database_display.cpp
|
|
||||||
src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp
|
|
||||||
src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.cpp
|
|
||||||
src/interface/widgets/tabs/visual_deck_storage/tab_deck_storage_visual.cpp
|
|
||||||
src/interface/key_signals.cpp
|
src/interface/key_signals.cpp
|
||||||
src/interface/logger.cpp
|
src/interface/logger.cpp
|
||||||
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_bracket_navigation_widget.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_bracket_navigation_widget.h
|
|
||||||
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_budget_navigation_widget.cpp
|
|
||||||
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_budget_navigation_widget.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(sounds)
|
add_subdirectory(sounds)
|
||||||
|
|
|
||||||
|
|
@ -1,213 +0,0 @@
|
||||||
#include "deck_filter_string.h"
|
|
||||||
|
|
||||||
#include <QFileInfo>
|
|
||||||
#include <libcockatrice/card/database/card_database_manager.h>
|
|
||||||
#include <libcockatrice/filters/filter_string.h>
|
|
||||||
#include <libcockatrice/utility/peglib.h>
|
|
||||||
|
|
||||||
static peg::parser search(R"(
|
|
||||||
Start <- QueryPartList
|
|
||||||
~ws <- [ ]+
|
|
||||||
QueryPartList <- ComplexQueryPart ( ws ("AND" ws)? ComplexQueryPart)* ws*
|
|
||||||
|
|
||||||
ComplexQueryPart <- SomewhatComplexQueryPart ws "OR" ws ComplexQueryPart / SomewhatComplexQueryPart
|
|
||||||
SomewhatComplexQueryPart <- [(] QueryPartList [)] / QueryPart
|
|
||||||
|
|
||||||
QueryPart <- NotQuery / DeckContentQuery / DeckNameQuery / FileNameQuery / PathQuery / FormatQuery / CommentQuery / GenericQuery
|
|
||||||
|
|
||||||
NotQuery <- ('NOT' ws/'-') SomewhatComplexQueryPart
|
|
||||||
|
|
||||||
DeckContentQuery <- CardSearch NumericExpression?
|
|
||||||
CardSearch <- '[[' CardFilterString ']]'
|
|
||||||
CardFilterString <- (!']]'.)*
|
|
||||||
|
|
||||||
DeckNameQuery <- ([Dd] 'eck')? [Nn] 'ame'? [:] String
|
|
||||||
FileNameQuery <- [Ff] ([Nn] / 'ile' ([Nn] 'ame')?) [:] String
|
|
||||||
PathQuery <- [Pp] 'ath'? [:] String
|
|
||||||
FormatQuery <- [Ff] 'ormat'? [:] String
|
|
||||||
CommentQuery <- [Cc] ('omment' 's'?)? [:] String
|
|
||||||
|
|
||||||
GenericQuery <- String
|
|
||||||
|
|
||||||
NonDoubleQuoteUnlessEscaped <- '\\\"'. / !["].
|
|
||||||
NonSingleQuoteUnlessEscaped <- "\\\'". / !['].
|
|
||||||
UnescapedStringListPart <- !['":<>()=! ].
|
|
||||||
SingleApostropheString <- (UnescapedStringListPart+ ws*)* ['] (UnescapedStringListPart+ ws*)*
|
|
||||||
|
|
||||||
String <- SingleApostropheString / UnescapedStringListPart+ / ["] <NonDoubleQuoteUnlessEscaped*> ["] / ['] <NonSingleQuoteUnlessEscaped*> [']
|
|
||||||
|
|
||||||
NumericExpression <- NumericOperator ws? NumericValue
|
|
||||||
NumericOperator <- [=:] / <[><!][=]?>
|
|
||||||
NumericValue <- [0-9]+
|
|
||||||
)");
|
|
||||||
|
|
||||||
static std::once_flag init;
|
|
||||||
|
|
||||||
static void setupParserRules()
|
|
||||||
{
|
|
||||||
// plumbing
|
|
||||||
auto passthru = [](const peg::SemanticValues &sv) -> DeckFilter {
|
|
||||||
return !sv.empty() ? std::any_cast<DeckFilter>(sv[0]) : nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
search["Start"] = passthru;
|
|
||||||
search["QueryPartList"] = [](const peg::SemanticValues &sv) -> DeckFilter {
|
|
||||||
return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &info) {
|
|
||||||
auto matchesFilter = [&deck, &info](const std::any &query) {
|
|
||||||
return std::any_cast<DeckFilter>(query)(deck, info);
|
|
||||||
};
|
|
||||||
return std::all_of(sv.begin(), sv.end(), matchesFilter);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
search["ComplexQueryPart"] = [](const peg::SemanticValues &sv) -> DeckFilter {
|
|
||||||
return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &info) {
|
|
||||||
auto matchesFilter = [&deck, &info](const std::any &query) {
|
|
||||||
return std::any_cast<DeckFilter>(query)(deck, info);
|
|
||||||
};
|
|
||||||
return std::any_of(sv.begin(), sv.end(), matchesFilter);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
search["SomewhatComplexQueryPart"] = passthru;
|
|
||||||
search["QueryPart"] = passthru;
|
|
||||||
search["NotQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter {
|
|
||||||
const auto dependent = std::any_cast<DeckFilter>(sv[0]);
|
|
||||||
return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &info) -> bool {
|
|
||||||
return !dependent(deck, info);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
search["String"] = [](const peg::SemanticValues &sv) -> QString {
|
|
||||||
if (sv.choice() == 0) {
|
|
||||||
return QString::fromStdString(std::string(sv.sv()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return QString::fromStdString(std::string(sv.token(0)));
|
|
||||||
};
|
|
||||||
|
|
||||||
search["NumericExpression"] = [](const peg::SemanticValues &sv) -> NumberMatcher {
|
|
||||||
const auto arg = std::any_cast<int>(sv[1]);
|
|
||||||
const auto op = std::any_cast<QString>(sv[0]);
|
|
||||||
|
|
||||||
if (op == ">")
|
|
||||||
return [=](const int s) { return s > arg; };
|
|
||||||
if (op == ">=")
|
|
||||||
return [=](const int s) { return s >= arg; };
|
|
||||||
if (op == "<")
|
|
||||||
return [=](const int s) { return s < arg; };
|
|
||||||
if (op == "<=")
|
|
||||||
return [=](const int s) { return s <= arg; };
|
|
||||||
if (op == "=")
|
|
||||||
return [=](const int s) { return s == arg; };
|
|
||||||
if (op == ":")
|
|
||||||
return [=](const int s) { return s == arg; };
|
|
||||||
if (op == "!=")
|
|
||||||
return [=](const int s) { return s != arg; };
|
|
||||||
return [](int) { return false; };
|
|
||||||
};
|
|
||||||
|
|
||||||
search["NumericValue"] = [](const peg::SemanticValues &sv) -> int {
|
|
||||||
return QString::fromStdString(std::string(sv.sv())).toInt();
|
|
||||||
};
|
|
||||||
|
|
||||||
search["NumericOperator"] = [](const peg::SemanticValues &sv) -> QString {
|
|
||||||
return QString::fromStdString(std::string(sv.sv()));
|
|
||||||
};
|
|
||||||
|
|
||||||
// actual functionality
|
|
||||||
search["DeckContentQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter {
|
|
||||||
auto cardFilter = FilterString(std::any_cast<QString>(sv[0]));
|
|
||||||
auto numberMatcher = sv.size() > 1 ? std::any_cast<NumberMatcher>(sv[1]) : [](int count) { return count > 0; };
|
|
||||||
|
|
||||||
return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) -> bool {
|
|
||||||
int count = 0;
|
|
||||||
auto cardNodes = deck->deckLoader->getDeck().deckList.getCardNodes();
|
|
||||||
for (auto node : cardNodes) {
|
|
||||||
auto cardInfoPtr = CardDatabaseManager::query()->getCardInfo(node->getName());
|
|
||||||
if (!cardInfoPtr.isNull() && cardFilter.check(cardInfoPtr)) {
|
|
||||||
count += node->getNumber();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return numberMatcher(count);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
search["CardSearch"] = [](const peg::SemanticValues &sv) -> QString { return std::any_cast<QString>(sv[0]); };
|
|
||||||
|
|
||||||
search["CardFilterString"] = [](const peg::SemanticValues &sv) -> QString {
|
|
||||||
return QString::fromStdString(std::string(sv.sv()));
|
|
||||||
};
|
|
||||||
|
|
||||||
search["DeckNameQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter {
|
|
||||||
auto name = std::any_cast<QString>(sv[0]);
|
|
||||||
return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) {
|
|
||||||
return deck->deckLoader->getDeck().deckList.getName().contains(name, Qt::CaseInsensitive);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
search["FileNameQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter {
|
|
||||||
auto name = std::any_cast<QString>(sv[0]);
|
|
||||||
return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) {
|
|
||||||
auto filename = QFileInfo(deck->filePath).fileName();
|
|
||||||
return filename.contains(name, Qt::CaseInsensitive);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
search["PathQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter {
|
|
||||||
auto name = std::any_cast<QString>(sv[0]);
|
|
||||||
return [=](const DeckPreviewWidget *, const ExtraDeckSearchInfo &info) {
|
|
||||||
return info.relativeFilePath.contains(name, Qt::CaseInsensitive);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
search["FormatQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter {
|
|
||||||
auto format = std::any_cast<QString>(sv[0]);
|
|
||||||
return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) {
|
|
||||||
auto gameFormat = deck->deckLoader->getDeck().deckList.getGameFormat();
|
|
||||||
return QString::compare(format, gameFormat, Qt::CaseInsensitive) == 0;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
search["CommentQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter {
|
|
||||||
auto value = std::any_cast<QString>(sv[0]);
|
|
||||||
return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) {
|
|
||||||
auto comments = deck->deckLoader->getDeck().deckList.getComments();
|
|
||||||
return comments.contains(value, Qt::CaseInsensitive);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
search["GenericQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter {
|
|
||||||
auto name = std::any_cast<QString>(sv[0]);
|
|
||||||
return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) {
|
|
||||||
return deck->getDisplayName().contains(name, Qt::CaseInsensitive);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
DeckFilterString::DeckFilterString()
|
|
||||||
{
|
|
||||||
filter = [](const DeckPreviewWidget *, const ExtraDeckSearchInfo &) { return false; };
|
|
||||||
_error = "Not initialized";
|
|
||||||
}
|
|
||||||
|
|
||||||
DeckFilterString::DeckFilterString(const QString &expr)
|
|
||||||
{
|
|
||||||
QByteArray ba = expr.simplified().toUtf8();
|
|
||||||
|
|
||||||
std::call_once(init, setupParserRules);
|
|
||||||
|
|
||||||
_error = QString();
|
|
||||||
|
|
||||||
if (ba.isEmpty()) {
|
|
||||||
filter = [](const DeckPreviewWidget *, const ExtraDeckSearchInfo &) { return true; };
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
search.set_logger([&](size_t /*ln*/, size_t col, const std::string &msg) {
|
|
||||||
_error = QString("Error at position %1: %2").arg(col).arg(QString::fromStdString(msg));
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!search.parse(ba.data(), filter)) {
|
|
||||||
qCInfo(DeckFilterStringLog).nospace() << "DeckFilterString error for " << expr << "; " << qPrintable(_error);
|
|
||||||
filter = [](const DeckPreviewWidget *, const ExtraDeckSearchInfo &) { return false; };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
/**
|
|
||||||
* @file deck_filter_string.h
|
|
||||||
* @ingroup DeckStorageWidgets
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef DECK_FILTER_STRING_H
|
|
||||||
#define DECK_FILTER_STRING_H
|
|
||||||
|
|
||||||
#include "../interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.h"
|
|
||||||
|
|
||||||
#include <QLoggingCategory>
|
|
||||||
#include <QString>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
inline Q_LOGGING_CATEGORY(DeckFilterStringLog, "deck_filter_string");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extra info relevant to filtering that isn't present in the DeckPreviewWidget
|
|
||||||
*/
|
|
||||||
struct ExtraDeckSearchInfo
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The relative filepath starting from the deck folder
|
|
||||||
*/
|
|
||||||
QString relativeFilePath;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::function<bool(const DeckPreviewWidget *, const ExtraDeckSearchInfo &)> DeckFilter;
|
|
||||||
|
|
||||||
class DeckFilterString
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DeckFilterString();
|
|
||||||
explicit DeckFilterString(const QString &expr);
|
|
||||||
bool check(const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &info) const
|
|
||||||
{
|
|
||||||
return filter(deck, info);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool valid() const
|
|
||||||
{
|
|
||||||
return _error.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString error()
|
|
||||||
{
|
|
||||||
return _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString _error;
|
|
||||||
DeckFilter filter;
|
|
||||||
};
|
|
||||||
#endif // DECK_FILTER_STRING_H
|
|
||||||
|
|
@ -46,7 +46,7 @@ void ToggleButton::setState(bool _state)
|
||||||
}
|
}
|
||||||
|
|
||||||
DeckViewContainer::DeckViewContainer(int _playerId, TabGame *parent)
|
DeckViewContainer::DeckViewContainer(int _playerId, TabGame *parent)
|
||||||
: QWidget(nullptr), visualDeckStorageWidget(nullptr), parentGame(parent), playerId(_playerId)
|
: QWidget(nullptr), parentGame(parent), playerId(_playerId)
|
||||||
{
|
{
|
||||||
loadLocalButton = new QPushButton;
|
loadLocalButton = new QPushButton;
|
||||||
loadRemoteButton = new QPushButton;
|
loadRemoteButton = new QPushButton;
|
||||||
|
|
@ -101,23 +101,6 @@ DeckViewContainer::DeckViewContainer(int _playerId, TabGame *parent)
|
||||||
switchToDeckSelectView();
|
switchToDeckSelectView();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the VDS widget and inserts it into the layout. No-ops if the widget already exists
|
|
||||||
*/
|
|
||||||
void DeckViewContainer::tryCreateVisualDeckStorageWidget()
|
|
||||||
{
|
|
||||||
if (visualDeckStorageWidget) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
visualDeckStorageWidget = new VisualDeckStorageWidget(this);
|
|
||||||
connect(visualDeckStorageWidget, &VisualDeckStorageWidget::deckLoadRequested, this,
|
|
||||||
&DeckViewContainer::loadDeckFromFile);
|
|
||||||
connect(visualDeckStorageWidget, &VisualDeckStorageWidget::openDeckEditor, parentGame, &TabGame::openDeckEditor);
|
|
||||||
|
|
||||||
deckViewLayout->addWidget(visualDeckStorageWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeckViewContainer::retranslateUi()
|
void DeckViewContainer::retranslateUi()
|
||||||
{
|
{
|
||||||
loadLocalButton->setText(tr("Load deck..."));
|
loadLocalButton->setText(tr("Load deck..."));
|
||||||
|
|
@ -138,17 +121,7 @@ static void setVisibility(QPushButton *button, bool visible)
|
||||||
|
|
||||||
void DeckViewContainer::switchToDeckSelectView()
|
void DeckViewContainer::switchToDeckSelectView()
|
||||||
{
|
{
|
||||||
if (SettingsCache::instance().getVisualDeckStorageInGame()) {
|
deckView->setHidden(false);
|
||||||
deckView->setHidden(true);
|
|
||||||
|
|
||||||
tryCreateVisualDeckStorageWidget();
|
|
||||||
visualDeckStorageWidget->setHidden(false);
|
|
||||||
} else {
|
|
||||||
deckView->setHidden(false);
|
|
||||||
if (visualDeckStorageWidget) {
|
|
||||||
visualDeckStorageWidget->setHidden(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deckViewLayout->update();
|
deckViewLayout->update();
|
||||||
|
|
||||||
|
|
@ -172,9 +145,6 @@ void DeckViewContainer::switchToDeckSelectView()
|
||||||
void DeckViewContainer::switchToDeckLoadedView()
|
void DeckViewContainer::switchToDeckLoadedView()
|
||||||
{
|
{
|
||||||
deckView->setHidden(false);
|
deckView->setHidden(false);
|
||||||
if (visualDeckStorageWidget) {
|
|
||||||
visualDeckStorageWidget->setHidden(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
deckViewLayout->update();
|
deckViewLayout->update();
|
||||||
|
|
||||||
|
|
@ -227,15 +197,9 @@ void DeckViewContainer::setVisualDeckStorageExists(bool exists)
|
||||||
if (loadLocalButton->isEnabled()) {
|
if (loadLocalButton->isEnabled()) {
|
||||||
// We only need to handle the setting changing while in deck select state; tryCreate already gets called
|
// We only need to handle the setting changing while in deck select state; tryCreate already gets called
|
||||||
// when switching from deck loaded to deck select state
|
// when switching from deck loaded to deck select state
|
||||||
tryCreateVisualDeckStorageWidget();
|
|
||||||
visualDeckStorageWidget->setHidden(false);
|
|
||||||
deckView->setHidden(true);
|
deckView->setHidden(true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (visualDeckStorageWidget) {
|
|
||||||
visualDeckStorageWidget->deleteLater();
|
|
||||||
visualDeckStorageWidget = nullptr;
|
|
||||||
}
|
|
||||||
deckView->setHidden(false);
|
deckView->setHidden(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,11 +54,9 @@ private:
|
||||||
QPushButton *unloadDeckButton, *forceStartGameButton;
|
QPushButton *unloadDeckButton, *forceStartGameButton;
|
||||||
ToggleButton *readyStartButton, *sideboardLockButton;
|
ToggleButton *readyStartButton, *sideboardLockButton;
|
||||||
DeckView *deckView;
|
DeckView *deckView;
|
||||||
VisualDeckStorageWidget *visualDeckStorageWidget;
|
|
||||||
TabGame *parentGame;
|
TabGame *parentGame;
|
||||||
int playerId;
|
int playerId;
|
||||||
|
|
||||||
void tryCreateVisualDeckStorageWidget();
|
|
||||||
void sendReadyStartCommand(bool ready);
|
void sendReadyStartCommand(bool ready);
|
||||||
private slots:
|
private slots:
|
||||||
void switchToDeckSelectView();
|
void switchToDeckSelectView();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#include "card_size_widget.h"
|
#include "card_size_widget.h"
|
||||||
|
|
||||||
#include "../printing_selector/printing_selector.h"
|
#include "../printing_selector/printing_selector.h"
|
||||||
#include "../visual_deck_storage/visual_deck_storage_widget.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class CardSizeWidget
|
* @class CardSizeWidget
|
||||||
|
|
|
||||||
|
|
@ -1,251 +0,0 @@
|
||||||
#include "deck_card_zone_display_widget.h"
|
|
||||||
|
|
||||||
#include "card_group_display_widgets/flat_card_group_display_widget.h"
|
|
||||||
#include "card_group_display_widgets/overlapped_card_group_display_widget.h"
|
|
||||||
#include "libcockatrice/card/database/card_database_manager.h"
|
|
||||||
|
|
||||||
#include <QResizeEvent>
|
|
||||||
#include <libcockatrice/models/deck_list/deck_list_model.h>
|
|
||||||
|
|
||||||
DeckCardZoneDisplayWidget::DeckCardZoneDisplayWidget(QWidget *parent,
|
|
||||||
DeckListModel *_deckListModel,
|
|
||||||
QItemSelectionModel *_selectionModel,
|
|
||||||
QPersistentModelIndex _trackedIndex,
|
|
||||||
QString _zoneName,
|
|
||||||
QString _activeGroupCriteria,
|
|
||||||
QStringList _activeSortCriteria,
|
|
||||||
DisplayType _displayType,
|
|
||||||
int bannerOpacity,
|
|
||||||
int subBannerOpacity,
|
|
||||||
CardSizeWidget *_cardSizeWidget)
|
|
||||||
: QWidget(parent), deckListModel(_deckListModel), selectionModel(_selectionModel), trackedIndex(_trackedIndex),
|
|
||||||
zoneName(_zoneName), activeGroupCriteria(_activeGroupCriteria), activeSortCriteria(_activeSortCriteria),
|
|
||||||
displayType(_displayType), bannerOpacity(bannerOpacity), subBannerOpacity(subBannerOpacity),
|
|
||||||
cardSizeWidget(_cardSizeWidget)
|
|
||||||
{
|
|
||||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
|
||||||
layout = new QVBoxLayout(this);
|
|
||||||
setLayout(layout);
|
|
||||||
|
|
||||||
banner = new BannerWidget(this, zoneName, Qt::Orientation::Vertical, bannerOpacity);
|
|
||||||
layout->addWidget(banner);
|
|
||||||
|
|
||||||
cardGroupContainer = new QWidget(this);
|
|
||||||
cardGroupLayout = new QVBoxLayout(cardGroupContainer);
|
|
||||||
cardGroupContainer->setLayout(cardGroupLayout);
|
|
||||||
layout->addWidget(cardGroupContainer);
|
|
||||||
|
|
||||||
banner->setBuddy(cardGroupContainer);
|
|
||||||
|
|
||||||
displayCards();
|
|
||||||
|
|
||||||
connect(deckListModel, &QAbstractItemModel::rowsInserted, this, &DeckCardZoneDisplayWidget::onCategoryAddition);
|
|
||||||
if (selectionModel) {
|
|
||||||
connect(selectionModel, &QItemSelectionModel::selectionChanged, this,
|
|
||||||
&DeckCardZoneDisplayWidget::onSelectionChanged);
|
|
||||||
}
|
|
||||||
connect(deckListModel, &QAbstractItemModel::rowsRemoved, this, &DeckCardZoneDisplayWidget::onCategoryRemoval);
|
|
||||||
}
|
|
||||||
|
|
||||||
// =====================================================================================================================
|
|
||||||
// User Interaction
|
|
||||||
// =====================================================================================================================
|
|
||||||
|
|
||||||
void DeckCardZoneDisplayWidget::onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card)
|
|
||||||
{
|
|
||||||
emit cardClicked(event, card, zoneName);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeckCardZoneDisplayWidget::onHover(const ExactCard &card)
|
|
||||||
{
|
|
||||||
emit cardHovered(card);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeckCardZoneDisplayWidget::onSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
|
|
||||||
{
|
|
||||||
for (auto &range : selected) {
|
|
||||||
for (int row = range.top(); row <= range.bottom(); ++row) {
|
|
||||||
QModelIndex idx = range.model()->index(row, 0, range.parent());
|
|
||||||
auto it = indexToWidgetMap.find(QPersistentModelIndex(idx));
|
|
||||||
if (it != indexToWidgetMap.end()) {
|
|
||||||
// it.value()->setHighlighted(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &range : deselected) {
|
|
||||||
for (int row = range.top(); row <= range.bottom(); ++row) {
|
|
||||||
QModelIndex idx = range.model()->index(row, 0, range.parent());
|
|
||||||
auto it = indexToWidgetMap.find(QPersistentModelIndex(idx));
|
|
||||||
if (it != indexToWidgetMap.end()) {
|
|
||||||
// it.value()->setHighlighted(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// =====================================================================================================================
|
|
||||||
// Display Widget Management
|
|
||||||
// =====================================================================================================================
|
|
||||||
|
|
||||||
void DeckCardZoneDisplayWidget::constructAppropriateWidget(QPersistentModelIndex index)
|
|
||||||
{
|
|
||||||
if (indexToWidgetMap.contains(index)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto categoryName = index.sibling(index.row(), DeckListModelColumns::CARD_NAME).data(Qt::EditRole).toString();
|
|
||||||
if (displayType == DisplayType::Overlap) {
|
|
||||||
auto *displayWidget = new OverlappedCardGroupDisplayWidget(
|
|
||||||
cardGroupContainer, deckListModel, selectionModel, index, zoneName, categoryName, activeGroupCriteria,
|
|
||||||
activeSortCriteria, subBannerOpacity, cardSizeWidget);
|
|
||||||
connect(displayWidget, &OverlappedCardGroupDisplayWidget::cardClicked, this,
|
|
||||||
&DeckCardZoneDisplayWidget::onClick);
|
|
||||||
connect(displayWidget, &OverlappedCardGroupDisplayWidget::cardHovered, this,
|
|
||||||
&DeckCardZoneDisplayWidget::onHover);
|
|
||||||
connect(displayWidget, &CardGroupDisplayWidget::cleanupRequested, this,
|
|
||||||
&DeckCardZoneDisplayWidget::cleanupInvalidCardGroup);
|
|
||||||
connect(this, &DeckCardZoneDisplayWidget::activeSortCriteriaChanged, displayWidget,
|
|
||||||
&CardGroupDisplayWidget::onActiveSortCriteriaChanged);
|
|
||||||
cardGroupLayout->addWidget(displayWidget);
|
|
||||||
indexToWidgetMap.insert(index, displayWidget);
|
|
||||||
} else if (displayType == DisplayType::Flat) {
|
|
||||||
auto *displayWidget = new FlatCardGroupDisplayWidget(cardGroupContainer, deckListModel, selectionModel, index,
|
|
||||||
zoneName, categoryName, activeGroupCriteria,
|
|
||||||
activeSortCriteria, subBannerOpacity, cardSizeWidget);
|
|
||||||
connect(displayWidget, &FlatCardGroupDisplayWidget::cardClicked, this, &DeckCardZoneDisplayWidget::onClick);
|
|
||||||
connect(displayWidget, &FlatCardGroupDisplayWidget::cardHovered, this, &DeckCardZoneDisplayWidget::onHover);
|
|
||||||
connect(displayWidget, &CardGroupDisplayWidget::cleanupRequested, this,
|
|
||||||
&DeckCardZoneDisplayWidget::cleanupInvalidCardGroup);
|
|
||||||
connect(this, &DeckCardZoneDisplayWidget::activeSortCriteriaChanged, displayWidget,
|
|
||||||
&CardGroupDisplayWidget::onActiveSortCriteriaChanged);
|
|
||||||
cardGroupLayout->addWidget(displayWidget);
|
|
||||||
indexToWidgetMap.insert(index, displayWidget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeckCardZoneDisplayWidget::displayCards()
|
|
||||||
{
|
|
||||||
QSortFilterProxyModel proxy;
|
|
||||||
proxy.setSourceModel(deckListModel);
|
|
||||||
proxy.setSortRole(Qt::EditRole);
|
|
||||||
proxy.sort(DeckListModelColumns::CARD_NAME, Qt::AscendingOrder);
|
|
||||||
|
|
||||||
// 1. trackedIndex is a source index → map it to proxy space
|
|
||||||
QModelIndex proxyParent = proxy.mapFromSource(trackedIndex);
|
|
||||||
|
|
||||||
// 2. iterate children under the proxy parent
|
|
||||||
for (int i = 0; i < proxy.rowCount(proxyParent); ++i) {
|
|
||||||
QModelIndex proxyIndex = proxy.index(i, 0, proxyParent);
|
|
||||||
|
|
||||||
// 3. map back to source
|
|
||||||
QModelIndex sourceIndex = proxy.mapToSource(proxyIndex);
|
|
||||||
|
|
||||||
// 4. persist the source index
|
|
||||||
QPersistentModelIndex persistent(sourceIndex);
|
|
||||||
|
|
||||||
constructAppropriateWidget(persistent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeckCardZoneDisplayWidget::refreshDisplayType(const DisplayType &_displayType)
|
|
||||||
{
|
|
||||||
displayType = _displayType;
|
|
||||||
QLayoutItem *item;
|
|
||||||
while ((item = cardGroupLayout->takeAt(0)) != nullptr) {
|
|
||||||
if (item->widget()) {
|
|
||||||
item->widget()->deleteLater();
|
|
||||||
} else if (item->layout()) {
|
|
||||||
item->layout()->deleteLater();
|
|
||||||
}
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
|
|
||||||
indexToWidgetMap.clear();
|
|
||||||
|
|
||||||
// We gotta wait for all the deleteLater's to finish so we fire after the next event cycle
|
|
||||||
|
|
||||||
auto timer = new QTimer(this);
|
|
||||||
timer->setSingleShot(true);
|
|
||||||
connect(timer, &QTimer::timeout, this, [this]() { displayCards(); });
|
|
||||||
timer->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeckCardZoneDisplayWidget::cleanupInvalidCardGroup(CardGroupDisplayWidget *displayWidget)
|
|
||||||
{
|
|
||||||
cardGroupLayout->removeWidget(displayWidget);
|
|
||||||
displayWidget->setParent(nullptr);
|
|
||||||
for (auto idx : indexToWidgetMap.keys()) {
|
|
||||||
if (!idx.isValid()) {
|
|
||||||
indexToWidgetMap.remove(idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete displayWidget;
|
|
||||||
}
|
|
||||||
|
|
||||||
// =====================================================================================================================
|
|
||||||
// DeckListModel Signal Responses
|
|
||||||
// =====================================================================================================================
|
|
||||||
|
|
||||||
void DeckCardZoneDisplayWidget::onCategoryAddition(const QModelIndex &parent, int first, int last)
|
|
||||||
{
|
|
||||||
if (!trackedIndex.isValid()) {
|
|
||||||
emit requestCleanup(this);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (parent == trackedIndex) {
|
|
||||||
for (int i = first; i <= last; i++) {
|
|
||||||
QPersistentModelIndex index = QPersistentModelIndex(deckListModel->index(i, 0, trackedIndex));
|
|
||||||
|
|
||||||
constructAppropriateWidget(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeckCardZoneDisplayWidget::onCategoryRemoval(const QModelIndex &parent, int first, int last)
|
|
||||||
{
|
|
||||||
Q_UNUSED(parent);
|
|
||||||
Q_UNUSED(first);
|
|
||||||
Q_UNUSED(last);
|
|
||||||
for (const QPersistentModelIndex &idx : indexToWidgetMap.keys()) {
|
|
||||||
if (!idx.isValid()) {
|
|
||||||
cardGroupLayout->removeWidget(indexToWidgetMap.value(idx));
|
|
||||||
indexToWidgetMap.value(idx)->deleteLater();
|
|
||||||
indexToWidgetMap.remove(idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!trackedIndex.isValid()) {
|
|
||||||
emit requestCleanup(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeckCardZoneDisplayWidget::onActiveGroupCriteriaChanged(QString _activeGroupCriteria)
|
|
||||||
{
|
|
||||||
activeGroupCriteria = _activeGroupCriteria;
|
|
||||||
displayCards();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeckCardZoneDisplayWidget::onActiveSortCriteriaChanged(QStringList _activeSortCriteria)
|
|
||||||
{
|
|
||||||
activeSortCriteria = _activeSortCriteria;
|
|
||||||
emit activeSortCriteriaChanged(activeSortCriteria);
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QString> DeckCardZoneDisplayWidget::getGroupCriteriaValueList()
|
|
||||||
{
|
|
||||||
QList<QString> groupCriteriaValues;
|
|
||||||
|
|
||||||
QList<const DecklistCardNode *> nodes = deckListModel->getCardNodesForZone(zoneName);
|
|
||||||
|
|
||||||
for (auto node : nodes) {
|
|
||||||
CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(node->getName());
|
|
||||||
if (info) {
|
|
||||||
groupCriteriaValues.append(info->getProperty(activeGroupCriteria));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
groupCriteriaValues.removeDuplicates();
|
|
||||||
groupCriteriaValues.sort();
|
|
||||||
|
|
||||||
return groupCriteriaValues;
|
|
||||||
}
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
/**
|
|
||||||
* @file deck_card_zone_display_widget.h
|
|
||||||
* @ingroup DeckEditorWidgets
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef DECK_CARD_ZONE_DISPLAY_WIDGET_H
|
|
||||||
#define DECK_CARD_ZONE_DISPLAY_WIDGET_H
|
|
||||||
|
|
||||||
#include "../general/display/banner_widget.h"
|
|
||||||
#include "../general/layout_containers/overlap_widget.h"
|
|
||||||
#include "../visual_deck_editor/visual_deck_editor_widget.h"
|
|
||||||
#include "card_group_display_widgets/card_group_display_widget.h"
|
|
||||||
#include "card_info_picture_with_text_overlay_widget.h"
|
|
||||||
#include "card_size_widget.h"
|
|
||||||
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QWidget>
|
|
||||||
#include <libcockatrice/models/deck_list/deck_list_model.h>
|
|
||||||
|
|
||||||
class DeckCardZoneDisplayWidget : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
DeckCardZoneDisplayWidget(QWidget *parent,
|
|
||||||
DeckListModel *deckListModel,
|
|
||||||
QItemSelectionModel *selectionModel,
|
|
||||||
QPersistentModelIndex trackedIndex,
|
|
||||||
QString zoneName,
|
|
||||||
QString activeGroupCriteria,
|
|
||||||
QStringList activeSortCriteria,
|
|
||||||
DisplayType displayType,
|
|
||||||
int bannerOpacity,
|
|
||||||
int subBannerOpacity,
|
|
||||||
CardSizeWidget *_cardSizeWidget);
|
|
||||||
void onSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
|
|
||||||
DeckListModel *deckListModel;
|
|
||||||
QItemSelectionModel *selectionModel;
|
|
||||||
QPersistentModelIndex trackedIndex;
|
|
||||||
QString zoneName;
|
|
||||||
void addCardsToOverlapWidget();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card);
|
|
||||||
void onHover(const ExactCard &card);
|
|
||||||
void cleanupInvalidCardGroup(CardGroupDisplayWidget *displayWidget);
|
|
||||||
void constructAppropriateWidget(QPersistentModelIndex index);
|
|
||||||
void displayCards();
|
|
||||||
void refreshDisplayType(const DisplayType &displayType);
|
|
||||||
void onActiveGroupCriteriaChanged(QString activeGroupCriteria);
|
|
||||||
void onActiveSortCriteriaChanged(QStringList activeSortCriteria);
|
|
||||||
QList<QString> getGroupCriteriaValueList();
|
|
||||||
void onCategoryAddition(const QModelIndex &parent, int first, int last);
|
|
||||||
void onCategoryRemoval(const QModelIndex &parent, int first, int last);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void cardClicked(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card, QString zoneName);
|
|
||||||
void cardHovered(const ExactCard &card);
|
|
||||||
void activeSortCriteriaChanged(QStringList activeSortCriteria);
|
|
||||||
void requestCleanup(DeckCardZoneDisplayWidget *displayWidget);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString activeGroupCriteria;
|
|
||||||
QStringList activeSortCriteria;
|
|
||||||
DisplayType displayType = DisplayType::Overlap;
|
|
||||||
int bannerOpacity = 20;
|
|
||||||
int subBannerOpacity = 10;
|
|
||||||
CardSizeWidget *cardSizeWidget;
|
|
||||||
QVBoxLayout *layout;
|
|
||||||
BannerWidget *banner;
|
|
||||||
QWidget *cardGroupContainer;
|
|
||||||
QVBoxLayout *cardGroupLayout;
|
|
||||||
OverlapWidget *overlapWidget;
|
|
||||||
QHash<QPersistentModelIndex, QWidget *> indexToWidgetMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // DECK_CARD_ZONE_DISPLAY_WIDGET_H
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
#include "deck_preview_card_picture_widget.h"
|
|
||||||
|
|
||||||
#include "../../../client/settings/cache_settings.h"
|
|
||||||
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QFileInfo>
|
|
||||||
#include <QFontMetrics>
|
|
||||||
#include <QMouseEvent>
|
|
||||||
#include <QPainterPath>
|
|
||||||
#include <QStylePainter>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Constructs a CardPictureWithTextOverlay widget.
|
|
||||||
* @param parent The parent widget.
|
|
||||||
* @param hoverToZoomEnabled If this widget will spawn a larger widget when hovered over.
|
|
||||||
* @param textColor The color of the overlay text.
|
|
||||||
* @param outlineColor The color of the outline around the text.
|
|
||||||
* @param fontSize The font size of the overlay text.
|
|
||||||
* @param alignment The alignment of the text within the overlay.
|
|
||||||
*
|
|
||||||
* Sets the widget's size policy and default border style.
|
|
||||||
*/
|
|
||||||
DeckPreviewCardPictureWidget::DeckPreviewCardPictureWidget(QWidget *parent,
|
|
||||||
const bool hoverToZoomEnabled,
|
|
||||||
const bool raiseOnEnter,
|
|
||||||
const QColor &textColor,
|
|
||||||
const QColor &outlineColor,
|
|
||||||
const int fontSize,
|
|
||||||
const Qt::Alignment alignment)
|
|
||||||
: CardInfoPictureWithTextOverlayWidget(parent,
|
|
||||||
hoverToZoomEnabled,
|
|
||||||
raiseOnEnter,
|
|
||||||
textColor,
|
|
||||||
outlineColor,
|
|
||||||
fontSize,
|
|
||||||
alignment)
|
|
||||||
{
|
|
||||||
singleClickTimer = new QTimer(this);
|
|
||||||
singleClickTimer->setSingleShot(true);
|
|
||||||
connect(singleClickTimer, &QTimer::timeout, this, [this]() { emit imageClicked(lastMouseEvent, this); });
|
|
||||||
connect(&SettingsCache::instance(), &SettingsCache::visualDeckStorageSelectionAnimationChanged, this,
|
|
||||||
&CardInfoPictureWidget::setRaiseOnEnterEnabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeckPreviewCardPictureWidget::mousePressEvent(QMouseEvent *event)
|
|
||||||
{
|
|
||||||
if (event->button() == Qt::LeftButton) {
|
|
||||||
lastMouseEvent = event;
|
|
||||||
singleClickTimer->start(QApplication::doubleClickInterval());
|
|
||||||
} else {
|
|
||||||
emit imageClicked(event, this);
|
|
||||||
event->accept();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeckPreviewCardPictureWidget::mouseDoubleClickEvent(QMouseEvent *event)
|
|
||||||
{
|
|
||||||
if (event->button() == Qt::LeftButton) {
|
|
||||||
singleClickTimer->stop(); // Prevent single-click logic
|
|
||||||
emit imageDoubleClicked(lastMouseEvent, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
/**
|
|
||||||
* @file deck_preview_card_picture_widget.h
|
|
||||||
* @ingroup CardWidgets
|
|
||||||
* @ingroup Lobby
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef DECK_PREVIEW_CARD_PICTURE_WIDGET_H
|
|
||||||
#define DECK_PREVIEW_CARD_PICTURE_WIDGET_H
|
|
||||||
|
|
||||||
#include "card_info_picture_with_text_overlay_widget.h"
|
|
||||||
|
|
||||||
#include <QColor>
|
|
||||||
#include <QSize>
|
|
||||||
#include <QTextOption>
|
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
class DeckPreviewCardPictureWidget final : public CardInfoPictureWithTextOverlayWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit DeckPreviewCardPictureWidget(QWidget *parent,
|
|
||||||
bool hoverToZoomEnabled = false,
|
|
||||||
bool raiseOnEnter = false,
|
|
||||||
const QColor &textColor = Qt::white,
|
|
||||||
const QColor &outlineColor = Qt::black,
|
|
||||||
int fontSize = 12,
|
|
||||||
Qt::Alignment alignment = Qt::AlignCenter);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void imageClicked(QMouseEvent *event, DeckPreviewCardPictureWidget *instance);
|
|
||||||
void imageDoubleClicked(QMouseEvent *event, DeckPreviewCardPictureWidget *instance);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QTimer *singleClickTimer;
|
|
||||||
QMouseEvent *lastMouseEvent = nullptr; // Store the last mouse event
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
|
||||||
void mouseDoubleClickEvent(QMouseEvent *event) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // DECK_PREVIEW_CARD_PICTURE_WIDGET_H
|
|
||||||
|
|
@ -14,13 +14,6 @@
|
||||||
#include <libcockatrice/card/database/card_database_manager.h>
|
#include <libcockatrice/card/database/card_database_manager.h>
|
||||||
#include <libcockatrice/card/relation/card_relation.h>
|
#include <libcockatrice/card/relation/card_relation.h>
|
||||||
|
|
||||||
static bool canBeCommander(const CardInfo &cardInfo)
|
|
||||||
{
|
|
||||||
return (cardInfo.getCardType().contains("Legendary", Qt::CaseInsensitive) &&
|
|
||||||
cardInfo.getCardType().contains("Creature", Qt::CaseInsensitive)) ||
|
|
||||||
cardInfo.getText().contains("can be your commander", Qt::CaseInsensitive);
|
|
||||||
}
|
|
||||||
|
|
||||||
DeckEditorDatabaseDisplayWidget::DeckEditorDatabaseDisplayWidget(QWidget *parent, AbstractTabDeckEditor *deckEditor)
|
DeckEditorDatabaseDisplayWidget::DeckEditorDatabaseDisplayWidget(QWidget *parent, AbstractTabDeckEditor *deckEditor)
|
||||||
: QWidget(parent), deckEditor(deckEditor)
|
: QWidget(parent), deckEditor(deckEditor)
|
||||||
{
|
{
|
||||||
|
|
@ -186,22 +179,14 @@ void DeckEditorDatabaseDisplayWidget::databaseCustomMenu(QPoint point)
|
||||||
|
|
||||||
if (card) {
|
if (card) {
|
||||||
// add to deck and sideboard options
|
// add to deck and sideboard options
|
||||||
QAction *addToDeck, *addToSideboard, *selectPrinting, *edhRecCommander, *edhRecCard;
|
QAction *addToDeck, *addToSideboard, *selectPrinting;
|
||||||
addToDeck = menu.addAction(tr("Add to Deck"));
|
addToDeck = menu.addAction(tr("Add to Deck"));
|
||||||
addToSideboard = menu.addAction(tr("Add to Sideboard"));
|
addToSideboard = menu.addAction(tr("Add to Sideboard"));
|
||||||
selectPrinting = menu.addAction(tr("Select Printing"));
|
selectPrinting = menu.addAction(tr("Select Printing"));
|
||||||
connect(selectPrinting, &QAction::triggered, this, [this, card] { deckEditor->showPrintingSelector(); });
|
connect(selectPrinting, &QAction::triggered, this, [this, card] { deckEditor->showPrintingSelector(); });
|
||||||
if (canBeCommander(card.getInfo())) {
|
|
||||||
edhRecCommander = menu.addAction(tr("Show on EDHRec (Commander)"));
|
|
||||||
connect(edhRecCommander, &QAction::triggered, this,
|
|
||||||
[this, card] { deckEditor->getTabSupervisor()->addEdhrecTab(card.getCardPtr(), true); });
|
|
||||||
}
|
|
||||||
edhRecCard = menu.addAction(tr("Show on EDHRec (Card)"));
|
|
||||||
|
|
||||||
connect(addToDeck, &QAction::triggered, this, &DeckEditorDatabaseDisplayWidget::actAddCardToMainDeck);
|
connect(addToDeck, &QAction::triggered, this, &DeckEditorDatabaseDisplayWidget::actAddCardToMainDeck);
|
||||||
connect(addToSideboard, &QAction::triggered, this, &DeckEditorDatabaseDisplayWidget::actAddCardToSideboard);
|
connect(addToSideboard, &QAction::triggered, this, &DeckEditorDatabaseDisplayWidget::actAddCardToSideboard);
|
||||||
connect(edhRecCard, &QAction::triggered, this,
|
|
||||||
[this, card] { deckEditor->getTabSupervisor()->addEdhrecTab(card.getCardPtr()); });
|
|
||||||
|
|
||||||
// filling out the related cards submenu
|
// filling out the related cards submenu
|
||||||
auto *relatedMenu = new QMenu(tr("Show Related cards"));
|
auto *relatedMenu = new QMenu(tr("Show Related cards"));
|
||||||
|
|
|
||||||
|
|
@ -119,8 +119,6 @@ void DeckEditorDeckDockWidget::createDeckDock()
|
||||||
showTagsWidgetCheckBox->setChecked(SettingsCache::instance().getDeckEditorTagsWidgetVisible());
|
showTagsWidgetCheckBox->setChecked(SettingsCache::instance().getDeckEditorTagsWidgetVisible());
|
||||||
connect(showTagsWidgetCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
connect(showTagsWidgetCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||||
&SettingsCache::setDeckEditorTagsWidgetVisible);
|
&SettingsCache::setDeckEditorTagsWidgetVisible);
|
||||||
connect(&SettingsCache::instance(), &SettingsCache::deckEditorTagsWidgetVisibleChanged, this,
|
|
||||||
&DeckEditorDeckDockWidget::updateShowTagsWidget);
|
|
||||||
|
|
||||||
quickSettingsWidget->addSettingsWidget(showBannerCardCheckBox);
|
quickSettingsWidget->addSettingsWidget(showBannerCardCheckBox);
|
||||||
quickSettingsWidget->addSettingsWidget(showTagsWidgetCheckBox);
|
quickSettingsWidget->addSettingsWidget(showTagsWidgetCheckBox);
|
||||||
|
|
@ -164,11 +162,6 @@ void DeckEditorDeckDockWidget::createDeckDock()
|
||||||
&DeckEditorDeckDockWidget::writeBannerCard);
|
&DeckEditorDeckDockWidget::writeBannerCard);
|
||||||
bannerCardComboBox->setHidden(!SettingsCache::instance().getDeckEditorBannerCardComboBoxVisible());
|
bannerCardComboBox->setHidden(!SettingsCache::instance().getDeckEditorBannerCardComboBoxVisible());
|
||||||
|
|
||||||
deckTagsDisplayWidget = new DeckPreviewDeckTagsDisplayWidget(this, {});
|
|
||||||
deckTagsDisplayWidget->setHidden(!SettingsCache::instance().getDeckEditorTagsWidgetVisible());
|
|
||||||
connect(deckTagsDisplayWidget, &DeckPreviewDeckTagsDisplayWidget::tagsChanged, deckStateManager,
|
|
||||||
&DeckStateManager::setTags);
|
|
||||||
|
|
||||||
activeGroupCriteriaLabel = new QLabel(this);
|
activeGroupCriteriaLabel = new QLabel(this);
|
||||||
|
|
||||||
activeGroupCriteriaComboBox = new QComboBox(this);
|
activeGroupCriteriaComboBox = new QComboBox(this);
|
||||||
|
|
@ -219,8 +212,6 @@ void DeckEditorDeckDockWidget::createDeckDock()
|
||||||
upperLayout->addWidget(bannerCardLabel, 3, 0);
|
upperLayout->addWidget(bannerCardLabel, 3, 0);
|
||||||
upperLayout->addWidget(bannerCardComboBox, 3, 1);
|
upperLayout->addWidget(bannerCardComboBox, 3, 1);
|
||||||
|
|
||||||
upperLayout->addWidget(deckTagsDisplayWidget, 4, 1);
|
|
||||||
|
|
||||||
upperLayout->addWidget(activeGroupCriteriaLabel, 5, 0);
|
upperLayout->addWidget(activeGroupCriteriaLabel, 5, 0);
|
||||||
upperLayout->addWidget(activeGroupCriteriaComboBox, 5, 1);
|
upperLayout->addWidget(activeGroupCriteriaComboBox, 5, 1);
|
||||||
|
|
||||||
|
|
@ -439,11 +430,6 @@ void DeckEditorDeckDockWidget::updateShowBannerCardComboBox(const bool visible)
|
||||||
bannerCardComboBox->setHidden(!visible);
|
bannerCardComboBox->setHidden(!visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeckEditorDeckDockWidget::updateShowTagsWidget(const bool visible)
|
|
||||||
{
|
|
||||||
deckTagsDisplayWidget->setHidden(!visible);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeckEditorDeckDockWidget::syncBannerCardComboBoxSelectionWithDeck()
|
void DeckEditorDeckDockWidget::syncBannerCardComboBoxSelectionWithDeck()
|
||||||
{
|
{
|
||||||
if (deckStateManager->getMetadata().bannerCard.name == "") {
|
if (deckStateManager->getMetadata().bannerCard.name == "") {
|
||||||
|
|
@ -488,10 +474,6 @@ void DeckEditorDeckDockWidget::syncDisplayWidgetsToModel()
|
||||||
formatComboBox->blockSignals(true);
|
formatComboBox->blockSignals(true);
|
||||||
formatComboBox->setCurrentIndex(formatComboBox->findData(deckStateManager->getMetadata().gameFormat));
|
formatComboBox->setCurrentIndex(formatComboBox->findData(deckStateManager->getMetadata().gameFormat));
|
||||||
formatComboBox->blockSignals(false);
|
formatComboBox->blockSignals(false);
|
||||||
|
|
||||||
deckTagsDisplayWidget->blockSignals(true);
|
|
||||||
deckTagsDisplayWidget->setTags(deckStateManager->getMetadata().tags);
|
|
||||||
deckTagsDisplayWidget->blockSignals(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,11 @@
|
||||||
#include "../../../interface/widgets/tabs/abstract_tab_deck_editor.h"
|
#include "../../../interface/widgets/tabs/abstract_tab_deck_editor.h"
|
||||||
#include "../../key_signals.h"
|
#include "../../key_signals.h"
|
||||||
#include "../utility/custom_line_edit.h"
|
#include "../utility/custom_line_edit.h"
|
||||||
#include "../visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h"
|
|
||||||
#include "deck_list_history_manager_widget.h"
|
#include "deck_list_history_manager_widget.h"
|
||||||
#include "deck_list_style_proxy.h"
|
#include "deck_list_style_proxy.h"
|
||||||
|
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QComboBox>
|
||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QTextEdit>
|
#include <QTextEdit>
|
||||||
|
|
@ -79,7 +80,6 @@ private:
|
||||||
QTextEdit *commentsEdit;
|
QTextEdit *commentsEdit;
|
||||||
QTimer *commentsDebounceTimer;
|
QTimer *commentsDebounceTimer;
|
||||||
QLabel *bannerCardLabel;
|
QLabel *bannerCardLabel;
|
||||||
DeckPreviewDeckTagsDisplayWidget *deckTagsDisplayWidget;
|
|
||||||
QLabel *hashLabel1;
|
QLabel *hashLabel1;
|
||||||
LineEditUnfocusable *hashLabel;
|
LineEditUnfocusable *hashLabel;
|
||||||
QLabel *activeGroupCriteriaLabel;
|
QLabel *activeGroupCriteriaLabel;
|
||||||
|
|
@ -104,7 +104,6 @@ private slots:
|
||||||
void updateHash();
|
void updateHash();
|
||||||
void refreshShortcuts();
|
void refreshShortcuts();
|
||||||
void updateShowBannerCardComboBox(bool visible);
|
void updateShowBannerCardComboBox(bool visible);
|
||||||
void updateShowTagsWidget(bool visible);
|
|
||||||
void syncBannerCardComboBoxSelectionWithDeck();
|
void syncBannerCardComboBoxSelectionWithDeck();
|
||||||
void changeSelectedCard(int changeBy);
|
void changeSelectedCard(int changeBy);
|
||||||
void recursiveExpand(const QModelIndex &parent);
|
void recursiveExpand(const QModelIndex &parent);
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
#include "../client/sound_engine.h"
|
#include "../client/sound_engine.h"
|
||||||
#include "../interface/card_picture_loader/card_picture_loader.h"
|
#include "../interface/card_picture_loader/card_picture_loader.h"
|
||||||
#include "../interface/theme_manager.h"
|
#include "../interface/theme_manager.h"
|
||||||
#include "../interface/widgets/general/background_sources.h"
|
|
||||||
#include "../interface/widgets/tabs/tab_supervisor.h"
|
#include "../interface/widgets/tabs/tab_supervisor.h"
|
||||||
#include "../interface/widgets/utility/custom_line_edit.h"
|
#include "../interface/widgets/utility/custom_line_edit.h"
|
||||||
#include "../interface/widgets/utility/get_text_with_max.h"
|
#include "../interface/widgets/utility/get_text_with_max.h"
|
||||||
|
|
@ -425,45 +424,10 @@ AppearanceSettingsPage::AppearanceSettingsPage()
|
||||||
connect(&themeBox, qOverload<int>(&QComboBox::currentIndexChanged), this, &AppearanceSettingsPage::themeBoxChanged);
|
connect(&themeBox, qOverload<int>(&QComboBox::currentIndexChanged), this, &AppearanceSettingsPage::themeBoxChanged);
|
||||||
connect(&openThemeButton, &QPushButton::clicked, this, &AppearanceSettingsPage::openThemeLocation);
|
connect(&openThemeButton, &QPushButton::clicked, this, &AppearanceSettingsPage::openThemeLocation);
|
||||||
|
|
||||||
for (const auto &entry : BackgroundSources::all()) {
|
|
||||||
homeTabBackgroundSourceBox.addItem(QObject::tr(entry.trKey), QVariant::fromValue(entry.type));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString homeTabBackgroundSource = SettingsCache::instance().getHomeTabBackgroundSource();
|
|
||||||
int homeTabBackgroundSourceId =
|
|
||||||
homeTabBackgroundSourceBox.findData(BackgroundSources::fromId(homeTabBackgroundSource));
|
|
||||||
if (homeTabBackgroundSourceId != -1) {
|
|
||||||
homeTabBackgroundSourceBox.setCurrentIndex(homeTabBackgroundSourceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
connect(&homeTabBackgroundSourceBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this]() {
|
|
||||||
auto type = homeTabBackgroundSourceBox.currentData().value<BackgroundSources::Type>();
|
|
||||||
SettingsCache::instance().setHomeTabBackgroundSource(BackgroundSources::toId(type));
|
|
||||||
updateHomeTabSettingsVisibility();
|
|
||||||
});
|
|
||||||
|
|
||||||
homeTabBackgroundShuffleFrequencySpinBox.setRange(0, 3600);
|
|
||||||
homeTabBackgroundShuffleFrequencySpinBox.setSuffix(tr(" seconds"));
|
|
||||||
homeTabBackgroundShuffleFrequencySpinBox.setValue(SettingsCache::instance().getHomeTabBackgroundShuffleFrequency());
|
|
||||||
connect(&homeTabBackgroundShuffleFrequencySpinBox, qOverload<int>(&QSpinBox::valueChanged),
|
|
||||||
&SettingsCache::instance(), &SettingsCache::setHomeTabBackgroundShuffleFrequency);
|
|
||||||
|
|
||||||
homeTabDisplayCardNameCheckBox.setChecked(settings.getHomeTabDisplayCardName());
|
|
||||||
connect(&homeTabDisplayCardNameCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings,
|
|
||||||
&SettingsCache::setHomeTabDisplayCardName);
|
|
||||||
|
|
||||||
updateHomeTabSettingsVisibility();
|
|
||||||
|
|
||||||
auto *themeGrid = new QGridLayout;
|
auto *themeGrid = new QGridLayout;
|
||||||
themeGrid->addWidget(&themeLabel, 0, 0);
|
themeGrid->addWidget(&themeLabel, 0, 0);
|
||||||
themeGrid->addWidget(&themeBox, 0, 1);
|
themeGrid->addWidget(&themeBox, 0, 1);
|
||||||
themeGrid->addWidget(&openThemeButton, 1, 1);
|
themeGrid->addWidget(&openThemeButton, 1, 1);
|
||||||
themeGrid->addWidget(&homeTabBackgroundSourceLabel, 2, 0);
|
|
||||||
themeGrid->addWidget(&homeTabBackgroundSourceBox, 2, 1);
|
|
||||||
themeGrid->addWidget(&homeTabBackgroundShuffleFrequencyLabel, 3, 0);
|
|
||||||
themeGrid->addWidget(&homeTabBackgroundShuffleFrequencySpinBox, 3, 1);
|
|
||||||
themeGrid->addWidget(&homeTabDisplayCardNameLabel, 4, 0);
|
|
||||||
themeGrid->addWidget(&homeTabDisplayCardNameCheckBox, 4, 1);
|
|
||||||
|
|
||||||
themeGroupBox = new QGroupBox;
|
themeGroupBox = new QGroupBox;
|
||||||
themeGroupBox->setLayout(themeGrid);
|
themeGroupBox->setLayout(themeGrid);
|
||||||
|
|
@ -660,17 +624,6 @@ void AppearanceSettingsPage::openThemeLocation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppearanceSettingsPage::updateHomeTabSettingsVisibility()
|
|
||||||
{
|
|
||||||
bool visible =
|
|
||||||
SettingsCache::instance().getHomeTabBackgroundSource() != BackgroundSources::toId(BackgroundSources::Theme);
|
|
||||||
|
|
||||||
homeTabBackgroundShuffleFrequencyLabel.setVisible(visible);
|
|
||||||
homeTabBackgroundShuffleFrequencySpinBox.setVisible(visible);
|
|
||||||
homeTabDisplayCardNameLabel.setVisible(visible);
|
|
||||||
homeTabDisplayCardNameCheckBox.setVisible(visible);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppearanceSettingsPage::showShortcutsChanged(QT_STATE_CHANGED_T value)
|
void AppearanceSettingsPage::showShortcutsChanged(QT_STATE_CHANGED_T value)
|
||||||
{
|
{
|
||||||
SettingsCache::instance().setShowShortcuts(value);
|
SettingsCache::instance().setShowShortcuts(value);
|
||||||
|
|
@ -724,10 +677,6 @@ void AppearanceSettingsPage::retranslateUi()
|
||||||
themeGroupBox->setTitle(tr("Theme settings"));
|
themeGroupBox->setTitle(tr("Theme settings"));
|
||||||
themeLabel.setText(tr("Current theme:"));
|
themeLabel.setText(tr("Current theme:"));
|
||||||
openThemeButton.setText(tr("Open themes folder"));
|
openThemeButton.setText(tr("Open themes folder"));
|
||||||
homeTabBackgroundSourceLabel.setText(tr("Home tab background source:"));
|
|
||||||
homeTabBackgroundShuffleFrequencyLabel.setText(tr("Home tab background shuffle frequency:"));
|
|
||||||
homeTabBackgroundShuffleFrequencySpinBox.setSpecialValueText(tr("Disabled"));
|
|
||||||
homeTabDisplayCardNameLabel.setText(tr("Display card name of background in bottom right:"));
|
|
||||||
|
|
||||||
menuGroupBox->setTitle(tr("Menu settings"));
|
menuGroupBox->setTitle(tr("Menu settings"));
|
||||||
showShortcutsCheckBox.setText(tr("Show keyboard shortcuts in right-click menus"));
|
showShortcutsCheckBox.setText(tr("Show keyboard shortcuts in right-click menus"));
|
||||||
|
|
@ -872,47 +821,8 @@ UserInterfaceSettingsPage::UserInterfaceSettingsPage()
|
||||||
connect(&openDeckInNewTabCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
connect(&openDeckInNewTabCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||||
&SettingsCache::setOpenDeckInNewTab);
|
&SettingsCache::setOpenDeckInNewTab);
|
||||||
|
|
||||||
visualDeckStorageInGameCheckBox.setChecked(SettingsCache::instance().getVisualDeckStorageInGame());
|
|
||||||
connect(&visualDeckStorageInGameCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
|
||||||
&SettingsCache::setVisualDeckStorageInGame);
|
|
||||||
|
|
||||||
visualDeckStorageSelectionAnimationCheckBox.setChecked(
|
|
||||||
SettingsCache::instance().getVisualDeckStorageSelectionAnimation());
|
|
||||||
connect(&visualDeckStorageSelectionAnimationCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
|
||||||
&SettingsCache::setVisualDeckStorageSelectionAnimation);
|
|
||||||
|
|
||||||
visualDeckStoragePromptForConversionSelector.addItem(""); // these will be set in retranslateUI
|
|
||||||
visualDeckStoragePromptForConversionSelector.addItem("");
|
|
||||||
visualDeckStoragePromptForConversionSelector.addItem("");
|
|
||||||
if (SettingsCache::instance().getVisualDeckStoragePromptForConversion()) {
|
|
||||||
visualDeckStoragePromptForConversionSelector.setCurrentIndex(visualDeckStoragePromptForConversionIndexPrompt);
|
|
||||||
} else if (SettingsCache::instance().getVisualDeckStorageAlwaysConvert()) {
|
|
||||||
visualDeckStoragePromptForConversionSelector.setCurrentIndex(visualDeckStoragePromptForConversionIndexAlways);
|
|
||||||
} else {
|
|
||||||
visualDeckStoragePromptForConversionSelector.setCurrentIndex(visualDeckStoragePromptForConversionIndexNone);
|
|
||||||
}
|
|
||||||
connect(&visualDeckStoragePromptForConversionSelector, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
|
||||||
[](int index) {
|
|
||||||
SettingsCache::instance().setVisualDeckStoragePromptForConversion(
|
|
||||||
index == visualDeckStoragePromptForConversionIndexPrompt);
|
|
||||||
SettingsCache::instance().setVisualDeckStorageAlwaysConvert(
|
|
||||||
index == visualDeckStoragePromptForConversionIndexAlways);
|
|
||||||
});
|
|
||||||
|
|
||||||
defaultDeckEditorTypeSelector.addItem(""); // these will be set in retranslateUI
|
|
||||||
defaultDeckEditorTypeSelector.addItem("");
|
|
||||||
defaultDeckEditorTypeSelector.setCurrentIndex(SettingsCache::instance().getDefaultDeckEditorType());
|
|
||||||
connect(&defaultDeckEditorTypeSelector, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
|
||||||
&SettingsCache::instance(), &SettingsCache::setDefaultDeckEditorType);
|
|
||||||
|
|
||||||
auto *deckEditorGrid = new QGridLayout;
|
auto *deckEditorGrid = new QGridLayout;
|
||||||
deckEditorGrid->addWidget(&openDeckInNewTabCheckBox, 0, 0);
|
deckEditorGrid->addWidget(&openDeckInNewTabCheckBox, 0, 0);
|
||||||
deckEditorGrid->addWidget(&visualDeckStorageInGameCheckBox, 1, 0);
|
|
||||||
deckEditorGrid->addWidget(&visualDeckStorageSelectionAnimationCheckBox, 2, 0);
|
|
||||||
deckEditorGrid->addWidget(&visualDeckStoragePromptForConversionLabel, 3, 0);
|
|
||||||
deckEditorGrid->addWidget(&visualDeckStoragePromptForConversionSelector, 3, 1);
|
|
||||||
deckEditorGrid->addWidget(&defaultDeckEditorTypeLabel, 4, 0);
|
|
||||||
deckEditorGrid->addWidget(&defaultDeckEditorTypeSelector, 4, 1);
|
|
||||||
|
|
||||||
deckEditorGroupBox = new QGroupBox;
|
deckEditorGroupBox = new QGroupBox;
|
||||||
deckEditorGroupBox->setLayout(deckEditorGrid);
|
deckEditorGroupBox->setLayout(deckEditorGrid);
|
||||||
|
|
@ -976,19 +886,6 @@ void UserInterfaceSettingsPage::retranslateUi()
|
||||||
tapAnimationCheckBox.setText(tr("&Tap/untap animation"));
|
tapAnimationCheckBox.setText(tr("&Tap/untap animation"));
|
||||||
deckEditorGroupBox->setTitle(tr("Deck editor/storage settings"));
|
deckEditorGroupBox->setTitle(tr("Deck editor/storage settings"));
|
||||||
openDeckInNewTabCheckBox.setText(tr("Open deck in new tab by default"));
|
openDeckInNewTabCheckBox.setText(tr("Open deck in new tab by default"));
|
||||||
visualDeckStorageInGameCheckBox.setText(tr("Use visual deck storage in game lobby"));
|
|
||||||
visualDeckStorageSelectionAnimationCheckBox.setText(tr("Use selection animation for Visual Deck Storage"));
|
|
||||||
visualDeckStoragePromptForConversionLabel.setText(
|
|
||||||
tr("When adding a tag in the visual deck storage to a .txt deck:"));
|
|
||||||
visualDeckStoragePromptForConversionSelector.setItemText(visualDeckStoragePromptForConversionIndexNone,
|
|
||||||
tr("do nothing"));
|
|
||||||
visualDeckStoragePromptForConversionSelector.setItemText(visualDeckStoragePromptForConversionIndexPrompt,
|
|
||||||
tr("ask to convert to .cod"));
|
|
||||||
visualDeckStoragePromptForConversionSelector.setItemText(visualDeckStoragePromptForConversionIndexAlways,
|
|
||||||
tr("always convert to .cod"));
|
|
||||||
defaultDeckEditorTypeLabel.setText(tr("Default deck editor type"));
|
|
||||||
defaultDeckEditorTypeSelector.setItemText(TabSupervisor::ClassicDeckEditor, tr("Classic Deck Editor"));
|
|
||||||
defaultDeckEditorTypeSelector.setItemText(TabSupervisor::VisualDeckEditor, tr("Visual Deck Editor"));
|
|
||||||
replayGroupBox->setTitle(tr("Replay settings"));
|
replayGroupBox->setTitle(tr("Replay settings"));
|
||||||
rewindBufferingMsLabel.setText(tr("Buffer time for backwards skip via shortcut:"));
|
rewindBufferingMsLabel.setText(tr("Buffer time for backwards skip via shortcut:"));
|
||||||
rewindBufferingMsBox.setSuffix(" ms");
|
rewindBufferingMsBox.setSuffix(" ms");
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,6 @@ class AppearanceSettingsPage : public AbstractSettingsPage
|
||||||
private slots:
|
private slots:
|
||||||
void themeBoxChanged(int index);
|
void themeBoxChanged(int index);
|
||||||
void openThemeLocation();
|
void openThemeLocation();
|
||||||
void updateHomeTabSettingsVisibility();
|
|
||||||
void showShortcutsChanged(QT_STATE_CHANGED_T enabled);
|
void showShortcutsChanged(QT_STATE_CHANGED_T enabled);
|
||||||
void overrideAllCardArtWithPersonalPreferenceToggled(QT_STATE_CHANGED_T enabled);
|
void overrideAllCardArtWithPersonalPreferenceToggled(QT_STATE_CHANGED_T enabled);
|
||||||
|
|
||||||
|
|
@ -114,12 +113,6 @@ private:
|
||||||
QLabel themeLabel;
|
QLabel themeLabel;
|
||||||
QComboBox themeBox;
|
QComboBox themeBox;
|
||||||
QPushButton openThemeButton;
|
QPushButton openThemeButton;
|
||||||
QLabel homeTabBackgroundSourceLabel;
|
|
||||||
QComboBox homeTabBackgroundSourceBox;
|
|
||||||
QLabel homeTabBackgroundShuffleFrequencyLabel;
|
|
||||||
QSpinBox homeTabBackgroundShuffleFrequencySpinBox;
|
|
||||||
QLabel homeTabDisplayCardNameLabel;
|
|
||||||
QCheckBox homeTabDisplayCardNameCheckBox;
|
|
||||||
QLabel minPlayersForMultiColumnLayoutLabel;
|
QLabel minPlayersForMultiColumnLayoutLabel;
|
||||||
QLabel maxFontSizeForCardsLabel;
|
QLabel maxFontSizeForCardsLabel;
|
||||||
QCheckBox showShortcutsCheckBox;
|
QCheckBox showShortcutsCheckBox;
|
||||||
|
|
@ -176,12 +169,6 @@ private:
|
||||||
QCheckBox useTearOffMenusCheckBox;
|
QCheckBox useTearOffMenusCheckBox;
|
||||||
QCheckBox tapAnimationCheckBox;
|
QCheckBox tapAnimationCheckBox;
|
||||||
QCheckBox openDeckInNewTabCheckBox;
|
QCheckBox openDeckInNewTabCheckBox;
|
||||||
QLabel visualDeckStoragePromptForConversionLabel;
|
|
||||||
QComboBox visualDeckStoragePromptForConversionSelector;
|
|
||||||
QCheckBox visualDeckStorageInGameCheckBox;
|
|
||||||
QCheckBox visualDeckStorageSelectionAnimationCheckBox;
|
|
||||||
QLabel defaultDeckEditorTypeLabel;
|
|
||||||
QComboBox defaultDeckEditorTypeSelector;
|
|
||||||
QLabel rewindBufferingMsLabel;
|
QLabel rewindBufferingMsLabel;
|
||||||
QSpinBox rewindBufferingMsBox;
|
QSpinBox rewindBufferingMsBox;
|
||||||
QGroupBox *generalGroupBox;
|
QGroupBox *generalGroupBox;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
#include "background_sources.h"
|
|
||||||
|
|
||||||
// Required so moc generates Q_OBJECT macros
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
/**
|
|
||||||
* @file background_sources.h
|
|
||||||
* @ingroup UI
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef COCKATRICE_BACKGROUND_SOURCES_H
|
|
||||||
#define COCKATRICE_BACKGROUND_SOURCES_H
|
|
||||||
|
|
||||||
#include <QList>
|
|
||||||
#include <QObject>
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
class BackgroundSources
|
|
||||||
{
|
|
||||||
Q_GADGET
|
|
||||||
public:
|
|
||||||
enum Type
|
|
||||||
{
|
|
||||||
Theme,
|
|
||||||
RandomCardArt,
|
|
||||||
DeckFileArt
|
|
||||||
};
|
|
||||||
Q_ENUM(Type)
|
|
||||||
|
|
||||||
struct Entry
|
|
||||||
{
|
|
||||||
Type type;
|
|
||||||
const char *id; // stable ID for settings
|
|
||||||
const char *trKey; // key for translation
|
|
||||||
};
|
|
||||||
|
|
||||||
static QList<Entry> all()
|
|
||||||
{
|
|
||||||
return {{Theme, "theme", QT_TR_NOOP("Theme")},
|
|
||||||
{RandomCardArt, "random_card_art", QT_TR_NOOP("Art crop of random card")},
|
|
||||||
{DeckFileArt, "deck_file_art", QT_TR_NOOP("Art crop of background.cod deck file")}};
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString toId(Type type)
|
|
||||||
{
|
|
||||||
for (const auto &e : all()) {
|
|
||||||
if (e.type == type)
|
|
||||||
return e.id;
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
static Type fromId(const QString &id)
|
|
||||||
{
|
|
||||||
for (const auto &e : all()) {
|
|
||||||
if (id == e.id)
|
|
||||||
return e.type;
|
|
||||||
}
|
|
||||||
return Theme; // default
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString toDisplay(Type type)
|
|
||||||
{
|
|
||||||
for (const auto &e : all()) {
|
|
||||||
if (e.type == type)
|
|
||||||
return QObject::tr(e.trKey);
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // COCKATRICE_BACKGROUND_SOURCES_H
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
#include "home_styled_button.h"
|
|
||||||
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QPainterPath>
|
|
||||||
#include <qgraphicseffect.h>
|
|
||||||
#include <qstyleoption.h>
|
|
||||||
|
|
||||||
HomeStyledButton::HomeStyledButton(const QString &text, QPair<QColor, QColor> _gradientColors, QWidget *parent)
|
|
||||||
: QPushButton(text, parent), gradientColors(_gradientColors)
|
|
||||||
{
|
|
||||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
|
||||||
setMinimumHeight(25);
|
|
||||||
setStyleSheet(generateButtonStylesheet(gradientColors));
|
|
||||||
}
|
|
||||||
|
|
||||||
void HomeStyledButton::updateStylesheet(const QPair<QColor, QColor> &colors)
|
|
||||||
{
|
|
||||||
gradientColors = colors;
|
|
||||||
setStyleSheet(generateButtonStylesheet(gradientColors));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString HomeStyledButton::generateButtonStylesheet(const QPair<QColor, QColor> &colors)
|
|
||||||
{
|
|
||||||
QColor baseGradientStart = colors.first;
|
|
||||||
QColor baseGradientEnd = colors.second;
|
|
||||||
|
|
||||||
QColor hoverGradientStart = baseGradientStart.lighter(120); // 20% lighter
|
|
||||||
QColor hoverGradientEnd = baseGradientEnd.lighter(120);
|
|
||||||
|
|
||||||
QColor pressedGradientStart = baseGradientStart.darker(130); // 30% darker
|
|
||||||
QColor pressedGradientEnd = baseGradientEnd.darker(130);
|
|
||||||
|
|
||||||
// Disabled: more gray, less saturated
|
|
||||||
QColor disabledGradientStart = baseGradientStart.toHsv();
|
|
||||||
disabledGradientStart.setHsv(disabledGradientStart.hue(), disabledGradientStart.saturation() * 0.2,
|
|
||||||
disabledGradientStart.value() * 0.6);
|
|
||||||
QColor disabledGradientEnd = baseGradientEnd.toHsv();
|
|
||||||
disabledGradientEnd.setHsv(disabledGradientEnd.hue(), disabledGradientEnd.saturation() * 0.2,
|
|
||||||
disabledGradientEnd.value() * 0.6);
|
|
||||||
|
|
||||||
return QString(R"(
|
|
||||||
QPushButton {
|
|
||||||
font-size: 34px;
|
|
||||||
font-weight: bold;
|
|
||||||
font-family: sans-serif, "Segoe UI", "Helvetica Neue";
|
|
||||||
padding: 30px;
|
|
||||||
color: white;
|
|
||||||
border: 2px solid %1;
|
|
||||||
border-radius: 20px;
|
|
||||||
background: qlineargradient(x1:0, y1:1, x2:0, y2:0,
|
|
||||||
stop:0 %2, stop:1 %3);
|
|
||||||
}
|
|
||||||
QPushButton:hover {
|
|
||||||
background: qlineargradient(x1:0, y1:1, x2:0, y2:0,
|
|
||||||
stop:0 %4, stop:1 %5);
|
|
||||||
}
|
|
||||||
QPushButton:pressed {
|
|
||||||
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
||||||
stop:0 %6, stop:1 %7);
|
|
||||||
}
|
|
||||||
QPushButton:disabled {
|
|
||||||
color: #aaaaaa;
|
|
||||||
border: 2px solid #888888;
|
|
||||||
background: qlineargradient(x1:0, y1:1, x2:0, y2:0,
|
|
||||||
stop:0 %8, stop:1 %9);
|
|
||||||
}
|
|
||||||
)")
|
|
||||||
.arg(baseGradientStart.name())
|
|
||||||
.arg(baseGradientStart.name())
|
|
||||||
.arg(baseGradientEnd.name())
|
|
||||||
.arg(hoverGradientStart.name())
|
|
||||||
.arg(hoverGradientEnd.name())
|
|
||||||
.arg(pressedGradientStart.name())
|
|
||||||
.arg(pressedGradientEnd.name())
|
|
||||||
.arg(disabledGradientStart.name())
|
|
||||||
.arg(disabledGradientEnd.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
void HomeStyledButton::paintEvent(QPaintEvent *event)
|
|
||||||
{
|
|
||||||
Q_UNUSED(event); // Event is just used for update clipping, we redraw the whole widget.
|
|
||||||
QStyleOptionButton opt;
|
|
||||||
initStyleOption(&opt);
|
|
||||||
opt.text.clear(); // prevent style from drawing text
|
|
||||||
|
|
||||||
QPainter painter(this);
|
|
||||||
style()->drawControl(QStyle::CE_PushButton, &opt, &painter, this);
|
|
||||||
|
|
||||||
// Draw white text with a black outline
|
|
||||||
painter.setRenderHint(QPainter::Antialiasing);
|
|
||||||
painter.setRenderHint(QPainter::TextAntialiasing);
|
|
||||||
|
|
||||||
QFontMetrics fm(font());
|
|
||||||
QSize textSize = fm.size(Qt::TextSingleLine, text());
|
|
||||||
QPointF center((width() - textSize.width()) / 2.0, (height() + textSize.height() / 2.0) / 2.0);
|
|
||||||
|
|
||||||
QPainterPath path;
|
|
||||||
path.addText(center, font(), text());
|
|
||||||
|
|
||||||
QPen pen(Qt::black, 4.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
|
|
||||||
painter.strokePath(path, pen);
|
|
||||||
painter.fillPath(path, Qt::white);
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
/**
|
|
||||||
* @file home_styled_button.h
|
|
||||||
* @ingroup Widgets
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HOME_STYLED_BUTTON_H
|
|
||||||
#define HOME_STYLED_BUTTON_H
|
|
||||||
#include <QPushButton>
|
|
||||||
|
|
||||||
class HomeStyledButton : public QPushButton
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
HomeStyledButton(const QString &text, QPair<QColor, QColor> gradientColors, QWidget *parent = nullptr);
|
|
||||||
void updateStylesheet(const QPair<QColor, QColor> &colors);
|
|
||||||
QString generateButtonStylesheet(const QPair<QColor, QColor> &colors);
|
|
||||||
public slots:
|
|
||||||
void paintEvent(QPaintEvent *event) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QPair<QColor, QColor> gradientColors;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // HOME_STYLED_BUTTON_H
|
|
||||||
|
|
@ -1,377 +0,0 @@
|
||||||
#include "home_widget.h"
|
|
||||||
|
|
||||||
#include "../../../client/settings/cache_settings.h"
|
|
||||||
#include "../../../interface/widgets/tabs/tab_supervisor.h"
|
|
||||||
#include "../../theme_manager.h"
|
|
||||||
#include "../../window_main.h"
|
|
||||||
#include "background_sources.h"
|
|
||||||
#include "home_styled_button.h"
|
|
||||||
|
|
||||||
#include <QGroupBox>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QPainterPath>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <libcockatrice/card/database/card_database_manager.h>
|
|
||||||
#include <libcockatrice/network/client/remote/remote_client.h>
|
|
||||||
|
|
||||||
HomeWidget::HomeWidget(QWidget *parent, TabSupervisor *_tabSupervisor)
|
|
||||||
: QWidget(parent), tabSupervisor(_tabSupervisor), background("theme:backgrounds/home"), overlay("theme:cockatrice")
|
|
||||||
{
|
|
||||||
layout = new QGridLayout(this);
|
|
||||||
|
|
||||||
backgroundSourceCard = new CardInfoPictureArtCropWidget(this);
|
|
||||||
|
|
||||||
gradientColors = extractDominantColors(background);
|
|
||||||
|
|
||||||
layout->addWidget(createButtons(), 1, 1, Qt::AlignVCenter | Qt::AlignHCenter);
|
|
||||||
|
|
||||||
layout->setRowStretch(0, 1);
|
|
||||||
layout->setRowStretch(2, 1);
|
|
||||||
layout->setColumnStretch(0, 1);
|
|
||||||
layout->setColumnStretch(2, 1);
|
|
||||||
|
|
||||||
setLayout(layout);
|
|
||||||
|
|
||||||
cardChangeTimer = new QTimer(this);
|
|
||||||
connect(cardChangeTimer, &QTimer::timeout, this, &HomeWidget::updateRandomCard);
|
|
||||||
|
|
||||||
initializeBackgroundFromSource();
|
|
||||||
|
|
||||||
updateConnectButton(tabSupervisor->getClient()->getStatus());
|
|
||||||
|
|
||||||
connect(tabSupervisor->getClient(), &RemoteClient::statusChanged, this, &HomeWidget::updateConnectButton);
|
|
||||||
connect(&SettingsCache::instance(), &SettingsCache::homeTabBackgroundSourceChanged, this,
|
|
||||||
&HomeWidget::initializeBackgroundFromSource);
|
|
||||||
connect(&SettingsCache::instance(), &SettingsCache::homeTabBackgroundShuffleFrequencyChanged, this,
|
|
||||||
&HomeWidget::onBackgroundShuffleFrequencyChanged);
|
|
||||||
// Lambda is cleaner to read than overloading this
|
|
||||||
connect(&SettingsCache::instance(), &SettingsCache::homeTabDisplayCardNameChanged, this, [this] { repaint(); });
|
|
||||||
connect(&SettingsCache::instance(), &SettingsCache::themeChanged, this,
|
|
||||||
&HomeWidget::initializeBackgroundFromSource);
|
|
||||||
connect(&SettingsCache::instance(), &SettingsCache::themeChanged, this,
|
|
||||||
&HomeWidget::updateButtonsToBackgroundColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HomeWidget::initializeBackgroundFromSource()
|
|
||||||
{
|
|
||||||
if (CardDatabaseManager::getInstance()->getLoadStatus() != LoadStatus::Ok) {
|
|
||||||
connect(CardDatabaseManager::getInstance(), &CardDatabase::cardDatabaseLoadingFinished, this,
|
|
||||||
&HomeWidget::initializeBackgroundFromSource);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto backgroundSourceType = BackgroundSources::fromId(SettingsCache::instance().getHomeTabBackgroundSource());
|
|
||||||
|
|
||||||
switch (backgroundSourceType) {
|
|
||||||
case BackgroundSources::Theme:
|
|
||||||
cardChangeTimer->stop();
|
|
||||||
background = QPixmap("theme:backgrounds/home");
|
|
||||||
backgroundSourceDeck = DeckList();
|
|
||||||
backgroundSourceCard->setCard(ExactCard());
|
|
||||||
updateButtonsToBackgroundColor();
|
|
||||||
update();
|
|
||||||
break;
|
|
||||||
case BackgroundSources::RandomCardArt:
|
|
||||||
backgroundSourceDeck = DeckList();
|
|
||||||
updateRandomCard();
|
|
||||||
onBackgroundShuffleFrequencyChanged();
|
|
||||||
break;
|
|
||||||
case BackgroundSources::DeckFileArt:
|
|
||||||
loadBackgroundSourceDeck();
|
|
||||||
updateRandomCard();
|
|
||||||
onBackgroundShuffleFrequencyChanged();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HomeWidget::loadBackgroundSourceDeck()
|
|
||||||
{
|
|
||||||
std::optional<LoadedDeck> deckOpt = DeckLoader::loadFromFile(
|
|
||||||
SettingsCache::instance().getDeckPath() + "background.cod", DeckFileFormat::Cockatrice, false);
|
|
||||||
backgroundSourceDeck = deckOpt.has_value() ? deckOpt.value().deckList : DeckList();
|
|
||||||
}
|
|
||||||
|
|
||||||
void HomeWidget::setRandomCard(ExactCard &newCard)
|
|
||||||
{
|
|
||||||
static constexpr int ATTEMPTS = 10;
|
|
||||||
for (int i = 0; i < ATTEMPTS; ++i) {
|
|
||||||
ExactCard tmpCard = CardDatabaseManager::query()->getRandomCard();
|
|
||||||
if (tmpCard != backgroundSourceCard->getCard() && tmpCard.getCardPtr()->getProperty("layout") == "normal" &&
|
|
||||||
tmpCard.getPrinting().getSet() != nullptr) {
|
|
||||||
newCard = tmpCard;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
qWarning() << "failed to set random card image after" << ATTEMPTS << "attempts";
|
|
||||||
}
|
|
||||||
|
|
||||||
void HomeWidget::updateRandomCard()
|
|
||||||
{
|
|
||||||
auto backgroundSourceType = BackgroundSources::fromId(SettingsCache::instance().getHomeTabBackgroundSource());
|
|
||||||
|
|
||||||
ExactCard newCard;
|
|
||||||
|
|
||||||
switch (backgroundSourceType) {
|
|
||||||
case BackgroundSources::Theme:
|
|
||||||
break;
|
|
||||||
case BackgroundSources::RandomCardArt:
|
|
||||||
setRandomCard(newCard);
|
|
||||||
break;
|
|
||||||
case BackgroundSources::DeckFileArt:
|
|
||||||
QList<CardRef> cardRefs = backgroundSourceDeck.getCardRefList();
|
|
||||||
ExactCard oldCard = backgroundSourceCard->getCard();
|
|
||||||
|
|
||||||
if (!cardRefs.empty()) {
|
|
||||||
if (cardRefs.size() == 1) {
|
|
||||||
newCard = CardDatabaseManager::query()->getCard(cardRefs.first());
|
|
||||||
} else {
|
|
||||||
// Keep picking until different
|
|
||||||
do {
|
|
||||||
int idx = QRandomGenerator::global()->bounded(cardRefs.size());
|
|
||||||
newCard = CardDatabaseManager::query()->getCard(cardRefs.at(idx));
|
|
||||||
} while (newCard == oldCard);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
do {
|
|
||||||
newCard = CardDatabaseManager::query()->getRandomCard();
|
|
||||||
} while (newCard == oldCard);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!newCard)
|
|
||||||
return;
|
|
||||||
|
|
||||||
connect(newCard.getCardPtr().data(), &CardInfo::pixmapUpdated, this, &HomeWidget::updateBackgroundProperties);
|
|
||||||
backgroundSourceCard->setCard(newCard);
|
|
||||||
background = backgroundSourceCard->getBackground();
|
|
||||||
}
|
|
||||||
|
|
||||||
void HomeWidget::onBackgroundShuffleFrequencyChanged()
|
|
||||||
{
|
|
||||||
cardChangeTimer->stop();
|
|
||||||
if (SettingsCache::instance().getHomeTabBackgroundShuffleFrequency() > 0) {
|
|
||||||
cardChangeTimer->start(SettingsCache::instance().getHomeTabBackgroundShuffleFrequency() * 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HomeWidget::updateBackgroundProperties()
|
|
||||||
{
|
|
||||||
background = backgroundSourceCard->getBackground();
|
|
||||||
updateButtonsToBackgroundColor();
|
|
||||||
update(); // Triggers repaint
|
|
||||||
}
|
|
||||||
|
|
||||||
void HomeWidget::updateButtonsToBackgroundColor()
|
|
||||||
{
|
|
||||||
gradientColors = extractDominantColors(background);
|
|
||||||
for (HomeStyledButton *button : findChildren<HomeStyledButton *>()) {
|
|
||||||
button->updateStylesheet(gradientColors);
|
|
||||||
button->update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QGroupBox *HomeWidget::createButtons()
|
|
||||||
{
|
|
||||||
QGroupBox *box = new QGroupBox(this);
|
|
||||||
box->setStyleSheet(R"(
|
|
||||||
QGroupBox {
|
|
||||||
font-size: 20px;
|
|
||||||
color: white; /* Title text color */
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
QGroupBox::title {
|
|
||||||
color: white;
|
|
||||||
subcontrol-origin: margin;
|
|
||||||
subcontrol-position: top center; /* or top left / right */
|
|
||||||
}
|
|
||||||
)");
|
|
||||||
box->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
|
||||||
QVBoxLayout *boxLayout = new QVBoxLayout;
|
|
||||||
boxLayout->setAlignment(Qt::AlignHCenter);
|
|
||||||
|
|
||||||
QLabel *logoLabel = new QLabel;
|
|
||||||
logoLabel->setPixmap(overlay.scaledToWidth(200, Qt::SmoothTransformation));
|
|
||||||
logoLabel->setAlignment(Qt::AlignCenter);
|
|
||||||
boxLayout->addWidget(logoLabel);
|
|
||||||
boxLayout->addSpacing(25);
|
|
||||||
|
|
||||||
connectButton = new HomeStyledButton("Connect/Play", gradientColors);
|
|
||||||
boxLayout->addWidget(connectButton);
|
|
||||||
|
|
||||||
auto visualDeckEditorButton = new HomeStyledButton(tr("Create New Deck"), gradientColors);
|
|
||||||
connect(visualDeckEditorButton, &QPushButton::clicked, tabSupervisor,
|
|
||||||
[this] { tabSupervisor->openDeckInNewTab(LoadedDeck()); });
|
|
||||||
boxLayout->addWidget(visualDeckEditorButton);
|
|
||||||
auto visualDeckStorageButton = new HomeStyledButton(tr("Browse Decks"), gradientColors);
|
|
||||||
connect(visualDeckStorageButton, &QPushButton::clicked, tabSupervisor,
|
|
||||||
[this] { tabSupervisor->actTabVisualDeckStorage(true); });
|
|
||||||
boxLayout->addWidget(visualDeckStorageButton);
|
|
||||||
auto visualDatabaseDisplayButton = new HomeStyledButton(tr("Browse Card Database"), gradientColors);
|
|
||||||
connect(visualDatabaseDisplayButton, &QPushButton::clicked, tabSupervisor,
|
|
||||||
&TabSupervisor::addVisualDatabaseDisplayTab);
|
|
||||||
boxLayout->addWidget(visualDatabaseDisplayButton);
|
|
||||||
auto edhrecButton = new HomeStyledButton(tr("Browse EDHRec"), gradientColors);
|
|
||||||
connect(edhrecButton, &QPushButton::clicked, tabSupervisor, &TabSupervisor::addEdhrecMainTab);
|
|
||||||
boxLayout->addWidget(edhrecButton);
|
|
||||||
auto archidektButton = new HomeStyledButton(tr("Browse Archidekt"), gradientColors);
|
|
||||||
connect(archidektButton, &QPushButton::clicked, tabSupervisor, &TabSupervisor::addArchidektTab);
|
|
||||||
boxLayout->addWidget(archidektButton);
|
|
||||||
auto replaybutton = new HomeStyledButton(tr("View Replays"), gradientColors);
|
|
||||||
connect(replaybutton, &QPushButton::clicked, tabSupervisor, [this] { tabSupervisor->actTabReplays(true); });
|
|
||||||
boxLayout->addWidget(replaybutton);
|
|
||||||
if (qobject_cast<MainWindow *>(tabSupervisor->parentWidget())) {
|
|
||||||
auto exitButton = new HomeStyledButton(tr("Quit"), gradientColors);
|
|
||||||
connect(exitButton, &QPushButton::clicked, qobject_cast<MainWindow *>(tabSupervisor->parentWidget()),
|
|
||||||
&MainWindow::actExit);
|
|
||||||
boxLayout->addWidget(exitButton);
|
|
||||||
}
|
|
||||||
|
|
||||||
box->setLayout(boxLayout);
|
|
||||||
return box;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HomeWidget::updateConnectButton(const ClientStatus status)
|
|
||||||
{
|
|
||||||
disconnect(connectButton, &QPushButton::clicked, nullptr, nullptr);
|
|
||||||
switch (status) {
|
|
||||||
case StatusConnecting:
|
|
||||||
connectButton->setText(tr("Connecting..."));
|
|
||||||
connectButton->setEnabled(false);
|
|
||||||
break;
|
|
||||||
case StatusDisconnected:
|
|
||||||
connectButton->setText(tr("Connect"));
|
|
||||||
connectButton->setEnabled(true);
|
|
||||||
connect(connectButton, &QPushButton::clicked, qobject_cast<MainWindow *>(tabSupervisor->parentWidget()),
|
|
||||||
&MainWindow::actConnect);
|
|
||||||
break;
|
|
||||||
case StatusLoggedIn:
|
|
||||||
connectButton->setText(tr("Play"));
|
|
||||||
connectButton->setEnabled(true);
|
|
||||||
connect(connectButton, &QPushButton::clicked, tabSupervisor,
|
|
||||||
&TabSupervisor::switchToFirstAvailableNetworkTab);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QPair<QColor, QColor> HomeWidget::extractDominantColors(const QPixmap &pixmap)
|
|
||||||
{
|
|
||||||
if (themeManager->isBuiltInTheme() &&
|
|
||||||
SettingsCache::instance().getHomeTabBackgroundSource() == BackgroundSources::toId(BackgroundSources::Theme)) {
|
|
||||||
return QPair<QColor, QColor>(QColor::fromRgb(20, 140, 60), QColor::fromRgb(120, 200, 80));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 1: Downscale image for performance
|
|
||||||
QImage image = pixmap.toImage()
|
|
||||||
.scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation)
|
|
||||||
.convertToFormat(QImage::Format_RGB32);
|
|
||||||
|
|
||||||
QMap<QRgb, int> colorCount;
|
|
||||||
|
|
||||||
// Step 2: Count quantized colors
|
|
||||||
for (int y = 0; y < image.height(); ++y) {
|
|
||||||
const QRgb *scanLine = reinterpret_cast<const QRgb *>(image.scanLine(y));
|
|
||||||
for (int x = 0; x < image.width(); ++x) {
|
|
||||||
QColor color = QColor::fromRgb(scanLine[x]);
|
|
||||||
|
|
||||||
int r = color.red() & 0xF0;
|
|
||||||
int g = color.green() & 0xF0;
|
|
||||||
int b = color.blue() & 0xF0;
|
|
||||||
|
|
||||||
QRgb quantized = qRgb(r, g, b);
|
|
||||||
colorCount[quantized]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 3: Sort by frequency
|
|
||||||
QVector<QPair<QRgb, int>> sortedColors;
|
|
||||||
for (auto it = colorCount.constBegin(); it != colorCount.constEnd(); ++it) {
|
|
||||||
sortedColors.append(qMakePair(it.key(), it.value()));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::sort(sortedColors.begin(), sortedColors.end(),
|
|
||||||
[](const QPair<QRgb, int> &a, const QPair<QRgb, int> &b) { return a.second > b.second; });
|
|
||||||
|
|
||||||
// Step 4: Pick top two distinct colors
|
|
||||||
QColor first = QColor(sortedColors.value(0).first);
|
|
||||||
QColor second = first;
|
|
||||||
|
|
||||||
for (int i = 1; i < sortedColors.size(); ++i) {
|
|
||||||
QColor candidate = QColor(sortedColors[i].first);
|
|
||||||
if (candidate != first) {
|
|
||||||
second = candidate;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return QPair<QColor, QColor>(first, second);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HomeWidget::paintEvent(QPaintEvent *event)
|
|
||||||
{
|
|
||||||
QPainter painter(this);
|
|
||||||
painter.setRenderHint(QPainter::Antialiasing);
|
|
||||||
|
|
||||||
if (!background.isNull()) {
|
|
||||||
QSize widgetSize = size() * devicePixelRatio();
|
|
||||||
QPixmap toDraw = background.scaled(widgetSize, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
|
|
||||||
|
|
||||||
// Draw scaled background centered
|
|
||||||
QSize bgSize = toDraw.size();
|
|
||||||
QPoint topLeft((widgetSize.width() - bgSize.width()) / (devicePixelRatio() * 2), // undo scaling for painter
|
|
||||||
(widgetSize.height() - bgSize.height()) / (devicePixelRatio() * 2));
|
|
||||||
|
|
||||||
painter.drawPixmap(topLeft, toDraw);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw translucent black overlay with rounded corners
|
|
||||||
QRectF overlayRect(5, 5, width() - 10, height() - 10);
|
|
||||||
QPainterPath roundedRectPath;
|
|
||||||
roundedRectPath.addRoundedRect(overlayRect, 20, 20);
|
|
||||||
|
|
||||||
QColor semiTransparentBlack(0, 0, 0, static_cast<int>(255 * 0.33));
|
|
||||||
painter.fillPath(roundedRectPath, semiTransparentBlack);
|
|
||||||
|
|
||||||
// Card name overlay (bottom-right)
|
|
||||||
QString cardName;
|
|
||||||
ExactCard card = backgroundSourceCard->getCard();
|
|
||||||
if (card) {
|
|
||||||
cardName = card.getCardPtr()->getName();
|
|
||||||
if (card.getPrinting().getSet() != nullptr) {
|
|
||||||
cardName += " (" + card.getPrinting().getSet()->getCorrectedShortName() + ") " +
|
|
||||||
card.getPrinting().getProperty("num");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cardName.isEmpty() && SettingsCache::instance().getHomeTabDisplayCardName()) {
|
|
||||||
QFont font = painter.font();
|
|
||||||
font.setPointSize(14);
|
|
||||||
font.setBold(true);
|
|
||||||
painter.setFont(font);
|
|
||||||
|
|
||||||
QFontMetrics fm(font);
|
|
||||||
constexpr int padding = 10;
|
|
||||||
constexpr int margin = 15;
|
|
||||||
|
|
||||||
QRect textRect = fm.boundingRect(cardName);
|
|
||||||
|
|
||||||
QRect bgRect(width() - textRect.width() - padding * 2 - margin,
|
|
||||||
height() - textRect.height() - padding * 2 - margin, textRect.width() + padding * 2,
|
|
||||||
textRect.height() + padding * 2);
|
|
||||||
|
|
||||||
// Background bubble
|
|
||||||
painter.setPen(Qt::NoPen);
|
|
||||||
painter.setBrush(QColor(0, 0, 0, 160));
|
|
||||||
painter.drawRoundedRect(bgRect, 8, 8);
|
|
||||||
|
|
||||||
// Text
|
|
||||||
painter.setPen(Qt::white);
|
|
||||||
painter.drawText(bgRect.adjusted(padding, padding, -padding, -padding), Qt::AlignRight | Qt::AlignVCenter,
|
|
||||||
cardName);
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget::paintEvent(event);
|
|
||||||
}
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
/**
|
|
||||||
* @file home_widget.h
|
|
||||||
* @ingroup Core
|
|
||||||
* @ingroup Widgets
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HOME_WIDGET_H
|
|
||||||
#define HOME_WIDGET_H
|
|
||||||
#include "../../../interface/widgets/tabs/tab_supervisor.h"
|
|
||||||
#include "../cards/card_info_picture_art_crop_widget.h"
|
|
||||||
#include "home_styled_button.h"
|
|
||||||
|
|
||||||
#include <QGridLayout>
|
|
||||||
#include <QWidget>
|
|
||||||
#include <libcockatrice/network/client/abstract/abstract_client.h>
|
|
||||||
|
|
||||||
class HomeWidget : public QWidget
|
|
||||||
{
|
|
||||||
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
HomeWidget(QWidget *parent, TabSupervisor *tabSupervisor);
|
|
||||||
void updateRandomCard();
|
|
||||||
QPair<QColor, QColor> extractDominantColors(const QPixmap &pixmap);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void paintEvent(QPaintEvent *event) override;
|
|
||||||
void initializeBackgroundFromSource();
|
|
||||||
void onBackgroundShuffleFrequencyChanged();
|
|
||||||
void updateBackgroundProperties();
|
|
||||||
void updateButtonsToBackgroundColor();
|
|
||||||
QGroupBox *createButtons();
|
|
||||||
void updateConnectButton(const ClientStatus status);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QGridLayout *layout;
|
|
||||||
QTimer *cardChangeTimer;
|
|
||||||
TabSupervisor *tabSupervisor;
|
|
||||||
QPixmap background;
|
|
||||||
CardInfoPictureArtCropWidget *backgroundSourceCard = nullptr;
|
|
||||||
DeckList backgroundSourceDeck;
|
|
||||||
QPixmap overlay;
|
|
||||||
QPair<QColor, QColor> gradientColors;
|
|
||||||
HomeStyledButton *connectButton;
|
|
||||||
|
|
||||||
void setRandomCard(ExactCard &newCard);
|
|
||||||
void loadBackgroundSourceDeck();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // HOME_WIDGET_H
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include "printing_selector_card_overlay_widget.h"
|
#include "printing_selector_card_overlay_widget.h"
|
||||||
|
|
||||||
#include "../../../client/settings/cache_settings.h"
|
#include "../../../client/settings/cache_settings.h"
|
||||||
|
#include "../cards/card_info_picture_widget.h"
|
||||||
#include "printing_selector_card_display_widget.h"
|
#include "printing_selector_card_display_widget.h"
|
||||||
|
|
||||||
#include <QImageReader>
|
#include <QImageReader>
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@
|
||||||
#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 "../../deck_loader/deck_loader.h"
|
||||||
|
#include "../../deck_loader/loaded_deck.h"
|
||||||
#include "../interface/widgets/deck_editor/deck_editor_card_database_dock_widget.h"
|
#include "../interface/widgets/deck_editor/deck_editor_card_database_dock_widget.h"
|
||||||
#include "../interface/widgets/deck_editor/deck_editor_card_info_dock_widget.h"
|
#include "../interface/widgets/deck_editor/deck_editor_card_info_dock_widget.h"
|
||||||
#include "../interface/widgets/deck_editor/deck_editor_database_display_widget.h"
|
#include "../interface/widgets/deck_editor/deck_editor_database_display_widget.h"
|
||||||
|
|
@ -15,7 +17,6 @@
|
||||||
#include "../interface/widgets/deck_editor/deck_editor_filter_dock_widget.h"
|
#include "../interface/widgets/deck_editor/deck_editor_filter_dock_widget.h"
|
||||||
#include "../interface/widgets/deck_editor/deck_editor_printing_selector_dock_widget.h"
|
#include "../interface/widgets/deck_editor/deck_editor_printing_selector_dock_widget.h"
|
||||||
#include "../interface/widgets/menus/deck_editor_menu.h"
|
#include "../interface/widgets/menus/deck_editor_menu.h"
|
||||||
#include "../interface/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h"
|
|
||||||
#include "tab.h"
|
#include "tab.h"
|
||||||
|
|
||||||
#include <libcockatrice/deck_list/deck_list_history_manager.h>
|
#include <libcockatrice/deck_list/deck_list_history_manager.h>
|
||||||
|
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
#include "archidekt_deck_listing_api_response.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QJsonArray>
|
|
||||||
|
|
||||||
void ArchidektDeckListingApiResponse::fromJson(const QJsonObject &json)
|
|
||||||
{
|
|
||||||
count = json.value("count").toInt();
|
|
||||||
next = QUrl(json.value("next").toString());
|
|
||||||
|
|
||||||
QJsonArray containerJson = json.value("results").toArray();
|
|
||||||
|
|
||||||
for (const QJsonValue &deckListingValue : containerJson) {
|
|
||||||
ArchidektApiResponseDeckListingContainer listingResult;
|
|
||||||
listingResult.fromJson(deckListingValue.toObject());
|
|
||||||
results.append(listingResult);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektDeckListingApiResponse::debugPrint() const
|
|
||||||
{
|
|
||||||
qDebug() << "Count:" << count;
|
|
||||||
qDebug() << "Next:" << next;
|
|
||||||
|
|
||||||
qDebug() << "Results:";
|
|
||||||
for (const auto &deckListing : results) {
|
|
||||||
deckListing.debugPrint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#ifndef COCKATRICE_ARCHIDEKT_DECK_LISTING_API_RESPONSE_H
|
|
||||||
#define COCKATRICE_ARCHIDEKT_DECK_LISTING_API_RESPONSE_H
|
|
||||||
|
|
||||||
#include "deck_listings/archidekt_api_response_deck_listing_container.h"
|
|
||||||
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QString>
|
|
||||||
#include <QUrl>
|
|
||||||
|
|
||||||
class ArchidektDeckListingApiResponse
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
int count;
|
|
||||||
QUrl next;
|
|
||||||
QVector<ArchidektApiResponseDeckListingContainer> results;
|
|
||||||
|
|
||||||
void fromJson(const QJsonObject &json);
|
|
||||||
void debugPrint() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // COCKATRICE_DECK_LISTING_API_RESPONSE_H
|
|
||||||
|
|
@ -1,227 +0,0 @@
|
||||||
#ifndef COCKATRICE_ARCHIDEKT_FORMATS_H
|
|
||||||
#define COCKATRICE_ARCHIDEKT_FORMATS_H
|
|
||||||
#include <QHash>
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
namespace ArchidektFormats
|
|
||||||
{
|
|
||||||
enum class DeckFormat
|
|
||||||
{
|
|
||||||
Standard = 0,
|
|
||||||
Modern = 1,
|
|
||||||
Commander = 2,
|
|
||||||
Legacy = 3,
|
|
||||||
Vintage = 4,
|
|
||||||
Pauper = 5,
|
|
||||||
Custom = 6,
|
|
||||||
Frontier = 7,
|
|
||||||
FutureStandard = 8,
|
|
||||||
PennyDreadful = 9,
|
|
||||||
Commander1v1 = 10,
|
|
||||||
DualCommander = 11,
|
|
||||||
Brawl = 12,
|
|
||||||
|
|
||||||
// Values outside Archidekt range
|
|
||||||
Alchemy = 1000,
|
|
||||||
Historic = 1001,
|
|
||||||
Gladiator = 1002,
|
|
||||||
Oathbreaker = 1003,
|
|
||||||
OldSchool = 1004,
|
|
||||||
PauperCommander = 1005,
|
|
||||||
Pioneer = 1006,
|
|
||||||
PreDH = 1007,
|
|
||||||
Premodern = 1008,
|
|
||||||
StandardBrawl = 1009,
|
|
||||||
Timeless = 1010,
|
|
||||||
Unknown = 1011
|
|
||||||
};
|
|
||||||
|
|
||||||
inline static QString formatToApiName(DeckFormat format)
|
|
||||||
{
|
|
||||||
switch (format) {
|
|
||||||
case DeckFormat::Standard:
|
|
||||||
return "Standard";
|
|
||||||
case DeckFormat::Modern:
|
|
||||||
return "Modern";
|
|
||||||
case DeckFormat::Commander:
|
|
||||||
return "Commander";
|
|
||||||
case DeckFormat::Legacy:
|
|
||||||
return "Legacy";
|
|
||||||
case DeckFormat::Vintage:
|
|
||||||
return "Vintage";
|
|
||||||
case DeckFormat::Pauper:
|
|
||||||
return "Pauper";
|
|
||||||
case DeckFormat::Custom:
|
|
||||||
return "Custom";
|
|
||||||
case DeckFormat::Frontier:
|
|
||||||
return "Frontier";
|
|
||||||
case DeckFormat::FutureStandard:
|
|
||||||
return "Future Std";
|
|
||||||
case DeckFormat::PennyDreadful:
|
|
||||||
return "Penny Dreadful";
|
|
||||||
case DeckFormat::Commander1v1:
|
|
||||||
return "1v1 Commander";
|
|
||||||
case DeckFormat::DualCommander:
|
|
||||||
return "Dual Commander";
|
|
||||||
case DeckFormat::Brawl:
|
|
||||||
return "Brawl";
|
|
||||||
|
|
||||||
case DeckFormat::Alchemy:
|
|
||||||
return "Alchemy";
|
|
||||||
case DeckFormat::Historic:
|
|
||||||
return "Historic";
|
|
||||||
case DeckFormat::Gladiator:
|
|
||||||
return "Gladiator";
|
|
||||||
case DeckFormat::Oathbreaker:
|
|
||||||
return "Oathbreaker";
|
|
||||||
case DeckFormat::OldSchool:
|
|
||||||
return "Old School";
|
|
||||||
case DeckFormat::PauperCommander:
|
|
||||||
return "Pauper Commander";
|
|
||||||
case DeckFormat::Pioneer:
|
|
||||||
return "Pioneer";
|
|
||||||
case DeckFormat::PreDH:
|
|
||||||
return "PreDH";
|
|
||||||
case DeckFormat::Premodern:
|
|
||||||
return "Premodern";
|
|
||||||
case DeckFormat::StandardBrawl:
|
|
||||||
return "Standard Brawl";
|
|
||||||
case DeckFormat::Timeless:
|
|
||||||
return "Timeless";
|
|
||||||
|
|
||||||
default:
|
|
||||||
return "Unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static DeckFormat apiNameToFormat(const QString &name)
|
|
||||||
{
|
|
||||||
const QString n = name.trimmed();
|
|
||||||
|
|
||||||
if (n.compare("Standard", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::Standard;
|
|
||||||
if (n.compare("Modern", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::Modern;
|
|
||||||
if (n.compare("Commander", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::Commander;
|
|
||||||
if (n.compare("Legacy", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::Legacy;
|
|
||||||
if (n.compare("Vintage", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::Vintage;
|
|
||||||
if (n.compare("Pauper", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::Pauper;
|
|
||||||
if (n.compare("Custom", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::Custom;
|
|
||||||
if (n.compare("Frontier", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::Frontier;
|
|
||||||
if (n.compare("Future Std", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::FutureStandard;
|
|
||||||
if (n.compare("Penny Dreadful", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::PennyDreadful;
|
|
||||||
if (n.compare("1v1 Commander", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::Commander1v1;
|
|
||||||
if (n.compare("Dual Commander", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::DualCommander;
|
|
||||||
if (n.compare("Brawl", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::Brawl;
|
|
||||||
|
|
||||||
if (n.compare("Alchemy", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::Alchemy;
|
|
||||||
if (n.compare("Historic", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::Historic;
|
|
||||||
if (n.compare("Gladiator", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::Gladiator;
|
|
||||||
if (n.compare("Oathbreaker", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::Oathbreaker;
|
|
||||||
if (n.compare("Old School", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::OldSchool;
|
|
||||||
if (n.compare("Pauper Commander", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::PauperCommander;
|
|
||||||
if (n.compare("Pioneer", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::Pioneer;
|
|
||||||
if (n.compare("PreDH", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::PreDH;
|
|
||||||
if (n.compare("Premodern", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::Premodern;
|
|
||||||
if (n.compare("Standard Brawl", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::StandardBrawl;
|
|
||||||
if (n.compare("Timeless", Qt::CaseInsensitive) == 0)
|
|
||||||
return DeckFormat::Timeless;
|
|
||||||
|
|
||||||
return DeckFormat::Unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static QString formatToCockatriceName(DeckFormat format)
|
|
||||||
{
|
|
||||||
switch (format) {
|
|
||||||
case DeckFormat::Standard:
|
|
||||||
return "standard";
|
|
||||||
case DeckFormat::Modern:
|
|
||||||
return "modern";
|
|
||||||
case DeckFormat::Commander:
|
|
||||||
return "commander";
|
|
||||||
case DeckFormat::Legacy:
|
|
||||||
return "legacy";
|
|
||||||
case DeckFormat::Vintage:
|
|
||||||
return "vintage";
|
|
||||||
case DeckFormat::Pauper:
|
|
||||||
return "pauper";
|
|
||||||
case DeckFormat::Brawl:
|
|
||||||
return "brawl";
|
|
||||||
case DeckFormat::PennyDreadful:
|
|
||||||
return "penny";
|
|
||||||
case DeckFormat::FutureStandard:
|
|
||||||
return "future";
|
|
||||||
case DeckFormat::Commander1v1:
|
|
||||||
return "duel";
|
|
||||||
case DeckFormat::DualCommander:
|
|
||||||
return "duel";
|
|
||||||
case DeckFormat::Alchemy:
|
|
||||||
return "alchemy";
|
|
||||||
case DeckFormat::Historic:
|
|
||||||
return "historic";
|
|
||||||
case DeckFormat::Gladiator:
|
|
||||||
return "gladiator";
|
|
||||||
case DeckFormat::Oathbreaker:
|
|
||||||
return "oathbreaker";
|
|
||||||
case DeckFormat::OldSchool:
|
|
||||||
return "oldschool";
|
|
||||||
case DeckFormat::PauperCommander:
|
|
||||||
return "paupercommander";
|
|
||||||
case DeckFormat::Pioneer:
|
|
||||||
return "pioneer";
|
|
||||||
case DeckFormat::PreDH:
|
|
||||||
return "predh";
|
|
||||||
case DeckFormat::Premodern:
|
|
||||||
return "premodern";
|
|
||||||
case DeckFormat::StandardBrawl:
|
|
||||||
return "standardbrawl";
|
|
||||||
case DeckFormat::Timeless:
|
|
||||||
return "timeless";
|
|
||||||
|
|
||||||
default:
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static DeckFormat cockatriceNameToFormat(const QString &apiName)
|
|
||||||
{
|
|
||||||
static const QHash<QString, DeckFormat> map = {
|
|
||||||
{"standard", DeckFormat::Standard}, {"modern", DeckFormat::Modern},
|
|
||||||
{"commander", DeckFormat::Commander}, {"legacy", DeckFormat::Legacy},
|
|
||||||
{"vintage", DeckFormat::Vintage}, {"pauper", DeckFormat::Pauper},
|
|
||||||
{"brawl", DeckFormat::Brawl}, {"penny", DeckFormat::PennyDreadful},
|
|
||||||
{"future", DeckFormat::FutureStandard}, {"duel", DeckFormat::Commander1v1},
|
|
||||||
{"alchemy", DeckFormat::Alchemy}, {"historic", DeckFormat::Historic},
|
|
||||||
{"gladiator", DeckFormat::Gladiator}, {"oathbreaker", DeckFormat::Oathbreaker},
|
|
||||||
{"oldschool", DeckFormat::OldSchool}, {"paupercommander", DeckFormat::PauperCommander},
|
|
||||||
{"pioneer", DeckFormat::Pioneer}, {"predh", DeckFormat::PreDH},
|
|
||||||
{"premodern", DeckFormat::Premodern}, {"standardbrawl", DeckFormat::StandardBrawl},
|
|
||||||
{"timeless", DeckFormat::Timeless}};
|
|
||||||
|
|
||||||
return map.value(apiName.toLower(), DeckFormat::Unknown);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ArchidektFormats
|
|
||||||
|
|
||||||
#endif // COCKATRICE_ARCHIDEKT_FORMATS_H
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
#include "archidekt_api_response_card.h"
|
|
||||||
|
|
||||||
void ArchidektApiResponseCard::fromJson(const QJsonObject &json)
|
|
||||||
{
|
|
||||||
id = json.value("id").toInt();
|
|
||||||
artist = json.value("artist").toString();
|
|
||||||
tcgProductId = json.value("tcgProductId").toInt();
|
|
||||||
ckFoilId = json.value("ckFoilId").toInt();
|
|
||||||
ckNormalId = json.value("ckNormalId").toInt();
|
|
||||||
cmEd = json.value("cmEd").toString();
|
|
||||||
scgSku = json.value("scgSku").toString();
|
|
||||||
scgFoilSku = json.value("scgFoilSku").toString();
|
|
||||||
collectorNumber = json.value("collectorNumber").toString();
|
|
||||||
multiverseId = json.value("multiverseId").toInt();
|
|
||||||
mtgoFoilId = json.value("mtgoFoilId").toInt();
|
|
||||||
mtgoNormalId = json.value("mtgoNormalId").toInt();
|
|
||||||
uid = json.value("uid").toString();
|
|
||||||
displayName = json.value("displayName").toString();
|
|
||||||
releasedAt = json.value("releasedAt").toString();
|
|
||||||
|
|
||||||
edition.fromJson(json.value("edition").toObject());
|
|
||||||
|
|
||||||
flavor = json.value("flavor").toString();
|
|
||||||
//! \todo but not really important
|
|
||||||
//! \todo games = {""};
|
|
||||||
//! \todo options = {""};
|
|
||||||
scryfallImageHash = json.value("scryfallImageHash").toString();
|
|
||||||
oracleCard = json.value("oracleCard").toObject();
|
|
||||||
owned = json.value("owned").toInt();
|
|
||||||
pinnedStatus = json.value("pinnedStatus").toInt();
|
|
||||||
rarity = json.value("rarity").toString();
|
|
||||||
//! \todo but not really important
|
|
||||||
//! \todo globalCategories = {""};
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseCard::debugPrint() const
|
|
||||||
{
|
|
||||||
qDebug() << "Id:" << id;
|
|
||||||
qDebug() << "id:" << artist;
|
|
||||||
qDebug() << "artist:" << tcgProductId;
|
|
||||||
qDebug() << "tcgProductId:" << ckFoilId;
|
|
||||||
qDebug() << "ckFoilId:" << ckNormalId;
|
|
||||||
qDebug() << "ckNormalId:" << cmEd;
|
|
||||||
qDebug() << "cmEd:" << scgSku;
|
|
||||||
qDebug() << "scgSku:" << scgFoilSku;
|
|
||||||
qDebug() << "scgFoilSku:" << collectorNumber;
|
|
||||||
qDebug() << "collectorNumber:" << multiverseId;
|
|
||||||
qDebug() << "multiverseId:" << mtgoFoilId;
|
|
||||||
qDebug() << "mtgoFoilId:" << mtgoNormalId;
|
|
||||||
qDebug() << "mtgoNormalId:" << uid;
|
|
||||||
qDebug() << "uid:" << displayName;
|
|
||||||
qDebug() << "displayName:" << releasedAt;
|
|
||||||
qDebug() << "releasedAt:" << flavor;
|
|
||||||
qDebug() << "flavor:" << games;
|
|
||||||
qDebug() << "games:" << options;
|
|
||||||
qDebug() << "options:" << scryfallImageHash;
|
|
||||||
qDebug() << "scryfallImageHash:" << owned;
|
|
||||||
qDebug() << "owned:" << pinnedStatus;
|
|
||||||
qDebug() << "pinnedStatus:" << rarity;
|
|
||||||
qDebug() << "rarity:" << globalCategories;
|
|
||||||
}
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
#ifndef COCKATRICE_ARCHIDEKT_API_RESPONSE_CARD_H
|
|
||||||
#define COCKATRICE_ARCHIDEKT_API_RESPONSE_CARD_H
|
|
||||||
|
|
||||||
#include "archidekt_api_response_edition.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QString>
|
|
||||||
#include <QVector>
|
|
||||||
|
|
||||||
class ArchidektApiResponseCard
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Constructor
|
|
||||||
ArchidektApiResponseCard() = default;
|
|
||||||
|
|
||||||
// Parse deck-related data from JSON
|
|
||||||
void fromJson(const QJsonObject &json);
|
|
||||||
|
|
||||||
// Debug method for logging
|
|
||||||
void debugPrint() const;
|
|
||||||
|
|
||||||
QJsonObject getOracleCard() const
|
|
||||||
{
|
|
||||||
return oracleCard;
|
|
||||||
};
|
|
||||||
|
|
||||||
QString getCollectorNumber() const
|
|
||||||
{
|
|
||||||
return collectorNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
ArchidektApiResponseEdition getEdition() const
|
|
||||||
{
|
|
||||||
return edition;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int id;
|
|
||||||
QString artist;
|
|
||||||
int tcgProductId;
|
|
||||||
int ckFoilId;
|
|
||||||
int ckNormalId;
|
|
||||||
QString cmEd;
|
|
||||||
QString scgSku;
|
|
||||||
QString scgFoilSku;
|
|
||||||
QString collectorNumber;
|
|
||||||
int multiverseId;
|
|
||||||
int mtgoFoilId;
|
|
||||||
int mtgoNormalId;
|
|
||||||
QString uid;
|
|
||||||
QString displayName;
|
|
||||||
QString releasedAt;
|
|
||||||
ArchidektApiResponseEdition edition;
|
|
||||||
QString flavor;
|
|
||||||
QStringList games;
|
|
||||||
QStringList options;
|
|
||||||
QString scryfallImageHash;
|
|
||||||
QJsonObject oracleCard;
|
|
||||||
int owned;
|
|
||||||
int pinnedStatus;
|
|
||||||
// ArchidektApiResponsePrices prices;
|
|
||||||
QString rarity;
|
|
||||||
QStringList globalCategories;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // COCKATRICE_ARCHIDEKT_API_RESPONSE_CARD_H
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
#include "archidekt_api_response_card_entry.h"
|
|
||||||
|
|
||||||
void ArchidektApiResponseCardEntry::fromJson(const QJsonObject &json)
|
|
||||||
{
|
|
||||||
id = json.value("id").toInt();
|
|
||||||
|
|
||||||
categories.clear();
|
|
||||||
|
|
||||||
auto categoriesJson = json.value("categories").toArray();
|
|
||||||
|
|
||||||
for (const auto &categoryValue : categoriesJson) {
|
|
||||||
Category cat;
|
|
||||||
|
|
||||||
if (categoryValue.isObject()) {
|
|
||||||
QJsonObject obj = categoryValue.toObject();
|
|
||||||
|
|
||||||
cat.id = obj.value("id").toInt();
|
|
||||||
cat.name = obj.value("name").toString();
|
|
||||||
cat.isPremier = obj.value("isPremier").toBool();
|
|
||||||
cat.includedInDeck = obj.value("includedInDeck").toBool();
|
|
||||||
cat.includedInPrice = obj.value("includedInPrice").toBool();
|
|
||||||
} else if (categoryValue.isString()) {
|
|
||||||
cat.name = categoryValue.toString();
|
|
||||||
|
|
||||||
// assume mainboard unless known otherwise
|
|
||||||
cat.includedInDeck = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
categories.append(cat);
|
|
||||||
}
|
|
||||||
|
|
||||||
companion = json.value("companion").toBool();
|
|
||||||
flippedDefault = json.value("flippedDefault").toBool();
|
|
||||||
label = json.value("label").toString();
|
|
||||||
modifier = json.value("modifier").toString();
|
|
||||||
quantity = json.value("quantity").toInt();
|
|
||||||
customCmc = json.value("customCmc").toInt();
|
|
||||||
// removedCategories = {""};
|
|
||||||
createdAt = json.value("createdAt").toString();
|
|
||||||
updatedAt = json.value("updatedAt").toString();
|
|
||||||
deletedAt = json.value("deletedAt").toString();
|
|
||||||
notes = json.value("notes").toString();
|
|
||||||
card.fromJson(json.value("card").toObject());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseCardEntry::debugPrint() const
|
|
||||||
{
|
|
||||||
qDebug() << "Id:" << id;
|
|
||||||
for (auto category : categories) {
|
|
||||||
qDebug() << "Category ID:" << category.id;
|
|
||||||
qDebug() << "Category Name:" << category.name;
|
|
||||||
qDebug() << "Category Premier:" << category.isPremier;
|
|
||||||
qDebug() << "Category Included in Deck:" << category.includedInDeck;
|
|
||||||
qDebug() << "Category Included in Price:" << category.includedInPrice;
|
|
||||||
}
|
|
||||||
qDebug() << "Companion:" << companion;
|
|
||||||
qDebug() << "FlippedDefault:" << flippedDefault;
|
|
||||||
qDebug() << "Label:" << label;
|
|
||||||
qDebug() << "Modifier:" << modifier;
|
|
||||||
qDebug() << "Quantity:" << quantity;
|
|
||||||
qDebug() << "CustomCmc:" << customCmc;
|
|
||||||
qDebug() << "RemovedCategories:" << removedCategories;
|
|
||||||
qDebug() << "CreatedAt:" << createdAt;
|
|
||||||
qDebug() << "UpdatedAt:" << updatedAt;
|
|
||||||
qDebug() << "DeletedAt:" << deletedAt;
|
|
||||||
qDebug() << "Notes:" << notes;
|
|
||||||
card.debugPrint();
|
|
||||||
}
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
#ifndef COCKATRICE_ARCHIDEKT_API_RESPONSE_CARD_ENTRY_H
|
|
||||||
#define COCKATRICE_ARCHIDEKT_API_RESPONSE_CARD_ENTRY_H
|
|
||||||
|
|
||||||
#include "archidekt_api_response_card.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QString>
|
|
||||||
#include <QVector>
|
|
||||||
|
|
||||||
struct Category
|
|
||||||
{
|
|
||||||
int id;
|
|
||||||
QString name;
|
|
||||||
bool isPremier;
|
|
||||||
bool includedInDeck;
|
|
||||||
bool includedInPrice;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ArchidektApiResponseCardEntry
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Constructor
|
|
||||||
ArchidektApiResponseCardEntry() = default;
|
|
||||||
|
|
||||||
// Parse deck-related data from JSON
|
|
||||||
void fromJson(const QJsonObject &json);
|
|
||||||
|
|
||||||
// Debug method for logging
|
|
||||||
void debugPrint() const;
|
|
||||||
|
|
||||||
ArchidektApiResponseCard getCard() const
|
|
||||||
{
|
|
||||||
return card;
|
|
||||||
};
|
|
||||||
|
|
||||||
QList<Category> getCategories() const
|
|
||||||
{
|
|
||||||
return categories;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getQuantity() const
|
|
||||||
{
|
|
||||||
return quantity;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int id;
|
|
||||||
QList<Category> categories;
|
|
||||||
bool companion;
|
|
||||||
bool flippedDefault;
|
|
||||||
QString label;
|
|
||||||
QString modifier;
|
|
||||||
int quantity;
|
|
||||||
int customCmc;
|
|
||||||
QStringList removedCategories;
|
|
||||||
QString createdAt;
|
|
||||||
QString updatedAt;
|
|
||||||
QString deletedAt;
|
|
||||||
QString notes;
|
|
||||||
ArchidektApiResponseCard card;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // COCKATRICE_ARCHIDEKT_API_RESPONSE_CARD_ENTRY_H
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
#include "archidekt_api_response_edition.h"
|
|
||||||
|
|
||||||
void ArchidektApiResponseEdition::fromJson(const QJsonObject &json)
|
|
||||||
{
|
|
||||||
editionCode = json.value("editioncode").toString();
|
|
||||||
editionName = json.value("editionname").toString();
|
|
||||||
editionDate = json.value("editiondate").toString();
|
|
||||||
editionType = json.value("editiontype").toString();
|
|
||||||
mtgoCode = json.value("mtgocode").toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseEdition::debugPrint() const
|
|
||||||
{
|
|
||||||
qDebug() << "Edition Code: " << editionCode;
|
|
||||||
qDebug() << "Edition Name: " << editionName;
|
|
||||||
qDebug() << "Edition Date: " << editionDate;
|
|
||||||
qDebug() << "Edition Type: " << editionType;
|
|
||||||
qDebug() << "Mtgo Code: " << mtgoCode;
|
|
||||||
}
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
#ifndef COCKATRICE_ARCHIDEKT_API_RESPONSE_EDITION_H
|
|
||||||
#define COCKATRICE_ARCHIDEKT_API_RESPONSE_EDITION_H
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QString>
|
|
||||||
#include <QVector>
|
|
||||||
|
|
||||||
class ArchidektApiResponseEdition
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Constructor
|
|
||||||
ArchidektApiResponseEdition() = default;
|
|
||||||
|
|
||||||
// Parse deck-related data from JSON
|
|
||||||
void fromJson(const QJsonObject &json);
|
|
||||||
|
|
||||||
// Debug method for logging
|
|
||||||
void debugPrint() const;
|
|
||||||
|
|
||||||
[[nodiscard]] QString getEditionCode() const
|
|
||||||
{
|
|
||||||
return editionCode;
|
|
||||||
}
|
|
||||||
[[nodiscard]] QString getEditionName() const
|
|
||||||
{
|
|
||||||
return editionName;
|
|
||||||
}
|
|
||||||
[[nodiscard]] QString getEditionDate() const
|
|
||||||
{
|
|
||||||
return editionDate;
|
|
||||||
}
|
|
||||||
[[nodiscard]] QString getEditionType() const
|
|
||||||
{
|
|
||||||
return editionType;
|
|
||||||
}
|
|
||||||
[[nodiscard]] QString getMtgoCode() const
|
|
||||||
{
|
|
||||||
return mtgoCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString editionCode;
|
|
||||||
QString editionName;
|
|
||||||
QString editionDate;
|
|
||||||
QString editionType;
|
|
||||||
QString mtgoCode;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // COCKATRICE_ARCHIDEKT_API_RESPONSE_EDITION_H
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
||||||
#include "archidekt_api_response_deck.h"
|
|
||||||
|
|
||||||
#include "../card/archidekt_api_response_card_entry.h"
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeck::fromJson(const QJsonObject &json)
|
|
||||||
{
|
|
||||||
id = json.value("id").toInt();
|
|
||||||
name = json.value("name").toString();
|
|
||||||
size = json.value("size").toInt();
|
|
||||||
updatedAt = json.value("updatedAt").toString();
|
|
||||||
createdAt = json.value("createdAt").toString();
|
|
||||||
deckFormat = json.value("deckFormat").toInt();
|
|
||||||
edhBracket = json.value("edhBracket").toInt();
|
|
||||||
featured = json.value("featured").toString();
|
|
||||||
customFeatured = json.value("customFeatured").toString();
|
|
||||||
viewCount = json.value("viewCount").toInt();
|
|
||||||
privateDeck = json.value("private").toBool();
|
|
||||||
unlisted = json.value("unlisted").toBool();
|
|
||||||
theoryCrafted = json.value("theoryCrafted").toBool();
|
|
||||||
points = json.value("points").toInt();
|
|
||||||
userInput = json.value("userInput").toInt();
|
|
||||||
owner.fromJson(json.value("owner").toObject());
|
|
||||||
commentRoot = json.value("commentRoot").toInt();
|
|
||||||
editors = json.value("editors").toString();
|
|
||||||
parentFolderId = json.value("parentFolderId").toInt();
|
|
||||||
bookmarked = json.value("bookmarked").toBool();
|
|
||||||
|
|
||||||
auto categoriesJson = json.value("categories").toArray();
|
|
||||||
for (auto category : categoriesJson) {
|
|
||||||
ArchidektApiResponseDeckCategory categoryEntry;
|
|
||||||
categoryEntry.fromJson(category.toObject());
|
|
||||||
categories.append(categoryEntry);
|
|
||||||
}
|
|
||||||
|
|
||||||
// deckTags = {""};
|
|
||||||
playgroupDeckUrl = json.value("playgroupDeckUrl").toString();
|
|
||||||
cardPackage = json.value("cardPackage").toString();
|
|
||||||
|
|
||||||
auto cardsObject = json.value("cards").toArray();
|
|
||||||
|
|
||||||
for (auto card : cardsObject) {
|
|
||||||
ArchidektApiResponseCardEntry entry;
|
|
||||||
entry.fromJson(card.toObject());
|
|
||||||
cards.append(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO but not really important
|
|
||||||
// customCards = {""};
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeck::debugPrint() const
|
|
||||||
{
|
|
||||||
qDebug() << "Id:" << id;
|
|
||||||
qDebug() << "Name:" << name;
|
|
||||||
qDebug() << "Size:" << size;
|
|
||||||
qDebug() << "UpdatedAt:" << updatedAt;
|
|
||||||
qDebug() << "CreatedAt:" << createdAt;
|
|
||||||
qDebug() << "DeckFormat:" << deckFormat;
|
|
||||||
qDebug() << "EdhBracket:" << edhBracket;
|
|
||||||
qDebug() << "Featured:" << featured;
|
|
||||||
qDebug() << "CustomFeatured:" << customFeatured;
|
|
||||||
qDebug() << "ViewCount:" << viewCount;
|
|
||||||
qDebug() << "Private:" << privateDeck;
|
|
||||||
qDebug() << "Unlisted:" << unlisted;
|
|
||||||
qDebug() << "TheoryCrafted:" << theoryCrafted;
|
|
||||||
qDebug() << "Points:" << points;
|
|
||||||
qDebug() << "UserInput:" << userInput;
|
|
||||||
owner.debugPrint();
|
|
||||||
qDebug() << "CommentRoot:" << commentRoot;
|
|
||||||
qDebug() << "Editors:" << editors;
|
|
||||||
qDebug() << "ParentFolderId:" << parentFolderId;
|
|
||||||
qDebug() << "Bookmarked:" << bookmarked;
|
|
||||||
qDebug() << "DeckTags:" << deckTags;
|
|
||||||
qDebug() << "PlaygroupDeckUrl:" << playgroupDeckUrl;
|
|
||||||
qDebug() << "CardPackage:" << cardPackage;
|
|
||||||
for (auto card : cards) {
|
|
||||||
card.debugPrint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
#ifndef COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_H
|
|
||||||
#define COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_H
|
|
||||||
|
|
||||||
#include "../card/archidekt_api_response_card.h"
|
|
||||||
#include "../card/archidekt_api_response_card_entry.h"
|
|
||||||
#include "../deck_listings/archidekt_api_response_deck_owner.h"
|
|
||||||
#include "archidekt_api_response_deck_category.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QString>
|
|
||||||
#include <QVector>
|
|
||||||
|
|
||||||
class ArchidektApiResponseDeck
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Constructor
|
|
||||||
ArchidektApiResponseDeck() = default;
|
|
||||||
|
|
||||||
// Parse deck-related data from JSON
|
|
||||||
void fromJson(const QJsonObject &json);
|
|
||||||
|
|
||||||
// Debug method for logging
|
|
||||||
void debugPrint() const;
|
|
||||||
|
|
||||||
QVector<ArchidektApiResponseCardEntry> getCards() const
|
|
||||||
{
|
|
||||||
return cards;
|
|
||||||
};
|
|
||||||
|
|
||||||
QVector<ArchidektApiResponseDeckCategory> getCategories() const
|
|
||||||
{
|
|
||||||
return categories;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString getDeckName() const
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
};
|
|
||||||
|
|
||||||
int getDeckFormat() const
|
|
||||||
{
|
|
||||||
return deckFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int id;
|
|
||||||
QString name;
|
|
||||||
int size;
|
|
||||||
QString updatedAt;
|
|
||||||
QString createdAt;
|
|
||||||
int deckFormat;
|
|
||||||
int edhBracket;
|
|
||||||
QString featured;
|
|
||||||
QString customFeatured;
|
|
||||||
int viewCount;
|
|
||||||
bool privateDeck;
|
|
||||||
bool unlisted;
|
|
||||||
bool theoryCrafted;
|
|
||||||
int points;
|
|
||||||
int userInput;
|
|
||||||
ArchidektApiResponseDeckOwner owner;
|
|
||||||
int commentRoot;
|
|
||||||
QString editors;
|
|
||||||
int parentFolderId;
|
|
||||||
bool bookmarked;
|
|
||||||
QVector<ArchidektApiResponseDeckCategory> categories;
|
|
||||||
QStringList deckTags;
|
|
||||||
QString playgroupDeckUrl;
|
|
||||||
QString cardPackage;
|
|
||||||
QVector<ArchidektApiResponseCardEntry> cards;
|
|
||||||
QStringList customCards;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_H
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
#include "archidekt_api_response_deck_category.h"
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckCategory::fromJson(const QJsonObject &json)
|
|
||||||
{
|
|
||||||
id = json.value("id").toInt();
|
|
||||||
name = json.value("name").toString();
|
|
||||||
isPremier = json.value("isPremier").toBool();
|
|
||||||
includedInDeck = json.value("includedInDeck").toBool();
|
|
||||||
includedInPrice = json.value("includedInPrice").toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckCategory::debugPrint() const
|
|
||||||
{
|
|
||||||
qDebug() << "Id:" << id;
|
|
||||||
qDebug() << "Name:" << name;
|
|
||||||
qDebug() << "isPremier:" << isPremier;
|
|
||||||
qDebug() << "IncludedInDeck:" << includedInDeck;
|
|
||||||
qDebug() << "IncludedInPrice:" << includedInPrice;
|
|
||||||
}
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
#ifndef COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_CATEGORY_H
|
|
||||||
#define COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_CATEGORY_H
|
|
||||||
|
|
||||||
#include "../card/archidekt_api_response_card.h"
|
|
||||||
#include "../card/archidekt_api_response_card_entry.h"
|
|
||||||
#include "../deck_listings/archidekt_api_response_deck_owner.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QString>
|
|
||||||
#include <QVector>
|
|
||||||
|
|
||||||
class ArchidektApiResponseDeckCategory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Constructor
|
|
||||||
ArchidektApiResponseDeckCategory() = default;
|
|
||||||
|
|
||||||
// Parse deck-related data from JSON
|
|
||||||
void fromJson(const QJsonObject &json);
|
|
||||||
|
|
||||||
// Debug method for logging
|
|
||||||
void debugPrint() const;
|
|
||||||
|
|
||||||
[[nodiscard]] int getId() const
|
|
||||||
{
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
[[nodiscard]] QString getName() const
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
[[nodiscard]] bool getIsPremier() const
|
|
||||||
{
|
|
||||||
return isPremier;
|
|
||||||
}
|
|
||||||
[[nodiscard]] bool getIncludedInDeck() const
|
|
||||||
{
|
|
||||||
return includedInDeck;
|
|
||||||
}
|
|
||||||
[[nodiscard]] bool getIncludedInPrice() const
|
|
||||||
{
|
|
||||||
return includedInPrice;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int id;
|
|
||||||
QString name;
|
|
||||||
bool isPremier;
|
|
||||||
bool includedInDeck;
|
|
||||||
bool includedInPrice;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_CATEGORY_H
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
#include "archidekt_api_response_deck_listing_container.h"
|
|
||||||
|
|
||||||
#include "archidekt_api_response_deck_owner.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QJsonObject>
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckListingContainer::fromJson(const QJsonObject &json)
|
|
||||||
{
|
|
||||||
id = json.value("id").toInt();
|
|
||||||
name = json.value("name").toString();
|
|
||||||
size = json.value("size").toInt();
|
|
||||||
updatedAt = json.value("updatedAt").toString();
|
|
||||||
createdAt = json.value("createdAt").toString();
|
|
||||||
deckFormat = json.value("deckFormat").toInt();
|
|
||||||
edhBracket = json.value("edhBracket").toInt();
|
|
||||||
featured = json.value("featured").toString();
|
|
||||||
customFeatured = json.value("customFeatured").toString();
|
|
||||||
viewCount = json.value("viewCount").toInt();
|
|
||||||
privateDeck = json.value("private").toBool();
|
|
||||||
unlisted = json.value("unlisted").toBool();
|
|
||||||
theoryCrafted = json.value("theoryCrafted").toBool();
|
|
||||||
game = json.value("game").toString();
|
|
||||||
hasDescription = json.value("hasDescription").toBool();
|
|
||||||
// TODO
|
|
||||||
// tags = {""};
|
|
||||||
parentFolderId = json.value("parentFolderId").toInt();
|
|
||||||
owner.fromJson(json.value("owner").toObject());
|
|
||||||
|
|
||||||
auto colorsJson = json.value("colors").toObject();
|
|
||||||
|
|
||||||
for (auto color : colorsJson.keys()) {
|
|
||||||
colors[color] = colorsJson[color].toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
cardPackage = json.value("cardPackage").toString();
|
|
||||||
contest = json.value("contest").toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckListingContainer::debugPrint() const
|
|
||||||
{
|
|
||||||
qDebug() << "Id:" << id;
|
|
||||||
qDebug() << "Name:" << name;
|
|
||||||
qDebug() << "Size:" << size;
|
|
||||||
qDebug() << "UpdatedAt:" << updatedAt;
|
|
||||||
qDebug() << "CreatedAt:" << createdAt;
|
|
||||||
qDebug() << "DeckFormat:" << deckFormat;
|
|
||||||
qDebug() << "EdhBracket:" << edhBracket;
|
|
||||||
qDebug() << "Featured:" << featured;
|
|
||||||
qDebug() << "CustomFeatured:" << customFeatured;
|
|
||||||
qDebug() << "ViewCount:" << viewCount;
|
|
||||||
qDebug() << "Private:" << privateDeck;
|
|
||||||
qDebug() << "Unlisted:" << unlisted;
|
|
||||||
qDebug() << "TheoryCrafted:" << theoryCrafted;
|
|
||||||
qDebug() << "Game:" << game;
|
|
||||||
qDebug() << "HasDescription:" << hasDescription;
|
|
||||||
qDebug() << "Tags:" << tags;
|
|
||||||
qDebug() << "ParentFolderId:" << parentFolderId;
|
|
||||||
owner.debugPrint();
|
|
||||||
qDebug() << "Colors:" << colors;
|
|
||||||
qDebug() << "CardPackage" << cardPackage;
|
|
||||||
qDebug() << "Contest:" << contest;
|
|
||||||
}
|
|
||||||
|
|
@ -1,133 +0,0 @@
|
||||||
#ifndef COCKATRICE_ARCHIDEKT_DECK_LISTING_API_RESPONSE_CONTAINER_H
|
|
||||||
#define COCKATRICE_ARCHIDEKT_DECK_LISTING_API_RESPONSE_CONTAINER_H
|
|
||||||
|
|
||||||
#include "archidekt_api_response_deck_owner.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QString>
|
|
||||||
#include <QVector>
|
|
||||||
|
|
||||||
class ArchidektApiResponseDeckListingContainer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Constructor
|
|
||||||
ArchidektApiResponseDeckListingContainer() = default;
|
|
||||||
|
|
||||||
// Parse deck-related data from JSON
|
|
||||||
void fromJson(const QJsonObject &json);
|
|
||||||
|
|
||||||
// Debug method for logging
|
|
||||||
void debugPrint() const;
|
|
||||||
|
|
||||||
[[nodiscard]] int getId() const
|
|
||||||
{
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
[[nodiscard]] QString getName() const
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
[[nodiscard]] int getSize() const
|
|
||||||
{
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
[[nodiscard]] QString getUpdatedAt() const
|
|
||||||
{
|
|
||||||
return updatedAt;
|
|
||||||
}
|
|
||||||
[[nodiscard]] QString getCreatedAt() const
|
|
||||||
{
|
|
||||||
return createdAt;
|
|
||||||
}
|
|
||||||
[[nodiscard]] int getDeckFormat() const
|
|
||||||
{
|
|
||||||
return deckFormat;
|
|
||||||
}
|
|
||||||
[[nodiscard]] int getEDHBracket() const
|
|
||||||
{
|
|
||||||
return edhBracket;
|
|
||||||
}
|
|
||||||
[[nodiscard]] QString getFeatured() const
|
|
||||||
{
|
|
||||||
return featured;
|
|
||||||
}
|
|
||||||
[[nodiscard]] QString getCustomFeatured() const
|
|
||||||
{
|
|
||||||
return customFeatured;
|
|
||||||
}
|
|
||||||
[[nodiscard]] int getViewCount() const
|
|
||||||
{
|
|
||||||
return viewCount;
|
|
||||||
}
|
|
||||||
[[nodiscard]] bool getPrivateDeck() const
|
|
||||||
{
|
|
||||||
return privateDeck;
|
|
||||||
}
|
|
||||||
[[nodiscard]] bool getUnlisted() const
|
|
||||||
{
|
|
||||||
return unlisted;
|
|
||||||
}
|
|
||||||
[[nodiscard]] bool getTheoryCrafted() const
|
|
||||||
{
|
|
||||||
return theoryCrafted;
|
|
||||||
}
|
|
||||||
[[nodiscard]] QString getGame() const
|
|
||||||
{
|
|
||||||
return game;
|
|
||||||
}
|
|
||||||
[[nodiscard]] bool getHasDescription() const
|
|
||||||
{
|
|
||||||
return hasDescription;
|
|
||||||
}
|
|
||||||
[[nodiscard]] QStringList getTags() const
|
|
||||||
{
|
|
||||||
return tags;
|
|
||||||
}
|
|
||||||
[[nodiscard]] int getParentFolderId() const
|
|
||||||
{
|
|
||||||
return parentFolderId;
|
|
||||||
}
|
|
||||||
[[nodiscard]] ArchidektApiResponseDeckOwner getOwner() const
|
|
||||||
{
|
|
||||||
return owner;
|
|
||||||
}
|
|
||||||
[[nodiscard]] QMap<QString, int> getColors() const
|
|
||||||
{
|
|
||||||
return colors;
|
|
||||||
}
|
|
||||||
[[nodiscard]] QString getCardPackage() const
|
|
||||||
{
|
|
||||||
return cardPackage;
|
|
||||||
}
|
|
||||||
[[nodiscard]] QString getContest() const
|
|
||||||
{
|
|
||||||
return contest;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int id;
|
|
||||||
QString name;
|
|
||||||
int size;
|
|
||||||
QString updatedAt;
|
|
||||||
QString createdAt;
|
|
||||||
int deckFormat;
|
|
||||||
int edhBracket;
|
|
||||||
QString featured;
|
|
||||||
QString customFeatured;
|
|
||||||
int viewCount;
|
|
||||||
bool privateDeck;
|
|
||||||
bool unlisted;
|
|
||||||
bool theoryCrafted;
|
|
||||||
QString game;
|
|
||||||
bool hasDescription;
|
|
||||||
QStringList tags;
|
|
||||||
int parentFolderId;
|
|
||||||
ArchidektApiResponseDeckOwner owner;
|
|
||||||
QMap<QString, int> colors;
|
|
||||||
QString cardPackage;
|
|
||||||
QString contest;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // COCKATRICE_ARCHIDEKT_DECK_LISTING_API_RESPONSE_CONTAINER_H
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#include "archidekt_api_response_deck_owner.h"
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckOwner::fromJson(const QJsonObject &json)
|
|
||||||
{
|
|
||||||
id = json.value("id").toInt();
|
|
||||||
userName = json.value("username").toString();
|
|
||||||
avatar = QUrl(json.value("avatar").toString());
|
|
||||||
moderator = json.value("moderator").toBool();
|
|
||||||
pledgeLevel = json.value("pledgeLevel").toInt();
|
|
||||||
// TODO but not really important
|
|
||||||
// roles = {""};
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckOwner::debugPrint() const
|
|
||||||
{
|
|
||||||
qDebug() << "Id:" << id;
|
|
||||||
qDebug() << "UserName:" << userName;
|
|
||||||
qDebug() << "Avatar:" << avatar;
|
|
||||||
qDebug() << "Moderator:" << moderator;
|
|
||||||
qDebug() << "PledgeLevel:" << pledgeLevel;
|
|
||||||
qDebug() << "Roles:" << roles;
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
#ifndef COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_OWNER_H
|
|
||||||
#define COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_OWNER_H
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QString>
|
|
||||||
#include <QVector>
|
|
||||||
|
|
||||||
class ArchidektApiResponseDeckOwner
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Constructor
|
|
||||||
ArchidektApiResponseDeckOwner() = default;
|
|
||||||
|
|
||||||
// Parse deck-related data from JSON
|
|
||||||
void fromJson(const QJsonObject &json);
|
|
||||||
|
|
||||||
// Debug method for logging
|
|
||||||
void debugPrint() const;
|
|
||||||
|
|
||||||
[[nodiscard]] QString getName() const
|
|
||||||
{
|
|
||||||
return userName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int id;
|
|
||||||
QString userName;
|
|
||||||
QUrl avatar;
|
|
||||||
bool moderator;
|
|
||||||
int pledgeLevel;
|
|
||||||
QStringList roles;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_OWNER_H
|
|
||||||
|
|
@ -1,218 +0,0 @@
|
||||||
#include "archidekt_api_response_deck_display_widget.h"
|
|
||||||
|
|
||||||
#include "../../../../../deck_loader/card_node_function.h"
|
|
||||||
#include "../../../../../deck_loader/deck_loader.h"
|
|
||||||
#include "../../../../cards/card_size_widget.h"
|
|
||||||
#include "../../../../cards/deck_card_zone_display_widget.h"
|
|
||||||
#include "../../../../visual_deck_editor/visual_deck_display_options_widget.h"
|
|
||||||
#include "../api_response/archidekt_formats.h"
|
|
||||||
#include "../api_response/deck/archidekt_api_response_deck.h"
|
|
||||||
|
|
||||||
#include <QSortFilterProxyModel>
|
|
||||||
#include <libcockatrice/card/import/card_name_normalizer.h>
|
|
||||||
|
|
||||||
ArchidektApiResponseDeckDisplayWidget::ArchidektApiResponseDeckDisplayWidget(QWidget *parent,
|
|
||||||
ArchidektApiResponseDeck _response,
|
|
||||||
CardSizeWidget *_cardSizeSlider)
|
|
||||||
: QWidget(parent), response(_response), cardSizeSlider(_cardSizeSlider)
|
|
||||||
{
|
|
||||||
layout = new QVBoxLayout(this);
|
|
||||||
setLayout(layout);
|
|
||||||
|
|
||||||
navigationContainer = new QWidget(this);
|
|
||||||
navigationContainerLayout = new QHBoxLayout(navigationContainer);
|
|
||||||
|
|
||||||
homeButton = new QPushButton(navigationContainer);
|
|
||||||
navigationContainerLayout->addWidget(homeButton);
|
|
||||||
|
|
||||||
connect(homeButton, &QPushButton::clicked, this, &ArchidektApiResponseDeckDisplayWidget::requestSearch);
|
|
||||||
|
|
||||||
openInEditorButton = new QPushButton(navigationContainer);
|
|
||||||
navigationContainerLayout->addWidget(openInEditorButton);
|
|
||||||
|
|
||||||
connect(openInEditorButton, &QPushButton::clicked, this,
|
|
||||||
&ArchidektApiResponseDeckDisplayWidget::actOpenInDeckEditor);
|
|
||||||
|
|
||||||
layout->addWidget(navigationContainer);
|
|
||||||
|
|
||||||
displayOptionsWidget = new VisualDeckDisplayOptionsWidget(this);
|
|
||||||
layout->addWidget(displayOptionsWidget);
|
|
||||||
|
|
||||||
connect(displayOptionsWidget, &VisualDeckDisplayOptionsWidget::groupCriteriaChanged, this,
|
|
||||||
&ArchidektApiResponseDeckDisplayWidget::onGroupCriteriaChange);
|
|
||||||
|
|
||||||
scrollArea = new QScrollArea(this);
|
|
||||||
scrollArea->setWidgetResizable(true);
|
|
||||||
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
||||||
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
|
||||||
|
|
||||||
layout->addWidget(scrollArea);
|
|
||||||
|
|
||||||
container = new QWidget(scrollArea);
|
|
||||||
|
|
||||||
scrollArea->setWidget(container);
|
|
||||||
|
|
||||||
containerLayout = new QVBoxLayout(container);
|
|
||||||
container->setLayout(containerLayout);
|
|
||||||
|
|
||||||
zoneContainer = new QWidget(container);
|
|
||||||
containerLayout->addWidget(zoneContainer);
|
|
||||||
zoneContainerLayout = new QVBoxLayout(zoneContainer);
|
|
||||||
zoneContainer->setLayout(zoneContainerLayout);
|
|
||||||
|
|
||||||
QString tempDeck;
|
|
||||||
QTextStream deckStream(&tempDeck);
|
|
||||||
|
|
||||||
QString mainboardText;
|
|
||||||
QString sideboardText;
|
|
||||||
|
|
||||||
QTextStream mainStream(&mainboardText);
|
|
||||||
QTextStream sideStream(&sideboardText);
|
|
||||||
|
|
||||||
for (const auto &card : response.getCards()) {
|
|
||||||
QString fullName = card.getCard().getOracleCard().value("name").toString();
|
|
||||||
// We don't really care about the second card, the card database already has it as a relation
|
|
||||||
QString cleanName = fullName.split("//").first().trimmed();
|
|
||||||
|
|
||||||
QString line = QString("%1 %2 (%3) %4\n")
|
|
||||||
.arg(card.getQuantity())
|
|
||||||
.arg(cleanName)
|
|
||||||
.arg(card.getCard().getEdition().getEditionCode().toUpper())
|
|
||||||
.arg(card.getCard().getCollectorNumber());
|
|
||||||
|
|
||||||
bool isCommander = false;
|
|
||||||
bool isSideboardCategory = false;
|
|
||||||
bool includedInDeck = false;
|
|
||||||
|
|
||||||
for (const auto &cat : card.getCategories()) {
|
|
||||||
|
|
||||||
if (cat.name.compare("Commander", Qt::CaseInsensitive) == 0) {
|
|
||||||
isCommander = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cat.name.compare("Sideboard", Qt::CaseInsensitive) == 0 ||
|
|
||||||
cat.name.compare("Maybeboard", Qt::CaseInsensitive) == 0) {
|
|
||||||
isSideboardCategory = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cat.includedInDeck) {
|
|
||||||
includedInDeck = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString target;
|
|
||||||
|
|
||||||
if (isCommander || isSideboardCategory) {
|
|
||||||
sideStream << line;
|
|
||||||
} else if (includedInDeck) {
|
|
||||||
mainStream << line;
|
|
||||||
} else {
|
|
||||||
sideStream << line;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Combine with blank line separator
|
|
||||||
tempDeck = mainboardText;
|
|
||||||
|
|
||||||
if (!sideboardText.isEmpty()) {
|
|
||||||
tempDeck += "\n";
|
|
||||||
tempDeck += sideboardText;
|
|
||||||
}
|
|
||||||
|
|
||||||
model = new DeckListModel(this);
|
|
||||||
connect(model, &DeckListModel::modelReset, this, &ArchidektApiResponseDeckDisplayWidget::decklistModelReset);
|
|
||||||
|
|
||||||
auto decklist = QSharedPointer<DeckList>(new DeckList);
|
|
||||||
decklist->loadFromStream_Plain(deckStream, false, CardNameNormalizer());
|
|
||||||
model->setDeckList(decklist);
|
|
||||||
|
|
||||||
model->forEachCard(CardNodeFunction::ResolveProviderId());
|
|
||||||
|
|
||||||
retranslateUi();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckDisplayWidget::retranslateUi()
|
|
||||||
{
|
|
||||||
homeButton->setText(tr("Back to results"));
|
|
||||||
openInEditorButton->setText(tr("Open Deck in Deck Editor"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckDisplayWidget::onGroupCriteriaChange(const QString &activeGroupCriteria)
|
|
||||||
{
|
|
||||||
model->setActiveGroupCriteria(DeckListModelGroupCriteria::fromString(activeGroupCriteria));
|
|
||||||
model->sort(DeckListModelColumns::CARD_NAME, Qt::AscendingOrder);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckDisplayWidget::actOpenInDeckEditor()
|
|
||||||
{
|
|
||||||
DeckList deckList(*model->getDeckList());
|
|
||||||
deckList.setName(response.getDeckName());
|
|
||||||
deckList.setGameFormat(
|
|
||||||
ArchidektFormats::formatToCockatriceName(ArchidektFormats::DeckFormat(response.getDeckFormat() - 1)));
|
|
||||||
|
|
||||||
LoadedDeck loadedDeck = {deckList, {}};
|
|
||||||
|
|
||||||
emit openInDeckEditor(loadedDeck);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckDisplayWidget::clearAllDisplayWidgets()
|
|
||||||
{
|
|
||||||
for (auto idx : indexToWidgetMap.keys()) {
|
|
||||||
auto displayWidget = indexToWidgetMap.value(idx);
|
|
||||||
zoneContainerLayout->removeWidget(displayWidget);
|
|
||||||
indexToWidgetMap.remove(idx);
|
|
||||||
delete displayWidget;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckDisplayWidget::decklistModelReset()
|
|
||||||
{
|
|
||||||
clearAllDisplayWidgets();
|
|
||||||
constructZoneWidgetsFromDeckListModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckDisplayWidget::constructZoneWidgetsFromDeckListModel()
|
|
||||||
{
|
|
||||||
qDebug() << model->rowCount(model->getRoot());
|
|
||||||
QSortFilterProxyModel proxy;
|
|
||||||
proxy.setSourceModel(model);
|
|
||||||
proxy.setSortRole(Qt::EditRole);
|
|
||||||
proxy.sort(DeckListModelColumns::CARD_NAME, Qt::AscendingOrder);
|
|
||||||
|
|
||||||
for (int i = 0; i < proxy.rowCount(); ++i) {
|
|
||||||
QModelIndex proxyIndex = proxy.index(i, 0);
|
|
||||||
QModelIndex sourceIndex = proxy.mapToSource(proxyIndex);
|
|
||||||
|
|
||||||
// Make a persistent index from the *source* model
|
|
||||||
QPersistentModelIndex persistent(sourceIndex);
|
|
||||||
|
|
||||||
if (indexToWidgetMap.contains(persistent)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString zoneName =
|
|
||||||
persistent.sibling(persistent.row(), DeckListModelColumns::CARD_NAME).data(Qt::EditRole).toString();
|
|
||||||
|
|
||||||
DeckCardZoneDisplayWidget *zoneDisplayWidget =
|
|
||||||
new DeckCardZoneDisplayWidget(zoneContainer, model, nullptr, persistent, zoneName, "maintype", {"name"},
|
|
||||||
DisplayType::Overlap, 20, 10, cardSizeSlider);
|
|
||||||
|
|
||||||
connect(displayOptionsWidget, &VisualDeckDisplayOptionsWidget::sortCriteriaChanged, zoneDisplayWidget,
|
|
||||||
&DeckCardZoneDisplayWidget::onActiveSortCriteriaChanged);
|
|
||||||
connect(displayOptionsWidget, &VisualDeckDisplayOptionsWidget::groupCriteriaChanged, zoneDisplayWidget,
|
|
||||||
&DeckCardZoneDisplayWidget::onActiveGroupCriteriaChanged);
|
|
||||||
connect(displayOptionsWidget, &VisualDeckDisplayOptionsWidget::displayTypeChanged, zoneDisplayWidget,
|
|
||||||
&DeckCardZoneDisplayWidget::refreshDisplayType);
|
|
||||||
zoneContainerLayout->addWidget(zoneDisplayWidget);
|
|
||||||
|
|
||||||
indexToWidgetMap.insert(persistent, zoneDisplayWidget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckDisplayWidget::resizeEvent(QResizeEvent *event)
|
|
||||||
{
|
|
||||||
QWidget::resizeEvent(event);
|
|
||||||
layout->invalidate();
|
|
||||||
layout->activate();
|
|
||||||
layout->update();
|
|
||||||
}
|
|
||||||
|
|
@ -1,129 +0,0 @@
|
||||||
#ifndef COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_DISPLAY_WIDGET_H
|
|
||||||
#define COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_DISPLAY_WIDGET_H
|
|
||||||
|
|
||||||
#include "../../../../../deck_loader/deck_loader.h"
|
|
||||||
#include "../../../../cards/card_size_widget.h"
|
|
||||||
#include "../../../../general/layout_containers/flow_widget.h"
|
|
||||||
#include "../../../../visual_deck_editor/visual_deck_display_options_widget.h"
|
|
||||||
#include "../api_response/deck/archidekt_api_response_deck.h"
|
|
||||||
#include "deck_list_model.h"
|
|
||||||
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QResizeEvent>
|
|
||||||
#include <QScrollArea>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class ArchidektApiResponseDeckDisplayWidget
|
|
||||||
* @brief Displays a full deck fetched from an Archidekt API response.
|
|
||||||
*
|
|
||||||
* This widget visualizes all cards in a deck retrieved from the Archidekt API.
|
|
||||||
* It supports:
|
|
||||||
* - Interactive display options via a VisualDeckDisplayOptionsWidget.
|
|
||||||
* - Scrollable display of deck zones/cards with DeckCardZoneDisplayWidget.
|
|
||||||
* - Integration with a CardSizeWidget slider for card scaling.
|
|
||||||
* - Opening the deck in a deck editor.
|
|
||||||
*
|
|
||||||
* The widget internally constructs a DeckListModel from the Archidekt API response,
|
|
||||||
* then builds zone widgets for each group of cards according to the active group
|
|
||||||
* criteria. It also responds dynamically to model resets or sorting/grouping changes.
|
|
||||||
*
|
|
||||||
* ### Signals
|
|
||||||
* - `requestNavigation(QString url)` — triggered when navigation to a deck URL is requested.
|
|
||||||
* - `openInDeckEditor(const LoadedDeck &deck)` — emitted when the user chooses to open the deck
|
|
||||||
* in the deck editor.
|
|
||||||
*
|
|
||||||
* ### Features
|
|
||||||
* - Automatically generates DeckCardZoneDisplayWidget instances for each card group.
|
|
||||||
* - Provides a scrollable layout for decks of arbitrary size.
|
|
||||||
* - Updates layouts dynamically when resized or when display/group/sort criteria change.
|
|
||||||
*/
|
|
||||||
class ArchidektApiResponseDeckDisplayWidget : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
signals:
|
|
||||||
/**
|
|
||||||
* @brief Emitted when navigation to a deck URL is requested.
|
|
||||||
* @param url URL of the deck on Archidekt.
|
|
||||||
*/
|
|
||||||
void requestNavigation(QString url);
|
|
||||||
void requestSearch();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Emitted when the deck should be opened in the deck editor.
|
|
||||||
* @param deck LoadedDeck containing the deck data.
|
|
||||||
*/
|
|
||||||
void openInDeckEditor(const LoadedDeck &deck);
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Constructs a display widget for an Archidekt deck.
|
|
||||||
* @param parent Parent widget.
|
|
||||||
* @param response API deck data container.
|
|
||||||
* @param cardSizeSlider Slider controlling card scaling.
|
|
||||||
*/
|
|
||||||
explicit ArchidektApiResponseDeckDisplayWidget(QWidget *parent,
|
|
||||||
ArchidektApiResponseDeck response,
|
|
||||||
CardSizeWidget *cardSizeSlider);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Updates all UI text for retranslation/localization.
|
|
||||||
*
|
|
||||||
* Called when the application language changes.
|
|
||||||
*/
|
|
||||||
void retranslateUi();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Opens the deck in the deck editor.
|
|
||||||
*/
|
|
||||||
void actOpenInDeckEditor();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Clears all dynamically generated card zone display widgets.
|
|
||||||
*/
|
|
||||||
void clearAllDisplayWidgets();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Handles model reset by clearing and reconstructing display widgets.
|
|
||||||
*/
|
|
||||||
void decklistModelReset();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Builds DeckCardZoneDisplayWidget instances from the current DeckListModel.
|
|
||||||
*/
|
|
||||||
void constructZoneWidgetsFromDeckListModel();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
/**
|
|
||||||
* @brief Slot triggered when the active group criteria change.
|
|
||||||
* @param activeGroupCriteria Name of the new grouping criteria.
|
|
||||||
*/
|
|
||||||
void onGroupCriteriaChange(const QString &activeGroupCriteria);
|
|
||||||
|
|
||||||
private:
|
|
||||||
ArchidektApiResponseDeck response; ///< API deck data container
|
|
||||||
CardSizeWidget *cardSizeSlider; ///< Slider for adjusting card sizes
|
|
||||||
QVBoxLayout *layout; ///< Main vertical layout
|
|
||||||
QWidget *navigationContainer;
|
|
||||||
QHBoxLayout *navigationContainerLayout;
|
|
||||||
QPushButton *homeButton;
|
|
||||||
QPushButton *openInEditorButton; ///< Button to open deck in editor
|
|
||||||
VisualDeckDisplayOptionsWidget *displayOptionsWidget; ///< Controls grouping/sorting/display
|
|
||||||
QScrollArea *scrollArea; ///< Scrollable area for deck zones
|
|
||||||
QWidget *zoneContainer; ///< Container for deck zones
|
|
||||||
QVBoxLayout *zoneContainerLayout; ///< Layout for deck zones
|
|
||||||
QWidget *container; ///< Outer container for scroll area
|
|
||||||
QHash<QPersistentModelIndex, QWidget *> indexToWidgetMap; ///< Maps model indices to widgets
|
|
||||||
QVBoxLayout *containerLayout; ///< Layout for container
|
|
||||||
DeckListModel *model; ///< Deck list model
|
|
||||||
protected slots:
|
|
||||||
/**
|
|
||||||
* @brief Updates layout and display on resize.
|
|
||||||
* @param event Resize event.
|
|
||||||
*/
|
|
||||||
void resizeEvent(QResizeEvent *event) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_DISPLAY_WIDGET_H
|
|
||||||
|
|
@ -1,237 +0,0 @@
|
||||||
#include "archidekt_api_response_deck_entry_display_widget.h"
|
|
||||||
|
|
||||||
#include "../../../../../card_picture_loader/card_picture_loader.h"
|
|
||||||
#include "../../../../cards/card_info_picture_with_text_overlay_widget.h"
|
|
||||||
#include "../../../../general/display/background_plate_widget.h"
|
|
||||||
#include "../../../../general/display/charts/bars/color_bar.h"
|
|
||||||
#include "archidekt_deck_preview_image_display_widget.h"
|
|
||||||
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QNetworkAccessManager>
|
|
||||||
#include <QNetworkReply>
|
|
||||||
#include <QPixmap>
|
|
||||||
#include <QWidget>
|
|
||||||
#include <version_string.h>
|
|
||||||
|
|
||||||
#define ARCHIDEKT_DEFAULT_IMAGE "https://storage.googleapis.com/topdekt-user/images/archidekt_deck_card_shadow.jpg"
|
|
||||||
|
|
||||||
static QString timeAgo(const QString ×tamp)
|
|
||||||
{
|
|
||||||
QDateTime dt = QDateTime::fromString(timestamp, Qt::ISODate);
|
|
||||||
|
|
||||||
if (!dt.isValid())
|
|
||||||
return timestamp; // fallback if parsing fails
|
|
||||||
|
|
||||||
qint64 secs = dt.secsTo(QDateTime::currentDateTimeUtc());
|
|
||||||
|
|
||||||
if (secs < 60)
|
|
||||||
return QString("%1 seconds ago").arg(secs);
|
|
||||||
if (secs < 3600)
|
|
||||||
return QString("%1 minutes ago").arg(secs / 60);
|
|
||||||
if (secs < 86400)
|
|
||||||
return QString("%1 hours ago").arg(secs / 3600);
|
|
||||||
if (secs < 30 * 86400)
|
|
||||||
return QString("%1 days ago").arg(secs / 86400);
|
|
||||||
if (secs < 365 * 86400)
|
|
||||||
return QString("%1 months ago").arg(secs / (30 * 86400));
|
|
||||||
|
|
||||||
return QString("%1 years ago").arg(secs / (365 * 86400));
|
|
||||||
}
|
|
||||||
|
|
||||||
ArchidektApiResponseDeckEntryDisplayWidget::ArchidektApiResponseDeckEntryDisplayWidget(
|
|
||||||
QWidget *parent,
|
|
||||||
ArchidektApiResponseDeckListingContainer _response,
|
|
||||||
QNetworkAccessManager *_imageNetworkManager)
|
|
||||||
: QWidget(parent), response(_response), imageNetworkManager(_imageNetworkManager)
|
|
||||||
{
|
|
||||||
layout = new QVBoxLayout(this);
|
|
||||||
setLayout(layout);
|
|
||||||
|
|
||||||
this->setMaximumWidth(400);
|
|
||||||
this->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
|
|
||||||
|
|
||||||
auto headerLayout = new QVBoxLayout();
|
|
||||||
|
|
||||||
previewWidget = new ArchidektDeckPreviewImageDisplayWidget(this);
|
|
||||||
|
|
||||||
previewWidget->setMaximumWidth(400);
|
|
||||||
previewWidget->setMinimumHeight(300); // consistent height
|
|
||||||
|
|
||||||
// Set deck name (ellided)
|
|
||||||
QFontMetrics fm(previewWidget->topLeftLabel->font());
|
|
||||||
QString elided = fm.elidedText(response.getName(), Qt::ElideRight, 280);
|
|
||||||
previewWidget->topLeftLabel->setLabelText(elided);
|
|
||||||
previewWidget->topLeftLabel->setToolTip(response.getName());
|
|
||||||
|
|
||||||
// Set count
|
|
||||||
previewWidget->topRightLabel->setLabelText(QString::number(response.getSize()));
|
|
||||||
|
|
||||||
// EDH bracket (skip if 0)
|
|
||||||
if (response.getEDHBracket() != 0) {
|
|
||||||
previewWidget->bottomLeftLabel->setLabelText(QString("EDH: %1").arg(response.getEDHBracket()));
|
|
||||||
} else {
|
|
||||||
previewWidget->bottomLeftLabel->hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Views
|
|
||||||
previewWidget->bottomRightLabel->setLabelText(QString("Views: %1").arg(response.getViewCount()));
|
|
||||||
|
|
||||||
// Use preview->imageLabel for image loading
|
|
||||||
picture = previewWidget->imageLabel;
|
|
||||||
|
|
||||||
imageUrl = response.getFeatured().isEmpty() ? QUrl(ARCHIDEKT_DEFAULT_IMAGE) : QUrl(response.getFeatured());
|
|
||||||
|
|
||||||
QNetworkRequest req(imageUrl);
|
|
||||||
req.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING));
|
|
||||||
QNetworkReply *reply = imageNetworkManager->get(req);
|
|
||||||
|
|
||||||
// tag the reply with "this" so we know it belongs to us later
|
|
||||||
reply->setProperty("deckWidget", QVariant::fromValue<void *>(this));
|
|
||||||
reply->setProperty("requestedUrl", imageUrl);
|
|
||||||
|
|
||||||
connect(imageNetworkManager, &QNetworkAccessManager::finished, this,
|
|
||||||
&ArchidektApiResponseDeckEntryDisplayWidget::onPreviewImageLoadFinished);
|
|
||||||
|
|
||||||
headerLayout->addWidget(previewWidget);
|
|
||||||
|
|
||||||
auto colors = response.getColors();
|
|
||||||
|
|
||||||
ColorBar *colorBar = new ColorBar(colors, this);
|
|
||||||
colorBar->setMinPercentThreshold(3);
|
|
||||||
colorBar->setFixedHeight(22);
|
|
||||||
|
|
||||||
headerLayout->addWidget(colorBar);
|
|
||||||
|
|
||||||
// Create a shared plate for the labels
|
|
||||||
backgroundPlateWidget = new BackgroundPlateWidget(this);
|
|
||||||
backgroundPlateWidget->setFixedHeight(120); // Adjust height to fit all labels
|
|
||||||
|
|
||||||
QVBoxLayout *plateLayout = new QVBoxLayout(backgroundPlateWidget);
|
|
||||||
|
|
||||||
// Add labels to the plate layout
|
|
||||||
QLabel *ownerLabel = new QLabel(QString("Owner: %1").arg(response.getOwner().getName()));
|
|
||||||
plateLayout->addWidget(ownerLabel);
|
|
||||||
|
|
||||||
QLabel *createdAtLabel = new QLabel(QString("Created: %1").arg(timeAgo(response.getCreatedAt())));
|
|
||||||
plateLayout->addWidget(createdAtLabel);
|
|
||||||
|
|
||||||
QLabel *updatedAtLabel = new QLabel(QString("Updated: %1").arg(timeAgo(response.getUpdatedAt())));
|
|
||||||
plateLayout->addWidget(updatedAtLabel);
|
|
||||||
|
|
||||||
// Add the shared plate to the header layout
|
|
||||||
headerLayout->addWidget(backgroundPlateWidget);
|
|
||||||
|
|
||||||
layout->addLayout(headerLayout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckEntryDisplayWidget::mousePressEvent(QMouseEvent *event)
|
|
||||||
{
|
|
||||||
QWidget::mousePressEvent(event);
|
|
||||||
actRequestNavigationToDeck();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
void ArchidektApiResponseDeckEntryDisplayWidget::enterEvent(QEnterEvent *event)
|
|
||||||
#else
|
|
||||||
void ArchidektApiResponseDeckEntryDisplayWidget::enterEvent(QEvent *event)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
QWidget::enterEvent(event);
|
|
||||||
backgroundPlateWidget->setFocused(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckEntryDisplayWidget::leaveEvent(QEvent *event)
|
|
||||||
{
|
|
||||||
QWidget::leaveEvent(event);
|
|
||||||
backgroundPlateWidget->setFocused(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckEntryDisplayWidget::setScaleFactor(int scale)
|
|
||||||
{
|
|
||||||
scaleFactor = scale;
|
|
||||||
updateScaledPreview();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckEntryDisplayWidget::onPreviewImageLoadFinished(QNetworkReply *reply)
|
|
||||||
{
|
|
||||||
// Check if this is our reply
|
|
||||||
void *owner = reply->property("deckWidget").value<void *>();
|
|
||||||
if (owner != this) {
|
|
||||||
return; // not our reply
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the requested URL matches what we asked
|
|
||||||
QUrl requestedUrl = reply->property("requestedUrl").toUrl();
|
|
||||||
if (requestedUrl != imageUrl) {
|
|
||||||
reply->deleteLater();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QPixmap loaded;
|
|
||||||
|
|
||||||
if (reply->error() != QNetworkReply::NoError || !loaded.loadFromData(reply->readAll())) {
|
|
||||||
CardPictureLoader::getCardBackLoadingFailedPixmap(loaded, QSize(400, 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
originalPixmap = loaded;
|
|
||||||
|
|
||||||
// Always scale preview widget to this ratio
|
|
||||||
previewWidget->setAspectRatio(DESIGN_RATIO);
|
|
||||||
previewWidget->setPreviewWidth(400);
|
|
||||||
|
|
||||||
// Initial scaling
|
|
||||||
updateScaledPreview();
|
|
||||||
|
|
||||||
reply->deleteLater();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckEntryDisplayWidget::updateScaledPreview()
|
|
||||||
{
|
|
||||||
if (originalPixmap.isNull()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int baseWidth = 400;
|
|
||||||
int newWidth = baseWidth * scaleFactor / 100;
|
|
||||||
int newHeight = static_cast<int>(newWidth * DESIGN_RATIO);
|
|
||||||
|
|
||||||
previewWidget->setFixedSize(newWidth, newHeight);
|
|
||||||
|
|
||||||
// Scale image to fill the preview area (crop edges)
|
|
||||||
QPixmap scaled =
|
|
||||||
originalPixmap.scaled(newWidth, newHeight, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
|
|
||||||
|
|
||||||
// Crop to exact target size
|
|
||||||
QRect cropRect((scaled.width() - newWidth) / 2, (scaled.height() - newHeight) / 2, newWidth, newHeight);
|
|
||||||
QPixmap cropped = scaled.copy(cropRect);
|
|
||||||
|
|
||||||
picture->setPixmap(cropped);
|
|
||||||
picture->setFixedSize(newWidth, newHeight);
|
|
||||||
|
|
||||||
// Update the elided deck name based on new width
|
|
||||||
int textMaxWidth = int(newWidth * 0.7); // allow 70% of width for text
|
|
||||||
QFontMetrics fm(previewWidget->topLeftLabel->font());
|
|
||||||
QString elided = fm.elidedText(response.getName(), Qt::ElideRight, textMaxWidth);
|
|
||||||
previewWidget->topLeftLabel->setLabelText(elided);
|
|
||||||
previewWidget->topLeftLabel->setToolTip(response.getName());
|
|
||||||
|
|
||||||
setFixedWidth(newWidth);
|
|
||||||
|
|
||||||
layout->invalidate();
|
|
||||||
layout->activate();
|
|
||||||
updateGeometry();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckEntryDisplayWidget::resizeEvent(QResizeEvent *event)
|
|
||||||
{
|
|
||||||
QWidget::resizeEvent(event);
|
|
||||||
layout->invalidate();
|
|
||||||
layout->activate();
|
|
||||||
layout->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckEntryDisplayWidget::actRequestNavigationToDeck()
|
|
||||||
{
|
|
||||||
emit requestNavigation(QString("https://archidekt.com/api/decks/%1/").arg(response.getId()));
|
|
||||||
}
|
|
||||||
|
|
@ -1,121 +0,0 @@
|
||||||
#ifndef COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_ENTRY_DISPLAY_WIDGET_H
|
|
||||||
#define COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_ENTRY_DISPLAY_WIDGET_H
|
|
||||||
|
|
||||||
#include "../../../../cards/card_info_picture_with_text_overlay_widget.h"
|
|
||||||
#include "../api_response/deck_listings/archidekt_api_response_deck_listing_container.h"
|
|
||||||
#include "archidekt_deck_preview_image_display_widget.h"
|
|
||||||
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QNetworkAccessManager>
|
|
||||||
#include <QResizeEvent>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class BackgroundPlateWidget;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class ArchidektApiResponseDeckEntryDisplayWidget
|
|
||||||
* @brief Displays a single Archidekt deck listing as a preview card with metadata.
|
|
||||||
*
|
|
||||||
* This widget renders a deck entry received from an Archidekt API response. It includes:
|
|
||||||
* - A scaled deck preview image loaded asynchronously via QNetworkAccessManager.
|
|
||||||
* - Elided deck name in the top-left corner.
|
|
||||||
* - Deck size, EDH bracket, and view count labels.
|
|
||||||
* - A color distribution bar summarizing deck colors.
|
|
||||||
* - Metadata labels including owner, creation date, and last update date.
|
|
||||||
*
|
|
||||||
* The widget dynamically scales the preview image and labels according to a linked
|
|
||||||
* CardSizeWidget slider. Hovering over the widget highlights the background plate,
|
|
||||||
* and clicking emits a `requestNavigation` signal pointing to the deck URL.
|
|
||||||
*
|
|
||||||
* ### Features
|
|
||||||
* - Asynchronous image loading with fallback to a default placeholder image.
|
|
||||||
* - Maintains a fixed aspect ratio for the preview image (150:267).
|
|
||||||
* - Updates text elision dynamically when resized or scaled.
|
|
||||||
* - Integrates with FlowWidget containers for scrollable deck galleries.
|
|
||||||
*
|
|
||||||
* ### Signals
|
|
||||||
* - `requestNavigation(QString url)` — emitted when the widget is clicked to request
|
|
||||||
* navigation to the deck's Archidekt page.
|
|
||||||
*
|
|
||||||
* ### Slots
|
|
||||||
* - `actRequestNavigationToDeck()` — triggers navigation.
|
|
||||||
* - `setScaleFactor(int scale)` — adjusts preview image scaling.
|
|
||||||
*/
|
|
||||||
class ArchidektApiResponseDeckEntryDisplayWidget : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
signals:
|
|
||||||
/**
|
|
||||||
* @brief Emitted when the user requests navigation.
|
|
||||||
* @param url Full URL to the Archidekt page.
|
|
||||||
*/
|
|
||||||
void requestNavigation(QString url);
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Constructs a deck entry display widget.
|
|
||||||
* @param parent Parent widget.
|
|
||||||
* @param response API container holding deck listing data.
|
|
||||||
* @param imageNetworkManager Shared network manager for fetching preview images.
|
|
||||||
*/
|
|
||||||
explicit ArchidektApiResponseDeckEntryDisplayWidget(QWidget *parent,
|
|
||||||
ArchidektApiResponseDeckListingContainer response,
|
|
||||||
QNetworkAccessManager *imageNetworkManager);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Handles finished network replies for preview images.
|
|
||||||
* @param reply QNetworkReply containing image data.
|
|
||||||
*
|
|
||||||
* Validates that the reply corresponds to this widget and updates the preview image.
|
|
||||||
*/
|
|
||||||
void onPreviewImageLoadFinished(QNetworkReply *reply);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Updates the scaled preview image and adjusts layout accordingly.
|
|
||||||
*/
|
|
||||||
void updateScaledPreview();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Ensures layout responds correctly on resize events.
|
|
||||||
* @param event Resize event.
|
|
||||||
*/
|
|
||||||
void resizeEvent(QResizeEvent *event) override;
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
/**
|
|
||||||
* @brief Emits `requestNavigation` for the deck's URL.
|
|
||||||
*/
|
|
||||||
void actRequestNavigationToDeck();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sets a scaling factor (percentage) for the preview image.
|
|
||||||
* @param scale Scale percentage (100 = normal size).
|
|
||||||
*/
|
|
||||||
void setScaleFactor(int scale);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
void enterEvent(QEnterEvent *event) override; ///< Qt6 hover enter
|
|
||||||
#else
|
|
||||||
void enterEvent(QEvent *event) override; ///< Qt5 hover enter
|
|
||||||
#endif
|
|
||||||
void leaveEvent(QEvent *event) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QVBoxLayout *layout; ///< Main vertical layout
|
|
||||||
ArchidektApiResponseDeckListingContainer response; ///< Deck data
|
|
||||||
QUrl imageUrl; ///< URL of the deck's preview image
|
|
||||||
QNetworkAccessManager *imageNetworkManager; ///< Shared network manager
|
|
||||||
ArchidektDeckPreviewImageDisplayWidget *previewWidget; ///< Widget showing the deck preview
|
|
||||||
QLabel *picture; ///< QLabel displaying the scaled pixmap
|
|
||||||
QPixmap originalPixmap; ///< Original image for scaling (avoids degradation)
|
|
||||||
int scaleFactor = 100; ///< Current scaling percentage
|
|
||||||
BackgroundPlateWidget *backgroundPlateWidget; ///< Plate for metadata labels
|
|
||||||
static constexpr float DESIGN_RATIO = 150.0f / 267.0f; ///< Design aspect ratio
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_ENTRY_DISPLAY_WIDGET_H
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
#include "archidekt_api_response_deck_listings_display_widget.h"
|
|
||||||
|
|
||||||
#include "../../../../cards/card_info_picture_with_text_overlay_widget.h"
|
|
||||||
#include "archidekt_api_response_deck_entry_display_widget.h"
|
|
||||||
|
|
||||||
ArchidektApiResponseDeckListingsDisplayWidget::ArchidektApiResponseDeckListingsDisplayWidget(
|
|
||||||
QWidget *parent,
|
|
||||||
ArchidektDeckListingApiResponse response,
|
|
||||||
CardSizeWidget *_cardSizeSlider)
|
|
||||||
: QWidget(parent), cardSizeSlider(_cardSizeSlider)
|
|
||||||
{
|
|
||||||
layout = new QHBoxLayout(this);
|
|
||||||
layout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
setLayout(layout);
|
|
||||||
|
|
||||||
flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAsNeeded);
|
|
||||||
|
|
||||||
imageNetworkManager = new QNetworkAccessManager(this);
|
|
||||||
imageNetworkManager->setTransferTimeout(); // Use Qt's default timeout
|
|
||||||
imageNetworkManager->setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy);
|
|
||||||
|
|
||||||
// Add widgets for deck listings
|
|
||||||
auto deckListings = response.results;
|
|
||||||
for (const auto &deckListing : deckListings) {
|
|
||||||
auto cardListDisplayWidget =
|
|
||||||
new ArchidektApiResponseDeckEntryDisplayWidget(this, deckListing, imageNetworkManager);
|
|
||||||
cardListDisplayWidget->setScaleFactor(cardSizeSlider->getSlider()->value());
|
|
||||||
connect(cardListDisplayWidget, &ArchidektApiResponseDeckEntryDisplayWidget::requestNavigation, this,
|
|
||||||
&ArchidektApiResponseDeckListingsDisplayWidget::requestNavigation);
|
|
||||||
connect(cardSizeSlider->getSlider(), &QSlider::valueChanged, cardListDisplayWidget,
|
|
||||||
&ArchidektApiResponseDeckEntryDisplayWidget::setScaleFactor);
|
|
||||||
flowWidget->addWidget(cardListDisplayWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
layout->addWidget(flowWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckListingsDisplayWidget::append(const ArchidektDeckListingApiResponse &data)
|
|
||||||
{
|
|
||||||
for (const auto &deckListing : data.results) {
|
|
||||||
auto cardListDisplayWidget =
|
|
||||||
new ArchidektApiResponseDeckEntryDisplayWidget(this, deckListing, imageNetworkManager);
|
|
||||||
cardListDisplayWidget->setScaleFactor(cardSizeSlider->getSlider()->value());
|
|
||||||
connect(cardListDisplayWidget, &ArchidektApiResponseDeckEntryDisplayWidget::requestNavigation, this,
|
|
||||||
&ArchidektApiResponseDeckListingsDisplayWidget::requestNavigation);
|
|
||||||
connect(cardSizeSlider->getSlider(), &QSlider::valueChanged, cardListDisplayWidget,
|
|
||||||
&ArchidektApiResponseDeckEntryDisplayWidget::setScaleFactor);
|
|
||||||
flowWidget->addWidget(cardListDisplayWidget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektApiResponseDeckListingsDisplayWidget::resizeEvent(QResizeEvent *event)
|
|
||||||
{
|
|
||||||
QWidget::resizeEvent(event);
|
|
||||||
layout->invalidate();
|
|
||||||
layout->activate();
|
|
||||||
layout->update();
|
|
||||||
}
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
#ifndef COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_LISTINGS_DISPLAY_WIDGET_H
|
|
||||||
#define COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_LISTINGS_DISPLAY_WIDGET_H
|
|
||||||
|
|
||||||
#include "../../../../cards/card_size_widget.h"
|
|
||||||
#include "../../../../general/layout_containers/flow_widget.h"
|
|
||||||
#include "../api_response/archidekt_deck_listing_api_response.h"
|
|
||||||
|
|
||||||
#include <QNetworkAccessManager>
|
|
||||||
#include <QResizeEvent>
|
|
||||||
#include <QScrollArea>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class ArchidektApiResponseDeckListingsDisplayWidget
|
|
||||||
* @brief Displays a scrollable horizontal list of Archidekt deck listings with dynamic card sizing.
|
|
||||||
*
|
|
||||||
* This widget serves as a container for multiple
|
|
||||||
* ArchidektApiResponseDeckEntryDisplayWidget instances, each representing one deck listing
|
|
||||||
* returned from an Archidekt API call.
|
|
||||||
*
|
|
||||||
* ### Responsibilities
|
|
||||||
* - Creates a **FlowWidget** that arranges deck entries horizontally with wrapping.
|
|
||||||
* - Creates a shared **QNetworkAccessManager** for entry widgets to fetch card thumbnails.
|
|
||||||
* - Connects a **CardSizeWidget** slider to all deck entries to dynamically rescale their preview cards.
|
|
||||||
* - Propagates deck-navigation requests (`requestNavigation`) from children to the parent.
|
|
||||||
*
|
|
||||||
* ### Layout
|
|
||||||
* The widget uses a single `QHBoxLayout` containing the `FlowWidget`.
|
|
||||||
* The FlowWidget automatically manages child flow and scrollbar behavior (horizontal = off,
|
|
||||||
* vertical = auto), providing an efficient scrollable gallery of deck entries.
|
|
||||||
*
|
|
||||||
* ### API Integration
|
|
||||||
* The constructor consumes an `ArchidektDeckListingApiResponse`, iterates through its
|
|
||||||
* `results`, and instantiates a child entry widget for each deck.
|
|
||||||
*
|
|
||||||
* ### Signals
|
|
||||||
* - `requestNavigation(QString url)` — emitted whenever a child entry widget requests
|
|
||||||
* navigation to a deck or related Archidekt page.
|
|
||||||
*
|
|
||||||
* ### Performance Notes
|
|
||||||
* - All entry widgets share a single QNetworkAccessManager instance to reuse connections
|
|
||||||
* and avoid redundant session creation.
|
|
||||||
* - `resizeEvent()` forces layout invalidation to ensure the flow layout responds properly
|
|
||||||
* to container resizing.
|
|
||||||
*/
|
|
||||||
class ArchidektApiResponseDeckListingsDisplayWidget : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
signals:
|
|
||||||
/**
|
|
||||||
* @brief Emitted when a child deck entry requests that the UI navigate to a particular URL.
|
|
||||||
* @param url The destination URL (typically an Archidekt deck page).
|
|
||||||
*/
|
|
||||||
void requestNavigation(QString url);
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Constructs a widget that displays multiple deck listing previews.
|
|
||||||
*
|
|
||||||
* @param parent Parent widget.
|
|
||||||
* @param response The Archidekt API response containing deck listings.
|
|
||||||
* @param cardSizeSlider A slider widget used to dynamically resize card previews.
|
|
||||||
*
|
|
||||||
* Each deck in `response.results` becomes its own
|
|
||||||
* ArchidektApiResponseDeckEntryDisplayWidget, added to the FlowWidget.
|
|
||||||
*/
|
|
||||||
explicit ArchidektApiResponseDeckListingsDisplayWidget(QWidget *parent,
|
|
||||||
ArchidektDeckListingApiResponse response,
|
|
||||||
CardSizeWidget *cardSizeSlider);
|
|
||||||
void append(const ArchidektDeckListingApiResponse &data);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Ensures FlowWidget layout properly recomputes on resize.
|
|
||||||
*
|
|
||||||
* Forces the layout to invalidate and activate itself so that the
|
|
||||||
* FlowWidget recalculates wrapping and child placement.
|
|
||||||
*
|
|
||||||
* @param event Resize event.
|
|
||||||
*/
|
|
||||||
void resizeEvent(QResizeEvent *event) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// Slider controlling the scale of card thumbnails in all deck entry widgets.
|
|
||||||
CardSizeWidget *cardSizeSlider;
|
|
||||||
|
|
||||||
/// Main horizontal layout containing the FlowWidget.
|
|
||||||
QHBoxLayout *layout;
|
|
||||||
|
|
||||||
/// Container providing scrollable multi-row flow layout of deck entries.
|
|
||||||
FlowWidget *flowWidget;
|
|
||||||
|
|
||||||
/// Shared network manager used to download card images for all child entry widgets.
|
|
||||||
QNetworkAccessManager *imageNetworkManager;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_LISTINGS_DISPLAY_WIDGET_H
|
|
||||||
|
|
@ -1,80 +0,0 @@
|
||||||
#include "archidekt_deck_preview_image_display_widget.h"
|
|
||||||
|
|
||||||
#include <QFontMetrics>
|
|
||||||
#include <QPainter>
|
|
||||||
|
|
||||||
ArchidektDeckPreviewImageDisplayWidget::ArchidektDeckPreviewImageDisplayWidget(QWidget *parent) : QWidget(parent)
|
|
||||||
{
|
|
||||||
imageLabel = new QLabel(this);
|
|
||||||
imageLabel->setAlignment(Qt::AlignCenter);
|
|
||||||
|
|
||||||
topLeftLabel = new ShadowBackgroundLabel(this, "");
|
|
||||||
topRightLabel = new ShadowBackgroundLabel(this, "");
|
|
||||||
bottomLeftLabel = new ShadowBackgroundLabel(this, "");
|
|
||||||
bottomRightLabel = new ShadowBackgroundLabel(this, "");
|
|
||||||
|
|
||||||
QFont f;
|
|
||||||
f.setBold(true);
|
|
||||||
f.setPointSize(16);
|
|
||||||
topLeftLabel->setFont(f);
|
|
||||||
topRightLabel->setFont(f);
|
|
||||||
bottomLeftLabel->setFont(f);
|
|
||||||
bottomRightLabel->setFont(f);
|
|
||||||
|
|
||||||
// Raise so labels appear above image
|
|
||||||
topLeftLabel->raise();
|
|
||||||
topRightLabel->raise();
|
|
||||||
bottomLeftLabel->raise();
|
|
||||||
bottomRightLabel->raise();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektDeckPreviewImageDisplayWidget::setAspectRatio(float ratio)
|
|
||||||
{
|
|
||||||
aspectRatio = ratio;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektDeckPreviewImageDisplayWidget::setPreviewWidth(int width)
|
|
||||||
{
|
|
||||||
int height = int(width * aspectRatio);
|
|
||||||
|
|
||||||
setFixedSize(width, height);
|
|
||||||
updateGeometry();
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArchidektDeckPreviewImageDisplayWidget::resizeEvent(QResizeEvent *event)
|
|
||||||
{
|
|
||||||
QWidget::resizeEvent(event);
|
|
||||||
|
|
||||||
// Full size for the image
|
|
||||||
imageLabel->setGeometry(rect());
|
|
||||||
|
|
||||||
topLeftLabel->adjustSize();
|
|
||||||
topRightLabel->adjustSize();
|
|
||||||
bottomLeftLabel->adjustSize();
|
|
||||||
bottomRightLabel->adjustSize();
|
|
||||||
|
|
||||||
// Padding settings
|
|
||||||
const int horizontalPadding = 8;
|
|
||||||
const int topPadding = 6;
|
|
||||||
const int bottomPadding = 6;
|
|
||||||
|
|
||||||
// Left-aligned, top-aligned (Deck Name)
|
|
||||||
topLeftLabel->move(horizontalPadding, topPadding);
|
|
||||||
|
|
||||||
// Right-aligned, top-aligned (Card Count)
|
|
||||||
topRightLabel->move(width() - topRightLabel->width() - horizontalPadding, topPadding);
|
|
||||||
|
|
||||||
// Bottom-left, bottom-aligned (EDH bracket)
|
|
||||||
bottomLeftLabel->move(horizontalPadding, height() - bottomLeftLabel->height() - bottomPadding);
|
|
||||||
|
|
||||||
// Bottom-right, bottom-aligned (views)
|
|
||||||
bottomRightLabel->move(width() - bottomRightLabel->width() - horizontalPadding,
|
|
||||||
height() - bottomRightLabel->height() - bottomPadding);
|
|
||||||
|
|
||||||
// Ensure labels stay above image
|
|
||||||
topLeftLabel->raise();
|
|
||||||
topRightLabel->raise();
|
|
||||||
bottomLeftLabel->raise();
|
|
||||||
bottomRightLabel->raise();
|
|
||||||
}
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
#ifndef COCKATRICE_ARCHIDEKT_DECK_PREVIEW_IMAGE_DISPLAY_WIDGET_H
|
|
||||||
#define COCKATRICE_ARCHIDEKT_DECK_PREVIEW_IMAGE_DISPLAY_WIDGET_H
|
|
||||||
|
|
||||||
#include "../../../../general/display/shadow_background_label.h"
|
|
||||||
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class ArchidektDeckPreviewImageDisplayWidget
|
|
||||||
* @brief Widget for displaying a deck preview image with overlaid metadata labels.
|
|
||||||
*
|
|
||||||
* This widget shows a deck's preview image along with several overlay labels:
|
|
||||||
* - Top-left: Deck name.
|
|
||||||
* - Top-right: Card count.
|
|
||||||
* - Bottom-left: EDH bracket (if applicable).
|
|
||||||
* - Bottom-right: View count.
|
|
||||||
*
|
|
||||||
* Labels automatically scale and position themselves relative to the widget's size.
|
|
||||||
* The image can be scaled while maintaining a specified aspect ratio.
|
|
||||||
*
|
|
||||||
* ### Features
|
|
||||||
* - Adjustable preview width and aspect ratio.
|
|
||||||
* - Labels automatically repositioned on resize.
|
|
||||||
* - Supports overlaying multiple pieces of metadata with shadowed labels for readability.
|
|
||||||
*/
|
|
||||||
class ArchidektDeckPreviewImageDisplayWidget : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Constructs the deck preview display widget.
|
|
||||||
* @param parent Optional parent widget.
|
|
||||||
*/
|
|
||||||
explicit ArchidektDeckPreviewImageDisplayWidget(QWidget *parent = nullptr);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sets the aspect ratio for the preview image (height / width).
|
|
||||||
* @param ratio Aspect ratio to maintain.
|
|
||||||
*/
|
|
||||||
void setAspectRatio(float ratio);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sets the width of the preview image; height is adjusted according to the aspect ratio.
|
|
||||||
* @param width Desired width in pixels.
|
|
||||||
*/
|
|
||||||
void setPreviewWidth(int width);
|
|
||||||
|
|
||||||
QLabel *imageLabel; ///< QLabel to display the deck image
|
|
||||||
ShadowBackgroundLabel *topLeftLabel; ///< Overlay label at top-left (deck name)
|
|
||||||
ShadowBackgroundLabel *topRightLabel; ///< Overlay label at top-right (card count)
|
|
||||||
ShadowBackgroundLabel *bottomLeftLabel; ///< Overlay label at bottom-left (EDH bracket)
|
|
||||||
ShadowBackgroundLabel *bottomRightLabel; ///< Overlay label at bottom-right (views)
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* @brief Handles resize events to reposition the image and overlay labels.
|
|
||||||
* @param event Resize event.
|
|
||||||
*/
|
|
||||||
void resizeEvent(QResizeEvent *event) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
float aspectRatio = 1.0f; ///< Aspect ratio to maintain for the preview image
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // COCKATRICE_ARCHIDEKT_DECK_PREVIEW_IMAGE_DISPLAY_WIDGET_H
|
|
||||||
|
|
@ -1,669 +0,0 @@
|
||||||
#include "tab_archidekt.h"
|
|
||||||
|
|
||||||
#include "../../../../../client/settings/cache_settings.h"
|
|
||||||
#include "../../../cards/additional_info/mana_symbol_widget.h"
|
|
||||||
#include "../../tab_supervisor.h"
|
|
||||||
#include "api_response/archidekt_deck_listing_api_response.h"
|
|
||||||
#include "display/archidekt_api_response_deck_display_widget.h"
|
|
||||||
#include "display/archidekt_api_response_deck_listings_display_widget.h"
|
|
||||||
|
|
||||||
#include <QCompleter>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QFormLayout>
|
|
||||||
#include <QGridLayout>
|
|
||||||
#include <QGroupBox>
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QJsonDocument>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QNetworkAccessManager>
|
|
||||||
#include <QNetworkReply>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QRegularExpression>
|
|
||||||
#include <QResizeEvent>
|
|
||||||
#include <QScrollArea>
|
|
||||||
#include <QScrollBar>
|
|
||||||
#include <QUrlQuery>
|
|
||||||
#include <libcockatrice/card/database/card_database_manager.h>
|
|
||||||
#include <libcockatrice/models/database/card/card_completer_proxy_model.h>
|
|
||||||
#include <libcockatrice/models/database/card/card_search_model.h>
|
|
||||||
#include <version_string.h>
|
|
||||||
|
|
||||||
TabArchidekt::TabArchidekt(TabSupervisor *_tabSupervisor)
|
|
||||||
: Tab(_tabSupervisor), currentPage(1), isLoadingMore(false), isListMode(true)
|
|
||||||
{
|
|
||||||
// Initialize network
|
|
||||||
networkManager = new QNetworkAccessManager(this);
|
|
||||||
networkManager->setTransferTimeout();
|
|
||||||
networkManager->setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy);
|
|
||||||
connect(networkManager, &QNetworkAccessManager::finished, this, &TabArchidekt::processApiJson);
|
|
||||||
|
|
||||||
// Initialize debounce timer
|
|
||||||
searchDebounceTimer = new QTimer(this);
|
|
||||||
searchDebounceTimer->setSingleShot(true);
|
|
||||||
searchDebounceTimer->setInterval(300);
|
|
||||||
connect(searchDebounceTimer, &QTimer::timeout, this, &TabArchidekt::doSearchImmediate);
|
|
||||||
|
|
||||||
initializeUi();
|
|
||||||
setupFilterWidgets();
|
|
||||||
connectSignals();
|
|
||||||
retranslateUi();
|
|
||||||
|
|
||||||
getTopDecks();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabArchidekt::initializeUi()
|
|
||||||
{
|
|
||||||
// Main container
|
|
||||||
container = new QWidget(this);
|
|
||||||
mainLayout = new QVBoxLayout(container);
|
|
||||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
mainLayout->setSpacing(0);
|
|
||||||
|
|
||||||
// Primary toolbar (most important filters)
|
|
||||||
primaryToolbar = new QWidget(container);
|
|
||||||
primaryToolbar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
|
||||||
primaryToolbarLayout = new QHBoxLayout(primaryToolbar);
|
|
||||||
primaryToolbarLayout->setContentsMargins(6, 6, 6, 6);
|
|
||||||
primaryToolbarLayout->setSpacing(6);
|
|
||||||
|
|
||||||
// Sort controls
|
|
||||||
sortByLabel = new QLabel(primaryToolbar);
|
|
||||||
orderByCombo = new QComboBox(primaryToolbar);
|
|
||||||
orderByCombo->addItems({"name", "updatedAt", "createdAt", "viewCount", "size", "edhBracket"});
|
|
||||||
orderByCombo->setCurrentText("updatedAt");
|
|
||||||
orderByCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
|
||||||
|
|
||||||
orderDirButton = new QPushButton(tr("Desc."), primaryToolbar);
|
|
||||||
orderDirButton->setCheckable(true);
|
|
||||||
orderDirButton->setChecked(true);
|
|
||||||
orderDirButton->setFixedWidth(60);
|
|
||||||
|
|
||||||
// Color filter (inline)
|
|
||||||
QWidget *colorWidget = new QWidget(primaryToolbar);
|
|
||||||
QHBoxLayout *colorLayout = new QHBoxLayout(colorWidget);
|
|
||||||
colorLayout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
colorLayout->setSpacing(2);
|
|
||||||
|
|
||||||
QString colorIdentity = "WUBRG";
|
|
||||||
for (const QChar &color : colorIdentity) {
|
|
||||||
auto *manaSymbol = new ManaSymbolWidget(colorWidget, color, false, true);
|
|
||||||
manaSymbol->setFixedSize(28, 28);
|
|
||||||
colorSymbols.append(manaSymbol);
|
|
||||||
colorLayout->addWidget(manaSymbol);
|
|
||||||
|
|
||||||
connect(manaSymbol, &ManaSymbolWidget::colorToggled, this, [this](QChar c, bool active) {
|
|
||||||
if (active)
|
|
||||||
activeColors.insert(c);
|
|
||||||
else
|
|
||||||
activeColors.remove(c);
|
|
||||||
doSearch();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
logicalAndCheck = new QCheckBox(tr("AND"), primaryToolbar);
|
|
||||||
logicalAndCheck->setToolTip(tr("Require ALL selected colors"));
|
|
||||||
|
|
||||||
// Common search fields
|
|
||||||
nameField = new QLineEdit(primaryToolbar);
|
|
||||||
nameField->setPlaceholderText(tr("Deck name..."));
|
|
||||||
nameField->setMinimumWidth(150);
|
|
||||||
|
|
||||||
ownerField = new QLineEdit(primaryToolbar);
|
|
||||||
ownerField->setPlaceholderText(tr("Owner..."));
|
|
||||||
ownerField->setMinimumWidth(120);
|
|
||||||
|
|
||||||
// Filter by label
|
|
||||||
filterByLabel = new QLabel(primaryToolbar);
|
|
||||||
|
|
||||||
// Package toggle
|
|
||||||
packagesCheck = new QCheckBox(tr("Packages"), primaryToolbar);
|
|
||||||
|
|
||||||
// Search button
|
|
||||||
searchButton = new QPushButton(tr("Search"), primaryToolbar);
|
|
||||||
searchButton->setDefault(true);
|
|
||||||
|
|
||||||
// Advanced filters toggle button
|
|
||||||
advancedFiltersButton = new QPushButton(tr("Advanced Filters"), primaryToolbar);
|
|
||||||
advancedFiltersButton->setCheckable(true);
|
|
||||||
advancedFiltersButton->setChecked(false);
|
|
||||||
|
|
||||||
// Settings
|
|
||||||
settingsButton = new SettingsButtonWidget(primaryToolbar);
|
|
||||||
cardSizeSlider = new CardSizeWidget(primaryToolbar, nullptr, SettingsCache::instance().getArchidektPreviewSize());
|
|
||||||
settingsButton->addSettingsWidget(cardSizeSlider);
|
|
||||||
|
|
||||||
// Assemble primary toolbar
|
|
||||||
primaryToolbarLayout->addWidget(sortByLabel);
|
|
||||||
primaryToolbarLayout->addWidget(orderByCombo);
|
|
||||||
primaryToolbarLayout->addWidget(orderDirButton);
|
|
||||||
|
|
||||||
// Add separator/spacing
|
|
||||||
primaryToolbarLayout->addSpacing(12);
|
|
||||||
|
|
||||||
primaryToolbarLayout->addWidget(filterByLabel);
|
|
||||||
primaryToolbarLayout->addWidget(colorWidget);
|
|
||||||
primaryToolbarLayout->addWidget(logicalAndCheck);
|
|
||||||
primaryToolbarLayout->addWidget(nameField, 1);
|
|
||||||
primaryToolbarLayout->addWidget(ownerField, 1);
|
|
||||||
primaryToolbarLayout->addWidget(packagesCheck);
|
|
||||||
primaryToolbarLayout->addWidget(searchButton, 1);
|
|
||||||
primaryToolbarLayout->addWidget(advancedFiltersButton);
|
|
||||||
primaryToolbarLayout->addWidget(settingsButton);
|
|
||||||
|
|
||||||
// Secondary toolbar (advanced filters - initially hidden)
|
|
||||||
secondaryToolbar = new QWidget(container);
|
|
||||||
secondaryToolbar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
|
||||||
secondaryToolbar->setVisible(false); // Start hidden
|
|
||||||
secondaryToolbarLayout = new QHBoxLayout(secondaryToolbar);
|
|
||||||
secondaryToolbarLayout->setContentsMargins(6, 3, 6, 6);
|
|
||||||
secondaryToolbarLayout->setSpacing(6);
|
|
||||||
|
|
||||||
// Scrollable results area
|
|
||||||
scrollArea = new QScrollArea(container);
|
|
||||||
scrollArea->setWidgetResizable(true);
|
|
||||||
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
||||||
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
|
||||||
|
|
||||||
resultsContainer = new QWidget();
|
|
||||||
resultsLayout = new QVBoxLayout(resultsContainer);
|
|
||||||
resultsLayout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
resultsLayout->setSpacing(0);
|
|
||||||
|
|
||||||
scrollArea->setWidget(resultsContainer);
|
|
||||||
|
|
||||||
scrollArea->viewport()->installEventFilter(this);
|
|
||||||
|
|
||||||
mainLayout->addWidget(primaryToolbar);
|
|
||||||
mainLayout->addWidget(secondaryToolbar);
|
|
||||||
mainLayout->addWidget(scrollArea);
|
|
||||||
|
|
||||||
setCentralWidget(container);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TabArchidekt::eventFilter(QObject *obj, QEvent *event)
|
|
||||||
{
|
|
||||||
if (obj == scrollArea->viewport() && event->type() == QEvent::Wheel) {
|
|
||||||
auto *wheelEvent = static_cast<QWheelEvent *>(event);
|
|
||||||
|
|
||||||
if (wheelEvent->angleDelta().y() < 0 && !isLoadingMore && isListMode) {
|
|
||||||
loadNextPage();
|
|
||||||
wheelEvent->accept();
|
|
||||||
return false; // allow scrolling
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Always pass the event to the parent to handle normal scrolling
|
|
||||||
return QWidget::eventFilter(obj, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabArchidekt::setupFilterWidgets()
|
|
||||||
{
|
|
||||||
// Advanced filters (in secondary toolbar)
|
|
||||||
|
|
||||||
// EDH Bracket
|
|
||||||
auto *bracketLabel = new QLabel(tr("Bracket:"), secondaryToolbar);
|
|
||||||
edhBracketCombo = new QComboBox(secondaryToolbar);
|
|
||||||
edhBracketCombo->addItem(tr("Any"));
|
|
||||||
edhBracketCombo->addItems({"1", "2", "3", "4", "5"});
|
|
||||||
edhBracketCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
|
||||||
|
|
||||||
// Format filter (collapsible)
|
|
||||||
formatButton = new SettingsButtonWidget(secondaryToolbar);
|
|
||||||
formatButton->setButtonText(tr("Formats"));
|
|
||||||
formatButton->setButtonIcon(QPixmap("theme:icons/scale_balanced"));
|
|
||||||
|
|
||||||
QWidget *formatContainer = new QWidget(secondaryToolbar);
|
|
||||||
QGridLayout *formatLayout = new QGridLayout(formatContainer);
|
|
||||||
formatLayout->setContentsMargins(4, 4, 4, 4);
|
|
||||||
|
|
||||||
QStringList formatNames = {"Standard", "Modern", "Commander", "Legacy", "Vintage",
|
|
||||||
"Pauper", "Custom", "Frontier", "Future Std", "Penny Dreadful",
|
|
||||||
"1v1 Commander", "Dual Commander", "Brawl"};
|
|
||||||
|
|
||||||
int row = 0, col = 0;
|
|
||||||
for (const QString &formatName : formatNames) {
|
|
||||||
auto *formatCheckBox = new QCheckBox(formatName, formatContainer);
|
|
||||||
formatChecks << formatCheckBox;
|
|
||||||
formatLayout->addWidget(formatCheckBox, row, col);
|
|
||||||
connect(formatCheckBox, &QCheckBox::clicked, this, &TabArchidekt::doSearch);
|
|
||||||
|
|
||||||
col++;
|
|
||||||
if (col >= 3) {
|
|
||||||
col = 0;
|
|
||||||
row++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
formatButton->addSettingsWidget(formatContainer);
|
|
||||||
|
|
||||||
cardsField = new QLineEdit(secondaryToolbar);
|
|
||||||
cardsField->setPlaceholderText(tr("Contains card..."));
|
|
||||||
cardsField->setMinimumWidth(140);
|
|
||||||
|
|
||||||
commandersField = new QLineEdit(secondaryToolbar);
|
|
||||||
commandersField->setPlaceholderText(tr("Commander..."));
|
|
||||||
commandersField->setMinimumWidth(140);
|
|
||||||
|
|
||||||
deckTagNameField = new QLineEdit(secondaryToolbar);
|
|
||||||
deckTagNameField->setPlaceholderText(tr("Tag..."));
|
|
||||||
deckTagNameField->setMinimumWidth(100);
|
|
||||||
|
|
||||||
// Deck size filter (collapsible)
|
|
||||||
deckSizeButton = new SettingsButtonWidget(secondaryToolbar);
|
|
||||||
deckSizeButton->setButtonText(tr("Deck Size"));
|
|
||||||
|
|
||||||
QWidget *sizeContainer = new QWidget(secondaryToolbar);
|
|
||||||
QHBoxLayout *sizeLayout = new QHBoxLayout(sizeContainer);
|
|
||||||
sizeLayout->setContentsMargins(4, 4, 4, 4);
|
|
||||||
|
|
||||||
minDeckSizeSpin = new QSpinBox(sizeContainer);
|
|
||||||
minDeckSizeSpin->setSpecialValueText(tr("Any"));
|
|
||||||
minDeckSizeSpin->setRange(0, 200);
|
|
||||||
minDeckSizeSpin->setValue(0);
|
|
||||||
|
|
||||||
minDeckSizeLogicCombo = new QComboBox(sizeContainer);
|
|
||||||
minDeckSizeLogicCombo->addItems({"Exact", "≥", "≤"});
|
|
||||||
minDeckSizeLogicCombo->setCurrentIndex(1);
|
|
||||||
|
|
||||||
sizeLayout->addWidget(new QLabel(tr("Cards:"), sizeContainer));
|
|
||||||
sizeLayout->addWidget(minDeckSizeSpin);
|
|
||||||
sizeLayout->addWidget(minDeckSizeLogicCombo);
|
|
||||||
|
|
||||||
deckSizeButton->addSettingsWidget(sizeContainer);
|
|
||||||
|
|
||||||
// Setup card name autocomplete
|
|
||||||
auto cardDatabaseModel = new CardDatabaseModel(CardDatabaseManager::getInstance(), false, this);
|
|
||||||
auto displayModel = new CardDatabaseDisplayModel(this);
|
|
||||||
displayModel->setSourceModel(cardDatabaseModel);
|
|
||||||
auto *searchModel = new CardSearchModel(displayModel, this);
|
|
||||||
|
|
||||||
auto *proxyModel = new CardCompleterProxyModel(this);
|
|
||||||
proxyModel->setSourceModel(searchModel);
|
|
||||||
proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
|
||||||
proxyModel->setFilterRole(Qt::DisplayRole);
|
|
||||||
|
|
||||||
auto *completer = new QCompleter(proxyModel, this);
|
|
||||||
completer->setCompletionRole(Qt::DisplayRole);
|
|
||||||
completer->setCompletionMode(QCompleter::PopupCompletion);
|
|
||||||
completer->setCaseSensitivity(Qt::CaseInsensitive);
|
|
||||||
completer->setFilterMode(Qt::MatchContains);
|
|
||||||
completer->setMaxVisibleItems(10);
|
|
||||||
|
|
||||||
cardsField->setCompleter(completer);
|
|
||||||
commandersField->setCompleter(completer);
|
|
||||||
|
|
||||||
// Keep autocomplete working for both fields
|
|
||||||
connect(cardsField, &QLineEdit::textChanged, this, [=](const QString &text) {
|
|
||||||
searchModel->updateSearchResults(text);
|
|
||||||
QString pattern = ".*" + QRegularExpression::escape(text) + ".*";
|
|
||||||
proxyModel->setFilterRegularExpression(QRegularExpression(pattern, QRegularExpression::CaseInsensitiveOption));
|
|
||||||
if (!text.isEmpty())
|
|
||||||
completer->complete();
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(commandersField, &QLineEdit::textChanged, this, [=](const QString &text) {
|
|
||||||
searchModel->updateSearchResults(text);
|
|
||||||
QString pattern = ".*" + QRegularExpression::escape(text) + ".*";
|
|
||||||
proxyModel->setFilterRegularExpression(QRegularExpression(pattern, QRegularExpression::CaseInsensitiveOption));
|
|
||||||
if (!text.isEmpty())
|
|
||||||
completer->complete();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Assemble secondary toolbar
|
|
||||||
secondaryToolbarLayout->addWidget(bracketLabel);
|
|
||||||
secondaryToolbarLayout->addWidget(edhBracketCombo);
|
|
||||||
secondaryToolbarLayout->addWidget(formatButton);
|
|
||||||
secondaryToolbarLayout->addWidget(cardsField);
|
|
||||||
secondaryToolbarLayout->addWidget(commandersField);
|
|
||||||
secondaryToolbarLayout->addWidget(deckTagNameField);
|
|
||||||
secondaryToolbarLayout->addWidget(deckSizeButton);
|
|
||||||
secondaryToolbarLayout->addStretch();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabArchidekt::connectSignals()
|
|
||||||
{
|
|
||||||
// Advanced filters toggle
|
|
||||||
connect(advancedFiltersButton, &QPushButton::clicked, this,
|
|
||||||
[this](bool checked) { secondaryToolbar->setVisible(checked); });
|
|
||||||
|
|
||||||
// These trigger immediate search (no debounce needed)
|
|
||||||
connect(orderByCombo, &QComboBox::currentTextChanged, this, &TabArchidekt::doSearch);
|
|
||||||
connect(orderDirButton, &QPushButton::clicked, [this](bool checked) {
|
|
||||||
orderDirButton->setText(checked ? tr("Desc.") : tr("Asc."));
|
|
||||||
doSearch();
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(cardSizeSlider, &CardSizeWidget::cardSizeSettingUpdated, &SettingsCache::instance(),
|
|
||||||
&SettingsCache::setArchidektPreviewCardSize);
|
|
||||||
|
|
||||||
// Search button triggers immediate search
|
|
||||||
connect(searchButton, &QPushButton::clicked, this, &TabArchidekt::doSearchImmediate);
|
|
||||||
|
|
||||||
// These trigger search (but not text fields)
|
|
||||||
connect(logicalAndCheck, &QCheckBox::clicked, this, &TabArchidekt::doSearch);
|
|
||||||
connect(packagesCheck, &QCheckBox::clicked, [this]() {
|
|
||||||
updatePackageModeState(packagesCheck->isChecked());
|
|
||||||
doSearch();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Format filters trigger search
|
|
||||||
connect(edhBracketCombo, &QComboBox::currentTextChanged, this, &TabArchidekt::doSearch);
|
|
||||||
connect(minDeckSizeSpin, qOverload<int>(&QSpinBox::valueChanged), this, &TabArchidekt::doSearch);
|
|
||||||
connect(minDeckSizeLogicCombo, &QComboBox::currentTextChanged, this, &TabArchidekt::doSearch);
|
|
||||||
|
|
||||||
// Allow Enter key in text fields to trigger search
|
|
||||||
connect(nameField, &QLineEdit::returnPressed, this, &TabArchidekt::doSearchImmediate);
|
|
||||||
connect(ownerField, &QLineEdit::returnPressed, this, &TabArchidekt::doSearchImmediate);
|
|
||||||
connect(cardsField, &QLineEdit::returnPressed, this, &TabArchidekt::doSearchImmediate);
|
|
||||||
connect(commandersField, &QLineEdit::returnPressed, this, &TabArchidekt::doSearchImmediate);
|
|
||||||
connect(deckTagNameField, &QLineEdit::returnPressed, this, &TabArchidekt::doSearchImmediate);
|
|
||||||
|
|
||||||
// Format checkboxes trigger search
|
|
||||||
for (auto *formatCheck : formatChecks) {
|
|
||||||
connect(formatCheck, &QCheckBox::clicked, this, &TabArchidekt::doSearch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabArchidekt::updatePackageModeState(bool isPackageMode)
|
|
||||||
{
|
|
||||||
// Disable format-specific and commander-specific filters in package mode
|
|
||||||
for (auto *cb : formatChecks) {
|
|
||||||
cb->setEnabled(!isPackageMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
edhBracketCombo->setEnabled(!isPackageMode);
|
|
||||||
if (isPackageMode) {
|
|
||||||
edhBracketCombo->setCurrentIndex(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
commandersField->setEnabled(!isPackageMode);
|
|
||||||
deckTagNameField->setEnabled(!isPackageMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabArchidekt::retranslateUi()
|
|
||||||
{
|
|
||||||
sortByLabel->setText(tr("Sort by:"));
|
|
||||||
orderDirButton->setText(orderDirButton->isChecked() ? tr("Desc.") : tr("Asc."));
|
|
||||||
|
|
||||||
filterByLabel->setText(tr("Filter by:"));
|
|
||||||
|
|
||||||
logicalAndCheck->setText(tr("AND"));
|
|
||||||
logicalAndCheck->setToolTip(tr("Require ALL selected colors"));
|
|
||||||
|
|
||||||
nameField->setPlaceholderText(tr("Deck name..."));
|
|
||||||
ownerField->setPlaceholderText(tr("Owner..."));
|
|
||||||
packagesCheck->setText(tr("Packages"));
|
|
||||||
advancedFiltersButton->setText(tr("Advanced Filters"));
|
|
||||||
|
|
||||||
cardsField->setPlaceholderText(tr("Contains card..."));
|
|
||||||
commandersField->setPlaceholderText(tr("Commander..."));
|
|
||||||
deckTagNameField->setPlaceholderText(tr("Tag..."));
|
|
||||||
|
|
||||||
formatButton->setButtonText(tr("Formats"));
|
|
||||||
deckSizeButton->setButtonText(tr("Deck Size"));
|
|
||||||
|
|
||||||
searchButton->setText(tr("Search"));
|
|
||||||
|
|
||||||
settingsButton->setToolTip(tr("Display Settings"));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString TabArchidekt::buildSearchUrl()
|
|
||||||
{
|
|
||||||
QUrlQuery query;
|
|
||||||
|
|
||||||
// orderBy (field + direction)
|
|
||||||
QString field = orderByCombo->currentText();
|
|
||||||
if (!field.isEmpty()) {
|
|
||||||
bool desc = orderDirButton->isChecked();
|
|
||||||
QString final = desc ? "-" + field : field;
|
|
||||||
query.addQueryItem("orderBy", final);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Colors
|
|
||||||
QStringList selectedColors;
|
|
||||||
for (QChar c : activeColors) {
|
|
||||||
selectedColors.append(c);
|
|
||||||
}
|
|
||||||
if (!selectedColors.isEmpty()) {
|
|
||||||
query.addQueryItem("colors", selectedColors.join(","));
|
|
||||||
}
|
|
||||||
|
|
||||||
// logicalAnd
|
|
||||||
if (logicalAndCheck->isChecked()) {
|
|
||||||
query.addQueryItem("logicalAnd", "true");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Formats (disabled in package mode)
|
|
||||||
if (!packagesCheck->isChecked()) {
|
|
||||||
QStringList formatIds;
|
|
||||||
for (int i = 0; i < formatChecks.size(); ++i) {
|
|
||||||
if (formatChecks[i]->isChecked()) {
|
|
||||||
formatIds << QString::number(i + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!formatIds.isEmpty()) {
|
|
||||||
query.addQueryItem("deckFormat", formatIds.join(","));
|
|
||||||
}
|
|
||||||
|
|
||||||
// edhBracket
|
|
||||||
if (edhBracketCombo->currentIndex() > 0) {
|
|
||||||
query.addQueryItem("edhBracket", edhBracketCombo->currentText());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Package mode
|
|
||||||
if (packagesCheck->isChecked()) {
|
|
||||||
query.addQueryItem("packages", "true");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name
|
|
||||||
if (!nameField->text().isEmpty()) {
|
|
||||||
query.addQueryItem("name", nameField->text());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Owner
|
|
||||||
if (!ownerField->text().isEmpty()) {
|
|
||||||
query.addQueryItem("ownerUsername", ownerField->text());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cards
|
|
||||||
if (!cardsField->text().isEmpty()) {
|
|
||||||
query.addQueryItem("cards", cardsField->text());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Commander (disabled in package mode)
|
|
||||||
if (!packagesCheck->isChecked() && !commandersField->text().isEmpty()) {
|
|
||||||
query.addQueryItem("commanderName", commandersField->text());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deck tag (disabled in package mode)
|
|
||||||
if (!packagesCheck->isChecked() && !deckTagNameField->text().isEmpty()) {
|
|
||||||
query.addQueryItem("deckTagName", deckTagNameField->text());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page number (for infinite scroll)
|
|
||||||
query.addQueryItem("page", QString::number(currentPage));
|
|
||||||
|
|
||||||
// Min deck size
|
|
||||||
if (minDeckSizeSpin->value() != 0) {
|
|
||||||
query.addQueryItem("size", QString::number(minDeckSizeSpin->value()));
|
|
||||||
|
|
||||||
QString logic = "GTE";
|
|
||||||
QString selected = minDeckSizeLogicCombo->currentText();
|
|
||||||
if (selected == "≥")
|
|
||||||
logic = "GTE";
|
|
||||||
else if (selected == "≤")
|
|
||||||
logic = "LTE";
|
|
||||||
else
|
|
||||||
logic = "";
|
|
||||||
|
|
||||||
if (!logic.isEmpty()) {
|
|
||||||
query.addQueryItem("sizeLogic", logic);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QUrl url("https://archidekt.com/api/decks/v3/");
|
|
||||||
url.setQuery(query);
|
|
||||||
|
|
||||||
return url.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabArchidekt::doSearch()
|
|
||||||
{
|
|
||||||
// Reset to first page on new search
|
|
||||||
currentPage = 1;
|
|
||||||
// We're searching, so we'll be in list mode
|
|
||||||
isListMode = true;
|
|
||||||
// Don't debounce - only called by explicit user actions now
|
|
||||||
doSearchImmediate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabArchidekt::doSearchImmediate()
|
|
||||||
{
|
|
||||||
QString url = buildSearchUrl();
|
|
||||||
QNetworkRequest req{QUrl(url)};
|
|
||||||
req.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING));
|
|
||||||
networkManager->get(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabArchidekt::loadNextPage()
|
|
||||||
{
|
|
||||||
if (isLoadingMore) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
isLoadingMore = true;
|
|
||||||
currentPage++;
|
|
||||||
|
|
||||||
QString url = buildSearchUrl();
|
|
||||||
QNetworkRequest req{QUrl(url)};
|
|
||||||
req.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING));
|
|
||||||
networkManager->get(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabArchidekt::actNavigatePage(QString url)
|
|
||||||
{
|
|
||||||
QNetworkRequest request{QUrl(url)};
|
|
||||||
request.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING));
|
|
||||||
networkManager->get(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabArchidekt::getTopDecks()
|
|
||||||
{
|
|
||||||
currentPage = 1;
|
|
||||||
QNetworkRequest request{QUrl(buildSearchUrl())};
|
|
||||||
request.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING));
|
|
||||||
networkManager->get(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabArchidekt::processApiJson(QNetworkReply *reply)
|
|
||||||
{
|
|
||||||
if (reply->error() != QNetworkReply::NoError) {
|
|
||||||
isLoadingMore = false;
|
|
||||||
reply->deleteLater();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray responseData = reply->readAll();
|
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(responseData);
|
|
||||||
|
|
||||||
if (!jsonDoc.isObject()) {
|
|
||||||
isLoadingMore = false;
|
|
||||||
reply->deleteLater();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject jsonObj = jsonDoc.object();
|
|
||||||
QString responseUrl = reply->url().toString();
|
|
||||||
|
|
||||||
if (responseUrl.startsWith("https://archidekt.com/api/decks/v3/")) {
|
|
||||||
processTopDecksResponse(jsonObj);
|
|
||||||
} else if (responseUrl.startsWith("https://archidekt.com/api/decks/")) {
|
|
||||||
processDeckResponse(jsonObj);
|
|
||||||
} else {
|
|
||||||
prettyPrintJson(jsonObj, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
isLoadingMore = false;
|
|
||||||
reply->deleteLater();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabArchidekt::processTopDecksResponse(QJsonObject reply)
|
|
||||||
{
|
|
||||||
ArchidektDeckListingApiResponse deckData;
|
|
||||||
deckData.fromJson(reply);
|
|
||||||
|
|
||||||
// New search → clear everything
|
|
||||||
if (currentPage == 1) {
|
|
||||||
QLayoutItem *item;
|
|
||||||
while ((item = resultsLayout->takeAt(0)) != nullptr) {
|
|
||||||
delete item->widget();
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
|
|
||||||
listingsWidget = new ArchidektApiResponseDeckListingsDisplayWidget(resultsContainer, deckData, cardSizeSlider);
|
|
||||||
|
|
||||||
connect(listingsWidget, &ArchidektApiResponseDeckListingsDisplayWidget::requestNavigation, this,
|
|
||||||
&TabArchidekt::actNavigatePage);
|
|
||||||
|
|
||||||
resultsLayout->addWidget(listingsWidget);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Infinite scroll → append
|
|
||||||
if (listingsWidget) {
|
|
||||||
listingsWidget->append(deckData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabArchidekt::processDeckResponse(QJsonObject reply)
|
|
||||||
{
|
|
||||||
ArchidektApiResponseDeck deckData;
|
|
||||||
deckData.fromJson(reply);
|
|
||||||
|
|
||||||
// We're in single deck mode - disable infinite scroll
|
|
||||||
isListMode = false;
|
|
||||||
|
|
||||||
// Clear existing results for single deck view
|
|
||||||
QLayoutItem *item;
|
|
||||||
while ((item = resultsLayout->takeAt(0)) != nullptr) {
|
|
||||||
delete item->widget();
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto display = new ArchidektApiResponseDeckDisplayWidget(resultsContainer, deckData, cardSizeSlider);
|
|
||||||
connect(display, &ArchidektApiResponseDeckDisplayWidget::requestNavigation, this, &TabArchidekt::actNavigatePage);
|
|
||||||
connect(display, &ArchidektApiResponseDeckDisplayWidget::requestSearch, this, &TabArchidekt::doSearchImmediate);
|
|
||||||
connect(display, &ArchidektApiResponseDeckDisplayWidget::openInDeckEditor, tabSupervisor,
|
|
||||||
&TabSupervisor::openDeckInNewTab);
|
|
||||||
resultsLayout->addWidget(display);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabArchidekt::prettyPrintJson(const QJsonValue &value, int indentLevel)
|
|
||||||
{
|
|
||||||
const QString indent(indentLevel * 2, ' ');
|
|
||||||
|
|
||||||
if (value.isObject()) {
|
|
||||||
QJsonObject obj = value.toObject();
|
|
||||||
for (auto it = obj.begin(); it != obj.end(); ++it) {
|
|
||||||
qInfo().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) {
|
|
||||||
qInfo().noquote() << indent + QString("[%1]:").arg(i);
|
|
||||||
prettyPrintJson(array[i], indentLevel + 1);
|
|
||||||
}
|
|
||||||
} else if (value.isString()) {
|
|
||||||
qInfo().noquote() << indent + "\"" + value.toString() + "\"";
|
|
||||||
} else if (value.isDouble()) {
|
|
||||||
qInfo().noquote() << indent + QString::number(value.toDouble());
|
|
||||||
} else if (value.isBool()) {
|
|
||||||
qInfo().noquote() << indent + (value.toBool() ? "true" : "false");
|
|
||||||
} else if (value.isNull()) {
|
|
||||||
qInfo().noquote() << indent + "null";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,294 +0,0 @@
|
||||||
#ifndef COCKATRICE_TAB_ARCHIDEKT_H
|
|
||||||
#define COCKATRICE_TAB_ARCHIDEKT_H
|
|
||||||
|
|
||||||
#include "../../interface/widgets/cards/card_size_widget.h"
|
|
||||||
#include "../../interface/widgets/quick_settings/settings_button_widget.h"
|
|
||||||
#include "../../tab.h"
|
|
||||||
#include "display/archidekt_api_response_deck_listings_display_widget.h"
|
|
||||||
|
|
||||||
#include <QCheckBox>
|
|
||||||
#include <QComboBox>
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QNetworkAccessManager>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QScrollArea>
|
|
||||||
#include <QSet>
|
|
||||||
#include <QSpinBox>
|
|
||||||
#include <QString>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QWidget>
|
|
||||||
#include <libcockatrice/card/database/card_database.h>
|
|
||||||
|
|
||||||
/** Base API link for Archidekt deck search */
|
|
||||||
inline QString archidektApiLink = "https://archidekt.com/api/decks/v3/?name=";
|
|
||||||
|
|
||||||
class ManaSymbolWidget;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Tab for browsing, searching, and filtering Archidekt decks.
|
|
||||||
*
|
|
||||||
* This class provides a comprehensive interface for querying decks from the Archidekt API.
|
|
||||||
* Users can filter decks by name, owner, included cards, commanders, deck tags, colors, EDH bracket,
|
|
||||||
* and formats. It supports infinite scroll pagination for seamless browsing.
|
|
||||||
*/
|
|
||||||
class TabArchidekt : public Tab
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Construct a new TabArchidekt object
|
|
||||||
* @param _tabSupervisor Parent tab supervisor responsible for tab management and callbacks
|
|
||||||
*
|
|
||||||
* Initializes the network manager, creates all UI components, sets up layouts,
|
|
||||||
* connects signals and slots, and triggers an initial fetch of top decks.
|
|
||||||
*/
|
|
||||||
explicit TabArchidekt(TabSupervisor *_tabSupervisor);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Update all UI text to reflect the current language or translation
|
|
||||||
*
|
|
||||||
* This function re-applies translations to all labels, buttons, and placeholders.
|
|
||||||
* It should be called after a language change.
|
|
||||||
*/
|
|
||||||
void retranslateUi() override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Construct the search URL from all current filters
|
|
||||||
* @return QString Fully constructed URL including all query parameters
|
|
||||||
*
|
|
||||||
* The search URL is dynamically built using the state of all filter widgets.
|
|
||||||
* Parameters included:
|
|
||||||
* - Deck name
|
|
||||||
* - Owner
|
|
||||||
* - Included cards
|
|
||||||
* - Commander cards
|
|
||||||
* - Deck tag
|
|
||||||
* - Colors and logical AND requirement
|
|
||||||
* - Formats
|
|
||||||
* - EDH bracket
|
|
||||||
* - Packages toggle
|
|
||||||
* - Sorting field and direction
|
|
||||||
* - Minimum amount of cards in the deck
|
|
||||||
* - Current page (for infinite scroll)
|
|
||||||
*/
|
|
||||||
QString buildSearchUrl();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Retrieve the tab display text
|
|
||||||
* @return QString Human-readable title for the tab
|
|
||||||
*
|
|
||||||
* If a card is pre-selected (cardToQuery), its name is appended to the tab title.
|
|
||||||
*/
|
|
||||||
QString getTabText() const override
|
|
||||||
{
|
|
||||||
auto cardName = cardToQuery.isNull() ? QString() : cardToQuery->getName();
|
|
||||||
return tr("Archidekt: ") + cardName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the card size slider widget
|
|
||||||
* @return CardSizeWidget* Pointer to the card size adjustment slider
|
|
||||||
*
|
|
||||||
* Allows external code to read or manipulate the current card size or hook up the sliders signals.
|
|
||||||
*/
|
|
||||||
CardSizeWidget *getCardSizeSlider()
|
|
||||||
{
|
|
||||||
return cardSizeSlider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
/**
|
|
||||||
* @brief Trigger a debounced search using the current filters
|
|
||||||
*
|
|
||||||
* Resets to page 1 and starts the debounce timer. The actual search will execute
|
|
||||||
* after 300ms of inactivity.
|
|
||||||
*/
|
|
||||||
void doSearch();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Immediately trigger a search using the current filters
|
|
||||||
*
|
|
||||||
* Sends a network request to the Archidekt API using the URL generated by buildSearchUrl().
|
|
||||||
* Updates the results display asynchronously.
|
|
||||||
*/
|
|
||||||
void doSearchImmediate();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Load the next page of results for infinite scroll
|
|
||||||
*
|
|
||||||
* Increments the current page and fetches additional results, which are appended
|
|
||||||
* to the existing results display.
|
|
||||||
*/
|
|
||||||
void loadNextPage();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Process a network reply containing JSON data
|
|
||||||
* @param reply QNetworkReply object with the API response
|
|
||||||
*
|
|
||||||
* Determines whether the response corresponds to a deck listing or a single deck,
|
|
||||||
* and dispatches it to the appropriate handler.
|
|
||||||
*/
|
|
||||||
void processApiJson(QNetworkReply *reply);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Handle a JSON response containing multiple decks
|
|
||||||
* @param reply QJsonObject containing deck listings
|
|
||||||
*
|
|
||||||
* If this is page 1, clears previous results. Appends new results to the display.
|
|
||||||
*/
|
|
||||||
void processTopDecksResponse(QJsonObject reply);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Handle a JSON response for a single deck
|
|
||||||
* @param reply QJsonObject containing deck data
|
|
||||||
*
|
|
||||||
* Clears the results area and displays the single deck details.
|
|
||||||
*/
|
|
||||||
void processDeckResponse(QJsonObject reply);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Pretty-print a QJsonValue for debugging
|
|
||||||
* @param value The JSON value to print
|
|
||||||
* @param indentLevel The indentation depth (number of levels)
|
|
||||||
*/
|
|
||||||
void prettyPrintJson(const QJsonValue &value, int indentLevel);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Navigate to a specified page URL
|
|
||||||
* @param url The URL to request
|
|
||||||
*
|
|
||||||
* Typically called when a deck card is clicked in the listing.
|
|
||||||
*/
|
|
||||||
void actNavigatePage(QString url);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Fetch top decks from the Archidekt API
|
|
||||||
*
|
|
||||||
* Called on initialization to populate the initial results display.
|
|
||||||
*/
|
|
||||||
void getTopDecks();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* @brief Event filter to catch wheel events for infinite scroll
|
|
||||||
* @param obj The object that received the event
|
|
||||||
* @param event The event to filter
|
|
||||||
* @return bool Whether the event was handled
|
|
||||||
*/
|
|
||||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* @brief Initialize the main UI layout and toolbars
|
|
||||||
*
|
|
||||||
* Creates the container, main layout, primary toolbar (sort, colors, name, owner, packages),
|
|
||||||
* secondary toolbar (advanced filters), and scrollable results area.
|
|
||||||
*/
|
|
||||||
void initializeUi();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set up all filter widgets
|
|
||||||
*
|
|
||||||
* Creates filter widgets for:
|
|
||||||
* - Card search with autocomplete
|
|
||||||
* - Commander search with autocomplete
|
|
||||||
* - Deck tags
|
|
||||||
* - Format selection (collapsible)
|
|
||||||
* - Deck size filter (collapsible)
|
|
||||||
*/
|
|
||||||
void setupFilterWidgets();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Connect all signals and slots for UI interactions
|
|
||||||
*
|
|
||||||
* Links all widget signals to their appropriate handlers, including
|
|
||||||
* search triggers, filter changes, package mode toggling, and infinite scroll.
|
|
||||||
*/
|
|
||||||
void connectSignals();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Update UI state when package mode is toggled
|
|
||||||
* @param isPackageMode Whether package mode is currently enabled
|
|
||||||
*
|
|
||||||
* Disables format-specific and commander-specific filters when searching
|
|
||||||
* for card packages instead of full decks.
|
|
||||||
*/
|
|
||||||
void updatePackageModeState(bool isPackageMode);
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
|
||||||
// Network & Timing
|
|
||||||
// ---------------------------------------------------------------------
|
|
||||||
|
|
||||||
QNetworkAccessManager *networkManager; ///< Network manager for handling API requests
|
|
||||||
QTimer *searchDebounceTimer; ///< Timer to debounce search requests
|
|
||||||
int currentPage; ///< Current page number for infinite scroll
|
|
||||||
bool isLoadingMore; ///< Flag to prevent multiple simultaneous page loads
|
|
||||||
bool isListMode;
|
|
||||||
ArchidektApiResponseDeckListingsDisplayWidget *listingsWidget = nullptr;
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
|
||||||
// Layout Containers
|
|
||||||
// ---------------------------------------------------------------------
|
|
||||||
|
|
||||||
QWidget *container; ///< Root container for the entire tab
|
|
||||||
QVBoxLayout *mainLayout; ///< Outer vertical layout containing toolbars and results
|
|
||||||
|
|
||||||
QWidget *primaryToolbar; ///< Primary toolbar with most important filters
|
|
||||||
QHBoxLayout *primaryToolbarLayout; ///< Layout for primary toolbar
|
|
||||||
|
|
||||||
QWidget *secondaryToolbar; ///< Secondary toolbar with advanced filters
|
|
||||||
QHBoxLayout *secondaryToolbarLayout; ///< Layout for secondary toolbar
|
|
||||||
|
|
||||||
QScrollArea *scrollArea; ///< Scrollable area for results (enables infinite scroll)
|
|
||||||
QWidget *resultsContainer; ///< Container widget inside scroll area
|
|
||||||
QVBoxLayout *resultsLayout; ///< Layout for results (decks appended here)
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
|
||||||
// Primary Toolbar Controls (Most Important)
|
|
||||||
// ---------------------------------------------------------------------
|
|
||||||
|
|
||||||
QLabel *sortByLabel; ///< Label for sort controls
|
|
||||||
QComboBox *orderByCombo; ///< Dropdown for selecting the sort field
|
|
||||||
QPushButton *orderDirButton; ///< Toggle button for ascending/descending sort
|
|
||||||
|
|
||||||
QLabel *filterByLabel; ///< Label for filter controls
|
|
||||||
QList<ManaSymbolWidget *> colorSymbols; ///< Mana symbol toggle buttons
|
|
||||||
QSet<QChar> activeColors; ///< Set of currently active mana colors
|
|
||||||
QCheckBox *logicalAndCheck; ///< Require ALL selected colors instead of ANY
|
|
||||||
|
|
||||||
QLineEdit *nameField; ///< Input for deck name filter
|
|
||||||
QLineEdit *ownerField; ///< Input for owner name filter
|
|
||||||
QCheckBox *packagesCheck; ///< Toggle for searching card packages instead of full decks
|
|
||||||
QPushButton *searchButton; ///< Button to trigger search
|
|
||||||
QPushButton *advancedFiltersButton; ///< Button to show/hide advanced filters
|
|
||||||
|
|
||||||
SettingsButtonWidget *settingsButton; ///< Container for card size settings
|
|
||||||
CardSizeWidget *cardSizeSlider; ///< Slider to adjust card size in results
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
|
||||||
// Secondary Toolbar Controls (Advanced Filters)
|
|
||||||
// ---------------------------------------------------------------------
|
|
||||||
|
|
||||||
QLineEdit *cardsField; ///< Input for cards included in the deck
|
|
||||||
QLineEdit *commandersField; ///< Input for commander cards
|
|
||||||
QLineEdit *deckTagNameField; ///< Input for deck tag filtering
|
|
||||||
|
|
||||||
SettingsButtonWidget *formatButton; ///< Collapsible button for format filters
|
|
||||||
QVector<QCheckBox *> formatChecks; ///< Individual checkboxes for each format
|
|
||||||
QComboBox *edhBracketCombo; ///< Dropdown for EDH bracket selection
|
|
||||||
|
|
||||||
SettingsButtonWidget *deckSizeButton; ///< Collapsible button for deck size filter
|
|
||||||
QSpinBox *minDeckSizeSpin; ///< Spinner to select minimum deck size
|
|
||||||
QComboBox *minDeckSizeLogicCombo; ///< Combo box for size comparison logic
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
|
||||||
// Optional Context
|
|
||||||
// ---------------------------------------------------------------------
|
|
||||||
|
|
||||||
CardInfoPtr cardToQuery; ///< Optional pre-selected card for initial filtering
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // COCKATRICE_TAB_ARCHIDEKT_H
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
#include "edhrec_api_response_archidekt_links.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QJsonObject>
|
|
||||||
|
|
||||||
void EdhrecApiResponseArchidektLink::fromJson(const QJsonObject &json)
|
|
||||||
{
|
|
||||||
c = json.value("c").toString();
|
|
||||||
f = json.value("f").toInt(0);
|
|
||||||
q = json.value("q").toInt(0);
|
|
||||||
u = json.value("u").toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecApiResponseArchidektLink::debugPrint() const
|
|
||||||
{
|
|
||||||
qDebug() << " C:" << c;
|
|
||||||
qDebug() << " F:" << f;
|
|
||||||
qDebug() << " Q:" << q;
|
|
||||||
qDebug() << " U:" << u;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecCommanderApiResponseArchidektLinks::fromJson(const QJsonArray &json)
|
|
||||||
{
|
|
||||||
entries.clear();
|
|
||||||
for (const QJsonValue &value : json) {
|
|
||||||
if (value.isObject()) {
|
|
||||||
QJsonObject entryJson = value.toObject();
|
|
||||||
EdhrecApiResponseArchidektLink entry;
|
|
||||||
entry.fromJson(entryJson);
|
|
||||||
entries.append(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecCommanderApiResponseArchidektLinks::debugPrint() const
|
|
||||||
{
|
|
||||||
qDebug() << "Archidekt Entries:";
|
|
||||||
for (const auto &entry : entries) {
|
|
||||||
entry.debugPrint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
#ifndef ARCHIDEKTENTRY_H
|
|
||||||
#define ARCHIDEKTENTRY_H
|
|
||||||
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QString>
|
|
||||||
#include <QVector>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class EdhrecApiResponseArchidektLink
|
|
||||||
* @ingroup ApiResponses
|
|
||||||
* @brief Represents a single Archidekt entry
|
|
||||||
*/
|
|
||||||
class EdhrecApiResponseArchidektLink
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QString c;
|
|
||||||
int f = 0;
|
|
||||||
int q = 0;
|
|
||||||
QString u;
|
|
||||||
|
|
||||||
void fromJson(const QJsonObject &json);
|
|
||||||
void debugPrint() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class EdhrecCommanderApiResponseArchidektLinks
|
|
||||||
* @ingroup ApiResponses
|
|
||||||
* @brief Represents the Archidekt section as a list of entries
|
|
||||||
*/
|
|
||||||
class EdhrecCommanderApiResponseArchidektLinks
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QVector<EdhrecApiResponseArchidektLink> entries;
|
|
||||||
|
|
||||||
void fromJson(const QJsonArray &json);
|
|
||||||
void debugPrint() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // ARCHIDEKTENTRY_H
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
#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();
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
#ifndef EDHREC_AVERAGE_DECK_API_RESPONSE_H
|
|
||||||
#define EDHREC_AVERAGE_DECK_API_RESPONSE_H
|
|
||||||
|
|
||||||
#include "../archidekt_links/edhrec_api_response_archidekt_links.h"
|
|
||||||
#include "../cards/edhrec_api_response_card_container.h"
|
|
||||||
#include "../commander/edhrec_commander_api_response_average_deck_statistics.h"
|
|
||||||
#include "edhrec_deck_api_response.h"
|
|
||||||
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class EdhrecAverageDeckApiResponse
|
|
||||||
* @ingroup ApiResponses
|
|
||||||
* @brief Represents the main structure of the JSON
|
|
||||||
*/
|
|
||||||
class EdhrecAverageDeckApiResponse
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
EdhrecCommanderApiResponseAverageDeckStatistics deckStats;
|
|
||||||
EdhrecCommanderApiResponseArchidektLinks archidekt;
|
|
||||||
QJsonObject similar;
|
|
||||||
QString header;
|
|
||||||
QJsonObject panels;
|
|
||||||
QString description;
|
|
||||||
EdhrecApiResponseCardContainer container;
|
|
||||||
EdhrecDeckApiResponse deck;
|
|
||||||
|
|
||||||
void fromJson(const QJsonObject &json);
|
|
||||||
void debugPrint() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EDHREC_AVERAGE_DECK_API_RESPONSE_H
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
#include "edhrec_deck_api_response.h"
|
|
||||||
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <libcockatrice/card/import/card_name_normalizer.h>
|
|
||||||
|
|
||||||
void EdhrecDeckApiResponse::fromJson(const QJsonArray &json)
|
|
||||||
{
|
|
||||||
QString deckList;
|
|
||||||
for (const QJsonValue &cardlistValue : json) {
|
|
||||||
deckList += cardlistValue.toString() + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
QTextStream stream(&deckList);
|
|
||||||
deck.loadFromStream_Plain(stream, true, CardNameNormalizer());
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecDeckApiResponse::debugPrint() const
|
|
||||||
{
|
|
||||||
qDebug() << "Breadcrumb:";
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
/**
|
|
||||||
* @file edhrec_deck_api_response.h
|
|
||||||
* @ingroup ApiResponses
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EDHREC_DECK_API_RESPONSE_H
|
|
||||||
#define EDHREC_DECK_API_RESPONSE_H
|
|
||||||
|
|
||||||
#include "../../../../../../deck_loader/deck_loader.h"
|
|
||||||
|
|
||||||
class EdhrecDeckApiResponse
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Constructor
|
|
||||||
EdhrecDeckApiResponse() = default;
|
|
||||||
|
|
||||||
// Parse deck-related data from JSON
|
|
||||||
void fromJson(const QJsonArray &json);
|
|
||||||
|
|
||||||
// Debug method for logging
|
|
||||||
void debugPrint() const;
|
|
||||||
|
|
||||||
DeckList deck;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EDHREC_DECK_API_RESPONSE_H
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
#include "edhrec_api_response_card_prices.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
void CardPrices::fromJson(const QJsonObject &json)
|
|
||||||
{
|
|
||||||
// Parse prices from various sources
|
|
||||||
cardhoarder = json.value("cardhoarder").toObject();
|
|
||||||
cardkingdom = json.value("cardkingdom").toObject();
|
|
||||||
cardmarket = json.value("cardmarket").toObject();
|
|
||||||
face2face = json.value("face2face").toObject();
|
|
||||||
manapool = json.value("manapool").toObject();
|
|
||||||
mtgstocks = json.value("mtgstocks").toObject();
|
|
||||||
scg = json.value("scg").toObject();
|
|
||||||
tcgl = json.value("tcgl").toObject();
|
|
||||||
tcgplayer = json.value("tcgplayer").toObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CardPrices::debugPrint() const
|
|
||||||
{
|
|
||||||
qInfo() << "Card Prices:";
|
|
||||||
qInfo() << "Cardhoarder:" << cardhoarder;
|
|
||||||
qInfo() << "Cardkingdom:" << cardkingdom;
|
|
||||||
qInfo() << "Cardmarket:" << cardmarket;
|
|
||||||
qInfo() << "Face2Face:" << face2face;
|
|
||||||
qInfo() << "Manapool:" << manapool;
|
|
||||||
qInfo() << "Mtgstocks:" << mtgstocks;
|
|
||||||
qInfo() << "SCG:" << scg;
|
|
||||||
qInfo() << "TCGL:" << tcgl;
|
|
||||||
qInfo() << "Tcgplayer:" << tcgplayer;
|
|
||||||
}
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
/**
|
|
||||||
* @file edhrec_api_response_card_prices.h
|
|
||||||
* @ingroup ApiResponses
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EDHREC_COMMANDER_API_RESPONSE_CARD_PRICES_H
|
|
||||||
#define EDHREC_COMMANDER_API_RESPONSE_CARD_PRICES_H
|
|
||||||
|
|
||||||
#include <QJsonObject>
|
|
||||||
|
|
||||||
class CardPrices
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Constructor
|
|
||||||
CardPrices() = default;
|
|
||||||
|
|
||||||
// Parse prices from JSON
|
|
||||||
void fromJson(const QJsonObject &json);
|
|
||||||
void debugPrint() const;
|
|
||||||
|
|
||||||
// Getter methods for card prices
|
|
||||||
[[nodiscard]] const QJsonObject &getCardhoarder() const
|
|
||||||
{
|
|
||||||
return cardhoarder;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QJsonObject &getCardkingdom() const
|
|
||||||
{
|
|
||||||
return cardkingdom;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QJsonObject &getCardmarket() const
|
|
||||||
{
|
|
||||||
return cardmarket;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QJsonObject &getFace2face() const
|
|
||||||
{
|
|
||||||
return face2face;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QJsonObject &getManapool() const
|
|
||||||
{
|
|
||||||
return manapool;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QJsonObject &getMtgstocks() const
|
|
||||||
{
|
|
||||||
return mtgstocks;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QJsonObject &getScg() const
|
|
||||||
{
|
|
||||||
return scg;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QJsonObject &getTcgl() const
|
|
||||||
{
|
|
||||||
return tcgl;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QJsonObject &getTcgplayer() const
|
|
||||||
{
|
|
||||||
return tcgplayer;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
QJsonObject cardhoarder;
|
|
||||||
QJsonObject cardkingdom;
|
|
||||||
QJsonObject cardmarket;
|
|
||||||
QJsonObject face2face;
|
|
||||||
QJsonObject manapool;
|
|
||||||
QJsonObject mtgstocks;
|
|
||||||
QJsonObject scg;
|
|
||||||
QJsonObject tcgl;
|
|
||||||
QJsonObject tcgplayer;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EDHREC_COMMANDER_API_RESPONSE_CARD_PRICES_H
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
#include "edhrec_api_response_card_container.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QJsonObject>
|
|
||||||
|
|
||||||
void EdhrecApiResponseCardContainer::fromJson(const QJsonObject &json)
|
|
||||||
{
|
|
||||||
// Parse breadcrumb
|
|
||||||
QJsonArray breadcrumbArray = json.value("breadcrumb").toArray();
|
|
||||||
for (const QJsonValue &breadcrumbValue : breadcrumbArray) {
|
|
||||||
breadcrumb.push_back(breadcrumbValue.toObject());
|
|
||||||
}
|
|
||||||
|
|
||||||
description = json.value("description").toString();
|
|
||||||
QJsonObject jsonDict = json.value("json_dict").toObject();
|
|
||||||
card.fromJson(jsonDict.value("card").toObject());
|
|
||||||
QJsonArray cardlistsArray = jsonDict.value("cardlists").toArray();
|
|
||||||
|
|
||||||
for (const QJsonValue &cardlistValue : cardlistsArray) {
|
|
||||||
QJsonObject cardlistObj = cardlistValue.toObject();
|
|
||||||
QJsonArray cardviewsArray = cardlistObj.value("cardviews").toArray();
|
|
||||||
EdhrecApiResponseCardList cardView;
|
|
||||||
cardView.fromJson(cardlistValue.toObject());
|
|
||||||
cardlists.push_back(cardView);
|
|
||||||
}
|
|
||||||
|
|
||||||
keywords = json.value("keywords").toString();
|
|
||||||
title = json.value("title").toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecApiResponseCardContainer::debugPrint() const
|
|
||||||
{
|
|
||||||
qDebug() << "Breadcrumb:";
|
|
||||||
for (const auto &breadcrumbEntry : breadcrumb) {
|
|
||||||
qDebug() << breadcrumbEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << "Description:" << description;
|
|
||||||
card.debugPrint();
|
|
||||||
|
|
||||||
qDebug() << "Cardlists:";
|
|
||||||
for (const auto &cardlist : cardlists) {
|
|
||||||
cardlist.debugPrint();
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << "Keywords:" << keywords;
|
|
||||||
qDebug() << "Title:" << title;
|
|
||||||
}
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
/**
|
|
||||||
* @file edhrec_api_response_card_container.h
|
|
||||||
* @ingroup ApiResponses
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CONTAINER_ENTRY_H
|
|
||||||
#define CONTAINER_ENTRY_H
|
|
||||||
|
|
||||||
#include "edhrec_api_response_card_list.h"
|
|
||||||
#include "edhrec_commander_api_response_commander_details.h"
|
|
||||||
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QString>
|
|
||||||
#include <QVector>
|
|
||||||
|
|
||||||
class EdhrecApiResponseCardContainer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Constructor
|
|
||||||
EdhrecApiResponseCardContainer() = default;
|
|
||||||
|
|
||||||
// Parse deck-related data from JSON
|
|
||||||
void fromJson(const QJsonObject &json);
|
|
||||||
|
|
||||||
// Debug method for logging
|
|
||||||
void debugPrint() const;
|
|
||||||
|
|
||||||
// Getter methods for deck container
|
|
||||||
[[nodiscard]] const QString &getDescription() const
|
|
||||||
{
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QVector<QJsonObject> &getBreadcrumb() const
|
|
||||||
{
|
|
||||||
return breadcrumb;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const EdhrecCommanderApiResponseCommanderDetails &getCommanderDetails() const
|
|
||||||
{
|
|
||||||
return card;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QVector<EdhrecApiResponseCardList> &getCardlists() const
|
|
||||||
{
|
|
||||||
return cardlists;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QString &getKeywords() const
|
|
||||||
{
|
|
||||||
return keywords;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QString &getTitle() const
|
|
||||||
{
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString description;
|
|
||||||
QVector<QJsonObject> breadcrumb;
|
|
||||||
EdhrecCommanderApiResponseCommanderDetails card;
|
|
||||||
QVector<EdhrecApiResponseCardList> cardlists;
|
|
||||||
QString keywords;
|
|
||||||
QString title;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CONTAINER_ENTRY_H
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
#include "edhrec_api_response_card_details.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
EdhrecApiResponseCardDetails::EdhrecApiResponseCardDetails()
|
|
||||||
: synergy(0.0), inclusion(0), numDecks(0), potentialDecks(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecApiResponseCardDetails::fromJson(const QJsonObject &json)
|
|
||||||
{
|
|
||||||
// Parse the fields from the JSON object
|
|
||||||
name = json.value("name").toString();
|
|
||||||
sanitized = json.value("sanitized").toString();
|
|
||||||
sanitizedWo = json.value("sanitized_wo").toString();
|
|
||||||
url = json.value("url").toString();
|
|
||||||
synergy = json.value("synergy").toDouble(0.0);
|
|
||||||
inclusion = json.value("inclusion").toInt(0);
|
|
||||||
label = json.value("label").toString();
|
|
||||||
numDecks = json.value("num_decks").toInt(0);
|
|
||||||
potentialDecks = json.value("potential_decks").toInt(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecApiResponseCardDetails::debugPrint() const
|
|
||||||
{
|
|
||||||
// Print out all the fields for debugging
|
|
||||||
qDebug() << "Name:" << name;
|
|
||||||
qDebug() << "Sanitized:" << sanitized;
|
|
||||||
qDebug() << "Sanitized Wo:" << sanitizedWo;
|
|
||||||
qDebug() << "URL:" << url;
|
|
||||||
qDebug() << "Synergy:" << synergy;
|
|
||||||
qDebug() << "Inclusion:" << inclusion;
|
|
||||||
qDebug() << "Label:" << label;
|
|
||||||
qDebug() << "Num Decks:" << numDecks;
|
|
||||||
qDebug() << "Potential Decks:" << potentialDecks;
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
/**
|
|
||||||
* @file edhrec_api_response_card_details.h
|
|
||||||
* @ingroup ApiResponses
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CARD_VIEW_H
|
|
||||||
#define CARD_VIEW_H
|
|
||||||
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
class EdhrecApiResponseCardDetails
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QString name;
|
|
||||||
QString sanitized;
|
|
||||||
QString sanitizedWo;
|
|
||||||
QString url;
|
|
||||||
double synergy;
|
|
||||||
int inclusion;
|
|
||||||
QString label;
|
|
||||||
int numDecks;
|
|
||||||
int potentialDecks;
|
|
||||||
|
|
||||||
EdhrecApiResponseCardDetails();
|
|
||||||
|
|
||||||
// Method to populate the object from a JSON object
|
|
||||||
void fromJson(const QJsonObject &json);
|
|
||||||
|
|
||||||
// Debug method to print out the data
|
|
||||||
void debugPrint() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CARD_VIEW_H
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
#include "edhrec_api_response_card_list.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
EdhrecApiResponseCardList::EdhrecApiResponseCardList()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecApiResponseCardList::fromJson(const QJsonObject &json)
|
|
||||||
{
|
|
||||||
// Parse the header from the JSON object
|
|
||||||
header = json.value("header").toString();
|
|
||||||
|
|
||||||
// Parse the cardviews array and populate cardViews
|
|
||||||
QJsonArray cardviewsArray = json.value("cardviews").toArray();
|
|
||||||
for (const QJsonValue &value : cardviewsArray) {
|
|
||||||
QJsonObject cardviewObj = value.toObject();
|
|
||||||
EdhrecApiResponseCardDetails cardView;
|
|
||||||
cardView.fromJson(cardviewObj);
|
|
||||||
cardViews.append(cardView);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecApiResponseCardList::debugPrint() const
|
|
||||||
{
|
|
||||||
// Print out the header
|
|
||||||
qDebug() << "Header:" << header;
|
|
||||||
|
|
||||||
// Print out all the CardView objects
|
|
||||||
for (const EdhrecApiResponseCardDetails &cardView : cardViews) {
|
|
||||||
cardView.debugPrint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
/**
|
|
||||||
* @file edhrec_api_response_card_list.h
|
|
||||||
* @ingroup ApiResponses
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CARD_LIST_H
|
|
||||||
#define CARD_LIST_H
|
|
||||||
|
|
||||||
#include "edhrec_api_response_card_details.h"
|
|
||||||
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QList>
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
class EdhrecApiResponseCardList
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QString header;
|
|
||||||
QList<EdhrecApiResponseCardDetails> cardViews;
|
|
||||||
|
|
||||||
// Default constructor
|
|
||||||
EdhrecApiResponseCardList();
|
|
||||||
|
|
||||||
// Method to populate the object from a JSON object
|
|
||||||
void fromJson(const QJsonObject &json);
|
|
||||||
|
|
||||||
// Debug method to print out the data
|
|
||||||
void debugPrint() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CARD_LIST_H
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
#include "edhrec_commander_api_response_commander_details.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
void EdhrecCommanderApiResponseCommanderDetails::fromJson(const QJsonObject &json)
|
|
||||||
{
|
|
||||||
// Parse card-related data
|
|
||||||
aetherhubUri = json.value("aetherhub_uri").toString();
|
|
||||||
archidektUri = json.value("archidekt_uri").toString();
|
|
||||||
cmc = json.value("cmc").toInt(0);
|
|
||||||
colorIdentity = json.value("color_identity").toArray();
|
|
||||||
combos = json.value("combos").toBool(false);
|
|
||||||
deckstatsUri = json.value("deckstats_uri").toString();
|
|
||||||
|
|
||||||
// Parse image URIs
|
|
||||||
QJsonArray imageUrisArray = json.value("image_uris").toArray();
|
|
||||||
for (const QJsonValue &imageValue : imageUrisArray) {
|
|
||||||
QJsonObject imageObject = imageValue.toObject();
|
|
||||||
imageUris.push_back(imageObject.value("normal").toString());
|
|
||||||
imageUris.push_back(imageObject.value("art_crop").toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
inclusion = json.value("inclusion").toInt(0);
|
|
||||||
isCommander = json.value("is_commander").toBool(false);
|
|
||||||
label = json.value("label").toString();
|
|
||||||
layout = json.value("layout").toString();
|
|
||||||
legalCommander = json.value("legal_commander").toBool(false);
|
|
||||||
moxfieldUri = json.value("moxfield_uri").toString();
|
|
||||||
mtggoldfishUri = json.value("mtggoldfish_uri").toString();
|
|
||||||
name = json.value("name").toString();
|
|
||||||
names = json.value("names").toArray();
|
|
||||||
numDecks = json.value("num_decks").toInt(0);
|
|
||||||
potentialDecks = json.value("potential_decks").toInt(0);
|
|
||||||
precon = json.value("precon").toString();
|
|
||||||
|
|
||||||
// Parse prices
|
|
||||||
prices.fromJson(json.value("prices").toObject());
|
|
||||||
|
|
||||||
primaryType = json.value("primary_type").toString();
|
|
||||||
rarity = json.value("rarity").toString();
|
|
||||||
salt = json.value("salt").toDouble(0.0);
|
|
||||||
sanitized = json.value("sanitized").toString();
|
|
||||||
sanitizedWo = json.value("sanitized_wo").toString();
|
|
||||||
scryfallUri = json.value("scryfall_uri").toString();
|
|
||||||
spellbookUri = json.value("spellbook_uri").toString();
|
|
||||||
type = json.value("type").toString();
|
|
||||||
url = json.value("url").toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecCommanderApiResponseCommanderDetails::debugPrint() const
|
|
||||||
{
|
|
||||||
qDebug() << "Card Data:";
|
|
||||||
qDebug() << "Aetherhub URI:" << aetherhubUri;
|
|
||||||
qDebug() << "Archidekt URI:" << archidektUri;
|
|
||||||
qDebug() << "CMC:" << cmc;
|
|
||||||
qDebug() << "Color Identity:" << colorIdentity;
|
|
||||||
qDebug() << "Combos:" << combos;
|
|
||||||
qDebug() << "Deckstats URI:" << deckstatsUri;
|
|
||||||
|
|
||||||
qDebug() << "Image URIs:";
|
|
||||||
for (const auto &uri : imageUris) {
|
|
||||||
qDebug() << uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << "Inclusion:" << inclusion;
|
|
||||||
qDebug() << "Is Commander:" << isCommander;
|
|
||||||
qDebug() << "Label:" << label;
|
|
||||||
qDebug() << "Layout:" << layout;
|
|
||||||
qDebug() << "Legal Commander:" << legalCommander;
|
|
||||||
qDebug() << "Moxfield URI:" << moxfieldUri;
|
|
||||||
qDebug() << "MTGGoldfish URI:" << mtggoldfishUri;
|
|
||||||
qDebug() << "Name:" << name;
|
|
||||||
qDebug() << "Names:" << names;
|
|
||||||
qDebug() << "Number of Decks:" << numDecks;
|
|
||||||
qDebug() << "Potential Decks:" << potentialDecks;
|
|
||||||
qDebug() << "Precon:" << precon;
|
|
||||||
|
|
||||||
// Print the prices using the debugPrint method from CardPrices
|
|
||||||
prices.debugPrint();
|
|
||||||
|
|
||||||
qDebug() << "Primary Type:" << primaryType;
|
|
||||||
qDebug() << "Rarity:" << rarity;
|
|
||||||
qDebug() << "Salt:" << salt;
|
|
||||||
qDebug() << "Sanitized:" << sanitized;
|
|
||||||
qDebug() << "Sanitized WO:" << sanitizedWo;
|
|
||||||
qDebug() << "Scryfall URI:" << scryfallUri;
|
|
||||||
qDebug() << "Spellbook URI:" << spellbookUri;
|
|
||||||
qDebug() << "Type:" << type;
|
|
||||||
qDebug() << "URL:" << url;
|
|
||||||
}
|
|
||||||
|
|
@ -1,178 +0,0 @@
|
||||||
/**
|
|
||||||
* @file edhrec_commander_api_response_commander_details.h
|
|
||||||
* @ingroup ApiResponses
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_H
|
|
||||||
#define EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_H
|
|
||||||
|
|
||||||
#include "../card_prices/edhrec_api_response_card_prices.h"
|
|
||||||
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QString>
|
|
||||||
#include <QVector>
|
|
||||||
|
|
||||||
class EdhrecCommanderApiResponseCommanderDetails
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Constructor
|
|
||||||
EdhrecCommanderApiResponseCommanderDetails() = default;
|
|
||||||
|
|
||||||
// Parse card-related data from JSON
|
|
||||||
void fromJson(const QJsonObject &json);
|
|
||||||
|
|
||||||
// Debug method for logging
|
|
||||||
void debugPrint() const;
|
|
||||||
|
|
||||||
// Getters for the card data
|
|
||||||
[[nodiscard]] const QString &getAetherhubUri() const
|
|
||||||
{
|
|
||||||
return aetherhubUri;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QString &getArchidektUri() const
|
|
||||||
{
|
|
||||||
return archidektUri;
|
|
||||||
}
|
|
||||||
[[nodiscard]] int getCmc() const
|
|
||||||
{
|
|
||||||
return cmc;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QJsonArray &getColorIdentity() const
|
|
||||||
{
|
|
||||||
return colorIdentity;
|
|
||||||
}
|
|
||||||
[[nodiscard]] bool isCombos() const
|
|
||||||
{
|
|
||||||
return combos;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QString &getDeckstatsUri() const
|
|
||||||
{
|
|
||||||
return deckstatsUri;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QVector<QString> &getImageUris() const
|
|
||||||
{
|
|
||||||
return imageUris;
|
|
||||||
}
|
|
||||||
[[nodiscard]] int getInclusion() const
|
|
||||||
{
|
|
||||||
return inclusion;
|
|
||||||
}
|
|
||||||
[[nodiscard]] bool getIsCommander() const
|
|
||||||
{
|
|
||||||
return isCommander;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QString &getLabel() const
|
|
||||||
{
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QString &getLayout() const
|
|
||||||
{
|
|
||||||
return layout;
|
|
||||||
}
|
|
||||||
[[nodiscard]] bool getLegalCommander() const
|
|
||||||
{
|
|
||||||
return legalCommander;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QString &getMoxfieldUri() const
|
|
||||||
{
|
|
||||||
return moxfieldUri;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QString &getMtggoldfishUri() const
|
|
||||||
{
|
|
||||||
return mtggoldfishUri;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QString &getName() const
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QJsonArray &getNames() const
|
|
||||||
{
|
|
||||||
return names;
|
|
||||||
}
|
|
||||||
[[nodiscard]] int getNumDecks() const
|
|
||||||
{
|
|
||||||
return numDecks;
|
|
||||||
}
|
|
||||||
[[nodiscard]] int getPotentialDecks() const
|
|
||||||
{
|
|
||||||
return potentialDecks;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QString &getPrecon() const
|
|
||||||
{
|
|
||||||
return precon;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const CardPrices &getPrices() const
|
|
||||||
{
|
|
||||||
return prices;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QString &getPrimaryType() const
|
|
||||||
{
|
|
||||||
return primaryType;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QString &getRarity() const
|
|
||||||
{
|
|
||||||
return rarity;
|
|
||||||
}
|
|
||||||
[[nodiscard]] double getSalt() const
|
|
||||||
{
|
|
||||||
return salt;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QString &getSanitized() const
|
|
||||||
{
|
|
||||||
return sanitized;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QString &getSanitizedWo() const
|
|
||||||
{
|
|
||||||
return sanitizedWo;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QString &getScryfallUri() const
|
|
||||||
{
|
|
||||||
return scryfallUri;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QString &getSpellbookUri() const
|
|
||||||
{
|
|
||||||
return spellbookUri;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QString &getType() const
|
|
||||||
{
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
[[nodiscard]] const QString &getUrl() const
|
|
||||||
{
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString aetherhubUri;
|
|
||||||
QString archidektUri;
|
|
||||||
int cmc = 0;
|
|
||||||
QJsonArray colorIdentity;
|
|
||||||
bool combos = false;
|
|
||||||
QString deckstatsUri;
|
|
||||||
QVector<QString> imageUris;
|
|
||||||
int inclusion = 0;
|
|
||||||
bool isCommander = false;
|
|
||||||
QString label;
|
|
||||||
QString layout;
|
|
||||||
bool legalCommander = false;
|
|
||||||
QString moxfieldUri;
|
|
||||||
QString mtggoldfishUri;
|
|
||||||
QString name;
|
|
||||||
QJsonArray names;
|
|
||||||
int numDecks = 0;
|
|
||||||
int potentialDecks = 0;
|
|
||||||
QString precon;
|
|
||||||
CardPrices prices;
|
|
||||||
QString primaryType;
|
|
||||||
QString rarity;
|
|
||||||
double salt = 0.0;
|
|
||||||
QString sanitized;
|
|
||||||
QString sanitizedWo;
|
|
||||||
QString scryfallUri;
|
|
||||||
QString spellbookUri;
|
|
||||||
QString type;
|
|
||||||
QString url;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_H
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
#include "edhrec_commander_api_response.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QJsonArray>
|
|
||||||
|
|
||||||
void EdhrecCommanderApiResponse::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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecCommanderApiResponse::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();
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
#ifndef DECKDATA_H
|
|
||||||
#define DECKDATA_H
|
|
||||||
|
|
||||||
#include "../archidekt_links/edhrec_api_response_archidekt_links.h"
|
|
||||||
#include "../cards/edhrec_api_response_card_container.h"
|
|
||||||
#include "edhrec_commander_api_response_average_deck_statistics.h"
|
|
||||||
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class EdhrecCommanderApiResponse
|
|
||||||
* @ingroup ApiResponses
|
|
||||||
* @brief Represents the main structure of the JSON
|
|
||||||
*/
|
|
||||||
class EdhrecCommanderApiResponse
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
EdhrecCommanderApiResponseAverageDeckStatistics deckStats;
|
|
||||||
EdhrecCommanderApiResponseArchidektLinks archidekt;
|
|
||||||
QJsonObject similar;
|
|
||||||
QString header;
|
|
||||||
QJsonObject panels;
|
|
||||||
QString description;
|
|
||||||
EdhrecApiResponseCardContainer container;
|
|
||||||
|
|
||||||
void fromJson(const QJsonObject &json);
|
|
||||||
void debugPrint() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // DECKDATA_H
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
#include "edhrec_commander_api_response_average_deck_statistics.h"
|
|
||||||
|
|
||||||
void EdhrecCommanderApiResponseAverageDeckStatistics::fromJson(const QJsonObject &json)
|
|
||||||
{
|
|
||||||
creature = json.value("creature").toInt(0);
|
|
||||||
instant = json.value("instant").toInt(0);
|
|
||||||
sorcery = json.value("sorcery").toInt(0);
|
|
||||||
artifact = json.value("artifact").toInt(0);
|
|
||||||
enchantment = json.value("enchantment").toInt(0);
|
|
||||||
battle = json.value("battle").toInt(0);
|
|
||||||
planeswalker = json.value("planeswalker").toInt(0);
|
|
||||||
land = json.value("land").toInt(0);
|
|
||||||
basic = json.value("basic").toInt(0);
|
|
||||||
nonbasic = json.value("nonbasic").toInt(0);
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
#ifndef AVERAGE_DECK_STATISTICS_H
|
|
||||||
#define AVERAGE_DECK_STATISTICS_H
|
|
||||||
|
|
||||||
#include <QJsonObject>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @struct EdhrecCommanderApiResponseAverageDeckStatistics
|
|
||||||
* @ingroup ApiResponses
|
|
||||||
* @brief Represents the typical deck statistics (collapsed section)
|
|
||||||
*/
|
|
||||||
struct EdhrecCommanderApiResponseAverageDeckStatistics
|
|
||||||
{
|
|
||||||
int creature = 0;
|
|
||||||
int instant = 0;
|
|
||||||
int sorcery = 0;
|
|
||||||
int artifact = 0;
|
|
||||||
int enchantment = 0;
|
|
||||||
int battle = 0;
|
|
||||||
int planeswalker = 0;
|
|
||||||
int land = 0;
|
|
||||||
int basic = 0;
|
|
||||||
int nonbasic = 0;
|
|
||||||
|
|
||||||
void fromJson(const QJsonObject &json);
|
|
||||||
};
|
|
||||||
#endif // AVERAGE_DECK_STATISTICS_H
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
#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();
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
/**
|
|
||||||
* @file edhrec_top_cards_api_response.h
|
|
||||||
* @ingroup ApiResponses
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EDHREC_TOP_CARDS_API_RESPONSE_H
|
|
||||||
#define EDHREC_TOP_CARDS_API_RESPONSE_H
|
|
||||||
|
|
||||||
#include "../cards/edhrec_api_response_card_container.h"
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
class EdhrecTopCardsApiResponse
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QString header;
|
|
||||||
QString description;
|
|
||||||
EdhrecApiResponseCardContainer container;
|
|
||||||
|
|
||||||
void fromJson(const QJsonObject &json);
|
|
||||||
void debugPrint() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EDHREC_TOP_CARDS_API_RESPONSE_H
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
#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();
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
/**
|
|
||||||
* @file edhrec_top_commanders_api_response.h
|
|
||||||
* @ingroup ApiResponses
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EDHREC_TOP_COMMANDERS_API_RESPONSE_H
|
|
||||||
#define EDHREC_TOP_COMMANDERS_API_RESPONSE_H
|
|
||||||
|
|
||||||
#include "../cards/edhrec_api_response_card_container.h"
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
class EdhrecTopCommandersApiResponse
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QString header;
|
|
||||||
QString description;
|
|
||||||
EdhrecApiResponseCardContainer container;
|
|
||||||
|
|
||||||
void fromJson(const QJsonObject &json);
|
|
||||||
void debugPrint() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EDHREC_TOP_COMMANDERS_API_RESPONSE_H
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
#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();
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
/**
|
|
||||||
* @file edhrec_top_tags_api_response.h
|
|
||||||
* @ingroup ApiResponses
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EDHREC_TOP_TAGS_API_RESPONSE_H
|
|
||||||
#define EDHREC_TOP_TAGS_API_RESPONSE_H
|
|
||||||
|
|
||||||
#include "../cards/edhrec_api_response_card_container.h"
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
class EdhrecTopTagsApiResponse
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QString header;
|
|
||||||
QString description;
|
|
||||||
EdhrecApiResponseCardContainer container;
|
|
||||||
|
|
||||||
void fromJson(const QJsonObject &json);
|
|
||||||
void debugPrint() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EDHREC_TOP_TAGS_API_RESPONSE_H
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
#include "edhrec_api_response_card_prices_display_widget.h"
|
|
||||||
|
|
||||||
EdhrecApiResponseCardPricesDisplayWidget::EdhrecApiResponseCardPricesDisplayWidget(QWidget *parent,
|
|
||||||
const CardPrices &_cardPrices)
|
|
||||||
: QWidget(parent), cardPrices(_cardPrices)
|
|
||||||
{
|
|
||||||
layout = new QGridLayout(this);
|
|
||||||
setLayout(layout);
|
|
||||||
|
|
||||||
cardHoarderLabel = new QLabel(this);
|
|
||||||
cardHoarderPrice = new QLabel(QString::number(cardPrices.getCardhoarder().value("price").toDouble()), this);
|
|
||||||
cardKingdomLabel = new QLabel(this);
|
|
||||||
cardKingdomPrice = new QLabel(QString::number(cardPrices.getCardkingdom().value("price").toDouble()), this);
|
|
||||||
cardMarketLabel = new QLabel(this);
|
|
||||||
cardMarketPrice = new QLabel(QString::number(cardPrices.getCardmarket().value("price").toDouble()), this);
|
|
||||||
face2faceLabel = new QLabel(this);
|
|
||||||
face2facePrice = new QLabel(QString::number(cardPrices.getFace2face().value("price").toDouble()), this);
|
|
||||||
manaPoolLabel = new QLabel(this);
|
|
||||||
manaPoolPrice = new QLabel(QString::number(cardPrices.getManapool().value("price").toDouble()), this);
|
|
||||||
mtgStocksLabel = new QLabel(this);
|
|
||||||
mtgStocksPrice = new QLabel(QString::number(cardPrices.getMtgstocks().value("price").toDouble()), this);
|
|
||||||
scgLabel = new QLabel(this);
|
|
||||||
scgPrice = new QLabel(QString::number(cardPrices.getScg().value("price").toDouble()), this);
|
|
||||||
tcglLabel = new QLabel(this);
|
|
||||||
tcglPrice = new QLabel(QString::number(cardPrices.getTcgl().value("price").toDouble()), this);
|
|
||||||
tcgplayerLabel = new QLabel(this);
|
|
||||||
tcgplayerPrice = new QLabel(QString::number(cardPrices.getTcgplayer().value("price").toDouble()), this);
|
|
||||||
|
|
||||||
layout->addWidget(cardHoarderLabel, 0, 0);
|
|
||||||
layout->addWidget(cardHoarderPrice, 0, 1);
|
|
||||||
layout->addWidget(cardKingdomLabel, 0, 2);
|
|
||||||
layout->addWidget(cardKingdomPrice, 0, 3);
|
|
||||||
|
|
||||||
layout->addWidget(cardMarketLabel, 1, 0);
|
|
||||||
layout->addWidget(cardMarketPrice, 1, 1);
|
|
||||||
layout->addWidget(face2faceLabel, 1, 2);
|
|
||||||
layout->addWidget(face2facePrice, 1, 3);
|
|
||||||
|
|
||||||
layout->addWidget(manaPoolLabel, 2, 0);
|
|
||||||
layout->addWidget(manaPoolPrice, 2, 1);
|
|
||||||
layout->addWidget(mtgStocksLabel, 2, 2);
|
|
||||||
layout->addWidget(mtgStocksPrice, 2, 3);
|
|
||||||
|
|
||||||
layout->addWidget(scgLabel, 3, 0);
|
|
||||||
layout->addWidget(scgPrice, 3, 1);
|
|
||||||
layout->addWidget(tcglLabel, 3, 2);
|
|
||||||
layout->addWidget(tcglPrice, 3, 3);
|
|
||||||
|
|
||||||
layout->addWidget(tcgplayerLabel, 4, 0);
|
|
||||||
layout->addWidget(tcgplayerPrice, 4, 1);
|
|
||||||
|
|
||||||
retranslateUi();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecApiResponseCardPricesDisplayWidget::retranslateUi()
|
|
||||||
{
|
|
||||||
cardHoarderLabel->setText(tr("Card Hoarder"));
|
|
||||||
cardKingdomLabel->setText(tr("Card Kingdom"));
|
|
||||||
cardMarketLabel->setText(tr("Card Market"));
|
|
||||||
face2faceLabel->setText(tr("Face 2-Face"));
|
|
||||||
manaPoolLabel->setText(tr("Mana Pool"));
|
|
||||||
mtgStocksLabel->setText(tr("MTG Stocks"));
|
|
||||||
scgLabel->setText(tr("Scg"));
|
|
||||||
tcglLabel->setText(tr("Tcgl"));
|
|
||||||
tcgplayerLabel->setText(tr("Tcgplayer"));
|
|
||||||
}
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
/**
|
|
||||||
* @file edhrec_api_response_card_prices_display_widget.h
|
|
||||||
* @ingroup ApiResponseDisplayWidgets
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EDHREC_API_RESPONSE_CARD_PRICES_DISPLAY_WIDGET_H
|
|
||||||
#define EDHREC_API_RESPONSE_CARD_PRICES_DISPLAY_WIDGET_H
|
|
||||||
|
|
||||||
#include "../../api_response/card_prices/edhrec_api_response_card_prices.h"
|
|
||||||
|
|
||||||
#include <QGridLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class EdhrecApiResponseCardPricesDisplayWidget : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
EdhrecApiResponseCardPricesDisplayWidget(QWidget *parent, const CardPrices &cardPrices);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void retranslateUi();
|
|
||||||
|
|
||||||
private:
|
|
||||||
CardPrices cardPrices;
|
|
||||||
QGridLayout *layout;
|
|
||||||
QLabel *cardHoarderLabel;
|
|
||||||
QLabel *cardHoarderPrice;
|
|
||||||
QLabel *cardKingdomLabel;
|
|
||||||
QLabel *cardKingdomPrice;
|
|
||||||
QLabel *cardMarketLabel;
|
|
||||||
QLabel *cardMarketPrice;
|
|
||||||
QLabel *face2faceLabel;
|
|
||||||
QLabel *face2facePrice;
|
|
||||||
QLabel *manaPoolLabel;
|
|
||||||
QLabel *manaPoolPrice;
|
|
||||||
QLabel *mtgStocksLabel;
|
|
||||||
QLabel *mtgStocksPrice;
|
|
||||||
QLabel *scgLabel;
|
|
||||||
QLabel *scgPrice;
|
|
||||||
QLabel *tcglLabel;
|
|
||||||
QLabel *tcglPrice;
|
|
||||||
QLabel *tcgplayerLabel;
|
|
||||||
QLabel *tcgplayerPrice;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EDHREC_API_RESPONSE_CARD_PRICES_DISPLAY_WIDGET_H
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
||||||
#include "edhrec_api_response_card_details_display_widget.h"
|
|
||||||
|
|
||||||
#include "../../../../../general/display/background_plate_widget.h"
|
|
||||||
#include "../../tab_edhrec_main.h"
|
|
||||||
|
|
||||||
#include <QMouseEvent>
|
|
||||||
#include <libcockatrice/card/database/card_database_manager.h>
|
|
||||||
|
|
||||||
EdhrecApiResponseCardDetailsDisplayWidget::EdhrecApiResponseCardDetailsDisplayWidget(
|
|
||||||
QWidget *parent,
|
|
||||||
const EdhrecApiResponseCardDetails &_toDisplay)
|
|
||||||
: QWidget(parent), toDisplay(_toDisplay)
|
|
||||||
{
|
|
||||||
layout = new QVBoxLayout(this);
|
|
||||||
setLayout(layout);
|
|
||||||
|
|
||||||
cardPictureWidget = new CardInfoPictureWidget(this);
|
|
||||||
cardPictureWidget->setCard(CardDatabaseManager::query()->guessCard({toDisplay.sanitized}));
|
|
||||||
|
|
||||||
nameLabel = new QLabel(this);
|
|
||||||
nameLabel->setText(toDisplay.name);
|
|
||||||
nameLabel->setAlignment(Qt::AlignHCenter);
|
|
||||||
nameLabel->setStyleSheet("font-size: 20px; font-weight: bold");
|
|
||||||
|
|
||||||
inclusionDisplayWidget = new EdhrecApiResponseCardInclusionDisplayWidget(this, toDisplay);
|
|
||||||
|
|
||||||
synergyDisplayWidget = new EdhrecApiResponseCardSynergyDisplayWidget(this, toDisplay);
|
|
||||||
|
|
||||||
backgroundPlateWidget = new BackgroundPlateWidget(this);
|
|
||||||
auto plateLayout = new QVBoxLayout(backgroundPlateWidget);
|
|
||||||
|
|
||||||
plateLayout->addWidget(nameLabel);
|
|
||||||
plateLayout->addWidget(cardPictureWidget);
|
|
||||||
plateLayout->addWidget(inclusionDisplayWidget);
|
|
||||||
plateLayout->addWidget(synergyDisplayWidget);
|
|
||||||
|
|
||||||
layout->addWidget(backgroundPlateWidget);
|
|
||||||
|
|
||||||
QWidget *currentParent = parentWidget();
|
|
||||||
TabEdhRecMain *parentTab = nullptr;
|
|
||||||
|
|
||||||
while (currentParent) {
|
|
||||||
if ((parentTab = qobject_cast<TabEdhRecMain *>(currentParent))) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
currentParent = currentParent->parentWidget();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parentTab) {
|
|
||||||
cardPictureWidget->setScaleFactor(parentTab->getCardSizeSlider()->getSlider()->value());
|
|
||||||
connect(cardPictureWidget, &CardInfoPictureWidget::cardClicked, this,
|
|
||||||
&EdhrecApiResponseCardDetailsDisplayWidget::mousePressEvent);
|
|
||||||
connect(parentTab->getCardSizeSlider()->getSlider(), &QSlider::valueChanged, cardPictureWidget,
|
|
||||||
&CardInfoPictureWidget::setScaleFactor);
|
|
||||||
connect(this, &EdhrecApiResponseCardDetailsDisplayWidget::requestUrl, parentTab,
|
|
||||||
&TabEdhRecMain::actNavigatePage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecApiResponseCardDetailsDisplayWidget::mousePressEvent(QMouseEvent *event)
|
|
||||||
{
|
|
||||||
QWidget::mousePressEvent(event);
|
|
||||||
if (event->button() == Qt::LeftButton) {
|
|
||||||
actRequestPageNavigation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
void EdhrecApiResponseCardDetailsDisplayWidget::enterEvent(QEnterEvent *event)
|
|
||||||
#else
|
|
||||||
void EdhrecApiResponseCardDetailsDisplayWidget::enterEvent(QEvent *event)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
QWidget::enterEvent(event);
|
|
||||||
backgroundPlateWidget->setFocused(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecApiResponseCardDetailsDisplayWidget::leaveEvent(QEvent *event)
|
|
||||||
{
|
|
||||||
QWidget::leaveEvent(event);
|
|
||||||
backgroundPlateWidget->setFocused(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecApiResponseCardDetailsDisplayWidget::actRequestPageNavigation()
|
|
||||||
{
|
|
||||||
emit requestUrl(toDisplay.url);
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
/**
|
|
||||||
* @file edhrec_api_response_card_details_display_widget.h
|
|
||||||
* @ingroup ApiResponseDisplayWidgets
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H
|
|
||||||
#define EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H
|
|
||||||
|
|
||||||
#include "../../../../../cards/card_info_picture_widget.h"
|
|
||||||
#include "../../../../../general/display/background_plate_widget.h"
|
|
||||||
#include "../../api_response/cards/edhrec_api_response_card_details.h"
|
|
||||||
#include "edhrec_api_response_card_inclusion_display_widget.h"
|
|
||||||
#include "edhrec_api_response_card_synergy_display_widget.h"
|
|
||||||
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class EdhrecApiResponseCardDetailsDisplayWidget : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit EdhrecApiResponseCardDetailsDisplayWidget(QWidget *parent, const EdhrecApiResponseCardDetails &_toDisplay);
|
|
||||||
public slots:
|
|
||||||
void actRequestPageNavigation();
|
|
||||||
signals:
|
|
||||||
void requestUrl(QString url);
|
|
||||||
|
|
||||||
private:
|
|
||||||
EdhrecApiResponseCardDetails toDisplay;
|
|
||||||
QVBoxLayout *layout;
|
|
||||||
CardInfoPictureWidget *cardPictureWidget;
|
|
||||||
BackgroundPlateWidget *backgroundPlateWidget; ///< Plate for metadata labels
|
|
||||||
QLabel *nameLabel;
|
|
||||||
EdhrecApiResponseCardInclusionDisplayWidget *inclusionDisplayWidget;
|
|
||||||
EdhrecApiResponseCardSynergyDisplayWidget *synergyDisplayWidget;
|
|
||||||
|
|
||||||
protected slots:
|
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
void enterEvent(QEnterEvent *event) override; ///< Qt6 hover enter
|
|
||||||
#else
|
|
||||||
void enterEvent(QEvent *event) override; ///< Qt5 hover enter
|
|
||||||
#endif
|
|
||||||
void leaveEvent(QEvent *event) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
#include "edhrec_api_response_card_inclusion_display_widget.h"
|
|
||||||
|
|
||||||
EdhrecApiResponseCardInclusionDisplayWidget::EdhrecApiResponseCardInclusionDisplayWidget(
|
|
||||||
QWidget *parent,
|
|
||||||
const EdhrecApiResponseCardDetails &_toDisplay)
|
|
||||||
: QWidget(parent), toDisplay(_toDisplay)
|
|
||||||
{
|
|
||||||
layout = new QVBoxLayout(this);
|
|
||||||
setLayout(layout);
|
|
||||||
|
|
||||||
commanderLabel = new QLabel(this);
|
|
||||||
commanderLabel->setAlignment(Qt::AlignCenter);
|
|
||||||
amountLabel = new QLabel(this);
|
|
||||||
amountLabel->setAlignment(Qt::AlignCenter);
|
|
||||||
inclusionLabel = new QLabel(this);
|
|
||||||
inclusionLabel->setAlignment(Qt::AlignCenter);
|
|
||||||
percentBarWidget = new PercentBarWidget(this, toDisplay.inclusion / (toDisplay.potentialDecks / 100.0));
|
|
||||||
|
|
||||||
if (toDisplay.inclusion != 0 && toDisplay.potentialDecks != 0) {
|
|
||||||
layout->addWidget(amountLabel);
|
|
||||||
layout->addWidget(inclusionLabel);
|
|
||||||
layout->addWidget(percentBarWidget);
|
|
||||||
commanderLabel->hide();
|
|
||||||
} else {
|
|
||||||
amountLabel->hide();
|
|
||||||
inclusionLabel->hide();
|
|
||||||
percentBarWidget->hide();
|
|
||||||
layout->addWidget(commanderLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
retranslateUi();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecApiResponseCardInclusionDisplayWidget::retranslateUi()
|
|
||||||
{
|
|
||||||
commanderLabel->setText(toDisplay.label);
|
|
||||||
amountLabel->setText(tr("In %1 decks").arg(QString::number(toDisplay.inclusion)));
|
|
||||||
inclusionLabel->setText(tr("%1% of %2 decks")
|
|
||||||
.arg(QString::number(toDisplay.inclusion / (toDisplay.potentialDecks / 100.0), 'f', 2),
|
|
||||||
QString::number(toDisplay.potentialDecks)));
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
/**
|
|
||||||
* @file edhrec_api_response_card_inclusion_display_widget.h
|
|
||||||
* @ingroup ApiResponseDisplayWidgets
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EDHREC_API_RESPONSE_CARD_INCLUSION_DISPLAY_WIDGET_H
|
|
||||||
#define EDHREC_API_RESPONSE_CARD_INCLUSION_DISPLAY_WIDGET_H
|
|
||||||
|
|
||||||
#include "../../../../../general/display/charts/bars/percent_bar_widget.h"
|
|
||||||
#include "../../api_response/cards/edhrec_api_response_card_details.h"
|
|
||||||
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class EdhrecApiResponseCardInclusionDisplayWidget : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
EdhrecApiResponseCardInclusionDisplayWidget(QWidget *parent, const EdhrecApiResponseCardDetails &_toDisplay);
|
|
||||||
void retranslateUi();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QVBoxLayout *layout;
|
|
||||||
EdhrecApiResponseCardDetails toDisplay;
|
|
||||||
QLabel *commanderLabel;
|
|
||||||
QLabel *amountLabel;
|
|
||||||
QLabel *inclusionLabel;
|
|
||||||
PercentBarWidget *percentBarWidget;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EDHREC_API_RESPONSE_CARD_INCLUSION_DISPLAY_WIDGET_H
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
#include "edhrec_api_response_card_list_display_widget.h"
|
|
||||||
|
|
||||||
#include "../../../../../general/display/banner_widget.h"
|
|
||||||
#include "edhrec_api_response_card_details_display_widget.h"
|
|
||||||
|
|
||||||
#include <QLabel>
|
|
||||||
|
|
||||||
EdhrecApiResponseCardListDisplayWidget::EdhrecApiResponseCardListDisplayWidget(QWidget *parent,
|
|
||||||
EdhrecApiResponseCardList toDisplay)
|
|
||||||
: QWidget(parent)
|
|
||||||
{
|
|
||||||
layout = new QVBoxLayout(this);
|
|
||||||
setLayout(layout);
|
|
||||||
|
|
||||||
header = new BannerWidget(this, toDisplay.header);
|
|
||||||
|
|
||||||
flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAlwaysOff);
|
|
||||||
header->setBuddy(flowWidget);
|
|
||||||
|
|
||||||
foreach (EdhrecApiResponseCardDetails card_detail, toDisplay.cardViews) {
|
|
||||||
auto widget = new EdhrecApiResponseCardDetailsDisplayWidget(flowWidget, card_detail);
|
|
||||||
flowWidget->addWidget(widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
layout->addWidget(header);
|
|
||||||
layout->addWidget(flowWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecApiResponseCardListDisplayWidget::resizeEvent(QResizeEvent *event)
|
|
||||||
{
|
|
||||||
QWidget::resizeEvent(event);
|
|
||||||
qDebug() << event->size();
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
/**
|
|
||||||
* @file edhrec_api_response_card_list_display_widget.h
|
|
||||||
* @ingroup ApiResponseDisplayWidgets
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EDHREC_COMMANDER_API_RESPONSE_CARD_LIST_DISPLAY_WIDGET_H
|
|
||||||
#define EDHREC_COMMANDER_API_RESPONSE_CARD_LIST_DISPLAY_WIDGET_H
|
|
||||||
|
|
||||||
#include "../../../../../general/display/banner_widget.h"
|
|
||||||
#include "../../../../../general/layout_containers/flow_widget.h"
|
|
||||||
#include "../../api_response/cards/edhrec_api_response_card_list.h"
|
|
||||||
|
|
||||||
#include <QResizeEvent>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class EdhrecApiResponseCardListDisplayWidget : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit EdhrecApiResponseCardListDisplayWidget(QWidget *parent, EdhrecApiResponseCardList toDisplay);
|
|
||||||
void resizeEvent(QResizeEvent *event) override;
|
|
||||||
[[nodiscard]] QString getBannerText() const
|
|
||||||
{
|
|
||||||
return header->getText();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
QVBoxLayout *layout;
|
|
||||||
BannerWidget *header;
|
|
||||||
FlowWidget *flowWidget;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EDHREC_COMMANDER_API_RESPONSE_CARD_LIST_DISPLAY_WIDGET_H
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
#include "edhrec_api_response_card_synergy_display_widget.h"
|
|
||||||
|
|
||||||
EdhrecApiResponseCardSynergyDisplayWidget::EdhrecApiResponseCardSynergyDisplayWidget(
|
|
||||||
QWidget *parent,
|
|
||||||
const EdhrecApiResponseCardDetails &_toDisplay)
|
|
||||||
: QWidget(parent), toDisplay(_toDisplay)
|
|
||||||
{
|
|
||||||
layout = new QVBoxLayout(this);
|
|
||||||
setLayout(layout);
|
|
||||||
|
|
||||||
label = new QLabel(this);
|
|
||||||
label->setAlignment(Qt::AlignCenter);
|
|
||||||
percentBarWidget = new PercentBarWidget(this, toDisplay.synergy * 100.0);
|
|
||||||
|
|
||||||
if (toDisplay.synergy != 0) {
|
|
||||||
layout->addWidget(label);
|
|
||||||
layout->addWidget(percentBarWidget);
|
|
||||||
} else {
|
|
||||||
hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
retranslateUi();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecApiResponseCardSynergyDisplayWidget::retranslateUi()
|
|
||||||
{
|
|
||||||
label->setText(tr("%1% Synergy").arg(QString::number(toDisplay.synergy * 100.0, 'f', 1)));
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
/**
|
|
||||||
* @file edhrec_api_response_card_synergy_display_widget.h
|
|
||||||
* @ingroup ApiResponseDisplayWidgets
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EDHREC_API_RESPONSE_CARD_SYNERGY_DISPLAY_WIDGET_H
|
|
||||||
#define EDHREC_API_RESPONSE_CARD_SYNERGY_DISPLAY_WIDGET_H
|
|
||||||
|
|
||||||
#include "../../../../../general/display/charts/bars/percent_bar_widget.h"
|
|
||||||
#include "../../api_response/cards/edhrec_api_response_card_details.h"
|
|
||||||
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class EdhrecApiResponseCardSynergyDisplayWidget : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
EdhrecApiResponseCardSynergyDisplayWidget(QWidget *parent, const EdhrecApiResponseCardDetails &_toDisplay);
|
|
||||||
void retranslateUi();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QVBoxLayout *layout;
|
|
||||||
EdhrecApiResponseCardDetails toDisplay;
|
|
||||||
QLabel *label;
|
|
||||||
PercentBarWidget *percentBarWidget;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EDHREC_API_RESPONSE_CARD_SYNERGY_DISPLAY_WIDGET_H
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
#include "edhrec_api_response_commander_details_display_widget.h"
|
|
||||||
|
|
||||||
#include "../../../../../cards/card_info_picture_widget.h"
|
|
||||||
#include "../../tab_edhrec_main.h"
|
|
||||||
#include "../card_prices/edhrec_api_response_card_prices_display_widget.h"
|
|
||||||
#include "edhrec_commander_api_response_bracket_navigation_widget.h"
|
|
||||||
|
|
||||||
#include <libcockatrice/card/database/card_database_manager.h>
|
|
||||||
|
|
||||||
EdhrecCommanderResponseCommanderDetailsDisplayWidget::EdhrecCommanderResponseCommanderDetailsDisplayWidget(
|
|
||||||
QWidget *parent,
|
|
||||||
const EdhrecCommanderApiResponseCommanderDetails &_commanderDetails,
|
|
||||||
QString baseUrl)
|
|
||||||
: QWidget(parent), commanderDetails(_commanderDetails)
|
|
||||||
{
|
|
||||||
layout = new QHBoxLayout(this);
|
|
||||||
setLayout(layout);
|
|
||||||
|
|
||||||
commanderLayout = new QHBoxLayout();
|
|
||||||
commanderDetailsLayout = new QVBoxLayout();
|
|
||||||
commanderDetailsLayout->setAlignment(Qt::AlignCenter);
|
|
||||||
navigationAndPricesLayout = new QVBoxLayout();
|
|
||||||
|
|
||||||
commanderPicture = new CardInfoPictureWidget(this);
|
|
||||||
commanderPicture->setCard(CardDatabaseManager::query()->getCard({commanderDetails.getName()}));
|
|
||||||
|
|
||||||
QWidget *currentParent = parentWidget();
|
|
||||||
TabEdhRecMain *parentTab = nullptr;
|
|
||||||
|
|
||||||
while (currentParent) {
|
|
||||||
if ((parentTab = qobject_cast<TabEdhRecMain *>(currentParent))) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
currentParent = currentParent->parentWidget();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parentTab) {
|
|
||||||
connect(parentTab->getCardSizeSlider()->getSlider(), &QSlider::valueChanged, commanderPicture,
|
|
||||||
&CardInfoPictureWidget::setScaleFactor);
|
|
||||||
commanderPicture->setScaleFactor(parentTab->getCardSizeSlider()->getSlider()->value());
|
|
||||||
}
|
|
||||||
|
|
||||||
commanderDetails.debugPrint();
|
|
||||||
|
|
||||||
commanderName = new QLabel(this);
|
|
||||||
commanderName->setText(commanderDetails.getName());
|
|
||||||
commanderName->setAlignment(Qt::AlignCenter);
|
|
||||||
commanderName->setStyleSheet("font-size: 28px; font-weight: bold");
|
|
||||||
|
|
||||||
label = new QLabel(this);
|
|
||||||
label->setAlignment(Qt::AlignCenter);
|
|
||||||
label->setStyleSheet("font-size: 16px");
|
|
||||||
|
|
||||||
salt = new QLabel(this);
|
|
||||||
salt->setAlignment(Qt::AlignCenter);
|
|
||||||
salt->setStyleSheet("font-size: 16px");
|
|
||||||
|
|
||||||
cardPricesDisplayWidget = new EdhrecApiResponseCardPricesDisplayWidget(this, commanderDetails.getPrices());
|
|
||||||
|
|
||||||
navigationWidget = new EdhrecCommanderApiResponseNavigationWidget(this, commanderDetails, baseUrl);
|
|
||||||
|
|
||||||
commanderLayout->addWidget(commanderPicture);
|
|
||||||
commanderDetailsLayout->addWidget(commanderName);
|
|
||||||
commanderDetailsLayout->addSpacing(1);
|
|
||||||
commanderDetailsLayout->addWidget(label);
|
|
||||||
commanderDetailsLayout->addWidget(salt);
|
|
||||||
commanderDetailsLayout->addWidget(cardPricesDisplayWidget);
|
|
||||||
commanderLayout->addLayout(commanderDetailsLayout);
|
|
||||||
navigationAndPricesLayout->addWidget(navigationWidget);
|
|
||||||
// navigationAndPricesLayout->addWidget(cardPricesDisplayWidget);
|
|
||||||
|
|
||||||
layout->addLayout(commanderLayout);
|
|
||||||
layout->addLayout(navigationAndPricesLayout);
|
|
||||||
|
|
||||||
retranslateUi();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecCommanderResponseCommanderDetailsDisplayWidget::retranslateUi()
|
|
||||||
{
|
|
||||||
label->setText(commanderDetails.getLabel());
|
|
||||||
salt->setText(tr("Salt: ") + QString::number(commanderDetails.getSalt()));
|
|
||||||
}
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
/**
|
|
||||||
* @file edhrec_api_response_commander_details_display_widget.h
|
|
||||||
* @ingroup ApiResponseDisplayWidgets
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_DISPLAY_WIDGET_H
|
|
||||||
#define EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_DISPLAY_WIDGET_H
|
|
||||||
|
|
||||||
#include "../../../../../cards/card_info_picture_widget.h"
|
|
||||||
#include "../../api_response/cards/edhrec_commander_api_response_commander_details.h"
|
|
||||||
#include "../card_prices/edhrec_api_response_card_prices_display_widget.h"
|
|
||||||
#include "edhrec_commander_api_response_navigation_widget.h"
|
|
||||||
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class EdhrecCommanderApiResponseNavigationWidget;
|
|
||||||
class EdhrecCommanderResponseCommanderDetailsDisplayWidget : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit EdhrecCommanderResponseCommanderDetailsDisplayWidget(
|
|
||||||
QWidget *parent,
|
|
||||||
const EdhrecCommanderApiResponseCommanderDetails &_commanderDetails,
|
|
||||||
QString baseUrl);
|
|
||||||
void retranslateUi();
|
|
||||||
|
|
||||||
private:
|
|
||||||
EdhrecCommanderApiResponseCommanderDetails commanderDetails;
|
|
||||||
QHBoxLayout *layout;
|
|
||||||
QHBoxLayout *commanderLayout;
|
|
||||||
QVBoxLayout *commanderDetailsLayout;
|
|
||||||
QVBoxLayout *navigationAndPricesLayout;
|
|
||||||
CardInfoPictureWidget *commanderPicture;
|
|
||||||
QLabel *commanderName;
|
|
||||||
QLabel *label;
|
|
||||||
QLabel *salt;
|
|
||||||
EdhrecApiResponseCardPricesDisplayWidget *cardPricesDisplayWidget;
|
|
||||||
EdhrecCommanderApiResponseNavigationWidget *navigationWidget;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_DISPLAY_WIDGET_H
|
|
||||||
|
|
@ -1,95 +0,0 @@
|
||||||
#include "edhrec_commander_api_response_bracket_navigation_widget.h"
|
|
||||||
|
|
||||||
#include <QSet>
|
|
||||||
|
|
||||||
EdhrecCommanderApiResponseBracketNavigationWidget::EdhrecCommanderApiResponseBracketNavigationWidget(
|
|
||||||
QWidget *parent,
|
|
||||||
const QString &baseUrl)
|
|
||||||
: QWidget(parent)
|
|
||||||
{
|
|
||||||
layout = new QGridLayout(this);
|
|
||||||
setLayout(layout);
|
|
||||||
|
|
||||||
gameChangerLabel = new QLabel(this);
|
|
||||||
|
|
||||||
layout->addWidget(gameChangerLabel, 1, 0, 1, 2);
|
|
||||||
|
|
||||||
for (int i = 0; i < gameChangerOptions.length(); i++) {
|
|
||||||
QString option = gameChangerOptions.at(i);
|
|
||||||
QString label = option.isEmpty() ? "All" : option.at(0).toUpper() + option.mid(1);
|
|
||||||
QPushButton *optionButton = new QPushButton(label, this);
|
|
||||||
optionButton->setMinimumHeight(84);
|
|
||||||
optionButton->setStyleSheet("font-size: 24px");
|
|
||||||
gameChangerButtons[option] = optionButton;
|
|
||||||
layout->addWidget(optionButton, 2, i);
|
|
||||||
connect(optionButton, &QPushButton::clicked, this, [=, this]() {
|
|
||||||
selectedGameChanger = option;
|
|
||||||
updateOptionButtonSelection(gameChangerButtons, option);
|
|
||||||
emit requestNavigation();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
updateOptionButtonSelection(gameChangerButtons, "");
|
|
||||||
|
|
||||||
retranslateUi();
|
|
||||||
applyOptionsFromUrl(baseUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecCommanderApiResponseBracketNavigationWidget::retranslateUi()
|
|
||||||
{
|
|
||||||
gameChangerLabel->setText(tr("Game Changers"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecCommanderApiResponseBracketNavigationWidget::applyOptionsFromUrl(const QString &url)
|
|
||||||
{
|
|
||||||
QString cleanedUrl = url;
|
|
||||||
|
|
||||||
// Remove base and file extension
|
|
||||||
if (cleanedUrl.startsWith("https://json.edhrec.com/pages/")) {
|
|
||||||
cleanedUrl = cleanedUrl.mid(QString("https://json.edhrec.com/pages/").length());
|
|
||||||
}
|
|
||||||
if (cleanedUrl.endsWith(".json")) {
|
|
||||||
cleanedUrl.chop(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expecting something like: "commanders/the-ur-dragon/core/expensive"
|
|
||||||
QStringList parts = cleanedUrl.split('/', Qt::SkipEmptyParts);
|
|
||||||
|
|
||||||
if (parts.size() < 2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString commanderName = parts[1];
|
|
||||||
QString gameChangerOpt;
|
|
||||||
|
|
||||||
// Define valid sets
|
|
||||||
QSet<QString> validGameChangers = {"exhibition", "core", "upgraded", "optimized", "cedh"};
|
|
||||||
|
|
||||||
// Check remaining parts after commander
|
|
||||||
for (int i = 2; i < parts.size(); ++i) {
|
|
||||||
QString part = parts[i].toLower();
|
|
||||||
if (validGameChangers.contains(part)) {
|
|
||||||
gameChangerOpt = part;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate and apply
|
|
||||||
if (!gameChangerButtons.contains(gameChangerOpt)) {
|
|
||||||
gameChangerOpt.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
selectedGameChanger = gameChangerOpt;
|
|
||||||
|
|
||||||
updateOptionButtonSelection(gameChangerButtons, selectedGameChanger);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecCommanderApiResponseBracketNavigationWidget::updateOptionButtonSelection(
|
|
||||||
QMap<QString, QPushButton *> &buttons,
|
|
||||||
const QString &selectedKey)
|
|
||||||
{
|
|
||||||
for (auto it = buttons.begin(); it != buttons.end(); ++it) {
|
|
||||||
it.value()->setStyleSheet(it.key() == selectedKey
|
|
||||||
? "background-color: lightblue; font-weight: bold; font-size: 24px;"
|
|
||||||
: "font-size: 24px");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
#ifndef COCKATRICE_EDHREC_COMMANDER_API_RESPONSE_BRACKET_NAVIGATION_WIDGET_H
|
|
||||||
#define COCKATRICE_EDHREC_COMMANDER_API_RESPONSE_BRACKET_NAVIGATION_WIDGET_H
|
|
||||||
|
|
||||||
#include <QGridLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QMap>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class EdhrecCommanderApiResponseBracketNavigationWidget : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit EdhrecCommanderApiResponseBracketNavigationWidget(QWidget *parent, const QString &baseUrl);
|
|
||||||
void retranslateUi();
|
|
||||||
void applyOptionsFromUrl(const QString &url);
|
|
||||||
QString getSelectedGameChanger() const
|
|
||||||
{
|
|
||||||
return selectedGameChanger;
|
|
||||||
}
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void requestNavigation();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QGridLayout *layout;
|
|
||||||
QLabel *gameChangerLabel;
|
|
||||||
|
|
||||||
QStringList gameChangerOptions = {"", "exhibition", "core", "upgraded", "optimized", "cedh"};
|
|
||||||
QString selectedGameChanger;
|
|
||||||
|
|
||||||
QMap<QString, QPushButton *> gameChangerButtons;
|
|
||||||
|
|
||||||
void updateOptionButtonSelection(QMap<QString, QPushButton *> &buttons, const QString &selectedKey);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // COCKATRICE_EDHREC_COMMANDER_API_RESPONSE_BRACKET_NAVIGATION_WIDGET_H
|
|
||||||
|
|
@ -1,97 +0,0 @@
|
||||||
#include "edhrec_commander_api_response_budget_navigation_widget.h"
|
|
||||||
|
|
||||||
#include <QSet>
|
|
||||||
|
|
||||||
EdhrecCommanderApiResponseBudgetNavigationWidget::EdhrecCommanderApiResponseBudgetNavigationWidget(
|
|
||||||
QWidget *parent,
|
|
||||||
const QString &baseUrl)
|
|
||||||
: QWidget(parent)
|
|
||||||
{
|
|
||||||
layout = new QGridLayout(this);
|
|
||||||
setLayout(layout);
|
|
||||||
|
|
||||||
budgetLabel = new QLabel(this);
|
|
||||||
|
|
||||||
layout->addWidget(budgetLabel, 3, 0, 1, 2);
|
|
||||||
|
|
||||||
for (int i = 0; i < budgetOptions.length(); i++) {
|
|
||||||
QString option = budgetOptions.at(i);
|
|
||||||
QString label = option.isEmpty() ? "Any" : option.at(0).toUpper() + option.mid(1);
|
|
||||||
QPushButton *btn = new QPushButton(label, this);
|
|
||||||
btn->setMinimumHeight(84);
|
|
||||||
btn->setStyleSheet("font-size: 24px");
|
|
||||||
budgetButtons[option] = btn;
|
|
||||||
layout->addWidget(btn, 4, i);
|
|
||||||
connect(btn, &QPushButton::clicked, this, [=, this]() {
|
|
||||||
selectedBudget = option;
|
|
||||||
updateOptionButtonSelection(budgetButtons, option);
|
|
||||||
emit requestNavigation();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
updateOptionButtonSelection(budgetButtons, "");
|
|
||||||
|
|
||||||
retranslateUi();
|
|
||||||
applyOptionsFromUrl(baseUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecCommanderApiResponseBudgetNavigationWidget::retranslateUi()
|
|
||||||
{
|
|
||||||
budgetLabel->setText(tr("Budget"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecCommanderApiResponseBudgetNavigationWidget::applyOptionsFromUrl(const QString &url)
|
|
||||||
{
|
|
||||||
QString cleanedUrl = url;
|
|
||||||
|
|
||||||
// Remove base and file extension
|
|
||||||
if (cleanedUrl.startsWith("https://json.edhrec.com/pages/")) {
|
|
||||||
cleanedUrl = cleanedUrl.mid(QString("https://json.edhrec.com/pages/").length());
|
|
||||||
}
|
|
||||||
if (cleanedUrl.endsWith(".json")) {
|
|
||||||
cleanedUrl.chop(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expecting something like: "commanders/the-ur-dragon/core/expensive"
|
|
||||||
QStringList parts = cleanedUrl.split('/', Qt::SkipEmptyParts);
|
|
||||||
|
|
||||||
if (parts.size() < 2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString commanderName = parts[1];
|
|
||||||
QString gameChangerOpt, budgetOpt;
|
|
||||||
|
|
||||||
// Define valid sets
|
|
||||||
QSet<QString> validGameChangers = {"exhibition", "core", "upgraded", "optimized", "cedh"};
|
|
||||||
QSet<QString> validBudgets = {"budget", "expensive"};
|
|
||||||
|
|
||||||
// Check remaining parts after commander
|
|
||||||
for (int i = 2; i < parts.size(); ++i) {
|
|
||||||
QString part = parts[i].toLower();
|
|
||||||
if (validGameChangers.contains(part)) {
|
|
||||||
gameChangerOpt = part;
|
|
||||||
} else if (validBudgets.contains(part)) {
|
|
||||||
budgetOpt = part;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!budgetButtons.contains(budgetOpt)) {
|
|
||||||
budgetOpt.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
selectedBudget = budgetOpt;
|
|
||||||
|
|
||||||
updateOptionButtonSelection(budgetButtons, selectedBudget);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecCommanderApiResponseBudgetNavigationWidget::updateOptionButtonSelection(
|
|
||||||
QMap<QString, QPushButton *> &buttons,
|
|
||||||
const QString &selectedKey)
|
|
||||||
{
|
|
||||||
for (auto it = buttons.begin(); it != buttons.end(); ++it) {
|
|
||||||
it.value()->setStyleSheet(it.key() == selectedKey
|
|
||||||
? "background-color: lightblue; font-weight: bold; font-size: 24px;"
|
|
||||||
: "font-size: 24px");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
#ifndef COCKATRICE_EDHREC_COMMANDER_API_RESPONSE_BUDGET_NAVIGATION_WIDGET_H
|
|
||||||
#define COCKATRICE_EDHREC_COMMANDER_API_RESPONSE_BUDGET_NAVIGATION_WIDGET_H
|
|
||||||
|
|
||||||
#include <QGridLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QMap>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class EdhrecCommanderApiResponseBudgetNavigationWidget : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit EdhrecCommanderApiResponseBudgetNavigationWidget(QWidget *parent, const QString &baseUrl);
|
|
||||||
void retranslateUi();
|
|
||||||
void applyOptionsFromUrl(const QString &url);
|
|
||||||
QString getSelectedBudget() const
|
|
||||||
{
|
|
||||||
return selectedBudget;
|
|
||||||
}
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void requestNavigation();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QGridLayout *layout;
|
|
||||||
QLabel *budgetLabel;
|
|
||||||
|
|
||||||
QStringList budgetOptions = {"", "budget", "expensive"};
|
|
||||||
QString selectedBudget;
|
|
||||||
|
|
||||||
QMap<QString, QPushButton *> budgetButtons;
|
|
||||||
|
|
||||||
void updateOptionButtonSelection(QMap<QString, QPushButton *> &buttons, const QString &selectedKey);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // COCKATRICE_EDHREC_COMMANDER_API_RESPONSE_BUDGET_NAVIGATION_WIDGET_H
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
#include "edhrec_commander_api_response_display_widget.h"
|
|
||||||
|
|
||||||
#include "../../../../../cards/card_info_picture_widget.h"
|
|
||||||
#include "../../api_response/commander/edhrec_commander_api_response.h"
|
|
||||||
#include "../cards/edhrec_api_response_card_list_display_widget.h"
|
|
||||||
#include "edhrec_api_response_commander_details_display_widget.h"
|
|
||||||
|
|
||||||
#include <QListView>
|
|
||||||
#include <QResizeEvent>
|
|
||||||
#include <QScrollArea>
|
|
||||||
#include <QSplitter>
|
|
||||||
#include <QStringListModel>
|
|
||||||
|
|
||||||
EdhrecCommanderApiResponseDisplayWidget::EdhrecCommanderApiResponseDisplayWidget(QWidget *parent,
|
|
||||||
EdhrecCommanderApiResponse response,
|
|
||||||
QString baseUrl)
|
|
||||||
: QWidget(parent)
|
|
||||||
{
|
|
||||||
layout = new QHBoxLayout(this);
|
|
||||||
setLayout(layout);
|
|
||||||
|
|
||||||
cardDisplayLayout = new QVBoxLayout(this);
|
|
||||||
|
|
||||||
// Create a QSplitter to hold the ListView and ScrollArea holding CardListdisplayWidgets side by side
|
|
||||||
auto splitter = new QSplitter(this);
|
|
||||||
splitter->setOrientation(Qt::Horizontal);
|
|
||||||
|
|
||||||
auto listView = new QListView(splitter);
|
|
||||||
listView->setMinimumWidth(50);
|
|
||||||
listView->setMaximumWidth(150);
|
|
||||||
auto listModel = new QStringListModel(this);
|
|
||||||
QStringList widgetNames;
|
|
||||||
|
|
||||||
// Add commander details
|
|
||||||
auto commanderPicture = new EdhrecCommanderResponseCommanderDetailsDisplayWidget(
|
|
||||||
this, response.container.getCommanderDetails(), baseUrl);
|
|
||||||
cardDisplayLayout->addWidget(commanderPicture);
|
|
||||||
widgetNames.append("Commander Details");
|
|
||||||
|
|
||||||
// Add card list widgets
|
|
||||||
auto edhrec_commander_api_response_card_lists = response.container.getCardlists();
|
|
||||||
for (const EdhrecApiResponseCardList &card_list : edhrec_commander_api_response_card_lists) {
|
|
||||||
auto cardListDisplayWidget = new EdhrecApiResponseCardListDisplayWidget(this, card_list);
|
|
||||||
cardDisplayLayout->addWidget(cardListDisplayWidget);
|
|
||||||
widgetNames.append(cardListDisplayWidget->getBannerText());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a QScrollArea to hold the card display widgets
|
|
||||||
scrollArea = new QScrollArea(splitter);
|
|
||||||
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);
|
|
||||||
connect(splitter, &QSplitter::splitterMoved, this, &EdhrecCommanderApiResponseDisplayWidget::onSplitterChange);
|
|
||||||
scrollArea->setWidget(scrollWidget);
|
|
||||||
|
|
||||||
// Configure the list view
|
|
||||||
listModel->setStringList(widgetNames);
|
|
||||||
listView->setModel(listModel);
|
|
||||||
listView->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
|
||||||
|
|
||||||
// Connect the list view to ensure the corresponding widget is visible
|
|
||||||
connect(listView, &QListView::clicked, this, [this](const QModelIndex &index) {
|
|
||||||
int widgetIndex = index.row();
|
|
||||||
qDebug() << "clicked: " << widgetIndex;
|
|
||||||
auto targetWidget = cardDisplayLayout->itemAt(widgetIndex)->widget();
|
|
||||||
if (targetWidget) {
|
|
||||||
qDebug() << "Found targetWidget" << targetWidget;
|
|
||||||
// Attempt to cast the parent to QScrollArea
|
|
||||||
auto scrollArea = qobject_cast<QScrollArea *>(this->scrollArea); // Use the scroll area instance
|
|
||||||
if (scrollArea) {
|
|
||||||
qDebug() << "ScrollArea" << scrollArea;
|
|
||||||
scrollArea->ensureWidgetVisible(targetWidget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add splitter to the main layout
|
|
||||||
splitter->addWidget(listView);
|
|
||||||
splitter->addWidget(scrollArea);
|
|
||||||
|
|
||||||
layout->addWidget(splitter);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecCommanderApiResponseDisplayWidget::onSplitterChange()
|
|
||||||
{
|
|
||||||
scrollArea->widget()->resize(scrollArea->size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecCommanderApiResponseDisplayWidget::resizeEvent(QResizeEvent *event)
|
|
||||||
{
|
|
||||||
QWidget::resizeEvent(event);
|
|
||||||
qDebug() << event->size();
|
|
||||||
layout->invalidate();
|
|
||||||
layout->activate();
|
|
||||||
layout->update();
|
|
||||||
if (scrollArea && scrollArea->widget()) {
|
|
||||||
scrollArea->widget()->resize(event->size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
/**
|
|
||||||
* @file edhrec_commander_api_response_display_widget.h
|
|
||||||
* @ingroup ApiResponseDisplayWidgets
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EDHREC_COMMANDER_API_RESPONSE_DISPLAY_WIDGET_H
|
|
||||||
#define EDHREC_COMMANDER_API_RESPONSE_DISPLAY_WIDGET_H
|
|
||||||
|
|
||||||
#include "../../api_response/commander/edhrec_commander_api_response.h"
|
|
||||||
|
|
||||||
#include <QScrollArea>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class EdhrecCommanderApiResponseDisplayWidget : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit EdhrecCommanderApiResponseDisplayWidget(QWidget *parent,
|
|
||||||
EdhrecCommanderApiResponse response,
|
|
||||||
QString baseUrl);
|
|
||||||
void resizeEvent(QResizeEvent *event) override;
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void onSplitterChange();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QHBoxLayout *layout;
|
|
||||||
QVBoxLayout *cardDisplayLayout;
|
|
||||||
QScrollArea *scrollArea;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EDHREC_COMMANDER_API_RESPONSE_DISPLAY_WIDGET_H
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
#include "edhrec_commander_api_response_navigation_widget.h"
|
|
||||||
|
|
||||||
#include "../../tab_edhrec_main.h"
|
|
||||||
|
|
||||||
EdhrecCommanderApiResponseNavigationWidget::EdhrecCommanderApiResponseNavigationWidget(
|
|
||||||
QWidget *parent,
|
|
||||||
const EdhrecCommanderApiResponseCommanderDetails &_commanderDetails,
|
|
||||||
QString baseUrl)
|
|
||||||
: QWidget(parent), commanderDetails(_commanderDetails)
|
|
||||||
{
|
|
||||||
layout = new QGridLayout(this);
|
|
||||||
setLayout(layout);
|
|
||||||
|
|
||||||
bracketNavigationWidget = new EdhrecCommanderApiResponseBracketNavigationWidget(this, baseUrl);
|
|
||||||
|
|
||||||
connect(bracketNavigationWidget, &EdhrecCommanderApiResponseBracketNavigationWidget::requestNavigation, this,
|
|
||||||
&EdhrecCommanderApiResponseNavigationWidget::actRequestCommanderNavigation);
|
|
||||||
|
|
||||||
budgetNavigationWidget = new EdhrecCommanderApiResponseBudgetNavigationWidget(this, baseUrl);
|
|
||||||
|
|
||||||
connect(budgetNavigationWidget, &EdhrecCommanderApiResponseBudgetNavigationWidget::requestNavigation, this,
|
|
||||||
&EdhrecCommanderApiResponseNavigationWidget::actRequestCommanderNavigation);
|
|
||||||
|
|
||||||
comboPushButton = new QPushButton(this);
|
|
||||||
comboPushButton->setMinimumHeight(84);
|
|
||||||
comboPushButton->setStyleSheet("font-size: 24px");
|
|
||||||
averageDeckPushButton = new QPushButton(this);
|
|
||||||
averageDeckPushButton->setMinimumHeight(84);
|
|
||||||
averageDeckPushButton->setStyleSheet("font-size: 24px");
|
|
||||||
|
|
||||||
layout->addWidget(comboPushButton, 0, 0, 1, 1);
|
|
||||||
layout->addWidget(averageDeckPushButton, 0, 1, 1, 1);
|
|
||||||
|
|
||||||
layout->addWidget(bracketNavigationWidget, 1, 0, 1, 2);
|
|
||||||
layout->addWidget(budgetNavigationWidget, 2, 0, 1, 2);
|
|
||||||
|
|
||||||
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,
|
|
||||||
&EdhrecCommanderApiResponseNavigationWidget::actRequestComboNavigation);
|
|
||||||
connect(averageDeckPushButton, &QPushButton::clicked, this,
|
|
||||||
&EdhrecCommanderApiResponseNavigationWidget::actRequestAverageDeckNavigation);
|
|
||||||
connect(this, &EdhrecCommanderApiResponseNavigationWidget::requestUrl, parentTab,
|
|
||||||
&TabEdhRecMain::actNavigatePage);
|
|
||||||
}
|
|
||||||
|
|
||||||
retranslateUi();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecCommanderApiResponseNavigationWidget::retranslateUi()
|
|
||||||
{
|
|
||||||
comboPushButton->setText(tr("Combos"));
|
|
||||||
averageDeckPushButton->setText(tr("Average Deck"));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString EdhrecCommanderApiResponseNavigationWidget::addNavigationOptionsToUrl(QString baseUrl)
|
|
||||||
{
|
|
||||||
if (!bracketNavigationWidget->getSelectedGameChanger().isEmpty()) {
|
|
||||||
baseUrl += "/" + bracketNavigationWidget->getSelectedGameChanger();
|
|
||||||
}
|
|
||||||
if (!budgetNavigationWidget->getSelectedBudget().isEmpty()) {
|
|
||||||
baseUrl += "/" + budgetNavigationWidget->getSelectedBudget();
|
|
||||||
}
|
|
||||||
return baseUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecCommanderApiResponseNavigationWidget::actRequestCommanderNavigation()
|
|
||||||
{
|
|
||||||
emit requestUrl(addNavigationOptionsToUrl("/commanders/" + commanderDetails.getSanitized()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecCommanderApiResponseNavigationWidget::actRequestComboNavigation()
|
|
||||||
{
|
|
||||||
emit requestUrl("/combos/" + commanderDetails.getSanitized());
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdhrecCommanderApiResponseNavigationWidget::actRequestAverageDeckNavigation()
|
|
||||||
{
|
|
||||||
emit requestUrl(addNavigationOptionsToUrl("/average-decks/" + commanderDetails.getSanitized()));
|
|
||||||
}
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
/**
|
|
||||||
* @file edhrec_commander_api_response_navigation_widget.h
|
|
||||||
* @ingroup ApiResponseDisplayWidgets
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EDHREC_COMMANDER_API_RESPONSE_NAVIGATION_WIDGET_H
|
|
||||||
#define EDHREC_COMMANDER_API_RESPONSE_NAVIGATION_WIDGET_H
|
|
||||||
|
|
||||||
#include "edhrec_api_response_commander_details_display_widget.h"
|
|
||||||
#include "edhrec_commander_api_response_bracket_navigation_widget.h"
|
|
||||||
#include "edhrec_commander_api_response_budget_navigation_widget.h"
|
|
||||||
|
|
||||||
#include <QGridLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class EdhrecCommanderApiResponseNavigationWidget : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit EdhrecCommanderApiResponseNavigationWidget(
|
|
||||||
QWidget *parent,
|
|
||||||
const EdhrecCommanderApiResponseCommanderDetails &_commanderDetails,
|
|
||||||
QString baseUrl);
|
|
||||||
void retranslateUi();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void actRequestCommanderNavigation();
|
|
||||||
void actRequestComboNavigation();
|
|
||||||
void actRequestAverageDeckNavigation();
|
|
||||||
signals:
|
|
||||||
void requestUrl(QString url);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QGridLayout *layout;
|
|
||||||
|
|
||||||
EdhrecCommanderApiResponseBracketNavigationWidget *bracketNavigationWidget;
|
|
||||||
EdhrecCommanderApiResponseBudgetNavigationWidget *budgetNavigationWidget;
|
|
||||||
|
|
||||||
QPushButton *comboPushButton;
|
|
||||||
QPushButton *averageDeckPushButton;
|
|
||||||
|
|
||||||
EdhrecCommanderApiResponseCommanderDetails commanderDetails;
|
|
||||||
|
|
||||||
QString addNavigationOptionsToUrl(QString baseUrl);
|
|
||||||
QString buildComboUrl() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EDHREC_COMMANDER_API_RESPONSE_NAVIGATION_WIDGET_H
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
#include "edhrec_top_cards_api_response_display_widget.h"
|
|
||||||
|
|
||||||
#include "../../api_response/top_cards/edhrec_top_cards_api_response.h"
|
|
||||||
#include "../cards/edhrec_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 EdhrecApiResponseCardList &card_list : edhrec_commander_api_response_card_lists) {
|
|
||||||
auto cardListDisplayWidget = new EdhrecApiResponseCardListDisplayWidget(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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
/**
|
|
||||||
* @file edhrec_top_cards_api_response_display_widget.h
|
|
||||||
* @ingroup ApiResponseDisplayWidgets
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
#include "edhrec_top_commanders_api_response_display_widget.h"
|
|
||||||
|
|
||||||
#include "../../api_response/top_commanders/edhrec_top_commanders_api_response.h"
|
|
||||||
#include "../cards/edhrec_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 EdhrecApiResponseCardList &card_list : edhrec_commander_api_response_card_lists) {
|
|
||||||
auto cardListDisplayWidget = new EdhrecApiResponseCardListDisplayWidget(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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
/**
|
|
||||||
* @file edhrec_top_commanders_api_response_display_widget.h
|
|
||||||
* @ingroup ApiResponseDisplayWidgets
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue