From 1931eb11a996d96c5187b727488c3e0003f3ce27 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Thu, 27 Nov 2025 21:56:49 +0100 Subject: [PATCH 01/40] [VDD] Change 'filter to most recent sets' default to false (#6358) --- cockatrice/src/client/settings/cache_settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cockatrice/src/client/settings/cache_settings.cpp b/cockatrice/src/client/settings/cache_settings.cpp index 7b8458726..b9d2e6bb2 100644 --- a/cockatrice/src/client/settings/cache_settings.cpp +++ b/cockatrice/src/client/settings/cache_settings.cpp @@ -310,7 +310,7 @@ SettingsCache::SettingsCache() settings->value("interface/visualdeckstorageselectionanimation", true).toBool(); defaultDeckEditorType = settings->value("interface/defaultDeckEditorType", 1).toInt(); visualDatabaseDisplayFilterToMostRecentSetsEnabled = - settings->value("interface/visualdatabasedisplayfiltertomostrecentsetsenabled", true).toBool(); + settings->value("interface/visualdatabasedisplayfiltertomostrecentsetsenabled", false).toBool(); visualDatabaseDisplayFilterToMostRecentSetsAmount = settings->value("interface/visualdatabasedisplayfiltertomostrecentsetsamount", 10).toInt(); visualDeckEditorSampleHandSize = settings->value("interface/visualdeckeditorsamplehandsize", 7).toInt(); From 553952132f0654349b60b6a326a4add7b5d5367e Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Thu, 27 Nov 2025 22:00:35 +0100 Subject: [PATCH 02/40] [Game] Fix CardZoneLogic::clearContents() (#6356) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Took 6 minutes Took 28 seconds Co-authored-by: Lukas Brübach --- .../src/game/zones/logic/card_zone_logic.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/cockatrice/src/game/zones/logic/card_zone_logic.cpp b/cockatrice/src/game/zones/logic/card_zone_logic.cpp index b5869489a..a5dc64b50 100644 --- a/cockatrice/src/game/zones/logic/card_zone_logic.cpp +++ b/cockatrice/src/game/zones/logic/card_zone_logic.cpp @@ -148,17 +148,24 @@ void CardZoneLogic::moveAllToZone() void CardZoneLogic::clearContents() { - for (int i = 0; i < cards.size(); i++) { + // First gather the cards into a safe temporary list. + const CardList toClear = cards; + + // Detach and notify attached cards and zones *before* deleting anything. + for (CardItem *card : toClear) { // If an incorrectly implemented server doesn't return attached cards to whom they belong before dropping a // player, we have to return them to avoid a crash. - - const QList &attachedCards = cards[i]->getAttachedCards(); - for (auto attachedCard : attachedCards) { + const QList &attachedCards = card->getAttachedCards(); + for (CardItem *attachedCard : attachedCards) { emit attachedCard->getZone()->cardAdded(attachedCard); } - - player->deleteCard(cards.at(i)); } + + // Now request deletions after all manipulations are done. + for (CardItem *card : toClear) { + player->deleteCard(card); + } + cards.clear(); emit cardCountChanged(); } From 1c5bfdbabe592c9ce2dca0b7bee6975a5bb08c43 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Thu, 27 Nov 2025 22:02:27 +0100 Subject: [PATCH 03/40] Rebuild tree any time setDeckList is called. (#6353) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Took 2 hours 5 minutes Co-authored-by: Lukas Brübach --- .../libcockatrice/models/deck_list/deck_list_model.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ed77b55ca..e3e2de58d 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.cpp +++ b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.cpp @@ -539,8 +539,8 @@ void DeckListModel::setDeckList(DeckList *_deck) { if (deckList != _deck) { deckList = _deck; - rebuildTree(); } + rebuildTree(); } QList DeckListModel::getCards() const From c75a483ee66e75a10627aef9166ed245f8ef8130 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Thu, 27 Nov 2025 22:16:12 +0100 Subject: [PATCH 04/40] [VDE] Add selection model (#6354) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Took 22 minutes Took 1 minute Took 17 seconds Co-authored-by: Lukas Brübach --- .../card_group_display_widget.cpp | 49 ++++++- .../card_group_display_widget.h | 5 + .../flat_card_group_display_widget.cpp | 2 + .../flat_card_group_display_widget.h | 1 + .../overlapped_card_group_display_widget.cpp | 5 +- .../overlapped_card_group_display_widget.h | 1 + ..._info_picture_with_text_overlay_widget.cpp | 47 ++++++- ...rd_info_picture_with_text_overlay_widget.h | 2 + .../cards/deck_card_zone_display_widget.cpp | 43 +++++-- .../cards/deck_card_zone_display_widget.h | 3 + .../deck_editor_deck_dock_widget.h | 5 + .../tab_deck_editor_visual.cpp | 70 ++++++++-- .../tab_deck_editor_visual.h | 5 +- .../tab_deck_editor_visual_tab_widget.cpp | 2 +- .../visual_deck_editor_widget.cpp | 121 ++++++++++++------ .../visual_deck_editor_widget.h | 11 +- 16 files changed, 303 insertions(+), 69 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 81bd52702..7734a61d0 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 @@ -10,6 +10,7 @@ CardGroupDisplayWidget::CardGroupDisplayWidget(QWidget *parent, DeckListModel *_deckListModel, + QItemSelectionModel *_selectionModel, QPersistentModelIndex _trackedIndex, QString _zoneName, QString _cardGroupCategory, @@ -17,8 +18,8 @@ CardGroupDisplayWidget::CardGroupDisplayWidget(QWidget *parent, QStringList _activeSortCriteria, int bannerOpacity, CardSizeWidget *_cardSizeWidget) - : QWidget(parent), deckListModel(_deckListModel), trackedIndex(_trackedIndex), zoneName(_zoneName), - cardGroupCategory(_cardGroupCategory), activeGroupCriteria(_activeGroupCriteria), + : QWidget(parent), deckListModel(_deckListModel), selectionModel(_selectionModel), trackedIndex(_trackedIndex), + zoneName(_zoneName), cardGroupCategory(_cardGroupCategory), activeGroupCriteria(_activeGroupCriteria), activeSortCriteria(_activeSortCriteria), cardSizeWidget(_cardSizeWidget) { layout = new QVBoxLayout(this); @@ -32,9 +33,47 @@ CardGroupDisplayWidget::CardGroupDisplayWidget(QWidget *parent, CardGroupDisplayWidget::updateCardDisplays(); connect(deckListModel, &QAbstractItemModel::rowsInserted, this, &CardGroupDisplayWidget::onCardAddition); + connect(selectionModel, &QItemSelectionModel::selectionChanged, this, &CardGroupDisplayWidget::onSelectionChanged); connect(deckListModel, &QAbstractItemModel::rowsRemoved, this, &CardGroupDisplayWidget::onCardRemoval); } +void CardGroupDisplayWidget::onSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected) +{ + auto proxyModel = qobject_cast(selectionModel->model()); + + for (auto &range : selected) { + for (int row = range.top(); row <= range.bottom(); ++row) { + QModelIndex idx = range.model()->index(row, 0, range.parent()); + + if (proxyModel) { + idx = proxyModel->mapToSource(idx); + } + + auto it = indexToWidgetMap.find(QPersistentModelIndex(idx)); + if (it != indexToWidgetMap.end()) { + if (auto displayWidget = qobject_cast(it.value())) { + displayWidget->setHighlighted(true); + } + } + } + } + + for (auto &range : deselected) { + for (int row = range.top(); row <= range.bottom(); ++row) { + QModelIndex idx = range.model()->index(row, 0, range.parent()); + if (proxyModel) + idx = proxyModel->mapToSource(idx); + + auto it = indexToWidgetMap.find(QPersistentModelIndex(idx)); + if (it != indexToWidgetMap.end()) { + if (auto displayWidget = qobject_cast(it.value())) { + displayWidget->setHighlighted(false); + } + } + } + } +} + void CardGroupDisplayWidget::clearAllDisplayWidgets() { for (auto idx : indexToWidgetMap.keys()) { @@ -138,6 +177,12 @@ void CardGroupDisplayWidget::onActiveSortCriteriaChanged(QStringList _activeSort updateCardDisplays(); } +void CardGroupDisplayWidget::mousePressEvent(QMouseEvent *event) +{ + QWidget::mousePressEvent(event); + selectionModel->clearSelection(); +} + void CardGroupDisplayWidget::onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card) { emit cardClicked(event, card); 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 a62a66803..4d911edde 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 @@ -11,6 +11,7 @@ #include "../card_info_picture_with_text_overlay_widget.h" #include "../card_size_widget.h" +#include #include #include #include @@ -24,6 +25,7 @@ class CardGroupDisplayWidget : public QWidget public: CardGroupDisplayWidget(QWidget *parent, DeckListModel *deckListModel, + QItemSelectionModel *selectionModel, QPersistentModelIndex trackedIndex, QString zoneName, QString cardGroupCategory, @@ -31,9 +33,11 @@ public: QStringList activeSortCriteria, int bannerOpacity, CardSizeWidget *cardSizeWidget); + void onSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected); void clearAllDisplayWidgets(); DeckListModel *deckListModel; + QItemSelectionModel *selectionModel; QPersistentModelIndex trackedIndex; QHash indexToWidgetMap; QString zoneName; @@ -43,6 +47,7 @@ public: CardSizeWidget *cardSizeWidget; public slots: + void mousePressEvent(QMouseEvent *event) override; void onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card); void onHover(const ExactCard &card); virtual QWidget *constructWidgetForIndex(QPersistentModelIndex index); diff --git a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/flat_card_group_display_widget.cpp b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/flat_card_group_display_widget.cpp index dad581874..5f3a2c2c0 100644 --- a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/flat_card_group_display_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/flat_card_group_display_widget.cpp @@ -10,6 +10,7 @@ FlatCardGroupDisplayWidget::FlatCardGroupDisplayWidget(QWidget *parent, DeckListModel *_deckListModel, + QItemSelectionModel *_selectionModel, QPersistentModelIndex _trackedIndex, QString _zoneName, QString _cardGroupCategory, @@ -19,6 +20,7 @@ FlatCardGroupDisplayWidget::FlatCardGroupDisplayWidget(QWidget *parent, CardSizeWidget *_cardSizeWidget) : CardGroupDisplayWidget(parent, _deckListModel, + _selectionModel, std::move(_trackedIndex), _zoneName, _cardGroupCategory, diff --git a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/flat_card_group_display_widget.h b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/flat_card_group_display_widget.h index 8b536c5e5..e07152b34 100644 --- a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/flat_card_group_display_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/flat_card_group_display_widget.h @@ -17,6 +17,7 @@ class FlatCardGroupDisplayWidget : public CardGroupDisplayWidget public: FlatCardGroupDisplayWidget(QWidget *parent, DeckListModel *deckListModel, + QItemSelectionModel *selectionModel, QPersistentModelIndex trackedIndex, QString zoneName, QString cardGroupCategory, diff --git a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/overlapped_card_group_display_widget.cpp b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/overlapped_card_group_display_widget.cpp index 4d8759cd8..27741a79c 100644 --- a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/overlapped_card_group_display_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/overlapped_card_group_display_widget.cpp @@ -1,14 +1,12 @@ #include "overlapped_card_group_display_widget.h" -#include "../card_info_picture_with_text_overlay_widget.h" - #include -#include #include #include OverlappedCardGroupDisplayWidget::OverlappedCardGroupDisplayWidget(QWidget *parent, DeckListModel *_deckListModel, + QItemSelectionModel *_selectionModel, QPersistentModelIndex _trackedIndex, QString _zoneName, QString _cardGroupCategory, @@ -18,6 +16,7 @@ OverlappedCardGroupDisplayWidget::OverlappedCardGroupDisplayWidget(QWidget *pare CardSizeWidget *_cardSizeWidget) : CardGroupDisplayWidget(parent, _deckListModel, + _selectionModel, _trackedIndex, _zoneName, _cardGroupCategory, diff --git a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/overlapped_card_group_display_widget.h b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/overlapped_card_group_display_widget.h index 1440c37e7..288e46129 100644 --- a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/overlapped_card_group_display_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/overlapped_card_group_display_widget.h @@ -17,6 +17,7 @@ class OverlappedCardGroupDisplayWidget : public CardGroupDisplayWidget public: OverlappedCardGroupDisplayWidget(QWidget *parent, DeckListModel *deckListModel, + QItemSelectionModel *selectionModel, QPersistentModelIndex trackedIndex, QString zoneName, QString cardGroupCategory, diff --git a/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.cpp b/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.cpp index 1545dc4f6..4cb61deab 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.cpp @@ -25,7 +25,7 @@ CardInfoPictureWithTextOverlayWidget::CardInfoPictureWithTextOverlayWidget(QWidg const int fontSize, const Qt::Alignment alignment) : CardInfoPictureWidget(parent, hoverToZoomEnabled, raiseOnEnter), textColor(textColor), outlineColor(outlineColor), - fontSize(fontSize), textAlignment(alignment) + fontSize(fontSize), textAlignment(alignment), highlighted(false) { this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); } @@ -82,6 +82,16 @@ void CardInfoPictureWithTextOverlayWidget::setTextAlignment(const Qt::Alignment update(); } +void CardInfoPictureWithTextOverlayWidget::setHighlighted(bool _highlighted) +{ + if (highlighted == _highlighted) { + return; + } + + highlighted = _highlighted; + update(); +} + void CardInfoPictureWithTextOverlayWidget::mousePressEvent(QMouseEvent *event) { emit imageClicked(event, this); @@ -98,11 +108,6 @@ void CardInfoPictureWithTextOverlayWidget::paintEvent(QPaintEvent *event) // Call the base class's paintEvent to draw the card image CardInfoPictureWidget::paintEvent(event); - // If no overlay text, skip drawing the text - if (overlayText.isEmpty()) { - return; - } - QStylePainter painter(this); // Get the pixmap from the base class using the getter @@ -116,6 +121,36 @@ void CardInfoPictureWithTextOverlayWidget::paintEvent(QPaintEvent *event) const QPoint topLeft{(width() - scaledSize.width()) / 2, (height() - scaledSize.height()) / 2}; const QRect pixmapRect(topLeft, scaledSize); + if (highlighted) { + painter.save(); + painter.setRenderHint(QPainter::Antialiasing, true); + + // Soft glow and border around the pixmap + const int padding = 4; // glow extends a little beyond image + QRect glowRect = pixmapRect.adjusted(-padding, -padding, padding, padding); + + QPainterPath path; + int radius = 8; // rounded corners + path.addRoundedRect(glowRect, radius, radius); + + // Soft outer glow + QColor glowColor(0, 150, 255, 80); // subtle blu + painter.setPen(QPen(glowColor, 6)); + painter.drawPath(path); + + // Thin inner border for crispness + QColor borderColor(0, 150, 255, 200); + painter.setPen(QPen(borderColor, 2)); + painter.drawRoundedRect(pixmapRect, radius, radius); + + painter.restore(); + } + + // If no overlay text, skip drawing the text + if (overlayText.isEmpty()) { + return; + } + // Calculate the optimal font size QFont font = painter.font(); int optimalFontSize = fontSize; // Start with the user-defined font size diff --git a/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.h b/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.h index 91c44cbb1..eed827292 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.h @@ -32,6 +32,7 @@ public: void setOutlineColor(const QColor &color); void setFontSize(int size); void setTextAlignment(Qt::Alignment alignment); + void setHighlighted(bool _highlighted); [[nodiscard]] QSize sizeHint() const override; signals: @@ -53,6 +54,7 @@ private: QColor outlineColor; int fontSize; Qt::Alignment textAlignment; + bool highlighted; }; #endif // CARD_PICTURE_WITH_TEXT_OVERLAY_H 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 be32d4f0e..5529c35b6 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 @@ -9,6 +9,7 @@ DeckCardZoneDisplayWidget::DeckCardZoneDisplayWidget(QWidget *parent, DeckListModel *_deckListModel, + QItemSelectionModel *_selectionModel, QPersistentModelIndex _trackedIndex, QString _zoneName, QString _activeGroupCriteria, @@ -17,9 +18,10 @@ DeckCardZoneDisplayWidget::DeckCardZoneDisplayWidget(QWidget *parent, int bannerOpacity, int subBannerOpacity, CardSizeWidget *_cardSizeWidget) - : QWidget(parent), deckListModel(_deckListModel), trackedIndex(_trackedIndex), zoneName(_zoneName), - activeGroupCriteria(_activeGroupCriteria), activeSortCriteria(_activeSortCriteria), displayType(_displayType), - bannerOpacity(bannerOpacity), subBannerOpacity(subBannerOpacity), cardSizeWidget(_cardSizeWidget) + : QWidget(parent), deckListModel(_deckListModel), selectionModel(_selectionModel), trackedIndex(_trackedIndex), + zoneName(_zoneName), activeGroupCriteria(_activeGroupCriteria), activeSortCriteria(_activeSortCriteria), + displayType(_displayType), bannerOpacity(bannerOpacity), subBannerOpacity(subBannerOpacity), + cardSizeWidget(_cardSizeWidget) { layout = new QVBoxLayout(this); setLayout(layout); @@ -37,9 +39,34 @@ DeckCardZoneDisplayWidget::DeckCardZoneDisplayWidget(QWidget *parent, displayCards(); connect(deckListModel, &QAbstractItemModel::rowsInserted, this, &DeckCardZoneDisplayWidget::onCategoryAddition); + connect(selectionModel, &QItemSelectionModel::selectionChanged, this, + &DeckCardZoneDisplayWidget::onSelectionChanged); connect(deckListModel, &QAbstractItemModel::rowsRemoved, this, &DeckCardZoneDisplayWidget::onCategoryRemoval); } +void DeckCardZoneDisplayWidget::onSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected) +{ + for (auto &range : selected) { + for (int row = range.top(); row <= range.bottom(); ++row) { + QModelIndex idx = range.model()->index(row, 0, range.parent()); + auto it = indexToWidgetMap.find(QPersistentModelIndex(idx)); + if (it != indexToWidgetMap.end()) { + // it.value()->setHighlighted(true); + } + } + } + + for (auto &range : deselected) { + for (int row = range.top(); row <= range.bottom(); ++row) { + QModelIndex idx = range.model()->index(row, 0, range.parent()); + auto it = indexToWidgetMap.find(QPersistentModelIndex(idx)); + if (it != indexToWidgetMap.end()) { + // it.value()->setHighlighted(false); + } + } + } +} + void DeckCardZoneDisplayWidget::cleanupInvalidCardGroup(CardGroupDisplayWidget *displayWidget) { cardGroupLayout->removeWidget(displayWidget); @@ -60,8 +87,8 @@ void DeckCardZoneDisplayWidget::constructAppropriateWidget(QPersistentModelIndex } if (displayType == DisplayType::Overlap) { auto *displayWidget = new OverlappedCardGroupDisplayWidget( - cardGroupContainer, deckListModel, index, zoneName, categoryName, activeGroupCriteria, activeSortCriteria, - subBannerOpacity, cardSizeWidget); + cardGroupContainer, deckListModel, selectionModel, index, zoneName, categoryName, activeGroupCriteria, + activeSortCriteria, subBannerOpacity, cardSizeWidget); connect(displayWidget, &OverlappedCardGroupDisplayWidget::cardClicked, this, &DeckCardZoneDisplayWidget::onClick); connect(displayWidget, &OverlappedCardGroupDisplayWidget::cardHovered, this, @@ -73,9 +100,9 @@ void DeckCardZoneDisplayWidget::constructAppropriateWidget(QPersistentModelIndex cardGroupLayout->addWidget(displayWidget); indexToWidgetMap.insert(index, displayWidget); } else if (displayType == DisplayType::Flat) { - auto *displayWidget = - new FlatCardGroupDisplayWidget(cardGroupContainer, deckListModel, index, zoneName, categoryName, - activeGroupCriteria, activeSortCriteria, subBannerOpacity, cardSizeWidget); + auto *displayWidget = new FlatCardGroupDisplayWidget(cardGroupContainer, deckListModel, selectionModel, index, + zoneName, categoryName, activeGroupCriteria, + activeSortCriteria, subBannerOpacity, cardSizeWidget); connect(displayWidget, &FlatCardGroupDisplayWidget::cardClicked, this, &DeckCardZoneDisplayWidget::onClick); connect(displayWidget, &FlatCardGroupDisplayWidget::cardHovered, this, &DeckCardZoneDisplayWidget::onHover); connect(displayWidget, &CardGroupDisplayWidget::cleanupRequested, this, 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 dbaeaa9ae..ac53cb704 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 @@ -26,6 +26,7 @@ class DeckCardZoneDisplayWidget : public QWidget public: DeckCardZoneDisplayWidget(QWidget *parent, DeckListModel *deckListModel, + QItemSelectionModel *selectionModel, QPersistentModelIndex trackedIndex, QString zoneName, QString activeGroupCriteria, @@ -34,7 +35,9 @@ public: int bannerOpacity, int subBannerOpacity, CardSizeWidget *_cardSizeWidget); + void onSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected); DeckListModel *deckListModel; + QItemSelectionModel *selectionModel; QPersistentModelIndex trackedIndex; QString zoneName; void addCardsToOverlapWidget(); 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 b633bdaed..78d5da9f7 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 @@ -51,6 +51,11 @@ public: return activeGroupCriteriaComboBox; } + [[nodiscard]] QItemSelectionModel *getSelectionModel() const + { + return deckView->selectionModel(); + } + public slots: void cleanDeck(); void updateBannerCardComboBox(); 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 109815816..7a811fd28 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 @@ -176,20 +176,74 @@ void TabDeckEditorVisual::changeModelIndexToCard(const ExactCard &activeCard) if (!index.isValid()) { index = deckDockWidget->deckModel->findCard(cardName, DECK_ZONE_SIDE); } - deckDockWidget->deckView->setCurrentIndex(index); + if (!deckDockWidget->getSelectionModel()->hasSelection()) { + deckDockWidget->getSelectionModel()->setCurrentIndex(index, QItemSelectionModel::NoUpdate); + } } -/** @brief Handles clicks on cards in the mainboard deck. */ void TabDeckEditorVisual::processMainboardCardClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance, - QString zoneName) + const QString &zoneName) { + auto card = instance->getCard(); + + // Get the model index for the card + QModelIndex idx = deckDockWidget->deckModel->findCard(card.getName(), zoneName); + if (!idx.isValid()) { + return; + } + + QItemSelectionModel *sel = deckDockWidget->getSelectionModel(); + + // Double click = swap + if (event->type() == QEvent::MouseButtonDblClick && event->button() == Qt::LeftButton) { + actSwapCard(card, zoneName); + idx = deckDockWidget->deckModel->findCard(card.getName(), zoneName); + sel->setCurrentIndex(idx, QItemSelectionModel::ClearAndSelect); + return; + } + + // Right-click = decrement + if (event->button() == Qt::RightButton) { + actDecrementCard(card); + // Keep selection intact. + return; + } + + // Alt + Left click = increment + if (event->button() == Qt::LeftButton && event->modifiers().testFlag(Qt::AltModifier)) { + // actIncrementCard(card); + // Keep selection intact. + return; + } + + // Normal selection behavior if (event->button() == Qt::LeftButton) { - actSwapCard(instance->getCard(), zoneName); - } else if (event->button() == Qt::RightButton) { - actDecrementCard(instance->getCard()); - } else if (event->button() == Qt::MiddleButton) { - deckDockWidget->actRemoveCard(); + Qt::KeyboardModifiers mods = event->modifiers(); + QItemSelectionModel::SelectionFlags flags; + + if (mods.testFlag(Qt::ControlModifier)) { + // CTRL + click = toggle selection + flags = QItemSelectionModel::Toggle; + } else if (mods.testFlag(Qt::ShiftModifier)) { + // SHIFT + click = select range + QModelIndex anchor = sel->currentIndex(); + if (!anchor.isValid()) { + anchor = idx; + } + + QItemSelection range(anchor, idx); + sel->select(range, QItemSelectionModel::SelectCurrent); + sel->setCurrentIndex(idx, QItemSelectionModel::NoUpdate); + return; + } else { + // Normal click = clear selection, select this, set current + deckDockWidget->deckView->setCurrentIndex(idx); + deckDockWidget->deckView->scrollTo(idx); + return; + } + + sel->setCurrentIndex(idx, flags); } } 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 87f6c5df8..2f1d11d82 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 @@ -176,8 +176,9 @@ public slots: * @param instance Widget representing the clicked card. * @param zoneName Deck zone of the card. */ - void - processMainboardCardClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance, QString zoneName); + void processMainboardCardClick(QMouseEvent *event, + CardInfoPictureWithTextOverlayWidget *instance, + const QString &zoneName); /** * @brief Handle card clicks in the database visual display. 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 08728dac0..98b6aff00 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 @@ -28,7 +28,7 @@ TabDeckEditorVisualTabWidget::TabDeckEditorVisualTabWidget(QWidget *parent, layout = new QVBoxLayout(this); setLayout(layout); - visualDeckView = new VisualDeckEditorWidget(this, deckModel); + visualDeckView = new VisualDeckEditorWidget(this, deckModel, _deckEditor->deckDockWidget->getSelectionModel()); visualDeckView->setObjectName("visualDeckView"); connect(visualDeckView, &VisualDeckEditorWidget::activeCardChanged, this, &TabDeckEditorVisualTabWidget::onCardChanged); 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 005efd6db..3536359be 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 @@ -25,8 +25,10 @@ #include #include -VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, DeckListModel *_deckListModel) - : QWidget(parent), deckListModel(_deckListModel) +VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, + DeckListModel *_deckListModel, + QItemSelectionModel *_selectionModel) + : QWidget(parent), deckListModel(_deckListModel), selectionModel(_selectionModel) { // The Main Widget and Main Layout, which contain a single Widget: The Scroll Area setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); @@ -204,6 +206,11 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, DeckListModel *_ connect(deckListModel, &QAbstractItemModel::rowsRemoved, this, &VisualDeckEditorWidget::onCardRemoval); constructZoneWidgetsFromDeckListModel(); + if (selectionModel) { + connect(selectionModel, &QItemSelectionModel::selectionChanged, this, + &VisualDeckEditorWidget::onSelectionChanged); + } + retranslateUi(); } @@ -219,6 +226,47 @@ void VisualDeckEditorWidget::retranslateUi() tr("Change how cards are displayed within zones (i.e. overlapped or fully visible.)")); } +void VisualDeckEditorWidget::setSelectionModel(QItemSelectionModel *model) +{ + if (selectionModel == model) { + return; + } + + if (selectionModel) { + // TODO: Possibly disconnect old ones? + } + + selectionModel = model; + + if (selectionModel) { + connect(selectionModel, &QItemSelectionModel::selectionChanged, this, + &VisualDeckEditorWidget::onSelectionChanged); + } +} + +void VisualDeckEditorWidget::onSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected) +{ + for (auto &range : selected) { + for (int row = range.top(); row <= range.bottom(); ++row) { + QModelIndex idx = range.model()->index(row, 0, range.parent()); + auto it = indexToWidgetMap.find(QPersistentModelIndex(idx)); + if (it != indexToWidgetMap.end()) { + // it.value()->setHighlighted(true); + } + } + } + + for (auto &range : deselected) { + for (int row = range.top(); row <= range.bottom(); ++row) { + QModelIndex idx = range.model()->index(row, 0, range.parent()); + auto it = indexToWidgetMap.find(QPersistentModelIndex(idx)); + if (it != indexToWidgetMap.end()) { + // it.value()->setHighlighted(false); + } + } + } +} + void VisualDeckEditorWidget::clearAllDisplayWidgets() { for (auto idx : indexToWidgetMap.keys()) { @@ -250,25 +298,7 @@ void VisualDeckEditorWidget::onCardAddition(const QModelIndex &parent, int first continue; } - DeckCardZoneDisplayWidget *zoneDisplayWidget = new DeckCardZoneDisplayWidget( - zoneContainer, deckListModel, index, - deckListModel->data(index.sibling(index.row(), 1), Qt::EditRole).toString(), activeGroupCriteria, - activeSortCriteria, currentDisplayType, 20, 10, cardSizeWidget); - connect(zoneDisplayWidget, &DeckCardZoneDisplayWidget::cardHovered, this, &VisualDeckEditorWidget::onHover); - connect(zoneDisplayWidget, &DeckCardZoneDisplayWidget::cardClicked, this, - &VisualDeckEditorWidget::onCardClick); - connect(zoneDisplayWidget, &DeckCardZoneDisplayWidget::requestCleanup, this, - &VisualDeckEditorWidget::cleanupInvalidZones); - connect(this, &VisualDeckEditorWidget::activeSortCriteriaChanged, zoneDisplayWidget, - &DeckCardZoneDisplayWidget::onActiveSortCriteriaChanged); - connect(this, &VisualDeckEditorWidget::activeGroupCriteriaChanged, zoneDisplayWidget, - &DeckCardZoneDisplayWidget::onActiveGroupCriteriaChanged); - connect(this, &VisualDeckEditorWidget::displayTypeChanged, zoneDisplayWidget, - &DeckCardZoneDisplayWidget::refreshDisplayType); - zoneDisplayWidget->refreshDisplayType(currentDisplayType); - zoneContainerLayout->addWidget(zoneDisplayWidget); - - indexToWidgetMap.insert(index, zoneDisplayWidget); + constructZoneWidgetForIndex(index); } } } @@ -287,6 +317,28 @@ void VisualDeckEditorWidget::onCardRemoval(const QModelIndex &parent, int first, } } +void VisualDeckEditorWidget::constructZoneWidgetForIndex(QPersistentModelIndex persistent) +{ + DeckCardZoneDisplayWidget *zoneDisplayWidget = new DeckCardZoneDisplayWidget( + zoneContainer, deckListModel, selectionModel, persistent, + deckListModel->data(persistent.sibling(persistent.row(), 1), Qt::EditRole).toString(), activeGroupCriteria, + activeSortCriteria, currentDisplayType, 20, 10, cardSizeWidget); + connect(zoneDisplayWidget, &DeckCardZoneDisplayWidget::cardHovered, this, &VisualDeckEditorWidget::onHover); + connect(zoneDisplayWidget, &DeckCardZoneDisplayWidget::cardClicked, this, &VisualDeckEditorWidget::onCardClick); + connect(zoneDisplayWidget, &DeckCardZoneDisplayWidget::requestCleanup, this, + &VisualDeckEditorWidget::cleanupInvalidZones); + connect(this, &VisualDeckEditorWidget::activeSortCriteriaChanged, zoneDisplayWidget, + &DeckCardZoneDisplayWidget::onActiveSortCriteriaChanged); + connect(this, &VisualDeckEditorWidget::activeGroupCriteriaChanged, zoneDisplayWidget, + &DeckCardZoneDisplayWidget::onActiveGroupCriteriaChanged); + connect(this, &VisualDeckEditorWidget::displayTypeChanged, zoneDisplayWidget, + &DeckCardZoneDisplayWidget::refreshDisplayType); + zoneDisplayWidget->refreshDisplayType(currentDisplayType); + zoneContainerLayout->addWidget(zoneDisplayWidget); + + indexToWidgetMap.insert(persistent, zoneDisplayWidget); +} + void VisualDeckEditorWidget::constructZoneWidgetsFromDeckListModel() { QSortFilterProxyModel proxy; @@ -305,23 +357,7 @@ void VisualDeckEditorWidget::constructZoneWidgetsFromDeckListModel() continue; } - DeckCardZoneDisplayWidget *zoneDisplayWidget = new DeckCardZoneDisplayWidget( - zoneContainer, deckListModel, persistent, - deckListModel->data(persistent.sibling(persistent.row(), 1), Qt::EditRole).toString(), activeGroupCriteria, - activeSortCriteria, currentDisplayType, 20, 10, cardSizeWidget); - connect(zoneDisplayWidget, &DeckCardZoneDisplayWidget::cardHovered, this, &VisualDeckEditorWidget::onHover); - connect(zoneDisplayWidget, &DeckCardZoneDisplayWidget::cardClicked, this, &VisualDeckEditorWidget::onCardClick); - connect(zoneDisplayWidget, &DeckCardZoneDisplayWidget::requestCleanup, this, - &VisualDeckEditorWidget::cleanupInvalidZones); - connect(this, &VisualDeckEditorWidget::activeSortCriteriaChanged, zoneDisplayWidget, - &DeckCardZoneDisplayWidget::onActiveSortCriteriaChanged); - connect(this, &VisualDeckEditorWidget::activeGroupCriteriaChanged, zoneDisplayWidget, - &DeckCardZoneDisplayWidget::onActiveGroupCriteriaChanged); - connect(this, &VisualDeckEditorWidget::displayTypeChanged, zoneDisplayWidget, - &DeckCardZoneDisplayWidget::refreshDisplayType); - zoneContainerLayout->addWidget(zoneDisplayWidget); - - indexToWidgetMap.insert(persistent, zoneDisplayWidget); + constructZoneWidgetForIndex(persistent); } } @@ -389,7 +425,16 @@ void VisualDeckEditorWidget::decklistDataChanged(QModelIndex topLeft, QModelInde void VisualDeckEditorWidget::onHover(const ExactCard &hoveredCard) { + // If user has any card selected, ignore hover + if (selectionModel->hasSelection()) { + return; + } + + // If nothing is selected -> this is our "active/preview" card emit activeCardChanged(hoveredCard); + + // TODO: highlight hovered card visually: + // highlightHoveredCard(hoveredCard); } void VisualDeckEditorWidget::onCardClick(QMouseEvent *event, diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h index 176086019..4cff68407 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h @@ -36,13 +36,20 @@ class VisualDeckEditorWidget : public QWidget Q_OBJECT public: - explicit VisualDeckEditorWidget(QWidget *parent, DeckListModel *deckListModel); + explicit VisualDeckEditorWidget(QWidget *parent, DeckListModel *deckListModel, QItemSelectionModel *selectionModel); void retranslateUi(); void clearAllDisplayWidgets(); void resizeEvent(QResizeEvent *event) override; void setDeckList(const DeckList &_deckListModel); + void setSelectionModel(QItemSelectionModel *model); + void onSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected); + QItemSelectionModel *getSelectionModel() const + { + return selectionModel; + } + QLineEdit *searchBar; CardSizeWidget *cardSizeWidget; @@ -53,6 +60,7 @@ public slots: void cleanupInvalidZones(DeckCardZoneDisplayWidget *displayWidget); void onCardAddition(const QModelIndex &parent, int first, int last); void onCardRemoval(const QModelIndex &parent, int first, int last); + void constructZoneWidgetForIndex(QPersistentModelIndex persistent); void constructZoneWidgetsFromDeckListModel(); signals: @@ -72,6 +80,7 @@ protected slots: private: DeckListModel *deckListModel; + QItemSelectionModel *selectionModel; QVBoxLayout *mainLayout; QWidget *searchContainer; QHBoxLayout *searchLayout; From bac6beeb5026fe70952294530f28919e928d83c9 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Thu, 27 Nov 2025 23:03:30 +0100 Subject: [PATCH 05/40] [VDE] Allow visual database display to toggle to table based display. (#6357) --- .../deck_editor_database_display_widget.h | 21 +++-- .../tabs/tab_visual_database_display.h | 3 +- .../visual_database_display_widget.cpp | 86 +++++++++++++------ .../visual_database_display_widget.h | 2 + 4 files changed, 78 insertions(+), 34 deletions(-) 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 efac97eae..0d3ce9f4c 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 @@ -29,10 +29,23 @@ public: CardDatabaseModel *databaseModel; CardDatabaseDisplayModel *databaseDisplayModel; + QTreeView *getDatabaseView() + { + return databaseView; + }; + public slots: ExactCard currentCard() const; void setFilterTree(FilterTree *filterTree); void clearAllDatabaseFilters(); + void updateSearch(const QString &search); + void updateCard(const QModelIndex ¤t, const QModelIndex &); + void actAddCardToMainDeck(); + void actAddCardToSideboard(); + void actDecrementCardFromMainDeck(); + void actDecrementCardFromSideboard(); + void databaseCustomMenu(QPoint point); + void copyDatabaseCellContents(); signals: void addCardToMainDeck(const ExactCard &card); @@ -51,14 +64,6 @@ private: private slots: void retranslateUi(); - void updateSearch(const QString &search); - void updateCard(const QModelIndex ¤t, const QModelIndex &); - void actAddCardToMainDeck(); - void actAddCardToSideboard(); - void actDecrementCardFromMainDeck(); - void actDecrementCardFromSideboard(); - void databaseCustomMenu(QPoint point); - void copyDatabaseCellContents(); void saveDbHeaderState(); }; diff --git a/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.h b/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.h index dd6128885..b01f3ab06 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.h +++ b/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.h @@ -25,7 +25,8 @@ public: void retranslateUi() override; [[nodiscard]] QString getTabText() const override { - return tr("Visual Database Display"); + return visualDatabaseDisplayWidget->displayModeButton->isChecked() ? tr("Database Display") + : tr("Visual Database Display"); } }; 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 d371d0ed3..66f6238b9 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 @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -60,28 +61,39 @@ VisualDatabaseDisplayWidget::VisualDatabaseDisplayWidget(QWidget *parent, setFocusProxy(searchEdit); setFocusPolicy(Qt::ClickFocus); + displayModeButton = new QPushButton(tr("Visual"), this); + displayModeButton->setCheckable(true); // Toggle button + + connect(displayModeButton, &QPushButton::toggled, this, &VisualDatabaseDisplayWidget::onDisplayModeChanged); + + displayModeButton->setChecked(false); // Start in Visual mode + filterModel = new FilterTreeModel(); filterModel->setObjectName("filterModel"); searchKeySignals.setObjectName("searchKeySignals"); - connect(searchEdit, &QLineEdit::textChanged, this, &VisualDatabaseDisplayWidget::updateSearch); - /*connect(&searchKeySignals, SIGNAL(onEnter()), this, SLOT(actAddCard())); - connect(&searchKeySignals, SIGNAL(onCtrlAltEqual()), this, SLOT(actAddCard())); - connect(&searchKeySignals, SIGNAL(onCtrlAltRBracket()), this, SLOT(actAddCardToSideboard())); - connect(&searchKeySignals, SIGNAL(onCtrlAltMinus()), this, SLOT(actDecrementCard())); - connect(&searchKeySignals, SIGNAL(onCtrlAltLBracket()), this, SLOT(actDecrementCardFromSideboard())); - connect(&searchKeySignals, SIGNAL(onCtrlAltEnter()), this, SLOT(actAddCardToSideboard())); - connect(&searchKeySignals, SIGNAL(onCtrlEnter()), this, SLOT(actAddCardToSideboard())); - connect(&searchKeySignals, SIGNAL(onCtrlC()), this, SLOT(copyDatabaseCellContents()));*/ + connect(searchEdit, &SearchLineEdit::textChanged, this, &VisualDatabaseDisplayWidget::updateSearch); + connect(&searchKeySignals, &KeySignals::onEnter, deckEditor->databaseDisplayDockWidget, + &DeckEditorDatabaseDisplayWidget::actAddCardToMainDeck); + connect(&searchKeySignals, &KeySignals::onCtrlAltEqual, deckEditor->databaseDisplayDockWidget, + &DeckEditorDatabaseDisplayWidget::actAddCardToMainDeck); + connect(&searchKeySignals, &KeySignals::onCtrlAltRBracket, deckEditor->databaseDisplayDockWidget, + &DeckEditorDatabaseDisplayWidget::actAddCardToSideboard); + connect(&searchKeySignals, &KeySignals::onCtrlAltMinus, deckEditor->databaseDisplayDockWidget, + &DeckEditorDatabaseDisplayWidget::actDecrementCardFromMainDeck); + connect(&searchKeySignals, &KeySignals::onCtrlAltLBracket, deckEditor->databaseDisplayDockWidget, + &DeckEditorDatabaseDisplayWidget::actDecrementCardFromSideboard); + connect(&searchKeySignals, &KeySignals::onCtrlAltEnter, deckEditor->databaseDisplayDockWidget, + &DeckEditorDatabaseDisplayWidget::actAddCardToSideboard); + connect(&searchKeySignals, &KeySignals::onCtrlEnter, deckEditor->databaseDisplayDockWidget, + &DeckEditorDatabaseDisplayWidget::actAddCardToSideboard); + connect(&searchKeySignals, &KeySignals::onCtrlC, deckEditor->databaseDisplayDockWidget, + &DeckEditorDatabaseDisplayWidget::copyDatabaseCellContents); + connect(help, &QAction::triggered, this, [this] { createSearchSyntaxHelpWindow(searchEdit); }); - databaseView = new QTreeView(this); - databaseView->setObjectName("databaseView"); + databaseView = deckEditor->databaseDisplayDockWidget->getDatabaseView(); databaseView->setFocusProxy(searchEdit); - databaseView->setRootIsDecorated(false); databaseView->setItemDelegate(nullptr); - databaseView->setSortingEnabled(true); - databaseView->sortByColumn(0, Qt::AscendingOrder); - databaseView->setModel(databaseDisplayModel); databaseView->setVisible(false); searchEdit->setTreeView(databaseView); @@ -168,11 +180,14 @@ void VisualDatabaseDisplayWidget::initialize() searchLayout->addWidget(colorFilterWidget); searchLayout->addWidget(clearFilterWidget); searchLayout->addWidget(searchEdit); + searchLayout->addWidget(displayModeButton); mainLayout->addWidget(searchContainer); mainLayout->addWidget(filterContainer); + mainLayout->addWidget(databaseView); + mainLayout->addWidget(flowWidget); mainLayout->addWidget(cardSizeWidget); @@ -213,6 +228,25 @@ void VisualDatabaseDisplayWidget::resizeEvent(QResizeEvent *event) loadCurrentPage(); } +void VisualDatabaseDisplayWidget::onDisplayModeChanged(bool checked) +{ + if (checked) { + // Table mode + displayModeButton->setText(tr("Table")); + flowWidget->setVisible(false); + cardSizeWidget->setVisible(false); + databaseView->setItemDelegate(new QStyledItemDelegate(databaseView)); + databaseView->setVisible(true); + } else { + // Visual mode + displayModeButton->setText(tr("Visual")); + flowWidget->setVisible(true); + cardSizeWidget->setVisible(true); + databaseView->setVisible(false); + populateCards(); + } +} + void VisualDatabaseDisplayWidget::onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance) { emit cardClickedDatabaseDisplay(event, instance); @@ -246,17 +280,19 @@ void VisualDatabaseDisplayWidget::updateSearch(const QString &search) const void VisualDatabaseDisplayWidget::searchModelChanged() { - // Clear the current page and prepare for new data - flowWidget->clearLayout(); // Clear existing cards - cards->clear(); // Clear the card list - // Reset scrollbar position to the top after loading new cards - if (QScrollBar *scrollBar = flowWidget->scrollArea->verticalScrollBar()) { - scrollBar->setValue(0); // Reset scrollbar to top - } + if (flowWidget->isVisible()) { + // Clear the current page and prepare for new data + flowWidget->clearLayout(); // Clear existing cards + cards->clear(); // Clear the card list + // Reset scrollbar position to the top after loading new cards + if (QScrollBar *scrollBar = flowWidget->scrollArea->verticalScrollBar()) { + scrollBar->setValue(0); // Reset scrollbar to top + } - currentPage = 0; - loadCurrentPage(); - qCDebug(VisualDatabaseDisplayLog) << "Search model changed"; + currentPage = 0; + loadCurrentPage(); + qCDebug(VisualDatabaseDisplayLog) << "Search model changed"; + } } void VisualDatabaseDisplayWidget::loadCurrentPage() diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h index c05c755f1..65eab99a4 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h @@ -57,6 +57,7 @@ public: QWidget *searchContainer; QHBoxLayout *searchLayout; SearchLineEdit *searchEdit; + QPushButton *displayModeButton; FilterTreeModel *filterModel; VisualDatabaseDisplayColorFilterWidget *colorFilterWidget; @@ -76,6 +77,7 @@ protected slots: void wheelEvent(QWheelEvent *event) override; void modelDirty() const; void updateSearch(const QString &search) const; + void onDisplayModeChanged(bool checked); private: QLabel *databaseLoadIndicator; From 122926c6cd8838e6c042bcf6ac97d7be378e87f4 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Thu, 27 Nov 2025 23:11:43 +0100 Subject: [PATCH 06/40] Deck Editor owns DeckHistoryManager (#6359) Took 4 minutes --- .../deck_editor_deck_dock_widget.cpp | 46 ++++++++----------- .../deck_editor_deck_dock_widget.h | 6 +-- .../widgets/tabs/abstract_tab_deck_editor.cpp | 27 ++++++++++- .../widgets/tabs/abstract_tab_deck_editor.h | 18 +++++++- 4 files changed, 64 insertions(+), 33 deletions(-) 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 56bd16f0a..4db7b8774 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 @@ -52,11 +52,6 @@ DeckEditorDeckDockWidget::DeckEditorDeckDockWidget(AbstractTabDeckEditor *parent void DeckEditorDeckDockWidget::createDeckDock() { - historyManager = new DeckListHistoryManager(); - - connect(deckEditor, &AbstractTabDeckEditor::cardAboutToBeAdded, this, - &DeckEditorDeckDockWidget::onCardAboutToBeAdded); - deckModel = new DeckListModel(this); deckModel->setObjectName("deckModel"); connect(deckModel, &DeckListModel::deckHashChanged, this, &DeckEditorDeckDockWidget::updateHash); @@ -66,7 +61,7 @@ void DeckEditorDeckDockWidget::createDeckDock() proxy = new DeckListStyleProxy(this); proxy->setSourceModel(deckModel); - historyManagerWidget = new DeckListHistoryManagerWidget(deckModel, proxy, historyManager, this); + historyManagerWidget = new DeckListHistoryManagerWidget(deckModel, proxy, deckEditor->getHistoryManager(), this); connect(historyManagerWidget, &DeckListHistoryManagerWidget::requestDisplayWidgetSync, this, &DeckEditorDeckDockWidget::syncDisplayWidgetsToModel); @@ -300,8 +295,8 @@ void DeckEditorDeckDockWidget::updateCard(const QModelIndex /*¤t*/, const void DeckEditorDeckDockWidget::updateName(const QString &name) { - historyManager->save(deckLoader->getDeckList()->createMemento( - QString(tr("Rename deck to \"%1\" from \"%2\"")).arg(name).arg(deckLoader->getDeckList()->getName()))); + emit requestDeckHistorySave( + QString(tr("Rename deck to \"%1\" from \"%2\"")).arg(name).arg(deckLoader->getDeckList()->getName())); deckModel->getDeckList()->setName(name); deckEditor->setModified(name.isEmpty()); emit nameChanged(); @@ -310,10 +305,9 @@ void DeckEditorDeckDockWidget::updateName(const QString &name) void DeckEditorDeckDockWidget::updateComments() { - historyManager->save( - deckLoader->getDeckList()->createMemento(QString(tr("Updated comments (was %1 chars, now %2 chars)")) - .arg(deckLoader->getDeckList()->getComments().size()) - .arg(commentsEdit->toPlainText().size()))); + emit requestDeckHistorySave(tr("Updated comments (was %1 chars, now %2 chars)") + .arg(deckLoader->getDeckList()->getComments().size()) + .arg(commentsEdit->toPlainText().size())); deckModel->getDeckList()->setComments(commentsEdit->toPlainText()); deckEditor->setModified(commentsEdit->toPlainText().isEmpty()); @@ -370,7 +364,7 @@ void DeckEditorDeckDockWidget::updateBannerCardComboBox() // Handle results if (restoreIndex != -1) { bannerCardComboBox->setCurrentIndex(restoreIndex); - setBannerCard(restoreIndex); + syncDeckListBannerCardWithComboBox(); } else { // Add a placeholder "-" and set it as the current selection bannerCardComboBox->insertItem(0, "-"); @@ -383,13 +377,18 @@ void DeckEditorDeckDockWidget::updateBannerCardComboBox() void DeckEditorDeckDockWidget::setBannerCard(int /* changedIndex */) { - historyManager->save(deckLoader->getDeckList()->createMemento(tr("Banner card changed"))); - auto [name, id] = bannerCardComboBox->currentData().value>(); - deckModel->getDeckList()->setBannerCard({name, id}); + emit requestDeckHistorySave(tr("Banner card changed")); + syncDeckListBannerCardWithComboBox(); deckEditor->setModified(true); emit deckModified(); } +void DeckEditorDeckDockWidget::syncDeckListBannerCardWithComboBox() +{ + auto [name, id] = bannerCardComboBox->currentData().value>(); + deckModel->getDeckList()->setBannerCard({name, id}); +} + void DeckEditorDeckDockWidget::updateShowBannerCardComboBox(const bool visible) { bannerCardLabel->setHidden(!visible); @@ -427,7 +426,7 @@ void DeckEditorDeckDockWidget::setDeck(DeckLoader *_deck) connect(deckLoader, &DeckLoader::deckLoaded, deckModel, &DeckListModel::rebuildTree); connect(deckLoader->getDeckList(), &DeckList::deckHashChanged, deckModel, &DeckListModel::deckHashChanged); - historyManager->clear(); + emit requestDeckHistoryClear(); historyManagerWidget->setDeckListModel(deckModel); syncDisplayWidgetsToModel(); @@ -521,14 +520,6 @@ QModelIndexList DeckEditorDeckDockWidget::getSelectedCardNodes() const return selectedRows; } -void DeckEditorDeckDockWidget::onCardAboutToBeAdded(const ExactCard &addedCard, const QString &zoneName) -{ - historyManager->save(deckLoader->getDeckList()->createMemento( - QString(tr("Added (%1): %2 (%3) %4")) - .arg(zoneName, addedCard.getName(), addedCard.getPrinting().getSet()->getCorrectedShortName(), - addedCard.getPrinting().getProperty("num")))); -} - void DeckEditorDeckDockWidget::actIncrement() { auto selectedRows = getSelectedCardNodes(); @@ -649,8 +640,7 @@ void DeckEditorDeckDockWidget::actRemoveCard() QModelIndex sourceIndex = proxy->mapToSource(index); QString cardName = sourceIndex.sibling(sourceIndex.row(), 1).data().toString(); - historyManager->save( - deckLoader->getDeckList()->createMemento(QString(tr("Removed \"%1\" (all copies)")).arg(cardName))); + emit requestDeckHistorySave(QString(tr("Removed \"%1\" (all copies)")).arg(cardName)); deckModel->removeRow(sourceIndex.row(), sourceIndex.parent()); isModified = true; @@ -685,7 +675,7 @@ void DeckEditorDeckDockWidget::offsetCountAtIndex(const QModelIndex &idx, int of .arg(cardName) .arg(deckModel->data(sourceIndex.sibling(sourceIndex.row(), 4), Qt::DisplayRole).toString()); - historyManager->save(deckLoader->getDeckList()->createMemento(reason)); + emit requestDeckHistorySave(reason); if (new_count <= 0) { deckModel->removeRow(sourceIndex.row(), sourceIndex.parent()); 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 78d5da9f7..86f3db9f8 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 @@ -14,7 +14,6 @@ #include "../visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h" #include "deck_list_history_manager_widget.h" #include "deck_list_style_proxy.h" -#include "libcockatrice/deck_list/deck_list_history_manager.h" #include #include @@ -70,7 +69,6 @@ public slots: void actDecrementSelection(); void actSwapCard(); void actRemoveCard(); - void onCardAboutToBeAdded(const ExactCard &card, const QString &zoneName); void offsetCountAtIndex(const QModelIndex &idx, int offset); signals: @@ -79,11 +77,12 @@ signals: void hashChanged(); void deckChanged(); void deckModified(); + void requestDeckHistorySave(const QString &modificationReason); + void requestDeckHistoryClear(); void cardChanged(const ExactCard &_card); private: AbstractTabDeckEditor *deckEditor; - DeckListHistoryManager *historyManager; DeckListHistoryManagerWidget *historyManagerWidget; KeySignals deckViewKeySignals; QLabel *nameLabel; @@ -113,6 +112,7 @@ private slots: void updateName(const QString &name); void updateComments(); void setBannerCard(int); + void syncDeckListBannerCardWithComboBox(); void updateHash(); void refreshShortcuts(); void updateShowBannerCardComboBox(bool visible); 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 ad68ecdbc..a3d3fe2cf 100644 --- a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp +++ b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp @@ -58,6 +58,8 @@ AbstractTabDeckEditor::AbstractTabDeckEditor(TabSupervisor *_tabSupervisor) : Ta { setDockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks); + historyManager = new DeckListHistoryManager(this); + databaseDisplayDockWidget = new DeckEditorDatabaseDisplayWidget(this); deckDockWidget = new DeckEditorDeckDockWidget(this); cardInfoDockWidget = new DeckEditorCardInfoDockWidget(this); @@ -70,6 +72,10 @@ AbstractTabDeckEditor::AbstractTabDeckEditor(TabSupervisor *_tabSupervisor) : Ta // Connect deck signals to this tab connect(deckDockWidget, &DeckEditorDeckDockWidget::deckChanged, this, &AbstractTabDeckEditor::onDeckChanged); connect(deckDockWidget, &DeckEditorDeckDockWidget::deckModified, this, &AbstractTabDeckEditor::onDeckModified); + connect(deckDockWidget, &DeckEditorDeckDockWidget::requestDeckHistorySave, this, + &AbstractTabDeckEditor::onDeckHistorySaveRequested); + connect(deckDockWidget, &DeckEditorDeckDockWidget::requestDeckHistoryClear, this, + &AbstractTabDeckEditor::onDeckHistoryClearRequested); connect(deckDockWidget, &DeckEditorDeckDockWidget::cardChanged, this, &AbstractTabDeckEditor::updateCard); connect(this, &AbstractTabDeckEditor::decrementCard, deckDockWidget, &DeckEditorDeckDockWidget::actDecrementCard); @@ -107,6 +113,7 @@ void AbstractTabDeckEditor::updateCard(const ExactCard &card) /** @brief Placeholder: called when the deck changes. */ void AbstractTabDeckEditor::onDeckChanged() { + historyManager->clear(); } /** @@ -118,6 +125,22 @@ void AbstractTabDeckEditor::onDeckModified() deckMenu->setSaveStatus(!isBlankNewDeck()); } +/** + * @brief Marks the tab as modified and updates the save menu status. + */ +void AbstractTabDeckEditor::onDeckHistorySaveRequested(const QString &modificationReason) +{ + historyManager->save(deckDockWidget->getDeckList()->createMemento(modificationReason)); +} + +/** + * @brief Marks the tab as modified and updates the save menu status. + */ +void AbstractTabDeckEditor::onDeckHistoryClearRequested() +{ + historyManager->clear(); +} + /** * @brief Helper for adding a card to a deck zone. * @param card Card to add. @@ -131,7 +154,9 @@ void AbstractTabDeckEditor::addCardHelper(const ExactCard &card, QString zoneNam if (card.getInfo().getIsToken()) zoneName = DECK_ZONE_TOKENS; - emit cardAboutToBeAdded(card, zoneName); + onDeckHistorySaveRequested(QString(tr("Added (%1): %2 (%3) %4")) + .arg(zoneName, card.getName(), card.getPrinting().getSet()->getCorrectedShortName(), + card.getPrinting().getProperty("num"))); QModelIndex newCardIndex = deckDockWidget->deckModel->addCard(card, zoneName); deckDockWidget->deckView->clearSelection(); 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 86517de63..8544e6c00 100644 --- a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.h +++ b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.h @@ -17,6 +17,8 @@ #include "../interface/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h" #include "tab.h" +#include + class CardDatabaseModel; class CardDatabaseDisplayModel; @@ -132,6 +134,13 @@ public: return deckDockWidget; } + DeckListHistoryManager *getHistoryManager() const + { + return historyManager; + } + + DeckListHistoryManager *historyManager; + // UI Elements DeckEditorMenu *deckMenu; ///< Menu for deck operations DeckEditorDatabaseDisplayWidget *databaseDisplayDockWidget; ///< Database dock @@ -147,6 +156,14 @@ public slots: /** @brief Called when the deck is modified. */ virtual void onDeckModified(); + /** @brief Called when a widget is about to modify the state of the DeckList. + * @param modificationReason The reason for the state modification + */ + virtual void onDeckHistorySaveRequested(const QString &modificationReason); + + /** @brief Called when a widget would like to clear the history. */ + virtual void onDeckHistoryClearRequested(); + /** @brief Updates the card info panel. * @param card The card to display. */ @@ -180,7 +197,6 @@ public slots: virtual void dockTopLevelChanged(bool topLevel) = 0; signals: - void cardAboutToBeAdded(const ExactCard &addedCard, const QString &zoneName); /** @brief Emitted when a deck should be opened in a new editor tab. */ void openDeckEditor(DeckLoader *deckLoader); From 587a8bc524505d5c12a3535e8b9f3788d92cf4e2 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Thu, 27 Nov 2025 23:31:40 +0100 Subject: [PATCH 07/40] [VDD] Add sorting (#6355) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [VDD] Add sorting Took 17 seconds Took 3 minutes * Adjust to contents. Took 13 minutes * Adjust sort order as well. Took 5 minutes --------- Co-authored-by: Lukas Brübach --- .../visual_database_display_widget.cpp | 49 +++++++++++++++++++ .../visual_database_display_widget.h | 5 ++ 2 files changed, 54 insertions(+) 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 66f6238b9..0c6f56894 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 @@ -98,12 +98,50 @@ VisualDatabaseDisplayWidget::VisualDatabaseDisplayWidget(QWidget *parent, searchEdit->setTreeView(databaseView); + sortByLabel = new QLabel(this); + sortColumnCombo = new QComboBox(this); + sortColumnCombo->setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy::AdjustToContents); + sortOrderCombo = new QComboBox(this); + sortOrderCombo->setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy::AdjustToContents); + + sortOrderCombo->addItem("Ascending", Qt::AscendingOrder); + sortOrderCombo->addItem("Descending", Qt::DescendingOrder); + sortOrderCombo->view()->setMinimumWidth(sortOrderCombo->view()->sizeHintForColumn(0)); + sortOrderCombo->adjustSize(); + + // Populate columns dynamically from the model + for (int i = 0; i < databaseDisplayModel->columnCount(); ++i) { + QString header = databaseDisplayModel->headerData(i, Qt::Horizontal).toString(); + sortColumnCombo->addItem(header, i); + } + + sortColumnCombo->view()->setMinimumWidth(sortColumnCombo->view()->sizeHintForColumn(0)); + sortColumnCombo->adjustSize(); + + connect(sortColumnCombo, QOverload::of(&QComboBox::currentIndexChanged), this, [this]() { + int column = sortColumnCombo->currentData().toInt(); + Qt::SortOrder order = static_cast(sortOrderCombo->currentData().toInt()); + databaseView->sortByColumn(column, order); + + searchModelChanged(); + }); + + connect(sortOrderCombo, QOverload::of(&QComboBox::currentIndexChanged), this, [this]() { + int column = sortColumnCombo->currentData().toInt(); + Qt::SortOrder order = static_cast(sortOrderCombo->currentData().toInt()); + databaseView->sortByColumn(column, order); + + searchModelChanged(); + }); + colorFilterWidget = new VisualDatabaseDisplayColorFilterWidget(this, filterModel); filterContainer = new QWidget(this); filterContainerLayout = new QHBoxLayout(filterContainer); filterContainer->setLayout(filterContainerLayout); + filterByLabel = new QLabel(this); + clearFilterWidget = new QToolButton(); clearFilterWidget->setFixedSize(32, 32); clearFilterWidget->setIcon(QPixmap("theme:icons/delete")); @@ -139,6 +177,8 @@ VisualDatabaseDisplayWidget::VisualDatabaseDisplayWidget(QWidget *parent, if (CardDatabaseManager::getInstance()->getLoadStatus() != LoadStatus::Ok) { connect(CardDatabaseManager::getInstance(), &CardDatabase::cardDatabaseLoadingFinished, this, &VisualDatabaseDisplayWidget::initialize); + sortByLabel->setVisible(false); + filterByLabel->setVisible(false); quickFilterSaveLoadWidget->setVisible(false); quickFilterNameWidget->setVisible(false); quickFilterSubTypeWidget->setVisible(false); @@ -155,6 +195,8 @@ void VisualDatabaseDisplayWidget::initialize() { databaseLoadIndicator->setVisible(false); + sortByLabel->setVisible(true); + filterByLabel->setVisible(true); quickFilterSaveLoadWidget->setVisible(true); quickFilterNameWidget->setVisible(true); quickFilterSubTypeWidget->setVisible(true); @@ -171,6 +213,10 @@ void VisualDatabaseDisplayWidget::initialize() quickFilterSubTypeWidget->addSettingsWidget(subTypeFilterWidget); quickFilterSetWidget->addSettingsWidget(setFilterWidget); + filterContainerLayout->addWidget(sortByLabel); + filterContainerLayout->addWidget(sortColumnCombo); + filterContainerLayout->addWidget(sortOrderCombo); + filterContainerLayout->addWidget(filterByLabel); filterContainerLayout->addWidget(quickFilterSaveLoadWidget); filterContainerLayout->addWidget(quickFilterNameWidget); filterContainerLayout->addWidget(quickFilterSubTypeWidget); @@ -216,6 +262,9 @@ void VisualDatabaseDisplayWidget::retranslateUi() clearFilterWidget->setToolTip(tr("Clear all filters")); + sortByLabel->setText(tr("Sort by:")); + filterByLabel->setText(tr("Filter by:")); + quickFilterSaveLoadWidget->setToolTip(tr("Save and load filters")); quickFilterNameWidget->setToolTip(tr("Filter by exact card name")); quickFilterSubTypeWidget->setToolTip(tr("Filter by card sub-type")); diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h index 65eab99a4..cc51cb003 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h @@ -81,6 +81,11 @@ protected slots: private: QLabel *databaseLoadIndicator; + + QLabel *sortByLabel; + QComboBox *sortColumnCombo, *sortOrderCombo; + + QLabel *filterByLabel; QToolButton *clearFilterWidget; QWidget *filterContainer; QHBoxLayout *filterContainerLayout; From bc2ae6c486a82d6aa6896008dc0d04b519f9b3fe Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Thu, 27 Nov 2025 23:41:44 +0100 Subject: [PATCH 08/40] Remember more card sizes. (#6360) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Took 22 minutes Co-authored-by: Lukas Brübach --- .../src/client/settings/cache_settings.cpp | 33 +++++++++++++++++++ .../src/client/settings/cache_settings.h | 28 ++++++++++++++++ .../tabs/api/edhrec/tab_edhrec_main.cpp | 5 ++- .../visual_database_display_widget.cpp | 4 ++- .../visual_deck_editor_widget.cpp | 5 ++- 5 files changed, 72 insertions(+), 3 deletions(-) diff --git a/cockatrice/src/client/settings/cache_settings.cpp b/cockatrice/src/client/settings/cache_settings.cpp index b9d2e6bb2..7a518df67 100644 --- a/cockatrice/src/client/settings/cache_settings.cpp +++ b/cockatrice/src/client/settings/cache_settings.cpp @@ -314,6 +314,11 @@ SettingsCache::SettingsCache() visualDatabaseDisplayFilterToMostRecentSetsAmount = settings->value("interface/visualdatabasedisplayfiltertomostrecentsetsamount", 10).toInt(); visualDeckEditorSampleHandSize = settings->value("interface/visualdeckeditorsamplehandsize", 7).toInt(); + visualDeckEditorCardSize = settings->value("interface/visualdeckeditorcardsize", 100).toInt(); + visualDatabaseDisplayCardSize = settings->value("interface/visualdatabasedisplaycardsize", 100).toInt(); + edhrecCardSize = settings->value("interface/edhreccardsize", 100).toInt(); + archidektPreviewSize = settings->value("interface/archidektpreviewsize", 100).toInt(); + horizontalHand = settings->value("hand/horizontal", true).toBool(); invertVerticalCoordinate = settings->value("table/invert_vertical", false).toBool(); minPlayersForMultiColumnLayout = settings->value("interface/min_players_multicolumn", 4).toInt(); @@ -863,6 +868,34 @@ void SettingsCache::setVisualDeckStorageSelectionAnimation(QT_STATE_CHANGED_T va emit visualDeckStorageSelectionAnimationChanged(visualDeckStorageSelectionAnimation); } +void SettingsCache::setVisualDeckEditorCardSize(int _visualDeckEditorCardSize) +{ + visualDeckEditorCardSize = _visualDeckEditorCardSize; + settings->setValue("interface/visualdeckeditorcardsize", visualDeckEditorCardSize); + emit visualDeckEditorCardSizeChanged(); +} + +void SettingsCache::setVisualDatabaseDisplayCardSize(int _visualDatabaseDisplayCardSize) +{ + visualDatabaseDisplayCardSize = _visualDatabaseDisplayCardSize; + settings->setValue("interface/visualdatabasedisplaycardsize", visualDatabaseDisplayCardSize); + emit visualDatabaseDisplayCardSizeChanged(); +} + +void SettingsCache::setEDHRecCardSize(int _edhrecCardSize) +{ + edhrecCardSize = _edhrecCardSize; + settings->setValue("interface/edhreccardsize", edhrecCardSize); + emit edhRecCardSizeChanged(); +} + +void SettingsCache::setArchidektPreviewCardSize(int _archidektPreviewCardSize) +{ + archidektPreviewSize = _archidektPreviewCardSize; + settings->setValue("interface/archidektpreviewsize", archidektPreviewSize); + emit archidektPreviewSizeChanged(); +} + void SettingsCache::setDefaultDeckEditorType(int value) { defaultDeckEditorType = value; diff --git a/cockatrice/src/client/settings/cache_settings.h b/cockatrice/src/client/settings/cache_settings.h index eb504e387..1cf04070c 100644 --- a/cockatrice/src/client/settings/cache_settings.h +++ b/cockatrice/src/client/settings/cache_settings.h @@ -167,6 +167,10 @@ signals: void visualDatabaseDisplayFilterToMostRecentSetsEnabledChanged(bool enabled); void visualDatabaseDisplayFilterToMostRecentSetsAmountChanged(int amount); void visualDeckEditorSampleHandSizeAmountChanged(int amount); + void visualDeckEditorCardSizeChanged(); + void visualDatabaseDisplayCardSizeChanged(); + void edhRecCardSizeChanged(); + void archidektPreviewSizeChanged(); void horizontalHandChanged(); void handJustificationChanged(); void invertVerticalCoordinateChanged(); @@ -250,6 +254,10 @@ private: QStringList visualDeckStorageDefaultTagsList; bool visualDeckStorageSearchFolderNames; int visualDeckStorageCardSize; + int visualDeckEditorCardSize; + int visualDatabaseDisplayCardSize; + int edhrecCardSize; + int archidektPreviewSize; bool visualDeckStorageDrawUnusedColorIdentities; int visualDeckStorageUnusedColorIdentitiesOpacity; int visualDeckStorageTooltipType; @@ -642,6 +650,22 @@ public: { return visualDeckStorageSelectionAnimation; } + int getVisualDeckEditorCardSize() const + { + return visualDeckEditorCardSize; + } + int getVisualDatabaseDisplayCardSize() const + { + return visualDatabaseDisplayCardSize; + } + int getEDHRecCardSize() const + { + return edhrecCardSize; + } + int getArchidektPreviewSize() const + { + return archidektPreviewSize; + } int getDefaultDeckEditorType() const { return defaultDeckEditorType; @@ -1018,6 +1042,10 @@ public slots: void setVisualDeckStorageAlwaysConvert(bool _visualDeckStorageAlwaysConvert); void setVisualDeckStorageInGame(QT_STATE_CHANGED_T value); void setVisualDeckStorageSelectionAnimation(QT_STATE_CHANGED_T value); + void setVisualDeckEditorCardSize(int _visualDeckEditorCardSize); + void setVisualDatabaseDisplayCardSize(int _visualDatabaseDisplayCardSize); + void setEDHRecCardSize(int _EDHRecCardSize); + void setArchidektPreviewCardSize(int _archidektPreviewCardSize); void setDefaultDeckEditorType(int value); void setVisualDatabaseDisplayFilterToMostRecentSetsEnabled(QT_STATE_CHANGED_T _enabled); void setVisualDatabaseDisplayFilterToMostRecentSetsAmount(int _amount); diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.cpp b/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.cpp index 208a5f717..0dcd5d0ae 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.cpp +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.cpp @@ -1,5 +1,6 @@ #include "tab_edhrec_main.h" +#include "../../../../../client/settings/cache_settings.h" #include "../../tab_supervisor.h" #include "api_response/average_deck/edhrec_average_deck_api_response.h" #include "api_response/commander/edhrec_commander_api_response.h" @@ -96,7 +97,9 @@ TabEdhRecMain::TabEdhRecMain(TabSupervisor *_tabSupervisor) : Tab(_tabSupervisor settingsButton = new SettingsButtonWidget(this); - cardSizeSlider = new CardSizeWidget(this); + cardSizeSlider = new CardSizeWidget(this, nullptr, SettingsCache::instance().getEDHRecCardSize()); + connect(cardSizeSlider, &CardSizeWidget::cardSizeSettingUpdated, &SettingsCache::instance(), + &SettingsCache::setEDHRecCardSize); settingsButton->addSettingsWidget(cardSizeSlider); 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 0c6f56894..7171d93b2 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 @@ -43,7 +43,9 @@ VisualDatabaseDisplayWidget::VisualDatabaseDisplayWidget(QWidget *parent, mainLayout->setContentsMargins(0, 0, 0, 0); flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarPolicy::ScrollBarAsNeeded); - cardSizeWidget = new CardSizeWidget(this, flowWidget); + cardSizeWidget = new CardSizeWidget(this, flowWidget, SettingsCache::instance().getVisualDatabaseDisplayCardSize()); + connect(cardSizeWidget, &CardSizeWidget::cardSizeSettingUpdated, &SettingsCache::instance(), + &SettingsCache::setVisualDatabaseDisplayCardSize); searchContainer = new QWidget(this); searchLayout = new QHBoxLayout(searchContainer); 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 3536359be..27f5b8e2e 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,5 +1,6 @@ #include "visual_deck_editor_widget.h" +#include "../../../client/settings/cache_settings.h" #include "../../../main.h" #include "../../deck_loader/deck_loader.h" #include "../../layouts/overlap_layout.h" @@ -194,7 +195,9 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, scrollArea->addScrollBarWidget(zoneContainer, Qt::AlignHCenter); scrollArea->setWidget(zoneContainer); - cardSizeWidget = new CardSizeWidget(this); + cardSizeWidget = new CardSizeWidget(this, nullptr, SettingsCache::instance().getVisualDeckEditorCardSize()); + connect(cardSizeWidget, &CardSizeWidget::cardSizeSettingUpdated, &SettingsCache::instance(), + &SettingsCache::setVisualDeckEditorCardSize); mainLayout->addWidget(groupAndSortContainer); mainLayout->addWidget(scrollArea); From a1a3b02d3a6eadc3b597df4e1ae1464b092baf9e Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Fri, 28 Nov 2025 00:42:46 +0100 Subject: [PATCH 09/40] Add clearer labeling, more tooltips, condense layout. (#6361) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Took 17 minutes Co-authored-by: Lukas Brübach --- .../visual_deck_editor_widget.cpp | 27 ++++++++++--------- .../visual_deck_editor_widget.h | 4 +-- 2 files changed, 17 insertions(+), 14 deletions(-) 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 27f5b8e2e..c1e5ead3a 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 @@ -38,10 +38,6 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, mainLayout->setContentsMargins(9, 0, 9, 5); mainLayout->setSpacing(0); - searchContainer = new QWidget(this); - searchLayout = new QHBoxLayout(searchContainer); - searchContainer->setLayout(searchLayout); - searchBar = new QLineEdit(this); connect(searchBar, &QLineEdit::returnPressed, this, [=, this]() { if (!searchBar->hasFocus()) @@ -114,16 +110,13 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, } }); - searchLayout->addWidget(searchBar); - searchLayout->addWidget(searchPushButton); - - mainLayout->addWidget(searchContainer); - groupAndSortContainer = new QWidget(this); groupAndSortLayout = new QHBoxLayout(groupAndSortContainer); groupAndSortLayout->setAlignment(Qt::AlignLeft); groupAndSortContainer->setLayout(groupAndSortLayout); + groupByLabel = new QLabel(groupAndSortContainer); + groupByComboBox = new QComboBox(this); if (auto tabWidget = qobject_cast(parent)) { // Inside a central widget QWidget container inside TabDeckEditorVisual @@ -149,6 +142,8 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, actChangeActiveGroupCriteria(); } + sortByLabel = new QLabel(groupAndSortContainer); + sortCriteriaButton = new SettingsButtonWidget(this); sortLabel = new QLabel(sortCriteriaButton); @@ -177,9 +172,13 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, displayTypeButton = new QPushButton(this); connect(displayTypeButton, &QPushButton::clicked, this, &VisualDeckEditorWidget::updateDisplayType); + groupAndSortLayout->addWidget(groupByLabel); groupAndSortLayout->addWidget(groupByComboBox); + groupAndSortLayout->addWidget(sortByLabel); groupAndSortLayout->addWidget(sortCriteriaButton); groupAndSortLayout->addWidget(displayTypeButton); + groupAndSortLayout->addWidget(searchBar); + groupAndSortLayout->addWidget(searchPushButton); scrollArea = new QScrollArea(this); scrollArea->setWidgetResizable(true); @@ -219,12 +218,16 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, void VisualDeckEditorWidget::retranslateUi() { + searchBar->setPlaceholderText(tr("Type a card name here for suggestions from the database...")); + groupByLabel->setText(tr("Group by:")); + groupByComboBox->setToolTip(tr("Change how cards are divided into categories/groups.")); + sortByLabel->setText(tr("Sort by:")); sortLabel->setText(tr("Click and drag to change the sort order within the groups")); searchPushButton->setText(tr("Quick search and add card")); searchPushButton->setToolTip(tr("Search for closest match in the database (with auto-suggestions) and add " "preferred printing to the deck on pressing enter")); sortCriteriaButton->setToolTip(tr("Configure how cards are sorted within their groups")); - displayTypeButton->setText(tr("Overlap Layout")); + displayTypeButton->setText(tr("Toggle Layout: Overlap")); displayTypeButton->setToolTip( tr("Change how cards are displayed within zones (i.e. overlapped or fully visible.)")); } @@ -376,10 +379,10 @@ void VisualDeckEditorWidget::updateDisplayType() // Update UI and emit signal switch (currentDisplayType) { case DisplayType::Flat: - displayTypeButton->setText(tr("Flat Layout")); + displayTypeButton->setText(tr("Toggle Layout: Flat")); break; case DisplayType::Overlap: - displayTypeButton->setText(tr("Overlap Layout")); + displayTypeButton->setText(tr("Toggle Layout: Overlap")); break; } emit displayTypeChanged(currentDisplayType); diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h index 4cff68407..e8ededc77 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h @@ -82,8 +82,6 @@ private: DeckListModel *deckListModel; QItemSelectionModel *selectionModel; QVBoxLayout *mainLayout; - QWidget *searchContainer; - QHBoxLayout *searchLayout; CardDatabaseModel *cardDatabaseModel; CardDatabaseDisplayModel *cardDatabaseDisplayModel; CardCompleterProxyModel *proxyModel; @@ -93,9 +91,11 @@ private: QPushButton *displayTypeButton; QWidget *groupAndSortContainer; QHBoxLayout *groupAndSortLayout; + QLabel *groupByLabel; QComboBox *groupByComboBox; QString activeGroupCriteria = "maintype"; SettingsButtonWidget *sortCriteriaButton; + QLabel *sortByLabel; QLabel *sortLabel; QListWidget *sortByListWidget; QStringList activeSortCriteria = {"name", "cmc", "colors", "maintype"}; From 9ece4bfd9ba9908b5db5a8b0e1da1ad5c9621450 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Fri, 28 Nov 2025 21:38:54 +0100 Subject: [PATCH 10/40] [Fix-Warnings] Mark const getters as [[nodiscard]] (#6365) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Took 45 minutes Co-authored-by: Lukas Brübach --- .../src/client/settings/cache_settings.h | 304 +++++++++--------- .../client/settings/card_counter_settings.h | 4 +- .../src/client/settings/shortcut_treeview.h | 2 +- .../src/client/settings/shortcuts_settings.h | 28 +- .../settings_card_preference_provider.h | 4 +- cockatrice/src/filters/deck_filter_string.h | 2 +- cockatrice/src/filters/filter_tree_model.h | 20 +- .../card_picture_loader_local.h | 10 +- .../src/interface/deck_loader/deck_loader.h | 8 +- .../src/interface/layouts/flow_layout.h | 8 +- .../deck_editor_deck_dock_widget.h | 2 +- .../dialogs/dlg_convert_deck_to_cod_format.h | 2 +- .../widgets/dialogs/dlg_edit_password.h | 4 +- .../widgets/dialogs/dlg_filter_games.h | 34 +- .../dialogs/dlg_forgot_password_request.h | 6 +- .../dialogs/dlg_forgot_password_reset.h | 10 +- .../interface/widgets/dialogs/dlg_register.h | 14 +- .../widgets/dialogs/tip_of_the_day.h | 12 +- .../widgets/replay/replay_timeline_widget.h | 6 +- .../interface/widgets/server/games_model.h | 51 +-- .../remote/remote_decklist_tree_widget.h | 41 +-- .../remote/remote_replay_list_tree_widget.h | 31 +- .../server/user/user_info_connection.h | 14 +- .../widgets/server/user/user_list_manager.h | 10 +- .../widgets/server/user/user_list_widget.h | 28 +- .../edhrec_api_response_card_container.h | 12 +- ...commander_api_response_commander_details.h | 58 ++-- .../widgets/tabs/api/edhrec/tab_edhrec_main.h | 4 +- cockatrice/src/interface/widgets/tabs/tab.h | 8 +- .../src/interface/widgets/tabs/tab_home.h | 2 +- .../src/interface/widgets/tabs/tab_message.h | 4 +- .../deck_preview_tag_display_widget.h | 6 +- .../libcockatrice/card/card_info.h | 48 +-- .../libcockatrice/card/card_info_comparator.h | 4 +- .../card/database/card_database_loader.h | 2 +- .../card/printing/printing_info.h | 10 +- .../libcockatrice/card/set/card_set.h | 20 +- .../deck_list/deck_list_card_node.h | 12 +- .../deck_list/deck_list_history_manager.h | 8 +- .../deck_list/deck_list_memento.h | 4 +- .../libcockatrice/filters/filter_card.h | 8 +- .../libcockatrice/filters/filter_string.h | 2 +- .../libcockatrice/filters/filter_tree.h | 86 ++--- .../interface_card_database_path_provider.h | 8 +- .../interface_card_preference_provider.h | 4 +- .../noop_card_database_path_provider.h | 8 +- .../noop_card_preference_provider.h | 4 +- .../card/card_completer_proxy_model.h | 2 +- .../models/database/card/card_search_model.h | 4 +- .../database/card_database_display_model.h | 10 +- .../models/database/card_database_model.h | 13 +- .../database/card_set/card_sets_model.h | 25 +- .../database/token/token_display_model.h | 4 +- .../models/database/token/token_edit_model.h | 4 +- .../models/deck_list/deck_list_model.h | 46 +-- .../deck_list_sort_filter_proxy_model.h | 2 +- .../libcockatrice/rng/rng_abstract.h | 2 +- .../settings/game_filters_settings.h | 2 +- 58 files changed, 548 insertions(+), 543 deletions(-) diff --git a/cockatrice/src/client/settings/cache_settings.h b/cockatrice/src/client/settings/cache_settings.h index 1cf04070c..5e329bf09 100644 --- a/cockatrice/src/client/settings/cache_settings.h +++ b/cockatrice/src/client/settings/cache_settings.h @@ -325,8 +325,8 @@ private: int keepalive; int timeout; void translateLegacySettings(); - QString getSafeConfigPath(QString configEntry, QString defaultPath) const; - QString getSafeConfigFilePath(QString configEntry, QString defaultPath) const; + [[nodiscard]] QString getSafeConfigPath(QString configEntry, QString defaultPath) const; + [[nodiscard]] QString getSafeConfigFilePath(QString configEntry, QString defaultPath) const; void loadPaths(); bool rememberGameSettings; QList releaseChannels; @@ -338,137 +338,137 @@ public: SettingsCache(); QString getDataPath(); QString getSettingsPath(); - QString getCachePath() const; - QString getNetworkCachePath() const; - const QByteArray &getMainWindowGeometry() const + [[nodiscard]] QString getCachePath() const; + [[nodiscard]] QString getNetworkCachePath() const; + [[nodiscard]] const QByteArray &getMainWindowGeometry() const { return mainWindowGeometry; } - const QByteArray &getTokenDialogGeometry() const + [[nodiscard]] const QByteArray &getTokenDialogGeometry() const { return tokenDialogGeometry; } - const QByteArray &getSetsDialogGeometry() const + [[nodiscard]] const QByteArray &getSetsDialogGeometry() const { return setsDialogGeometry; } - QString getLang() const + [[nodiscard]] QString getLang() const { return lang; } - QString getDeckPath() const + [[nodiscard]] QString getDeckPath() const { return deckPath; } - QString getFiltersPath() const + [[nodiscard]] QString getFiltersPath() const { return filtersPath; } - QString getReplaysPath() const + [[nodiscard]] QString getReplaysPath() const { return replaysPath; } - QString getThemesPath() const + [[nodiscard]] QString getThemesPath() const { return themesPath; } - QString getPicsPath() const + [[nodiscard]] QString getPicsPath() const { return picsPath; } - QString getRedirectCachePath() const + [[nodiscard]] QString getRedirectCachePath() const { return redirectCachePath; } - QString getCustomPicsPath() const + [[nodiscard]] QString getCustomPicsPath() const { return customPicsPath; } - QString getCustomCardDatabasePath() const override + [[nodiscard]] QString getCustomCardDatabasePath() const override { return customCardDatabasePath; } - QString getCardDatabasePath() const override + [[nodiscard]] QString getCardDatabasePath() const override { return cardDatabasePath; } - QString getSpoilerCardDatabasePath() const override + [[nodiscard]] QString getSpoilerCardDatabasePath() const override { return spoilerDatabasePath; } - QString getTokenDatabasePath() const override + [[nodiscard]] QString getTokenDatabasePath() const override { return tokenDatabasePath; } - QString getThemeName() const + [[nodiscard]] QString getThemeName() const { return themeName; } - QString getHomeTabBackgroundSource() const + [[nodiscard]] QString getHomeTabBackgroundSource() const { return homeTabBackgroundSource; } - int getHomeTabBackgroundShuffleFrequency() const + [[nodiscard]] int getHomeTabBackgroundShuffleFrequency() const { return homeTabBackgroundShuffleFrequency; } - bool getTabVisualDeckStorageOpen() const + [[nodiscard]] bool getTabVisualDeckStorageOpen() const { return tabVisualDeckStorageOpen; } - bool getTabServerOpen() const + [[nodiscard]] bool getTabServerOpen() const { return tabServerOpen; } - bool getTabAccountOpen() const + [[nodiscard]] bool getTabAccountOpen() const { return tabAccountOpen; } - bool getTabDeckStorageOpen() const + [[nodiscard]] bool getTabDeckStorageOpen() const { return tabDeckStorageOpen; } - bool getTabReplaysOpen() const + [[nodiscard]] bool getTabReplaysOpen() const { return tabReplaysOpen; } - bool getTabAdminOpen() const + [[nodiscard]] bool getTabAdminOpen() const { return tabAdminOpen; } - bool getTabLogOpen() const + [[nodiscard]] bool getTabLogOpen() const { return tabLogOpen; } - QString getChatMentionColor() const + [[nodiscard]] QString getChatMentionColor() const { return chatMentionColor; } - QString getChatHighlightColor() const + [[nodiscard]] QString getChatHighlightColor() const { return chatHighlightColor; } - bool getPicDownload() const + [[nodiscard]] bool getPicDownload() const { return picDownload; } - bool getShowStatusBar() const + [[nodiscard]] bool getShowStatusBar() const { return showStatusBar; } - bool getNotificationsEnabled() const + [[nodiscard]] bool getNotificationsEnabled() const { return notificationsEnabled; } - bool getSpectatorNotificationsEnabled() const + [[nodiscard]] bool getSpectatorNotificationsEnabled() const { return spectatorNotificationsEnabled; } - bool getBuddyConnectNotificationsEnabled() const + [[nodiscard]] bool getBuddyConnectNotificationsEnabled() const { return buddyConnectNotificationsEnabled; } - bool getCheckUpdatesOnStartup() const + [[nodiscard]] bool getCheckUpdatesOnStartup() const { return checkUpdatesOnStartup; } @@ -480,263 +480,263 @@ public: { return startupCardUpdateCheckAlwaysUpdate; } - int getCardUpdateCheckInterval() const + [[nodiscard]] int getCardUpdateCheckInterval() const { return cardUpdateCheckInterval; } - QDate getLastCardUpdateCheck() const + [[nodiscard]] QDate getLastCardUpdateCheck() const { return lastCardUpdateCheck; } - bool getCardUpdateCheckRequired() const + [[nodiscard]] bool getCardUpdateCheckRequired() const { return getLastCardUpdateCheck().daysTo(QDateTime::currentDateTime().date()) >= getCardUpdateCheckInterval() && getLastCardUpdateCheck() != QDateTime::currentDateTime().date(); } - bool getNotifyAboutUpdates() const override + [[nodiscard]] bool getNotifyAboutUpdates() const override { return notifyAboutUpdates; } - bool getNotifyAboutNewVersion() const + [[nodiscard]] bool getNotifyAboutNewVersion() const { return notifyAboutNewVersion; } - bool getShowTipsOnStartup() const + [[nodiscard]] bool getShowTipsOnStartup() const { return showTipsOnStartup; } - QList getSeenTips() const + [[nodiscard]] QList getSeenTips() const { return seenTips; } - int getUpdateReleaseChannelIndex() const + [[nodiscard]] int getUpdateReleaseChannelIndex() const { return updateReleaseChannel; } - ReleaseChannel *getUpdateReleaseChannel() const + [[nodiscard]] ReleaseChannel *getUpdateReleaseChannel() const { return releaseChannels.at(qMax(0, updateReleaseChannel)); } - QList getUpdateReleaseChannels() const + [[nodiscard]] QList getUpdateReleaseChannels() const { return releaseChannels; } - bool getDoubleClickToPlay() const + [[nodiscard]] bool getDoubleClickToPlay() const { return doubleClickToPlay; } - bool getClickPlaysAllSelected() const + [[nodiscard]] bool getClickPlaysAllSelected() const { return clickPlaysAllSelected; } - bool getPlayToStack() const + [[nodiscard]] bool getPlayToStack() const { return playToStack; } - bool getDoNotDeleteArrowsInSubPhases() const + [[nodiscard]] bool getDoNotDeleteArrowsInSubPhases() const { return doNotDeleteArrowsInSubPhases; } - int getStartingHandSize() const + [[nodiscard]] int getStartingHandSize() const { return startingHandSize; } - bool getAnnotateTokens() const + [[nodiscard]] bool getAnnotateTokens() const { return annotateTokens; } - QByteArray getTabGameSplitterSizes() const + [[nodiscard]] QByteArray getTabGameSplitterSizes() const { return tabGameSplitterSizes; } - bool getShowShortcuts() const + [[nodiscard]] bool getShowShortcuts() const { return showShortcuts; } - bool getDisplayCardNames() const + [[nodiscard]] bool getDisplayCardNames() const { return displayCardNames; } - bool getOverrideAllCardArtWithPersonalPreference() const + [[nodiscard]] bool getOverrideAllCardArtWithPersonalPreference() const { return overrideAllCardArtWithPersonalPreference; } - bool getBumpSetsWithCardsInDeckToTop() const + [[nodiscard]] bool getBumpSetsWithCardsInDeckToTop() const { return bumpSetsWithCardsInDeckToTop; } - int getPrintingSelectorSortOrder() const + [[nodiscard]] int getPrintingSelectorSortOrder() const { return printingSelectorSortOrder; } - int getPrintingSelectorCardSize() const + [[nodiscard]] int getPrintingSelectorCardSize() const { return printingSelectorCardSize; } - bool getIncludeRebalancedCards() const + [[nodiscard]] bool getIncludeRebalancedCards() const { return includeRebalancedCards; } - bool getPrintingSelectorNavigationButtonsVisible() const + [[nodiscard]] bool getPrintingSelectorNavigationButtonsVisible() const { return printingSelectorNavigationButtonsVisible; } - bool getDeckEditorBannerCardComboBoxVisible() const + [[nodiscard]] bool getDeckEditorBannerCardComboBoxVisible() const { return deckEditorBannerCardComboBoxVisible; } - bool getDeckEditorTagsWidgetVisible() const + [[nodiscard]] bool getDeckEditorTagsWidgetVisible() const { return deckEditorTagsWidgetVisible; } - int getVisualDeckStorageSortingOrder() const + [[nodiscard]] int getVisualDeckStorageSortingOrder() const { return visualDeckStorageSortingOrder; } - bool getVisualDeckStorageShowFolders() const + [[nodiscard]] bool getVisualDeckStorageShowFolders() const { return visualDeckStorageShowFolders; } - bool getVisualDeckStorageShowTagFilter() const + [[nodiscard]] bool getVisualDeckStorageShowTagFilter() const { return visualDeckStorageShowTagFilter; } - QStringList getVisualDeckStorageDefaultTagsList() const + [[nodiscard]] QStringList getVisualDeckStorageDefaultTagsList() const { return visualDeckStorageDefaultTagsList; } - bool getVisualDeckStorageSearchFolderNames() const + [[nodiscard]] bool getVisualDeckStorageSearchFolderNames() const { return visualDeckStorageSearchFolderNames; } - bool getVisualDeckStorageShowBannerCardComboBox() const + [[nodiscard]] bool getVisualDeckStorageShowBannerCardComboBox() const { return visualDeckStorageShowBannerCardComboBox; } - bool getVisualDeckStorageShowTagsOnDeckPreviews() const + [[nodiscard]] bool getVisualDeckStorageShowTagsOnDeckPreviews() const { return visualDeckStorageShowTagsOnDeckPreviews; } - int getVisualDeckStorageCardSize() const + [[nodiscard]] int getVisualDeckStorageCardSize() const { return visualDeckStorageCardSize; } - bool getVisualDeckStorageDrawUnusedColorIdentities() const + [[nodiscard]] bool getVisualDeckStorageDrawUnusedColorIdentities() const { return visualDeckStorageDrawUnusedColorIdentities; } - int getVisualDeckStorageUnusedColorIdentitiesOpacity() const + [[nodiscard]] int getVisualDeckStorageUnusedColorIdentitiesOpacity() const { return visualDeckStorageUnusedColorIdentitiesOpacity; } - int getVisualDeckStorageTooltipType() const + [[nodiscard]] int getVisualDeckStorageTooltipType() const { return visualDeckStorageTooltipType; } - bool getVisualDeckStoragePromptForConversion() const + [[nodiscard]] bool getVisualDeckStoragePromptForConversion() const { return visualDeckStoragePromptForConversion; } - bool getVisualDeckStorageAlwaysConvert() const + [[nodiscard]] bool getVisualDeckStorageAlwaysConvert() const { return visualDeckStorageAlwaysConvert; } - bool getVisualDeckStorageInGame() const + [[nodiscard]] bool getVisualDeckStorageInGame() const { return visualDeckStorageInGame; } - bool getVisualDeckStorageSelectionAnimation() const + [[nodiscard]] bool getVisualDeckStorageSelectionAnimation() const { return visualDeckStorageSelectionAnimation; } - int getVisualDeckEditorCardSize() const + [[nodiscard]] int getVisualDeckEditorCardSize() const { return visualDeckEditorCardSize; } - int getVisualDatabaseDisplayCardSize() const + [[nodiscard]] int getVisualDatabaseDisplayCardSize() const { return visualDatabaseDisplayCardSize; } - int getEDHRecCardSize() const + [[nodiscard]] int getEDHRecCardSize() const { return edhrecCardSize; } - int getArchidektPreviewSize() const + [[nodiscard]] int getArchidektPreviewSize() const { return archidektPreviewSize; } - int getDefaultDeckEditorType() const + [[nodiscard]] int getDefaultDeckEditorType() const { return defaultDeckEditorType; } - bool getVisualDatabaseDisplayFilterToMostRecentSetsEnabled() const + [[nodiscard]] bool getVisualDatabaseDisplayFilterToMostRecentSetsEnabled() const { return visualDatabaseDisplayFilterToMostRecentSetsEnabled; } - int getVisualDatabaseDisplayFilterToMostRecentSetsAmount() const + [[nodiscard]] int getVisualDatabaseDisplayFilterToMostRecentSetsAmount() const { return visualDatabaseDisplayFilterToMostRecentSetsAmount; } - int getVisualDeckEditorSampleHandSize() const + [[nodiscard]] int getVisualDeckEditorSampleHandSize() const { return visualDeckEditorSampleHandSize; } - bool getHorizontalHand() const + [[nodiscard]] bool getHorizontalHand() const { return horizontalHand; } - bool getInvertVerticalCoordinate() const + [[nodiscard]] bool getInvertVerticalCoordinate() const { return invertVerticalCoordinate; } - int getMinPlayersForMultiColumnLayout() const + [[nodiscard]] int getMinPlayersForMultiColumnLayout() const { return minPlayersForMultiColumnLayout; } - bool getTapAnimation() const + [[nodiscard]] bool getTapAnimation() const { return tapAnimation; } - bool getAutoRotateSidewaysLayoutCards() const + [[nodiscard]] bool getAutoRotateSidewaysLayoutCards() const { return autoRotateSidewaysLayoutCards; } - bool getOpenDeckInNewTab() const + [[nodiscard]] bool getOpenDeckInNewTab() const { return openDeckInNewTab; } - int getRewindBufferingMs() const + [[nodiscard]] int getRewindBufferingMs() const { return rewindBufferingMs; } - bool getChatMention() const + [[nodiscard]] bool getChatMention() const { return chatMention; } - bool getChatMentionCompleter() const + [[nodiscard]] bool getChatMentionCompleter() const { return chatMentionCompleter; } - bool getChatMentionForeground() const + [[nodiscard]] bool getChatMentionForeground() const { return chatMentionForeground; } - bool getChatHighlightForeground() const + [[nodiscard]] bool getChatHighlightForeground() const { return chatHighlightForeground; } /** * Currently selected index for the `Group by X` QComboBox */ - int getZoneViewGroupByIndex() const + [[nodiscard]] int getZoneViewGroupByIndex() const { return zoneViewGroupByIndex; } /** * Currently selected index for the `Sort by X` QComboBox */ - int getZoneViewSortByIndex() const + [[nodiscard]] int getZoneViewSortByIndex() const { return zoneViewSortByIndex; } @@ -744,136 +744,136 @@ public: Returns if the view should be sorted into pile view. @return zoneViewPileView if the view should be sorted into pile view. */ - bool getZoneViewPileView() const + [[nodiscard]] bool getZoneViewPileView() const { return zoneViewPileView; } - bool getSoundEnabled() const + [[nodiscard]] bool getSoundEnabled() const { return soundEnabled; } - QString getSoundThemeName() const + [[nodiscard]] QString getSoundThemeName() const { return soundThemeName; } - bool getIgnoreUnregisteredUsers() const + [[nodiscard]] bool getIgnoreUnregisteredUsers() const { return ignoreUnregisteredUsers; } - bool getIgnoreUnregisteredUserMessages() const + [[nodiscard]] bool getIgnoreUnregisteredUserMessages() const { return ignoreUnregisteredUserMessages; } - int getPixmapCacheSize() const + [[nodiscard]] int getPixmapCacheSize() const { return pixmapCacheSize; } - int getNetworkCacheSizeInMB() const + [[nodiscard]] int getNetworkCacheSizeInMB() const { return networkCacheSize; } - int getRedirectCacheTtl() const + [[nodiscard]] int getRedirectCacheTtl() const { return redirectCacheTtl; } - bool getScaleCards() const + [[nodiscard]] bool getScaleCards() const { return scaleCards; } - int getStackCardOverlapPercent() const + [[nodiscard]] int getStackCardOverlapPercent() const { return verticalCardOverlapPercent; } - bool getShowMessagePopup() const + [[nodiscard]] bool getShowMessagePopup() const { return showMessagePopups; } - bool getShowMentionPopup() const + [[nodiscard]] bool getShowMentionPopup() const { return showMentionPopups; } - bool getRoomHistory() const + [[nodiscard]] bool getRoomHistory() const { return roomHistory; } - bool getLeftJustified() const + [[nodiscard]] bool getLeftJustified() const { return leftJustified; } - int getMasterVolume() const + [[nodiscard]] int getMasterVolume() const { return masterVolume; } - int getCardInfoViewMode() const + [[nodiscard]] int getCardInfoViewMode() const { return cardInfoViewMode; } - QStringList getCountries() const; - QString getHighlightWords() const + [[nodiscard]] QStringList getCountries() const; + [[nodiscard]] QString getHighlightWords() const { return highlightWords; } - QString getGameDescription() const + [[nodiscard]] QString getGameDescription() const { return gameDescription; } - int getMaxPlayers() const + [[nodiscard]] int getMaxPlayers() const { return maxPlayers; } - QString getGameTypes() const + [[nodiscard]] QString getGameTypes() const { return gameTypes; } - bool getOnlyBuddies() const + [[nodiscard]] bool getOnlyBuddies() const { return onlyBuddies; } - bool getOnlyRegistered() const + [[nodiscard]] bool getOnlyRegistered() const { return onlyRegistered; } - bool getSpectatorsAllowed() const + [[nodiscard]] bool getSpectatorsAllowed() const { return spectatorsAllowed; } - bool getSpectatorsNeedPassword() const + [[nodiscard]] bool getSpectatorsNeedPassword() const { return spectatorsNeedPassword; } - bool getSpectatorsCanTalk() const + [[nodiscard]] bool getSpectatorsCanTalk() const { return spectatorsCanTalk; } - bool getSpectatorsCanSeeEverything() const + [[nodiscard]] bool getSpectatorsCanSeeEverything() const { return spectatorsCanSeeEverything; } - int getDefaultStartingLifeTotal() const + [[nodiscard]] int getDefaultStartingLifeTotal() const { return defaultStartingLifeTotal; } - bool getShareDecklistsOnLoad() const + [[nodiscard]] bool getShareDecklistsOnLoad() const { return shareDecklistsOnLoad; } - bool getCreateGameAsSpectator() const + [[nodiscard]] bool getCreateGameAsSpectator() const { return createGameAsSpectator; } - bool getRememberGameSettings() const + [[nodiscard]] bool getRememberGameSettings() const { return rememberGameSettings; } - int getKeepAlive() const override + [[nodiscard]] int getKeepAlive() const override { return keepalive; } - int getTimeOut() const override + [[nodiscard]] int getTimeOut() const override { return timeout; } - int getMaxFontSize() const + [[nodiscard]] int getMaxFontSize() const { return maxFontSize; } @@ -901,73 +901,73 @@ public: { return useTearOffMenus; } - int getCardViewInitialRowsMax() const + [[nodiscard]] int getCardViewInitialRowsMax() const { return cardViewInitialRowsMax; } - int getCardViewExpandedRowsMax() const + [[nodiscard]] int getCardViewExpandedRowsMax() const { return cardViewExpandedRowsMax; } - bool getCloseEmptyCardView() const + [[nodiscard]] bool getCloseEmptyCardView() const { return closeEmptyCardView; } - bool getFocusCardViewSearchBar() const + [[nodiscard]] bool getFocusCardViewSearchBar() const { return focusCardViewSearchBar; } - ShortcutsSettings &shortcuts() const + [[nodiscard]] ShortcutsSettings &shortcuts() const { return *shortcutsSettings; } - CardDatabaseSettings *cardDatabase() const + [[nodiscard]] CardDatabaseSettings *cardDatabase() const { return cardDatabaseSettings; } - ServersSettings &servers() const + [[nodiscard]] ServersSettings &servers() const { return *serversSettings; } - MessageSettings &messages() const + [[nodiscard]] MessageSettings &messages() const { return *messageSettings; } - GameFiltersSettings &gameFilters() const + [[nodiscard]] GameFiltersSettings &gameFilters() const { return *gameFiltersSettings; } - LayoutsSettings &layouts() const + [[nodiscard]] LayoutsSettings &layouts() const { return *layoutsSettings; } - DownloadSettings &downloads() const + [[nodiscard]] DownloadSettings &downloads() const { return *downloadSettings; } - RecentsSettings &recents() const + [[nodiscard]] RecentsSettings &recents() const { return *recentsSettings; } - CardOverrideSettings &cardOverrides() const + [[nodiscard]] CardOverrideSettings &cardOverrides() const { return *cardOverrideSettings; } - DebugSettings &debug() const + [[nodiscard]] DebugSettings &debug() const { return *debugSettings; } - CardCounterSettings &cardCounters() const; + [[nodiscard]] CardCounterSettings &cardCounters() const; - bool getIsPortableBuild() const + [[nodiscard]] bool getIsPortableBuild() const { return isPortableBuild; } - bool getDownloadSpoilersStatus() const + [[nodiscard]] bool getDownloadSpoilersStatus() const { return mbDownloadSpoilers; } - bool getRoundCardCorners() const + [[nodiscard]] bool getRoundCardCorners() const { return roundCardCorners; } diff --git a/cockatrice/src/client/settings/card_counter_settings.h b/cockatrice/src/client/settings/card_counter_settings.h index f2c1c1d43..63615d0e2 100644 --- a/cockatrice/src/client/settings/card_counter_settings.h +++ b/cockatrice/src/client/settings/card_counter_settings.h @@ -20,9 +20,9 @@ class CardCounterSettings : public SettingsManager public: CardCounterSettings(const QString &settingsPath, QObject *parent = nullptr); - QColor color(int counterId) const; + [[nodiscard]] QColor color(int counterId) const; - QString displayName(int counterId) const; + [[nodiscard]] QString displayName(int counterId) const; public slots: void setColor(int counterId, const QColor &color); diff --git a/cockatrice/src/client/settings/shortcut_treeview.h b/cockatrice/src/client/settings/shortcut_treeview.h index 229bf2ed2..d503140f0 100644 --- a/cockatrice/src/client/settings/shortcut_treeview.h +++ b/cockatrice/src/client/settings/shortcut_treeview.h @@ -22,7 +22,7 @@ public: explicit ShortcutFilterProxyModel(QObject *parent = nullptr); protected: - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; + [[nodiscard]] bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; }; class ShortcutTreeView : public QTreeView diff --git a/cockatrice/src/client/settings/shortcuts_settings.h b/cockatrice/src/client/settings/shortcuts_settings.h index 31e90bdc7..d1b0301d1 100644 --- a/cockatrice/src/client/settings/shortcuts_settings.h +++ b/cockatrice/src/client/settings/shortcuts_settings.h @@ -100,11 +100,11 @@ public: { QList::operator=(_sequence); }; - QString getName() const + [[nodiscard]] QString getName() const { return QApplication::translate("shortcutsTab", name.toUtf8().data()); }; - QString getGroupName() const + [[nodiscard]] QString getGroupName() const { return ShortcutGroup::getGroupName(group); }; @@ -120,13 +120,13 @@ class ShortcutsSettings : public QObject public: explicit ShortcutsSettings(const QString &settingsFilePath, QObject *parent = nullptr); - ShortcutKey getDefaultShortcut(const QString &name) const; - ShortcutKey getShortcut(const QString &name) const; - QKeySequence getSingleShortcut(const QString &name) const; - QString getDefaultShortcutString(const QString &name) const; - QString getShortcutString(const QString &name) const; - QString getShortcutFriendlyName(const QString &shortcutName) const; - QList getAllShortcutKeys() const + [[nodiscard]] ShortcutKey getDefaultShortcut(const QString &name) const; + [[nodiscard]] ShortcutKey getShortcut(const QString &name) const; + [[nodiscard]] QKeySequence getSingleShortcut(const QString &name) const; + [[nodiscard]] QString getDefaultShortcutString(const QString &name) const; + [[nodiscard]] QString getShortcutString(const QString &name) const; + [[nodiscard]] QString getShortcutFriendlyName(const QString &shortcutName) const; + [[nodiscard]] QList getAllShortcutKeys() const { return shortCuts.keys(); }; @@ -135,9 +135,9 @@ public: void setShortcuts(const QString &name, const QKeySequence &Sequence); void setShortcuts(const QString &name, const QString &sequences); - bool isKeyAllowed(const QString &name, const QString &sequences) const; - bool isValid(const QString &name, const QString &sequences) const; - QStringList findOverlaps(const QString &name, const QString &sequences) const; + [[nodiscard]] bool isKeyAllowed(const QString &name, const QString &sequences) const; + [[nodiscard]] bool isValid(const QString &name, const QString &sequences) const; + [[nodiscard]] QStringList findOverlaps(const QString &name, const QString &sequences) const; void resetAllShortcuts(); void clearAllShortcuts(); @@ -152,8 +152,8 @@ private: QString settingsFilePath; QHash shortCuts; - QString stringifySequence(const QList &Sequence) const; - QList parseSequenceString(const QString &stringSequence) const; + [[nodiscard]] QString stringifySequence(const QList &Sequence) const; + [[nodiscard]] QList parseSequenceString(const QString &stringSequence) const; const QHash defaultShortCuts = { {"MainWindow/aCheckCardUpdates", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Check for Card Updates..."), diff --git a/cockatrice/src/database/interface/settings_card_preference_provider.h b/cockatrice/src/database/interface/settings_card_preference_provider.h index 4197bb53c..5ec23ea60 100644 --- a/cockatrice/src/database/interface/settings_card_preference_provider.h +++ b/cockatrice/src/database/interface/settings_card_preference_provider.h @@ -7,12 +7,12 @@ class SettingsCardPreferenceProvider : public ICardPreferenceProvider { public: - QString getCardPreferenceOverride(const QString &cardName) const override + [[nodiscard]] QString getCardPreferenceOverride(const QString &cardName) const override { return SettingsCache::instance().cardOverrides().getCardPreferenceOverride(cardName); } - bool getIncludeRebalancedCards() const override + [[nodiscard]] bool getIncludeRebalancedCards() const override { return SettingsCache::instance().getIncludeRebalancedCards(); }; diff --git a/cockatrice/src/filters/deck_filter_string.h b/cockatrice/src/filters/deck_filter_string.h index 15782b3ad..635745592 100644 --- a/cockatrice/src/filters/deck_filter_string.h +++ b/cockatrice/src/filters/deck_filter_string.h @@ -40,7 +40,7 @@ public: return filter(deck, info); } - bool valid() const + [[nodiscard]] bool valid() const { return _error.isEmpty(); } diff --git a/cockatrice/src/filters/filter_tree_model.h b/cockatrice/src/filters/filter_tree_model.h index ce6eb85fc..c6666a838 100644 --- a/cockatrice/src/filters/filter_tree_model.h +++ b/cockatrice/src/filters/filter_tree_model.h @@ -24,8 +24,8 @@ public slots: void addFilter(const CardFilter *f); void removeFilter(const CardFilter *f); void clearFiltersOfType(CardFilter::Attr filterType); - QList getFiltersOfType(CardFilter::Attr filterType) const; - QList allFilters() const; + [[nodiscard]] QList getFiltersOfType(CardFilter::Attr filterType) const; + [[nodiscard]] QList allFilters() const; private slots: void proxyBeginInsertRow(const FilterTreeNode *, int); @@ -34,23 +34,23 @@ private slots: void proxyEndRemoveRow(const FilterTreeNode *, int); private: - FilterTreeNode *indexToNode(const QModelIndex &idx) const; + [[nodiscard]] FilterTreeNode *indexToNode(const QModelIndex &idx) const; QModelIndex nodeIndex(const FilterTreeNode *node, int row, int column) const; public: FilterTreeModel(QObject *parent = nullptr); ~FilterTreeModel() override; - FilterTree *filterTree() const + [[nodiscard]] FilterTree *filterTree() const { return fTree; } - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - int columnCount(const QModelIndex & /*parent*/ = QModelIndex()) const override; - QVariant data(const QModelIndex &index, int role) const override; + [[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override; + [[nodiscard]] int columnCount(const QModelIndex & /*parent*/ = QModelIndex()) const override; + [[nodiscard]] QVariant data(const QModelIndex &index, int role) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; - Qt::ItemFlags flags(const QModelIndex &index) const override; - QModelIndex parent(const QModelIndex &ind) const override; - QModelIndex index(int row, int column, const QModelIndex &parent) const override; + [[nodiscard]] Qt::ItemFlags flags(const QModelIndex &index) const override; + [[nodiscard]] QModelIndex parent(const QModelIndex &ind) const override; + [[nodiscard]] QModelIndex index(int row, int column, const QModelIndex &parent) const override; bool removeRows(int row, int count, const QModelIndex &parent) override; void clear(); }; diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.h b/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.h index 84f16cc38..25692f318 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.h +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.h @@ -42,7 +42,7 @@ public: * * Uses a set of name variants and folder paths to attempt to locate the correct image. */ - QImage tryLoad(const ExactCard &toLoad) const; + [[nodiscard]] QImage tryLoad(const ExactCard &toLoad) const; private: QString picsPath; ///< Path to standard card image folder @@ -72,10 +72,10 @@ private: * Uses several filename patterns to match card images, in order from * most-specific to least-specific. */ - QImage tryLoadCardImageFromDisk(const QString &setName, - const QString &correctedCardName, - const QString &collectorNumber, - const QString &providerId) const; + [[nodiscard]] QImage tryLoadCardImageFromDisk(const QString &setName, + const QString &correctedCardName, + const QString &collectorNumber, + const QString &providerId) const; private slots: /** diff --git a/cockatrice/src/interface/deck_loader/deck_loader.h b/cockatrice/src/interface/deck_loader/deck_loader.h index 57305b7de..ba9ba807d 100644 --- a/cockatrice/src/interface/deck_loader/deck_loader.h +++ b/cockatrice/src/interface/deck_loader/deck_loader.h @@ -56,7 +56,7 @@ public: DeckLoader(const DeckLoader &) = delete; DeckLoader &operator=(const DeckLoader &) = delete; - const QString &getLastFileName() const + [[nodiscard]] const QString &getLastFileName() const { return lastFileName; } @@ -64,16 +64,16 @@ public: { lastFileName = _lastFileName; } - FileFormat getLastFileFormat() const + [[nodiscard]] FileFormat getLastFileFormat() const { return lastFileFormat; } - int getLastRemoteDeckId() const + [[nodiscard]] int getLastRemoteDeckId() const { return lastRemoteDeckId; } - bool hasNotBeenLoaded() const + [[nodiscard]] bool hasNotBeenLoaded() const { return getLastFileName().isEmpty() && getLastRemoteDeckId() == -1; } diff --git a/cockatrice/src/interface/layouts/flow_layout.h b/cockatrice/src/interface/layouts/flow_layout.h index f4c9e3001..cf109d260 100644 --- a/cockatrice/src/interface/layouts/flow_layout.h +++ b/cockatrice/src/interface/layouts/flow_layout.h @@ -23,9 +23,9 @@ public: ~FlowLayout() override; void insertWidgetAtIndex(QWidget *toInsert, int index); - QSize calculateMinimumSizeHorizontal() const; - QSize calculateSizeHintVertical() const; - QSize calculateMinimumSizeVertical() const; + [[nodiscard]] QSize calculateMinimumSizeHorizontal() const; + [[nodiscard]] QSize calculateSizeHintVertical() const; + [[nodiscard]] QSize calculateMinimumSizeVertical() const; void addItem(QLayoutItem *item) override; [[nodiscard]] int count() const override; [[nodiscard]] QLayoutItem *itemAt(int index) const override; @@ -48,7 +48,7 @@ public: void layoutSingleColumn(const QVector &colItems, int x, int y); [[nodiscard]] QSize sizeHint() const override; [[nodiscard]] QSize minimumSize() const override; - QSize calculateSizeHintHorizontal() const; + [[nodiscard]] QSize calculateSizeHintHorizontal() const; protected: QList items; // List to store layout items 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 86f3db9f8..0c89d51f5 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 @@ -104,7 +104,7 @@ private: QAction *aRemoveCard, *aIncrement, *aDecrement, *aSwapCard; void recursiveExpand(const QModelIndex &index); - QModelIndexList getSelectedCardNodes() const; + [[nodiscard]] QModelIndexList getSelectedCardNodes() const; private slots: void decklistCustomMenu(QPoint point); diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_convert_deck_to_cod_format.h b/cockatrice/src/interface/widgets/dialogs/dlg_convert_deck_to_cod_format.h index 7c5ea303a..61eea1d6e 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_convert_deck_to_cod_format.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_convert_deck_to_cod_format.h @@ -22,7 +22,7 @@ public: explicit DialogConvertDeckToCodFormat(QWidget *parent); void retranslateUi(); - bool dontAskAgain() const; + [[nodiscard]] bool dontAskAgain() const; private: QVBoxLayout *layout; diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_edit_password.h b/cockatrice/src/interface/widgets/dialogs/dlg_edit_password.h index 38f782228..311774d11 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_edit_password.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_edit_password.h @@ -20,11 +20,11 @@ class DlgEditPassword : public QDialog Q_OBJECT public: explicit DlgEditPassword(QWidget *parent = nullptr); - QString getOldPassword() const + [[nodiscard]] QString getOldPassword() const { return oldPasswordEdit->text(); } - QString getNewPassword() const + [[nodiscard]] QString getNewPassword() const { return newPasswordEdit->text(); } diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_filter_games.h b/cockatrice/src/interface/widgets/dialogs/dlg_filter_games.h index 37b208749..abfdab28a 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_filter_games.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_filter_games.h @@ -58,32 +58,32 @@ public: const GamesProxyModel *_gamesProxyModel, QWidget *parent = nullptr); - bool getHideFullGames() const; - bool getHideGamesThatStarted() const; - bool getHidePasswordProtectedGames() const; + [[nodiscard]] bool getHideFullGames() const; + [[nodiscard]] bool getHideGamesThatStarted() const; + [[nodiscard]] bool getHidePasswordProtectedGames() const; void setShowPasswordProtectedGames(bool _passwordProtectedGamesHidden); - bool getHideBuddiesOnlyGames() const; + [[nodiscard]] bool getHideBuddiesOnlyGames() const; void setHideBuddiesOnlyGames(bool _hideBuddiesOnlyGames); - bool getHideOpenDecklistGames() const; + [[nodiscard]] bool getHideOpenDecklistGames() const; void setHideOpenDecklistGames(bool _hideOpenDecklistGames); - bool getHideIgnoredUserGames() const; + [[nodiscard]] bool getHideIgnoredUserGames() const; void setHideIgnoredUserGames(bool _hideIgnoredUserGames); - bool getHideNotBuddyCreatedGames() const; - QString getGameNameFilter() const; + [[nodiscard]] bool getHideNotBuddyCreatedGames() const; + [[nodiscard]] QString getGameNameFilter() const; void setGameNameFilter(const QString &_gameNameFilter); - QStringList getCreatorNameFilters() const; + [[nodiscard]] QStringList getCreatorNameFilters() const; void setCreatorNameFilter(const QString &_creatorNameFilter); - QSet getGameTypeFilter() const; + [[nodiscard]] QSet getGameTypeFilter() const; void setGameTypeFilter(const QSet &_gameTypeFilter); - int getMaxPlayersFilterMin() const; - int getMaxPlayersFilterMax() const; + [[nodiscard]] int getMaxPlayersFilterMin() const; + [[nodiscard]] int getMaxPlayersFilterMax() const; void setMaxPlayersFilter(int _maxPlayersFilterMin, int _maxPlayersFilterMax); - QTime getMaxGameAge() const; + [[nodiscard]] QTime getMaxGameAge() const; const QMap gameAgeMap; - bool getShowOnlyIfSpectatorsCanWatch() const; - bool getShowSpectatorPasswordProtected() const; - bool getShowOnlyIfSpectatorsCanChat() const; - bool getShowOnlyIfSpectatorsCanSeeHands() const; + [[nodiscard]] bool getShowOnlyIfSpectatorsCanWatch() const; + [[nodiscard]] bool getShowSpectatorPasswordProtected() const; + [[nodiscard]] bool getShowOnlyIfSpectatorsCanChat() const; + [[nodiscard]] bool getShowOnlyIfSpectatorsCanSeeHands() const; }; #endif diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_request.h b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_request.h index da4d9e726..e51dad810 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_request.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_request.h @@ -20,15 +20,15 @@ class DlgForgotPasswordRequest : public QDialog Q_OBJECT public: explicit DlgForgotPasswordRequest(QWidget *parent = nullptr); - QString getHost() const + [[nodiscard]] QString getHost() const { return hostEdit->text(); } - int getPort() const + [[nodiscard]] int getPort() const { return portEdit->text().toInt(); } - QString getPlayerName() const + [[nodiscard]] QString getPlayerName() const { return playernameEdit->text(); } diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_reset.h b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_reset.h index ede22e2aa..3d110c71d 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_reset.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_reset.h @@ -20,23 +20,23 @@ class DlgForgotPasswordReset : public QDialog Q_OBJECT public: explicit DlgForgotPasswordReset(QWidget *parent = nullptr); - QString getHost() const + [[nodiscard]] QString getHost() const { return hostEdit->text(); } - int getPort() const + [[nodiscard]] int getPort() const { return portEdit->text().toInt(); } - QString getPlayerName() const + [[nodiscard]] QString getPlayerName() const { return playernameEdit->text(); } - QString getToken() const + [[nodiscard]] QString getToken() const { return tokenEdit->text(); } - QString getPassword() const + [[nodiscard]] QString getPassword() const { return newpasswordEdit->text(); } diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_register.h b/cockatrice/src/interface/widgets/dialogs/dlg_register.h index a614386fc..bebbfc500 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_register.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_register.h @@ -20,31 +20,31 @@ class DlgRegister : public QDialog Q_OBJECT public: explicit DlgRegister(QWidget *parent = nullptr); - QString getHost() const + [[nodiscard]] QString getHost() const { return hostEdit->text(); } - int getPort() const + [[nodiscard]] int getPort() const { return portEdit->text().toInt(); } - QString getPlayerName() const + [[nodiscard]] QString getPlayerName() const { return playernameEdit->text(); } - QString getPassword() const + [[nodiscard]] QString getPassword() const { return passwordEdit->text(); } - QString getEmail() const + [[nodiscard]] QString getEmail() const { return emailEdit->text(); } - QString getCountry() const + [[nodiscard]] QString getCountry() const { return countryEdit->currentIndex() == 0 ? "" : countryEdit->currentText(); } - QString getRealName() const + [[nodiscard]] QString getRealName() const { return realnameEdit->text(); } diff --git a/cockatrice/src/interface/widgets/dialogs/tip_of_the_day.h b/cockatrice/src/interface/widgets/dialogs/tip_of_the_day.h index 1cb0cf6fb..d61fddab5 100644 --- a/cockatrice/src/interface/widgets/dialogs/tip_of_the_day.h +++ b/cockatrice/src/interface/widgets/dialogs/tip_of_the_day.h @@ -14,19 +14,19 @@ class TipOfTheDay { public: explicit TipOfTheDay(QString _title, QString _content, QString _imagePath, QDate _date); - QString getTitle() const + [[nodiscard]] QString getTitle() const { return title; } - QString getContent() const + [[nodiscard]] QString getContent() const { return content; } - QString getImagePath() const + [[nodiscard]] QString getImagePath() const { return imagePath; } - QDate getDate() const + [[nodiscard]] QDate getDate() const { return date; } @@ -51,8 +51,8 @@ public: explicit TipsOfTheDay(QString xmlPath, QObject *parent = nullptr); ~TipsOfTheDay() override; TipOfTheDay getTip(int tipId); - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - QVariant data(const QModelIndex &index, int role) const override; + [[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override; + [[nodiscard]] QVariant data(const QModelIndex &index, int role) const override; private: QList *tipList; diff --git a/cockatrice/src/interface/widgets/replay/replay_timeline_widget.h b/cockatrice/src/interface/widgets/replay/replay_timeline_widget.h index e55d408ce..17a235365 100644 --- a/cockatrice/src/interface/widgets/replay/replay_timeline_widget.h +++ b/cockatrice/src/interface/widgets/replay/replay_timeline_widget.h @@ -60,10 +60,10 @@ public: explicit ReplayTimelineWidget(QWidget *parent = nullptr); void setTimeline(const QList &_replayTimeline); - QSize sizeHint() const override; - QSize minimumSizeHint() const override; + [[nodiscard]] QSize sizeHint() const override; + [[nodiscard]] QSize minimumSizeHint() const override; void setTimeScaleFactor(qreal _timeScaleFactor); - int getCurrentEvent() const + [[nodiscard]] int getCurrentEvent() const { return currentEvent; } diff --git a/cockatrice/src/interface/widgets/server/games_model.h b/cockatrice/src/interface/widgets/server/games_model.h index c704befcc..03602a74e 100644 --- a/cockatrice/src/interface/widgets/server/games_model.h +++ b/cockatrice/src/interface/widgets/server/games_model.h @@ -42,19 +42,20 @@ public: */ GamesModel(const QMap &_rooms, const QMap &_gameTypes, QObject *parent = nullptr); - int rowCount(const QModelIndex &parent = QModelIndex()) const override + [[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override { return parent.isValid() ? 0 : gameList.size(); } - int columnCount(const QModelIndex & /*parent*/ = QModelIndex()) const override + [[nodiscard]] int columnCount(const QModelIndex & /*parent*/ = QModelIndex()) const override { return NUM_COLS; } - QVariant data(const QModelIndex &index, int role) const override; + [[nodiscard]] QVariant data(const QModelIndex &index, int role) const override; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + [[nodiscard]] QVariant + headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; /** * @brief Formats the game creation time into a human-readable string. @@ -148,71 +149,71 @@ public: explicit GamesProxyModel(QObject *parent = nullptr, const UserListProxy *_userListProxy = nullptr); // Getters for filter parameters - bool getHideBuddiesOnlyGames() const + [[nodiscard]] bool getHideBuddiesOnlyGames() const { return hideBuddiesOnlyGames; } - bool getHideIgnoredUserGames() const + [[nodiscard]] bool getHideIgnoredUserGames() const { return hideIgnoredUserGames; } - bool getHideFullGames() const + [[nodiscard]] bool getHideFullGames() const { return hideFullGames; } - bool getHideGamesThatStarted() const + [[nodiscard]] bool getHideGamesThatStarted() const { return hideGamesThatStarted; } - bool getHidePasswordProtectedGames() const + [[nodiscard]] bool getHidePasswordProtectedGames() const { return hidePasswordProtectedGames; } - bool getHideNotBuddyCreatedGames() const + [[nodiscard]] bool getHideNotBuddyCreatedGames() const { return hideNotBuddyCreatedGames; } - bool getHideOpenDecklistGames() const + [[nodiscard]] bool getHideOpenDecklistGames() const { return hideOpenDecklistGames; } - QString getGameNameFilter() const + [[nodiscard]] QString getGameNameFilter() const { return gameNameFilter; } - QStringList getCreatorNameFilters() const + [[nodiscard]] QStringList getCreatorNameFilters() const { return creatorNameFilters; } - QSet getGameTypeFilter() const + [[nodiscard]] QSet getGameTypeFilter() const { return gameTypeFilter; } - int getMaxPlayersFilterMin() const + [[nodiscard]] int getMaxPlayersFilterMin() const { return maxPlayersFilterMin; } - int getMaxPlayersFilterMax() const + [[nodiscard]] int getMaxPlayersFilterMax() const { return maxPlayersFilterMax; } - const QTime &getMaxGameAge() const + [[nodiscard]] const QTime &getMaxGameAge() const { return maxGameAge; } - bool getShowOnlyIfSpectatorsCanWatch() const + [[nodiscard]] bool getShowOnlyIfSpectatorsCanWatch() const { return showOnlyIfSpectatorsCanWatch; } - bool getShowSpectatorPasswordProtected() const + [[nodiscard]] bool getShowSpectatorPasswordProtected() const { return showSpectatorPasswordProtected; } - bool getShowOnlyIfSpectatorsCanChat() const + [[nodiscard]] bool getShowOnlyIfSpectatorsCanChat() const { return showOnlyIfSpectatorsCanChat; } - bool getShowOnlyIfSpectatorsCanSeeHands() const + [[nodiscard]] bool getShowOnlyIfSpectatorsCanSeeHands() const { return showOnlyIfSpectatorsCanSeeHands; } @@ -328,7 +329,7 @@ public: /** * @brief Returns the number of games filtered out by the current filter. */ - int getNumFilteredGames() const; + [[nodiscard]] int getNumFilteredGames() const; /** * @brief Resets all filter parameters to default values. @@ -338,7 +339,7 @@ public: /** * @brief Returns true if all filter parameters are set to their defaults. */ - bool areFilterParametersSetToDefaults() const; + [[nodiscard]] bool areFilterParametersSetToDefaults() const; /** * @brief Loads filter parameters from persistent settings. @@ -358,8 +359,8 @@ public: void refresh(); protected: - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; - bool filterAcceptsRow(int sourceRow) const; + [[nodiscard]] bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; + [[nodiscard]] bool filterAcceptsRow(int sourceRow) const; }; #endif diff --git a/cockatrice/src/interface/widgets/server/remote/remote_decklist_tree_widget.h b/cockatrice/src/interface/widgets/server/remote/remote_decklist_tree_widget.h index 0153f0414..6836ff435 100644 --- a/cockatrice/src/interface/widgets/server/remote/remote_decklist_tree_widget.h +++ b/cockatrice/src/interface/widgets/server/remote/remote_decklist_tree_widget.h @@ -34,11 +34,11 @@ public: { } virtual ~Node() = default; - DirectoryNode *getParent() const + [[nodiscard]] DirectoryNode *getParent() const { return parent; } - QString getName() const + [[nodiscard]] QString getName() const { return name; } @@ -49,9 +49,9 @@ public: explicit DirectoryNode(const QString &_name = QString(), DirectoryNode *_parent = nullptr); ~DirectoryNode() override; void clearTree(); - QString getPath() const; + [[nodiscard]] QString getPath() const; DirectoryNode *getNodeByPath(QStringList path); - FileNode *getNodeById(int id) const; + [[nodiscard]] FileNode *getNodeById(int id) const; }; class FileNode : public Node { @@ -64,17 +64,17 @@ public: : Node(_name, _parent), id(_id), uploadTime(_uploadTime) { } - int getId() const + [[nodiscard]] int getId() const { return id; } - QDateTime getUploadTime() const + [[nodiscard]] QDateTime getUploadTime() const { return uploadTime; } }; - template T getNode(const QModelIndex &index) const + template [[nodiscard]] T getNode(const QModelIndex &index) const { if (!index.isValid()) return dynamic_cast(root); @@ -96,15 +96,16 @@ private slots: public: explicit RemoteDeckList_TreeModel(AbstractClient *_client, QObject *parent = nullptr); ~RemoteDeckList_TreeModel() override; - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - int columnCount(const QModelIndex & /*parent*/ = QModelIndex()) const override; - QVariant data(const QModelIndex &index, int role) const override; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; - QModelIndex parent(const QModelIndex &index) const override; - Qt::ItemFlags flags(const QModelIndex &index) const override; + [[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override; + [[nodiscard]] int columnCount(const QModelIndex & /*parent*/ = QModelIndex()) const override; + [[nodiscard]] QVariant data(const QModelIndex &index, int role) const override; + [[nodiscard]] QVariant + headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + [[nodiscard]] QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; + [[nodiscard]] QModelIndex parent(const QModelIndex &index) const override; + [[nodiscard]] Qt::ItemFlags flags(const QModelIndex &index) const override; - DirectoryNode *getRoot() const + [[nodiscard]] DirectoryNode *getRoot() const { return root; } @@ -124,11 +125,11 @@ private: public: explicit RemoteDeckList_TreeWidget(AbstractClient *_client, QWidget *parent = nullptr); - RemoteDeckList_TreeModel::Node *getNode(const QModelIndex &ind) const; - RemoteDeckList_TreeModel::Node *getCurrentItem() const; - QList getCurrentSelection() const; - RemoteDeckList_TreeModel::DirectoryNode *getNodeByPath(const QString &path) const; - RemoteDeckList_TreeModel::FileNode *getNodeById(int id) const; + [[nodiscard]] RemoteDeckList_TreeModel::Node *getNode(const QModelIndex &ind) const; + [[nodiscard]] RemoteDeckList_TreeModel::Node *getCurrentItem() const; + [[nodiscard]] QList getCurrentSelection() const; + [[nodiscard]] RemoteDeckList_TreeModel::DirectoryNode *getNodeByPath(const QString &path) const; + [[nodiscard]] RemoteDeckList_TreeModel::FileNode *getNodeById(int id) const; void addFileToTree(const ServerInfo_DeckStorage_TreeItem &file, RemoteDeckList_TreeModel::DirectoryNode *parent); void addFolderToTree(const ServerInfo_DeckStorage_TreeItem &folder, RemoteDeckList_TreeModel::DirectoryNode *parent); diff --git a/cockatrice/src/interface/widgets/server/remote/remote_replay_list_tree_widget.h b/cockatrice/src/interface/widgets/server/remote/remote_replay_list_tree_widget.h index d5d70af53..f83cce46a 100644 --- a/cockatrice/src/interface/widgets/server/remote/remote_replay_list_tree_widget.h +++ b/cockatrice/src/interface/widgets/server/remote/remote_replay_list_tree_widget.h @@ -35,7 +35,7 @@ private: { } virtual ~Node() = default; - QString getName() const + [[nodiscard]] QString getName() const { return name; } @@ -91,21 +91,22 @@ private slots: public: explicit RemoteReplayList_TreeModel(AbstractClient *_client, QObject *parent = nullptr); ~RemoteReplayList_TreeModel() override; - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - int columnCount(const QModelIndex & /*parent*/ = QModelIndex()) const override + [[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override; + [[nodiscard]] int columnCount(const QModelIndex & /*parent*/ = QModelIndex()) const override { return numberOfColumns; } - QVariant data(const QModelIndex &index, int role) const override; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; - QModelIndex parent(const QModelIndex &index) const override; - Qt::ItemFlags flags(const QModelIndex &index) const override; + [[nodiscard]] QVariant data(const QModelIndex &index, int role) const override; + [[nodiscard]] QVariant + headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + [[nodiscard]] QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; + [[nodiscard]] QModelIndex parent(const QModelIndex &index) const override; + [[nodiscard]] Qt::ItemFlags flags(const QModelIndex &index) const override; void clearTree(); void refreshTree(); - ServerInfo_Replay const *getReplay(const QModelIndex &index) const; - ServerInfo_ReplayMatch const *getReplayMatch(const QModelIndex &index) const; - ServerInfo_ReplayMatch const *getEnclosingReplayMatch(const QModelIndex &index) const; + [[nodiscard]] ServerInfo_Replay const *getReplay(const QModelIndex &index) const; + [[nodiscard]] ServerInfo_ReplayMatch const *getReplayMatch(const QModelIndex &index) const; + [[nodiscard]] ServerInfo_ReplayMatch const *getEnclosingReplayMatch(const QModelIndex &index) const; void addMatchInfo(const ServerInfo_ReplayMatch &matchInfo); void updateMatchInfo(int gameId, const ServerInfo_ReplayMatch &matchInfo); void removeMatchInfo(int gameId); @@ -119,10 +120,10 @@ private: public: explicit RemoteReplayList_TreeWidget(AbstractClient *_client, QWidget *parent = nullptr); - ServerInfo_Replay const *getReplay(const QModelIndex &ind) const; - ServerInfo_ReplayMatch const *getReplayMatch(const QModelIndex &ind) const; - QList getSelectedReplays() const; - QSet getSelectedReplayMatches() const; + [[nodiscard]] ServerInfo_Replay const *getReplay(const QModelIndex &ind) const; + [[nodiscard]] ServerInfo_ReplayMatch const *getReplayMatch(const QModelIndex &ind) const; + [[nodiscard]] QList getSelectedReplays() const; + [[nodiscard]] QSet getSelectedReplayMatches() const; void clearTree() { treeModel->clearTree(); diff --git a/cockatrice/src/interface/widgets/server/user/user_info_connection.h b/cockatrice/src/interface/widgets/server/user/user_info_connection.h index 90be05570..cfba22346 100644 --- a/cockatrice/src/interface/widgets/server/user/user_info_connection.h +++ b/cockatrice/src/interface/widgets/server/user/user_info_connection.h @@ -30,31 +30,31 @@ private: public: UserConnection_Information(); UserConnection_Information(QString, QString, QString, QString, QString, bool, QString); - QString getSaveName() const + [[nodiscard]] QString getSaveName() const { return saveName; } - QString getServer() const + [[nodiscard]] QString getServer() const { return server; } - QString getPort() const + [[nodiscard]] QString getPort() const { return port; } - QString getUsername() const + [[nodiscard]] QString getUsername() const { return username; } - QString getPassword() const + [[nodiscard]] QString getPassword() const { return password; } - bool getSavePassword() const + [[nodiscard]] bool getSavePassword() const { return savePassword; } - QString getSite() const + [[nodiscard]] QString getSite() const { return site; } diff --git a/cockatrice/src/interface/widgets/server/user/user_list_manager.h b/cockatrice/src/interface/widgets/server/user/user_list_manager.h index 56f50c0be..f378bd08d 100644 --- a/cockatrice/src/interface/widgets/server/user/user_list_manager.h +++ b/cockatrice/src/interface/widgets/server/user/user_list_manager.h @@ -60,11 +60,11 @@ public: return ignoredUsers; } - bool isOwnUserRegistered() const override; - QString getOwnUsername() const override; - bool isUserBuddy(const QString &userName) const override; - bool isUserIgnored(const QString &userName) const override; - const ServerInfo_User *getOnlineUser(const QString &userName) const override; + [[nodiscard]] bool isOwnUserRegistered() const override; + [[nodiscard]] QString getOwnUsername() const override; + [[nodiscard]] bool isUserBuddy(const QString &userName) const override; + [[nodiscard]] bool isUserIgnored(const QString &userName) const override; + [[nodiscard]] const ServerInfo_User *getOnlineUser(const QString &userName) const override; public slots: void handleConnect(); diff --git a/cockatrice/src/interface/widgets/server/user/user_list_widget.h b/cockatrice/src/interface/widgets/server/user/user_list_widget.h index 897c01b83..036837673 100644 --- a/cockatrice/src/interface/widgets/server/user/user_list_widget.h +++ b/cockatrice/src/interface/widgets/server/user/user_list_widget.h @@ -45,13 +45,13 @@ private slots: public: explicit BanDialog(const ServerInfo_User &info, QWidget *parent = nullptr); - QString getBanName() const; - QString getBanIP() const; - QString getBanId() const; - int getMinutes() const; - QString getReason() const; - QString getVisibleReason() const; - int getDeleteMessages() const; + [[nodiscard]] QString getBanName() const; + [[nodiscard]] QString getBanIP() const; + [[nodiscard]] QString getBanId() const; + [[nodiscard]] int getMinutes() const; + [[nodiscard]] QString getReason() const; + [[nodiscard]] QString getVisibleReason() const; + [[nodiscard]] int getDeleteMessages() const; }; class WarningDialog : public QDialog @@ -68,10 +68,10 @@ private slots: public: WarningDialog(const QString userName, const QString clientID, QWidget *parent = nullptr); - QString getName() const; - QString getWarnID() const; - QString getReason() const; - int getDeleteMessages() const; + [[nodiscard]] QString getName() const; + [[nodiscard]] QString getWarnID() const; + [[nodiscard]] QString getReason() const; + [[nodiscard]] int getDeleteMessages() const; void addWarningOption(const QString warning); }; @@ -85,11 +85,11 @@ private: public: explicit AdminNotesDialog(const QString &_userName, const QString &_notes, QWidget *_parent = nullptr); - QString getName() const + [[nodiscard]] QString getName() const { return userName; } - QString getNotes() const; + [[nodiscard]] QString getNotes() const; }; class UserListItemDelegate : public QStyledItemDelegate @@ -159,7 +159,7 @@ public: void processUserInfo(const ServerInfo_User &user, bool online); bool deleteUser(const QString &userName); void setUserOnline(const QString &userName, bool online); - const QMap &getUsers() const + [[nodiscard]] const QMap &getUsers() const { return users; } diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_container.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_container.h index d23c4f27d..df6c2eaeb 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_container.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_container.h @@ -29,27 +29,27 @@ public: void debugPrint() const; // Getter methods for deck container - const QString &getDescription() const + [[nodiscard]] const QString &getDescription() const { return description; } - const QVector &getBreadcrumb() const + [[nodiscard]] const QVector &getBreadcrumb() const { return breadcrumb; } - const EdhrecCommanderApiResponseCommanderDetails &getCommanderDetails() const + [[nodiscard]] const EdhrecCommanderApiResponseCommanderDetails &getCommanderDetails() const { return card; } - const QVector &getCardlists() const + [[nodiscard]] const QVector &getCardlists() const { return cardlists; } - const QString &getKeywords() const + [[nodiscard]] const QString &getKeywords() const { return keywords; } - const QString &getTitle() const + [[nodiscard]] const QString &getTitle() const { return title; } diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_commander_api_response_commander_details.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_commander_api_response_commander_details.h index 64b5970da..09d0667c7 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_commander_api_response_commander_details.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_commander_api_response_commander_details.h @@ -27,119 +27,119 @@ public: void debugPrint() const; // Getters for the card data - const QString &getAetherhubUri() const + [[nodiscard]] const QString &getAetherhubUri() const { return aetherhubUri; } - const QString &getArchidektUri() const + [[nodiscard]] const QString &getArchidektUri() const { return archidektUri; } - int getCmc() const + [[nodiscard]] int getCmc() const { return cmc; } - const QJsonArray &getColorIdentity() const + [[nodiscard]] const QJsonArray &getColorIdentity() const { return colorIdentity; } - bool isCombos() const + [[nodiscard]] bool isCombos() const { return combos; } - const QString &getDeckstatsUri() const + [[nodiscard]] const QString &getDeckstatsUri() const { return deckstatsUri; } - const QVector &getImageUris() const + [[nodiscard]] const QVector &getImageUris() const { return imageUris; } - int getInclusion() const + [[nodiscard]] int getInclusion() const { return inclusion; } - bool getIsCommander() const + [[nodiscard]] bool getIsCommander() const { return isCommander; } - const QString &getLabel() const + [[nodiscard]] const QString &getLabel() const { return label; } - const QString &getLayout() const + [[nodiscard]] const QString &getLayout() const { return layout; } - bool getLegalCommander() const + [[nodiscard]] bool getLegalCommander() const { return legalCommander; } - const QString &getMoxfieldUri() const + [[nodiscard]] const QString &getMoxfieldUri() const { return moxfieldUri; } - const QString &getMtggoldfishUri() const + [[nodiscard]] const QString &getMtggoldfishUri() const { return mtggoldfishUri; } - const QString &getName() const + [[nodiscard]] const QString &getName() const { return name; } - const QJsonArray &getNames() const + [[nodiscard]] const QJsonArray &getNames() const { return names; } - int getNumDecks() const + [[nodiscard]] int getNumDecks() const { return numDecks; } - int getPotentialDecks() const + [[nodiscard]] int getPotentialDecks() const { return potentialDecks; } - const QString &getPrecon() const + [[nodiscard]] const QString &getPrecon() const { return precon; } - const CardPrices &getPrices() const + [[nodiscard]] const CardPrices &getPrices() const { return prices; } - const QString &getPrimaryType() const + [[nodiscard]] const QString &getPrimaryType() const { return primaryType; } - const QString &getRarity() const + [[nodiscard]] const QString &getRarity() const { return rarity; } - double getSalt() const + [[nodiscard]] double getSalt() const { return salt; } - const QString &getSanitized() const + [[nodiscard]] const QString &getSanitized() const { return sanitized; } - const QString &getSanitizedWo() const + [[nodiscard]] const QString &getSanitizedWo() const { return sanitizedWo; } - const QString &getScryfallUri() const + [[nodiscard]] const QString &getScryfallUri() const { return scryfallUri; } - const QString &getSpellbookUri() const + [[nodiscard]] const QString &getSpellbookUri() const { return spellbookUri; } - const QString &getType() const + [[nodiscard]] const QString &getType() const { return type; } - const QString &getUrl() const + [[nodiscard]] const QString &getUrl() const { return url; } diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.h index 2cca18504..3d4c2fa00 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.h @@ -27,13 +27,13 @@ public: void retranslateUi() override; void doSearch(); - QString getTabText() const override + [[nodiscard]] QString getTabText() const override { auto cardName = cardToQuery.isNull() ? QString() : cardToQuery->getName(); return tr("EDHRec: ") + cardName; } - CardSizeWidget *getCardSizeSlider() + CardSizeWidget *getCardSizeSlider() const { return cardSizeSlider; } diff --git a/cockatrice/src/interface/widgets/tabs/tab.h b/cockatrice/src/interface/widgets/tabs/tab.h index 56a9f0b7e..7cff01130 100644 --- a/cockatrice/src/interface/widgets/tabs/tab.h +++ b/cockatrice/src/interface/widgets/tabs/tab.h @@ -39,15 +39,15 @@ private: public: explicit Tab(TabSupervisor *_tabSupervisor); - const QList &getTabMenus() const + [[nodiscard]] const QList &getTabMenus() const { return tabMenus; } - TabSupervisor *getTabSupervisor() const + [[nodiscard]] TabSupervisor *getTabSupervisor() const { return tabSupervisor; } - bool getContentsChanged() const + [[nodiscard]] bool getContentsChanged() const { return contentsChanged; } @@ -55,7 +55,7 @@ public: { contentsChanged = _contentsChanged; } - virtual QString getTabText() const = 0; + [[nodiscard]] virtual QString getTabText() const = 0; virtual void retranslateUi() = 0; /** diff --git a/cockatrice/src/interface/widgets/tabs/tab_home.h b/cockatrice/src/interface/widgets/tabs/tab_home.h index 3738b73fd..fbadc99aa 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_home.h +++ b/cockatrice/src/interface/widgets/tabs/tab_home.h @@ -26,7 +26,7 @@ private: public: TabHome(TabSupervisor *_tabSupervisor, AbstractClient *_client); void retranslateUi() override; - QString getTabText() const override + [[nodiscard]] QString getTabText() const override { return tr("Home"); } diff --git a/cockatrice/src/interface/widgets/tabs/tab_message.h b/cockatrice/src/interface/widgets/tabs/tab_message.h index 098089e46..36a0b5f78 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_message.h +++ b/cockatrice/src/interface/widgets/tabs/tab_message.h @@ -54,8 +54,8 @@ public: ~TabMessage() override; void retranslateUi() override; void tabActivated() override; - QString getUserName() const; - QString getTabText() const override; + [[nodiscard]] QString getUserName() const; + [[nodiscard]] QString getTabText() const override; void processUserMessageEvent(const Event_UserMessage &event); diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.h index 9b828fa3d..a4ea3633b 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.h @@ -30,12 +30,12 @@ public: * @param tagName The name of the tag to display. */ explicit DeckPreviewTagDisplayWidget(QWidget *parent = nullptr, const QString &tagName = ""); - QSize sizeHint() const override; - QString getTagName() const + [[nodiscard]] QSize sizeHint() const override; + [[nodiscard]] QString getTagName() const { return tagName; } - TagState getState() const + [[nodiscard]] TagState getState() const { return state; } diff --git a/libcockatrice_card/libcockatrice/card/card_info.h b/libcockatrice_card/libcockatrice/card/card_info.h index ab1d51a49..3ff78f38c 100644 --- a/libcockatrice_card/libcockatrice/card/card_info.h +++ b/libcockatrice_card/libcockatrice/card/card_info.h @@ -159,7 +159,7 @@ public: * * @return Shared pointer to the cloned CardInfo. */ - CardInfoPtr clone() const + [[nodiscard]] CardInfoPtr clone() const { auto newCardInfo = CardInfoPtr(new CardInfo(*this)); newCardInfo->setSmartPointer(newCardInfo); // Set the smart pointer for the new instance @@ -179,11 +179,11 @@ public: } /** @name Basic Properties Accessors */ //@{ - inline const QString &getName() const + [[nodiscard]] inline const QString &getName() const { return name; } - const QString &getSimpleName() const + [[nodiscard]] const QString &getSimpleName() const { return simpleName; } @@ -191,7 +191,7 @@ public: { return altNames; }; - const QString &getText() const + [[nodiscard]] const QString &getText() const { return text; } @@ -200,15 +200,15 @@ public: text = _text; emit cardInfoChanged(smartThis); } - bool getIsToken() const + [[nodiscard]] bool getIsToken() const { return isToken; } - QStringList getProperties() const + [[nodiscard]] QStringList getProperties() const { return properties.keys(); } - QString getProperty(const QString &propertyName) const + [[nodiscard]] QString getProperty(const QString &propertyName) const { return properties.value(propertyName).toString(); } @@ -217,34 +217,34 @@ public: properties.insert(_name, _value); emit cardInfoChanged(smartThis); } - bool hasProperty(const QString &propertyName) const + [[nodiscard]] bool hasProperty(const QString &propertyName) const { return properties.contains(propertyName); } - const SetToPrintingsMap &getSets() const + [[nodiscard]] const SetToPrintingsMap &getSets() const { return setsToPrintings; } - const QString &getSetsNames() const + [[nodiscard]] const QString &getSetsNames() const { return setsNames; } //@} /** @name Related Cards Accessors */ //@{ - const QList &getRelatedCards() const + [[nodiscard]] const QList &getRelatedCards() const { return relatedCards; } - const QList &getReverseRelatedCards() const + [[nodiscard]] const QList &getReverseRelatedCards() const { return reverseRelatedCards; } - const QList &getReverseRelatedCards2Me() const + [[nodiscard]] const QList &getReverseRelatedCards2Me() const { return reverseRelatedCardsToMe; } - QList getAllRelatedCards() const + [[nodiscard]] QList getAllRelatedCards() const { QList result; result.append(getRelatedCards()); @@ -259,24 +259,24 @@ public: //@} /** @name UI Positioning */ //@{ - const UiAttributes &getUiAttributes() const + [[nodiscard]] const UiAttributes &getUiAttributes() const { return uiAttributes; } //@} - const QChar getColorChar() const; + [[nodiscard]] const QChar getColorChar() const; /** @name Legacy/Convenience Property Accessors */ //@{ - const QString getCardType() const; + [[nodiscard]] const QString getCardType() const; void setCardType(const QString &value); - const QString getCmc() const; - const QString getColors() const; + [[nodiscard]] const QString getCmc() const; + [[nodiscard]] const QString getColors() const; void setColors(const QString &value); - const QString getLoyalty() const; - const QString getMainCardType() const; - const QString getManaCost() const; - const QString getPowTough() const; + [[nodiscard]] const QString getLoyalty() const; + [[nodiscard]] const QString getMainCardType() const; + [[nodiscard]] const QString getManaCost() const; + [[nodiscard]] const QString getPowTough() const; void setPowTough(const QString &value); //@} @@ -287,7 +287,7 @@ public: * * @return Corrected card name as a QString. */ - QString getCorrectedName() const; + [[nodiscard]] QString getCorrectedName() const; /** * @brief Adds a printing to a specific set. diff --git a/libcockatrice_card/libcockatrice/card/card_info_comparator.h b/libcockatrice_card/libcockatrice/card/card_info_comparator.h index bafc303a5..2b101701c 100644 --- a/libcockatrice_card/libcockatrice/card/card_info_comparator.h +++ b/libcockatrice_card/libcockatrice/card/card_info_comparator.h @@ -23,8 +23,8 @@ private: QStringList m_properties; // List of properties to sort by Qt::SortOrder m_order; - QVariant getProperty(const CardInfoPtr &card, const QString &property) const; - bool compareVariants(const QVariant &a, const QVariant &b) const; + [[nodiscard]] QVariant getProperty(const CardInfoPtr &card, const QString &property) const; + [[nodiscard]] bool compareVariants(const QVariant &a, const QVariant &b) const; }; #endif // CARD_INFO_COMPARATOR_H diff --git a/libcockatrice_card/libcockatrice/card/database/card_database_loader.h b/libcockatrice_card/libcockatrice/card/database/card_database_loader.h index db1376ac7..631ba685f 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database_loader.h +++ b/libcockatrice_card/libcockatrice/card/database/card_database_loader.h @@ -110,7 +110,7 @@ private: * @brief Collects custom card database paths recursively. * @return Sorted list of file paths to custom databases. */ - QStringList collectCustomDatabasePaths() const; + [[nodiscard]] QStringList collectCustomDatabasePaths() const; private: CardDatabase *database; /**< Non-owning pointer to the target CardDatabase. */ diff --git a/libcockatrice_card/libcockatrice/card/printing/printing_info.h b/libcockatrice_card/libcockatrice/card/printing/printing_info.h index 4329ca2f4..e0978bd55 100644 --- a/libcockatrice_card/libcockatrice/card/printing/printing_info.h +++ b/libcockatrice_card/libcockatrice/card/printing/printing_info.h @@ -65,7 +65,7 @@ public: * * @return Pointer to the associated CardSet. */ - CardSetPtr getSet() const + [[nodiscard]] CardSetPtr getSet() const { return set; } @@ -75,7 +75,7 @@ public: * * @return List of keys stored in the properties map. */ - QStringList getProperties() const + [[nodiscard]] QStringList getProperties() const { return properties.keys(); } @@ -86,7 +86,7 @@ public: * @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 + [[nodiscard]] QString getProperty(const QString &propertyName) const { return properties.value(propertyName).toString(); } @@ -109,14 +109,14 @@ public: * * @return A string representing the providerID. */ - QString getUuid() const; + [[nodiscard]] QString getUuid() const; /** * @brief Returns the flavorName for this printing. * * @return The flavorName, or empty if it isn't present. */ - QString getFlavorName() const; + [[nodiscard]] QString getFlavorName() const; }; #endif // COCKATRICE_PRINTING_INFO_H diff --git a/libcockatrice_card/libcockatrice/card/set/card_set.h b/libcockatrice_card/libcockatrice/card/set/card_set.h index 5fc769bb6..fe4b66522 100644 --- a/libcockatrice_card/libcockatrice/card/set/card_set.h +++ b/libcockatrice_card/libcockatrice/card/set/card_set.h @@ -105,34 +105,34 @@ public: * * @return Sanitized short name. */ - QString getCorrectedShortName() const; + [[nodiscard]] QString getCorrectedShortName() const; /// @return Short identifier of the set. - QString getShortName() const + [[nodiscard]] QString getShortName() const { return shortName; } /// @return Descriptive name of the set. - QString getLongName() const + [[nodiscard]] QString getLongName() const { return longName; } /// @return Type/category string of the set. - QString getSetType() const + [[nodiscard]] QString getSetType() const { return setType; } /// @return Release date of the set. - QDate getReleaseDate() const + [[nodiscard]] QDate getReleaseDate() const { return releaseDate; } /// @return Priority level of the set. - Priority getPriority() const + [[nodiscard]] Priority getPriority() const { return priority; } @@ -182,7 +182,7 @@ public: void loadSetOptions(); /// @return The sort key assigned to this set. - int getSortKey() const + [[nodiscard]] int getSortKey() const { return sortKey; } @@ -194,7 +194,7 @@ public: void setSortKey(unsigned int _sortKey); /// @return True if the set is enabled. - bool getEnabled() const + [[nodiscard]] bool getEnabled() const { return enabled; } @@ -206,7 +206,7 @@ public: void setEnabled(bool _enabled); /// @return True if the set is considered known. - bool getIsKnown() const + [[nodiscard]] bool getIsKnown() const { return isknown; } @@ -222,7 +222,7 @@ public: * * @return True if the long name, type, and release date are all empty. */ - bool getIsKnownIgnored() const + [[nodiscard]] bool getIsKnownIgnored() const { return longName.length() + setType.length() + releaseDate.toString().length() == 0; } diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_card_node.h b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_card_node.h index 6d61ed970..c2fe038e6 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_card_node.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_card_node.h @@ -91,7 +91,7 @@ public: explicit DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent); /// @return The quantity of this card. - int getNumber() const override + [[nodiscard]] int getNumber() const override { return number; } @@ -103,7 +103,7 @@ public: } /// @return The display name of this card. - QString getName() const override + [[nodiscard]] QString getName() const override { return name; } @@ -115,7 +115,7 @@ public: } /// @return The provider identifier for this card. - QString getCardProviderId() const override + [[nodiscard]] QString getCardProviderId() const override { return cardProviderId; } @@ -127,7 +127,7 @@ public: } /// @return The short set code (e.g., "NEO"). - QString getCardSetShortName() const override + [[nodiscard]] QString getCardSetShortName() const override { return cardSetShortName; } @@ -139,7 +139,7 @@ public: } /// @return The collector number of this card within its set. - QString getCardCollectorNumber() const override + [[nodiscard]] QString getCardCollectorNumber() const override { return cardSetNumber; } @@ -162,7 +162,7 @@ public: * @return A CardRef with the card’s name and provider ID, suitable * for database lookups or comparison with other card sources. */ - CardRef toCardRef() const + [[nodiscard]] CardRef toCardRef() const { return {name, cardProviderId}; } diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_history_manager.h b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_history_manager.h index f30c0affe..e6bd27e2d 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_history_manager.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_history_manager.h @@ -23,12 +23,12 @@ public: void clear(); - bool canUndo() const + [[nodiscard]] bool canUndo() const { return !undoStack.isEmpty(); } - bool canRedo() const + [[nodiscard]] bool canRedo() const { return !redoStack.isEmpty(); } @@ -37,11 +37,11 @@ public: void redo(DeckList *deck); - QStack getRedoStack() const + [[nodiscard]] QStack getRedoStack() const { return redoStack; } - QStack getUndoStack() const + [[nodiscard]] QStack getUndoStack() const { return undoStack; } diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_memento.h b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_memento.h index d2e36b804..6ddf430c5 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_memento.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_memento.h @@ -11,11 +11,11 @@ public: { } - QString getMemento() const + [[nodiscard]] QString getMemento() const { return memento; } - QString getReason() const + [[nodiscard]] QString getReason() const { return reason; } diff --git a/libcockatrice_filters/libcockatrice/filters/filter_card.h b/libcockatrice_filters/libcockatrice/filters/filter_card.h index 58dbf954b..344ae5224 100644 --- a/libcockatrice_filters/libcockatrice/filters/filter_card.h +++ b/libcockatrice_filters/libcockatrice/filters/filter_card.h @@ -56,20 +56,20 @@ public: { } - Type type() const + [[nodiscard]] Type type() const { return t; } - const QString &term() const + [[nodiscard]] const QString &term() const { return trm; } - Attr attr() const + [[nodiscard]] Attr attr() const { return a; } - QJsonObject toJson() const; + [[nodiscard]] QJsonObject toJson() const; static CardFilter *fromJson(const QJsonObject &json); static const QString typeName(Type t); static const QString attrName(Attr a); diff --git a/libcockatrice_filters/libcockatrice/filters/filter_string.h b/libcockatrice_filters/libcockatrice/filters/filter_string.h index 4e6cb38bf..8fc41ce68 100644 --- a/libcockatrice_filters/libcockatrice/filters/filter_string.h +++ b/libcockatrice_filters/libcockatrice/filters/filter_string.h @@ -35,7 +35,7 @@ class FilterString public: FilterString(); explicit FilterString(const QString &exp); - bool check(const CardData &card) const + [[nodiscard]] bool check(const CardData &card) const { if (card.isNull()) { static CardInfoPtr blankCard = CardInfo::newInstance(""); diff --git a/libcockatrice_filters/libcockatrice/filters/filter_tree.h b/libcockatrice_filters/libcockatrice/filters/filter_tree.h index 350fd2f14..7e0f211ef 100644 --- a/libcockatrice_filters/libcockatrice/filters/filter_tree.h +++ b/libcockatrice_filters/libcockatrice/filters/filter_tree.h @@ -24,7 +24,7 @@ public: FilterTreeNode() : enabled(true) { } - virtual bool isEnabled() const + [[nodiscard]] virtual bool isEnabled() const { return enabled; } @@ -38,18 +38,18 @@ public: enabled = false; nodeChanged(); } - virtual FilterTreeNode *parent() const + [[nodiscard]] virtual FilterTreeNode *parent() const { return nullptr; } - virtual FilterTreeNode *nodeAt(int /* i */) const + [[nodiscard]] virtual FilterTreeNode *nodeAt(int /* i */) const { return nullptr; } virtual void deleteAt(int /* i */) { } - virtual int childCount() const + [[nodiscard]] virtual int childCount() const { return 0; } @@ -57,15 +57,15 @@ public: { return -1; } - virtual int index() const + [[nodiscard]] virtual int index() const { return (parent() != nullptr) ? parent()->childIndex(this) : -1; } - virtual const QString text() const + [[nodiscard]] virtual const QString text() const { return QString(""); } - virtual bool isLeaf() const + [[nodiscard]] virtual bool isLeaf() const { return false; } @@ -104,9 +104,9 @@ protected: public: virtual ~FilterTreeBranch(); void removeFiltersByAttr(CardFilter::Attr filterType); - FilterTreeNode *nodeAt(int i) const override; + [[nodiscard]] FilterTreeNode *nodeAt(int i) const override; void deleteAt(int i) override; - int childCount() const override + [[nodiscard]] int childCount() const override { return childNodes.size(); } @@ -127,10 +127,10 @@ public: LogicMap(CardFilter::Attr a, FilterTree *parent) : p(parent), attr(a) { } - const FilterItemList *findTypeList(CardFilter::Type type) const; + [[nodiscard]] const FilterItemList *findTypeList(CardFilter::Type type) const; FilterItemList *typeList(CardFilter::Type type); - FilterTreeNode *parent() const override; - const QString text() const override + [[nodiscard]] FilterTreeNode *parent() const override; + [[nodiscard]] const QString text() const override { return CardFilter::attrName(attr); } @@ -148,25 +148,25 @@ public: FilterItemList(CardFilter::Type t, LogicMap *parent) : p(parent), type(t) { } - CardFilter::Attr attr() const + [[nodiscard]] CardFilter::Attr attr() const { return p->attr; } - FilterTreeNode *parent() const override + [[nodiscard]] FilterTreeNode *parent() const override { return p; } - int termIndex(const QString &term) const; + [[nodiscard]] int termIndex(const QString &term) const; FilterTreeNode *termNode(const QString &term); - const QString text() const override + [[nodiscard]] const QString text() const override { return CardFilter::typeName(type); } - bool testTypeAnd(CardInfoPtr info, CardFilter::Attr attr) const; - bool testTypeAndNot(CardInfoPtr info, CardFilter::Attr attr) const; - bool testTypeOr(CardInfoPtr info, CardFilter::Attr attr) const; - bool testTypeOrNot(CardInfoPtr info, CardFilter::Attr attr) const; + [[nodiscard]] bool testTypeAnd(CardInfoPtr info, CardFilter::Attr attr) const; + [[nodiscard]] bool testTypeAndNot(CardInfoPtr info, CardFilter::Attr attr) const; + [[nodiscard]] bool testTypeOr(CardInfoPtr info, CardFilter::Attr attr) const; + [[nodiscard]] bool testTypeOrNot(CardInfoPtr info, CardFilter::Attr attr) const; }; class FilterItem : public FilterTreeNode @@ -182,42 +182,42 @@ public: } virtual ~FilterItem() = default; - CardFilter::Attr attr() const + [[nodiscard]] CardFilter::Attr attr() const { return p->attr(); } - CardFilter::Type type() const + [[nodiscard]] CardFilter::Type type() const { return p->type; } - FilterTreeNode *parent() const override + [[nodiscard]] FilterTreeNode *parent() const override { return p; } - const QString text() const override + [[nodiscard]] const QString text() const override { return term; } - bool isLeaf() const override + [[nodiscard]] bool isLeaf() const override { return true; } - bool acceptName(CardInfoPtr info) const; - bool acceptType(CardInfoPtr info) const; - bool acceptMainType(CardInfoPtr info) const; - bool acceptSubType(CardInfoPtr info) const; - bool acceptColor(CardInfoPtr info) const; - bool acceptText(CardInfoPtr info) const; - bool acceptSet(CardInfoPtr info) const; - bool acceptManaCost(CardInfoPtr info) const; - bool acceptCmc(CardInfoPtr info) const; - bool acceptPowerToughness(CardInfoPtr info, CardFilter::Attr attr) const; - bool acceptLoyalty(CardInfoPtr info) const; - bool acceptRarity(CardInfoPtr info) const; - bool acceptCardAttr(CardInfoPtr info, CardFilter::Attr attr) const; - bool acceptFormat(CardInfoPtr info) const; - bool relationCheck(int cardInfo) const; + [[nodiscard]] bool acceptName(CardInfoPtr info) const; + [[nodiscard]] bool acceptType(CardInfoPtr info) const; + [[nodiscard]] bool acceptMainType(CardInfoPtr info) const; + [[nodiscard]] bool acceptSubType(CardInfoPtr info) const; + [[nodiscard]] bool acceptColor(CardInfoPtr info) const; + [[nodiscard]] bool acceptText(CardInfoPtr info) const; + [[nodiscard]] bool acceptSet(CardInfoPtr info) const; + [[nodiscard]] bool acceptManaCost(CardInfoPtr info) const; + [[nodiscard]] bool acceptCmc(CardInfoPtr info) const; + [[nodiscard]] bool acceptPowerToughness(CardInfoPtr info, CardFilter::Attr attr) const; + [[nodiscard]] bool acceptLoyalty(CardInfoPtr info) const; + [[nodiscard]] bool acceptRarity(CardInfoPtr info) const; + [[nodiscard]] bool acceptCardAttr(CardInfoPtr info, CardFilter::Attr attr) const; + [[nodiscard]] bool acceptFormat(CardInfoPtr info) const; + [[nodiscard]] bool relationCheck(int cardInfo) const; }; class FilterTree : public QObject, public FilterTreeBranch @@ -265,16 +265,16 @@ public: FilterTreeNode *termNode(CardFilter::Attr attr, CardFilter::Type type, const QString &term); FilterTreeNode *termNode(const CardFilter *f); - const QString text() const override + [[nodiscard]] const QString text() const override { return QString("root"); } - int index() const override + [[nodiscard]] int index() const override { return 0; } - bool acceptsCard(CardInfoPtr info) const; + [[nodiscard]] bool acceptsCard(CardInfoPtr info) const; void removeFiltersByAttr(CardFilter::Attr filterType); void removeFilter(const CardFilter *toRemove); void clear(); diff --git a/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_database_path_provider.h b/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_database_path_provider.h index f5e54a6f8..dd55ab789 100644 --- a/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_database_path_provider.h +++ b/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_database_path_provider.h @@ -9,10 +9,10 @@ class ICardDatabasePathProvider : public QObject public: virtual ~ICardDatabasePathProvider() = default; - virtual QString getCardDatabasePath() const = 0; - virtual QString getCustomCardDatabasePath() const = 0; - virtual QString getTokenDatabasePath() const = 0; - virtual QString getSpoilerCardDatabasePath() const = 0; + [[nodiscard]] virtual QString getCardDatabasePath() const = 0; + [[nodiscard]] virtual QString getCustomCardDatabasePath() const = 0; + [[nodiscard]] virtual QString getTokenDatabasePath() const = 0; + [[nodiscard]] virtual QString getSpoilerCardDatabasePath() const = 0; signals: void cardDatabasePathChanged(); diff --git a/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_preference_provider.h b/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_preference_provider.h index 7c0944f29..a6cf941fb 100644 --- a/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_preference_provider.h +++ b/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_preference_provider.h @@ -7,8 +7,8 @@ class ICardPreferenceProvider { public: virtual ~ICardPreferenceProvider() = default; - virtual QString getCardPreferenceOverride(const QString &cardName) const = 0; - virtual bool getIncludeRebalancedCards() const = 0; + [[nodiscard]] virtual QString getCardPreferenceOverride(const QString &cardName) const = 0; + [[nodiscard]] virtual bool getIncludeRebalancedCards() const = 0; }; #endif // COCKATRICE_INTERFACE_CARD_PREFERENCE_PROVIDER_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 index fb3ab0cc3..bacd7a2bb 100644 --- a/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_database_path_provider.h +++ b/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_database_path_provider.h @@ -5,19 +5,19 @@ class NoopCardDatabasePathProvider : public ICardDatabasePathProvider { public: - QString getCardDatabasePath() const override + [[nodiscard]] QString getCardDatabasePath() const override { return ""; } - QString getCustomCardDatabasePath() const override + [[nodiscard]] QString getCustomCardDatabasePath() const override { return ""; } - QString getTokenDatabasePath() const override + [[nodiscard]] QString getTokenDatabasePath() const override { return ""; } - QString getSpoilerCardDatabasePath() const override + [[nodiscard]] QString getSpoilerCardDatabasePath() const override { return ""; } diff --git a/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_preference_provider.h b/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_preference_provider.h index 9fc7e5bb4..3781f4b63 100644 --- a/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_preference_provider.h +++ b/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_preference_provider.h @@ -5,12 +5,12 @@ class NoopCardPreferenceProvider : public ICardPreferenceProvider { public: - QString getCardPreferenceOverride(const QString &) const override + [[nodiscard]] QString getCardPreferenceOverride(const QString &) const override { return {}; } - bool getIncludeRebalancedCards() const override + [[nodiscard]] bool getIncludeRebalancedCards() const override { return true; } diff --git a/libcockatrice_models/libcockatrice/models/database/card/card_completer_proxy_model.h b/libcockatrice_models/libcockatrice/models/database/card/card_completer_proxy_model.h index 7a4626059..afb6f1fcf 100644 --- a/libcockatrice_models/libcockatrice/models/database/card/card_completer_proxy_model.h +++ b/libcockatrice_models/libcockatrice/models/database/card/card_completer_proxy_model.h @@ -16,7 +16,7 @@ public: explicit CardCompleterProxyModel(QObject *parent = nullptr); protected: - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; + [[nodiscard]] bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; }; #endif // CARD_COMPLETER_PROXY_MODEL_H diff --git a/libcockatrice_models/libcockatrice/models/database/card/card_search_model.h b/libcockatrice_models/libcockatrice/models/database/card/card_search_model.h index 98d66cb5e..18be2c55a 100644 --- a/libcockatrice_models/libcockatrice/models/database/card/card_search_model.h +++ b/libcockatrice_models/libcockatrice/models/database/card/card_search_model.h @@ -17,8 +17,8 @@ class CardSearchModel : public QAbstractListModel public: explicit CardSearchModel(CardDatabaseDisplayModel *sourceModel, QObject *parent = nullptr); - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + [[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override; + [[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; void updateSearchResults(const QString &query); // Update results based on input 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 467b7f0a5..e7abb2642 100644 --- a/libcockatrice_models/libcockatrice/models/database/card_database_display_model.h +++ b/libcockatrice_models/libcockatrice/models/database/card_database_display_model.h @@ -77,17 +77,17 @@ public: dirtyTimer.start(20); } void clearFilterAll(); - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - bool canFetchMore(const QModelIndex &parent) const override; + [[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override; + [[nodiscard]] bool canFetchMore(const QModelIndex &parent) const override; void fetchMore(const QModelIndex &parent) override; signals: void modelDirty(); protected: - bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; + [[nodiscard]] bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; static int lessThanNumerically(const QString &left, const QString &right); - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; - bool rowMatchesCardName(CardInfoPtr info) const; + [[nodiscard]] bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; + [[nodiscard]] bool rowMatchesCardName(CardInfoPtr info) const; private slots: void filterTreeChanged(); diff --git a/libcockatrice_models/libcockatrice/models/database/card_database_model.h b/libcockatrice_models/libcockatrice/models/database/card_database_model.h index 7c48c4e6d..218cfff92 100644 --- a/libcockatrice_models/libcockatrice/models/database/card_database_model.h +++ b/libcockatrice_models/libcockatrice/models/database/card_database_model.h @@ -31,15 +31,16 @@ public: }; CardDatabaseModel(CardDatabase *_db, bool _showOnlyCardsFromEnabledSets, QObject *parent = nullptr); ~CardDatabaseModel() override; - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - int columnCount(const QModelIndex &parent = QModelIndex()) const override; - QVariant data(const QModelIndex &index, int role) const override; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - CardDatabase *getDatabase() const + [[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override; + [[nodiscard]] int columnCount(const QModelIndex &parent = QModelIndex()) const override; + [[nodiscard]] QVariant data(const QModelIndex &index, int role) const override; + [[nodiscard]] QVariant + headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + [[nodiscard]] CardDatabase *getDatabase() const { return db; } - CardInfoPtr getCard(int index) const + [[nodiscard]] CardInfoPtr getCard(int index) const { return cardList[index]; } diff --git a/libcockatrice_models/libcockatrice/models/database/card_set/card_sets_model.h b/libcockatrice_models/libcockatrice/models/database/card_set/card_sets_model.h index 6f5911b6e..0ffc5a847 100644 --- a/libcockatrice_models/libcockatrice/models/database/card_set/card_sets_model.h +++ b/libcockatrice_models/libcockatrice/models/database/card_set/card_sets_model.h @@ -25,11 +25,11 @@ public: SetsMimeData(int _oldRow) : oldRow(_oldRow) { } - int getOldRow() const + [[nodiscard]] int getOldRow() const { return oldRow; } - QStringList formats() const + [[nodiscard]] QStringList formats() const { return QStringList() << "application/x-cockatricecardset"; } @@ -64,22 +64,23 @@ public: explicit SetsModel(CardDatabase *_db, QObject *parent = nullptr); ~SetsModel() override; - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - int columnCount(const QModelIndex &parent = QModelIndex()) const override + [[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override; + [[nodiscard]] int columnCount(const QModelIndex &parent = QModelIndex()) const override { Q_UNUSED(parent); return NUM_COLS; } - QVariant data(const QModelIndex &index, int role) const override; + [[nodiscard]] QVariant data(const QModelIndex &index, int role) const override; bool setData(const QModelIndex &index, const QVariant &value, int role) override; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - Qt::ItemFlags flags(const QModelIndex &index) const override; - Qt::DropActions supportedDropActions() const override; + [[nodiscard]] QVariant + headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + [[nodiscard]] Qt::ItemFlags flags(const QModelIndex &index) const override; + [[nodiscard]] Qt::DropActions supportedDropActions() const override; - QMimeData *mimeData(const QModelIndexList &indexes) const override; + [[nodiscard]] QMimeData *mimeData(const QModelIndexList &indexes) const override; bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override; - QStringList mimeTypes() const override; + [[nodiscard]] QStringList mimeTypes() const override; void swapRows(int oldRow, int newRow); void toggleRow(int row, bool enable); void toggleRow(int row); @@ -97,8 +98,8 @@ public: explicit SetsDisplayModel(QObject *parent = nullptr); protected: - bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; + [[nodiscard]] bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; + [[nodiscard]] bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; void fetchMore(const QModelIndex &index) override; }; diff --git a/libcockatrice_models/libcockatrice/models/database/token/token_display_model.h b/libcockatrice_models/libcockatrice/models/database/token/token_display_model.h index 5d3b63a36..f6b2fdfbb 100644 --- a/libcockatrice_models/libcockatrice/models/database/token/token_display_model.h +++ b/libcockatrice_models/libcockatrice/models/database/token/token_display_model.h @@ -14,10 +14,10 @@ class TokenDisplayModel : public CardDatabaseDisplayModel Q_OBJECT public: explicit TokenDisplayModel(QObject *parent = nullptr); - int rowCount(const QModelIndex &parent = QModelIndex()) const override; + [[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override; protected: - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; + [[nodiscard]] bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; }; #endif // COCKATRICE_TOKEN_DISPLAY_MODEL_H diff --git a/libcockatrice_models/libcockatrice/models/database/token/token_edit_model.h b/libcockatrice_models/libcockatrice/models/database/token/token_edit_model.h index 50c7eb642..5e5843761 100644 --- a/libcockatrice_models/libcockatrice/models/database/token/token_edit_model.h +++ b/libcockatrice_models/libcockatrice/models/database/token/token_edit_model.h @@ -14,10 +14,10 @@ class TokenEditModel : public CardDatabaseDisplayModel Q_OBJECT public: explicit TokenEditModel(QObject *parent = nullptr); - int rowCount(const QModelIndex &parent = QModelIndex()) const override; + [[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override; protected: - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; + [[nodiscard]] bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; }; #endif // COCKATRICE_TOKEN_EDIT_MODEL_H 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 8beabd4ba..08a4592ae 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h +++ b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h @@ -101,7 +101,7 @@ public: : AbstractDecklistCardNode(_parent, position), dataNode(_dataNode) { } - int getNumber() const override + [[nodiscard]] int getNumber() const override { return dataNode->getNumber(); } @@ -109,7 +109,7 @@ public: { dataNode->setNumber(_number); } - QString getName() const override + [[nodiscard]] QString getName() const override { return dataNode->getName(); } @@ -117,7 +117,7 @@ public: { dataNode->setName(_name); } - QString getCardProviderId() const override + [[nodiscard]] QString getCardProviderId() const override { return dataNode->getCardProviderId(); } @@ -125,7 +125,7 @@ public: { dataNode->setCardProviderId(_cardProviderId); } - QString getCardSetShortName() const override + [[nodiscard]] QString getCardSetShortName() const override { return dataNode->getCardSetShortName(); } @@ -133,7 +133,7 @@ public: { dataNode->setCardSetShortName(_cardSetShortName); } - QString getCardCollectorNumber() const override + [[nodiscard]] QString getCardCollectorNumber() const override { return dataNode->getCardCollectorNumber(); } @@ -146,7 +146,7 @@ public: * @brief Returns the underlying data node. * @return Pointer to the DecklistCardNode wrapped by this node. */ - DecklistCardNode *getDataNode() const + [[nodiscard]] DecklistCardNode *getDataNode() const { return dataNode; } @@ -200,7 +200,7 @@ public: * @brief Returns the root index of the model. * @return QModelIndex representing the root node. */ - QModelIndex getRoot() const + [[nodiscard]] QModelIndex getRoot() const { return nodeToIndex(root); }; @@ -210,17 +210,17 @@ public: * @param info Pointer to card information. * @return String representing the value of the current grouping criteria for the card. */ - QString getGroupCriteriaForCard(CardInfoPtr info) const; + [[nodiscard]] QString getGroupCriteriaForCard(CardInfoPtr info) const; // Qt model overrides - int rowCount(const QModelIndex &parent) const override; - int columnCount(const QModelIndex & /*parent*/ = QModelIndex()) const override; - QVariant data(const QModelIndex &index, int role) const override; + [[nodiscard]] int rowCount(const QModelIndex &parent) const override; + [[nodiscard]] int columnCount(const QModelIndex & /*parent*/ = QModelIndex()) const override; + [[nodiscard]] 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; - Qt::ItemFlags flags(const QModelIndex &index) const override; + [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + [[nodiscard]] QModelIndex index(int row, int column, const QModelIndex &parent) const override; + [[nodiscard]] QModelIndex parent(const QModelIndex &index) const override; + [[nodiscard]] Qt::ItemFlags flags(const QModelIndex &index) const override; bool setData(const QModelIndex &index, const QVariant &value, int role) override; bool removeRows(int row, int count, const QModelIndex &parent) override; @@ -232,8 +232,8 @@ public: * @param cardNumber Optional collector number. * @return QModelIndex of the card, or invalid index if not found. */ - QModelIndex findCard(const QString &cardName, - const QString &zoneName, + [[nodiscard]] QModelIndex findCard(const QString &cardName, + const QString &zoneName, const QString &providerId = "", const QString &cardNumber = "") const; @@ -269,15 +269,15 @@ public: * @brief Removes all cards and resets the model. */ void cleanList(); - DeckList *getDeckList() const + [[nodiscard]] DeckList *getDeckList() const { return deckList; } void setDeckList(DeckList *_deck); - QList getCards() const; - QList getCardsForZone(const QString &zoneName) const; - QList *getZones() const; + [[nodiscard]] QList getCards() const; + [[nodiscard]] QList getCardsForZone(const QString &zoneName) const; + [[nodiscard]] QList *getZones() const; /** * @brief Sets the criteria used to group cards in the model. @@ -294,8 +294,8 @@ private: InnerDecklistNode *createNodeIfNeeded(const QString &name, InnerDecklistNode *parent); QModelIndex nodeToIndex(AbstractDecklistNode *node) const; - DecklistModelCardNode *findCardNode(const QString &cardName, - const QString &zoneName, + [[nodiscard]] DecklistModelCardNode *findCardNode(const QString &cardName, + const QString &zoneName, const QString &providerId = "", const QString &cardNumber = "") const; void emitRecursiveUpdates(const QModelIndex &index); diff --git a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_sort_filter_proxy_model.h b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_sort_filter_proxy_model.h index 0603beace..94742795d 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_sort_filter_proxy_model.h +++ b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_sort_filter_proxy_model.h @@ -25,7 +25,7 @@ public: } protected: - bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; + [[nodiscard]] bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; private: QStringList sortCriteria; diff --git a/libcockatrice_rng/libcockatrice/rng/rng_abstract.h b/libcockatrice_rng/libcockatrice/rng/rng_abstract.h index ffd45b9d7..903e6ef1a 100644 --- a/libcockatrice_rng/libcockatrice/rng/rng_abstract.h +++ b/libcockatrice_rng/libcockatrice/rng/rng_abstract.h @@ -13,7 +13,7 @@ public: } virtual unsigned int rand(int min, int max) = 0; QVector makeNumbersVector(int n, int min, int max); - double testRandom(const QVector &numbers) const; + [[nodiscard]] double testRandom(const QVector &numbers) const; }; extern RNG_Abstract *rng; diff --git a/libcockatrice_settings/libcockatrice/settings/game_filters_settings.h b/libcockatrice_settings/libcockatrice/settings/game_filters_settings.h index d62fea03d..45e9b7441 100644 --- a/libcockatrice_settings/libcockatrice/settings/game_filters_settings.h +++ b/libcockatrice_settings/libcockatrice/settings/game_filters_settings.h @@ -57,7 +57,7 @@ private: explicit GameFiltersSettings(const QString &settingPath, QObject *parent = nullptr); GameFiltersSettings(const GameFiltersSettings & /*other*/); - QString hashGameType(const QString &gameType) const; + [[nodiscard]] QString hashGameType(const QString &gameType) const; }; #endif // GAMEFILTERSSETTINGS_H From 858361e6d3acc968a31318ef0c87bd94014b9703 Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Fri, 28 Nov 2025 14:41:11 -0800 Subject: [PATCH 11/40] [DeckLoader] Refactor last load info into struct (#6366) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [DeckLoader] Refactor last load info into struct * Use constant * [[nodiscard]] * do discard, I guess. --------- Co-authored-by: Brübach, Lukas --- .../src/interface/deck_loader/deck_loader.cpp | 42 +++++++++++-------- .../src/interface/deck_loader/deck_loader.h | 38 ++++++++++------- .../widgets/tabs/abstract_tab_deck_editor.cpp | 12 +++--- .../deck_preview_deck_tags_display_widget.cpp | 4 +- .../deck_preview/deck_preview_widget.cpp | 8 ++-- 5 files changed, 60 insertions(+), 44 deletions(-) diff --git a/cockatrice/src/interface/deck_loader/deck_loader.cpp b/cockatrice/src/interface/deck_loader/deck_loader.cpp index 320302142..372aa0aa8 100644 --- a/cockatrice/src/interface/deck_loader/deck_loader.cpp +++ b/cockatrice/src/interface/deck_loader/deck_loader.cpp @@ -25,13 +25,11 @@ 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(QObject *parent) - : QObject(parent), deckList(new DeckList()), lastFileFormat(CockatriceFormat), lastRemoteDeckId(-1) +DeckLoader::DeckLoader(QObject *parent) : QObject(parent), deckList(new DeckList()) { } -DeckLoader::DeckLoader(QObject *parent, DeckList *_deckList) - : QObject(parent), deckList(_deckList), lastFileFormat(CockatriceFormat), lastRemoteDeckId(-1) +DeckLoader::DeckLoader(QObject *parent, DeckList *_deckList) : QObject(parent), deckList(_deckList) { } @@ -64,8 +62,10 @@ bool DeckLoader::loadFromFile(const QString &fileName, FileFormat fmt, bool user } if (result) { - lastFileName = fileName; - lastFileFormat = fmt; + lastLoadInfo = { + .fileName = fileName, + .fileFormat = fmt, + }; if (userRequest) { updateLastLoadedTimestamp(fileName, fmt); } @@ -86,8 +86,10 @@ bool DeckLoader::loadFromFileAsync(const QString &fileName, FileFormat fmt, bool watcher->deleteLater(); if (result) { - lastFileName = fileName; - lastFileFormat = fmt; + lastLoadInfo = { + .fileName = fileName, + .fileFormat = fmt, + }; if (userRequest) { updateLastLoadedTimestamp(fileName, fmt); } @@ -129,9 +131,9 @@ bool DeckLoader::loadFromRemote(const QString &nativeString, int remoteDeckId) { bool result = deckList->loadFromString_Native(nativeString); if (result) { - lastFileName = QString(); - lastFileFormat = CockatriceFormat; - lastRemoteDeckId = remoteDeckId; + lastLoadInfo = { + .remoteDeckId = remoteDeckId, + }; emit deckLoaded(); } @@ -157,8 +159,10 @@ bool DeckLoader::saveToFile(const QString &fileName, FileFormat fmt) } if (result) { - lastFileName = fileName; - lastFileFormat = fmt; + lastLoadInfo = { + .fileName = fileName, + .fileFormat = fmt, + }; qCInfo(DeckLoaderLog) << "Deck was saved -" << result; } @@ -201,8 +205,10 @@ bool DeckLoader::updateLastLoadedTimestamp(const QString &fileName, FileFormat f file.close(); // Close the file to ensure changes are flushed if (result) { - lastFileName = fileName; - lastFileFormat = fmt; + lastLoadInfo = { + .fileName = fileName, + .fileFormat = fmt, + }; // Re-open the file and set the original timestamp if (!file.open(QIODevice::ReadWrite)) { @@ -582,8 +588,10 @@ bool DeckLoader::convertToCockatriceFormat(QString fileName) } else { qCInfo(DeckLoaderLog) << "Original file deleted successfully:" << fileName; } - lastFileName = newFileName; - lastFileFormat = CockatriceFormat; + lastLoadInfo = { + .fileName = newFileName, + .fileFormat = CockatriceFormat, + }; } return result; diff --git a/cockatrice/src/interface/deck_loader/deck_loader.h b/cockatrice/src/interface/deck_loader/deck_loader.h index ba9ba807d..00136e6bb 100644 --- a/cockatrice/src/interface/deck_loader/deck_loader.h +++ b/cockatrice/src/interface/deck_loader/deck_loader.h @@ -28,6 +28,21 @@ public: CockatriceFormat }; + /** + * @brief Information about where the deck was loaded from. + * + * For local decks, the remoteDeckId field will always be -1. + * For remote decks, fileName will be empty and fileFormat will always be CockatriceFormat + */ + struct LoadInfo + { + static constexpr int NON_REMOTE_ID = -1; + + QString fileName = ""; + FileFormat fileFormat = CockatriceFormat; + int remoteDeckId = NON_REMOTE_ID; + }; + /** * Supported file extensions for decklist files */ @@ -46,9 +61,7 @@ public: private: DeckList *deckList; - QString lastFileName; - FileFormat lastFileFormat; - int lastRemoteDeckId; + LoadInfo lastLoadInfo; public: DeckLoader(QObject *parent); @@ -56,26 +69,19 @@ public: DeckLoader(const DeckLoader &) = delete; DeckLoader &operator=(const DeckLoader &) = delete; - [[nodiscard]] const QString &getLastFileName() const + const LoadInfo &getLastLoadInfo() const { - return lastFileName; + return lastLoadInfo; } - void setLastFileName(const QString &_lastFileName) + + void setLastLoadInfo(const LoadInfo &info) { - lastFileName = _lastFileName; - } - [[nodiscard]] FileFormat getLastFileFormat() const - { - return lastFileFormat; - } - [[nodiscard]] int getLastRemoteDeckId() const - { - return lastRemoteDeckId; + lastLoadInfo = info; } [[nodiscard]] bool hasNotBeenLoaded() const { - return getLastFileName().isEmpty() && getLastRemoteDeckId() == -1; + return lastLoadInfo.fileName.isEmpty() && lastLoadInfo.remoteDeckId == LoadInfo::NON_REMOTE_ID; } static void clearSetNamesAndNumbers(const DeckList *deckList); 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 a3d3fe2cf..89611aa48 100644 --- a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp +++ b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp @@ -224,8 +224,8 @@ void AbstractTabDeckEditor::openDeck(DeckLoader *deck) { setDeck(deck); - if (!deck->getLastFileName().isEmpty()) { - SettingsCache::instance().recents().updateRecentlyOpenedDeckPaths(deck->getLastFileName()); + if (!deck->getLastLoadInfo().fileName.isEmpty()) { + SettingsCache::instance().recents().updateRecentlyOpenedDeckPaths(deck->getLastLoadInfo().fileName); } } @@ -411,7 +411,7 @@ void AbstractTabDeckEditor::openDeckFromFile(const QString &fileName, DeckOpenLo bool AbstractTabDeckEditor::actSaveDeck() { DeckLoader *const deck = getDeckLoader(); - if (deck->getLastRemoteDeckId() != -1) { + if (deck->getLastLoadInfo().remoteDeckId != DeckLoader::LoadInfo::NON_REMOTE_ID) { QString deckString = deck->getDeckList()->writeToString_Native(); if (deckString.length() > MAX_FILE_LENGTH) { QMessageBox::critical(this, tr("Error"), tr("Could not save remote deck")); @@ -419,7 +419,7 @@ bool AbstractTabDeckEditor::actSaveDeck() } Command_DeckUpload cmd; - cmd.set_deck_id(static_cast(deck->getLastRemoteDeckId())); + cmd.set_deck_id(static_cast(deck->getLastLoadInfo().remoteDeckId)); cmd.set_deck_list(deckString.toStdString()); PendingCommand *pend = AbstractClient::prepareSessionCommand(cmd); @@ -427,9 +427,9 @@ bool AbstractTabDeckEditor::actSaveDeck() tabSupervisor->getClient()->sendCommand(pend); return true; - } else if (deck->getLastFileName().isEmpty()) + } else if (deck->getLastLoadInfo().fileName.isEmpty()) return actSaveDeckAs(); - else if (deck->saveToFile(deck->getLastFileName(), deck->getLastFileFormat())) { + else if (deck->saveToFile(deck->getLastLoadInfo().fileName, deck->getLastLoadInfo().fileFormat)) { setModified(false); return true; } 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 eb105697f..b8425e842 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 @@ -112,7 +112,7 @@ void DeckPreviewDeckTagsDisplayWidget::openTagEditDlg() return; deckPreviewWidget->deckLoader->convertToCockatriceFormat(deckPreviewWidget->filePath); - deckPreviewWidget->filePath = deckPreviewWidget->deckLoader->getLastFileName(); + deckPreviewWidget->filePath = deckPreviewWidget->deckLoader->getLastLoadInfo().fileName; deckPreviewWidget->refreshBannerCardText(); canAddTags = true; } @@ -125,7 +125,7 @@ void DeckPreviewDeckTagsDisplayWidget::openTagEditDlg() return; deckPreviewWidget->deckLoader->convertToCockatriceFormat(deckPreviewWidget->filePath); - deckPreviewWidget->filePath = deckPreviewWidget->deckLoader->getLastFileName(); + deckPreviewWidget->filePath = deckPreviewWidget->deckLoader->getLastLoadInfo().fileName; deckPreviewWidget->refreshBannerCardText(); canAddTags = true; 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 8b2bec10b..b330b0c4c 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 @@ -79,7 +79,7 @@ void DeckPreviewWidget::initializeUi(const bool deckLoadSuccess) bannerCardDisplayWidget->setCard(bannerCard); bannerCardDisplayWidget->setFontSize(24); - setFilePath(deckLoader->getLastFileName()); + setFilePath(deckLoader->getLastLoadInfo().fileName); colorIdentityWidget = new ColorIdentityWidget(this, getColorIdentity()); deckTagsDisplayWidget = new DeckPreviewDeckTagsDisplayWidget(this, deckLoader->getDeckList()); @@ -185,7 +185,7 @@ QString DeckPreviewWidget::getColorIdentity() */ QString DeckPreviewWidget::getDisplayName() const { - return deckLoader->getDeckList()->getName().isEmpty() ? QFileInfo(deckLoader->getLastFileName()).fileName() + return deckLoader->getDeckList()->getName().isEmpty() ? QFileInfo(deckLoader->getLastLoadInfo().fileName).fileName() : deckLoader->getDeckList()->getName(); } @@ -408,7 +408,9 @@ void DeckPreviewWidget::actRenameFile() return; } - deckLoader->setLastFileName(newFilePath); + DeckLoader::LoadInfo lastLoadInfo = deckLoader->getLastLoadInfo(); + lastLoadInfo.fileName = newFilePath; + deckLoader->setLastLoadInfo(lastLoadInfo); // update VDS setFilePath(newFilePath); From 8abd04dab1820cf5e14802bd8e2cb0a4b7811dcc Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Sat, 29 Nov 2025 14:19:11 +0100 Subject: [PATCH 12/40] [Fix-Warnings] Remove more redundant empty declarations. (extra semicolons) (#6374) --- .../update/card_spoiler/spoiler_background_updater.h | 2 +- cockatrice/src/client/settings/shortcuts_settings.h | 8 ++++---- .../interface/settings_card_preference_provider.h | 2 +- cockatrice/src/game/player/player.h | 4 ++-- cockatrice/src/game/zones/logic/card_zone_logic.h | 2 +- .../cards/additional_info/mana_symbol_widget.h | 6 +++--- .../deck_editor_database_display_widget.h | 2 +- .../widgets/printing_selector/printing_selector.h | 2 +- .../widgets/server/user/user_list_manager.cpp | 2 +- .../edhrec_api_response_card_list_display_widget.h | 2 +- .../deck_preview/deck_preview_tag_display_widget.h | 2 +- .../visual_deck_storage_folder_display_widget.h | 2 +- cockatrice/src/interface/window_main.h | 2 +- libcockatrice_card/libcockatrice/card/card_info.h | 2 +- .../libcockatrice/card/game_specific_terms.h | 2 +- .../libcockatrice/deck_list/deck_list.h | 4 ++-- .../libcockatrice/models/deck_list/deck_list_model.h | 2 +- .../network/server/local/local_server_interface.h | 2 +- .../server/remote/game/server_abstract_participant.h | 2 +- .../server/remote/server_database_interface.h | 10 +++++----- servatrice/src/serversocketinterface.h | 12 ++++++------ 21 files changed, 37 insertions(+), 37 deletions(-) diff --git a/cockatrice/src/client/network/update/card_spoiler/spoiler_background_updater.h b/cockatrice/src/client/network/update/card_spoiler/spoiler_background_updater.h index 387f93820..a2feb5ccf 100644 --- a/cockatrice/src/client/network/update/card_spoiler/spoiler_background_updater.h +++ b/cockatrice/src/client/network/update/card_spoiler/spoiler_background_updater.h @@ -22,7 +22,7 @@ public: inline QString getCardUpdaterBinaryName() { return "oracle"; - }; + } QByteArray getHash(const QString fileName); QByteArray getHash(QByteArray data); static bool deleteSpoilerFile(); diff --git a/cockatrice/src/client/settings/shortcuts_settings.h b/cockatrice/src/client/settings/shortcuts_settings.h index d1b0301d1..736f0c896 100644 --- a/cockatrice/src/client/settings/shortcuts_settings.h +++ b/cockatrice/src/client/settings/shortcuts_settings.h @@ -99,15 +99,15 @@ public: void setSequence(const QList &_sequence) { QList::operator=(_sequence); - }; + } [[nodiscard]] QString getName() const { return QApplication::translate("shortcutsTab", name.toUtf8().data()); - }; + } [[nodiscard]] QString getGroupName() const { return ShortcutGroup::getGroupName(group); - }; + } private: QString name; @@ -129,7 +129,7 @@ public: [[nodiscard]] QList getAllShortcutKeys() const { return shortCuts.keys(); - }; + } void setShortcuts(const QString &name, const QList &Sequence); void setShortcuts(const QString &name, const QKeySequence &Sequence); diff --git a/cockatrice/src/database/interface/settings_card_preference_provider.h b/cockatrice/src/database/interface/settings_card_preference_provider.h index 5ec23ea60..6c31b9d6d 100644 --- a/cockatrice/src/database/interface/settings_card_preference_provider.h +++ b/cockatrice/src/database/interface/settings_card_preference_provider.h @@ -15,7 +15,7 @@ public: [[nodiscard]] bool getIncludeRebalancedCards() const override { return SettingsCache::instance().getIncludeRebalancedCards(); - }; + } }; #endif // COCKATRICE_SETTINGS_CARD_PREFERENCE_PROVIDER_H diff --git a/cockatrice/src/game/player/player.h b/cockatrice/src/game/player/player.h index 0751abb14..4501b0c91 100644 --- a/cockatrice/src/game/player/player.h +++ b/cockatrice/src/game/player/player.h @@ -113,7 +113,7 @@ public: [[nodiscard]] PlayerActions *getPlayerActions() const { return playerActions; - }; + } [[nodiscard]] PlayerEventHandler *getPlayerEventHandler() const { @@ -123,7 +123,7 @@ public: [[nodiscard]] PlayerInfo *getPlayerInfo() const { return playerInfo; - }; + } [[nodiscard]] PlayerMenu *getPlayerMenu() const { diff --git a/cockatrice/src/game/zones/logic/card_zone_logic.h b/cockatrice/src/game/zones/logic/card_zone_logic.h index 4d02b7dd1..1aa46effd 100644 --- a/cockatrice/src/game/zones/logic/card_zone_logic.h +++ b/cockatrice/src/game/zones/logic/card_zone_logic.h @@ -52,7 +52,7 @@ public: void rawInsertCard(CardItem *card, int index) { cards.insert(index, card); - }; + } [[nodiscard]] const CardList &getCards() const { diff --git a/cockatrice/src/interface/widgets/cards/additional_info/mana_symbol_widget.h b/cockatrice/src/interface/widgets/cards/additional_info/mana_symbol_widget.h index 2ae76e9c0..8d2c6813f 100644 --- a/cockatrice/src/interface/widgets/cards/additional_info/mana_symbol_widget.h +++ b/cockatrice/src/interface/widgets/cards/additional_info/mana_symbol_widget.h @@ -23,15 +23,15 @@ public: [[nodiscard]] bool isColorActive() const { return isActive; - }; + } [[nodiscard]] QString getSymbol() const { return symbol; - }; + } [[nodiscard]] QChar getSymbolChar() const { return symbol[0]; - }; + } void loadManaIcon(); 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 0d3ce9f4c..593be7825 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 @@ -32,7 +32,7 @@ public: QTreeView *getDatabaseView() { return databaseView; - }; + } public slots: ExactCard currentCard() const; diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector.h b/cockatrice/src/interface/widgets/printing_selector/printing_selector.h index b83768327..88a49f1e0 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector.h +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector.h @@ -39,7 +39,7 @@ public: [[nodiscard]] DeckListModel *getDeckModel() const { return deckModel; - }; + } public slots: void retranslateUi(); diff --git a/cockatrice/src/interface/widgets/server/user/user_list_manager.cpp b/cockatrice/src/interface/widgets/server/user/user_list_manager.cpp index 9b930b7f6..4bc2c84d6 100644 --- a/cockatrice/src/interface/widgets/server/user/user_list_manager.cpp +++ b/cockatrice/src/interface/widgets/server/user/user_list_manager.cpp @@ -167,4 +167,4 @@ const ServerInfo_User *UserListManager::getOnlineUser(const QString &userName) c } return nullptr; -}; \ No newline at end of file +} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_list_display_widget.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_list_display_widget.h index 0ebb9b927..d34c3da34 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_list_display_widget.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_list_display_widget.h @@ -24,7 +24,7 @@ public: [[nodiscard]] QString getBannerText() const { return header->getText(); - }; + } private: QVBoxLayout *layout; diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.h index a4ea3633b..a868aa4f1 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.h @@ -44,7 +44,7 @@ public: { state = newState; update(); - }; + } signals: /** diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.h index fe1693c7e..f735d0ad3 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.h @@ -31,7 +31,7 @@ public: [[nodiscard]] FlowWidget *getFlowWidget() const { return flowWidget; - }; + } public slots: void updateVisibility(bool recursive = true); diff --git a/cockatrice/src/interface/window_main.h b/cockatrice/src/interface/window_main.h index 620a09467..477d7b07c 100644 --- a/cockatrice/src/interface/window_main.h +++ b/cockatrice/src/interface/window_main.h @@ -135,7 +135,7 @@ private: inline QString getCardUpdaterBinaryName() { return "oracle"; - }; + } void createCardUpdateProcess(bool background = false); void exitCardDatabaseUpdate(); diff --git a/libcockatrice_card/libcockatrice/card/card_info.h b/libcockatrice_card/libcockatrice/card/card_info.h index 3ff78f38c..92b7f3121 100644 --- a/libcockatrice_card/libcockatrice/card/card_info.h +++ b/libcockatrice_card/libcockatrice/card/card_info.h @@ -190,7 +190,7 @@ public: const QSet &getAltNames() { return altNames; - }; + } [[nodiscard]] const QString &getText() const { return text; diff --git a/libcockatrice_card/libcockatrice/card/game_specific_terms.h b/libcockatrice_card/libcockatrice/card/game_specific_terms.h index 8f13039da..2931365ad 100644 --- a/libcockatrice_card/libcockatrice/card/game_specific_terms.h +++ b/libcockatrice_card/libcockatrice/card/game_specific_terms.h @@ -53,6 +53,6 @@ inline static const QString getNicePropertyName(QString key) return QCoreApplication::translate("Mtg", "Color Identity"); return key; } -}; // namespace Mtg +} // namespace Mtg #endif diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h index 1be673fcf..fd3b4677e 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h @@ -158,7 +158,7 @@ protected: virtual QString getCardZoneFromName(const QString /*cardName*/, QString currentZoneName) { return currentZoneName; - }; + } /** * @brief Produce the complete display name of a card. @@ -169,7 +169,7 @@ protected: virtual QString getCompleteCardName(const QString &cardName) const { return cardName; - }; + } signals: /// Emitted when the deck hash changes. 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 08a4592ae..9b96c0ce6 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h +++ b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h @@ -203,7 +203,7 @@ public: [[nodiscard]] QModelIndex getRoot() const { return nodeToIndex(root); - }; + } /** * @brief Returns the value of the grouping category for a card based on the current criteria. diff --git a/libcockatrice_network/libcockatrice/network/server/local/local_server_interface.h b/libcockatrice_network/libcockatrice/network/server/local/local_server_interface.h index 1ddf5a85a..4410fd65c 100644 --- a/libcockatrice_network/libcockatrice/network/server/local/local_server_interface.h +++ b/libcockatrice_network/libcockatrice/network/server/local/local_server_interface.h @@ -25,7 +25,7 @@ public: QString getConnectionType() const override { return "local"; - }; + } void transmitProtocolItem(const ServerMessage &item) override; signals: void itemToClient(const ServerMessage &item); diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_participant.h b/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_participant.h index 10fbb3349..f60d56dcf 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_participant.h +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_participant.h @@ -76,7 +76,7 @@ public: virtual void prepareDestroy() { removeFromGame(); - }; + } void removeFromGame(); Server_AbstractUserInterface *getUserInterface() const { diff --git a/libcockatrice_network/libcockatrice/network/server/remote/server_database_interface.h b/libcockatrice_network/libcockatrice/network/server/remote/server_database_interface.h index d2577a99b..b43dbde42 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/server_database_interface.h +++ b/libcockatrice_network/libcockatrice/network/server/remote/server_database_interface.h @@ -83,7 +83,7 @@ public: virtual bool usernameIsValid(const QString & /*userName */, QString & /* error */) { return true; - }; + } public slots: virtual void endSession(qint64 /* sessionId */) { @@ -154,16 +154,16 @@ public: int & /* banSecondsRemaining */) { return false; - }; + } virtual int checkNumberOfUserAccounts(const QString & /* email */) { return 0; - }; + } virtual bool changeUserPassword(const QString & /* user */, const QString & /* password */, bool /* passwordNeedsHash */) { return false; - }; + } virtual bool changeUserPassword(const QString & /* user */, const QString & /* oldPassword */, bool /* oldPasswordNeedsHash */, @@ -171,7 +171,7 @@ public: bool /* newPasswordNeedsHash */) { return false; - }; + } }; #endif diff --git a/servatrice/src/serversocketinterface.h b/servatrice/src/serversocketinterface.h index e522ea6c1..e10aa0dde 100644 --- a/servatrice/src/serversocketinterface.h +++ b/servatrice/src/serversocketinterface.h @@ -177,7 +177,7 @@ public: QString getConnectionType() const { return "tcp"; - }; + } private: QTcpSocket *socket; @@ -190,11 +190,11 @@ protected: void writeToSocket(QByteArray &data) { socket->write(data); - }; + } void flushSocket() { socket->flush(); - }; + } void initSessionDeprecated(); bool initTcpSession(); protected slots: @@ -224,7 +224,7 @@ public: QString getConnectionType() const { return "websocket"; - }; + } private: QWebSocket *socket; @@ -234,11 +234,11 @@ protected: void writeToSocket(QByteArray &data) { socket->sendBinaryMessage(data); - }; + } void flushSocket() { socket->flush(); - }; + } bool initWebsocketSession(); protected slots: void binaryMessageReceived(const QByteArray &message); From c5fde071e79c162fa20a74d133b97c9488a4cb95 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Sat, 29 Nov 2025 18:53:11 +0100 Subject: [PATCH 13/40] [Cleanup] Unused #includes (#6367) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Cleanup] Unused #includes Took 44 minutes * [Cleanup] More unused #includes Took 55 minutes * [Cleanup] Include QSet Took 4 minutes * [Cleanup] Include QDebug in deck_list.cpp Took 3 minutes * [Cleanup] Include protocol stuff in servatrice_database_interface.h Took 3 minutes * [Cleanup] Include QDialogButtonBox Took 8 minutes * [Cleanup] Include QUrl Took 8 minutes * [Cleanup] Include QTextOption in header. Took 3 minutes * [Cleanup] Include QMap in user_list_manager.h Took 8 minutes * [Cleanup] Adjust qjson Took 8 minutes * [Cleanup] include button box. Took 3 minutes * [Cleanup] Redo fwd declarations. * [Cleanup] Redo last removed fwd declarations. --------- Co-authored-by: Lukas Brübach --- .../interfaces/deck_stats_interface.cpp | 1 - .../network/interfaces/deck_stats_interface.h | 1 - .../interfaces/tapped_out_interface.cpp | 1 - .../network/interfaces/tapped_out_interface.h | 2 - .../spoiler_background_updater.cpp | 2 - .../update/client/update_downloader.cpp | 1 - .../network/update/client/update_downloader.h | 2 - .../src/client/settings/cache_settings.h | 1 - .../client/settings/card_counter_settings.h | 1 - .../src/client/settings/shortcut_treeview.h | 1 - cockatrice/src/filters/deck_filter_string.cpp | 1 + cockatrice/src/filters/deck_filter_string.h | 2 - .../src/game/board/abstract_counter.cpp | 3 +- cockatrice/src/game/board/arrow_item.cpp | 1 + cockatrice/src/game/board/card_item.cpp | 2 +- cockatrice/src/game/deckview/deck_view.h | 3 -- .../src/game/deckview/deck_view_container.cpp | 4 -- .../src/game/dialogs/dlg_create_token.cpp | 1 - .../src/game/dialogs/dlg_create_token.h | 1 - cockatrice/src/game/game_event_handler.cpp | 1 - cockatrice/src/game/game_scene.cpp | 1 - cockatrice/src/game/game_state.h | 2 - .../src/game/log/message_log_widget.cpp | 2 - cockatrice/src/game/log/message_log_widget.h | 3 -- .../src/game/player/menu/grave_menu.cpp | 1 - .../src/game/player/menu/player_menu.cpp | 5 +-- .../src/game/player/menu/sideboard_menu.cpp | 1 + .../src/game/player/menu/utility_menu.cpp | 2 + cockatrice/src/game/player/player.cpp | 2 +- cockatrice/src/game/player/player.h | 8 ++-- cockatrice/src/game/player/player_actions.cpp | 3 +- cockatrice/src/game/player/player_actions.h | 1 + .../src/game/player/player_event_handler.cpp | 1 + .../src/game/player/player_graphics_item.cpp | 5 +++ cockatrice/src/game/player/player_info.h | 5 --- .../src/game/player/player_list_widget.cpp | 4 -- cockatrice/src/game/player/player_target.h | 1 - cockatrice/src/game/zones/hand_zone.cpp | 1 + .../src/game/zones/logic/card_zone_logic.cpp | 3 +- cockatrice/src/game/zones/pile_zone.cpp | 1 + cockatrice/src/game/zones/stack_zone.cpp | 2 +- cockatrice/src/game/zones/table_zone.cpp | 2 +- cockatrice/src/game/zones/view_zone.cpp | 2 +- .../src/game/zones/view_zone_widget.cpp | 2 +- .../card_picture_loader.cpp | 1 - .../card_picture_loader/card_picture_loader.h | 1 - .../card_picture_loader_local.h | 2 - ...ure_loader_request_status_display_widget.h | 4 +- .../card_picture_loader_status_bar.h | 1 - .../card_picture_loader_worker.cpp | 1 - .../card_picture_loader_worker_work.cpp | 2 - .../card_picture_to_load.h | 1 - .../additional_info/color_identity_widget.cpp | 1 - .../additional_info/mana_cost_widget.cpp | 1 - .../card_group_display_widget.cpp | 1 - .../card_group_display_widget.h | 1 - .../flat_card_group_display_widget.cpp | 3 -- .../cards/card_info_display_widget.cpp | 2 - .../widgets/cards/card_info_frame_widget.cpp | 1 - .../card_info_picture_enlarged_widget.cpp | 1 - .../cards/card_info_picture_enlarged_widget.h | 1 - .../widgets/cards/card_info_picture_widget.h | 1 - ..._info_picture_with_text_overlay_widget.cpp | 1 - .../widgets/cards/card_info_text_widget.cpp | 1 - .../widgets/cards/card_size_widget.cpp | 1 - .../cards/deck_card_zone_display_widget.cpp | 1 - .../cards/deck_card_zone_display_widget.h | 1 - .../deck_preview_card_picture_widget.cpp | 1 - .../cards/deck_preview_card_picture_widget.h | 1 + .../deck_analytics/deck_analytics_widget.h | 3 -- .../deck_analytics/mana_devotion_widget.cpp | 3 -- .../deck_editor_database_display_widget.cpp | 2 - .../deck_editor_deck_dock_widget.h | 1 - .../deck_editor_filter_dock_widget.cpp | 1 - .../deck_editor_filter_dock_widget.h | 1 - .../deck_list_history_manager_widget.h | 1 - .../interface/widgets/dialogs/dlg_connect.cpp | 2 - .../widgets/dialogs/dlg_create_game.cpp | 1 - .../dialogs/dlg_default_tags_editor.cpp | 1 + .../widgets/dialogs/dlg_default_tags_editor.h | 1 - .../widgets/dialogs/dlg_edit_avatar.cpp | 1 - .../widgets/dialogs/dlg_edit_password.h | 1 - .../widgets/dialogs/dlg_edit_tokens.cpp | 2 - .../widgets/dialogs/dlg_edit_user.cpp | 1 - .../dialogs/dlg_forgot_password_challenge.cpp | 2 - .../dialogs/dlg_forgot_password_request.cpp | 2 - .../dialogs/dlg_forgot_password_reset.cpp | 2 - .../widgets/dialogs/dlg_load_remote_deck.cpp | 2 - .../widgets/dialogs/dlg_manage_sets.cpp | 3 -- .../widgets/dialogs/dlg_manage_sets.h | 1 - .../widgets/dialogs/dlg_register.cpp | 2 - .../dialogs/dlg_select_set_for_cards.cpp | 2 +- .../widgets/dialogs/dlg_settings.cpp | 1 - .../widgets/dialogs/dlg_tip_of_the_day.cpp | 1 - .../widgets/dialogs/dlg_tip_of_the_day.h | 2 - .../interface/widgets/dialogs/dlg_update.cpp | 2 - .../widgets/general/display/bar_widget.h | 2 - .../display/dynamic_font_size_label.cpp | 1 - .../display/dynamic_font_size_push_button.cpp | 1 - .../general/display/percent_bar_widget.h | 1 - .../interface/widgets/general/home_widget.cpp | 1 + .../interface/widgets/general/home_widget.h | 1 - .../widgets/menus/deck_editor_menu.cpp | 1 + .../widgets/menus/deck_editor_menu.h | 2 - .../all_zones_card_amount_widget.h | 1 - .../printing_selector/card_amount_widget.h | 2 - .../printing_selector/printing_selector.cpp | 3 +- .../printing_selector/printing_selector.h | 1 - .../printing_selector_card_display_widget.cpp | 2 - .../printing_selector_card_display_widget.h | 2 - .../printing_selector_card_overlay_widget.h | 3 -- .../widgets/replay/replay_timeline_widget.cpp | 1 - .../widgets/replay/replay_timeline_widget.h | 1 - .../widgets/server/game_selector.cpp | 5 --- .../game_selector_quick_filter_toolbar.cpp | 1 - .../game_selector_quick_filter_toolbar.h | 3 -- .../interface/widgets/server/games_model.cpp | 3 -- .../interface/widgets/server/games_model.h | 2 - .../widgets/server/handle_public_servers.cpp | 2 - .../remote/remote_decklist_tree_widget.h | 1 - .../remote/remote_replay_list_tree_widget.h | 1 - .../widgets/server/user/user_context_menu.cpp | 2 - .../widgets/server/user/user_list_widget.cpp | 7 ---- .../widgets/tabs/abstract_tab_deck_editor.cpp | 6 --- .../edhrec_api_response_archidekt_links.cpp | 1 - .../edhrec_api_response_archidekt_links.h | 1 - .../edhrec_average_deck_api_response.h | 1 - .../average_deck/edhrec_deck_api_response.cpp | 1 - .../average_deck/edhrec_deck_api_response.h | 6 --- .../edhrec_api_response_card_container.h | 2 - .../cards/edhrec_api_response_card_list.h | 1 - ...commander_api_response_commander_details.h | 1 - .../commander/edhrec_commander_api_response.h | 1 - .../top_cards/edhrec_top_cards_api_response.h | 1 - .../edhrec_top_commanders_api_response.h | 1 - .../top_tags/edhrec_top_tags_api_response.h | 1 - ...rec_top_tags_api_response_display_widget.h | 1 - .../widgets/tabs/api/edhrec/tab_edhrec.cpp | 1 - .../tabs/api/edhrec/tab_edhrec_main.cpp | 1 - .../widgets/tabs/api/edhrec/tab_edhrec_main.h | 1 - .../widgets/tabs/tab_deck_editor.cpp | 17 -------- .../widgets/tabs/tab_deck_storage.cpp | 1 - .../src/interface/widgets/tabs/tab_game.cpp | 5 --- .../src/interface/widgets/tabs/tab_game.h | 2 - .../src/interface/widgets/tabs/tab_home.cpp | 3 -- .../src/interface/widgets/tabs/tab_home.h | 2 - .../src/interface/widgets/tabs/tab_logs.cpp | 8 ++-- .../src/interface/widgets/tabs/tab_logs.h | 1 - .../interface/widgets/tabs/tab_replays.cpp | 1 - .../src/interface/widgets/tabs/tab_room.h | 1 - .../src/interface/widgets/tabs/tab_server.cpp | 5 --- .../interface/widgets/tabs/tab_supervisor.cpp | 1 - .../interface/widgets/tabs/tab_supervisor.h | 2 - .../tabs/tab_visual_database_display.h | 2 - .../tab_deck_editor_visual.cpp | 6 --- .../tab_deck_storage_visual.cpp | 3 -- .../widgets/utility/get_text_with_max.cpp | 2 + .../widgets/utility/get_text_with_max.h | 3 +- .../widgets/utility/line_edit_completer.cpp | 1 - .../widgets/utility/line_edit_completer.h | 2 - .../widgets/utility/sequence_edit.cpp | 1 - .../interface/widgets/utility/sequence_edit.h | 1 - ...l_database_display_color_filter_widget.cpp | 1 - ...tabase_display_filter_save_load_widget.cpp | 3 +- ...database_display_filter_save_load_widget.h | 2 - ...database_display_main_type_filter_widget.h | 1 - ...sual_database_display_name_filter_widget.h | 1 - ...isual_database_display_set_filter_widget.h | 1 - ..._database_display_sub_type_filter_widget.h | 2 - .../visual_database_display_widget.cpp | 1 - .../visual_database_display_widget.h | 3 -- .../visual_deck_editor_widget.cpp | 1 - .../visual_deck_editor_widget.h | 1 - ...k_preview_color_identity_filter_widget.cpp | 1 - ...eck_preview_color_identity_filter_widget.h | 2 - .../deck_preview_deck_tags_display_widget.cpp | 1 - .../deck_preview_tag_addition_widget.cpp | 1 - .../deck_preview_tag_addition_widget.h | 4 -- .../deck_preview/deck_preview_tag_dialog.cpp | 1 - .../deck_preview/deck_preview_tag_dialog.h | 3 -- .../deck_preview/deck_preview_widget.cpp | 1 + ...ual_deck_storage_folder_display_widget.cpp | 1 + ...isual_deck_storage_folder_display_widget.h | 5 +-- .../visual_deck_storage_search_widget.cpp | 1 + .../visual_deck_storage_search_widget.h | 3 +- .../visual_deck_storage_sort_widget.cpp | 2 + .../visual_deck_storage_tag_filter_widget.cpp | 4 +- .../visual_deck_storage_tag_filter_widget.h | 2 +- .../visual_deck_storage_widget.cpp | 1 - .../visual_deck_storage_widget.h | 4 -- cockatrice/src/interface/window_main.cpp | 1 - cockatrice/src/interface/window_main.h | 2 - cockatrice/src/main.cpp | 6 --- cockatrice/src/main.h | 1 - .../libcockatrice/card/card_info.h | 1 - .../libcockatrice/card/card_info_comparator.h | 1 - .../card/database/card_database.cpp | 2 - .../card/database/card_database.h | 2 - .../card/database/card_database_loader.h | 1 - .../card/printing/printing_info.h | 1 - .../libcockatrice/card/set/card_set_list.h | 1 - .../deck_list/abstract_deck_list_node.h | 1 - .../libcockatrice/deck_list/deck_list.cpp | 1 + .../libcockatrice/deck_list/deck_list.h | 1 - .../libcockatrice/filters/filter_card.h | 1 - .../libcockatrice/filters/filter_tree.h | 1 - .../interface_card_set_priority_controller.h | 1 - .../database/card_database_display_model.h | 2 - .../network/client/abstract/abstract_client.h | 1 - .../network/client/remote/remote_client.h | 1 - .../game/server_abstract_participant.cpp | 37 ------------------ .../remote/game/server_abstract_player.h | 1 - .../server/remote/game/server_cardzone.h | 1 - .../server/remote/game/server_game.cpp | 2 - .../server/remote/game/server_player.cpp | 39 ------------------- .../network/server/remote/server.cpp | 1 - .../network/server/remote/server.h | 4 -- .../remote/server_abstractuserinterface.cpp | 2 - .../remote/server_abstractuserinterface.h | 1 - .../server/remote/server_protocolhandler.h | 1 - .../network/server/remote/server_room.h | 2 - .../libcockatrice/protocol/featureset.cpp | 1 - .../libcockatrice/protocol/featureset.h | 1 - .../settings/card_database_settings.h | 3 -- .../settings/download_settings.h | 2 - .../libcockatrice/settings/settings_manager.h | 1 - .../src/servatrice_database_interface.h | 2 + 227 files changed, 58 insertions(+), 446 deletions(-) diff --git a/cockatrice/src/client/network/interfaces/deck_stats_interface.cpp b/cockatrice/src/client/network/interfaces/deck_stats_interface.cpp index a5cea5358..eeb48959c 100644 --- a/cockatrice/src/client/network/interfaces/deck_stats_interface.cpp +++ b/cockatrice/src/client/network/interfaces/deck_stats_interface.cpp @@ -2,7 +2,6 @@ #include #include -#include #include #include #include diff --git a/cockatrice/src/client/network/interfaces/deck_stats_interface.h b/cockatrice/src/client/network/interfaces/deck_stats_interface.h index f621fff7c..fd1691a8b 100644 --- a/cockatrice/src/client/network/interfaces/deck_stats_interface.h +++ b/cockatrice/src/client/network/interfaces/deck_stats_interface.h @@ -7,7 +7,6 @@ #ifndef DECKSTATS_INTERFACE_H #define DECKSTATS_INTERFACE_H -#include #include #include diff --git a/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp b/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp index d18d811b0..cebbce8b8 100644 --- a/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp +++ b/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp @@ -2,7 +2,6 @@ #include #include -#include #include #include #include diff --git a/cockatrice/src/client/network/interfaces/tapped_out_interface.h b/cockatrice/src/client/network/interfaces/tapped_out_interface.h index e4e9498a3..056d7fd9a 100644 --- a/cockatrice/src/client/network/interfaces/tapped_out_interface.h +++ b/cockatrice/src/client/network/interfaces/tapped_out_interface.h @@ -7,8 +7,6 @@ #ifndef TAPPEDOUT_INTERFACE_H #define TAPPEDOUT_INTERFACE_H -#include -#include #include #include 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 cfd4cbbf8..f6f851037 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 @@ -4,13 +4,11 @@ #include "../../../../main.h" #include "../../../settings/cache_settings.h" -#include #include #include #include #include #include -#include #include #include #include diff --git a/cockatrice/src/client/network/update/client/update_downloader.cpp b/cockatrice/src/client/network/update/client/update_downloader.cpp index 40186bec4..c0f3e945c 100644 --- a/cockatrice/src/client/network/update/client/update_downloader.cpp +++ b/cockatrice/src/client/network/update/client/update_downloader.cpp @@ -1,6 +1,5 @@ #include "update_downloader.h" -#include #include UpdateDownloader::UpdateDownloader(QObject *parent) : QObject(parent), response(nullptr) diff --git a/cockatrice/src/client/network/update/client/update_downloader.h b/cockatrice/src/client/network/update/client/update_downloader.h index 4f79f3f6d..d70759038 100644 --- a/cockatrice/src/client/network/update/client/update_downloader.h +++ b/cockatrice/src/client/network/update/client/update_downloader.h @@ -7,9 +7,7 @@ #ifndef COCKATRICE_UPDATEDOWNLOADER_H #define COCKATRICE_UPDATEDOWNLOADER_H -#include #include -#include #include class UpdateDownloader : public QObject diff --git a/cockatrice/src/client/settings/cache_settings.h b/cockatrice/src/client/settings/cache_settings.h index 5e329bf09..df68ce0c4 100644 --- a/cockatrice/src/client/settings/cache_settings.h +++ b/cockatrice/src/client/settings/cache_settings.h @@ -11,7 +11,6 @@ #include #include -#include #include #include #include diff --git a/cockatrice/src/client/settings/card_counter_settings.h b/cockatrice/src/client/settings/card_counter_settings.h index 63615d0e2..b1d467d67 100644 --- a/cockatrice/src/client/settings/card_counter_settings.h +++ b/cockatrice/src/client/settings/card_counter_settings.h @@ -7,7 +7,6 @@ #ifndef CARD_COUNTER_SETTINGS_H #define CARD_COUNTER_SETTINGS_H -#include #include class QSettings; diff --git a/cockatrice/src/client/settings/shortcut_treeview.h b/cockatrice/src/client/settings/shortcut_treeview.h index d503140f0..8d74a6f1e 100644 --- a/cockatrice/src/client/settings/shortcut_treeview.h +++ b/cockatrice/src/client/settings/shortcut_treeview.h @@ -7,7 +7,6 @@ #ifndef SHORTCUT_TREEVIEW_H #define SHORTCUT_TREEVIEW_H -#include #include #include #include diff --git a/cockatrice/src/filters/deck_filter_string.cpp b/cockatrice/src/filters/deck_filter_string.cpp index c9adc17e9..52b6a38d1 100644 --- a/cockatrice/src/filters/deck_filter_string.cpp +++ b/cockatrice/src/filters/deck_filter_string.cpp @@ -1,5 +1,6 @@ #include "deck_filter_string.h" +#include #include #include #include diff --git a/cockatrice/src/filters/deck_filter_string.h b/cockatrice/src/filters/deck_filter_string.h index 635745592..1b43d770d 100644 --- a/cockatrice/src/filters/deck_filter_string.h +++ b/cockatrice/src/filters/deck_filter_string.h @@ -10,10 +10,8 @@ #include "../interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.h" #include -#include #include #include -#include inline Q_LOGGING_CATEGORY(DeckFilterStringLog, "deck_filter_string"); diff --git a/cockatrice/src/game/board/abstract_counter.cpp b/cockatrice/src/game/board/abstract_counter.cpp index 985c78ad2..08d19ec8a 100644 --- a/cockatrice/src/game/board/abstract_counter.cpp +++ b/cockatrice/src/game/board/abstract_counter.cpp @@ -3,15 +3,14 @@ #include "../../client/settings/cache_settings.h" #include "../../interface/widgets/tabs/tab_game.h" #include "../player/player.h" +#include "../player/player_actions.h" #include "translate_counter_name.h" #include #include -#include #include #include #include -#include #include #include #include diff --git a/cockatrice/src/game/board/arrow_item.cpp b/cockatrice/src/game/board/arrow_item.cpp index d5d0ebfe0..1352b3a05 100644 --- a/cockatrice/src/game/board/arrow_item.cpp +++ b/cockatrice/src/game/board/arrow_item.cpp @@ -3,6 +3,7 @@ #include "../../client/settings/cache_settings.h" #include "../player/player.h" +#include "../player/player_actions.h" #include "../player/player_target.h" #include "../zones/card_zone.h" #include "card_item.h" diff --git a/cockatrice/src/game/board/card_item.cpp b/cockatrice/src/game/board/card_item.cpp index e786b5329..34c2f9a98 100644 --- a/cockatrice/src/game/board/card_item.cpp +++ b/cockatrice/src/game/board/card_item.cpp @@ -5,7 +5,7 @@ #include "../game_scene.h" #include "../phase.h" #include "../player/player.h" -#include "../zones/card_zone.h" +#include "../player/player_actions.h" #include "../zones/logic/view_zone_logic.h" #include "../zones/table_zone.h" #include "../zones/view_zone.h" diff --git a/cockatrice/src/game/deckview/deck_view.h b/cockatrice/src/game/deckview/deck_view.h index 027d0fafd..5abc558bd 100644 --- a/cockatrice/src/game/deckview/deck_view.h +++ b/cockatrice/src/game/deckview/deck_view.h @@ -9,11 +9,8 @@ #include "../board/abstract_card_drag_item.h" -#include #include #include -#include -#include #include class DeckList; diff --git a/cockatrice/src/game/deckview/deck_view_container.cpp b/cockatrice/src/game/deckview/deck_view_container.cpp index da24aa814..cf6ab00b8 100644 --- a/cockatrice/src/game/deckview/deck_view_container.cpp +++ b/cockatrice/src/game/deckview/deck_view_container.cpp @@ -8,13 +8,9 @@ #include "../../interface/widgets/dialogs/dlg_load_deck_from_website.h" #include "../../interface/widgets/dialogs/dlg_load_remote_deck.h" #include "../../interface/widgets/tabs/tab_game.h" -#include "../game_scene.h" #include "deck_view.h" #include -#include -#include -#include #include #include #include diff --git a/cockatrice/src/game/dialogs/dlg_create_token.cpp b/cockatrice/src/game/dialogs/dlg_create_token.cpp index 6594e339d..1f6f9b08c 100644 --- a/cockatrice/src/game/dialogs/dlg_create_token.cpp +++ b/cockatrice/src/game/dialogs/dlg_create_token.cpp @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include diff --git a/cockatrice/src/game/dialogs/dlg_create_token.h b/cockatrice/src/game/dialogs/dlg_create_token.h index 8235aa4cc..9a18f1a57 100644 --- a/cockatrice/src/game/dialogs/dlg_create_token.h +++ b/cockatrice/src/game/dialogs/dlg_create_token.h @@ -8,7 +8,6 @@ #define DLG_CREATETOKEN_H #include -#include class QLabel; class QLineEdit; diff --git a/cockatrice/src/game/game_event_handler.cpp b/cockatrice/src/game/game_event_handler.cpp index 1cb47f368..7bfc4da75 100644 --- a/cockatrice/src/game/game_event_handler.cpp +++ b/cockatrice/src/game/game_event_handler.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/cockatrice/src/game/game_scene.cpp b/cockatrice/src/game/game_scene.cpp index 2175f4aa2..77037cd6e 100644 --- a/cockatrice/src/game/game_scene.cpp +++ b/cockatrice/src/game/game_scene.cpp @@ -8,7 +8,6 @@ #include "zones/view_zone.h" #include "zones/view_zone_widget.h" -#include #include #include #include diff --git a/cockatrice/src/game/game_state.h b/cockatrice/src/game/game_state.h index b5d6a6572..54f6d9276 100644 --- a/cockatrice/src/game/game_state.h +++ b/cockatrice/src/game/game_state.h @@ -7,10 +7,8 @@ #ifndef COCKATRICE_GAME_STATE_H #define COCKATRICE_GAME_STATE_H -#include #include #include -#include class AbstractGame; class ServerInfo_PlayerProperties; diff --git a/cockatrice/src/game/log/message_log_widget.cpp b/cockatrice/src/game/log/message_log_widget.cpp index d4af5d00d..1ff3e32ff 100644 --- a/cockatrice/src/game/log/message_log_widget.cpp +++ b/cockatrice/src/game/log/message_log_widget.cpp @@ -6,12 +6,10 @@ #include "../board/translate_counter_name.h" #include "../phase.h" #include "../player/player.h" -#include "../zones/card_zone.h" #include <../../client/settings/card_counter_settings.h> #include #include -#include #include static const QString TABLE_ZONE_NAME = "table"; diff --git a/cockatrice/src/game/log/message_log_widget.h b/cockatrice/src/game/log/message_log_widget.h index a185cb288..369debd33 100644 --- a/cockatrice/src/game/log/message_log_widget.h +++ b/cockatrice/src/game/log/message_log_widget.h @@ -7,12 +7,9 @@ #ifndef MESSAGELOGWIDGET_H #define MESSAGELOGWIDGET_H -#include "../../client/translation.h" #include "../../interface/widgets/server/chat_view/chat_view.h" #include "../zones/logic/card_zone_logic.h" -#include - class AbstractGame; class CardItem; class GameEventContext; diff --git a/cockatrice/src/game/player/menu/grave_menu.cpp b/cockatrice/src/game/player/menu/grave_menu.cpp index 47d01bc77..d4faca42b 100644 --- a/cockatrice/src/game/player/menu/grave_menu.cpp +++ b/cockatrice/src/game/player/menu/grave_menu.cpp @@ -3,7 +3,6 @@ #include "../../abstract_game.h" #include "../player.h" #include "../player_actions.h" -#include "grave_menu.h" #include #include diff --git a/cockatrice/src/game/player/menu/player_menu.cpp b/cockatrice/src/game/player/menu/player_menu.cpp index 82747d482..3016a727f 100644 --- a/cockatrice/src/game/player/menu/player_menu.cpp +++ b/cockatrice/src/game/player/menu/player_menu.cpp @@ -3,12 +3,11 @@ #include "../../../interface/widgets/tabs/tab_game.h" #include "../../board/card_item.h" #include "../../zones/hand_zone.h" -#include "../card_menu_action_type.h" -#include "../player_actions.h" +#include "../../zones/pile_zone.h" +#include "../../zones/table_zone.h" #include "card_menu.h" #include "hand_menu.h" -#include #include PlayerMenu::PlayerMenu(Player *_player) : player(_player) diff --git a/cockatrice/src/game/player/menu/sideboard_menu.cpp b/cockatrice/src/game/player/menu/sideboard_menu.cpp index bfc40cfd3..beaabfcc6 100644 --- a/cockatrice/src/game/player/menu/sideboard_menu.cpp +++ b/cockatrice/src/game/player/menu/sideboard_menu.cpp @@ -1,6 +1,7 @@ #include "sideboard_menu.h" #include "../player.h" +#include "../player_actions.h" SideboardMenu::SideboardMenu(Player *player, QMenu *playerMenu) : QMenu(playerMenu) { diff --git a/cockatrice/src/game/player/menu/utility_menu.cpp b/cockatrice/src/game/player/menu/utility_menu.cpp index 15128defe..ca2832ec7 100644 --- a/cockatrice/src/game/player/menu/utility_menu.cpp +++ b/cockatrice/src/game/player/menu/utility_menu.cpp @@ -1,7 +1,9 @@ #include "utility_menu.h" +#include "../../../interface/deck_loader/deck_loader.h" #include "../player.h" #include "../player_actions.h" +#include "libcockatrice/deck_list/inner_deck_list_node.h" #include "player_menu.h" UtilityMenu::UtilityMenu(Player *_player, QMenu *playerMenu) : QMenu(playerMenu), player(_player) diff --git a/cockatrice/src/game/player/player.cpp b/cockatrice/src/game/player/player.cpp index ffb26c26e..efce40cd7 100644 --- a/cockatrice/src/game/player/player.cpp +++ b/cockatrice/src/game/player/player.cpp @@ -11,7 +11,7 @@ #include "../zones/pile_zone.h" #include "../zones/stack_zone.h" #include "../zones/table_zone.h" -#include "../zones/view_zone.h" +#include "player_actions.h" #include "player_target.h" #include diff --git a/cockatrice/src/game/player/player.h b/cockatrice/src/game/player/player.h index 4501b0c91..0a4fc9e69 100644 --- a/cockatrice/src/game/player/player.h +++ b/cockatrice/src/game/player/player.h @@ -9,9 +9,11 @@ #include "../../game_graphics/board/abstract_graphics_item.h" #include "../../interface/widgets/menus/tearoff_menu.h" -#include "../dialogs/dlg_create_token.h" +#include "../zones/logic/hand_zone_logic.h" +#include "../zones/logic/pile_zone_logic.h" +#include "../zones/logic/stack_zone_logic.h" +#include "../zones/logic/table_zone_logic.h" #include "menu/player_menu.h" -#include "player_actions.h" #include "player_area.h" #include "player_event_handler.h" #include "player_graphics_item.h" @@ -20,9 +22,7 @@ #include #include #include -#include #include -#include #include #include #include diff --git a/cockatrice/src/game/player/player_actions.cpp b/cockatrice/src/game/player/player_actions.cpp index e6efaf854..058fdb510 100644 --- a/cockatrice/src/game/player/player_actions.cpp +++ b/cockatrice/src/game/player/player_actions.cpp @@ -5,14 +5,15 @@ #include "../board/card_item.h" #include "../dialogs/dlg_move_top_cards_until.h" #include "../dialogs/dlg_roll_dice.h" +#include "../zones/hand_zone.h" #include "../zones/logic/view_zone_logic.h" +#include "../zones/table_zone.h" #include "card_menu_action_type.h" #include #include #include #include -#include #include #include #include diff --git a/cockatrice/src/game/player/player_actions.h b/cockatrice/src/game/player/player_actions.h index 9c775691c..e0f86e4fc 100644 --- a/cockatrice/src/game/player/player_actions.h +++ b/cockatrice/src/game/player/player_actions.h @@ -7,6 +7,7 @@ #ifndef COCKATRICE_PLAYER_ACTIONS_H #define COCKATRICE_PLAYER_ACTIONS_H +#include "../dialogs/dlg_create_token.h" #include "event_processing_options.h" #include "player.h" diff --git a/cockatrice/src/game/player/player_event_handler.cpp b/cockatrice/src/game/player/player_event_handler.cpp index 972229489..4cf814d86 100644 --- a/cockatrice/src/game/player/player_event_handler.cpp +++ b/cockatrice/src/game/player/player_event_handler.cpp @@ -6,6 +6,7 @@ #include "../board/card_list.h" #include "../zones/view_zone.h" #include "player.h" +#include "player_actions.h" #include #include diff --git a/cockatrice/src/game/player/player_graphics_item.cpp b/cockatrice/src/game/player/player_graphics_item.cpp index 27fbc82c8..30648c926 100644 --- a/cockatrice/src/game/player/player_graphics_item.cpp +++ b/cockatrice/src/game/player/player_graphics_item.cpp @@ -1,7 +1,12 @@ #include "player_graphics_item.h" #include "../../interface/widgets/tabs/tab_game.h" +#include "../board/abstract_card_item.h" #include "../hand_counter.h" +#include "../zones/hand_zone.h" +#include "../zones/pile_zone.h" +#include "../zones/stack_zone.h" +#include "../zones/table_zone.h" PlayerGraphicsItem::PlayerGraphicsItem(Player *_player) : player(_player) { diff --git a/cockatrice/src/game/player/player_info.h b/cockatrice/src/game/player/player_info.h index d60c245e2..2e9b49d6d 100644 --- a/cockatrice/src/game/player/player_info.h +++ b/cockatrice/src/game/player/player_info.h @@ -7,11 +7,6 @@ #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" -#include "../zones/table_zone.h" #include "player_target.h" #include diff --git a/cockatrice/src/game/player/player_list_widget.cpp b/cockatrice/src/game/player/player_list_widget.cpp index 7cf7c34a6..9506e0729 100644 --- a/cockatrice/src/game/player/player_list_widget.cpp +++ b/cockatrice/src/game/player/player_list_widget.cpp @@ -4,15 +4,11 @@ #include "../../interface/widgets/server/user/user_context_menu.h" #include "../../interface/widgets/server/user/user_list_manager.h" #include "../../interface/widgets/server/user/user_list_widget.h" -#include "../../interface/widgets/tabs/tab_account.h" #include "../../interface/widgets/tabs/tab_game.h" #include "../../interface/widgets/tabs/tab_supervisor.h" -#include #include -#include #include -#include #include #include #include diff --git a/cockatrice/src/game/player/player_target.h b/cockatrice/src/game/player/player_target.h index aaa0f0610..b60464e12 100644 --- a/cockatrice/src/game/player/player_target.h +++ b/cockatrice/src/game/player/player_target.h @@ -11,7 +11,6 @@ #include "../board/abstract_counter.h" #include "../board/arrow_target.h" -#include #include class Player; diff --git a/cockatrice/src/game/zones/hand_zone.cpp b/cockatrice/src/game/zones/hand_zone.cpp index 860881f38..cc3b44910 100644 --- a/cockatrice/src/game/zones/hand_zone.cpp +++ b/cockatrice/src/game/zones/hand_zone.cpp @@ -5,6 +5,7 @@ #include "../board/card_drag_item.h" #include "../board/card_item.h" #include "../player/player.h" +#include "../player/player_actions.h" #include #include diff --git a/cockatrice/src/game/zones/logic/card_zone_logic.cpp b/cockatrice/src/game/zones/logic/card_zone_logic.cpp index a5dc64b50..bd32eab3e 100644 --- a/cockatrice/src/game/zones/logic/card_zone_logic.cpp +++ b/cockatrice/src/game/zones/logic/card_zone_logic.cpp @@ -2,7 +2,7 @@ #include "../../board/card_item.h" #include "../../player/player.h" -#include "../pile_zone.h" +#include "../../player/player_actions.h" #include "../view_zone.h" #include "view_zone_logic.h" @@ -10,7 +10,6 @@ #include #include #include -#include /** * @param _player the player that the zone belongs to diff --git a/cockatrice/src/game/zones/pile_zone.cpp b/cockatrice/src/game/zones/pile_zone.cpp index cafb29038..2d1390826 100644 --- a/cockatrice/src/game/zones/pile_zone.cpp +++ b/cockatrice/src/game/zones/pile_zone.cpp @@ -3,6 +3,7 @@ #include "../board/card_drag_item.h" #include "../board/card_item.h" #include "../player/player.h" +#include "../player/player_actions.h" #include "logic/pile_zone_logic.h" #include "view_zone.h" diff --git a/cockatrice/src/game/zones/stack_zone.cpp b/cockatrice/src/game/zones/stack_zone.cpp index 0c0501705..820008b27 100644 --- a/cockatrice/src/game/zones/stack_zone.cpp +++ b/cockatrice/src/game/zones/stack_zone.cpp @@ -6,10 +6,10 @@ #include "../board/card_drag_item.h" #include "../board/card_item.h" #include "../player/player.h" +#include "../player/player_actions.h" #include "logic/stack_zone_logic.h" #include -#include #include StackZone::StackZone(StackZoneLogic *_logic, int _zoneHeight, QGraphicsItem *parent) diff --git a/cockatrice/src/game/zones/table_zone.cpp b/cockatrice/src/game/zones/table_zone.cpp index 55aaeaa39..c76514350 100644 --- a/cockatrice/src/game/zones/table_zone.cpp +++ b/cockatrice/src/game/zones/table_zone.cpp @@ -6,11 +6,11 @@ #include "../board/card_drag_item.h" #include "../board/card_item.h" #include "../player/player.h" +#include "../player/player_actions.h" #include "logic/table_zone_logic.h" #include #include -#include #include #include #include diff --git a/cockatrice/src/game/zones/view_zone.cpp b/cockatrice/src/game/zones/view_zone.cpp index d5eea9dfe..4ae25989e 100644 --- a/cockatrice/src/game/zones/view_zone.cpp +++ b/cockatrice/src/game/zones/view_zone.cpp @@ -3,6 +3,7 @@ #include "../board/card_drag_item.h" #include "../board/card_item.h" #include "../player/player.h" +#include "../player/player_actions.h" #include "logic/view_zone_logic.h" #include @@ -10,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/cockatrice/src/game/zones/view_zone_widget.cpp b/cockatrice/src/game/zones/view_zone_widget.cpp index e2f242883..91abb4663 100644 --- a/cockatrice/src/game/zones/view_zone_widget.cpp +++ b/cockatrice/src/game/zones/view_zone_widget.cpp @@ -6,6 +6,7 @@ #include "../board/card_item.h" #include "../game_scene.h" #include "../player/player.h" +#include "../player/player_actions.h" #include "view_zone.h" #include @@ -16,7 +17,6 @@ #include #include #include -#include #include /** 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 296355940..06a0476c9 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader.cpp +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader.h b/cockatrice/src/interface/card_picture_loader/card_picture_loader.h index 29bdf26c8..4000fd99a 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader.h +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader.h @@ -5,7 +5,6 @@ #include "card_picture_loader_worker.h" #include -#include inline Q_LOGGING_CATEGORY(CardPictureLoaderLog, "card_picture_loader"); inline Q_LOGGING_CATEGORY(CardPictureLoaderCardBackCacheFailLog, "card_picture_loader.card_back_cache_fail"); diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.h b/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.h index 25692f318..44163d1db 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.h +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.h @@ -1,8 +1,6 @@ #ifndef PICTURE_LOADER_LOCAL_H #define PICTURE_LOADER_LOCAL_H -#include -#include #include #include diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader_request_status_display_widget.h b/cockatrice/src/interface/card_picture_loader/card_picture_loader_request_status_display_widget.h index 2e3233c2d..c9a272b68 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader_request_status_display_widget.h +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader_request_status_display_widget.h @@ -1,11 +1,11 @@ #ifndef PICTURE_LOADER_REQUEST_STATUS_DISPLAY_WIDGET_H #define PICTURE_LOADER_REQUEST_STATUS_DISPLAY_WIDGET_H -#include "card_picture_loader_worker_work.h" - #include #include +#include #include +#include /** * @class CardPictureLoaderRequestStatusDisplayWidget diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader_status_bar.h b/cockatrice/src/interface/card_picture_loader/card_picture_loader_status_bar.h index cb469269c..7f1f509db 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader_status_bar.h +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader_status_bar.h @@ -6,7 +6,6 @@ #include #include -#include #include /** 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 a2da3c953..30c979cb5 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 @@ -9,7 +9,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 e74103419..d5aac645e 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 @@ -7,11 +7,9 @@ #include #include #include -#include #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.h b/cockatrice/src/interface/card_picture_loader/card_picture_to_load.h index b0a555c86..b57e57644 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_to_load.h +++ b/cockatrice/src/interface/card_picture_loader/card_picture_to_load.h @@ -1,7 +1,6 @@ #ifndef PICTURE_TO_LOAD_H #define PICTURE_TO_LOAD_H -#include #include inline Q_LOGGING_CATEGORY(CardPictureToLoadLog, "card_picture_loader.picture_to_load"); 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 20f4b29df..e8beae61e 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 @@ -5,7 +5,6 @@ #include #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/cards/additional_info/mana_cost_widget.cpp b/cockatrice/src/interface/widgets/cards/additional_info/mana_cost_widget.cpp index e5d1127aa..fcbb69c2e 100644 --- a/cockatrice/src/interface/widgets/cards/additional_info/mana_cost_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/additional_info/mana_cost_widget.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include #include 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 7734a61d0..75e075de6 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 @@ -3,7 +3,6 @@ #include "../card_info_picture_with_text_overlay_widget.h" #include -#include #include #include #include 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 4d911edde..73c43abbc 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 @@ -15,7 +15,6 @@ #include #include #include -#include #include class CardGroupDisplayWidget : public QWidget diff --git a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/flat_card_group_display_widget.cpp b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/flat_card_group_display_widget.cpp index 5f3a2c2c0..e52242c7b 100644 --- a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/flat_card_group_display_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/flat_card_group_display_widget.cpp @@ -1,9 +1,6 @@ #include "flat_card_group_display_widget.h" -#include "../card_info_picture_with_text_overlay_widget.h" - #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/cards/card_info_display_widget.cpp b/cockatrice/src/interface/widgets/cards/card_info_display_widget.cpp index c08e0ed3c..b13a085bd 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_display_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_display_widget.cpp @@ -1,7 +1,6 @@ #include "card_info_display_widget.h" #include "../../../game/board/card_item.h" -#include "../../../main.h" #include "card_info_picture_widget.h" #include "card_info_text_widget.h" @@ -9,7 +8,6 @@ #include #include #include -#include CardInfoDisplayWidget::CardInfoDisplayWidget(const CardRef &cardRef, QWidget *parent, Qt::WindowFlags flags) : QFrame(parent, flags), aspectRatio((qreal)CARD_HEIGHT / (qreal)CARD_WIDTH) 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 9fea41076..829292b53 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_frame_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_frame_widget.cpp @@ -10,7 +10,6 @@ #include #include #include -#include CardInfoFrameWidget::CardInfoFrameWidget(QWidget *parent) : QTabWidget(parent), viewTransformationButton(nullptr), cardTextOnly(false) 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 9a79bd32f..1024315a1 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 @@ -5,7 +5,6 @@ #include #include -#include /** * @brief Constructs a CardPictureEnlargedWidget. diff --git a/cockatrice/src/interface/widgets/cards/card_info_picture_enlarged_widget.h b/cockatrice/src/interface/widgets/cards/card_info_picture_enlarged_widget.h index ec1de166b..10eb32940 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_picture_enlarged_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_info_picture_enlarged_widget.h @@ -8,7 +8,6 @@ #ifndef CARD_PICTURE_ENLARGED_WIDGET_H #define CARD_PICTURE_ENLARGED_WIDGET_H -#include #include #include diff --git a/cockatrice/src/interface/widgets/cards/card_info_picture_widget.h b/cockatrice/src/interface/widgets/cards/card_info_picture_widget.h index b628e6982..980d700f6 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_picture_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_info_picture_widget.h @@ -10,7 +10,6 @@ #include "card_info_picture_enlarged_widget.h" #include -#include #include #include diff --git a/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.cpp b/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.cpp index 4cb61deab..2f0aeccfd 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.cpp @@ -3,7 +3,6 @@ #include #include #include -#include /** * @brief Constructs a CardPictureWithTextOverlay widget. diff --git a/cockatrice/src/interface/widgets/cards/card_info_text_widget.cpp b/cockatrice/src/interface/widgets/cards/card_info_text_widget.cpp index f11be533a..775f6fb9e 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_text_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_text_widget.cpp @@ -6,7 +6,6 @@ #include #include #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 927d9bf5f..14e45743d 100644 --- a/cockatrice/src/interface/widgets/cards/card_size_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_size_widget.cpp @@ -1,6 +1,5 @@ #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" 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 5529c35b6..618d7e565 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 @@ -4,7 +4,6 @@ #include "card_group_display_widgets/overlapped_card_group_display_widget.h" #include -#include #include DeckCardZoneDisplayWidget::DeckCardZoneDisplayWidget(QWidget *parent, 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 ac53cb704..d5603017c 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 @@ -16,7 +16,6 @@ #include #include -#include #include class DeckCardZoneDisplayWidget : public QWidget 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 8f4e1a115..486b3302d 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 @@ -8,7 +8,6 @@ #include #include #include -#include /** * @brief Constructs a CardPictureWithTextOverlay widget. diff --git a/cockatrice/src/interface/widgets/cards/deck_preview_card_picture_widget.h b/cockatrice/src/interface/widgets/cards/deck_preview_card_picture_widget.h index c4339da22..acb67a49a 100644 --- a/cockatrice/src/interface/widgets/cards/deck_preview_card_picture_widget.h +++ b/cockatrice/src/interface/widgets/cards/deck_preview_card_picture_widget.h @@ -13,6 +13,7 @@ #include #include #include +#include class DeckPreviewCardPictureWidget final : public CardInfoPictureWithTextOverlayWidget { diff --git a/cockatrice/src/interface/widgets/deck_analytics/deck_analytics_widget.h b/cockatrice/src/interface/widgets/deck_analytics/deck_analytics_widget.h index 29dc9c33c..e2f00bf0d 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/deck_analytics_widget.h +++ b/cockatrice/src/interface/widgets/deck_analytics/deck_analytics_widget.h @@ -7,16 +7,13 @@ #ifndef DECK_ANALYTICS_WIDGET_H #define DECK_ANALYTICS_WIDGET_H -#include "../general/layout_containers/flow_widget.h" #include "mana_base_widget.h" #include "mana_curve_widget.h" #include "mana_devotion_widget.h" #include #include -#include #include -#include #include class DeckAnalyticsWidget : public QWidget 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 3cafdaeab..63e4255b5 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/mana_devotion_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/mana_devotion_widget.cpp @@ -1,16 +1,13 @@ #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" -#include #include #include #include #include -#include #include ManaDevotionWidget::ManaDevotionWidget(QWidget *parent, DeckListModel *_deckListModel) 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 b5aa007f0..b4b27e48a 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 @@ -7,10 +7,8 @@ #include "../../pixel_map_generator.h" #include -#include #include #include -#include #include #include #include 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 0c89d51f5..852ce7164 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 @@ -15,7 +15,6 @@ #include "deck_list_history_manager_widget.h" #include "deck_list_style_proxy.h" -#include #include #include #include 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 4957e24ec..5790131c5 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 @@ -7,7 +7,6 @@ #include #include #include -#include DeckEditorFilterDockWidget::DeckEditorFilterDockWidget(AbstractTabDeckEditor *parent) : QDockWidget(parent), deckEditor(parent) diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.h b/cockatrice/src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.h index de135460f..b61fc72b5 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.h +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.h @@ -12,7 +12,6 @@ #include "../../key_signals.h" #include -#include class FilterTreeModel; class AbstractTabDeckEditor; diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_list_history_manager_widget.h b/cockatrice/src/interface/widgets/deck_editor/deck_list_history_manager_widget.h index 23619b91b..0e208ad2b 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_list_history_manager_widget.h +++ b/cockatrice/src/interface/widgets/deck_editor/deck_list_history_manager_widget.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_connect.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_connect.cpp index ed32b356c..0bb0eb1c9 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_connect.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_connect.cpp @@ -4,9 +4,7 @@ #include #include -#include #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_create_game.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_create_game.cpp index 629b23787..55b999ee9 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_create_game.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_create_game.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include 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 5b120b1e2..349f4ca4c 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_default_tags_editor.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_default_tags_editor.cpp @@ -3,6 +3,7 @@ #include "../../../client/settings/cache_settings.h" #include +#include #include DlgDefaultTagsEditor::DlgDefaultTagsEditor(QWidget *parent) : QDialog(parent) diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_default_tags_editor.h b/cockatrice/src/interface/widgets/dialogs/dlg_default_tags_editor.h index b552ae737..27af74105 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_default_tags_editor.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_default_tags_editor.h @@ -11,7 +11,6 @@ #include #include #include -#include #include class DlgDefaultTagsEditor : public QDialog diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_edit_avatar.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_edit_avatar.cpp index 7330c749b..db5f21701 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_edit_avatar.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_edit_avatar.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_edit_password.h b/cockatrice/src/interface/widgets/dialogs/dlg_edit_password.h index 311774d11..ee8e45985 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_edit_password.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_edit_password.h @@ -7,7 +7,6 @@ #ifndef DLG_EDITPASSWORD_H #define DLG_EDITPASSWORD_H -#include #include #include diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_edit_tokens.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_edit_tokens.cpp index a47a8221a..fe9cd181c 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_edit_tokens.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_edit_tokens.cpp @@ -1,7 +1,6 @@ #include "dlg_edit_tokens.h" #include "../interface/widgets/utility/get_text_with_max.h" -#include "../main.h" #include #include @@ -16,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_edit_user.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_edit_user.cpp index c39c87d4a..dcfbc91e9 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_edit_user.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_edit_user.cpp @@ -2,7 +2,6 @@ #include "../../../client/settings/cache_settings.h" -#include #include #include #include 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 7ad957e6c..24e9030e0 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_challenge.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_challenge.cpp @@ -2,8 +2,6 @@ #include "../../../client/settings/cache_settings.h" -#include -#include #include #include #include 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 8f79b543f..c33a41bed 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_request.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_request.cpp @@ -2,8 +2,6 @@ #include "../../../client/settings/cache_settings.h" -#include -#include #include #include #include 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 f08347879..e0d855d7e 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_reset.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_reset.cpp @@ -2,8 +2,6 @@ #include "../../../client/settings/cache_settings.h" -#include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_load_remote_deck.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_load_remote_deck.cpp index 214ccc588..ffe08bec9 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_load_remote_deck.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_load_remote_deck.cpp @@ -1,10 +1,8 @@ #include "dlg_load_remote_deck.h" #include "../interface/widgets/server/remote/remote_decklist_tree_widget.h" -#include "../main.h" #include -#include #include #include diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_manage_sets.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_manage_sets.cpp index 2d3bc08a4..2cda51f2a 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_manage_sets.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_manage_sets.cpp @@ -3,11 +3,9 @@ #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" #include #include -#include #include #include #include @@ -15,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_manage_sets.h b/cockatrice/src/interface/widgets/dialogs/dlg_manage_sets.h index c3a3c2455..d7341caff 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_manage_sets.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_manage_sets.h @@ -11,7 +11,6 @@ #include #include #include -#include class CardDatabase; class LineEditUnfocusable; diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_register.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_register.cpp index 3493c1047..4be4cdf78 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_register.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_register.cpp @@ -3,13 +3,11 @@ #include "../../../client/settings/cache_settings.h" #include -#include #include #include #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 121ce4c86..893c84512 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 @@ -3,7 +3,6 @@ #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" #include #include @@ -14,6 +13,7 @@ #include #include #include +#include #include #include #include diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp index e92593d55..c0b80c6c1 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include 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 0197d3dbf..59330e27e 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 @@ -7,7 +7,6 @@ #include #include #include -#include #include #include diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_tip_of_the_day.h b/cockatrice/src/interface/widgets/dialogs/dlg_tip_of_the_day.h index 46598fb02..3dad7c652 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_tip_of_the_day.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_tip_of_the_day.h @@ -10,10 +10,8 @@ #include #include #include -#include #include #include -#include #include inline Q_LOGGING_CATEGORY(DlgTipOfTheDayLog, "dlg_tip_of_the_day"); diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp index 19182c55b..0a9244dec 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp @@ -5,12 +5,10 @@ #include "../client/network/update/client/release_channel.h" #include "../interface/window_main.h" -#include #include #include #include #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/general/display/bar_widget.h b/cockatrice/src/interface/widgets/general/display/bar_widget.h index 672f5b7ac..67ad24995 100644 --- a/cockatrice/src/interface/widgets/general/display/bar_widget.h +++ b/cockatrice/src/interface/widgets/general/display/bar_widget.h @@ -8,8 +8,6 @@ #ifndef BAR_WIDGET_H #define BAR_WIDGET_H -#include -#include #include class BarWidget : public QWidget diff --git a/cockatrice/src/interface/widgets/general/display/dynamic_font_size_label.cpp b/cockatrice/src/interface/widgets/general/display/dynamic_font_size_label.cpp index ed4db1fd3..f485e0040 100644 --- a/cockatrice/src/interface/widgets/general/display/dynamic_font_size_label.cpp +++ b/cockatrice/src/interface/widgets/general/display/dynamic_font_size_label.cpp @@ -1,7 +1,6 @@ #include "dynamic_font_size_label.h" #define FONT_PRECISION (0.5) -#include #include DynamicFontSizeLabel::DynamicFontSizeLabel(QWidget *parent, Qt::WindowFlags f) : QLabel(parent, f) diff --git a/cockatrice/src/interface/widgets/general/display/dynamic_font_size_push_button.cpp b/cockatrice/src/interface/widgets/general/display/dynamic_font_size_push_button.cpp index fce4512e8..653b2cd5c 100644 --- a/cockatrice/src/interface/widgets/general/display/dynamic_font_size_push_button.cpp +++ b/cockatrice/src/interface/widgets/general/display/dynamic_font_size_push_button.cpp @@ -2,7 +2,6 @@ #include "dynamic_font_size_label.h" -#include #include DynamicFontSizePushButton::DynamicFontSizePushButton(QWidget *parent) : QPushButton(parent) diff --git a/cockatrice/src/interface/widgets/general/display/percent_bar_widget.h b/cockatrice/src/interface/widgets/general/display/percent_bar_widget.h index 9ebdb172a..ff7d91363 100644 --- a/cockatrice/src/interface/widgets/general/display/percent_bar_widget.h +++ b/cockatrice/src/interface/widgets/general/display/percent_bar_widget.h @@ -8,7 +8,6 @@ #ifndef PERCENT_BAR_WIDGET_H #define PERCENT_BAR_WIDGET_H -#include #include #include diff --git a/cockatrice/src/interface/widgets/general/home_widget.cpp b/cockatrice/src/interface/widgets/general/home_widget.cpp index cbf53ee4f..2dfd129d5 100644 --- a/cockatrice/src/interface/widgets/general/home_widget.cpp +++ b/cockatrice/src/interface/widgets/general/home_widget.cpp @@ -6,6 +6,7 @@ #include "background_sources.h" #include "home_styled_button.h" +#include #include #include #include diff --git a/cockatrice/src/interface/widgets/general/home_widget.h b/cockatrice/src/interface/widgets/general/home_widget.h index 23598cc5a..1db33446a 100644 --- a/cockatrice/src/interface/widgets/general/home_widget.h +++ b/cockatrice/src/interface/widgets/general/home_widget.h @@ -12,7 +12,6 @@ #include "home_styled_button.h" #include -#include #include #include diff --git a/cockatrice/src/interface/widgets/menus/deck_editor_menu.cpp b/cockatrice/src/interface/widgets/menus/deck_editor_menu.cpp index 775efafbd..23d19abbb 100644 --- a/cockatrice/src/interface/widgets/menus/deck_editor_menu.cpp +++ b/cockatrice/src/interface/widgets/menus/deck_editor_menu.cpp @@ -2,6 +2,7 @@ #include "../../../client/settings/cache_settings.h" #include "../../../client/settings/shortcuts_settings.h" +#include "../tabs/abstract_tab_deck_editor.h" DeckEditorMenu::DeckEditorMenu(AbstractTabDeckEditor *parent) : QMenu(parent), deckEditor(parent) { diff --git a/cockatrice/src/interface/widgets/menus/deck_editor_menu.h b/cockatrice/src/interface/widgets/menus/deck_editor_menu.h index b35f35864..ac8f3b787 100644 --- a/cockatrice/src/interface/widgets/menus/deck_editor_menu.h +++ b/cockatrice/src/interface/widgets/menus/deck_editor_menu.h @@ -7,8 +7,6 @@ #ifndef DECK_EDITOR_MENU_H #define DECK_EDITOR_MENU_H -#include "../interface/widgets/tabs/abstract_tab_deck_editor.h" - #include class AbstractTabDeckEditor; 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 bf8ade36a..1a8ec8bfd 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 @@ -10,7 +10,6 @@ #include "../../deck_loader/deck_loader.h" #include "card_amount_widget.h" -#include #include #include 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 543964a79..1da999c78 100644 --- a/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.h +++ b/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.h @@ -9,12 +9,10 @@ #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 #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector.cpp b/cockatrice/src/interface/widgets/printing_selector/printing_selector.cpp index a551ac290..f27101b93 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector.cpp +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector.cpp @@ -8,9 +8,8 @@ #include "printing_selector_card_selection_widget.h" #include "printing_selector_card_sorting_widget.h" -#include +#include #include -#include /** * @brief Constructs a PrintingSelector widget to display and manage card printings. diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector.h b/cockatrice/src/interface/widgets/printing_selector/printing_selector.h index 88a49f1e0..7130e436c 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector.h +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector.h @@ -13,7 +13,6 @@ #include #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_display_widget.cpp b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_display_widget.cpp index 0da80b522..24c45a7e3 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_display_widget.cpp +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_display_widget.cpp @@ -1,11 +1,9 @@ #include "printing_selector_card_display_widget.h" -#include "card_amount_widget.h" #include "printing_selector_card_overlay_widget.h" #include "set_name_and_collectors_number_display_widget.h" #include -#include #include #include diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_display_widget.h b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_display_widget.h index 931322117..2f6bd6920 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_display_widget.h +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_display_widget.h @@ -11,9 +11,7 @@ #include "printing_selector_card_overlay_widget.h" #include "set_name_and_collectors_number_display_widget.h" -#include #include -#include #include class PrintingSelectorCardDisplayWidget : public QWidget 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 f2351f509..10df9d53e 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 @@ -8,12 +8,9 @@ #define PRINTING_SELECTOR_CARD_OVERLAY_WIDGET_H #include "../../../interface/widgets/tabs/abstract_tab_deck_editor.h" -#include "../cards/card_info_picture_widget.h" #include "all_zones_card_amount_widget.h" -#include "card_amount_widget.h" #include "set_name_and_collectors_number_display_widget.h" -#include #include class PrintingSelectorCardOverlayWidget : public QWidget diff --git a/cockatrice/src/interface/widgets/replay/replay_timeline_widget.cpp b/cockatrice/src/interface/widgets/replay/replay_timeline_widget.cpp index fb5936cae..25ee58b67 100644 --- a/cockatrice/src/interface/widgets/replay/replay_timeline_widget.cpp +++ b/cockatrice/src/interface/widgets/replay/replay_timeline_widget.cpp @@ -4,7 +4,6 @@ #include #include -#include #include ReplayTimelineWidget::ReplayTimelineWidget(QWidget *parent) diff --git a/cockatrice/src/interface/widgets/replay/replay_timeline_widget.h b/cockatrice/src/interface/widgets/replay/replay_timeline_widget.h index 17a235365..07a0c0b4c 100644 --- a/cockatrice/src/interface/widgets/replay/replay_timeline_widget.h +++ b/cockatrice/src/interface/widgets/replay/replay_timeline_widget.h @@ -9,7 +9,6 @@ #include "../../../game/player/event_processing_options.h" -#include #include #include diff --git a/cockatrice/src/interface/widgets/server/game_selector.cpp b/cockatrice/src/interface/widgets/server/game_selector.cpp index f4366d8ab..48a12d5b3 100644 --- a/cockatrice/src/interface/widgets/server/game_selector.cpp +++ b/cockatrice/src/interface/widgets/server/game_selector.cpp @@ -10,17 +10,12 @@ #include "games_model.h" #include "user/user_list_manager.h" -#include -#include #include #include #include -#include -#include #include #include #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/server/game_selector_quick_filter_toolbar.cpp b/cockatrice/src/interface/widgets/server/game_selector_quick_filter_toolbar.cpp index c63b52450..daab4d6eb 100644 --- a/cockatrice/src/interface/widgets/server/game_selector_quick_filter_toolbar.cpp +++ b/cockatrice/src/interface/widgets/server/game_selector_quick_filter_toolbar.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include GameSelectorQuickFilterToolBar::GameSelectorQuickFilterToolBar(QWidget *parent, diff --git a/cockatrice/src/interface/widgets/server/game_selector_quick_filter_toolbar.h b/cockatrice/src/interface/widgets/server/game_selector_quick_filter_toolbar.h index f7e0c6fb1..642fdd1c4 100644 --- a/cockatrice/src/interface/widgets/server/game_selector_quick_filter_toolbar.h +++ b/cockatrice/src/interface/widgets/server/game_selector_quick_filter_toolbar.h @@ -4,10 +4,7 @@ #include "../tabs/tab_supervisor.h" #include "games_model.h" -#include -#include #include -#include #include #include diff --git a/cockatrice/src/interface/widgets/server/games_model.cpp b/cockatrice/src/interface/widgets/server/games_model.cpp index dfb41fd29..cdac71b28 100644 --- a/cockatrice/src/interface/widgets/server/games_model.cpp +++ b/cockatrice/src/interface/widgets/server/games_model.cpp @@ -7,10 +7,7 @@ #include "user/user_list_widget.h" #include -#include #include -#include -#include #include #include diff --git a/cockatrice/src/interface/widgets/server/games_model.h b/cockatrice/src/interface/widgets/server/games_model.h index 03602a74e..56c806fb6 100644 --- a/cockatrice/src/interface/widgets/server/games_model.h +++ b/cockatrice/src/interface/widgets/server/games_model.h @@ -3,11 +3,9 @@ #include "game_type_map.h" -#include #include #include #include -#include #include #include diff --git a/cockatrice/src/interface/widgets/server/handle_public_servers.cpp b/cockatrice/src/interface/widgets/server/handle_public_servers.cpp index 6a8754a79..f37c957a4 100644 --- a/cockatrice/src/interface/widgets/server/handle_public_servers.cpp +++ b/cockatrice/src/interface/widgets/server/handle_public_servers.cpp @@ -3,8 +3,6 @@ #include "../../../client/settings/cache_settings.h" #include -#include -#include #include #include diff --git a/cockatrice/src/interface/widgets/server/remote/remote_decklist_tree_widget.h b/cockatrice/src/interface/widgets/server/remote/remote_decklist_tree_widget.h index 6836ff435..8254eb57b 100644 --- a/cockatrice/src/interface/widgets/server/remote/remote_decklist_tree_widget.h +++ b/cockatrice/src/interface/widgets/server/remote/remote_decklist_tree_widget.h @@ -8,7 +8,6 @@ #ifndef REMOTEDECKLIST_TREEWIDGET_H #define REMOTEDECKLIST_TREEWIDGET_H -#include #include #include diff --git a/cockatrice/src/interface/widgets/server/remote/remote_replay_list_tree_widget.h b/cockatrice/src/interface/widgets/server/remote/remote_replay_list_tree_widget.h index f83cce46a..6d81aefca 100644 --- a/cockatrice/src/interface/widgets/server/remote/remote_replay_list_tree_widget.h +++ b/cockatrice/src/interface/widgets/server/remote/remote_replay_list_tree_widget.h @@ -9,7 +9,6 @@ #ifndef REMOTEREPLAYLIST_TREEWIDGET_H #define REMOTEREPLAYLIST_TREEWIDGET_H -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/server/user/user_context_menu.cpp b/cockatrice/src/interface/widgets/server/user/user_context_menu.cpp index cb7d2eca9..7083ac899 100644 --- a/cockatrice/src/interface/widgets/server/user/user_context_menu.cpp +++ b/cockatrice/src/interface/widgets/server/user/user_context_menu.cpp @@ -12,8 +12,6 @@ #include #include -#include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/server/user/user_list_widget.cpp b/cockatrice/src/interface/widgets/server/user/user_list_widget.cpp index b6d65c5fa..852743479 100644 --- a/cockatrice/src/interface/widgets/server/user/user_list_widget.cpp +++ b/cockatrice/src/interface/widgets/server/user/user_list_widget.cpp @@ -5,7 +5,6 @@ #include "../../interface/widgets/tabs/tab_supervisor.h" #include "../game_selector.h" #include "user_context_menu.h" -#include "user_list_manager.h" #include #include @@ -14,21 +13,15 @@ #include #include #include -#include #include #include #include #include #include #include -#include #include #include -#include #include -#include -#include -#include #include BanDialog::BanDialog(const ServerInfo_User &info, QWidget *parent) : QDialog(parent) 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 89611aa48..6d05e656d 100644 --- a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp +++ b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp @@ -14,7 +14,6 @@ #include "../client/network/interfaces/tapped_out_interface.h" #include "../interface/card_picture_loader/card_picture_loader.h" #include "../interface/pixel_map_generator.h" -#include "../interface/widgets/cards/card_info_frame_widget.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" @@ -22,15 +21,11 @@ #include #include -#include #include -#include #include -#include #include #include #include -#include #include #include #include @@ -38,7 +33,6 @@ #include #include #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/archidekt_links/edhrec_api_response_archidekt_links.cpp b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/archidekt_links/edhrec_api_response_archidekt_links.cpp index f071949f2..145a3fca0 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/archidekt_links/edhrec_api_response_archidekt_links.cpp +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/archidekt_links/edhrec_api_response_archidekt_links.cpp @@ -2,7 +2,6 @@ #include #include -#include #include void EdhrecApiResponseArchidektLink::fromJson(const QJsonObject &json) diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/archidekt_links/edhrec_api_response_archidekt_links.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/archidekt_links/edhrec_api_response_archidekt_links.h index 236e36305..d265c164d 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/archidekt_links/edhrec_api_response_archidekt_links.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/archidekt_links/edhrec_api_response_archidekt_links.h @@ -1,7 +1,6 @@ #ifndef ARCHIDEKTENTRY_H #define ARCHIDEKTENTRY_H -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_average_deck_api_response.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_average_deck_api_response.h index 1a60b95d0..70d37cbae 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_average_deck_api_response.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_average_deck_api_response.h @@ -6,7 +6,6 @@ #include "../commander/edhrec_commander_api_response_average_deck_statistics.h" #include "edhrec_deck_api_response.h" -#include #include #include 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 73c26050d..ceafb719b 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 @@ -6,7 +6,6 @@ #include #include #include -#include void EdhrecDeckApiResponse::fromJson(const QJsonArray &json) { 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 b362819df..96205e149 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 @@ -9,12 +9,6 @@ #include "../../../../../../deck_loader/deck_loader.h" -#include -#include -#include -#include -#include - class EdhrecDeckApiResponse { public: diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_container.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_container.h index df6c2eaeb..07b53dd97 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_container.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_container.h @@ -10,8 +10,6 @@ #include "edhrec_api_response_card_list.h" #include "edhrec_commander_api_response_commander_details.h" -#include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_list.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_list.h index 068945a30..15691fbe4 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_list.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_list.h @@ -10,7 +10,6 @@ #include "edhrec_api_response_card_details.h" #include -#include #include #include diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_commander_api_response_commander_details.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_commander_api_response_commander_details.h index 09d0667c7..629eb8273 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_commander_api_response_commander_details.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_commander_api_response_commander_details.h @@ -10,7 +10,6 @@ #include "../card_prices/edhrec_api_response_card_prices.h" #include -#include #include #include diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/commander/edhrec_commander_api_response.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/commander/edhrec_commander_api_response.h index 9e6629142..64f2fd7cd 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/commander/edhrec_commander_api_response.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/commander/edhrec_commander_api_response.h @@ -5,7 +5,6 @@ #include "../cards/edhrec_api_response_card_container.h" #include "edhrec_commander_api_response_average_deck_statistics.h" -#include #include #include diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_cards/edhrec_top_cards_api_response.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_cards/edhrec_top_cards_api_response.h index a9a6316e3..fb89c0b12 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_cards/edhrec_top_cards_api_response.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_cards/edhrec_top_cards_api_response.h @@ -9,7 +9,6 @@ #include "../cards/edhrec_api_response_card_container.h" -#include #include class EdhrecTopCardsApiResponse diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_commanders/edhrec_top_commanders_api_response.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_commanders/edhrec_top_commanders_api_response.h index 1e99e90f0..26c5afedb 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_commanders/edhrec_top_commanders_api_response.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_commanders/edhrec_top_commanders_api_response.h @@ -9,7 +9,6 @@ #include "../cards/edhrec_api_response_card_container.h" -#include #include class EdhrecTopCommandersApiResponse diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_tags/edhrec_top_tags_api_response.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_tags/edhrec_top_tags_api_response.h index 382e2899e..48219893a 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_tags/edhrec_top_tags_api_response.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_tags/edhrec_top_tags_api_response.h @@ -9,7 +9,6 @@ #include "../cards/edhrec_api_response_card_container.h" -#include #include class EdhrecTopTagsApiResponse diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/top_tags/edhrec_top_tags_api_response_display_widget.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/top_tags/edhrec_top_tags_api_response_display_widget.h index 84b401eb7..64228b85d 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/top_tags/edhrec_top_tags_api_response_display_widget.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/top_tags/edhrec_top_tags_api_response_display_widget.h @@ -9,7 +9,6 @@ #include "../../api_response/top_tags/edhrec_top_tags_api_response.h" -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec.cpp b/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec.cpp index 4c740e5d1..93dbd6bc5 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec.cpp +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec.cpp @@ -4,7 +4,6 @@ #include "display/commander/edhrec_commander_api_response_display_widget.h" #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.cpp b/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.cpp index 0dcd5d0ae..06ce88f06 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.cpp +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.h index 3d4c2fa00..04cf03fc1 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.h @@ -8,7 +8,6 @@ #define TAB_EDHREC_MAIN_H #include "../../interface/widgets/cards/card_size_widget.h" -#include "../../interface/widgets/general/layout_containers/flow_widget.h" #include "../../interface/widgets/quick_settings/settings_button_widget.h" #include "../../tab.h" #include "display/commander/edhrec_commander_api_response_display_widget.h" diff --git a/cockatrice/src/interface/widgets/tabs/tab_deck_editor.cpp b/cockatrice/src/interface/widgets/tabs/tab_deck_editor.cpp index 88f08eae1..4fa12259c 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_deck_editor.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_deck_editor.cpp @@ -1,39 +1,22 @@ #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" #include "../interface/pixel_map_generator.h" #include "../interface/widgets/cards/card_info_frame_widget.h" #include "../interface/widgets/deck_editor/deck_editor_filter_dock_widget.h" -#include "../interface/widgets/dialogs/dlg_load_deck.h" -#include "../interface/widgets/dialogs/dlg_load_deck_from_clipboard.h" #include "../interface/widgets/menus/deck_editor_menu.h" #include "tab_supervisor.h" #include -#include #include -#include #include #include #include -#include #include -#include -#include #include -#include -#include #include -#include -#include #include -#include -#include -#include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/tabs/tab_deck_storage.cpp b/cockatrice/src/interface/widgets/tabs/tab_deck_storage.cpp index b483f0616..854990e19 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_deck_storage.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_deck_storage.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/tabs/tab_game.cpp b/cockatrice/src/interface/widgets/tabs/tab_game.cpp index 8f187575c..2f83ba2e6 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_game.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_game.cpp @@ -13,11 +13,9 @@ #include "../game/player/player.h" #include "../game/player/player_list_widget.h" #include "../game/replay.h" -#include "../game/zones/card_zone.h" #include "../interface/card_picture_loader/card_picture_loader.h" #include "../interface/widgets/cards/card_info_frame_widget.h" #include "../interface/widgets/dialogs/dlg_create_game.h" -#include "../interface/widgets/replay/replay_timeline_widget.h" #include "../interface/widgets/server/user/user_list_manager.h" #include "../interface/widgets/utility/line_edit_completer.h" #include "../interface/window_main.h" @@ -28,15 +26,12 @@ #include #include #include -#include #include #include #include #include -#include #include #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/tabs/tab_game.h b/cockatrice/src/interface/widgets/tabs/tab_game.h index e500fefbd..b6fe5b51c 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_game.h +++ b/cockatrice/src/interface/widgets/tabs/tab_game.h @@ -14,13 +14,11 @@ #include "../game/player/player.h" #include "../interface/widgets/menus/tearoff_menu.h" #include "../interface/widgets/replay/replay_manager.h" -#include "../interface/widgets/visual_deck_storage/visual_deck_storage_widget.h" #include "tab.h" #include #include #include -#include class ServerInfo_PlayerProperties; class TabbedDeckViewContainer; diff --git a/cockatrice/src/interface/widgets/tabs/tab_home.cpp b/cockatrice/src/interface/widgets/tabs/tab_home.cpp index a44945315..7a79b1785 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_home.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_home.cpp @@ -1,8 +1,5 @@ #include "tab_home.h" -#include -#include - TabHome::TabHome(TabSupervisor *_tabSupervisor, AbstractClient *_client) : Tab(_tabSupervisor), client(_client) { homeWidget = new HomeWidget(this, tabSupervisor); diff --git a/cockatrice/src/interface/widgets/tabs/tab_home.h b/cockatrice/src/interface/widgets/tabs/tab_home.h index fbadc99aa..c40dfc269 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_home.h +++ b/cockatrice/src/interface/widgets/tabs/tab_home.h @@ -10,9 +10,7 @@ #include "../interface/widgets/general/home_widget.h" #include "tab.h" -#include #include -#include class AbstractClient; diff --git a/cockatrice/src/interface/widgets/tabs/tab_logs.cpp b/cockatrice/src/interface/widgets/tabs/tab_logs.cpp index 86e10b755..e4f699160 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_logs.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_logs.cpp @@ -1,20 +1,18 @@ #include "tab_logs.h" -#include "../interface/widgets/dialogs/dlg_manage_sets.h" #include "../interface/widgets/utility/custom_line_edit.h" #include -#include +#include +#include #include -#include #include #include #include #include #include #include -#include -#include +#include #include #include #include diff --git a/cockatrice/src/interface/widgets/tabs/tab_logs.h b/cockatrice/src/interface/widgets/tabs/tab_logs.h index 7cbf6aedc..a73af651b 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_logs.h +++ b/cockatrice/src/interface/widgets/tabs/tab_logs.h @@ -13,7 +13,6 @@ class AbstractClient; class LineEditUnfocusable; - class QGroupBox; class QPushButton; class QSpinBox; diff --git a/cockatrice/src/interface/widgets/tabs/tab_replays.cpp b/cockatrice/src/interface/widgets/tabs/tab_replays.cpp index 8d7081407..2db9e83c5 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_replays.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_replays.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/tabs/tab_room.h b/cockatrice/src/interface/widgets/tabs/tab_room.h index c5d0a950a..67d9afc86 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_room.h +++ b/cockatrice/src/interface/widgets/tabs/tab_room.h @@ -13,7 +13,6 @@ #include #include -#include #include class UserListProxy; diff --git a/cockatrice/src/interface/widgets/tabs/tab_server.cpp b/cockatrice/src/interface/widgets/tabs/tab_server.cpp index bd4fa2be3..aa52b4b1a 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_server.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_server.cpp @@ -3,17 +3,12 @@ #include "../interface/widgets/server/user/user_list_widget.h" #include "tab_supervisor.h" -#include -#include #include #include #include -#include #include #include #include -#include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp b/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp index 902b1f589..18a98f5ec 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/tabs/tab_supervisor.h b/cockatrice/src/interface/widgets/tabs/tab_supervisor.h index 7a3b9cbb9..9fd00f584 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_supervisor.h +++ b/cockatrice/src/interface/widgets/tabs/tab_supervisor.h @@ -15,11 +15,9 @@ #include "api/edhrec/tab_edhrec_main.h" #include "tab_visual_database_display.h" #include "visual_deck_editor/tab_deck_editor_visual.h" -#include "visual_deck_editor/tab_deck_editor_visual_tab_widget.h" #include "visual_deck_storage/tab_deck_storage_visual.h" #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.h b/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.h index b01f3ab06..66f38fb3d 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.h +++ b/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.h @@ -10,8 +10,6 @@ #include "../interface/widgets/visual_database_display/visual_database_display_widget.h" #include "tab.h" -#include - class TabVisualDatabaseDisplay : public Tab { Q_OBJECT 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 7a811fd28..1540df0bf 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,7 +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" #include "../../interface/widgets/cards/card_info_frame_widget.h" @@ -12,27 +11,22 @@ #include "tab_deck_editor_visual_tab_widget.h" #include -#include #include #include #include #include -#include #include #include #include -#include #include #include #include #include #include #include -#include #include #include #include -#include /** * @brief Constructs the TabDeckEditorVisual instance. 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 bfb498909..975c011dc 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 @@ -1,12 +1,9 @@ #include "tab_deck_storage_visual.h" -#include "../../interface/widgets/cards/deck_preview_card_picture_widget.h" #include "../../interface/widgets/visual_deck_storage/visual_deck_storage_widget.h" #include "../tab_supervisor.h" #include -#include -#include #include TabDeckStorageVisual::TabDeckStorageVisual(TabSupervisor *_tabSupervisor) diff --git a/cockatrice/src/interface/widgets/utility/get_text_with_max.cpp b/cockatrice/src/interface/widgets/utility/get_text_with_max.cpp index 73745be02..134352eb3 100644 --- a/cockatrice/src/interface/widgets/utility/get_text_with_max.cpp +++ b/cockatrice/src/interface/widgets/utility/get_text_with_max.cpp @@ -1,5 +1,7 @@ #include "get_text_with_max.h" +#include + QString getTextWithMax(QWidget *parent, const QString &title, const QString &label, diff --git a/cockatrice/src/interface/widgets/utility/get_text_with_max.h b/cockatrice/src/interface/widgets/utility/get_text_with_max.h index 894eb80f2..923d6f427 100644 --- a/cockatrice/src/interface/widgets/utility/get_text_with_max.h +++ b/cockatrice/src/interface/widgets/utility/get_text_with_max.h @@ -7,7 +7,8 @@ #ifndef GETTEXTWITHMAX_H #define GETTEXTWITHMAX_H -#include +#include +#include #include QString getTextWithMax(QWidget *parent, diff --git a/cockatrice/src/interface/widgets/utility/line_edit_completer.cpp b/cockatrice/src/interface/widgets/utility/line_edit_completer.cpp index 7820ad91b..389e69d57 100644 --- a/cockatrice/src/interface/widgets/utility/line_edit_completer.cpp +++ b/cockatrice/src/interface/widgets/utility/line_edit_completer.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/utility/line_edit_completer.h b/cockatrice/src/interface/widgets/utility/line_edit_completer.h index 23e4d4aba..7b3756e3c 100644 --- a/cockatrice/src/interface/widgets/utility/line_edit_completer.h +++ b/cockatrice/src/interface/widgets/utility/line_edit_completer.h @@ -9,9 +9,7 @@ #include "custom_line_edit.h" -#include #include -#include class LineEditCompleter : public LineEditUnfocusable { diff --git a/cockatrice/src/interface/widgets/utility/sequence_edit.cpp b/cockatrice/src/interface/widgets/utility/sequence_edit.cpp index 7e14d4335..a34f39042 100644 --- a/cockatrice/src/interface/widgets/utility/sequence_edit.cpp +++ b/cockatrice/src/interface/widgets/utility/sequence_edit.cpp @@ -5,7 +5,6 @@ #include #include #include -#include SequenceEdit::SequenceEdit(const QString &_shortcutName, QWidget *parent) : QWidget(parent) { diff --git a/cockatrice/src/interface/widgets/utility/sequence_edit.h b/cockatrice/src/interface/widgets/utility/sequence_edit.h index a146aa752..a5fe1a1c6 100644 --- a/cockatrice/src/interface/widgets/utility/sequence_edit.h +++ b/cockatrice/src/interface/widgets/utility/sequence_edit.h @@ -8,7 +8,6 @@ #define SEQUENCEEDIT_H #include -#include #include #include #include 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 d4947d6c5..3ca709071 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 @@ -2,7 +2,6 @@ #include "../cards/additional_info/mana_symbol_widget.h" -#include #include #include 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 062774969..4d8eb5c57 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 @@ -5,8 +5,7 @@ #include #include -#include -#include +#include #include VisualDatabaseDisplayFilterSaveLoadWidget::VisualDatabaseDisplayFilterSaveLoadWidget(QWidget *parent, diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.h index 7dea3fd01..48e6f9498 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.h @@ -10,10 +10,8 @@ #include "../../../filters/filter_tree_model.h" #include "../general/layout_containers/flow_widget.h" -#include #include #include -#include #include #include #include diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_main_type_filter_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_main_type_filter_widget.h index 34c6ddac2..27c61dffc 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_main_type_filter_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_main_type_filter_widget.h @@ -13,7 +13,6 @@ #include #include #include -#include #include #include diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.h index b98d83523..76d3ec29e 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.h @@ -14,7 +14,6 @@ #include #include #include -#include #include class VisualDatabaseDisplayNameFilterWidget : public QWidget diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_set_filter_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_set_filter_widget.h index ea006c88e..b4362d1db 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_set_filter_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_set_filter_widget.h @@ -15,7 +15,6 @@ #include #include #include -#include #include #include diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.h index fdddbed41..c02db29be 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.h @@ -13,8 +13,6 @@ #include #include #include -#include -#include #include class VisualDatabaseDisplaySubTypeFilterWidget : public QWidget 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 7171d93b2..cc0fc8033 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 @@ -20,7 +20,6 @@ #include #include #include -#include #include VisualDatabaseDisplayWidget::VisualDatabaseDisplayWidget(QWidget *parent, diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h index cc51cb003..5cab2ca9b 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h @@ -10,7 +10,6 @@ #include "../../../filters/filter_tree_model.h" #include "../../../interface/widgets/tabs/abstract_tab_deck_editor.h" #include "../../key_signals.h" -#include "../../layouts/flow_layout.h" #include "../cards/card_info_picture_with_text_overlay_widget.h" #include "../cards/card_size_widget.h" #include "../general/layout_containers/flow_widget.h" @@ -24,11 +23,9 @@ #include "visual_database_display_sub_type_filter_widget.h" #include -#include #include #include #include -#include #include #include #include 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 c1e5ead3a..5acad9df1 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 @@ -7,7 +7,6 @@ #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" diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h index e8ededc77..524762d89 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h @@ -9,7 +9,6 @@ #include "../cards/card_info_picture_with_text_overlay_widget.h" #include "../cards/card_size_widget.h" -#include "../general/layout_containers/flow_widget.h" #include "../general/layout_containers/overlap_control_widget.h" #include "../quick_settings/settings_button_widget.h" diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.cpp index ef59e90ff..575632724 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.cpp @@ -4,7 +4,6 @@ #include "deck_preview_widget.h" #include -#include DeckPreviewColorIdentityFilterWidget::DeckPreviewColorIdentityFilterWidget(VisualDeckStorageWidget *parent) : QWidget(parent), layout(new QHBoxLayout(this)) diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.h index 0e4a5837c..551dbb35c 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.h @@ -9,9 +9,7 @@ #include "../visual_deck_storage_widget.h" -#include #include -#include #include #include 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 b8425e842..706444545 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 @@ -11,7 +11,6 @@ #include #include -#include #include DeckPreviewDeckTagsDisplayWidget::DeckPreviewDeckTagsDisplayWidget(QWidget *_parent, DeckList *_deckList) 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 a221442ba..fdf4b2a28 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 @@ -2,7 +2,6 @@ #include "../../../../client/settings/cache_settings.h" #include "../../../../interface/widgets/tabs/abstract_tab_deck_editor.h" -#include "deck_preview_tag_dialog.h" #include #include diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.h index bb39943b6..c0fa86d19 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.h @@ -9,10 +9,6 @@ #include "deck_preview_deck_tags_display_widget.h" -#include -#include -#include - class DeckPreviewTagAdditionWidget : public QWidget { Q_OBJECT 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 df7f9738d..e8a399fe5 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 @@ -11,7 +11,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_tag_dialog.h b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_dialog.h index f23040a81..59b330a65 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_dialog.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_dialog.h @@ -8,13 +8,10 @@ #ifndef DECK_PREVIEW_TAG_DIALOG_H #define DECK_PREVIEW_TAG_DIALOG_H -#include #include #include #include #include -#include -#include #include class DeckPreviewTagDialog : public QDialog 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 b330b0c4c..2735b4856 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 @@ -6,6 +6,7 @@ #include "deck_preview_deck_tags_display_widget.h" #include +#include #include #include #include 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 c5758c5a6..883682749 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 @@ -2,6 +2,7 @@ #include "../../../client/settings/cache_settings.h" #include "deck_preview/deck_preview_widget.h" +#include "visual_deck_storage_widget.h" #include #include diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.h index f735d0ad3..d76fb0497 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.h @@ -9,11 +9,8 @@ #include "../general/display/banner_widget.h" #include "../general/layout_containers/flow_widget.h" -#include "visual_deck_storage_widget.h" - -#include -#include +class VisualDeckStorageWidget; class VisualDeckStorageFolderDisplayWidget : public QWidget { Q_OBJECT 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 dbd7929c5..70b438232 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 @@ -6,6 +6,7 @@ #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_search_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_search_widget.h index eff238e7e..67d260b21 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_search_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_search_widget.h @@ -7,11 +7,10 @@ #ifndef VISUAL_DECK_STORAGE_SEARCH_WIDGET_H #define VISUAL_DECK_STORAGE_SEARCH_WIDGET_H -#include "visual_deck_storage_widget.h" +#include "deck_preview/deck_preview_widget.h" #include #include -#include #include class VisualDeckStorageWidget; 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 ad49e0065..cbc78ba50 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 @@ -2,6 +2,8 @@ #include "../../../client/settings/cache_settings.h" +#include + /** * @brief Constructs a PrintingSelectorCardSortWidget for searching cards by set name or set code. * 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 4e78a67c4..1686de054 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 @@ -1,12 +1,10 @@ #include "visual_deck_storage_tag_filter_widget.h" #include "../general/layout_containers/flow_widget.h" -#include "deck_preview/deck_preview_tag_addition_widget.h" #include "deck_preview/deck_preview_tag_display_widget.h" -#include "deck_preview/deck_preview_widget.h" +#include "visual_deck_storage_widget.h" #include -#include VisualDeckStorageTagFilterWidget::VisualDeckStorageTagFilterWidget(VisualDeckStorageWidget *_parent) : QWidget(_parent), parent(_parent) diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.h index f5f160b55..ada94a244 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.h @@ -7,7 +7,7 @@ #ifndef VISUAL_DECK_STORAGE_TAG_FILTER_WIDGET_H #define VISUAL_DECK_STORAGE_TAG_FILTER_WIDGET_H -#include "visual_deck_storage_widget.h" +#include "deck_preview/deck_preview_widget.h" #include 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 d9cf74e7f..bfc425993 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 @@ -11,7 +11,6 @@ #include #include #include -#include #include #include 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 69e70f969..b205cb67e 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 @@ -9,18 +9,14 @@ #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" #include "deck_preview/deck_preview_color_identity_filter_widget.h" -#include "deck_preview/deck_preview_widget.h" #include "visual_deck_storage_folder_display_widget.h" #include "visual_deck_storage_quick_settings_widget.h" #include "visual_deck_storage_search_widget.h" #include "visual_deck_storage_sort_widget.h" #include "visual_deck_storage_tag_filter_widget.h" -#include -#include #include class QSpinBox; diff --git a/cockatrice/src/interface/window_main.cpp b/cockatrice/src/interface/window_main.cpp index 622c04a08..4c9922c80 100644 --- a/cockatrice/src/interface/window_main.cpp +++ b/cockatrice/src/interface/window_main.cpp @@ -54,7 +54,6 @@ #include #include #include -#include #include #include #include diff --git a/cockatrice/src/interface/window_main.h b/cockatrice/src/interface/window_main.h index 477d7b07c..75b0f5062 100644 --- a/cockatrice/src/interface/window_main.h +++ b/cockatrice/src/interface/window_main.h @@ -26,10 +26,8 @@ #define WINDOW_H #include -#include #include #include -#include #include #include #include diff --git a/cockatrice/src/main.cpp b/cockatrice/src/main.cpp index f20dab6fb..29dacee74 100644 --- a/cockatrice/src/main.cpp +++ b/cockatrice/src/main.cpp @@ -20,7 +20,6 @@ #include "main.h" -#include "QtNetwork/QNetworkInterface" #include "client/network/update/card_spoiler/spoiler_background_updater.h" #include "client/settings/cache_settings.h" #include "client/sound_engine.h" @@ -36,16 +35,11 @@ #include #include #include -#include -#include #include #include #include -#include #include -#include #include -#include #include QTranslator *translator, *qtTranslator; diff --git a/cockatrice/src/main.h b/cockatrice/src/main.h index 487abc0ea..b6e086744 100644 --- a/cockatrice/src/main.h +++ b/cockatrice/src/main.h @@ -8,7 +8,6 @@ #define MAIN_H #include -#include inline Q_LOGGING_CATEGORY(MainLog, "main"); inline Q_LOGGING_CATEGORY(QtTranslatorDebug, "qt_translator"); diff --git a/libcockatrice_card/libcockatrice/card/card_info.h b/libcockatrice_card/libcockatrice/card/card_info.h index 92b7f3121..7bd51356c 100644 --- a/libcockatrice_card/libcockatrice/card/card_info.h +++ b/libcockatrice_card/libcockatrice/card/card_info.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #include diff --git a/libcockatrice_card/libcockatrice/card/card_info_comparator.h b/libcockatrice_card/libcockatrice/card/card_info_comparator.h index 2b101701c..b8d9c47e6 100644 --- a/libcockatrice_card/libcockatrice/card/card_info_comparator.h +++ b/libcockatrice_card/libcockatrice/card/card_info_comparator.h @@ -9,7 +9,6 @@ #include "card_info.h" -#include #include #include diff --git a/libcockatrice_card/libcockatrice/card/database/card_database.cpp b/libcockatrice_card/libcockatrice/card/database/card_database.cpp index 57b3ce06e..2e977901f 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database.cpp +++ b/libcockatrice_card/libcockatrice/card/database/card_database.cpp @@ -1,12 +1,10 @@ #include "card_database.h" #include "../relation/card_relation.h" -#include "parser/cockatrice_xml_3.h" #include "parser/cockatrice_xml_4.h" #include #include -#include #include #include #include diff --git a/libcockatrice_card/libcockatrice/card/database/card_database.h b/libcockatrice_card/libcockatrice/card/database/card_database.h index cb46d6d00..6028cce86 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database.h +++ b/libcockatrice_card/libcockatrice/card/database/card_database.h @@ -10,10 +10,8 @@ #include #include #include -#include #include #include -#include #include inline Q_LOGGING_CATEGORY(CardDatabaseLog, "card_database"); diff --git a/libcockatrice_card/libcockatrice/card/database/card_database_loader.h b/libcockatrice_card/libcockatrice/card/database/card_database_loader.h index 631ba685f..f4e690428 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database_loader.h +++ b/libcockatrice_card/libcockatrice/card/database/card_database_loader.h @@ -4,7 +4,6 @@ #include #include #include -#include #include #include diff --git a/libcockatrice_card/libcockatrice/card/printing/printing_info.h b/libcockatrice_card/libcockatrice/card/printing/printing_info.h index e0978bd55..43d82a9cb 100644 --- a/libcockatrice_card/libcockatrice/card/printing/printing_info.h +++ b/libcockatrice_card/libcockatrice/card/printing/printing_info.h @@ -5,7 +5,6 @@ #include #include -#include #include class PrintingInfo; diff --git a/libcockatrice_card/libcockatrice/card/set/card_set_list.h b/libcockatrice_card/libcockatrice/card/set/card_set_list.h index 21b4a55d4..81d605374 100644 --- a/libcockatrice_card/libcockatrice/card/set/card_set_list.h +++ b/libcockatrice_card/libcockatrice/card/set/card_set_list.h @@ -4,7 +4,6 @@ #include "card_set.h" #include -#include /** * @class CardSetList diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/abstract_deck_list_node.h b/libcockatrice_deck_list/libcockatrice/deck_list/abstract_deck_list_node.h index 31e7b165e..877705705 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/abstract_deck_list_node.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/abstract_deck_list_node.h @@ -17,7 +17,6 @@ #ifndef COCKATRICE_ABSTRACT_DECK_LIST_NODE_H #define COCKATRICE_ABSTRACT_DECK_LIST_NODE_H -#include #include /** diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp index e26e55e08..f06652d7c 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h index fd3b4677e..f6bd54382 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h @@ -16,7 +16,6 @@ #include #include #include -#include #include #include diff --git a/libcockatrice_filters/libcockatrice/filters/filter_card.h b/libcockatrice_filters/libcockatrice/filters/filter_card.h index 344ae5224..4392a4630 100644 --- a/libcockatrice_filters/libcockatrice/filters/filter_card.h +++ b/libcockatrice_filters/libcockatrice/filters/filter_card.h @@ -9,7 +9,6 @@ #include #include -#include class CardFilter : public QObject { diff --git a/libcockatrice_filters/libcockatrice/filters/filter_tree.h b/libcockatrice_filters/libcockatrice/filters/filter_tree.h index 7e0f211ef..af91d2dbf 100644 --- a/libcockatrice_filters/libcockatrice/filters/filter_tree.h +++ b/libcockatrice_filters/libcockatrice/filters/filter_tree.h @@ -10,7 +10,6 @@ #include "filter_card.h" #include -#include #include #include #include diff --git a/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_set_priority_controller.h b/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_set_priority_controller.h index 8f8b7e62e..a4f3184cc 100644 --- a/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_set_priority_controller.h +++ b/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_set_priority_controller.h @@ -1,6 +1,5 @@ #ifndef COCKATRICE_INTERFACE_CARD_SET_PRIORITY_CONTROLLER_H #define COCKATRICE_INTERFACE_CARD_SET_PRIORITY_CONTROLLER_H -#include class ICardSetPriorityController { 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 e7abb2642..0c5994a3a 100644 --- a/libcockatrice_models/libcockatrice/models/database/card_database_display_model.h +++ b/libcockatrice_models/libcockatrice/models/database/card_database_display_model.h @@ -8,8 +8,6 @@ #ifndef COCKATRICE_CARD_DATABASE_DISPLAY_MODEL_H #define COCKATRICE_CARD_DATABASE_DISPLAY_MODEL_H -#include -#include #include #include #include diff --git a/libcockatrice_network/libcockatrice/network/client/abstract/abstract_client.h b/libcockatrice_network/libcockatrice/network/client/abstract/abstract_client.h index 165737e95..dc3be5a94 100644 --- a/libcockatrice_network/libcockatrice/network/client/abstract/abstract_client.h +++ b/libcockatrice_network/libcockatrice/network/client/abstract/abstract_client.h @@ -8,7 +8,6 @@ #define ABSTRACTCLIENT_H #include -#include #include #include #include diff --git a/libcockatrice_network/libcockatrice/network/client/remote/remote_client.h b/libcockatrice_network/libcockatrice/network/client/remote/remote_client.h index 939e88dfc..15e3e8ef5 100644 --- a/libcockatrice_network/libcockatrice/network/client/remote/remote_client.h +++ b/libcockatrice_network/libcockatrice/network/client/remote/remote_client.h @@ -10,7 +10,6 @@ #include "../abstract/abstract_client.h" #include -#include #include #include #include diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_participant.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_participant.cpp index c6a29b275..493b8e966 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_participant.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_participant.cpp @@ -4,18 +4,10 @@ #include "../server_abstractuserinterface.h" #include "../server_database_interface.h" #include "../server_room.h" -#include "server_arrow.h" #include "server_card.h" -#include "server_cardzone.h" -#include "server_counter.h" #include "server_game.h" #include "server_player.h" -#include -#include -#include -#include -#include #include #include #include @@ -49,42 +41,13 @@ #include #include #include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include #include -#include #include -#include -#include -#include -#include -#include #include -#include -#include #include #include -#include -#include #include Server_AbstractParticipant::Server_AbstractParticipant(Server_Game *_game, diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.h b/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.h index 4a32b6fef..40fe84aa1 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.h +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.h @@ -4,7 +4,6 @@ #include "../serverinfo_user_container.h" #include "server_abstract_participant.h" -#include #include #include diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_cardzone.h b/libcockatrice_network/libcockatrice/network/server/remote/game/server_cardzone.h index 0dc368a80..77fea54ca 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_cardzone.h +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_cardzone.h @@ -20,7 +20,6 @@ #ifndef SERVER_CARDZONE_H #define SERVER_CARDZONE_H -#include #include #include #include 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 b0dc7fc5b..5ec7b3c5d 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -50,7 +49,6 @@ #include #include #include -#include Server_Game::Server_Game(const ServerInfo_User &_creatorInfo, int _gameId, diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp index b840a172c..b59d89ed8 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp @@ -4,7 +4,6 @@ #include "../server_abstractuserinterface.h" #include "../server_database_interface.h" #include "../server_room.h" -#include "server_arrow.h" #include "server_card.h" #include "server_cardzone.h" #include "server_counter.h" @@ -16,66 +15,28 @@ #include #include #include -#include #include #include #include -#include #include -#include #include #include -#include #include -#include -#include -#include -#include #include -#include -#include #include #include -#include -#include -#include -#include -#include #include -#include -#include #include #include #include #include -#include -#include -#include #include -#include #include -#include #include -#include -#include -#include -#include #include -#include #include -#include -#include #include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include #include #include #include diff --git a/libcockatrice_network/libcockatrice/network/server/remote/server.cpp b/libcockatrice_network/libcockatrice/network/server/remote/server.cpp index 2f1232b8f..a5a74c54c 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/server.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/server.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/libcockatrice_network/libcockatrice/network/server/remote/server.h b/libcockatrice_network/libcockatrice/network/server/remote/server.h index f9dada801..ab57fac4e 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/server.h +++ b/libcockatrice_network/libcockatrice/network/server/remote/server.h @@ -3,17 +3,13 @@ #include "server_player_reference.h" -#include #include #include #include #include -#include #include #include -#include #include -#include class Server_DatabaseInterface; class Server_Game; diff --git a/libcockatrice_network/libcockatrice/network/server/remote/server_abstractuserinterface.cpp b/libcockatrice_network/libcockatrice/network/server/remote/server_abstractuserinterface.cpp index e228f0128..f9b61ab48 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/server_abstractuserinterface.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/server_abstractuserinterface.cpp @@ -9,10 +9,8 @@ #include #include -#include #include #include -#include void Server_AbstractUserInterface::sendProtocolItemByType(ServerMessage::MessageType type, const ::google::protobuf::Message &item) diff --git a/libcockatrice_network/libcockatrice/network/server/remote/server_abstractuserinterface.h b/libcockatrice_network/libcockatrice/network/server/remote/server_abstractuserinterface.h index 10a2aee62..b11260003 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/server_abstractuserinterface.h +++ b/libcockatrice_network/libcockatrice/network/server/remote/server_abstractuserinterface.h @@ -5,7 +5,6 @@ #include #include -#include #include #include diff --git a/libcockatrice_network/libcockatrice/network/server/remote/server_protocolhandler.h b/libcockatrice_network/libcockatrice/network/server/remote/server_protocolhandler.h index 9f3b1f4e7..0d05b91c8 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/server_protocolhandler.h +++ b/libcockatrice_network/libcockatrice/network/server/remote/server_protocolhandler.h @@ -5,7 +5,6 @@ #include "server_abstractuserinterface.h" #include -#include #include #include diff --git a/libcockatrice_network/libcockatrice/network/server/remote/server_room.h b/libcockatrice_network/libcockatrice/network/server/remote/server_room.h index 34b9063e9..3d9988f20 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/server_room.h +++ b/libcockatrice_network/libcockatrice/network/server/remote/server_room.h @@ -3,12 +3,10 @@ #include "serverinfo_user_container.h" -#include #include #include #include #include -#include #include #include diff --git a/libcockatrice_protocol/libcockatrice/protocol/featureset.cpp b/libcockatrice_protocol/libcockatrice/protocol/featureset.cpp index d9f253ab9..1b08c4040 100644 --- a/libcockatrice_protocol/libcockatrice/protocol/featureset.cpp +++ b/libcockatrice_protocol/libcockatrice/protocol/featureset.cpp @@ -1,6 +1,5 @@ #include "featureset.h" -#include #include FeatureSet::FeatureSet() diff --git a/libcockatrice_protocol/libcockatrice/protocol/featureset.h b/libcockatrice_protocol/libcockatrice/protocol/featureset.h index 424d0b975..32625d5f8 100644 --- a/libcockatrice_protocol/libcockatrice/protocol/featureset.h +++ b/libcockatrice_protocol/libcockatrice/protocol/featureset.h @@ -3,7 +3,6 @@ #include #include -#include #include class FeatureSet : public QObject diff --git a/libcockatrice_settings/libcockatrice/settings/card_database_settings.h b/libcockatrice_settings/libcockatrice/settings/card_database_settings.h index 8d45efbec..9a176a99b 100644 --- a/libcockatrice_settings/libcockatrice/settings/card_database_settings.h +++ b/libcockatrice_settings/libcockatrice/settings/card_database_settings.h @@ -10,9 +10,6 @@ #include "settings_manager.h" -#include -#include -#include #include class CardDatabaseSettings : public SettingsManager, public ICardSetPriorityController diff --git a/libcockatrice_settings/libcockatrice/settings/download_settings.h b/libcockatrice_settings/libcockatrice/settings/download_settings.h index a67a7f9c7..ed3634ea1 100644 --- a/libcockatrice_settings/libcockatrice/settings/download_settings.h +++ b/libcockatrice_settings/libcockatrice/settings/download_settings.h @@ -9,8 +9,6 @@ #include "settings_manager.h" -#include - class DownloadSettings : public SettingsManager { Q_OBJECT diff --git a/libcockatrice_settings/libcockatrice/settings/settings_manager.h b/libcockatrice_settings/libcockatrice/settings/settings_manager.h index a72094b4e..3592d8f8c 100644 --- a/libcockatrice_settings/libcockatrice/settings/settings_manager.h +++ b/libcockatrice_settings/libcockatrice/settings/settings_manager.h @@ -7,7 +7,6 @@ #ifndef SETTINGSMANAGER_H #define SETTINGSMANAGER_H -#include #include #include #include diff --git a/servatrice/src/servatrice_database_interface.h b/servatrice/src/servatrice_database_interface.h index be1d1ff19..68080404c 100644 --- a/servatrice/src/servatrice_database_interface.h +++ b/servatrice/src/servatrice_database_interface.h @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include #include From 8ee7163014053c8d15e26f955e8cccad2829fce2 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Sat, 29 Nov 2025 18:56:06 +0100 Subject: [PATCH 14/40] [Printing Selector] Notify deck editor about history changes. (#6364) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Took 44 minutes Took 2 minutes Co-authored-by: Lukas Brübach --- .../printing_selector/card_amount_widget.cpp | 55 +++++++++++++++++-- .../printing_selector/card_amount_widget.h | 4 ++ 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.cpp b/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.cpp index 416de18dc..80258be61 100644 --- a/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.cpp +++ b/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.cpp @@ -61,6 +61,10 @@ CardAmountWidget::CardAmountWidget(QWidget *parent, // Connect slider for dynamic font size adjustment connect(cardSizeSlider, &QSlider::valueChanged, this, &CardAmountWidget::adjustFontSize); + + if (deckEditor) { + connect(this, &CardAmountWidget::deckModified, deckEditor, &AbstractTabDeckEditor::onDeckHistorySaveRequested); + } } /** @@ -140,24 +144,52 @@ void CardAmountWidget::updateCardCount() */ void CardAmountWidget::addPrinting(const QString &zone) { + int addedCount = 1; + // Check if we will need to add extra copies due to replacing copies without providerIds + QModelIndex existing = deckModel->findCard(rootCard.getName(), zone); + int extraCopies = 0; + bool replacingProviderless = false; + + if (existing.isValid()) { + QString providerId = deckModel->data(existing.sibling(existing.row(), 4), Qt::DisplayRole).toString(); + if (providerId.isEmpty()) { + int amount = deckModel->data(existing, Qt::DisplayRole).toInt(); + extraCopies = amount - 1; // One less because we *always* add one + replacingProviderless = true; + } + } + + addedCount += extraCopies; + + QString reason = QString("Added %1 copies of '%2 (%3) %4' to %5 [ProviderID: %6]%7") + .arg(addedCount) + .arg(rootCard.getName()) + .arg(rootCard.getPrinting().getSet()->getShortName()) + .arg(rootCard.getPrinting().getProperty("num")) + .arg(zone == DECK_ZONE_MAIN ? "mainboard" : "sideboard") + .arg(rootCard.getPrinting().getUuid()) + .arg(replacingProviderless ? " (replaced providerless printings)" : ""); + + emit deckModified(reason); + // Add the card and expand the list UI auto newCardIndex = deckModel->addCard(rootCard, zone); recursiveExpand(newCardIndex); // Check if a card without a providerId already exists in the deckModel and replace it, if so. - QModelIndex find_card = deckModel->findCard(rootCard.getName(), zone); - QString foundProviderId = deckModel->data(find_card.sibling(find_card.row(), 4), Qt::DisplayRole).toString(); - if (find_card.isValid() && find_card != newCardIndex && foundProviderId == "") { - auto amount = deckModel->data(find_card, Qt::DisplayRole); + QString foundProviderId = deckModel->data(existing.sibling(existing.row(), 4), Qt::DisplayRole).toString(); + if (existing.isValid() && existing != newCardIndex && foundProviderId == "") { + auto amount = deckModel->data(existing, Qt::DisplayRole); for (int i = 0; i < amount.toInt() - 1; i++) { deckModel->addCard(rootCard, zone); } - deckModel->removeRow(find_card.row(), find_card.parent()); + deckModel->removeRow(existing.row(), existing.parent()); } // Set Index and Focus as if the user had just clicked the new card and modify the deckEditor saveState newCardIndex = deckModel->findCard(rootCard.getName(), zone, rootCard.getPrinting().getUuid(), rootCard.getPrinting().getProperty("num")); + deckView->setCurrentIndex(newCardIndex); deckView->setFocus(Qt::FocusReason::MouseFocusReason); deckEditor->setModified(true); @@ -223,12 +255,15 @@ void CardAmountWidget::offsetCountAtIndex(const QModelIndex &idx, int offset) const QModelIndex numberIndex = idx.sibling(idx.row(), 0); const int count = deckModel->data(numberIndex, Qt::EditRole).toInt(); const int new_count = count + offset; + deckView->setCurrentIndex(numberIndex); + if (new_count <= 0) { deckModel->removeRow(idx.row(), idx.parent()); } else { deckModel->setData(numberIndex, new_count, Qt::EditRole); } + deckEditor->setModified(true); } @@ -239,8 +274,18 @@ void CardAmountWidget::offsetCountAtIndex(const QModelIndex &idx, int offset) */ void CardAmountWidget::decrementCardHelper(const QString &zone) { + QString reason = QString("Removed 1 copy of '%1 (%2) %3' from %4 [ProviderID: %5]") + .arg(rootCard.getName()) + .arg(rootCard.getPrinting().getSet()->getShortName()) + .arg(rootCard.getPrinting().getProperty("num")) + .arg(zone == DECK_ZONE_MAIN ? "mainboard" : "sideboard") + .arg(rootCard.getPrinting().getUuid()); + + emit deckModified(reason); + QModelIndex idx = deckModel->findCard(rootCard.getName(), zone, rootCard.getPrinting().getUuid(), rootCard.getPrinting().getProperty("num")); + offsetCountAtIndex(idx, -1); deckEditor->setModified(true); } 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 1da999c78..6d059bc04 100644 --- a/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.h +++ b/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.h @@ -21,6 +21,10 @@ class CardAmountWidget : public QWidget { Q_OBJECT + +signals: + void deckModified(const QString &modificationReason); + public: explicit CardAmountWidget(QWidget *parent, AbstractTabDeckEditor *deckEditor, From de13c22552d1d96be733d7d81a741e131983f5a2 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Sat, 29 Nov 2025 18:58:39 +0100 Subject: [PATCH 15/40] [Fix-Warnings] Suppress C4100: unreferenced parameter for protobuf files (#6373) * [Fix-Warnings] Suppress C4100: unreferenced parameter for protobuf files. * [Fix-Warnings] Compiler specific options. * [Fix-Warnings] Lint. --- .../libcockatrice/protocol/pb/CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt b/libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt index 32e7f3238..212ab69dd 100644 --- a/libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt +++ b/libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt @@ -165,6 +165,12 @@ set(PROTO_FILES session_event.proto ) +if(MSVC) + set(unused_warning /wd4100) +else() + set(unused_warning -Wno-unused-parameter) +endif() + if(${Protobuf_VERSION} VERSION_LESS "3.21.0.0") message(STATUS "Using Protobuf Legacy Mode") include_directories(${PROTOBUF_INCLUDE_DIRS}) @@ -172,6 +178,7 @@ if(${Protobuf_VERSION} VERSION_LESS "3.21.0.0") protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ${PROTO_FILES}) add_library(libcockatrice_protocol_pb ${PROTO_SRCS} ${PROTO_HDRS}) + target_compile_options(libcockatrice_protocol_pb PRIVATE ${unused_warning}) set(libcockatrice_protocol_pb_LIBS ${PROTOBUF_LIBRARIES}) if(UNIX) set(libcockatrice_protocol_pb_LIBS ${libcockatrice_protocol_pb_LIBS} -lpthread) @@ -189,6 +196,7 @@ if(${Protobuf_VERSION} VERSION_LESS "3.21.0.0") endif() else() add_library(libcockatrice_protocol_pb ${PROTO_FILES}) + target_compile_options(libcockatrice_protocol_pb PRIVATE ${unused_warning}) target_link_libraries(libcockatrice_protocol_pb PUBLIC protobuf::libprotobuf) set(PROTO_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}") target_include_directories(libcockatrice_protocol_pb PUBLIC "${PROTOBUF_INCLUDE_DIRS}") From eab4d435f8f5c04b2950ead35fc7f352819ecf37 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Sun, 30 Nov 2025 08:41:01 +0100 Subject: [PATCH 16/40] [Feature] TabArchidekt and Archidekt API integration (#6348) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * TabArchidekt and Archidekt API integration. Took 37 seconds Took 4 minutes Took 40 seconds Took 4 minutes * Lint. * Lont. * Search bar, fancier display, resolve providerId * Delegate click to base. * Be explicit for pedantic compilers. * Liiint. * Leave them default I guess * Leave them default I guess * Small fixes. * New utility display widgets. * New style for deck listing. * Lint. * Lont. * Scale things. * Delegate paint to base. * Use default Archidekt preview image for decks without featured. * Consistent sizes. * Increase font size, qt version guard. * More version guards. * Clean up filter layout, use mana symbols. * Set content margins. * Refresh on filter change. * Lint. * Better elision. * Query actual new endpoints, new query parameters. * Doxygen, reorder fields in constructor, readability. * Update page size doc to min size. * Update initial min deck size value. * Add label to page selection. * Okay, so, people upload a lot of 1 card decks frequently. * Whoops. * Add a selection combobox for sorting logic. * Debounce and limit searches. * Include. * Lint. * Don't imply that Archidekt supports multiple cards/commander names. * Let's not lambda it and slot it instead. * Overload. * Add button to home tab. Took 8 minutes * Adjust to selection model change. Took 5 minutes * Cleanup auto-generated comments. Took 8 minutes * Remember card sizes. Took 1 minute * Initialize with correct size. Took 3 minutes * Use correct placeholders. Took 2 minutes * Style lint. Took 16 minutes * Parse double-faced cards correctly. * Parse double-faced cards correctly. * Allow TabArchidekt to use VDE group/sort/display buttons * Lint. * Indicate that things are clickable. * Min treshold for nicer display. * Lint. * We have good labels at home. * We do a little linting. * Qt version guards. * Qt5 is the devil. * Update comments. * Lint comments. * More doxys. * One more doxy. * Lint. * Update. * Small fixes. Took 7 minutes Took 13 seconds --------- Co-authored-by: Lukas Brübach --- cockatrice/CMakeLists.txt | 16 + .../card_group_display_widget.cpp | 9 +- .../cards/deck_card_zone_display_widget.cpp | 6 +- .../display/background_plate_widget.cpp | 34 ++ .../general/display/background_plate_widget.h | 22 + .../widgets/general/display/color_bar.cpp | 163 +++++ .../widgets/general/display/color_bar.h | 128 ++++ .../display/shadow_background_label.cpp | 10 +- .../general/display/shadow_background_label.h | 1 + .../interface/widgets/general/home_widget.cpp | 3 + .../archidekt_deck_listing_api_response.cpp | 29 + .../archidekt_deck_listing_api_response.h | 22 + .../card/archidekt_api_response_card.cpp | 61 ++ .../card/archidekt_api_response_card.h | 68 +++ .../archidekt_api_response_card_entry.cpp | 43 ++ .../card/archidekt_api_response_card_entry.h | 56 ++ .../card/archidekt_api_response_edition.cpp | 19 + .../card/archidekt_api_response_edition.h | 51 ++ .../deck/archidekt_api_response_deck.cpp | 79 +++ .../deck/archidekt_api_response_deck.h | 71 +++ .../archidekt_api_response_deck_category.cpp | 19 + .../archidekt_api_response_deck_category.h | 55 ++ ...kt_api_response_deck_listing_container.cpp | 64 ++ ...dekt_api_response_deck_listing_container.h | 133 +++++ .../archidekt_api_response_deck_owner.cpp | 22 + .../archidekt_api_response_deck_owner.h | 36 ++ ...idekt_api_response_deck_display_widget.cpp | 157 +++++ ...chidekt_api_response_deck_display_widget.h | 125 ++++ ...api_response_deck_entry_display_widget.cpp | 235 ++++++++ ...t_api_response_deck_entry_display_widget.h | 121 ++++ ..._response_deck_listings_display_widget.cpp | 47 ++ ...pi_response_deck_listings_display_widget.h | 97 +++ ...dekt_deck_preview_image_display_widget.cpp | 80 +++ ...hidekt_deck_preview_image_display_widget.h | 66 ++ .../tabs/api/archidekt/tab_archidekt.cpp | 562 ++++++++++++++++++ .../tabs/api/archidekt/tab_archidekt.h | 250 ++++++++ .../interface/widgets/tabs/tab_supervisor.cpp | 15 + .../interface/widgets/tabs/tab_supervisor.h | 4 +- .../visual_deck_display_options_widget.cpp | 124 ++++ .../visual_deck_display_options_widget.h | 138 +++++ .../visual_deck_editor_widget.cpp | 135 +---- .../visual_deck_editor_widget.h | 19 +- .../models/deck_list/deck_list_model.h | 31 +- 43 files changed, 3285 insertions(+), 141 deletions(-) create mode 100644 cockatrice/src/interface/widgets/general/display/background_plate_widget.cpp create mode 100644 cockatrice/src/interface/widgets/general/display/background_plate_widget.h create mode 100644 cockatrice/src/interface/widgets/general/display/color_bar.cpp create mode 100644 cockatrice/src/interface/widgets/general/display/color_bar.h create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/archidekt_deck_listing_api_response.cpp create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/archidekt_deck_listing_api_response.h create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.cpp create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.h create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card_entry.cpp create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card_entry.h create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_edition.cpp create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_edition.h create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.cpp create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.h create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck_category.cpp create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck_category.h create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_listing_container.cpp create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_listing_container.h create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_owner.cpp create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_owner.h create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_display_widget.cpp create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_display_widget.h create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.cpp create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.h create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_listings_display_widget.cpp create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_listings_display_widget.h create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_deck_preview_image_display_widget.cpp create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_deck_preview_image_display_widget.h create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp create mode 100644 cockatrice/src/interface/widgets/tabs/api/archidekt/tab_archidekt.h create mode 100644 cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.cpp create mode 100644 cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 522300346..eacbc8825 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -153,8 +153,10 @@ set(cockatrice_SOURCES 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/background_plate_widget.cpp src/interface/widgets/general/display/banner_widget.cpp src/interface/widgets/general/display/bar_widget.cpp + src/interface/widgets/general/display/color_bar.cpp src/interface/widgets/general/display/dynamic_font_size_label.cpp src/interface/widgets/general/display/dynamic_font_size_push_button.cpp src/interface/widgets/general/display/labeled_input.cpp @@ -202,6 +204,7 @@ set(cockatrice_SOURCES src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.cpp src/interface/widgets/visual_database_display/visual_database_display_widget.cpp src/interface/widgets/visual_database_display/visual_database_filter_display_widget.cpp + src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.cpp src/interface/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.cpp @@ -220,6 +223,19 @@ set(cockatrice_SOURCES src/interface/window_main.cpp src/main.cpp src/interface/widgets/tabs/abstract_tab_deck_editor.cpp + src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp + src/interface/widgets/tabs/api/archidekt/api_response/archidekt_deck_listing_api_response.cpp + src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.cpp + src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card_entry.cpp + src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_edition.cpp + src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.cpp + src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck_category.cpp + src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_listing_container.cpp + src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_owner.cpp + src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_display_widget.cpp + src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.cpp + src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_listings_display_widget.cpp + src/interface/widgets/tabs/api/archidekt/display/archidekt_deck_preview_image_display_widget.cpp src/interface/widgets/tabs/api/edhrec/api_response/archidekt_links/edhrec_api_response_archidekt_links.cpp src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_average_deck_api_response.cpp src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_deck_api_response.cpp 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 75e075de6..cb83768f4 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 @@ -32,7 +32,10 @@ CardGroupDisplayWidget::CardGroupDisplayWidget(QWidget *parent, CardGroupDisplayWidget::updateCardDisplays(); connect(deckListModel, &QAbstractItemModel::rowsInserted, this, &CardGroupDisplayWidget::onCardAddition); - connect(selectionModel, &QItemSelectionModel::selectionChanged, this, &CardGroupDisplayWidget::onSelectionChanged); + if (selectionModel) { + connect(selectionModel, &QItemSelectionModel::selectionChanged, this, + &CardGroupDisplayWidget::onSelectionChanged); + } connect(deckListModel, &QAbstractItemModel::rowsRemoved, this, &CardGroupDisplayWidget::onCardRemoval); } @@ -179,7 +182,9 @@ void CardGroupDisplayWidget::onActiveSortCriteriaChanged(QStringList _activeSort void CardGroupDisplayWidget::mousePressEvent(QMouseEvent *event) { QWidget::mousePressEvent(event); - selectionModel->clearSelection(); + if (selectionModel) { + selectionModel->clearSelection(); + } } void CardGroupDisplayWidget::onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card) 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 618d7e565..132964f13 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 @@ -38,8 +38,10 @@ DeckCardZoneDisplayWidget::DeckCardZoneDisplayWidget(QWidget *parent, displayCards(); connect(deckListModel, &QAbstractItemModel::rowsInserted, this, &DeckCardZoneDisplayWidget::onCategoryAddition); - connect(selectionModel, &QItemSelectionModel::selectionChanged, this, - &DeckCardZoneDisplayWidget::onSelectionChanged); + if (selectionModel) { + connect(selectionModel, &QItemSelectionModel::selectionChanged, this, + &DeckCardZoneDisplayWidget::onSelectionChanged); + } connect(deckListModel, &QAbstractItemModel::rowsRemoved, this, &DeckCardZoneDisplayWidget::onCategoryRemoval); } diff --git a/cockatrice/src/interface/widgets/general/display/background_plate_widget.cpp b/cockatrice/src/interface/widgets/general/display/background_plate_widget.cpp new file mode 100644 index 000000000..aad259900 --- /dev/null +++ b/cockatrice/src/interface/widgets/general/display/background_plate_widget.cpp @@ -0,0 +1,34 @@ +#include "background_plate_widget.h" + +#include +#include +#include +#include + +BackgroundPlateWidget::BackgroundPlateWidget(QWidget *parent) : QWidget(parent) +{ + setAutoFillBackground(true); // For automatic background filling +} + +void BackgroundPlateWidget::paintEvent(QPaintEvent *event) +{ + QWidget::paintEvent(event); + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing, true); + + // Set the background color to semi-transparent black with rounded corners + QRect rect = this->rect(); + painter.setPen(Qt::NoPen); // No border + if (focused) { + painter.setBrush(QColor(85, 190, 75, 140)); + } else { + painter.setBrush(QColor(0, 0, 0, 140)); // semi-transparent black + } + painter.drawRoundedRect(rect, 6, 6); // rounded corners +} + +void BackgroundPlateWidget::setFocused(bool _focused) +{ + focused = _focused; + update(); +} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/general/display/background_plate_widget.h b/cockatrice/src/interface/widgets/general/display/background_plate_widget.h new file mode 100644 index 000000000..d529cb6fa --- /dev/null +++ b/cockatrice/src/interface/widgets/general/display/background_plate_widget.h @@ -0,0 +1,22 @@ +#ifndef COCKATRICE_BACKGROUND_PLATE_WIDGET_H +#define COCKATRICE_BACKGROUND_PLATE_WIDGET_H + +#include + +class BackgroundPlateWidget : public QWidget +{ + Q_OBJECT + +public: + explicit BackgroundPlateWidget(QWidget *parent = nullptr); + + void setFocused(bool focused); + +private: + bool focused = false; + +protected: + void paintEvent(QPaintEvent *event) override; +}; + +#endif // COCKATRICE_BACKGROUND_PLATE_WIDGET_H diff --git a/cockatrice/src/interface/widgets/general/display/color_bar.cpp b/cockatrice/src/interface/widgets/general/display/color_bar.cpp new file mode 100644 index 000000000..d1eb7ef4c --- /dev/null +++ b/cockatrice/src/interface/widgets/general/display/color_bar.cpp @@ -0,0 +1,163 @@ + +#include "color_bar.h" + +#include +#include +#include +#include + +ColorBar::ColorBar(const QMap &_colors, QWidget *parent) : QWidget(parent), colors(_colors) +{ + setMouseTracking(true); +} + +void ColorBar::setColors(const QMap &_colors) +{ + colors = _colors; + update(); +} + +QSize ColorBar::minimumSizeHint() const +{ + return QSize(200, 22); +} + +void ColorBar::paintEvent(QPaintEvent *) +{ + if (colors.isEmpty()) + return; + + int total = 0; + for (int v : colors.values()) + total += v; + + // Prevent divide-by-zero + if (total == 0) + return; + + QPainter p(this); + p.setRenderHint(QPainter::Antialiasing, true); + + const int w = width(); + const int h = height(); + int x = 0; + + // Draw rounded border background + QRectF bounds(0.5, 0.5, w - 1, h - 1); + p.setPen(QPen(Qt::black, 1)); + p.setBrush(Qt::NoBrush); + p.drawRoundedRect(bounds, 6, 6); + + // Clip to inside the border + p.setClipRect(bounds.adjusted(2, 2, -2, -2)); + + // Ensure predictable order + QList sortedKeys = colors.keys(); + std::sort(sortedKeys.begin(), sortedKeys.end()); // Sort alphabetically + + // Draw each color segment in the sorted order + for (const QString &key : sortedKeys) { + int value = colors[key]; + double ratio = double(value) / total; + + if (ratio <= minRatioThreshold) { + continue; + } + + int segmentWidth = int(ratio * w); + + // Ensure the segment width is at least 1 to avoid degenerate rectangles + if (segmentWidth < 1) + segmentWidth = 1; + + QColor base = colorFromName(key); + + // Slight gradient for nicer look + QLinearGradient grad(x, 0, x, h); + grad.setColorAt(0, base.lighter(120)); + grad.setColorAt(1, base.darker(120)); + + p.fillRect(QRect(x, 0, segmentWidth, h), grad); + + x += segmentWidth; + } +} + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +void ColorBar::enterEvent(QEnterEvent *event) +{ + Q_UNUSED(event); + isHovered = true; +} +#else +void ColorBar::enterEvent(QEvent *event) +{ + Q_UNUSED(event); + isHovered = true; +} +#endif + +void ColorBar::leaveEvent(QEvent *) +{ + isHovered = false; +} + +void ColorBar::mouseMoveEvent(QMouseEvent *event) +{ + if (!isHovered || colors.isEmpty()) + return; + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + int x = int(event->position().x()); + QPoint gp = event->globalPosition().toPoint(); +#else + int x = event->pos().x(); + QPoint gp = event->globalPos(); +#endif + + QString text = tooltipForPosition(x); + if (!text.isEmpty()) + QToolTip::showText(gp, text, this); +} + +QString ColorBar::tooltipForPosition(int x) const +{ + int total = 0; + for (int v : colors.values()) + total += v; + + if (total == 0) + return {}; + + int pos = 0; + for (auto it = colors.cbegin(); it != colors.cend(); ++it) { + const double ratio = double(it.value()) / total; + const int segmentWidth = int(ratio * width()); + + if (x >= pos && x < pos + segmentWidth) { + const double percent = (100.0 * it.value()) / total; + return QString("%1: %2 cards (%3%)").arg(it.key()).arg(it.value()).arg(QString::number(percent, 'f', 1)); + } + + pos += segmentWidth; + } + + return {}; +} + +QColor ColorBar::colorFromName(const QString &name) const +{ + static QMap map = { + {"R", QColor(220, 30, 30)}, {"G", QColor(40, 170, 40)}, {"U", QColor(40, 90, 200)}, + {"W", QColor(235, 235, 230)}, {"B", QColor(30, 30, 30)}, + }; + + if (map.contains(name)) + return map[name]; + + QColor c(name); + if (!c.isValid()) + c = Qt::gray; + + return c; +} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/general/display/color_bar.h b/cockatrice/src/interface/widgets/general/display/color_bar.h new file mode 100644 index 000000000..f61ab6942 --- /dev/null +++ b/cockatrice/src/interface/widgets/general/display/color_bar.h @@ -0,0 +1,128 @@ +#ifndef COCKATRICE_COLOR_BAR_H +#define COCKATRICE_COLOR_BAR_H + +#include +#include +#include +#include + +/** + * @class ColorBar + * @brief A widget for visualizing proportional color distributions as a horizontal bar. + * + * This widget renders a horizontal bar divided into colored segments whose widths reflect + * the relative values associated with each color key in a `QMap`. The class + * is designed as a small, lightweight, and self-contained visualization component suitable + * for representing distributions such as color counts, mana statistics, categorical frequencies, and similar data sets. + * + * Key features: + * - Filled segments for better visual clarity. + * - Deterministic alphabetical ordering of color keys. + * - Optional minimum percentage threshold for filtering out insignificant segments. + * - Mouse-hover tooltips showing each segment’s key, count, and percentage of total. + * + * Default color mappings exist for `"R"`, `"G"`, `"U"`, `"W"`, and `"B"`, using named + * colors, but any string recognized by `QColor` may be used. If an unknown name is provided, + * the segment will fall back to gray. + * + * This component is display-only and does not interpret or mutate domain-level data. + */ +class ColorBar : public QWidget +{ + Q_OBJECT + +public: + /** + * @brief Constructs a ColorBar widget. + * + * @param colors Map of color identifiers to integer counts. + * @param parent Optional parent widget. + */ + explicit ColorBar(const QMap &colors, QWidget *parent = nullptr); + + /** + * @brief Updates the color distribution map. + * @param colors New color → count mapping. + * + * Triggers an immediate repaint. + */ + void setColors(const QMap &colors); + + /** + * @brief Sets a minimum percentage threshold below which segments are not drawn. + * + * @param treshold Percentage from 0 to 100. + * + * Internally converted into a ratio (0.05 = 5%). + */ + void setMinPercentThreshold(double treshold) + { + minRatioThreshold = treshold / 100.0; + } + + /** + * @brief Returns the recommended minimum size. + */ + QSize minimumSizeHint() const override; + +protected: + /** + * @brief Paints the color distribution bar. + * + * Draws: + * - A rounded border + * - Filled segments for each color + * - Only segments above the minimum ratio threshold + */ + void paintEvent(QPaintEvent *event) override; + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + /** + * @brief Handles mouse hover entering (Qt6 version). + */ + void enterEvent(QEnterEvent *event) override; +#else + /** + * @brief Handles mouse hover entering (Qt5 version). + */ + void enterEvent(QEvent *event) override; +#endif + + /** + * @brief Handles mouse hover leaving. + */ + void leaveEvent(QEvent *event) override; + + /** + * @brief Handles mouse movement to update contextual tooltips. + */ + void mouseMoveEvent(QMouseEvent *event) override; + +private: + /// Map of color keys to counts used for rendering. + QMap colors; + + /// True if the mouse is currently inside the widget. + bool isHovered = false; + + /// Minimum ratio a segment must exceed to be drawn. + double minRatioThreshold = 0.0; + + /** + * @brief Converts a color name into a display QColor. + * + * Recognized special keys: `"R", "G", "U", "W", "B"`. + * Other strings are treated as QColor names or fall back to gray. + */ + QColor colorFromName(const QString &name) const; + + /** + * @brief Returns tooltip text for a given x-coordinate in the bar. + * + * @param x Horizontal coordinate relative to widget. + * @return Tooltip text or empty string if no segment applies. + */ + QString tooltipForPosition(int x) const; +}; + +#endif // COCKATRICE_COLOR_BAR_H diff --git a/cockatrice/src/interface/widgets/general/display/shadow_background_label.cpp b/cockatrice/src/interface/widgets/general/display/shadow_background_label.cpp index fbca8df8d..7db18c57d 100644 --- a/cockatrice/src/interface/widgets/general/display/shadow_background_label.cpp +++ b/cockatrice/src/interface/widgets/general/display/shadow_background_label.cpp @@ -12,12 +12,18 @@ */ ShadowBackgroundLabel::ShadowBackgroundLabel(QWidget *parent, const QString &text) : QLabel(parent) { - setAttribute(Qt::WA_TranslucentBackground); // Allows transparency. - setText("" + text + ""); ///< Ensures the text is rendered in white. + setAttribute(Qt::WA_TranslucentBackground); // Allows transparency. + setLabelText(text); setAlignment(Qt::AlignCenter); ///< Centers the text within the label. setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); ///< Ensures minimum size constraints. } +void ShadowBackgroundLabel::setLabelText(const QString &text) +{ + setText("" + text + ""); ///< Ensures the text is rendered in white. + update(); +} + /** * @brief Handles resizing of the label. * diff --git a/cockatrice/src/interface/widgets/general/display/shadow_background_label.h b/cockatrice/src/interface/widgets/general/display/shadow_background_label.h index 3483452f5..b2344b7d0 100644 --- a/cockatrice/src/interface/widgets/general/display/shadow_background_label.h +++ b/cockatrice/src/interface/widgets/general/display/shadow_background_label.h @@ -15,6 +15,7 @@ class ShadowBackgroundLabel : public QLabel public: explicit ShadowBackgroundLabel(QWidget *parent, const QString &text); + void setLabelText(const QString &text); protected: void resizeEvent(QResizeEvent *event) override; diff --git a/cockatrice/src/interface/widgets/general/home_widget.cpp b/cockatrice/src/interface/widgets/general/home_widget.cpp index 2dfd129d5..88eec230c 100644 --- a/cockatrice/src/interface/widgets/general/home_widget.cpp +++ b/cockatrice/src/interface/widgets/general/home_widget.cpp @@ -196,6 +196,9 @@ QGroupBox *HomeWidget::createButtons() auto edhrecButton = new HomeStyledButton(tr("Browse EDHRec"), gradientColors); connect(edhrecButton, &QPushButton::clicked, tabSupervisor, &TabSupervisor::addEdhrecMainTab); boxLayout->addWidget(edhrecButton); + auto archidektButton = new HomeStyledButton(tr("Browse Archidekt"), gradientColors); + connect(archidektButton, &QPushButton::clicked, tabSupervisor, &TabSupervisor::addArchidektTab); + boxLayout->addWidget(archidektButton); auto replaybutton = new HomeStyledButton(tr("View Replays"), gradientColors); connect(replaybutton, &QPushButton::clicked, tabSupervisor, [this] { tabSupervisor->actTabReplays(true); }); boxLayout->addWidget(replaybutton); diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/archidekt_deck_listing_api_response.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/archidekt_deck_listing_api_response.cpp new file mode 100644 index 000000000..40882db04 --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/archidekt_deck_listing_api_response.cpp @@ -0,0 +1,29 @@ +#include "archidekt_deck_listing_api_response.h" + +#include +#include + +void ArchidektDeckListingApiResponse::fromJson(const QJsonObject &json) +{ + count = json.value("count").toInt(); + next = QUrl(json.value("next").toString()); + + QJsonArray containerJson = json.value("results").toArray(); + + for (const QJsonValue &deckListingValue : containerJson) { + ArchidektApiResponseDeckListingContainer listingResult; + listingResult.fromJson(deckListingValue.toObject()); + results.append(listingResult); + } +} + +void ArchidektDeckListingApiResponse::debugPrint() const +{ + qDebug() << "Count:" << count; + qDebug() << "Next:" << next; + + qDebug() << "Results:"; + for (const auto &deckListing : results) { + deckListing.debugPrint(); + } +} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/archidekt_deck_listing_api_response.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/archidekt_deck_listing_api_response.h new file mode 100644 index 000000000..723c65ce2 --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/archidekt_deck_listing_api_response.h @@ -0,0 +1,22 @@ +#ifndef COCKATRICE_ARCHIDEKT_DECK_LISTING_API_RESPONSE_H +#define COCKATRICE_ARCHIDEKT_DECK_LISTING_API_RESPONSE_H + +#include "deck_listings/archidekt_api_response_deck_listing_container.h" + +#include +#include +#include + +class ArchidektDeckListingApiResponse +{ + +public: + int count; + QUrl next; + QVector results; + + void fromJson(const QJsonObject &json); + void debugPrint() const; +}; + +#endif // COCKATRICE_DECK_LISTING_API_RESPONSE_H diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.cpp new file mode 100644 index 000000000..909c4d9eb --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.cpp @@ -0,0 +1,61 @@ +#include "archidekt_api_response_card.h" + +void ArchidektApiResponseCard::fromJson(const QJsonObject &json) +{ + id = json.value("id").toInt(); + artist = json.value("artist").toString(); + tcgProductId = json.value("tcgProductId").toInt(); + ckFoilId = json.value("ckFoilId").toInt(); + ckNormalId = json.value("ckNormalId").toInt(); + cmEd = json.value("cmEd").toString(); + scgSku = json.value("scgSku").toString(); + scgFoilSku = json.value("scgFoilSku").toString(); + collectorNumber = json.value("collectorNumber").toString(); + multiverseId = json.value("multiverseId").toInt(); + mtgoFoilId = json.value("mtgoFoilId").toInt(); + mtgoNormalId = json.value("mtgoNormalId").toInt(); + uid = json.value("uid").toString(); + displayName = json.value("displayName").toString(); + releasedAt = json.value("releasedAt").toString(); + + edition.fromJson(json.value("edition").toObject()); + + flavor = json.value("flavor").toString(); + // TODO but not really important + // games = {""}; + // options = {""}; + scryfallImageHash = json.value("scryfallImageHash").toString(); + oracleCard = json.value("oracleCard").toObject(); + owned = json.value("owned").toInt(); + pinnedStatus = json.value("pinnedStatus").toInt(); + rarity = json.value("rarity").toString(); + // TODO but not really important + // globalCategories = {""}; +} + +void ArchidektApiResponseCard::debugPrint() const +{ + qDebug() << "Id:" << id; + qDebug() << "id:" << artist; + qDebug() << "artist:" << tcgProductId; + qDebug() << "tcgProductId:" << ckFoilId; + qDebug() << "ckFoilId:" << ckNormalId; + qDebug() << "ckNormalId:" << cmEd; + qDebug() << "cmEd:" << scgSku; + qDebug() << "scgSku:" << scgFoilSku; + qDebug() << "scgFoilSku:" << collectorNumber; + qDebug() << "collectorNumber:" << multiverseId; + qDebug() << "multiverseId:" << mtgoFoilId; + qDebug() << "mtgoFoilId:" << mtgoNormalId; + qDebug() << "mtgoNormalId:" << uid; + qDebug() << "uid:" << displayName; + qDebug() << "displayName:" << releasedAt; + qDebug() << "releasedAt:" << flavor; + qDebug() << "flavor:" << games; + qDebug() << "games:" << options; + qDebug() << "options:" << scryfallImageHash; + qDebug() << "scryfallImageHash:" << owned; + qDebug() << "owned:" << pinnedStatus; + qDebug() << "pinnedStatus:" << rarity; + qDebug() << "rarity:" << globalCategories; +} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.h new file mode 100644 index 000000000..265498228 --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.h @@ -0,0 +1,68 @@ +#ifndef COCKATRICE_ARCHIDEKT_API_RESPONSE_CARD_H +#define COCKATRICE_ARCHIDEKT_API_RESPONSE_CARD_H + +#include "archidekt_api_response_edition.h" + +#include +#include +#include +#include +#include + +class ArchidektApiResponseCard +{ +public: + // Constructor + ArchidektApiResponseCard() = default; + + // Parse deck-related data from JSON + void fromJson(const QJsonObject &json); + + // Debug method for logging + void debugPrint() const; + + QJsonObject getOracleCard() const + { + return oracleCard; + }; + + QString getCollectorNumber() const + { + return collectorNumber; + } + + ArchidektApiResponseEdition getEdition() const + { + return edition; + } + +private: + int id; + QString artist; + int tcgProductId; + int ckFoilId; + int ckNormalId; + QString cmEd; + QString scgSku; + QString scgFoilSku; + QString collectorNumber; + int multiverseId; + int mtgoFoilId; + int mtgoNormalId; + QString uid; + QString displayName; + QString releasedAt; + ArchidektApiResponseEdition edition; + QString flavor; + QStringList games; + QStringList options; + QString scryfallImageHash; + QJsonObject oracleCard; + int owned; + int pinnedStatus; + // ArchidektApiResponsePrices prices; + QString rarity; + QStringList globalCategories; +}; + +#endif // COCKATRICE_ARCHIDEKT_API_RESPONSE_CARD_H diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card_entry.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card_entry.cpp new file mode 100644 index 000000000..7a424de8b --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card_entry.cpp @@ -0,0 +1,43 @@ +#include "archidekt_api_response_card_entry.h" + +void ArchidektApiResponseCardEntry::fromJson(const QJsonObject &json) +{ + id = json.value("id").toInt(); + + auto categoriesJson = json.value("categories").toArray(); + + for (auto category : categoriesJson) { + categories.append(category.toString()); + } + + companion = json.value("companion").toBool(); + flippedDefault = json.value("flippedDefault").toBool(); + label = json.value("label").toString(); + modifier = json.value("modifier").toString(); + quantity = json.value("quantity").toInt(); + customCmc = json.value("customCmc").toInt(); + // removedCategories = {""}; + createdAt = json.value("createdAt").toString(); + updatedAt = json.value("updatedAt").toString(); + deletedAt = json.value("deletedAt").toString(); + notes = json.value("notes").toString(); + card.fromJson(json.value("card").toObject()); +} + +void ArchidektApiResponseCardEntry::debugPrint() const +{ + qDebug() << "Id:" << id; + qDebug() << "Categories:" << categories; + qDebug() << "Companion:" << companion; + qDebug() << "FlippedDefault:" << flippedDefault; + qDebug() << "Label:" << label; + qDebug() << "Modifier:" << modifier; + qDebug() << "Quantity:" << quantity; + qDebug() << "CustomCmc:" << customCmc; + qDebug() << "RemovedCategories:" << removedCategories; + qDebug() << "CreatedAt:" << createdAt; + qDebug() << "UpdatedAt:" << updatedAt; + qDebug() << "DeletedAt:" << deletedAt; + qDebug() << "Notes:" << notes; + card.debugPrint(); +} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card_entry.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card_entry.h new file mode 100644 index 000000000..f7f86e9ed --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card_entry.h @@ -0,0 +1,56 @@ +#ifndef COCKATRICE_ARCHIDEKT_API_RESPONSE_CARD_ENTRY_H +#define COCKATRICE_ARCHIDEKT_API_RESPONSE_CARD_ENTRY_H + +#include "archidekt_api_response_card.h" + +#include +#include +#include +#include +#include + +class ArchidektApiResponseCardEntry +{ +public: + // Constructor + ArchidektApiResponseCardEntry() = default; + + // Parse deck-related data from JSON + void fromJson(const QJsonObject &json); + + // Debug method for logging + void debugPrint() const; + + ArchidektApiResponseCard getCard() const + { + return card; + }; + + QStringList getCategories() const + { + return categories; + } + + int getQuantity() const + { + return quantity; + } + +private: + int id; + QStringList categories; + bool companion; + bool flippedDefault; + QString label; + QString modifier; + int quantity; + int customCmc; + QStringList removedCategories; + QString createdAt; + QString updatedAt; + QString deletedAt; + QString notes; + ArchidektApiResponseCard card; +}; + +#endif // COCKATRICE_ARCHIDEKT_API_RESPONSE_CARD_ENTRY_H diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_edition.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_edition.cpp new file mode 100644 index 000000000..122617a22 --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_edition.cpp @@ -0,0 +1,19 @@ +#include "archidekt_api_response_edition.h" + +void ArchidektApiResponseEdition::fromJson(const QJsonObject &json) +{ + editionCode = json.value("editioncode").toString(); + editionName = json.value("editionname").toString(); + editionDate = json.value("editiondate").toString(); + editionType = json.value("editiontype").toString(); + mtgoCode = json.value("mtgocode").toString(); +} + +void ArchidektApiResponseEdition::debugPrint() const +{ + qDebug() << "Edition Code: " << editionCode; + qDebug() << "Edition Name: " << editionName; + qDebug() << "Edition Date: " << editionDate; + qDebug() << "Edition Type: " << editionType; + qDebug() << "Mtgo Code: " << mtgoCode; +} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_edition.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_edition.h new file mode 100644 index 000000000..b898cd816 --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_edition.h @@ -0,0 +1,51 @@ +#ifndef COCKATRICE_ARCHIDEKT_API_RESPONSE_EDITION_H +#define COCKATRICE_ARCHIDEKT_API_RESPONSE_EDITION_H + +#include +#include +#include +#include +#include + +class ArchidektApiResponseEdition +{ +public: + // Constructor + ArchidektApiResponseEdition() = default; + + // Parse deck-related data from JSON + void fromJson(const QJsonObject &json); + + // Debug method for logging + void debugPrint() const; + + [[nodiscard]] QString getEditionCode() const + { + return editionCode; + } + [[nodiscard]] QString getEditionName() const + { + return editionName; + } + [[nodiscard]] QString getEditionDate() const + { + return editionDate; + } + [[nodiscard]] QString getEditionType() const + { + return editionType; + } + [[nodiscard]] QString getMtgoCode() const + { + return mtgoCode; + } + +private: + QString editionCode; + QString editionName; + QString editionDate; + QString editionType; + QString mtgoCode; +}; + +#endif // COCKATRICE_ARCHIDEKT_API_RESPONSE_EDITION_H diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.cpp new file mode 100644 index 000000000..98d8c6c8c --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.cpp @@ -0,0 +1,79 @@ +#include "archidekt_api_response_deck.h" + +#include "../card/archidekt_api_response_card_entry.h" + +void ArchidektApiResponseDeck::fromJson(const QJsonObject &json) +{ + id = json.value("id").toInt(); + name = json.value("name").toString(); + size = json.value("size").toInt(); + updatedAt = json.value("updatedAt").toString(); + createdAt = json.value("createdAt").toString(); + deckFormat = json.value("deckFormat").toInt(); + edhBracket = json.value("edhBracket").toInt(); + featured = json.value("featured").toString(); + customFeatured = json.value("customFeatured").toString(); + viewCount = json.value("viewCount").toInt(); + privateDeck = json.value("private").toBool(); + unlisted = json.value("unlisted").toBool(); + theoryCrafted = json.value("theoryCrafted").toBool(); + points = json.value("points").toInt(); + userInput = json.value("userInput").toInt(); + owner.fromJson(json.value("owner").toObject()); + commentRoot = json.value("commentRoot").toInt(); + editors = json.value("editors").toString(); + parentFolderId = json.value("parentFolderId").toInt(); + bookmarked = json.value("bookmarked").toBool(); + + auto categoriesJson = json.value("categories").toArray(); + for (auto category : categoriesJson) { + ArchidektApiResponseDeckCategory categoryEntry; + categoryEntry.fromJson(category.toObject()); + categories.append(categoryEntry); + } + + // deckTags = {""}; + playgroupDeckUrl = json.value("playgroupDeckUrl").toString(); + cardPackage = json.value("cardPackage").toString(); + + auto cardsObject = json.value("cards").toArray(); + + for (auto card : cardsObject) { + ArchidektApiResponseCardEntry entry; + entry.fromJson(card.toObject()); + cards.append(entry); + } + + // TODO but not really important + // customCards = {""}; +} + +void ArchidektApiResponseDeck::debugPrint() const +{ + qDebug() << "Id:" << id; + qDebug() << "Name:" << name; + qDebug() << "Size:" << size; + qDebug() << "UpdatedAt:" << updatedAt; + qDebug() << "CreatedAt:" << createdAt; + qDebug() << "DeckFormat:" << deckFormat; + qDebug() << "EdhBracket:" << edhBracket; + qDebug() << "Featured:" << featured; + qDebug() << "CustomFeatured:" << customFeatured; + qDebug() << "ViewCount:" << viewCount; + qDebug() << "Private:" << privateDeck; + qDebug() << "Unlisted:" << unlisted; + qDebug() << "TheoryCrafted:" << theoryCrafted; + qDebug() << "Points:" << points; + qDebug() << "UserInput:" << userInput; + owner.debugPrint(); + qDebug() << "CommentRoot:" << commentRoot; + qDebug() << "Editors:" << editors; + qDebug() << "ParentFolderId:" << parentFolderId; + qDebug() << "Bookmarked:" << bookmarked; + qDebug() << "DeckTags:" << deckTags; + qDebug() << "PlaygroupDeckUrl:" << playgroupDeckUrl; + qDebug() << "CardPackage:" << cardPackage; + for (auto card : cards) { + card.debugPrint(); + } +} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.h new file mode 100644 index 000000000..8cb81cac3 --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.h @@ -0,0 +1,71 @@ +#ifndef COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_H +#define COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_H + +#include "../card/archidekt_api_response_card.h" +#include "../card/archidekt_api_response_card_entry.h" +#include "../deck_listings/archidekt_api_response_deck_owner.h" +#include "archidekt_api_response_deck_category.h" + +#include +#include +#include +#include +#include + +class ArchidektApiResponseDeck +{ +public: + // Constructor + ArchidektApiResponseDeck() = default; + + // Parse deck-related data from JSON + void fromJson(const QJsonObject &json); + + // Debug method for logging + void debugPrint() const; + + QVector getCards() const + { + return cards; + }; + + QVector getCategories() const + { + return categories; + } + + QString getDeckName() const + { + return name; + }; + +private: + int id; + QString name; + int size; + QString updatedAt; + QString createdAt; + int deckFormat; + int edhBracket; + QString featured; + QString customFeatured; + int viewCount; + bool privateDeck; + bool unlisted; + bool theoryCrafted; + int points; + int userInput; + ArchidektApiResponseDeckOwner owner; + int commentRoot; + QString editors; + int parentFolderId; + bool bookmarked; + QVector categories; + QStringList deckTags; + QString playgroupDeckUrl; + QString cardPackage; + QVector cards; + QStringList customCards; +}; + +#endif // COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_H diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck_category.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck_category.cpp new file mode 100644 index 000000000..990293bc6 --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck_category.cpp @@ -0,0 +1,19 @@ +#include "archidekt_api_response_deck_category.h" + +void ArchidektApiResponseDeckCategory::fromJson(const QJsonObject &json) +{ + id = json.value("id").toInt(); + name = json.value("name").toString(); + isPremier = json.value("isPremier").toBool(); + includedInDeck = json.value("includedInDeck").toBool(); + includedInPrice = json.value("includedInPrice").toBool(); +} + +void ArchidektApiResponseDeckCategory::debugPrint() const +{ + qDebug() << "Id:" << id; + qDebug() << "Name:" << name; + qDebug() << "isPremier:" << isPremier; + qDebug() << "IncludedInDeck:" << includedInDeck; + qDebug() << "IncludedInPrice:" << includedInPrice; +} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck_category.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck_category.h new file mode 100644 index 000000000..5e218b6a4 --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck_category.h @@ -0,0 +1,55 @@ +#ifndef COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_CATEGORY_H +#define COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_CATEGORY_H + +#include "../card/archidekt_api_response_card.h" +#include "../card/archidekt_api_response_card_entry.h" +#include "../deck_listings/archidekt_api_response_deck_owner.h" + +#include +#include +#include +#include +#include + +class ArchidektApiResponseDeckCategory +{ +public: + // Constructor + ArchidektApiResponseDeckCategory() = default; + + // Parse deck-related data from JSON + void fromJson(const QJsonObject &json); + + // Debug method for logging + void debugPrint() const; + + [[nodiscard]] int getId() const + { + return id; + } + [[nodiscard]] QString getName() const + { + return name; + } + [[nodiscard]] bool getIsPremier() const + { + return isPremier; + } + [[nodiscard]] bool getIncludedInDeck() const + { + return includedInDeck; + } + [[nodiscard]] bool getIncludedInPrice() const + { + return includedInPrice; + } + +private: + int id; + QString name; + bool isPremier; + bool includedInDeck; + bool includedInPrice; +}; + +#endif // COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_CATEGORY_H diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_listing_container.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_listing_container.cpp new file mode 100644 index 000000000..16ea60487 --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_listing_container.cpp @@ -0,0 +1,64 @@ +#include "archidekt_api_response_deck_listing_container.h" + +#include "archidekt_api_response_deck_owner.h" + +#include +#include +#include + +void ArchidektApiResponseDeckListingContainer::fromJson(const QJsonObject &json) +{ + id = json.value("id").toInt(); + name = json.value("name").toString(); + size = json.value("size").toInt(); + updatedAt = json.value("updatedAt").toString(); + createdAt = json.value("createdAt").toString(); + deckFormat = json.value("deckFormat").toInt(); + edhBracket = json.value("edhBracket").toInt(); + featured = json.value("featured").toString(); + customFeatured = json.value("customFeatured").toString(); + viewCount = json.value("viewCount").toInt(); + privateDeck = json.value("private").toBool(); + unlisted = json.value("unlisted").toBool(); + theoryCrafted = json.value("theoryCrafted").toBool(); + game = json.value("game").toString(); + hasDescription = json.value("hasDescription").toBool(); + // TODO + // tags = {""}; + parentFolderId = json.value("parentFolderId").toInt(); + owner.fromJson(json.value("owner").toObject()); + + auto colorsJson = json.value("colors").toObject(); + + for (auto color : colorsJson.keys()) { + colors[color] = colorsJson[color].toInt(); + } + + cardPackage = json.value("cardPackage").toString(); + contest = json.value("contest").toString(); +} + +void ArchidektApiResponseDeckListingContainer::debugPrint() const +{ + qDebug() << "Id:" << id; + qDebug() << "Name:" << name; + qDebug() << "Size:" << size; + qDebug() << "UpdatedAt:" << updatedAt; + qDebug() << "CreatedAt:" << createdAt; + qDebug() << "DeckFormat:" << deckFormat; + qDebug() << "EdhBracket:" << edhBracket; + qDebug() << "Featured:" << featured; + qDebug() << "CustomFeatured:" << customFeatured; + qDebug() << "ViewCount:" << viewCount; + qDebug() << "Private:" << privateDeck; + qDebug() << "Unlisted:" << unlisted; + qDebug() << "TheoryCrafted:" << theoryCrafted; + qDebug() << "Game:" << game; + qDebug() << "HasDescription:" << hasDescription; + qDebug() << "Tags:" << tags; + qDebug() << "ParentFolderId:" << parentFolderId; + owner.debugPrint(); + qDebug() << "Colors:" << colors; + qDebug() << "CardPackage" << cardPackage; + qDebug() << "Contest:" << contest; +} diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_listing_container.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_listing_container.h new file mode 100644 index 000000000..8924bb3f5 --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_listing_container.h @@ -0,0 +1,133 @@ +#ifndef COCKATRICE_ARCHIDEKT_DECK_LISTING_API_RESPONSE_CONTAINER_H +#define COCKATRICE_ARCHIDEKT_DECK_LISTING_API_RESPONSE_CONTAINER_H + +#include "archidekt_api_response_deck_owner.h" + +#include +#include +#include +#include +#include + +class ArchidektApiResponseDeckListingContainer +{ +public: + // Constructor + ArchidektApiResponseDeckListingContainer() = default; + + // Parse deck-related data from JSON + void fromJson(const QJsonObject &json); + + // Debug method for logging + void debugPrint() const; + + [[nodiscard]] int getId() const + { + return id; + } + [[nodiscard]] QString getName() const + { + return name; + } + [[nodiscard]] int getSize() const + { + return size; + } + [[nodiscard]] QString getUpdatedAt() const + { + return updatedAt; + } + [[nodiscard]] QString getCreatedAt() const + { + return createdAt; + } + [[nodiscard]] int getDeckFormat() const + { + return deckFormat; + } + [[nodiscard]] int getEDHBracket() const + { + return edhBracket; + } + [[nodiscard]] QString getFeatured() const + { + return featured; + } + [[nodiscard]] QString getCustomFeatured() const + { + return customFeatured; + } + [[nodiscard]] int getViewCount() const + { + return viewCount; + } + [[nodiscard]] bool getPrivateDeck() const + { + return privateDeck; + } + [[nodiscard]] bool getUnlisted() const + { + return unlisted; + } + [[nodiscard]] bool getTheoryCrafted() const + { + return theoryCrafted; + } + [[nodiscard]] QString getGame() const + { + return game; + } + [[nodiscard]] bool getHasDescription() const + { + return hasDescription; + } + [[nodiscard]] QStringList getTags() const + { + return tags; + } + [[nodiscard]] int getParentFolderId() const + { + return parentFolderId; + } + [[nodiscard]] ArchidektApiResponseDeckOwner getOwner() const + { + return owner; + } + [[nodiscard]] QMap getColors() const + { + return colors; + } + [[nodiscard]] QString getCardPackage() const + { + return cardPackage; + } + [[nodiscard]] QString getContest() const + { + return contest; + } + +private: + int id; + QString name; + int size; + QString updatedAt; + QString createdAt; + int deckFormat; + int edhBracket; + QString featured; + QString customFeatured; + int viewCount; + bool privateDeck; + bool unlisted; + bool theoryCrafted; + QString game; + bool hasDescription; + QStringList tags; + int parentFolderId; + ArchidektApiResponseDeckOwner owner; + QMap colors; + QString cardPackage; + QString contest; +}; + +#endif // COCKATRICE_ARCHIDEKT_DECK_LISTING_API_RESPONSE_CONTAINER_H diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_owner.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_owner.cpp new file mode 100644 index 000000000..2ba926f8b --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_owner.cpp @@ -0,0 +1,22 @@ +#include "archidekt_api_response_deck_owner.h" + +void ArchidektApiResponseDeckOwner::fromJson(const QJsonObject &json) +{ + id = json.value("id").toInt(); + userName = json.value("username").toString(); + avatar = QUrl(json.value("avatar").toString()); + moderator = json.value("moderator").toBool(); + pledgeLevel = json.value("pledgeLevel").toInt(); + // TODO but not really important + // roles = {""}; +} + +void ArchidektApiResponseDeckOwner::debugPrint() const +{ + qDebug() << "Id:" << id; + qDebug() << "UserName:" << userName; + qDebug() << "Avatar:" << avatar; + qDebug() << "Moderator:" << moderator; + qDebug() << "PledgeLevel:" << pledgeLevel; + qDebug() << "Roles:" << roles; +} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_owner.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_owner.h new file mode 100644 index 000000000..df3f48fd2 --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_owner.h @@ -0,0 +1,36 @@ +#ifndef COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_OWNER_H +#define COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_OWNER_H + +#include +#include +#include +#include +#include + +class ArchidektApiResponseDeckOwner +{ +public: + // Constructor + ArchidektApiResponseDeckOwner() = default; + + // Parse deck-related data from JSON + void fromJson(const QJsonObject &json); + + // Debug method for logging + void debugPrint() const; + + [[nodiscard]] QString getName() const + { + return userName; + } + +private: + int id; + QString userName; + QUrl avatar; + bool moderator; + int pledgeLevel; + QStringList roles; +}; + +#endif // COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_OWNER_H diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_display_widget.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_display_widget.cpp new file mode 100644 index 000000000..33ee67a1f --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_display_widget.cpp @@ -0,0 +1,157 @@ +#include "archidekt_api_response_deck_display_widget.h" + +#include "../../../../../deck_loader/deck_loader.h" +#include "../../../../cards/card_info_picture_with_text_overlay_widget.h" +#include "../../../../cards/card_size_widget.h" +#include "../../../../cards/deck_card_zone_display_widget.h" +#include "../../../../visual_deck_editor/visual_deck_display_options_widget.h" +#include "../api_response/deck/archidekt_api_response_deck.h" + +#include +#include + +ArchidektApiResponseDeckDisplayWidget::ArchidektApiResponseDeckDisplayWidget(QWidget *parent, + ArchidektApiResponseDeck _response, + CardSizeWidget *_cardSizeSlider) + : QWidget(parent), response(_response), cardSizeSlider(_cardSizeSlider) +{ + layout = new QVBoxLayout(this); + setLayout(layout); + + openInEditorButton = new QPushButton(this); + layout->addWidget(openInEditorButton); + + connect(openInEditorButton, &QPushButton::clicked, this, + &ArchidektApiResponseDeckDisplayWidget::actOpenInDeckEditor); + + displayOptionsWidget = new VisualDeckDisplayOptionsWidget(this); + layout->addWidget(displayOptionsWidget); + + connect(displayOptionsWidget, &VisualDeckDisplayOptionsWidget::groupCriteriaChanged, this, + &ArchidektApiResponseDeckDisplayWidget::onGroupCriteriaChange); + + scrollArea = new QScrollArea(this); + scrollArea->setWidgetResizable(true); + scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + + layout->addWidget(scrollArea); + + container = new QWidget(scrollArea); + + scrollArea->setWidget(container); + + containerLayout = new QVBoxLayout(container); + container->setLayout(containerLayout); + + zoneContainer = new QWidget(container); + containerLayout->addWidget(zoneContainer); + zoneContainerLayout = new QVBoxLayout(zoneContainer); + zoneContainer->setLayout(zoneContainerLayout); + + QString tempDeck; + QTextStream deckStream(&tempDeck); + + for (auto card : response.getCards()) { + QString fullName = card.getCard().getOracleCard().value("name").toString(); + // We don't really care about the second card, the card database already has it as a relation + QString cleanName = fullName.split("//").first().trimmed(); + + tempDeck += QString("%1 %2 (%3) %4\n") + .arg(card.getQuantity()) + .arg(cleanName) + .arg(card.getCard().getEdition().getEditionCode().toUpper()) + .arg(card.getCard().getCollectorNumber()); + } + + model = new DeckListModel(this); + connect(model, &DeckListModel::modelReset, this, &ArchidektApiResponseDeckDisplayWidget::decklistModelReset); + model->getDeckList()->loadFromStream_Plain(deckStream, false); + + DeckLoader::resolveSetNameAndNumberToProviderID(model->getDeckList()); + + model->rebuildTree(); + + retranslateUi(); +} + +void ArchidektApiResponseDeckDisplayWidget::retranslateUi() +{ + openInEditorButton->setText(tr("Open Deck in Deck Editor")); +} + +void ArchidektApiResponseDeckDisplayWidget::onGroupCriteriaChange(const QString &activeGroupCriteria) +{ + model->setActiveGroupCriteria(DeckListModelGroupCriteria::fromString(activeGroupCriteria)); + model->sort(1, Qt::AscendingOrder); +} + +void ArchidektApiResponseDeckDisplayWidget::actOpenInDeckEditor() +{ + auto loader = new DeckLoader(this); + loader->getDeckList()->loadFromString_Native(model->getDeckList()->writeToString_Native()); + + loader->getDeckList()->setName(response.getDeckName()); + + emit openInDeckEditor(loader); +} + +void ArchidektApiResponseDeckDisplayWidget::clearAllDisplayWidgets() +{ + for (auto idx : indexToWidgetMap.keys()) { + auto displayWidget = indexToWidgetMap.value(idx); + zoneContainerLayout->removeWidget(displayWidget); + indexToWidgetMap.remove(idx); + delete displayWidget; + } +} + +void ArchidektApiResponseDeckDisplayWidget::decklistModelReset() +{ + clearAllDisplayWidgets(); + constructZoneWidgetsFromDeckListModel(); +} + +void ArchidektApiResponseDeckDisplayWidget::constructZoneWidgetsFromDeckListModel() +{ + qDebug() << model->rowCount(model->getRoot()); + QSortFilterProxyModel proxy; + proxy.setSourceModel(model); + proxy.setSortRole(Qt::EditRole); + proxy.sort(1, Qt::AscendingOrder); + + for (int i = 0; i < proxy.rowCount(); ++i) { + QModelIndex proxyIndex = proxy.index(i, 0); + QModelIndex sourceIndex = proxy.mapToSource(proxyIndex); + + // Make a persistent index from the *source* model + QPersistentModelIndex persistent(sourceIndex); + + if (indexToWidgetMap.contains(persistent)) { + continue; + } + + DeckCardZoneDisplayWidget *zoneDisplayWidget = + new DeckCardZoneDisplayWidget(zoneContainer, model, nullptr, persistent, + model->data(persistent.sibling(persistent.row(), 1), Qt::EditRole).toString(), + "maintype", {"name"}, DisplayType::Overlap, 20, 10, cardSizeSlider); + + connect(displayOptionsWidget, &VisualDeckDisplayOptionsWidget::sortCriteriaChanged, zoneDisplayWidget, + &DeckCardZoneDisplayWidget::onActiveSortCriteriaChanged); + connect(displayOptionsWidget, &VisualDeckDisplayOptionsWidget::groupCriteriaChanged, zoneDisplayWidget, + &DeckCardZoneDisplayWidget::onActiveGroupCriteriaChanged); + connect(displayOptionsWidget, &VisualDeckDisplayOptionsWidget::displayTypeChanged, zoneDisplayWidget, + &DeckCardZoneDisplayWidget::refreshDisplayType); + zoneContainerLayout->addWidget(zoneDisplayWidget); + + indexToWidgetMap.insert(persistent, zoneDisplayWidget); + } +} + +void ArchidektApiResponseDeckDisplayWidget::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); + layout->invalidate(); + layout->activate(); + layout->update(); +} diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_display_widget.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_display_widget.h new file mode 100644 index 000000000..3d624d293 --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_display_widget.h @@ -0,0 +1,125 @@ +#ifndef COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_DISPLAY_WIDGET_H +#define COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_DISPLAY_WIDGET_H + +#include "../../../../../deck_loader/deck_loader.h" +#include "../../../../cards/card_size_widget.h" +#include "../../../../general/layout_containers/flow_widget.h" +#include "../../../../visual_deck_editor/visual_deck_display_options_widget.h" +#include "../api_response/deck/archidekt_api_response_deck.h" +#include "deck_list_model.h" + +#include +#include +#include +#include +#include + +/** + * @class ArchidektApiResponseDeckDisplayWidget + * @brief Displays a full deck fetched from an Archidekt API response. + * + * This widget visualizes all cards in a deck retrieved from the Archidekt API. + * It supports: + * - Interactive display options via a VisualDeckDisplayOptionsWidget. + * - Scrollable display of deck zones/cards with DeckCardZoneDisplayWidget. + * - Integration with a CardSizeWidget slider for card scaling. + * - Opening the deck in a deck editor. + * + * The widget internally constructs a DeckListModel from the Archidekt API response, + * then builds zone widgets for each group of cards according to the active group + * criteria. It also responds dynamically to model resets or sorting/grouping changes. + * + * ### Signals + * - `requestNavigation(QString url)` — triggered when navigation to a deck URL is requested. + * - `openInDeckEditor(DeckLoader *loader)` — emitted when the user chooses to open the deck + * in the deck editor. + * + * ### Features + * - Automatically generates DeckCardZoneDisplayWidget instances for each card group. + * - Provides a scrollable layout for decks of arbitrary size. + * - Updates layouts dynamically when resized or when display/group/sort criteria change. + */ +class ArchidektApiResponseDeckDisplayWidget : public QWidget +{ + Q_OBJECT + +signals: + /** + * @brief Emitted when navigation to a deck URL is requested. + * @param url URL of the deck on Archidekt. + */ + void requestNavigation(QString url); + + /** + * @brief Emitted when the deck should be opened in the deck editor. + * @param loader Initialized DeckLoader containing the deck data. + */ + void openInDeckEditor(DeckLoader *loader); + +public: + /** + * @brief Constructs a display widget for an Archidekt deck. + * @param parent Parent widget. + * @param response API deck data container. + * @param cardSizeSlider Slider controlling card scaling. + */ + explicit ArchidektApiResponseDeckDisplayWidget(QWidget *parent, + ArchidektApiResponseDeck response, + CardSizeWidget *cardSizeSlider); + + /** + * @brief Updates all UI text for retranslation/localization. + * + * Called when the application language changes. + */ + void retranslateUi(); + + /** + * @brief Opens the deck in the deck editor via DeckLoader. + */ + void actOpenInDeckEditor(); + + /** + * @brief Clears all dynamically generated card zone display widgets. + */ + void clearAllDisplayWidgets(); + + /** + * @brief Handles model reset by clearing and reconstructing display widgets. + */ + void decklistModelReset(); + + /** + * @brief Builds DeckCardZoneDisplayWidget instances from the current DeckListModel. + */ + void constructZoneWidgetsFromDeckListModel(); + +private slots: + /** + * @brief Slot triggered when the active group criteria change. + * @param activeGroupCriteria Name of the new grouping criteria. + */ + void onGroupCriteriaChange(const QString &activeGroupCriteria); + +private: + ArchidektApiResponseDeck response; ///< API deck data container + CardSizeWidget *cardSizeSlider; ///< Slider for adjusting card sizes + QVBoxLayout *layout; ///< Main vertical layout + QPushButton *openInEditorButton; ///< Button to open deck in editor + VisualDeckDisplayOptionsWidget *displayOptionsWidget; ///< Controls grouping/sorting/display + QScrollArea *scrollArea; ///< Scrollable area for deck zones + QWidget *zoneContainer; ///< Container for deck zones + QVBoxLayout *zoneContainerLayout; ///< Layout for deck zones + QWidget *container; ///< Outer container for scroll area + QHash indexToWidgetMap; ///< Maps model indices to widgets + QVBoxLayout *containerLayout; ///< Layout for container + DeckListModel *model; ///< Deck list model +protected slots: + /** + * @brief Updates layout and display on resize. + * @param event Resize event. + */ + void resizeEvent(QResizeEvent *event) override; +}; + +#endif // COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.cpp new file mode 100644 index 000000000..1b633c4d3 --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.cpp @@ -0,0 +1,235 @@ +#include "archidekt_api_response_deck_entry_display_widget.h" + +#include "../../../../../card_picture_loader/card_picture_loader.h" +#include "../../../../cards/card_info_picture_with_text_overlay_widget.h" +#include "../../../../general/display/background_plate_widget.h" +#include "../../../../general/display/color_bar.h" +#include "archidekt_deck_preview_image_display_widget.h" + +#include +#include +#include +#include +#include +#include + +#define ARCHIDEKT_DEFAULT_IMAGE "https://storage.googleapis.com/topdekt-user/images/archidekt_deck_card_shadow.jpg" + +QString timeAgo(const QString ×tamp) +{ + QDateTime dt = QDateTime::fromString(timestamp, Qt::ISODate); + + if (!dt.isValid()) + return timestamp; // fallback if parsing fails + + qint64 secs = dt.secsTo(QDateTime::currentDateTimeUtc()); + + if (secs < 60) + return QString("%1 seconds ago").arg(secs); + if (secs < 3600) + return QString("%1 minutes ago").arg(secs / 60); + if (secs < 86400) + return QString("%1 hours ago").arg(secs / 3600); + if (secs < 30 * 86400) + return QString("%1 days ago").arg(secs / 86400); + if (secs < 365 * 86400) + return QString("%1 months ago").arg(secs / (30 * 86400)); + + return QString("%1 years ago").arg(secs / (365 * 86400)); +} + +ArchidektApiResponseDeckEntryDisplayWidget::ArchidektApiResponseDeckEntryDisplayWidget( + QWidget *parent, + ArchidektApiResponseDeckListingContainer _response, + QNetworkAccessManager *_imageNetworkManager) + : QWidget(parent), response(_response), imageNetworkManager(_imageNetworkManager) +{ + layout = new QVBoxLayout(this); + setLayout(layout); + + this->setMaximumWidth(400); + this->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); + + auto headerLayout = new QVBoxLayout(); + + previewWidget = new ArchidektDeckPreviewImageDisplayWidget(this); + + previewWidget->setMaximumWidth(400); + previewWidget->setMinimumHeight(300); // consistent height + + // Set deck name (ellided) + QFontMetrics fm(previewWidget->topLeftLabel->font()); + QString elided = fm.elidedText(response.getName(), Qt::ElideRight, 280); + previewWidget->topLeftLabel->setLabelText(elided); + previewWidget->topLeftLabel->setToolTip(response.getName()); + + // Set count + previewWidget->topRightLabel->setLabelText(QString::number(response.getSize())); + + // EDH bracket (skip if 0) + if (response.getEDHBracket() != 0) { + previewWidget->bottomLeftLabel->setLabelText(QString("EDH: %1").arg(response.getEDHBracket())); + } else { + previewWidget->bottomLeftLabel->hide(); + } + + // Views + previewWidget->bottomRightLabel->setLabelText(QString("Views: %1").arg(response.getViewCount())); + + // Use preview->imageLabel for image loading + picture = previewWidget->imageLabel; + + imageUrl = response.getFeatured().isEmpty() ? QUrl(ARCHIDEKT_DEFAULT_IMAGE) : QUrl(response.getFeatured()); + + QNetworkRequest req(imageUrl); + QNetworkReply *reply = imageNetworkManager->get(req); + + // tag the reply with "this" so we know it belongs to us later + reply->setProperty("deckWidget", QVariant::fromValue(this)); + reply->setProperty("requestedUrl", imageUrl); + + connect(imageNetworkManager, &QNetworkAccessManager::finished, this, + &ArchidektApiResponseDeckEntryDisplayWidget::onPreviewImageLoadFinished); + + headerLayout->addWidget(previewWidget); + + auto colors = response.getColors(); + + ColorBar *colorBar = new ColorBar(colors, this); + colorBar->setMinPercentThreshold(3); + colorBar->setFixedHeight(22); + + headerLayout->addWidget(colorBar); + + // Create a shared plate for the labels + backgroundPlateWidget = new BackgroundPlateWidget(this); + backgroundPlateWidget->setFixedHeight(120); // Adjust height to fit all labels + + QVBoxLayout *plateLayout = new QVBoxLayout(backgroundPlateWidget); + + // Add labels to the plate layout + QLabel *ownerLabel = new QLabel(QString("Owner: %1").arg(response.getOwner().getName())); + plateLayout->addWidget(ownerLabel); + + QLabel *createdAtLabel = new QLabel(QString("Created: %1").arg(timeAgo(response.getCreatedAt()))); + plateLayout->addWidget(createdAtLabel); + + QLabel *updatedAtLabel = new QLabel(QString("Updated: %1").arg(timeAgo(response.getUpdatedAt()))); + plateLayout->addWidget(updatedAtLabel); + + // Add the shared plate to the header layout + headerLayout->addWidget(backgroundPlateWidget); + + layout->addLayout(headerLayout); +} + +void ArchidektApiResponseDeckEntryDisplayWidget::mousePressEvent(QMouseEvent *event) +{ + QWidget::mousePressEvent(event); + actRequestNavigationToDeck(); +} + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +void ArchidektApiResponseDeckEntryDisplayWidget::enterEvent(QEnterEvent *event) +#else +void ArchidektApiResponseDeckEntryDisplayWidget::enterEvent(QEvent *event) +#endif +{ + QWidget::enterEvent(event); + backgroundPlateWidget->setFocused(true); +} + +void ArchidektApiResponseDeckEntryDisplayWidget::leaveEvent(QEvent *event) +{ + QWidget::leaveEvent(event); + backgroundPlateWidget->setFocused(false); +} + +void ArchidektApiResponseDeckEntryDisplayWidget::setScaleFactor(int scale) +{ + scaleFactor = scale; + updateScaledPreview(); +} + +void ArchidektApiResponseDeckEntryDisplayWidget::onPreviewImageLoadFinished(QNetworkReply *reply) +{ + // Check if this is our reply + void *owner = reply->property("deckWidget").value(); + if (owner != this) { + return; // not our reply + } + + // Check that the requested URL matches what we asked + QUrl requestedUrl = reply->property("requestedUrl").toUrl(); + if (requestedUrl != imageUrl) { + reply->deleteLater(); + return; + } + + QPixmap loaded; + + if (reply->error() != QNetworkReply::NoError || !loaded.loadFromData(reply->readAll())) { + CardPictureLoader::getCardBackLoadingFailedPixmap(loaded, QSize(400, 400)); + } + + originalPixmap = loaded; + + // Always scale preview widget to this ratio + previewWidget->setAspectRatio(DESIGN_RATIO); + previewWidget->setPreviewWidth(400); + + // Initial scaling + updateScaledPreview(); + + reply->deleteLater(); +} + +void ArchidektApiResponseDeckEntryDisplayWidget::updateScaledPreview() +{ + if (originalPixmap.isNull()) { + return; + } + + int baseWidth = 400; + int newWidth = baseWidth * scaleFactor / 100; + int newHeight = static_cast(newWidth * DESIGN_RATIO); + + previewWidget->setFixedSize(newWidth, newHeight); + + // Scale image to fill the preview area (crop edges) + QPixmap scaled = + originalPixmap.scaled(newWidth, newHeight, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); + + // Crop to exact target size + QRect cropRect((scaled.width() - newWidth) / 2, (scaled.height() - newHeight) / 2, newWidth, newHeight); + QPixmap cropped = scaled.copy(cropRect); + + picture->setPixmap(cropped); + picture->setFixedSize(newWidth, newHeight); + + // Update the elided deck name based on new width + int textMaxWidth = int(newWidth * 0.7); // allow 70% of width for text + QFontMetrics fm(previewWidget->topLeftLabel->font()); + QString elided = fm.elidedText(response.getName(), Qt::ElideRight, textMaxWidth); + previewWidget->topLeftLabel->setText(elided); + previewWidget->topLeftLabel->setToolTip(response.getName()); + + setFixedWidth(newWidth); + + layout->invalidate(); + layout->activate(); + updateGeometry(); +} + +void ArchidektApiResponseDeckEntryDisplayWidget::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); + layout->invalidate(); + layout->activate(); + layout->update(); +} + +void ArchidektApiResponseDeckEntryDisplayWidget::actRequestNavigationToDeck() +{ + emit requestNavigation(QString("https://archidekt.com/api/decks/%1/").arg(response.getId())); +} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.h new file mode 100644 index 000000000..365a99c9c --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.h @@ -0,0 +1,121 @@ +#ifndef COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_ENTRY_DISPLAY_WIDGET_H +#define COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_ENTRY_DISPLAY_WIDGET_H + +#include "../../../../cards/card_info_picture_with_text_overlay_widget.h" +#include "../api_response/deck_listings/archidekt_api_response_deck_listing_container.h" +#include "archidekt_deck_preview_image_display_widget.h" + +#include +#include +#include +#include +#include + +class BackgroundPlateWidget; + +/** + * @class ArchidektApiResponseDeckEntryDisplayWidget + * @brief Displays a single Archidekt deck listing as a preview card with metadata. + * + * This widget renders a deck entry received from an Archidekt API response. It includes: + * - A scaled deck preview image loaded asynchronously via QNetworkAccessManager. + * - Elided deck name in the top-left corner. + * - Deck size, EDH bracket, and view count labels. + * - A color distribution bar summarizing deck colors. + * - Metadata labels including owner, creation date, and last update date. + * + * The widget dynamically scales the preview image and labels according to a linked + * CardSizeWidget slider. Hovering over the widget highlights the background plate, + * and clicking emits a `requestNavigation` signal pointing to the deck URL. + * + * ### Features + * - Asynchronous image loading with fallback to a default placeholder image. + * - Maintains a fixed aspect ratio for the preview image (150:267). + * - Updates text elision dynamically when resized or scaled. + * - Integrates with FlowWidget containers for scrollable deck galleries. + * + * ### Signals + * - `requestNavigation(QString url)` — emitted when the widget is clicked to request + * navigation to the deck's Archidekt page. + * + * ### Slots + * - `actRequestNavigationToDeck()` — triggers navigation. + * - `setScaleFactor(int scale)` — adjusts preview image scaling. + */ +class ArchidektApiResponseDeckEntryDisplayWidget : public QWidget +{ + Q_OBJECT + +signals: + /** + * @brief Emitted when the user requests navigation. + * @param url Full URL to the Archidekt page. + */ + void requestNavigation(QString url); + +public: + /** + * @brief Constructs a deck entry display widget. + * @param parent Parent widget. + * @param response API container holding deck listing data. + * @param imageNetworkManager Shared network manager for fetching preview images. + */ + explicit ArchidektApiResponseDeckEntryDisplayWidget(QWidget *parent, + ArchidektApiResponseDeckListingContainer response, + QNetworkAccessManager *imageNetworkManager); + + /** + * @brief Handles finished network replies for preview images. + * @param reply QNetworkReply containing image data. + * + * Validates that the reply corresponds to this widget and updates the preview image. + */ + void onPreviewImageLoadFinished(QNetworkReply *reply); + + /** + * @brief Updates the scaled preview image and adjusts layout accordingly. + */ + void updateScaledPreview(); + + /** + * @brief Ensures layout responds correctly on resize events. + * @param event Resize event. + */ + void resizeEvent(QResizeEvent *event) override; + +public slots: + /** + * @brief Emits `requestNavigation` for the deck's URL. + */ + void actRequestNavigationToDeck(); + + /** + * @brief Sets a scaling factor (percentage) for the preview image. + * @param scale Scale percentage (100 = normal size). + */ + void setScaleFactor(int scale); + +protected: + void mousePressEvent(QMouseEvent *event) override; + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + void enterEvent(QEnterEvent *event) override; ///< Qt6 hover enter +#else + void enterEvent(QEvent *event) override; ///< Qt5 hover enter +#endif + void leaveEvent(QEvent *event) override; + +private: + QVBoxLayout *layout; ///< Main vertical layout + ArchidektApiResponseDeckListingContainer response; ///< Deck data + QUrl imageUrl; ///< URL of the deck's preview image + QNetworkAccessManager *imageNetworkManager; ///< Shared network manager + ArchidektDeckPreviewImageDisplayWidget *previewWidget; ///< Widget showing the deck preview + QLabel *picture; ///< QLabel displaying the scaled pixmap + QPixmap originalPixmap; ///< Original image for scaling (avoids degradation) + int scaleFactor = 100; ///< Current scaling percentage + BackgroundPlateWidget *backgroundPlateWidget; ///< Plate for metadata labels + static constexpr float DESIGN_RATIO = 150.0f / 267.0f; ///< Design aspect ratio +}; + +#endif // COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_ENTRY_DISPLAY_WIDGET_H 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 new file mode 100644 index 000000000..5747ce90d --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_listings_display_widget.cpp @@ -0,0 +1,47 @@ +#include "archidekt_api_response_deck_listings_display_widget.h" + +#include "../../../../cards/card_info_picture_with_text_overlay_widget.h" +#include "archidekt_api_response_deck_entry_display_widget.h" + +ArchidektApiResponseDeckListingsDisplayWidget::ArchidektApiResponseDeckListingsDisplayWidget( + QWidget *parent, + ArchidektDeckListingApiResponse response, + CardSizeWidget *_cardSizeSlider) + : QWidget(parent), cardSizeSlider(_cardSizeSlider) +{ + layout = new QHBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + setLayout(layout); + + flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAsNeeded); + + imageNetworkManager = new QNetworkAccessManager(this); +#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) + imageNetworkManager->setTransferTimeout(); // Use Qt's default timeout +#endif + + imageNetworkManager->setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy); + + // Add widgets for deck listings + auto deckListings = response.results; + for (const auto &deckListing : deckListings) { + auto cardListDisplayWidget = + new ArchidektApiResponseDeckEntryDisplayWidget(this, deckListing, imageNetworkManager); + cardListDisplayWidget->setScaleFactor(cardSizeSlider->getSlider()->value()); + connect(cardListDisplayWidget, &ArchidektApiResponseDeckEntryDisplayWidget::requestNavigation, this, + &ArchidektApiResponseDeckListingsDisplayWidget::requestNavigation); + connect(cardSizeSlider->getSlider(), &QSlider::valueChanged, cardListDisplayWidget, + &ArchidektApiResponseDeckEntryDisplayWidget::setScaleFactor); + flowWidget->addWidget(cardListDisplayWidget); + } + + layout->addWidget(flowWidget); +} + +void ArchidektApiResponseDeckListingsDisplayWidget::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); + layout->invalidate(); + layout->activate(); + layout->update(); +} diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_listings_display_widget.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_listings_display_widget.h new file mode 100644 index 000000000..f00941239 --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_listings_display_widget.h @@ -0,0 +1,97 @@ +#ifndef COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_LISTINGS_DISPLAY_WIDGET_H +#define COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_LISTINGS_DISPLAY_WIDGET_H + +#include "../../../../cards/card_size_widget.h" +#include "../../../../general/layout_containers/flow_widget.h" +#include "../api_response/archidekt_deck_listing_api_response.h" + +#include +#include +#include +#include +#include + +/** + * @class ArchidektApiResponseDeckListingsDisplayWidget + * @brief Displays a scrollable horizontal list of Archidekt deck listings with dynamic card sizing. + * + * This widget serves as a container for multiple + * ArchidektApiResponseDeckEntryDisplayWidget instances, each representing one deck listing + * returned from an Archidekt API call. + * + * ### Responsibilities + * - Creates a **FlowWidget** that arranges deck entries horizontally with wrapping. + * - Creates a shared **QNetworkAccessManager** for entry widgets to fetch card thumbnails. + * - Connects a **CardSizeWidget** slider to all deck entries to dynamically rescale their preview cards. + * - Propagates deck-navigation requests (`requestNavigation`) from children to the parent. + * + * ### Layout + * The widget uses a single `QHBoxLayout` containing the `FlowWidget`. + * The FlowWidget automatically manages child flow and scrollbar behavior (horizontal = off, + * vertical = auto), providing an efficient scrollable gallery of deck entries. + * + * ### API Integration + * The constructor consumes an `ArchidektDeckListingApiResponse`, iterates through its + * `results`, and instantiates a child entry widget for each deck. + * + * ### Signals + * - `requestNavigation(QString url)` — emitted whenever a child entry widget requests + * navigation to a deck or related Archidekt page. + * + * ### Performance Notes + * - All entry widgets share a single QNetworkAccessManager instance to reuse connections + * and avoid redundant session creation. + * - `resizeEvent()` forces layout invalidation to ensure the flow layout responds properly + * to container resizing. + */ +class ArchidektApiResponseDeckListingsDisplayWidget : public QWidget +{ + Q_OBJECT + +signals: + /** + * @brief Emitted when a child deck entry requests that the UI navigate to a particular URL. + * @param url The destination URL (typically an Archidekt deck page). + */ + void requestNavigation(QString url); + +public: + /** + * @brief Constructs a widget that displays multiple deck listing previews. + * + * @param parent Parent widget. + * @param response The Archidekt API response containing deck listings. + * @param cardSizeSlider A slider widget used to dynamically resize card previews. + * + * Each deck in `response.results` becomes its own + * ArchidektApiResponseDeckEntryDisplayWidget, added to the FlowWidget. + */ + explicit ArchidektApiResponseDeckListingsDisplayWidget(QWidget *parent, + ArchidektDeckListingApiResponse response, + CardSizeWidget *cardSizeSlider); + + /** + * @brief Ensures FlowWidget layout properly recomputes on resize. + * + * Forces the layout to invalidate and activate itself so that the + * FlowWidget recalculates wrapping and child placement. + * + * @param event Resize event. + */ + void resizeEvent(QResizeEvent *event) override; + +private: + /// Slider controlling the scale of card thumbnails in all deck entry widgets. + CardSizeWidget *cardSizeSlider; + + /// Main horizontal layout containing the FlowWidget. + QHBoxLayout *layout; + + /// Container providing scrollable multi-row flow layout of deck entries. + FlowWidget *flowWidget; + + /// Shared network manager used to download card images for all child entry widgets. + QNetworkAccessManager *imageNetworkManager; +}; + +#endif // COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_LISTINGS_DISPLAY_WIDGET_H \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_deck_preview_image_display_widget.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_deck_preview_image_display_widget.cpp new file mode 100644 index 000000000..ced08491e --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_deck_preview_image_display_widget.cpp @@ -0,0 +1,80 @@ +#include "archidekt_deck_preview_image_display_widget.h" + +#include +#include + +ArchidektDeckPreviewImageDisplayWidget::ArchidektDeckPreviewImageDisplayWidget(QWidget *parent) : QWidget(parent) +{ + imageLabel = new QLabel(this); + imageLabel->setAlignment(Qt::AlignCenter); + + topLeftLabel = new ShadowBackgroundLabel(this, ""); + topRightLabel = new ShadowBackgroundLabel(this, ""); + bottomLeftLabel = new ShadowBackgroundLabel(this, ""); + bottomRightLabel = new ShadowBackgroundLabel(this, ""); + + QFont f; + f.setBold(true); + f.setPointSize(16); + topLeftLabel->setFont(f); + topRightLabel->setFont(f); + bottomLeftLabel->setFont(f); + bottomRightLabel->setFont(f); + + // Raise so labels appear above image + topLeftLabel->raise(); + topRightLabel->raise(); + bottomLeftLabel->raise(); + bottomRightLabel->raise(); +} + +void ArchidektDeckPreviewImageDisplayWidget::setAspectRatio(float ratio) +{ + aspectRatio = ratio; +} + +void ArchidektDeckPreviewImageDisplayWidget::setPreviewWidth(int width) +{ + int height = int(width * aspectRatio); + + setFixedSize(width, height); + updateGeometry(); + update(); +} + +void ArchidektDeckPreviewImageDisplayWidget::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); + + // Full size for the image + imageLabel->setGeometry(rect()); + + topLeftLabel->adjustSize(); + topRightLabel->adjustSize(); + bottomLeftLabel->adjustSize(); + bottomRightLabel->adjustSize(); + + // Padding settings + const int horizontalPadding = 8; + const int topPadding = 6; + const int bottomPadding = 6; + + // Left-aligned, top-aligned (Deck Name) + topLeftLabel->move(horizontalPadding, topPadding); + + // Right-aligned, top-aligned (Card Count) + topRightLabel->move(width() - topRightLabel->width() - horizontalPadding, topPadding); + + // Bottom-left, bottom-aligned (EDH bracket) + bottomLeftLabel->move(horizontalPadding, height() - bottomLeftLabel->height() - bottomPadding); + + // Bottom-right, bottom-aligned (views) + bottomRightLabel->move(width() - bottomRightLabel->width() - horizontalPadding, + height() - bottomRightLabel->height() - bottomPadding); + + // Ensure labels stay above image + topLeftLabel->raise(); + topRightLabel->raise(); + bottomLeftLabel->raise(); + bottomRightLabel->raise(); +} diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_deck_preview_image_display_widget.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_deck_preview_image_display_widget.h new file mode 100644 index 000000000..053823c45 --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_deck_preview_image_display_widget.h @@ -0,0 +1,66 @@ +#ifndef COCKATRICE_ARCHIDEKT_DECK_PREVIEW_IMAGE_DISPLAY_WIDGET_H +#define COCKATRICE_ARCHIDEKT_DECK_PREVIEW_IMAGE_DISPLAY_WIDGET_H + +#include "../../../../general/display/shadow_background_label.h" + +#include +#include + +/** + * @class ArchidektDeckPreviewImageDisplayWidget + * @brief Widget for displaying a deck preview image with overlaid metadata labels. + * + * This widget shows a deck's preview image along with several overlay labels: + * - Top-left: Deck name. + * - Top-right: Card count. + * - Bottom-left: EDH bracket (if applicable). + * - Bottom-right: View count. + * + * Labels automatically scale and position themselves relative to the widget's size. + * The image can be scaled while maintaining a specified aspect ratio. + * + * ### Features + * - Adjustable preview width and aspect ratio. + * - Labels automatically repositioned on resize. + * - Supports overlaying multiple pieces of metadata with shadowed labels for readability. + */ +class ArchidektDeckPreviewImageDisplayWidget : public QWidget +{ + Q_OBJECT +public: + /** + * @brief Constructs the deck preview display widget. + * @param parent Optional parent widget. + */ + explicit ArchidektDeckPreviewImageDisplayWidget(QWidget *parent = nullptr); + + /** + * @brief Sets the aspect ratio for the preview image (height / width). + * @param ratio Aspect ratio to maintain. + */ + void setAspectRatio(float ratio); + + /** + * @brief Sets the width of the preview image; height is adjusted according to the aspect ratio. + * @param width Desired width in pixels. + */ + void setPreviewWidth(int width); + + QLabel *imageLabel; ///< QLabel to display the deck image + ShadowBackgroundLabel *topLeftLabel; ///< Overlay label at top-left (deck name) + ShadowBackgroundLabel *topRightLabel; ///< Overlay label at top-right (card count) + ShadowBackgroundLabel *bottomLeftLabel; ///< Overlay label at bottom-left (EDH bracket) + ShadowBackgroundLabel *bottomRightLabel; ///< Overlay label at bottom-right (views) + +protected: + /** + * @brief Handles resize events to reposition the image and overlay labels. + * @param event Resize event. + */ + void resizeEvent(QResizeEvent *event) override; + +private: + float aspectRatio = 1.0f; ///< Aspect ratio to maintain for the preview image +}; + +#endif // COCKATRICE_ARCHIDEKT_DECK_PREVIEW_IMAGE_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp new file mode 100644 index 000000000..7f04987c1 --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp @@ -0,0 +1,562 @@ +#include "tab_archidekt.h" + +#include "../../../../../client/settings/cache_settings.h" +#include "../../../cards/additional_info/mana_symbol_widget.h" +#include "../../tab_supervisor.h" +#include "api_response/archidekt_deck_listing_api_response.h" +#include "display/archidekt_api_response_deck_display_widget.h" +#include "display/archidekt_api_response_deck_listings_display_widget.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +TabArchidekt::TabArchidekt(TabSupervisor *_tabSupervisor) : Tab(_tabSupervisor) +{ + networkManager = new QNetworkAccessManager(this); +#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) + networkManager->setTransferTimeout(); // Use Qt's default timeout +#endif + + networkManager->setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy); + connect(networkManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(processApiJson(QNetworkReply *))); + + searchDebounceTimer = new QTimer(this); + searchDebounceTimer->setSingleShot(true); // We only want it to fire once after inactivity + searchDebounceTimer->setInterval(300); // 300ms debounce + + connect(searchDebounceTimer, &QTimer::timeout, this, [this]() { doSearchImmediate(); }); + + container = new QWidget(this); + mainLayout = new QVBoxLayout(container); + mainLayout->setContentsMargins(0, 0, 0, 0); + container->setLayout(mainLayout); + + navigationContainer = new QWidget(container); + navigationContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + navigationLayout = new QHBoxLayout(navigationContainer); + navigationLayout->setSpacing(3); + navigationContainer->setLayout(navigationLayout); + + // Sort by + + orderByCombo = new QComboBox(navigationContainer); + orderByCombo->addItems({"name", "updatedAt", "createdAt", "viewCount", "size", "edhBracket"}); + orderByCombo->setCurrentText("updatedAt"); // Pre-select updatedAt + + // Asc/Desc toggle + orderDirButton = new QPushButton(tr("Desc."), navigationContainer); + orderDirButton->setCheckable(true); // checked = DESC, unchecked = ASC + orderDirButton->setChecked(true); + + connect(orderByCombo, &QComboBox::currentTextChanged, this, &TabArchidekt::doSearch); + connect(orderDirButton, &QPushButton::clicked, this, [this](bool checked) { + orderDirButton->setText(checked ? tr("Desc.") : tr("Asc.")); + doSearch(); + }); + + // Colors + QHBoxLayout *colorLayout = new QHBoxLayout(); + QString colorIdentity = "WUBRG"; // Optionally include "C" for colorless once we have a symbol for it + + for (const QChar &color : colorIdentity) { + auto *manaSymbol = new ManaSymbolWidget(navigationContainer, color, false, true); + manaSymbol->setFixedWidth(25); + colorLayout->addWidget(manaSymbol); + + connect(manaSymbol, &ManaSymbolWidget::colorToggled, this, [this](QChar c, bool active) { + if (active) { + activeColors.insert(c); + } else { + activeColors.remove(c); + } + doSearch(); + }); + } + + logicalAndCheck = new QCheckBox("Require ALL colors", navigationContainer); + + // Formats + + formatLabel = new QLabel(this); + + formatSettingsWidget = new SettingsButtonWidget(this); + + QStringList formatNames = {"Standard", "Modern", "Commander", "Legacy", "Vintage", + "Pauper", "Custom", "Frontier", "Future Std", "Penny Dreadful", + "1v1 Commander", "Dual Commander", "Brawl"}; + + for (int i = 0; i < formatNames.size(); ++i) { + QCheckBox *formatCheckBox = new QCheckBox(formatNames[i], navigationContainer); + connect(formatCheckBox, &QCheckBox::clicked, this, &TabArchidekt::doSearch); + formatChecks << formatCheckBox; + formatSettingsWidget->addSettingsWidget(formatCheckBox); + } + + // EDH Bracket + edhBracketCombo = new QComboBox(navigationContainer); + edhBracketCombo->addItem(tr("Any Bracket")); + edhBracketCombo->addItems({"1", "2", "3", "4", "5"}); + + connect(edhBracketCombo, &QComboBox::currentTextChanged, this, &TabArchidekt::doSearch); + + // Search for Card Packages instead of Decks + packagesCheck = new QCheckBox("Packages", navigationContainer); + + connect(packagesCheck, &QCheckBox::clicked, this, [this]() { + bool disable = packagesCheck->isChecked(); + for (auto *cb : formatChecks) + cb->setEnabled(!disable); + commandersField->setEnabled(!disable); + deckTagNameField->setEnabled(!disable); + edhBracketCombo->setCurrentIndex(0); + edhBracketCombo->setEnabled(!disable); + doSearch(); + }); + + // Deck Name + nameField = new QLineEdit(navigationContainer); + nameField->setPlaceholderText(tr("Deck name contains...")); + + // Owner Name + ownerField = new QLineEdit(navigationContainer); + ownerField->setPlaceholderText(tr("Owner name contains...")); + + // Contained cards + cardsField = new QLineEdit(navigationContainer); + cardsField->setPlaceholderText("Deck contains card..."); + + // Commanders + commandersField = new QLineEdit(navigationContainer); + commandersField->setPlaceholderText("Deck has commander..."); + + // DB supplemented card search + auto cardDatabaseModel = new CardDatabaseModel(CardDatabaseManager::getInstance(), false, this); + auto displayModel = new CardDatabaseDisplayModel(this); + displayModel->setSourceModel(cardDatabaseModel); + auto *searchModel = new CardSearchModel(displayModel, this); + + auto *proxyModel = new CardCompleterProxyModel(this); + proxyModel->setSourceModel(searchModel); + proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + proxyModel->setFilterRole(Qt::DisplayRole); + + auto *completer = new QCompleter(proxyModel, this); + completer->setCompletionRole(Qt::DisplayRole); + completer->setCompletionMode(QCompleter::PopupCompletion); + completer->setCaseSensitivity(Qt::CaseInsensitive); + completer->setFilterMode(Qt::MatchContains); + completer->setMaxVisibleItems(10); + + cardsField->setCompleter(completer); + commandersField->setCompleter(completer); + + connect(cardsField, &QLineEdit::textChanged, searchModel, &CardSearchModel::updateSearchResults); + + connect(cardsField, &QLineEdit::textChanged, this, [=](const QString &text) { + QString pattern = ".*" + QRegularExpression::escape(text) + ".*"; + proxyModel->setFilterRegularExpression(QRegularExpression(pattern, QRegularExpression::CaseInsensitiveOption)); + if (!text.isEmpty()) + completer->complete(); + }); + + connect(commandersField, &QLineEdit::textChanged, searchModel, &CardSearchModel::updateSearchResults); + + connect(commandersField, &QLineEdit::textChanged, this, [=](const QString &text) { + QString pattern = ".*" + QRegularExpression::escape(text) + ".*"; + proxyModel->setFilterRegularExpression(QRegularExpression(pattern, QRegularExpression::CaseInsensitiveOption)); + if (!text.isEmpty()) + completer->complete(); + }); + + // Tag Name + deckTagNameField = new QLineEdit(navigationContainer); + deckTagNameField->setPlaceholderText("Deck tag"); + + connect(deckTagNameField, &QLineEdit::textChanged, this, &TabArchidekt::doSearch); + + // Search button + searchPushButton = new QPushButton(navigationContainer); + searchPushButton->setText("Search"); + + connect(searchPushButton, &QPushButton::clicked, this, &TabArchidekt::doSearch); + + // Card Size settings + settingsButton = new SettingsButtonWidget(this); + cardSizeSlider = new CardSizeWidget(this, nullptr, SettingsCache::instance().getArchidektPreviewSize()); + connect(cardSizeSlider, &CardSizeWidget::cardSizeSettingUpdated, &SettingsCache::instance(), + &SettingsCache::setArchidektPreviewCardSize); + settingsButton->addSettingsWidget(cardSizeSlider); + + // Min deck size + minDeckSizeLabel = new QLabel(navigationContainer); + + minDeckSizeSpin = new QSpinBox(navigationContainer); + minDeckSizeSpin->setSpecialValueText(tr("Disabled")); + minDeckSizeSpin->setRange(0, 200); + minDeckSizeSpin->setValue(0); + + // Size logic + minDeckSizeLogicCombo = new QComboBox(navigationContainer); + minDeckSizeLogicCombo->addItems({"Exact", "≥", "≤"}); // Exact = unset, ≥ = GTE, ≤ = LTE + minDeckSizeLogicCombo->setCurrentIndex(1); // default GTE + + connect(minDeckSizeSpin, QOverload::of(&QSpinBox::valueChanged), this, &TabArchidekt::doSearch); + connect(minDeckSizeLogicCombo, &QComboBox::currentTextChanged, this, &TabArchidekt::doSearch); + + // Page number + pageLabel = new QLabel(navigationContainer); + + pageSpin = new QSpinBox(navigationContainer); + pageSpin->setRange(1, 9999); + pageSpin->setValue(1); + + connect(pageSpin, QOverload::of(&QSpinBox::valueChanged), this, &TabArchidekt::doSearch); + + // Page display + currentPageDisplay = new QWidget(container); + currentPageLayout = new QVBoxLayout(currentPageDisplay); + currentPageLayout->setContentsMargins(0, 0, 0, 0); + currentPageDisplay->setLayout(currentPageLayout); + + // Layout composition + + // Sort section + navigationLayout->addWidget(orderByCombo); + navigationLayout->addWidget(orderDirButton); + + // Colors section + navigationLayout->addLayout(colorLayout); + navigationLayout->addWidget(logicalAndCheck); + + // Formats section + navigationLayout->addWidget(formatSettingsWidget); + navigationLayout->addWidget(formatLabel); + + // EDH Bracket + navigationLayout->addWidget(edhBracketCombo); + + // Packages toggle + navigationLayout->addWidget(packagesCheck); + + // Deck name + navigationLayout->addWidget(nameField); + + // Owner name + navigationLayout->addWidget(ownerField); + + // Contained cards + navigationLayout->addWidget(cardsField); + + // Commanders + navigationLayout->addWidget(commandersField); + + // Deck tag + navigationLayout->addWidget(deckTagNameField); + + // Search button + navigationLayout->addWidget(searchPushButton); + + // Card size settings + navigationLayout->addWidget(settingsButton); + + // Min. # of cards in deck + navigationLayout->addWidget(minDeckSizeLabel); + navigationLayout->addWidget(minDeckSizeSpin); + navigationLayout->addWidget(minDeckSizeLogicCombo); + + // Page number + navigationLayout->addWidget(pageLabel); + navigationLayout->addWidget(pageSpin); + + mainLayout->addWidget(navigationContainer); + mainLayout->addWidget(currentPageDisplay); + + // Ensure navigation stays at the top and currentPageDisplay takes remaining space + mainLayout->setStretch(0, 0); // navigationContainer gets minimum space + mainLayout->setStretch(1, 1); // currentPageDisplay expands as much as possible + + setCentralWidget(container); + + TabArchidekt::retranslateUi(); + + getTopDecks(); +} + +void TabArchidekt::retranslateUi() +{ + searchPushButton->setText(tr("Search")); + formatLabel->setText(tr("Formats")); + minDeckSizeLabel->setText(tr("Min. # of Cards:")); + pageLabel->setText(tr("Page:")); +} + +QString TabArchidekt::buildSearchUrl() +{ + QUrlQuery query; + + // orderBy (field + direction) + { + QString field = orderByCombo->currentText(); + if (!field.isEmpty()) { + bool desc = orderDirButton->isChecked(); + QString final = desc ? "-" + field : field; + query.addQueryItem("orderBy", final); + } + } + + // Colors + QStringList selectedColors; + for (QChar c : activeColors) { + selectedColors.append(c); + } + if (!selectedColors.isEmpty()) { + query.addQueryItem("colors", selectedColors.join(",")); + } + + // logicalAnd + if (logicalAndCheck->isChecked()) { + query.addQueryItem("logicalAnd", "true"); + } + + // Formats + if (!packagesCheck->isChecked()) { + QStringList formatIds; + for (int i = 0; i < formatChecks.size(); ++i) + if (formatChecks[i]->isChecked()) { + formatIds << QString::number(i + 1); + } + + if (!formatIds.isEmpty()) { + query.addQueryItem("deckFormat", formatIds.join(",")); + } + } + + // edhBracket + if (!packagesCheck->isChecked()) { + if (!edhBracketCombo->currentText().isEmpty()) { + if (edhBracketCombo->currentText() != tr("Any Bracket")) { + query.addQueryItem("edhBracket", edhBracketCombo->currentText()); + } + } + } + + // Search for card packages instead of decks + if (packagesCheck->isChecked()) { + query.addQueryItem("packages", "true"); + } + + // Name + if (!nameField->text().isEmpty()) { + query.addQueryItem("name", nameField->text()); + } + + // owner + if (!ownerField->text().isEmpty()) { + query.addQueryItem("ownerUsername", ownerField->text()); + } + + // cards + if (!cardsField->text().isEmpty()) { + query.addQueryItem("cardName", cardsField->text()); + } + + // Commander Name + if (!packagesCheck->isChecked()) { + if (!commandersField->text().isEmpty()) { + query.addQueryItem("commanderName", commandersField->text()); + } + } + + // deckTagName + if (!packagesCheck->isChecked()) { + if (!deckTagNameField->text().isEmpty()) { + query.addQueryItem("deckTagName", deckTagNameField->text()); + } + } + + // page number + if (pageSpin->value() <= 1) { + query.addQueryItem("page", QString::number(pageSpin->value())); + } + + // Min deck size + if (minDeckSizeSpin->value() != 0) { + query.addQueryItem("size", QString::number(minDeckSizeSpin->value())); + + QString logic = "GTE"; // default + QString selected = minDeckSizeLogicCombo->currentText(); + if (selected == "≥") + logic = "GTE"; + else if (selected == "≤") + logic = "LTE"; + else + logic = ""; // Exact = unset + + if (!logic.isEmpty()) { + query.addQueryItem("sizeLogic", logic); + } + } + + // build final URL + QUrl url("https://archidekt.com/api/decks/v3/"); + url.setQuery(query); + + return url.toString(); +} + +void TabArchidekt::doSearch() +{ + searchDebounceTimer->start(); +} + +void TabArchidekt::doSearchImmediate() +{ + QString url = buildSearchUrl(); + QNetworkRequest req{QUrl(url)}; + networkManager->get(req); +} + +void TabArchidekt::actNavigatePage(QString url) +{ + QNetworkRequest request{QUrl(url)}; + networkManager->get(request); +} + +void TabArchidekt::getTopDecks() +{ + QNetworkRequest request{QUrl(buildSearchUrl())}; + networkManager->get(request); +} + +void TabArchidekt::processApiJson(QNetworkReply *reply) +{ + if (reply->error() != QNetworkReply::NoError) { + qDebug() << "Network error occurred:" << reply->errorString(); + reply->deleteLater(); + return; + } + + QByteArray responseData = reply->readAll(); + QJsonDocument jsonDoc = QJsonDocument::fromJson(responseData); + + if (!jsonDoc.isObject()) { + qDebug() << "Invalid JSON response received."; + reply->deleteLater(); + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + + // Get the actual URL from the reply + QString responseUrl = reply->url().toString(); + + // Check if the response URL matches a commander request + if (responseUrl.startsWith("https://archidekt.com/api/decks/v3/")) { + processTopDecksResponse(jsonObj); + } else if (responseUrl.startsWith("https://archidekt.com/api/decks/")) { + processDeckResponse(jsonObj); + } else { + prettyPrintJson(jsonObj, 4); + } + + reply->deleteLater(); +} + +void TabArchidekt::processTopDecksResponse(QJsonObject reply) +{ + ArchidektDeckListingApiResponse deckData; + deckData.fromJson(reply); + + // **Remove previous page display to prevent stacking** + if (currentPageDisplay) { + mainLayout->removeWidget(currentPageDisplay); + delete currentPageDisplay; + currentPageDisplay = nullptr; + } + + // **Create new currentPageDisplay** + currentPageDisplay = new QWidget(container); + currentPageLayout = new QVBoxLayout(currentPageDisplay); + currentPageDisplay->setLayout(currentPageLayout); + + auto display = new ArchidektApiResponseDeckListingsDisplayWidget(currentPageDisplay, deckData, cardSizeSlider); + connect(display, &ArchidektApiResponseDeckListingsDisplayWidget::requestNavigation, this, + &TabArchidekt::actNavigatePage); + currentPageLayout->addWidget(display); + + mainLayout->addWidget(currentPageDisplay); + + // **Ensure layout stays correct** + mainLayout->setStretch(0, 0); // Keep navigationContainer at the top + mainLayout->setStretch(1, 1); // Make sure currentPageDisplay takes remaining space +} + +void TabArchidekt::processDeckResponse(QJsonObject reply) +{ + ArchidektApiResponseDeck deckData; + deckData.fromJson(reply); + + // **Remove previous page display to prevent stacking** + if (currentPageDisplay) { + mainLayout->removeWidget(currentPageDisplay); + delete currentPageDisplay; + currentPageDisplay = nullptr; + } + + // **Create new currentPageDisplay** + currentPageDisplay = new QWidget(container); + currentPageLayout = new QVBoxLayout(currentPageDisplay); + currentPageDisplay->setLayout(currentPageLayout); + + auto display = new ArchidektApiResponseDeckDisplayWidget(currentPageDisplay, deckData, cardSizeSlider); + connect(display, &ArchidektApiResponseDeckDisplayWidget::requestNavigation, this, &TabArchidekt::actNavigatePage); + connect(display, &ArchidektApiResponseDeckDisplayWidget::openInDeckEditor, tabSupervisor, + &TabSupervisor::openDeckInNewTab); + currentPageLayout->addWidget(display); + + mainLayout->addWidget(currentPageDisplay); + + // **Ensure layout stays correct** + mainLayout->setStretch(0, 0); // Keep navigationContainer at the top + mainLayout->setStretch(1, 1); // Make sure currentPageDisplay takes remaining space +} + +void TabArchidekt::prettyPrintJson(const QJsonValue &value, int indentLevel) +{ + const QString indent(indentLevel * 2, ' '); // Adjust spacing as needed for pretty printing + + if (value.isObject()) { + QJsonObject obj = value.toObject(); + for (auto it = obj.begin(); it != obj.end(); ++it) { + qDebug().noquote() << indent + it.key() + ":"; + prettyPrintJson(it.value(), indentLevel + 1); + } + } else if (value.isArray()) { + QJsonArray array = value.toArray(); + for (int i = 0; i < array.size(); ++i) { + qDebug().noquote() << indent + QString("[%1]:").arg(i); + prettyPrintJson(array[i], indentLevel + 1); + } + } else if (value.isString()) { + qDebug().noquote() << indent + "\"" + value.toString() + "\""; + } else if (value.isDouble()) { + qDebug().noquote() << indent + QString::number(value.toDouble()); + } else if (value.isBool()) { + qDebug().noquote() << indent + (value.toBool() ? "true" : "false"); + } else if (value.isNull()) { + qDebug().noquote() << indent + "null"; + } +} diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/tab_archidekt.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/tab_archidekt.h new file mode 100644 index 000000000..68a5b78c9 --- /dev/null +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/tab_archidekt.h @@ -0,0 +1,250 @@ +#ifndef COCKATRICE_TAB_ARCHIDEKT_H +#define COCKATRICE_TAB_ARCHIDEKT_H + +#include "../../interface/widgets/cards/card_size_widget.h" +#include "../../interface/widgets/quick_settings/settings_button_widget.h" +#include "../../tab.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** Base API link for Archidekt deck search */ +inline QString archidektApiLink = "https://archidekt.com/api/decks/v3/?name="; + +/** + * @brief Tab for browsing, searching, and filtering Archidekt decks. + * + * This class provides a comprehensive interface for querying decks from the Archidekt API. + * Users can filter decks by name, owner, included cards, commanders, deck tags, colors, EDH bracket, + * and formats. It also provides sorting and pagination, as well as a card size adjustment widget. + */ +class TabArchidekt : public Tab +{ + Q_OBJECT +public: + /** + * @brief Construct a new TabArchidekt object + * @param _tabSupervisor Parent tab supervisor responsible for tab management and callbacks + * + * Initializes the network manager, creates all UI components, sets up layouts, + * connects signals and slots, and triggers an initial fetch of top decks. + */ + explicit TabArchidekt(TabSupervisor *_tabSupervisor); + + /** + * @brief Update all UI text to reflect the current language or translation + * + * This function re-applies translations to all labels, buttons, and placeholders. + * It should be called after a language change. + */ + void retranslateUi() override; + + /** + * @brief Construct the search URL from all current filters + * @return QString Fully constructed URL including all query parameters + * + * The search URL is dynamically built using the state of all filter widgets. + * Parameters included: + * - Deck name + * - Owner + * - Included cards + * - Commander cards + * - Deck tag + * - Colors and logical AND requirement + * - Formats + * - EDH bracket + * - Packages toggle + * - Sorting field and direction + * - Minimum amount of cards in the deck + * - Pagination (page) + */ + QString buildSearchUrl(); + + /** + * @brief Retrieve the tab display text + * @return QString Human-readable title for the tab + * + * If a card is pre-selected (cardToQuery), its name is appended to the tab title. + */ + QString getTabText() const override + { + auto cardName = cardToQuery.isNull() ? QString() : cardToQuery->getName(); + return tr("Archidekt: ") + cardName; + } + + /** + * @brief Get the card size slider widget + * @return CardSizeWidget* Pointer to the card size adjustment slider + * + * Allows external code to read or manipulate the current card size or hook up the sliders signals. + */ + CardSizeWidget *getCardSizeSlider() + { + return cardSizeSlider; + } + + /** @brief Network manager for handling API requests */ + QNetworkAccessManager *networkManager; + +public slots: + /** + * @brief Trigger a search using the current filters + * + * Sends a network request to the Archidekt API using the URL generated by buildSearchUrl(). + * Updates the current page display with results asynchronously. + */ + void doSearch(); + void doSearchImmediate(); + /** + * @brief Process a network reply containing JSON data + * @param reply QNetworkReply object with the API response + * + * Determines whether the response corresponds to a top decks query or a single deck, + * and dispatches it to the appropriate handler. + */ + void processApiJson(QNetworkReply *reply); + + /** + * @brief Handle a JSON response containing multiple decks + * @param reply QJsonObject containing top deck listings + * + * Clears the previous page display and creates a new display widget for the results. + */ + void processTopDecksResponse(QJsonObject reply); + + /** + * @brief Handle a JSON response for a single deck + * @param reply QJsonObject containing deck data + * + * Clears the previous page display and creates a new display widget for the deck details. + */ + void processDeckResponse(QJsonObject reply); + + /** + * @brief Pretty-print a QJsonValue for debugging + * @param value The JSON value to print + * @param indentLevel The indentation depth (number of levels) + */ + void prettyPrintJson(const QJsonValue &value, int indentLevel); + + /** + * @brief Navigate to a specified page URL + * @param url The URL to request + * + * Typically called when a navigation button is clicked in a deck listing. + */ + void actNavigatePage(QString url); + + /** + * @brief Fetch top decks from the Archidekt API + * + * Called on initialization to populate the initial page display. + */ + void getTopDecks(); + +private: + QTimer *searchDebounceTimer; ///< Timer to debounce search requests by spin-boxes etc. + + // --------------------------------------------------------------------- + // Layout Containers + // --------------------------------------------------------------------- + + QWidget *container; ///< Root container for the entire tab + QVBoxLayout *mainLayout; ///< Outer vertical layout containing navigation and page display + QWidget *navigationContainer; ///< Container for all navigation/filter controls + QHBoxLayout *navigationLayout; ///< Layout for horizontal arrangement of filter widgets + QWidget *currentPageDisplay; ///< Widget containing the currently displayed deck(s) + QVBoxLayout *currentPageLayout; ///< Layout for deck display widgets + + // --------------------------------------------------------------------- + // Sorting Controls + // --------------------------------------------------------------------- + + QComboBox *orderByCombo; ///< Dropdown for selecting the sort field + QPushButton *orderDirButton; ///< Toggle button for ascending/descending sort + + // --------------------------------------------------------------------- + // Color Filters + // --------------------------------------------------------------------- + + QSet activeColors; ///< Set of currently active mana colors + QCheckBox *logicalAndCheck; ///< Require ALL selected colors instead of ANY + + // --------------------------------------------------------------------- + // Format Filters + // --------------------------------------------------------------------- + + QLabel *formatLabel; ///< Label displaying "Formats" + SettingsButtonWidget *formatSettingsWidget; ///< Collapsible widget containing format checkboxes + QVector formatChecks; ///< Individual checkboxes for each format + + // --------------------------------------------------------------------- + // EDH Bracket / Package Toggle + // --------------------------------------------------------------------- + + QComboBox *edhBracketCombo; ///< Dropdown for EDH bracket selection + QCheckBox *packagesCheck; ///< Toggle for searching card packages instead of full decks + + // --------------------------------------------------------------------- + // Basic Search Fields + // --------------------------------------------------------------------- + + QLineEdit *nameField; ///< Input for deck name filter + QLineEdit *ownerField; ///< Input for owner name filter + + // --------------------------------------------------------------------- + // Card Filters + // --------------------------------------------------------------------- + + QLineEdit *cardsField; ///< Input for cards included in the deck (comma-separated) + QLineEdit *commandersField; ///< Input for commander cards (comma-separated) + + // --------------------------------------------------------------------- + // Deck Tag + // --------------------------------------------------------------------- + + QLineEdit *deckTagNameField; ///< Input for deck tag filtering + + // --------------------------------------------------------------------- + // Search Trigger + // --------------------------------------------------------------------- + + QPushButton *searchPushButton; ///< Button to trigger the search manually + + // --------------------------------------------------------------------- + // UI Settings (Card Size) + // --------------------------------------------------------------------- + + SettingsButtonWidget *settingsButton; ///< Container for additional UI settings + CardSizeWidget *cardSizeSlider; ///< Slider to adjust card size in results + + // --------------------------------------------------------------------- + // Minimum Cards in Deck + // --------------------------------------------------------------------- + + QLabel *minDeckSizeLabel; ///< Label for minimum number of cards per deck + QSpinBox *minDeckSizeSpin; ///< Spinner to select minimum deck size + QComboBox *minDeckSizeLogicCombo; ///< Combo box for the size logic to apply + + // --------------------------------------------------------------------- + // Pagination + // --------------------------------------------------------------------- + + QLabel *pageLabel; ///< Label for current page selection + QSpinBox *pageSpin; ///< Spinner to select the page number for results + + // --------------------------------------------------------------------- + // Optional Context + // --------------------------------------------------------------------- + + CardInfoPtr cardToQuery; ///< Optional pre-selected card for initial filtering +}; + +#endif // COCKATRICE_TAB_ARCHIDEKT_H diff --git a/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp b/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp index 18a98f5ec..df9387a6c 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp @@ -5,6 +5,7 @@ #include "../interface/widgets/server/user/user_list_manager.h" #include "../interface/widgets/server/user/user_list_widget.h" #include "../main.h" +#include "api/archidekt/tab_archidekt.h" #include "api/edhrec/tab_edhrec_main.h" #include "tab_account.h" #include "tab_admin.h" @@ -140,6 +141,9 @@ TabSupervisor::TabSupervisor(AbstractClient *_client, QMenu *tabsMenu, QWidget * aTabEdhRec = new QAction(this); connect(aTabEdhRec, &QAction::triggered, this, [this] { addEdhrecMainTab(); }); + aTabArchidekt = new QAction(this); + connect(aTabArchidekt, &QAction::triggered, this, [this] { addArchidektTab(); }); + aTabHome = new QAction(this); aTabHome->setCheckable(true); connect(aTabHome, &QAction::triggered, this, &TabSupervisor::actTabHome); @@ -204,6 +208,7 @@ void TabSupervisor::retranslateUi() aTabDeckEditor->setText(tr("Deck Editor")); aTabVisualDeckEditor->setText(tr("Visual Deck Editor")); aTabEdhRec->setText(tr("EDHRec")); + aTabArchidekt->setText(tr("Archidekt")); aTabHome->setText(tr("Home")); aTabVisualDeckStorage->setText(tr("&Visual Deck Storage")); aTabVisualDatabaseDisplay->setText(tr("Visual Database Display")); @@ -386,6 +391,7 @@ void TabSupervisor::resetTabsMenu() tabsMenu->addAction(aTabDeckEditor); tabsMenu->addAction(aTabVisualDeckEditor); tabsMenu->addAction(aTabEdhRec); + tabsMenu->addAction(aTabArchidekt); tabsMenu->addSeparator(); tabsMenu->addAction(aTabHome); tabsMenu->addAction(aTabVisualDeckStorage); @@ -899,6 +905,15 @@ TabEdhRecMain *TabSupervisor::addEdhrecMainTab() return tab; } +TabArchidekt *TabSupervisor::addArchidektTab() +{ + auto *tab = new TabArchidekt(this); + + myAddTab(tab); + setCurrentWidget(tab); + return tab; +} + TabVisualDatabaseDisplay *TabSupervisor::addVisualDatabaseDisplayTab() { auto *tab = new TabVisualDatabaseDisplay(this); diff --git a/cockatrice/src/interface/widgets/tabs/tab_supervisor.h b/cockatrice/src/interface/widgets/tabs/tab_supervisor.h index 9fd00f584..948ac6d7e 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_supervisor.h +++ b/cockatrice/src/interface/widgets/tabs/tab_supervisor.h @@ -11,6 +11,7 @@ #include "../../deck_loader/deck_loader.h" #include "../interface/widgets/server/user/user_list_proxy.h" #include "abstract_tab_deck_editor.h" +#include "api/archidekt/tab_archidekt.h" #include "api/edhrec/tab_edhrec.h" #include "api/edhrec/tab_edhrec_main.h" #include "tab_visual_database_display.h" @@ -110,7 +111,7 @@ private: QList deckEditorTabs; bool isLocalGame; - QAction *aTabHome, *aTabDeckEditor, *aTabVisualDeckEditor, *aTabEdhRec, *aTabVisualDeckStorage, + QAction *aTabHome, *aTabDeckEditor, *aTabVisualDeckEditor, *aTabEdhRec, *aTabArchidekt, *aTabVisualDeckStorage, *aTabVisualDatabaseDisplay, *aTabServer, *aTabAccount, *aTabDeckStorage, *aTabReplays, *aTabAdmin, *aTabLog; int myAddTab(Tab *tab, QAction *manager = nullptr); @@ -172,6 +173,7 @@ public slots: TabDeckEditorVisual *addVisualDeckEditorTab(DeckLoader *deckToOpen); TabVisualDatabaseDisplay *addVisualDatabaseDisplayTab(); TabEdhRecMain *addEdhrecMainTab(); + TabArchidekt *addArchidektTab(); TabEdhRec *addEdhrecTab(const CardInfoPtr &cardToQuery, bool isCommander = false); void openReplay(GameReplay *replay); void switchToFirstAvailableNetworkTab(); diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.cpp new file mode 100644 index 000000000..c190038a5 --- /dev/null +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.cpp @@ -0,0 +1,124 @@ +#include "visual_deck_display_options_widget.h" + +#include "../tabs/visual_deck_editor/tab_deck_editor_visual.h" + +VisualDeckDisplayOptionsWidget::VisualDeckDisplayOptionsWidget(QWidget *parent) +{ + groupAndSortLayout = new QHBoxLayout(this); + groupAndSortLayout->setAlignment(Qt::AlignLeft); + this->setLayout(groupAndSortLayout); + + groupByLabel = new QLabel(this); + + groupByComboBox = new QComboBox(this); + if (auto visualDeckEditorWidget = qobject_cast(parent)) { + if (auto tabWidget = qobject_cast(visualDeckEditorWidget)) { + // 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 { + groupByComboBox->addItem( + tr(qPrintable(DeckListModelGroupCriteria::toString(DeckListModelGroupCriteria::MAIN_TYPE))), + DeckListModelGroupCriteria::MAIN_TYPE); + groupByComboBox->addItem( + tr(qPrintable(DeckListModelGroupCriteria::toString(DeckListModelGroupCriteria::MANA_COST))), + DeckListModelGroupCriteria::MANA_COST); + groupByComboBox->addItem( + tr(qPrintable(DeckListModelGroupCriteria::toString(DeckListModelGroupCriteria::COLOR))), + DeckListModelGroupCriteria::COLOR); + groupByComboBox->setMinimumWidth(300); + connect(groupByComboBox, QOverload::of(&QComboBox::currentTextChanged), this, + &VisualDeckDisplayOptionsWidget::groupCriteriaChanged); + emit groupCriteriaChanged(groupByComboBox->currentText()); + } + + sortByLabel = new QLabel(this); + + sortCriteriaButton = new SettingsButtonWidget(this); + + sortLabel = new QLabel(sortCriteriaButton); + sortLabel->setWordWrap(true); + + QStringList sortProperties = {"colors", "cmc", "name", "maintype"}; + sortByListWidget = new QListWidget(); + sortByListWidget->setSelectionMode(QAbstractItemView::SingleSelection); + sortByListWidget->setDragDropMode(QAbstractItemView::InternalMove); + sortByListWidget->setDefaultDropAction(Qt::MoveAction); + + for (const QString &property : sortProperties) { + QListWidgetItem *item = new QListWidgetItem(property, sortByListWidget); + item->setFlags(item->flags() | Qt::ItemIsDragEnabled | Qt::ItemIsSelectable | Qt::ItemIsEnabled); + } + + connect(sortByListWidget->model(), &QAbstractItemModel::rowsMoved, this, + &VisualDeckDisplayOptionsWidget::onSortCriteriaChange); + onSortCriteriaChange(); + + sortByListWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + + sortCriteriaButton->addSettingsWidget(sortLabel); + sortCriteriaButton->addSettingsWidget(sortByListWidget); + + displayTypeButton = new QPushButton(this); + connect(displayTypeButton, &QPushButton::clicked, this, &VisualDeckDisplayOptionsWidget::updateDisplayType); + + groupAndSortLayout->addWidget(groupByLabel); + groupAndSortLayout->addWidget(groupByComboBox); + groupAndSortLayout->addWidget(sortByLabel); + groupAndSortLayout->addWidget(sortCriteriaButton); + groupAndSortLayout->addWidget(displayTypeButton); + + retranslateUi(); +} + +void VisualDeckDisplayOptionsWidget::retranslateUi() +{ + groupByLabel->setText(tr("Group by:")); + groupByComboBox->setToolTip(tr("Change how cards are divided into categories/groups.")); + sortByLabel->setText(tr("Sort by:")); + sortLabel->setText(tr("Click and drag to change the sort order within the groups")); + sortCriteriaButton->setToolTip(tr("Configure how cards are sorted within their groups")); + displayTypeButton->setText(tr("Toggle Layout: Overlap")); + displayTypeButton->setToolTip( + tr("Change how cards are displayed within zones (i.e. overlapped or fully visible.)")); +} + +void VisualDeckDisplayOptionsWidget::onSortCriteriaChange() +{ + QStringList selectedCriteria; + for (int i = 0; i < sortByListWidget->count(); ++i) { + QListWidgetItem *item = sortByListWidget->item(i); + selectedCriteria.append(item->text()); // Collect user-defined sort order + } + + emit sortCriteriaChanged(selectedCriteria); +} + +void VisualDeckDisplayOptionsWidget::updateDisplayType() +{ + // Toggle the display type + currentDisplayType = (currentDisplayType == DisplayType::Overlap) ? DisplayType::Flat : DisplayType::Overlap; + + // Update UI and emit signal + switch (currentDisplayType) { + case DisplayType::Flat: + displayTypeButton->setText(tr("Toggle Layout: Flat")); + break; + case DisplayType::Overlap: + displayTypeButton->setText(tr("Toggle Layout: Overlap")); + break; + } + emit displayTypeChanged(currentDisplayType); +} diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.h b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.h new file mode 100644 index 000000000..7a447753f --- /dev/null +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.h @@ -0,0 +1,138 @@ +#ifndef COCKATRICE_VISUAL_DECK_DISPLAY_OPTIONS_WIDGET_H +#define COCKATRICE_VISUAL_DECK_DISPLAY_OPTIONS_WIDGET_H + +#include "visual_deck_editor_widget.h" + +#include +#include +#include +#include +#include +#include + +/** + * @class VisualDeckDisplayOptionsWidget + * @brief A widget that controls how deck cards are displayed in the visual deck editor. + * + * This widget provides: + * - A **group-by** selector (QComboBox) + * - A **sort-by** multi-criteria, draggable list (QListWidget within a SettingsButtonWidget) + * - A **display-type toggler** (flat vs. overlap layout) + * + * Depending on whether the parent is a VisualDeckEditorWidget, this widget can mirror the + * original group by checkbox from the main deck editor UI to maintain synchronization. + * + * It emits signals whenever the grouping criterion, sorting criteria, or display mode changes. + */ +class VisualDeckDisplayOptionsWidget : public QWidget +{ + Q_OBJECT +signals: + /** + * @brief Emitted when the display type (flat or overlapping layout) changes. + * @param displayType The newly selected display layout. + */ + void displayTypeChanged(const DisplayType &displayType); + + /** + * @brief Emitted when a new grouping criterion is selected. + * @param activeGroupCriteria Name of the selected group-by criterion. + */ + void groupCriteriaChanged(const QString &activeGroupCriteria); + + /** + * @brief Emitted when the order of sort criteria changes. + * @param activeSortCriteria Ordered list of sorting keys. + */ + void sortCriteriaChanged(const QStringList &activeSortCriteria); + +public slots: + /** + * @brief Updates all UI text for retranslation/localization. + * + * Called when the application language changes. + */ + void retranslateUi(); + +public: + /** + * @brief Constructs a new VisualDeckDisplayOptionsWidget. + * @param parent The parent QWidget—may trigger cloning of models if the parent is a visual deck editor. + */ + explicit VisualDeckDisplayOptionsWidget(QWidget *parent); + + /** + * @brief Gets the current display type (Overlap or Flat). + */ + DisplayType getDisplayType() const + { + return currentDisplayType; + } + + /** + * @brief Gets the currently active group-by criterion. + */ + QString getActiveGroupCriteria() const + { + return activeGroupCriteria; + } + + /** + * @brief Gets the currently active ordered sort criteria. + */ + QStringList getActiveSortCriteria() const + { + return activeSortCriteria; + } + +private slots: + /** + * @brief Slot triggered whenever the sort list is reordered. + * + * Reads the QListWidget’s order and emits `sortCriteriaChanged()`. + */ + void onSortCriteriaChange(); + + /** + * @brief Toggles the display layout between flat and overlapping modes. + * + * Emits `displayTypeChanged()`. + */ + void updateDisplayType(); + +private: + /// Layout for grouping and sorting UI elements. + QHBoxLayout *groupAndSortLayout; + + /// Current deck display type. + DisplayType currentDisplayType = DisplayType::Overlap; + + /// Button used to toggle the display layout. + QPushButton *displayTypeButton; + + /// Label for the group-by selector. + QLabel *groupByLabel; + + /// Combo box listing group-by criteria. + QComboBox *groupByComboBox; + + /// Currently active group-by criterion. + QString activeGroupCriteria = "maintype"; + + /// Encapsulates the sort settings widgets (label + list). + SettingsButtonWidget *sortCriteriaButton; + + /// Label for “Sort by”. + QLabel *sortByLabel; + + /// Descriptive label inside the sort criteria button. + QLabel *sortLabel; + + /// Draggable list of sort criteria. + QListWidget *sortByListWidget; + + /// Ordered list of current sort criteria. + QStringList activeSortCriteria = {"name", "cmc", "colors", "maintype"}; +}; + +#endif // COCKATRICE_VISUAL_DECK_DISPLAY_OPTIONS_WIDGET_H 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 5acad9df1..76cfe8c8e 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 @@ -9,6 +9,7 @@ #include "../general/layout_containers/flow_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 "visual_deck_display_options_widget.h" #include #include @@ -109,75 +110,22 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, } }); - groupAndSortContainer = new QWidget(this); - groupAndSortLayout = new QHBoxLayout(groupAndSortContainer); - groupAndSortLayout->setAlignment(Qt::AlignLeft); - groupAndSortContainer->setLayout(groupAndSortLayout); + displayOptionsAndSearch = new QWidget(this); + displayOptionsAndSearchLayout = new QHBoxLayout(displayOptionsAndSearch); + displayOptionsAndSearchLayout->setAlignment(Qt::AlignLeft); + displayOptionsAndSearch->setLayout(displayOptionsAndSearchLayout); - groupByLabel = new QLabel(groupAndSortContainer); + displayOptionsWidget = new VisualDeckDisplayOptionsWidget(this); + connect(displayOptionsWidget, &VisualDeckDisplayOptionsWidget::displayTypeChanged, this, + &VisualDeckEditorWidget::displayTypeChanged); + connect(displayOptionsWidget, &VisualDeckDisplayOptionsWidget::groupCriteriaChanged, this, + &VisualDeckEditorWidget::activeGroupCriteriaChanged); + connect(displayOptionsWidget, &VisualDeckDisplayOptionsWidget::sortCriteriaChanged, this, + &VisualDeckEditorWidget::activeSortCriteriaChanged); - 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(); - } - - sortByLabel = new QLabel(groupAndSortContainer); - - sortCriteriaButton = new SettingsButtonWidget(this); - - sortLabel = new QLabel(sortCriteriaButton); - sortLabel->setWordWrap(true); - - QStringList sortProperties = {"colors", "cmc", "name", "maintype"}; - sortByListWidget = new QListWidget(); - sortByListWidget->setSelectionMode(QAbstractItemView::SingleSelection); - sortByListWidget->setDragDropMode(QAbstractItemView::InternalMove); - sortByListWidget->setDefaultDropAction(Qt::MoveAction); - - for (const QString &property : sortProperties) { - QListWidgetItem *item = new QListWidgetItem(property, sortByListWidget); - item->setFlags(item->flags() | Qt::ItemIsDragEnabled | Qt::ItemIsSelectable | Qt::ItemIsEnabled); - } - - connect(sortByListWidget->model(), &QAbstractItemModel::rowsMoved, this, - &VisualDeckEditorWidget::actChangeActiveSortCriteria); - actChangeActiveSortCriteria(); - - sortByListWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); - - sortCriteriaButton->addSettingsWidget(sortLabel); - sortCriteriaButton->addSettingsWidget(sortByListWidget); - - displayTypeButton = new QPushButton(this); - connect(displayTypeButton, &QPushButton::clicked, this, &VisualDeckEditorWidget::updateDisplayType); - - groupAndSortLayout->addWidget(groupByLabel); - groupAndSortLayout->addWidget(groupByComboBox); - groupAndSortLayout->addWidget(sortByLabel); - groupAndSortLayout->addWidget(sortCriteriaButton); - groupAndSortLayout->addWidget(displayTypeButton); - groupAndSortLayout->addWidget(searchBar); - groupAndSortLayout->addWidget(searchPushButton); + displayOptionsAndSearchLayout->addWidget(displayOptionsWidget); + displayOptionsAndSearchLayout->addWidget(searchBar); + displayOptionsAndSearchLayout->addWidget(searchPushButton); scrollArea = new QScrollArea(this); scrollArea->setWidgetResizable(true); @@ -197,7 +145,7 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, connect(cardSizeWidget, &CardSizeWidget::cardSizeSettingUpdated, &SettingsCache::instance(), &SettingsCache::setVisualDeckEditorCardSize); - mainLayout->addWidget(groupAndSortContainer); + mainLayout->addWidget(displayOptionsAndSearch); mainLayout->addWidget(scrollArea); mainLayout->addWidget(cardSizeWidget); @@ -218,17 +166,9 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, void VisualDeckEditorWidget::retranslateUi() { searchBar->setPlaceholderText(tr("Type a card name here for suggestions from the database...")); - groupByLabel->setText(tr("Group by:")); - groupByComboBox->setToolTip(tr("Change how cards are divided into categories/groups.")); - sortByLabel->setText(tr("Sort by:")); - sortLabel->setText(tr("Click and drag to change the sort order within the groups")); searchPushButton->setText(tr("Quick search and add card")); searchPushButton->setToolTip(tr("Search for closest match in the database (with auto-suggestions) and add " "preferred printing to the deck on pressing enter")); - sortCriteriaButton->setToolTip(tr("Configure how cards are sorted within their groups")); - displayTypeButton->setText(tr("Toggle Layout: Overlap")); - displayTypeButton->setToolTip( - tr("Change how cards are displayed within zones (i.e. overlapped or fully visible.)")); } void VisualDeckEditorWidget::setSelectionModel(QItemSelectionModel *model) @@ -326,8 +266,9 @@ void VisualDeckEditorWidget::constructZoneWidgetForIndex(QPersistentModelIndex p { DeckCardZoneDisplayWidget *zoneDisplayWidget = new DeckCardZoneDisplayWidget( zoneContainer, deckListModel, selectionModel, persistent, - deckListModel->data(persistent.sibling(persistent.row(), 1), Qt::EditRole).toString(), activeGroupCriteria, - activeSortCriteria, currentDisplayType, 20, 10, cardSizeWidget); + deckListModel->data(persistent.sibling(persistent.row(), 1), Qt::EditRole).toString(), + displayOptionsWidget->getActiveGroupCriteria(), displayOptionsWidget->getActiveSortCriteria(), + displayOptionsWidget->getDisplayType(), 20, 10, cardSizeWidget); connect(zoneDisplayWidget, &DeckCardZoneDisplayWidget::cardHovered, this, &VisualDeckEditorWidget::onHover); connect(zoneDisplayWidget, &DeckCardZoneDisplayWidget::cardClicked, this, &VisualDeckEditorWidget::onCardClick); connect(zoneDisplayWidget, &DeckCardZoneDisplayWidget::requestCleanup, this, @@ -338,7 +279,7 @@ void VisualDeckEditorWidget::constructZoneWidgetForIndex(QPersistentModelIndex p &DeckCardZoneDisplayWidget::onActiveGroupCriteriaChanged); connect(this, &VisualDeckEditorWidget::displayTypeChanged, zoneDisplayWidget, &DeckCardZoneDisplayWidget::refreshDisplayType); - zoneDisplayWidget->refreshDisplayType(currentDisplayType); + zoneDisplayWidget->refreshDisplayType(displayOptionsWidget->getDisplayType()); zoneContainerLayout->addWidget(zoneDisplayWidget); indexToWidgetMap.insert(persistent, zoneDisplayWidget); @@ -370,48 +311,12 @@ void VisualDeckEditorWidget::updateZoneWidgets() { } -void VisualDeckEditorWidget::updateDisplayType() -{ - // Toggle the display type - currentDisplayType = (currentDisplayType == DisplayType::Overlap) ? DisplayType::Flat : DisplayType::Overlap; - - // Update UI and emit signal - switch (currentDisplayType) { - case DisplayType::Flat: - displayTypeButton->setText(tr("Toggle Layout: Flat")); - break; - case DisplayType::Overlap: - displayTypeButton->setText(tr("Toggle Layout: Overlap")); - break; - } - emit displayTypeChanged(currentDisplayType); -} - void VisualDeckEditorWidget::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); zoneContainer->setMaximumWidth(scrollArea->viewport()->width()); } -void VisualDeckEditorWidget::actChangeActiveGroupCriteria() -{ - activeGroupCriteria = groupByComboBox->currentText(); - emit activeGroupCriteriaChanged(activeGroupCriteria); -} - -void VisualDeckEditorWidget::actChangeActiveSortCriteria() -{ - QStringList selectedCriteria; - for (int i = 0; i < sortByListWidget->count(); ++i) { - QListWidgetItem *item = sortByListWidget->item(i); - selectedCriteria.append(item->text()); // Collect user-defined sort order - } - - activeSortCriteria = selectedCriteria; - - emit activeSortCriteriaChanged(selectedCriteria); -} - void VisualDeckEditorWidget::decklistModelReset() { clearAllDisplayWidgets(); diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h index 524762d89..3a60d09a7 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h @@ -23,6 +23,7 @@ #include #include +class VisualDeckDisplayOptionsWidget; class DeckCardZoneDisplayWidget; enum class DisplayType { @@ -55,7 +56,6 @@ public: public slots: void decklistDataChanged(QModelIndex topLeft, QModelIndex bottomRight); void updateZoneWidgets(); - void updateDisplayType(); void cleanupInvalidZones(DeckCardZoneDisplayWidget *displayWidget); void onCardAddition(const QModelIndex &parent, int first, int last); void onCardRemoval(const QModelIndex &parent, int first, int last); @@ -73,8 +73,6 @@ signals: protected slots: void onHover(const ExactCard &hoveredCard); void onCardClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance, QString zoneName); - void actChangeActiveGroupCriteria(); - void actChangeActiveSortCriteria(); void decklistModelReset(); private: @@ -85,19 +83,10 @@ private: CardDatabaseDisplayModel *cardDatabaseDisplayModel; CardCompleterProxyModel *proxyModel; QCompleter *completer; + QWidget *displayOptionsAndSearch; + QHBoxLayout *displayOptionsAndSearchLayout; + VisualDeckDisplayOptionsWidget *displayOptionsWidget; QPushButton *searchPushButton; - DisplayType currentDisplayType = DisplayType::Overlap; - QPushButton *displayTypeButton; - QWidget *groupAndSortContainer; - QHBoxLayout *groupAndSortLayout; - QLabel *groupByLabel; - QComboBox *groupByComboBox; - QString activeGroupCriteria = "maintype"; - SettingsButtonWidget *sortCriteriaButton; - QLabel *sortByLabel; - QLabel *sortLabel; - QListWidget *sortByListWidget; - QStringList activeSortCriteria = {"name", "cmc", "colors", "maintype"}; QScrollArea *scrollArea; QWidget *zoneContainer; QVBoxLayout *zoneContainerLayout; 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 9b96c0ce6..1e4a53553 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h +++ b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h @@ -74,6 +74,29 @@ enum Type MANA_COST, /**< Group cards by their total mana cost. */ COLOR /**< Group cards by their color identity. */ }; +static inline QString toString(Type t) +{ + switch (t) { + case MAIN_TYPE: + return "Main Type"; + case MANA_COST: + return "Mana Cost"; + case COLOR: + return "Colors"; + } + return {}; +} + +static inline Type fromString(const QString &s) +{ + if (s == "Main Type") + return MAIN_TYPE; + if (s == "Mana Cost") + return MANA_COST; + if (s == "Colors") + return COLOR; + return MAIN_TYPE; // default +} } // namespace DeckListModelGroupCriteria /** @@ -234,8 +257,8 @@ public: */ [[nodiscard]] QModelIndex findCard(const QString &cardName, const QString &zoneName, - const QString &providerId = "", - const QString &cardNumber = "") const; + const QString &providerId = "", + const QString &cardNumber = "") const; /** * @brief Adds a card using the preferred printing if available. @@ -296,8 +319,8 @@ private: QModelIndex nodeToIndex(AbstractDecklistNode *node) const; [[nodiscard]] DecklistModelCardNode *findCardNode(const QString &cardName, const QString &zoneName, - const QString &providerId = "", - const QString &cardNumber = "") const; + const QString &providerId = "", + const QString &cardNumber = "") const; void emitRecursiveUpdates(const QModelIndex &index); void sortHelper(InnerDecklistNode *node, Qt::SortOrder order); From 2b64e65f450191df37023db78e65c813da10261f Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Sun, 30 Nov 2025 13:03:18 +0100 Subject: [PATCH 17/40] [CardInfoPictureEnlargedWidget] Fix DPR scaling. (#6382) --- .../card_info_picture_enlarged_widget.cpp | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) 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 1024315a1..185bb20d1 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 @@ -33,10 +33,13 @@ CardInfoPictureEnlargedWidget::CardInfoPictureEnlargedWidget(QWidget *parent) : */ void CardInfoPictureEnlargedWidget::loadPixmap(const QSize &size) { + // Handle DPI scaling + qreal dpr = devicePixelRatio(); // Get the actual scaling factor + QSize availableSize = size * dpr; // Convert to physical pixel size if (card) { - CardPictureLoader::getPixmap(enlargedPixmap, card, size); + CardPictureLoader::getPixmap(enlargedPixmap, card, availableSize); } else { - CardPictureLoader::getCardBackPixmap(enlargedPixmap, size); + CardPictureLoader::getCardBackPixmap(enlargedPixmap, availableSize); } pixmapDirty = false; } @@ -77,25 +80,35 @@ void CardInfoPictureEnlargedWidget::paintEvent(QPaintEvent *event) loadPixmap(size()); } - // Scale the size of the pixmap to fit the widget while maintaining the aspect ratio - QSize scaledSize = enlargedPixmap.size().scaled(size().width(), size().height(), Qt::KeepAspectRatio); + qreal dpr = enlargedPixmap.devicePixelRatio(); - // Calculate the position to center the scaled pixmap - QPoint topLeft{(width() - scaledSize.width()) / 2, (height() - scaledSize.height()) / 2}; + QSize logicalPixmapSize(enlargedPixmap.width() / dpr, enlargedPixmap.height() / dpr); - // Define the radius for rounded corners - // Adjust the radius as needed for rounded corners - qreal radius = SettingsCache::instance().getRoundCardCorners() ? 0.05 * scaledSize.width() : 0.; + // Scale the pixmap to fit the widget (logical → logical) + QSize scaledLogicalSize = logicalPixmapSize.scaled(size(), Qt::KeepAspectRatio); + + // Convert scaled logical size → physical size for scaled() + QSize scaledPhysicalSize = scaledLogicalSize * dpr; + + // Pixmap scaled in PHYSICAL pixels + QPixmap finalPixmap = enlargedPixmap.scaled(scaledPhysicalSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); + + finalPixmap.setDevicePixelRatio(dpr); + + // Center inside widget + QPoint topLeft{(width() - scaledLogicalSize.width()) / 2, (height() - scaledLogicalSize.height()) / 2}; + + // Rounded corner radius based on logical width + qreal radius = SettingsCache::instance().getRoundCardCorners() ? 0.05 * scaledLogicalSize.width() : 0.0; QStylePainter painter(this); // Fill the background with transparent color to ensure rounded corners are rendered properly painter.fillRect(rect(), Qt::transparent); // Use the transparent background QPainterPath shape; - shape.addRoundedRect(QRect(topLeft, scaledSize), radius, radius); + shape.addRoundedRect(QRect(topLeft, scaledLogicalSize), radius, radius); painter.setClipPath(shape); // Set the clipping path // Draw the pixmap scaled to the calculated size - painter.drawItemPixmap(QRect(topLeft, scaledSize), Qt::AlignCenter, - enlargedPixmap.scaled(scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation)); + painter.drawPixmap(QRect(topLeft, scaledLogicalSize), finalPixmap); } From d57bec8ec600c725379c3e312e120c1919c91006 Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Sun, 30 Nov 2025 04:05:49 -0800 Subject: [PATCH 18/40] [DeckList] Move decklist node classes into new folder (#6381) * [DeckList] Move decklist node classes into new folder * reformat * fix --- .../network/interfaces/deck_stats_interface.cpp | 2 +- .../network/interfaces/tapped_out_interface.cpp | 2 +- cockatrice/src/game/deckview/deck_view.cpp | 2 +- cockatrice/src/game/player/menu/utility_menu.cpp | 3 ++- .../src/interface/deck_loader/deck_loader.cpp | 2 +- libcockatrice_deck_list/CMakeLists.txt | 16 ++++++++-------- .../libcockatrice/deck_list/deck_list.cpp | 6 +++--- .../libcockatrice/deck_list/deck_list.h | 2 +- .../{ => tree}/abstract_deck_list_card_node.cpp | 0 .../{ => tree}/abstract_deck_list_card_node.h | 0 .../{ => tree}/abstract_deck_list_node.cpp | 0 .../{ => tree}/abstract_deck_list_node.h | 0 .../deck_list/{ => tree}/deck_list_card_node.cpp | 0 .../deck_list/{ => tree}/deck_list_card_node.h | 0 .../{ => tree}/inner_deck_list_node.cpp | 0 .../deck_list/{ => tree}/inner_deck_list_node.h | 0 .../models/deck_list/deck_list_model.h | 4 ++-- .../network/server/remote/game/server_player.cpp | 2 +- .../loading_from_clipboard/clipboard_testing.cpp | 2 +- 19 files changed, 22 insertions(+), 21 deletions(-) rename libcockatrice_deck_list/libcockatrice/deck_list/{ => tree}/abstract_deck_list_card_node.cpp (100%) rename libcockatrice_deck_list/libcockatrice/deck_list/{ => tree}/abstract_deck_list_card_node.h (100%) rename libcockatrice_deck_list/libcockatrice/deck_list/{ => tree}/abstract_deck_list_node.cpp (100%) rename libcockatrice_deck_list/libcockatrice/deck_list/{ => tree}/abstract_deck_list_node.h (100%) rename libcockatrice_deck_list/libcockatrice/deck_list/{ => tree}/deck_list_card_node.cpp (100%) rename libcockatrice_deck_list/libcockatrice/deck_list/{ => tree}/deck_list_card_node.h (100%) rename libcockatrice_deck_list/libcockatrice/deck_list/{ => tree}/inner_deck_list_node.cpp (100%) rename libcockatrice_deck_list/libcockatrice/deck_list/{ => tree}/inner_deck_list_node.h (100%) diff --git a/cockatrice/src/client/network/interfaces/deck_stats_interface.cpp b/cockatrice/src/client/network/interfaces/deck_stats_interface.cpp index eeb48959c..6c295beb9 100644 --- a/cockatrice/src/client/network/interfaces/deck_stats_interface.cpp +++ b/cockatrice/src/client/network/interfaces/deck_stats_interface.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include DeckStatsInterface::DeckStatsInterface(CardDatabase &_cardDatabase, QObject *parent) : QObject(parent), cardDatabase(_cardDatabase) diff --git a/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp b/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp index cebbce8b8..4bfeba7b1 100644 --- a/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp +++ b/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include TappedOutInterface::TappedOutInterface(CardDatabase &_cardDatabase, QObject *parent) : QObject(parent), cardDatabase(_cardDatabase) diff --git a/cockatrice/src/game/deckview/deck_view.cpp b/cockatrice/src/game/deckview/deck_view.cpp index 64e9abc46..edef3fad4 100644 --- a/cockatrice/src/game/deckview/deck_view.cpp +++ b/cockatrice/src/game/deckview/deck_view.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include DeckViewCardDragItem::DeckViewCardDragItem(DeckViewCard *_item, const QPointF &_hotSpot, diff --git a/cockatrice/src/game/player/menu/utility_menu.cpp b/cockatrice/src/game/player/menu/utility_menu.cpp index ca2832ec7..a3117abf8 100644 --- a/cockatrice/src/game/player/menu/utility_menu.cpp +++ b/cockatrice/src/game/player/menu/utility_menu.cpp @@ -3,9 +3,10 @@ #include "../../../interface/deck_loader/deck_loader.h" #include "../player.h" #include "../player_actions.h" -#include "libcockatrice/deck_list/inner_deck_list_node.h" #include "player_menu.h" +#include + UtilityMenu::UtilityMenu(Player *_player, QMenu *playerMenu) : QMenu(playerMenu), player(_player) { PlayerActions *playerActions = player->getPlayerActions(); diff --git a/cockatrice/src/interface/deck_loader/deck_loader.cpp b/cockatrice/src/interface/deck_loader/deck_loader.cpp index 372aa0aa8..eea906a97 100644 --- a/cockatrice/src/interface/deck_loader/deck_loader.cpp +++ b/cockatrice/src/interface/deck_loader/deck_loader.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include const QStringList DeckLoader::ACCEPTED_FILE_EXTENSIONS = {"*.cod", "*.dec", "*.dek", "*.txt", "*.mwDeck"}; diff --git a/libcockatrice_deck_list/CMakeLists.txt b/libcockatrice_deck_list/CMakeLists.txt index d9b27354b..5dffff3f7 100644 --- a/libcockatrice_deck_list/CMakeLists.txt +++ b/libcockatrice_deck_list/CMakeLists.txt @@ -3,13 +3,13 @@ set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) set(HEADERS - libcockatrice/deck_list/abstract_deck_list_card_node.h - libcockatrice/deck_list/abstract_deck_list_node.h + libcockatrice/deck_list/tree/abstract_deck_list_card_node.h + libcockatrice/deck_list/tree/abstract_deck_list_node.h + libcockatrice/deck_list/tree/deck_list_card_node.h + libcockatrice/deck_list/tree/inner_deck_list_node.h libcockatrice/deck_list/deck_list.h - libcockatrice/deck_list/deck_list_card_node.h libcockatrice/deck_list/deck_list_history_manager.h libcockatrice/deck_list/deck_list_memento.h - libcockatrice/deck_list/inner_deck_list_node.h ) if(Qt6_FOUND) @@ -21,12 +21,12 @@ endif() add_library( libcockatrice_deck_list STATIC ${MOC_SOURCES} - libcockatrice/deck_list/abstract_deck_list_card_node.cpp - libcockatrice/deck_list/abstract_deck_list_node.cpp + libcockatrice/deck_list/tree/abstract_deck_list_card_node.cpp + libcockatrice/deck_list/tree/abstract_deck_list_node.cpp + libcockatrice/deck_list/tree/deck_list_card_node.cpp + libcockatrice/deck_list/tree/inner_deck_list_node.cpp libcockatrice/deck_list/deck_list.cpp - libcockatrice/deck_list/deck_list_card_node.cpp libcockatrice/deck_list/deck_list_history_manager.cpp - libcockatrice/deck_list/inner_deck_list_node.cpp ) add_dependencies(libcockatrice_deck_list libcockatrice_protocol) diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp index f06652d7c..c44012486 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp @@ -1,9 +1,9 @@ #include "deck_list.h" -#include "abstract_deck_list_node.h" -#include "deck_list_card_node.h" #include "deck_list_memento.h" -#include "inner_deck_list_node.h" +#include "tree/abstract_deck_list_node.h" +#include "tree/deck_list_card_node.h" +#include "tree/inner_deck_list_node.h" #include #include diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h index f6bd54382..cbab9ce5d 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h @@ -11,7 +11,7 @@ #define DECKLIST_H #include "deck_list_memento.h" -#include "inner_deck_list_node.h" +#include "tree/inner_deck_list_node.h" #include #include diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/abstract_deck_list_card_node.cpp b/libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_card_node.cpp similarity index 100% rename from libcockatrice_deck_list/libcockatrice/deck_list/abstract_deck_list_card_node.cpp rename to libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_card_node.cpp diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/abstract_deck_list_card_node.h b/libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_card_node.h similarity index 100% rename from libcockatrice_deck_list/libcockatrice/deck_list/abstract_deck_list_card_node.h rename to libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_card_node.h diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/abstract_deck_list_node.cpp b/libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_node.cpp similarity index 100% rename from libcockatrice_deck_list/libcockatrice/deck_list/abstract_deck_list_node.cpp rename to libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_node.cpp diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/abstract_deck_list_node.h b/libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_node.h similarity index 100% rename from libcockatrice_deck_list/libcockatrice/deck_list/abstract_deck_list_node.h rename to libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_node.h diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_card_node.cpp b/libcockatrice_deck_list/libcockatrice/deck_list/tree/deck_list_card_node.cpp similarity index 100% rename from libcockatrice_deck_list/libcockatrice/deck_list/deck_list_card_node.cpp rename to libcockatrice_deck_list/libcockatrice/deck_list/tree/deck_list_card_node.cpp diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_card_node.h b/libcockatrice_deck_list/libcockatrice/deck_list/tree/deck_list_card_node.h similarity index 100% rename from libcockatrice_deck_list/libcockatrice/deck_list/deck_list_card_node.h rename to libcockatrice_deck_list/libcockatrice/deck_list/tree/deck_list_card_node.h diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/inner_deck_list_node.cpp b/libcockatrice_deck_list/libcockatrice/deck_list/tree/inner_deck_list_node.cpp similarity index 100% rename from libcockatrice_deck_list/libcockatrice/deck_list/inner_deck_list_node.cpp rename to libcockatrice_deck_list/libcockatrice/deck_list/tree/inner_deck_list_node.cpp diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/inner_deck_list_node.h b/libcockatrice_deck_list/libcockatrice/deck_list/tree/inner_deck_list_node.h similarity index 100% rename from libcockatrice_deck_list/libcockatrice/deck_list/inner_deck_list_node.h rename to libcockatrice_deck_list/libcockatrice/deck_list/tree/inner_deck_list_node.h 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 1e4a53553..a480c606b 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h +++ b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h @@ -1,12 +1,12 @@ #ifndef DECKLISTMODEL_H #define DECKLISTMODEL_H +#include <../../../../libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_card_node.h> +#include <../../../../libcockatrice_deck_list/libcockatrice/deck_list/tree/deck_list_card_node.h> #include #include #include -#include #include -#include class CardDatabase; class QPrinter; diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp index b59d89ed8..8190155e9 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/tests/loading_from_clipboard/clipboard_testing.cpp b/tests/loading_from_clipboard/clipboard_testing.cpp index df2806585..2342bc088 100644 --- a/tests/loading_from_clipboard/clipboard_testing.cpp +++ b/tests/loading_from_clipboard/clipboard_testing.cpp @@ -1,7 +1,7 @@ #include "clipboard_testing.h" #include -#include +#include void testEmpty(const QString &clipboard) { From 3ff2df279681be9e690e30b07dfb9fe17a939d91 Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Sun, 30 Nov 2025 04:09:09 -0800 Subject: [PATCH 19/40] [DeckList] Move metadata into struct (#6380) * [DeckList] Move metadata into struct * wipe metadata if preserveMetadata is false --- .../libcockatrice/deck_list/deck_list.cpp | 59 +++++++++++-------- .../libcockatrice/deck_list/deck_list.h | 56 ++++++++++++------ .../libcockatrice/utility/card_ref.h | 5 ++ 3 files changed, 76 insertions(+), 44 deletions(-) diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp index c44012486..37f537249 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp @@ -77,6 +77,11 @@ void SideboardPlan::write(QXmlStreamWriter *xml) xml->writeEndElement(); } +bool DeckList::Metadata::isEmpty() const +{ + return name.isEmpty() && comments.isEmpty() && bannerCard.isEmpty() && tags.isEmpty(); +} + DeckList::DeckList() { root = new InnerDecklistNode; @@ -122,20 +127,20 @@ bool DeckList::readElement(QXmlStreamReader *xml) const QString childName = xml->name().toString(); if (xml->isStartElement()) { if (childName == "lastLoadedTimestamp") { - lastLoadedTimestamp = xml->readElementText(); + metadata.lastLoadedTimestamp = xml->readElementText(); } else if (childName == "deckname") { - name = xml->readElementText(); + metadata.name = xml->readElementText(); } else if (childName == "comments") { - comments = xml->readElementText(); + metadata.comments = xml->readElementText(); } else if (childName == "bannerCard") { QString providerId = xml->attributes().value("providerId").toString(); QString cardName = xml->readElementText(); - bannerCard = {cardName, providerId}; + metadata.bannerCard = {cardName, providerId}; } else if (childName == "tags") { - tags.clear(); // Clear existing tags + metadata.tags.clear(); // Clear existing tags while (xml->readNextStartElement()) { if (xml->name().toString() == "tag") { - tags.append(xml->readElementText()); + metadata.tags.append(xml->readElementText()); } } } else if (childName == "zone") { @@ -155,24 +160,30 @@ bool DeckList::readElement(QXmlStreamReader *xml) return true; } +void writeMetadata(QXmlStreamWriter *xml, const DeckList::Metadata &metadata) +{ + xml->writeTextElement("lastLoadedTimestamp", metadata.lastLoadedTimestamp); + xml->writeTextElement("deckname", metadata.name); + xml->writeStartElement("bannerCard"); + xml->writeAttribute("providerId", metadata.bannerCard.providerId); + xml->writeCharacters(metadata.bannerCard.name); + xml->writeEndElement(); + xml->writeTextElement("comments", metadata.comments); + + // Write tags + xml->writeStartElement("tags"); + for (const QString &tag : metadata.tags) { + xml->writeTextElement("tag", tag); + } + xml->writeEndElement(); +} + void DeckList::write(QXmlStreamWriter *xml) const { xml->writeStartElement("cockatrice_deck"); xml->writeAttribute("version", "1"); - xml->writeTextElement("lastLoadedTimestamp", lastLoadedTimestamp); - xml->writeTextElement("deckname", name); - xml->writeStartElement("bannerCard"); - xml->writeAttribute("providerId", bannerCard.providerId); - xml->writeCharacters(bannerCard.name); - xml->writeEndElement(); - xml->writeTextElement("comments", comments); - // Write tags - xml->writeStartElement("tags"); - for (const QString &tag : tags) { - xml->writeTextElement("tag", tag); - } - xml->writeEndElement(); + writeMetadata(xml, metadata); // Write zones for (int i = 0; i < root->size(); i++) { @@ -329,7 +340,7 @@ bool DeckList::loadFromStream_Plain(QTextStream &in, bool preserveMetadata) const auto ¤t = inputs.at(index++); if (!current.contains(reEmpty)) { match = reComment.match(current); - name = match.captured(); + metadata.name = match.captured(); break; } } @@ -337,10 +348,10 @@ bool DeckList::loadFromStream_Plain(QTextStream &in, bool preserveMetadata) const auto ¤t = inputs.at(index++); if (!current.contains(reEmpty)) { match = reComment.match(current); - comments += match.captured() + '\n'; + metadata.comments += match.captured() + '\n'; } } - comments.chop(1); + metadata.comments.chop(1); // Discard empty lines while (index < max_line && inputs.at(index).contains(reEmpty)) { @@ -504,9 +515,7 @@ void DeckList::cleanList(bool preserveMetadata) { root->clearTree(); if (!preserveMetadata) { - setName(); - setComments(); - setTags(); + metadata = {}; } refreshDeckHash(); } diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h index cbab9ce5d..5340d69fe 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h @@ -126,12 +126,24 @@ public: class DeckList : public QObject { Q_OBJECT + +public: + struct Metadata + { + QString name; ///< User-defined deck name. + QString comments; ///< Free-form comments or notes. + CardRef bannerCard; ///< Optional representative card for the deck. + QStringList tags; ///< User-defined tags for deck classification. + QString lastLoadedTimestamp; ///< Timestamp string of last load. + + /** + * @brief Checks if all values (except for lastLoadedTimestamp) in the metadata is empty. + */ + bool isEmpty() const; + }; + private: - QString name; ///< User-defined deck name. - QString comments; ///< Free-form comments or notes. - CardRef bannerCard; ///< Optional representative card for the deck. - QString lastLoadedTimestamp; ///< Timestamp string of last load. - QStringList tags; ///< User-defined tags for deck classification. + Metadata metadata; ///< Deck metadata that is stored in the deck file QMap sideboardPlans; ///< Named sideboard plans. InnerDecklistNode *root; ///< Root of the deck tree (zones + cards). @@ -181,34 +193,34 @@ public slots: ///@{ void setName(const QString &_name = QString()) { - name = _name; + metadata.name = _name; } void setComments(const QString &_comments = QString()) { - comments = _comments; + metadata.comments = _comments; } void setTags(const QStringList &_tags = QStringList()) { - tags = _tags; + metadata.tags = _tags; emit deckTagsChanged(); } void addTag(const QString &_tag) { - tags.append(_tag); + metadata.tags.append(_tag); emit deckTagsChanged(); } void clearTags() { - tags.clear(); + metadata.tags.clear(); emit deckTagsChanged(); } void setBannerCard(const CardRef &_bannerCard = {}) { - bannerCard = _bannerCard; + metadata.bannerCard = _bannerCard; } void setLastLoadedTimestamp(const QString &_lastLoadedTimestamp = QString()) { - lastLoadedTimestamp = _lastLoadedTimestamp; + metadata.lastLoadedTimestamp = _lastLoadedTimestamp; } ///@} @@ -223,32 +235,38 @@ public: ~DeckList() override; /// @name Metadata getters + /// The individual metadata getters still exist for backwards compatibility. + /// TODO: Figure out when we can remove them. ///@{ + const Metadata &getMetadata() const + { + return metadata; + } QString getName() const { - return name; + return metadata.name; } QString getComments() const { - return comments; + return metadata.comments; } QStringList getTags() const { - return tags; + return metadata.tags; } CardRef getBannerCard() const { - return bannerCard; + return metadata.bannerCard; } QString getLastLoadedTimestamp() const { - return lastLoadedTimestamp; + return metadata.lastLoadedTimestamp; } ///@} bool isBlankDeck() const { - return name.isEmpty() && comments.isEmpty() && getCardList().isEmpty(); + return metadata.isEmpty() && getCardList().isEmpty(); } /// @name Sideboard plans @@ -286,7 +304,7 @@ public: void cleanList(bool preserveMetadata = false); bool isEmpty() const { - return root->isEmpty() && name.isEmpty() && comments.isEmpty() && sideboardPlans.isEmpty(); + return root->isEmpty() && metadata.isEmpty() && sideboardPlans.isEmpty(); } QStringList getCardList() const; QList getCardRefList() const; diff --git a/libcockatrice_utility/libcockatrice/utility/card_ref.h b/libcockatrice_utility/libcockatrice/utility/card_ref.h index d29eee0bb..d89fe590b 100644 --- a/libcockatrice_utility/libcockatrice/utility/card_ref.h +++ b/libcockatrice_utility/libcockatrice/utility/card_ref.h @@ -19,6 +19,11 @@ struct CardRef { return name == other.name && providerId == other.providerId; } + + bool isEmpty() const + { + return name.isEmpty() && providerId.isEmpty(); + } }; #endif // CARD_REF_H From 364d0ca52b701f4cde78d4ed1eb462ca69cb5ddb Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Mon, 1 Dec 2025 09:37:48 +0100 Subject: [PATCH 20/40] [EDHRec] Add background plate and "selection highlight" to card display widgets (#6390) --- .../general/display/background_plate_widget.h | 2 +- ...i_response_card_details_display_widget.cpp | 33 +++++++++++++++++-- ...api_response_card_details_display_widget.h | 12 +++++++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/cockatrice/src/interface/widgets/general/display/background_plate_widget.h b/cockatrice/src/interface/widgets/general/display/background_plate_widget.h index d529cb6fa..1fc1bc3ba 100644 --- a/cockatrice/src/interface/widgets/general/display/background_plate_widget.h +++ b/cockatrice/src/interface/widgets/general/display/background_plate_widget.h @@ -8,7 +8,7 @@ class BackgroundPlateWidget : public QWidget Q_OBJECT public: - explicit BackgroundPlateWidget(QWidget *parent = nullptr); + explicit BackgroundPlateWidget(QWidget *parent); void setFocused(bool focused); 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 108694d8d..26ade96dd 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 @@ -1,5 +1,6 @@ #include "edhrec_api_response_card_details_display_widget.h" +#include "../../../../../general/display/background_plate_widget.h" #include "../../tab_edhrec_main.h" #include @@ -25,8 +26,14 @@ EdhrecApiResponseCardDetailsDisplayWidget::EdhrecApiResponseCardDetailsDisplayWi layout->addWidget(nameLabel); layout->addWidget(cardPictureWidget); - layout->addWidget(inclusionDisplayWidget); - layout->addWidget(synergyDisplayWidget); + + backgroundPlateWidget = new BackgroundPlateWidget(this); + auto plateLayout = new QVBoxLayout(backgroundPlateWidget); + + plateLayout->addWidget(inclusionDisplayWidget); + plateLayout->addWidget(synergyDisplayWidget); + + layout->addWidget(backgroundPlateWidget); QWidget *currentParent = parentWidget(); TabEdhRecMain *parentTab = nullptr; @@ -49,6 +56,28 @@ EdhrecApiResponseCardDetailsDisplayWidget::EdhrecApiResponseCardDetailsDisplayWi } } +void EdhrecApiResponseCardDetailsDisplayWidget::mousePressEvent(QMouseEvent *event) +{ + QWidget::mousePressEvent(event); + actRequestPageNavigation(); +} + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +void EdhrecApiResponseCardDetailsDisplayWidget::enterEvent(QEnterEvent *event) +#else +void EdhrecApiResponseCardDetailsDisplayWidget::enterEvent(QEvent *event) +#endif +{ + QWidget::enterEvent(event); + backgroundPlateWidget->setFocused(true); +} + +void EdhrecApiResponseCardDetailsDisplayWidget::leaveEvent(QEvent *event) +{ + QWidget::leaveEvent(event); + backgroundPlateWidget->setFocused(false); +} + void EdhrecApiResponseCardDetailsDisplayWidget::actRequestPageNavigation() { emit requestUrl(toDisplay.url); diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.h index 548cdc0af..82dcfb8b0 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.h @@ -8,6 +8,7 @@ #define EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H #include "../../../../../cards/card_info_picture_widget.h" +#include "../../../../../general/display/background_plate_widget.h" #include "../../api_response/cards/edhrec_api_response_card_details.h" #include "edhrec_api_response_card_inclusion_display_widget.h" #include "edhrec_api_response_card_synergy_display_widget.h" @@ -30,9 +31,20 @@ private: EdhrecApiResponseCardDetails toDisplay; QVBoxLayout *layout; CardInfoPictureWidget *cardPictureWidget; + BackgroundPlateWidget *backgroundPlateWidget; ///< Plate for metadata labels QLabel *nameLabel; EdhrecApiResponseCardInclusionDisplayWidget *inclusionDisplayWidget; EdhrecApiResponseCardSynergyDisplayWidget *synergyDisplayWidget; + +protected slots: + void mousePressEvent(QMouseEvent *event) override; + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + void enterEvent(QEnterEvent *event) override; ///< Qt6 hover enter +#else + void enterEvent(QEvent *event) override; ///< Qt5 hover enter +#endif + void leaveEvent(QEvent *event) override; }; #endif // EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H From f0ebd281487ffb53e80aa775bf1b103cf5cf30de Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Tue, 2 Dec 2025 13:51:08 +0100 Subject: [PATCH 21/40] [VDE] Consolidate statistical analysis into a separate object (#6392) * [VDE] Consolidate statistical analysis into a separate object so multiple widgets can re-use calculations and calculation is only performed once on data change. * [VDE] Lint. * [VDE] Move struct up to not confuse compiler. * [VDE] NoDiscards * [VDE] Move variables * [VDE] Lint. --- cockatrice/CMakeLists.txt | 1 + .../deck_analytics/deck_analytics_widget.cpp | 15 +-- .../deck_analytics/deck_analytics_widget.h | 3 +- .../deck_list_statistics_analyzer.cpp | 120 ++++++++++++++++++ .../deck_list_statistics_analyzer.h | 60 +++++++++ .../deck_analytics/mana_base_widget.cpp | 68 +--------- .../widgets/deck_analytics/mana_base_widget.h | 11 +- .../deck_analytics/mana_curve_widget.cpp | 36 +----- .../deck_analytics/mana_curve_widget.h | 8 +- .../deck_analytics/mana_devotion_widget.cpp | 82 +----------- .../deck_analytics/mana_devotion_widget.h | 11 +- .../tab_deck_editor_visual.cpp | 2 +- 12 files changed, 215 insertions(+), 202 deletions(-) create mode 100644 cockatrice/src/interface/widgets/deck_analytics/deck_list_statistics_analyzer.cpp create mode 100644 cockatrice/src/interface/widgets/deck_analytics/deck_list_statistics_analyzer.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index eacbc8825..1dbeddc5e 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -142,6 +142,7 @@ set(cockatrice_SOURCES src/interface/widgets/cards/deck_card_zone_display_widget.cpp src/interface/widgets/cards/deck_preview_card_picture_widget.cpp src/interface/widgets/deck_analytics/deck_analytics_widget.cpp + src/interface/widgets/deck_analytics/deck_list_statistics_analyzer.cpp src/interface/widgets/deck_analytics/mana_base_widget.cpp src/interface/widgets/deck_analytics/mana_curve_widget.cpp src/interface/widgets/deck_analytics/mana_devotion_widget.cpp diff --git a/cockatrice/src/interface/widgets/deck_analytics/deck_analytics_widget.cpp b/cockatrice/src/interface/widgets/deck_analytics/deck_analytics_widget.cpp index 2131700fd..45393bb5d 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/deck_analytics_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/deck_analytics_widget.cpp @@ -17,20 +17,19 @@ DeckAnalyticsWidget::DeckAnalyticsWidget(QWidget *parent, DeckListModel *_deckLi container->setLayout(containerLayout); scrollArea->setWidget(container); - manaCurveWidget = new ManaCurveWidget(this, deckListModel); + deckListStatisticsAnalyzer = new DeckListStatisticsAnalyzer(this, deckListModel); + + manaCurveWidget = new ManaCurveWidget(this, deckListStatisticsAnalyzer); containerLayout->addWidget(manaCurveWidget); - manaDevotionWidget = new ManaDevotionWidget(this, deckListModel); + manaDevotionWidget = new ManaDevotionWidget(this, deckListStatisticsAnalyzer); containerLayout->addWidget(manaDevotionWidget); - manaBaseWidget = new ManaBaseWidget(this, deckListModel); + manaBaseWidget = new ManaBaseWidget(this, deckListStatisticsAnalyzer); containerLayout->addWidget(manaBaseWidget); } -void DeckAnalyticsWidget::refreshDisplays(DeckListModel *_deckModel) +void DeckAnalyticsWidget::refreshDisplays() { - deckListModel = _deckModel; - manaCurveWidget->setDeckModel(_deckModel); - manaDevotionWidget->setDeckModel(_deckModel); - manaBaseWidget->setDeckModel(_deckModel); + deckListStatisticsAnalyzer->update(); } diff --git a/cockatrice/src/interface/widgets/deck_analytics/deck_analytics_widget.h b/cockatrice/src/interface/widgets/deck_analytics/deck_analytics_widget.h index e2f00bf0d..524362aed 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/deck_analytics_widget.h +++ b/cockatrice/src/interface/widgets/deck_analytics/deck_analytics_widget.h @@ -24,10 +24,11 @@ public: explicit DeckAnalyticsWidget(QWidget *parent, DeckListModel *deckListModel); void setDeckList(const DeckList &_deckListModel); std::map analyzeManaCurve(); - void refreshDisplays(DeckListModel *_deckListModel); + void refreshDisplays(); private: DeckListModel *deckListModel; + DeckListStatisticsAnalyzer *deckListStatisticsAnalyzer; QVBoxLayout *mainLayout; QWidget *container; diff --git a/cockatrice/src/interface/widgets/deck_analytics/deck_list_statistics_analyzer.cpp b/cockatrice/src/interface/widgets/deck_analytics/deck_list_statistics_analyzer.cpp new file mode 100644 index 000000000..a5ddf37a1 --- /dev/null +++ b/cockatrice/src/interface/widgets/deck_analytics/deck_list_statistics_analyzer.cpp @@ -0,0 +1,120 @@ +#include "deck_list_statistics_analyzer.h" + +#include "deck_list_model.h" +#include "deck_list_statistics_analyzer.h" + +#include +#include +#include + +DeckListStatisticsAnalyzer::DeckListStatisticsAnalyzer(QObject *parent, + DeckListModel *_model, + DeckListStatisticsAnalyzerConfig cfg) + : QObject(parent), model(_model), config(cfg) +{ + connect(model, &DeckListModel::dataChanged, this, &DeckListStatisticsAnalyzer::update); +} + +void DeckListStatisticsAnalyzer::update() +{ + manaBaseMap.clear(); + manaCurveMap.clear(); + manaDevotionMap.clear(); + + auto nodes = model->getDeckList()->getCardNodes(); + + for (auto *node : nodes) { + CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(node->getName()); + if (!info) + continue; + + for (int i = 0; i < node->getNumber(); ++i) { + // ---- Mana curve ---- + if (config.computeManaCurve) { + manaCurveMap[info->getCmc().toInt()]++; + } + + // ---- Mana base ---- + if (config.computeManaBase) { + auto mana = determineManaProduction(info->getText()); + for (auto it = mana.begin(); it != mana.end(); ++it) + manaBaseMap[it.key()] += it.value(); + } + + // ---- Devotion ---- + if (config.computeDevotion) { + auto devo = countManaSymbols(info->getManaCost()); + for (auto &d : devo) + manaDevotionMap[d.first] += d.second; + } + } + } + + emit statsUpdated(); +} + +QHash DeckListStatisticsAnalyzer::determineManaProduction(const QString &rulesText) +{ + QHash manaCounts = {{"W", 0}, {"U", 0}, {"B", 0}, {"R", 0}, {"G", 0}, {"C", 0}}; + + QString text = rulesText.toLower(); // Normalize case for matching + + // Quick keyword-based checks for any color and colorless mana + if (text.contains("{t}: add one mana of any color") || text.contains("add one mana of any color")) { + for (const auto &color : {QStringLiteral("W"), QStringLiteral("U"), QStringLiteral("B"), QStringLiteral("R"), + QStringLiteral("G")}) { + manaCounts[color]++; + } + } + if (text.contains("{t}: add {c}") || text.contains("add one colorless mana")) { + manaCounts["C"]++; + } + + // Optimized regex for specific mana symbols + static const QRegularExpression specificColorRegex(R"(\{T\}:\s*Add\s*\{([WUBRG])\})"); + QRegularExpressionMatch match = specificColorRegex.match(rulesText); + if (match.hasMatch()) { + manaCounts[match.captured(1)]++; + } + + return manaCounts; +} + +std::unordered_map DeckListStatisticsAnalyzer::countManaSymbols(const QString &manaString) +{ + std::unordered_map manaCounts = {{'W', 0}, {'U', 0}, {'B', 0}, {'R', 0}, {'G', 0}}; + + int len = manaString.length(); + for (int i = 0; i < len; ++i) { + if (manaString[i] == '{') { + ++i; // Move past '{' + if (i < len && manaCounts.find(manaString[i].toLatin1()) != manaCounts.end()) { + char mana1 = manaString[i].toLatin1(); + ++i; // Move to next character + if (i < len && manaString[i] == '/') { + ++i; // Move past '/' + if (i < len && manaCounts.find(manaString[i].toLatin1()) != manaCounts.end()) { + char mana2 = manaString[i].toLatin1(); + manaCounts[mana1]++; + manaCounts[mana2]++; + } else { + // Handle cases like "{W/}" where second part is invalid + manaCounts[mana1]++; + } + } else { + manaCounts[mana1]++; + } + } + // Ensure we always skip to the closing '}' + while (i < len && manaString[i] != '}') { + ++i; + } + } + // Check if the character is a standalone mana symbol (not inside {}) + else if (manaCounts.find(manaString[i].toLatin1()) != manaCounts.end()) { + manaCounts[manaString[i].toLatin1()]++; + } + } + + return manaCounts; +} diff --git a/cockatrice/src/interface/widgets/deck_analytics/deck_list_statistics_analyzer.h b/cockatrice/src/interface/widgets/deck_analytics/deck_list_statistics_analyzer.h new file mode 100644 index 000000000..8fa033971 --- /dev/null +++ b/cockatrice/src/interface/widgets/deck_analytics/deck_list_statistics_analyzer.h @@ -0,0 +1,60 @@ +#ifndef COCKATRICE_DECK_LIST_STATISTICS_ANALYZER_H +#define COCKATRICE_DECK_LIST_STATISTICS_ANALYZER_H + +#include "deck_list_model.h" + +#include +#include +#include + +class DeckListModel; + +struct DeckListStatisticsAnalyzerConfig +{ + bool computeManaBase = true; + bool computeManaCurve = true; + bool computeDevotion = true; +}; + +class DeckListStatisticsAnalyzer : public QObject +{ + Q_OBJECT + +public: + explicit DeckListStatisticsAnalyzer(QObject *parent, + DeckListModel *model, + DeckListStatisticsAnalyzerConfig cfg = DeckListStatisticsAnalyzerConfig()); + + void update(); + + [[nodiscard]] const QHash &getManaBase() const + { + return manaBaseMap; + } + [[nodiscard]] const std::unordered_map &getManaCurve() const + { + return manaCurveMap; + } + [[nodiscard]] const std::unordered_map &getDevotion() const + { + return manaDevotionMap; + } + +signals: + void statsUpdated(); + +private: + DeckListModel *model; + DeckListStatisticsAnalyzerConfig config; + + // Internal result containers + QHash manaBaseMap; + std::unordered_map manaCurveMap; + std::unordered_map manaDevotionMap; + + // Internal helper functions + QHash determineManaProduction(const QString &); + std::unordered_map countManaSymbols(const QString &); +}; + +#endif // COCKATRICE_DECK_LIST_STATISTICS_ANALYZER_H 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 568583af5..2e530db0b 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/mana_base_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/mana_base_widget.cpp @@ -10,8 +10,8 @@ #include #include -ManaBaseWidget::ManaBaseWidget(QWidget *parent, DeckListModel *_deckListModel) - : QWidget(parent), deckListModel(_deckListModel) +ManaBaseWidget::ManaBaseWidget(QWidget *parent, DeckListStatisticsAnalyzer *_deckStatAnalyzer) + : QWidget(parent), deckStatAnalyzer(_deckStatAnalyzer) { layout = new QVBoxLayout(this); setLayout(layout); @@ -24,7 +24,7 @@ ManaBaseWidget::ManaBaseWidget(QWidget *parent, DeckListModel *_deckListModel) barLayout = new QHBoxLayout(barContainer); layout->addWidget(barContainer); - connect(deckListModel, &DeckListModel::dataChanged, this, &ManaBaseWidget::analyzeManaBase); + connect(deckStatAnalyzer, &DeckListStatisticsAnalyzer::statsUpdated, this, &ManaBaseWidget::updateDisplay); retranslateUi(); } @@ -34,13 +34,6 @@ void ManaBaseWidget::retranslateUi() bannerWidget->setText(tr("Mana Base")); } -void ManaBaseWidget::setDeckModel(DeckListModel *deckModel) -{ - deckListModel = deckModel; - connect(deckListModel, &DeckListModel::dataChanged, this, &ManaBaseWidget::analyzeManaBase); - analyzeManaBase(); -} - void ManaBaseWidget::updateDisplay() { // Clear the layout first @@ -50,6 +43,8 @@ void ManaBaseWidget::updateDisplay() delete item; } + auto manaBaseMap = deckStatAnalyzer->getManaBase(); + int highestEntry = 0; for (auto entry : manaBaseMap) { if (entry > highestEntry) { @@ -74,56 +69,3 @@ void ManaBaseWidget::updateDisplay() update(); } - -QHash ManaBaseWidget::analyzeManaBase() -{ - manaBaseMap.clear(); - QList cardsInDeck = deckListModel->getDeckList()->getCardNodes(); - - for (auto currentCard : cardsInDeck) { - for (int k = 0; k < currentCard->getNumber(); ++k) { - CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(currentCard->getName()); - if (info) { - auto devotion = determineManaProduction(info->getText()); - mergeManaCounts(manaBaseMap, devotion); - } - } - } - - updateDisplay(); - return manaBaseMap; -} - -QHash ManaBaseWidget::determineManaProduction(const QString &rulesText) -{ - QHash manaCounts = {{"W", 0}, {"U", 0}, {"B", 0}, {"R", 0}, {"G", 0}, {"C", 0}}; - - QString text = rulesText.toLower(); // Normalize case for matching - - // Quick keyword-based checks for any color and colorless mana - if (text.contains("{t}: add one mana of any color") || text.contains("add one mana of any color")) { - for (const auto &color : {QStringLiteral("W"), QStringLiteral("U"), QStringLiteral("B"), QStringLiteral("R"), - QStringLiteral("G")}) { - manaCounts[color]++; - } - } - if (text.contains("{t}: add {c}") || text.contains("add one colorless mana")) { - manaCounts["C"]++; - } - - // Optimized regex for specific mana symbols - static const QRegularExpression specificColorRegex(R"(\{T\}:\s*Add\s*\{([WUBRG])\})"); - QRegularExpressionMatch match = specificColorRegex.match(rulesText); - if (match.hasMatch()) { - manaCounts[match.captured(1)]++; - } - - return manaCounts; -} - -void ManaBaseWidget::mergeManaCounts(QHash &manaCounts1, const QHash &manaCounts2) -{ - for (auto it = manaCounts2.constBegin(); it != manaCounts2.constEnd(); ++it) { - manaCounts1[it.key()] += it.value(); - } -} diff --git a/cockatrice/src/interface/widgets/deck_analytics/mana_base_widget.h b/cockatrice/src/interface/widgets/deck_analytics/mana_base_widget.h index e88fe3b85..079449353 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/mana_base_widget.h +++ b/cockatrice/src/interface/widgets/deck_analytics/mana_base_widget.h @@ -8,6 +8,7 @@ #define MANA_BASE_WIDGET_H #include "../general/display/banner_widget.h" +#include "deck_list_statistics_analyzer.h" #include #include @@ -20,21 +21,15 @@ class ManaBaseWidget : public QWidget Q_OBJECT public: - explicit ManaBaseWidget(QWidget *parent, DeckListModel *deckListModel); - QHash analyzeManaBase(); + explicit ManaBaseWidget(QWidget *parent, DeckListStatisticsAnalyzer *deckStatAnalyzer); void updateDisplay(); - QHash determineManaProduction(const QString &manaString); - void mergeManaCounts(QHash &manaCounts1, const QHash &manaCounts2); - public slots: - void setDeckModel(DeckListModel *deckModel); void retranslateUi(); private: - DeckListModel *deckListModel; + DeckListStatisticsAnalyzer *deckStatAnalyzer; BannerWidget *bannerWidget; - QHash manaBaseMap; QVBoxLayout *layout; QWidget *barContainer; QHBoxLayout *barLayout; 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 4515b723b..c094eb590 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/mana_curve_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/mana_curve_widget.cpp @@ -10,8 +10,8 @@ #include #include -ManaCurveWidget::ManaCurveWidget(QWidget *parent, DeckListModel *_deckListModel) - : QWidget(parent), deckListModel(_deckListModel) +ManaCurveWidget::ManaCurveWidget(QWidget *parent, DeckListStatisticsAnalyzer *_deckStatAnalyzer) + : QWidget(parent), deckStatAnalyzer(_deckStatAnalyzer) { layout = new QVBoxLayout(this); setLayout(layout); @@ -24,7 +24,7 @@ ManaCurveWidget::ManaCurveWidget(QWidget *parent, DeckListModel *_deckListModel) barLayout = new QHBoxLayout(barContainer); layout->addWidget(barContainer); - connect(deckListModel, &DeckListModel::dataChanged, this, &ManaCurveWidget::analyzeManaCurve); + connect(deckStatAnalyzer, &DeckListStatisticsAnalyzer::statsUpdated, this, &ManaCurveWidget::updateDisplay); retranslateUi(); } @@ -34,34 +34,6 @@ void ManaCurveWidget::retranslateUi() bannerWidget->setText(tr("Mana Curve")); } -void ManaCurveWidget::setDeckModel(DeckListModel *deckModel) -{ - deckListModel = deckModel; - connect(deckListModel, &DeckListModel::dataChanged, this, &ManaCurveWidget::analyzeManaCurve); - analyzeManaCurve(); -} - -std::unordered_map ManaCurveWidget::analyzeManaCurve() -{ - manaCurveMap.clear(); - - QList cardsInDeck = deckListModel->getDeckList()->getCardNodes(); - - for (auto currentCard : cardsInDeck) { - for (int k = 0; k < currentCard->getNumber(); ++k) { - CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(currentCard->getName()); - if (info) { - int cmc = info->getCmc().toInt(); - manaCurveMap[cmc]++; - } - } - } - - updateDisplay(); - - return manaCurveMap; -} - void ManaCurveWidget::updateDisplay() { // Clear the layout first @@ -73,6 +45,8 @@ void ManaCurveWidget::updateDisplay() } } + auto manaCurveMap = deckStatAnalyzer->getManaCurve(); + int highestEntry = 0; for (const auto &entry : manaCurveMap) { if (entry.second > highestEntry) { diff --git a/cockatrice/src/interface/widgets/deck_analytics/mana_curve_widget.h b/cockatrice/src/interface/widgets/deck_analytics/mana_curve_widget.h index 7362e0c72..fad1fb0f8 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/mana_curve_widget.h +++ b/cockatrice/src/interface/widgets/deck_analytics/mana_curve_widget.h @@ -8,6 +8,7 @@ #define MANA_CURVE_WIDGET_H #include "../general/display/banner_widget.h" +#include "deck_list_statistics_analyzer.h" #include #include @@ -19,17 +20,14 @@ class ManaCurveWidget : public QWidget Q_OBJECT public: - explicit ManaCurveWidget(QWidget *parent, DeckListModel *deckListModel); + explicit ManaCurveWidget(QWidget *parent, DeckListStatisticsAnalyzer *deckStatAnalyzer); void updateDisplay(); public slots: - void setDeckModel(DeckListModel *deckModel); - std::unordered_map analyzeManaCurve(); void retranslateUi(); private: - DeckListModel *deckListModel; - std::unordered_map manaCurveMap; + DeckListStatisticsAnalyzer *deckStatAnalyzer; QVBoxLayout *layout; BannerWidget *bannerWidget; QWidget *barContainer; 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 63e4255b5..476bb8077 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/mana_devotion_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/mana_devotion_widget.cpp @@ -10,8 +10,8 @@ #include #include -ManaDevotionWidget::ManaDevotionWidget(QWidget *parent, DeckListModel *_deckListModel) - : QWidget(parent), deckListModel(_deckListModel) +ManaDevotionWidget::ManaDevotionWidget(QWidget *parent, DeckListStatisticsAnalyzer *_deckStatAnalyzer) + : QWidget(parent), deckStatAnalyzer(_deckStatAnalyzer) { layout = new QVBoxLayout(this); setLayout(layout); @@ -23,7 +23,7 @@ ManaDevotionWidget::ManaDevotionWidget(QWidget *parent, DeckListModel *_deckList barLayout = new QHBoxLayout(); layout->addLayout(barLayout); - connect(deckListModel, &DeckListModel::dataChanged, this, &ManaDevotionWidget::analyzeManaDevotion); + connect(deckStatAnalyzer, &DeckListStatisticsAnalyzer::statsUpdated, this, &ManaDevotionWidget::updateDisplay); retranslateUi(); } @@ -33,33 +33,6 @@ void ManaDevotionWidget::retranslateUi() bannerWidget->setText(tr("Mana Devotion")); } -void ManaDevotionWidget::setDeckModel(DeckListModel *deckModel) -{ - deckListModel = deckModel; - connect(deckListModel, &DeckListModel::dataChanged, this, &ManaDevotionWidget::analyzeManaDevotion); - analyzeManaDevotion(); -} - -std::unordered_map ManaDevotionWidget::analyzeManaDevotion() -{ - manaDevotionMap.clear(); - - QList cardsInDeck = deckListModel->getDeckList()->getCardNodes(); - - for (auto currentCard : cardsInDeck) { - for (int k = 0; k < currentCard->getNumber(); ++k) { - CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(currentCard->getName()); - if (info) { - auto devotion = countManaSymbols(info->getManaCost()); - mergeManaCounts(manaDevotionMap, devotion); - } - } - } - - updateDisplay(); - return manaDevotionMap; -} - void ManaDevotionWidget::updateDisplay() { // Clear the layout first @@ -69,6 +42,8 @@ void ManaDevotionWidget::updateDisplay() delete item; } + auto manaDevotionMap = deckStatAnalyzer->getDevotion(); + int highestEntry = 0; for (auto entry : manaDevotionMap) { if (highestEntry < entry.second) { @@ -89,50 +64,3 @@ void ManaDevotionWidget::updateDisplay() update(); // Update the widget display } - -std::unordered_map ManaDevotionWidget::countManaSymbols(const QString &manaString) -{ - std::unordered_map manaCounts = {{'W', 0}, {'U', 0}, {'B', 0}, {'R', 0}, {'G', 0}}; - - int len = manaString.length(); - for (int i = 0; i < len; ++i) { - if (manaString[i] == '{') { - ++i; // Move past '{' - if (i < len && manaCounts.find(manaString[i].toLatin1()) != manaCounts.end()) { - char mana1 = manaString[i].toLatin1(); - ++i; // Move to next character - if (i < len && manaString[i] == '/') { - ++i; // Move past '/' - if (i < len && manaCounts.find(manaString[i].toLatin1()) != manaCounts.end()) { - char mana2 = manaString[i].toLatin1(); - manaCounts[mana1]++; - manaCounts[mana2]++; - } else { - // Handle cases like "{W/}" where second part is invalid - manaCounts[mana1]++; - } - } else { - manaCounts[mana1]++; - } - } - // Ensure we always skip to the closing '}' - while (i < len && manaString[i] != '}') { - ++i; - } - } - // Check if the character is a standalone mana symbol (not inside {}) - else if (manaCounts.find(manaString[i].toLatin1()) != manaCounts.end()) { - manaCounts[manaString[i].toLatin1()]++; - } - } - - return manaCounts; -} - -void ManaDevotionWidget::mergeManaCounts(std::unordered_map &manaCounts1, - const std::unordered_map &manaCounts2) -{ - for (const auto &pair : manaCounts2) { - manaCounts1[pair.first] += pair.second; // Add values for matching keys - } -} diff --git a/cockatrice/src/interface/widgets/deck_analytics/mana_devotion_widget.h b/cockatrice/src/interface/widgets/deck_analytics/mana_devotion_widget.h index b8ec7950a..ff2e86159 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/mana_devotion_widget.h +++ b/cockatrice/src/interface/widgets/deck_analytics/mana_devotion_widget.h @@ -8,6 +8,7 @@ #define MANA_DEVOTION_WIDGET_H #include "../general/display/banner_widget.h" +#include "deck_list_statistics_analyzer.h" #include #include @@ -20,21 +21,15 @@ class ManaDevotionWidget : public QWidget Q_OBJECT public: - explicit ManaDevotionWidget(QWidget *parent, DeckListModel *deckListModel); + explicit ManaDevotionWidget(QWidget *parent, DeckListStatisticsAnalyzer *deckStatAnalyzer); void updateDisplay(); - std::unordered_map countManaSymbols(const QString &manaString); - void mergeManaCounts(std::unordered_map &manaCounts1, const std::unordered_map &manaCounts2); - public slots: - void setDeckModel(DeckListModel *deckModel); - std::unordered_map analyzeManaDevotion(); void retranslateUi(); private: - DeckListModel *deckListModel; + DeckListStatisticsAnalyzer *deckStatAnalyzer; BannerWidget *bannerWidget; - std::unordered_map manaDevotionMap; QVBoxLayout *layout; QHBoxLayout *barLayout; }; 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 1540df0bf..6dd55d545 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 @@ -84,7 +84,7 @@ void TabDeckEditorVisual::onDeckChanged() { AbstractTabDeckEditor::onDeckModified(); tabContainer->visualDeckView->constructZoneWidgetsFromDeckListModel(); - tabContainer->deckAnalytics->refreshDisplays(deckDockWidget->deckModel); + tabContainer->deckAnalytics->refreshDisplays(); tabContainer->sampleHandWidget->setDeckModel(deckDockWidget->deckModel); } From 30cc8ad6f9c03e4d376572d5d039d535007beaa5 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Tue, 2 Dec 2025 22:19:44 +0100 Subject: [PATCH 22/40] [DeckEditor] Expand DeckDock TreeView when adding card through deck editor (#6388) * [DeckEditor] Expand DeckDock TreeView when adding card through deck editor * [DeckEditor] Expand first, then set selection. --- .../widgets/deck_editor/deck_editor_deck_dock_widget.h | 2 +- .../src/interface/widgets/tabs/abstract_tab_deck_editor.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) 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 852ce7164..37891072d 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 @@ -69,6 +69,7 @@ public slots: void actSwapCard(); void actRemoveCard(); void offsetCountAtIndex(const QModelIndex &idx, int offset); + void expandAll(); signals: void nameChanged(); @@ -117,7 +118,6 @@ private slots: void updateShowBannerCardComboBox(bool visible); void updateShowTagsWidget(bool visible); void syncBannerCardComboBoxSelectionWithDeck(); - void expandAll(); }; #endif // DECK_EDITOR_DECK_DOCK_WIDGET_H 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 6d05e656d..a03b79e3f 100644 --- a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp +++ b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp @@ -153,6 +153,7 @@ void AbstractTabDeckEditor::addCardHelper(const ExactCard &card, QString zoneNam card.getPrinting().getProperty("num"))); QModelIndex newCardIndex = deckDockWidget->deckModel->addCard(card, zoneName); + deckDockWidget->expandAll(); deckDockWidget->deckView->clearSelection(); deckDockWidget->deckView->setCurrentIndex(newCardIndex); setModified(true); From d29e72ce7212e7c9e90d60398719eca969d87f82 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Tue, 2 Dec 2025 22:24:39 +0100 Subject: [PATCH 23/40] [CardInfo] Display set short name and collector number in info widget. (#6378) * [CardInfo] Display set short name and collector number in info widget. * Lint. * Use reference. --- .../widgets/cards/card_info_display_widget.cpp | 2 +- .../widgets/cards/card_info_frame_widget.cpp | 2 +- .../widgets/cards/card_info_text_widget.cpp | 12 +++++++++++- .../interface/widgets/cards/card_info_text_widget.h | 4 +++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/cockatrice/src/interface/widgets/cards/card_info_display_widget.cpp b/cockatrice/src/interface/widgets/cards/card_info_display_widget.cpp index b13a085bd..819bc57d0 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_display_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_display_widget.cpp @@ -49,7 +49,7 @@ void CardInfoDisplayWidget::setCard(const ExactCard &card) if (exactCard) connect(exactCard.getCardPtr().data(), &QObject::destroyed, this, &CardInfoDisplayWidget::clear); - text->setCard(exactCard.getCardPtr()); + text->setCard(exactCard); pic->setCard(exactCard); } 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 829292b53..21bee8f54 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_frame_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_frame_widget.cpp @@ -154,7 +154,7 @@ void CardInfoFrameWidget::setCard(const ExactCard &card) setViewTransformationButtonVisibility(hasTransformation(exactCard.getInfo())); - text->setCard(exactCard.getCardPtr()); + text->setCard(exactCard); pic->setCard(exactCard); } diff --git a/cockatrice/src/interface/widgets/cards/card_info_text_widget.cpp b/cockatrice/src/interface/widgets/cards/card_info_text_widget.cpp index 775f6fb9e..456e1533a 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_text_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_text_widget.cpp @@ -50,8 +50,9 @@ void CardInfoTextWidget::setTexts(const QString &propsText, const QString &textT textLabel->setText(textText); } -void CardInfoTextWidget::setCard(CardInfoPtr card) +void CardInfoTextWidget::setCard(const ExactCard &exactCard) { + auto card = exactCard.getCardPtr(); if (card == nullptr) { setTexts("", ""); return; @@ -61,6 +62,15 @@ void CardInfoTextWidget::setCard(CardInfoPtr card) text += QString("%1%2") .arg(tr("Name:"), card->getName().toHtmlEscaped()); + if (exactCard.getPrinting() != PrintingInfo()) { + QString setShort = exactCard.getPrinting().getSet()->getShortName().toHtmlEscaped(); + QString cardNum = exactCard.getPrinting().getProperty("num").toHtmlEscaped(); + + text += QString("%1%2").arg(tr("Set:"), setShort); + + text += QString("%1%2").arg(tr("Collector Number:"), cardNum); + } + QStringList cardProps = card->getProperties(); for (const QString &key : cardProps) { if (key.contains("-")) diff --git a/cockatrice/src/interface/widgets/cards/card_info_text_widget.h b/cockatrice/src/interface/widgets/cards/card_info_text_widget.h index 8711422b0..95b588882 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_text_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_info_text_widget.h @@ -7,6 +7,8 @@ #ifndef CARDINFOTEXT_H #define CARDINFOTEXT_H +#include "libcockatrice/card/printing/exact_card.h" + #include #include class QLabel; @@ -32,7 +34,7 @@ public: signals: void linkActivated(const QString &link); public slots: - void setCard(CardInfoPtr card); + void setCard(const ExactCard &card); }; #endif From 658ae83157d0d9566683da3a477cbd8875911f08 Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Tue, 2 Dec 2025 21:18:46 -0800 Subject: [PATCH 24/40] [DeckList] Make DeckList not a QObject (#6383) --- .../deck_editor_deck_dock_widget.cpp | 5 +- .../deck_preview_deck_tags_display_widget.cpp | 12 ++-- .../deck_preview_deck_tags_display_widget.h | 2 +- .../libcockatrice/deck_list/deck_list.cpp | 14 +++-- .../libcockatrice/deck_list/deck_list.h | 55 +++---------------- .../models/deck_list/deck_list_model.cpp | 7 ++- 6 files changed, 28 insertions(+), 67 deletions(-) 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 4db7b8774..075b73216 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 @@ -424,7 +424,6 @@ void DeckEditorDeckDockWidget::setDeck(DeckLoader *_deck) deckLoader->setParent(this); deckModel->setDeckList(deckLoader->getDeckList()); connect(deckLoader, &DeckLoader::deckLoaded, deckModel, &DeckListModel::rebuildTree); - connect(deckLoader->getDeckList(), &DeckList::deckHashChanged, deckModel, &DeckListModel::deckHashChanged); emit requestDeckHistoryClear(); historyManagerWidget->setDeckListModel(deckModel); @@ -452,7 +451,7 @@ void DeckEditorDeckDockWidget::syncDisplayWidgetsToModel() sortDeckModelToDeckView(); expandAll(); - deckTagsDisplayWidget->connectDeckList(deckModel->getDeckList()); + deckTagsDisplayWidget->setDeckList(deckModel->getDeckList()); } void DeckEditorDeckDockWidget::sortDeckModelToDeckView() @@ -485,7 +484,7 @@ void DeckEditorDeckDockWidget::cleanDeck() emit deckModified(); emit deckChanged(); updateBannerCardComboBox(); - deckTagsDisplayWidget->connectDeckList(deckModel->getDeckList()); + deckTagsDisplayWidget->setDeckList(deckModel->getDeckList()); } void DeckEditorDeckDockWidget::recursiveExpand(const QModelIndex &index) 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 706444545..a29f3bfc4 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 @@ -28,21 +28,15 @@ DeckPreviewDeckTagsDisplayWidget::DeckPreviewDeckTagsDisplayWidget(QWidget *_par flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAsNeeded); if (_deckList) { - connectDeckList(_deckList); + setDeckList(_deckList); } layout->addWidget(flowWidget); } -void DeckPreviewDeckTagsDisplayWidget::connectDeckList(DeckList *_deckList) +void DeckPreviewDeckTagsDisplayWidget::setDeckList(DeckList *_deckList) { - if (deckList) { - disconnect(deckList, &DeckList::deckTagsChanged, this, &DeckPreviewDeckTagsDisplayWidget::refreshTags); - } - deckList = _deckList; - connect(deckList, &DeckList::deckTagsChanged, this, &DeckPreviewDeckTagsDisplayWidget::refreshTags); - refreshTags(); } @@ -150,6 +144,7 @@ void DeckPreviewDeckTagsDisplayWidget::openTagEditDlg() QStringList updatedTags = dialog.getActiveTags(); deckList->setTags(updatedTags); deckPreviewWidget->deckLoader->saveToFile(deckPreviewWidget->filePath, DeckLoader::CockatriceFormat); + refreshTags(); } } } else if (parentWidget()) { @@ -181,6 +176,7 @@ void DeckPreviewDeckTagsDisplayWidget::openTagEditDlg() QStringList updatedTags = dialog.getActiveTags(); deckList->setTags(updatedTags); deckEditor->setModified(true); + refreshTags(); } } } 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 4270e38e5..b1b1117ae 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 @@ -21,7 +21,7 @@ class DeckPreviewDeckTagsDisplayWidget : public QWidget public: explicit DeckPreviewDeckTagsDisplayWidget(QWidget *_parent, DeckList *_deckList); - void connectDeckList(DeckList *_deckList); + void setDeckList(DeckList *_deckList); void refreshTags(); DeckList *deckList; FlowWidget *flowWidget; diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp index 37f537249..cea759428 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp @@ -87,6 +87,12 @@ DeckList::DeckList() root = new InnerDecklistNode; } +DeckList::DeckList(const DeckList &other) + : metadata(other.metadata), sideboardPlans(other.sideboardPlans), root(new InnerDecklistNode(other.getRoot())), + cachedDeckHash(other.cachedDeckHash) +{ +} + DeckList::DeckList(const QString &nativeString) { root = new InnerDecklistNode; @@ -443,11 +449,8 @@ bool DeckList::loadFromStream_Plain(QTextStream &in, bool preserveMetadata) cardName.replace(diff.key(), diff.value()); } - // Resolve complete card name, this function does nothing if the name is not found - cardName = getCompleteCardName(cardName); - // Determine the zone (mainboard/sideboard) - QString zoneName = getCardZoneFromName(cardName, sideboard ? DECK_ZONE_SIDE : DECK_ZONE_MAIN); + QString zoneName = sideboard ? DECK_ZONE_SIDE : DECK_ZONE_MAIN; // make new entry in decklist new DecklistCardNode(cardName, amount, getZoneObjFromName(zoneName), -1, setCode, collectorNumber); @@ -708,12 +711,11 @@ QString DeckList::getDeckHash() const } /** - * Invalidates the cached deckHash and emits the deckHashChanged signal. + * Invalidates the cached deckHash. */ void DeckList::refreshDeckHash() { cachedDeckHash = QString(); - emit deckHashChanged(); } /** diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h index 5340d69fe..d4d1204e6 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h @@ -1,5 +1,5 @@ /** - * @file decklist.h + * @file deck_list.h * @brief Defines the DeckList class and supporting types for managing a full * deck structure including cards, zones, sideboard plans, and * serialization to/from multiple formats. This is a logic class which @@ -93,7 +93,7 @@ public: * @brief Represents a complete deck, including metadata, zones, cards, * and sideboard plans. * - * A DeckList is a QObject wrapper around an `InnerDecklistNode` tree, + * A DeckList is a wrapper around an `InnerDecklistNode` tree, * enriched with metadata like deck name, comments, tags, banner card, * and multiple sideboard plans. * @@ -110,10 +110,6 @@ public: * - Owns the root `InnerDecklistNode` tree. * - Owns `SideboardPlan` instances stored in `sideboardPlans`. * - * ### Signals: - * - @c deckHashChanged() — emitted when the deck contents change. - * - @c deckTagsChanged() — emitted when tags are added/removed. - * * ### Example workflow: * ``` * DeckList deck; @@ -123,10 +119,8 @@ public: * deck.saveToFile_Native(device); * ``` */ -class DeckList : public QObject +class DeckList { - Q_OBJECT - public: struct Metadata { @@ -158,37 +152,7 @@ private: static void getCardRefListHelper(InnerDecklistNode *item, QList &result); InnerDecklistNode *getZoneObjFromName(const QString &zoneName); -protected: - /** - * @brief Map a card name to its zone. - * Override in subclasses for format-specific logic. - * @param cardName Card being placed. - * @param currentZoneName Zone candidate. - * @return Zone name to use. - */ - virtual QString getCardZoneFromName(const QString /*cardName*/, QString currentZoneName) - { - return currentZoneName; - } - - /** - * @brief Produce the complete display name of a card. - * Override in subclasses to add set suffixes or annotations. - * @param cardName Base name. - * @return Full display name. - */ - virtual QString getCompleteCardName(const QString &cardName) const - { - return cardName; - } - -signals: - /// Emitted when the deck hash changes. - void deckHashChanged(); - /// Emitted when the deck tags are modified. - void deckTagsChanged(); - -public slots: +public: /// @name Metadata setters ///@{ void setName(const QString &_name = QString()) @@ -202,17 +166,14 @@ public slots: void setTags(const QStringList &_tags = QStringList()) { metadata.tags = _tags; - emit deckTagsChanged(); } void addTag(const QString &_tag) { metadata.tags.append(_tag); - emit deckTagsChanged(); } void clearTags() { metadata.tags.clear(); - emit deckTagsChanged(); } void setBannerCard(const CardRef &_bannerCard = {}) { @@ -224,15 +185,13 @@ public slots: } ///@} -public: /// @brief Construct an empty deck. explicit DeckList(); - /// @brief Delete copy constructor. - DeckList(const DeckList &) = delete; - DeckList &operator=(const DeckList &) = delete; + /// @brief Copy constructor (deep copies the node tree) + DeckList(const DeckList &other); /// @brief Construct from a serialized native-format string. explicit DeckList(const QString &nativeString); - ~DeckList() override; + virtual ~DeckList(); /// @name Metadata getters /// The individual metadata getters still exist for backwards compatibility. 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 e3e2de58d..bd16ab3d2 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.cpp +++ b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.cpp @@ -5,8 +5,11 @@ DeckListModel::DeckListModel(QObject *parent) : QAbstractItemModel(parent), lastKnownColumn(1), lastKnownOrder(Qt::AscendingOrder) { + // This class will leak the decklist object. We cannot safely delete it in the dtor because the deckList field is a + // non-owning pointer and another deckList might have been assigned to it. + // `DeckListModel::cleanList` also leaks for the same reason. + // TODO: fix the leak deckList = new DeckList; - deckList->setParent(this); root = new InnerDecklistNode; } @@ -284,6 +287,7 @@ bool DeckListModel::setData(const QModelIndex &index, const QVariant &value, con emitRecursiveUpdates(index); deckList->refreshDeckHash(); + emit deckHashChanged(); emit dataChanged(index, index); return true; @@ -422,6 +426,7 @@ QModelIndex DeckListModel::addCard(const ExactCard &card, const QString &zoneNam cardNode->setCardCollectorNumber(printingInfo.getProperty("num")); cardNode->setCardProviderId(printingInfo.getProperty("uuid")); deckList->refreshDeckHash(); + emit deckHashChanged(); } sort(lastKnownColumn, lastKnownOrder); emitRecursiveUpdates(parentIndex); From b4e3f2cba989554c97bd383842520545f1e48fee Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Tue, 2 Dec 2025 21:19:56 -0800 Subject: [PATCH 25/40] [Oracle] Support importing tokens and spoilers from local file (#6387) --- oracle/src/pages.cpp | 20 +++++++- oracle/src/pages.h | 2 + oracle/src/pagetemplates.cpp | 97 ++++++++++++++++++++++++++++-------- oracle/src/pagetemplates.h | 11 +++- 4 files changed, 105 insertions(+), 25 deletions(-) diff --git a/oracle/src/pages.cpp b/oracle/src/pages.cpp index 9b2f5ce7c..46edf1cf8 100644 --- a/oracle/src/pages.cpp +++ b/oracle/src/pages.cpp @@ -672,13 +672,21 @@ QString LoadTokensPage::getFileType() return tr("XML; token database (*.xml)"); } +QString LoadTokensPage::getFilePromptName() +{ + return tr("tokens"); +} + void LoadTokensPage::retranslateUi() { setTitle(tr("Tokens import")); setSubTitle(tr("Please specify a compatible source for token data.")); - urlLabel->setText(tr("Download URL:")); + urlRadioButton->setText(tr("Download URL:")); + fileRadioButton->setText(tr("Local file:")); urlButton->setText(tr("Restore default URL")); + fileButton->setText(tr("Choose file...")); + pathLabel->setText(tr("The token database will be saved at the following location:") + "
" + SettingsCache::instance().getTokenDatabasePath()); defaultPathCheckBox->setText(tr("Save to a custom path (not recommended)")); @@ -709,13 +717,21 @@ QString LoadSpoilersPage::getFileType() return tr("XML; spoiler database (*.xml)"); } +QString LoadSpoilersPage::getFilePromptName() +{ + return tr("spoiler"); +} + void LoadSpoilersPage::retranslateUi() { setTitle(tr("Spoilers import")); setSubTitle(tr("Please specify a compatible source for spoiler data.")); - urlLabel->setText(tr("Download URL:")); + urlRadioButton->setText(tr("Download URL:")); + fileRadioButton->setText(tr("Local file:")); urlButton->setText(tr("Restore default URL")); + fileButton->setText(tr("Choose file...")); + pathLabel->setText(tr("The spoiler database will be saved at the following location:") + "
" + SettingsCache::instance().getSpoilerCardDatabasePath()); defaultPathCheckBox->setText(tr("Save to a custom path (not recommended)")); diff --git a/oracle/src/pages.h b/oracle/src/pages.h index 6a88b6099..066cc2e1b 100644 --- a/oracle/src/pages.h +++ b/oracle/src/pages.h @@ -131,6 +131,7 @@ protected: QString getDefaultSavePath() override; QString getWindowTitle() override; QString getFileType() override; + QString getFilePromptName() override; }; class LoadTokensPage : public SimpleDownloadFilePage @@ -148,6 +149,7 @@ protected: QString getDefaultSavePath() override; QString getWindowTitle() override; QString getFileType() override; + QString getFilePromptName() override; void initializePage() override; }; diff --git a/oracle/src/pagetemplates.cpp b/oracle/src/pagetemplates.cpp index d9ce3300f..4a27fef30 100644 --- a/oracle/src/pagetemplates.cpp +++ b/oracle/src/pagetemplates.cpp @@ -12,32 +12,43 @@ #include #include #include +#include #include SimpleDownloadFilePage::SimpleDownloadFilePage(QWidget *parent) : OracleWizardPage(parent) { - urlLabel = new QLabel(this); + urlRadioButton = new QRadioButton(this); + fileRadioButton = new QRadioButton(this); + urlLineEdit = new QLineEdit(this); + fileLineEdit = new QLineEdit(this); progressLabel = new QLabel(this); progressBar = new QProgressBar(this); + urlRadioButton->setChecked(true); + urlButton = new QPushButton(this); connect(urlButton, &QPushButton::clicked, this, &SimpleDownloadFilePage::actRestoreDefaultUrl); - defaultPathCheckBox = new QCheckBox(this); + fileButton = new QPushButton(this); + connect(fileButton, &QPushButton::clicked, this, &SimpleDownloadFilePage::actLoadCardFile); + defaultPathCheckBox = new QCheckBox(this); pathLabel = new QLabel(this); pathLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); auto *layout = new QGridLayout(this); - layout->addWidget(urlLabel, 0, 0); + layout->addWidget(urlRadioButton, 0, 0); layout->addWidget(urlLineEdit, 0, 1); layout->addWidget(urlButton, 1, 1, Qt::AlignRight); - layout->addWidget(pathLabel, 2, 0, 1, 2); - layout->addWidget(defaultPathCheckBox, 3, 0, 1, 2); - layout->addWidget(progressLabel, 4, 0); - layout->addWidget(progressBar, 4, 1); + layout->addWidget(fileRadioButton, 2, 0); + layout->addWidget(fileLineEdit, 2, 1); + layout->addWidget(fileButton, 3, 1, Qt::AlignRight); + layout->addWidget(pathLabel, 4, 0, 1, 2); + layout->addWidget(defaultPathCheckBox, 5, 0, 1, 2); + layout->addWidget(progressLabel, 6, 0); + layout->addWidget(progressBar, 6, 1); setLayout(layout); } @@ -56,6 +67,31 @@ void SimpleDownloadFilePage::actRestoreDefaultUrl() urlLineEdit->setText(getDefaultUrl()); } +void SimpleDownloadFilePage::actLoadCardFile() +{ + QFileDialog dialog(this, tr("Load %1 file").arg(getFilePromptName())); + dialog.setFileMode(QFileDialog::ExistingFile); + + QString extensions = "*.json *.xml"; +#ifdef HAS_ZLIB + extensions += " *.zip"; +#endif +#ifdef HAS_LZMA + extensions += " *.xz"; +#endif + dialog.setNameFilter(tr("%1 file (%1)").arg(getFilePromptName(), extensions)); + + if (!fileLineEdit->text().isEmpty() && QFile::exists(fileLineEdit->text())) { + dialog.selectFile(fileLineEdit->text()); + } + + if (!dialog.exec()) { + return; + } + + fileLineEdit->setText(dialog.selectedFiles().at(0)); +} + bool SimpleDownloadFilePage::validatePage() { // if data has already been downloaded, pass directly to the "save" step @@ -68,22 +104,41 @@ bool SimpleDownloadFilePage::validatePage() } } - QUrl url = QUrl::fromUserInput(urlLineEdit->text()); - if (!url.isValid()) { - QMessageBox::critical(this, tr("Error"), tr("The provided URL is not valid: ") + url.toString()); - return false; + // else, try to import sets + if (urlRadioButton->isChecked()) { + QUrl url = QUrl::fromUserInput(urlLineEdit->text()); + if (!url.isValid()) { + QMessageBox::critical(this, tr("Error"), tr("The provided URL is not valid: ") + url.toString()); + return false; + } + + progressLabel->setText(tr("Downloading (0MB)")); + // show an infinite progressbar + progressBar->setMaximum(0); + progressBar->setMinimum(0); + progressBar->setValue(0); + progressLabel->show(); + progressBar->show(); + + wizard()->disableButtons(); + downloadFile(url); + + } else if (fileRadioButton->isChecked()) { + QFile cardFile(fileLineEdit->text()); + if (!cardFile.exists()) { + QMessageBox::critical(this, tr("Error"), tr("Please choose a file.")); + return false; + } + + if (!cardFile.open(QIODevice::ReadOnly)) { + QMessageBox::critical(nullptr, tr("Error"), tr("Cannot open file '%1'.").arg(fileLineEdit->text())); + return false; + } + + downloadData = cardFile.readAll(); + wizard()->next(); } - progressLabel->setText(tr("Downloading (0MB)")); - // show an infinite progressbar - progressBar->setMaximum(0); - progressBar->setMinimum(0); - progressBar->setValue(0); - progressLabel->show(); - progressBar->show(); - - wizard()->disableButtons(); - downloadFile(url); return false; } diff --git a/oracle/src/pagetemplates.h b/oracle/src/pagetemplates.h index 372aa2fef..79dcdd632 100644 --- a/oracle/src/pagetemplates.h +++ b/oracle/src/pagetemplates.h @@ -3,6 +3,8 @@ #include +class QFile; +class QRadioButton; class OracleWizard; class QCheckBox; class QLabel; @@ -43,15 +45,19 @@ protected: virtual QString getDefaultSavePath() = 0; virtual QString getWindowTitle() = 0; virtual QString getFileType() = 0; + virtual QString getFilePromptName() = 0; bool saveToFile(); bool internalSaveToFile(const QString &fileName); protected: QByteArray downloadData; - QLabel *urlLabel; - QLabel *pathLabel; + QRadioButton *urlRadioButton; + QRadioButton *fileRadioButton; QLineEdit *urlLineEdit; + QLineEdit *fileLineEdit; QPushButton *urlButton; + QPushButton *fileButton; + QLabel *pathLabel; QLabel *progressLabel; QProgressBar *progressBar; QCheckBox *defaultPathCheckBox; @@ -60,6 +66,7 @@ signals: void parsedDataReady(); private slots: void actRestoreDefaultUrl(); + void actLoadCardFile(); void actDownloadProgress(qint64 received, qint64 total); void actDownloadFinished(); }; From a799cd097af44651279e8ce80420c3c4a92f9e6f Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Wed, 3 Dec 2025 08:23:34 +0100 Subject: [PATCH 26/40] [PrintingSelector] Sync modified and history state on bulk selection (#6379) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [PrintingSelector] Emit deckModified when using bulk selection * [PrintingSelector] Hook up history manager. * [PrintingSelector] Remember card amount. * Return early. Took 18 minutes --------- Co-authored-by: Lukas Brübach --- .../dialogs/dlg_select_set_for_cards.cpp | 20 ++++++++++++++++++- .../dialogs/dlg_select_set_for_cards.h | 2 ++ .../printing_selector/printing_selector.h | 5 +++++ ...rinting_selector_card_selection_widget.cpp | 5 +++++ 4 files changed, 31 insertions(+), 1 deletion(-) 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 893c84512..905ac5db0 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 @@ -145,31 +145,49 @@ void DlgSelectSetForCards::retranslateUi() void DlgSelectSetForCards::actOK() { QMap modifiedSetsAndCardsMap = getModifiedCards(); + + if (modifiedSetsAndCardsMap.isEmpty()) { + accept(); // Nothing to do + } else { + emit deckAboutToBeModified(tr("Bulk modified printings.")); + } + for (QString modifiedSet : modifiedSetsAndCardsMap.keys()) { for (QString card : modifiedSetsAndCardsMap.value(modifiedSet)) { QModelIndex find_card = model->findCard(card, DECK_ZONE_MAIN); if (!find_card.isValid()) { continue; } + int amount = + model->data(find_card.siblingAtColumn(DeckListModelColumns::CARD_AMOUNT), Qt::DisplayRole).toInt(); model->removeRow(find_card.row(), find_card.parent()); CardInfoPtr cardInfo = CardDatabaseManager::query()->getCardInfo(card); PrintingInfo printing = CardDatabaseManager::query()->getSpecificPrinting(card, modifiedSet, ""); - model->addCard(ExactCard(cardInfo, printing), DECK_ZONE_MAIN); + for (int i = 0; i < amount; i++) { + model->addCard(ExactCard(cardInfo, printing), DECK_ZONE_MAIN); + } } } + if (!modifiedSetsAndCardsMap.isEmpty()) { + emit deckModified(); + } accept(); } void DlgSelectSetForCards::actClear() { + emit deckAboutToBeModified(tr("Cleared all printing information.")); DeckLoader::clearSetNamesAndNumbers(model->getDeckList()); + emit deckModified(); accept(); } void DlgSelectSetForCards::actSetAllToPreferred() { + emit deckAboutToBeModified(tr("Set all printings to preferred.")); DeckLoader::clearSetNamesAndNumbers(model->getDeckList()); DeckLoader::setProviderIdToPreferredPrinting(model->getDeckList()); + emit deckModified(); accept(); } diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_select_set_for_cards.h b/cockatrice/src/interface/widgets/dialogs/dlg_select_set_for_cards.h index 335b86d2c..5cdef5a30 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_select_set_for_cards.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_select_set_for_cards.h @@ -37,6 +37,8 @@ public: signals: void widgetOrderChanged(); void orderChanged(); + void deckAboutToBeModified(const QString &reason); + void deckModified(); public slots: void actOK(); diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector.h b/cockatrice/src/interface/widgets/printing_selector/printing_selector.h index 7130e436c..fbe3b5b06 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector.h +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector.h @@ -40,6 +40,11 @@ public: return deckModel; } + [[nodiscard]] AbstractTabDeckEditor *getDeckEditor() const + { + return deckEditor; + } + public slots: void retranslateUi(); void updateDisplay(); diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_selection_widget.cpp b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_selection_widget.cpp index 57d5fd895..fc17cecd0 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_selection_widget.cpp +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_selection_widget.cpp @@ -1,6 +1,7 @@ #include "printing_selector_card_selection_widget.h" #include "../../../interface/widgets/dialogs/dlg_select_set_for_cards.h" +#include "../tabs/abstract_tab_deck_editor.h" /** * @brief Constructs a PrintingSelectorCardSelectionWidget for navigating through cards in the deck. @@ -48,6 +49,10 @@ void PrintingSelectorCardSelectionWidget::connectSignals() void PrintingSelectorCardSelectionWidget::selectSetForCards() { auto *setSelectionDialog = new DlgSelectSetForCards(nullptr, parent->getDeckModel()); + connect(setSelectionDialog, &DlgSelectSetForCards::deckAboutToBeModified, parent->getDeckEditor(), + &AbstractTabDeckEditor::onDeckHistorySaveRequested); + connect(setSelectionDialog, &DlgSelectSetForCards::deckModified, parent->getDeckEditor(), + &AbstractTabDeckEditor::onDeckModified); if (!setSelectionDialog->exec()) { return; } From f0be6972cccd4b030710ac605109ff1bc8c5903d Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Thu, 4 Dec 2025 09:40:24 -0800 Subject: [PATCH 27/40] [TagsDisplayWidget] cleanup refactor (#6394) * Make fields private * Move method to static * clean up code * move code --- .../deck_preview_deck_tags_display_widget.cpp | 155 ++++++++++-------- .../deck_preview_deck_tags_display_widget.h | 10 +- 2 files changed, 96 insertions(+), 69 deletions(-) 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 a29f3bfc4..28b786951 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 @@ -71,74 +71,36 @@ static QStringList getAllFiles(const QString &filePath) return allFiles; } -bool confirmOverwriteIfExists(QWidget *parent, const QString &filePath) +/** + * Gets all tags that appear in the deck folder + */ +static QStringList findAllKnownTags() { - QFileInfo fileInfo(filePath); - QString newFileName = QDir::toNativeSeparators(fileInfo.path() + "/" + fileInfo.completeBaseName() + ".cod"); + QStringList allFiles = getAllFiles(SettingsCache::instance().getDeckPath()); - if (QFile::exists(newFileName)) { - QMessageBox::StandardButton reply = - QMessageBox::question(parent, QObject::tr("Overwrite Existing File?"), - QObject::tr("A .cod version of this deck already exists. Overwrite it?"), - QMessageBox::Yes | QMessageBox::No); - return reply == QMessageBox::Yes; + QStringList knownTags; + auto loader = DeckLoader(nullptr); + for (const QString &file : allFiles) { + loader.loadFromFile(file, DeckLoader::getFormatFromName(file), false); + QStringList tags = loader.getDeckList()->getTags(); + knownTags.append(tags); + knownTags.removeDuplicates(); } - return true; // Safe to proceed + + return knownTags; } void DeckPreviewDeckTagsDisplayWidget::openTagEditDlg() { if (qobject_cast(parentWidget())) { auto *deckPreviewWidget = qobject_cast(parentWidget()); - QStringList knownTags = deckPreviewWidget->visualDeckStorageWidget->tagFilterWidget->getAllKnownTags(); - QStringList activeTags = deckList->getTags(); - bool canAddTags = true; - - if (DeckLoader::getFormatFromName(deckPreviewWidget->filePath) != DeckLoader::CockatriceFormat) { - canAddTags = false; - // Retrieve saved preference if the prompt is disabled - if (!SettingsCache::instance().getVisualDeckStoragePromptForConversion()) { - if (SettingsCache::instance().getVisualDeckStorageAlwaysConvert()) { - - if (!confirmOverwriteIfExists(this, deckPreviewWidget->filePath)) - return; - - deckPreviewWidget->deckLoader->convertToCockatriceFormat(deckPreviewWidget->filePath); - deckPreviewWidget->filePath = deckPreviewWidget->deckLoader->getLastLoadInfo().fileName; - deckPreviewWidget->refreshBannerCardText(); - canAddTags = true; - } - } else { - // Show the dialog to the user - DialogConvertDeckToCodFormat conversionDialog(parentWidget()); - if (conversionDialog.exec() == QDialog::Accepted) { - - if (!confirmOverwriteIfExists(this, deckPreviewWidget->filePath)) - return; - - deckPreviewWidget->deckLoader->convertToCockatriceFormat(deckPreviewWidget->filePath); - deckPreviewWidget->filePath = deckPreviewWidget->deckLoader->getLastLoadInfo().fileName; - deckPreviewWidget->refreshBannerCardText(); - canAddTags = true; - - if (conversionDialog.dontAskAgain()) { - SettingsCache::instance().setVisualDeckStoragePromptForConversion(false); - SettingsCache::instance().setVisualDeckStorageAlwaysConvert(true); - } - } else { - SettingsCache::instance().setVisualDeckStorageAlwaysConvert(false); - - if (conversionDialog.dontAskAgain()) { - SettingsCache::instance().setVisualDeckStoragePromptForConversion(false); - } else { - SettingsCache::instance().setVisualDeckStoragePromptForConversion(true); - } - } - } - } + bool canAddTags = promptFileConversionIfRequired(deckPreviewWidget); if (canAddTags) { + QStringList knownTags = deckPreviewWidget->visualDeckStorageWidget->tagFilterWidget->getAllKnownTags(); + QStringList activeTags = deckList->getTags(); + DeckPreviewTagDialog dialog(knownTags, activeTags); if (dialog.exec() == QDialog::Accepted) { QStringList updatedTags = dialog.getActiveTags(); @@ -159,16 +121,8 @@ void DeckPreviewDeckTagsDisplayWidget::openTagEditDlg() } if (qobject_cast(currentParent)) { auto *deckEditor = qobject_cast(currentParent); - QStringList knownTags; - QStringList allFiles = getAllFiles(SettingsCache::instance().getDeckPath()); - DeckLoader loader(this); - for (const QString &file : allFiles) { - loader.loadFromFile(file, DeckLoader::getFormatFromName(file), false); - QStringList tags = loader.getDeckList()->getTags(); - knownTags.append(tags); - knownTags.removeDuplicates(); - } + QStringList knownTags = findAllKnownTags(); QStringList activeTags = deckList->getTags(); DeckPreviewTagDialog dialog(knownTags, activeTags); @@ -181,3 +135,74 @@ void DeckPreviewDeckTagsDisplayWidget::openTagEditDlg() } } } + +static bool confirmOverwriteIfExists(QWidget *parent, const QString &filePath) +{ + QFileInfo fileInfo(filePath); + QString newFileName = QDir::toNativeSeparators(fileInfo.path() + "/" + fileInfo.completeBaseName() + ".cod"); + + if (QFile::exists(newFileName)) { + QMessageBox::StandardButton reply = + QMessageBox::question(parent, QObject::tr("Overwrite Existing File?"), + QObject::tr("A .cod version of this deck already exists. Overwrite it?"), + QMessageBox::Yes | QMessageBox::No); + return reply == QMessageBox::Yes; + } + return true; // Safe to proceed +} + +static void convertFileToCockatriceFormat(DeckPreviewWidget *deckPreviewWidget) +{ + deckPreviewWidget->deckLoader->convertToCockatriceFormat(deckPreviewWidget->filePath); + deckPreviewWidget->filePath = deckPreviewWidget->deckLoader->getLastLoadInfo().fileName; + deckPreviewWidget->refreshBannerCardText(); +} + +/** + * Checks if the deck's file format supports tags. + * If not, then prompt the user for file conversion. + * @return whether the resulting file can support adding tags + */ +bool DeckPreviewDeckTagsDisplayWidget::promptFileConversionIfRequired(DeckPreviewWidget *deckPreviewWidget) +{ + if (DeckLoader::getFormatFromName(deckPreviewWidget->filePath) == DeckLoader::CockatriceFormat) { + return true; + } + + // Retrieve saved preference if the prompt is disabled + if (!SettingsCache::instance().getVisualDeckStoragePromptForConversion()) { + if (!SettingsCache::instance().getVisualDeckStorageAlwaysConvert()) { + return false; + } + + if (!confirmOverwriteIfExists(this, deckPreviewWidget->filePath)) { + return false; + } + + convertFileToCockatriceFormat(deckPreviewWidget); + return true; + } + + // Show the dialog to the user + DialogConvertDeckToCodFormat conversionDialog(parentWidget()); + if (conversionDialog.exec() != QDialog::Accepted) { + SettingsCache::instance().setVisualDeckStoragePromptForConversion(!conversionDialog.dontAskAgain()); + SettingsCache::instance().setVisualDeckStorageAlwaysConvert(false); + + return false; + } + + // Try to convert file + if (!confirmOverwriteIfExists(this, deckPreviewWidget->filePath)) { + return false; + } + + convertFileToCockatriceFormat(deckPreviewWidget); + + if (conversionDialog.dontAskAgain()) { + SettingsCache::instance().setVisualDeckStoragePromptForConversion(false); + SettingsCache::instance().setVisualDeckStorageAlwaysConvert(true); + } + + return true; +} \ No newline at end of file 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 b1b1117ae..85b0bb9f8 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 @@ -12,21 +12,23 @@ #include -inline bool confirmOverwriteIfExists(QWidget *parent, const QString &filePath); - class DeckPreviewWidget; class DeckPreviewDeckTagsDisplayWidget : public QWidget { Q_OBJECT + DeckList *deckList; + FlowWidget *flowWidget; + public: explicit DeckPreviewDeckTagsDisplayWidget(QWidget *_parent, DeckList *_deckList); void setDeckList(DeckList *_deckList); void refreshTags(); - DeckList *deckList; - FlowWidget *flowWidget; public slots: void openTagEditDlg(); + +private: + bool promptFileConversionIfRequired(DeckPreviewWidget *deckPreviewWidget); }; #endif // DECK_PREVIEW_DECK_TAGS_DISPLAY_WIDGET_H From 95c34342053bb49392f35b6971d3508190c73b9b Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Thu, 4 Dec 2025 10:26:39 -0800 Subject: [PATCH 28/40] [TagDisplayWidget] Refactor to just store tags and use signals (#6395) --- .../deck_editor_deck_dock_widget.cpp | 15 ++++- .../deck_editor_deck_dock_widget.h | 1 + .../deck_preview_deck_tags_display_widget.cpp | 67 +++++++------------ .../deck_preview_deck_tags_display_widget.h | 14 +++- .../deck_preview/deck_preview_widget.cpp | 9 ++- .../deck_preview/deck_preview_widget.h | 2 + 6 files changed, 59 insertions(+), 49 deletions(-) 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 075b73216..7e4287ac5 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 @@ -154,8 +154,10 @@ void DeckEditorDeckDockWidget::createDeckDock() &DeckEditorDeckDockWidget::setBannerCard); bannerCardComboBox->setHidden(!SettingsCache::instance().getDeckEditorBannerCardComboBoxVisible()); - deckTagsDisplayWidget = new DeckPreviewDeckTagsDisplayWidget(this, deckModel->getDeckList()); + deckTagsDisplayWidget = new DeckPreviewDeckTagsDisplayWidget(this, deckModel->getDeckList()->getTags()); deckTagsDisplayWidget->setHidden(!SettingsCache::instance().getDeckEditorTagsWidgetVisible()); + connect(deckTagsDisplayWidget, &DeckPreviewDeckTagsDisplayWidget::tagsChanged, this, + &DeckEditorDeckDockWidget::setTags); activeGroupCriteriaLabel = new QLabel(this); @@ -383,6 +385,13 @@ void DeckEditorDeckDockWidget::setBannerCard(int /* changedIndex */) emit deckModified(); } +void DeckEditorDeckDockWidget::setTags(const QStringList &tags) +{ + deckModel->getDeckList()->setTags(tags); + deckEditor->setModified(true); + emit deckModified(); +} + void DeckEditorDeckDockWidget::syncDeckListBannerCardWithComboBox() { auto [name, id] = bannerCardComboBox->currentData().value>(); @@ -451,7 +460,7 @@ void DeckEditorDeckDockWidget::syncDisplayWidgetsToModel() sortDeckModelToDeckView(); expandAll(); - deckTagsDisplayWidget->setDeckList(deckModel->getDeckList()); + deckTagsDisplayWidget->setTags(deckModel->getDeckList()->getTags()); } void DeckEditorDeckDockWidget::sortDeckModelToDeckView() @@ -484,7 +493,7 @@ void DeckEditorDeckDockWidget::cleanDeck() emit deckModified(); emit deckChanged(); updateBannerCardComboBox(); - deckTagsDisplayWidget->setDeckList(deckModel->getDeckList()); + deckTagsDisplayWidget->setTags(deckModel->getDeckList()->getTags()); } void DeckEditorDeckDockWidget::recursiveExpand(const QModelIndex &index) 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 37891072d..d1f1da300 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 @@ -112,6 +112,7 @@ private slots: void updateName(const QString &name); void updateComments(); void setBannerCard(int); + void setTags(const QStringList &tags); void syncDeckListBannerCardWithComboBox(); void updateHash(); void refreshShortcuts(); 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 28b786951..fce0916bb 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 @@ -13,8 +13,8 @@ #include #include -DeckPreviewDeckTagsDisplayWidget::DeckPreviewDeckTagsDisplayWidget(QWidget *_parent, DeckList *_deckList) - : QWidget(_parent), deckList(nullptr) +DeckPreviewDeckTagsDisplayWidget::DeckPreviewDeckTagsDisplayWidget(QWidget *_parent, const QStringList &_tags) + : QWidget(_parent), currentTags(_tags) { setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); @@ -27,16 +27,14 @@ DeckPreviewDeckTagsDisplayWidget::DeckPreviewDeckTagsDisplayWidget(QWidget *_par flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAsNeeded); - if (_deckList) { - setDeckList(_deckList); - } - layout->addWidget(flowWidget); + + refreshTags(); } -void DeckPreviewDeckTagsDisplayWidget::setDeckList(DeckList *_deckList) +void DeckPreviewDeckTagsDisplayWidget::setTags(const QStringList &_tags) { - deckList = _deckList; + currentTags = _tags; refreshTags(); } @@ -44,7 +42,7 @@ void DeckPreviewDeckTagsDisplayWidget::refreshTags() { flowWidget->clearLayout(); - for (const QString &tag : deckList->getTags()) { + for (const QString &tag : currentTags) { flowWidget->addWidget(new DeckPreviewTagDisplayWidget(this, tag)); } @@ -93,46 +91,19 @@ static QStringList findAllKnownTags() void DeckPreviewDeckTagsDisplayWidget::openTagEditDlg() { if (qobject_cast(parentWidget())) { + // If we're the child of a DeckPreviewWidget, then we need to handle conversion auto *deckPreviewWidget = qobject_cast(parentWidget()); bool canAddTags = promptFileConversionIfRequired(deckPreviewWidget); if (canAddTags) { QStringList knownTags = deckPreviewWidget->visualDeckStorageWidget->tagFilterWidget->getAllKnownTags(); - QStringList activeTags = deckList->getTags(); - - DeckPreviewTagDialog dialog(knownTags, activeTags); - if (dialog.exec() == QDialog::Accepted) { - QStringList updatedTags = dialog.getActiveTags(); - deckList->setTags(updatedTags); - deckPreviewWidget->deckLoader->saveToFile(deckPreviewWidget->filePath, DeckLoader::CockatriceFormat); - refreshTags(); - } - } - } else if (parentWidget()) { - // If we're the child of an AbstractTabDeckEditor, we are buried under a ton of childWidgets in the - // DeckInfoDock. - QWidget *currentParent = parentWidget(); - while (currentParent) { - if (qobject_cast(currentParent)) { - break; - } - currentParent = currentParent->parentWidget(); - } - if (qobject_cast(currentParent)) { - auto *deckEditor = qobject_cast(currentParent); - - QStringList knownTags = findAllKnownTags(); - QStringList activeTags = deckList->getTags(); - - DeckPreviewTagDialog dialog(knownTags, activeTags); - if (dialog.exec() == QDialog::Accepted) { - QStringList updatedTags = dialog.getActiveTags(); - deckList->setTags(updatedTags); - deckEditor->setModified(true); - refreshTags(); - } + execTagDialog(knownTags); } + } else { + // If we're the child of an AbstractTabDeckEditor, then we don't bother with conversion + QStringList knownTags = findAllKnownTags(); + execTagDialog(knownTags); } } @@ -205,4 +176,16 @@ bool DeckPreviewDeckTagsDisplayWidget::promptFileConversionIfRequired(DeckPrevie } return true; +} + +void DeckPreviewDeckTagsDisplayWidget::execTagDialog(const QStringList &knownTags) +{ + DeckPreviewTagDialog dialog(knownTags, currentTags); + if (dialog.exec() == QDialog::Accepted) { + QStringList updatedTags = dialog.getActiveTags(); + if (updatedTags != currentTags) { + setTags(updatedTags); + emit tagsChanged(updatedTags); + } + } } \ No newline at end of file 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 85b0bb9f8..74ea1cbdf 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 @@ -17,12 +17,12 @@ class DeckPreviewDeckTagsDisplayWidget : public QWidget { Q_OBJECT - DeckList *deckList; + QStringList currentTags; FlowWidget *flowWidget; public: - explicit DeckPreviewDeckTagsDisplayWidget(QWidget *_parent, DeckList *_deckList); - void setDeckList(DeckList *_deckList); + explicit DeckPreviewDeckTagsDisplayWidget(QWidget *_parent, const QStringList &_tags); + void setTags(const QStringList &_tags); void refreshTags(); public slots: @@ -30,5 +30,13 @@ public slots: private: bool promptFileConversionIfRequired(DeckPreviewWidget *deckPreviewWidget); + void execTagDialog(const QStringList &knownTags); + +signals: + /** + * Emitted when the tags have changed due to user interaction. + * @param tags The new list of tags. + */ + void tagsChanged(const QStringList &tags); }; #endif // DECK_PREVIEW_DECK_TAGS_DISPLAY_WIDGET_H 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 2735b4856..bf915bbea 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 @@ -83,7 +83,8 @@ void DeckPreviewWidget::initializeUi(const bool deckLoadSuccess) setFilePath(deckLoader->getLastLoadInfo().fileName); colorIdentityWidget = new ColorIdentityWidget(this, getColorIdentity()); - deckTagsDisplayWidget = new DeckPreviewDeckTagsDisplayWidget(this, deckLoader->getDeckList()); + deckTagsDisplayWidget = new DeckPreviewDeckTagsDisplayWidget(this, deckLoader->getDeckList()->getTags()); + connect(deckTagsDisplayWidget, &DeckPreviewDeckTagsDisplayWidget::tagsChanged, this, &DeckPreviewWidget::setTags); bannerCardLabel = new QLabel(this); bannerCardLabel->setObjectName("bannerCardLabel"); @@ -307,6 +308,12 @@ void DeckPreviewWidget::imageDoubleClickedEvent(QMouseEvent *event, DeckPreviewC emit deckLoadRequested(filePath); } +void DeckPreviewWidget::setTags(const QStringList &tags) +{ + deckLoader->getDeckList()->setTags(tags); + deckLoader->saveToFile(filePath, DeckLoader::CockatriceFormat); +} + QMenu *DeckPreviewWidget::createRightClickMenu() { auto *menu = new QMenu(this); 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 76db9e569..6e6fdb9af 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 @@ -72,6 +72,8 @@ private: void addSetBannerCardMenu(QMenu *menu); private slots: + void setTags(const QStringList &tags); + void actRenameDeck(); void actRenameFile(); void actDeleteFile(); From 0a239712dd4a16aba3f7bf7f0b624df210cb9815 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Thu, 4 Dec 2025 23:14:19 +0100 Subject: [PATCH 29/40] [VDD] Add search bar for filters. (#6389) * [VDD] Add search bar for filters. * Update cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.cpp Co-authored-by: RickyRister <42636155+RickyRister@users.noreply.github.com> --------- Co-authored-by: RickyRister <42636155+RickyRister@users.noreply.github.com> --- ...tabase_display_filter_save_load_widget.cpp | 78 ++++++++++--------- ...database_display_filter_save_load_widget.h | 5 +- 2 files changed, 46 insertions(+), 37 deletions(-) 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 4d8eb5c57..44b275afd 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 @@ -18,6 +18,16 @@ VisualDatabaseDisplayFilterSaveLoadWidget::VisualDatabaseDisplayFilterSaveLoadWi layout = new QVBoxLayout(this); setLayout(layout); + // Filter search input + searchInput = new QLineEdit(this); + layout->addWidget(searchInput); + + connect(searchInput, &QLineEdit::textChanged, this, &VisualDatabaseDisplayFilterSaveLoadWidget::applySearchFilter); + + // File list container + fileListWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAsNeeded); + layout->addWidget(fileListWidget); + // Input for filter filename filenameInput = new QLineEdit(this); layout->addWidget(filenameInput); @@ -25,11 +35,12 @@ VisualDatabaseDisplayFilterSaveLoadWidget::VisualDatabaseDisplayFilterSaveLoadWi // Save button saveButton = new QPushButton(this); layout->addWidget(saveButton); - connect(saveButton, &QPushButton::clicked, this, &VisualDatabaseDisplayFilterSaveLoadWidget::saveFilter); + // Disable save if empty + saveButton->setEnabled(false); + connect(filenameInput, &QLineEdit::textChanged, this, + [this](const QString &text) { saveButton->setEnabled(!text.trimmed().isEmpty()); }); - // File list container - fileListWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAsNeeded); - layout->addWidget(fileListWidget); + connect(saveButton, &QPushButton::clicked, this, &VisualDatabaseDisplayFilterSaveLoadWidget::saveFilter); refreshFilterList(); // Populate the file list on startup retranslateUi(); @@ -37,6 +48,7 @@ VisualDatabaseDisplayFilterSaveLoadWidget::VisualDatabaseDisplayFilterSaveLoadWi void VisualDatabaseDisplayFilterSaveLoadWidget::retranslateUi() { + searchInput->setPlaceholderText(tr("Search filter...")); saveButton->setText(tr("Save Filter")); saveButton->setToolTip(tr("Save all currently applied filters to a file")); filenameInput->setPlaceholderText(tr("Enter filename...")); @@ -112,42 +124,36 @@ void VisualDatabaseDisplayFilterSaveLoadWidget::loadFilter(const QString &filena emit filterModel->layoutChanged(); } +void VisualDatabaseDisplayFilterSaveLoadWidget::applySearchFilter(const QString &text) +{ + fileListWidget->clearLayout(); + + QString filter = text.trimmed(); + QStringList filtered = allFilterFiles; + + if (!filter.isEmpty()) { + filtered = filtered.filter(QRegularExpression(filter, QRegularExpression::CaseInsensitiveOption)); + } + + for (const QString &filename : filtered) { + FilterDisplayWidget *filterWidget = new FilterDisplayWidget(this, filename, filterModel); + fileListWidget->addWidget(filterWidget); + + connect(filterWidget, &FilterDisplayWidget::filterLoadRequested, this, + &VisualDatabaseDisplayFilterSaveLoadWidget::loadFilter); + + connect(filterWidget, &FilterDisplayWidget::filterDeleted, this, + &VisualDatabaseDisplayFilterSaveLoadWidget::refreshFilterList); + } +} + void VisualDatabaseDisplayFilterSaveLoadWidget::refreshFilterList() { fileListWidget->clearLayout(); - // Clear existing widgets - for (auto buttonPair : fileButtons) { - buttonPair.first->deleteLater(); - buttonPair.second->deleteLater(); - } - fileButtons.clear(); // Clear the list of buttons + fileButtons.clear(); - // Refresh the filter file list QDir dir(SettingsCache::instance().getFiltersPath()); - QStringList filterFiles = dir.entryList(QStringList() << "*.json", QDir::Files, QDir::Name); + allFilterFiles = dir.entryList({"*.json"}, QDir::Files, QDir::Name); - // Loop through the filter files and create widgets for them - for (const QString &filename : filterFiles) { - bool alreadyAdded = false; - - // Check if the widget for this filter file already exists to avoid duplicates - for (const auto &pair : fileButtons) { - if (pair.first->text() == filename) { - alreadyAdded = true; - break; - } - } - - if (!alreadyAdded) { - // Create a new custom widget for the filter - FilterDisplayWidget *filterWidget = new FilterDisplayWidget(this, filename, filterModel); - fileListWidget->addWidget(filterWidget); - - // Connect signals to handle loading and deletion - connect(filterWidget, &FilterDisplayWidget::filterLoadRequested, this, - &VisualDatabaseDisplayFilterSaveLoadWidget::loadFilter); - connect(filterWidget, &FilterDisplayWidget::filterDeleted, this, - &VisualDatabaseDisplayFilterSaveLoadWidget::refreshFilterList); - } - } + applySearchFilter(searchInput->text()); } diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.h index 48e6f9498..bb5921a02 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.h @@ -27,6 +27,7 @@ public: void saveFilter(); void loadFilter(const QString &filename); + void applySearchFilter(const QString &text); void refreshFilterList(); void deleteFilter(const QString &filename, QPushButton *deleteButton); @@ -37,9 +38,11 @@ private: FilterTreeModel *filterModel; QVBoxLayout *layout; + QLineEdit *searchInput; + FlowWidget *fileListWidget; QLineEdit *filenameInput; QPushButton *saveButton; - FlowWidget *fileListWidget; + QStringList allFilterFiles; QMap> fileButtons; }; From edb0a954e2b9cf57cdc15ea5a582971a50494d39 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Fri, 5 Dec 2025 17:26:35 +0100 Subject: [PATCH 30/40] [GameInformation] Check for existence of room for create as judge checkbox (#6398) --- cockatrice/src/interface/widgets/dialogs/dlg_create_game.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_create_game.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_create_game.cpp index 55b999ee9..7f109f600 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_create_game.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_create_game.cpp @@ -109,7 +109,7 @@ void DlgCreateGame::sharedCtor() gameSetupOptionsLayout->addWidget(startingLifeTotalLabel, 0, 0); gameSetupOptionsLayout->addWidget(startingLifeTotalEdit, 0, 1); gameSetupOptionsLayout->addWidget(shareDecklistsOnLoadCheckBox, 1, 0); - if (room->getUserInfo()->user_level() & ServerInfo_User::IsJudge) { + if (room && room->getUserInfo()->user_level() & ServerInfo_User::IsJudge) { gameSetupOptionsLayout->addWidget(createGameAsJudgeCheckBox, 2, 0); } else { createGameAsJudgeCheckBox->setChecked(false); From 7c7f2dd8d5c4196ed1562d1b6c8773796c96c6c4 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Fri, 5 Dec 2025 18:42:45 +0100 Subject: [PATCH 31/40] [Doxygen] Logging (#6399) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Doxygen] Logging Took 50 minutes Took 36 seconds * [Doxygen] Newline. Took 2 minutes * [Doxygen] Add another example. Took 7 minutes * [Doxygen] \note and \warning Took 4 minutes Took 32 seconds --------- Co-authored-by: Lukas Brübach --- cockatrice/resources/config/qtlogging.ini | 4 + .../developer_documentation/index.md | 2 + .../developer_documentation/logging.md | 184 ++++++++++++++++++ 3 files changed, 190 insertions(+) create mode 100644 doc/doxygen/extra-pages/developer_documentation/logging.md diff --git a/cockatrice/resources/config/qtlogging.ini b/cockatrice/resources/config/qtlogging.ini index 083d7234e..20aa206ce 100644 --- a/cockatrice/resources/config/qtlogging.ini +++ b/cockatrice/resources/config/qtlogging.ini @@ -1,6 +1,10 @@ [Rules] # The default log level is info *.debug = false +#*.info = true +#*.warning = true +#*.critical = true +#*.fatal = true # Uncomment a rule to see debug level logs for that category, # or set = false to disable logging diff --git a/doc/doxygen/extra-pages/developer_documentation/index.md b/doc/doxygen/extra-pages/developer_documentation/index.md index b26faf836..da2d444d8 100644 --- a/doc/doxygen/extra-pages/developer_documentation/index.md +++ b/doc/doxygen/extra-pages/developer_documentation/index.md @@ -1,5 +1,7 @@ @page developer_reference Developer Reference +- @subpage logging + - @subpage primer_cards - @subpage card_database_schema_and_parsing diff --git a/doc/doxygen/extra-pages/developer_documentation/logging.md b/doc/doxygen/extra-pages/developer_documentation/logging.md new file mode 100644 index 000000000..8fd5cb015 --- /dev/null +++ b/doc/doxygen/extra-pages/developer_documentation/logging.md @@ -0,0 +1,184 @@ +@page logging Logging + +Cockatrice uses QtLogging from the QtCore module for its logging. See +the [official documentation](https://doc.qt.io/qt-6/qtlogging.html) for further details. + +# Log Message Pattern + +Any message logged through the QtLogging system automatically conforms to this message pattern: + +Generic: + +``` +[ ] [] - [:] +``` + +Example: + +``` +[2025-12-05 14:48:25.908 I] [MainWindow::startupConfigCheck] - Startup: found config with current version [window_main.cpp:951] +``` + +For more information, see [Logging Setup](#logging-setup). + +# Log Level and Categories + +\note The default log level for the application is info. + +This means that you should only use qInfo() in production-level code if you are truly sure that this message is +beneficial to end-users and other developers. As a general rule, if your functionality logs to info more than twice in +response to a user interaction, you are advised to consider moving some of these logs down to the debug level. + +\warning You are strongly advised to avoid the use of the generic logging macros (e.g. qDebug(), qInfo(), qWarn()). + +\note You should instead use the corresponding category logging macros (qCDebug(), qCInfo(), qCWarn()) and define +logging +categories for your log statements. + +Example: + +```c++ +in .h + +inline Q_LOGGING_CATEGORY(ExampleCategory, "cockatrice_example_category"); +inline Q_LOGGING_CATEGORY(ExampleSubCategory, "cockatrice_example_category.sub_category"); + +in .cpp + +qCInfo(ExampleCategory) << "Info level logs are usually sent through the main category" +qCDebug(ExampleSubCategory) << "Debug level logs are permitted their own category to allow selective silencing" +``` + +For more information on how to enable or disable logging categories, +see [Logging Configuration](#logging-configuration). + +# Logging Configuration + +For configuring our logging, we use the qtlogging.ini, located under cockatrice/resources/config/qtlogging.ini, which is +baked into the application in release version and set as the QT_LOGGING_CONF environment variable in main.cpp. + +```c++ +#ifdef Q_OS_APPLE + // /cockatrice/cockatrice.app/Contents/MacOS/cockatrice + const QByteArray configPath = "../../../qtlogging.ini"; +#elif defined(Q_OS_UNIX) + // /cockatrice/cockatrice + const QByteArray configPath = "./qtlogging.ini"; +#elif defined(Q_OS_WIN) + // /cockatrice/Debug/cockatrice.exe + const QByteArray configPath = "../qtlogging.ini"; +#else + const QByteArray configPath = ""; +#endif + + if (!qEnvironmentVariableIsSet(("QT_LOGGING_CONF"))) { + // Set the QT_LOGGING_CONF environment variable + qputenv("QT_LOGGING_CONF", configPath); + } +``` + +For more information on how to use this file and on how Qt evaluates which logging rules/file to use, please +see the [official Qt documentation](https://doc.qt.io/qt-6/qloggingcategory.html#configuring-categories). + +Some examples: + +``` +# Turn off all logging except everything from card_picture_loader and all sub categories + +[Rules] +# The default log level is info +*.debug = false +*.info = false +*.warning = false +*.critical = false +*.fatal = false + +card_picture_loader.* = true +``` + +``` +# Turn off all logging except info level logs from card_picture_loader and all sub categories + +[Rules] +# The default log level is info +*.debug = false +*.info = false +*.warning = false +*.critical = false +*.fatal = false + +card_picture_loader.*.info = true +``` + +``` +[Rules] +# Turn on debug level logs for card_picture_loader but keep logging for sub categories suppressed +*.debug = false + +card_picture_loader.debug = true +``` + +``` +[Rules] +# Turn on all logs for worker subcategory of card_picture_loader +*.debug = false + +card_picture_loader.worker = true +``` + +``` +[Rules] +# Turn off some noisy and irrelevant startup logging for local development +*.debug = false + +qt_translator = false +window_main.* = false +release_channel = false +spoiler_background_updater = false +theme_manager = false +sound_engine = false +tapped_out_interface = false +card_database = false +card_database.loading = false +card_database.loading.success_or_failure = true +cockatrice_xml.* = false +``` + +# Logging Setup + +This is achieved through our logging setup in @ref main.cpp, where we set the message pattern and install a custom +logger which replaces the full file path at the end with just the file name (Qt shows the full and quite lengthy path by +default). + +```c++ + qSetMessagePattern( + "\033[0m[%{time yyyy-MM-dd h:mm:ss.zzz} " + "%{if-debug}\033[36mD%{endif}%{if-info}\033[32mI%{endif}%{if-warning}\033[33mW%{endif}%{if-critical}\033[31mC%{" + "endif}%{if-fatal}\033[1;31mF%{endif}\033[0m] [%{function}] - %{message} [%{file}:%{line}]"); + QApplication app(argc, argv); + + QObject::connect(&app, &QApplication::lastWindowClosed, &app, &QApplication::quit); + + qInstallMessageHandler(CockatriceLogger); +``` + +```c++ +static void CockatriceLogger(QtMsgType type, const QMessageLogContext &ctx, const QString &message) +{ + QString logMessage = qFormatLogMessage(type, ctx, message); + + // Regular expression to match the full path in the square brackets and extract only the filename and line number + QRegularExpression regex(R"(\[(?:.:)?[\/\\].*[\/\\]([^\/\\]+\:\d+)\])"); + QRegularExpressionMatch match = regex.match(logMessage); + + if (match.hasMatch()) { + // Extract the filename and line number (e.g., "main.cpp:211") + QString filenameLine = match.captured(1); + + // Replace the full path in square brackets with just the filename and line number + logMessage.replace(match.captured(0), QString("[%1]").arg(filenameLine)); + } + + Logger::getInstance().log(type, ctx, logMessage); +} +``` \ No newline at end of file From dde36183ce4c1532e216e56eac2d41f5da134d41 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Fri, 5 Dec 2025 23:27:27 +0100 Subject: [PATCH 32/40] [VDE] Proper parent lookup syncs group-by box again (#6396) * [VDE] Proper parent lookup syncs group-by box again * [VDE] Proper lib inclusion. * [VDE] Lint. --- .../visual_deck_display_options_widget.cpp | 30 +++++++++---------- .../libcockatrice/utility/qt_utils.h | 20 +++++++++++++ 2 files changed, 34 insertions(+), 16 deletions(-) create mode 100644 libcockatrice_utility/libcockatrice/utility/qt_utils.h diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.cpp index c190038a5..b169e73cb 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.cpp @@ -2,7 +2,9 @@ #include "../tabs/visual_deck_editor/tab_deck_editor_visual.h" -VisualDeckDisplayOptionsWidget::VisualDeckDisplayOptionsWidget(QWidget *parent) +#include + +VisualDeckDisplayOptionsWidget::VisualDeckDisplayOptionsWidget(QWidget *parent) : QWidget(parent) { groupAndSortLayout = new QHBoxLayout(this); groupAndSortLayout->setAlignment(Qt::AlignLeft); @@ -11,23 +13,19 @@ VisualDeckDisplayOptionsWidget::VisualDeckDisplayOptionsWidget(QWidget *parent) groupByLabel = new QLabel(this); groupByComboBox = new QComboBox(this); - if (auto visualDeckEditorWidget = qobject_cast(parent)) { - if (auto tabWidget = qobject_cast(visualDeckEditorWidget)) { - // 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); }); + if (auto tab = QtUtils::findParentOfType(this)) { + auto originalBox = tab->getDeckDockWidget()->getGroupByComboBox(); + groupByComboBox->setModel(originalBox->model()); + groupByComboBox->setModelColumn(originalBox->modelColumn()); - // Clone -> original - connect(groupByComboBox, QOverload::of(&QComboBox::currentIndexChanged), - [originalBox](int index) { originalBox->setCurrentIndex(index); }); - } - } + // 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 { groupByComboBox->addItem( tr(qPrintable(DeckListModelGroupCriteria::toString(DeckListModelGroupCriteria::MAIN_TYPE))), diff --git a/libcockatrice_utility/libcockatrice/utility/qt_utils.h b/libcockatrice_utility/libcockatrice/utility/qt_utils.h new file mode 100644 index 000000000..855cc8b18 --- /dev/null +++ b/libcockatrice_utility/libcockatrice/utility/qt_utils.h @@ -0,0 +1,20 @@ +#ifndef COCKATRICE_QT_UTILS_H +#define COCKATRICE_QT_UTILS_H +#include + +namespace QtUtils +{ +template T *findParentOfType(const QObject *obj) +{ + const QObject *p = obj ? obj->parent() : nullptr; + while (p) { + if (auto casted = qobject_cast(const_cast(p))) { + return casted; + } + p = p->parent(); + } + return nullptr; +} +} // namespace QtUtils + +#endif // COCKATRICE_QT_UTILS_H From 5c1bb27d5cb900bbe60985c2ceb596fff3317a28 Mon Sep 17 00:00:00 2001 From: tooomm Date: Fri, 5 Dec 2025 23:28:25 +0100 Subject: [PATCH 33/40] README: Add code docs + flathub repo links (#6384) * Add code docs + flathub repo links * Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3e415fa23..b1233f749 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,8 @@ Latest beta version: - [Magic-Token](https://github.com/Cockatrice/Magic-Token): MtG token data to use in Cockatrice - [Magic-Spoiler](https://github.com/Cockatrice/Magic-Spoiler): Script to generate MtG spoiler data from [MTGJSON](https://github.com/mtgjson/mtgjson) to use in Cockatrice -- [cockatrice.github.io](https://github.com/Cockatrice/cockatrice.github.io): Code of the official webpage of the Cockatrice project +- [cockatrice.github.io](https://github.com/Cockatrice/cockatrice.github.io): Code of the official Cockatrice webpage +- [Cockatrice @Flathub](https://github.com/flathub/io.github.Cockatrice.cockatrice): Configuration for our Linux `flatpak` package # Community Resources [![Discord](https://img.shields.io/discord/314987288398659595?label=Discord&logo=discord&logoColor=white)](https://discord.gg/3Z9yzmA) @@ -54,6 +55,7 @@ Latest beta version: Join our [Discord community](https://discord.gg/3Z9yzmA) to connect with other projet contributors (`#dev` channel) or fellow users of the app. Come here to talk about the application, features, or just to hang out. - [Official Website](https://cockatrice.github.io) - [Official Wiki](https://github.com/Cockatrice/Cockatrice/wiki) +- [Official Code Documentation](https://cockatrice.github.io/docs) - [Official Discord](https://discord.gg/3Z9yzmA) - [reddit r/Cockatrice](https://reddit.com/r/cockatrice) From d3302d521fbc5f2b164e5ab97c7e0afda2812c84 Mon Sep 17 00:00:00 2001 From: Lily Huang <112970249+lilyhuang-github@users.noreply.github.com> Date: Sat, 6 Dec 2025 08:09:55 -0500 Subject: [PATCH 34/40] Fix flipped svg for donator/judge/vip (#6400) --- cockatrice/resources/usericons/pawn_donator_double.svg | 4 ++-- cockatrice/resources/usericons/pawn_judge_double.svg | 4 ++-- cockatrice/resources/usericons/pawn_vip_double.svg | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cockatrice/resources/usericons/pawn_donator_double.svg b/cockatrice/resources/usericons/pawn_donator_double.svg index f0dba08b2..30b353652 100644 --- a/cockatrice/resources/usericons/pawn_donator_double.svg +++ b/cockatrice/resources/usericons/pawn_donator_double.svg @@ -350,11 +350,11 @@ style="fill-opacity:1;stroke:black;stroke-width:2.78220296;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" d="M 49.84375 1.71875 C 36.719738 1.71875 26.0625 12.375988 26.0625 25.5 C 26.0625 32.977454 29.538325 39.612734 34.9375 43.96875 C 24.439951 49.943698 17.919149 62.196126 14.3125 75.65625 C 9.0380874 95.34065 30.224013 98.21875 49.84375 98.21875 C 69.463486 98.21875 90.549327 94.96715 85.375 75.65625 C 81.693381 61.916246 75.224585 49.827177 64.8125 43.9375 C 70.181573 39.580662 73.59375 32.953205 73.59375 25.5 C 73.59375 12.375988 62.967762 1.71875 49.84375 1.71875 z " transform="translate(0,952.36218)" - id="right" /> + id="left" /> + id="left" /> + id="left" /> Date: Sun, 7 Dec 2025 06:03:52 -0800 Subject: [PATCH 35/40] [DeckLoader] Extract LoadedDeck struct (#6406) * [DeckLoader] Extract LoadedDeck struct * update usages * Move enum to separate namespace * format * format * format --- cockatrice/CMakeLists.txt | 2 + .../src/game/deckview/deck_view_container.cpp | 2 +- .../deck_loader/deck_file_format.cpp | 9 ++++ .../interface/deck_loader/deck_file_format.h | 36 +++++++++++++++ .../src/interface/deck_loader/deck_loader.cpp | 42 +++++++----------- .../src/interface/deck_loader/deck_loader.h | 44 +++++-------------- .../src/interface/deck_loader/loaded_deck.cpp | 11 +++++ .../src/interface/deck_loader/loaded_deck.h | 39 ++++++++++++++++ .../interface/widgets/general/home_widget.cpp | 4 +- .../widgets/tabs/abstract_tab_deck_editor.cpp | 6 +-- .../widgets/tabs/tab_deck_storage.cpp | 6 +-- .../tab_deck_storage_visual.cpp | 2 +- .../deck_preview_deck_tags_display_widget.cpp | 4 +- .../deck_preview/deck_preview_widget.cpp | 10 ++--- 14 files changed, 143 insertions(+), 74 deletions(-) create mode 100644 cockatrice/src/interface/deck_loader/deck_file_format.cpp create mode 100644 cockatrice/src/interface/deck_loader/deck_file_format.h create mode 100644 cockatrice/src/interface/deck_loader/loaded_deck.cpp create mode 100644 cockatrice/src/interface/deck_loader/loaded_deck.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 1dbeddc5e..f531bc2c8 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -19,7 +19,9 @@ set(cockatrice_SOURCES src/client/settings/card_counter_settings.cpp src/client/settings/shortcut_treeview.cpp src/client/settings/shortcuts_settings.cpp + src/interface/deck_loader/deck_file_format.cpp src/interface/deck_loader/deck_loader.cpp + src/interface/deck_loader/loaded_deck.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 diff --git a/cockatrice/src/game/deckview/deck_view_container.cpp b/cockatrice/src/game/deckview/deck_view_container.cpp index cf6ab00b8..5d4a07bdf 100644 --- a/cockatrice/src/game/deckview/deck_view_container.cpp +++ b/cockatrice/src/game/deckview/deck_view_container.cpp @@ -259,7 +259,7 @@ void DeckViewContainer::loadLocalDeck() void DeckViewContainer::loadDeckFromFile(const QString &filePath) { - DeckLoader::FileFormat fmt = DeckLoader::getFormatFromName(filePath); + DeckFileFormat::Format fmt = DeckFileFormat::getFormatFromName(filePath); DeckLoader deck(this); bool success = deck.loadFromFile(filePath, fmt, true); diff --git a/cockatrice/src/interface/deck_loader/deck_file_format.cpp b/cockatrice/src/interface/deck_loader/deck_file_format.cpp new file mode 100644 index 000000000..3c88cde4e --- /dev/null +++ b/cockatrice/src/interface/deck_loader/deck_file_format.cpp @@ -0,0 +1,9 @@ +#include "deck_file_format.h" + +DeckFileFormat::Format DeckFileFormat::getFormatFromName(const QString &fileName) +{ + if (fileName.endsWith(".cod", Qt::CaseInsensitive)) { + return Cockatrice; + } + return PlainText; +} \ No newline at end of file diff --git a/cockatrice/src/interface/deck_loader/deck_file_format.h b/cockatrice/src/interface/deck_loader/deck_file_format.h new file mode 100644 index 000000000..995de32c0 --- /dev/null +++ b/cockatrice/src/interface/deck_loader/deck_file_format.h @@ -0,0 +1,36 @@ +#ifndef COCKATRICE_DECK_FILE_FORMAT_H +#define COCKATRICE_DECK_FILE_FORMAT_H +#include + +namespace DeckFileFormat +{ + +/** + * The deck file formats that Cockatrice supports. + */ +enum Format +{ + /** + * Plaintext deck files, a format that is intended to be widely supported among different programs. + * This format does not support Cockatrice specific features such as banner cards or tags. + */ + PlainText, + + /** + * This is cockatrice's native deck file format, and supports deck metadata such as banner cards and tags. + * Stored as .cod files. + */ + Cockatrice +}; + +/** + * Determines what deck file format the given filename corresponds to. + * + * @param fileName The filename + * @return The deck format + */ +Format getFormatFromName(const QString &fileName); + +} // namespace DeckFileFormat + +#endif // COCKATRICE_DECK_FILE_FORMAT_H diff --git a/cockatrice/src/interface/deck_loader/deck_loader.cpp b/cockatrice/src/interface/deck_loader/deck_loader.cpp index eea906a97..e3d1ce965 100644 --- a/cockatrice/src/interface/deck_loader/deck_loader.cpp +++ b/cockatrice/src/interface/deck_loader/deck_loader.cpp @@ -33,7 +33,7 @@ DeckLoader::DeckLoader(QObject *parent, DeckList *_deckList) : QObject(parent), { } -bool DeckLoader::loadFromFile(const QString &fileName, FileFormat fmt, bool userRequest) +bool DeckLoader::loadFromFile(const QString &fileName, DeckFileFormat::Format fmt, bool userRequest) { QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { @@ -42,17 +42,17 @@ bool DeckLoader::loadFromFile(const QString &fileName, FileFormat fmt, bool user bool result = false; switch (fmt) { - case PlainTextFormat: + case DeckFileFormat::PlainText: result = deckList->loadFromFile_Plain(&file); break; - case CockatriceFormat: { + case DeckFileFormat::Cockatrice: { result = deckList->loadFromFile_Native(&file); qCInfo(DeckLoaderLog) << "Loaded from" << fileName << "-" << result; if (!result) { qCInfo(DeckLoaderLog) << "Retrying as plain format"; file.seek(0); result = deckList->loadFromFile_Plain(&file); - fmt = PlainTextFormat; + fmt = DeckFileFormat::PlainText; } break; } @@ -77,7 +77,7 @@ bool DeckLoader::loadFromFile(const QString &fileName, FileFormat fmt, bool user return result; } -bool DeckLoader::loadFromFileAsync(const QString &fileName, FileFormat fmt, bool userRequest) +bool DeckLoader::loadFromFileAsync(const QString &fileName, DeckFileFormat::Format fmt, bool userRequest) { auto *watcher = new QFutureWatcher(this); @@ -106,9 +106,9 @@ bool DeckLoader::loadFromFileAsync(const QString &fileName, FileFormat fmt, bool } switch (fmt) { - case PlainTextFormat: + case DeckFileFormat::PlainText: return deckList->loadFromFile_Plain(&file); - case CockatriceFormat: { + case DeckFileFormat::Cockatrice: { bool result = false; result = deckList->loadFromFile_Native(&file); if (!result) { @@ -140,7 +140,7 @@ bool DeckLoader::loadFromRemote(const QString &nativeString, int remoteDeckId) return result; } -bool DeckLoader::saveToFile(const QString &fileName, FileFormat fmt) +bool DeckLoader::saveToFile(const QString &fileName, DeckFileFormat::Format fmt) { QFile file(fileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { @@ -149,10 +149,10 @@ bool DeckLoader::saveToFile(const QString &fileName, FileFormat fmt) bool result = false; switch (fmt) { - case PlainTextFormat: + case DeckFileFormat::PlainText: result = deckList->saveToFile_Plain(&file); break; - case CockatriceFormat: + case DeckFileFormat::Cockatrice: result = deckList->saveToFile_Native(&file); qCInfo(DeckLoaderLog) << "Saving to " << fileName << "-" << result; break; @@ -172,7 +172,7 @@ bool DeckLoader::saveToFile(const QString &fileName, FileFormat fmt) return result; } -bool DeckLoader::updateLastLoadedTimestamp(const QString &fileName, FileFormat fmt) +bool DeckLoader::updateLastLoadedTimestamp(const QString &fileName, DeckFileFormat::Format fmt) { QFileInfo fileInfo(fileName); if (!fileInfo.exists()) { @@ -193,10 +193,10 @@ bool DeckLoader::updateLastLoadedTimestamp(const QString &fileName, FileFormat f // Perform file modifications switch (fmt) { - case PlainTextFormat: + case DeckFileFormat::PlainText: result = deckList->saveToFile_Plain(&file); break; - case CockatriceFormat: + case DeckFileFormat::Cockatrice: deckList->setLastLoadedTimestamp(QDateTime::currentDateTime().toString()); result = deckList->saveToFile_Native(&file); break; @@ -414,14 +414,6 @@ void DeckLoader::clearSetNamesAndNumbers(const DeckList *deckList) deckList->forEachCard(clearSetNameAndNumber); } -DeckLoader::FileFormat DeckLoader::getFormatFromName(const QString &fileName) -{ - if (fileName.endsWith(".cod", Qt::CaseInsensitive)) { - return CockatriceFormat; - } - return PlainTextFormat; -} - void DeckLoader::saveToClipboard(const DeckList *deckList, bool addComments, bool addSetNameAndNumber) { QString buffer; @@ -564,12 +556,12 @@ bool DeckLoader::convertToCockatriceFormat(QString fileName) bool result = false; // Perform file modifications based on the detected format - switch (getFormatFromName(fileName)) { - case PlainTextFormat: + switch (DeckFileFormat::getFormatFromName(fileName)) { + case DeckFileFormat::PlainText: // Save in Cockatrice's native format result = deckList->saveToFile_Native(&file); break; - case CockatriceFormat: + case DeckFileFormat::Cockatrice: qCInfo(DeckLoaderLog) << "File is already in Cockatrice format. No conversion needed."; result = true; break; @@ -590,7 +582,7 @@ bool DeckLoader::convertToCockatriceFormat(QString fileName) } lastLoadInfo = { .fileName = newFileName, - .fileFormat = CockatriceFormat, + .fileFormat = DeckFileFormat::Cockatrice, }; } diff --git a/cockatrice/src/interface/deck_loader/deck_loader.h b/cockatrice/src/interface/deck_loader/deck_loader.h index 00136e6bb..d356f255d 100644 --- a/cockatrice/src/interface/deck_loader/deck_loader.h +++ b/cockatrice/src/interface/deck_loader/deck_loader.h @@ -7,14 +7,16 @@ #ifndef DECK_LOADER_H #define DECK_LOADER_H +#include "loaded_deck.h" + #include #include #include #include -inline Q_LOGGING_CATEGORY(DeckLoaderLog, "deck_loader") +inline Q_LOGGING_CATEGORY(DeckLoaderLog, "deck_loader"); - class DeckLoader : public QObject +class DeckLoader : public QObject { Q_OBJECT signals: @@ -22,27 +24,6 @@ signals: void loadFinished(bool success); public: - enum FileFormat - { - PlainTextFormat, - CockatriceFormat - }; - - /** - * @brief Information about where the deck was loaded from. - * - * For local decks, the remoteDeckId field will always be -1. - * For remote decks, fileName will be empty and fileFormat will always be CockatriceFormat - */ - struct LoadInfo - { - static constexpr int NON_REMOTE_ID = -1; - - QString fileName = ""; - FileFormat fileFormat = CockatriceFormat; - int remoteDeckId = NON_REMOTE_ID; - }; - /** * Supported file extensions for decklist files */ @@ -61,7 +42,7 @@ public: private: DeckList *deckList; - LoadInfo lastLoadInfo; + LoadedDeck::LoadInfo lastLoadInfo; public: DeckLoader(QObject *parent); @@ -69,29 +50,28 @@ public: DeckLoader(const DeckLoader &) = delete; DeckLoader &operator=(const DeckLoader &) = delete; - const LoadInfo &getLastLoadInfo() const + const LoadedDeck::LoadInfo &getLastLoadInfo() const { return lastLoadInfo; } - void setLastLoadInfo(const LoadInfo &info) + void setLastLoadInfo(const LoadedDeck::LoadInfo &info) { lastLoadInfo = info; } [[nodiscard]] bool hasNotBeenLoaded() const { - return lastLoadInfo.fileName.isEmpty() && lastLoadInfo.remoteDeckId == LoadInfo::NON_REMOTE_ID; + return lastLoadInfo.isEmpty(); } static void clearSetNamesAndNumbers(const DeckList *deckList); - static FileFormat getFormatFromName(const QString &fileName); - bool loadFromFile(const QString &fileName, FileFormat fmt, bool userRequest = false); - bool loadFromFileAsync(const QString &fileName, FileFormat fmt, bool userRequest); + bool loadFromFile(const QString &fileName, DeckFileFormat::Format fmt, bool userRequest = false); + bool loadFromFileAsync(const QString &fileName, DeckFileFormat::Format fmt, bool userRequest); bool loadFromRemote(const QString &nativeString, int remoteDeckId); - bool saveToFile(const QString &fileName, FileFormat fmt); - bool updateLastLoadedTimestamp(const QString &fileName, FileFormat fmt); + bool saveToFile(const QString &fileName, DeckFileFormat::Format fmt); + bool updateLastLoadedTimestamp(const QString &fileName, DeckFileFormat::Format fmt); static QString exportDeckToDecklist(const DeckList *deckList, DecklistWebsite website); diff --git a/cockatrice/src/interface/deck_loader/loaded_deck.cpp b/cockatrice/src/interface/deck_loader/loaded_deck.cpp new file mode 100644 index 000000000..633545718 --- /dev/null +++ b/cockatrice/src/interface/deck_loader/loaded_deck.cpp @@ -0,0 +1,11 @@ +#include "loaded_deck.h" + +bool LoadedDeck::LoadInfo::isEmpty() const +{ + return fileName.isEmpty() && remoteDeckId == NON_REMOTE_ID; +} + +bool LoadedDeck::isEmpty() const +{ + return deckList.isEmpty() && lastLoadInfo.isEmpty(); +} \ No newline at end of file diff --git a/cockatrice/src/interface/deck_loader/loaded_deck.h b/cockatrice/src/interface/deck_loader/loaded_deck.h new file mode 100644 index 000000000..90f3853cf --- /dev/null +++ b/cockatrice/src/interface/deck_loader/loaded_deck.h @@ -0,0 +1,39 @@ +#ifndef COCKATRICE_LOADED_DECK_H +#define COCKATRICE_LOADED_DECK_H + +#include "deck_file_format.h" +#include "libcockatrice/deck_list/deck_list.h" + +#include + +/** + * @brief Represents a deck that was loaded from somewhere. + * Contains the DeckList itself, as well as info about where it was loaded from. + */ +struct LoadedDeck +{ + + /** + * @brief Information about where the deck was loaded from. + * + * For local decks, the remoteDeckId field will always be -1. + * For remote decks, fileName will be empty and fileFormat will always be CockatriceFormat + */ + struct LoadInfo + { + static constexpr int NON_REMOTE_ID = -1; + + QString fileName = ""; + DeckFileFormat::Format fileFormat = DeckFileFormat::Cockatrice; + int remoteDeckId = NON_REMOTE_ID; + + bool isEmpty() const; + }; + + DeckList deckList; ///< The decklist itself + LoadInfo lastLoadInfo; ///< info about where the deck was loaded from + + bool isEmpty() const; +}; + +#endif // COCKATRICE_LOADED_DECK_H diff --git a/cockatrice/src/interface/widgets/general/home_widget.cpp b/cockatrice/src/interface/widgets/general/home_widget.cpp index 88eec230c..7aa6b40c7 100644 --- a/cockatrice/src/interface/widgets/general/home_widget.cpp +++ b/cockatrice/src/interface/widgets/general/home_widget.cpp @@ -23,7 +23,7 @@ HomeWidget::HomeWidget(QWidget *parent, TabSupervisor *_tabSupervisor) backgroundSourceDeck = new DeckLoader(this); backgroundSourceDeck->loadFromFile(SettingsCache::instance().getDeckPath() + "background.cod", - DeckLoader::CockatriceFormat, false); + DeckFileFormat::Cockatrice, false); gradientColors = extractDominantColors(background); @@ -73,7 +73,7 @@ void HomeWidget::initializeBackgroundFromSource() break; case BackgroundSources::DeckFileArt: backgroundSourceDeck->loadFromFile(SettingsCache::instance().getDeckPath() + "background.cod", - DeckLoader::CockatriceFormat, false); + DeckFileFormat::Cockatrice, false); cardChangeTimer->start(SettingsCache::instance().getHomeTabBackgroundShuffleFrequency() * 1000); break; } 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 a03b79e3f..55fa0b95c 100644 --- a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp +++ b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp @@ -380,7 +380,7 @@ void AbstractTabDeckEditor::actOpenRecent(const QString &fileName) */ void AbstractTabDeckEditor::openDeckFromFile(const QString &fileName, DeckOpenLocation deckOpenLocation) { - DeckLoader::FileFormat fmt = DeckLoader::getFormatFromName(fileName); + DeckFileFormat::Format fmt = DeckFileFormat::getFormatFromName(fileName); auto *l = new DeckLoader(this); if (l->loadFromFile(fileName, fmt, true)) { @@ -406,7 +406,7 @@ void AbstractTabDeckEditor::openDeckFromFile(const QString &fileName, DeckOpenLo bool AbstractTabDeckEditor::actSaveDeck() { DeckLoader *const deck = getDeckLoader(); - if (deck->getLastLoadInfo().remoteDeckId != DeckLoader::LoadInfo::NON_REMOTE_ID) { + if (deck->getLastLoadInfo().remoteDeckId != LoadedDeck::LoadInfo::NON_REMOTE_ID) { QString deckString = deck->getDeckList()->writeToString_Native(); if (deckString.length() > MAX_FILE_LENGTH) { QMessageBox::critical(this, tr("Error"), tr("Could not save remote deck")); @@ -452,7 +452,7 @@ bool AbstractTabDeckEditor::actSaveDeckAs() return false; QString fileName = dialog.selectedFiles().at(0); - DeckLoader::FileFormat fmt = DeckLoader::getFormatFromName(fileName); + DeckFileFormat::Format fmt = DeckFileFormat::getFormatFromName(fileName); if (!getDeckLoader()->saveToFile(fileName, fmt)) { QMessageBox::critical( diff --git a/cockatrice/src/interface/widgets/tabs/tab_deck_storage.cpp b/cockatrice/src/interface/widgets/tabs/tab_deck_storage.cpp index 854990e19..a54c16258 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_deck_storage.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_deck_storage.cpp @@ -242,7 +242,7 @@ void TabDeckStorage::actOpenLocalDeck() QString filePath = localDirModel->filePath(curLeft); auto deckLoader = new DeckLoader(this); - if (!deckLoader->loadFromFile(filePath, DeckLoader::CockatriceFormat, true)) + if (!deckLoader->loadFromFile(filePath, DeckFileFormat::Cockatrice, true)) continue; emit openDeckEditor(deckLoader); @@ -308,7 +308,7 @@ void TabDeckStorage::uploadDeck(const QString &filePath, const QString &targetPa QFileInfo deckFileInfo(deckFile); DeckLoader deck(this); - if (!deck.loadFromFile(filePath, DeckLoader::CockatriceFormat)) { + if (!deck.loadFromFile(filePath, DeckFileFormat::Cockatrice)) { QMessageBox::critical(this, tr("Error"), tr("Invalid deck file")); return; } @@ -493,7 +493,7 @@ void TabDeckStorage::downloadFinished(const Response &r, QString filePath = extraData.toString(); DeckLoader deck(this, new DeckList(QString::fromStdString(resp.deck()))); - deck.saveToFile(filePath, DeckLoader::CockatriceFormat); + deck.saveToFile(filePath, DeckFileFormat::Cockatrice); } void TabDeckStorage::actNewFolder() 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 975c011dc..69c80bb35 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 @@ -25,7 +25,7 @@ TabDeckStorageVisual::TabDeckStorageVisual(TabSupervisor *_tabSupervisor) void TabDeckStorageVisual::actOpenLocalDeck(const QString &filePath) { auto deckLoader = new DeckLoader(this); - if (!deckLoader->loadFromFile(filePath, DeckLoader::getFormatFromName(filePath), true)) { + if (!deckLoader->loadFromFile(filePath, DeckFileFormat::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/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 fce0916bb..d3858a135 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 @@ -79,7 +79,7 @@ static QStringList findAllKnownTags() QStringList knownTags; auto loader = DeckLoader(nullptr); for (const QString &file : allFiles) { - loader.loadFromFile(file, DeckLoader::getFormatFromName(file), false); + loader.loadFromFile(file, DeckFileFormat::getFormatFromName(file), false); QStringList tags = loader.getDeckList()->getTags(); knownTags.append(tags); knownTags.removeDuplicates(); @@ -136,7 +136,7 @@ static void convertFileToCockatriceFormat(DeckPreviewWidget *deckPreviewWidget) */ bool DeckPreviewDeckTagsDisplayWidget::promptFileConversionIfRequired(DeckPreviewWidget *deckPreviewWidget) { - if (DeckLoader::getFormatFromName(deckPreviewWidget->filePath) == DeckLoader::CockatriceFormat) { + if (DeckFileFormat::getFormatFromName(deckPreviewWidget->filePath) == DeckFileFormat::Cockatrice) { return true; } 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 bf915bbea..1db0feb63 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 @@ -32,7 +32,7 @@ DeckPreviewWidget::DeckPreviewWidget(QWidget *_parent, many deck loads have finished already and if we've loaded all decks and THEN load all the tags at once. */ connect(deckLoader, &DeckLoader::loadFinished, visualDeckStorageWidget->tagFilterWidget, &VisualDeckStorageTagFilterWidget::refreshTags); - deckLoader->loadFromFileAsync(filePath, DeckLoader::getFormatFromName(filePath), false); + deckLoader->loadFromFileAsync(filePath, DeckFileFormat::getFormatFromName(filePath), false); bannerCardDisplayWidget = new DeckPreviewCardPictureWidget(this, false, visualDeckStorageWidget->deckPreviewSelectionAnimationEnabled); @@ -288,7 +288,7 @@ void DeckPreviewWidget::setBannerCard(int /* changedIndex */) auto [name, id] = bannerCardComboBox->currentData().value>(); CardRef cardRef = {name, id}; deckLoader->getDeckList()->setBannerCard(cardRef); - deckLoader->saveToFile(filePath, DeckLoader::getFormatFromName(filePath)); + deckLoader->saveToFile(filePath, DeckFileFormat::getFormatFromName(filePath)); bannerCardDisplayWidget->setCard(CardDatabaseManager::query()->getCard(cardRef)); } @@ -311,7 +311,7 @@ void DeckPreviewWidget::imageDoubleClickedEvent(QMouseEvent *event, DeckPreviewC void DeckPreviewWidget::setTags(const QStringList &tags) { deckLoader->getDeckList()->setTags(tags); - deckLoader->saveToFile(filePath, DeckLoader::CockatriceFormat); + deckLoader->saveToFile(filePath, DeckFileFormat::Cockatrice); } QMenu *DeckPreviewWidget::createRightClickMenu() @@ -386,7 +386,7 @@ void DeckPreviewWidget::actRenameDeck() // write change deckLoader->getDeckList()->setName(newName); - deckLoader->saveToFile(filePath, DeckLoader::getFormatFromName(filePath)); + deckLoader->saveToFile(filePath, DeckFileFormat::getFormatFromName(filePath)); // update VDS refreshBannerCardText(); @@ -416,7 +416,7 @@ void DeckPreviewWidget::actRenameFile() return; } - DeckLoader::LoadInfo lastLoadInfo = deckLoader->getLastLoadInfo(); + LoadedDeck::LoadInfo lastLoadInfo = deckLoader->getLastLoadInfo(); lastLoadInfo.fileName = newFilePath; deckLoader->setLastLoadInfo(lastLoadInfo); From 2b690f8c87038031dcc473fda2165bbfde9275c8 Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Mon, 8 Dec 2025 00:47:24 -0800 Subject: [PATCH 36/40] [DeckLoader] Extract cardNode functions to own file (#6408) * [DeckLoader] Extract cardNode functions to own file * update usages --- cockatrice/CMakeLists.txt | 1 + .../parsers/interface_json_deck_parser.h | 6 +- .../deck_loader/card_node_function.cpp | 40 ++++++++ .../deck_loader/card_node_function.h | 39 ++++++++ .../src/interface/deck_loader/deck_loader.cpp | 98 ------------------- .../src/interface/deck_loader/deck_loader.h | 5 - .../dialogs/dlg_load_deck_from_clipboard.cpp | 5 +- .../dialogs/dlg_load_deck_from_website.cpp | 2 +- .../dialogs/dlg_select_set_for_cards.cpp | 7 +- ...idekt_api_response_deck_display_widget.cpp | 3 +- 10 files changed, 94 insertions(+), 112 deletions(-) create mode 100644 cockatrice/src/interface/deck_loader/card_node_function.cpp create mode 100644 cockatrice/src/interface/deck_loader/card_node_function.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index f531bc2c8..dec1b3d62 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -19,6 +19,7 @@ set(cockatrice_SOURCES src/client/settings/card_counter_settings.cpp src/client/settings/shortcut_treeview.cpp src/client/settings/shortcuts_settings.cpp + src/interface/deck_loader/card_node_function.cpp src/interface/deck_loader/deck_file_format.cpp src/interface/deck_loader/deck_loader.cpp src/interface/deck_loader/loaded_deck.cpp 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 8ac05a84b..e0fe4967a 100644 --- a/cockatrice/src/client/network/parsers/interface_json_deck_parser.h +++ b/cockatrice/src/client/network/parsers/interface_json_deck_parser.h @@ -6,6 +6,8 @@ #ifndef INTERFACE_JSON_DECK_PARSER_H #define INTERFACE_JSON_DECK_PARSER_H + +#include "../../../interface/deck_loader/card_node_function.h" #include "../../../interface/deck_loader/deck_loader.h" #include @@ -48,7 +50,7 @@ public: } loader->getDeckList()->loadFromStream_Plain(outStream, false); - DeckLoader::resolveSetNameAndNumberToProviderID(loader->getDeckList()); + loader->getDeckList()->forEachCard(CardNodeFunction::ResolveProviderId()); return loader; } @@ -95,7 +97,7 @@ public: } loader->getDeckList()->loadFromStream_Plain(outStream, false); - DeckLoader::resolveSetNameAndNumberToProviderID(loader->getDeckList()); + loader->getDeckList()->forEachCard(CardNodeFunction::ResolveProviderId()); QJsonObject commandersObj = obj.value("commanders").toObject(); if (!commandersObj.isEmpty()) { diff --git a/cockatrice/src/interface/deck_loader/card_node_function.cpp b/cockatrice/src/interface/deck_loader/card_node_function.cpp new file mode 100644 index 000000000..9441fe428 --- /dev/null +++ b/cockatrice/src/interface/deck_loader/card_node_function.cpp @@ -0,0 +1,40 @@ +#include "card_node_function.h" + +#include +#include +#include + +void CardNodeFunction::SetProviderIdToPreferred::operator()(const InnerDecklistNode *node, DecklistCardNode *card) const +{ + Q_UNUSED(node); + PrintingInfo preferredPrinting = CardDatabaseManager::query()->getPreferredPrinting(card->getName()); + QString providerId = preferredPrinting.getUuid(); + QString setShortName = preferredPrinting.getSet()->getShortName(); + QString collectorNumber = preferredPrinting.getProperty("num"); + + card->setCardProviderId(providerId); + card->setCardCollectorNumber(collectorNumber); + card->setCardSetShortName(setShortName); +} + +void CardNodeFunction::ClearPrintingData::operator()(const InnerDecklistNode *node, DecklistCardNode *card) const +{ + Q_UNUSED(node); + card->setCardSetShortName(nullptr); + card->setCardCollectorNumber(nullptr); + card->setCardProviderId(nullptr); +} + +void CardNodeFunction::ResolveProviderId::operator()(const InnerDecklistNode *node, DecklistCardNode *card) const +{ + Q_UNUSED(node); + // Retrieve the providerId based on setName and collectorNumber + QString providerId = + CardDatabaseManager::getInstance() + ->query() + ->getSpecificPrinting(card->getName(), card->getCardSetShortName(), card->getCardCollectorNumber()) + .getUuid(); + + // Set the providerId on the card + card->setCardProviderId(providerId); +} \ No newline at end of file diff --git a/cockatrice/src/interface/deck_loader/card_node_function.h b/cockatrice/src/interface/deck_loader/card_node_function.h new file mode 100644 index 000000000..398dc0c0e --- /dev/null +++ b/cockatrice/src/interface/deck_loader/card_node_function.h @@ -0,0 +1,39 @@ +#ifndef COCKATRICE_DECK_FUNCTION_H +#define COCKATRICE_DECK_FUNCTION_H + +class DecklistCardNode; +class InnerDecklistNode; + +/** + * Functions to be used with DeckList::forEachCard + */ +namespace CardNodeFunction +{ + +/** + * @brief Sets the providerId of the card to the preferred printing. + */ +struct SetProviderIdToPreferred +{ + void operator()(const InnerDecklistNode *node, DecklistCardNode *card) const; +}; + +/** + * @brief Clears all fields on the card related to the printing + */ +struct ClearPrintingData +{ + void operator()(const InnerDecklistNode *node, DecklistCardNode *card) const; +}; + +/** + * @brief Sets the providerId of the card based on its set name and collector number. + */ +struct ResolveProviderId +{ + void operator()(const InnerDecklistNode *node, DecklistCardNode *card) const; +}; + +} // namespace CardNodeFunction + +#endif // COCKATRICE_DECK_FUNCTION_H diff --git a/cockatrice/src/interface/deck_loader/deck_loader.cpp b/cockatrice/src/interface/deck_loader/deck_loader.cpp index e3d1ce965..d866b684b 100644 --- a/cockatrice/src/interface/deck_loader/deck_loader.cpp +++ b/cockatrice/src/interface/deck_loader/deck_loader.cpp @@ -316,104 +316,6 @@ QString DeckLoader::exportDeckToDecklist(const DeckList *deckList, DecklistWebsi return deckString; } -// This struct is here to support the forEachCard function call, defined in decklist. -// It requires a function to be called for each card, and it will set the providerId to the preferred printing. -struct SetProviderIdToPreferred -{ - // Main operator for struct, allowing the foreachcard to work. - SetProviderIdToPreferred() - { - } - - void operator()(const InnerDecklistNode *node, DecklistCardNode *card) const - { - Q_UNUSED(node); - PrintingInfo preferredPrinting = CardDatabaseManager::query()->getPreferredPrinting(card->getName()); - QString providerId = preferredPrinting.getUuid(); - QString setShortName = preferredPrinting.getSet()->getShortName(); - QString collectorNumber = preferredPrinting.getProperty("num"); - - card->setCardProviderId(providerId); - card->setCardCollectorNumber(collectorNumber); - card->setCardSetShortName(setShortName); - } -}; - -/** - * This function iterates through each card in the decklist and sets the providerId - * on each card based on its set name and collector number. - * - * @param deckList The decklist to modify - */ -void DeckLoader::setProviderIdToPreferredPrinting(const DeckList *deckList) -{ - // Set up the struct to call. - SetProviderIdToPreferred setProviderIdToPreferred; - - // Call the forEachCard method for each card in the deck - deckList->forEachCard(setProviderIdToPreferred); -} - -/** - * Sets the providerId on each card in the decklist based on its set name and collector number. - * - * @param deckList The decklist to modify - */ -void DeckLoader::resolveSetNameAndNumberToProviderID(const DeckList *deckList) -{ - auto setProviderId = [](const auto node, const auto card) { - Q_UNUSED(node); - // Retrieve the providerId based on setName and collectorNumber - QString providerId = - CardDatabaseManager::getInstance() - ->query() - ->getSpecificPrinting(card->getName(), card->getCardSetShortName(), card->getCardCollectorNumber()) - .getUuid(); - - // Set the providerId on the card - card->setCardProviderId(providerId); - }; - - deckList->forEachCard(setProviderId); -} - -// This struct is here to support the forEachCard function call, defined in decklist. -// It requires a function to be called for each card, and it will set the providerId. -struct ClearSetNameNumberAndProviderId -{ - // Main operator for struct, allowing the foreachcard to work. - ClearSetNameNumberAndProviderId() - { - } - - void operator()(const InnerDecklistNode *node, DecklistCardNode *card) const - { - Q_UNUSED(node); - // Set the providerId on the card - card->setCardSetShortName(nullptr); - card->setCardCollectorNumber(nullptr); - card->setCardProviderId(nullptr); - } -}; - -/** - * Clears the set name and numbers on each card in the decklist. - * - * @param deckList The decklist to modify - */ -void DeckLoader::clearSetNamesAndNumbers(const DeckList *deckList) -{ - auto clearSetNameAndNumber = [](const auto node, auto card) { - Q_UNUSED(node) - // Set the providerId on the card - card->setCardSetShortName(nullptr); - card->setCardCollectorNumber(nullptr); - card->setCardProviderId(nullptr); - }; - - deckList->forEachCard(clearSetNameAndNumber); -} - void DeckLoader::saveToClipboard(const DeckList *deckList, bool addComments, bool addSetNameAndNumber) { QString buffer; diff --git a/cockatrice/src/interface/deck_loader/deck_loader.h b/cockatrice/src/interface/deck_loader/deck_loader.h index d356f255d..474eee149 100644 --- a/cockatrice/src/interface/deck_loader/deck_loader.h +++ b/cockatrice/src/interface/deck_loader/deck_loader.h @@ -65,8 +65,6 @@ public: return lastLoadInfo.isEmpty(); } - static void clearSetNamesAndNumbers(const DeckList *deckList); - bool loadFromFile(const QString &fileName, DeckFileFormat::Format fmt, bool userRequest = false); bool loadFromFileAsync(const QString &fileName, DeckFileFormat::Format fmt, bool userRequest); bool loadFromRemote(const QString &nativeString, int remoteDeckId); @@ -75,9 +73,6 @@ public: static QString exportDeckToDecklist(const DeckList *deckList, DecklistWebsite website); - static void setProviderIdToPreferredPrinting(const DeckList *deckList); - static void resolveSetNameAndNumberToProviderID(const DeckList *deckList); - static void saveToClipboard(const DeckList *deckList, bool addComments = true, bool addSetNameAndNumber = true); static bool saveToStream_Plain(QTextStream &out, const DeckList *deckList, 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 2a276479f..952364e37 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,6 +1,7 @@ #include "dlg_load_deck_from_clipboard.h" #include "../../../client/settings/cache_settings.h" +#include "../../deck_loader/card_node_function.h" #include "../../deck_loader/deck_loader.h" #include "dlg_settings.h" @@ -82,9 +83,9 @@ bool AbstractDlgDeckTextEdit::loadIntoDeck(DeckLoader *deckLoader) const if (deckLoader->getDeckList()->loadFromStream_Plain(stream, true)) { if (loadSetNameAndNumberCheckBox->isChecked()) { - DeckLoader::resolveSetNameAndNumberToProviderID(deckLoader->getDeckList()); + deckLoader->getDeckList()->forEachCard(CardNodeFunction::ResolveProviderId()); } else { - DeckLoader::clearSetNamesAndNumbers(deckLoader->getDeckList()); + deckLoader->getDeckList()->forEachCard(CardNodeFunction::ClearPrintingData()); } return true; } 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 f29984ab0..20eb00083 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 @@ -98,7 +98,7 @@ void DlgLoadDeckFromWebsite::accept() DeckLoader *loader = new DeckLoader(this); QTextStream stream(&deckText); loader->getDeckList()->loadFromStream_Plain(stream, false); - DeckLoader::resolveSetNameAndNumberToProviderID(loader->getDeckList()); + loader->getDeckList()->forEachCard(CardNodeFunction::ResolveProviderId()); deck = loader; QDialog::accept(); 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 905ac5db0..5b6eff923 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/card_node_function.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" @@ -177,7 +178,7 @@ void DlgSelectSetForCards::actOK() void DlgSelectSetForCards::actClear() { emit deckAboutToBeModified(tr("Cleared all printing information.")); - DeckLoader::clearSetNamesAndNumbers(model->getDeckList()); + model->getDeckList()->forEachCard(CardNodeFunction::ClearPrintingData()); emit deckModified(); accept(); } @@ -185,8 +186,8 @@ void DlgSelectSetForCards::actClear() void DlgSelectSetForCards::actSetAllToPreferred() { emit deckAboutToBeModified(tr("Set all printings to preferred.")); - DeckLoader::clearSetNamesAndNumbers(model->getDeckList()); - DeckLoader::setProviderIdToPreferredPrinting(model->getDeckList()); + model->getDeckList()->forEachCard(CardNodeFunction::ClearPrintingData()); + model->getDeckList()->forEachCard(CardNodeFunction::SetProviderIdToPreferred()); emit deckModified(); accept(); } diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_display_widget.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_display_widget.cpp index 33ee67a1f..63d732c9a 100644 --- a/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_display_widget.cpp +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_display_widget.cpp @@ -1,5 +1,6 @@ #include "archidekt_api_response_deck_display_widget.h" +#include "../../../../../deck_loader/card_node_function.h" #include "../../../../../deck_loader/deck_loader.h" #include "../../../../cards/card_info_picture_with_text_overlay_widget.h" #include "../../../../cards/card_size_widget.h" @@ -68,7 +69,7 @@ ArchidektApiResponseDeckDisplayWidget::ArchidektApiResponseDeckDisplayWidget(QWi connect(model, &DeckListModel::modelReset, this, &ArchidektApiResponseDeckDisplayWidget::decklistModelReset); model->getDeckList()->loadFromStream_Plain(deckStream, false); - DeckLoader::resolveSetNameAndNumberToProviderID(model->getDeckList()); + model->getDeckList()->forEachCard(CardNodeFunction::ResolveProviderId()); model->rebuildTree(); From da703445479ce07a8eea5c7bf4fd4d01a4a666ef Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Fri, 12 Dec 2025 03:57:18 +0100 Subject: [PATCH 37/40] [VDD] Implement ExactMatch Name filter (#6409) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [VDD] Implement ExactMatch Name filter Took 7 minutes Took 4 minutes * Update cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.cpp Co-authored-by: RickyRister <42636155+RickyRister@users.noreply.github.com> --------- Co-authored-by: Lukas Brübach Co-authored-by: RickyRister <42636155+RickyRister@users.noreply.github.com> --- .../visual_database_display_name_filter_widget.cpp | 8 ++++---- .../libcockatrice/filters/filter_card.cpp | 2 ++ libcockatrice_filters/libcockatrice/filters/filter_card.h | 1 + .../libcockatrice/filters/filter_tree.cpp | 7 +++++++ libcockatrice_filters/libcockatrice/filters/filter_tree.h | 1 + 5 files changed, 15 insertions(+), 4 deletions(-) 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 64eed8b16..28c4e5ab9 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 @@ -51,7 +51,7 @@ VisualDatabaseDisplayNameFilterWidget::VisualDatabaseDisplayNameFilterWidget(QWi void VisualDatabaseDisplayNameFilterWidget::retranslateUi() { - searchBox->setPlaceholderText(tr("Filter by name...")); + searchBox->setPlaceholderText(tr("Filter by name... (Exact match)")); loadFromDeckButton->setText(tr("Load from Deck")); loadFromDeckButton->setToolTip(tr("Apply all card names in currently loaded deck as exact match name filters")); loadFromClipboardButton->setText(tr("Load from Clipboard")); @@ -123,14 +123,14 @@ void VisualDatabaseDisplayNameFilterWidget::updateFilterModel() { // Clear existing name filters emit filterModel->layoutAboutToBeChanged(); - filterModel->clearFiltersOfType(CardFilter::Attr::AttrName); + filterModel->clearFiltersOfType(CardFilter::Attr::AttrNameExact); filterModel->blockSignals(true); filterModel->filterTree()->blockSignals(true); for (const auto &name : activeFilters.keys()) { QString nameString = name; - filterModel->addFilter(new CardFilter(nameString, CardFilter::Type::TypeOr, CardFilter::Attr::AttrName)); + filterModel->addFilter(new CardFilter(nameString, CardFilter::Type::TypeOr, CardFilter::Attr::AttrNameExact)); } filterModel->blockSignals(false); @@ -146,7 +146,7 @@ void VisualDatabaseDisplayNameFilterWidget::updateFilterModel() void VisualDatabaseDisplayNameFilterWidget::syncWithFilterModel() { QStringList currentFilters; - for (const auto &filter : filterModel->getFiltersOfType(CardFilter::Attr::AttrName)) { + for (const auto &filter : filterModel->getFiltersOfType(CardFilter::Attr::AttrNameExact)) { if (filter->type() == CardFilter::Type::TypeOr) { currentFilters.append(filter->term()); } diff --git a/libcockatrice_filters/libcockatrice/filters/filter_card.cpp b/libcockatrice_filters/libcockatrice/filters/filter_card.cpp index d49a1b9cb..5fdce7ae0 100644 --- a/libcockatrice_filters/libcockatrice/filters/filter_card.cpp +++ b/libcockatrice_filters/libcockatrice/filters/filter_card.cpp @@ -60,6 +60,8 @@ const QString CardFilter::attrName(Attr a) switch (a) { case AttrName: return tr("Name"); + case AttrNameExact: + return tr("Name (Exact)"); case AttrType: return tr("Type"); case AttrColor: diff --git a/libcockatrice_filters/libcockatrice/filters/filter_card.h b/libcockatrice_filters/libcockatrice/filters/filter_card.h index 4392a4630..732e43a09 100644 --- a/libcockatrice_filters/libcockatrice/filters/filter_card.h +++ b/libcockatrice_filters/libcockatrice/filters/filter_card.h @@ -33,6 +33,7 @@ public: AttrLoyalty, AttrManaCost, AttrName, + AttrNameExact, AttrPow, AttrRarity, AttrSet, diff --git a/libcockatrice_filters/libcockatrice/filters/filter_tree.cpp b/libcockatrice_filters/libcockatrice/filters/filter_tree.cpp index 89b772b8e..afb2d8563 100644 --- a/libcockatrice_filters/libcockatrice/filters/filter_tree.cpp +++ b/libcockatrice_filters/libcockatrice/filters/filter_tree.cpp @@ -153,6 +153,11 @@ bool FilterItem::acceptName(const CardInfoPtr info) const return info->getName().contains(term, Qt::CaseInsensitive); } +bool FilterItem::acceptNameExact(const CardInfoPtr info) const +{ + return info->getName() == term; +} + bool FilterItem::acceptType(const CardInfoPtr info) const { return info->getCardType().contains(term, Qt::CaseInsensitive); @@ -401,6 +406,8 @@ bool FilterItem::acceptCardAttr(const CardInfoPtr info, CardFilter::Attr attr) c switch (attr) { case CardFilter::AttrName: return acceptName(info); + case CardFilter::AttrNameExact: + return acceptNameExact(info); case CardFilter::AttrType: return acceptType(info); case CardFilter::AttrColor: diff --git a/libcockatrice_filters/libcockatrice/filters/filter_tree.h b/libcockatrice_filters/libcockatrice/filters/filter_tree.h index af91d2dbf..75d4241a5 100644 --- a/libcockatrice_filters/libcockatrice/filters/filter_tree.h +++ b/libcockatrice_filters/libcockatrice/filters/filter_tree.h @@ -203,6 +203,7 @@ public: } [[nodiscard]] bool acceptName(CardInfoPtr info) const; + [[nodiscard]] bool acceptNameExact(CardInfoPtr info) const; [[nodiscard]] bool acceptType(CardInfoPtr info) const; [[nodiscard]] bool acceptMainType(CardInfoPtr info) const; [[nodiscard]] bool acceptSubType(CardInfoPtr info) const; From a390c8ada7cded393de291569406c4b96924b8e4 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Fri, 12 Dec 2025 11:29:18 +0100 Subject: [PATCH 38/40] [NetworkManager] Set Version string as user agent (#6411) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [NetworkManager] Set Version string as user agent Took 13 minutes * Update in oracle. Took 14 minutes --------- Co-authored-by: Lukas Brübach --- .../client/network/interfaces/deck_stats_interface.cpp | 2 ++ .../client/network/interfaces/tapped_out_interface.cpp | 2 ++ .../update/card_spoiler/spoiler_background_updater.cpp | 5 ++++- .../card_picture_loader/card_picture_loader_worker.cpp | 2 ++ .../widgets/dialogs/dlg_load_deck_from_website.cpp | 2 ++ .../archidekt_api_response_deck_entry_display_widget.cpp | 2 ++ .../widgets/tabs/api/archidekt/tab_archidekt.cpp | 4 ++++ .../interface/widgets/tabs/api/edhrec/tab_edhrec_main.cpp | 7 ++++++- oracle/src/pages.cpp | 8 ++++++-- 9 files changed, 30 insertions(+), 4 deletions(-) diff --git a/cockatrice/src/client/network/interfaces/deck_stats_interface.cpp b/cockatrice/src/client/network/interfaces/deck_stats_interface.cpp index 6c295beb9..5e9b874d0 100644 --- a/cockatrice/src/client/network/interfaces/deck_stats_interface.cpp +++ b/cockatrice/src/client/network/interfaces/deck_stats_interface.cpp @@ -8,6 +8,7 @@ #include #include #include +#include DeckStatsInterface::DeckStatsInterface(CardDatabase &_cardDatabase, QObject *parent) : QObject(parent), cardDatabase(_cardDatabase) @@ -62,6 +63,7 @@ void DeckStatsInterface::analyzeDeck(DeckList *deck) QNetworkRequest request(QUrl("https://deckstats.net/index.php")); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); + request.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING)); manager->post(request, data); } diff --git a/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp b/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp index 4bfeba7b1..137c7728c 100644 --- a/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp +++ b/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp @@ -8,6 +8,7 @@ #include #include #include +#include TappedOutInterface::TappedOutInterface(CardDatabase &_cardDatabase, QObject *parent) : QObject(parent), cardDatabase(_cardDatabase) @@ -87,6 +88,7 @@ void TappedOutInterface::analyzeDeck(DeckList *deck) QNetworkRequest request(QUrl("https://tappedout.net/mtg-decks/paste/")); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); + request.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING)); manager->post(request, data); } 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 f6f851037..7194c46e5 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 @@ -14,6 +14,7 @@ #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" @@ -39,7 +40,9 @@ void SpoilerBackgroundUpdater::startSpoilerDownloadProcess(QString url, bool sav void SpoilerBackgroundUpdater::downloadFromURL(QUrl url, bool saveResults) { auto *nam = new QNetworkAccessManager(this); - QNetworkReply *reply = nam->get(QNetworkRequest(url)); + auto request = QNetworkRequest(url); + request.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING)); + QNetworkReply *reply = nam->get(request); if (saveResults) { // This will write out to the file (used for spoiler.xml) 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 30c979cb5..77fddc9de 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 @@ -10,6 +10,7 @@ #include #include #include +#include static constexpr int MAX_REQUESTS_PER_SEC = 10; @@ -86,6 +87,7 @@ QNetworkReply *CardPictureLoaderWorker::makeRequest(const QUrl &url, CardPicture } QNetworkRequest req(url); + req.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING)); if (!picDownload) { req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysCache); } 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 20eb00083..2b63af1a4 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 @@ -8,6 +8,7 @@ #include #include #include +#include DlgLoadDeckFromWebsite::DlgLoadDeckFromWebsite(QWidget *parent) : QDialog(parent) { @@ -67,6 +68,7 @@ void DlgLoadDeckFromWebsite::accept() } QNetworkRequest request(QUrl(info.fullUrl)); + request.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING)); QNetworkReply *reply = nam->get(request); QEventLoop loop; diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.cpp index 1b633c4d3..7a838d1ff 100644 --- a/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.cpp +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #define ARCHIDEKT_DEFAULT_IMAGE "https://storage.googleapis.com/topdekt-user/images/archidekt_deck_card_shadow.jpg" @@ -82,6 +83,7 @@ ArchidektApiResponseDeckEntryDisplayWidget::ArchidektApiResponseDeckEntryDisplay imageUrl = response.getFeatured().isEmpty() ? QUrl(ARCHIDEKT_DEFAULT_IMAGE) : QUrl(response.getFeatured()); QNetworkRequest req(imageUrl); + req.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING)); QNetworkReply *reply = imageNetworkManager->get(req); // tag the reply with "this" so we know it belongs to us later diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp index 7f04987c1..1376efd47 100644 --- a/cockatrice/src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp @@ -22,6 +22,7 @@ #include #include #include +#include TabArchidekt::TabArchidekt(TabSupervisor *_tabSupervisor) : Tab(_tabSupervisor) { @@ -426,18 +427,21 @@ void TabArchidekt::doSearchImmediate() { QString url = buildSearchUrl(); QNetworkRequest req{QUrl(url)}; + req.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING)); networkManager->get(req); } void TabArchidekt::actNavigatePage(QString url) { QNetworkRequest request{QUrl(url)}; + request.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING)); networkManager->get(request); } void TabArchidekt::getTopDecks() { QNetworkRequest request{QUrl(buildSearchUrl())}; + request.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING)); networkManager->get(request); } diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.cpp b/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.cpp index 06ce88f06..92163997c 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.cpp +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.cpp @@ -25,6 +25,7 @@ #include #include #include +#include static bool canBeCommander(const CardInfoPtr &cardInfo) { @@ -166,6 +167,7 @@ void TabEdhRecMain::setCard(CardInfoPtr _cardToQuery, bool isCommander) } QNetworkRequest request{QUrl(url)}; + request.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING)); networkManager->get(request); } @@ -173,6 +175,7 @@ void TabEdhRecMain::setCard(CardInfoPtr _cardToQuery, bool isCommander) void TabEdhRecMain::actNavigatePage(QString url) { QNetworkRequest request{QUrl("https://json.edhrec.com/pages" + url + ".json")}; + request.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING)); networkManager->get(request); } @@ -180,6 +183,7 @@ void TabEdhRecMain::actNavigatePage(QString url) void TabEdhRecMain::getTopCards() { QNetworkRequest request{QUrl("https://json.edhrec.com/pages/top/year.json")}; + request.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING)); networkManager->get(request); } @@ -187,6 +191,7 @@ void TabEdhRecMain::getTopCards() void TabEdhRecMain::getTopCommanders() { QNetworkRequest request{QUrl("https://json.edhrec.com/pages/commanders/year.json")}; + request.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING)); networkManager->get(request); } @@ -194,7 +199,7 @@ void TabEdhRecMain::getTopCommanders() void TabEdhRecMain::getTopTags() { QNetworkRequest request{QUrl("https://json.edhrec.com/pages/tags.json")}; - + request.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING)); networkManager->get(request); } diff --git a/oracle/src/pages.cpp b/oracle/src/pages.cpp index 46edf1cf8..7629a291b 100644 --- a/oracle/src/pages.cpp +++ b/oracle/src/pages.cpp @@ -302,7 +302,9 @@ void LoadSetsPage::downloadSetsFile(const QUrl &url) const auto urlString = url.toString(); if (urlString == ALLSETS_URL || urlString == ALLSETS_URL_FALLBACK) { const auto versionUrl = QUrl::fromUserInput(MTGJSON_VERSION_URL); - auto *versionReply = wizard()->nam->get(QNetworkRequest(versionUrl)); + QNetworkRequest request = QNetworkRequest(versionUrl); + request.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING)); + auto *versionReply = wizard()->nam->get(request); connect(versionReply, &QNetworkReply::finished, [this, versionReply]() { if (versionReply->error() == QNetworkReply::NoError) { auto data = versionReply->readAll(); @@ -326,7 +328,9 @@ void LoadSetsPage::downloadSetsFile(const QUrl &url) wizard()->setCardSourceUrl(url.toString()); - auto *reply = wizard()->nam->get(QNetworkRequest(url)); + QNetworkRequest request = QNetworkRequest(url); + request.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING)); + auto *reply = wizard()->nam->get(request); connect(reply, &QNetworkReply::finished, this, &LoadSetsPage::actDownloadFinishedSetsFile); connect(reply, &QNetworkReply::downloadProgress, this, &LoadSetsPage::actDownloadProgressSetsFile); From 2e2682aad47909d2c374bc4cf283a5b956635d51 Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Fri, 12 Dec 2025 12:37:44 -0800 Subject: [PATCH 39/40] [DeckList] Refactor and cleanup methods that iterate over nodes (#6407) * remove helpers * create getZoneNodes method * replace direct calls to getRoot and forEachCard * remove more non-const uses of forEachCard * make node getter return const lists * one more usage * address comment * address comment again * fix hash * fix hashes (for real this time) --- cockatrice/src/filters/deck_filter_string.cpp | 5 +- cockatrice/src/game/deckview/deck_view.cpp | 5 +- .../src/game/player/menu/utility_menu.cpp | 13 +- .../src/interface/deck_loader/deck_loader.cpp | 49 ++++---- .../src/interface/deck_loader/deck_loader.h | 2 +- .../deck_editor_deck_dock_widget.cpp | 2 +- .../dialogs/dlg_select_set_for_cards.cpp | 6 +- .../printing_selector/card_amount_widget.cpp | 2 +- ...al_database_display_name_filter_widget.cpp | 2 +- .../visual_deck_editor_sample_hand_widget.cpp | 2 +- .../deck_preview/deck_preview_widget.cpp | 2 +- .../libcockatrice/deck_list/deck_list.cpp | 113 ++++++++---------- .../libcockatrice/deck_list/deck_list.h | 5 +- .../models/deck_list/deck_list_model.cpp | 89 ++++---------- .../models/deck_list/deck_list_model.h | 2 +- .../server/remote/game/server_player.cpp | 28 ++--- 16 files changed, 125 insertions(+), 202 deletions(-) diff --git a/cockatrice/src/filters/deck_filter_string.cpp b/cockatrice/src/filters/deck_filter_string.cpp index 52b6a38d1..dfc54afe0 100644 --- a/cockatrice/src/filters/deck_filter_string.cpp +++ b/cockatrice/src/filters/deck_filter_string.cpp @@ -118,12 +118,13 @@ static void setupParserRules() return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) -> bool { int count = 0; - deck->deckLoader->getDeckList()->forEachCard([&](InnerDecklistNode *, const DecklistCardNode *node) { + auto cardNodes = deck->deckLoader->getDeckList()->getCardNodes(); + for (auto node : cardNodes) { auto cardInfoPtr = CardDatabaseManager::query()->getCardInfo(node->getName()); if (!cardInfoPtr.isNull() && cardFilter.check(cardInfoPtr)) { count += node->getNumber(); } - }); + } return numberMatcher(count); }; }; diff --git a/cockatrice/src/game/deckview/deck_view.cpp b/cockatrice/src/game/deckview/deck_view.cpp index edef3fad4..383545cf3 100644 --- a/cockatrice/src/game/deckview/deck_view.cpp +++ b/cockatrice/src/game/deckview/deck_view.cpp @@ -343,10 +343,7 @@ void DeckViewScene::rebuildTree() if (!deck) return; - InnerDecklistNode *listRoot = deck->getRoot(); - for (int i = 0; i < listRoot->size(); i++) { - auto *currentZone = dynamic_cast(listRoot->at(i)); - + for (auto *currentZone : deck->getZoneNodes()) { DeckViewCardContainer *container = cardContainers.value(currentZone->getName(), 0); if (!container) { container = new DeckViewCardContainer(currentZone->getName()); diff --git a/cockatrice/src/game/player/menu/utility_menu.cpp b/cockatrice/src/game/player/menu/utility_menu.cpp index a3117abf8..ab14d629a 100644 --- a/cockatrice/src/game/player/menu/utility_menu.cpp +++ b/cockatrice/src/game/player/menu/utility_menu.cpp @@ -5,6 +5,7 @@ #include "../player_actions.h" #include "player_menu.h" +#include #include UtilityMenu::UtilityMenu(Player *_player, QMenu *playerMenu) : QMenu(playerMenu), player(_player) @@ -65,15 +66,13 @@ void UtilityMenu::populatePredefinedTokensMenu() return; } - InnerDecklistNode *tokenZone = - dynamic_cast(_deck->getDeckList()->getRoot()->findChild(DECK_ZONE_TOKENS)); + auto tokenCardNodes = _deck->getDeckList()->getCardNodes({DECK_ZONE_TOKENS}); - if (tokenZone) { - if (!tokenZone->empty()) - setEnabled(true); + if (!tokenCardNodes.isEmpty()) { + setEnabled(true); - for (int i = 0; i < tokenZone->size(); ++i) { - const QString tokenName = tokenZone->at(i)->getName(); + for (int i = 0; i < tokenCardNodes.size(); ++i) { + const QString tokenName = tokenCardNodes[i]->getName(); predefinedTokens.append(tokenName); QAction *a = addAction(tokenName); if (i < 10) { diff --git a/cockatrice/src/interface/deck_loader/deck_loader.cpp b/cockatrice/src/interface/deck_loader/deck_loader.cpp index d866b684b..a3f0ff619 100644 --- a/cockatrice/src/interface/deck_loader/deck_loader.cpp +++ b/cockatrice/src/interface/deck_loader/deck_loader.cpp @@ -269,6 +269,20 @@ static QString toDecklistExportString(const DecklistCardNode *card) return cardString; } +/** + * Converts all cards in the list to their decklist export string and joins them into one string + */ +static QString toDecklistExportString(const QList &cardNodes) +{ + QString result; + + for (auto cardNode : cardNodes) { + result += toDecklistExportString(cardNode); + } + + return result; +} + /** * Export deck to decklist function, called to format the deck in a way to be sent to a server * @@ -279,29 +293,11 @@ QString DeckLoader::exportDeckToDecklist(const DeckList *deckList, DecklistWebsi { // Add the base url QString deckString = "https://" + getDomainForWebsite(website) + "/?"; - // Create two strings to pass to function - QString mainBoardCards, sideBoardCards; - // Set up the function to call - auto formatDeckListForExport = [&mainBoardCards, &sideBoardCards](const auto *node, const auto *card) { - // Get the card name - CardInfoPtr dbCard = CardDatabaseManager::query()->getCardInfo(card->getName()); - if (!dbCard || dbCard->getIsToken()) { - // If it's a token, we don't care about the card. - return; - } + // export all cards in zone + QString mainBoardCards = toDecklistExportString(deckList->getCardNodes({DECK_ZONE_MAIN})); + QString sideBoardCards = toDecklistExportString(deckList->getCardNodes({DECK_ZONE_SIDE})); - // Check if it's a sideboard card. - if (node->getName() == DECK_ZONE_SIDE) { - sideBoardCards += toDecklistExportString(card); - } else { - // If it's a mainboard card, do the same thing, but for the mainboard card string - mainBoardCards += toDecklistExportString(card); - } - }; - - // call our struct function for each card in the deck - deckList->forEachCard(formatDeckListForExport); // Remove the extra return at the end of the last cards mainBoardCards.chop(3); sideBoardCards.chop(3); @@ -335,9 +331,7 @@ bool DeckLoader::saveToStream_Plain(QTextStream &out, } // loop zones - for (int i = 0; i < deckList->getRoot()->size(); i++) { - const auto *zoneNode = dynamic_cast(deckList->getRoot()->at(i)); - + for (auto zoneNode : deckList->getZoneNodes()) { saveToStream_DeckZone(out, zoneNode, addComments, addSetNameAndNumber); // end of zone @@ -514,7 +508,7 @@ QString DeckLoader::getCompleteCardName(const QString &cardName) return cardName; } -void DeckLoader::printDeckListNode(QTextCursor *cursor, InnerDecklistNode *node) +void DeckLoader::printDeckListNode(QTextCursor *cursor, const InnerDecklistNode *node) { const int totalColumns = 2; @@ -597,12 +591,11 @@ void DeckLoader::printDeckList(QPrinter *printer, const DeckList *deckList) cursor.insertText(deckList->getComments()); cursor.insertBlock(headerBlockFormat, headerCharFormat); - for (int i = 0; i < deckList->getRoot()->size(); i++) { + for (auto zoneNode : deckList->getZoneNodes()) { cursor.insertHtml("
"); - // cursor.insertHtml("
"); cursor.insertBlock(headerBlockFormat, headerCharFormat); - printDeckListNode(&cursor, dynamic_cast(deckList->getRoot()->at(i))); + printDeckListNode(&cursor, zoneNode); } doc.print(printer); diff --git a/cockatrice/src/interface/deck_loader/deck_loader.h b/cockatrice/src/interface/deck_loader/deck_loader.h index 474eee149..ae3088ff8 100644 --- a/cockatrice/src/interface/deck_loader/deck_loader.h +++ b/cockatrice/src/interface/deck_loader/deck_loader.h @@ -94,7 +94,7 @@ public: } private: - static void printDeckListNode(QTextCursor *cursor, InnerDecklistNode *node); + static void printDeckListNode(QTextCursor *cursor, const InnerDecklistNode *node); static void saveToStream_DeckHeader(QTextStream &out, const DeckList *deckList); static void saveToStream_DeckZone(QTextStream &out, 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 7e4287ac5..08ebf23ba 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 @@ -337,7 +337,7 @@ void DeckEditorDeckDockWidget::updateBannerCardComboBox() // Collect unique (name, providerId) pairs QSet> bannerCardSet; - QList cardsInDeck = deckModel->getDeckList()->getCardNodes(); + QList cardsInDeck = deckModel->getDeckList()->getCardNodes(); for (auto currentCard : cardsInDeck) { if (!CardDatabaseManager::query()->getCard(currentCard->toCardRef())) { 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 5b6eff923..2bfe650c3 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 @@ -228,7 +228,7 @@ QMap DlgSelectSetForCards::getSetsForCards() if (!decklist) return setCounts; - QList cardsInDeck = decklist->getCardNodes(); + QList cardsInDeck = decklist->getCardNodes(); for (auto currentCard : cardsInDeck) { CardInfoPtr infoPtr = CardDatabaseManager::query()->getCardInfo(currentCard->getName()); @@ -271,7 +271,7 @@ void DlgSelectSetForCards::updateCardLists() if (!decklist) return; - QList cardsInDeck = decklist->getCardNodes(); + QList cardsInDeck = decklist->getCardNodes(); for (auto currentCard : cardsInDeck) { bool found = false; @@ -360,7 +360,7 @@ QMap DlgSelectSetForCards::getCardsForSets() if (!decklist) return setCards; - QList cardsInDeck = decklist->getCardNodes(); + QList cardsInDeck = decklist->getCardNodes(); for (auto currentCard : cardsInDeck) { CardInfoPtr infoPtr = CardDatabaseManager::query()->getCardInfo(currentCard->getName()); diff --git a/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.cpp b/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.cpp index 80258be61..0d0195d34 100644 --- a/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.cpp +++ b/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.cpp @@ -311,7 +311,7 @@ int CardAmountWidget::countCardsInZone(const QString &deckZone) return -1; } - QList cardsInDeck = decklist->getCardNodes({deckZone}); + QList cardsInDeck = decklist->getCardNodes({deckZone}); int count = 0; for (auto currentCard : cardsInDeck) { 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 28c4e5ab9..9bc506056 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 @@ -68,7 +68,7 @@ void VisualDatabaseDisplayNameFilterWidget::actLoadFromDeck() if (!decklist) return; - QList cardsInDeck = decklist->getCardNodes(); + QList cardsInDeck = decklist->getCardNodes(); for (auto currentCard : cardsInDeck) { createNameFilter(currentCard->getName()); 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 b1db1cf37..341b94a3b 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 @@ -84,7 +84,7 @@ QList VisualDeckEditorSampleHandWidget::getRandomCards(int amountToGe if (!decklist) return randomCards; - QList cardsInDeck = decklist->getCardNodes({DECK_ZONE_MAIN}); + QList cardsInDeck = decklist->getCardNodes({DECK_ZONE_MAIN}); // Collect all cards in the main deck, allowing duplicates based on their count for (auto currentCard : cardsInDeck) { 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 1db0feb63..68243100c 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 @@ -235,7 +235,7 @@ void DeckPreviewWidget::updateBannerCardComboBox() // Prepare the new items with deduplication QSet> bannerCardSet; - QList cardsInDeck = deckLoader->getDeckList()->getCardNodes(); + QList cardsInDeck = deckLoader->getDeckList()->getCardNodes(); for (auto currentCard : cardsInDeck) { for (int k = 0; k < currentCard->getNumber(); ++k) { diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp index cea759428..333be017b 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp @@ -523,56 +523,34 @@ void DeckList::cleanList(bool preserveMetadata) refreshDeckHash(); } -void DeckList::getCardListHelper(InnerDecklistNode *item, QSet &result) -{ - for (int i = 0; i < item->size(); ++i) { - auto *node = dynamic_cast(item->at(i)); - - if (node) { - result.insert(node->getName()); - } else { - getCardListHelper(dynamic_cast(item->at(i)), result); - } - } -} - -void DeckList::getCardRefListHelper(InnerDecklistNode *item, QList &result) -{ - for (int i = 0; i < item->size(); ++i) { - auto *node = dynamic_cast(item->at(i)); - - if (node) { - result.append(node->toCardRef()); - } else { - getCardRefListHelper(dynamic_cast(item->at(i)), result); - } - } -} - QStringList DeckList::getCardList() const { - QSet result; - getCardListHelper(root, result); - return result.values(); + auto nodes = getCardNodes(); + + QStringList result; + std::transform(nodes.cbegin(), nodes.cend(), std::back_inserter(result), [](auto node) { return node->getName(); }); + + return result; } QList DeckList::getCardRefList() const { + auto nodes = getCardNodes(); + QList result; - getCardRefListHelper(root, result); + std::transform(nodes.cbegin(), nodes.cend(), std::back_inserter(result), + [](auto node) { return node->toCardRef(); }); + return result; } -QList DeckList::getCardNodes(const QStringList &restrictToZones) const +QList DeckList::getCardNodes(const QStringList &restrictToZones) const { - QList result; + QList result; - for (auto *node : *root) { - auto *zoneNode = dynamic_cast(node); - if (zoneNode == nullptr) { - continue; - } - if (!restrictToZones.isEmpty() && !restrictToZones.contains(node->getName())) { + auto zoneNodes = getZoneNodes(); + for (auto *zoneNode : zoneNodes) { + if (!restrictToZones.isEmpty() && !restrictToZones.contains(zoneNode->getName())) { continue; } for (auto *cardNode : *zoneNode) { @@ -586,20 +564,28 @@ QList DeckList::getCardNodes(const QStringList &restrictToZo return result; } +QList DeckList::getZoneNodes() const +{ + QList zones; + for (auto *node : *root) { + InnerDecklistNode *currentZone = dynamic_cast(node); + if (!currentZone) + continue; + zones.append(currentZone); + } + + return zones; +} + int DeckList::getSideboardSize() const { - int size = 0; - for (int i = 0; i < root->size(); ++i) { - auto *node = dynamic_cast(root->at(i)); - if (node->getName() != DECK_ZONE_SIDE) { - continue; - } + auto cards = getCardNodes({DECK_ZONE_SIDE}); - for (int j = 0; j < node->size(); j++) { - auto *card = dynamic_cast(node->at(j)); - size += card->getNumber(); - } + int size = 0; + for (auto card : cards) { + size += card->getNumber(); } + return size; } @@ -665,26 +651,23 @@ bool DeckList::deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNod return false; } -static QString computeDeckHash(const InnerDecklistNode *root) +static QString computeDeckHash(const DeckList &deckList) { - QStringList cardList; - QSet hashZones, optionalZones; + auto mainDeckNodes = deckList.getCardNodes({DECK_ZONE_MAIN}); + auto sideDeckNodes = deckList.getCardNodes({DECK_ZONE_SIDE}); - hashZones << DECK_ZONE_MAIN << DECK_ZONE_SIDE; // Zones in deck to be included in hashing process - optionalZones << DECK_ZONE_TOKENS; // Optional zones in deck not included in hashing process - - for (int i = 0; i < root->size(); i++) { - auto *node = dynamic_cast(root->at(i)); - for (int j = 0; j < node->size(); j++) { - if (hashZones.contains(node->getName())) // Mainboard or Sideboard - { - auto *card = dynamic_cast(node->at(j)); - for (int k = 0; k < card->getNumber(); ++k) { - cardList.append((node->getName() == DECK_ZONE_SIDE ? "SB:" : "") + card->getName().toLower()); - } + static auto nodesToCardList = [](const QList &nodes, const QString &prefix = {}) { + QStringList result; + for (auto node : nodes) { + for (int i = 0; i < node->getNumber(); ++i) { + result.append(prefix + node->getName().toLower()); } } - } + return result; + }; + + QStringList cardList = nodesToCardList(mainDeckNodes) + nodesToCardList(sideDeckNodes, "SB:"); + cardList.sort(); QByteArray deckHashArray = QCryptographicHash::hash(cardList.join(";").toUtf8(), QCryptographicHash::Sha1); quint64 number = (((quint64)(unsigned char)deckHashArray[0]) << 32) + @@ -706,7 +689,7 @@ QString DeckList::getDeckHash() const return cachedDeckHash; } - cachedDeckHash = computeDeckHash(root); + cachedDeckHash = computeDeckHash(*this); return cachedDeckHash; } diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h index d4d1204e6..6f90b6b14 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h @@ -148,8 +148,6 @@ private: mutable QString cachedDeckHash; // Helpers for traversing the tree - static void getCardListHelper(InnerDecklistNode *node, QSet &result); - static void getCardRefListHelper(InnerDecklistNode *item, QList &result); InnerDecklistNode *getZoneObjFromName(const QString &zoneName); public: @@ -267,7 +265,8 @@ public: } QStringList getCardList() const; QList getCardRefList() const; - QList getCardNodes(const QStringList &restrictToZones = QStringList()) const; + QList getCardNodes(const QStringList &restrictToZones = QStringList()) const; + QList getZoneNodes() const; int getSideboardSize() const; InnerDecklistNode *getRoot() const { 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 bd16ab3d2..2856198b8 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.cpp +++ b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.cpp @@ -550,86 +550,49 @@ void DeckListModel::setDeckList(DeckList *_deck) QList DeckListModel::getCards() const { - QList cards; - DeckList *decklist = getDeckList(); - if (!decklist) { - return cards; - } - InnerDecklistNode *listRoot = decklist->getRoot(); - if (!listRoot) - return cards; + auto nodes = deckList->getCardNodes(); - for (int i = 0; i < listRoot->size(); i++) { - InnerDecklistNode *currentZone = dynamic_cast(listRoot->at(i)); - if (!currentZone) - continue; - for (int j = 0; j < currentZone->size(); j++) { - DecklistCardNode *currentCard = dynamic_cast(currentZone->at(j)); - if (!currentCard) - continue; - for (int k = 0; k < currentCard->getNumber(); ++k) { - ExactCard card = CardDatabaseManager::query()->getCard(currentCard->toCardRef()); - if (card) { - cards.append(card); - } else { - qDebug() << "Card not found in database!"; - } + QList cards; + for (auto node : nodes) { + ExactCard card = CardDatabaseManager::query()->getCard(node->toCardRef()); + if (card) { + for (int k = 0; k < node->getNumber(); ++k) { + cards.append(card); } + } else { + qDebug() << "Card not found in database!"; } } + return cards; } QList DeckListModel::getCardsForZone(const QString &zoneName) const { - QList cards; - DeckList *decklist = getDeckList(); - if (!decklist) { - return cards; - } - InnerDecklistNode *listRoot = decklist->getRoot(); - if (!listRoot) - return cards; + auto nodes = deckList->getCardNodes({zoneName}); - for (int i = 0; i < listRoot->size(); i++) { - InnerDecklistNode *currentZone = dynamic_cast(listRoot->at(i)); - if (!currentZone) - continue; - if (currentZone->getName() == zoneName) { - for (int j = 0; j < currentZone->size(); j++) { - DecklistCardNode *currentCard = dynamic_cast(currentZone->at(j)); - if (!currentCard) - continue; - for (int k = 0; k < currentCard->getNumber(); ++k) { - ExactCard card = CardDatabaseManager::query()->getCard(currentCard->toCardRef()); - if (card) { - cards.append(card); - } else { - qDebug() << "Card not found in database!"; - } - } + QList cards; + for (auto node : nodes) { + ExactCard card = CardDatabaseManager::query()->getCard(node->toCardRef()); + if (card) { + for (int k = 0; k < node->getNumber(); ++k) { + cards.append(card); } + } else { + qDebug() << "Card not found in database!"; } } + return cards; } -QList *DeckListModel::getZones() const +QList DeckListModel::getZones() const { - QList *zones = new QList(); - DeckList *decklist = getDeckList(); - if (!decklist) { - return zones; - } - InnerDecklistNode *listRoot = decklist->getRoot(); - if (!listRoot) - return zones; + auto zoneNodes = deckList->getZoneNodes(); + + QList zones; + std::transform(zoneNodes.cbegin(), zoneNodes.cend(), std::back_inserter(zones), + [](auto zoneNode) { return zoneNode->getName(); }); - for (int i = 0; i < listRoot->size(); i++) { - InnerDecklistNode *currentZone = dynamic_cast(listRoot->at(i)); - if (!currentZone) - continue; - zones->append(currentZone->getName()); - } return zones; } \ 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 a480c606b..0b47faed4 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h +++ b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h @@ -300,7 +300,7 @@ public: [[nodiscard]] QList getCards() const; [[nodiscard]] QList getCardsForZone(const QString &zoneName) const; - [[nodiscard]] QList *getZones() const; + [[nodiscard]] QList getZones() const; /** * @brief Sets the criteria used to group cards in the model. diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp index 8190155e9..e62f861a9 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp @@ -102,28 +102,16 @@ void Server_Player::setupZones() // ------------------------------------------------------------------ // Assign card ids and create deck from deck list - InnerDecklistNode *listRoot = deck->getRoot(); - for (int i = 0; i < listRoot->size(); ++i) { - auto *currentZone = dynamic_cast(listRoot->at(i)); - Server_CardZone *z; - if (currentZone->getName() == DECK_ZONE_MAIN) { - z = deckZone; - } else if (currentZone->getName() == DECK_ZONE_SIDE) { - z = sbZone; - } else { - continue; + auto insertCardsIntoZone = [this](auto cards, auto *zone) { + for (auto card : cards) { + for (int k = 0; k < card->getNumber(); ++k) { + zone->insertCard(new Server_Card(card->toCardRef(), nextCardId++, 0, 0, zone), -1, 0); + } } + }; - for (int j = 0; j < currentZone->size(); ++j) { - auto *currentCard = dynamic_cast(currentZone->at(j)); - if (!currentCard) { - continue; - } - for (int k = 0; k < currentCard->getNumber(); ++k) { - z->insertCard(new Server_Card(currentCard->toCardRef(), nextCardId++, 0, 0, z), -1, 0); - } - } - } + insertCardsIntoZone(deck->getCardNodes({DECK_ZONE_MAIN}), deckZone); + insertCardsIntoZone(deck->getCardNodes({DECK_ZONE_SIDE}), sbZone); const QList &sideboardPlan = deck->getCurrentSideboardPlan(); for (const auto &m : sideboardPlan) { From ccdda39e78fc24d7cf5e2ea610f1faf611aa5197 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:17:55 +0100 Subject: [PATCH 40/40] Deck format legality checker (#6166) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Deck legality checker. Took 51 seconds Took 1 minute Took 1 minute Took 5 minutes Took 3 minutes * Adjust format parsing. Took 8 minutes Took 3 seconds * toString() the xmlName Took 4 minutes * more toStrings() Took 5 minutes * Comments Took 3 minutes * Layout Took 2 minutes * Layout part 2: Electric boogaloo Took 59 seconds * Update cockatrice/src/interface/widgets/visual_database_display/visual_database_display_format_legality_filter_widget.cpp Co-authored-by: RickyRister <42636155+RickyRister@users.noreply.github.com> * Move layout. Took 4 minutes Took 10 seconds * Emit deckModified Took 6 minutes * Fix qOverloads Took 4 minutes * Fix qOverloads Took 12 seconds * Consider text and name in a special way. Took 11 minutes * Adjust "Any number of" oracle text Took 5 minutes * Store allowedCounts by format Took 15 minutes Took 6 seconds * Only restrict vintage. Took 2 minutes * Adjust for DBConverter. Took 6 minutes --------- Co-authored-by: Lukas Brübach Co-authored-by: RickyRister <42636155+RickyRister@users.noreply.github.com> --- cockatrice/CMakeLists.txt | 1 + .../deck_editor_deck_dock_widget.cpp | 67 +++++- .../deck_editor_deck_dock_widget.h | 3 + .../deck_editor/deck_list_style_proxy.cpp | 3 +- .../tabs/api/archidekt/tab_archidekt.cpp | 4 +- ..._display_format_legality_filter_widget.cpp | 205 ++++++++++++++++++ ...se_display_format_legality_filter_widget.h | 43 ++++ ...tabase_display_main_type_filter_widget.cpp | 2 +- ...ual_database_display_set_filter_widget.cpp | 2 +- ...atabase_display_sub_type_filter_widget.cpp | 2 +- .../visual_database_display_widget.cpp | 2 + .../visual_database_display_widget.h | 2 + .../visual_deck_editor_sample_hand_widget.cpp | 4 +- ...ual_deck_storage_quick_settings_widget.cpp | 6 +- dbconverter/src/main.h | 72 +++++- libcockatrice_card/CMakeLists.txt | 2 + .../libcockatrice/card/card_info.h | 3 + .../card/database/card_database.cpp | 5 + .../card/database/card_database.h | 4 + .../card/database/card_database_loader.cpp | 3 +- .../card/database/card_database_querier.cpp | 23 ++ .../card/database/card_database_querier.h | 2 + .../database/parser/card_database_parser.h | 6 +- .../card/database/parser/cockatrice_xml_3.cpp | 5 +- .../card/database/parser/cockatrice_xml_3.h | 3 +- .../card/database/parser/cockatrice_xml_4.cpp | 179 ++++++++++++++- .../card/database/parser/cockatrice_xml_4.h | 4 +- .../card/format/format_legality_rules.cpp | 53 +++++ .../card/format/format_legality_rules.h | 73 +++++++ .../libcockatrice/deck_list/deck_list.cpp | 10 +- .../libcockatrice/deck_list/deck_list.h | 12 +- .../tree/abstract_deck_list_card_node.h | 6 + .../deck_list/tree/deck_list_card_node.h | 19 +- .../models/deck_list/deck_list_model.cpp | 105 ++++++++- .../models/deck_list/deck_list_model.h | 14 ++ oracle/src/oracleimporter.cpp | 72 +++++- oracle/src/oracleimporter.h | 1 + 37 files changed, 987 insertions(+), 35 deletions(-) create mode 100644 cockatrice/src/interface/widgets/visual_database_display/visual_database_display_format_legality_filter_widget.cpp create mode 100644 cockatrice/src/interface/widgets/visual_database_display/visual_database_display_format_legality_filter_widget.h create mode 100644 libcockatrice_card/libcockatrice/card/format/format_legality_rules.cpp create mode 100644 libcockatrice_card/libcockatrice/card/format/format_legality_rules.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index dec1b3d62..c9fa80e6b 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -202,6 +202,7 @@ set(cockatrice_SOURCES src/interface/widgets/utility/sequence_edit.cpp src/interface/widgets/visual_database_display/visual_database_display_color_filter_widget.cpp src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.cpp + src/interface/widgets/visual_database_display/visual_database_display_format_legality_filter_widget.cpp src/interface/widgets/visual_database_display/visual_database_display_main_type_filter_widget.cpp src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.cpp src/interface/widgets/visual_database_display/visual_database_display_set_filter_widget.cpp 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 08ebf23ba..268a13d5f 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 @@ -124,6 +124,12 @@ void DeckEditorDeckDockWidget::createDeckDock() quickSettingsWidget->addSettingsWidget(showBannerCardCheckBox); quickSettingsWidget->addSettingsWidget(showTagsWidgetCheckBox); + formatLabel = new QLabel(this); + + formatComboBox = new QComboBox(this); + formatComboBox->addItem(tr("Loading Database...")); + formatComboBox->setEnabled(false); // Disable until loaded + commentsLabel = new QLabel(); commentsLabel->setObjectName("commentsLabel"); commentsEdit = new QTextEdit; @@ -208,13 +214,16 @@ void DeckEditorDeckDockWidget::createDeckDock() upperLayout->addWidget(commentsLabel, 1, 0); upperLayout->addWidget(commentsEdit, 1, 1); - upperLayout->addWidget(bannerCardLabel, 2, 0); - upperLayout->addWidget(bannerCardComboBox, 2, 1); + upperLayout->addWidget(formatLabel, 2, 0); + upperLayout->addWidget(formatComboBox, 2, 1); - upperLayout->addWidget(deckTagsDisplayWidget, 3, 1); + upperLayout->addWidget(bannerCardLabel, 3, 0); + upperLayout->addWidget(bannerCardComboBox, 3, 1); - upperLayout->addWidget(activeGroupCriteriaLabel, 4, 0); - upperLayout->addWidget(activeGroupCriteriaComboBox, 4, 1); + upperLayout->addWidget(deckTagsDisplayWidget, 4, 1); + + upperLayout->addWidget(activeGroupCriteriaLabel, 5, 0); + upperLayout->addWidget(activeGroupCriteriaComboBox, 5, 1); hashLabel1 = new QLabel(); hashLabel1->setObjectName("hashLabel1"); @@ -263,6 +272,46 @@ void DeckEditorDeckDockWidget::createDeckDock() refreshShortcuts(); retranslateUi(); + + connect(CardDatabaseManager::getInstance(), &CardDatabase::cardDatabaseLoadingFinished, this, + &DeckEditorDeckDockWidget::initializeFormats); + + if (CardDatabaseManager::getInstance()->getLoadStatus() == LoadStatus::Ok) { + initializeFormats(); + } +} + +void DeckEditorDeckDockWidget::initializeFormats() +{ + QMap allFormats = CardDatabaseManager::query()->getAllFormatsWithCount(); + + formatComboBox->clear(); // Remove "Loading Database..." + formatComboBox->setEnabled(true); + + // Populate with formats + formatComboBox->addItem("", ""); + for (auto it = allFormats.constBegin(); it != allFormats.constEnd(); ++it) { + QString displayText = QString("%1").arg(it.key()); + formatComboBox->addItem(displayText, it.key()); // store the raw key in itemData + } + + if (!deckModel->getDeckList()->getGameFormat().isEmpty()) { + deckModel->setActiveFormat(deckModel->getDeckList()->getGameFormat()); + formatComboBox->setCurrentIndex(formatComboBox->findData(deckModel->getDeckList()->getGameFormat())); + } else { + // Ensure no selection is visible initially + formatComboBox->setCurrentIndex(-1); + } + + connect(formatComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, [this](int index) { + if (index >= 0) { + QString formatKey = formatComboBox->itemData(index).toString(); + deckModel->setActiveFormat(formatKey); + } else { + deckModel->setActiveFormat(QString()); // clear format if deselected + } + emit deckModified(); + }); } ExactCard DeckEditorDeckDockWidget::getCurrentCard() @@ -466,6 +515,12 @@ void DeckEditorDeckDockWidget::syncDisplayWidgetsToModel() void DeckEditorDeckDockWidget::sortDeckModelToDeckView() { deckModel->sort(deckView->header()->sortIndicatorSection(), deckView->header()->sortIndicatorOrder()); + deckModel->setActiveFormat(deckModel->getDeckList()->getGameFormat()); + formatComboBox->setCurrentIndex(formatComboBox->findData(deckModel->getDeckList()->getGameFormat())); + deckView->expandAll(); + deckView->expandAll(); + + emit deckChanged(); } DeckLoader *DeckEditorDeckDockWidget::getDeckLoader() @@ -724,6 +779,8 @@ void DeckEditorDeckDockWidget::retranslateUi() showTagsWidgetCheckBox->setText(tr("Show tags selection menu")); commentsLabel->setText(tr("&Comments:")); activeGroupCriteriaLabel->setText(tr("Group by:")); + formatLabel->setText(tr("Format:")); + hashLabel1->setText(tr("Hash:")); aIncrement->setText(tr("&Increment number")); 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 d1f1da300..08aa38e5e 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 @@ -69,6 +69,7 @@ public slots: void actSwapCard(); void actRemoveCard(); void offsetCountAtIndex(const QModelIndex &idx, int offset); + void initializeFormats(); void expandAll(); signals: @@ -100,6 +101,8 @@ private: LineEditUnfocusable *hashLabel; QLabel *activeGroupCriteriaLabel; QComboBox *activeGroupCriteriaComboBox; + QLabel *formatLabel; + QComboBox *formatComboBox; QAction *aRemoveCard, *aIncrement, *aDecrement, *aSwapCard; 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 index 9c2265dfd..14c5faae7 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_list_style_proxy.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_list_style_proxy.cpp @@ -23,8 +23,7 @@ QVariant DeckListStyleProxy::data(const QModelIndex &index, int role) const if (role == Qt::BackgroundRole) { if (isCard) { - const bool legal = - true; // TODO: Not implemented yet. QIdentityProxyModel::data(index, DeckRoles::IsLegalRole).toBool(); + const bool legal = 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 { diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp index 1376efd47..e6615fa7b 100644 --- a/cockatrice/src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp @@ -214,7 +214,7 @@ TabArchidekt::TabArchidekt(TabSupervisor *_tabSupervisor) : Tab(_tabSupervisor) minDeckSizeLogicCombo->addItems({"Exact", "≥", "≤"}); // Exact = unset, ≥ = GTE, ≤ = LTE minDeckSizeLogicCombo->setCurrentIndex(1); // default GTE - connect(minDeckSizeSpin, QOverload::of(&QSpinBox::valueChanged), this, &TabArchidekt::doSearch); + connect(minDeckSizeSpin, qOverload(&QSpinBox::valueChanged), this, &TabArchidekt::doSearch); connect(minDeckSizeLogicCombo, &QComboBox::currentTextChanged, this, &TabArchidekt::doSearch); // Page number @@ -224,7 +224,7 @@ TabArchidekt::TabArchidekt(TabSupervisor *_tabSupervisor) : Tab(_tabSupervisor) pageSpin->setRange(1, 9999); pageSpin->setValue(1); - connect(pageSpin, QOverload::of(&QSpinBox::valueChanged), this, &TabArchidekt::doSearch); + connect(pageSpin, qOverload(&QSpinBox::valueChanged), this, &TabArchidekt::doSearch); // Page display currentPageDisplay = new QWidget(container); diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_format_legality_filter_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_format_legality_filter_widget.cpp new file mode 100644 index 000000000..1f1b7b94c --- /dev/null +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_format_legality_filter_widget.cpp @@ -0,0 +1,205 @@ +#include "visual_database_display_format_legality_filter_widget.h" + +#include "../../../filters/filter_tree_model.h" + +#include +#include +#include +#include +#include + +VisualDatabaseDisplayFormatLegalityFilterWidget::VisualDatabaseDisplayFormatLegalityFilterWidget( + QWidget *parent, + FilterTreeModel *_filterModel) + : QWidget(parent), filterModel(_filterModel) +{ + allFormatsWithCount = CardDatabaseManager::query()->getAllFormatsWithCount(); + + setMaximumHeight(75); + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); + + layout = new QHBoxLayout(this); + setLayout(layout); + layout->setContentsMargins(0, 1, 0, 1); + layout->setSpacing(1); + layout->setAlignment(Qt::AlignTop); + + flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAsNeeded); + layout->addWidget(flowWidget); + + // Create the spinbox + spinBox = new QSpinBox(this); + spinBox->setMinimum(1); + spinBox->setMaximum(getMaxMainTypeCount()); // Set the max value dynamically + spinBox->setValue(150); + layout->addWidget(spinBox); + connect(spinBox, qOverload(&QSpinBox::valueChanged), this, + &VisualDatabaseDisplayFormatLegalityFilterWidget::updateFormatButtonsVisibility); + + // Create the toggle button for Exact Match/Includes mode + toggleButton = new QPushButton(this); + toggleButton->setCheckable(true); + layout->addWidget(toggleButton); + connect(toggleButton, &QPushButton::toggled, this, + &VisualDatabaseDisplayFormatLegalityFilterWidget::updateFilterMode); + connect(filterModel, &FilterTreeModel::layoutChanged, this, [this]() { + QTimer::singleShot(100, this, &VisualDatabaseDisplayFormatLegalityFilterWidget::syncWithFilterModel); + }); + + createFormatButtons(); // Populate buttons initially + updateFilterMode(false); // Initialize toggle button text + + retranslateUi(); +} + +void VisualDatabaseDisplayFormatLegalityFilterWidget::retranslateUi() +{ + spinBox->setToolTip(tr("Do not display formats with less than this amount of cards in the database")); + toggleButton->setToolTip(tr("Filter mode (AND/OR/NOT conjunctions of filters)")); +} + +void VisualDatabaseDisplayFormatLegalityFilterWidget::createFormatButtons() +{ + // Iterate through main types and create buttons + for (auto it = allFormatsWithCount.begin(); it != allFormatsWithCount.end(); ++it) { + auto *button = new QPushButton(it.key(), flowWidget); + button->setCheckable(true); + button->setStyleSheet("QPushButton { background-color: lightgray; border: 1px solid gray; padding: 5px; }" + "QPushButton:checked { background-color: green; color: white; }"); + + flowWidget->addWidget(button); + formatButtons[it.key()] = button; + + // Connect toggle signal + connect(button, &QPushButton::toggled, this, + [this, mainType = it.key()](bool checked) { handleFormatToggled(mainType, checked); }); + } + updateFormatButtonsVisibility(); // Ensure visibility is updated initially +} + +void VisualDatabaseDisplayFormatLegalityFilterWidget::updateFormatButtonsVisibility() +{ + int threshold = spinBox->value(); // Get the current spinbox value + + // Iterate through buttons and hide/disable those below the threshold + for (auto it = formatButtons.begin(); it != formatButtons.end(); ++it) { + bool visible = allFormatsWithCount[it.key()] >= threshold; + it.value()->setVisible(visible); + it.value()->setEnabled(visible); + } +} + +int VisualDatabaseDisplayFormatLegalityFilterWidget::getMaxMainTypeCount() const +{ + int maxCount = 1; + for (auto it = allFormatsWithCount.begin(); it != allFormatsWithCount.end(); ++it) { + maxCount = qMax(maxCount, it.value()); + } + return maxCount; +} + +void VisualDatabaseDisplayFormatLegalityFilterWidget::handleFormatToggled(const QString &format, bool active) +{ + activeFormats[format] = active; + + if (formatButtons.contains(format)) { + formatButtons[format]->setChecked(active); + } + + updateFormatFilter(); +} + +void VisualDatabaseDisplayFormatLegalityFilterWidget::updateFormatFilter() +{ + // Clear existing filters related to main type + filterModel->blockSignals(true); + filterModel->filterTree()->blockSignals(true); + filterModel->clearFiltersOfType(CardFilter::Attr::AttrFormat); + + if (exactMatchMode) { + // Exact Match: Only selected main types are allowed + QSet selectedTypes; + for (const auto &type : activeFormats.keys()) { + if (activeFormats[type]) { + selectedTypes.insert(type); + } + } + + if (!selectedTypes.isEmpty()) { + // Require all selected types (TypeAnd) + for (const auto &type : selectedTypes) { + QString typeString = type; + filterModel->addFilter( + new CardFilter(typeString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrFormat)); + } + + // Exclude any other types (TypeAndNot) + for (const auto &type : formatButtons.keys()) { + if (!selectedTypes.contains(type)) { + QString typeString = type; + filterModel->addFilter( + new CardFilter(typeString, CardFilter::Type::TypeAndNot, CardFilter::Attr::AttrFormat)); + } + } + } + } else { + // Default Includes Mode (TypeOr) - match any selected main types + for (const auto &type : activeFormats.keys()) { + if (activeFormats[type]) { + QString typeString = type; + filterModel->addFilter( + new CardFilter(typeString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrFormat)); + } + } + } + + filterModel->blockSignals(false); + filterModel->filterTree()->blockSignals(false); + + emit filterModel->filterTree()->changed(); + emit filterModel->layoutChanged(); +} + +void VisualDatabaseDisplayFormatLegalityFilterWidget::updateFilterMode(bool checked) +{ + exactMatchMode = checked; + toggleButton->setText(exactMatchMode ? tr("Mode: Exact Match") : tr("Mode: Includes")); + updateFormatFilter(); +} + +void VisualDatabaseDisplayFormatLegalityFilterWidget::syncWithFilterModel() +{ + // Temporarily block signals for each button to prevent toggling while updating button states + for (auto it = formatButtons.begin(); it != formatButtons.end(); ++it) { + it.value()->blockSignals(true); + } + + // Uncheck all buttons + for (auto it = formatButtons.begin(); it != formatButtons.end(); ++it) { + it.value()->setChecked(false); + } + + // Get active filters for main types + QSet activeTypes; + for (const auto &filter : filterModel->getFiltersOfType(CardFilter::AttrFormat)) { + if (filter->type() == CardFilter::Type::TypeAnd) { + activeTypes.insert(filter->term()); + } + } + + // Check the buttons for active types + for (const auto &type : activeTypes) { + activeFormats[type] = true; + if (formatButtons.contains(type)) { + formatButtons[type]->setChecked(true); + } + } + + // Re-enable signal emissions for each button + for (auto it = formatButtons.begin(); it != formatButtons.end(); ++it) { + it.value()->blockSignals(false); + } + + // Update the visibility of buttons + updateFormatButtonsVisibility(); +} diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_format_legality_filter_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_format_legality_filter_widget.h new file mode 100644 index 000000000..a2a00b740 --- /dev/null +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_format_legality_filter_widget.h @@ -0,0 +1,43 @@ +#ifndef COCKATRICE_VISUAL_DATABASE_DISPLAY_FORMAT_LEGALITY_FILTER_WIDGET_H +#define COCKATRICE_VISUAL_DATABASE_DISPLAY_FORMAT_LEGALITY_FILTER_WIDGET_H + +#include "../../../filters/filter_tree_model.h" +#include "../general/layout_containers/flow_widget.h" + +#include +#include +#include +#include +#include +#include + +class VisualDatabaseDisplayFormatLegalityFilterWidget : public QWidget +{ + Q_OBJECT +public: + explicit VisualDatabaseDisplayFormatLegalityFilterWidget(QWidget *parent, FilterTreeModel *filterModel); + void retranslateUi(); + void createFormatButtons(); + void updateFormatButtonsVisibility(); + int getMaxMainTypeCount() const; + + void handleFormatToggled(const QString &format, bool active); + void updateFormatFilter(); + void updateFilterMode(bool checked); + void syncWithFilterModel(); + +private: + FilterTreeModel *filterModel; + QMap allFormatsWithCount; + QSpinBox *spinBox; + QHBoxLayout *layout; + FlowWidget *flowWidget; + QPushButton *toggleButton; // Mode switch button + + QMap activeFormats; // Track active filters + QMap formatButtons; // Store toggle buttons + + bool exactMatchMode = false; // Toggle between "Exact Match" and "Includes" +}; + +#endif // COCKATRICE_VISUAL_DATABASE_DISPLAY_FORMAT_LEGALITY_FILTER_WIDGET_H 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 32652c346..368ac8719 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 @@ -33,7 +33,7 @@ VisualDatabaseDisplayMainTypeFilterWidget::VisualDatabaseDisplayMainTypeFilterWi spinBox->setMaximum(getMaxMainTypeCount()); // Set the max value dynamically spinBox->setValue(150); layout->addWidget(spinBox); - connect(spinBox, QOverload::of(&QSpinBox::valueChanged), this, + connect(spinBox, qOverload(&QSpinBox::valueChanged), this, &VisualDatabaseDisplayMainTypeFilterWidget::updateMainTypeButtonsVisibility); // Create the toggle button for Exact Match/Includes mode 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 1ea6e8e67..dee89f06a 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 @@ -27,7 +27,7 @@ VisualDatabaseDisplayRecentSetFilterSettingsWidget::VisualDatabaseDisplayRecentS filterToMostRecentSetsAmount->setMaximum(100); filterToMostRecentSetsAmount->setValue( SettingsCache::instance().getVisualDatabaseDisplayFilterToMostRecentSetsAmount()); - connect(filterToMostRecentSetsAmount, QOverload::of(&QSpinBox::valueChanged), &SettingsCache::instance(), + connect(filterToMostRecentSetsAmount, qOverload(&QSpinBox::valueChanged), &SettingsCache::instance(), &SettingsCache::setVisualDatabaseDisplayFilterToMostRecentSetsAmount); layout->addWidget(filterToMostRecentSetsCheckBox); 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 7a88b51cf..b34bb65d3 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 @@ -26,7 +26,7 @@ VisualDatabaseDisplaySubTypeFilterWidget::VisualDatabaseDisplaySubTypeFilterWidg spinBox->setMaximum(getMaxSubTypeCount()); spinBox->setValue(150); layout->addWidget(spinBox); - connect(spinBox, QOverload::of(&QSpinBox::valueChanged), this, + connect(spinBox, qOverload(&QSpinBox::valueChanged), this, &VisualDatabaseDisplaySubTypeFilterWidget::updateSubTypeButtonsVisibility); // Create search box 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 cc0fc8033..c5eaa171a 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 @@ -206,6 +206,7 @@ void VisualDatabaseDisplayWidget::initialize() saveLoadWidget = new VisualDatabaseDisplayFilterSaveLoadWidget(this, filterModel); nameFilterWidget = new VisualDatabaseDisplayNameFilterWidget(this, deckEditor, filterModel); mainTypeFilterWidget = new VisualDatabaseDisplayMainTypeFilterWidget(this, filterModel); + formatLegalityWidget = new VisualDatabaseDisplayFormatLegalityFilterWidget(this, filterModel); subTypeFilterWidget = new VisualDatabaseDisplaySubTypeFilterWidget(this, filterModel); setFilterWidget = new VisualDatabaseDisplaySetFilterWidget(this, filterModel); @@ -223,6 +224,7 @@ void VisualDatabaseDisplayWidget::initialize() filterContainerLayout->addWidget(quickFilterSubTypeWidget); filterContainerLayout->addWidget(quickFilterSetWidget); filterContainerLayout->addWidget(mainTypeFilterWidget); + filterContainerLayout->addWidget(formatLegalityWidget); searchLayout->addWidget(colorFilterWidget); searchLayout->addWidget(clearFilterWidget); diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h index 5cab2ca9b..24990f8e5 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h @@ -17,6 +17,7 @@ #include "../utility/custom_line_edit.h" #include "visual_database_display_color_filter_widget.h" #include "visual_database_display_filter_save_load_widget.h" +#include "visual_database_display_format_legality_filter_widget.h" #include "visual_database_display_main_type_filter_widget.h" #include "visual_database_display_name_filter_widget.h" #include "visual_database_display_set_filter_widget.h" @@ -91,6 +92,7 @@ private: SettingsButtonWidget *quickFilterNameWidget; VisualDatabaseDisplayNameFilterWidget *nameFilterWidget; VisualDatabaseDisplayMainTypeFilterWidget *mainTypeFilterWidget; + VisualDatabaseDisplayFormatLegalityFilterWidget *formatLegalityWidget; SettingsButtonWidget *quickFilterSubTypeWidget; VisualDatabaseDisplaySubTypeFilterWidget *subTypeFilterWidget; SettingsButtonWidget *quickFilterSetWidget; 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 341b94a3b..778706f9a 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 @@ -24,9 +24,9 @@ VisualDeckEditorSampleHandWidget::VisualDeckEditorSampleHandWidget(QWidget *pare handSizeSpinBox = new QSpinBox(this); handSizeSpinBox->setValue(SettingsCache::instance().getVisualDeckEditorSampleHandSize()); handSizeSpinBox->setMinimum(1); - connect(handSizeSpinBox, QOverload::of(&QSpinBox::valueChanged), &SettingsCache::instance(), + connect(handSizeSpinBox, qOverload(&QSpinBox::valueChanged), &SettingsCache::instance(), &SettingsCache::setVisualDeckEditorSampleHandSize); - connect(handSizeSpinBox, QOverload::of(&QSpinBox::valueChanged), this, + connect(handSizeSpinBox, qOverload(&QSpinBox::valueChanged), this, &VisualDeckEditorSampleHandWidget::updateDisplay); resetAndHandSizeLayout->addWidget(handSizeSpinBox); 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 c1e9bfa6a..a396b8cd3 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 @@ -61,10 +61,10 @@ VisualDeckStorageQuickSettingsWidget::VisualDeckStorageQuickSettingsWidget(QWidg unusedColorIdentitiesOpacitySpinBox->setMaximum(100); unusedColorIdentitiesOpacitySpinBox->setValue( SettingsCache::instance().getVisualDeckStorageUnusedColorIdentitiesOpacity()); - connect(unusedColorIdentitiesOpacitySpinBox, QOverload::of(&QSpinBox::valueChanged), this, + connect(unusedColorIdentitiesOpacitySpinBox, qOverload(&QSpinBox::valueChanged), this, &VisualDeckStorageQuickSettingsWidget::unusedColorIdentitiesOpacityChanged); - connect(unusedColorIdentitiesOpacitySpinBox, QOverload::of(&QSpinBox::valueChanged), - &SettingsCache::instance(), &SettingsCache::setVisualDeckStorageUnusedColorIdentitiesOpacity); + connect(unusedColorIdentitiesOpacitySpinBox, qOverload(&QSpinBox::valueChanged), &SettingsCache::instance(), + &SettingsCache::setVisualDeckStorageUnusedColorIdentitiesOpacity); unusedColorIdentitiesOpacityLabel->setBuddy(unusedColorIdentitiesOpacitySpinBox); diff --git a/dbconverter/src/main.h b/dbconverter/src/main.h index 7a5809b1b..d6e734316 100644 --- a/dbconverter/src/main.h +++ b/dbconverter/src/main.h @@ -5,6 +5,10 @@ #include #include +static const QList kConstructedCounts = {{4, "legal"}, {0, "banned"}}; + +static const QList kSingletonCounts = {{1, "legal"}, {0, "banned"}}; + class CardDatabaseConverter : public CardDatabase { public: @@ -23,7 +27,73 @@ public: bool saveCardDatabase(const QString &fileName) { CockatriceXml4Parser parser(new NoopCardPreferenceProvider()); - return parser.saveToFile(sets, cards, fileName); + + return parser.saveToFile(createDefaultMagicFormats(), sets, cards, fileName); + } + + FormatRulesNameMap createDefaultMagicFormats() + { + // Predefined common exceptions + CardCondition superTypeIsBasic; + superTypeIsBasic.field = "type"; + superTypeIsBasic.matchType = "contains"; + superTypeIsBasic.value = "Basic Land"; + + ExceptionRule basicLands; + basicLands.conditions.append(superTypeIsBasic); + + CardCondition anyNumberAllowed; + anyNumberAllowed.field = "text"; + anyNumberAllowed.matchType = "contains"; + anyNumberAllowed.value = "A deck can have any number of"; + + ExceptionRule mayContainAnyNumber; + mayContainAnyNumber.conditions.append(anyNumberAllowed); + + // Map to store default rules + FormatRulesNameMap defaultFormatRulesNameMap; + + // ----------------- Helper lambda to create format ----------------- + auto makeFormat = [&](const QString &name, int minDeck = 60, int maxDeck = -1, int maxSideboardSize = 15, + const QList &allowedCounts = kConstructedCounts) -> FormatRulesPtr { + FormatRulesPtr f(new FormatRules); + f->formatName = name; + f->allowedCounts = allowedCounts; + f->minDeckSize = minDeck; + f->maxDeckSize = maxDeck; + f->maxSideboardSize = maxSideboardSize; + f->exceptions.append(basicLands); + f->exceptions.append(mayContainAnyNumber); + defaultFormatRulesNameMap.insert(name.toLower(), f); + return f; + }; + + // ----------------- Standard formats ----------------- + makeFormat("Standard"); + makeFormat("Modern"); + makeFormat("Legacy"); + makeFormat("Pioneer"); + makeFormat("Historic"); + makeFormat("Timeless"); + makeFormat("Future"); + makeFormat("OldSchool"); + makeFormat("Premodern"); + makeFormat("Pauper"); + makeFormat("Penny"); + + // ----------------- Singleton formats ----------------- + makeFormat("Commander", 100, 100, 15, kSingletonCounts); + makeFormat("Duel", 100, 100, 15, kSingletonCounts); + makeFormat("Brawl", 60, 60, 15, kSingletonCounts); + makeFormat("StandardBrawl", 60, 60, 15, kSingletonCounts); + makeFormat("Oathbreaker", 60, 60, 15, kSingletonCounts); + makeFormat("PauperCommander", 100, 100, 15, kSingletonCounts); + makeFormat("Predh", 100, 100, 15, kSingletonCounts); + + // ----------------- Restricted formats ----------------- + makeFormat("Vintage", 60, -1, 15, {{4, "legal"}, {1, "restricted"}, {0, "banned"}}); + + return defaultFormatRulesNameMap; } }; diff --git a/libcockatrice_card/CMakeLists.txt b/libcockatrice_card/CMakeLists.txt index 857376163..f516cde00 100644 --- a/libcockatrice_card/CMakeLists.txt +++ b/libcockatrice_card/CMakeLists.txt @@ -41,6 +41,8 @@ add_library( libcockatrice/card/relation/card_relation.cpp libcockatrice/card/set/card_set.cpp libcockatrice/card/set/card_set_list.cpp + libcockatrice/card/format/format_legality_rules.cpp + libcockatrice/card/format/format_legality_rules.h ) target_include_directories( diff --git a/libcockatrice_card/libcockatrice/card/card_info.h b/libcockatrice_card/libcockatrice/card/card_info.h index 7bd51356c..00e8fec37 100644 --- a/libcockatrice_card/libcockatrice/card/card_info.h +++ b/libcockatrice_card/libcockatrice/card/card_info.h @@ -1,6 +1,7 @@ #ifndef CARD_INFO_H #define CARD_INFO_H +#include "format/format_legality_rules.h" #include "printing/printing_info.h" #include @@ -22,10 +23,12 @@ class ICardDatabaseParser; typedef QSharedPointer CardInfoPtr; typedef QSharedPointer CardSetPtr; +typedef QSharedPointer FormatRulesPtr; typedef QMap> SetToPrintingsMap; typedef QHash CardNameMap; typedef QHash SetNameMap; +typedef QHash FormatRulesNameMap; Q_DECLARE_METATYPE(CardInfoPtr) diff --git a/libcockatrice_card/libcockatrice/card/database/card_database.cpp b/libcockatrice_card/libcockatrice/card/database/card_database.cpp index 2e977901f..de84ad814 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database.cpp +++ b/libcockatrice_card/libcockatrice/card/database/card_database.cpp @@ -199,3 +199,8 @@ void CardDatabase::notifyEnabledSetsChanged() // inform the carddatabasemodels that they need to re-check their list of cards emit cardDatabaseEnabledSetsChanged(); } + +void CardDatabase::addFormat(FormatRulesPtr format) +{ + formats.insert(format->formatName.toLower(), format); +} \ No newline at end of file diff --git a/libcockatrice_card/libcockatrice/card/database/card_database.h b/libcockatrice_card/libcockatrice/card/database/card_database.h index 6028cce86..7f8fc39db 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database.h +++ b/libcockatrice_card/libcockatrice/card/database/card_database.h @@ -42,6 +42,8 @@ protected: /// Sets indexed by short name SetNameMap sets; + FormatRulesNameMap formats; + /// Loader responsible for file discovery and parsing CardDatabaseLoader *loader; @@ -141,6 +143,8 @@ public slots: */ void addSet(CardSetPtr set); + void addFormat(FormatRulesPtr format); + /** @brief Loads card databases from configured paths. */ void loadCardDatabases(); diff --git a/libcockatrice_card/libcockatrice/card/database/card_database_loader.cpp b/libcockatrice_card/libcockatrice/card/database/card_database_loader.cpp index f56f6a0b5..91bb4c741 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database_loader.cpp +++ b/libcockatrice_card/libcockatrice/card/database/card_database_loader.cpp @@ -23,6 +23,7 @@ CardDatabaseLoader::CardDatabaseLoader(QObject *parent, // connect parser outputs to the database adders connect(p, &ICardDatabaseParser::addCard, database, &CardDatabase::addCard, Qt::DirectConnection); connect(p, &ICardDatabaseParser::addSet, database, &CardDatabase::addSet, Qt::DirectConnection); + connect(p, &ICardDatabaseParser::addFormat, database, &CardDatabase::addFormat, Qt::DirectConnection); } // when SettingsCache's path changes, trigger reloads @@ -149,6 +150,6 @@ bool CardDatabaseLoader::saveCustomTokensToFile() } } - availableParsers.first()->saveToFile(tmpSets, tmpCards, fileName); + availableParsers.first()->saveToFile(FormatRulesNameMap(), tmpSets, tmpCards, fileName); return true; } diff --git a/libcockatrice_card/libcockatrice/card/database/card_database_querier.cpp b/libcockatrice_card/libcockatrice/card/database/card_database_querier.cpp index 65999e590..b2a675b99 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database_querier.cpp +++ b/libcockatrice_card/libcockatrice/card/database/card_database_querier.cpp @@ -341,4 +341,27 @@ QMap CardDatabaseQuerier::getAllSubCardTypesWithCount() const } return typeCounts; +} + +FormatRulesPtr CardDatabaseQuerier::getFormat(const QString &formatName) const +{ + return db->formats.value(formatName.toLower()); +} + +QMap CardDatabaseQuerier::getAllFormatsWithCount() const +{ + QMap formatCounts; + + for (const auto &card : db->cards.values()) { + QStringList allProps = card->getProperties(); + + for (const QString &prop : allProps) { + if (prop.startsWith("format-")) { + QString formatName = prop.mid(QStringLiteral("format-").size()); + formatCounts[formatName]++; + } + } + } + + return formatCounts; } \ No newline at end of file diff --git a/libcockatrice_card/libcockatrice/card/database/card_database_querier.h b/libcockatrice_card/libcockatrice/card/database/card_database_querier.h index d9a980f06..ff8d7958b 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database_querier.h +++ b/libcockatrice_card/libcockatrice/card/database/card_database_querier.h @@ -214,6 +214,8 @@ public: * @return Map of subtype string to count. */ [[nodiscard]] QMap getAllSubCardTypesWithCount() const; + FormatRulesPtr getFormat(const QString &formatName) const; + QMap getAllFormatsWithCount() const; private: const CardDatabase *db; //!< Card database used for all lookups. 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 35012dbc5..93d46a3cc 100644 --- a/libcockatrice_card/libcockatrice/card/database/parser/card_database_parser.h +++ b/libcockatrice_card/libcockatrice/card/database/parser/card_database_parser.h @@ -38,6 +38,7 @@ public: /** * @brief Saves card and set data to a file. + * @param _formats * @param sets Map of sets to save. * @param cards Map of cards to save. * @param fileName Target file path. @@ -45,7 +46,8 @@ public: * @param sourceVersion Optional version string of the source. * @return true if save succeeded. */ - virtual bool saveToFile(SetNameMap sets, + virtual bool saveToFile(FormatRulesNameMap _formats, + SetNameMap sets, CardNameMap cards, const QString &fileName, const QString &sourceUrl = "unknown", @@ -79,6 +81,8 @@ signals: /** Emitted when a set is loaded from the database. */ void addSet(CardSetPtr set); + + void addFormat(FormatRulesPtr format); }; Q_DECLARE_INTERFACE(ICardDatabaseParser, "ICardDatabaseParser") diff --git a/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_3.cpp b/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_3.cpp index 35e2f3d83..9df396c74 100644 --- a/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_3.cpp +++ b/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_3.cpp @@ -438,12 +438,15 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfoPtr &in return xml; } -bool CockatriceXml3Parser::saveToFile(SetNameMap _sets, +bool CockatriceXml3Parser::saveToFile(FormatRulesNameMap _formats, + SetNameMap _sets, CardNameMap cards, const QString &fileName, const QString &sourceUrl, const QString &sourceVersion) { + Q_UNUSED(_formats); + QFile file(fileName); if (!file.open(QIODevice::WriteOnly)) { return false; 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 a727561ea..c3a261739 100644 --- a/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_3.h +++ b/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_3.h @@ -46,7 +46,8 @@ public: /** * @brief Save sets and cards back to an XML3 file. */ - bool saveToFile(SetNameMap _sets, + bool saveToFile(FormatRulesNameMap _formats, + SetNameMap _sets, CardNameMap cards, const QString &fileName, const QString &sourceUrl = "unknown", 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 ab4c8002d..0d46aad0f 100644 --- a/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_4.cpp +++ b/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_4.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #define COCKATRICE_XML4_TAGNAME "cockatrice_carddatabase" @@ -60,7 +61,9 @@ void CockatriceXml4Parser::parseFile(QIODevice &device) } auto xmlName = xml.name().toString(); - if (xmlName == "sets") { + if (xmlName == "formats") { + loadFormats(xml); + } else if (xmlName == "sets") { loadSetsFromXml(xml); } else if (xmlName == "cards") { loadCardsFromXml(xml); @@ -78,6 +81,116 @@ void CockatriceXml4Parser::parseFile(QIODevice &device) } } +static QSharedPointer parseFormat(QXmlStreamReader &xml) +{ + auto rulesPtr = FormatRulesPtr(new FormatRules()); + + if (xml.attributes().hasAttribute("formatName")) { + rulesPtr->formatName = xml.attributes().value("formatName").toString(); + } + + while (!xml.atEnd()) { + auto token = xml.readNext(); + + if (token == QXmlStreamReader::EndElement && xml.name().toString() == "format") { + break; + } + + if (token != QXmlStreamReader::StartElement) { + continue; + } + + QString xmlName = xml.name().toString(); + + if (xmlName == "minDeckSize") { + rulesPtr->minDeckSize = xml.readElementText().toInt(); + } else if (xmlName == "maxDeckSize") { + QString text = xml.readElementText(); + rulesPtr->maxDeckSize = text.toInt(); + } else if (xmlName == "maxSideboardSize") { + rulesPtr->maxSideboardSize = xml.readElementText().toInt(); + } else if (xmlName == "allowedCounts") { + while (!xml.atEnd()) { + token = xml.readNext(); + + if (token == QXmlStreamReader::EndElement && xml.name().toString() == "allowedCounts") { + break; + } + + if (token == QXmlStreamReader::StartElement && xml.name().toString() == "count") { + + AllowedCount c; + + QString maxAttr = xml.attributes().value("max").toString(); + c.max = (maxAttr == "unlimited") ? -1 : maxAttr.toInt(); + + c.label = xml.readElementText().trimmed(); + + rulesPtr->allowedCounts.append(c); + } + } + } else if (xmlName == "exceptions") { + while (!xml.atEnd()) { + token = xml.readNext(); + + if (token == QXmlStreamReader::EndElement && xml.name().toString() == "exceptions") { + break; + } + + if (token == QXmlStreamReader::StartElement && xml.name().toString() == "exception") { + ExceptionRule ex; + + while (!xml.atEnd()) { + token = xml.readNext(); + + if (token == QXmlStreamReader::EndElement && xml.name().toString() == "exception") { + break; + } + + if (token == QXmlStreamReader::StartElement) { + QString ename = xml.name().toString(); + + if (ename == "maxCopies") { + QString text = xml.readElementText(); + ex.maxCopies = (text == "unlimited") ? -1 : text.toInt(); + } else if (ename == "cardCondition") { + CardCondition cond; + cond.field = xml.attributes().value("field").toString(); + cond.matchType = xml.attributes().value("match").toString(); + cond.value = xml.attributes().value("value").toString(); + ex.conditions.append(cond); + xml.skipCurrentElement(); + } else { + xml.skipCurrentElement(); + } + } + } + + rulesPtr->exceptions.append(ex); + } + } + } else { + xml.skipCurrentElement(); + } + } + + return rulesPtr; +} + +void CockatriceXml4Parser::loadFormats(QXmlStreamReader &xml) +{ + while (!xml.atEnd()) { + if (xml.readNext() == QXmlStreamReader::EndElement) { + break; + } + + if (xml.name().toString() == "format") { + auto rulesPtr = parseFormat(xml); + emit addFormat(rulesPtr); + } + } +} + void CockatriceXml4Parser::loadSetsFromXml(QXmlStreamReader &xml) { while (!xml.atEnd()) { @@ -273,6 +386,59 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml) } } +static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const QSharedPointer &rulesPtr) +{ + if (rulesPtr.isNull()) { + qCWarning(CockatriceXml4Log) << "&operator<< FormatRules is nullptr"; + return xml; + } + + const FormatRules &rules = *rulesPtr; + + xml.writeStartElement("format"); + if (!rules.formatName.isEmpty()) { + xml.writeAttribute("formatName", rules.formatName); + } + + xml.writeTextElement("minDeckSize", QString::number(rules.minDeckSize)); + xml.writeTextElement("maxDeckSize", rules.maxDeckSize >= 0 ? QString::number(rules.maxDeckSize) : "0"); + xml.writeTextElement("maxSideboardSize", QString::number(rules.maxSideboardSize)); + if (!rules.allowedCounts.isEmpty()) { + xml.writeStartElement("allowedCounts"); + + for (const AllowedCount &c : rules.allowedCounts) { + xml.writeStartElement("count"); + xml.writeAttribute("max", c.max == -1 ? "unlimited" : QString::number(c.max)); + xml.writeCharacters(c.label); + xml.writeEndElement(); // count + } + + xml.writeEndElement(); // allowedCounts + } + + if (!rules.exceptions.isEmpty()) { + xml.writeStartElement("exceptions"); + for (const ExceptionRule &ex : rules.exceptions) { + xml.writeStartElement("exception"); + xml.writeTextElement("maxCopies", ex.maxCopies == -1 ? "unlimited" : QString::number(ex.maxCopies)); + + for (const CardCondition &cond : ex.conditions) { + xml.writeStartElement("cardCondition"); + xml.writeAttribute("field", cond.field); + xml.writeAttribute("match", cond.matchType); + xml.writeAttribute("value", cond.value); + xml.writeEndElement(); // cardCondition + } + + xml.writeEndElement(); // exception + } + xml.writeEndElement(); // exceptions + } + + xml.writeEndElement(); // format + return xml; +} + static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardSetPtr &set) { if (set.isNull()) { @@ -399,7 +565,8 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfoPtr &in return xml; } -bool CockatriceXml4Parser::saveToFile(SetNameMap _sets, +bool CockatriceXml4Parser::saveToFile(FormatRulesNameMap _formats, + SetNameMap _sets, CardNameMap cards, const QString &fileName, const QString &sourceUrl, @@ -426,6 +593,14 @@ bool CockatriceXml4Parser::saveToFile(SetNameMap _sets, xml.writeTextElement("sourceVersion", sourceVersion); xml.writeEndElement(); + if (_formats.count() > 0) { + xml.writeStartElement("formats"); + for (FormatRulesPtr format : _formats) { + xml << format; + } + xml.writeEndElement(); + } + if (_sets.count() > 0) { xml.writeStartElement("sets"); for (CardSetPtr set : _sets) { 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 b83f6929e..5b47e9090 100644 --- a/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_4.h +++ b/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_4.h @@ -49,7 +49,8 @@ public: /** * @brief Save sets and cards back to an XML4 file. */ - bool saveToFile(SetNameMap _sets, + bool saveToFile(FormatRulesNameMap _formats, + SetNameMap _sets, CardNameMap cards, const QString &fileName, const QString &sourceUrl = "unknown", @@ -72,6 +73,7 @@ private: */ void loadCardsFromXml(QXmlStreamReader &xml); + void loadFormats(QXmlStreamReader &xml); /** * @brief Load all elements from the XML stream. * @param xml The open QXmlStreamReader positioned at the element. diff --git a/libcockatrice_card/libcockatrice/card/format/format_legality_rules.cpp b/libcockatrice_card/libcockatrice/card/format/format_legality_rules.cpp new file mode 100644 index 000000000..a6b3bb038 --- /dev/null +++ b/libcockatrice_card/libcockatrice/card/format/format_legality_rules.cpp @@ -0,0 +1,53 @@ +#include "format_legality_rules.h" + +#include + +bool cardMatchesCondition(const CardInfo &card, const CardCondition &cond) +{ + CardMatchType type = matchTypeFromString(cond.matchType); + QString fieldValue; + if (cond.field == "name") { + fieldValue = card.getName(); + } else if (cond.field == "text") { + fieldValue = card.getText(); + } else { + fieldValue = card.getProperty(cond.field); + } + + switch (type) { + case CardMatchType::Equals: + return fieldValue == cond.value; + case CardMatchType::NotEquals: + return fieldValue != cond.value; + case CardMatchType::Contains: + return fieldValue.contains(cond.value, Qt::CaseInsensitive); + case CardMatchType::NotContains: + return !fieldValue.contains(cond.value, Qt::CaseInsensitive); + case CardMatchType::Regex: { + QRegularExpression re(cond.value, QRegularExpression::CaseInsensitiveOption); + return re.match(fieldValue).hasMatch(); + } + default: + return false; + } +} + +bool exceptionAppliesToCard(const CardInfo &card, const ExceptionRule &rule) +{ + for (const CardCondition &cond : rule.conditions) { + if (!cardMatchesCondition(card, cond)) { + return false; // all conditions must match + } + } + return true; +} + +bool cardHasAnyException(const CardInfo &card, const FormatRules &format) +{ + for (const ExceptionRule &rule : format.exceptions) { + if (exceptionAppliesToCard(card, rule)) { + return true; + } + } + return false; +} \ No newline at end of file diff --git a/libcockatrice_card/libcockatrice/card/format/format_legality_rules.h b/libcockatrice_card/libcockatrice/card/format/format_legality_rules.h new file mode 100644 index 000000000..16f2359ab --- /dev/null +++ b/libcockatrice_card/libcockatrice/card/format/format_legality_rules.h @@ -0,0 +1,73 @@ +#ifndef COCKATRICE_FORMAT_LEGALITY_RULES_H +#define COCKATRICE_FORMAT_LEGALITY_RULES_H + +#include +#include +#include + +class CardInfo; +using CardInfoPtr = QSharedPointer; + +struct CardCondition +{ + QString field; // e.g. "type", "maintype", "text" + QString matchType; // "contains", "equals", "regex", "notContains", etc. + QString value; // e.g. "Basic Land" +}; + +struct AllowedCount +{ + int max = 0; // 4, 1, 0, or -1 for unlimited + QString label; // "legal", "restricted", "banned" +}; + +struct ExceptionRule +{ + QList conditions; // All must match + int maxCopies = -1; // -1 = unlimited +}; + +struct FormatRules +{ + QString formatName; + int minDeckSize = 60; + int maxDeckSize = -1; // -1 = unlimited + int maxSideboardSize = 15; + + QList allowedCounts; + + QList exceptions; // Cards allowed to break maxCopies +}; + +enum class CardMatchType +{ + Equals, + NotEquals, + Contains, + NotContains, + Regex +}; + +// convert string to enum +inline CardMatchType matchTypeFromString(const QString &str) +{ + if (str == "equals") + return CardMatchType::Equals; + if (str == "notEquals") + return CardMatchType::NotEquals; + if (str == "contains") + return CardMatchType::Contains; + if (str == "notContains") + return CardMatchType::NotContains; + if (str == "regex") + return CardMatchType::Regex; + return CardMatchType::Equals; // fallback default +} + +bool cardMatchesCondition(const CardInfo &card, const CardCondition &cond); + +bool exceptionAppliesToCard(const CardInfo &card, const ExceptionRule &rule); + +bool cardHasAnyException(const CardInfo &card, const FormatRules &format); + +#endif // COCKATRICE_FORMAT_LEGALITY_RULES_H diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp index 333be017b..09326e619 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp @@ -136,6 +136,8 @@ bool DeckList::readElement(QXmlStreamReader *xml) metadata.lastLoadedTimestamp = xml->readElementText(); } else if (childName == "deckname") { metadata.name = xml->readElementText(); + } else if (childName == "format") { + metadata.gameFormat = xml->readElementText(); } else if (childName == "comments") { metadata.comments = xml->readElementText(); } else if (childName == "bannerCard") { @@ -170,6 +172,7 @@ void writeMetadata(QXmlStreamWriter *xml, const DeckList::Metadata &metadata) { xml->writeTextElement("lastLoadedTimestamp", metadata.lastLoadedTimestamp); xml->writeTextElement("deckname", metadata.name); + xml->writeTextElement("format", metadata.gameFormat); xml->writeStartElement("bannerCard"); xml->writeAttribute("providerId", metadata.bannerCard.providerId); xml->writeCharacters(metadata.bannerCard.name); @@ -594,15 +597,16 @@ DecklistCardNode *DeckList::addCard(const QString &cardName, const int position, const QString &cardSetName, const QString &cardSetCollectorNumber, - const QString &cardProviderId) + const QString &cardProviderId, + const bool formatLegal) { auto *zoneNode = dynamic_cast(root->findChild(zoneName)); if (zoneNode == nullptr) { zoneNode = new InnerDecklistNode(zoneName, root); } - auto *node = - new DecklistCardNode(cardName, 1, zoneNode, position, cardSetName, cardSetCollectorNumber, cardProviderId); + auto *node = new DecklistCardNode(cardName, 1, zoneNode, position, cardSetName, cardSetCollectorNumber, + cardProviderId, formatLegal); refreshDeckHash(); return node; diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h index 6f90b6b14..e4206ebc6 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h @@ -126,6 +126,7 @@ public: { QString name; ///< User-defined deck name. QString comments; ///< Free-form comments or notes. + QString gameFormat; ///< The name of the game format this deck contains legal cards for CardRef bannerCard; ///< Optional representative card for the deck. QStringList tags; ///< User-defined tags for deck classification. QString lastLoadedTimestamp; ///< Timestamp string of last load. @@ -181,6 +182,10 @@ public: { metadata.lastLoadedTimestamp = _lastLoadedTimestamp; } + void setGameFormat(const QString &_gameFormat = QString()) + { + metadata.gameFormat = _gameFormat; + } ///@} /// @brief Construct an empty deck. @@ -219,6 +224,10 @@ public: { return metadata.lastLoadedTimestamp; } + QString getGameFormat() const + { + return metadata.gameFormat; + } ///@} bool isBlankDeck() const @@ -277,7 +286,8 @@ public: int position, const QString &cardSetName = QString(), const QString &cardSetCollectorNumber = QString(), - const QString &cardProviderId = QString()); + const QString &cardProviderId = QString(), + const bool formatLegal = true); bool deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode = nullptr); ///@} diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_card_node.h b/libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_card_node.h index 1d201a4c1..88d8b0930 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_card_node.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_card_node.h @@ -88,6 +88,12 @@ public: /// @param _cardSetNumber Set the collector number. virtual void setCardCollectorNumber(const QString &_cardSetNumber) = 0; + /// @return The format legality of the card + virtual bool getFormatLegality() const = 0; + + /// @param _formatLegal If the card is considered legal + virtual void setFormatLegality(const bool _formatLegal) = 0; + /** * @brief Get the height of this node in the tree. * diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/tree/deck_list_card_node.h b/libcockatrice_deck_list/libcockatrice/deck_list/tree/deck_list_card_node.h index c2fe038e6..b3d42b89a 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/tree/deck_list_card_node.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/tree/deck_list_card_node.h @@ -51,6 +51,7 @@ class DecklistCardNode : public AbstractDecklistCardNode QString cardSetShortName; ///< Short set code (e.g., "NEO"). QString cardSetNumber; ///< Collector number within the set. QString cardProviderId; ///< External provider identifier (e.g., UUID). + bool formatLegal; ///< Format legality public: /** @@ -63,6 +64,7 @@ public: * @param _cardSetShortName Short set code (e.g., "NEO"). * @param _cardSetNumber Collector number within the set. * @param _cardProviderId External provider ID (e.g., UUID). + * @param _formatLegality If the card is legal in the format * * On construction, if a parent is provided, this node is inserted into * the parent’s children list automatically. @@ -73,10 +75,11 @@ public: int position = -1, QString _cardSetShortName = QString(), QString _cardSetNumber = QString(), - QString _cardProviderId = QString()) + QString _cardProviderId = QString(), + bool _formatLegality = true) : AbstractDecklistCardNode(_parent, position), name(std::move(_name)), number(_number), cardSetShortName(std::move(_cardSetShortName)), cardSetNumber(std::move(_cardSetNumber)), - cardProviderId(std::move(_cardProviderId)) + cardProviderId(std::move(_cardProviderId)), formatLegal(_formatLegality) { } @@ -150,6 +153,18 @@ public: cardSetNumber = _cardSetNumber; } + /// @return The format legality of the card + [[nodiscard]] bool getFormatLegality() const override + { + return formatLegal; + } + + /// @param _formatLegal If the card is considered legal + void setFormatLegality(const bool _formatLegal) override + { + formatLegal = _formatLegal; + } + /// @return Always false; card nodes are not deck headers. [[nodiscard]] bool isDeckHeader() const override { 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 2856198b8..05ee480a5 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.cpp +++ b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.cpp @@ -168,6 +168,10 @@ QVariant DeckListModel::data(const QModelIndex &index, int role) const return card->depth(); } + case DeckRoles::IsLegalRole: { + return card->getFormatLegality(); + } + default: { return {}; } @@ -268,6 +272,7 @@ bool DeckListModel::setData(const QModelIndex &index, const QVariant &value, con switch (index.column()) { case DeckListModelColumns::CARD_AMOUNT: node->setNumber(value.toInt()); + refreshCardFormatLegalities(); break; case DeckListModelColumns::CARD_NAME: node->setName(value.toString()); @@ -414,8 +419,9 @@ QModelIndex DeckListModel::addCard(const ExactCard &card, const QString &zoneNam // Determine the correct index int insertRow = findSortedInsertRow(groupNode, cardInfo); - auto *decklistCard = deckList->addCard(cardInfo->getName(), zoneName, insertRow, cardSetName, - printingInfo.getProperty("num"), printingInfo.getProperty("uuid")); + auto *decklistCard = + deckList->addCard(cardInfo->getName(), zoneName, insertRow, cardSetName, printingInfo.getProperty("num"), + printingInfo.getProperty("uuid"), isCardLegalForCurrentFormat(cardInfo)); beginInsertRows(parentIndex, insertRow, insertRow); cardNode = new DecklistModelCardNode(decklistCard, groupNode, insertRow); @@ -532,6 +538,13 @@ void DeckListModel::setActiveGroupCriteria(DeckListModelGroupCriteria::Type newC rebuildTree(); } +void DeckListModel::setActiveFormat(const QString &_format) +{ + deckList->setGameFormat(_format); + refreshCardFormatLegalities(); + emitBackgroundUpdates(QModelIndex()); // start from root +} + void DeckListModel::cleanList() { setDeckList(new DeckList); @@ -595,4 +608,90 @@ QList DeckListModel::getZones() const [](auto zoneNode) { return zoneNode->getName(); }); return zones; -} \ No newline at end of file +} + +bool DeckListModel::isCardLegalForCurrentFormat(const CardInfoPtr cardInfo) +{ + if (!deckList->getGameFormat().isEmpty()) { + if (cardInfo->getProperties().contains("format-" + deckList->getGameFormat())) { + QString formatLegality = cardInfo->getProperty("format-" + deckList->getGameFormat()); + return formatLegality == "legal" || formatLegality == "restricted"; + } + return false; + } + return true; +} + +int maxAllowedForLegality(const FormatRules &format, const QString &legality) +{ + for (const AllowedCount &c : format.allowedCounts) { + if (c.label == legality) { + return c.max; + } + } + return -1; // unknown legality → treat as illegal +} + + +bool DeckListModel::isCardQuantityLegalForCurrentFormat(const CardInfoPtr cardInfo, int quantity) +{ + auto formatRules = CardDatabaseManager::query()->getFormat(deckList->getGameFormat()); + + if (!formatRules) { + return true; + } + + // Exceptions always win + if (cardHasAnyException(*cardInfo, *formatRules)) { + return true; + } + + const QString legalityProp = "format-" + deckList->getGameFormat(); + if (!cardInfo->getProperties().contains(legalityProp)) { + return false; + } + + const QString legality = cardInfo->getProperty(legalityProp); + + int maxAllowed = maxAllowedForLegality(*formatRules, legality); + + if (maxAllowed == -1) { + return false; + } + + if (maxAllowed < 0) { // unlimited + return true; + } + + return quantity <= maxAllowed; +} + +void DeckListModel::refreshCardFormatLegalities() +{ + InnerDecklistNode *listRoot = deckList->getRoot(); + + for (int i = 0; i < listRoot->size(); i++) { + auto *currentZone = static_cast(listRoot->at(i)); + for (int j = 0; j < currentZone->size(); j++) { + auto *currentCard = static_cast(currentZone->at(j)); + + // TODO: better sanity checking + if (currentCard == nullptr) { + continue; + } + + ExactCard exactCard = CardDatabaseManager::query()->getCard(currentCard->toCardRef()); + if (!exactCard) { + continue; + } + + bool legal = isCardLegalForCurrentFormat(exactCard.getCardPtr()); + + if (legal) { + legal = isCardQuantityLegalForCurrentFormat(exactCard.getCardPtr(), currentCard->getNumber()); + } + + currentCard->setFormatLegality(legal); + } + } +} 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 0b47faed4..c03497bd5 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h +++ b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h @@ -164,6 +164,14 @@ public: { dataNode->setCardCollectorNumber(_cardSetNumber); } + bool getFormatLegality() const override + { + return dataNode->getFormatLegality(); + } + void setFormatLegality(const bool _formatLegal) override + { + dataNode->setFormatLegality(_formatLegal); + } /** * @brief Returns the underlying data node. @@ -209,6 +217,9 @@ public slots: */ void rebuildTree(); +public slots: + void setActiveFormat(const QString &_format); + signals: /** * @brief Emitted whenever the deck hash changes due to modifications in the model. @@ -301,6 +312,9 @@ public: [[nodiscard]] QList getCards() const; [[nodiscard]] QList getCardsForZone(const QString &zoneName) const; [[nodiscard]] QList getZones() const; + bool isCardLegalForCurrentFormat(CardInfoPtr cardInfo); + bool isCardQuantityLegalForCurrentFormat(CardInfoPtr cardInfo, int quantity); + void refreshCardFormatLegalities(); /** * @brief Sets the criteria used to group cards in the model. diff --git a/oracle/src/oracleimporter.cpp b/oracle/src/oracleimporter.cpp index f316e439d..813df49ae 100644 --- a/oracle/src/oracleimporter.cpp +++ b/oracle/src/oracleimporter.cpp @@ -13,6 +13,10 @@ #include #include +static const QList kConstructedCounts = {{4, "legal"}, {0, "banned"}}; + +static const QList kSingletonCounts = {{1, "legal"}, {0, "banned"}}; + SplitCardPart::SplitCardPart(const QString &_name, const QString &_text, const QVariantHash &_properties, @@ -463,6 +467,71 @@ int OracleImporter::importCardsFromSet(const CardSetPtr ¤tSet, const QList return numCards; } +FormatRulesNameMap OracleImporter::createDefaultMagicFormats() +{ + // Predefined common exceptions + CardCondition superTypeIsBasic; + superTypeIsBasic.field = "type"; + superTypeIsBasic.matchType = "contains"; + superTypeIsBasic.value = "Basic Land"; + + ExceptionRule basicLands; + basicLands.conditions.append(superTypeIsBasic); + + CardCondition anyNumberAllowed; + anyNumberAllowed.field = "text"; + anyNumberAllowed.matchType = "contains"; + anyNumberAllowed.value = "A deck can have any number of"; + + ExceptionRule mayContainAnyNumber; + mayContainAnyNumber.conditions.append(anyNumberAllowed); + + // Map to store default rules + FormatRulesNameMap defaultFormatRulesNameMap; + + // ----------------- Helper lambda to create format ----------------- + auto makeFormat = [&](const QString &name, int minDeck = 60, int maxDeck = -1, int maxSideboardSize = 15, + const QList &allowedCounts = kConstructedCounts) -> FormatRulesPtr { + FormatRulesPtr f(new FormatRules); + f->formatName = name; + f->allowedCounts = allowedCounts; + f->minDeckSize = minDeck; + f->maxDeckSize = maxDeck; + f->maxSideboardSize = maxSideboardSize; + f->exceptions.append(basicLands); + f->exceptions.append(mayContainAnyNumber); + defaultFormatRulesNameMap.insert(name.toLower(), f); + return f; + }; + + // ----------------- Standard formats ----------------- + makeFormat("Standard"); + makeFormat("Modern"); + makeFormat("Legacy"); + makeFormat("Pioneer"); + makeFormat("Historic"); + makeFormat("Timeless"); + makeFormat("Future"); + makeFormat("OldSchool"); + makeFormat("Premodern"); + makeFormat("Pauper"); + makeFormat("Penny"); + + // ----------------- Singleton formats ----------------- + makeFormat("Commander", 100, 100, 15, kSingletonCounts); + makeFormat("Duel", 100, 100, 15, kSingletonCounts); + makeFormat("Brawl", 60, 60, 15, kSingletonCounts); + makeFormat("StandardBrawl", 60, 60, 15, kSingletonCounts); + makeFormat("Oathbreaker", 60, 60, 15, kSingletonCounts); + makeFormat("PauperCommander", 100, 100, 15, kSingletonCounts); + makeFormat("Predh", 100, 100, 15, kSingletonCounts); + + // ----------------- Restricted formats ----------------- + makeFormat("Vintage", 60, -1, 15, {{4, "legal"}, {1, "restricted"}, {0, "banned"}}); + + return defaultFormatRulesNameMap; +} + int OracleImporter::startImport() { static ICardSetPriorityController *noOpController = new NoopCardSetPriorityController(); @@ -497,7 +566,8 @@ int OracleImporter::startImport() bool OracleImporter::saveToFile(const QString &fileName, const QString &sourceUrl, const QString &sourceVersion) { CockatriceXml4Parser parser(new NoopCardPreferenceProvider()); - return parser.saveToFile(sets, cards, fileName, sourceUrl, sourceVersion); + + return parser.saveToFile(createDefaultMagicFormats(), sets, cards, fileName, sourceUrl, sourceVersion); } void OracleImporter::clear() diff --git a/oracle/src/oracleimporter.h b/oracle/src/oracleimporter.h index 3ec6da6e1..e83958d73 100644 --- a/oracle/src/oracleimporter.h +++ b/oracle/src/oracleimporter.h @@ -154,6 +154,7 @@ public: int startImport(); bool saveToFile(const QString &fileName, const QString &sourceUrl, const QString &sourceVersion); int importCardsFromSet(const CardSetPtr ¤tSet, const QList &cardsList); + FormatRulesNameMap createDefaultMagicFormats(); const CardNameMap &getCardList() const { return cards;