diff --git a/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.cpp b/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.cpp index 324cc7288..4cfd9447d 100644 --- a/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.cpp +++ b/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.cpp @@ -6,7 +6,7 @@ #include DeckPreviewTagDisplayWidget::DeckPreviewTagDisplayWidget(QWidget *parent, const QString &_tagName) - : QWidget(parent), tagName(_tagName), isSelected(false) + : QWidget(parent), tagName(_tagName), state(TagState::NotSelected) { // Create layout auto *layout = new QHBoxLayout(this); @@ -48,36 +48,58 @@ QSize DeckPreviewTagDisplayWidget::sizeHint() const void DeckPreviewTagDisplayWidget::mousePressEvent(QMouseEvent *event) { - if (event->button() == Qt::LeftButton) { - setSelected(!isSelected); - emit tagClicked(); + switch (event->button()) { + case Qt::LeftButton: + setState(TagState::Selected); + break; + case Qt::RightButton: + setState(TagState::Excluded); + break; + case Qt::MiddleButton: + setState(TagState::NotSelected); + break; + default: + break; } - QWidget::mousePressEvent(event); -} -void DeckPreviewTagDisplayWidget::setSelected(bool selected) -{ - isSelected = selected; - update(); // Trigger a repaint + emit tagClicked(); + QWidget::mousePressEvent(event); } void DeckPreviewTagDisplayWidget::paintEvent(QPaintEvent *event) { QPainter painter(this); - // Set background color - QColor backgroundColor = isSelected ? QColor(173, 216, 230) : Qt::white; + QColor backgroundColor; + QColor borderColor; + int borderWidth; + + switch (state) { + case TagState::Selected: + backgroundColor = QColor(173, 216, 230); // Light blue + borderColor = Qt::blue; + borderWidth = 2; + break; + case TagState::Excluded: + backgroundColor = QColor(255, 182, 193); // Light red/pink + borderColor = Qt::red; + borderWidth = 2; + break; + case TagState::NotSelected: + default: + backgroundColor = Qt::white; + borderColor = Qt::gray; + borderWidth = 1; + break; + } + painter.setBrush(backgroundColor); painter.setPen(Qt::NoPen); - - // Draw background painter.drawRect(rect()); - // Draw border - QColor borderColor = isSelected ? Qt::blue : Qt::gray; - QPen borderPen(borderColor, isSelected ? 2 : 1); + QPen borderPen(borderColor, borderWidth); painter.setPen(borderPen); - painter.drawRect(rect().adjusted(0, 0, -1, -1)); // Adjust for pen width + painter.drawRect(rect().adjusted(0, 0, -1, -1)); // Calculate font size based on widget height QFont font = painter.font(); diff --git a/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.h b/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.h index 10cc39baf..ff649dd32 100644 --- a/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.h +++ b/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.h @@ -6,6 +6,13 @@ #include #include +enum class TagState +{ + NotSelected, + Selected, + Excluded +}; + class DeckPreviewTagDisplayWidget : public QWidget { Q_OBJECT @@ -22,16 +29,16 @@ public: { return tagName; } - bool getSelected() const + TagState getState() const { - return isSelected; + return state; } - /** - * @brief Sets the selected state of the tag. - * @param selected True if the tag is selected, false otherwise. - */ - void setSelected(bool selected); + void setState(const TagState newState) + { + state = newState; + update(); + }; signals: /** @@ -61,7 +68,7 @@ private: QLabel *tagLabel; ///< Label for displaying the tag name. QPushButton *closeButton; ///< Button to close/remove the tag. QString tagName; ///< The name of the tag. - bool isSelected; ///< Indicates whether the tag is selected. + TagState state; ///< Indicates whether the tag is unselected, selected, or excluded. }; #endif // DECK_PREVIEW_TAG_DISPLAY_WIDGET_H diff --git a/cockatrice/src/client/ui/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.cpp b/cockatrice/src/client/ui/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.cpp index 25cb5a1e5..47ed6ebee 100644 --- a/cockatrice/src/client/ui/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.cpp +++ b/cockatrice/src/client/ui/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.cpp @@ -33,32 +33,42 @@ void VisualDeckStorageTagFilterWidget::showEvent(QShowEvent *event) void VisualDeckStorageTagFilterWidget::filterDecksBySelectedTags(const QList &deckPreviews) const { - // Collect selected tags from DeckPreviewTagDisplayWidget QStringList selectedTags; + QStringList excludedTags; + + // Collect selected and excluded tags for (DeckPreviewTagDisplayWidget *tagWidget : findChildren()) { - if (tagWidget->getSelected()) { - selectedTags.append(tagWidget->getTagName()); + switch (tagWidget->getState()) { + case TagState::Selected: + selectedTags.append(tagWidget->getTagName()); + break; + case TagState::Excluded: + excludedTags.append(tagWidget->getTagName()); + break; + default: + break; } } - // If no tags are selected, set all decks as visible - if (selectedTags.isEmpty()) { + // If no tags are selected or excluded, show all + if (selectedTags.isEmpty() && excludedTags.isEmpty()) { for (DeckPreviewWidget *deckPreview : deckPreviews) { deckPreview->filteredByTags = false; } return; } - // Filter DeckPreviewWidgets that contain all of the selected tags - QList filteredDecks; for (DeckPreviewWidget *deckPreview : deckPreviews) { QStringList deckTags = deckPreview->deckLoader->getTags(); - // Check if all selectedTags are in deckTags - bool allTagsPresent = std::all_of(selectedTags.begin(), selectedTags.end(), + bool hasAllSelected = std::all_of(selectedTags.begin(), selectedTags.end(), [&deckTags](const QString &tag) { return deckTags.contains(tag); }); - deckPreview->filteredByTags = !allTagsPresent; + bool hasAnyExcluded = std::any_of(excludedTags.begin(), excludedTags.end(), + [&deckTags](const QString &tag) { return deckTags.contains(tag); }); + + // Filter out if any excluded tag is present or if any selected tag is missing + deckPreview->filteredByTags = !(hasAllSelected && !hasAnyExcluded); } } @@ -72,13 +82,15 @@ void VisualDeckStorageTagFilterWidget::refreshTags() void VisualDeckStorageTagFilterWidget::removeTagsNotInList(const QSet &tags) { - // Iterate through all DeckPreviewTagDisplayWidgets + auto *flowWidget = findChild(); + for (DeckPreviewTagDisplayWidget *tagWidget : findChildren()) { - // If the tag is not in the provided tags list, remove the widget - if (!tags.contains(tagWidget->getTagName())) { - auto *flowWidget = findChild(); + const QString &tagName = tagWidget->getTagName(); + + // Keep the tag widget if it is either selected or excluded + if (!tags.contains(tagName) && tagWidget->getState() == TagState::NotSelected) { flowWidget->removeWidget(tagWidget); - tagWidget->deleteLater(); // Safely delete the widget + tagWidget->deleteLater(); } } }