diff --git a/.ci/Fedora41/Dockerfile b/.ci/Fedora43/Dockerfile similarity index 95% rename from .ci/Fedora41/Dockerfile rename to .ci/Fedora43/Dockerfile index fc9e86c2e..27570cf99 100644 --- a/.ci/Fedora41/Dockerfile +++ b/.ci/Fedora43/Dockerfile @@ -1,4 +1,4 @@ -FROM fedora:41 +FROM fedora:43 RUN dnf install -y \ ccache \ diff --git a/.ci/Servatrice_Debian11/Dockerfile b/.ci/Servatrice_Debian11/Dockerfile new file mode 100644 index 000000000..fadc9e0e7 --- /dev/null +++ b/.ci/Servatrice_Debian11/Dockerfile @@ -0,0 +1,21 @@ +FROM debian:11 + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + build-essential \ + ccache \ + clang-format \ + cmake \ + file \ + g++ \ + git \ + libmariadb-dev-compat \ + libprotobuf-dev \ + libqt5sql5-mysql \ + libqt5websockets5-dev \ + ninja-build \ + protobuf-compiler \ + qttools5-dev \ + qttools5-dev-tools \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* diff --git a/.ci/compile.sh b/.ci/compile.sh index ac1dc2a22..6c8a7db18 100755 --- a/.ci/compile.sh +++ b/.ci/compile.sh @@ -12,7 +12,7 @@ # --ccache [] uses ccache and shows stats, optionally provide size # --dir sets the name of the build dir, default is "build" # --target-macos-version sets the min os version - only used for macOS builds -# uses env: BUILDTYPE MAKE_INSTALL MAKE_PACKAGE PACKAGE_TYPE PACKAGE_SUFFIX MAKE_SERVER MAKE_TEST USE_CCACHE CCACHE_SIZE BUILD_DIR CMAKE_GENERATOR TARGET_MACOS_VERSION +# uses env: BUILDTYPE MAKE_INSTALL MAKE_PACKAGE PACKAGE_TYPE PACKAGE_SUFFIX MAKE_SERVER MAKE_NO_CLIENT MAKE_TEST USE_CCACHE CCACHE_SIZE BUILD_DIR CMAKE_GENERATOR TARGET_MACOS_VERSION # (correspond to args: --debug/--release --install --package --suffix --server --test --ccache --dir ) # exitcode: 1 for failure, 3 for invalid arguments @@ -47,6 +47,10 @@ while [[ $# != 0 ]]; do MAKE_SERVER=1 shift ;; + '--no-client') + MAKE_NO_CLIENT=1 + shift + ;; '--test') MAKE_TEST=1 shift @@ -117,6 +121,9 @@ flags=("-DCMAKE_BUILD_TYPE=$BUILDTYPE") if [[ $MAKE_SERVER ]]; then flags+=("-DWITH_SERVER=1") fi +if [[ $MAKE_NO_CLIENT ]]; then + flags+=("-DWITH_CLIENT=0" "-DWITH_ORACLE=0" "-DWITH_DBCONVERTER=0") +fi if [[ $MAKE_TEST ]]; then flags+=("-DTEST=1") fi @@ -220,12 +227,12 @@ fi echo "::group::Configure cmake" cmake --version -echo "Running cmake with flags: ${flags[@]}" +echo "Running cmake with flags: ${flags[*]}" cmake .. "${flags[@]}" echo "::endgroup::" echo "::group::Build project" -echo "Running cmake --build with flags: ${buildflags[@]}" +echo "Running cmake --build with flags: ${buildflags[*]}" cmake --build . "${buildflags[@]}" echo "::endgroup::" diff --git a/.ci/release_template.md b/.ci/release_template.md index e5c66a29a..0207662b5 100644 --- a/.ci/release_template.md +++ b/.ci/release_template.md @@ -23,8 +23,8 @@ Available pre-compiled binaries for installation: • Debian 13 TrixieDebian 12 BookwormDebian 11 Bullseye + • Fedora 43Fedora 42 - • Fedora 41 We are also packaged in Arch Linux's official extra repository, courtesy of @FFY00. General Linux support is available via a flatpak package at Flathub! diff --git a/.github/workflows/desktop-build.yml b/.github/workflows/desktop-build.yml index 045289c08..4c5b560d7 100644 --- a/.github/workflows/desktop-build.yml +++ b/.github/workflows/desktop-build.yml @@ -114,7 +114,12 @@ jobs: - distro: Debian version: 11 package: DEB - test: skip # Running tests on all distros is superfluous + + - distro: Servatrice_Debian + version: 11 + package: DEB + test: skip + server_only: yes - distro: Debian version: 12 @@ -126,12 +131,12 @@ jobs: package: DEB - distro: Fedora - version: 41 + version: 42 package: RPM test: skip # Running tests on all distros is superfluous - distro: Fedora - version: 42 + version: 43 package: RPM - distro: Ubuntu @@ -191,10 +196,11 @@ jobs: SUFFIX: '-${{matrix.distro}}${{matrix.version}}' package: '${{matrix.package}}' CMAKE_GENERATOR: '${{env.CMAKE_GENERATOR}}' + NO_CLIENT: ${{matrix.server_only == 'yes' && '--no-client' || '' }} run: | source .ci/docker.sh RUN --server --release --package "$package" --dir "$BUILD_DIR" \ - --ccache "$CCACHE_SIZE" + --ccache "$CCACHE_SIZE" $NO_CLIENT .ci/name_build.sh - name: Save compiler cache (ccache) diff --git a/.github/workflows/desktop-lint.yml b/.github/workflows/desktop-lint.yml index e54bdb087..087b27b79 100644 --- a/.github/workflows/desktop-lint.yml +++ b/.github/workflows/desktop-lint.yml @@ -20,7 +20,7 @@ on: jobs: format: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml index aa341c7a9..028d5ddf9 100644 --- a/.github/workflows/docker-release.yml +++ b/.github/workflows/docker-release.yml @@ -11,6 +11,7 @@ on: - master paths: - '.github/workflows/docker-release.yml' + - 'Dockerfile' jobs: docker: diff --git a/CMakeLists.txt b/CMakeLists.txt index 0af0823c8..affc6472d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -328,14 +328,19 @@ endif() include(CPack) +add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_interfaces ${CMAKE_BINARY_DIR}/libcockatrice_interfaces) add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_protocol ${CMAKE_BINARY_DIR}/libcockatrice_protocol) add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_network ${CMAKE_BINARY_DIR}/libcockatrice_network) add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_deck_list ${CMAKE_BINARY_DIR}/libcockatrice_deck_list) add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_rng ${CMAKE_BINARY_DIR}/libcockatrice_rng) -add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_settings ${CMAKE_BINARY_DIR}/libcockatrice_settings) add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_card ${CMAKE_BINARY_DIR}/libcockatrice_card) add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_utility ${CMAKE_BINARY_DIR}/libcockatrice_utility) -add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_models ${CMAKE_BINARY_DIR}/libcockatrice_models) +if(WITH_ORACLE OR WITH_CLIENT) + add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_settings ${CMAKE_BINARY_DIR}/libcockatrice_settings) + add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_models ${CMAKE_BINARY_DIR}/libcockatrice_models) + add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_filters ${CMAKE_BINARY_DIR}/libcockatrice_filters) +endif() + if(WITH_SERVER) add_subdirectory(servatrice) set(CPACK_INSTALL_CMAKE_PROJECTS "Servatrice;Servatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS}) diff --git a/Dockerfile b/Dockerfile index 2a0d10eba..80f9f69f2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,9 @@ -FROM ubuntu:24.04 +# -------- Build Stage -------- +FROM ubuntu:24.04 AS build ARG DEBIAN_FRONTEND=noninteractive -RUN apt-get update && apt-get install -y\ +RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ cmake \ file \ @@ -16,20 +17,28 @@ RUN apt-get update && apt-get install -y\ qt6-tools-dev \ qt6-tools-dev-tools -COPY ./CMakeLists.txt ./LICENSE ./README.md /home/servatrice/code/ -COPY ./cmake /home/servatrice/code/cmake -COPY ./common /home/servatrice/code/common -COPY ./servatrice /home/servatrice/code/servatrice +WORKDIR /src +COPY . . +RUN mkdir build && cd build && \ + cmake .. -DWITH_SERVER=1 -DWITH_CLIENT=0 -DWITH_ORACLE=0 -DWITH_DBCONVERTER=0 && \ + make -j$(nproc) && \ + make install -WORKDIR /home/servatrice/code -WORKDIR build -RUN cmake .. -DWITH_SERVER=1 -DWITH_CLIENT=0 -DWITH_ORACLE=0 -DWITH_DBCONVERTER=0 &&\ - make &&\ - make install +# -------- Runtime Stage (clean) -------- +FROM ubuntu:24.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + libprotobuf32t64 \ + libqt6sql6-mysql \ + libqt6websockets6 \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Only copy installed binaries, not source +COPY --from=build /usr/local /usr/local WORKDIR /home/servatrice EXPOSE 4748 - ENTRYPOINT [ "servatrice", "--log-to-console" ] diff --git a/Doxyfile b/Doxyfile index 298edc7f7..5b125ef13 100644 --- a/Doxyfile +++ b/Doxyfile @@ -991,7 +991,7 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = cockatrice common doc/doxygen-groups +INPUT = cockatrice doc/doxygen-groups libcockatrice_card libcockatrice_deck_list libcockatrice_filters libcockatrice_interfaces libcockatrice_models libcockatrice_network libcockatrice_protocol libcockatrice_rng libcockatrice_settings libcockatrice_utility # This tag can be used to specify the character encoding of the source files # that Doxygen parses. Internally Doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 9eed16ff7..995b55258 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -15,6 +15,11 @@ set(cockatrice_SOURCES src/client/network/update/client/release_channel.cpp src/client/network/update/card_spoiler/spoiler_background_updater.cpp src/client/sound_engine.cpp + src/client/settings/cache_settings.cpp + src/client/settings/card_counter_settings.cpp + src/client/settings/shortcut_treeview.cpp + src/client/settings/shortcuts_settings.cpp + src/interface/deck_loader/deck_loader.cpp src/interface/widgets/dialogs/dlg_connect.cpp src/interface/widgets/dialogs/dlg_convert_deck_to_cod_format.cpp src/interface/widgets/dialogs/dlg_create_game.cpp @@ -42,9 +47,6 @@ set(cockatrice_SOURCES src/interface/widgets/dialogs/tip_of_the_day.cpp src/filters/deck_filter_string.cpp src/filters/filter_builder.cpp - src/filters/filter_card.cpp - src/filters/filter_string.cpp - src/filters/filter_tree.cpp src/filters/filter_tree_model.cpp src/filters/syntax_help.cpp src/game/abstract_game.cpp @@ -148,6 +150,7 @@ set(cockatrice_SOURCES src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.cpp src/interface/widgets/deck_editor/deck_editor_printing_selector_dock_widget.cpp + src/interface/widgets/deck_editor/deck_list_style_proxy.cpp src/interface/widgets/general/background_sources.cpp src/interface/widgets/general/display/banner_widget.cpp src/interface/widgets/general/display/bar_widget.cpp @@ -360,10 +363,12 @@ if(Qt5_FOUND) cockatrice libcockatrice_card libcockatrice_deck_list + libcockatrice_filters libcockatrice_utility libcockatrice_network libcockatrice_models libcockatrice_rng + libcockatrice_settings ${COCKATRICE_QT_MODULES} ) else() @@ -371,10 +376,12 @@ else() cockatrice PUBLIC libcockatrice_card libcockatrice_deck_list + libcockatrice_filters libcockatrice_utility libcockatrice_network libcockatrice_models libcockatrice_rng + libcockatrice_settings ${COCKATRICE_QT_MODULES} ) endif() diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index 88d1e62dc..469cf3d77 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -25,6 +25,7 @@ resources/icons/lock.svg resources/icons/not_ready_start.svg resources/icons/pencil.svg + resources/icons/pin.svg resources/icons/player.svg resources/icons/ready_start.svg resources/icons/reload.svg diff --git a/cockatrice/resources/icons/pin.svg b/cockatrice/resources/icons/pin.svg new file mode 100644 index 000000000..71d4c9c9c --- /dev/null +++ b/cockatrice/resources/icons/pin.svg @@ -0,0 +1,24 @@ + + + + + + + diff --git a/cockatrice/resources/usericons/pawn_vip_double.svg b/cockatrice/resources/usericons/pawn_vip_double.svg index 0d002a791..b8c94387b 100644 --- a/cockatrice/resources/usericons/pawn_vip_double.svg +++ b/cockatrice/resources/usericons/pawn_vip_double.svg @@ -363,6 +363,6 @@ d="m 38.011063,984.77381 -10.143601,-5.23583 -10.063711,5.38779 1.845023,-11.2651 -8.233948,-7.90624 11.283888,-1.72639 4.974851,-10.27411 5.128803,10.19813 11.308575,1.55649 -8.114112,8.02918 z" inkscape:transform-center-x="0.094945927" inkscape:transform-center-y="-3.9764964" - transform="matrix(2.3768784,0,0,2.4799382,-15.920285,-1400.1716)" /> + transform="matrix(-2.3768784,0,0,2.4799382,115.920285,-1400.1716)" /> diff --git a/cockatrice/src/client/network/parsers/interface_json_deck_parser.h b/cockatrice/src/client/network/parsers/interface_json_deck_parser.h index 91915c306..1c8cbbed2 100644 --- a/cockatrice/src/client/network/parsers/interface_json_deck_parser.h +++ b/cockatrice/src/client/network/parsers/interface_json_deck_parser.h @@ -6,9 +6,10 @@ #ifndef INTERFACE_JSON_DECK_PARSER_H #define INTERFACE_JSON_DECK_PARSER_H +#include "../../../interface/deck_loader/deck_loader.h" + #include #include -#include class IJsonDeckParser { @@ -23,13 +24,13 @@ class ArchidektJsonParser : public IJsonDeckParser public: DeckLoader *parse(const QJsonObject &obj) override { - DeckLoader *list = new DeckLoader(); + DeckLoader *loader = new DeckLoader(nullptr); QString deckName = obj.value("name").toString(); QString deckDescription = obj.value("description").toString(); - list->setName(deckName); - list->setComments(deckDescription); + loader->getDeckList()->setName(deckName); + loader->getDeckList()->setComments(deckDescription); QString outputText; QTextStream outStream(&outputText); @@ -46,10 +47,10 @@ public: outStream << quantity << ' ' << cardName << " (" << setName << ") " << collectorNumber << '\n'; } - list->loadFromStream_Plain(outStream, false); - list->resolveSetNameAndNumberToProviderID(); + loader->getDeckList()->loadFromStream_Plain(outStream, false); + loader->resolveSetNameAndNumberToProviderID(); - return list; + return loader; } }; @@ -58,13 +59,13 @@ class MoxfieldJsonParser : public IJsonDeckParser public: DeckLoader *parse(const QJsonObject &obj) override { - DeckLoader *list = new DeckLoader(); + DeckLoader *loader = new DeckLoader(nullptr); QString deckName = obj.value("name").toString(); QString deckDescription = obj.value("description").toString(); - list->setName(deckName); - list->setComments(deckDescription); + loader->getDeckList()->setName(deckName); + loader->getDeckList()->setComments(deckDescription); QString outputText; QTextStream outStream(&outputText); @@ -93,8 +94,8 @@ public: outStream << quantity << ' ' << cardName << " (" << setName << ") " << collectorNumber << '\n'; } - list->loadFromStream_Plain(outStream, false); - list->resolveSetNameAndNumberToProviderID(); + loader->getDeckList()->loadFromStream_Plain(outStream, false); + loader->resolveSetNameAndNumberToProviderID(); QJsonObject commandersObj = obj.value("commanders").toObject(); if (!commandersObj.isEmpty()) { @@ -105,12 +106,12 @@ public: QString collectorNumber = cardData.value("cn").toString(); QString providerId = cardData.value("scryfall_id").toString(); - list->setBannerCard({commanderName, providerId}); - list->addCard(commanderName, DECK_ZONE_MAIN, -1, setName, collectorNumber, providerId); + loader->getDeckList()->setBannerCard({commanderName, providerId}); + loader->getDeckList()->addCard(commanderName, DECK_ZONE_MAIN, -1, setName, collectorNumber, providerId); } } - return list; + return loader; } }; diff --git a/cockatrice/src/client/network/update/card_spoiler/spoiler_background_updater.cpp b/cockatrice/src/client/network/update/card_spoiler/spoiler_background_updater.cpp index 7dce6a65c..cfd4cbbf8 100644 --- a/cockatrice/src/client/network/update/card_spoiler/spoiler_background_updater.cpp +++ b/cockatrice/src/client/network/update/card_spoiler/spoiler_background_updater.cpp @@ -2,6 +2,7 @@ #include "../../../../interface/window_main.h" #include "../../../../main.h" +#include "../../../settings/cache_settings.h" #include #include @@ -15,7 +16,6 @@ #include #include #include -#include #define SPOILERS_STATUS_URL "https://raw.githubusercontent.com/Cockatrice/Magic-Spoiler/files/SpoilerSeasonEnabled" #define SPOILERS_URL "https://raw.githubusercontent.com/Cockatrice/Magic-Spoiler/files/spoiler.xml" diff --git a/cockatrice/src/client/network/update/client/client_update_checker.cpp b/cockatrice/src/client/network/update/client/client_update_checker.cpp index f965ff6dc..64709113a 100644 --- a/cockatrice/src/client/network/update/client/client_update_checker.cpp +++ b/cockatrice/src/client/network/update/client/client_update_checker.cpp @@ -1,9 +1,8 @@ #include "client_update_checker.h" +#include "../../../settings/cache_settings.h" #include "release_channel.h" -#include - ClientUpdateChecker::ClientUpdateChecker(QObject *parent) : QObject(parent) { } diff --git a/libcockatrice_settings/libcockatrice/settings/cache_settings.cpp b/cockatrice/src/client/settings/cache_settings.cpp similarity index 99% rename from libcockatrice_settings/libcockatrice/settings/cache_settings.cpp rename to cockatrice/src/client/settings/cache_settings.cpp index f730877d1..0c6091a35 100644 --- a/libcockatrice_settings/libcockatrice/settings/cache_settings.cpp +++ b/cockatrice/src/client/settings/cache_settings.cpp @@ -1,8 +1,7 @@ #include "cache_settings.h" -#include "../../../cockatrice/src/client/network/update/client/release_channel.h" +#include "../network/update/client/release_channel.h" #include "card_counter_settings.h" -#include "card_override_settings.h" #include #include @@ -12,9 +11,15 @@ #include #include #include +#include #include -Q_GLOBAL_STATIC(SettingsCache, settingsCache); +Q_GLOBAL_STATIC(SettingsCache, settingsCache) + +SettingsCache &SettingsCache::instance() +{ + return *settingsCache; // returns a QT managed singleton reference +} QString SettingsCache::getDataPath() { @@ -61,9 +66,9 @@ void SettingsCache::translateLegacySettings() QStringList setsGroups = legacySetting.childGroups(); for (int i = 0; i < setsGroups.size(); i++) { legacySetting.beginGroup(setsGroups.at(i)); - cardDatabase().setEnabled(setsGroups.at(i), legacySetting.value("enabled").toBool()); - cardDatabase().setIsKnown(setsGroups.at(i), legacySetting.value("isknown").toBool()); - cardDatabase().setSortKey(setsGroups.at(i), legacySetting.value("sortkey").toUInt()); + cardDatabase()->setEnabled(setsGroups.at(i), legacySetting.value("enabled").toBool()); + cardDatabase()->setIsKnown(setsGroups.at(i), legacySetting.value("isknown").toBool()); + cardDatabase()->setSortKey(setsGroups.at(i), legacySetting.value("sortkey").toUInt()); legacySetting.endGroup(); } QStringList setsKeys = legacySetting.allKeys(); @@ -1500,11 +1505,6 @@ void SettingsCache::resetPaths() } } -SettingsCache &SettingsCache::instance() -{ - return *settingsCache; -} - CardCounterSettings &SettingsCache::cardCounters() const { return *cardCounterSettings; diff --git a/libcockatrice_settings/libcockatrice/settings/cache_settings.h b/cockatrice/src/client/settings/cache_settings.h similarity index 96% rename from libcockatrice_settings/libcockatrice/settings/cache_settings.h rename to cockatrice/src/client/settings/cache_settings.h index 90eba0cb1..cf0daff69 100644 --- a/libcockatrice_settings/libcockatrice/settings/cache_settings.h +++ b/cockatrice/src/client/settings/cache_settings.h @@ -7,15 +7,6 @@ #ifndef SETTINGSCACHE_H #define SETTINGSCACHE_H -#include "card_database_settings.h" -#include "card_override_settings.h" -#include "debug_settings.h" -#include "download_settings.h" -#include "game_filters_settings.h" -#include "layouts_settings.h" -#include "message_settings.h" -#include "recents_settings.h" -#include "servers_settings.h" #include "shortcuts_settings.h" #include @@ -23,6 +14,17 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include inline Q_LOGGING_CATEGORY(SettingsCacheLog, "settings_cache"); @@ -132,14 +134,13 @@ inline QStringList defaultTags = { class QSettings; class CardCounterSettings; -class SettingsCache : public QObject +class SettingsCache : public ICardDatabasePathProvider, public INetworkSettingsProvider { Q_OBJECT signals: void langChanged(); void picsPathChanged(); - void cardDatabasePathChanged(); void themeChanged(); void homeTabBackgroundSourceChanged(); void homeTabBackgroundShuffleFrequencyChanged(); @@ -374,19 +375,19 @@ public: { return customPicsPath; } - QString getCustomCardDatabasePath() const + QString getCustomCardDatabasePath() const override { return customCardDatabasePath; } - QString getCardDatabasePath() const + QString getCardDatabasePath() const override { return cardDatabasePath; } - QString getSpoilerCardDatabasePath() const + QString getSpoilerCardDatabasePath() const override { return spoilerDatabasePath; } - QString getTokenDatabasePath() const + QString getTokenDatabasePath() const override { return tokenDatabasePath; } @@ -483,7 +484,7 @@ public: return getLastCardUpdateCheck().daysTo(QDateTime::currentDateTime().date()) >= getCardUpdateCheckInterval() && getLastCardUpdateCheck() != QDateTime::currentDateTime().date(); } - bool getNotifyAboutUpdates() const + bool getNotifyAboutUpdates() const override { return notifyAboutUpdates; } @@ -835,11 +836,11 @@ public: { return rememberGameSettings; } - int getKeepAlive() const + int getKeepAlive() const override { return keepalive; } - int getTimeOut() const + int getTimeOut() const override { return timeout; } @@ -849,13 +850,13 @@ public: } void setClientID(const QString &clientID); void setClientVersion(const QString &clientVersion); - void setKnownMissingFeatures(const QString &_knownMissingFeatures); + void setKnownMissingFeatures(const QString &_knownMissingFeatures) override; void setUseTearOffMenus(bool _useTearOffMenus); void setCardViewInitialRowsMax(int _cardViewInitialRowsMax); void setCardViewExpandedRowsMax(int value); void setCloseEmptyCardView(QT_STATE_CHANGED_T value); void setFocusCardViewSearchBar(QT_STATE_CHANGED_T value); - QString getClientID() + QString getClientID() override { return clientID; } @@ -863,7 +864,7 @@ public: { return clientVersion; } - QString getKnownMissingFeatures() + QString getKnownMissingFeatures() override { return knownMissingFeatures; } @@ -891,9 +892,9 @@ public: { return *shortcutsSettings; } - CardDatabaseSettings &cardDatabase() const + CardDatabaseSettings *cardDatabase() const { - return *cardDatabaseSettings; + return cardDatabaseSettings; } ServersSettings &servers() const { diff --git a/libcockatrice_settings/libcockatrice/settings/card_counter_settings.cpp b/cockatrice/src/client/settings/card_counter_settings.cpp similarity index 100% rename from libcockatrice_settings/libcockatrice/settings/card_counter_settings.cpp rename to cockatrice/src/client/settings/card_counter_settings.cpp diff --git a/libcockatrice_settings/libcockatrice/settings/card_counter_settings.h b/cockatrice/src/client/settings/card_counter_settings.h similarity index 92% rename from libcockatrice_settings/libcockatrice/settings/card_counter_settings.h rename to cockatrice/src/client/settings/card_counter_settings.h index 94baeb9e2..f2c1c1d43 100644 --- a/libcockatrice_settings/libcockatrice/settings/card_counter_settings.h +++ b/cockatrice/src/client/settings/card_counter_settings.h @@ -7,9 +7,8 @@ #ifndef CARD_COUNTER_SETTINGS_H #define CARD_COUNTER_SETTINGS_H -#include "settings_manager.h" - #include +#include class QSettings; class QColor; diff --git a/libcockatrice_settings/libcockatrice/settings/shortcut_treeview.cpp b/cockatrice/src/client/settings/shortcut_treeview.cpp similarity index 100% rename from libcockatrice_settings/libcockatrice/settings/shortcut_treeview.cpp rename to cockatrice/src/client/settings/shortcut_treeview.cpp diff --git a/libcockatrice_settings/libcockatrice/settings/shortcut_treeview.h b/cockatrice/src/client/settings/shortcut_treeview.h similarity index 100% rename from libcockatrice_settings/libcockatrice/settings/shortcut_treeview.h rename to cockatrice/src/client/settings/shortcut_treeview.h diff --git a/libcockatrice_settings/libcockatrice/settings/shortcuts_settings.cpp b/cockatrice/src/client/settings/shortcuts_settings.cpp similarity index 100% rename from libcockatrice_settings/libcockatrice/settings/shortcuts_settings.cpp rename to cockatrice/src/client/settings/shortcuts_settings.cpp diff --git a/libcockatrice_settings/libcockatrice/settings/shortcuts_settings.h b/cockatrice/src/client/settings/shortcuts_settings.h similarity index 96% rename from libcockatrice_settings/libcockatrice/settings/shortcuts_settings.h rename to cockatrice/src/client/settings/shortcuts_settings.h index b6820798d..31e90bdc7 100644 --- a/libcockatrice_settings/libcockatrice/settings/shortcuts_settings.h +++ b/cockatrice/src/client/settings/shortcuts_settings.h @@ -33,6 +33,7 @@ public: Move_bottom, Gameplay, Drawing, + Hand, Chat_room, Game_window, Load_deck, @@ -71,6 +72,8 @@ public: return QApplication::translate("shortcutsTab", "Gameplay"); case Drawing: return QApplication::translate("shortcutsTab", "Drawing"); + case Hand: + return QApplication::translate("shortcutsTab", "Hand"); case Chat_room: return QApplication::translate("shortcutsTab", "Chat Room"); case Game_window: @@ -540,6 +543,9 @@ private: {"Player/aSelectColumn", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Select All Cards in Column"), parseSequenceString("Ctrl+Shift+C"), ShortcutGroup::Playing_Area)}, + {"Player/aRevealToAll", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Reveal Selected Cards to All Players"), + parseSequenceString(""), + ShortcutGroup::Playing_Area)}, {"Player/aMoveToBottomLibrary", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Bottom of Library"), parseSequenceString("Ctrl+B"), ShortcutGroup::Move_selected)}, @@ -562,9 +568,6 @@ private: ShortcutGroup::Move_selected)}, {"Player/aViewHand", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Hand"), parseSequenceString(""), ShortcutGroup::View)}, - {"Player/aSortHand", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Sort Hand"), - parseSequenceString("Ctrl+Shift+H"), - ShortcutGroup::View)}, {"Player/aViewGraveyard", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Graveyard"), parseSequenceString("F4"), ShortcutGroup::View)}, {"Player/aViewLibrary", @@ -672,6 +675,22 @@ private: {"Player/aAlwaysLookAtTopCard", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Always Look At Top Card"), parseSequenceString("Ctrl+Shift+N"), ShortcutGroup::Drawing)}, + {"Player/aSortHandByName", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Sort Hand by Name"), + parseSequenceString(""), + ShortcutGroup::Hand)}, + {"Player/aSortHandByType", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Sort Hand by Type"), + parseSequenceString("Ctrl+Shift+H"), + ShortcutGroup::Hand)}, + {"Player/aSortHandByManaValue", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Sort Hand by Mana Value"), + parseSequenceString(""), + ShortcutGroup::Hand)}, + {"Player/aRevealHandToAll", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Reveal Hand to All Players"), + parseSequenceString(""), + ShortcutGroup::Hand)}, + {"Player/aRevealRandomHandCardToAll", + ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Reveal Random Card to All Players"), + parseSequenceString(""), + ShortcutGroup::Hand)}, {"Player/aRotateViewCW", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Rotate View Clockwise"), parseSequenceString(""), ShortcutGroup::Gameplay)}, diff --git a/cockatrice/src/client/sound_engine.cpp b/cockatrice/src/client/sound_engine.cpp index 05f2d12d8..31cb2a35e 100644 --- a/cockatrice/src/client/sound_engine.cpp +++ b/cockatrice/src/client/sound_engine.cpp @@ -1,8 +1,9 @@ #include "sound_engine.h" +#include "settings/cache_settings.h" + #include #include -#include #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) #include diff --git a/cockatrice/src/database/interface/settings_card_preference_provider.h b/cockatrice/src/database/interface/settings_card_preference_provider.h new file mode 100644 index 000000000..4197bb53c --- /dev/null +++ b/cockatrice/src/database/interface/settings_card_preference_provider.h @@ -0,0 +1,21 @@ +#ifndef COCKATRICE_SETTINGS_CARD_PREFERENCE_PROVIDER_H +#define COCKATRICE_SETTINGS_CARD_PREFERENCE_PROVIDER_H +#include "../../client/settings/cache_settings.h" + +#include + +class SettingsCardPreferenceProvider : public ICardPreferenceProvider +{ +public: + QString getCardPreferenceOverride(const QString &cardName) const override + { + return SettingsCache::instance().cardOverrides().getCardPreferenceOverride(cardName); + } + + bool getIncludeRebalancedCards() const override + { + return SettingsCache::instance().getIncludeRebalancedCards(); + }; +}; + +#endif // COCKATRICE_SETTINGS_CARD_PREFERENCE_PROVIDER_H diff --git a/cockatrice/src/filters/deck_filter_string.cpp b/cockatrice/src/filters/deck_filter_string.cpp index ad0cdc336..c9adc17e9 100644 --- a/cockatrice/src/filters/deck_filter_string.cpp +++ b/cockatrice/src/filters/deck_filter_string.cpp @@ -1,8 +1,7 @@ #include "deck_filter_string.h" -#include "filter_string.h" - #include +#include #include static peg::parser search(R"( @@ -118,7 +117,7 @@ static void setupParserRules() return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) -> bool { int count = 0; - deck->deckLoader->forEachCard([&](InnerDecklistNode *, const DecklistCardNode *node) { + deck->deckLoader->getDeckList()->forEachCard([&](InnerDecklistNode *, const DecklistCardNode *node) { auto cardInfoPtr = CardDatabaseManager::query()->getCardInfo(node->getName()); if (!cardInfoPtr.isNull() && cardFilter.check(cardInfoPtr)) { count += node->getNumber(); @@ -137,7 +136,7 @@ static void setupParserRules() search["DeckNameQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter { auto name = std::any_cast(sv[0]); return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) { - return deck->deckLoader->getName().contains(name, Qt::CaseInsensitive); + return deck->deckLoader->getDeckList()->getName().contains(name, Qt::CaseInsensitive); }; }; diff --git a/cockatrice/src/filters/filter_builder.cpp b/cockatrice/src/filters/filter_builder.cpp index 8f91bcca7..7178ce95a 100644 --- a/cockatrice/src/filters/filter_builder.cpp +++ b/cockatrice/src/filters/filter_builder.cpp @@ -1,11 +1,11 @@ #include "filter_builder.h" #include "../interface/widgets/utility/custom_line_edit.h" -#include "filter_card.h" #include #include #include +#include FilterBuilder::FilterBuilder(QWidget *parent) : QWidget(parent) { diff --git a/cockatrice/src/filters/filter_tree_model.cpp b/cockatrice/src/filters/filter_tree_model.cpp index c4ce3aa35..f0a02ec79 100644 --- a/cockatrice/src/filters/filter_tree_model.cpp +++ b/cockatrice/src/filters/filter_tree_model.cpp @@ -1,9 +1,8 @@ #include "filter_tree_model.h" -#include "filter_card.h" -#include "filter_tree.h" - #include +#include +#include FilterTreeModel::FilterTreeModel(QObject *parent) : QAbstractItemModel(parent) { diff --git a/cockatrice/src/filters/filter_tree_model.h b/cockatrice/src/filters/filter_tree_model.h index 9e407f748..ce6eb85fc 100644 --- a/cockatrice/src/filters/filter_tree_model.h +++ b/cockatrice/src/filters/filter_tree_model.h @@ -7,9 +7,8 @@ #ifndef FILTERTREEMODEL_H #define FILTERTREEMODEL_H -#include "filter_card.h" - #include +#include class FilterTree; class CardFilter; diff --git a/cockatrice/src/game/board/abstract_card_drag_item.cpp b/cockatrice/src/game/board/abstract_card_drag_item.cpp index 3507a5a27..c961cbcb6 100644 --- a/cockatrice/src/game/board/abstract_card_drag_item.cpp +++ b/cockatrice/src/game/board/abstract_card_drag_item.cpp @@ -1,10 +1,11 @@ #include "abstract_card_drag_item.h" +#include "../../client/settings/cache_settings.h" + #include #include #include #include -#include static const float CARD_WIDTH_HALF = CARD_WIDTH / 2; static const float CARD_HEIGHT_HALF = CARD_HEIGHT / 2; diff --git a/cockatrice/src/game/board/abstract_card_item.cpp b/cockatrice/src/game/board/abstract_card_item.cpp index 2b3811b53..48720aa96 100644 --- a/cockatrice/src/game/board/abstract_card_item.cpp +++ b/cockatrice/src/game/board/abstract_card_item.cpp @@ -1,5 +1,6 @@ #include "abstract_card_item.h" +#include "../../client/settings/cache_settings.h" #include "../../interface/card_picture_loader/card_picture_loader.h" #include "../game_scene.h" @@ -10,7 +11,6 @@ #include #include #include -#include AbstractCardItem::AbstractCardItem(QGraphicsItem *parent, const CardRef &cardRef, Player *_owner, int _id) : ArrowTarget(_owner, parent), id(_id), cardRef(cardRef), tapped(false), facedown(false), tapAngle(0), diff --git a/cockatrice/src/game/board/abstract_counter.cpp b/cockatrice/src/game/board/abstract_counter.cpp index 44340cc34..8ca593ace 100644 --- a/cockatrice/src/game/board/abstract_counter.cpp +++ b/cockatrice/src/game/board/abstract_counter.cpp @@ -1,5 +1,6 @@ #include "abstract_counter.h" +#include "../../client/settings/cache_settings.h" #include "../../interface/widgets/tabs/tab_game.h" #include "../player/player.h" #include "translate_counter_name.h" @@ -14,7 +15,6 @@ #include #include #include -#include #include AbstractCounter::AbstractCounter(Player *_player, diff --git a/cockatrice/src/game/board/arrow_item.cpp b/cockatrice/src/game/board/arrow_item.cpp index cc4a4e6aa..fd044d042 100644 --- a/cockatrice/src/game/board/arrow_item.cpp +++ b/cockatrice/src/game/board/arrow_item.cpp @@ -1,6 +1,7 @@ #define _USE_MATH_DEFINES #include "arrow_item.h" +#include "../../client/settings/cache_settings.h" #include "../player/player.h" #include "../player/player_target.h" #include "../zones/card_zone.h" @@ -15,7 +16,6 @@ #include #include #include -#include #include ArrowItem::ArrowItem(Player *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &_color) diff --git a/cockatrice/src/game/board/card_item.cpp b/cockatrice/src/game/board/card_item.cpp index 64f905fee..52e237897 100644 --- a/cockatrice/src/game/board/card_item.cpp +++ b/cockatrice/src/game/board/card_item.cpp @@ -1,5 +1,6 @@ #include "card_item.h" +#include "../../client/settings/cache_settings.h" #include "../../interface/widgets/tabs/tab_game.h" #include "../game_scene.h" #include "../player/player.h" @@ -10,14 +11,13 @@ #include "arrow_item.h" #include "card_drag_item.h" +#include <../../client/settings/card_counter_settings.h> #include #include #include #include #include #include -#include -#include CardItem::CardItem(Player *_owner, QGraphicsItem *parent, const CardRef &cardRef, int _cardid, CardZoneLogic *_zone) : AbstractCardItem(parent, cardRef, _owner, _cardid), zone(_zone), attacking(false), destroyOnZoneChange(false), diff --git a/cockatrice/src/game/deckview/deck_view.cpp b/cockatrice/src/game/deckview/deck_view.cpp index da9c97db9..6c5e51fc4 100644 --- a/cockatrice/src/game/deckview/deck_view.cpp +++ b/cockatrice/src/game/deckview/deck_view.cpp @@ -1,5 +1,6 @@ #include "deck_view.h" +#include "../../client/settings/cache_settings.h" #include "../../interface/theme_manager.h" #include @@ -10,7 +11,6 @@ #include #include #include -#include DeckViewCardDragItem::DeckViewCardDragItem(DeckViewCard *_item, const QPointF &_hotSpot, diff --git a/cockatrice/src/game/deckview/deck_view_container.cpp b/cockatrice/src/game/deckview/deck_view_container.cpp index fc1c569b5..da24aa814 100644 --- a/cockatrice/src/game/deckview/deck_view_container.cpp +++ b/cockatrice/src/game/deckview/deck_view_container.cpp @@ -1,6 +1,8 @@ #include "deck_view_container.h" +#include "../../client/settings/cache_settings.h" #include "../../interface/card_picture_loader/card_picture_loader.h" +#include "../../interface/deck_loader/deck_loader.h" #include "../../interface/widgets/dialogs/dlg_load_deck.h" #include "../../interface/widgets/dialogs/dlg_load_deck_from_clipboard.h" #include "../../interface/widgets/dialogs/dlg_load_deck_from_website.h" @@ -15,14 +17,12 @@ #include #include #include -#include #include #include #include #include #include #include -#include #include ToggleButton::ToggleButton(QWidget *parent) : QPushButton(parent), state(false) @@ -264,7 +264,7 @@ void DeckViewContainer::loadLocalDeck() void DeckViewContainer::loadDeckFromFile(const QString &filePath) { DeckLoader::FileFormat fmt = DeckLoader::getFormatFromName(filePath); - DeckLoader deck; + DeckLoader deck(this); bool success = deck.loadFromFile(filePath, fmt, true); @@ -276,9 +276,9 @@ void DeckViewContainer::loadDeckFromFile(const QString &filePath) loadDeckFromDeckLoader(&deck); } -void DeckViewContainer::loadDeckFromDeckLoader(const DeckLoader *deck) +void DeckViewContainer::loadDeckFromDeckLoader(DeckLoader *deck) { - QString deckString = deck->writeToString_Native(); + QString deckString = deck->getDeckList()->writeToString_Native(); if (deckString.length() > MAX_FILE_LENGTH) { QMessageBox::critical(this, tr("Error"), tr("Deck is greater than maximum file size.")); @@ -331,8 +331,9 @@ void DeckViewContainer::loadFromWebsite() void DeckViewContainer::deckSelectFinished(const Response &r) { const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext); - DeckLoader newDeck(QString::fromStdString(resp.deck())); - CardPictureLoader::cacheCardPixmaps(CardDatabaseManager::query()->getCards(newDeck.getCardRefList())); + DeckLoader newDeck(this, new DeckList(QString::fromStdString(resp.deck()))); + CardPictureLoader::cacheCardPixmaps( + CardDatabaseManager::query()->getCards(newDeck.getDeckList()->getCardRefList())); setDeck(newDeck); switchToDeckLoadedView(); } @@ -413,8 +414,8 @@ void DeckViewContainer::setSideboardLocked(bool locked) deckView->resetSideboardPlan(); } -void DeckViewContainer::setDeck(const DeckLoader &deck) +void DeckViewContainer::setDeck(DeckLoader &deck) { - deckView->setDeck(deck); + deckView->setDeck(*deck.getDeckList()); switchToDeckLoadedView(); } \ No newline at end of file diff --git a/cockatrice/src/game/deckview/deck_view_container.h b/cockatrice/src/game/deckview/deck_view_container.h index 7f283527f..b764a6db3 100644 --- a/cockatrice/src/game/deckview/deck_view_container.h +++ b/cockatrice/src/game/deckview/deck_view_container.h @@ -7,8 +7,9 @@ #ifndef DECK_VIEW_CONTAINER_H #define DECK_VIEW_CONTAINER_H +#include "../../interface/deck_loader/deck_loader.h" + #include -#include class QVBoxLayout; class AbstractCardItem; @@ -84,12 +85,12 @@ public: void setReadyStart(bool ready); void readyAndUpdate(); void setSideboardLocked(bool locked); - void setDeck(const DeckLoader &deck); + void setDeck(DeckLoader &deck); void setVisualDeckStorageExists(bool exists); public slots: void loadDeckFromFile(const QString &filePath); - void loadDeckFromDeckLoader(const DeckLoader *deck); + void loadDeckFromDeckLoader(DeckLoader *deck); }; #endif // DECK_VIEW_CONTAINER_H diff --git a/cockatrice/src/game/dialogs/dlg_create_token.cpp b/cockatrice/src/game/dialogs/dlg_create_token.cpp index d2002b6e0..7cafc3219 100644 --- a/cockatrice/src/game/dialogs/dlg_create_token.cpp +++ b/cockatrice/src/game/dialogs/dlg_create_token.cpp @@ -1,5 +1,6 @@ #include "dlg_create_token.h" +#include "../../client/settings/cache_settings.h" #include "../../interface/widgets/cards/card_info_picture_widget.h" #include "../../main.h" @@ -20,7 +21,6 @@ #include #include #include -#include #include DlgCreateToken::DlgCreateToken(const QStringList &_predefinedTokens, QWidget *parent) @@ -199,16 +199,7 @@ void DlgCreateToken::tokenSelectionChanged(const QModelIndex ¤t, const QMo annotationEdit->setText(""); } - const auto &cardProviderId = - SettingsCache::instance().cardOverrides().getCardPreferenceOverride(cardInfo->getName()); - if (!cardProviderId.isEmpty()) { - CardRef ref; - ref.name = cardInfo->getName(); - ref.providerId = cardProviderId; - pic->setCard(CardDatabaseManager::query()->getCard(ref)); - } else { - pic->setCard(CardDatabaseManager::query()->getPreferredCard(cardInfo)); - } + pic->setCard(CardDatabaseManager::query()->getPreferredCard(cardInfo)); } void DlgCreateToken::updateSearchFieldWithoutUpdatingFilter(const QString &newValue) const diff --git a/cockatrice/src/game/dialogs/dlg_move_top_cards_until.cpp b/cockatrice/src/game/dialogs/dlg_move_top_cards_until.cpp index 3ea164f1e..a9db4cef6 100644 --- a/cockatrice/src/game/dialogs/dlg_move_top_cards_until.cpp +++ b/cockatrice/src/game/dialogs/dlg_move_top_cards_until.cpp @@ -1,7 +1,5 @@ #include "dlg_move_top_cards_until.h" -#include "../../filters/filter_string.h" - #include #include #include @@ -12,6 +10,7 @@ #include #include #include +#include DlgMoveTopCardsUntil::DlgMoveTopCardsUntil(QWidget *parent, QStringList exprs, uint _numberOfHits, bool autoPlay) : QDialog(parent) diff --git a/cockatrice/src/game/game_scene.cpp b/cockatrice/src/game/game_scene.cpp index 5af7b2e1d..2175f4aa2 100644 --- a/cockatrice/src/game/game_scene.cpp +++ b/cockatrice/src/game/game_scene.cpp @@ -1,5 +1,6 @@ #include "game_scene.h" +#include "../client/settings/cache_settings.h" #include "board/card_item.h" #include "phases_toolbar.h" #include "player/player.h" @@ -14,7 +15,6 @@ #include #include #include -#include #include /** diff --git a/cockatrice/src/game/game_view.cpp b/cockatrice/src/game/game_view.cpp index 607f0c85a..dd5cc70c1 100644 --- a/cockatrice/src/game/game_view.cpp +++ b/cockatrice/src/game/game_view.cpp @@ -1,11 +1,11 @@ #include "game_view.h" +#include "../client/settings/cache_settings.h" #include "game_scene.h" #include #include #include -#include GameView::GameView(GameScene *scene, QWidget *parent) : QGraphicsView(scene, parent), rubberBand(0) { diff --git a/cockatrice/src/game/log/message_log_widget.cpp b/cockatrice/src/game/log/message_log_widget.cpp index b9ad47d61..d4af5d00d 100644 --- a/cockatrice/src/game/log/message_log_widget.cpp +++ b/cockatrice/src/game/log/message_log_widget.cpp @@ -8,10 +8,10 @@ #include "../player/player.h" #include "../zones/card_zone.h" +#include <../../client/settings/card_counter_settings.h> #include #include #include -#include #include static const QString TABLE_ZONE_NAME = "table"; diff --git a/cockatrice/src/game/player/menu/card_menu.cpp b/cockatrice/src/game/player/menu/card_menu.cpp index cd73c6d88..ddf0a55f3 100644 --- a/cockatrice/src/game/player/menu/card_menu.cpp +++ b/cockatrice/src/game/player/menu/card_menu.cpp @@ -1,5 +1,6 @@ #include "card_menu.h" +#include "../../../client/settings/card_counter_settings.h" #include "../../../interface/widgets/tabs/tab_game.h" #include "../../board/card_item.h" #include "../../zones/logic/view_zone_logic.h" @@ -11,7 +12,6 @@ #include #include -#include CardMenu::CardMenu(Player *_player, const CardItem *_card, bool _shortcutsActive) : player(_player), card(_card), shortcutsActive(_shortcutsActive) @@ -66,6 +66,8 @@ CardMenu::CardMenu(Player *_player, const CardItem *_card, bool _shortcutsActive aPlayFacedown = new QAction(this); connect(aPlayFacedown, &QAction::triggered, playerActions, &PlayerActions::actPlayFacedown); + aRevealToAll = new QAction(this); + mCardCounters = new QMenu; for (int i = 0; i < 6; ++i) { @@ -274,7 +276,7 @@ void CardMenu::createHandOrCustomZoneMenu() QMenu *revealMenu = addMenu(tr("Re&veal to...")); - initContextualPlayersMenu(revealMenu); + initContextualPlayersMenu(revealMenu, aRevealToAll); connect(revealMenu, &QMenu::triggered, player->getPlayerActions(), &PlayerActions::actReveal); @@ -301,9 +303,19 @@ void CardMenu::createHandOrCustomZoneMenu() } } -void CardMenu::initContextualPlayersMenu(QMenu *menu) +/** + * @brief Populates the menu with an action for each active player. + * + * The "all players" action is created separately, so it has to be passed into this function. + * It will be put at the top of the menu. + * + * @param menu The menu to add the player actions to. + * @param allPlayersAction The action for "all players". + */ +void CardMenu::initContextualPlayersMenu(QMenu *menu, QAction *allPlayersAction) { - menu->addAction(tr("&All players"))->setData(-1); + allPlayersAction->setData(-1); + menu->addAction(allPlayersAction); menu->addSeparator(); for (const auto &playerInfo : playersInfo) { @@ -431,6 +443,7 @@ void CardMenu::retranslateUi() aPlay->setText(tr("&Play")); aHide->setText(tr("&Hide")); aPlayFacedown->setText(tr("Play &Face Down")); + aRevealToAll->setText(tr("&All players")); //: Turn sideways or back again aTap->setText(tr("&Tap / Untap")); aDoesntUntap->setText(tr("Toggle &normal untapping")); @@ -466,6 +479,9 @@ void CardMenu::setShortcutsActive() aHide->setShortcuts(shortcuts.getShortcut("Player/aHide")); aPlay->setShortcuts(shortcuts.getShortcut("Player/aPlay")); + aPlayFacedown->setShortcuts(shortcuts.getShortcut("Player/aPlayFacedown")); + aRevealToAll->setShortcuts(shortcuts.getShortcut("Player/aRevealToAll")); + aTap->setShortcuts(shortcuts.getShortcut("Player/aTap")); aDoesntUntap->setShortcuts(shortcuts.getShortcut("Player/aDoesntUntap")); aFlip->setShortcuts(shortcuts.getShortcut("Player/aFlip")); @@ -480,9 +496,6 @@ void CardMenu::setShortcutsActive() aSelectRow->setShortcuts(shortcuts.getShortcut("Player/aSelectRow")); aSelectColumn->setShortcuts(shortcuts.getShortcut("Player/aSelectColumn")); - aPlayFacedown->setShortcuts(shortcuts.getShortcut("Player/aPlayFacedown")); - aPlay->setShortcuts(shortcuts.getShortcut("Player/aPlay")); - static const QStringList colorWords = {"Red", "Yellow", "Green", "Cyan", "Purple", "Magenta"}; for (int i = 0; i < aAddCounter.size(); i++) { aAddCounter[i]->setShortcuts(shortcuts.getShortcut("Player/aCC" + colorWords[i])); diff --git a/cockatrice/src/game/player/menu/card_menu.h b/cockatrice/src/game/player/menu/card_menu.h index d42cda5fb..afe24da62 100644 --- a/cockatrice/src/game/player/menu/card_menu.h +++ b/cockatrice/src/game/player/menu/card_menu.h @@ -26,6 +26,7 @@ public: QMenu *mCardCounters; QAction *aPlay, *aPlayFacedown; + QAction *aRevealToAll; QAction *aHide; QAction *aClone; QAction *aSelectAll, *aSelectRow, *aSelectColumn; @@ -45,7 +46,7 @@ private: void addRelatedCardActions(); void retranslateUi(); - void initContextualPlayersMenu(QMenu *menu); + void initContextualPlayersMenu(QMenu *menu, QAction *allPlayersAction); void setShortcutsActive(); void addRelatedCardView(); }; diff --git a/cockatrice/src/game/player/menu/hand_menu.cpp b/cockatrice/src/game/player/menu/hand_menu.cpp index b8908bc3e..e193d2e4a 100644 --- a/cockatrice/src/game/player/menu/hand_menu.cpp +++ b/cockatrice/src/game/player/menu/hand_menu.cpp @@ -1,5 +1,7 @@ #include "hand_menu.h" +#include "../../../client/settings/cache_settings.h" +#include "../../../client/settings/shortcuts_settings.h" #include "../../abstract_game.h" #include "../../zones/hand_zone.h" #include "../player.h" @@ -7,8 +9,6 @@ #include #include -#include -#include HandMenu::HandMenu(Player *_player, PlayerActions *actions, QWidget *parent) : TearOffMenu(parent), player(_player) { @@ -17,18 +17,43 @@ HandMenu::HandMenu(Player *_player, PlayerActions *actions, QWidget *parent) : T connect(aViewHand, &QAction::triggered, actions, &PlayerActions::actViewHand); addAction(aViewHand); - aSortHand = new QAction(this); - connect(aSortHand, &QAction::triggered, actions, &PlayerActions::actSortHand); - addAction(aSortHand); + mSortHand = addMenu(QString()); + + aSortHandByName = new QAction(this); + aSortHandByName->setData(CardList::SortByName); + aSortHandByType = new QAction(this); + aSortHandByType->setData(CardList::SortByMainType); + aSortHandByManaValue = new QAction(this); + aSortHandByManaValue->setData(CardList::SortByManaValue); + + connect(aSortHandByType, &QAction::triggered, actions, &PlayerActions::actSortHand); + connect(aSortHandByName, &QAction::triggered, actions, &PlayerActions::actSortHand); + connect(aSortHandByManaValue, &QAction::triggered, actions, &PlayerActions::actSortHand); + + mSortHand->addAction(aSortHandByName); + mSortHand->addAction(aSortHandByType); + mSortHand->addAction(aSortHandByManaValue); } mRevealHand = addMenu(QString()); connect(mRevealHand, &QMenu::aboutToShow, this, &HandMenu::populateRevealHandMenuWithActivePlayers); + aRevealHandToAll = new QAction(this); + aRevealHandToAll->setData(-1); + connect(aRevealHandToAll, &QAction::triggered, this, &HandMenu::onRevealHandTriggered); + mRevealRandomHandCard = addMenu(QString()); connect(mRevealRandomHandCard, &QMenu::aboutToShow, this, &HandMenu::populateRevealRandomHandCardMenuWithActivePlayers); + aRevealRandomHandCardToAll = new QAction(this); + aRevealRandomHandCardToAll->setData(-1); + connect(aRevealRandomHandCardToAll, &QAction::triggered, this, &HandMenu::onRevealRandomHandCardTriggered); + + // We still need to add these actions to menu here so that the shortcuts are active right away + mRevealHand->addAction(aRevealHandToAll); + mRevealRandomHandCard->addAction(aRevealRandomHandCardToAll); + addSeparator(); aMulligan = new QAction(this); @@ -73,7 +98,12 @@ void HandMenu::retranslateUi() if (player->getPlayerInfo()->getLocalOrJudge()) { aViewHand->setText(tr("&View hand")); - aSortHand->setText(tr("&Sort hand")); + + mSortHand->setTitle(tr("Sort hand by...")); + aSortHandByName->setText(tr("Name")); + aSortHandByType->setText(tr("Type")); + aSortHandByManaValue->setText(tr("Mana Value")); + aMulligan->setText(tr("Take &mulligan")); mMoveHandMenu->setTitle(tr("&Move hand to...")); @@ -83,7 +113,10 @@ void HandMenu::retranslateUi() aMoveHandToRfg->setText(tr("&Exile")); mRevealHand->setTitle(tr("&Reveal hand to...")); + aRevealHandToAll->setText(tr("All players")); + mRevealRandomHandCard->setTitle(tr("Reveal r&andom card to...")); + aRevealRandomHandCardToAll->setText(tr("All players")); } } @@ -91,24 +124,30 @@ void HandMenu::setShortcutsActive() { ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); aViewHand->setShortcuts(shortcuts.getShortcut("Player/aViewHand")); - aSortHand->setShortcuts(shortcuts.getShortcut("Player/aSortHand")); + aSortHandByName->setShortcuts(shortcuts.getShortcut("Player/aSortHandByName")); + aSortHandByType->setShortcuts(shortcuts.getShortcut("Player/aSortHandByType")); + aSortHandByManaValue->setShortcuts(shortcuts.getShortcut("Player/aSortHandByManaValue")); aMulligan->setShortcuts(shortcuts.getShortcut("Player/aMulligan")); + aRevealHandToAll->setShortcuts(shortcuts.getShortcut("Player/aRevealHandToAll")); + aRevealRandomHandCardToAll->setShortcuts(shortcuts.getShortcut("Player/aRevealRandomHandCardToAll")); } void HandMenu::setShortcutsInactive() { aViewHand->setShortcut(QKeySequence()); - aSortHand->setShortcut(QKeySequence()); + aSortHandByName->setShortcut(QKeySequence()); + aSortHandByType->setShortcut(QKeySequence()); + aSortHandByManaValue->setShortcut(QKeySequence()); aMulligan->setShortcut(QKeySequence()); + aRevealHandToAll->setShortcut(QKeySequence()); + aRevealRandomHandCardToAll->setShortcut(QKeySequence()); } void HandMenu::populateRevealHandMenuWithActivePlayers() { mRevealHand->clear(); - QAction *allPlayers = mRevealHand->addAction(tr("&All players")); - allPlayers->setData(-1); - connect(allPlayers, &QAction::triggered, this, &HandMenu::onRevealHandTriggered); + mRevealHand->addAction(aRevealHandToAll); mRevealHand->addSeparator(); @@ -126,9 +165,7 @@ void HandMenu::populateRevealRandomHandCardMenuWithActivePlayers() { mRevealRandomHandCard->clear(); - QAction *allPlayers = mRevealRandomHandCard->addAction(tr("&All players")); - allPlayers->setData(-1); - connect(allPlayers, &QAction::triggered, this, &HandMenu::onRevealRandomHandCardTriggered); + mRevealRandomHandCard->addAction(aRevealRandomHandCardToAll); mRevealRandomHandCard->addSeparator(); diff --git a/cockatrice/src/game/player/menu/hand_menu.h b/cockatrice/src/game/player/menu/hand_menu.h index f66cf25bb..2c776b857 100644 --- a/cockatrice/src/game/player/menu/hand_menu.h +++ b/cockatrice/src/game/player/menu/hand_menu.h @@ -45,11 +45,18 @@ private: Player *player; QAction *aViewHand = nullptr; - QAction *aSortHand = nullptr; QAction *aMulligan = nullptr; + QMenu *mSortHand = nullptr; + QAction *aSortHandByName = nullptr; + QAction *aSortHandByType = nullptr; + QAction *aSortHandByManaValue = nullptr; + QMenu *mRevealHand = nullptr; + QAction *aRevealHandToAll = nullptr; + QMenu *mRevealRandomHandCard = nullptr; + QAction *aRevealRandomHandCardToAll = nullptr; QMenu *mMoveHandMenu = nullptr; QAction *aMoveHandToTopLibrary = nullptr; diff --git a/cockatrice/src/game/player/menu/library_menu.cpp b/cockatrice/src/game/player/menu/library_menu.cpp index 4303a6540..749439558 100644 --- a/cockatrice/src/game/player/menu/library_menu.cpp +++ b/cockatrice/src/game/player/menu/library_menu.cpp @@ -1,5 +1,7 @@ #include "library_menu.h" +#include "../../../client/settings/cache_settings.h" +#include "../../../client/settings/shortcuts_settings.h" #include "../../../interface/widgets/tabs/tab_game.h" #include "../../abstract_game.h" #include "../player.h" @@ -7,8 +9,6 @@ #include #include -#include -#include LibraryMenu::LibraryMenu(Player *_player, QWidget *parent) : TearOffMenu(parent), player(_player) { diff --git a/cockatrice/src/game/player/menu/player_menu.cpp b/cockatrice/src/game/player/menu/player_menu.cpp index f1c461435..82747d482 100644 --- a/cockatrice/src/game/player/menu/player_menu.cpp +++ b/cockatrice/src/game/player/menu/player_menu.cpp @@ -139,7 +139,14 @@ void PlayerMenu::retranslateUi() void PlayerMenu::refreshShortcuts() { if (shortcutsActive) { - setShortcutsActive(); + // Judges get access to every player's menus but only want shortcuts to be set for their own. + if (player->getPlayerInfo()->getLocalOrJudge() && !player->getPlayerInfo()->getLocal()) { + setShortcutsInactive(); + } else { + setShortcutsActive(); + } + } else { + setShortcutsInactive(); } } diff --git a/cockatrice/src/game/player/menu/say_menu.cpp b/cockatrice/src/game/player/menu/say_menu.cpp index 7db8f60be..3c4802aa5 100644 --- a/cockatrice/src/game/player/menu/say_menu.cpp +++ b/cockatrice/src/game/player/menu/say_menu.cpp @@ -1,10 +1,9 @@ #include "say_menu.h" +#include "../../../client/settings/cache_settings.h" #include "../player.h" #include "../player_actions.h" -#include - SayMenu::SayMenu(Player *_player) : player(_player) { connect(&SettingsCache::instance().messages(), &MessageSettings::messageMacrosChanged, this, &SayMenu::initSayMenu); diff --git a/cockatrice/src/game/player/menu/utility_menu.cpp b/cockatrice/src/game/player/menu/utility_menu.cpp index fa41579a5..15128defe 100644 --- a/cockatrice/src/game/player/menu/utility_menu.cpp +++ b/cockatrice/src/game/player/menu/utility_menu.cpp @@ -62,7 +62,8 @@ void UtilityMenu::populatePredefinedTokensMenu() return; } - InnerDecklistNode *tokenZone = dynamic_cast(_deck->getRoot()->findChild(DECK_ZONE_TOKENS)); + InnerDecklistNode *tokenZone = + dynamic_cast(_deck->getDeckList()->getRoot()->findChild(DECK_ZONE_TOKENS)); if (tokenZone) { if (!tokenZone->empty()) diff --git a/cockatrice/src/game/player/player.h b/cockatrice/src/game/player/player.h index eb62437fa..92125530a 100644 --- a/cockatrice/src/game/player/player.h +++ b/cockatrice/src/game/player/player.h @@ -7,7 +7,6 @@ #ifndef PLAYER_H #define PLAYER_H -#include "../../filters/filter_string.h" #include "../../interface/widgets/menus/tearoff_menu.h" #include "../board/abstract_graphics_item.h" #include "../dialogs/dlg_create_token.h" @@ -24,6 +23,7 @@ #include #include #include +#include #include #include @@ -66,7 +66,7 @@ class Player : public QObject Q_OBJECT signals: - void openDeckEditor(const DeckLoader *deck); + void openDeckEditor(DeckLoader *deck); void deckChanged(); void newCardAdded(AbstractCardItem *card); void rearrangeCounters(); diff --git a/cockatrice/src/game/player/player_actions.cpp b/cockatrice/src/game/player/player_actions.cpp index e37b34604..1fc91c492 100644 --- a/cockatrice/src/game/player/player_actions.cpp +++ b/cockatrice/src/game/player/player_actions.cpp @@ -139,9 +139,36 @@ void PlayerActions::actViewHand() player->getGameScene()->toggleZoneView(player, "hand", -1); } +/** + * @brief The sortHand actions only pass along a single SortOption in its data. + * This method fills out the rest of the sort priority list given that option. + * @param option The single sort option + * @return The sort priority list + */ +static QList expandSortOption(CardList::SortOption option) +{ + switch (option) { + case CardList::SortByName: + return {}; + case CardList::SortByMainType: + return {CardList::SortByMainType, CardList::SortByManaValue}; + case CardList::SortByManaValue: + return {CardList::SortByManaValue, CardList::SortByColors}; + default: + return {option}; + } +} + void PlayerActions::actSortHand() { - player->getGraphicsItem()->getHandZoneGraphicsItem()->sortHand(); + auto *action = qobject_cast(sender()); + CardList::SortOption option = static_cast(action->data().toInt()); + + QList sortOptions = expandSortOption(option); + + static QList defaultOptions = {CardList::SortByName, CardList::SortByPrinting}; + + player->getGraphicsItem()->getHandZoneGraphicsItem()->sortHand(sortOptions + defaultOptions); } void PlayerActions::actViewTopCards() diff --git a/cockatrice/src/game/player/player_actions.h b/cockatrice/src/game/player/player_actions.h index aba3726e8..2317d0b92 100644 --- a/cockatrice/src/game/player/player_actions.h +++ b/cockatrice/src/game/player/player_actions.h @@ -13,6 +13,7 @@ #include #include #include +#include #include namespace google diff --git a/cockatrice/src/game/player/player_info.h b/cockatrice/src/game/player/player_info.h index 81f3f1487..d60c245e2 100644 --- a/cockatrice/src/game/player/player_info.h +++ b/cockatrice/src/game/player/player_info.h @@ -7,6 +7,7 @@ #ifndef COCKATRICE_PLAYER_INFO_H #define COCKATRICE_PLAYER_INFO_H +#include "../../interface/deck_loader/deck_loader.h" #include "../zones/hand_zone.h" #include "../zones/pile_zone.h" #include "../zones/stack_zone.h" @@ -14,7 +15,6 @@ #include "player_target.h" #include -#include #include class PlayerInfo : public QObject diff --git a/cockatrice/src/game/zones/hand_zone.cpp b/cockatrice/src/game/zones/hand_zone.cpp index 5d63e8a28..860881f38 100644 --- a/cockatrice/src/game/zones/hand_zone.cpp +++ b/cockatrice/src/game/zones/hand_zone.cpp @@ -1,5 +1,6 @@ #include "hand_zone.h" +#include "../../client/settings/cache_settings.h" #include "../../interface/theme_manager.h" #include "../board/card_drag_item.h" #include "../board/card_item.h" @@ -7,7 +8,6 @@ #include #include -#include HandZone::HandZone(HandZoneLogic *_logic, int _zoneHeight, QGraphicsItem *parent) : SelectZone(_logic, parent), zoneHeight(_zoneHeight) @@ -111,12 +111,13 @@ void HandZone::reorganizeCards() update(); } -void HandZone::sortHand() +void HandZone::sortHand(const QList &options) { if (getLogic()->getCards().isEmpty()) { return; } - getLogic()->sortCards({CardList::SortByMainType, CardList::SortByManaValue, CardList::SortByColorGrouping}); + + getLogic()->sortCards(options); reorganizeCards(); } diff --git a/cockatrice/src/game/zones/hand_zone.h b/cockatrice/src/game/zones/hand_zone.h index 1cee40372..25f4148bd 100644 --- a/cockatrice/src/game/zones/hand_zone.h +++ b/cockatrice/src/game/zones/hand_zone.h @@ -27,7 +27,7 @@ public: QRectF boundingRect() const override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; void reorganizeCards() override; - void sortHand(); + void sortHand(const QList &options); void setWidth(qreal _width); }; diff --git a/cockatrice/src/game/zones/logic/view_zone_logic.cpp b/cockatrice/src/game/zones/logic/view_zone_logic.cpp index e61c126e7..5a4db3163 100644 --- a/cockatrice/src/game/zones/logic/view_zone_logic.cpp +++ b/cockatrice/src/game/zones/logic/view_zone_logic.cpp @@ -1,9 +1,8 @@ #include "view_zone_logic.h" +#include "../../../client/settings/cache_settings.h" #include "../../board/card_item.h" -#include - /** * @param _player the player that the cards are revealed to. * @param _origZone the zone the cards were revealed from. diff --git a/cockatrice/src/game/zones/select_zone.cpp b/cockatrice/src/game/zones/select_zone.cpp index ec24e4f9f..719eec148 100644 --- a/cockatrice/src/game/zones/select_zone.cpp +++ b/cockatrice/src/game/zones/select_zone.cpp @@ -1,11 +1,11 @@ #include "select_zone.h" +#include "../../client/settings/cache_settings.h" #include "../board/card_item.h" #include "../game_scene.h" #include #include -#include qreal divideCardSpaceInZone(qreal index, int cardCount, qreal totalHeight, qreal cardHeight, bool reverse) { diff --git a/cockatrice/src/game/zones/stack_zone.cpp b/cockatrice/src/game/zones/stack_zone.cpp index 4d8c15da8..0c0501705 100644 --- a/cockatrice/src/game/zones/stack_zone.cpp +++ b/cockatrice/src/game/zones/stack_zone.cpp @@ -1,5 +1,6 @@ #include "stack_zone.h" +#include "../../client/settings/cache_settings.h" #include "../../interface/theme_manager.h" #include "../board/arrow_item.h" #include "../board/card_drag_item.h" @@ -10,7 +11,6 @@ #include #include #include -#include StackZone::StackZone(StackZoneLogic *_logic, int _zoneHeight, QGraphicsItem *parent) : SelectZone(_logic, parent), zoneHeight(_zoneHeight) diff --git a/cockatrice/src/game/zones/table_zone.cpp b/cockatrice/src/game/zones/table_zone.cpp index b0484f984..55aaeaa39 100644 --- a/cockatrice/src/game/zones/table_zone.cpp +++ b/cockatrice/src/game/zones/table_zone.cpp @@ -1,5 +1,6 @@ #include "table_zone.h" +#include "../../client/settings/cache_settings.h" #include "../../interface/theme_manager.h" #include "../board/arrow_item.h" #include "../board/card_drag_item.h" @@ -13,7 +14,6 @@ #include #include #include -#include const QColor TableZone::BACKGROUND_COLOR = QColor(100, 100, 100); const QColor TableZone::FADE_MASK = QColor(0, 0, 0, 80); diff --git a/cockatrice/src/game/zones/view_zone.h b/cockatrice/src/game/zones/view_zone.h index 06c1e77fb..2ebb65cf0 100644 --- a/cockatrice/src/game/zones/view_zone.h +++ b/cockatrice/src/game/zones/view_zone.h @@ -7,12 +7,12 @@ #ifndef ZONEVIEWERZONE_H #define ZONEVIEWERZONE_H -#include "../../filters/filter_string.h" #include "logic/view_zone_logic.h" #include "select_zone.h" #include #include +#include #include inline Q_LOGGING_CATEGORY(ViewZoneLog, "view_zone"); diff --git a/cockatrice/src/game/zones/view_zone_widget.cpp b/cockatrice/src/game/zones/view_zone_widget.cpp index 2424feb9b..e2f242883 100644 --- a/cockatrice/src/game/zones/view_zone_widget.cpp +++ b/cockatrice/src/game/zones/view_zone_widget.cpp @@ -1,5 +1,6 @@ #include "view_zone_widget.h" +#include "../../client/settings/cache_settings.h" #include "../../filters/syntax_help.h" #include "../../interface/pixel_map_generator.h" #include "../board/card_item.h" @@ -17,7 +18,6 @@ #include #include #include -#include /** * @param _player the player the cards were revealed to. diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader.cpp b/cockatrice/src/interface/card_picture_loader/card_picture_loader.cpp index 56b00e4b8..aebb09f0f 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader.cpp +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader.cpp @@ -1,5 +1,7 @@ #include "card_picture_loader.h" +#include "../../client/settings/cache_settings.h" + #include #include #include @@ -15,7 +17,6 @@ #include #include #include -#include #include // never cache more than 300 cards at once for a single deck diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.cpp b/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.cpp index a2058b0ed..33a78ddaf 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.cpp +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.cpp @@ -1,11 +1,11 @@ #include "card_picture_loader_local.h" +#include "../../client/settings/cache_settings.h" #include "card_picture_to_load.h" #include #include #include -#include static constexpr int REFRESH_INTERVAL_MS = 10 * 1000; diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker.cpp b/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker.cpp index f92848b22..4a831c24a 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker.cpp +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker.cpp @@ -1,5 +1,6 @@ #include "card_picture_loader_worker.h" +#include "../../client/settings/cache_settings.h" #include "card_picture_loader_local.h" #include "card_picture_loader_worker_work.h" @@ -9,7 +10,6 @@ #include #include #include -#include #include static constexpr int MAX_REQUESTS_PER_SEC = 10; diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker_work.cpp b/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker_work.cpp index eae93d46f..07478ee70 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker_work.cpp +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker_work.cpp @@ -1,5 +1,6 @@ #include "card_picture_loader_worker_work.h" +#include "../../client/settings/cache_settings.h" #include "card_picture_loader_worker.h" #include @@ -11,7 +12,6 @@ #include #include #include -#include // Card back returned by gatherer when card is not found static const QStringList MD5_BLACKLIST = {"db0c48db407a907c16ade38de048a441"}; diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_to_load.cpp b/cockatrice/src/interface/card_picture_loader/card_picture_to_load.cpp index 4f1a27a98..3727988ad 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_to_load.cpp +++ b/cockatrice/src/interface/card_picture_loader/card_picture_to_load.cpp @@ -1,12 +1,14 @@ #include "card_picture_to_load.h" +#include "../../client/settings/cache_settings.h" + #include #include #include #include #include #include -#include +#include CardPictureToLoad::CardPictureToLoad(const ExactCard &_card) : card(_card), urlTemplates(SettingsCache::instance().downloads().getAllURLs()) @@ -33,7 +35,7 @@ QList CardPictureToLoad::extractSetsSorted(const ExactCard &card) } } if (sortedSets.empty()) { - sortedSets << CardSet::newInstance("", "", "", QDate()); + sortedSets << CardSet::newInstance(new NoopCardSetPriorityController(), "", "", "", QDate()); } std::sort(sortedSets.begin(), sortedSets.end(), SetPriorityComparator()); diff --git a/libcockatrice_models/libcockatrice/models/deck_list/deck_loader.cpp b/cockatrice/src/interface/deck_loader/deck_loader.cpp similarity index 76% rename from libcockatrice_models/libcockatrice/models/deck_list/deck_loader.cpp rename to cockatrice/src/interface/deck_loader/deck_loader.cpp index 95f4d9224..9e309c55d 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_loader.cpp +++ b/cockatrice/src/interface/deck_loader/deck_loader.cpp @@ -7,8 +7,13 @@ #include #include #include +#include #include #include +#include +#include +#include +#include #include #include #include @@ -20,26 +25,27 @@ const QStringList DeckLoader::ACCEPTED_FILE_EXTENSIONS = {"*.cod", "*.dec", "*.d const QStringList DeckLoader::FILE_NAME_FILTERS = { tr("Common deck formats (%1)").arg(ACCEPTED_FILE_EXTENSIONS.join(" ")), tr("All files (*.*)")}; -DeckLoader::DeckLoader() : DeckList(), lastFileName(QString()), lastFileFormat(CockatriceFormat), lastRemoteDeckId(-1) +DeckLoader::DeckLoader(QObject *parent) + : QObject(parent), deckList(new DeckList()), lastFileFormat(CockatriceFormat), lastRemoteDeckId(-1) { } -DeckLoader::DeckLoader(const QString &nativeString) - : DeckList(nativeString), lastFileName(QString()), lastFileFormat(CockatriceFormat), lastRemoteDeckId(-1) -{ -} - -DeckLoader::DeckLoader(const DeckList &other) - : DeckList(other), lastFileName(QString()), lastFileFormat(CockatriceFormat), lastRemoteDeckId(-1) +DeckLoader::DeckLoader(QObject *parent, DeckList *_deckList) + : QObject(parent), deckList(_deckList), lastFileFormat(CockatriceFormat), lastRemoteDeckId(-1) { } DeckLoader::DeckLoader(const DeckLoader &other) - : DeckList(other), lastFileName(other.lastFileName), lastFileFormat(other.lastFileFormat), + : QObject(), deckList(other.deckList), lastFileName(other.lastFileName), lastFileFormat(other.lastFileFormat), lastRemoteDeckId(other.lastRemoteDeckId) { } +void DeckLoader::setDeckList(DeckList *_deckList) +{ + deckList = _deckList; +} + bool DeckLoader::loadFromFile(const QString &fileName, FileFormat fmt, bool userRequest) { QFile file(fileName); @@ -50,15 +56,15 @@ bool DeckLoader::loadFromFile(const QString &fileName, FileFormat fmt, bool user bool result = false; switch (fmt) { case PlainTextFormat: - result = loadFromFile_Plain(&file); + result = deckList->loadFromFile_Plain(&file); break; case CockatriceFormat: { - result = loadFromFile_Native(&file); + result = deckList->loadFromFile_Native(&file); qCInfo(DeckLoaderLog) << "Loaded from" << fileName << "-" << result; if (!result) { qCInfo(DeckLoaderLog) << "Retrying as plain format"; file.seek(0); - result = loadFromFile_Plain(&file); + result = deckList->loadFromFile_Plain(&file); fmt = PlainTextFormat; } break; @@ -110,13 +116,13 @@ bool DeckLoader::loadFromFileAsync(const QString &fileName, FileFormat fmt, bool switch (fmt) { case PlainTextFormat: - return loadFromFile_Plain(&file); + return deckList->loadFromFile_Plain(&file); case CockatriceFormat: { bool result = false; - result = loadFromFile_Native(&file); + result = deckList->loadFromFile_Native(&file); if (!result) { file.seek(0); - return loadFromFile_Plain(&file); + return deckList->loadFromFile_Plain(&file); } return result; } @@ -132,7 +138,7 @@ bool DeckLoader::loadFromFileAsync(const QString &fileName, FileFormat fmt, bool bool DeckLoader::loadFromRemote(const QString &nativeString, int remoteDeckId) { - bool result = loadFromString_Native(nativeString); + bool result = deckList->loadFromString_Native(nativeString); if (result) { lastFileName = QString(); lastFileFormat = CockatriceFormat; @@ -153,10 +159,10 @@ bool DeckLoader::saveToFile(const QString &fileName, FileFormat fmt) bool result = false; switch (fmt) { case PlainTextFormat: - result = saveToFile_Plain(&file); + result = deckList->saveToFile_Plain(&file); break; case CockatriceFormat: - result = saveToFile_Native(&file); + result = deckList->saveToFile_Native(&file); break; } @@ -193,11 +199,11 @@ bool DeckLoader::updateLastLoadedTimestamp(const QString &fileName, FileFormat f // Perform file modifications switch (fmt) { case PlainTextFormat: - result = saveToFile_Plain(&file); + result = deckList->saveToFile_Plain(&file); break; case CockatriceFormat: - setLastLoadedTimestamp(QDateTime::currentDateTime().toString()); - result = saveToFile_Native(&file); + deckList->setLastLoadedTimestamp(QDateTime::currentDateTime().toString()); + result = deckList->saveToFile_Native(&file); break; } @@ -296,7 +302,7 @@ QString DeckLoader::exportDeckToDecklist(DecklistWebsite website) }; // call our struct function for each card in the deck - forEachCard(formatDeckListForExport); + deckList->forEachCard(formatDeckListForExport); // Remove the extra return at the end of the last cards mainBoardCards.chop(3); sideBoardCards.chop(3); @@ -344,7 +350,7 @@ void DeckLoader::setProviderIdToPreferredPrinting() SetProviderIdToPreferred setProviderIdToPreferred; // Call the forEachCard method for each card in the deck - forEachCard(setProviderIdToPreferred); + deckList->forEachCard(setProviderIdToPreferred); } /** @@ -365,7 +371,7 @@ void DeckLoader::resolveSetNameAndNumberToProviderID() card->setCardProviderId(providerId); }; - forEachCard(setProviderId); + deckList->forEachCard(setProviderId); } // This struct is here to support the forEachCard function call, defined in decklist. @@ -400,7 +406,7 @@ void DeckLoader::clearSetNamesAndNumbers() card->setCardProviderId(nullptr); }; - forEachCard(clearSetNameAndNumber); + deckList->forEachCard(clearSetNameAndNumber); } DeckLoader::FileFormat DeckLoader::getFormatFromName(const QString &fileName) @@ -427,8 +433,8 @@ bool DeckLoader::saveToStream_Plain(QTextStream &out, bool addComments, bool add } // loop zones - for (int i = 0; i < getRoot()->size(); i++) { - const auto *zoneNode = dynamic_cast(getRoot()->at(i)); + for (int i = 0; i < deckList->getRoot()->size(); i++) { + const auto *zoneNode = dynamic_cast(deckList->getRoot()->at(i)); saveToStream_DeckZone(out, zoneNode, addComments, addSetNameAndNumber); @@ -441,12 +447,12 @@ bool DeckLoader::saveToStream_Plain(QTextStream &out, bool addComments, bool add void DeckLoader::saveToStream_DeckHeader(QTextStream &out) const { - if (!getName().isEmpty()) { - out << "// " << getName() << "\n\n"; + if (!deckList->getName().isEmpty()) { + out << "// " << deckList->getName() << "\n\n"; } - if (!getComments().isEmpty()) { - QStringList commentRows = getComments().split(QRegularExpression("\n|\r\n|\r")); + if (!deckList->getComments().isEmpty()) { + QStringList commentRows = deckList->getComments().split(QRegularExpression("\n|\r\n|\r")); for (const QString &row : commentRows) { out << "// " << row << "\n"; } @@ -553,7 +559,7 @@ bool DeckLoader::convertToCockatriceFormat(QString fileName) switch (getFormatFromName(fileName)) { case PlainTextFormat: // Save in Cockatrice's native format - result = saveToFile_Native(&file); + result = deckList->saveToFile_Native(&file); break; case CockatriceFormat: qCInfo(DeckLoaderLog) << "File is already in Cockatrice format. No conversion needed."; @@ -603,3 +609,97 @@ QString DeckLoader::getCompleteCardName(const QString &cardName) const return cardName; } + +void DeckLoader::printDeckListNode(QTextCursor *cursor, InnerDecklistNode *node) +{ + const int totalColumns = 2; + + if (node->height() == 1) { + QTextBlockFormat blockFormat; + QTextCharFormat charFormat; + charFormat.setFontPointSize(11); + charFormat.setFontWeight(QFont::Bold); + cursor->insertBlock(blockFormat, charFormat); + + QTextTableFormat tableFormat; + tableFormat.setCellPadding(0); + tableFormat.setCellSpacing(0); + tableFormat.setBorder(0); + QTextTable *table = cursor->insertTable(node->size() + 1, totalColumns, tableFormat); + for (int i = 0; i < node->size(); i++) { + auto *card = dynamic_cast(node->at(i)); + + QTextCharFormat cellCharFormat; + cellCharFormat.setFontPointSize(9); + + QTextTableCell cell = table->cellAt(i, 0); + cell.setFormat(cellCharFormat); + QTextCursor cellCursor = cell.firstCursorPosition(); + cellCursor.insertText(QString("%1 ").arg(card->getNumber())); + + cell = table->cellAt(i, 1); + cell.setFormat(cellCharFormat); + cellCursor = cell.firstCursorPosition(); + cellCursor.insertText(card->getName()); + } + } else if (node->height() == 2) { + QTextBlockFormat blockFormat; + QTextCharFormat charFormat; + charFormat.setFontPointSize(14); + charFormat.setFontWeight(QFont::Bold); + + cursor->insertBlock(blockFormat, charFormat); + + QTextTableFormat tableFormat; + tableFormat.setCellPadding(10); + tableFormat.setCellSpacing(0); + tableFormat.setBorder(0); + QVector constraints; + for (int i = 0; i < totalColumns; i++) { + constraints << QTextLength(QTextLength::PercentageLength, 100.0 / totalColumns); + } + tableFormat.setColumnWidthConstraints(constraints); + + QTextTable *table = cursor->insertTable(1, totalColumns, tableFormat); + for (int i = 0; i < node->size(); i++) { + QTextCursor cellCursor = table->cellAt(0, (i * totalColumns) / node->size()).lastCursorPosition(); + printDeckListNode(&cellCursor, dynamic_cast(node->at(i))); + } + } + + cursor->movePosition(QTextCursor::End); +} + +void DeckLoader::printDeckList(QPrinter *printer) +{ + QTextDocument doc; + + QFont font("Serif"); + font.setStyleHint(QFont::Serif); + doc.setDefaultFont(font); + + QTextCursor cursor(&doc); + + QTextBlockFormat headerBlockFormat; + QTextCharFormat headerCharFormat; + headerCharFormat.setFontPointSize(16); + headerCharFormat.setFontWeight(QFont::Bold); + + cursor.insertBlock(headerBlockFormat, headerCharFormat); + cursor.insertText(deckList->getName()); + + headerCharFormat.setFontPointSize(12); + cursor.insertBlock(headerBlockFormat, headerCharFormat); + cursor.insertText(deckList->getComments()); + cursor.insertBlock(headerBlockFormat, headerCharFormat); + + for (int i = 0; i < deckList->getRoot()->size(); i++) { + cursor.insertHtml("
"); + // cursor.insertHtml("
"); + cursor.insertBlock(headerBlockFormat, headerCharFormat); + + printDeckListNode(&cursor, dynamic_cast(deckList->getRoot()->at(i))); + } + + doc.print(printer); +} diff --git a/libcockatrice_models/libcockatrice/models/deck_list/deck_loader.h b/cockatrice/src/interface/deck_loader/deck_loader.h similarity index 83% rename from libcockatrice_models/libcockatrice/models/deck_list/deck_loader.h rename to cockatrice/src/interface/deck_loader/deck_loader.h index f11ded444..c8d010f23 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_loader.h +++ b/cockatrice/src/interface/deck_loader/deck_loader.h @@ -8,17 +8,26 @@ #define DECK_LOADER_H #include +#include +#include #include inline Q_LOGGING_CATEGORY(DeckLoaderLog, "deck_loader") - class DeckLoader : public DeckList + class DeckLoader : public QObject { Q_OBJECT signals: void deckLoaded(); void loadFinished(bool success); +public slots: + /** + * @brief Prints the decklist to the provided QPrinter. + * @param printer The printer to render the decklist to. + */ + void printDeckList(QPrinter *printer); + public: enum FileFormat { @@ -43,14 +52,15 @@ public: }; private: + DeckList *deckList; QString lastFileName; FileFormat lastFileFormat; int lastRemoteDeckId; public: - DeckLoader(); - explicit DeckLoader(const QString &nativeString); - explicit DeckLoader(const DeckList &other); + DeckLoader(QObject *parent); + DeckLoader(QObject *parent, DeckList *_deckList); + void setDeckList(DeckList *_deckList); DeckLoader(const DeckLoader &other); const QString &getLastFileName() const { @@ -93,6 +103,14 @@ public: bool saveToStream_Plain(QTextStream &out, bool addComments = true, bool addSetNameAndNumber = true) const; bool convertToCockatriceFormat(QString fileName); + DeckList *getDeckList() + { + return deckList; + } + +private: + void printDeckListNode(QTextCursor *cursor, InnerDecklistNode *node); + protected: void saveToStream_DeckHeader(QTextStream &out) const; void saveToStream_DeckZone(QTextStream &out, @@ -104,8 +122,8 @@ protected: QList cards, bool addComments = true, bool addSetNameAndNumber = true) const; - [[nodiscard]] QString getCardZoneFromName(QString cardName, QString currentZoneName) override; - [[nodiscard]] QString getCompleteCardName(const QString &cardName) const override; + [[nodiscard]] QString getCardZoneFromName(QString cardName, QString currentZoneName); + [[nodiscard]] QString getCompleteCardName(const QString &cardName) const; }; #endif diff --git a/cockatrice/src/interface/theme_manager.cpp b/cockatrice/src/interface/theme_manager.cpp index 4cb66e2b1..ec52a0f6e 100644 --- a/cockatrice/src/interface/theme_manager.cpp +++ b/cockatrice/src/interface/theme_manager.cpp @@ -1,12 +1,13 @@ #include "theme_manager.h" +#include "../../client/settings/cache_settings.h" + #include #include #include #include #include #include -#include #define NONE_THEME_NAME "Default" #define STYLE_CSS_NAME "style.css" diff --git a/cockatrice/src/interface/widgets/cards/additional_info/color_identity_widget.cpp b/cockatrice/src/interface/widgets/cards/additional_info/color_identity_widget.cpp index c134b0aff..20f4b29df 100644 --- a/cockatrice/src/interface/widgets/cards/additional_info/color_identity_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/additional_info/color_identity_widget.cpp @@ -1,5 +1,6 @@ #include "color_identity_widget.h" +#include "../../../../client/settings/cache_settings.h" #include "mana_symbol_widget.h" #include @@ -8,7 +9,6 @@ #include #include #include -#include ColorIdentityWidget::ColorIdentityWidget(QWidget *parent, CardInfoPtr _card) : QWidget(parent), card(_card) { diff --git a/cockatrice/src/interface/widgets/cards/additional_info/mana_symbol_widget.cpp b/cockatrice/src/interface/widgets/cards/additional_info/mana_symbol_widget.cpp index 942635871..07cc382ad 100644 --- a/cockatrice/src/interface/widgets/cards/additional_info/mana_symbol_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/additional_info/mana_symbol_widget.cpp @@ -1,7 +1,8 @@ #include "mana_symbol_widget.h" +#include "../../../../client/settings/cache_settings.h" + #include -#include ManaSymbolWidget::ManaSymbolWidget(QWidget *parent, QString _symbol, bool _isActive, bool _mayBeToggled) : QLabel(parent), symbol(_symbol), isActive(_isActive), mayBeToggled(_mayBeToggled) diff --git a/cockatrice/src/interface/widgets/cards/card_info_frame_widget.cpp b/cockatrice/src/interface/widgets/cards/card_info_frame_widget.cpp index 6dad6424b..9fea41076 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_frame_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_frame_widget.cpp @@ -1,5 +1,6 @@ #include "card_info_frame_widget.h" +#include "../../../client/settings/cache_settings.h" #include "../../../game/board/card_item.h" #include "card_info_display_widget.h" #include "card_info_picture_widget.h" @@ -9,7 +10,6 @@ #include #include #include -#include #include CardInfoFrameWidget::CardInfoFrameWidget(QWidget *parent) diff --git a/cockatrice/src/interface/widgets/cards/card_info_picture_enlarged_widget.cpp b/cockatrice/src/interface/widgets/cards/card_info_picture_enlarged_widget.cpp index ead669e7c..9a79bd32f 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_picture_enlarged_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_picture_enlarged_widget.cpp @@ -1,10 +1,10 @@ #include "card_info_picture_enlarged_widget.h" +#include "../../../client/settings/cache_settings.h" #include "../../../interface/card_picture_loader/card_picture_loader.h" #include #include -#include #include /** diff --git a/cockatrice/src/interface/widgets/cards/card_info_picture_widget.cpp b/cockatrice/src/interface/widgets/cards/card_info_picture_widget.cpp index 8b744dc73..8ad86eadc 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_picture_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_picture_widget.cpp @@ -1,5 +1,6 @@ #include "card_info_picture_widget.h" +#include "../../../client/settings/cache_settings.h" #include "../../../game/board/card_item.h" #include "../../../interface/card_picture_loader/card_picture_loader.h" #include "../../../interface/widgets/tabs/tab_supervisor.h" @@ -12,7 +13,6 @@ #include #include #include -#include #include /** diff --git a/cockatrice/src/interface/widgets/cards/card_size_widget.cpp b/cockatrice/src/interface/widgets/cards/card_size_widget.cpp index c084dac64..927d9bf5f 100644 --- a/cockatrice/src/interface/widgets/cards/card_size_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_size_widget.cpp @@ -1,10 +1,9 @@ #include "card_size_widget.h" +#include "../../../client/settings/cache_settings.h" #include "../printing_selector/printing_selector.h" #include "../visual_deck_storage/visual_deck_storage_widget.h" -#include - /** * @class CardSizeWidget * @brief A widget for adjusting card sizes using a slider. diff --git a/cockatrice/src/interface/widgets/cards/deck_preview_card_picture_widget.cpp b/cockatrice/src/interface/widgets/cards/deck_preview_card_picture_widget.cpp index dfa7bc025..8f4e1a115 100644 --- a/cockatrice/src/interface/widgets/cards/deck_preview_card_picture_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/deck_preview_card_picture_widget.cpp @@ -1,5 +1,7 @@ #include "deck_preview_card_picture_widget.h" +#include "../../../client/settings/cache_settings.h" + #include #include #include @@ -7,7 +9,6 @@ #include #include #include -#include /** * @brief Constructs a CardPictureWithTextOverlay widget. diff --git a/cockatrice/src/interface/widgets/deck_analytics/mana_base_widget.cpp b/cockatrice/src/interface/widgets/deck_analytics/mana_base_widget.cpp index 29fa3ece8..27079dd52 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/mana_base_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/mana_base_widget.cpp @@ -1,5 +1,6 @@ #include "mana_base_widget.h" +#include "../../deck_loader/deck_loader.h" #include "../general/display/banner_widget.h" #include "../general/display/bar_widget.h" @@ -8,7 +9,6 @@ #include #include #include -#include ManaBaseWidget::ManaBaseWidget(QWidget *parent, DeckListModel *_deckListModel) : QWidget(parent), deckListModel(_deckListModel) diff --git a/cockatrice/src/interface/widgets/deck_analytics/mana_curve_widget.cpp b/cockatrice/src/interface/widgets/deck_analytics/mana_curve_widget.cpp index e2067326a..668b3afd5 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/mana_curve_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/mana_curve_widget.cpp @@ -1,13 +1,13 @@ #include "mana_curve_widget.h" #include "../../../main.h" +#include "../../deck_loader/deck_loader.h" #include "../general/display/banner_widget.h" #include "../general/display/bar_widget.h" #include #include #include -#include #include ManaCurveWidget::ManaCurveWidget(QWidget *parent, DeckListModel *_deckListModel) diff --git a/cockatrice/src/interface/widgets/deck_analytics/mana_devotion_widget.cpp b/cockatrice/src/interface/widgets/deck_analytics/mana_devotion_widget.cpp index d23d6bfab..4454caef1 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/mana_devotion_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/mana_devotion_widget.cpp @@ -1,6 +1,7 @@ #include "mana_devotion_widget.h" #include "../../../main.h" +#include "../../deck_loader/deck_loader.h" #include "../general/display/banner_widget.h" #include "../general/display/bar_widget.h" @@ -8,7 +9,6 @@ #include #include #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp index 4695eda0b..b5aa007f0 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp @@ -1,5 +1,6 @@ #include "deck_editor_database_display_widget.h" +#include "../../../client/settings/cache_settings.h" #include "../../../filters/syntax_help.h" #include "../../../interface/widgets/tabs/abstract_tab_deck_editor.h" #include "../../../interface/widgets/tabs/tab_supervisor.h" @@ -14,7 +15,6 @@ #include #include #include -#include static bool canBeCommander(const CardInfo &cardInfo) { @@ -143,7 +143,7 @@ void DeckEditorDatabaseDisplayWidget::updateCard(const QModelIndex ¤t, con } if (!current.model()->hasChildren(current.sibling(current.row(), 0))) { - emit cardChanged(getCardOrPinnedPrinting(cardName)); + emit cardChanged(CardDatabaseManager::query()->getPreferredCard(cardName)); } } @@ -176,21 +176,7 @@ ExactCard DeckEditorDatabaseDisplayWidget::currentCard() const const QString cardName = currentIndex.sibling(currentIndex.row(), 0).data().toString(); - return getCardOrPinnedPrinting(cardName); -} - -ExactCard DeckEditorDatabaseDisplayWidget::getCardOrPinnedPrinting(QString cardName) const -{ - const auto &cardProviderId = SettingsCache::instance().cardOverrides().getCardPreferenceOverride(cardName); - - ExactCard card = CardDatabaseManager::query()->getCard({cardName}); - - if (cardProviderId != "") { - return ExactCard(card.getCardPtr(), - CardDatabaseManager::query()->getSpecificPrinting({cardName, cardProviderId})); - } - - return card; + return CardDatabaseManager::query()->getPreferredCard(cardName); } void DeckEditorDatabaseDisplayWidget::databaseCustomMenu(QPoint point) diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.h b/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.h index 0add31322..efac97eae 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.h +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.h @@ -31,7 +31,6 @@ public: public slots: ExactCard currentCard() const; - ExactCard getCardOrPinnedPrinting(QString cardName) const; void setFilterTree(FilterTree *filterTree); void clearAllDatabaseFilters(); diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp index f5970c1e6..c83171c78 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp @@ -1,5 +1,9 @@ #include "deck_editor_deck_dock_widget.h" +#include "../../../client/settings/cache_settings.h" +#include "../../deck_loader/deck_loader.h" +#include "deck_list_style_proxy.h" + #include #include #include @@ -7,7 +11,6 @@ #include #include #include -#include #include DeckEditorDeckDockWidget::DeckEditorDeckDockWidget(AbstractTabDeckEditor *parent) @@ -28,9 +31,15 @@ void DeckEditorDeckDockWidget::createDeckDock() deckModel = new DeckListModel(this); deckModel->setObjectName("deckModel"); connect(deckModel, &DeckListModel::deckHashChanged, this, &DeckEditorDeckDockWidget::updateHash); + + deckLoader = new DeckLoader(this, deckModel->getDeckList()); + + DeckListStyleProxy *proxy = new DeckListStyleProxy(this); + proxy->setSourceModel(deckModel); + deckView = new QTreeView(); deckView->setObjectName("deckView"); - deckView->setModel(deckModel); + deckView->setModel(proxy); deckView->setUniformRowHeights(true); deckView->setSortingEnabled(true); deckView->sortByColumn(1, Qt::AscendingOrder); @@ -110,8 +119,8 @@ void DeckEditorDeckDockWidget::createDeckDock() activeGroupCriteriaComboBox->addItem(tr("Mana Cost"), DeckListModelGroupCriteria::MANA_COST); activeGroupCriteriaComboBox->addItem(tr("Colors"), DeckListModelGroupCriteria::COLOR); connect(activeGroupCriteriaComboBox, QOverload::of(&QComboBox::currentIndexChanged), [this]() { - deckModel->setActiveGroupCriteria( - static_cast(activeGroupCriteriaComboBox->currentData(Qt::UserRole).toInt())); + deckModel->setActiveGroupCriteria(static_cast( + activeGroupCriteriaComboBox->currentData(Qt::UserRole).toInt())); deckModel->sort(deckView->header()->sortIndicatorSection(), deckView->header()->sortIndicatorOrder()); deckView->expandAll(); deckView->expandAll(); @@ -365,7 +374,10 @@ void DeckEditorDeckDockWidget::syncBannerCardComboBoxSelectionWithDeck() */ void DeckEditorDeckDockWidget::setDeck(DeckLoader *_deck) { - deckModel->setDeckList(_deck); + deckLoader = _deck; + deckModel->setDeckList(deckLoader->getDeckList()); + connect(deckLoader, &DeckLoader::deckLoaded, deckModel, &DeckListModel::rebuildTree); + connect(deckLoader->getDeckList(), &DeckList::deckHashChanged, deckModel, &DeckListModel::deckHashChanged); nameEdit->setText(deckModel->getDeckList()->getName()); commentsEdit->setText(deckModel->getDeckList()->getComments()); @@ -382,7 +394,12 @@ void DeckEditorDeckDockWidget::setDeck(DeckLoader *_deck) emit deckChanged(); } -DeckLoader *DeckEditorDeckDockWidget::getDeckList() +DeckLoader *DeckEditorDeckDockWidget::getDeckLoader() +{ + return deckLoader; +} + +DeckList *DeckEditorDeckDockWidget::getDeckList() { return deckModel->getDeckList(); } diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.h b/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.h index c6c3181b8..90b6f9797 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.h +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.h @@ -27,6 +27,7 @@ class DeckEditorDeckDockWidget : public QDockWidget Q_OBJECT public: explicit DeckEditorDeckDockWidget(AbstractTabDeckEditor *parent); + DeckLoader *deckLoader; DeckListModel *deckModel; QTreeView *deckView; QComboBox *bannerCardComboBox; @@ -41,12 +42,17 @@ public: { return nameEdit->text().simplified(); } + QComboBox *getGroupByComboBox() + { + return activeGroupCriteriaComboBox; + } public slots: void cleanDeck(); void updateBannerCardComboBox(); void setDeck(DeckLoader *_deck); - DeckLoader *getDeckList(); + DeckLoader *getDeckLoader(); + DeckList *getDeckList(); void actIncrement(); bool swapCard(const QModelIndex &idx); void actDecrementCard(const ExactCard &card, QString zoneName); diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.cpp index 69eb71c2b..4957e24ec 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.cpp @@ -1,5 +1,6 @@ #include "deck_editor_filter_dock_widget.h" +#include "../../../client/settings/cache_settings.h" #include "../../../filters/filter_builder.h" #include "../../../filters/filter_tree_model.h" @@ -7,7 +8,6 @@ #include #include #include -#include DeckEditorFilterDockWidget::DeckEditorFilterDockWidget(AbstractTabDeckEditor *parent) : QDockWidget(parent), deckEditor(parent) diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_list_style_proxy.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_list_style_proxy.cpp new file mode 100644 index 000000000..b697f130f --- /dev/null +++ b/cockatrice/src/interface/widgets/deck_editor/deck_list_style_proxy.cpp @@ -0,0 +1,38 @@ +#include "deck_list_style_proxy.h" + +#include +#include +#include +#include + +QVariant DeckListStyleProxy::data(const QModelIndex &index, int role) const +{ + QVariant value = QIdentityProxyModel::data(index, role); + + const bool isCard = QIdentityProxyModel::data(index, DeckRoles::IsCardRole).toBool(); + + if (role == Qt::FontRole && !isCard) { + QFont f; + f.setBold(true); + return f; + } + + if (role == Qt::BackgroundRole) { + if (isCard) { + const bool legal = + true; // TODO: Not implemented yet. QIdentityProxyModel::data(index, DeckRoles::IsLegalRole).toBool(); + int base = 255 - (index.row() % 2) * 30; + return legal ? QBrush(QColor(base, base, base)) : QBrush(QColor(255, base / 3, base / 3)); + } else { + int depth = QIdentityProxyModel::data(index, DeckRoles::DepthRole).toInt(); + int color = 90 + 60 * depth; + return QBrush(QColor(color, 255, color)); + } + } + + if (role == Qt::ForegroundRole) { + return QBrush(QColor(0, 0, 0)); + } + + return value; +} diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_list_style_proxy.h b/cockatrice/src/interface/widgets/deck_editor/deck_list_style_proxy.h new file mode 100644 index 000000000..a7e58eb02 --- /dev/null +++ b/cockatrice/src/interface/widgets/deck_editor/deck_list_style_proxy.h @@ -0,0 +1,15 @@ +#ifndef COCKATRICE_DECK_LIST_STYLE_PROXY_H +#define COCKATRICE_DECK_LIST_STYLE_PROXY_H + +#include + +class DeckListStyleProxy : public QIdentityProxyModel +{ + Q_OBJECT +public: + using QIdentityProxyModel::QIdentityProxyModel; + + QVariant data(const QModelIndex &index, int role) const override; +}; + +#endif // COCKATRICE_DECK_LIST_STYLE_PROXY_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_connect.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_connect.cpp index 3f398218e..ed32b356c 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_connect.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_connect.cpp @@ -1,5 +1,7 @@ #include "dlg_connect.h" +#include "../../../client/settings/cache_settings.h" + #include #include #include @@ -12,7 +14,6 @@ #include #include #include -#include #include DlgConnect::DlgConnect(QWidget *parent) : QDialog(parent) diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_create_game.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_create_game.cpp index 86b002c92..d69c7a08a 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_create_game.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_create_game.cpp @@ -1,5 +1,6 @@ #include "dlg_create_game.h" +#include "../../../client/settings/cache_settings.h" #include "../interface/widgets/tabs/tab_room.h" #include @@ -17,7 +18,6 @@ #include #include #include -#include #include void DlgCreateGame::sharedCtor() diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_default_tags_editor.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_default_tags_editor.cpp index 39b7333c5..5b120b1e2 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_default_tags_editor.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_default_tags_editor.cpp @@ -1,8 +1,9 @@ #include "dlg_default_tags_editor.h" +#include "../../../client/settings/cache_settings.h" + #include #include -#include DlgDefaultTagsEditor::DlgDefaultTagsEditor(QWidget *parent) : QDialog(parent) { diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_edit_password.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_edit_password.cpp index 105783210..998dafb66 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_edit_password.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_edit_password.cpp @@ -1,11 +1,12 @@ #include "dlg_edit_password.h" +#include "../../../client/settings/cache_settings.h" + #include #include #include #include #include -#include #include DlgEditPassword::DlgEditPassword(QWidget *parent) : QDialog(parent) diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_edit_user.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_edit_user.cpp index 70e99ca28..c39c87d4a 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_edit_user.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_edit_user.cpp @@ -1,11 +1,12 @@ #include "dlg_edit_user.h" +#include "../../../client/settings/cache_settings.h" + #include #include #include #include #include -#include #include DlgEditUser::DlgEditUser(QWidget *parent, QString email, QString country, QString realName) : QDialog(parent) diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_challenge.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_challenge.cpp index a8999d1e3..c8c86d1f1 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_challenge.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_challenge.cpp @@ -1,5 +1,7 @@ #include "dlg_forgot_password_challenge.h" +#include "../../../client/settings/cache_settings.h" + #include #include #include @@ -7,7 +9,6 @@ #include #include #include -#include #include DlgForgotPasswordChallenge::DlgForgotPasswordChallenge(QWidget *parent) : QDialog(parent) diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_request.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_request.cpp index 000e7b0f1..4921630f3 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_request.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_request.cpp @@ -1,5 +1,7 @@ #include "dlg_forgot_password_request.h" +#include "../../../client/settings/cache_settings.h" + #include #include #include @@ -7,7 +9,6 @@ #include #include #include -#include #include DlgForgotPasswordRequest::DlgForgotPasswordRequest(QWidget *parent) : QDialog(parent) diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_reset.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_reset.cpp index 43b6c2fb9..f08347879 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_reset.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_reset.cpp @@ -1,5 +1,7 @@ #include "dlg_forgot_password_reset.h" +#include "../../../client/settings/cache_settings.h" + #include #include #include @@ -7,7 +9,6 @@ #include #include #include -#include #include DlgForgotPasswordReset::DlgForgotPasswordReset(QWidget *parent) : QDialog(parent) diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_load_deck.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_load_deck.cpp index 47718e158..b87800909 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_load_deck.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_load_deck.cpp @@ -1,7 +1,7 @@ #include "dlg_load_deck.h" -#include -#include +#include "../../../client/settings/cache_settings.h" +#include "../../deck_loader/deck_loader.h" DlgLoadDeck::DlgLoadDeck(QWidget *parent) : QFileDialog(parent, tr("Load Deck")) { diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_load_deck_from_clipboard.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_load_deck_from_clipboard.cpp index e15e7518f..59170c0fc 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_load_deck_from_clipboard.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_load_deck_from_clipboard.cpp @@ -1,5 +1,7 @@ #include "dlg_load_deck_from_clipboard.h" +#include "../../../client/settings/cache_settings.h" +#include "../../deck_loader/deck_loader.h" #include "dlg_settings.h" #include @@ -11,8 +13,6 @@ #include #include #include -#include -#include /** * Creates the main layout and connects the signals that are common to all versions of this window @@ -75,12 +75,12 @@ bool AbstractDlgDeckTextEdit::loadIntoDeck(DeckLoader *deckLoader) const QString buffer = contentsEdit->toPlainText(); if (buffer.contains("")) { - return deckLoader->loadFromString_Native(buffer); + return deckLoader->getDeckList()->loadFromString_Native(buffer); } QTextStream stream(&buffer); - if (deckLoader->loadFromStream_Plain(stream, true)) { + if (deckLoader->getDeckList()->loadFromStream_Plain(stream, true)) { if (loadSetNameAndNumberCheckBox->isChecked()) { deckLoader->resolveSetNameAndNumberToProviderID(); } else { @@ -121,8 +121,7 @@ void DlgLoadDeckFromClipboard::actRefresh() void DlgLoadDeckFromClipboard::actOK() { - deckList = new DeckLoader; - deckList->setParent(this); + deckList = new DeckLoader(this); if (loadIntoDeck(deckList)) { accept(); diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_load_deck_from_website.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_load_deck_from_website.cpp index 44a4432c7..5b3e44877 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_load_deck_from_website.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_load_deck_from_website.cpp @@ -95,9 +95,9 @@ void DlgLoadDeckFromWebsite::accept() } // Parse the plain text deck here - DeckLoader *loader = new DeckLoader(); + DeckLoader *loader = new DeckLoader(this); QTextStream stream(&deckText); - loader->loadFromStream_Plain(stream, false); + loader->getDeckList()->loadFromStream_Plain(stream, false); loader->resolveSetNameAndNumberToProviderID(); deck = loader; diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_manage_sets.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_manage_sets.cpp index 50233e03b..2d3bc08a4 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_manage_sets.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_manage_sets.cpp @@ -1,5 +1,6 @@ #include "dlg_manage_sets.h" +#include "../../../client/settings/cache_settings.h" #include "../interface/card_picture_loader/card_picture_loader.h" #include "../interface/widgets/utility/custom_line_edit.h" #include "../main.h" @@ -21,7 +22,6 @@ #include #include #include -#include #define SORT_RESET -1 diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_register.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_register.cpp index e71759554..dff99e4d8 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_register.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_register.cpp @@ -1,5 +1,7 @@ #include "dlg_register.h" +#include "../../../client/settings/cache_settings.h" + #include #include #include @@ -8,7 +10,6 @@ #include #include #include -#include #include DlgRegister::DlgRegister(QWidget *parent) : QDialog(parent) diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_select_set_for_cards.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_select_set_for_cards.cpp index a2c68410c..31e2f8d14 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_select_set_for_cards.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_select_set_for_cards.cpp @@ -1,5 +1,6 @@ #include "dlg_select_set_for_cards.h" +#include "../../deck_loader/deck_loader.h" #include "../interface/widgets/cards/card_info_picture_widget.h" #include "../interface/widgets/general/layout_containers/flow_widget.h" #include "dlg_select_set_for_cards.h" @@ -16,7 +17,6 @@ #include #include #include -#include #include #include @@ -162,14 +162,14 @@ void DlgSelectSetForCards::actOK() void DlgSelectSetForCards::actClear() { - model->getDeckList()->clearSetNamesAndNumbers(); + qobject_cast(model->getDeckList())->clearSetNamesAndNumbers(); accept(); } void DlgSelectSetForCards::actSetAllToPreferred() { - model->getDeckList()->clearSetNamesAndNumbers(); - model->getDeckList()->setProviderIdToPreferredPrinting(); + qobject_cast(model->getDeckList())->clearSetNamesAndNumbers(); + qobject_cast(model->getDeckList())->setProviderIdToPreferredPrinting(); accept(); } diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp index 0c4b7797e..d825a2125 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp @@ -1,5 +1,7 @@ #include "dlg_settings.h" +#include "../../../client/settings/cache_settings.h" +#include "../../../client/settings/shortcut_treeview.h" #include "../client/network/update/card_spoiler/spoiler_background_updater.h" #include "../client/network/update/client/release_channel.h" #include "../client/sound_engine.h" @@ -12,6 +14,7 @@ #include "../interface/widgets/utility/sequence_edit.h" #include "../main.h" +#include <../../client/settings/card_counter_settings.h> #include #include #include @@ -45,9 +48,6 @@ #include #include #include -#include -#include -#include #define WIKI_CUSTOM_PIC_URL "https://github.com/Cockatrice/Cockatrice/wiki/Custom-Picture-Download-URLs" #define WIKI_CUSTOM_SHORTCUTS "https://github.com/Cockatrice/Cockatrice/wiki/Custom-Keyboard-Shortcuts" diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_startup_card_check.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_startup_card_check.cpp index c2a03a55e..ac1922a9d 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_startup_card_check.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_startup_card_check.cpp @@ -1,7 +1,8 @@ #include "dlg_startup_card_check.h" +#include "../../../client/settings/cache_settings.h" + #include -#include DlgStartupCardCheck::DlgStartupCardCheck(QWidget *parent) : QDialog(parent) { diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_tip_of_the_day.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_tip_of_the_day.cpp index 6023ac48c..0197d3dbf 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_tip_of_the_day.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_tip_of_the_day.cpp @@ -1,5 +1,6 @@ #include "dlg_tip_of_the_day.h" +#include "../../../client/settings/cache_settings.h" #include "tip_of_the_day.h" #include @@ -9,7 +10,6 @@ #include #include #include -#include #define MIN_TIP_IMAGE_HEIGHT 200 #define MIN_TIP_IMAGE_WIDTH 200 diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp index cd7f3e8ba..19182c55b 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp @@ -1,5 +1,6 @@ #include "dlg_update.h" +#include "../../../client/settings/cache_settings.h" #include "../client/network/update/client/client_update_checker.h" #include "../client/network/update/client/release_channel.h" #include "../interface/window_main.h" @@ -13,7 +14,6 @@ #include #include #include -#include #include DlgUpdate::DlgUpdate(QWidget *parent) : QDialog(parent) diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_view_log.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_view_log.cpp index 0fb98bef9..3dd0fedb3 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_view_log.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_view_log.cpp @@ -1,5 +1,6 @@ #include "dlg_view_log.h" +#include "../../../client/settings/cache_settings.h" #include "../../logger.h" #include @@ -7,7 +8,6 @@ #include #include #include -#include DlgViewLog::DlgViewLog(QWidget *parent) : QDialog(parent) { diff --git a/cockatrice/src/interface/widgets/general/home_styled_button.cpp b/cockatrice/src/interface/widgets/general/home_styled_button.cpp index 66bb0417b..07c9894c1 100644 --- a/cockatrice/src/interface/widgets/general/home_styled_button.cpp +++ b/cockatrice/src/interface/widgets/general/home_styled_button.cpp @@ -9,7 +9,7 @@ HomeStyledButton::HomeStyledButton(const QString &text, QPair _g : QPushButton(text, parent), gradientColors(_gradientColors) { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - setMinimumHeight(50); + setMinimumHeight(25); setStyleSheet(generateButtonStylesheet(gradientColors)); } diff --git a/cockatrice/src/interface/widgets/general/home_widget.cpp b/cockatrice/src/interface/widgets/general/home_widget.cpp index f36f1831a..59237cc47 100644 --- a/cockatrice/src/interface/widgets/general/home_widget.cpp +++ b/cockatrice/src/interface/widgets/general/home_widget.cpp @@ -1,5 +1,6 @@ #include "home_widget.h" +#include "../../../client/settings/cache_settings.h" #include "../../../interface/widgets/tabs/tab_supervisor.h" #include "../../window_main.h" #include "background_sources.h" @@ -11,7 +12,6 @@ #include #include #include -#include HomeWidget::HomeWidget(QWidget *parent, TabSupervisor *_tabSupervisor) : QWidget(parent), tabSupervisor(_tabSupervisor), background("theme:backgrounds/home"), overlay("theme:cockatrice") @@ -19,7 +19,7 @@ HomeWidget::HomeWidget(QWidget *parent, TabSupervisor *_tabSupervisor) layout = new QGridLayout(this); backgroundSourceCard = new CardInfoPictureArtCropWidget(this); - backgroundSourceDeck = new DeckLoader(); + backgroundSourceDeck = new DeckLoader(this); backgroundSourceDeck->loadFromFile(SettingsCache::instance().getDeckPath() + "background.cod", DeckLoader::CockatriceFormat, false); @@ -94,7 +94,7 @@ void HomeWidget::updateRandomCard() newCard.getCardPtr()->getProperty("layout") != "normal"); break; case BackgroundSources::DeckFileArt: - QList cardRefs = backgroundSourceDeck->getCardRefList(); + QList cardRefs = backgroundSourceDeck->getDeckList()->getCardRefList(); ExactCard oldCard = backgroundSourceCard->getCard(); if (!cardRefs.empty()) { diff --git a/cockatrice/src/interface/widgets/menus/deck_editor_menu.cpp b/cockatrice/src/interface/widgets/menus/deck_editor_menu.cpp index aac488dd1..775efafbd 100644 --- a/cockatrice/src/interface/widgets/menus/deck_editor_menu.cpp +++ b/cockatrice/src/interface/widgets/menus/deck_editor_menu.cpp @@ -1,7 +1,7 @@ #include "../../../interface/widgets/menus/deck_editor_menu.h" -#include -#include +#include "../../../client/settings/cache_settings.h" +#include "../../../client/settings/shortcuts_settings.h" DeckEditorMenu::DeckEditorMenu(AbstractTabDeckEditor *parent) : QMenu(parent), deckEditor(parent) { diff --git a/cockatrice/src/interface/widgets/menus/tearoff_menu.h b/cockatrice/src/interface/widgets/menus/tearoff_menu.h index d2b3f3413..3e6c47012 100644 --- a/cockatrice/src/interface/widgets/menus/tearoff_menu.h +++ b/cockatrice/src/interface/widgets/menus/tearoff_menu.h @@ -6,8 +6,9 @@ #pragma once +#include "../../../client/settings/cache_settings.h" + #include -#include class TearOffMenu : public QMenu { diff --git a/cockatrice/src/interface/widgets/printing_selector/all_zones_card_amount_widget.h b/cockatrice/src/interface/widgets/printing_selector/all_zones_card_amount_widget.h index b16319da9..bf8ade36a 100644 --- a/cockatrice/src/interface/widgets/printing_selector/all_zones_card_amount_widget.h +++ b/cockatrice/src/interface/widgets/printing_selector/all_zones_card_amount_widget.h @@ -7,12 +7,12 @@ #ifndef ALL_ZONES_CARD_AMOUNT_WIDGET_H #define ALL_ZONES_CARD_AMOUNT_WIDGET_H +#include "../../deck_loader/deck_loader.h" #include "card_amount_widget.h" #include #include #include -#include class AllZonesCardAmountWidget : public QWidget { diff --git a/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.h b/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.h index 8bb3b2ee5..543964a79 100644 --- a/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.h +++ b/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.h @@ -9,6 +9,7 @@ #define CARD_AMOUNT_WIDGET_H #include "../../../interface/widgets/tabs/abstract_tab_deck_editor.h" +#include "../../deck_loader/deck_loader.h" #include "../general/display/dynamic_font_size_push_button.h" #include @@ -18,7 +19,6 @@ #include #include #include -#include class CardAmountWidget : public QWidget { diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector.cpp b/cockatrice/src/interface/widgets/printing_selector/printing_selector.cpp index 8afd56f9a..1a47c56a6 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector.cpp +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector.cpp @@ -1,5 +1,6 @@ #include "printing_selector.h" +#include "../../../client/settings/cache_settings.h" #include "../../../interface/card_picture_loader/card_picture_loader.h" #include "../../../interface/widgets/dialogs/dlg_select_set_for_cards.h" #include "printing_selector_card_display_widget.h" @@ -9,7 +10,6 @@ #include #include -#include #include /** diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.cpp b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.cpp index 56e5d1aab..5f3a44b30 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.cpp +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.cpp @@ -1,13 +1,16 @@ #include "printing_selector_card_overlay_widget.h" +#include "../../../client/settings/cache_settings.h" #include "printing_selector_card_display_widget.h" +#include +#include #include #include #include +#include #include #include -#include #include /** @@ -46,6 +49,15 @@ PrintingSelectorCardOverlayWidget::PrintingSelectorCardOverlayWidget(QWidget *pa cardInfoPicture->setCard(_rootCard); mainLayout->addWidget(cardInfoPicture); + initializePinBadge(); + + // Update when this overlay emits cardPreferenceChanged or when size/scale changes + connect(this, &PrintingSelectorCardOverlayWidget::cardPreferenceChanged, this, + &PrintingSelectorCardOverlayWidget::updatePinBadgeVisibility); + connect(cardSizeSlider, &QSlider::valueChanged, this, &PrintingSelectorCardOverlayWidget::updatePinBadgeVisibility); + // initial state + updatePinBadgeVisibility(); + // Add AllZonesCardAmountWidget allZonesCardAmountWidget = new AllZonesCardAmountWidget(this, deckEditor, deckModel, deckView, cardSizeSlider, _rootCard); @@ -128,6 +140,40 @@ void PrintingSelectorCardOverlayWidget::enterEvent(QEvent *event) // Show the widget if amounts are 0 allZonesCardAmountWidget->setVisible(true); } +/** + * @brief Updates the pin badge visibility and position based on the card's pinned state. + * + * This method checks whether the current card printing is pinned and updates the + * pin badge accordingly. If the card is pinned, the badge is made visible and positioned in the + * top-right corner of the card image with appropriate margins. If the card is not pinned, the + * badge is hidden. + * + * The method is called whenever the card preference changes or the card size is adjusted via + * the slider to ensure the badge remains properly positioned. + */ +void PrintingSelectorCardOverlayWidget::updatePinBadgeVisibility() +{ + if (!pinBadge || !cardInfoPicture) + return; + + // Query the persisted preference override to decide whether this printing is pinned. + const auto &preferredProviderId = + SettingsCache::instance().cardOverrides().getCardPreferenceOverride(rootCard.getName()); + const auto &cardProviderId = rootCard.getPrinting().getUuid(); + const bool isPinned = (!preferredProviderId.isEmpty() && preferredProviderId == cardProviderId); + + // Toggle the badge once; the pixmap was already rasterized in initializePinBadge(). + pinBadge->setVisible(isPinned); + + if (isPinned) { + // Keep a small margin that scales with the card size to avoid obscuring stuff. + const int margin = qMax(3, int(cardInfoPicture->width() * 0.03)); + int x = qMax(0, cardInfoPicture->width() - pinBadge->width() - margin); + int y = margin * 3; + pinBadge->move(x, y); + pinBadge->raise(); + } +} /** * @brief Handles the mouse leave event when the cursor leaves the overlay widget area. @@ -204,3 +250,57 @@ void PrintingSelectorCardOverlayWidget::customMenu(QPoint point) } menu.exec(this->mapToGlobal(point)); } + +/** + * @brief Initializes the pin badge overlay and loads its icon with DPI-aware rasterization. + * + * The icon is rasterized once using the label's device pixel ratio so it stays crisp on HiDPI + * displays. The resulting pixmap is cached on the QLabel and simply shown/hidden when needed. + * If the SVG cannot be read, a textual fallback badge is created instead. + */ +void PrintingSelectorCardOverlayWidget::initializePinBadge() +{ + if (!pinBadge) { + // construct the overlay label once + pinBadge = new QLabel(this); + pinBadge->setObjectName(QStringLiteral("printingSelectorPinBadge")); + } else { + // Clear any previous pixmap / style in case we reinitialize for a DPR change. + pinBadge->clear(); + pinBadge->setStyleSheet(QString()); + } + + bool pinLoaded = false; + QImageReader pinReader(QStringLiteral("theme:icons/pin")); + + if (pinReader.canRead()) { + // Rasterize a 64×64 logical icon so it has a consistent size regardless of card scaling. + const QSize targetSize(64, 64); + const qreal dpr = pinBadge->devicePixelRatioF(); + const QSize rasterSize(qMax(1, qCeil(targetSize.width() * dpr)), qMax(1, qCeil(targetSize.height() * dpr))); + pinReader.setScaledSize(rasterSize); + const QImage pinImage = pinReader.read(); + if (!pinImage.isNull()) { + // Tag the pixmap with the same DPR so Qt renders it at the correct physical size. + QPixmap pinPix = QPixmap::fromImage(pinImage); + pinPix.setDevicePixelRatio(dpr); + pinBadge->setPixmap(pinPix); + pinBadge->setFixedSize(targetSize); + pinBadge->setStyleSheet(QStringLiteral("background: transparent;")); + pinLoaded = true; + } + } + + if (!pinLoaded) { + // Fall back to a text badge when the SVG cannot be decoded (e.g., missing theme resource). + pinBadge->setText(QStringLiteral("PIN")); + pinBadge->setAlignment(Qt::AlignCenter); + pinBadge->setFixedSize(24, 12); + pinBadge->setStyleSheet(QStringLiteral("background: yellow; color: black; border: 1px solid red;")); + } + + // The overlay is mouse-transparent and hidden until we know the card is pinned. + pinBadge->setAttribute(Qt::WA_TransparentForMouseEvents); + pinBadge->setVisible(false); + pinBadge->raise(); +} diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.h b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.h index 1bafda4fe..f2351f509 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.h +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.h @@ -42,9 +42,14 @@ protected: signals: void cardPreferenceChanged(); +private slots: + void updatePinBadgeVisibility(); + private: + void initializePinBadge(); CardInfoPictureWidget *cardInfoPicture; AllZonesCardAmountWidget *allZonesCardAmountWidget; + QLabel *pinBadge = nullptr; AbstractTabDeckEditor *deckEditor; DeckListModel *deckModel; QTreeView *deckView; diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_sorting_widget.cpp b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_sorting_widget.cpp index d95019e80..af7cedbeb 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_sorting_widget.cpp +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_sorting_widget.cpp @@ -1,7 +1,8 @@ #include "printing_selector_card_sorting_widget.h" +#include "../../../client/settings/cache_settings.h" + #include -#include const QString PrintingSelectorCardSortingWidget::SORT_OPTIONS_ALPHABETICAL = tr("Alphabetical"); const QString PrintingSelectorCardSortingWidget::SORT_OPTIONS_PREFERENCE = tr("Preference"); @@ -88,7 +89,7 @@ QList PrintingSelectorCardSortingWidget::sortSets(const SetToPrint } if (sortedSets.empty()) { - sortedSets << CardSet::newInstance("", "", "", QDate()); + sortedSets << CardSet::newInstance(SettingsCache::instance().cardDatabase(), "", "", "", QDate()); } if (sortOptionsSelector->currentText() == SORT_OPTIONS_PREFERENCE) { diff --git a/cockatrice/src/interface/widgets/replay/replay_timeline_widget.cpp b/cockatrice/src/interface/widgets/replay/replay_timeline_widget.cpp index 2b9ab72e9..fb5936cae 100644 --- a/cockatrice/src/interface/widgets/replay/replay_timeline_widget.cpp +++ b/cockatrice/src/interface/widgets/replay/replay_timeline_widget.cpp @@ -1,10 +1,11 @@ #include "replay_timeline_widget.h" +#include "../../../client/settings/cache_settings.h" + #include #include #include #include -#include ReplayTimelineWidget::ReplayTimelineWidget(QWidget *parent) : QWidget(parent), maxBinValue(1), maxTime(1), timeScaleFactor(1.0), currentVisualTime(0), currentProcessedTime(0), diff --git a/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp b/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp index 10897b651..c97d32d44 100644 --- a/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp +++ b/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp @@ -1,5 +1,6 @@ #include "chat_view.h" +#include "../../../../client/settings/cache_settings.h" #include "../../client/sound_engine.h" #include "../../interface/pixel_map_generator.h" #include "../../interface/widgets/tabs/tab_account.h" @@ -13,7 +14,6 @@ #include #include #include -#include const QColor DEFAULT_MENTION_COLOR = QColor(194, 31, 47); diff --git a/cockatrice/src/interface/widgets/server/games_model.cpp b/cockatrice/src/interface/widgets/server/games_model.cpp index 8c9e2c723..1da92cdad 100644 --- a/cockatrice/src/interface/widgets/server/games_model.cpp +++ b/cockatrice/src/interface/widgets/server/games_model.cpp @@ -1,5 +1,6 @@ #include "games_model.h" +#include "../../../client/settings/cache_settings.h" #include "../interface/pixel_map_generator.h" #include "../interface/widgets/tabs/tab_account.h" #include "user/user_list_manager.h" @@ -12,7 +13,6 @@ #include #include #include -#include enum GameListColumn { diff --git a/cockatrice/src/interface/widgets/server/handle_public_servers.cpp b/cockatrice/src/interface/widgets/server/handle_public_servers.cpp index 2497ecdcc..6a8754a79 100644 --- a/cockatrice/src/interface/widgets/server/handle_public_servers.cpp +++ b/cockatrice/src/interface/widgets/server/handle_public_servers.cpp @@ -1,11 +1,12 @@ #include "handle_public_servers.h" +#include "../../../client/settings/cache_settings.h" + #include #include #include #include #include -#include #define PUBLIC_SERVERS_JSON "https://cockatrice.github.io/public-servers.json" diff --git a/cockatrice/src/interface/widgets/server/user/user_info_connection.cpp b/cockatrice/src/interface/widgets/server/user/user_info_connection.cpp index 813a9236c..069e438a9 100644 --- a/cockatrice/src/interface/widgets/server/user/user_info_connection.cpp +++ b/cockatrice/src/interface/widgets/server/user/user_info_connection.cpp @@ -1,7 +1,8 @@ #include "user_info_connection.h" +#include "../../../../client/settings/cache_settings.h" + #include -#include #include UserConnection_Information::UserConnection_Information() = default; diff --git a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp index 631803092..e8ead5a02 100644 --- a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp +++ b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp @@ -1,5 +1,15 @@ +/** + * @file abstract_tab_deck_editor.cpp + * @brief Implementation of the AbstractTabDeckEditor class. + * + * Handles deck editor tab UI, deck management, card operations, clipboard + * operations, printing, deck export, remote uploads, and interactions with + * external services (DeckStats, TappedOut, etc.). + */ + #include "abstract_tab_deck_editor.h" +#include "../../../client/settings/cache_settings.h" #include "../client/network/interfaces/deck_stats_interface.h" #include "../client/network/interfaces/tapped_out_interface.h" #include "../interface/card_picture_loader/card_picture_loader.h" @@ -37,9 +47,13 @@ #include #include #include -#include #include +/** + * @brief Constructs the AbstractTabDeckEditor. + * Initializes all dock widgets and connects signals/slots. + * @param _tabSupervisor The tab supervisor managing this tab. + */ AbstractTabDeckEditor::AbstractTabDeckEditor(TabSupervisor *_tabSupervisor) : Tab(_tabSupervisor) { setDockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks); @@ -53,10 +67,13 @@ AbstractTabDeckEditor::AbstractTabDeckEditor(TabSupervisor *_tabSupervisor) : Ta printingSelectorDockWidget->setHidden(SettingsCache::instance().getOverrideAllCardArtWithPersonalPreference()); }); + // Connect deck signals to this tab connect(deckDockWidget, &DeckEditorDeckDockWidget::deckChanged, this, &AbstractTabDeckEditor::onDeckChanged); connect(deckDockWidget, &DeckEditorDeckDockWidget::deckModified, this, &AbstractTabDeckEditor::onDeckModified); connect(deckDockWidget, &DeckEditorDeckDockWidget::cardChanged, this, &AbstractTabDeckEditor::updateCard); connect(this, &AbstractTabDeckEditor::decrementCard, deckDockWidget, &DeckEditorDeckDockWidget::actDecrementCard); + + // Connect database display signals to this tab connect(databaseDisplayDockWidget, &DeckEditorDatabaseDisplayWidget::cardChanged, this, &AbstractTabDeckEditor::updateCard); connect(databaseDisplayDockWidget, &DeckEditorDatabaseDisplayWidget::addCardToMainDeck, this, @@ -68,69 +85,97 @@ AbstractTabDeckEditor::AbstractTabDeckEditor(TabSupervisor *_tabSupervisor) : Ta connect(databaseDisplayDockWidget, &DeckEditorDatabaseDisplayWidget::decrementCardFromSideboard, this, &AbstractTabDeckEditor::actDecrementCardFromSideboard); + // Connect filter signals connect(filterDockWidget, &DeckEditorFilterDockWidget::clearAllDatabaseFilters, databaseDisplayDockWidget, &DeckEditorDatabaseDisplayWidget::clearAllDatabaseFilters); + // Connect shortcut changes connect(&SettingsCache::instance().shortcuts(), &ShortcutsSettings::shortCutChanged, this, &AbstractTabDeckEditor::refreshShortcuts); } +/** + * @brief Updates the card info dock and printing selector. + * @param card The card to display. + */ void AbstractTabDeckEditor::updateCard(const ExactCard &card) { cardInfoDockWidget->updateCard(card); printingSelectorDockWidget->printingSelector->setCard(card.getCardPtr(), DECK_ZONE_MAIN); } +/** @brief Placeholder: called when the deck changes. */ void AbstractTabDeckEditor::onDeckChanged() { } +/** + * @brief Marks the tab as modified and updates the save menu status. + */ void AbstractTabDeckEditor::onDeckModified() { setModified(!isBlankNewDeck()); deckMenu->setSaveStatus(!isBlankNewDeck()); } +/** + * @brief Helper for adding a card to a deck zone. + * @param card Card to add. + * @param zoneName Zone to add the card to. + */ void AbstractTabDeckEditor::addCardHelper(const ExactCard &card, QString zoneName) { if (!card) return; + if (card.getInfo().getIsToken()) zoneName = DECK_ZONE_TOKENS; QModelIndex newCardIndex = deckDockWidget->deckModel->addCard(card, zoneName); - // recursiveExpand(newCardIndex); deckDockWidget->deckView->clearSelection(); deckDockWidget->deckView->setCurrentIndex(newCardIndex); setModified(true); + databaseDisplayDockWidget->searchEdit->setSelection(0, databaseDisplayDockWidget->searchEdit->text().length()); } +/** + * @brief Adds a card to the main deck or sideboard depending on Ctrl key. + */ void AbstractTabDeckEditor::actAddCard(const ExactCard &card) { if (QApplication::keyboardModifiers() & Qt::ControlModifier) actAddCardToSideboard(card); else addCardHelper(card, DECK_ZONE_MAIN); + deckMenu->setSaveStatus(true); } +/** @brief Adds a card to the sideboard explicitly. */ void AbstractTabDeckEditor::actAddCardToSideboard(const ExactCard &card) { addCardHelper(card, DECK_ZONE_SIDE); deckMenu->setSaveStatus(true); } +/** @brief Decrements a card from the main deck. */ void AbstractTabDeckEditor::actDecrementCard(const ExactCard &card) { emit decrementCard(card, DECK_ZONE_MAIN); } +/** @brief Decrements a card from the sideboard. */ void AbstractTabDeckEditor::actDecrementCardFromSideboard(const ExactCard &card) { emit decrementCard(card, DECK_ZONE_SIDE); } +/** + * @brief Swaps a card in a deck zone. + * @param card Card to swap. + * @param zoneName Zone to swap in. + */ void AbstractTabDeckEditor::actSwapCard(const ExactCard &card, const QString &zoneName) { QString providerId = card.getPrinting().getUuid(); @@ -145,8 +190,8 @@ void AbstractTabDeckEditor::actSwapCard(const ExactCard &card, const QString &zo } /** - * Opens the deck in this tab. - * @param deck The deck. Takes ownership of the object + * @brief Opens a deck in this tab. + * @param deck DeckLoader object (takes ownership). */ void AbstractTabDeckEditor::openDeck(DeckLoader *deck) { @@ -158,8 +203,8 @@ void AbstractTabDeckEditor::openDeck(DeckLoader *deck) } /** - * Sets the currently active deck for this tab - * @param _deck The deck. Takes ownership of the object + * @brief Sets the currently active deck. + * @param _deck DeckLoader object. */ void AbstractTabDeckEditor::setDeck(DeckLoader *_deck) { @@ -167,16 +212,26 @@ void AbstractTabDeckEditor::setDeck(DeckLoader *_deck) CardPictureLoader::cacheCardPixmaps(CardDatabaseManager::query()->getCards(getDeckList()->getCardRefList())); setModified(false); - // If they load a deck, make the deck list appear aDeckDockVisible->setChecked(true); deckDockWidget->setVisible(aDeckDockVisible->isChecked()); } -DeckLoader *AbstractTabDeckEditor::getDeckList() const +/** @brief Returns the currently loaded deck. */ +DeckLoader *AbstractTabDeckEditor::getDeckLoader() const +{ + return deckDockWidget->getDeckLoader(); +} + +/** @brief Returns the currently loaded deck list. */ +DeckList *AbstractTabDeckEditor::getDeckList() const { return deckDockWidget->getDeckList(); } +/** + * @brief Sets the modified state of the tab. + * @param _modified True if tab is modified, false otherwise. + */ void AbstractTabDeckEditor::setModified(bool _modified) { modified = _modified; @@ -184,21 +239,20 @@ void AbstractTabDeckEditor::setModified(bool _modified) } /** - * @brief Returns true if this tab is a blank newly opened tab, as if it was just created with the `New Deck` action. + * @brief Returns true if the tab is a blank newly created deck. */ bool AbstractTabDeckEditor::isBlankNewDeck() const { - DeckLoader *deck = getDeckList(); - return !modified && deck->isBlankDeck() && deck->hasNotBeenLoaded(); + DeckLoader *deck = deckDockWidget->getDeckLoader(); + return !modified && deck->getDeckList()->isBlankDeck() && deck->hasNotBeenLoaded(); } +/** @brief Creates a new deck. Handles opening in new tab if needed. */ void AbstractTabDeckEditor::actNewDeck() { auto deckOpenLocation = confirmOpen(false); - - if (deckOpenLocation == CANCELLED) { + if (deckOpenLocation == CANCELLED) return; - } if (deckOpenLocation == NEW_TAB) { emit openDeckEditor(nullptr); @@ -208,6 +262,7 @@ void AbstractTabDeckEditor::actNewDeck() cleanDeckAndResetModified(); } +/** @brief Clears the current deck and resets modified flag. */ void AbstractTabDeckEditor::cleanDeckAndResetModified() { deckMenu->setSaveStatus(false); @@ -216,43 +271,29 @@ void AbstractTabDeckEditor::cleanDeckAndResetModified() } /** - * @brief Displays the save confirmation dialogue that is shown before loading a deck, if required. Takes into - * account the `openDeckInNewTab` settting. - * - * @param openInSameTabIfBlank Open the deck in the same tab instead of a new tab if the current tab is completely - * blank. Only relevant when the `openDeckInNewTab` setting is enabled. - * - * @returns An enum that indicates if and where to load the deck + * @brief Displays the save confirmation dialog before loading a deck. + * @param openInSameTabIfBlank Open in same tab if current tab is blank. + * @return DeckOpenLocation enum indicating where to open the deck. */ AbstractTabDeckEditor::DeckOpenLocation AbstractTabDeckEditor::confirmOpen(const bool openInSameTabIfBlank) { - // handle `openDeckInNewTab` setting if (SettingsCache::instance().getOpenDeckInNewTab()) { - if (openInSameTabIfBlank && isBlankNewDeck()) { + if (openInSameTabIfBlank && isBlankNewDeck()) return SAME_TAB; - } else { + else return NEW_TAB; - } } - // early return if deck is unmodified - if (!modified) { + if (!modified) return SAME_TAB; - } - // do the save confirmation dialogue tabSupervisor->setCurrentWidget(this); - QMessageBox *msgBox = createSaveConfirmationWindow(); QPushButton *newTabButton = msgBox->addButton(tr("Open in new tab"), QMessageBox::ApplyRole); - int ret = msgBox->exec(); - // `exec()` returns an opaque value if a non-standard button was clicked. - // Directly check if newTabButton was clicked before switching over the standard buttons. - if (msgBox->clickedButton() == newTabButton) { + if (msgBox->clickedButton() == newTabButton) return NEW_TAB; - } switch (ret) { case QMessageBox::Save: @@ -265,9 +306,8 @@ AbstractTabDeckEditor::DeckOpenLocation AbstractTabDeckEditor::confirmOpen(const } /** - * @brief Creates the base save confirmation dialogue box. - * - * @returns A QMessageBox that can be further modified + * @brief Creates the base save confirmation dialog. + * @return Pointer to a QMessageBox. */ QMessageBox *AbstractTabDeckEditor::createSaveConfirmationWindow() { @@ -279,13 +319,15 @@ QMessageBox *AbstractTabDeckEditor::createSaveConfirmationWindow() return msgBox; } +/** + * @brief Loads a deck from file using a dialog. + * Displays a save confirmation if needed. + */ void AbstractTabDeckEditor::actLoadDeck() { auto deckOpenLocation = confirmOpen(); - - if (deckOpenLocation == CANCELLED) { + if (deckOpenLocation == CANCELLED) return; - } DlgLoadDeck dialog(this); if (!dialog.exec()) @@ -296,27 +338,29 @@ void AbstractTabDeckEditor::actLoadDeck() deckDockWidget->updateBannerCardComboBox(); } +/** + * @brief Opens a recently used deck file. + * @param fileName Path to the deck file. + */ void AbstractTabDeckEditor::actOpenRecent(const QString &fileName) { auto deckOpenLocation = confirmOpen(); - - if (deckOpenLocation == CANCELLED) { + if (deckOpenLocation == CANCELLED) return; - } openDeckFromFile(fileName, deckOpenLocation); } /** - * Actually opens the deck from file - * @param fileName The path of the deck to open - * @param deckOpenLocation Which tab to open the deck + * @brief Actually opens a deck from file. + * @param fileName Path to the deck file. + * @param deckOpenLocation Where to open the deck (same or new tab). */ void AbstractTabDeckEditor::openDeckFromFile(const QString &fileName, DeckOpenLocation deckOpenLocation) { DeckLoader::FileFormat fmt = DeckLoader::getFormatFromName(fileName); - auto *l = new DeckLoader; + auto *l = new DeckLoader(this); if (l->loadFromFile(fileName, fmt, true)) { if (deckOpenLocation == NEW_TAB) { emit openDeckEditor(l); @@ -332,11 +376,16 @@ void AbstractTabDeckEditor::openDeckFromFile(const QString &fileName, DeckOpenLo deckMenu->setSaveStatus(true); } +/** + * @brief Saves the current deck. + * If remote deck, sends upload command. + * @return True if save succeeded, false otherwise. + */ bool AbstractTabDeckEditor::actSaveDeck() { - DeckLoader *const deck = getDeckList(); + DeckLoader *const deck = getDeckLoader(); if (deck->getLastRemoteDeckId() != -1) { - QString deckString = deck->writeToString_Native(); + QString deckString = deck->getDeckList()->writeToString_Native(); if (deckString.length() > MAX_FILE_LENGTH) { QMessageBox::critical(this, tr("Error"), tr("Could not save remote deck")); return false; @@ -357,12 +406,17 @@ bool AbstractTabDeckEditor::actSaveDeck() setModified(false); return true; } + QMessageBox::critical( this, tr("Error"), tr("The deck could not be saved.\nPlease check that the directory is writable and try again.")); return false; } +/** + * @brief Saves the deck to a user-selected file. + * @return True if save succeeded. + */ bool AbstractTabDeckEditor::actSaveDeckAs() { QFileDialog dialog(this, tr("Save deck")); @@ -378,19 +432,22 @@ bool AbstractTabDeckEditor::actSaveDeckAs() QString fileName = dialog.selectedFiles().at(0); DeckLoader::FileFormat fmt = DeckLoader::getFormatFromName(fileName); - if (!getDeckList()->saveToFile(fileName, fmt)) { + if (!getDeckLoader()->saveToFile(fileName, fmt)) { QMessageBox::critical( this, tr("Error"), tr("The deck could not be saved.\nPlease check that the directory is writable and try again.")); return false; } + setModified(false); - SettingsCache::instance().recents().updateRecentlyOpenedDeckPaths(fileName); - return true; } +/** + * @brief Callback for remote deck save completion. + * @param response Server response. + */ void AbstractTabDeckEditor::saveDeckRemoteFinished(const Response &response) { if (response.response_code() != Response::RespOk) @@ -399,13 +456,15 @@ void AbstractTabDeckEditor::saveDeckRemoteFinished(const Response &response) setModified(false); } +/** + * @brief Loads a deck from clipboard. + * Displays confirmation if the tab is modified. + */ void AbstractTabDeckEditor::actLoadDeckFromClipboard() { auto deckOpenLocation = confirmOpen(); - - if (deckOpenLocation == CANCELLED) { + if (deckOpenLocation == CANCELLED) return; - } DlgLoadDeckFromClipboard dlg(this); if (!dlg.exec()) @@ -421,62 +480,73 @@ void AbstractTabDeckEditor::actLoadDeckFromClipboard() deckMenu->setSaveStatus(true); } +/** + * @brief Opens the deck editor to edit clipboard contents. + * @param annotated If true, edits with annotations. + */ void AbstractTabDeckEditor::editDeckInClipboard(bool annotated) { - DlgEditDeckInClipboard dlg(*getDeckList(), annotated, this); + DlgEditDeckInClipboard dlg(*getDeckLoader(), annotated, this); if (!dlg.exec()) return; setDeck(dlg.getDeckList()); setModified(true); - deckMenu->setSaveStatus(true); } +/** @brief Slot for editing deck in clipboard with annotations. */ void AbstractTabDeckEditor::actEditDeckInClipboard() { editDeckInClipboard(true); } +/** @brief Slot for editing deck in clipboard without annotations. */ void AbstractTabDeckEditor::actEditDeckInClipboardRaw() { editDeckInClipboard(false); } +/** @brief Saves deck to clipboard with set info and annotation. */ void AbstractTabDeckEditor::actSaveDeckToClipboard() { - getDeckList()->saveToClipboard(true, true); + getDeckLoader()->saveToClipboard(true, true); } +/** @brief Saves deck to clipboard with annotation, without set info. */ void AbstractTabDeckEditor::actSaveDeckToClipboardNoSetInfo() { - getDeckList()->saveToClipboard(true, false); + getDeckLoader()->saveToClipboard(true, false); } +/** @brief Saves deck to clipboard without annotations, with set info. */ void AbstractTabDeckEditor::actSaveDeckToClipboardRaw() { - getDeckList()->saveToClipboard(false, true); + getDeckLoader()->saveToClipboard(false, true); } +/** @brief Saves deck to clipboard without annotations or set info. */ void AbstractTabDeckEditor::actSaveDeckToClipboardRawNoSetInfo() { - getDeckList()->saveToClipboard(false, false); + getDeckLoader()->saveToClipboard(false, false); } +/** @brief Prints the deck using a QPrintPreviewDialog. */ void AbstractTabDeckEditor::actPrintDeck() { auto *dlg = new QPrintPreviewDialog(this); - connect(dlg, &QPrintPreviewDialog::paintRequested, deckDockWidget->deckModel, &DeckListModel::printDeckList); + connect(dlg, &QPrintPreviewDialog::paintRequested, deckDockWidget->getDeckLoader(), &DeckLoader::printDeckList); dlg->exec(); } +/** + * @brief Loads a deck from a website. + */ void AbstractTabDeckEditor::actLoadDeckFromWebsite() { auto deckOpenLocation = confirmOpen(); - - if (deckOpenLocation == CANCELLED) { + if (deckOpenLocation == CANCELLED) return; - } DlgLoadDeckFromWebsite dlg(this); if (!dlg.exec()) @@ -492,18 +562,21 @@ void AbstractTabDeckEditor::actLoadDeckFromWebsite() deckMenu->setSaveStatus(true); } +/** + * @brief Exports the deck to a decklist website. + * @param website Website to export to. + */ void AbstractTabDeckEditor::exportToDecklistWebsite(DeckLoader::DecklistWebsite website) { - // check if deck is not null - if (DeckLoader *const deck = getDeckList()) { - // Get the decklist url string from the deck loader class. + if (DeckLoader *const deck = getDeckLoader()) { QString decklistUrlString = deck->exportDeckToDecklist(website); // Check to make sure the string isn't empty. - if (QString::compare(decklistUrlString, "", Qt::CaseInsensitive) == 0) { + if (decklistUrlString.isEmpty()) { // Show an error if the deck is empty, and return. QMessageBox::critical(this, tr("Error"), tr("There are no cards in your deck to be exported")); return; } + // Encode the string recieved from the model to make sure all characters are encoded. // first we put it into a qurl object QUrl decklistUrl = QUrl(decklistUrlString); @@ -517,48 +590,54 @@ void AbstractTabDeckEditor::exportToDecklistWebsite(DeckLoader::DecklistWebsite } } -/** - * Exports the deck to www.decklist.org (the old website) - */ +/** @brief Exports deck to www.decklist.org. */ void AbstractTabDeckEditor::actExportDeckDecklist() { exportToDecklistWebsite(DeckLoader::DecklistOrg); } -/** - * Exports the deck to www.decklist.xyz (the new website) - */ +/** @brief Exports deck to www.decklist.xyz. */ void AbstractTabDeckEditor::actExportDeckDecklistXyz() { exportToDecklistWebsite(DeckLoader::DecklistXyz); } +/** @brief Analyzes the deck using DeckStats. */ void AbstractTabDeckEditor::actAnalyzeDeckDeckstats() { - auto *interface = new DeckStatsInterface(*databaseDisplayDockWidget->databaseModel->getDatabase(), - this); // it deletes itself when done + auto *interface = new DeckStatsInterface(*databaseDisplayDockWidget->databaseModel->getDatabase(), this); interface->analyzeDeck(getDeckList()); } +/** @brief Analyzes the deck using TappedOut. */ void AbstractTabDeckEditor::actAnalyzeDeckTappedout() { - auto *interface = new TappedOutInterface(*databaseDisplayDockWidget->databaseModel->getDatabase(), - this); // it deletes itself when done + auto *interface = new TappedOutInterface(*databaseDisplayDockWidget->databaseModel->getDatabase(), this); interface->analyzeDeck(getDeckList()); } +/** @brief Applies a new filter tree to the database display. */ void AbstractTabDeckEditor::filterTreeChanged(FilterTree *filterTree) { databaseDisplayDockWidget->setFilterTree(filterTree); } +/** + * @brief Handles the close event of the tab. + * @param event Close event. + */ void AbstractTabDeckEditor::closeEvent(QCloseEvent *event) { emit deckEditorClosing(this); event->accept(); } -// Method uses to sync docks state with menu items state +/** + * @brief Event filter for dock visibility and geometry changes. + * @param o Object sending the event. + * @param e Event. + * @return False always. + */ bool AbstractTabDeckEditor::eventFilter(QObject *o, QEvent *e) { if (e->type() == QEvent::Close) { @@ -576,6 +655,7 @@ bool AbstractTabDeckEditor::eventFilter(QObject *o, QEvent *e) aPrintingSelectorDockFloating->setEnabled(false); } } + if (o == this && e->type() == QEvent::Hide) { LayoutsSettings &layouts = SettingsCache::instance().layouts(); layouts.setDeckEditorLayoutState(saveState()); @@ -585,9 +665,11 @@ bool AbstractTabDeckEditor::eventFilter(QObject *o, QEvent *e) layouts.setDeckEditorDeckSize(deckDockWidget->size()); layouts.setDeckEditorPrintingSelectorSize(printingSelectorDockWidget->size()); } + return false; } +/** @brief Shows a confirmation dialog before closing. */ bool AbstractTabDeckEditor::confirmClose() { if (modified) { @@ -601,11 +683,10 @@ bool AbstractTabDeckEditor::confirmClose() return true; } +/** @brief Handles close requests from outside (tab manager). */ bool AbstractTabDeckEditor::closeRequest() { - if (!confirmClose()) { + if (!confirmClose()) return false; - } - return close(); -} \ No newline at end of file +} diff --git a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.h b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.h index bdf35b3da..c0a5518c6 100644 --- a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.h +++ b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.h @@ -1,3 +1,10 @@ +/** + * @file abstract_tab_deck_editor.h + * @brief Defines the AbstractTabDeckEditor class, which provides a base for + * deck editor tabs in the application. + * + */ + #ifndef TAB_GENERIC_DECK_EDITOR_H #define TAB_GENERIC_DECK_EDITOR_H @@ -40,6 +47,45 @@ class QDockWidget; class QMenu; class QAction; +/** + * @class AbstractTabDeckEditor + * @ingroup DeckEditorTabs + * @brief AbstractTabDeckEditor is the base class for all deck editor tabs. + * + * **Description:** + * AbstractTabDeckEditor is the base class for all deck editor tabs. It provides core functionality such as deck model + * management, card addition/removal, and integration with dock widgets and tab supervisors. + * + * **Purpose:** + * + * - Acts as the foundation for deck editor tabs (TabDeckEditor and TabDeckEditorVisual). + * - Provides basic deck operations like adding, removing, swapping, and decrementing cards. + * - Integrates with DeckListModel and CardDatabaseModel to access deck and card data. + * - Handles saving, loading, and layout persistence at the tab level. + * + * **Dock Widgets (typically managed in derived classes):** + * + * - DeckEditorCardInfoDockWidget — Displays detailed card info. + * - DeckEditorDeckDockWidget— Displays mainboard/sideboard cards and zones. + * - DeckEditorFilterDockWidget— Provides filtering options for card searches. + * - DeckEditorPrintingSelectorDockWidget— Selector for different card printings. + * - DeckEditorDatabaseDisplayWidget— Shows card database for adding cards to deck. + * + * **Key Methods:** + * + * - actAddCard(const ExactCard &card) — Adds a card to the deck. + * - actDecrementCard(const ExactCard &card) — Removes a single instance of a card from the deck. + * - actSwapCard(const ExactCard &card, const QString &zone) — Swaps a card between zones. + * - actRemoveCard() — Removes the currently selected card from the deck. + * - actSaveDeckAs() — Performs a "Save As" action for the deck. + * - updateCard(const ExactCard &card) — Updates the currently displayed card info in the dock. + * - onDeckModified() — Called when the deck model is changed. + * + * Provides UI docks for the deck, database, card info, printing selector, + * and filters. Supports loading, saving, editing, exporting decks, and + * interactions with external services such as DeckStats, TappedOut, and + * remote deck uploads. + */ class AbstractTabDeckEditor : public Tab { Q_OBJECT @@ -47,68 +93,158 @@ class AbstractTabDeckEditor : public Tab friend class DeckEditorMenu; public: + /** + * @brief Constructs an AbstractTabDeckEditor. + * @param _tabSupervisor Pointer to the TabSupervisor managing this tab. + */ explicit AbstractTabDeckEditor(TabSupervisor *_tabSupervisor); - // UI and Navigation + /** @brief Creates the menus for this tab. Pure virtual. */ virtual void createMenus() = 0; + + /** @brief Returns the display text for the tab. */ [[nodiscard]] virtual QString getTabText() const override = 0; + + /** @brief Confirms whether the tab can be safely closed. */ bool confirmClose(); + + /** @brief Retranslates the UI text. Pure virtual. */ virtual void retranslateUi() override = 0; - // Deck Management + /** @brief Opens a deck in this tab. + * @param deck Pointer to a DeckLoader object. + */ void openDeck(DeckLoader *deck); - DeckLoader *getDeckList() const; + + /** @brief Returns the currently active deck loader. */ + DeckLoader *getDeckLoader() const; + + /** @brief Returns the currently active deck list. */ + DeckList *getDeckList() const; + + /** @brief Sets the modified state of the tab. + * @param _windowModified Whether the tab is modified. + */ void setModified(bool _windowModified); + DeckEditorDeckDockWidget *getDeckDockWidget() const + { + return deckDockWidget; + } + // UI Elements - DeckEditorMenu *deckMenu; - DeckEditorDatabaseDisplayWidget *databaseDisplayDockWidget; - DeckEditorCardInfoDockWidget *cardInfoDockWidget; - DeckEditorDeckDockWidget *deckDockWidget; - DeckEditorFilterDockWidget *filterDockWidget; - DeckEditorPrintingSelectorDockWidget *printingSelectorDockWidget; + DeckEditorMenu *deckMenu; ///< Menu for deck operations + DeckEditorDatabaseDisplayWidget *databaseDisplayDockWidget; ///< Database dock + DeckEditorCardInfoDockWidget *cardInfoDockWidget; ///< Card info dock + DeckEditorDeckDockWidget *deckDockWidget; ///< Deck dock + DeckEditorFilterDockWidget *filterDockWidget; ///< Filter dock + DeckEditorPrintingSelectorDockWidget *printingSelectorDockWidget; ///< Printing selector dock public slots: + /** @brief Called when the deck changes. */ virtual void onDeckChanged(); + + /** @brief Called when the deck is modified. */ virtual void onDeckModified(); + + /** @brief Updates the card info panel. + * @param card The card to display. + */ void updateCard(const ExactCard &card); + + /** @brief Adds a card to the main deck or sideboard based on Ctrl key. */ void actAddCard(const ExactCard &card); + + /** @brief Adds a card to the sideboard explicitly. */ void actAddCardToSideboard(const ExactCard &card); + + /** @brief Decrements a card from the main deck. */ void actDecrementCard(const ExactCard &card); + + /** @brief Decrements a card from the sideboard. */ void actDecrementCardFromSideboard(const ExactCard &card); + + /** @brief Opens a recently opened deck file. */ void actOpenRecent(const QString &fileName); + + /** @brief Called when the filter tree changes. */ void filterTreeChanged(FilterTree *filterTree); + + /** @brief Requests closing the tab. */ bool closeRequest() override; + + /** @brief Shows the printing selector dock. Pure virtual. */ virtual void showPrintingSelector() = 0; + + /** @brief Slot for when a dock's top-level state changes. Pure virtual. */ virtual void dockTopLevelChanged(bool topLevel) = 0; signals: - void openDeckEditor(const DeckLoader *deckLoader); + /** @brief Emitted when a deck should be opened in a new editor tab. */ + void openDeckEditor(DeckLoader *deckLoader); + + /** @brief Emitted before the tab is closed. */ void deckEditorClosing(AbstractTabDeckEditor *tab); + + /** @brief Emitted when a card should be decremented. */ void decrementCard(const ExactCard &card, QString zoneName); protected slots: - // Deck Operations + /** @brief Starts a new deck in this tab. */ virtual void actNewDeck(); + + /** @brief Cleans the current deck and resets the modified state. */ void cleanDeckAndResetModified(); + + /** @brief Loads a deck from file. */ virtual void actLoadDeck(); + + /** @brief Saves the current deck. */ bool actSaveDeck(); + + /** @brief Saves the current deck under a new name. */ virtual bool actSaveDeckAs(); + + /** @brief Loads a deck from the clipboard. */ virtual void actLoadDeckFromClipboard(); + + /** @brief Opens a deck editor for clipboard contents. */ void actEditDeckInClipboard(); + + /** @brief Opens a raw clipboard deck editor. */ void actEditDeckInClipboardRaw(); + + /** @brief Saves deck to clipboard with full info. */ void actSaveDeckToClipboard(); + + /** @brief Saves deck to clipboard without set info. */ void actSaveDeckToClipboardNoSetInfo(); + + /** @brief Saves deck to clipboard in raw format. */ void actSaveDeckToClipboardRaw(); + + /** @brief Saves deck to clipboard in raw format without set info. */ void actSaveDeckToClipboardRawNoSetInfo(); + + /** @brief Prints the deck using a preview dialog. */ void actPrintDeck(); + + /** @brief Loads a deck from an online website. */ void actLoadDeckFromWebsite(); + + /** @brief Exports the deck to decklist.org. */ void actExportDeckDecklist(); + + /** @brief Exports the deck to decklist.xyz. */ void actExportDeckDecklistXyz(); + + /** @brief Analyzes the deck using deckstats.net. */ void actAnalyzeDeckDeckstats(); + + /** @brief Analyzes the deck using tappedout.net. */ void actAnalyzeDeckTappedout(); - // Remote Save + /** @brief Callback when a remote deck save finishes. */ void saveDeckRemoteFinished(const Response &r); // UI Layout Management @@ -117,34 +253,62 @@ protected slots: virtual void freeDocksSize() = 0; virtual void refreshShortcuts() = 0; + /** @brief Handles dock close events. */ void closeEvent(QCloseEvent *event) override; + + /** @brief Event filter for dock state changes. */ bool eventFilter(QObject *o, QEvent *e) override; + + /** @brief Slot triggered when a dock visibility changes. Pure virtual. */ virtual void dockVisibleTriggered() = 0; + + /** @brief Slot triggered when a dock floating state changes. Pure virtual. */ virtual void dockFloatingTriggered() = 0; private: + /** @brief Sets the deck for this tab. + * @param _deck The deck object. + */ virtual void setDeck(DeckLoader *_deck); + + /** @brief Helper for editing decks from the clipboard. */ void editDeckInClipboard(bool annotated); + + /** @brief Helper for exporting decks to websites. + * @param website Target website. + */ void exportToDecklistWebsite(DeckLoader::DecklistWebsite website); protected: - /** - * @brief Enum for selecting deck open location - */ + /** @brief Enum describing deck open locations */ enum DeckOpenLocation { - CANCELLED, - SAME_TAB, - NEW_TAB + CANCELLED, ///< Operation cancelled + SAME_TAB, ///< Open deck in the same tab + NEW_TAB ///< Open deck in a new tab }; + /** @brief Confirms deck open action based on settings and modified state. + * @param openInSameTabIfBlank Whether to reuse same tab if blank. + * @return Selected DeckOpenLocation. + */ DeckOpenLocation confirmOpen(bool openInSameTabIfBlank = true); + + /** @brief Creates a save confirmation message box. + * @return Pointer to a QMessageBox. + */ QMessageBox *createSaveConfirmationWindow(); + + /** @brief Returns true if the tab is a blank newly created deck. */ bool isBlankNewDeck() const; - // Helper functions for card actions + /** @brief Helper function to add a card to a specific deck zone. */ void addCardHelper(const ExactCard &card, QString zoneName); + + /** @brief Swaps a card in the deck view. */ void actSwapCard(const ExactCard &card, const QString &zoneName); + + /** @brief Opens a deck from a file. */ virtual void openDeckFromFile(const QString &fileName, DeckOpenLocation deckOpenLocation); // UI Menu Elements @@ -154,7 +318,7 @@ protected: QAction *aCardInfoDockVisible, *aCardInfoDockFloating, *aDeckDockVisible, *aDeckDockFloating; QAction *aFilterDockVisible, *aFilterDockFloating, *aPrintingSelectorDockVisible, *aPrintingSelectorDockFloating; - bool modified = false; + bool modified = false; ///< Whether the deck/tab has unsaved changes }; #endif // TAB_GENERIC_DECK_EDITOR_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_deck_api_response.cpp b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_deck_api_response.cpp index d525baafb..73c26050d 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_deck_api_response.cpp +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_deck_api_response.cpp @@ -1,11 +1,12 @@ #include "edhrec_deck_api_response.h" +#include "../../../../../../deck_loader/deck_loader.h" + #include #include #include #include #include -#include void EdhrecDeckApiResponse::fromJson(const QJsonArray &json) { @@ -14,10 +15,10 @@ void EdhrecDeckApiResponse::fromJson(const QJsonArray &json) deckList += cardlistValue.toString() + "\n"; } - deckLoader = new DeckLoader(); + deckLoader = new DeckLoader(nullptr); QTextStream stream(&deckList); - deckLoader->loadFromStream_Plain(stream, true); + deckLoader->getDeckList()->loadFromStream_Plain(stream, true); } void EdhrecDeckApiResponse::debugPrint() const diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_deck_api_response.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_deck_api_response.h index 2666789e9..b362819df 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_deck_api_response.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_deck_api_response.h @@ -7,12 +7,13 @@ #ifndef EDHREC_DECK_API_RESPONSE_H #define EDHREC_DECK_API_RESPONSE_H +#include "../../../../../../deck_loader/deck_loader.h" + #include #include #include #include #include -#include class EdhrecDeckApiResponse { diff --git a/cockatrice/src/interface/widgets/tabs/tab_deck_editor.cpp b/cockatrice/src/interface/widgets/tabs/tab_deck_editor.cpp index 034800158..88f08eae1 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_deck_editor.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_deck_editor.cpp @@ -1,5 +1,6 @@ #include "tab_deck_editor.h" +#include "../../../client/settings/cache_settings.h" #include "../client/network/interfaces/tapped_out_interface.h" #include "../filters/filter_builder.h" #include "../filters/filter_tree_model.h" @@ -36,9 +37,13 @@ #include #include #include -#include #include +/** + * @brief Constructs a new TabDeckEditor object. + * Sets up menus, translations, shortcuts, and loads the layout. + * @param _tabSupervisor Pointer to parent TabSupervisor. + */ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor) : AbstractTabDeckEditor(_tabSupervisor) { setObjectName("TabDeckEditor"); @@ -53,6 +58,11 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor) : AbstractTabDeckEdi TabDeckEditor::loadLayout(); } +/** + * @brief Creates menus for deck editing and view customization. + * + * Adds DeckEditorMenu, view menus, and actions for dock visibility and floating. + */ void TabDeckEditor::createMenus() { deckMenu = new DeckEditorMenu(this); @@ -65,6 +75,7 @@ void TabDeckEditor::createMenus() filterDockMenu = viewMenu->addMenu(QString()); printingSelectorDockMenu = viewMenu->addMenu(QString()); + // Card Info dock aCardInfoDockVisible = cardInfoDockMenu->addAction(QString()); aCardInfoDockVisible->setCheckable(true); connect(aCardInfoDockVisible, &QAction::triggered, this, &TabDeckEditor::dockVisibleTriggered); @@ -72,6 +83,7 @@ void TabDeckEditor::createMenus() aCardInfoDockFloating->setCheckable(true); connect(aCardInfoDockFloating, &QAction::triggered, this, &TabDeckEditor::dockFloatingTriggered); + // Deck dock aDeckDockVisible = deckDockMenu->addAction(QString()); aDeckDockVisible->setCheckable(true); connect(aDeckDockVisible, &QAction::triggered, this, &TabDeckEditor::dockVisibleTriggered); @@ -79,6 +91,7 @@ void TabDeckEditor::createMenus() aDeckDockFloating->setCheckable(true); connect(aDeckDockFloating, &QAction::triggered, this, &TabDeckEditor::dockFloatingTriggered); + // Filter dock aFilterDockVisible = filterDockMenu->addAction(QString()); aFilterDockVisible->setCheckable(true); connect(aFilterDockVisible, &QAction::triggered, this, &TabDeckEditor::dockVisibleTriggered); @@ -86,6 +99,7 @@ void TabDeckEditor::createMenus() aFilterDockFloating->setCheckable(true); connect(aFilterDockFloating, &QAction::triggered, this, &TabDeckEditor::dockFloatingTriggered); + // Printing selector dock aPrintingSelectorDockVisible = printingSelectorDockMenu->addAction(QString()); aPrintingSelectorDockVisible->setCheckable(true); connect(aPrintingSelectorDockVisible, &QAction::triggered, this, &TabDeckEditor::dockVisibleTriggered); @@ -107,10 +121,14 @@ void TabDeckEditor::createMenus() viewMenu->addAction(aResetLayout); deckMenu->setSaveStatus(false); - addTabMenu(viewMenu); } +/** + * @brief Returns the text to display in the tab. + * Prepends "*" if the deck is modified. + * @return Tab text including modified mark. + */ QString TabDeckEditor::getTabText() const { QString result = tr("Deck: %1").arg(deckDockWidget->getSimpleDeckName()); @@ -119,10 +137,10 @@ QString TabDeckEditor::getTabText() const return result; } +/** @brief Updates text of menus and actions for localization. */ void TabDeckEditor::retranslateUi() { deckMenu->retranslateUi(); - cardInfoDockWidget->retranslateUi(); deckDockWidget->retranslateUi(); filterDockWidget->retranslateUi(); @@ -136,25 +154,25 @@ void TabDeckEditor::retranslateUi() aCardInfoDockVisible->setText(tr("Visible")); aCardInfoDockFloating->setText(tr("Floating")); - aDeckDockVisible->setText(tr("Visible")); aDeckDockFloating->setText(tr("Floating")); - aFilterDockVisible->setText(tr("Visible")); aFilterDockFloating->setText(tr("Floating")); - aPrintingSelectorDockVisible->setText(tr("Visible")); aPrintingSelectorDockFloating->setText(tr("Floating")); - aResetLayout->setText(tr("Reset layout")); } +/** @brief Refreshes shortcuts for deck editor menu actions. */ void TabDeckEditor::refreshShortcuts() { ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); aResetLayout->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aResetLayout")); } +/** + * @brief Displays the printing selector dock with the current card. + */ void TabDeckEditor::showPrintingSelector() { printingSelectorDockWidget->printingSelector->setCard(cardInfoDockWidget->cardInfo->getCard().getCardPtr(), @@ -164,16 +182,18 @@ void TabDeckEditor::showPrintingSelector() printingSelectorDockWidget->setVisible(true); } +/** + * @brief Loads deck editor layout from settings or resets to default. + */ void TabDeckEditor::loadLayout() { LayoutsSettings &layouts = SettingsCache::instance().layouts(); - setCentralWidget(databaseDisplayDockWidget); auto &layoutState = layouts.getDeckEditorLayoutState(); - if (layoutState.isNull()) { + if (layoutState.isNull()) restartLayout(); - } else { + else { restoreState(layoutState); restoreGeometry(layouts.getDeckEditorGeometry()); } @@ -215,9 +235,13 @@ void TabDeckEditor::loadLayout() QTimer::singleShot(100, this, &TabDeckEditor::freeDocksSize); } +/** + * @brief Resets all dock widgets to default layout. + */ void TabDeckEditor::restartLayout() { + // Update menu checkboxes aCardInfoDockVisible->setChecked(true); aDeckDockVisible->setChecked(true); aFilterDockVisible->setChecked(true); @@ -234,6 +258,7 @@ void TabDeckEditor::restartLayout() addDockWidget(Qt::RightDockWidgetArea, filterDockWidget); addDockWidget(Qt::RightDockWidgetArea, printingSelectorDockWidget); + // Show/hide and reset floating deckDockWidget->setFloating(false); cardInfoDockWidget->setFloating(false); filterDockWidget->setFloating(false); @@ -252,98 +277,78 @@ void TabDeckEditor::restartLayout() QTimer::singleShot(100, this, &TabDeckEditor::freeDocksSize); } +/** @brief Frees dock sizes to allow flexible resizing. */ void TabDeckEditor::freeDocksSize() { - deckDockWidget->setMinimumSize(100, 100); - deckDockWidget->setMaximumSize(5000, 5000); + const QSize minSize(100, 100); + const QSize maxSize(5000, 5000); - cardInfoDockWidget->setMinimumSize(100, 100); - cardInfoDockWidget->setMaximumSize(5000, 5000); + deckDockWidget->setMinimumSize(minSize); + deckDockWidget->setMaximumSize(maxSize); - filterDockWidget->setMinimumSize(100, 100); - filterDockWidget->setMaximumSize(5000, 5000); + cardInfoDockWidget->setMinimumSize(minSize); + cardInfoDockWidget->setMaximumSize(maxSize); - printingSelectorDockWidget->setMinimumSize(100, 100); - printingSelectorDockWidget->setMaximumSize(5000, 5000); + filterDockWidget->setMinimumSize(minSize); + filterDockWidget->setMaximumSize(maxSize); + + printingSelectorDockWidget->setMinimumSize(minSize); + printingSelectorDockWidget->setMaximumSize(maxSize); } +/** @brief Handles dock visibility toggling from menu actions. */ void TabDeckEditor::dockVisibleTriggered() { QObject *o = sender(); if (o == aCardInfoDockVisible) { cardInfoDockWidget->setHidden(!aCardInfoDockVisible->isChecked()); aCardInfoDockFloating->setEnabled(aCardInfoDockVisible->isChecked()); - return; - } - - if (o == aDeckDockVisible) { + } else if (o == aDeckDockVisible) { deckDockWidget->setHidden(!aDeckDockVisible->isChecked()); aDeckDockFloating->setEnabled(aDeckDockVisible->isChecked()); - return; - } - - if (o == aFilterDockVisible) { + } else if (o == aFilterDockVisible) { filterDockWidget->setHidden(!aFilterDockVisible->isChecked()); aFilterDockFloating->setEnabled(aFilterDockVisible->isChecked()); - return; - } - - if (o == aPrintingSelectorDockVisible) { + } else if (o == aPrintingSelectorDockVisible) { printingSelectorDockWidget->setHidden(!aPrintingSelectorDockVisible->isChecked()); aPrintingSelectorDockFloating->setEnabled(aPrintingSelectorDockVisible->isChecked()); - return; } } +/** @brief Handles dock floating toggling from menu actions. */ void TabDeckEditor::dockFloatingTriggered() { QObject *o = sender(); - if (o == aCardInfoDockFloating) { + if (o == aCardInfoDockFloating) cardInfoDockWidget->setFloating(aCardInfoDockFloating->isChecked()); - return; - } - - if (o == aDeckDockFloating) { + else if (o == aDeckDockFloating) deckDockWidget->setFloating(aDeckDockFloating->isChecked()); - return; - } - - if (o == aFilterDockFloating) { + else if (o == aFilterDockFloating) filterDockWidget->setFloating(aFilterDockFloating->isChecked()); - return; - } - - if (o == aPrintingSelectorDockFloating) { + else if (o == aPrintingSelectorDockFloating) printingSelectorDockWidget->setFloating(aPrintingSelectorDockFloating->isChecked()); - return; - } } +/** @brief Syncs menu state with dock floating changes. */ void TabDeckEditor::dockTopLevelChanged(bool topLevel) { QObject *o = sender(); - if (o == cardInfoDockWidget) { + if (o == cardInfoDockWidget) aCardInfoDockFloating->setChecked(topLevel); - return; - } - - if (o == deckDockWidget) { + else if (o == deckDockWidget) aDeckDockFloating->setChecked(topLevel); - return; - } - - if (o == filterDockWidget) { + else if (o == filterDockWidget) aFilterDockFloating->setChecked(topLevel); - return; - } - - if (o == printingSelectorDockWidget) { + else if (o == printingSelectorDockWidget) aPrintingSelectorDockFloating->setChecked(topLevel); - return; - } } -// Method uses to sync docks state with menu items state +/** + * @brief Handles close/hide events to update menu state and save layout. + * @param o Object sending the event. + * @param e Event. + * @return Always returns false. + */ bool TabDeckEditor::eventFilter(QObject *o, QEvent *e) { if (e->type() == QEvent::Close) { @@ -361,6 +366,7 @@ bool TabDeckEditor::eventFilter(QObject *o, QEvent *e) aPrintingSelectorDockFloating->setEnabled(false); } } + if (o == this && e->type() == QEvent::Hide) { LayoutsSettings &layouts = SettingsCache::instance().layouts(); layouts.setDeckEditorLayoutState(saveState()); @@ -371,4 +377,4 @@ bool TabDeckEditor::eventFilter(QObject *o, QEvent *e) layouts.setDeckEditorPrintingSelectorSize(printingSelectorDockWidget->size()); } return false; -} \ No newline at end of file +} diff --git a/cockatrice/src/interface/widgets/tabs/tab_deck_editor.h b/cockatrice/src/interface/widgets/tabs/tab_deck_editor.h index b80ce8f75..8f6e1f90d 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_deck_editor.h +++ b/cockatrice/src/interface/widgets/tabs/tab_deck_editor.h @@ -14,28 +14,85 @@ class DeckListModel; class QLabel; class DeckLoader; +/** + * @class TabDeckEditor + * @ingroup DeckEditorTabs + * @brief TabDeckEditor provides a fully-featured deck editor tab. It extends AbstractTabDeckEditor. + * + * **Description:** + * TabDeckEditor is a fully-featured deck editor tab. It extends AbstractTabDeckEditor. It manages layout, dock + * widgets, menus, and deck-specific actions for traditional (non-visual) editing. + * + * **Purpose:** + * + * - Provides a complete deck editing interface for mainboard, sideboard, and card database interactions. + * - Handles dock widgets, keyboard shortcuts, layout persistence, and UI updates. + * - Facilitates card addition, removal, and deck saving/loading through menu and UI interactions. + * + * **Dock Widgets:** + * + * - DeckEditorCardInfoDockWidget — Displays detailed card information. + * - DeckEditorDeckDockWidget — Shows deck contents and zones. + * - DeckEditorDatabaseDisplayWidget — Displays cards from the database in a table view for adding to the deck. + * - DeckEditorFilterDockWidget — Provides filter/search capabilities for the database display. + * - DeckEditorPrintingSelectorDockWidget — Allows selection of specific card printings. + * + * **Key Methods:** + * + * - loadLayout() — Loads saved layout or applies default layout positions and dock states. + * - restartLayout() — Resets dock visibility, positions, and floating states to defaults. + * - freeDocksSize() — Frees constraints on dock sizes to allow flexible resizing. + * - refreshShortcuts() — Updates tab-specific shortcuts from settings. + * - eventFilter(QObject *o, QEvent *e) — Handles dock close/hide events and saves layout state. + * - dockVisibleTriggered() — Responds to menu actions toggling dock visibility. + * - dockFloatingTriggered() — Responds to menu actions toggling dock floating state. + * - dockTopLevelChanged(bool topLevel) — Updates menu states when a dock changes top-level/floating status. + * - retranslateUi() — Updates all text/UI elements for localization. + * - getTabText() const — Returns the tab title with a modified marker if applicable. + * - createMenus() — Initializes menus for deck and view actions. + * - showPrintingSelector() — Displays the printing selector dock for the current card. + */ class TabDeckEditor : public AbstractTabDeckEditor { Q_OBJECT protected slots: + /** @brief Loads the saved layout or default layout. */ void loadLayout() override; + + /** @brief Resets the layout to default positions and dock states. */ void restartLayout() override; + + /** @brief Frees the dock sizes for resizing flexibility. */ void freeDocksSize() override; + + /** @brief Refreshes shortcuts for this tab from settings. */ void refreshShortcuts() override; + /** @brief Handles dock visibility, floating, and top-level changes. */ bool eventFilter(QObject *o, QEvent *e) override; void dockVisibleTriggered() override; void dockFloatingTriggered() override; void dockTopLevelChanged(bool topLevel) override; public: + /** + * @brief Constructs a TabDeckEditor instance. + * @param _tabSupervisor Parent tab supervisor for managing tabs. + */ explicit TabDeckEditor(TabSupervisor *_tabSupervisor); + + /** @brief Retranslates UI elements for localization. */ void retranslateUi() override; + + /** @brief Returns the tab text, including modified mark if applicable. */ QString getTabText() const override; + + /** @brief Creates menus for deck editing and view options. */ void createMenus() override; public slots: + /** @brief Shows the printing selector dock and updates it with current card. */ void showPrintingSelector() override; }; diff --git a/cockatrice/src/interface/widgets/tabs/tab_deck_storage.cpp b/cockatrice/src/interface/widgets/tabs/tab_deck_storage.cpp index 7ca0bad1f..bf74b73fb 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_deck_storage.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_deck_storage.cpp @@ -1,5 +1,7 @@ #include "tab_deck_storage.h" +#include "../../../client/settings/cache_settings.h" +#include "../../deck_loader/deck_loader.h" #include "../interface/widgets/server/remote/remote_decklist_tree_widget.h" #include "../interface/widgets/utility/get_text_with_max.h" @@ -18,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -28,7 +29,6 @@ #include #include #include -#include TabDeckStorage::TabDeckStorage(TabSupervisor *_tabSupervisor, AbstractClient *_client, @@ -242,7 +242,7 @@ void TabDeckStorage::actOpenLocalDeck() continue; QString filePath = localDirModel->filePath(curLeft); - DeckLoader deckLoader; + DeckLoader deckLoader(this); if (!deckLoader.loadFromFile(filePath, DeckLoader::CockatriceFormat, true)) continue; @@ -308,13 +308,13 @@ void TabDeckStorage::uploadDeck(const QString &filePath, const QString &targetPa QFile deckFile(filePath); QFileInfo deckFileInfo(deckFile); - DeckLoader deck; + DeckLoader deck(this); if (!deck.loadFromFile(filePath, DeckLoader::CockatriceFormat)) { QMessageBox::critical(this, tr("Error"), tr("Invalid deck file")); return; } - if (deck.getName().isEmpty()) { + if (deck.getDeckList()->getName().isEmpty()) { bool ok; QString deckName = getTextWithMax(this, tr("Enter deck name"), tr("This decklist does not have a name.\nPlease enter a name:"), @@ -323,12 +323,12 @@ void TabDeckStorage::uploadDeck(const QString &filePath, const QString &targetPa return; if (deckName.isEmpty()) deckName = tr("Unnamed deck"); - deck.setName(deckName); + deck.getDeckList()->setName(deckName); } else { - deck.setName(deck.getName().left(MAX_NAME_LENGTH)); + deck.getDeckList()->setName(deck.getDeckList()->getName().left(MAX_NAME_LENGTH)); } - QString deckString = deck.writeToString_Native(); + QString deckString = deck.getDeckList()->writeToString_Native(); if (deckString.length() > MAX_FILE_LENGTH) { QMessageBox::critical(this, tr("Error"), tr("Invalid deck file")); return; @@ -433,7 +433,7 @@ void TabDeckStorage::openRemoteDeckFinished(const Response &r, const CommandCont const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext); const Command_DeckDownload &cmd = commandContainer.session_command(0).GetExtension(Command_DeckDownload::ext); - DeckLoader loader; + DeckLoader loader(this); if (!loader.loadFromRemote(QString::fromStdString(resp.deck()), cmd.deck_id())) return; @@ -493,7 +493,7 @@ void TabDeckStorage::downloadFinished(const Response &r, const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext); QString filePath = extraData.toString(); - DeckLoader deck(QString::fromStdString(resp.deck())); + DeckLoader deck(this, new DeckList(QString::fromStdString(resp.deck()))); deck.saveToFile(filePath, DeckLoader::CockatriceFormat); } diff --git a/cockatrice/src/interface/widgets/tabs/tab_deck_storage.h b/cockatrice/src/interface/widgets/tabs/tab_deck_storage.h index 9509d2329..0226785e3 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_deck_storage.h +++ b/cockatrice/src/interface/widgets/tabs/tab_deck_storage.h @@ -87,7 +87,7 @@ public: return tr("Deck Storage"); } signals: - void openDeckEditor(const DeckLoader *deckLoader); + void openDeckEditor(DeckLoader *deckLoader); }; #endif diff --git a/cockatrice/src/interface/widgets/tabs/tab_game.cpp b/cockatrice/src/interface/widgets/tabs/tab_game.cpp index f55450de9..02d176cef 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_game.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_game.cpp @@ -1,5 +1,6 @@ #include "tab_game.h" +#include "../../../client/settings/cache_settings.h" #include "../game/board/arrow_item.h" #include "../game/board/card_item.h" #include "../game/deckview/deck_view_container.h" @@ -44,7 +45,6 @@ #include #include #include -#include #include TabGame::TabGame(TabSupervisor *_tabSupervisor, GameReplay *_replay) @@ -754,8 +754,9 @@ void TabGame::loadDeckForLocalPlayer(Player *localPlayer, int playerId, ServerIn { TabbedDeckViewContainer *deckViewContainer = deckViewContainers.value(playerId); if (playerInfo.has_deck_list()) { - DeckLoader newDeck(QString::fromStdString(playerInfo.deck_list())); - CardPictureLoader::cacheCardPixmaps(CardDatabaseManager::query()->getCards(newDeck.getCardRefList())); + DeckLoader newDeck(this, new DeckList(QString::fromStdString(playerInfo.deck_list()))); + CardPictureLoader::cacheCardPixmaps( + CardDatabaseManager::query()->getCards(newDeck.getDeckList()->getCardRefList())); deckViewContainer->playerDeckView->setDeck(newDeck); localPlayer->setDeck(newDeck); } diff --git a/cockatrice/src/interface/widgets/tabs/tab_game.h b/cockatrice/src/interface/widgets/tabs/tab_game.h index e6ba912f4..7c42ce5d2 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_game.h +++ b/cockatrice/src/interface/widgets/tabs/tab_game.h @@ -121,7 +121,7 @@ signals: void containerProcessingStarted(const GameEventContext &context); void containerProcessingDone(); void openMessageDialog(const QString &userName, bool focus); - void openDeckEditor(const DeckLoader *deck); + void openDeckEditor(DeckLoader *deck); void notIdle(); void phaseChanged(int phase); diff --git a/cockatrice/src/interface/widgets/tabs/tab_message.cpp b/cockatrice/src/interface/widgets/tabs/tab_message.cpp index 3e6a86384..f1a942f16 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_message.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_message.cpp @@ -1,5 +1,6 @@ #include "tab_message.h" +#include "../../../client/settings/cache_settings.h" #include "../client/sound_engine.h" #include "../interface/widgets/server/chat_view/chat_view.h" #include "../interface/widgets/server/user/user_list_manager.h" @@ -16,7 +17,6 @@ #include #include #include -#include #include TabMessage::TabMessage(TabSupervisor *_tabSupervisor, diff --git a/cockatrice/src/interface/widgets/tabs/tab_replays.cpp b/cockatrice/src/interface/widgets/tabs/tab_replays.cpp index e90926768..8d7081407 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_replays.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_replays.cpp @@ -1,5 +1,6 @@ #include "tab_replays.h" +#include "../../../client/settings/cache_settings.h" #include "../interface/widgets/server/remote/remote_replay_list_tree_widget.h" #include "tab_game.h" @@ -29,7 +30,6 @@ #include #include #include -#include TabReplays::TabReplays(TabSupervisor *_tabSupervisor, AbstractClient *_client, const ServerInfo_User *currentUserInfo) : Tab(_tabSupervisor), client(_client) diff --git a/cockatrice/src/interface/widgets/tabs/tab_room.cpp b/cockatrice/src/interface/widgets/tabs/tab_room.cpp index 808c888cd..e1fcca216 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_room.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_room.cpp @@ -1,5 +1,6 @@ #include "tab_room.h" +#include "../../../client/settings/cache_settings.h" #include "../interface/widgets/dialogs/dlg_settings.h" #include "../interface/widgets/server/chat_view/chat_view.h" #include "../interface/widgets/server/game_selector.h" @@ -30,7 +31,6 @@ #include #include #include -#include #include TabRoom::TabRoom(TabSupervisor *_tabSupervisor, diff --git a/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp b/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp index 8eee1d5e0..6d6f2d4ec 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp @@ -1,5 +1,6 @@ #include "tab_supervisor.h" +#include "../../../client/settings/cache_settings.h" #include "../interface/pixel_map_generator.h" #include "../interface/widgets/server/user/user_list_manager.h" #include "../interface/widgets/server/user/user_list_widget.h" @@ -35,7 +36,6 @@ #include #include #include -#include QRect MacOSTabFixStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const { @@ -491,10 +491,6 @@ void TabSupervisor::stop() tabsToDelete << i.value(); } - for (auto i = messageTabs.cbegin(), end = messageTabs.cend(); i != end; ++i) { - tabsToDelete << i.value(); - } - for (const auto tab : tabsToDelete) { tab->close(); } @@ -847,7 +843,7 @@ void TabSupervisor::talkLeft(TabMessage *tab) * Creates either a classic or visual deck editor tab depending on settings * @param deckToOpen The deck to open in the tab. Creates a copy of the DeckLoader instance. */ -void TabSupervisor::openDeckInNewTab(const DeckLoader *deckToOpen) +void TabSupervisor::openDeckInNewTab(DeckLoader *deckToOpen) { int type = SettingsCache::instance().getDefaultDeckEditorType(); switch (type) { @@ -869,11 +865,11 @@ void TabSupervisor::openDeckInNewTab(const DeckLoader *deckToOpen) * Creates a new deck editor tab * @param deckToOpen The deck to open in the tab. Creates a copy of the DeckLoader instance. */ -TabDeckEditor *TabSupervisor::addDeckEditorTab(const DeckLoader *deckToOpen) +TabDeckEditor *TabSupervisor::addDeckEditorTab(DeckLoader *deckToOpen) { auto *tab = new TabDeckEditor(this); if (deckToOpen) - tab->openDeck(new DeckLoader(*deckToOpen)); + tab->openDeck(new DeckLoader(this, deckToOpen->getDeckList())); connect(tab, &AbstractTabDeckEditor::deckEditorClosing, this, &TabSupervisor::deckEditorClosed); connect(tab, &AbstractTabDeckEditor::openDeckEditor, this, &TabSupervisor::addDeckEditorTab); myAddTab(tab); @@ -882,11 +878,11 @@ TabDeckEditor *TabSupervisor::addDeckEditorTab(const DeckLoader *deckToOpen) return tab; } -TabDeckEditorVisual *TabSupervisor::addVisualDeckEditorTab(const DeckLoader *deckToOpen) +TabDeckEditorVisual *TabSupervisor::addVisualDeckEditorTab(DeckLoader *deckToOpen) { auto *tab = new TabDeckEditorVisual(this); if (deckToOpen) - tab->openDeck(new DeckLoader(*deckToOpen)); + tab->openDeck(new DeckLoader(this, deckToOpen->getDeckList())); connect(tab, &AbstractTabDeckEditor::deckEditorClosing, this, &TabSupervisor::deckEditorClosed); connect(tab, &AbstractTabDeckEditor::openDeckEditor, this, &TabSupervisor::addVisualDeckEditorTab); myAddTab(tab); diff --git a/cockatrice/src/interface/widgets/tabs/tab_supervisor.h b/cockatrice/src/interface/widgets/tabs/tab_supervisor.h index fbc7062cc..e20ba5fb4 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_supervisor.h +++ b/cockatrice/src/interface/widgets/tabs/tab_supervisor.h @@ -8,6 +8,7 @@ #ifndef TAB_SUPERVISOR_H #define TAB_SUPERVISOR_H +#include "../../deck_loader/deck_loader.h" #include "../interface/widgets/server/user/user_list_proxy.h" #include "abstract_tab_deck_editor.h" #include "api/edhrec/tab_edhrec.h" @@ -23,7 +24,6 @@ #include #include #include -#include inline Q_LOGGING_CATEGORY(TabSupervisorLog, "tab_supervisor"); @@ -169,9 +169,9 @@ signals: void showWindowIfHidden(); public slots: - void openDeckInNewTab(const DeckLoader *deckToOpen); - TabDeckEditor *addDeckEditorTab(const DeckLoader *deckToOpen); - TabDeckEditorVisual *addVisualDeckEditorTab(const DeckLoader *deckToOpen); + void openDeckInNewTab(DeckLoader *deckToOpen); + TabDeckEditor *addDeckEditorTab(DeckLoader *deckToOpen); + TabDeckEditorVisual *addVisualDeckEditorTab(DeckLoader *deckToOpen); TabVisualDatabaseDisplay *addVisualDatabaseDisplayTab(); TabEdhRecMain *addEdhrecMainTab(); TabEdhRec *addEdhrecTab(const CardInfoPtr &cardToQuery, bool isCommander = false); diff --git a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp index 725a4e106..109815816 100644 --- a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp +++ b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp @@ -1,5 +1,6 @@ #include "tab_deck_editor_visual.h" +#include "../../../../client/settings/cache_settings.h" #include "../../client/network/interfaces/deck_stats_interface.h" #include "../../filters/filter_builder.h" #include "../../interface/pixel_map_generator.h" @@ -31,27 +32,33 @@ #include #include #include -#include #include +/** + * @brief Constructs the TabDeckEditorVisual instance. + * + * Sets up the central widget, tab container, menus, shortcuts, + * and restores the saved layout. + * @param _tabSupervisor Parent tab supervisor managing this tab. + */ TabDeckEditorVisual::TabDeckEditorVisual(TabSupervisor *_tabSupervisor) : AbstractTabDeckEditor(_tabSupervisor) { setObjectName("TabDeckEditorVisual"); createCentralFrame(); - - TabDeckEditorVisual::createMenus(); + createMenus(); installEventFilter(this); - TabDeckEditorVisual::retranslateUi(); + retranslateUi(); connect(&SettingsCache::instance().shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts())); - TabDeckEditorVisual::refreshShortcuts(); + refreshShortcuts(); - TabDeckEditorVisual::loadLayout(); + loadLayout(); databaseDisplayDockWidget->setHidden(true); } +/** @brief Creates the central frame containing the tab container. */ void TabDeckEditorVisual::createCentralFrame() { centralWidget = new QWidget(this); @@ -63,21 +70,22 @@ void TabDeckEditorVisual::createCentralFrame() tabContainer = new TabDeckEditorVisualTabWidget(centralWidget, this, deckDockWidget->deckModel, databaseDisplayDockWidget->databaseModel, databaseDisplayDockWidget->databaseDisplayModel); + connect(tabContainer, &TabDeckEditorVisualTabWidget::cardChanged, this, &TabDeckEditorVisual::changeModelIndexAndCardInfo); connect(tabContainer, &TabDeckEditorVisualTabWidget::cardChangedDatabaseDisplay, this, &AbstractTabDeckEditor::updateCard); connect(tabContainer, &TabDeckEditorVisualTabWidget::cardClicked, this, &TabDeckEditorVisual::processMainboardCardClick); - connect(tabContainer, &TabDeckEditorVisualTabWidget::cardClickedDatabaseDisplay, this, &TabDeckEditorVisual::processCardClickDatabaseDisplay); - centralFrame->addWidget(tabContainer); + centralFrame->addWidget(tabContainer); setCentralWidget(centralWidget); setDockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks); } +/** @brief Updates the visual deck, analytics, and sample hand after a deck change. */ void TabDeckEditorVisual::onDeckChanged() { AbstractTabDeckEditor::onDeckModified(); @@ -86,6 +94,7 @@ void TabDeckEditorVisual::onDeckChanged() tabContainer->sampleHandWidget->setDeckModel(deckDockWidget->deckModel); } +/** @brief Creates menus for deck editing and view options, including dock actions. */ void TabDeckEditorVisual::createMenus() { deckMenu = new DeckEditorMenu(this); @@ -140,10 +149,10 @@ void TabDeckEditorVisual::createMenus() viewMenu->addAction(aResetLayout); deckMenu->setSaveStatus(false); - addTabMenu(viewMenu); } +/** @brief Returns the tab text, prepending a mark if the deck has unsaved changes. */ QString TabDeckEditorVisual::getTabText() const { QString result = tr("Visual Deck: %1").arg(deckDockWidget->getSimpleDeckName()); @@ -152,12 +161,14 @@ QString TabDeckEditorVisual::getTabText() const return result; } +/** @brief Updates card info and highlights the corresponding card in the deck view. */ void TabDeckEditorVisual::changeModelIndexAndCardInfo(const ExactCard &activeCard) { updateCard(activeCard); changeModelIndexToCard(activeCard); } +/** @brief Selects the given card in the deck view, checking main and side zones. */ void TabDeckEditorVisual::changeModelIndexToCard(const ExactCard &activeCard) { QString cardName = activeCard.getName(); @@ -168,6 +179,7 @@ void TabDeckEditorVisual::changeModelIndexToCard(const ExactCard &activeCard) deckDockWidget->deckView->setCurrentIndex(index); } +/** @brief Handles clicks on cards in the mainboard deck. */ void TabDeckEditorVisual::processMainboardCardClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance, QString zoneName) @@ -181,6 +193,7 @@ void TabDeckEditorVisual::processMainboardCardClick(QMouseEvent *event, } } +/** @brief Handles clicks on cards in the database display. */ void TabDeckEditorVisual::processCardClickDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance) { @@ -193,15 +206,16 @@ void TabDeckEditorVisual::processCardClickDatabaseDisplay(QMouseEvent *event, } } +/** @brief Performs "Save Deck As..." while temporarily disabling the search bar. */ bool TabDeckEditorVisual::actSaveDeckAs() { - // We have to disable the quick-add search bar or else it'll steal focus after dialog creation. tabContainer->visualDeckView->searchBar->setEnabled(false); auto result = AbstractTabDeckEditor::actSaveDeckAs(); tabContainer->visualDeckView->searchBar->setEnabled(true); return result; } +/** @brief Shows the printing selector dock and updates it with the current card. */ void TabDeckEditorVisual::showPrintingSelector() { printingSelectorDockWidget->printingSelector->setCard(cardInfoDockWidget->cardInfo->getCard().getCardPtr(), @@ -211,6 +225,7 @@ void TabDeckEditorVisual::showPrintingSelector() printingSelectorDockWidget->setVisible(true); } +/** @brief Set size restrictions for free floating dock widgets. */ void TabDeckEditorVisual::freeDocksSize() { deckDockWidget->setMinimumSize(100, 100); @@ -226,12 +241,14 @@ void TabDeckEditorVisual::freeDocksSize() printingSelectorDockWidget->setMaximumSize(5000, 5000); } +/** @brief Refreshes keyboard shortcuts for this tab from settings. */ void TabDeckEditorVisual::refreshShortcuts() { ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); aResetLayout->setShortcuts(shortcuts.getShortcut("TabDeckEditorVisual/aResetLayout")); } +/** @brief Loads the saved layout or resets to default if no layout exists. */ void TabDeckEditorVisual::loadLayout() { LayoutsSettings &layouts = SettingsCache::instance().layouts(); @@ -280,6 +297,7 @@ void TabDeckEditorVisual::loadLayout() QTimer::singleShot(100, this, &TabDeckEditorVisual::freeDocksSize); } +/** @brief Resets the layout to default positions and dock states. */ void TabDeckEditorVisual::restartLayout() { aCardInfoDockVisible->setChecked(true); @@ -315,6 +333,7 @@ void TabDeckEditorVisual::restartLayout() QTimer::singleShot(100, this, SLOT(freeDocksSize())); } +/** @brief Retranslates UI elements for localization. */ void TabDeckEditorVisual::retranslateUi() { deckMenu->setTitle(tr("&Visual Deck Editor")); @@ -344,7 +363,11 @@ void TabDeckEditorVisual::retranslateUi() aResetLayout->setText(tr("Reset layout")); } -// Method uses to sync docks state with menu items state +/** + * @brief Handles dock visibility, floating, and layout saving events. + * + * Keeps dock state in sync with menu items and saves layout when hidden. + */ bool TabDeckEditorVisual::eventFilter(QObject *o, QEvent *e) { if (e->type() == QEvent::Close) { @@ -362,6 +385,7 @@ bool TabDeckEditorVisual::eventFilter(QObject *o, QEvent *e) aPrintingSelectorDockFloating->setEnabled(false); } } + if (o == this && e->type() == QEvent::Hide) { LayoutsSettings &layouts = SettingsCache::instance().layouts(); layouts.setDeckEditorLayoutState(saveState()); @@ -374,6 +398,7 @@ bool TabDeckEditorVisual::eventFilter(QObject *o, QEvent *e) return false; } +/** @brief Toggles dock visibility based on the corresponding menu action. */ void TabDeckEditorVisual::dockVisibleTriggered() { QObject *o = sender(); @@ -402,6 +427,7 @@ void TabDeckEditorVisual::dockVisibleTriggered() } } +/** @brief Toggles dock floating state based on the corresponding menu action. */ void TabDeckEditorVisual::dockFloatingTriggered() { QObject *o = sender(); @@ -426,6 +452,7 @@ void TabDeckEditorVisual::dockFloatingTriggered() } } +/** @brief Updates menu checkboxes when a dock's top-level/floating state changes. */ void TabDeckEditorVisual::dockTopLevelChanged(bool topLevel) { QObject *o = sender(); @@ -448,4 +475,4 @@ void TabDeckEditorVisual::dockTopLevelChanged(bool topLevel) aPrintingSelectorDockFloating->setChecked(topLevel); return; } -} \ No newline at end of file +} diff --git a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.h b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.h index b77beede8..0d34ac91f 100644 --- a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.h +++ b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.h @@ -4,47 +4,193 @@ #include "../tab.h" #include "tab_deck_editor_visual_tab_widget.h" +/** + * @class TabDeckEditorVisual + * @ingroup DeckEditorTabs + * @brief TabDeckEditorVisual provides a fully-featured deck editor tab with an enhanced visual interface. It extends + * AbstractTabDeckEditor. + * + * **Description:** + * TabDeckEditorVisual is a fully-featured deck editor tab with an enhanced visual interface. It extends + * AbstractTabDeckEditor and integrates multiple visual components such as a visual deck view, database display, + * deck analytics, and sample hand preview. + * + * **Purpose:** + * + * - Provides an intuitive, visual interface for deck editing. + * - Combines visual deck representation, card database browsing, and analytics into one tab. + * - Supports card interactions via clicks, hover events, and drag-and-drop-like behavior (not yet). + * + * **Dock Widgets and Components:** + * + * - TabDeckEditorVisualTabWidget — Container for visual sub-tabs (further described in @ref + * code_client_tabs_deck_editor_visual_tab). + * - VisualDeckEditorWidget — Displays and interacts with the deck visually. + * - VisualDatabaseDisplayWidget — Allows adding cards from the database visually. + * - DeckAnalyticsWidget — Displays deck statistics and analytics. + * - VisualDeckEditorSampleHandWidget — Simulates a sample hand from the deck. + * - DeckEditorCardInfoDockWidget — Shows detailed card info for hovered/selected cards. + * - DeckEditorDeckDockWidget — Displays deck zones and cards in a tree-view. + * - DeckEditorFilterDockWidget — Provides filtering options for card searches. + * - DeckEditorPrintingSelectorDockWidget — Selects specific card printings. + * + * **Key Methods:** + * + * - createCentralFrame() — Sets up the central widget and visual sub-tabs. + * - onDeckChanged() — Refreshes visual widgets when the deck is modified. + * - changeModelIndexAndCardInfo(const ExactCard &card) — Updates deck model selection and card info. + * - changeModelIndexToCard(const ExactCard &card) — Selects the card in the deck view. + * - processMainboardCardClick(QMouseEvent *event, ...) — Handles clicks on mainboard cards. + * - processCardClickDatabaseDisplay(QMouseEvent *event, ...) — Handles clicks on database cards. + * - actSaveDeckAs() — Overrides save action with temporary UI adjustments. + * - showPrintingSelector() — Opens the printing selector dock for the current card. + * - freeDocksSize() — Frees constraints on dock widget sizes. + * - refreshShortcuts() — Updates tab-specific shortcuts from settings. + * - loadLayout() — Loads saved layout or applies default if none exists. + * - restartLayout() — Resets dock positions, visibility, and floating states. + * - retranslateUi() — Updates text/UI elements for localization. + * - eventFilter(QObject *o, QEvent *e) — Syncs dock states with menu actions and saves layout. + */ class TabDeckEditorVisual : public AbstractTabDeckEditor { Q_OBJECT + protected slots: + /** + * @brief Load the editor layout from settings. + */ void loadLayout() override; + + /** + * @brief Reset and restart the layout to default. + */ void restartLayout() override; + + /** + * @brief Set size restrictions for free floating dock widgets. + */ void freeDocksSize() override; + + /** + * @brief Refresh keyboard shortcuts for this tab. + */ void refreshShortcuts() override; + /** + * @brief Synchronize dock state with menu items. + * @param o The object sending the event. + * @param e The event being filtered. + * @return true if the event is handled, false otherwise. + */ bool eventFilter(QObject *o, QEvent *e) override; + + /** + * @brief Triggered when a dock visibility menu item is clicked. + */ void dockVisibleTriggered() override; + + /** + * @brief Triggered when a dock floating menu item is clicked. + */ void dockFloatingTriggered() override; + + /** + * @brief Triggered when a dock top-level state changes. + * @param topLevel True if the dock became floating. + */ void dockTopLevelChanged(bool topLevel) override; protected: - TabDeckEditorVisualTabWidget *tabContainer; + TabDeckEditorVisualTabWidget *tabContainer; ///< Tab container holding different visual widgets. - QVBoxLayout *centralFrame; - QVBoxLayout *searchAndDatabaseFrame; - QHBoxLayout *searchLayout; - QDockWidget *searchAndDatabaseDock; - QWidget *centralWidget; + QVBoxLayout *centralFrame; ///< Layout for central widgets. + QVBoxLayout *searchAndDatabaseFrame; ///< Layout for search and database display. + QHBoxLayout *searchLayout; ///< Layout for search bar. + QDockWidget *searchAndDatabaseDock; ///< Dock widget for search/database display. + QWidget *centralWidget; ///< Central widget of the editor. public: + /** + * @brief Constructs a visual deck editor tab. + * @param _tabSupervisor Pointer to the tab supervisor managing this tab. + */ explicit TabDeckEditorVisual(TabSupervisor *_tabSupervisor); + + /** + * @brief Retranslate UI strings (for i18n support). + */ void retranslateUi() override; + + /** + * @brief Get the display text for the tab. + * @return Tab text with optional modification indicator. + */ QString getTabText() const override; + + /** + * @brief Update the currently selected card in the deck and UI. + * @param activeCard Card to display. + */ void changeModelIndexAndCardInfo(const ExactCard &activeCard); + + /** + * @brief Change the deck view selection to a specific card. + * @param activeCard Card to select in the deck view. + */ void changeModelIndexToCard(const ExactCard &activeCard); + + /** + * @brief Create the deck analytics dock widget. + */ void createDeckAnalyticsDock(); + + /** + * @brief Setup menus for this visual deck editor. + */ void createMenus() override; + + /** + * @brief Create search and database display frame. + */ void createSearchAndDatabaseFrame(); + + /** + * @brief Create central frame for visual widgets. + */ void createCentralFrame(); public slots: + /** + * @brief Refresh UI when the deck changes. + */ void onDeckChanged() override; + + /** + * @brief Show the printing selector dock for the currently active card. + */ void showPrintingSelector() override; + + /** + * @brief Handle card clicks in the mainboard visual deck. + * @param event Mouse event triggering the action. + * @param instance Widget representing the clicked card. + * @param zoneName Deck zone of the card. + */ void processMainboardCardClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance, QString zoneName); + + /** + * @brief Handle card clicks in the database visual display. + * @param event Mouse event triggering the action. + * @param instance Widget representing the clicked card. + */ void processCardClickDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance); + + /** + * @brief Save the deck under a new name. + * @return true if successful, false otherwise. + */ bool actSaveDeckAs() override; }; -#endif +#endif \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.cpp b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.cpp index f42b1ff70..08728dac0 100644 --- a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.cpp +++ b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.cpp @@ -3,6 +3,17 @@ #include "../../interface/widgets/visual_database_display/visual_database_display_widget.h" #include "../abstract_tab_deck_editor.h" +/** + * @brief Constructs the TabDeckEditorVisualTabWidget. + * @param parent The parent QWidget. + * @param _deckEditor Pointer to the associated deck editor. + * @param _deckModel Pointer to the deck list model. + * @param _cardDatabaseModel Pointer to the card database model. + * @param _cardDatabaseDisplayModel Pointer to the card database display model. + * + * Initializes all sub-widgets (visual deck view, database display, deck analytics, + * sample hand) and sets up the tab layout and signal connections. + */ TabDeckEditorVisualTabWidget::TabDeckEditorVisualTabWidget(QWidget *parent, AbstractTabDeckEditor *_deckEditor, DeckListModel *_deckModel, @@ -14,7 +25,6 @@ TabDeckEditorVisualTabWidget::TabDeckEditorVisualTabWidget(QWidget *parent, this->setTabsClosable(true); // Enable tab closing connect(this, &QTabWidget::tabCloseRequested, this, &TabDeckEditorVisualTabWidget::handleTabClose); - // Set up the layout and add tab widget layout = new QVBoxLayout(this); setLayout(layout); @@ -46,16 +56,30 @@ TabDeckEditorVisualTabWidget::TabDeckEditorVisualTabWidget(QWidget *parent, this->addNewTab(sampleHandWidget, tr("Sample Hand")); } +/** + * @brief Emits the cardChanged signal when a card is activated in the visual deck view. + * @param activeCard The card that was activated. + */ void TabDeckEditorVisualTabWidget::onCardChanged(const ExactCard &activeCard) { emit cardChanged(activeCard); } +/** + * @brief Emits the cardChangedDatabaseDisplay signal when a card is hovered in the database display. + * @param activeCard The card that was hovered. + */ void TabDeckEditorVisualTabWidget::onCardChangedDatabaseDisplay(const ExactCard &activeCard) { emit cardChangedDatabaseDisplay(activeCard); } +/** + * @brief Emits the cardClicked signal when a card is clicked in the visual deck view. + * @param event The mouse event. + * @param instance The widget instance of the clicked card. + * @param zoneName The zone of the deck where the card is located. + */ void TabDeckEditorVisualTabWidget::onCardClickedDeckEditor(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance, QString zoneName) @@ -63,51 +87,77 @@ void TabDeckEditorVisualTabWidget::onCardClickedDeckEditor(QMouseEvent *event, emit cardClicked(event, instance, zoneName); } +/** + * @brief Emits the cardClickedDatabaseDisplay signal when a card is clicked in the database display. + * @param event The mouse event. + * @param instance The widget instance of the clicked card. + */ void TabDeckEditorVisualTabWidget::onCardClickedDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance) { emit cardClickedDatabaseDisplay(event, instance); } +/** + * @brief Adds a new tab with the given widget and title. + * @param widget The widget to add. + * @param title The title of the tab. + */ void TabDeckEditorVisualTabWidget::addNewTab(QWidget *widget, const QString &title) { - // Add new tab to the tab widget this->addTab(widget, title); } +/** + * @brief Removes the currently selected tab. + */ void TabDeckEditorVisualTabWidget::removeCurrentTab() { - // Remove the currently selected tab int currentIndex = this->currentIndex(); if (currentIndex != -1) { this->removeTab(currentIndex); } } +/** + * @brief Sets the title of a tab at a given index. + * @param index The index of the tab. + * @param title The new title. + */ void TabDeckEditorVisualTabWidget::setTabTitle(int index, const QString &title) { - // Set the title of the tab at the given index if (index >= 0 && index < this->count()) { this->setTabText(index, title); } } +/** + * @brief Returns the currently selected tab widget. + * @return Pointer to the current tab widget. + */ QWidget *TabDeckEditorVisualTabWidget::getCurrentTab() const { - // Return the currently selected tab widget return this->currentWidget(); } +/** + * @brief Returns the number of tabs in the tab widget. + * @return Number of tabs. + */ int TabDeckEditorVisualTabWidget::getTabCount() const { - // Return the number of tabs return this->count(); } +/** + * @brief Handles the closing of a tab. + * @param index The index of the tab to close. + * + * Removes the tab and deletes the widget to free memory. + */ void TabDeckEditorVisualTabWidget::handleTabClose(int index) { - // Handle closing of the tab at the given index QWidget *tab = this->widget(index); this->removeTab(index); - delete tab; // Delete the tab's widget to free memory + delete tab; } diff --git a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h index 36027f819..b84e9bf33 100644 --- a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h +++ b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h @@ -12,34 +12,104 @@ #include #include +/** + * @class TabDeckEditorVisualTabWidget + * @ingroup DeckEditorWidgets + * @brief Tab container for the visual deck editor. + * + * **Description:** + * TabDeckEditorVisualTabWidget is a QTabWidget container for visual deck editing sub-tabs. It organizes the visual + * deck, database display, deck analytics, and sample hand preview into separate tabs. + * + * **Purpose:** + * - Provides a tabbed interface for multiple visual components of the deck editor. + * - Handles forwarding of card events (hover, click, selection) to TabDeckEditorVisual. + * - Manages dynamic tab addition, removal, and title updates. + * + * **Contained Sub-Tabs and Widgets:** + * - VisualDeckEditorWidget — Visual deck interface with card interactions. + * - VisualDatabaseDisplayWidget — Displays card database visually and supports interactions. + * - DeckAnalyticsWidget — Shows deck statistics and metrics. + * - VisualDeckEditorSampleHandWidget — Simulates and displays sample hands. + * + * **Key Methods:** + * - addNewTab(QWidget *widget, const QString &title) — Adds a new tab to the container. + * - removeCurrentTab() — Removes the currently selected tab. + * - setTabTitle(int index, const QString &title) — Sets the title of a specific tab. + * - getCurrentTab() const — Returns the currently active tab widget. + * - getTabCount() const — Returns the number of tabs. + * - handleTabClose(int index) — Handles tab close requests and deletes the widget. + * - onCardChanged(const ExactCard &activeCard) — Emits card change signal from visual deck. + * - onCardChangedDatabaseDisplay(const ExactCard &activeCard) — Emits card change signal from database display. + * - onCardClickedDeckEditor(QMouseEvent *event, ...) — Emits click events from deck editor visual tab. + * - onCardClickedDatabaseDisplay(QMouseEvent *event, ...) — Emits click events from database display tab. + */ class TabDeckEditorVisualTabWidget : public QTabWidget { Q_OBJECT public: + /** + * @brief Construct the tab widget with required models. + * @param parent Parent widget. + * @param _deckEditor Pointer to the deck editor instance. + * @param _deckModel Deck list model. + * @param _cardDatabaseModel Card database model. + * @param _cardDatabaseDisplayModel Database display model. + */ explicit TabDeckEditorVisualTabWidget(QWidget *parent, AbstractTabDeckEditor *_deckEditor, DeckListModel *_deckModel, CardDatabaseModel *_cardDatabaseModel, CardDatabaseDisplayModel *_cardDatabaseDisplayModel); - // Utility functions + /// Add a new tab with a widget and title. void addNewTab(QWidget *widget, const QString &title); + + /// Remove the currently active tab. void removeCurrentTab(); + + /// Set the title of a specific tab. void setTabTitle(int index, const QString &title); + + /// Get the currently active tab widget. QWidget *getCurrentTab() const; + + /// Get the total number of tabs. int getTabCount() const; - VisualDeckEditorWidget *visualDeckView; - DeckAnalyticsWidget *deckAnalytics; - VisualDatabaseDisplayWidget *visualDatabaseDisplay; - PrintingSelector *printingSelector; - VisualDeckEditorSampleHandWidget *sampleHandWidget; + VisualDeckEditorWidget *visualDeckView; ///< Visual deck editor widget. + DeckAnalyticsWidget *deckAnalytics; ///< Deck analytics widget. + VisualDatabaseDisplayWidget *visualDatabaseDisplay; ///< Database display widget. + PrintingSelector *printingSelector; ///< Printing selector widget. + VisualDeckEditorSampleHandWidget *sampleHandWidget; ///< Sample hand simulation widget. public slots: + /** + * @brief Emitted when the active card changes in the deck view. + * @param activeCard New active card. + */ void onCardChanged(const ExactCard &activeCard); + + /** + * @brief Emitted when the active card changes in the database display. + * @param activeCard New active card. + */ void onCardChangedDatabaseDisplay(const ExactCard &activeCard); + + /** + * @brief Emitted when a card is clicked in the deck view. + * @param event Mouse event. + * @param instance Widget representing the clicked card. + * @param zoneName Deck zone of the card. + */ void onCardClickedDeckEditor(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance, QString zoneName); + + /** + * @brief Emitted when a card is clicked in the database display. + * @param event Mouse event. + * @param instance Widget representing the clicked card. + */ void onCardClickedDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance); signals: @@ -49,14 +119,18 @@ signals: void cardClickedDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance); private: - QVBoxLayout *layout; // Layout for the tab widget and other controls - AbstractTabDeckEditor *deckEditor; - DeckListModel *deckModel; - CardDatabaseModel *cardDatabaseModel; - CardDatabaseDisplayModel *cardDatabaseDisplayModel; + QVBoxLayout *layout; ///< Layout for tabs and controls. + AbstractTabDeckEditor *deckEditor; ///< Reference to the deck editor. + DeckListModel *deckModel; ///< Deck list model. + CardDatabaseModel *cardDatabaseModel; ///< Card database model. + CardDatabaseDisplayModel *cardDatabaseDisplayModel; ///< Card database display model. private slots: - void handleTabClose(int index); // Slot for closing a tab + /** + * @brief Handle closing of a tab at a given index. + * @param index Index of the tab to close. + */ + void handleTabClose(int index); }; -#endif // TAB_DECK_EDITOR_VISUAL_TAB_WIDGET_H +#endif // TAB_DECK_EDITOR_VISUAL_TAB_WIDGET_H \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/tabs/visual_deck_storage/tab_deck_storage_visual.cpp b/cockatrice/src/interface/widgets/tabs/visual_deck_storage/tab_deck_storage_visual.cpp index f3b271026..b4749f408 100644 --- a/cockatrice/src/interface/widgets/tabs/visual_deck_storage/tab_deck_storage_visual.cpp +++ b/cockatrice/src/interface/widgets/tabs/visual_deck_storage/tab_deck_storage_visual.cpp @@ -27,7 +27,7 @@ TabDeckStorageVisual::TabDeckStorageVisual(TabSupervisor *_tabSupervisor) void TabDeckStorageVisual::actOpenLocalDeck(const QString &filePath) { - DeckLoader deckLoader; + DeckLoader deckLoader(this); if (!deckLoader.loadFromFile(filePath, DeckLoader::getFormatFromName(filePath), true)) { QMessageBox::critical(this, tr("Error"), tr("Could not open deck at %1").arg(filePath)); return; diff --git a/cockatrice/src/interface/widgets/tabs/visual_deck_storage/tab_deck_storage_visual.h b/cockatrice/src/interface/widgets/tabs/visual_deck_storage/tab_deck_storage_visual.h index b3a4598c0..a56ce4c24 100644 --- a/cockatrice/src/interface/widgets/tabs/visual_deck_storage/tab_deck_storage_visual.h +++ b/cockatrice/src/interface/widgets/tabs/visual_deck_storage/tab_deck_storage_visual.h @@ -39,7 +39,7 @@ public slots: void actOpenLocalDeck(const QString &filePath); signals: - void openDeckEditor(const DeckLoader *deckLoader); + void openDeckEditor(DeckLoader *deckLoader); private: VisualDeckStorageWidget *visualDeckStorageWidget; diff --git a/cockatrice/src/interface/widgets/utility/custom_line_edit.cpp b/cockatrice/src/interface/widgets/utility/custom_line_edit.cpp index 532afc114..c137b4f35 100644 --- a/cockatrice/src/interface/widgets/utility/custom_line_edit.cpp +++ b/cockatrice/src/interface/widgets/utility/custom_line_edit.cpp @@ -1,12 +1,13 @@ #include "custom_line_edit.h" +#include "../../../client/settings/cache_settings.h" +#include "../../../client/settings/shortcuts_settings.h" + #include #include #include #include #include -#include -#include LineEditUnfocusable::LineEditUnfocusable(QWidget *parent) : QLineEdit(parent) { diff --git a/cockatrice/src/interface/widgets/utility/sequence_edit.cpp b/cockatrice/src/interface/widgets/utility/sequence_edit.cpp index 53776a3b0..7e14d4335 100644 --- a/cockatrice/src/interface/widgets/utility/sequence_edit.cpp +++ b/cockatrice/src/interface/widgets/utility/sequence_edit.cpp @@ -1,9 +1,10 @@ #include "sequence_edit.h" +#include "../../../client/settings/cache_settings.h" + #include #include #include -#include #include SequenceEdit::SequenceEdit(const QString &_shortcutName, QWidget *parent) : QWidget(parent) diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_color_filter_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_color_filter_widget.cpp index e8eb97125..d4947d6c5 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_color_filter_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_color_filter_widget.cpp @@ -1,10 +1,10 @@ #include "visual_database_display_color_filter_widget.h" -#include "../../../filters/filter_tree.h" #include "../cards/additional_info/mana_symbol_widget.h" #include #include +#include /** * This widget provides a graphical control element for the CardFilter::Attr::AttrColor filters applied to the filter diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.cpp index e8c42a28a..062774969 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.cpp @@ -1,13 +1,13 @@ #include "visual_database_display_filter_save_load_widget.h" -#include "../../../filters/filter_tree.h" +#include "../../../client/settings/cache_settings.h" #include "visual_database_filter_display_widget.h" #include #include #include #include -#include +#include VisualDatabaseDisplayFilterSaveLoadWidget::VisualDatabaseDisplayFilterSaveLoadWidget(QWidget *parent, FilterTreeModel *_filterModel) diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_main_type_filter_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_main_type_filter_widget.cpp index 8ffb29eca..32652c346 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_main_type_filter_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_main_type_filter_widget.cpp @@ -1,12 +1,12 @@ #include "visual_database_display_main_type_filter_widget.h" -#include "../../../filters/filter_tree.h" #include "../../../filters/filter_tree_model.h" #include #include #include #include +#include VisualDatabaseDisplayMainTypeFilterWidget::VisualDatabaseDisplayMainTypeFilterWidget(QWidget *parent, FilterTreeModel *_filterModel) diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.cpp index 33929341e..cdb9a8d0c 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.cpp @@ -91,7 +91,7 @@ void VisualDatabaseDisplayNameFilterWidget::actLoadFromClipboard() if (!dlg.exec()) return; - QStringList cardsInClipboard = dlg.getDeckList()->getCardList(); + QStringList cardsInClipboard = dlg.getDeckList()->getDeckList()->getCardList(); for (QString cardName : cardsInClipboard) { createNameFilter(cardName); } diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_set_filter_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_set_filter_widget.cpp index 5a9c1029c..1ea6e8e67 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_set_filter_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_set_filter_widget.cpp @@ -1,6 +1,6 @@ #include "visual_database_display_set_filter_widget.h" -#include "../../../filters/filter_tree.h" +#include "../../../client/settings/cache_settings.h" #include "../../../filters/filter_tree_model.h" #include @@ -8,7 +8,7 @@ #include #include #include -#include +#include VisualDatabaseDisplayRecentSetFilterSettingsWidget::VisualDatabaseDisplayRecentSetFilterSettingsWidget(QWidget *parent) : QWidget(parent) diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.cpp index ece3fca3b..7a88b51cf 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.cpp @@ -1,6 +1,5 @@ #include "visual_database_display_sub_type_filter_widget.h" -#include "../../../filters/filter_tree.h" #include "../../../filters/filter_tree_model.h" #include @@ -8,6 +7,7 @@ #include #include #include +#include VisualDatabaseDisplaySubTypeFilterWidget::VisualDatabaseDisplaySubTypeFilterWidget(QWidget *parent, FilterTreeModel *_filterModel) diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp index 673a2ec1a..d371d0ed3 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp @@ -1,5 +1,6 @@ #include "visual_database_display_widget.h" +#include "../../../client/settings/cache_settings.h" #include "../../../filters/filter_tree_model.h" #include "../../../filters/syntax_help.h" #include "../../pixel_map_generator.h" @@ -18,7 +19,6 @@ #include #include #include -#include #include #include diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_filter_display_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_filter_display_widget.cpp index 093a52d72..5364fa813 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_filter_display_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_filter_display_widget.cpp @@ -1,12 +1,13 @@ #include "visual_database_filter_display_widget.h" +#include "../../../client/settings/cache_settings.h" + #include #include #include #include #include #include -#include FilterDisplayWidget::FilterDisplayWidget(QWidget *parent, const QString &filename, FilterTreeModel *_filterModel) : QWidget(parent), filterFilename(filename), filterModel(_filterModel) diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp index a2bd051ff..ae9cb10ef 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp @@ -1,10 +1,10 @@ #include "visual_deck_editor_sample_hand_widget.h" +#include "../../../client/settings/cache_settings.h" +#include "../../deck_loader/deck_loader.h" #include "../cards/card_info_picture_widget.h" #include -#include -#include #include VisualDeckEditorSampleHandWidget::VisualDeckEditorSampleHandWidget(QWidget *parent, DeckListModel *_deckListModel) diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp index d0f1bf034..005efd6db 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp @@ -1,11 +1,14 @@ #include "visual_deck_editor_widget.h" #include "../../../main.h" +#include "../../deck_loader/deck_loader.h" #include "../../layouts/overlap_layout.h" #include "../cards/card_info_picture_with_text_overlay_widget.h" #include "../cards/deck_card_zone_display_widget.h" #include "../general/layout_containers/flow_widget.h" #include "../general/layout_containers/overlap_control_widget.h" +#include "../tabs/visual_deck_editor/tab_deck_editor_visual.h" +#include "../tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h" #include #include @@ -20,7 +23,6 @@ #include #include #include -#include #include VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, DeckListModel *_deckListModel) @@ -119,13 +121,30 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, DeckListModel *_ groupAndSortLayout->setAlignment(Qt::AlignLeft); groupAndSortContainer->setLayout(groupAndSortLayout); - groupByComboBox = new QComboBox(); - QStringList groupProperties = {"maintype", "colors", "cmc", "name"}; - groupByComboBox->addItems(groupProperties); - groupByComboBox->setMinimumWidth(300); - connect(groupByComboBox, QOverload::of(&QComboBox::currentTextChanged), this, - &VisualDeckEditorWidget::actChangeActiveGroupCriteria); - actChangeActiveGroupCriteria(); + groupByComboBox = new QComboBox(this); + if (auto tabWidget = qobject_cast(parent)) { + // Inside a central widget QWidget container inside TabDeckEditorVisual + if (auto tab = qobject_cast(tabWidget->parent()->parent())) { + auto originalBox = tab->getDeckDockWidget()->getGroupByComboBox(); + groupByComboBox->setModel(originalBox->model()); + groupByComboBox->setModelColumn(originalBox->modelColumn()); + + // Original -> clone + connect(originalBox, QOverload::of(&QComboBox::currentIndexChanged), + [this](int index) { groupByComboBox->setCurrentIndex(index); }); + + // Clone -> original + connect(groupByComboBox, QOverload::of(&QComboBox::currentIndexChanged), + [originalBox](int index) { originalBox->setCurrentIndex(index); }); + } + } else { + QStringList groupProperties = {"maintype", "colors", "cmc", "name"}; + groupByComboBox->addItems(groupProperties); + groupByComboBox->setMinimumWidth(300); + connect(groupByComboBox, QOverload::of(&QComboBox::currentTextChanged), this, + &VisualDeckEditorWidget::actChangeActiveGroupCriteria); + actChangeActiveGroupCriteria(); + } sortCriteriaButton = new SettingsButtonWidget(this); diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.cpp index 4053de89b..eb105697f 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.cpp @@ -1,5 +1,6 @@ #include "deck_preview_deck_tags_display_widget.h" +#include "../../../../client/settings/cache_settings.h" #include "../../../../interface/widgets/dialogs/dlg_convert_deck_to_cod_format.h" #include "../../../../interface/widgets/tabs/tab_deck_editor.h" #include "../../general/layout_containers/flow_widget.h" @@ -12,7 +13,6 @@ #include #include #include -#include DeckPreviewDeckTagsDisplayWidget::DeckPreviewDeckTagsDisplayWidget(QWidget *_parent, DeckList *_deckList) : QWidget(_parent), deckList(nullptr) @@ -167,10 +167,10 @@ void DeckPreviewDeckTagsDisplayWidget::openTagEditDlg() auto *deckEditor = qobject_cast(currentParent); QStringList knownTags; QStringList allFiles = getAllFiles(SettingsCache::instance().getDeckPath()); - DeckLoader loader; + DeckLoader loader(this); for (const QString &file : allFiles) { loader.loadFromFile(file, DeckLoader::getFormatFromName(file), false); - QStringList tags = loader.getTags(); + QStringList tags = loader.getDeckList()->getTags(); knownTags.append(tags); knownTags.removeDuplicates(); } diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h index 5f6059549..4270e38e5 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h @@ -7,10 +7,10 @@ #ifndef DECK_PREVIEW_DECK_TAGS_DISPLAY_WIDGET_H #define DECK_PREVIEW_DECK_TAGS_DISPLAY_WIDGET_H +#include "../../../deck_loader/deck_loader.h" #include "deck_preview_widget.h" #include -#include inline bool confirmOverwriteIfExists(QWidget *parent, const QString &filePath); diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.cpp index a8979bae9..a221442ba 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.cpp @@ -1,5 +1,6 @@ #include "deck_preview_tag_addition_widget.h" +#include "../../../../client/settings/cache_settings.h" #include "../../../../interface/widgets/tabs/abstract_tab_deck_editor.h" #include "deck_preview_tag_dialog.h" @@ -7,7 +8,6 @@ #include #include #include -#include #include DeckPreviewTagAdditionWidget::DeckPreviewTagAdditionWidget(QWidget *_parent, QString _tagName) diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_dialog.cpp b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_dialog.cpp index 9d130946f..df7f9738d 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_dialog.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_dialog.cpp @@ -1,5 +1,6 @@ #include "deck_preview_tag_dialog.h" +#include "../../../../client/settings/cache_settings.h" #include "../../../../interface/widgets/dialogs/dlg_default_tags_editor.h" #include "deck_preview_tag_item_widget.h" @@ -11,7 +12,6 @@ #include #include #include -#include DeckPreviewTagDialog::DeckPreviewTagDialog(const QStringList &knownTags, const QStringList &_activeTags, diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp index afa6b6d72..ca380bc22 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp @@ -1,5 +1,6 @@ #include "deck_preview_widget.h" +#include "../../../../client/settings/cache_settings.h" #include "../../cards/additional_info/color_identity_widget.h" #include "../../cards/deck_preview_card_picture_widget.h" #include "deck_preview_deck_tags_display_widget.h" @@ -14,7 +15,6 @@ #include #include #include -#include DeckPreviewWidget::DeckPreviewWidget(QWidget *_parent, VisualDeckStorageWidget *_visualDeckStorageWidget, @@ -25,8 +25,7 @@ DeckPreviewWidget::DeckPreviewWidget(QWidget *_parent, layout = new QVBoxLayout(this); setLayout(layout); - deckLoader = new DeckLoader(); - deckLoader->setParent(this); + deckLoader = new DeckLoader(this); connect(deckLoader, &DeckLoader::loadFinished, this, &DeckPreviewWidget::initializeUi); /* TODO: We shouldn't update the tags on *every* deck load, since it's kinda expensive. We should instead count how many deck loads have finished already and if we've loaded all decks and THEN load all the tags at once. */ @@ -74,23 +73,23 @@ void DeckPreviewWidget::initializeUi(const bool deckLoadSuccess) if (!deckLoadSuccess) { return; } - auto bannerCard = deckLoader->getBannerCard().name.isEmpty() + auto bannerCard = deckLoader->getDeckList()->getBannerCard().name.isEmpty() ? ExactCard() - : CardDatabaseManager::query()->getCard(deckLoader->getBannerCard()); + : CardDatabaseManager::query()->getCard(deckLoader->getDeckList()->getBannerCard()); bannerCardDisplayWidget->setCard(bannerCard); bannerCardDisplayWidget->setFontSize(24); setFilePath(deckLoader->getLastFileName()); colorIdentityWidget = new ColorIdentityWidget(this, getColorIdentity()); - deckTagsDisplayWidget = new DeckPreviewDeckTagsDisplayWidget(this, deckLoader); + deckTagsDisplayWidget = new DeckPreviewDeckTagsDisplayWidget(this, deckLoader->getDeckList()); bannerCardLabel = new QLabel(this); bannerCardLabel->setObjectName("bannerCardLabel"); bannerCardComboBox = new QComboBox(this); bannerCardComboBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); bannerCardComboBox->setObjectName("bannerCardComboBox"); - bannerCardComboBox->setCurrentText(deckLoader->getBannerCard().name); + bannerCardComboBox->setCurrentText(deckLoader->getDeckList()->getBannerCard().name); bannerCardComboBox->installEventFilter(new NoScrollFilter()); connect(bannerCardComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &DeckPreviewWidget::setBannerCard); @@ -152,7 +151,7 @@ void DeckPreviewWidget::updateTagsVisibility(bool visible) QString DeckPreviewWidget::getColorIdentity() { - QStringList cardList = deckLoader->getCardList(); + QStringList cardList = deckLoader->getDeckList()->getCardList(); if (cardList.isEmpty()) { return {}; } @@ -186,8 +185,8 @@ QString DeckPreviewWidget::getColorIdentity() */ QString DeckPreviewWidget::getDisplayName() const { - return deckLoader->getName().isEmpty() ? QFileInfo(deckLoader->getLastFileName()).fileName() - : deckLoader->getName(); + return deckLoader->getDeckList()->getName().isEmpty() ? QFileInfo(deckLoader->getLastFileName()).fileName() + : deckLoader->getDeckList()->getName(); } void DeckPreviewWidget::setFilePath(const QString &_filePath) @@ -233,7 +232,7 @@ void DeckPreviewWidget::updateBannerCardComboBox() // Prepare the new items with deduplication QSet> bannerCardSet; - InnerDecklistNode *listRoot = deckLoader->getRoot(); + InnerDecklistNode *listRoot = deckLoader->getDeckList()->getRoot(); for (auto i : *listRoot) { auto *currentZone = dynamic_cast(i); for (auto j : *currentZone) { @@ -273,7 +272,7 @@ void DeckPreviewWidget::updateBannerCardComboBox() bannerCardComboBox->setCurrentIndex(restoredIndex); } else { // Add a placeholder "-" and set it as the current selection - int bannerIndex = bannerCardComboBox->findText(deckLoader->getBannerCard().name); + int bannerIndex = bannerCardComboBox->findText(deckLoader->getDeckList()->getBannerCard().name); if (bannerIndex != -1) { bannerCardComboBox->setCurrentIndex(bannerIndex); } else { @@ -291,7 +290,7 @@ void DeckPreviewWidget::setBannerCard(int /* changedIndex */) { auto [name, id] = bannerCardComboBox->currentData().value>(); CardRef cardRef = {name, id}; - deckLoader->setBannerCard(cardRef); + deckLoader->getDeckList()->setBannerCard(cardRef); deckLoader->saveToFile(filePath, DeckLoader::getFormatFromName(filePath)); bannerCardDisplayWidget->setCard(CardDatabaseManager::query()->getCard(cardRef)); } @@ -374,7 +373,7 @@ void DeckPreviewWidget::addSetBannerCardMenu(QMenu *menu) void DeckPreviewWidget::actRenameDeck() { // read input - const QString oldName = deckLoader->getName(); + const QString oldName = deckLoader->getDeckList()->getName(); bool ok; QString newName = QInputDialog::getText(this, "Rename deck", tr("New name:"), QLineEdit::Normal, oldName, &ok); @@ -383,7 +382,7 @@ void DeckPreviewWidget::actRenameDeck() } // write change - deckLoader->setName(newName); + deckLoader->getDeckList()->setName(newName); deckLoader->saveToFile(filePath, DeckLoader::getFormatFromName(filePath)); // update VDS diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.h index 154af3dfc..25a29b9bd 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.h @@ -7,6 +7,7 @@ #ifndef DECK_PREVIEW_WIDGET_H #define DECK_PREVIEW_WIDGET_H +#include "../../../deck_loader/deck_loader.h" #include "../../cards/additional_info/color_identity_widget.h" #include "../../cards/deck_preview_card_picture_widget.h" #include "../visual_deck_storage_widget.h" @@ -18,7 +19,6 @@ #include #include #include -#include class QMenu; class VisualDeckStorageWidget; @@ -51,7 +51,7 @@ public: signals: void deckLoadRequested(const QString &filePath); - void openDeckEditor(const DeckLoader *deck); + void openDeckEditor(DeckLoader *deck); public slots: void setFilePath(const QString &filePath); diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.cpp index f36b84a1c..c5758c5a6 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.cpp @@ -1,10 +1,10 @@ #include "visual_deck_storage_folder_display_widget.h" +#include "../../../client/settings/cache_settings.h" #include "deck_preview/deck_preview_widget.h" #include #include -#include VisualDeckStorageFolderDisplayWidget::VisualDeckStorageFolderDisplayWidget( QWidget *parent, @@ -210,7 +210,7 @@ QStringList VisualDeckStorageFolderDisplayWidget::gatherAllTagsFromFlowWidget() // Iterate through all DeckPreviewWidgets for (DeckPreviewWidget *display : flowWidget->findChildren()) { // Get tags from each DeckPreviewWidget - QStringList tags = display->deckLoader->getTags(); + QStringList tags = display->deckLoader->getDeckList()->getTags(); // Add tags to the list while avoiding duplicates allTags.append(tags); diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_quick_settings_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_quick_settings_widget.cpp index 19bf070c9..c1e9bfa6a 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_quick_settings_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_quick_settings_widget.cpp @@ -1,11 +1,11 @@ #include "visual_deck_storage_quick_settings_widget.h" +#include "../../../client/settings/cache_settings.h" #include "visual_deck_storage_widget.h" #include #include #include -#include VisualDeckStorageQuickSettingsWidget::VisualDeckStorageQuickSettingsWidget(QWidget *parent) : SettingsButtonWidget(parent) diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_search_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_search_widget.cpp index 18430d698..dbd7929c5 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_search_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_search_widget.cpp @@ -1,11 +1,11 @@ #include "visual_deck_storage_search_widget.h" +#include "../../../client/settings/cache_settings.h" #include "../../../filters/deck_filter_string.h" #include "../../../filters/syntax_help.h" #include "../../pixel_map_generator.h" #include -#include /** * @brief Constructs a PrintingSelectorCardSearchWidget for searching cards by set name or set code. diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_sort_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_sort_widget.cpp index c68dfdc3b..ad49e0065 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_sort_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_sort_widget.cpp @@ -1,6 +1,6 @@ #include "visual_deck_storage_sort_widget.h" -#include +#include "../../../client/settings/cache_settings.h" /** * @brief Constructs a PrintingSelectorCardSortWidget for searching cards by set name or set code. @@ -93,14 +93,14 @@ QList VisualDeckStorageSortWidget::filterFiles(QListdeckLoader->getName() < widget2->deckLoader->getName(); + return widget1->deckLoader->getDeckList()->getName() < widget2->deckLoader->getDeckList()->getName(); case Alphabetical: return QString::localeAwareCompare(info1.fileName(), info2.fileName()) <= 0; case ByLastModified: return info1.lastModified() > info2.lastModified(); case ByLastLoaded: { - QDateTime time1 = QDateTime::fromString(widget1->deckLoader->getLastLoadedTimestamp()); - QDateTime time2 = QDateTime::fromString(widget2->deckLoader->getLastLoadedTimestamp()); + QDateTime time1 = QDateTime::fromString(widget1->deckLoader->getDeckList()->getLastLoadedTimestamp()); + QDateTime time2 = QDateTime::fromString(widget2->deckLoader->getDeckList()->getLastLoadedTimestamp()); return time1 > time2; } } diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.cpp index 47ed6ebee..4e78a67c4 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.cpp @@ -59,7 +59,7 @@ void VisualDeckStorageTagFilterWidget::filterDecksBySelectedTags(const QListdeckLoader->getTags(); + QStringList deckTags = deckPreview->deckLoader->getDeckList()->getTags(); bool hasAllSelected = std::all_of(selectedTags.begin(), selectedTags.end(), [&deckTags](const QString &tag) { return deckTags.contains(tag); }); @@ -155,7 +155,7 @@ QSet VisualDeckStorageTagFilterWidget::gatherAllTags() const for (DeckPreviewWidget *widget : deckWidgets) { if (widget->checkVisibility()) { - for (const QString &tag : widget->deckLoader->getTags()) { + for (const QString &tag : widget->deckLoader->getDeckList()->getTags()) { allTags.insert(tag); } } diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.cpp index 164aff8bc..d9cf74e7f 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.cpp @@ -1,5 +1,6 @@ #include "visual_deck_storage_widget.h" +#include "../../../client/settings/cache_settings.h" #include "../quick_settings/settings_button_widget.h" #include "deck_preview/deck_preview_widget.h" #include "visual_deck_storage_folder_display_widget.h" @@ -13,7 +14,6 @@ #include #include #include -#include VisualDeckStorageWidget::VisualDeckStorageWidget(QWidget *parent) : QWidget(parent), folderWidget(nullptr) { diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.h index f49d2544b..5ff56bb33 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.h @@ -7,6 +7,7 @@ #ifndef VISUAL_DECK_STORAGE_WIDGET_H #define VISUAL_DECK_STORAGE_WIDGET_H +#include "../../deck_loader/deck_loader.h" #include "../cards/card_size_widget.h" #include "../general/layout_containers/flow_widget.h" #include "../quick_settings/settings_button_widget.h" @@ -56,7 +57,7 @@ public slots: signals: void bannerCardsRefreshed(); void deckLoadRequested(const QString &filePath); - void openDeckEditor(const DeckLoader *deck); + void openDeckEditor(DeckLoader *deck); private: QVBoxLayout *layout; diff --git a/cockatrice/src/interface/window_main.cpp b/cockatrice/src/interface/window_main.cpp index 4186f7ce7..622c04a08 100644 --- a/cockatrice/src/interface/window_main.cpp +++ b/cockatrice/src/interface/window_main.cpp @@ -21,6 +21,7 @@ #include "../client/network/update/client/client_update_checker.h" #include "../client/network/update/client/release_channel.h" +#include "../client/settings/cache_settings.h" #include "../interface/widgets/dialogs/dlg_connect.h" #include "../interface/widgets/dialogs/dlg_edit_tokens.h" #include "../interface/widgets/dialogs/dlg_forgot_password_challenge.h" @@ -71,7 +72,6 @@ #include #include #include -#include #define GITHUB_PAGES_URL "https://cockatrice.github.io" #define GITHUB_CONTRIBUTORS_URL "https://github.com/Cockatrice/Cockatrice/graphs/contributors?type=c" @@ -846,7 +846,7 @@ MainWindow::MainWindow(QWidget *parent) &MainWindow::pixmapCacheSizeChanged); pixmapCacheSizeChanged(SettingsCache::instance().getPixmapCacheSize()); - client = new RemoteClient; + client = new RemoteClient(nullptr, &SettingsCache::instance()); connect(client, &RemoteClient::connectionClosedEventReceived, this, &MainWindow::processConnectionClosedEvent); connect(client, &RemoteClient::serverShutdownEventReceived, this, &MainWindow::processServerShutdownEvent); connect(client, &RemoteClient::loginError, this, &MainWindow::loginError); diff --git a/cockatrice/src/main.cpp b/cockatrice/src/main.cpp index ecb915cee..f20dab6fb 100644 --- a/cockatrice/src/main.cpp +++ b/cockatrice/src/main.cpp @@ -22,7 +22,9 @@ #include "QtNetwork/QNetworkInterface" #include "client/network/update/card_spoiler/spoiler_background_updater.h" +#include "client/settings/cache_settings.h" #include "client/sound_engine.h" +#include "database/interface/settings_card_preference_provider.h" #include "interface/logger.h" #include "interface/pixel_map_generator.h" #include "interface/theme_manager.h" @@ -42,9 +44,9 @@ #include #include #include +#include #include #include -#include QTranslator *translator, *qtTranslator; RNG_Abstract *rng; @@ -250,6 +252,11 @@ int main(int argc, char *argv[]) QLocale::setDefault(QLocale::English); + // Dependency Injections + CardDatabaseManager::setCardPreferenceProvider(new SettingsCardPreferenceProvider()); + CardDatabaseManager::setCardDatabasePathProvider(&SettingsCache::instance()); + CardDatabaseManager::setCardSetPriorityController(SettingsCache::instance().cardDatabase()); + qCInfo(MainLog) << "Starting main program"; MainWindow ui; diff --git a/dbconverter/CMakeLists.txt b/dbconverter/CMakeLists.txt index acf60bf03..b2de9dcb8 100644 --- a/dbconverter/CMakeLists.txt +++ b/dbconverter/CMakeLists.txt @@ -25,6 +25,7 @@ add_executable(dbconverter MACOSX_BUNDLE ${dbconverter_SOURCES}) target_link_libraries( dbconverter PRIVATE libcockatrice_card + PRIVATE libcockatrice_interfaces PRIVATE libcockatrice_settings PRIVATE ${DB_CONVERTER_QT_MODULES} ) diff --git a/dbconverter/src/main.cpp b/dbconverter/src/main.cpp index f64392fa8..67748fa45 100644 --- a/dbconverter/src/main.cpp +++ b/dbconverter/src/main.cpp @@ -54,7 +54,6 @@ int main(int argc, char *argv[]) exit(0); } - settingsCache = new SettingsCache; CardDatabaseConverter *db = new CardDatabaseConverter; qInfo() << "---------------------------------------------"; diff --git a/dbconverter/src/main.h b/dbconverter/src/main.h index 1fa1335d0..7a5809b1b 100644 --- a/dbconverter/src/main.h +++ b/dbconverter/src/main.h @@ -3,10 +3,18 @@ #include #include +#include class CardDatabaseConverter : public CardDatabase { public: + explicit CardDatabaseConverter() + { + // Replace querier with one that ignores SettingsCache + delete querier; + querier = new CardDatabaseQuerier(this, this, new NoopCardPreferenceProvider()); + }; + LoadStatus loadCardDatabase(const QString &path) { return loader->loadCardDatabase(path); @@ -14,7 +22,7 @@ public: bool saveCardDatabase(const QString &fileName) { - CockatriceXml4Parser parser; + CockatriceXml4Parser parser(new NoopCardPreferenceProvider()); return parser.saveToFile(sets, cards, fileName); } }; diff --git a/dbconverter/src/mocks.cpp b/dbconverter/src/mocks.cpp index 6aa108e57..c54d2b9c2 100644 --- a/dbconverter/src/mocks.cpp +++ b/dbconverter/src/mocks.cpp @@ -46,12 +46,7 @@ QString SettingsCache::getSafeConfigFilePath(QString /* configEntry */, QString { return defaultPath; } -SettingsCache::SettingsCache() - : settings{new QSettings("global.ini", QSettings::IniFormat, this)}, shortcutsSettings{nullptr}, - cardDatabaseSettings{new CardDatabaseSettings("", this)}, serversSettings{nullptr}, messageSettings{nullptr}, - gameFiltersSettings{nullptr}, layoutsSettings{nullptr}, downloadSettings{nullptr} -{ -} + void SettingsCache::setUseTearOffMenus(bool /* _useTearOffMenus */) { } @@ -450,11 +445,4 @@ void SettingsCache::setRoundCardCorners(bool /* _roundCardCorners */) void CardPictureLoader::clearPixmapCache(CardInfoPtr /* card */) { -} - -SettingsCache *settingsCache; - -SettingsCache &SettingsCache::instance() -{ - return *settingsCache; -} +} \ No newline at end of file diff --git a/dbconverter/src/mocks.h b/dbconverter/src/mocks.h index 497f76e72..929092bd7 100644 --- a/dbconverter/src/mocks.h +++ b/dbconverter/src/mocks.h @@ -10,8 +10,9 @@ #define PICTURELOADER_H +#include "../../cockatrice/src/client/settings/cache_settings.h" + #include -#include #include extern SettingsCache *settingsCache; diff --git a/libcockatrice_card/CMakeLists.txt b/libcockatrice_card/CMakeLists.txt index 7217f7bff..857376163 100644 --- a/libcockatrice_card/CMakeLists.txt +++ b/libcockatrice_card/CMakeLists.txt @@ -51,6 +51,7 @@ target_include_directories( target_link_libraries( libcockatrice_card - PUBLIC libcockatrice_settings + PUBLIC libcockatrice_interfaces + PUBLIC libcockatrice_utility PUBLIC ${QT_CORE_MODULE} ) diff --git a/libcockatrice_card/libcockatrice/card/card_info.cpp b/libcockatrice_card/libcockatrice/card/card_info.cpp index 4646b3890..4f1280d74 100644 --- a/libcockatrice_card/libcockatrice/card/card_info.cpp +++ b/libcockatrice_card/libcockatrice/card/card_info.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include class CardRelation; diff --git a/libcockatrice_card/libcockatrice/card/database/card_database.cpp b/libcockatrice_card/libcockatrice/card/database/card_database.cpp index 6ff5fe02c..7e23b4663 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database.cpp +++ b/libcockatrice_card/libcockatrice/card/database/card_database.cpp @@ -9,26 +9,28 @@ #include #include #include -#include #include #include -#include #include -CardDatabase::CardDatabase(QObject *parent) : QObject(parent), loadStatus(NotLoaded) +CardDatabase::CardDatabase(QObject *parent, + ICardPreferenceProvider *prefs, + ICardDatabasePathProvider *pathProvider, + ICardSetPriorityController *_setPriorityController) + : QObject(parent), setPriorityController(_setPriorityController), loadStatus(NotLoaded) { qRegisterMetaType("CardInfoPtr"); qRegisterMetaType("CardSetPtr"); // create loader and wire it up - loader = new CardDatabaseLoader(this, this); + loader = new CardDatabaseLoader(this, this, pathProvider, prefs); // re-emit loader signals (so other code doesn't need to know about internals) connect(loader, &CardDatabaseLoader::loadingFinished, this, &CardDatabase::cardDatabaseLoadingFinished); connect(loader, &CardDatabaseLoader::loadingFailed, this, &CardDatabase::cardDatabaseLoadingFailed); connect(loader, &CardDatabaseLoader::newSetsFound, this, &CardDatabase::cardDatabaseNewSetsFound); connect(loader, &CardDatabaseLoader::allNewSetsEnabled, this, &CardDatabase::cardDatabaseAllNewSetsEnabled); - querier = new CardDatabaseQuerier(this, this); + querier = new CardDatabaseQuerier(this, this, prefs); } CardDatabase::~CardDatabase() @@ -138,7 +140,7 @@ CardSetPtr CardDatabase::getSet(const QString &setName) if (sets.contains(setName)) { return sets.value(setName); } else { - CardSetPtr newSet = CardSet::newInstance(setName); + CardSetPtr newSet = CardSet::newInstance(setPriorityController, setName); sets.insert(setName, newSet); return newSet; } diff --git a/libcockatrice_card/libcockatrice/card/database/card_database.h b/libcockatrice_card/libcockatrice/card/database/card_database.h index 8c7a78ffe..4b2769fcb 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database.h +++ b/libcockatrice_card/libcockatrice/card/database/card_database.h @@ -1,7 +1,8 @@ /** * @file card_database.h * @ingroup CardDatabase - * @brief The CardDatabase is responsible for holding the card and set maps. + * @brief The CardDatabase is responsible for holding the card and set maps, managing card additions/removals, + * and providing access to sets and card querying via CardDatabaseQuerier. */ #ifndef CARDDATABASE_H @@ -18,85 +19,173 @@ #include #include #include +#include #include #include inline Q_LOGGING_CATEGORY(CardDatabaseLog, "card_database"); +/** + * @class CardDatabase + * @ingroup CardDatabase + * @brief Core in-memory container for card and set data. + * + * Responsible for maintaining CardInfo objects, CardSet objects, and + * providing access to CardDatabaseQuerier for query operations. + * Handles addition, removal, and clearing of cards and sets. + */ class CardDatabase : public QObject { Q_OBJECT + protected: - /* - * The cards, indexed by name. - */ + /// Controller to determine set priority when choosing preferred printings. + ICardSetPriorityController *setPriorityController; + + /// Cards indexed by exact name CardNameMap cards; - /** - * The cards, indexed by their simple name. - */ + /// Cards indexed by simplified name (normalized) CardNameMap simpleNameCards; - /* - * The sets, indexed by short name. - */ + /// Sets indexed by short name SetNameMap sets; - // loader responsible for file discovery & parsing + /// Loader responsible for file discovery and parsing CardDatabaseLoader *loader; + /// Current load status of the database LoadStatus loadStatus; + /// Querier for higher-level card lookups CardDatabaseQuerier *querier; private: + /** + * @brief Check for sets that are unknown and emit signals if needed. + */ void checkUnknownSets(); + + /** + * @brief Refreshes the cached reverse-related cards for all cards. + */ void refreshCachedReverseRelatedCards(); + /// Mutexes for thread safety QBasicMutex *clearDatabaseMutex = new QBasicMutex(), *addCardMutex = new QBasicMutex(), *removeCardMutex = new QBasicMutex(); public: - explicit CardDatabase(QObject *parent = nullptr); + /** + * @brief Constructs a new CardDatabase instance. + * @param parent QObject parent. + * @param prefs Optional card preference provider. + * @param pathProvider Optional database path provider. + * @param setPriorityController Optional controller for set priority. + */ + explicit CardDatabase(QObject *parent = nullptr, + ICardPreferenceProvider *prefs = nullptr, + ICardDatabasePathProvider *pathProvider = nullptr, + ICardSetPriorityController *setPriorityController = nullptr); + + /** @brief Destructor clears all internal data. */ ~CardDatabase() override; + /** + * @brief Removes a card from the database. + * @param card Pointer to the card to remove. + */ void removeCard(CardInfoPtr card); + + /** @brief Clears all cards, sets, and internal state. */ void clear(); + /** @brief Returns the map of cards by name. */ const CardNameMap &getCardList() const { return cards; } + + /** + * @brief Retrieves a set by short name, creating a new one if missing. + * @param setName Short name of the set. + * @return Pointer to the CardSet. + */ CardSetPtr getSet(const QString &setName); + + /** @brief Returns a list of all sets in the database. */ CardSetList getSetList() const; + + /** @brief Returns the current load status. */ LoadStatus getLoadStatus() const { return loadStatus; } + + /** @brief Returns the querier for performing card lookups. */ CardDatabaseQuerier *query() const { return querier; } + + /** @brief Enables all unknown sets in the database. */ void enableAllUnknownSets(); + + /** @brief Marks all sets as known. */ void markAllSetsAsKnown(); + + /** @brief Notifies listeners that enabled sets changed. */ void notifyEnabledSetsChanged(); public slots: + /** + * @brief Adds a card to the database. + * @param card CardInfoPtr to add. + */ void addCard(CardInfoPtr card); + + /** + * @brief Adds a set to the database. + * @param set Pointer to CardSet to add. + */ void addSet(CardSetPtr set); + + /** @brief Loads card databases from configured paths. */ void loadCardDatabases(); + + /** @brief Saves custom tokens to file. + * @return True if successful. + */ bool saveCustomTokensToFile(); + signals: + /** @brief Emitted when the card database has finished loading successfully. */ void cardDatabaseLoadingFinished(); + + /** @brief Emitted when the card database fails to load. */ void cardDatabaseLoadingFailed(); + + /** + * @brief Emitted when new sets are found. + * @param numUnknownSets Number of unknown sets. + * @param unknownSetsNames Names of unknown sets. + */ void cardDatabaseNewSetsFound(int numUnknownSets, QStringList unknownSetsNames); + + /** @brief Emitted when all new sets have been enabled. */ void cardDatabaseAllNewSetsEnabled(); + + /** @brief Emitted when enabled sets have changed. */ void cardDatabaseEnabledSetsChanged(); + + /** @brief Emitted when a new card is added. */ void cardAdded(CardInfoPtr card); + + /** @brief Emitted when a card is removed. */ void cardRemoved(CardInfoPtr card); friend class CardDatabaseLoader; friend class CardDatabaseQuerier; }; -#endif +#endif // CARDDATABASE_H diff --git a/libcockatrice_card/libcockatrice/card/database/card_database_loader.cpp b/libcockatrice_card/libcockatrice/card/database/card_database_loader.cpp index b1300e2a2..f56f6a0b5 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database_loader.cpp +++ b/libcockatrice_card/libcockatrice/card/database/card_database_loader.cpp @@ -8,12 +8,15 @@ #include #include #include -#include -CardDatabaseLoader::CardDatabaseLoader(QObject *parent, CardDatabase *db) : QObject(parent), database(db) +CardDatabaseLoader::CardDatabaseLoader(QObject *parent, + CardDatabase *db, + ICardDatabasePathProvider *_pathProvider, + ICardPreferenceProvider *_preferenceProvider) + : QObject(parent), database(db), pathProvider(_pathProvider) { // instantiate available parsers here and connect them to the database - availableParsers << new CockatriceXml4Parser; + availableParsers << new CockatriceXml4Parser(_preferenceProvider); availableParsers << new CockatriceXml3Parser; for (auto *p : availableParsers) { @@ -23,7 +26,7 @@ CardDatabaseLoader::CardDatabaseLoader(QObject *parent, CardDatabase *db) : QObj } // when SettingsCache's path changes, trigger reloads - connect(&SettingsCache::instance(), &SettingsCache::cardDatabasePathChanged, this, + connect(pathProvider, &ICardDatabasePathProvider::cardDatabasePathChanged, this, &CardDatabaseLoader::loadCardDatabases); } @@ -83,10 +86,9 @@ LoadStatus CardDatabaseLoader::loadCardDatabases() database->clear(); // remove old db - LoadStatus loadStatus = - loadCardDatabase(SettingsCache::instance().getCardDatabasePath()); // load main card database - loadCardDatabase(SettingsCache::instance().getTokenDatabasePath()); // load tokens database - loadCardDatabase(SettingsCache::instance().getSpoilerCardDatabasePath()); // load spoilers database + LoadStatus loadStatus = loadCardDatabase(pathProvider->getCardDatabasePath()); // load main card database + loadCardDatabase(pathProvider->getTokenDatabasePath()); // load tokens database + loadCardDatabase(pathProvider->getSpoilerCardDatabasePath()); // load spoilers database // find all custom card databases, recursively & following symlinks // then load them alphabetically @@ -117,7 +119,7 @@ LoadStatus CardDatabaseLoader::loadCardDatabases() QStringList CardDatabaseLoader::collectCustomDatabasePaths() const { - QDirIterator it(SettingsCache::instance().getCustomCardDatabasePath(), {"*.xml"}, QDir::Files, + QDirIterator it(pathProvider->getCustomCardDatabasePath(), {"*.xml"}, QDir::Files, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks); QStringList paths; @@ -134,7 +136,7 @@ bool CardDatabaseLoader::saveCustomTokensToFile() return false; } - QString fileName = SettingsCache::instance().getCustomCardDatabasePath() + "/" + CardSet::TOKENS_SETNAME + ".xml"; + QString fileName = pathProvider->getCustomCardDatabasePath() + "/" + CardSet::TOKENS_SETNAME + ".xml"; SetNameMap tmpSets; CardSetPtr customTokensSet = database->getSet(CardSet::TOKENS_SETNAME); diff --git a/libcockatrice_card/libcockatrice/card/database/card_database_loader.h b/libcockatrice_card/libcockatrice/card/database/card_database_loader.h index 030ca56d5..7bf02cc9a 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database_loader.h +++ b/libcockatrice_card/libcockatrice/card/database/card_database_loader.h @@ -1,7 +1,10 @@ /** * @file card_database_loader.h * @ingroup CardDatabase - * @brief The CardDatabaseLoader is responsible for populating the card database from files on disk. + * @brief The CardDatabaseLoader is responsible for discovering, loading, and saving card databases from files on disk. + * + * This class interacts with available parsers to populate a CardDatabase instance. It also handles + * loading main, token, spoiler, and custom card databases. */ #ifndef COCKATRICE_CARD_DATABASE_LOADER_H @@ -11,6 +14,8 @@ #include #include #include +#include +#include inline Q_LOGGING_CATEGORY(CardDatabaseLoadingLog, "card_database.loading"); inline Q_LOGGING_CATEGORY(CardDatabaseLoadingSuccessOrFailureLog, "card_database.loading.success_or_failure"); @@ -18,46 +23,111 @@ inline Q_LOGGING_CATEGORY(CardDatabaseLoadingSuccessOrFailureLog, "card_database class CardDatabase; class ICardDatabaseParser; +/** + * @enum LoadStatus + * @brief Represents the result of attempting to load a card database. + */ enum LoadStatus { - Ok, - VersionTooOld, - Invalid, - NotLoaded, - FileError, - NoCards + Ok, /**< Database loaded successfully. */ + VersionTooOld, /**< Database version is too old to load. */ + Invalid, /**< Database is invalid or unparsable. */ + NotLoaded, /**< Database has not been loaded. */ + FileError, /**< Error opening or reading the file. */ + NoCards /**< Database contains no cards. */ }; +/** + * @class CardDatabaseLoader + * @ingroup CardDatabase + * @brief Handles loading card databases from disk and saving custom tokens. + * + * This class is responsible for: + * - Discovering configured card database paths. + * - Loading main, token, spoiler, and custom databases. + * - Populating a CardDatabase instance using connected parsers. + * - Emitting signals about loading progress and new sets. + */ class CardDatabaseLoader : public QObject { Q_OBJECT public: - explicit CardDatabaseLoader(QObject *parent, CardDatabase *db); + /** + * @brief Constructs a CardDatabaseLoader. + * @param parent QObject parent. + * @param db Pointer to the CardDatabase to populate (non-owning). + * @param pathProvider Provider for card database file paths. + * @param preferenceProvider Optional card preference provider for pinned printings. + */ + explicit CardDatabaseLoader(QObject *parent, + CardDatabase *db, + ICardDatabasePathProvider *pathProvider, + ICardPreferenceProvider *preferenceProvider); + + /** @brief Destructor cleans up allocated parsers. */ ~CardDatabaseLoader() override; public slots: - LoadStatus loadCardDatabases(); // discover & load the configured databases - LoadStatus loadCardDatabase(const QString &path); // load a single file - bool saveCustomTokensToFile(); // write tokens to custom DB path + /** + * @brief Loads all configured card databases. + * @return Status of the main database load. + */ + LoadStatus loadCardDatabases(); + + /** + * @brief Loads a single card database file. + * @param path Path to the database file. + * @return LoadStatus indicating success or failure. + */ + LoadStatus loadCardDatabase(const QString &path); + + /** + * @brief Saves custom tokens to the user-defined custom database path. + * @return True if the save was successful. + */ + bool saveCustomTokensToFile(); signals: + /** @brief Emitted when loading starts. */ void loadingStarted(); + + /** @brief Emitted when loading finishes successfully. */ void loadingFinished(); + + /** @brief Emitted when loading fails. */ void loadingFailed(); + + /** + * @brief Emitted when new sets are discovered during loading. + * @param numSets Number of new sets. + * @param setNames Names of the discovered sets. + */ void newSetsFound(int numSets, const QStringList &setNames); + + /** @brief Emitted when all newly discovered sets have been enabled. */ void allNewSetsEnabled(); private: - LoadStatus loadFromFile(const QString &fileName); // internal helper + /** + * @brief Loads a database from a single file using the available parsers. + * @param fileName Path to the database file. + * @return LoadStatus indicating success or failure. + */ + LoadStatus loadFromFile(const QString &fileName); + + /** + * @brief Collects custom card database paths recursively. + * @return Sorted list of file paths to custom databases. + */ QStringList collectCustomDatabasePaths() const; - CardDatabase *database; // non-owning pointer to the container +private: + CardDatabase *database; /**< Non-owning pointer to the target CardDatabase. */ + ICardDatabasePathProvider *pathProvider; /**< Pointer to the path provider. */ + QList availableParsers; /**< List of available parsers for different formats. */ - // parsers - QList availableParsers; - - QBasicMutex *loadFromFileMutex = new QBasicMutex(); - QBasicMutex *reloadDatabaseMutex = new QBasicMutex(); + QBasicMutex *loadFromFileMutex = new QBasicMutex(); /**< Mutex for single-file loading. */ + QBasicMutex *reloadDatabaseMutex = new QBasicMutex(); /**< Mutex for reloading entire database. */ }; #endif // COCKATRICE_CARD_DATABASE_LOADER_H diff --git a/libcockatrice_card/libcockatrice/card/database/card_database_manager.cpp b/libcockatrice_card/libcockatrice/card/database/card_database_manager.cpp index 4ffe0cc70..614b4a7f8 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database_manager.cpp +++ b/libcockatrice_card/libcockatrice/card/database/card_database_manager.cpp @@ -1,8 +1,31 @@ #include "card_database_manager.h" +#include +#include +#include + +ICardPreferenceProvider *CardDatabaseManager::cardPreferenceProvider = new NoopCardPreferenceProvider(); +ICardDatabasePathProvider *CardDatabaseManager::pathProvider = new NoopCardDatabasePathProvider(); +ICardSetPriorityController *CardDatabaseManager::setPriorityController = new NoopCardSetPriorityController(); + +void CardDatabaseManager::setCardPreferenceProvider(ICardPreferenceProvider *provider) +{ + cardPreferenceProvider = provider; +} + +void CardDatabaseManager::setCardDatabasePathProvider(ICardDatabasePathProvider *provider) +{ + pathProvider = provider; +} + +void CardDatabaseManager::setCardSetPriorityController(ICardSetPriorityController *controller) +{ + setPriorityController = controller; +} + CardDatabase *CardDatabaseManager::getInstance() { - static CardDatabase instance; // Created only once, on first access + static CardDatabase instance(nullptr, cardPreferenceProvider, pathProvider, setPriorityController); return &instance; } diff --git a/libcockatrice_card/libcockatrice/card/database/card_database_manager.h b/libcockatrice_card/libcockatrice/card/database/card_database_manager.h index 1962460fc..58a744fbb 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database_manager.h +++ b/libcockatrice_card/libcockatrice/card/database/card_database_manager.h @@ -1,29 +1,80 @@ -/** - * @file card_database_manager.h - * @ingroup CardDatabase - * @brief The CardDatabaseManager is responsible for managing the global database singleton. - */ - #ifndef CARD_DATABASE_ACCESSOR_H #define CARD_DATABASE_ACCESSOR_H #pragma once #include "card_database.h" +/** + * @class CardDatabaseManager + * @ingroup CardDatabase + * @brief The CardDatabaseManager is responsible for managing the global CardDatabase singleton. + * + * This class provides a static interface for accessing the global CardDatabase instance + * and its CardDatabaseQuerier. It also allows the configuration of optional providers: + * - ICardPreferenceProvider + * - ICardDatabasePathProvider + * - ICardSetPriorityController + * + * Only a single instance of CardDatabase exists, enforced via a private constructor and + * deleted copy/move operations. + */ class CardDatabaseManager { public: - // Delete copy constructor and assignment operator to enforce singleton + /** @brief Deleted copy constructor to enforce singleton. */ CardDatabaseManager(const CardDatabaseManager &) = delete; + + /** @brief Deleted assignment operator to enforce singleton. */ CardDatabaseManager &operator=(const CardDatabaseManager &) = delete; - // Static method to access the singleton instance + /** + * @brief Sets the card preference provider. + * @param provider Pointer to an ICardPreferenceProvider. + * @note Must be called before the first call to getInstance(). + */ + static void setCardPreferenceProvider(ICardPreferenceProvider *provider); + + /** + * @brief Sets the card database path provider. + * @param provider Pointer to an ICardDatabasePathProvider. + * @note Must be called before the first call to getInstance(). + */ + static void setCardDatabasePathProvider(ICardDatabasePathProvider *provider); + + /** + * @brief Sets the card set priority controller. + * @param controller Pointer to an ICardSetPriorityController. + * @note Must be called before the first call to getInstance(). + */ + static void setCardSetPriorityController(ICardSetPriorityController *controller); + + /** + * @brief Returns the singleton CardDatabase instance. + * @return Pointer to the global CardDatabase. + */ static CardDatabase *getInstance(); + + /** + * @brief Returns the CardDatabaseQuerier of the singleton database. + * @return Pointer to CardDatabaseQuerier. + */ static CardDatabaseQuerier *query(); private: - CardDatabaseManager() = default; // Private constructor + /** @brief Private default constructor to enforce singleton. */ + CardDatabaseManager() = default; + + /** @brief Private destructor. */ ~CardDatabaseManager() = default; + + /// Static card preference provider pointer (default: Noop) + static ICardPreferenceProvider *cardPreferenceProvider; + + /// Static path provider pointer (default: Noop) + static ICardDatabasePathProvider *pathProvider; + + /// Static set priority controller pointer (default: Noop) + static ICardSetPriorityController *setPriorityController; }; #endif // CARD_DATABASE_ACCESSOR_H diff --git a/libcockatrice_card/libcockatrice/card/database/card_database_querier.cpp b/libcockatrice_card/libcockatrice/card/database/card_database_querier.cpp index f422c51f9..65999e590 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database_querier.cpp +++ b/libcockatrice_card/libcockatrice/card/database/card_database_querier.cpp @@ -7,7 +7,10 @@ #include -CardDatabaseQuerier::CardDatabaseQuerier(QObject *_parent, const CardDatabase *_db) : QObject(_parent), db(_db) +CardDatabaseQuerier::CardDatabaseQuerier(QObject *_parent, + const CardDatabase *_db, + const ICardPreferenceProvider *prefs) + : QObject(_parent), db(_db), prefs(prefs) { } @@ -204,6 +207,17 @@ PrintingInfo CardDatabaseQuerier::getSpecificPrinting(const QString &cardName, return PrintingInfo(nullptr); } +/** + * Gets the card representing the preferred printing of the cardInfo + * + * @param cardName The cardName to find the preferred card and printing for + * @return A specific printing of a card + */ +ExactCard CardDatabaseQuerier::getPreferredCard(const QString &cardName) const +{ + return getPreferredCard(getCardInfo(cardName)); +} + /** * Gets the card representing the preferred printing of the cardInfo * @@ -236,6 +250,12 @@ PrintingInfo CardDatabaseQuerier::getPreferredPrinting(const CardInfoPtr &cardIn return PrintingInfo(nullptr); } + const auto &pinnedPrintingProviderId = prefs->getCardPreferenceOverride(cardInfo->getName()); + + if (!pinnedPrintingProviderId.isEmpty()) { + return getSpecificPrinting({cardInfo->getName(), pinnedPrintingProviderId}); + } + SetToPrintingsMap setMap = cardInfo->getSets(); if (setMap.empty()) { return PrintingInfo(nullptr); diff --git a/libcockatrice_card/libcockatrice/card/database/card_database_querier.h b/libcockatrice_card/libcockatrice/card/database/card_database_querier.h index cb440706b..fcef3fea1 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database_querier.h +++ b/libcockatrice_card/libcockatrice/card/database/card_database_querier.h @@ -1,9 +1,3 @@ -/** - * @file card_database_querier.h - * @ingroup CardDatabase - * @brief The CardDatabaseQuerier is responsible for querying the database and returning data. - */ - #ifndef COCKATRICE_CARD_DATABASE_QUERIER_H #define COCKATRICE_CARD_DATABASE_QUERIER_H @@ -11,51 +5,219 @@ #include "../printing/exact_card.h" #include +#include #include class CardDatabase; + +/** + * @class CardDatabaseQuerier + * @ingroup CardDatabase + * @brief Provides lookup and convenience functions for querying cards and their printings. + * + * The CardDatabaseQuerier class offers various lookup helpers for retrieving card information + * (e.g., CardInfoPtr, ExactCard, and PrintingInfo) from a CardDatabase. It also applies user + * printing preferences via ICardPreferenceProvider when determining preferred printings. + */ class CardDatabaseQuerier : public QObject { Q_OBJECT public: - explicit CardDatabaseQuerier(QObject *parent, const CardDatabase *db); + /** + * @brief Constructs a CardDatabaseQuerier. + * + * @param parent Parent QObject. + * @param db Pointer to the CardDatabase used for lookups. + * @param prefs Pointer to card preference provider which supplies user-preference for printings. + */ + explicit CardDatabaseQuerier(QObject *parent, const CardDatabase *db, const ICardPreferenceProvider *prefs); + /** + * @brief Retrieves a card by its exact name. + * + * @param cardName Exact card name. + * @return A CardInfoPtr, or null if no matching card exists. + */ [[nodiscard]] CardInfoPtr getCardInfo(const QString &cardName) const; + + /** + * @brief Retrieves multiple cards by their exact names. + * + * Failed lookups are skipped and not included in the result. + * + * @param cardNames List of exact card names. + * @return List of CardInfoPtr objects for which a match was found. + */ [[nodiscard]] QList getCardInfos(const QStringList &cardNames) const; - /* - * Get a card by its simple name. The name will be simplified in this - * function, so you don't need to simplify it beforehand. + /** + * @brief Retrieves a card using simplified name matching. + * + * The name is automatically normalized, so callers do not need to simplify it. + * + * @param cardName A (possibly simplified or misspelled) card name. + * @return A CardInfoPtr, or null if not found. */ [[nodiscard]] CardInfoPtr getCardBySimpleName(const QString &cardName) const; - [[nodiscard]] ExactCard guessCard(const CardRef &cardRef) const; + /** + * @brief Looks up a card using exact name first, then simplified matching as fallback. + * + * @param name Raw card name input. + * @return The best-match CardInfoPtr, or null if no match is found. + */ + [[nodiscard]] CardInfoPtr lookupCardByName(const QString &name) const; + + /** + * @brief Converts a CardRef into an ExactCard. + * + * If the providerId is empty, the preferred printing is used. + * If providerId exists but cannot be found, an ExactCard with an empty PrintingInfo is returned. + * + * @param cardRef Card reference with name and optional providerId. + * @return The resolved ExactCard, or empty if no card was found. + */ [[nodiscard]] ExactCard getCard(const CardRef &cardRef) const; + + /** + * @brief Resolves multiple CardRefs into ExactCards. + * + * Failed entries are not included in the result. + * + * @param cardRefs List of card references. + * @return List of successfully resolved ExactCards. + */ [[nodiscard]] QList getCards(const QList &cardRefs) const; + /** + * @brief Attempts a more flexible card lookup using both simple name matching and CardRef rules. + * + * If providerId is missing, uses preferred printing. If lookup fails, attempts simplified name. + * + * @param cardRef Card reference to resolve. + * @return The best-guess ExactCard, or empty if unresolved. + */ + [[nodiscard]] ExactCard guessCard(const CardRef &cardRef) const; + + /** + * @brief Returns a random card from the database using the preferred printing. + * + * @return A random ExactCard, or empty if the database is empty. + */ [[nodiscard]] ExactCard getRandomCard() const; + + /** + * @brief Returns a printing of a card from the same set as another given printing when possible. + * + * If no matching printing exists, falls back to a standard lookup. + * + * @param cardName Card to retrieve. + * @param otherPrinting Printing to match the set against. + * @return Matching ExactCard if found, otherwise fallback ExactCard. + */ [[nodiscard]] ExactCard getCardFromSameSet(const QString &cardName, const PrintingInfo &otherPrinting) const; - [[nodiscard]] ExactCard getPreferredCard(const CardInfoPtr &card) const; + /** + * @brief Returns the preferred printing of a card based on user preferences and set priority. + * + * @param cardName Name of the card. + * @return The preferred ExactCard. + */ + ExactCard getPreferredCard(const QString &cardName) const; + + /** + * @brief Returns the preferred printing of a card based on user preferences and set priority. + * + * @param cardInfo Card information object. + * @return The preferred ExactCard. + */ + [[nodiscard]] ExactCard getPreferredCard(const CardInfoPtr &cardInfo) const; + + /** + * @brief Checks whether the CardRef refers to the preferred printing. + * + * @param cardRef Card reference to test. + * @return True if providerId matches the preferred printing. + */ [[nodiscard]] bool isPreferredPrinting(const CardRef &cardRef) const; - [[nodiscard]] PrintingInfo getPreferredPrinting(const CardInfoPtr &card) const; + + /** + * @brief Returns the preferred printing for the given card name. + * + * @param cardName Card name. + * @return Preferred PrintingInfo, or empty if not found. + */ [[nodiscard]] PrintingInfo getPreferredPrinting(const QString &cardName) const; + + /** + * @brief Returns the preferred printing for the given card. + * + * @param cardInfo Card information object. + * @return Preferred PrintingInfo, or empty if not applicable. + */ + [[nodiscard]] PrintingInfo getPreferredPrinting(const CardInfoPtr &cardInfo) const; + + /** + * @brief Returns the providerId of the preferred printing. + * + * @param cardName Card name. + * @return ProviderId string for preferred printing. + */ [[nodiscard]] QString getPreferredPrintingProviderId(const QString &cardName) const; + /** + * @brief Retrieves a specific printing referenced by CardRef. + * + * @param cardRef Card reference including providerId. + * @return Matching PrintingInfo, or empty if not found. + */ [[nodiscard]] PrintingInfo getSpecificPrinting(const CardRef &cardRef) const; + + /** + * @brief Searches for a specific printing by set code and collector number. + * + * @param cardName Card name to search. + * @param setCode Set (short) code to match. + * @param collectorNumber Collector number. If empty, any printing from the set is returned. + * @return Matching PrintingInfo, or empty if not found. + */ [[nodiscard]] PrintingInfo getSpecificPrinting(const QString &cardName, const QString &setCode, const QString &collectorNumber) const; + + /** + * @brief Searches for a printing that matches a given providerId. + * + * @param card Card to search. + * @param providerId Provider identifier to match. + * @return Matching PrintingInfo, or empty if not found. + */ [[nodiscard]] PrintingInfo findPrintingWithId(const CardInfoPtr &card, const QString &providerId) const; + /** + * @brief Returns a list of all main card types present in the database. + * + * @return List of main card type strings. + */ [[nodiscard]] QStringList getAllMainCardTypes() const; + + /** + * @brief Returns a mapping of main card types to their occurrence counts. + * + * @return Map of main card type to count. + */ [[nodiscard]] QMap getAllMainCardTypesWithCount() const; + + /** + * @brief Returns a mapping of card subtypes to their occurrence counts. + * + * @return Map of subtype string to count. + */ [[nodiscard]] QMap getAllSubCardTypesWithCount() const; private: - const CardDatabase *db; - - CardInfoPtr lookupCardByName(const QString &name) const; + const CardDatabase *db; //!< Card database used for all lookups. + const ICardPreferenceProvider *prefs; //!< Preference provider for preferred printings. }; #endif // COCKATRICE_CARD_DATABASE_QUERIER_H diff --git a/libcockatrice_card/libcockatrice/card/database/parser/card_database_parser.cpp b/libcockatrice_card/libcockatrice/card/database/parser/card_database_parser.cpp index ac1372f7f..e9686f816 100644 --- a/libcockatrice_card/libcockatrice/card/database/parser/card_database_parser.cpp +++ b/libcockatrice_card/libcockatrice/card/database/parser/card_database_parser.cpp @@ -1,5 +1,7 @@ #include "card_database_parser.h" +#include + SetNameMap ICardDatabaseParser::sets; void ICardDatabaseParser::clearSetlist() @@ -17,7 +19,7 @@ CardSetPtr ICardDatabaseParser::internalAddSet(const QString &setName, return sets.value(setName); } - CardSetPtr newSet = CardSet::newInstance(setName); + CardSetPtr newSet = CardSet::newInstance(new NoopCardSetPriorityController(), setName); newSet->setLongName(longName); newSet->setSetType(setType); newSet->setReleaseDate(releaseDate); diff --git a/libcockatrice_card/libcockatrice/card/database/parser/card_database_parser.h b/libcockatrice_card/libcockatrice/card/database/parser/card_database_parser.h index c67e3dafe..35012dbc5 100644 --- a/libcockatrice_card/libcockatrice/card/database/parser/card_database_parser.h +++ b/libcockatrice_card/libcockatrice/card/database/parser/card_database_parser.h @@ -1,9 +1,3 @@ -/** - * @file card_database_parser.h - * @ingroup CardDatabaseParsers - * @brief The ICardDatabaseParser defines the base interface for parser sub-classes. - */ - #ifndef CARDDATABASE_PARSER_H #define CARDDATABASE_PARSER_H @@ -14,35 +8,76 @@ #define COCKATRICE_XML_XSI_NAMESPACE "http://www.w3.org/2001/XMLSchema-instance" +/** + * @class ICardDatabaseParser + * @ingroup CardDatabase + * @brief Defines the base parser interface (ICardDatabaseParser) for all card database parsers. + * + * Provides methods for checking file compatibility, parsing, and saving card databases. + * Also provides shared access to the global set list for cross-referencing. + */ class ICardDatabaseParser : public QObject { Q_OBJECT public: ~ICardDatabaseParser() override = default; + /** + * @brief Checks whether this parser can parse the given file. + * @param name File name (used for extension checks). + * @param device QIODevice representing the file content. + * @return true if the parser can handle this file. + */ virtual bool getCanParseFile(const QString &name, QIODevice &device) = 0; + + /** + * @brief Parses a database file and emits addCard/addSet signals. + * @param device QIODevice representing the file content. + */ virtual void parseFile(QIODevice &device) = 0; + + /** + * @brief Saves card and set data to a file. + * @param sets Map of sets to save. + * @param cards Map of cards to save. + * @param fileName Target file path. + * @param sourceUrl Optional source URL of the database. + * @param sourceVersion Optional version string of the source. + * @return true if save succeeded. + */ virtual bool saveToFile(SetNameMap sets, CardNameMap cards, const QString &fileName, const QString &sourceUrl = "unknown", const QString &sourceVersion = "unknown") = 0; + + /** @brief Clears the cached global set list. */ static void clearSetlist(); protected: - /* - * A cached list of the available sets, needed to cross-reference sets from cards. - * Shared between all parsers - */ + /** @brief Cached global list of sets shared between all parsers. */ static SetNameMap sets; + /** + * @brief Internal helper to add a set to the global set cache. + * @param setName Short set name. + * @param longName Optional full name. + * @param setType Optional set type string. + * @param releaseDate Optional release date. + * @param priority Optional priority (fallback if not specified). + * @return Pointer to the added or existing CardSet instance. + */ CardSetPtr internalAddSet(const QString &setName, const QString &longName = "", const QString &setType = "", const QDate &releaseDate = QDate(), const CardSet::Priority priority = CardSet::PriorityFallback); + signals: + /** Emitted when a card is loaded from the database. */ void addCard(CardInfoPtr card); + + /** Emitted when a set is loaded from the database. */ void addSet(CardSetPtr set); }; diff --git a/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_3.h b/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_3.h index 50fa9c587..a727561ea 100644 --- a/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_3.h +++ b/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_3.h @@ -1,9 +1,3 @@ -/** - * @file cockatrice_xml_3.h - * @ingroup CardDatabaseParsers - * @brief The CockatriceXml3Parser is capable of parsing version 3 of the Cockatrice XML Schema. - */ - #ifndef COCKATRICE_XML3_H #define COCKATRICE_XML3_H @@ -14,14 +8,44 @@ inline Q_LOGGING_CATEGORY(CockatriceXml3Log, "cockatrice_xml.xml_3_parser"); +/** + * @class CockatriceXml3Parser + * @ingroup CardDatabase + * @brief Parses version 3 of the Cockatrice XML Schema. + * + * This parser reads a Cockatrice XML3 database and emits CardInfoPtr + * and CardSetPtr objects. All card properties are read individually. + * + * @note Differences from v4: + * - No block; properties are hardcoded (manacost, cmc, type, pt, loyalty, etc.). + * - No set priority field. + * - No support for rebalanced cards or preferences. + * - Related cards support only attach, exclude, variable, and count attributes. + */ class CockatriceXml3Parser : public ICardDatabaseParser { Q_OBJECT public: CockatriceXml3Parser() = default; ~CockatriceXml3Parser() override = default; + + /** + * @brief Determines if the parser can handle this file. + * @param name File name. + * @param device Open QIODevice containing the XML. + * @return True if the file is a Cockatrice XML3 database. + */ bool getCanParseFile(const QString &name, QIODevice &device) override; + + /** + * @brief Parse the XML database. + * @param device Open QIODevice positioned at start of file. + */ void parseFile(QIODevice &device) override; + + /** + * @brief Save sets and cards back to an XML3 file. + */ bool saveToFile(SetNameMap _sets, CardNameMap cards, const QString &fileName, @@ -29,8 +53,25 @@ public: const QString &sourceVersion = "unknown") override; private: + /** + * @brief Load all elements from the XML stream. + * @param xml The open QXmlStreamReader positioned at the element. + * Parses each node and emits addCard signals for each CardInfoPtr created. + */ void loadCardsFromXml(QXmlStreamReader &xml); + + /** + * @brief Load all elements from the XML stream. + * @param xml The open QXmlStreamReader positioned at the element. + * Parses each node and adds them to the shared set cache. + */ void loadSetsFromXml(QXmlStreamReader &xml); + + /** + * @brief Extracts the main card type from a full type string. + * @param type The full type string (e.g., "Legendary Artifact Creature - Golem") + * @return The primary type (e.g., "Creature"). + */ QString getMainCardType(QString &type); }; diff --git a/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_4.cpp b/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_4.cpp index 9c80014bf..92525d6e1 100644 --- a/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_4.cpp +++ b/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_4.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #define COCKATRICE_XML4_TAGNAME "cockatrice_carddatabase" @@ -14,6 +13,11 @@ #define COCKATRICE_XML4_SCHEMALOCATION \ "https://raw.githubusercontent.com/Cockatrice/Cockatrice/master/doc/carddatabase_v4/cards.xsd" +CockatriceXml4Parser::CockatriceXml4Parser(ICardPreferenceProvider *_cardPreferenceProvider) + : cardPreferenceProvider(_cardPreferenceProvider) +{ +} + bool CockatriceXml4Parser::getCanParseFile(const QString &fileName, QIODevice &device) { qCInfo(CockatriceXml4Log) << "Trying to parse: " << fileName; @@ -132,7 +136,7 @@ QVariantHash CockatriceXml4Parser::loadCardPropertiesFromXml(QXmlStreamReader &x void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml) { - bool includeRebalancedCards = SettingsCache::instance().getIncludeRebalancedCards(); + bool includeRebalancedCards = cardPreferenceProvider->getIncludeRebalancedCards(); while (!xml.atEnd()) { if (xml.readNext() == QXmlStreamReader::EndElement) { break; diff --git a/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_4.h b/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_4.h index f438f94b2..b83f6929e 100644 --- a/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_4.h +++ b/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_4.h @@ -1,9 +1,3 @@ -/** - * @file cockatrice_xml_4.h - * @ingroup CardDatabaseParsers - * @brief The CockatriceXml4Parser is capable of parsing version 4 of the Cockatrice XML Schema. - */ - #ifndef COCKATRICE_XML4_H #define COCKATRICE_XML4_H @@ -11,17 +5,50 @@ #include #include +#include inline Q_LOGGING_CATEGORY(CockatriceXml4Log, "cockatrice_xml.xml_4_parser"); +/** + * @class CockatriceXml4Parser + * @ingroup CardDatabase + * @brief Parses version 4 of the Cockatrice XML Schema. + * + * This parser reads a Cockatrice XML4 database and emits CardInfoPtr + * and CardSetPtr objects. Card properties are read inside blocks, + * making the parser more extensible and schema-compliant. + * + * @note Differences from v3: + * - Card properties are stored in blocks as a QVariantHash. + * - Sets can include a element. + * - Supports user preferences via ICardPreferenceProvider (e.g., skipping rebalanced cards). + * - Related cards support persistent relations and multiple attach types (e.g., transform). + * - More robust serialization; easier to extend schema in the future. + */ class CockatriceXml4Parser : public ICardDatabaseParser { Q_OBJECT public: - CockatriceXml4Parser() = default; + explicit CockatriceXml4Parser(ICardPreferenceProvider *cardPreferenceProvider); ~CockatriceXml4Parser() override = default; + + /** + * @brief Determines if the parser can handle this file. + * @param name File name. + * @param device Open QIODevice containing the XML. + * @return True if the file is a Cockatrice XML4 database. + */ bool getCanParseFile(const QString &name, QIODevice &device) override; + + /** + * @brief Parse the XML database. + * @param device Open QIODevice positioned at start of file. + */ void parseFile(QIODevice &device) override; + + /** + * @brief Save sets and cards back to an XML4 file. + */ bool saveToFile(SetNameMap _sets, CardNameMap cards, const QString &fileName, @@ -29,8 +56,27 @@ public: const QString &sourceVersion = "unknown") override; private: + ICardPreferenceProvider *cardPreferenceProvider; ///< Interface to handle user preferences + + /** + * @brief Loads a generic block from a element. + * @param xml The open QXmlStreamReader positioned at a element. + * @return A QVariantHash mapping property names to values. + */ QVariantHash loadCardPropertiesFromXml(QXmlStreamReader &xml); + + /** + * @brief Load all elements from the XML stream. + * @param xml The open QXmlStreamReader positioned at the element. + * Honors the user's preference regarding rebalanced cards. + */ void loadCardsFromXml(QXmlStreamReader &xml); + + /** + * @brief Load all elements from the XML stream. + * @param xml The open QXmlStreamReader positioned at the element. + * Parses nodes including priority information. + */ void loadSetsFromXml(QXmlStreamReader &xml); }; diff --git a/libcockatrice_card/libcockatrice/card/printing/exact_card.h b/libcockatrice_card/libcockatrice/card/printing/exact_card.h index e3d5d828a..b36233bd5 100644 --- a/libcockatrice_card/libcockatrice/card/printing/exact_card.h +++ b/libcockatrice_card/libcockatrice/card/printing/exact_card.h @@ -6,7 +6,14 @@ /** * @class ExactCard * @ingroup Cards - * @brief Identifies the card by its CardInfoPtr along with its exact printing by its PrintingInfo. + * + * @brief Represents a specific card instance, defined by its CardInfo + * and a particular printing. + * + * An ExactCard identifies a card not only by its underlying CardInfoPtr + * (which may be null), but also by its PrintingInfo, which specifies the + * exact printing/variant. This allows distinguishing between different + * printings of the same logical card (e.g., different sets, promos, foils). */ class ExactCard { @@ -14,34 +21,97 @@ class ExactCard PrintingInfo printing; public: + /** + * @brief Constructs an empty ExactCard. + * + * The CardInfoPtr will be null, and PrintingInfo will be default-constructed. + * An empty ExactCard represents "no card". + */ ExactCard(); + + /** + * @brief Constructs an ExactCard from a card and printing. + * + * @param _card The card info pointer. May be null. + * @param _printing The printing details. Defaults to an empty PrintingInfo. + */ explicit ExactCard(const CardInfoPtr &_card, const PrintingInfo &_printing = PrintingInfo()); /** - * Gets the CardInfoPtr. Can be null. + * @brief Returns the underlying CardInfoPtr. + * + * May be null if the ExactCard is empty. */ - CardInfoPtr getCardPtr() const + [[nodiscard]] CardInfoPtr getCardPtr() const { return card; } /** - * Gets the PrintingInfo. Can be empty. + * @brief Returns the printing information associated with this card. + * + * May be empty if no specific printing was assigned. */ - PrintingInfo getPrinting() const + [[nodiscard]] PrintingInfo getPrinting() const { return printing; } + /** + * @brief Compares both card pointer and printing for equality. + * + * Two ExactCard objects are equal only if both their CardInfoPtr and + * PrintingInfo values are equal. + */ bool operator==(const ExactCard &other) const; - QString getName() const; - const CardInfo &getInfo() const; - QString getPixmapCacheKey() const; + /** + * @brief Convenience helper to get the card's display name. + * + * @return The card's name, or an empty string if the CardInfoPtr is null. + */ + [[nodiscard]] QString getName() const; - bool isEmpty() const; + /** + * @brief Returns a reference to the underlying CardInfo object. + * + * If the CardInfoPtr is null, returns a reference to a static empty CardInfo + * instance instead. This avoids null-dereferencing but means modifications + * to the returned object do not affect the ExactCard. + * + * @return A const reference to the CardInfo object. + */ + [[nodiscard]] const CardInfo &getInfo() const; + + /** + * @brief Generates a stable cache key for pixmap caching. + * + * The key includes the card's name and (if present) the printing UUID, + * allowing different printings of the same card to map to different cache entries. + */ + [[nodiscard]] QString getPixmapCacheKey() const; + + /** + * @brief Indicates whether this ExactCard represents no valid card. + * + * An ExactCard is considered empty if the CardInfoPtr is null or the + * card's name is empty. + */ + [[nodiscard]] bool isEmpty() const; + + /** + * @brief Boolean conversion indicating whether the card is valid (non-empty). + * + * @return true if not empty, false otherwise. + */ explicit operator bool() const; + /** + * @brief Emits the pixmapUpdated signal on the underlying CardInfo. + * + * Assumes CardInfoPtr is non-null. If called on an empty ExactCard, + * the behavior is undefined. + */ void emitPixmapUpdated() const; }; diff --git a/libcockatrice_card/libcockatrice/card/printing/printing_info.h b/libcockatrice_card/libcockatrice/card/printing/printing_info.h index c2afe983a..cacb98068 100644 --- a/libcockatrice_card/libcockatrice/card/printing/printing_info.h +++ b/libcockatrice_card/libcockatrice/card/printing/printing_info.h @@ -13,43 +13,102 @@ class PrintingInfo; using SetToPrintingsMap = QMap>; /** - * Info relating to a specific printing for a card. + * @class PrintingInfo + * @ingroup Cards + * + * @brief Represents metadata for a specific variation of a card within a set. + * + * A card can have multiple variations across sets. PrintingInfo associates + * a card with one such variation, and provides per-printing attributes + * such as identifiers or additional properties. + * + * Equality is defined as both the set and the property values being equal. */ class PrintingInfo { public: + /** + * @brief Constructs a PrintingInfo associated with a specific set. + * + * @param _set The set this printing belongs to (defaults to null). + */ explicit PrintingInfo(const CardSetPtr &_set = nullptr); + + /** + * @brief Destroys the PrintingInfo. + * + * Defaulted since no special cleanup is required. + */ ~PrintingInfo() = default; + /** + * @brief Equality operator. + * + * Two PrintingInfo objects are equal if they refer to the same set + * and contain the exact same property key/value pairs. + * + * @param other Another PrintingInfo to compare against. + * @return True if both set and properties are equal, otherwise false. + */ bool operator==(const PrintingInfo &other) const { return this->set == other.set && this->properties == other.properties; } private: - CardSetPtr set; - // per-printing card properties; - QVariantHash properties; + CardSetPtr set; ///< The set this variation belongs to. + QVariantHash properties; ///< Key-value store for variation-specific attributes. public: + /** + * @brief Returns the set this printing belongs to. + * + * @return Pointer to the associated CardSet. + */ CardSetPtr getSet() const { return set; } + /** + * @brief Returns the list of property names defined for this printing. + * + * @return List of keys stored in the properties map. + */ QStringList getProperties() const { return properties.keys(); } + + /** + * @brief Retrieves the value of a specific property. + * + * @param propertyName The key name of the property to query. + * @return The property value as a string, or an empty string if not set. + */ QString getProperty(const QString &propertyName) const { return properties.value(propertyName).toString(); } + + /** + * @brief Sets or updates the value of a specific property. + * + * If the property already exists, its value is replaced. + * + * @param _name The name of the property. + * @param _value The string value to assign. + */ void setProperty(const QString &_name, const QString &_value) { properties.insert(_name, _value); } + /** + * @brief Returns the providerID for this printing. + * + * @return A string representing the providerID. + */ QString getUuid() const; }; diff --git a/libcockatrice_card/libcockatrice/card/relation/card_relation.h b/libcockatrice_card/libcockatrice/card/relation/card_relation.h index 34f88e651..9ff704097 100644 --- a/libcockatrice_card/libcockatrice/card/relation/card_relation.h +++ b/libcockatrice_card/libcockatrice/card/relation/card_relation.h @@ -6,19 +6,43 @@ #include #include +/** + * @class CardRelation + * @ingroup Cards + * + * @brief Represents a relationship between two cards. + * + * CardRelation objects define directional relationships, such as: + * - One card attaching to another. + * - One card transforming into another. + * - One card creating another instance. + * + * Relations may also define metadata such as whether multiple creations + * are possible, whether the relation is persistent, and default counts. + */ class CardRelation : public QObject { Q_OBJECT private: - QString name; - CardRelationType attachType; - bool isCreateAllExclusion; - bool isVariableCount; - int defaultCount; - bool isPersistent; + QString name; ///< Name of the related card. + CardRelationType attachType; ///< Type of attachment. + bool isCreateAllExclusion; ///< True if this relation should exclude multiple creations in "create all" operations. + bool isVariableCount; ///< True if the number of creations is variable. + int defaultCount; ///< Default number of cards created or involved. + bool isPersistent; ///< True if this relation persists (i.e. is not destroyed) on zone change. public: + /** + * @brief Constructs a CardRelation with optional parameters. + * + * @param _name Name of the related card. + * @param _attachType Type of attachment. + * @param _isCreateAllExclusion Whether this relation excludes mass creation. + * @param _isVariableCount Whether the count is variable. + * @param _defaultCount Default number for creations or transformations. + * @param _isPersistent Whether the relation persists across zone changes. + */ explicit CardRelation(const QString &_name = QString(), CardRelationType _attachType = CardRelationType::DoesNotAttach, bool _isCreateAllExclusion = false, @@ -26,45 +50,104 @@ public: int _defaultCount = 1, bool _isPersistent = false); - const QString &getName() const + /** + * @brief Returns the name of the related card. + * + * @return Name as QString reference. + */ + [[nodiscard]] inline const QString &getName() const { return name; } - CardRelationType getAttachType() const + + /** + * @brief Returns the type of attachment. + * + * @return Enum value representing the attachment type. + */ + [[nodiscard]] CardRelationType getAttachType() const { return attachType; } - bool getDoesAttach() const + + /** + * @brief Returns true if the card is attached to another. + * + * @return True if attached, false otherwise. + */ + [[nodiscard]] bool getDoesAttach() const { return attachType != CardRelationType::DoesNotAttach; } - bool getDoesTransform() const + + /** + * @brief Returns true if this card transforms into another card. + * + * @return True if it transforms, false otherwise. + */ + [[nodiscard]] bool getDoesTransform() const { return attachType == CardRelationType::TransformInto; } - QString getAttachTypeAsString() const + /** + * @brief Returns a string description of the attachment type. + * + * @return "attach" for AttachTo, "transform" for TransformInto, empty string otherwise. + */ + [[nodiscard]] QString getAttachTypeAsString() const { return cardAttachTypeToString(attachType); } - bool getCanCreateAnother() const + /** + * @brief Determines whether another instance can be created. + * + * @return True if creation is allowed, false if constrained by attachment. + */ + [[nodiscard]] bool getCanCreateAnother() const { return !getDoesAttach(); } - bool getIsCreateAllExclusion() const + + /** + * @brief Returns whether this relation is excluded from "create all" operations. + * + * @return True if excluded, false otherwise. + */ + [[nodiscard]] bool getIsCreateAllExclusion() const { return isCreateAllExclusion; } - bool getIsVariable() const + + /** + * @brief Returns whether the relation count is variable. + * + * @return True if variable, false otherwise. + */ + [[nodiscard]] bool getIsVariable() const { return isVariableCount; } - int getDefaultCount() const + + /** + * @brief Returns the default count of related cards. + * + * @return Integer representing default number. + */ + [[nodiscard]] int getDefaultCount() const { return defaultCount; } - bool getIsPersistent() const + + /** + * @brief Returns whether the relation is persistent. + * + * Persistent relations are not destroyed on zone changes. + * + * @return True if persistent, false otherwise. + */ + [[nodiscard]] bool getIsPersistent() const { return isPersistent; } diff --git a/libcockatrice_card/libcockatrice/card/relation/card_relation_type.h b/libcockatrice_card/libcockatrice/card/relation/card_relation_type.h index c1ea49fa3..9bd85f3ac 100644 --- a/libcockatrice_card/libcockatrice/card/relation/card_relation_type.h +++ b/libcockatrice_card/libcockatrice/card/relation/card_relation_type.h @@ -4,7 +4,13 @@ #include /** - * Represents how a card relates to another (attach, transform, etc.). + * @enum CardRelationType + * @ingroup Cards + * @brief Types of attachments between cards. + * + * DoesNotAttach: No attachment is present. + * AttachTo: This card attaches to another card. + * TransformInto: This card transforms into another card. */ enum class CardRelationType { @@ -13,7 +19,7 @@ enum class CardRelationType TransformInto = 2, }; -// Optional helper +// Helper function to transform the enum values into human-readable strings inline QString cardAttachTypeToString(CardRelationType type) { switch (type) { diff --git a/libcockatrice_card/libcockatrice/card/set/card_set.cpp b/libcockatrice_card/libcockatrice/card/set/card_set.cpp index 6b4a8f764..20d0aced8 100644 --- a/libcockatrice_card/libcockatrice/card/set/card_set.cpp +++ b/libcockatrice_card/libcockatrice/card/set/card_set.cpp @@ -1,26 +1,30 @@ #include "card_set.h" -#include +#include +#include const char *CardSet::TOKENS_SETNAME = "TK"; -CardSet::CardSet(const QString &_shortName, +CardSet::CardSet(ICardSetPriorityController *_priorityController, + const QString &_shortName, const QString &_longName, const QString &_setType, const QDate &_releaseDate, const CardSet::Priority _priority) - : shortName(_shortName), longName(_longName), releaseDate(_releaseDate), setType(_setType), priority(_priority) + : priorityController(std::move(_priorityController)), shortName(_shortName), longName(_longName), + releaseDate(_releaseDate), setType(_setType), priority(_priority) { loadSetOptions(); } -CardSetPtr CardSet::newInstance(const QString &_shortName, +CardSetPtr CardSet::newInstance(ICardSetPriorityController *_priorityController, + const QString &_shortName, const QString &_longName, const QString &_setType, const QDate &_releaseDate, const Priority _priority) { - CardSetPtr ptr(new CardSet(_shortName, _longName, _setType, _releaseDate, _priority)); + CardSetPtr ptr(new CardSet(_priorityController, _shortName, _longName, _setType, _releaseDate, _priority)); // ptr->setSmartPointer(ptr); return ptr; } @@ -57,25 +61,25 @@ QString CardSet::getCorrectedShortName() const void CardSet::loadSetOptions() { - sortKey = SettingsCache::instance().cardDatabase().getSortKey(shortName); - enabled = SettingsCache::instance().cardDatabase().isEnabled(shortName); - isknown = SettingsCache::instance().cardDatabase().isKnown(shortName); + sortKey = priorityController->getSortKey(shortName); + enabled = priorityController->isEnabled(shortName); + isknown = priorityController->isKnown(shortName); } void CardSet::setSortKey(unsigned int _sortKey) { sortKey = _sortKey; - SettingsCache::instance().cardDatabase().setSortKey(shortName, _sortKey); + priorityController->setSortKey(shortName, _sortKey); } void CardSet::setEnabled(bool _enabled) { enabled = _enabled; - SettingsCache::instance().cardDatabase().setEnabled(shortName, _enabled); + priorityController->setEnabled(shortName, _enabled); } void CardSet::setIsKnown(bool _isknown) { isknown = _isknown; - SettingsCache::instance().cardDatabase().setIsKnown(shortName, _isknown); + priorityController->setIsKnown(shortName, _isknown); } \ No newline at end of file diff --git a/libcockatrice_card/libcockatrice/card/set/card_set.h b/libcockatrice_card/libcockatrice/card/set/card_set.h index fc4d42239..b3e35f2db 100644 --- a/libcockatrice_card/libcockatrice/card/set/card_set.h +++ b/libcockatrice_card/libcockatrice/card/set/card_set.h @@ -5,6 +5,7 @@ #include #include #include +#include class CardInfo; using CardInfoPtr = QSharedPointer; @@ -12,101 +13,215 @@ using CardInfoPtr = QSharedPointer; class CardSet; using CardSetPtr = QSharedPointer; +/** + * @class CardSet + * @ingroup Cards + * + * @brief A collection of cards grouped under a common identifier. + * + * A set serves both as metadata (identifier, title, category, release date, and priority) + * and as a container of all cards that belong to it. Each set can be enabled/disabled + * and marked as known/unknown depending on context. + * + * The class inherits from `QList`, so it can be iterated over directly + * to access its contents. + * + * Typical usage: + * - Query metadata such as identifier, category, or release date. + * - Enable or disable sets according to user preference. + * - Store and retrieve CardInfo objects associated with the set. + */ class CardSet : public QList { public: + /** + * @enum Priority + * @brief Defines relative ordering and importance of sets. + */ enum Priority { - PriorityFallback = 0, - PriorityPrimary = 10, - PrioritySecondary = 20, - PriorityReprint = 30, - PriorityOther = 40, - PriorityLowest = 100, + PriorityFallback = 0, ///< Used when no other priority is defined. + PriorityPrimary = 10, ///< Primary, canonical set. + PrioritySecondary = 20, ///< Secondary but relevant. + PriorityReprint = 30, ///< Duplicate or reprint category. + PriorityOther = 40, ///< Miscellaneous grouping. + PriorityLowest = 100, ///< Lowest sorting priority. }; - static const char *TOKENS_SETNAME; + static const char *TOKENS_SETNAME; ///< Reserved identifier for token-like sets. private: - QString shortName, longName; - unsigned int sortKey; - QDate releaseDate; - QString setType; - Priority priority; - bool enabled, isknown; + ICardSetPriorityController *priorityController; ///< Interface to the card set priority controller. + QString shortName; ///< Short identifier for the set. + QString longName; ///< Full name for the set. + unsigned int sortKey; ///< Custom numeric sort key. + QDate releaseDate; ///< Release date, may be empty if unknown. + QString setType; ///< Type/category label for the set. + Priority priority; ///< Priority level for sorting and relevance. + bool enabled; ///< Whether the set is active/enabled. + bool isknown; ///< Whether the set is considered known. public: - explicit CardSet(const QString &_shortName = QString(), + /** + * @brief Constructs a CardSet. + * + * @param priorityController Interface to a card set priority controller. + * @param _shortName Identifier string. + * @param _longName Full descriptive name. + * @param _setType Type/category string. + * @param _releaseDate Release date (optional). + * @param _priority Sorting/priority level. + */ + explicit CardSet(ICardSetPriorityController *priorityController, + const QString &_shortName = QString(), const QString &_longName = QString(), const QString &_setType = QString(), const QDate &_releaseDate = QDate(), const Priority _priority = PriorityFallback); - static CardSetPtr newInstance(const QString &_shortName = QString(), + /** + * @brief Creates and returns a new shared CardSet instance. + * + * @param priorityController Interface to a card set priority controller. + * @param _shortName Identifier string. + * @param _longName Full descriptive name. + * @param _setType Type/category string. + * @param _releaseDate Release date (optional). + * @param _priority Sorting/priority level. + * @return A shared pointer to the new CardSet. + */ + static CardSetPtr newInstance(ICardSetPriorityController *priorityController, + const QString &_shortName = QString(), const QString &_longName = QString(), const QString &_setType = QString(), const QDate &_releaseDate = QDate(), const Priority _priority = PriorityFallback); + /** + * @brief Returns a safe, sanitized version of the short name. + * + * Intended for file paths or identifiers where only certain + * characters are allowed. + * + * @return Sanitized short name. + */ QString getCorrectedShortName() const; + /// @return Short identifier of the set. QString getShortName() const { return shortName; } + + /// @return Descriptive name of the set. QString getLongName() const { return longName; } + + /// @return Type/category string of the set. QString getSetType() const { return setType; } + + /// @return Release date of the set. QDate getReleaseDate() const { return releaseDate; } + + /// @return Priority level of the set. Priority getPriority() const { return priority; } + /** + * @brief Sets the full name of the set. + * @param _longName New full name. + */ void setLongName(const QString &_longName) { longName = _longName; } + + /** + * @brief Sets the category/type of the set. + * @param _setType New category string. + */ void setSetType(const QString &_setType) { setType = _setType; } + + /** + * @brief Sets the release date of the set. + * @param _releaseDate New release date. + */ void setReleaseDate(const QDate &_releaseDate) { releaseDate = _releaseDate; } + + /** + * @brief Updates the priority of the set. + * @param _priority New priority value. + */ + void setPriority(const Priority _priority) { priority = _priority; } + /** + * @brief Loads state values (enabled, known, sort key) from configuration. + * + * Reads external configuration and applies it to this set. + */ void loadSetOptions(); + + /// @return The sort key assigned to this set. int getSortKey() const { return sortKey; } + + /** + * @brief Assigns a new sort key to this set. + * @param _sortKey The numeric key to use for sorting. + */ void setSortKey(unsigned int _sortKey); + /// @return True if the set is enabled. bool getEnabled() const { return enabled; } + + /** + * @brief Enables or disables the set. + * @param _enabled True to enable, false to disable. + */ void setEnabled(bool _enabled); + /// @return True if the set is considered known. bool getIsKnown() const { return isknown; } + + /** + * @brief Marks the set as known or unknown. + * @param _isknown True if known, false if unknown. + */ void setIsKnown(bool _isknown); + /** + * @brief Determines whether the set has incomplete metadata and should be ignored. + * + * @return True if the long name, type, and release date are all empty. + */ bool getIsKnownIgnored() const { return longName.length() + setType.length() + releaseDate.toString().length() == 0; diff --git a/libcockatrice_card/libcockatrice/card/set/card_set_list.h b/libcockatrice_card/libcockatrice/card/set/card_set_list.h index af1bb365b..2e644a277 100644 --- a/libcockatrice_card/libcockatrice/card/set/card_set_list.h +++ b/libcockatrice_card/libcockatrice/card/set/card_set_list.h @@ -6,20 +6,97 @@ #include #include +/** + * @class CardSetList + * @ingroup Cards + * + * @brief A list-like container for CardSet objects with extended management methods. + * + * Extends `QList` by adding convenience operations for sorting, + * enabling/disabling sets, and tracking known/unknown status. Unlike a plain + * list, this container provides domain-specific functionality for handling + * groups of sets in bulk. + */ class CardSetList : public QList { private: + /** + * @class KeyCompareFunctor + * @brief Internal comparison functor for sorting by sort key. + * + * Used internally by `sortByKey()` to order sets consistently + * according to their assigned numeric sort keys. + */ class KeyCompareFunctor; public: + /** + * @brief Sorts the set list by each set’s assigned sort key. + * + * Uses KeyCompareFunctor internally. If two sets share the + * same sort key, their relative order is unspecified. + */ void sortByKey(); + + /** + * @brief Reassigns sort keys based on the current order. + * + * Calls defaultSort() and then assigns sequential sort keys + * to all sets according to their resulting positions, replacing + * any existing sort keys to ensure consistent ordering. + */ void guessSortKeys(); + + /** + * @brief Enables all sets that are unknown or ignored. + * + * Sets that are not marked as known and not ignored are marked as known + * and enabled. Ignored-known sets are also enabled, but remain ignored. + */ void enableAllUnknown(); + + /** + * @brief Enables all sets in the list. + * + * Equivalent to calling `setEnabled(true)` on each entry. + */ void enableAll(); + + /** + * @brief Marks all sets as known and adjusts their enabled state. + * + * Unknown, non-ignored sets become known and disabled. + * Ignored-known sets are enabled if they were previously disabled. + */ void markAllAsKnown(); + + /** + * @brief Counts the number of sets that are currently enabled. + * + * @return Integer count of enabled sets. + */ int getEnabledSetsNum(); + + /** + * @brief Counts the number of sets that are currently unknown. + * + * @return Integer count of unknown sets. + */ int getUnknownSetsNum(); + + /** + * @brief Collects the short names of all sets marked as unknown. + * + * @return A list of unknown set names. + */ QStringList getUnknownSetsNames(); + + /** + * @brief Sorts the list by default rules. + * + * Orders sets first by priority (ascending), then by release date + * (most recent first), and finally alphabetically by short name. + */ void defaultSort(); }; diff --git a/libcockatrice_filters/CMakeLists.txt b/libcockatrice_filters/CMakeLists.txt new file mode 100644 index 000000000..74566ca05 --- /dev/null +++ b/libcockatrice_filters/CMakeLists.txt @@ -0,0 +1,24 @@ +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + +set(HEADERS libcockatrice/filters/filter_card.h libcockatrice/filters/filter_string.h + libcockatrice/filters/filter_tree.h +) + +if(Qt6_FOUND) + qt6_wrap_cpp(MOC_SOURCES ${HEADERS}) +elseif(Qt5_FOUND) + qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) +endif() + +add_library( + libcockatrice_filters STATIC ${MOC_SOURCES} libcockatrice/filters/filter_card.cpp + libcockatrice/filters/filter_string.cpp libcockatrice/filters/filter_tree.cpp +) + +add_dependencies(libcockatrice_filters libcockatrice_card) + +target_include_directories(libcockatrice_filters PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +target_link_libraries(libcockatrice_filters PUBLIC libcockatrice_card ${QT_CORE_MODULE}) diff --git a/cockatrice/src/filters/filter_card.cpp b/libcockatrice_filters/libcockatrice/filters/filter_card.cpp similarity index 100% rename from cockatrice/src/filters/filter_card.cpp rename to libcockatrice_filters/libcockatrice/filters/filter_card.cpp diff --git a/cockatrice/src/filters/filter_card.h b/libcockatrice_filters/libcockatrice/filters/filter_card.h similarity index 100% rename from cockatrice/src/filters/filter_card.h rename to libcockatrice_filters/libcockatrice/filters/filter_card.h diff --git a/cockatrice/src/filters/filter_string.cpp b/libcockatrice_filters/libcockatrice/filters/filter_string.cpp similarity index 100% rename from cockatrice/src/filters/filter_string.cpp rename to libcockatrice_filters/libcockatrice/filters/filter_string.cpp diff --git a/cockatrice/src/filters/filter_string.h b/libcockatrice_filters/libcockatrice/filters/filter_string.h similarity index 100% rename from cockatrice/src/filters/filter_string.h rename to libcockatrice_filters/libcockatrice/filters/filter_string.h diff --git a/cockatrice/src/filters/filter_tree.cpp b/libcockatrice_filters/libcockatrice/filters/filter_tree.cpp similarity index 100% rename from cockatrice/src/filters/filter_tree.cpp rename to libcockatrice_filters/libcockatrice/filters/filter_tree.cpp diff --git a/cockatrice/src/filters/filter_tree.h b/libcockatrice_filters/libcockatrice/filters/filter_tree.h similarity index 100% rename from cockatrice/src/filters/filter_tree.h rename to libcockatrice_filters/libcockatrice/filters/filter_tree.h diff --git a/libcockatrice_interfaces/CMakeLists.txt b/libcockatrice_interfaces/CMakeLists.txt new file mode 100644 index 000000000..4f34f7985 --- /dev/null +++ b/libcockatrice_interfaces/CMakeLists.txt @@ -0,0 +1,25 @@ +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + +set(HEADERS + libcockatrice/interfaces/interface_card_database_path_provider.h + libcockatrice/interfaces/interface_card_preference_provider.h + libcockatrice/interfaces/interface_card_set_priority_controller.h + libcockatrice/interfaces/interface_network_settings_provider.h + libcockatrice/interfaces/noop_card_database_path_provider.h + libcockatrice/interfaces/noop_card_preference_provider.h + libcockatrice/interfaces/noop_card_set_priority_controller.h +) + +if(Qt6_FOUND) + qt6_wrap_cpp(MOC_SOURCES ${HEADERS}) +elseif(Qt5_FOUND) + qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) +endif() + +add_library(libcockatrice_interfaces STATIC ${MOC_SOURCES}) + +target_include_directories(libcockatrice_interfaces PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +target_link_libraries(libcockatrice_interfaces PUBLIC ${QT_CORE_MODULE}) diff --git a/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_database_path_provider.h b/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_database_path_provider.h new file mode 100644 index 000000000..f5e54a6f8 --- /dev/null +++ b/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_database_path_provider.h @@ -0,0 +1,21 @@ +#ifndef COCKATRICE_INTERFACE_CARD_DATABASE_PATH_PROVIDER_H +#define COCKATRICE_INTERFACE_CARD_DATABASE_PATH_PROVIDER_H +#include + +class ICardDatabasePathProvider : public QObject +{ + Q_OBJECT + +public: + virtual ~ICardDatabasePathProvider() = default; + + virtual QString getCardDatabasePath() const = 0; + virtual QString getCustomCardDatabasePath() const = 0; + virtual QString getTokenDatabasePath() const = 0; + virtual QString getSpoilerCardDatabasePath() const = 0; + +signals: + void cardDatabasePathChanged(); +}; + +#endif // COCKATRICE_INTERFACE_CARD_DATABASE_PATH_PROVIDER_H diff --git a/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_preference_provider.h b/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_preference_provider.h new file mode 100644 index 000000000..7c0944f29 --- /dev/null +++ b/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_preference_provider.h @@ -0,0 +1,14 @@ +#ifndef COCKATRICE_INTERFACE_CARD_PREFERENCE_PROVIDER_H +#define COCKATRICE_INTERFACE_CARD_PREFERENCE_PROVIDER_H + +#include + +class ICardPreferenceProvider +{ +public: + virtual ~ICardPreferenceProvider() = default; + virtual QString getCardPreferenceOverride(const QString &cardName) const = 0; + virtual bool getIncludeRebalancedCards() const = 0; +}; + +#endif // COCKATRICE_INTERFACE_CARD_PREFERENCE_PROVIDER_H diff --git a/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_set_priority_controller.h b/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_set_priority_controller.h new file mode 100644 index 000000000..8f8b7e62e --- /dev/null +++ b/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_set_priority_controller.h @@ -0,0 +1,19 @@ +#ifndef COCKATRICE_INTERFACE_CARD_SET_PRIORITY_CONTROLLER_H +#define COCKATRICE_INTERFACE_CARD_SET_PRIORITY_CONTROLLER_H +#include + +class ICardSetPriorityController +{ +public: + virtual ~ICardSetPriorityController() = default; + + virtual void setSortKey(QString shortName, unsigned int sortKey) = 0; + virtual void setEnabled(QString shortName, bool enabled) = 0; + virtual void setIsKnown(QString shortName, bool isknown) = 0; + + virtual unsigned int getSortKey(QString shortName) = 0; + virtual bool isEnabled(QString shortName) = 0; + virtual bool isKnown(QString shortName) = 0; +}; + +#endif // COCKATRICE_INTERFACE_CARD_SET_PRIORITY_CONTROLLER_H diff --git a/libcockatrice_interfaces/libcockatrice/interfaces/interface_network_settings_provider.h b/libcockatrice_interfaces/libcockatrice/interfaces/interface_network_settings_provider.h new file mode 100644 index 000000000..bd136513d --- /dev/null +++ b/libcockatrice_interfaces/libcockatrice/interfaces/interface_network_settings_provider.h @@ -0,0 +1,20 @@ +#ifndef COCKATRICE_INETWORKSETTINGSPROVIDER_H +#define COCKATRICE_INETWORKSETTINGSPROVIDER_H +#include + +class INetworkSettingsProvider +{ +public: + virtual ~INetworkSettingsProvider() = default; + + virtual QString getClientID() = 0; + + [[nodiscard]] virtual int getTimeOut() const = 0; + [[nodiscard]] virtual int getKeepAlive() const = 0; + [[nodiscard]] virtual bool getNotifyAboutUpdates() const = 0; + + virtual void setKnownMissingFeatures(const QString &_knownMissingFeatures) = 0; + virtual QString getKnownMissingFeatures() = 0; +}; + +#endif // COCKATRICE_INETWORKSETTINGSPROVIDER_H diff --git a/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_database_path_provider.h b/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_database_path_provider.h new file mode 100644 index 000000000..fb3ab0cc3 --- /dev/null +++ b/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_database_path_provider.h @@ -0,0 +1,26 @@ +#ifndef COCKATRICE_NOOP_CARD_DATABASE_PATH_PROVIDER_H +#define COCKATRICE_NOOP_CARD_DATABASE_PATH_PROVIDER_H +#include "interface_card_database_path_provider.h" + +class NoopCardDatabasePathProvider : public ICardDatabasePathProvider +{ +public: + QString getCardDatabasePath() const override + { + return ""; + } + QString getCustomCardDatabasePath() const override + { + return ""; + } + QString getTokenDatabasePath() const override + { + return ""; + } + QString getSpoilerCardDatabasePath() const override + { + return ""; + } +}; + +#endif // COCKATRICE_NOOP_CARD_DATABASE_PATH_PROVIDER_H diff --git a/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_preference_provider.h b/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_preference_provider.h new file mode 100644 index 000000000..9fc7e5bb4 --- /dev/null +++ b/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_preference_provider.h @@ -0,0 +1,19 @@ +#ifndef COCKATRICE_NOOP_CARD_PREFERENCE_PROVIDER_H +#define COCKATRICE_NOOP_CARD_PREFERENCE_PROVIDER_H +#include "interface_card_preference_provider.h" + +class NoopCardPreferenceProvider : public ICardPreferenceProvider +{ +public: + QString getCardPreferenceOverride(const QString &) const override + { + return {}; + } + + bool getIncludeRebalancedCards() const override + { + return true; + } +}; + +#endif // COCKATRICE_NOOP_CARD_PREFERENCE_PROVIDER_H diff --git a/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_set_priority_controller.h b/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_set_priority_controller.h new file mode 100644 index 000000000..b2410781c --- /dev/null +++ b/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_set_priority_controller.h @@ -0,0 +1,33 @@ +#ifndef COCKATRICE_NOOP_CARD_SET_PRIORITY_CONTROLLER_H +#define COCKATRICE_NOOP_CARD_SET_PRIORITY_CONTROLLER_H + +#include "interface_card_set_priority_controller.h" + +class NoopCardSetPriorityController : public ICardSetPriorityController +{ +public: + void setSortKey(QString /* shortName */, unsigned int /* sortKey */) + { + } + void setEnabled(QString /* shortName */, bool /* enabled */) + { + } + void setIsKnown(QString /* shortName */, bool /* isknown */) + { + } + + unsigned int getSortKey(QString /* shortName */) + { + return 0; + } + bool isEnabled(QString /* shortName */) + { + return true; + } + bool isKnown(QString /* shortName */) + { + return true; + } +}; + +#endif // COCKATRICE_NOOP_CARD_SET_PRIORITY_CONTROLLER_H diff --git a/libcockatrice_models/CMakeLists.txt b/libcockatrice_models/CMakeLists.txt index a9fc34bfd..7af35b2d5 100644 --- a/libcockatrice_models/CMakeLists.txt +++ b/libcockatrice_models/CMakeLists.txt @@ -2,40 +2,11 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) -set(HEADERS - libcockatrice/models/database/card_database_model.h - libcockatrice/models/database/card_database_display_model.h - libcockatrice/models/database/card/card_completer_proxy_model.h - libcockatrice/models/database/card/card_search_model.h - libcockatrice/models/database/card_set/card_sets_model.h - libcockatrice/models/database/token/token_display_model.h - libcockatrice/models/database/token/token_edit_model.h - libcockatrice/models/deck_list/deck_list_model.h - libcockatrice/models/deck_list/deck_list_sort_filter_proxy_model.h - libcockatrice/models/deck_list/deck_loader.h -) +add_subdirectory(libcockatrice/models/database) +add_subdirectory(libcockatrice/models/deck_list) -if(Qt6_FOUND) - qt6_wrap_cpp(MOC_SOURCES ${HEADERS}) -elseif(Qt5_FOUND) - qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) -endif() +add_library(libcockatrice_models INTERFACE) -add_library( - libcockatrice_models STATIC - ${MOC_SOURCES} - libcockatrice/models/database/card_database_model.cpp - libcockatrice/models/database/card_database_display_model.cpp - libcockatrice/models/database/card/card_completer_proxy_model.cpp - libcockatrice/models/database/card/card_search_model.cpp - libcockatrice/models/database/card_set/card_sets_model.cpp - libcockatrice/models/database/token/token_display_model.cpp - libcockatrice/models/database/token/token_edit_model.cpp - libcockatrice/models/deck_list/deck_list_model.cpp - libcockatrice/models/deck_list/deck_list_sort_filter_proxy_model.cpp - libcockatrice/models/deck_list/deck_loader.cpp -) +target_include_directories(libcockatrice_models INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) -target_include_directories(libcockatrice_models PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) - -target_link_libraries(libcockatrice_models PUBLIC libcockatrice_card libcockatrice_deck_list ${COCKATRICE_QT_MODULES}) +target_link_libraries(libcockatrice_models INTERFACE libcockatrice_models_database libcockatrice_models_deck_list) diff --git a/libcockatrice_models/libcockatrice/models/database/CMakeLists.txt b/libcockatrice_models/libcockatrice/models/database/CMakeLists.txt new file mode 100644 index 000000000..950d6d79f --- /dev/null +++ b/libcockatrice_models/libcockatrice/models/database/CMakeLists.txt @@ -0,0 +1,35 @@ +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + +set(HEADERS + card_database_model.h + card_database_display_model.h + card/card_completer_proxy_model.h + card/card_search_model.h + card_set/card_sets_model.h + token/token_display_model.h + token/token_edit_model.h +) + +if(Qt6_FOUND) + qt6_wrap_cpp(MOC_SOURCES ${HEADERS}) +elseif(Qt5_FOUND) + qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) +endif() + +add_library( + libcockatrice_models_database STATIC + ${MOC_SOURCES} + card_database_model.cpp + card_database_display_model.cpp + card/card_completer_proxy_model.cpp + card/card_search_model.cpp + card_set/card_sets_model.cpp + token/token_display_model.cpp + token/token_edit_model.cpp +) + +target_include_directories(libcockatrice_models_database PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +target_link_libraries(libcockatrice_models_database PUBLIC libcockatrice_card libcockatrice_filters ${QT_CORE_MODULE}) diff --git a/libcockatrice_models/libcockatrice/models/database/card_database_display_model.h b/libcockatrice_models/libcockatrice/models/database/card_database_display_model.h index a1e949eba..467b7f0a5 100644 --- a/libcockatrice_models/libcockatrice/models/database/card_database_display_model.h +++ b/libcockatrice_models/libcockatrice/models/database/card_database_display_model.h @@ -8,12 +8,11 @@ #ifndef COCKATRICE_CARD_DATABASE_DISPLAY_MODEL_H #define COCKATRICE_CARD_DATABASE_DISPLAY_MODEL_H -#include "filter_string.h" - #include #include #include #include +#include class FilterTree; class CardDatabaseDisplayModel : public QSortFilterProxyModel diff --git a/libcockatrice_models/libcockatrice/models/deck_list/CMakeLists.txt b/libcockatrice_models/libcockatrice/models/deck_list/CMakeLists.txt new file mode 100644 index 000000000..851636a35 --- /dev/null +++ b/libcockatrice_models/libcockatrice/models/deck_list/CMakeLists.txt @@ -0,0 +1,21 @@ +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + +set(HEADERS deck_list_model.h deck_list_sort_filter_proxy_model.h) + +if(Qt6_FOUND) + qt6_wrap_cpp(MOC_SOURCES ${HEADERS}) +elseif(Qt5_FOUND) + qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) +endif() + +add_library( + libcockatrice_models_deck_list STATIC ${MOC_SOURCES} deck_list_model.cpp deck_list_sort_filter_proxy_model.cpp +) + +target_include_directories(libcockatrice_models_deck_list PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +target_link_libraries( + libcockatrice_models_deck_list PUBLIC libcockatrice_card libcockatrice_deck_list ${QT_CORE_MODULE} +) diff --git a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.cpp b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.cpp index 01ae68a71..52e3b678c 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.cpp +++ b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.cpp @@ -1,25 +1,12 @@ #include "deck_list_model.h" -#include "deck_loader.h" - -#include -#include -#include -#include -#include -#include -#include -#include #include -#include DeckListModel::DeckListModel(QObject *parent) : QAbstractItemModel(parent), lastKnownColumn(1), lastKnownOrder(Qt::AscendingOrder) { - deckList = new DeckLoader; + deckList = new DeckList; deckList->setParent(this); - connect(deckList, &DeckLoader::deckLoaded, this, &DeckListModel::rebuildTree); - connect(deckList, &DeckLoader::deckHashChanged, this, &DeckListModel::deckHashChanged); root = new InnerDecklistNode; } @@ -108,83 +95,96 @@ QVariant DeckListModel::data(const QModelIndex &index, int role) const return {}; } - auto *temp = static_cast(index.internalPointer()); - auto *card = dynamic_cast(temp); - if (card == nullptr) { - const auto *node = dynamic_cast(temp); + auto *node = static_cast(index.internalPointer()); + auto *card = dynamic_cast(node); + + // Group node + if (!card) { + const auto *group = dynamic_cast(node); + switch (role) { - case Qt::FontRole: { - QFont f; - f.setBold(true); - return f; - } case Qt::DisplayRole: case Qt::EditRole: { switch (index.column()) { - case 0: - return node->recursiveCount(true); - case 1: { - if (role == Qt::DisplayRole) - return node->getVisibleName(); - return node->getName(); - } - case 2: { - return node->getCardSetShortName(); - } - case 3: { - return node->getCardCollectorNumber(); - } - case 4: { - return node->getCardProviderId(); - } + case DeckListModelColumns::CARD_AMOUNT: + return group->recursiveCount(true); + case DeckListModelColumns::CARD_NAME: + if (role == Qt::DisplayRole) { + return group->getVisibleName(); + } + return group->getName(); + case DeckListModelColumns::CARD_SET: + return group->getCardSetShortName(); + case DeckListModelColumns::CARD_COLLECTOR_NUMBER: + return group->getCardCollectorNumber(); + case DeckListModelColumns::CARD_PROVIDER_ID: + return group->getCardProviderId(); default: return {}; } } - case Qt::UserRole + 1: + case DeckRoles::IsCardRole: return false; - case Qt::BackgroundRole: { - int color = 90 + 60 * node->depth(); - return QBrush(QColor(color, 255, color)); - } - case Qt::ForegroundRole: { - return QBrush(QColor(0, 0, 0)); - } - default: - return {}; - } - } else { - switch (role) { - case Qt::DisplayRole: - case Qt::EditRole: { - switch (index.column()) { - case 0: - return card->getNumber(); - case 1: - return card->getName(); - case 2: - return card->getCardSetShortName(); - case 3: - return card->getCardCollectorNumber(); - case 4: - return card->getCardProviderId(); - default: - return {}; - } - } - case Qt::UserRole + 1: + + case DeckRoles::DepthRole: + return group->depth(); + + // legality does not apply to group nodes + case DeckRoles::IsLegalRole: return true; - case Qt::BackgroundRole: { - int color = 255 - (index.row() % 2) * 30; - return QBrush(QColor(color, color, color)); - } - case Qt::ForegroundRole: { - return QBrush(QColor(0, 0, 0)); - } + default: return {}; } } + + // Card node + switch (role) { + case Qt::DisplayRole: + case Qt::EditRole: + switch (index.column()) { + case DeckListModelColumns::CARD_AMOUNT: + return card->getNumber(); + case DeckListModelColumns::CARD_NAME: + return card->getName(); + case DeckListModelColumns::CARD_SET: + return card->getCardSetShortName(); + case DeckListModelColumns::CARD_COLLECTOR_NUMBER: + return card->getCardCollectorNumber(); + case DeckListModelColumns::CARD_PROVIDER_ID: + return card->getCardProviderId(); + default: + return {}; + } + + case DeckRoles::IsCardRole: { + return true; + } + + case DeckRoles::DepthRole: { + return card->depth(); + } + + default: { + return {}; + } + } +} + +void DeckListModel::emitBackgroundUpdates(const QModelIndex &parent) +{ + int rows = rowCount(parent); + if (rows == 0) + return; + + QModelIndex topLeft = index(0, 0, parent); + QModelIndex bottomRight = index(rows - 1, columnCount() - 1, parent); + emit dataChanged(topLeft, bottomRight, {Qt::BackgroundRole}); + + for (int r = 0; r < rows; ++r) { + QModelIndex child = index(r, 0, parent); + emitBackgroundUpdates(child); + } } QVariant DeckListModel::headerData(const int section, const Qt::Orientation orientation, const int role) const @@ -198,15 +198,15 @@ QVariant DeckListModel::headerData(const int section, const Qt::Orientation orie } switch (section) { - case 0: + case DeckListModelColumns::CARD_AMOUNT: return tr("Count"); - case 1: + case DeckListModelColumns::CARD_NAME: return tr("Card"); - case 2: + case DeckListModelColumns::CARD_SET: return tr("Set"); - case 3: + case DeckListModelColumns::CARD_COLLECTOR_NUMBER: return tr("Number"); - case 4: + case DeckListModelColumns::CARD_PROVIDER_ID: return tr("Provider ID"); default: return {}; @@ -263,19 +263,19 @@ bool DeckListModel::setData(const QModelIndex &index, const QVariant &value, con } switch (index.column()) { - case 0: + case DeckListModelColumns::CARD_AMOUNT: node->setNumber(value.toInt()); break; - case 1: + case DeckListModelColumns::CARD_NAME: node->setName(value.toString()); break; - case 2: + case DeckListModelColumns::CARD_SET: node->setCardSetShortName(value.toString()); break; - case 3: + case DeckListModelColumns::CARD_COLLECTOR_NUMBER: node->setCardCollectorNumber(value.toString()); break; - case 4: + case DeckListModelColumns::CARD_PROVIDER_ID: node->setCardProviderId(value.toString()); break; default: @@ -521,7 +521,7 @@ void DeckListModel::sort(int column, Qt::SortOrder order) emit layoutChanged(); } -void DeckListModel::setActiveGroupCriteria(DeckListModelGroupCriteria newCriteria) +void DeckListModel::setActiveGroupCriteria(DeckListModelGroupCriteria::Type newCriteria) { activeGroupCriteria = newCriteria; rebuildTree(); @@ -529,19 +529,17 @@ void DeckListModel::setActiveGroupCriteria(DeckListModelGroupCriteria newCriteri void DeckListModel::cleanList() { - setDeckList(new DeckLoader); + setDeckList(new DeckList); } /** * @param _deck The deck. Takes ownership of the object */ -void DeckListModel::setDeckList(DeckLoader *_deck) +void DeckListModel::setDeckList(DeckList *_deck) { deckList->deleteLater(); deckList = _deck; deckList->setParent(this); - connect(deckList, &DeckLoader::deckLoaded, this, &DeckListModel::rebuildTree); - connect(deckList, &DeckLoader::deckHashChanged, this, &DeckListModel::deckHashChanged); rebuildTree(); } @@ -629,98 +627,4 @@ QList *DeckListModel::getZones() const zones->append(currentZone->getName()); } return zones; -} - -void DeckListModel::printDeckListNode(QTextCursor *cursor, InnerDecklistNode *node) -{ - const int totalColumns = 2; - - if (node->height() == 1) { - QTextBlockFormat blockFormat; - QTextCharFormat charFormat; - charFormat.setFontPointSize(11); - charFormat.setFontWeight(QFont::Bold); - cursor->insertBlock(blockFormat, charFormat); - - QTextTableFormat tableFormat; - tableFormat.setCellPadding(0); - tableFormat.setCellSpacing(0); - tableFormat.setBorder(0); - QTextTable *table = cursor->insertTable(node->size() + 1, totalColumns, tableFormat); - for (int i = 0; i < node->size(); i++) { - auto *card = dynamic_cast(node->at(i)); - - QTextCharFormat cellCharFormat; - cellCharFormat.setFontPointSize(9); - - QTextTableCell cell = table->cellAt(i, 0); - cell.setFormat(cellCharFormat); - QTextCursor cellCursor = cell.firstCursorPosition(); - cellCursor.insertText(QString("%1 ").arg(card->getNumber())); - - cell = table->cellAt(i, 1); - cell.setFormat(cellCharFormat); - cellCursor = cell.firstCursorPosition(); - cellCursor.insertText(card->getName()); - } - } else if (node->height() == 2) { - QTextBlockFormat blockFormat; - QTextCharFormat charFormat; - charFormat.setFontPointSize(14); - charFormat.setFontWeight(QFont::Bold); - - cursor->insertBlock(blockFormat, charFormat); - - QTextTableFormat tableFormat; - tableFormat.setCellPadding(10); - tableFormat.setCellSpacing(0); - tableFormat.setBorder(0); - QVector constraints; - for (int i = 0; i < totalColumns; i++) { - constraints << QTextLength(QTextLength::PercentageLength, 100.0 / totalColumns); - } - tableFormat.setColumnWidthConstraints(constraints); - - QTextTable *table = cursor->insertTable(1, totalColumns, tableFormat); - for (int i = 0; i < node->size(); i++) { - QTextCursor cellCursor = table->cellAt(0, (i * totalColumns) / node->size()).lastCursorPosition(); - printDeckListNode(&cellCursor, dynamic_cast(node->at(i))); - } - } - - cursor->movePosition(QTextCursor::End); -} - -void DeckListModel::printDeckList(QPrinter *printer) -{ - QTextDocument doc; - - QFont font("Serif"); - font.setStyleHint(QFont::Serif); - doc.setDefaultFont(font); - - QTextCursor cursor(&doc); - - QTextBlockFormat headerBlockFormat; - QTextCharFormat headerCharFormat; - headerCharFormat.setFontPointSize(16); - headerCharFormat.setFontWeight(QFont::Bold); - - cursor.insertBlock(headerBlockFormat, headerCharFormat); - cursor.insertText(deckList->getName()); - - headerCharFormat.setFontPointSize(12); - cursor.insertBlock(headerBlockFormat, headerCharFormat); - cursor.insertText(deckList->getComments()); - cursor.insertBlock(headerBlockFormat, headerCharFormat); - - for (int i = 0; i < root->size(); i++) { - cursor.insertHtml("
"); - // cursor.insertHtml("
"); - cursor.insertBlock(headerBlockFormat, headerCharFormat); - - printDeckListNode(&cursor, dynamic_cast(root->at(i))); - } - - doc.print(printer); -} +} \ No newline at end of file diff --git a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h index e169af395..8beabd4ba 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h +++ b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h @@ -8,20 +8,73 @@ #include #include -class DeckLoader; class CardDatabase; class QPrinter; class QTextCursor; /** - * @brief Specifies the criteria used to group cards in the DeckListModel. + * @namespace DeckRoles + * @brief Custom model roles used by the DeckListModel for data retrieval. + * + * These roles extend Qt's item data roles starting at Qt::UserRole. */ -enum DeckListModelGroupCriteria +namespace DeckRoles +{ +/** + * @enum DeckRoles + * @brief Custom data roles for deck-related model items. + * + * These roles are used to retrieve specialized data from the DeckListModel. + */ +enum +{ + IsCardRole = Qt::UserRole + 1, /**< Indicates whether the item represents a card. */ + DepthRole, /**< Depth level within the deck's grouping hierarchy. */ + IsLegalRole /**< Whether the card is legal in the current deck format. */ +}; +} // namespace DeckRoles + +/** + * @namespace DeckListModelColumns + * @brief Column indices for the DeckListModel. + * + * These values map to the columns in the deck list table representation. + */ +namespace DeckListModelColumns +{ +/** + * @enum DeckListModelColumns + * @brief Column identifiers for displaying card information in the deck list. + */ +enum +{ + CARD_AMOUNT = 0, /**< The number of copies of the card. */ + CARD_NAME = 1, /**< The card's name. */ + CARD_SET = 2, /**< The set or expansion the card belongs to. */ + CARD_COLLECTOR_NUMBER = 3, /**< Collector number of the card within the set. */ + CARD_PROVIDER_ID = 4 /**< ID used by the external data provider (e.g., Scryfall). */ +}; +} // namespace DeckListModelColumns + +/** + * @namespace DeckListModelGroupCriteria + * @brief Specifies criteria used to group cards in the DeckListModel. + * + * These values determine how cards are grouped in UI views such as the deck editor. + */ +namespace DeckListModelGroupCriteria +{ +/** + * @enum DeckListModelGroupCriteria + * @brief Available grouping strategies for deck visualization. + */ +enum Type { MAIN_TYPE, /**< Group cards by their main type (e.g., creature, instant). */ - MANA_COST, /**< Group cards by their mana cost. */ + MANA_COST, /**< Group cards by their total mana cost. */ COLOR /**< Group cards by their color identity. */ }; +} // namespace DeckListModelGroupCriteria /** * @class DecklistModelCardNode @@ -119,12 +172,12 @@ public: * * Slots: * - rebuildTree(): rebuilds the model structure from the underlying DeckLoader. - * - printDeckList(): renders the decklist to a QPrinter. */ class DeckListModel : public QAbstractItemModel { Q_OBJECT -private slots: + +public slots: /** * @brief Rebuilds the model tree from the underlying DeckLoader. * @@ -133,13 +186,6 @@ private slots: */ void rebuildTree(); -public slots: - /** - * @brief Prints the decklist to the provided QPrinter. - * @param printer The printer to render the decklist to. - */ - void printDeckList(QPrinter *printer); - signals: /** * @brief Emitted whenever the deck hash changes due to modifications in the model. @@ -170,6 +216,7 @@ public: int rowCount(const QModelIndex &parent) const override; int columnCount(const QModelIndex & /*parent*/ = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role) const override; + void emitBackgroundUpdates(const QModelIndex &parent); QVariant headerData(int section, Qt::Orientation orientation, int role) const override; QModelIndex index(int row, int column, const QModelIndex &parent) const override; QModelIndex parent(const QModelIndex &index) const override; @@ -222,11 +269,11 @@ public: * @brief Removes all cards and resets the model. */ void cleanList(); - DeckLoader *getDeckList() const + DeckList *getDeckList() const { return deckList; } - void setDeckList(DeckLoader *_deck); + void setDeckList(DeckList *_deck); QList getCards() const; QList getCardsForZone(const QString &zoneName) const; @@ -236,12 +283,12 @@ public: * @brief Sets the criteria used to group cards in the model. * @param newCriteria The new grouping criteria. */ - void setActiveGroupCriteria(DeckListModelGroupCriteria newCriteria); + void setActiveGroupCriteria(DeckListModelGroupCriteria::Type newCriteria); private: - DeckLoader *deckList; /**< Pointer to the deck loader providing the underlying data. */ + DeckList *deckList; /**< Pointer to the deck loader providing the underlying data. */ InnerDecklistNode *root; /**< Root node of the model tree. */ - DeckListModelGroupCriteria activeGroupCriteria = DeckListModelGroupCriteria::MAIN_TYPE; + DeckListModelGroupCriteria::Type activeGroupCriteria = DeckListModelGroupCriteria::MAIN_TYPE; int lastKnownColumn; /**< Last column used for sorting. */ Qt::SortOrder lastKnownOrder; /**< Last known sort order. */ @@ -254,8 +301,6 @@ private: void emitRecursiveUpdates(const QModelIndex &index); void sortHelper(InnerDecklistNode *node, Qt::SortOrder order); - void printDeckListNode(QTextCursor *cursor, InnerDecklistNode *node); - template T getNode(const QModelIndex &index) const { if (!index.isValid()) diff --git a/libcockatrice_network/libcockatrice/network/client/CMakeLists.txt b/libcockatrice_network/libcockatrice/network/client/CMakeLists.txt index d86210edd..bcf62463c 100644 --- a/libcockatrice_network/libcockatrice/network/client/CMakeLists.txt +++ b/libcockatrice_network/libcockatrice/network/client/CMakeLists.txt @@ -11,6 +11,8 @@ add_library(libcockatrice_network_client INTERFACE) target_include_directories(libcockatrice_network_client INTERFACE .) target_link_libraries( - libcockatrice_network_client INTERFACE ${COCKATRICE_QT_MODULES} libcockatrice_network_client_abstract - libcockatrice_network_client_local libcockatrice_network_client_remote + libcockatrice_network_client + INTERFACE ${COCKATRICE_QT_VERSION_NAME}::Network ${COCKATRICE_QT_VERSION_NAME}::WebSockets + libcockatrice_network_client_abstract libcockatrice_network_client_local + libcockatrice_network_client_remote ) diff --git a/libcockatrice_network/libcockatrice/network/client/abstract/CMakeLists.txt b/libcockatrice_network/libcockatrice/network/client/abstract/CMakeLists.txt index 54e4d83e0..2753246de 100644 --- a/libcockatrice_network/libcockatrice/network/client/abstract/CMakeLists.txt +++ b/libcockatrice_network/libcockatrice/network/client/abstract/CMakeLists.txt @@ -19,6 +19,7 @@ add_dependencies(libcockatrice_network_client_abstract libcockatrice_protocol li target_include_directories(libcockatrice_network_client_abstract PUBLIC .) target_link_libraries( - libcockatrice_network_client_abstract PUBLIC ${COCKATRICE_QT_MODULES} libcockatrice_protocol - libcockatrice_network_server_remote + libcockatrice_network_client_abstract + PUBLIC ${COCKATRICE_QT_VERSION_NAME}::Network ${COCKATRICE_QT_VERSION_NAME}::WebSockets libcockatrice_protocol + libcockatrice_network_server_remote ) diff --git a/libcockatrice_network/libcockatrice/network/client/local/CMakeLists.txt b/libcockatrice_network/libcockatrice/network/client/local/CMakeLists.txt index 3c202904d..d12a324dc 100644 --- a/libcockatrice_network/libcockatrice/network/client/local/CMakeLists.txt +++ b/libcockatrice_network/libcockatrice/network/client/local/CMakeLists.txt @@ -19,5 +19,7 @@ add_dependencies(libcockatrice_network_client_local libcockatrice_network_client target_include_directories(libcockatrice_network_client_local PUBLIC .) target_link_libraries( - libcockatrice_network_client_local PUBLIC ${COCKATRICE_QT_MODULES} libcockatrice_network_client_abstract + libcockatrice_network_client_local + PUBLIC ${COCKATRICE_QT_VERSION_NAME}::Network ${COCKATRICE_QT_VERSION_NAME}::WebSockets + libcockatrice_network_client_abstract ) diff --git a/libcockatrice_network/libcockatrice/network/client/remote/CMakeLists.txt b/libcockatrice_network/libcockatrice/network/client/remote/CMakeLists.txt index 01f438b08..0548700e4 100644 --- a/libcockatrice_network/libcockatrice/network/client/remote/CMakeLists.txt +++ b/libcockatrice_network/libcockatrice/network/client/remote/CMakeLists.txt @@ -19,6 +19,7 @@ add_dependencies(libcockatrice_network_client_remote libcockatrice_network_clien target_include_directories(libcockatrice_network_client_remote PUBLIC .) target_link_libraries( - libcockatrice_network_client_remote PUBLIC ${COCKATRICE_QT_MODULES} libcockatrice_network_client_abstract - libcockatrice_settings libcockatrice_utility libcockatrice_protocol + libcockatrice_network_client_remote + PUBLIC ${COCKATRICE_QT_VERSION_NAME}::Network ${COCKATRICE_QT_VERSION_NAME}::WebSockets + libcockatrice_network_client_abstract libcockatrice_interfaces libcockatrice_utility libcockatrice_protocol ) diff --git a/libcockatrice_network/libcockatrice/network/client/remote/remote_client.cpp b/libcockatrice_network/libcockatrice/network/client/remote/remote_client.cpp index fdcbfae88..c0167a875 100644 --- a/libcockatrice_network/libcockatrice/network/client/remote/remote_client.cpp +++ b/libcockatrice_network/libcockatrice/network/client/remote/remote_client.cpp @@ -1,6 +1,5 @@ #include "remote_client.h" -#include "../../../../cockatrice/src/main.h" #include "version_string.h" #include @@ -11,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -21,19 +21,18 @@ #include #include #include -#include #include static const unsigned int protocolVersion = 14; -RemoteClient::RemoteClient(QObject *parent) - : AbstractClient(parent), timeRunning(0), lastDataReceived(0), messageInProgress(false), handshakeStarted(false), - usingWebSocket(false), messageLength(0), hashedPassword() +RemoteClient::RemoteClient(QObject *parent, INetworkSettingsProvider *_networkSettingsProvider) + : AbstractClient(parent), networkSettingsProvider(_networkSettingsProvider), timeRunning(0), lastDataReceived(0), + messageInProgress(false), handshakeStarted(false), usingWebSocket(false), messageLength(0), hashedPassword() { clearNewClientFeatures(); - maxTimeout = SettingsCache::instance().getTimeOut(); - int keepalive = SettingsCache::instance().getKeepAlive(); + maxTimeout = networkSettingsProvider->getTimeOut(); + int keepalive = networkSettingsProvider->getKeepAlive(); timer = new QTimer(this); timer->setInterval(keepalive * 1000); connect(timer, &QTimer::timeout, this, &RemoteClient::ping); @@ -308,8 +307,8 @@ void RemoteClient::loginResponse(const Response &response) emit ignoreListReceived(ignoreList); if (newMissingFeatureFound(possibleMissingFeatures) && resp.missing_features_size() > 0 && - SettingsCache::instance().getNotifyAboutUpdates()) { - SettingsCache::instance().setKnownMissingFeatures(possibleMissingFeatures); + networkSettingsProvider->getNotifyAboutUpdates()) { + networkSettingsProvider->setKnownMissingFeatures(possibleMissingFeatures); emit notifyUserAboutUpdate(); } @@ -586,7 +585,7 @@ void RemoteClient::disconnectFromServer() QString RemoteClient::getSrvClientID(const QString &_hostname) { - QString srvClientID = SettingsCache::instance().getClientID(); + QString srvClientID = networkSettingsProvider->getClientID(); QHostInfo hostInfo = QHostInfo::fromName(_hostname); if (!hostInfo.error()) { QHostAddress hostAddress = hostInfo.addresses().first(); @@ -606,7 +605,7 @@ bool RemoteClient::newMissingFeatureFound(const QString &_serversMissingFeatures QStringList serversMissingFeaturesList = _serversMissingFeatures.split(","); for (const QString &feature : serversMissingFeaturesList) { if (!feature.isEmpty()) { - if (!SettingsCache::instance().getKnownMissingFeatures().contains(feature)) + if (!networkSettingsProvider->getKnownMissingFeatures().contains(feature)) return true; } } @@ -616,14 +615,14 @@ bool RemoteClient::newMissingFeatureFound(const QString &_serversMissingFeatures void RemoteClient::clearNewClientFeatures() { QString newKnownMissingFeatures; - QStringList existingKnownMissingFeatures = SettingsCache::instance().getKnownMissingFeatures().split(","); + QStringList existingKnownMissingFeatures = networkSettingsProvider->getKnownMissingFeatures().split(","); for (const QString &existingKnownFeature : existingKnownMissingFeatures) { if (!existingKnownFeature.isEmpty()) { if (!clientFeatures.contains(existingKnownFeature)) newKnownMissingFeatures.append("," + existingKnownFeature); } } - SettingsCache::instance().setKnownMissingFeatures(newKnownMissingFeatures); + networkSettingsProvider->setKnownMissingFeatures(newKnownMissingFeatures); } void RemoteClient::requestForgotPasswordToServer(const QString &hostname, unsigned int port, const QString &_userName) diff --git a/libcockatrice_network/libcockatrice/network/client/remote/remote_client.h b/libcockatrice_network/libcockatrice/network/client/remote/remote_client.h index d3984d5dd..939e88dfc 100644 --- a/libcockatrice_network/libcockatrice/network/client/remote/remote_client.h +++ b/libcockatrice_network/libcockatrice/network/client/remote/remote_client.h @@ -12,6 +12,7 @@ #include #include #include +#include #include inline Q_LOGGING_CATEGORY(RemoteClientLog, "remote_client"); @@ -97,6 +98,7 @@ private slots: void submitForgotPasswordChallengeResponse(const Response &response); private: + INetworkSettingsProvider *networkSettingsProvider; int maxTimeout; int timeRunning, lastDataReceived; QByteArray inputBuffer; @@ -120,7 +122,7 @@ protected slots: void sendCommandContainer(const CommandContainer &cont) override; public: - explicit RemoteClient(QObject *parent = nullptr); + explicit RemoteClient(QObject *parent = nullptr, INetworkSettingsProvider *networkSettingsProvider = nullptr); ~RemoteClient() override; QString peerName() const { diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp index 67c1aa8d6..647d1d078 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp @@ -340,6 +340,7 @@ void Server_Game::doStartGameIfReady(bool forceStartGame) } } + players = getPlayers(); // players could have been kicked, get new list of players for (Server_AbstractPlayer *player : players.values()) { player->setupZones(); } @@ -586,27 +587,26 @@ void Server_Game::removeArrowsRelatedToPlayer(GameEventStorage &ges, Server_Abst // Also remove all arrows starting at one of his cards. This is necessary since players can create // arrows that start at another person's cards. for (Server_AbstractPlayer *anyPlayer : getPlayers().values()) { - QList arrows = anyPlayer->getArrows().values(); QList toDelete; - for (int i = 0; i < arrows.size(); ++i) { - Server_Arrow *arrow = arrows[i]; + for (auto *arrow : anyPlayer->getArrows().values()) { Server_Card *targetCard = qobject_cast(arrow->getTargetItem()); if (targetCard) { if (targetCard->getZone() != nullptr && targetCard->getZone()->getPlayer() == player) toDelete.append(arrow); - } else if (static_cast(arrow->getTargetItem()) == player) + } else if (arrow->getTargetItem() == player) { toDelete.append(arrow); + } // Don't use else here! It has to happen regardless of whether targetCard == 0. if (arrow->getStartCard()->getZone() != nullptr && arrow->getStartCard()->getZone()->getPlayer() == player) toDelete.append(arrow); } - for (int i = 0; i < toDelete.size(); ++i) { + for (auto *arrow : toDelete) { Event_DeleteArrow event; - event.set_arrow_id(toDelete[i]->getId()); - ges.enqueueGameEvent(event, player->getPlayerId()); + event.set_arrow_id(arrow->getId()); + ges.enqueueGameEvent(event, anyPlayer->getPlayerId()); - player->deleteArrow(toDelete[i]->getId()); + anyPlayer->deleteArrow(arrow->getId()); } } } diff --git a/libcockatrice_settings/CMakeLists.txt b/libcockatrice_settings/CMakeLists.txt index bacb397bf..3afe6e00a 100644 --- a/libcockatrice_settings/CMakeLists.txt +++ b/libcockatrice_settings/CMakeLists.txt @@ -3,8 +3,6 @@ set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) set(HEADERS - libcockatrice/settings/cache_settings.h - libcockatrice/settings/card_counter_settings.h libcockatrice/settings/card_database_settings.h libcockatrice/settings/card_override_settings.h libcockatrice/settings/debug_settings.h @@ -15,8 +13,6 @@ set(HEADERS libcockatrice/settings/recents_settings.h libcockatrice/settings/servers_settings.h libcockatrice/settings/settings_manager.h - libcockatrice/settings/shortcut_treeview.h - libcockatrice/settings/shortcuts_settings.h ) if(Qt6_FOUND) @@ -28,8 +24,6 @@ endif() add_library( libcockatrice_settings STATIC ${MOC_SOURCES} - libcockatrice/settings/cache_settings.cpp - libcockatrice/settings/card_counter_settings.cpp libcockatrice/settings/card_database_settings.cpp libcockatrice/settings/card_override_settings.cpp libcockatrice/settings/debug_settings.cpp @@ -40,8 +34,6 @@ add_library( libcockatrice/settings/recents_settings.cpp libcockatrice/settings/servers_settings.cpp libcockatrice/settings/settings_manager.cpp - libcockatrice/settings/shortcut_treeview.cpp - libcockatrice/settings/shortcuts_settings.cpp ) target_include_directories( @@ -50,4 +42,4 @@ target_include_directories( PUBLIC ${CMAKE_SOURCE_DIR}/cockatrice/src/client/network ) -target_link_libraries(libcockatrice_settings PUBLIC libcockatrice_utility ${COCKATRICE_QT_MODULES}) +target_link_libraries(libcockatrice_settings PUBLIC libcockatrice_card libcockatrice_utility ${QT_CORE_MODULE}) diff --git a/libcockatrice_settings/libcockatrice/settings/card_database_settings.h b/libcockatrice_settings/libcockatrice/settings/card_database_settings.h index 5bc7eb59f..8d45efbec 100644 --- a/libcockatrice_settings/libcockatrice/settings/card_database_settings.h +++ b/libcockatrice_settings/libcockatrice/settings/card_database_settings.h @@ -13,27 +13,24 @@ #include #include #include +#include -class CardDatabaseSettings : public SettingsManager +class CardDatabaseSettings : public SettingsManager, public ICardSetPriorityController { Q_OBJECT friend class SettingsCache; public: - void setSortKey(QString shortName, unsigned int sortKey); - void setEnabled(QString shortName, bool enabled); - void setIsKnown(QString shortName, bool isknown); + void setSortKey(QString shortName, unsigned int sortKey) override; + void setEnabled(QString shortName, bool enabled) override; + void setIsKnown(QString shortName, bool isknown) override; - unsigned int getSortKey(QString shortName); - bool isEnabled(QString shortName); - bool isKnown(QString shortName); -signals: - -public slots: + unsigned int getSortKey(QString shortName) override; + bool isEnabled(QString shortName) override; + bool isKnown(QString shortName) override; private: explicit CardDatabaseSettings(const QString &settingPath, QObject *parent = nullptr); - CardDatabaseSettings(const CardDatabaseSettings & /*other*/); }; #endif // CARDDATABASESETTINGS_H diff --git a/oracle/CMakeLists.txt b/oracle/CMakeLists.txt index 0331b287c..36001a566 100644 --- a/oracle/CMakeLists.txt +++ b/oracle/CMakeLists.txt @@ -23,6 +23,9 @@ set(oracle_SOURCES src/pagetemplates.cpp src/parsehelpers.cpp src/qt-json/json.cpp + ../cockatrice/src/client/settings/cache_settings.cpp + ../cockatrice/src/client/settings/card_counter_settings.cpp + ../cockatrice/src/client/settings/shortcuts_settings.cpp ../cockatrice/src/client/network/update/client/release_channel.cpp ../cockatrice/src/interface/theme_manager.cpp ../cockatrice/src/interface/widgets/quick_settings/settings_button_widget.cpp @@ -140,6 +143,7 @@ target_link_libraries( oracle PUBLIC libcockatrice_card PUBLIC libcockatrice_settings + PUBLIC libcockatrice_network PUBLIC ${ORACLE_QT_MODULES} ) diff --git a/oracle/src/main.cpp b/oracle/src/main.cpp index 3215f1d44..5def0c887 100644 --- a/oracle/src/main.cpp +++ b/oracle/src/main.cpp @@ -3,13 +3,13 @@ #include "interface/theme_manager.h" #include "oraclewizard.h" +#include <../../cockatrice/src/client/settings/cache_settings.h> #include #include #include #include #include #include -#include QTranslator *translator, *qtTranslator; ThemeManager *themeManager; diff --git a/oracle/src/oracleimporter.cpp b/oracle/src/oracleimporter.cpp index 204772857..98149e0b0 100644 --- a/oracle/src/oracleimporter.cpp +++ b/oracle/src/oracleimporter.cpp @@ -1,5 +1,6 @@ #include "oracleimporter.h" +#include "client/settings/cache_settings.h" #include "parsehelpers.h" #include "qt-json/json.h" @@ -7,6 +8,7 @@ #include #include #include +#include #include #include @@ -38,8 +40,6 @@ static CardSet::Priority getSetPriority(const QString &setType, const QString &s bool OracleImporter::readSetsFromByteArray(const QByteArray &data) { - QList newSetList; - bool ok; auto setsMap = QtJson::Json::parse(QString(data), ok).toMap().value("data").toMap(); if (!ok) { @@ -47,6 +47,8 @@ bool OracleImporter::readSetsFromByteArray(const QByteArray &data) return false; } + QList newSetList; + QListIterator it(setsMap.values()); while (it.hasNext()) { @@ -150,7 +152,8 @@ CardInfoPtr OracleImporter::addCard(QString name, QStringList symbols = manacost.split("}"); QString formattedCardCost; for (QString symbol : symbols) { - if (symbol.contains(QRegularExpression("[0-9WUBGRP]/[0-9WUBGRP]"))) { + static const auto manaCostPattern = QRegularExpression("[0-9WUBGRP]/[0-9WUBGRP]"); + if (symbol.contains(manaCostPattern)) { symbol.append("}"); } else { symbol.remove(QChar('{')); @@ -184,9 +187,9 @@ CardInfoPtr OracleImporter::addCard(QString name, // table row int tableRow = 1; QString mainCardType = properties.value("maintype").toString(); - if ((mainCardType == "Land")) + if (mainCardType == "Land") tableRow = 0; - else if ((mainCardType == "Sorcery") || (mainCardType == "Instant")) + else if (mainCardType == "Sorcery" || mainCardType == "Instant") tableRow = 3; else if (mainCardType == "Creature") tableRow = 2; @@ -235,26 +238,26 @@ int OracleImporter::importCardsFromSet(const CardSetPtr ¤tSet, const QList // mtgjson name => xml name static const QMap identifierProperties{{"multiverseId", "muid"}, {"scryfallId", "uuid"}}; - int numCards = 0; - QMap, QString>> splitCards; - QString ptSeparator("/"); - QVariantMap card; - QString layout, name, text, colors, colorIdentity, faceName; + static const QString ptSeparator = "/"; static constexpr bool isToken = false; static const QList setsWithCardsWithSameNameButDifferentText = {"UST"}; - QVariantHash properties; - PrintingInfo printingInfo; - QList relatedCards; + + int numCards = 0; + + // Keeps track of any split card faces encountered so far + QMap, QString>> splitCards; + + // Keeps track of all names encountered so far QList allNameProps; for (const QVariant &cardVar : cardsList) { - card = cardVar.toMap(); + QVariantMap card = cardVar.toMap(); /* Currently used layouts are: * augment, double_faced_token, flip, host, leveler, meld, normal, planar, * saga, scheme, split, token, transform, vanguard */ - layout = getStringPropertyFromMap(card, "layout"); + QString layout = getStringPropertyFromMap(card, "layout"); // don't import tokens from the json file if (layout == "token") { @@ -262,44 +265,38 @@ int OracleImporter::importCardsFromSet(const CardSetPtr ¤tSet, const QList } // normal cards handling - name = getStringPropertyFromMap(card, "name"); - text = getStringPropertyFromMap(card, "text"); - faceName = getStringPropertyFromMap(card, "faceName"); + QString name = getStringPropertyFromMap(card, "name"); + QString text = getStringPropertyFromMap(card, "text"); + QString faceName = getStringPropertyFromMap(card, "faceName"); if (faceName.isEmpty()) { faceName = name; } // card properties - properties.clear(); - QMapIterator it(cardProperties); - while (it.hasNext()) { - it.next(); - QString mtgjsonProperty = it.key(); - QString xmlPropertyName = it.value(); + QVariantHash properties; + for (auto i = cardProperties.cbegin(), end = cardProperties.cend(); i != end; ++i) { + QString mtgjsonProperty = i.key(); + QString xmlPropertyName = i.value(); QString propertyValue = getStringPropertyFromMap(card, mtgjsonProperty); if (!propertyValue.isEmpty()) properties.insert(xmlPropertyName, propertyValue); } // per-set properties - printingInfo = PrintingInfo(currentSet); - QMapIterator it2(setInfoProperties); - while (it2.hasNext()) { - it2.next(); - QString mtgjsonProperty = it2.key(); - QString xmlPropertyName = it2.value(); + PrintingInfo printingInfo = PrintingInfo(currentSet); + for (auto i = setInfoProperties.cbegin(), end = setInfoProperties.cend(); i != end; ++i) { + QString mtgjsonProperty = i.key(); + QString xmlPropertyName = i.value(); QString propertyValue = getStringPropertyFromMap(card, mtgjsonProperty); if (!propertyValue.isEmpty()) printingInfo.setProperty(xmlPropertyName, propertyValue); } // Identifiers - QMapIterator it3(identifierProperties); - while (it3.hasNext()) { - it3.next(); - auto mtgjsonProperty = it3.key(); - auto xmlPropertyName = it3.value(); - auto propertyValue = getStringPropertyFromMap(card.value("identifiers").toMap(), mtgjsonProperty); + for (auto i = identifierProperties.cbegin(), end = identifierProperties.cend(); i != end; ++i) { + QString mtgjsonProperty = i.key(); + QString xmlPropertyName = i.value(); + QString propertyValue = getStringPropertyFromMap(card.value("identifiers").toMap(), mtgjsonProperty); if (!propertyValue.isEmpty()) { printingInfo.setProperty(xmlPropertyName, propertyValue); } @@ -318,13 +315,13 @@ int OracleImporter::importCardsFromSet(const CardSetPtr ¤tSet, const QList allNameProps.append(faceName); // special handling properties - colors = card.value("colors").toStringList().join(""); + QString colors = card.value("colors").toStringList().join(""); if (!colors.isEmpty()) { properties.insert("colors", colors); } // special handling properties - colorIdentity = card.value("colorIdentity").toStringList().join(""); + QString colorIdentity = card.value("colorIdentity").toStringList().join(""); if (!colorIdentity.isEmpty()) { properties.insert("coloridentity", colorIdentity); } @@ -347,8 +344,8 @@ int OracleImporter::importCardsFromSet(const CardSetPtr ¤tSet, const QList } auto legalities = card.value("legalities").toMap(); - for (const QString &fmtName : legalities.keys()) { - properties.insert(QString("format-%1").arg(fmtName), legalities.value(fmtName).toString().toLower()); + for (auto i = legalities.cbegin(), end = legalities.cend(); i != end; ++i) { + properties.insert(QString("format-%1").arg(i.key()), i.value().toString().toLower()); } // split cards are considered a single card, enqueue for later merging @@ -365,7 +362,7 @@ int OracleImporter::importCardsFromSet(const CardSetPtr ¤tSet, const QList } } else { // relations - relatedCards.clear(); + QList relatedCards; // add other face for split cards as card relation if (!getStringPropertyFromMap(card, "side").isEmpty()) { @@ -413,17 +410,15 @@ int OracleImporter::importCardsFromSet(const CardSetPtr ¤tSet, const QList // split cards handling static const QString splitCardPropSeparator = QString(" // "); static const QString splitCardTextSeparator = QString("\n\n---\n\n"); - for (const QString &nameSplit : splitCards.keys()) { - // get all parts for this specific card - QList splitCardParts = splitCards.value(nameSplit).first; - name = splitCards.value(nameSplit).second; + static const QList noRelatedCards = {}; - text.clear(); - properties.clear(); - relatedCards.clear(); + QList, QString>> partsAndNames = splitCards.values(); + for (auto [splitCardParts, name] : partsAndNames) { + QString text; + QVariantHash properties; + PrintingInfo printingInfo; for (const SplitCardPart &tmp : splitCardParts) { - QString splitName = tmp.getName(); if (!text.isEmpty()) { text.append(splitCardTextSeparator); } @@ -434,9 +429,10 @@ int OracleImporter::importCardsFromSet(const CardSetPtr ¤tSet, const QList printingInfo = tmp.getPrintingInfo(); } else { const QVariantHash &tmpProps = tmp.getProperties(); - for (const QString &prop : tmpProps.keys()) { + for (auto i = tmpProps.cbegin(), end = tmpProps.cend(); i != end; ++i) { + QString prop = i.key(); QString originalPropertyValue = properties.value(prop).toString(); - QString thisCardPropertyValue = tmpProps.value(prop).toString(); + QString thisCardPropertyValue = i.value().toString(); if (!thisCardPropertyValue.isEmpty() && originalPropertyValue != thisCardPropertyValue) { if (originalPropertyValue.isEmpty()) { // don't create //es if one field is empty properties.insert(prop, thisCardPropertyValue); @@ -452,7 +448,7 @@ int OracleImporter::importCardsFromSet(const CardSetPtr ¤tSet, const QList } } } - CardInfoPtr newCard = addCard(name, text, isToken, properties, relatedCards, printingInfo); + CardInfoPtr newCard = addCard(name, text, isToken, properties, noRelatedCards, printingInfo); numCards++; } @@ -461,15 +457,16 @@ int OracleImporter::importCardsFromSet(const CardSetPtr ¤tSet, const QList int OracleImporter::startImport() { - int setCards = 0, setIndex = 0; + int setIndex = 0; // add an empty set for tokens - CardSetPtr tokenSet = CardSet::newInstance(CardSet::TOKENS_SETNAME, tr("Dummy set containing tokens"), "Tokens"); + CardSetPtr tokenSet = CardSet::newInstance(SettingsCache::instance().cardDatabase(), CardSet::TOKENS_SETNAME, + tr("Dummy set containing tokens"), "Tokens"); sets.insert(CardSet::TOKENS_SETNAME, tokenSet); for (const SetToDownload &curSetToParse : allSets) { - CardSetPtr newSet = - CardSet::newInstance(curSetToParse.getShortName(), curSetToParse.getLongName(), curSetToParse.getSetType(), - curSetToParse.getReleaseDate(), curSetToParse.getPriority()); + CardSetPtr newSet = CardSet::newInstance(SettingsCache::instance().cardDatabase(), curSetToParse.getShortName(), + curSetToParse.getLongName(), curSetToParse.getSetType(), + curSetToParse.getReleaseDate(), curSetToParse.getPriority()); if (!sets.contains(newSet->getShortName())) sets.insert(newSet->getShortName(), newSet); @@ -480,7 +477,7 @@ int OracleImporter::startImport() emit setIndexChanged(numCardsInSet, setIndex, curSetToParse.getLongName()); } - emit setIndexChanged(setCards, setIndex, QString()); + emit setIndexChanged(0, setIndex, QString()); // total number of sets return setIndex; @@ -488,7 +485,7 @@ int OracleImporter::startImport() bool OracleImporter::saveToFile(const QString &fileName, const QString &sourceUrl, const QString &sourceVersion) { - CockatriceXml4Parser parser; + CockatriceXml4Parser parser(new SettingsCardPreferenceProvider()); return parser.saveToFile(sets, cards, fileName, sourceUrl, sourceVersion); } diff --git a/oracle/src/oraclewizard.cpp b/oracle/src/oraclewizard.cpp index eeadfb8be..6b463d5de 100644 --- a/oracle/src/oraclewizard.cpp +++ b/oracle/src/oraclewizard.cpp @@ -1,5 +1,6 @@ #include "oraclewizard.h" +#include "client/settings/cache_settings.h" #include "main.h" #include "oracleimporter.h" #include "version_string.h" @@ -24,7 +25,6 @@ #include #include #include -#include #ifdef HAS_LZMA #include "lzma/decompress.h" @@ -637,13 +637,15 @@ void SaveSetsPage::initializePage() retranslateUi(); if (wizard()->downloadedPlainXml) { messageLog->hide(); - return; - } - messageLog->show(); - connect(wizard()->importer, &OracleImporter::setIndexChanged, this, &SaveSetsPage::updateTotalProgress); + } else { + messageLog->show(); + connect(wizard()->importer, &OracleImporter::setIndexChanged, this, &SaveSetsPage::updateTotalProgress); - if (!wizard()->importer->startImport()) { - QMessageBox::critical(this, tr("Error"), tr("No set has been imported.")); + int setsImported = wizard()->importer->startImport(); + + if (setsImported == 0) { + QMessageBox::critical(this, tr("Error"), tr("No set has been imported.")); + } } if (wizard()->backgroundMode) { diff --git a/tests/carddatabase/CMakeLists.txt b/tests/carddatabase/CMakeLists.txt index 4030cb124..4eeffc363 100644 --- a/tests/carddatabase/CMakeLists.txt +++ b/tests/carddatabase/CMakeLists.txt @@ -21,7 +21,6 @@ add_executable(carddatabase_test ${MOCKS_SOURCES} ${VERSION_STRING_CPP} carddata target_link_libraries( carddatabase_test PRIVATE libcockatrice_card - PRIVATE libcockatrice_settings PRIVATE Threads::Threads PRIVATE ${GTEST_BOTH_LIBRARIES} PRIVATE ${TEST_QT_MODULES} @@ -32,21 +31,11 @@ add_test(NAME carddatabase_test COMMAND carddatabase_test) # ------------------------ # Filter String Test # ------------------------ -add_executable( - filter_string_test - ${MOCKS_SOURCES} - ${VERSION_STRING_CPP} - ../../cockatrice/src/filters/filter_card.cpp - ../../cockatrice/src/filters/filter_string.cpp - ../../cockatrice/src/filters/filter_tree.cpp - filter_string_test.cpp - mocks.cpp -) +add_executable(filter_string_test ${MOCKS_SOURCES} ${VERSION_STRING_CPP} filter_string_test.cpp mocks.cpp) target_link_libraries( filter_string_test - PRIVATE libcockatrice_card - PRIVATE libcockatrice_settings + PRIVATE libcockatrice_filters PRIVATE Threads::Threads PRIVATE ${GTEST_BOTH_LIBRARIES} PRIVATE ${TEST_QT_MODULES} diff --git a/tests/carddatabase/carddatabase_test.cpp b/tests/carddatabase/carddatabase_test.cpp index f3de287e5..3fa0e3834 100644 --- a/tests/carddatabase/carddatabase_test.cpp +++ b/tests/carddatabase/carddatabase_test.cpp @@ -1,14 +1,17 @@ #include "mocks.h" +#include "test_card_database_path_provider.h" #include "gtest/gtest.h" +#include +#include namespace { TEST(CardDatabaseTest, LoadXml) { - settingsCache = new SettingsCache; - CardDatabase *db = new CardDatabase; + CardDatabase *db = new CardDatabase(nullptr, new NoopCardPreferenceProvider(), new TestCardDatabasePathProvider(), + new NoopCardSetPriorityController()); // ensure the card database is empty at start ASSERT_EQ(0, db->getCardList().size()) << "Cards not empty at start"; diff --git a/tests/carddatabase/filter_string_test.cpp b/tests/carddatabase/filter_string_test.cpp index f0c7d9768..c3e8c6fb7 100644 --- a/tests/carddatabase/filter_string_test.cpp +++ b/tests/carddatabase/filter_string_test.cpp @@ -1,8 +1,10 @@ -#include "../../cockatrice/src/filters/filter_string.h" #include "mocks.h" +#include "test_card_database_path_provider.h" #include "gtest/gtest.h" -#include +#include +#include +#include #define QUERY(name, card, query, match) \ TEST_F(CardQuery, name) \ @@ -18,10 +20,14 @@ class CardQuery : public ::testing::Test protected: void SetUp() override { - cat = CardDatabaseManager::query()->getCardBySimpleName("Cat"); - notDeadAfterAll = CardDatabaseManager::query()->getCardBySimpleName("Not Dead"); - truth = CardDatabaseManager::query()->getCardBySimpleName("Truth"); - doctor = CardDatabaseManager::query()->getCardBySimpleName("Doctor"); + CardDatabase *db = new CardDatabase(nullptr, new NoopCardPreferenceProvider(), + new TestCardDatabasePathProvider(), new NoopCardSetPriorityController()); + db->loadCardDatabases(); + + cat = db->query()->getCardBySimpleName("Cat"); + notDeadAfterAll = db->query()->getCardBySimpleName("Not Dead"); + truth = db->query()->getCardBySimpleName("Truth"); + doctor = db->query()->getCardBySimpleName("Doctor"); } // void TearDown() override {} @@ -69,9 +75,6 @@ QUERY(Color4, cat, "c!gw", false) int main(int argc, char **argv) { - settingsCache = new SettingsCache; - CardDatabaseManager::getInstance()->loadCardDatabases(); - ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/tests/carddatabase/mocks.cpp b/tests/carddatabase/mocks.cpp index 7d46a68c2..5568ac84f 100644 --- a/tests/carddatabase/mocks.cpp +++ b/tests/carddatabase/mocks.cpp @@ -1,464 +1,6 @@ #include "mocks.h" -CardDatabaseSettings::CardDatabaseSettings(const QString &settingPath, QObject *parent) - : SettingsManager(settingPath + "cardDatabase.ini", parent) -{ -} -void CardDatabaseSettings::setSortKey(QString /* shortName */, unsigned int /* sortKey */) -{ -} -void CardDatabaseSettings::setEnabled(QString /* shortName */, bool /* enabled */) -{ -} -void CardDatabaseSettings::setIsKnown(QString /* shortName */, bool /* isknown */) -{ -} -unsigned int CardDatabaseSettings::getSortKey(QString /* shortName */) -{ - return 0; -}; -bool CardDatabaseSettings::isEnabled(QString /* shortName */) -{ - return true; -}; -bool CardDatabaseSettings::isKnown(QString /* shortName */) -{ - return true; -}; - -QString SettingsCache::getDataPath() -{ - return ""; -} -QString SettingsCache::getSettingsPath() -{ - return ""; -} -void SettingsCache::translateLegacySettings() -{ -} -QString SettingsCache::getSafeConfigPath(QString /* configEntry */, QString defaultPath) const -{ - return defaultPath; -} -QString SettingsCache::getSafeConfigFilePath(QString /* configEntry */, QString defaultPath) const -{ - return defaultPath; -} -SettingsCache::SettingsCache() - : settings{new QSettings("global.ini", QSettings::IniFormat, this)}, shortcutsSettings{nullptr}, - cardDatabaseSettings{new CardDatabaseSettings("", this)}, serversSettings{nullptr}, messageSettings{nullptr}, - gameFiltersSettings{nullptr}, layoutsSettings{nullptr}, downloadSettings{nullptr}, - cardDatabasePath{QString("%1/cards.xml").arg(CARDDB_DATADIR)}, - customCardDatabasePath{QString("%1/customsets/").arg(CARDDB_DATADIR)}, - spoilerDatabasePath{QString("%1/spoiler.xml").arg(CARDDB_DATADIR)}, - tokenDatabasePath{QString("%1/tokens.xml").arg(CARDDB_DATADIR)} -{ -} -void SettingsCache::setUseTearOffMenus(bool /* _useTearOffMenus */) -{ -} -void SettingsCache::setCardViewInitialRowsMax(int /* _cardViewInitialRowsMax */) -{ -} -void SettingsCache::setCardViewExpandedRowsMax(int /* value */) -{ -} -void SettingsCache::setCloseEmptyCardView(QT_STATE_CHANGED_T /* value */) -{ -} -void SettingsCache::setFocusCardViewSearchBar(QT_STATE_CHANGED_T /* value */) -{ -} -void SettingsCache::setKnownMissingFeatures(const QString & /* _knownMissingFeatures */) -{ -} -void SettingsCache::setCardInfoViewMode(const int /* _viewMode */) -{ -} -void SettingsCache::setHighlightWords(const QString & /* _highlightWords */) -{ -} -void SettingsCache::setMasterVolume(int /* _masterVolume */) -{ -} -void SettingsCache::setLeftJustified(const QT_STATE_CHANGED_T /* _leftJustified */) -{ -} -void SettingsCache::setCardScaling(const QT_STATE_CHANGED_T /* _scaleCards */) -{ -} -void SettingsCache::setStackCardOverlapPercent(const int /* _verticalCardOverlapPercent */) -{ -} -void SettingsCache::setShowMessagePopups(const QT_STATE_CHANGED_T /* _showMessagePopups */) -{ -} -void SettingsCache::setShowMentionPopups(const QT_STATE_CHANGED_T /* _showMentionPopus */) -{ -} -void SettingsCache::setRoomHistory(const QT_STATE_CHANGED_T /* _roomHistory */) -{ -} -void SettingsCache::setLang(const QString & /* _lang */) -{ -} -void SettingsCache::setShowTipsOnStartup(bool /* _showTipsOnStartup */) -{ -} -void SettingsCache::setSeenTips(const QList & /* _seenTips */) -{ -} -void SettingsCache::setDeckPath(const QString & /* _deckPath */) -{ -} -void SettingsCache::setFiltersPath(const QString & /*_filtersPath */) -{ -} -void SettingsCache::setReplaysPath(const QString & /* _replaysPath */) -{ -} -void SettingsCache::setThemesPath(const QString & /* _themesPath */) -{ -} -void SettingsCache::setPicsPath(const QString & /* _picsPath */) -{ -} -void SettingsCache::setCardDatabasePath(const QString & /* _cardDatabasePath */) -{ -} -void SettingsCache::setCustomCardDatabasePath(const QString & /* _customCardDatabasePath */) -{ -} -void SettingsCache::setSpoilerDatabasePath(const QString & /* _spoilerDatabasePath */) -{ -} -void SettingsCache::setTokenDatabasePath(const QString & /* _tokenDatabasePath */) -{ -} -void SettingsCache::setThemeName(const QString & /* _themeName */) -{ -} -void SettingsCache::setHomeTabBackgroundSource(const QString & /* _backgroundSource */) -{ -} -void SettingsCache::setHomeTabBackgroundShuffleFrequency(int /* frequency */) -{ -} -void SettingsCache::setTabVisualDeckStorageOpen(bool /*value*/) -{ -} -void SettingsCache::setTabServerOpen(bool /*value*/) -{ -} -void SettingsCache::setTabAccountOpen(bool /*value*/) -{ -} -void SettingsCache::setTabDeckStorageOpen(bool /*value*/) -{ -} -void SettingsCache::setTabReplaysOpen(bool /*value*/) -{ -} -void SettingsCache::setTabAdminOpen(bool /*value*/) -{ -} -void SettingsCache::setTabLogOpen(bool /*value*/) -{ -} -void SettingsCache::setPicDownload(QT_STATE_CHANGED_T /* _picDownload */) -{ -} -void SettingsCache::setShowStatusBar(bool /* value */) -{ -} -void SettingsCache::setNotificationsEnabled(QT_STATE_CHANGED_T /* _notificationsEnabled */) -{ -} -void SettingsCache::setSpectatorNotificationsEnabled(QT_STATE_CHANGED_T /* _spectatorNotificationsEnabled */) -{ -} -void SettingsCache::setBuddyConnectNotificationsEnabled(QT_STATE_CHANGED_T /* _buddyConnectNotificationsEnabled */) -{ -} -void SettingsCache::setDoubleClickToPlay(QT_STATE_CHANGED_T /* _doubleClickToPlay */) -{ -} -void SettingsCache::setClickPlaysAllSelected(QT_STATE_CHANGED_T /* _clickPlaysAllSelected */) -{ -} -void SettingsCache::setPlayToStack(QT_STATE_CHANGED_T /* _playToStack */) -{ -} -void SettingsCache::setStartingHandSize(int /* _startingHandSize */) -{ -} -void SettingsCache::setAnnotateTokens(QT_STATE_CHANGED_T /* _annotateTokens */) -{ -} -void SettingsCache::setTabGameSplitterSizes(const QByteArray & /* _tabGameSplitterSizes */) -{ -} -void SettingsCache::setShowShortcuts(QT_STATE_CHANGED_T /* _showShortcuts */) -{ -} -void SettingsCache::setDisplayCardNames(QT_STATE_CHANGED_T /* _displayCardNames */) -{ -} -void SettingsCache::setOverrideAllCardArtWithPersonalPreference(QT_STATE_CHANGED_T /* _overrideAllCardArt */) -{ -} -void SettingsCache::setBumpSetsWithCardsInDeckToTop(QT_STATE_CHANGED_T /* _bumpSetsWithCardsInDeckToTop */) -{ -} -void SettingsCache::setPrintingSelectorSortOrder(int /* _printingSelectorSortOrder */) -{ -} -void SettingsCache::setPrintingSelectorCardSize(int /* _printingSelectorCardSize */) -{ -} -void SettingsCache::setIncludeRebalancedCards(bool /* _includeRebalancedCards */) -{ -} -void SettingsCache::setPrintingSelectorNavigationButtonsVisible(QT_STATE_CHANGED_T /* _navigationButtonsVisible */) -{ -} -void SettingsCache::setDeckEditorBannerCardComboBoxVisible( - QT_STATE_CHANGED_T /* _deckEditorBannerCardComboBoxVisible */) -{ -} -void SettingsCache::setDeckEditorTagsWidgetVisible(QT_STATE_CHANGED_T /* _deckEditorTagsWidgetVisible */) -{ -} -void SettingsCache::setVisualDeckStorageSortingOrder(int /* _visualDeckStorageSortingOrder */) -{ -} -void SettingsCache::setVisualDeckStorageShowFolders(QT_STATE_CHANGED_T /* value */) -{ -} -void SettingsCache::setVisualDeckStorageShowTagFilter(QT_STATE_CHANGED_T /* _showTags */) -{ -} -void SettingsCache::setVisualDeckStorageDefaultTagsList(QStringList /* _defaultTagsList */) -{ -} -void SettingsCache::setVisualDeckStorageSearchFolderNames(QT_STATE_CHANGED_T /* value */) -{ -} -void SettingsCache::setVisualDeckStorageShowBannerCardComboBox(QT_STATE_CHANGED_T /* _showBannerCardComboBox */) -{ -} -void SettingsCache::setVisualDeckStorageShowTagsOnDeckPreviews(QT_STATE_CHANGED_T /* _showTags */) -{ -} -void SettingsCache::setVisualDeckStorageCardSize(int /* _visualDeckStorageCardSize */) -{ -} -void SettingsCache::setVisualDeckStorageDrawUnusedColorIdentities( - QT_STATE_CHANGED_T /* _visualDeckStorageDrawUnusedColorIdentities */) -{ -} -void SettingsCache::setVisualDeckStorageUnusedColorIdentitiesOpacity( - int /* _visualDeckStorageUnusedColorIdentitiesOpacity */) -{ -} -void SettingsCache::setVisualDeckStorageTooltipType(int /* value */) -{ -} -void SettingsCache::setVisualDeckStoragePromptForConversion(bool /* _visualDeckStoragePromptForConversion */) -{ -} -void SettingsCache::setVisualDeckStorageAlwaysConvert(bool /* _visualDeckStorageAlwaysConvert */) -{ -} -void SettingsCache::setVisualDeckStorageInGame(QT_STATE_CHANGED_T /* value */) -{ -} -void SettingsCache::setVisualDeckStorageSelectionAnimation(QT_STATE_CHANGED_T /* value */) -{ -} -void SettingsCache::setDefaultDeckEditorType(int /* value */) -{ -} -void SettingsCache::setVisualDatabaseDisplayFilterToMostRecentSetsEnabled(QT_STATE_CHANGED_T /* _enabled */) -{ -} -void SettingsCache::setVisualDatabaseDisplayFilterToMostRecentSetsAmount(int /* _amount */) -{ -} -void SettingsCache::setVisualDeckEditorSampleHandSize(int /* _amount */) -{ -} -void SettingsCache::setHorizontalHand(QT_STATE_CHANGED_T /* _horizontalHand */) -{ -} -void SettingsCache::setInvertVerticalCoordinate(QT_STATE_CHANGED_T /* _invertVerticalCoordinate */) -{ -} -void SettingsCache::setMinPlayersForMultiColumnLayout(int /* _minPlayersForMultiColumnLayout */) -{ -} -void SettingsCache::setTapAnimation(QT_STATE_CHANGED_T /* _tapAnimation */) -{ -} -void SettingsCache::setAutoRotateSidewaysLayoutCards(QT_STATE_CHANGED_T /* _autoRotateSidewaysLayoutCards */) -{ -} -void SettingsCache::setOpenDeckInNewTab(QT_STATE_CHANGED_T /* _openDeckInNewTab */) -{ -} -void SettingsCache::setRewindBufferingMs(int /* _rewindBufferingMs */) -{ -} -void SettingsCache::setChatMention(QT_STATE_CHANGED_T /* _chatMention */) -{ -} -void SettingsCache::setChatMentionCompleter(const QT_STATE_CHANGED_T /* _enableMentionCompleter */) -{ -} -void SettingsCache::setChatMentionForeground(QT_STATE_CHANGED_T /* _chatMentionForeground */) -{ -} -void SettingsCache::setChatHighlightForeground(QT_STATE_CHANGED_T /* _chatHighlightForeground */) -{ -} -void SettingsCache::setChatMentionColor(const QString & /* _chatMentionColor */) -{ -} -void SettingsCache::setChatHighlightColor(const QString & /* _chatHighlightColor */) -{ -} -void SettingsCache::setZoneViewGroupByIndex(int /* _zoneViewGroupByIndex */) -{ -} -void SettingsCache::setZoneViewSortByIndex(int /* _zoneViewSortByIndex */) -{ -} -void SettingsCache::setZoneViewPileView(QT_STATE_CHANGED_T /* _zoneViewPileView */) -{ -} -void SettingsCache::setSoundEnabled(QT_STATE_CHANGED_T /* _soundEnabled */) -{ -} -void SettingsCache::setSoundThemeName(const QString & /* _soundThemeName */) -{ -} -void SettingsCache::setIgnoreUnregisteredUsers(QT_STATE_CHANGED_T /* _ignoreUnregisteredUsers */) -{ -} -void SettingsCache::setIgnoreUnregisteredUserMessages(QT_STATE_CHANGED_T /* _ignoreUnregisteredUserMessages */) -{ -} -void SettingsCache::setMainWindowGeometry(const QByteArray & /* _mainWindowGeometry */) -{ -} -void SettingsCache::setTokenDialogGeometry(const QByteArray & /* _tokenDialogGeometry */) -{ -} -void SettingsCache::setSetsDialogGeometry(const QByteArray & /* _setsDialogGeometry */) -{ -} -void SettingsCache::setPixmapCacheSize(const int /* _pixmapCacheSize */) -{ -} -void SettingsCache::setNetworkCacheSizeInMB(const int /* _networkCacheSize */) -{ -} -void SettingsCache::setNetworkRedirectCacheTtl(const int /* _redirectCacheTtl */) -{ -} -void SettingsCache::setClientID(const QString & /* _clientID */) -{ -} -void SettingsCache::setClientVersion(const QString & /* _clientVersion */) -{ -} -QStringList SettingsCache::getCountries() const -{ - static QStringList countries = QStringList() << "us"; - return countries; -} -void SettingsCache::setGameDescription(const QString /* _gameDescription */) -{ -} -void SettingsCache::setMaxPlayers(const int /* _maxPlayers */) -{ -} -void SettingsCache::setGameTypes(const QString /* _gameTypes */) -{ -} -void SettingsCache::setOnlyBuddies(const bool /* _onlyBuddies */) -{ -} -void SettingsCache::setOnlyRegistered(const bool /* _onlyRegistered */) -{ -} -void SettingsCache::setSpectatorsAllowed(const bool /* _spectatorsAllowed */) -{ -} -void SettingsCache::setSpectatorsNeedPassword(const bool /* _spectatorsNeedPassword */) -{ -} -void SettingsCache::setSpectatorsCanTalk(const bool /* _spectatorsCanTalk */) -{ -} -void SettingsCache::setSpectatorsCanSeeEverything(const bool /* _spectatorsCanSeeEverything */) -{ -} -void SettingsCache::setCreateGameAsSpectator(const bool /* _createGameAsSpectator */) -{ -} -void SettingsCache::setDefaultStartingLifeTotal(const int /* _startingLifeTotal */) -{ -} -void SettingsCache::setShareDecklistsOnLoad(const bool /* _shareDecklistsOnLoad */) -{ -} -void SettingsCache::setRememberGameSettings(const bool /* _rememberGameSettings */) -{ -} -void SettingsCache::setCheckUpdatesOnStartup(QT_STATE_CHANGED_T /* value */) -{ -} -void SettingsCache::setStartupCardUpdateCheckPromptForUpdate(bool /* value */) -{ -} -void SettingsCache::setStartupCardUpdateCheckAlwaysUpdate(bool /* value */) -{ -} -void SettingsCache::setCardUpdateCheckInterval(int /* value */) -{ -} -void SettingsCache::setLastCardUpdateCheck(QDate /* value */) -{ -} -void SettingsCache::setNotifyAboutUpdate(QT_STATE_CHANGED_T /* _notifyaboutupdate */) -{ -} -void SettingsCache::setNotifyAboutNewVersion(QT_STATE_CHANGED_T /* _notifyaboutnewversion */) -{ -} -void SettingsCache::setDownloadSpoilerStatus(bool /* _spoilerStatus */) -{ -} -void SettingsCache::setUpdateReleaseChannelIndex(int /* value */) -{ -} -void SettingsCache::setMaxFontSize(int /* _max */) -{ -} -void SettingsCache::setRoundCardCorners(bool /* _roundCardCorners */) -{ -} - void CardPictureLoader::clearPixmapCache(CardInfoPtr /* card */) { } - -SettingsCache *settingsCache; - -SettingsCache &SettingsCache::instance() -{ - return *settingsCache; -} diff --git a/tests/carddatabase/mocks.h b/tests/carddatabase/mocks.h index 497f76e72..016642005 100644 --- a/tests/carddatabase/mocks.h +++ b/tests/carddatabase/mocks.h @@ -5,16 +5,9 @@ * with mocked objects. */ -#include -#include - #define PICTURELOADER_H #include -#include -#include - -extern SettingsCache *settingsCache; class CardPictureLoader { diff --git a/tests/carddatabase/test_card_database_path_provider.h b/tests/carddatabase/test_card_database_path_provider.h new file mode 100644 index 000000000..8fc8ef962 --- /dev/null +++ b/tests/carddatabase/test_card_database_path_provider.h @@ -0,0 +1,28 @@ +#ifndef COCKATRICE_TEST_CARD_DATABASE_PATH_PROVIDER_H +#define COCKATRICE_TEST_CARD_DATABASE_PATH_PROVIDER_H + +#include + +class TestCardDatabasePathProvider : public ICardDatabasePathProvider +{ + +public: + QString getCardDatabasePath() const override + { + return QString("%1/cards.xml").arg(CARDDB_DATADIR); + } + QString getCustomCardDatabasePath() const override + { + return QString("%1/customsets/").arg(CARDDB_DATADIR); + } + QString getTokenDatabasePath() const override + { + return QString("%1/tokens.xml").arg(CARDDB_DATADIR); + } + QString getSpoilerCardDatabasePath() const override + { + return QString("%1/spoiler.xml").arg(CARDDB_DATADIR); + } +}; + +#endif // COCKATRICE_TEST_CARD_DATABASE_PATH_PROVIDER_H