From 2b24b52cfc17a14b5d2e60fe28b91178aafe32f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Br=C3=BCbach?= Date: Mon, 7 Apr 2025 03:52:59 +0200 Subject: [PATCH] Update color filter logic to be proper and implement include/exclude mode. --- ...l_database_display_color_filter_widget.cpp | 173 +++++++++++++----- ...ual_database_display_color_filter_widget.h | 12 +- 2 files changed, 138 insertions(+), 47 deletions(-) diff --git a/cockatrice/src/client/ui/widgets/visual_database_display/visual_database_display_color_filter_widget.cpp b/cockatrice/src/client/ui/widgets/visual_database_display/visual_database_display_color_filter_widget.cpp index 5b08b09d5..de531394b 100644 --- a/cockatrice/src/client/ui/widgets/visual_database_display/visual_database_display_color_filter_widget.cpp +++ b/cockatrice/src/client/ui/widgets/visual_database_display/visual_database_display_color_filter_widget.cpp @@ -41,8 +41,12 @@ VisualDatabaseDisplayColorFilterWidget::VisualDatabaseDisplayColorFilterWidget(Q &VisualDatabaseDisplayColorFilterWidget::updateColorFilter); connect(this, &VisualDatabaseDisplayColorFilterWidget::filterModeChanged, this, &VisualDatabaseDisplayColorFilterWidget::updateColorFilter); - connect(filterModel, &FilterTreeModel::layoutChanged, this, - [this]() { QTimer::singleShot(100, this, &VisualDatabaseDisplayColorFilterWidget::syncWithFilterModel); }); + connect(filterModel, &FilterTreeModel::layoutChanged, this, [this]() { + if (blockSync) { + return; // Skip sync if we're blocking it + } + QTimer::singleShot(100, this, &VisualDatabaseDisplayColorFilterWidget::syncWithFilterModel); + }); // Call retranslateUi to set the initial text retranslateUi(); @@ -50,74 +54,152 @@ VisualDatabaseDisplayColorFilterWidget::VisualDatabaseDisplayColorFilterWidget(Q void VisualDatabaseDisplayColorFilterWidget::retranslateUi() { - // Set the toggle button text based on the current mode - toggleButton->setText(exactMatchMode ? tr("Mode: Exact Match") : tr("Mode: Includes")); + switch (currentMode) { + case FilterMode::ExactMatch: + toggleButton->setText(tr("Mode: Exact Match")); + break; + case FilterMode::Includes: + toggleButton->setText(tr("Mode: Includes")); + break; + case FilterMode::IncludeExclude: + toggleButton->setText(tr("Mode: Include/Exclude")); + break; + } } void VisualDatabaseDisplayColorFilterWidget::handleColorToggled(QChar color, bool active) { - activeColors[color] = active; - emit activeColorsChanged(); + switch (currentMode) { + case FilterMode::ExactMatch: + // In Exact Match Mode, only allow the selected colors + if (active) { + activeColors[color] = true; // Add color to the selected list + } else { + activeColors[color] = false; // Remove color from the selected list + } + break; + + case FilterMode::Includes: + // In Includes Mode, toggle the color freely (include selected colors) + activeColors[color] = active; + break; + + case FilterMode::IncludeExclude: + // In Include/Exclude Mode, toggle the color freely (include selected, exclude unselected) + if (active) { + activeColors[color] = true; // Include the color + } else { + activeColors[color] = false; // Exclude the color + } + break; + } + + emit activeColorsChanged(); // Notify listeners that the active colors have changed } void VisualDatabaseDisplayColorFilterWidget::updateColorFilter() { - // Clear existing filters related to color + blockSync = true; + + // Clear previous filters filterModel->clearFiltersOfType(CardFilter::Attr::AttrColor); - if (exactMatchMode) { - // Exact match: card must have ONLY the selected colors - QSet selectedColors; - for (const auto &color : activeColors.keys()) { - if (activeColors[color]) { - selectedColors.insert(color); - } - } + QSet selectedColors; + QSet excludedColors; - if (!selectedColors.isEmpty()) { - // Require all selected colors (TypeAnd) - for (const auto &color : selectedColors) { - QString colorString = color; - filterModel->addFilter( - new CardFilter(colorString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrColor)); - } - - // Exclude any other colors (TypeAndNot) - QStringList allPossibleColors = {"W", "U", "B", "R", "G"}; - for (const auto &color : allPossibleColors) { - if (!selectedColors.contains(color)) { - QString colorString = color; - filterModel->addFilter( - new CardFilter(colorString, CardFilter::Type::TypeAndNot, CardFilter::Attr::AttrColor)); - } - } - } - } else { - // Default includes mode (TypeAnd) - match any selected colors - for (const auto &color : activeColors.keys()) { - if (activeColors[color]) { // If the color is active - QString colorString = color; - filterModel->addFilter( - new CardFilter(colorString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrColor)); - } + // Collect active colors in the selected and excluded sets + for (const auto &color : activeColors.keys()) { + if (activeColors[color]) { + selectedColors.insert(color); // Include this color + } else { + excludedColors.insert(color); // Exclude this color } } + + switch (currentMode) { + case FilterMode::ExactMatch: + // Exact Match Mode: Only selected colors are allowed + if (!selectedColors.isEmpty()) { + // Require all selected colors (TypeAnd) + for (const auto &color : selectedColors) { + QString colorString = color; + filterModel->addFilter( + new CardFilter(colorString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrColor)); + } + + // Exclude all other colors + QStringList allPossibleColors = {"W", "U", "B", "R", "G"}; + for (const auto &color : allPossibleColors) { + if (!selectedColors.contains(color)) { + QString colorString = color; + filterModel->addFilter( + new CardFilter(colorString, CardFilter::Type::TypeAndNot, CardFilter::Attr::AttrColor)); + } + } + } + break; + + case FilterMode::Includes: + // Includes Mode: Just include selected colors without restrictions + for (const auto &color : selectedColors) { + QString colorString = color; + filterModel->addFilter(new CardFilter(colorString, CardFilter::Type::TypeOr, + CardFilter::Attr::AttrColor)); // OR for selected colors + } + break; + + case FilterMode::IncludeExclude: + // Include/Exclude Mode: Include selected colors and exclude unselected colors + for (const auto &color : selectedColors) { + QString colorString = color; + filterModel->addFilter(new CardFilter(colorString, CardFilter::Type::TypeOr, + CardFilter::Attr::AttrColor)); // OR for selected colors + } + for (const auto &color : excludedColors) { + QString colorString = color; + filterModel->addFilter(new CardFilter(colorString, CardFilter::Type::TypeAndNot, + CardFilter::Attr::AttrColor)); // AND NOT for excluded colors + } + break; + } + + blockSync = false; } void VisualDatabaseDisplayColorFilterWidget::updateFilterMode(bool checked) { - exactMatchMode = checked; // Toggle between modes - retranslateUi(); // Update the button text - emit filterModeChanged(exactMatchMode); + blockSync = true; + + if (checked) { + // Cycle through the modes in a clear manner + switch (currentMode) { + case FilterMode::ExactMatch: + currentMode = FilterMode::Includes; // Switch to Includes + break; + case FilterMode::Includes: + currentMode = FilterMode::IncludeExclude; // Switch to Include/Exclude + break; + case FilterMode::IncludeExclude: + currentMode = FilterMode::ExactMatch; // Switch to Exact Match + break; + } + } + + retranslateUi(); // Update button text based on the mode + emit filterModeChanged(currentMode); // Signal mode change + updateColorFilter(); // Reapply the filter based on the new mode + + blockSync = false; } void VisualDatabaseDisplayColorFilterWidget::syncWithFilterModel() { + blockSync = true; QSet currentFilters; // Get current filters of type color for (const auto &filter : filterModel->getFiltersOfType(CardFilter::Attr::AttrColor)) { - if (filter->type() == CardFilter::Type::TypeAnd || filter->type() == CardFilter::Type::TypeAndNot) { + if (filter->type() == CardFilter::Type::TypeAnd || filter->type() == CardFilter::Type::TypeOr) { currentFilters.insert(filter->term()); } } @@ -157,4 +239,5 @@ void VisualDatabaseDisplayColorFilterWidget::syncWithFilterModel() } updateColorFilter(); + blockSync = false; } \ No newline at end of file diff --git a/cockatrice/src/client/ui/widgets/visual_database_display/visual_database_display_color_filter_widget.h b/cockatrice/src/client/ui/widgets/visual_database_display/visual_database_display_color_filter_widget.h index 0eb7f05d0..99383a953 100644 --- a/cockatrice/src/client/ui/widgets/visual_database_display/visual_database_display_color_filter_widget.h +++ b/cockatrice/src/client/ui/widgets/visual_database_display/visual_database_display_color_filter_widget.h @@ -26,6 +26,13 @@ private: int circleDiameter; }; +enum class FilterMode +{ + ExactMatch, // Only selected colors are included, all others are excluded. + Includes, // Include selected colors (OR condition). + IncludeExclude // Include selected colors (OR) and exclude unselected colors (AND NOT). +}; + class VisualDatabaseDisplayColorFilterWidget : public QWidget { Q_OBJECT @@ -35,7 +42,7 @@ public: void retranslateUi(); signals: - void filterModeChanged(bool exactMatchMode); + void filterModeChanged(FilterMode filterMode); void activeColorsChanged(); private slots: @@ -49,7 +56,8 @@ private: QHBoxLayout *layout; QPushButton *toggleButton; QMap activeColors; - bool exactMatchMode = false; // Default to "includes" mode + FilterMode currentMode = FilterMode::Includes; // Default mode + bool blockSync = false; }; #endif // VISUAL_DATABASE_DISPLAY_COLOR_FILTER_WIDGET_H