From 71ef36374d837e58ee56a7c46fd8ff687a7917fc Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Wed, 23 Sep 2026 19:19:30 +0200 Subject: [PATCH 1/2] [DeckEditor] Show card counts in Visual Deck Editor banners (#7339) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Lukas BrĂ¼bach --- .../card_group_display_widget.cpp | 28 ++++++++++++++++- .../card_group_display_widget.h | 1 + .../cards/deck_card_zone_display_widget.cpp | 26 ++++++++++++++++ .../cards/deck_card_zone_display_widget.h | 1 + .../user_interface_settings_page.cpp | 31 ++++++++++++------- .../user_interface_settings_page.h | 1 + ...nterface_cards_display_settings_provider.h | 1 + .../settings/cards_display_settings.cpp | 14 +++++++++ .../settings/cards_display_settings.h | 3 ++ tests/settings/settings_defaults_test.cpp | 15 +++++++++ 10 files changed, 108 insertions(+), 13 deletions(-) diff --git a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp index bfbdd7e42..a062a2026 100644 --- a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp @@ -1,11 +1,13 @@ #include "card_group_display_widget.h" +#include "../../../../client/settings/cache_settings.h" #include "../card_info_picture_with_text_overlay_widget.h" #include #include #include #include +#include CardGroupDisplayWidget::CardGroupDisplayWidget(QWidget *parent, DeckListModel *_deckListModel, @@ -30,6 +32,7 @@ CardGroupDisplayWidget::CardGroupDisplayWidget(QWidget *parent, layout->addWidget(banner); CardGroupDisplayWidget::updateCardDisplays(); + updateCardCount(); connect(deckListModel, &QAbstractItemModel::rowsInserted, this, &CardGroupDisplayWidget::onCardAddition); if (selectionModel) { @@ -38,6 +41,11 @@ CardGroupDisplayWidget::CardGroupDisplayWidget(QWidget *parent, } connect(deckListModel, &QAbstractItemModel::rowsRemoved, this, &CardGroupDisplayWidget::onCardRemoval); connect(deckListModel, &QAbstractItemModel::dataChanged, this, &CardGroupDisplayWidget::onDataChanged); + connect(deckListModel, &QAbstractItemModel::rowsInserted, this, &CardGroupDisplayWidget::updateCardCount); + connect(deckListModel, &QAbstractItemModel::rowsRemoved, this, &CardGroupDisplayWidget::updateCardCount); + connect(deckListModel, &QAbstractItemModel::dataChanged, this, &CardGroupDisplayWidget::updateCardCount); + connect(&SettingsCache::instance().cardsDisplay(), &CardsDisplaySettings::visualDeckEditorShowCardCountsChanged, + this, &CardGroupDisplayWidget::updateCardCount); } // Just here so it can get overwritten in subclasses. @@ -348,4 +356,22 @@ void CardGroupDisplayWidget::onActiveSortCriteriaChanged(QStringList _activeSort clearAllDisplayWidgets(); updateCardDisplays(); -} \ No newline at end of file +} + +void CardGroupDisplayWidget::updateCardCount() +{ + if (!banner || !deckListModel || !trackedIndex.isValid()) { + return; + } + + QString text = cardGroupCategory; + if (SettingsCache::instance().cardsDisplay().getVisualDeckEditorShowCardCounts()) { + int total = 0; + for (int i = 0; i < deckListModel->rowCount(trackedIndex); ++i) { + total += + deckListModel->index(i, DeckListModelColumns::CARD_AMOUNT, trackedIndex).data(Qt::EditRole).toInt(); + } + text += QStringLiteral(" (%1)").arg(total); + } + banner->setText(text); +} diff --git a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.h b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.h index a3bf70981..e5f7c7ee2 100644 --- a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.h @@ -55,6 +55,7 @@ public slots: virtual void onCardRemoval(const QModelIndex &parent, int first, int last); void onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles); void onActiveSortCriteriaChanged(QStringList activeSortCriteria); + void updateCardCount(); void resizeEvent(QResizeEvent *event) override; signals: diff --git a/cockatrice/src/interface/widgets/cards/deck_card_zone_display_widget.cpp b/cockatrice/src/interface/widgets/cards/deck_card_zone_display_widget.cpp index b00d9db1e..a4b4eaf54 100644 --- a/cockatrice/src/interface/widgets/cards/deck_card_zone_display_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/deck_card_zone_display_widget.cpp @@ -1,8 +1,10 @@ #include "deck_card_zone_display_widget.h" +#include "../../../client/settings/cache_settings.h" #include "card_group_display_widgets/flat_card_group_display_widget.h" #include "card_group_display_widgets/overlapped_card_group_display_widget.h" #include "libcockatrice/card/database/card_database_manager.h" +#include "libcockatrice/settings/cards_display_settings.h" #include #include @@ -39,6 +41,7 @@ DeckCardZoneDisplayWidget::DeckCardZoneDisplayWidget(QWidget *parent, banner->setBuddy(cardGroupContainer); displayCards(); + updateZoneCardCount(); connect(deckListModel, &QAbstractItemModel::rowsInserted, this, &DeckCardZoneDisplayWidget::onCategoryAddition); if (selectionModel) { @@ -46,6 +49,11 @@ DeckCardZoneDisplayWidget::DeckCardZoneDisplayWidget(QWidget *parent, &DeckCardZoneDisplayWidget::onSelectionChanged); } connect(deckListModel, &QAbstractItemModel::rowsRemoved, this, &DeckCardZoneDisplayWidget::onCategoryRemoval); + connect(deckListModel, &QAbstractItemModel::rowsInserted, this, &DeckCardZoneDisplayWidget::updateZoneCardCount); + connect(deckListModel, &QAbstractItemModel::rowsRemoved, this, &DeckCardZoneDisplayWidget::updateZoneCardCount); + connect(deckListModel, &QAbstractItemModel::dataChanged, this, &DeckCardZoneDisplayWidget::updateZoneCardCount); + connect(&SettingsCache::instance().cardsDisplay(), &CardsDisplaySettings::visualDeckEditorShowCardCountsChanged, + this, &DeckCardZoneDisplayWidget::updateZoneCardCount); } // ===================================================================================================================== @@ -245,3 +253,21 @@ QList DeckCardZoneDisplayWidget::getGroupCriteriaValueList() return groupCriteriaValues; } + +void DeckCardZoneDisplayWidget::updateZoneCardCount() +{ + if (!banner || !deckListModel) { + return; + } + + QString text = zoneName; + if (SettingsCache::instance().cardsDisplay().getVisualDeckEditorShowCardCounts()) { + int total = 0; + const auto cardNodes = deckListModel->getCardNodesForZone(zoneName); + for (const auto *node : cardNodes) { + total += node->getNumber(); + } + text += QStringLiteral(" (%1)").arg(total); + } + banner->setText(text); +} diff --git a/cockatrice/src/interface/widgets/cards/deck_card_zone_display_widget.h b/cockatrice/src/interface/widgets/cards/deck_card_zone_display_widget.h index 53f3fa7cf..f25108834 100644 --- a/cockatrice/src/interface/widgets/cards/deck_card_zone_display_widget.h +++ b/cockatrice/src/interface/widgets/cards/deck_card_zone_display_widget.h @@ -52,6 +52,7 @@ public slots: QList getGroupCriteriaValueList(); void onCategoryAddition(const QModelIndex &parent, int first, int last); void onCategoryRemoval(const QModelIndex &parent, int first, int last); + void updateZoneCardCount(); signals: void cardClicked(QMouseEvent *event, const ExactCard &card, const QString &zoneName); diff --git a/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.cpp b/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.cpp index 2c6e062da..03b9455fa 100644 --- a/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.cpp +++ b/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.cpp @@ -149,6 +149,11 @@ UserInterfaceSettingsPage::UserInterfaceSettingsPage() connect(&openDeckInNewTabCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance().deckEditor(), &DeckEditorSettings::setOpenDeckInNewTab); + visualDeckEditorShowCardCountsCheckBox.setChecked( + SettingsCache::instance().cardsDisplay().getVisualDeckEditorShowCardCounts()); + connect(&visualDeckEditorShowCardCountsCheckBox, &QCheckBox::QT_STATE_CHANGED, + &SettingsCache::instance().cardsDisplay(), &CardsDisplaySettings::setVisualDeckEditorShowCardCounts); + visualDeckStorageInGameCheckBox.setChecked( SettingsCache::instance().visualDeckStorage().getVisualDeckStorageInGame()); connect(&visualDeckStorageInGameCheckBox, &QCheckBox::QT_STATE_CHANGED, @@ -244,18 +249,19 @@ UserInterfaceSettingsPage::UserInterfaceSettingsPage() auto *deckEditorGrid = new QGridLayout; deckEditorGrid->addWidget(&openDeckInNewTabCheckBox, 0, 0); - deckEditorGrid->addWidget(&visualDeckStorageInGameCheckBox, 1, 0); - deckEditorGrid->addWidget(&visualDeckStorageSelectionAnimationCheckBox, 2, 0); - deckEditorGrid->addWidget(&visualDeckStoragePromptForConversionLabel, 3, 0); - deckEditorGrid->addWidget(&visualDeckStoragePromptForConversionSelector, 3, 1); - deckEditorGrid->addWidget(&defaultDeckEditorTypeLabel, 4, 0); - deckEditorGrid->addWidget(&defaultDeckEditorTypeSelector, 4, 1); - deckEditorGrid->addWidget(&vdeStartupTabLabel, 5, 0); - deckEditorGrid->addWidget(&vdeStartupTabSelector, 5, 1); - deckEditorGrid->addWidget(&commanderSpellbookIntegrationEnabledLabel, 6, 0); - deckEditorGrid->addWidget(&commanderSpellbookIntegrationEnabledSelector, 6, 1); - deckEditorGrid->addWidget(labelWidget, 7, 0); - deckEditorGrid->addWidget(&commanderSpellbookIntegrationBracketNamingSelector, 7, 1); + deckEditorGrid->addWidget(&visualDeckEditorShowCardCountsCheckBox, 1, 0); + deckEditorGrid->addWidget(&visualDeckStorageInGameCheckBox, 2, 0); + deckEditorGrid->addWidget(&visualDeckStorageSelectionAnimationCheckBox, 3, 0); + deckEditorGrid->addWidget(&visualDeckStoragePromptForConversionLabel, 4, 0); + deckEditorGrid->addWidget(&visualDeckStoragePromptForConversionSelector, 4, 1); + deckEditorGrid->addWidget(&defaultDeckEditorTypeLabel, 5, 0); + deckEditorGrid->addWidget(&defaultDeckEditorTypeSelector, 5, 1); + deckEditorGrid->addWidget(&vdeStartupTabLabel, 6, 0); + deckEditorGrid->addWidget(&vdeStartupTabSelector, 6, 1); + deckEditorGrid->addWidget(&commanderSpellbookIntegrationEnabledLabel, 7, 0); + deckEditorGrid->addWidget(&commanderSpellbookIntegrationEnabledSelector, 7, 1); + deckEditorGrid->addWidget(labelWidget, 8, 0); + deckEditorGrid->addWidget(&commanderSpellbookIntegrationBracketNamingSelector, 8, 1); deckEditorGroupBox = new QGroupBox; deckEditorGroupBox->setLayout(deckEditorGrid); @@ -367,6 +373,7 @@ void UserInterfaceSettingsPage::retranslateUi() deckEditorGroupBox->setTitle(tr("Deck editor/storage settings")); openDeckInNewTabCheckBox.setText(tr("Open deck in new tab by default")); + visualDeckEditorShowCardCountsCheckBox.setText(tr("Show card counts in Visual Deck Editor")); visualDeckStorageInGameCheckBox.setText(tr("Use visual deck storage in game lobby")); visualDeckStorageSelectionAnimationCheckBox.setText(tr("Use selection animation for Visual Deck Storage")); visualDeckStoragePromptForConversionLabel.setText( diff --git a/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.h b/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.h index e8a30fb1f..277c5461e 100644 --- a/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.h +++ b/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.h @@ -51,6 +51,7 @@ private: QComboBox visualDeckStoragePromptForConversionSelector; QCheckBox visualDeckStorageInGameCheckBox; QCheckBox visualDeckStorageSelectionAnimationCheckBox; + QCheckBox visualDeckEditorShowCardCountsCheckBox; QLabel defaultDeckEditorTypeLabel; QComboBox defaultDeckEditorTypeSelector; QLabel vdeStartupTabLabel; diff --git a/libcockatrice_interfaces/libcockatrice/interfaces/interface_cards_display_settings_provider.h b/libcockatrice_interfaces/libcockatrice/interfaces/interface_cards_display_settings_provider.h index 900f51f2b..2821fb96e 100644 --- a/libcockatrice_interfaces/libcockatrice/interfaces/interface_cards_display_settings_provider.h +++ b/libcockatrice_interfaces/libcockatrice/interfaces/interface_cards_display_settings_provider.h @@ -25,6 +25,7 @@ public: [[nodiscard]] virtual int getVisualDeckStorageCardSize() const = 0; [[nodiscard]] virtual int getVisualDatabaseDisplayCardSize() const = 0; [[nodiscard]] virtual int getVisualDeckEditorCardSize() const = 0; + [[nodiscard]] virtual bool getVisualDeckEditorShowCardCounts() const = 0; [[nodiscard]] virtual int getEDHRecCardSize() const = 0; [[nodiscard]] virtual int getArchidektPreviewSize() const = 0; [[nodiscard]] virtual int getSampleHandSize() const = 0; diff --git a/libcockatrice_settings/libcockatrice/settings/cards_display_settings.cpp b/libcockatrice_settings/libcockatrice/settings/cards_display_settings.cpp index 94e888504..3af607198 100644 --- a/libcockatrice_settings/libcockatrice/settings/cards_display_settings.cpp +++ b/libcockatrice_settings/libcockatrice/settings/cards_display_settings.cpp @@ -90,6 +90,11 @@ int CardsDisplaySettings::getVisualDeckEditorCardSize() const return getValue("visualDeckEditor", "cards", "cardSize", 100).toInt(); } +bool CardsDisplaySettings::getVisualDeckEditorShowCardCounts() const +{ + return getValue("visualDeckEditorShowCardCounts", QString(), QString(), true).toBool(); +} + int CardsDisplaySettings::getEDHRecCardSize() const { return getValue("edhrec", "cards", "cardSize", 100).toInt(); @@ -217,6 +222,15 @@ void CardsDisplaySettings::setVisualDeckEditorCardSize(int _cardSize) emit visualDeckEditorCardSizeChanged(); } +void CardsDisplaySettings::setVisualDeckEditorShowCardCounts(bool _showCardCounts) +{ + if (_showCardCounts == getVisualDeckEditorShowCardCounts()) { + return; + } + setValue(_showCardCounts, "visualDeckEditorShowCardCounts"); + emit visualDeckEditorShowCardCountsChanged(_showCardCounts); +} + void CardsDisplaySettings::setEDHRecCardSize(int _edhrecCardSize) { setValue(_edhrecCardSize, "edhrec", "cards", "cardSize"); diff --git a/libcockatrice_settings/libcockatrice/settings/cards_display_settings.h b/libcockatrice_settings/libcockatrice/settings/cards_display_settings.h index 85eb5adbd..77924d14c 100644 --- a/libcockatrice_settings/libcockatrice/settings/cards_display_settings.h +++ b/libcockatrice_settings/libcockatrice/settings/cards_display_settings.h @@ -29,6 +29,7 @@ public: [[nodiscard]] int getVisualDeckStorageCardSize() const override; [[nodiscard]] int getVisualDatabaseDisplayCardSize() const override; [[nodiscard]] int getVisualDeckEditorCardSize() const override; + [[nodiscard]] bool getVisualDeckEditorShowCardCounts() const override; [[nodiscard]] int getEDHRecCardSize() const override; [[nodiscard]] int getArchidektPreviewSize() const override; [[nodiscard]] int getSampleHandSize() const override; @@ -52,6 +53,7 @@ public: void setVisualDeckStorageCardSize(int _cardSize); void setVisualDatabaseDisplayCardSize(int _cardSize); void setVisualDeckEditorCardSize(int _cardSize); + void setVisualDeckEditorShowCardCounts(bool _showCardCounts); void setEDHRecCardSize(int _edhrecCardSize); void setArchidektPreviewCardSize(int _archidektPreviewCardSize); void setSampleHandSize(int _sampleHandSize); @@ -70,6 +72,7 @@ signals: void visualDeckStorageCardSizeChanged(); void visualDatabaseDisplayCardSizeChanged(); void visualDeckEditorCardSizeChanged(); + void visualDeckEditorShowCardCountsChanged(bool showCardCounts); void edhRecCardSizeChanged(); void archidektPreviewSizeChanged(); void sampleHandSizeChanged(int amount); diff --git a/tests/settings/settings_defaults_test.cpp b/tests/settings/settings_defaults_test.cpp index 87b21f015..56555eae6 100644 --- a/tests/settings/settings_defaults_test.cpp +++ b/tests/settings/settings_defaults_test.cpp @@ -570,6 +570,21 @@ TEST_F(SettingsDefaultsTest, CardsDisplay_VisualDeckEditorCardSize_Default) ASSERT_EQ(s.getVisualDeckEditorCardSize(), 100); } +TEST_F(SettingsDefaultsTest, CardsDisplay_VisualDeckEditorShowCardCounts_Default) +{ + CardsDisplaySettings s(settingsPath, nullptr); + ASSERT_EQ(s.getVisualDeckEditorShowCardCounts(), true); +} + +TEST_F(SettingsDefaultsTest, CardsDisplay_VisualDeckEditorShowCardCounts_SetAndGet) +{ + CardsDisplaySettings s(settingsPath, nullptr); + s.setVisualDeckEditorShowCardCounts(false); + ASSERT_EQ(s.getVisualDeckEditorShowCardCounts(), false); + s.setVisualDeckEditorShowCardCounts(true); + ASSERT_EQ(s.getVisualDeckEditorShowCardCounts(), true); +} + TEST_F(SettingsDefaultsTest, CardsDisplay_EDHRecCardSize_Default) { CardsDisplaySettings s(settingsPath, nullptr); From a1d8ce6165e33927fb3cc9f0e69e5d8c320cbadf Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Wed, 23 Sep 2026 21:03:34 +0200 Subject: [PATCH 2/2] [Accessibility] Bind card size sliders to Ctrl + Scroll (#7338) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ctrl+scroll over a card display now resizes the cards everywhere a card size slider is shown, matching the standard way of resizing content. CardSizeWidget learns to forward Ctrl+wheel events onto its slider via an event filter that is installed on the display container and, when present, on the scroll area's content widget so the resize intercepts the wheel event before the view scrolls. The existing slider valueChanged wiring then rescales the displayed cards. Applied to the visual deck editor (per card group, covering flat and overlapped layouts), visual database display, printing selector, sample hand, visual and public deck storage, Archidekt previews and EDHRec card displays. Co-authored-by: Lukas BrĂ¼bach --- .../card_group_display_widget.cpp | 2 + .../widgets/cards/card_size_widget.cpp | 39 +++++++++++++++++++ .../widgets/cards/card_size_widget.h | 18 +++++++++ .../printing_selector/printing_selector.cpp | 1 + ..._response_deck_listings_display_widget.cpp | 2 + ...i_response_card_details_display_widget.cpp | 1 + ...ponse_commander_details_display_widget.cpp | 1 + .../widgets/tabs/tab_public_decks.cpp | 2 + .../visual_database_display_widget.cpp | 1 + .../visual_deck_editor_sample_hand_widget.cpp | 1 + ...ual_deck_storage_folder_display_widget.cpp | 3 ++ ...isual_deck_storage_quick_settings_widget.h | 9 +++++ 12 files changed, 80 insertions(+) diff --git a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp index a062a2026..8df3700c3 100644 --- a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp @@ -46,6 +46,8 @@ CardGroupDisplayWidget::CardGroupDisplayWidget(QWidget *parent, connect(deckListModel, &QAbstractItemModel::dataChanged, this, &CardGroupDisplayWidget::updateCardCount); connect(&SettingsCache::instance().cardsDisplay(), &CardsDisplaySettings::visualDeckEditorShowCardCountsChanged, this, &CardGroupDisplayWidget::updateCardCount); + + cardSizeWidget->enableCtrlScrollResize(this); } // Just here so it can get overwritten in subclasses. diff --git a/cockatrice/src/interface/widgets/cards/card_size_widget.cpp b/cockatrice/src/interface/widgets/cards/card_size_widget.cpp index 14e45743d..9cdfd4bce 100644 --- a/cockatrice/src/interface/widgets/cards/card_size_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_size_widget.cpp @@ -3,6 +3,9 @@ #include "../printing_selector/printing_selector.h" #include "../visual_deck_storage/visual_deck_storage_widget.h" +#include +#include + /** * @class CardSizeWidget * @brief A widget for adjusting card sizes using a slider. @@ -58,3 +61,39 @@ QSlider *CardSizeWidget::getSlider() const { return cardSizeSlider; } + +void CardSizeWidget::enableCtrlScrollResize(QWidget *host) +{ + host->installEventFilter(this); + + const auto scrollAreas = host->findChildren(); + for (QScrollArea *scrollArea : scrollAreas) { + if (QWidget *content = scrollArea->widget()) { + content->installEventFilter(this); + } + } +} + +bool CardSizeWidget::eventFilter(QObject *watched, QEvent *event) +{ + if (event->type() == QEvent::Wheel && adjustSliderForWheel(static_cast(event))) { + return true; + } + return QWidget::eventFilter(watched, event); +} + +bool CardSizeWidget::adjustSliderForWheel(QWheelEvent *event) +{ + if (!(event->modifiers() & Qt::ControlModifier)) { + return false; + } + + const int angleDelta = event->angleDelta().y(); + if (angleDelta == 0) { + return false; + } + + const int wheelSteps = angleDelta > 0 ? qMax(1, angleDelta / 120) : qMin(-1, angleDelta / 120); + cardSizeSlider->setValue(cardSizeSlider->value() + wheelSteps * CARD_SIZE_WHEEL_STEP); + return true; +} diff --git a/cockatrice/src/interface/widgets/cards/card_size_widget.h b/cockatrice/src/interface/widgets/cards/card_size_widget.h index 9f4c165fd..46883e792 100644 --- a/cockatrice/src/interface/widgets/cards/card_size_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_size_widget.h @@ -17,6 +17,8 @@ #include #include +class QWheelEvent; + class CardSizeWidget : public QWidget { Q_OBJECT @@ -25,6 +27,18 @@ public: explicit CardSizeWidget(QWidget *parent, FlowWidget *flowWidget = nullptr, int defaultValue = 100); [[nodiscard]] QSlider *getSlider() const; + /** + * @brief Resizes the cards when the user Ctrl + scrolls over @p host or any of its descendants. + * + * Installs this widget as an event filter on the given host widget. If the host contains a + * scroll area the filter is also installed on the scroll area's content widget, so the resize + * intercepts the wheel event before the scroll area would scroll the view. + */ + void enableCtrlScrollResize(QWidget *host); + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + private slots: void updateCardSizeSetting(int newValue); @@ -44,6 +58,10 @@ private: QSlider *cardSizeSlider; QTimer debounceTimer; // Debounce timer int pendingValue; // Stores the latest slider value + + bool adjustSliderForWheel(QWheelEvent *event); + + static constexpr int CARD_SIZE_WHEEL_STEP = 10; ///< Slider step applied per Ctrl + scroll notch. }; #endif // CARD_SIZE_WIDGET_H diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector.cpp b/cockatrice/src/interface/widgets/printing_selector/printing_selector.cpp index 0c3bbbe00..f16b4885c 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector.cpp +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector.cpp @@ -58,6 +58,7 @@ PrintingSelector::PrintingSelector(QWidget *parent, AbstractTabDeckEditor *_deck SettingsCache::instance().cardsDisplay().getPrintingSelectorCardSize()); connect(cardSizeWidget, &CardSizeWidget::cardSizeSettingUpdated, &SettingsCache::instance().cardsDisplay(), &CardsDisplaySettings::setPrintingSelectorCardSize); + cardSizeWidget->enableCtrlScrollResize(flowWidget); displayOptionsWidget->addSettingsWidget(sortToolBar); displayOptionsWidget->addSettingsWidget(navigationCheckBox); diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_listings_display_widget.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_listings_display_widget.cpp index 4d3dfd660..21e8e3f9a 100644 --- a/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_listings_display_widget.cpp +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_listings_display_widget.cpp @@ -15,6 +15,8 @@ ArchidektApiResponseDeckListingsDisplayWidget::ArchidektApiResponseDeckListingsD flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAsNeeded); + cardSizeSlider->enableCtrlScrollResize(flowWidget); + imageNetworkManager = new QNetworkAccessManager(this); imageNetworkManager->setTransferTimeout(); // Use Qt's default timeout imageNetworkManager->setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy); diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.cpp b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.cpp index 9d294f10c..00c1741df 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.cpp +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.cpp @@ -54,6 +54,7 @@ EdhrecApiResponseCardDetailsDisplayWidget::EdhrecApiResponseCardDetailsDisplayWi &CardInfoPictureWidget::setScaleFactor); connect(this, &EdhrecApiResponseCardDetailsDisplayWidget::requestUrl, parentTab, &TabEdhRecMain::actNavigatePage); + parentTab->getCardSizeSlider()->enableCtrlScrollResize(this); } } diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_api_response_commander_details_display_widget.cpp b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_api_response_commander_details_display_widget.cpp index 515475f3e..40a803e77 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_api_response_commander_details_display_widget.cpp +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_api_response_commander_details_display_widget.cpp @@ -38,6 +38,7 @@ EdhrecCommanderResponseCommanderDetailsDisplayWidget::EdhrecCommanderResponseCom connect(parentTab->getCardSizeSlider()->getSlider(), &QSlider::valueChanged, commanderPicture, &CardInfoPictureWidget::setScaleFactor); commanderPicture->setScaleFactor(parentTab->getCardSizeSlider()->getSlider()->value()); + parentTab->getCardSizeSlider()->enableCtrlScrollResize(this); } commanderDetails.debugPrint(); diff --git a/cockatrice/src/interface/widgets/tabs/tab_public_decks.cpp b/cockatrice/src/interface/widgets/tabs/tab_public_decks.cpp index 35389d3bf..d13f9d1e3 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_public_decks.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_public_decks.cpp @@ -2,6 +2,7 @@ #include "../../../client/settings/cache_settings.h" #include "../../deck_loader/deck_loader.h" +#include "../cards/card_size_widget.h" #include "../general/layout_containers/flow_widget.h" #include "../visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.h" #include "../visual_deck_storage/deck_preview/public_deck_preview_widget.h" @@ -107,6 +108,7 @@ TabPublicDecks::TabPublicDecks(TabSupervisor *_tabSupervisor, AbstractClient *_c &TabPublicDecks::updateCardSize); connect(quickSettingsWidget, &VisualDeckStorageQuickSettingsWidget::showTagFilterChanged, this, &TabPublicDecks::updateTagsVisibility); + quickSettingsWidget->getCardSizeWidget()->enableCtrlScrollResize(flowWidget); retranslateUi(); model->refresh(userName); 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 a20d56f63..6e0fee53f 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 @@ -69,6 +69,7 @@ VisualDatabaseDisplayWidget::VisualDatabaseDisplayWidget(QWidget *parent, SettingsCache::instance().cardsDisplay().getVisualDatabaseDisplayCardSize()); connect(cardSizeWidget, &CardSizeWidget::cardSizeSettingUpdated, &SettingsCache::instance().cardsDisplay(), &CardsDisplaySettings::setVisualDatabaseDisplayCardSize); + cardSizeWidget->enableCtrlScrollResize(flowWidget); searchContainer = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAlwaysOff); 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 a4268563a..cee268228 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 @@ -48,6 +48,7 @@ VisualDeckEditorSampleHandWidget::VisualDeckEditorSampleHandWidget(QWidget *pare upperLayout->addWidget(flowWidget); cardSizeWidget = new CardSizeWidget(this, flowWidget); + cardSizeWidget->enableCtrlScrollResize(flowWidget); upperLayout->addWidget(cardSizeWidget); auto upperLayoutWidget = new QWidget(this); 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 911f3dee9..53f21d1a1 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,6 +1,7 @@ #include "visual_deck_storage_folder_display_widget.h" #include "../cards/card_info_picture_widget.h" +#include "../cards/card_size_widget.h" #include "../general/display/banner_widget.h" #include "../general/layout_containers/flow_widget.h" #include "deck_preview/deck_preview_widget.h" @@ -45,6 +46,8 @@ VisualDeckStorageFolderDisplayWidget::VisualDeckStorageFolderDisplayWidget( flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAlwaysOff); containerLayout->addWidget(flowWidget); + visualDeckStorageWidget->settings()->getCardSizeWidget()->enableCtrlScrollResize(this); + auto *proxy = visualDeckStorageWidget->proxyModel(); // A burst of proxy changes (one dataChanged per finished deck load, plus the filter // invalidations) coalesces into a single reconcile, so a scan of many decks doesn't diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_quick_settings_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_quick_settings_widget.h index fc250cb20..a85e9e654 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_quick_settings_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_quick_settings_widget.h @@ -70,6 +70,15 @@ public: [[nodiscard]] TooltipType getDeckPreviewTooltip() const; [[nodiscard]] int getCardSize() const; + /** + * @return The card size widget, so card display hosts can resize the cards on + * Ctrl + scroll even though the slider itself lives inside this menu. + */ + [[nodiscard]] CardSizeWidget *getCardSizeWidget() const + { + return cardSizeWidget; + } + signals: void showFoldersChanged(bool enabled); void drawUnusedColorIdentitiesChanged(bool enabled);