Restore filters on load correctly.

This commit is contained in:
Lukas Brübach 2025-03-13 14:35:21 +01:00
parent b823ad2d9d
commit aeb24fa58e
10 changed files with 196 additions and 28 deletions

View file

@ -89,11 +89,14 @@ void VisualDatabaseDisplayFilterSaveLoadWidget::loadFilter(const QString &filena
filterModel->blockSignals(true);
filterModel->filterTree()->blockSignals(true);
for (const QJsonValue &value : filtersArray) {
qDebug() << value;
if (value.isObject()) {
QJsonObject filterObj = value.toObject();
CardFilter *filter = CardFilter::fromJson(filterObj);
if (filter)
if (filter) {
qDebug() << "Adding filter " << filter->type() << filter->attr() << filter->term();
filterModel->addFilter(filter);
}
}
}
filterModel->blockSignals(false);

View file

@ -5,6 +5,7 @@
#include <QPushButton>
#include <QSpinBox>
#include <QTimer>
VisualDatabaseDisplayMainTypeFilterWidget::VisualDatabaseDisplayMainTypeFilterWidget(QWidget *parent,
FilterTreeModel *_filterModel)
@ -35,6 +36,9 @@ VisualDatabaseDisplayMainTypeFilterWidget::VisualDatabaseDisplayMainTypeFilterWi
toggleButton->setCheckable(true);
layout->addWidget(toggleButton);
connect(toggleButton, &QPushButton::toggled, this, &VisualDatabaseDisplayMainTypeFilterWidget::updateFilterMode);
connect(filterModel, &FilterTreeModel::layoutChanged, this, [this]() {
QTimer::singleShot(100, this, &VisualDatabaseDisplayMainTypeFilterWidget::syncWithFilterModel);
});
createMainTypeButtons(); // Populate buttons initially
updateFilterMode(false); // Initialize toggle button text
@ -94,7 +98,7 @@ void VisualDatabaseDisplayMainTypeFilterWidget::handleMainTypeToggled(const QStr
void VisualDatabaseDisplayMainTypeFilterWidget::updateMainTypeFilter()
{
// Clear existing filters related to main type
filterModel->clearFiltersOfType(CardFilter::Attr::AttrType);
filterModel->clearFiltersOfType(CardFilter::Attr::AttrMainType);
if (exactMatchMode) {
// Exact Match: Only selected main types are allowed
@ -110,7 +114,7 @@ void VisualDatabaseDisplayMainTypeFilterWidget::updateMainTypeFilter()
for (const auto &type : selectedTypes) {
QString typeString = type;
filterModel->addFilter(
new CardFilter(typeString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrType));
new CardFilter(typeString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrMainType));
}
// Exclude any other types (TypeAndNot)
@ -118,7 +122,7 @@ void VisualDatabaseDisplayMainTypeFilterWidget::updateMainTypeFilter()
if (!selectedTypes.contains(type)) {
QString typeString = type;
filterModel->addFilter(
new CardFilter(typeString, CardFilter::Type::TypeAndNot, CardFilter::Attr::AttrType));
new CardFilter(typeString, CardFilter::Type::TypeAndNot, CardFilter::Attr::AttrMainType));
}
}
}
@ -128,7 +132,7 @@ void VisualDatabaseDisplayMainTypeFilterWidget::updateMainTypeFilter()
if (activeMainTypes[type]) {
QString typeString = type;
filterModel->addFilter(
new CardFilter(typeString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrType));
new CardFilter(typeString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrMainType));
}
}
}
@ -140,3 +144,40 @@ void VisualDatabaseDisplayMainTypeFilterWidget::updateFilterMode(bool checked)
toggleButton->setText(exactMatchMode ? tr("Mode: Exact Match") : tr("Mode: Includes"));
updateMainTypeFilter();
}
void VisualDatabaseDisplayMainTypeFilterWidget::syncWithFilterModel()
{
// Temporarily block signals for each button to prevent toggling while updating button states
for (auto it = typeButtons.begin(); it != typeButtons.end(); ++it) {
it.value()->blockSignals(true);
}
// Uncheck all buttons
for (auto it = typeButtons.begin(); it != typeButtons.end(); ++it) {
it.value()->setChecked(false);
}
// Get active filters for main types
QSet<QString> activeTypes;
for (const auto &filter : filterModel->getFiltersOfType(CardFilter::AttrMainType)) {
if (filter->type() == CardFilter::Type::TypeAnd) {
activeTypes.insert(filter->term());
}
}
// Check the buttons for active types
for (const auto &type : activeTypes) {
activeMainTypes[type] = true;
if (typeButtons.contains(type)) {
typeButtons[type]->setChecked(true);
}
}
// Re-enable signal emissions for each button
for (auto it = typeButtons.begin(); it != typeButtons.end(); ++it) {
it.value()->blockSignals(false);
}
// Update the visibility of buttons
updateMainTypeButtonsVisibility();
}

View file

@ -23,6 +23,7 @@ public:
void handleMainTypeToggled(const QString &mainType, bool active);
void updateMainTypeFilter();
void updateFilterMode(bool checked);
void syncWithFilterModel();
private:
FilterTreeModel *filterModel;

View file

@ -38,6 +38,8 @@ VisualDatabaseDisplayNameFilterWidget::VisualDatabaseDisplayNameFilterWidget(QWi
layout->addWidget(loadFromDeckButton);
connect(loadFromDeckButton, &QPushButton::clicked, this, &VisualDatabaseDisplayNameFilterWidget::actLoadFromDeck);
connect(filterModel, &FilterTreeModel::layoutChanged, this,
[this]() { QTimer::singleShot(100, this, &VisualDatabaseDisplayNameFilterWidget::syncWithFilterModel); });
}
void VisualDatabaseDisplayNameFilterWidget::actLoadFromDeck()
@ -86,9 +88,11 @@ void VisualDatabaseDisplayNameFilterWidget::createNameFilter(const QString &name
void VisualDatabaseDisplayNameFilterWidget::removeNameFilter(const QString &name)
{
if (activeFilters.contains(name)) {
delete activeFilters[name]; // Remove button
activeFilters[name]->deleteLater(); // Safe deletion
activeFilters.remove(name);
updateFilterModel();
QTimer::singleShot(0, this,
&VisualDatabaseDisplayNameFilterWidget::updateFilterModel); // Avoid concurrent modification
}
}
@ -112,3 +116,37 @@ void VisualDatabaseDisplayNameFilterWidget::updateFilterModel()
filterModel->filterTree()->nodeAt(0)->nodeChanged();
emit filterModel->layoutChanged();
}
void VisualDatabaseDisplayNameFilterWidget::syncWithFilterModel()
{
QStringList currentFilters;
for (const auto &filter : filterModel->getFiltersOfType(CardFilter::Attr::AttrName)) {
if (filter->type() == CardFilter::Type::TypeOr) {
currentFilters.append(filter->term());
}
}
QStringList activeFilterList = activeFilters.keys();
// Sort lists for efficient comparison
std::sort(currentFilters.begin(), currentFilters.end());
std::sort(activeFilterList.begin(), activeFilterList.end());
if (currentFilters == activeFilterList) {
return;
}
// Remove filters that are in the UI but not in the model
for (const auto &name : activeFilterList) {
if (!currentFilters.contains(name)) {
removeNameFilter(name);
}
}
// Add filters that are in the model but not in the UI
for (const auto &name : currentFilters) {
if (!activeFilters.contains(name)) {
createNameFilter(name);
}
}
}

View file

@ -23,6 +23,7 @@ public:
void removeNameFilter(const QString &name);
void updateFilterList();
void updateFilterModel();
void syncWithFilterModel();
private:
AbstractTabDeckEditor *deckEditor;

View file

@ -5,6 +5,7 @@
#include <QLineEdit>
#include <QPushButton>
#include <QTimer>
#include <algorithm>
VisualDatabaseDisplaySetFilterWidget::VisualDatabaseDisplaySetFilterWidget(QWidget *parent,
@ -32,6 +33,8 @@ VisualDatabaseDisplaySetFilterWidget::VisualDatabaseDisplaySetFilterWidget(QWidg
toggleButton->setCheckable(true);
layout->addWidget(toggleButton);
connect(toggleButton, &QPushButton::toggled, this, &VisualDatabaseDisplaySetFilterWidget::updateFilterMode);
connect(filterModel, &FilterTreeModel::layoutChanged, this,
[this]() { QTimer::singleShot(100, this, &VisualDatabaseDisplaySetFilterWidget::syncWithFilterModel); });
createSetButtons(); // Populate buttons initially
updateFilterMode(false); // Initialize toggle button text
@ -130,6 +133,43 @@ void VisualDatabaseDisplaySetFilterWidget::updateSetFilter()
}
}
void VisualDatabaseDisplaySetFilterWidget::syncWithFilterModel()
{
// Clear activeSets
activeSets.clear();
// Read the current filters in filterModel
auto currentFilters = filterModel->getFiltersOfType(CardFilter::Attr::AttrSet);
// Determine if we're in Exact Match mode or Includes mode
QSet<QString> selectedSets;
QSet<QString> excludedSets;
for (const auto &filter : currentFilters) {
if (filter->type() == CardFilter::Type::TypeAnd) {
selectedSets.insert(filter->term());
} else if (filter->type() == CardFilter::Type::TypeAndNot) {
excludedSets.insert(filter->term());
} else if (filter->type() == CardFilter::Type::TypeOr) {
selectedSets.insert(filter->term());
}
}
// Determine exact match mode based on filter structure
bool newExactMatchMode = !excludedSets.isEmpty();
if (newExactMatchMode != exactMatchMode) {
exactMatchMode = newExactMatchMode;
toggleButton->setText(exactMatchMode ? tr("Mode: Exact Match") : tr("Mode: Includes"));
}
// Sync button states with selected sets
for (auto it = setButtons.begin(); it != setButtons.end(); ++it) {
bool active = selectedSets.contains(it.key());
activeSets[it.key()] = active;
it.value()->setChecked(active);
}
}
void VisualDatabaseDisplaySetFilterWidget::updateFilterMode(bool checked)
{
exactMatchMode = checked;

View file

@ -21,6 +21,7 @@ public:
void handleSetToggled(const QString &setShortName, bool active);
void updateSetFilter();
void syncWithFilterModel();
void updateFilterMode(bool checked);
private:

View file

@ -6,6 +6,7 @@
#include <QLineEdit>
#include <QPushButton>
#include <QSpinBox>
#include <QTimer>
VisualDatabaseDisplaySubTypeFilterWidget::VisualDatabaseDisplaySubTypeFilterWidget(QWidget *parent,
FilterTreeModel *_filterModel)
@ -18,7 +19,7 @@ VisualDatabaseDisplaySubTypeFilterWidget::VisualDatabaseDisplaySubTypeFilterWidg
layout = new QVBoxLayout(this);
setLayout(layout);
// Create the spinbox
// Create and setup the spinbox
spinBox = new QSpinBox(this);
spinBox->setMinimum(1);
spinBox->setMaximum(getMaxSubTypeCount());
@ -27,7 +28,7 @@ VisualDatabaseDisplaySubTypeFilterWidget::VisualDatabaseDisplaySubTypeFilterWidg
connect(spinBox, QOverload<int>::of(&QSpinBox::valueChanged), this,
&VisualDatabaseDisplaySubTypeFilterWidget::updateSubTypeButtonsVisibility);
// Create the search box
// Create search box
searchBox = new QLineEdit(this);
searchBox->setPlaceholderText(tr("Search subtypes..."));
layout->addWidget(searchBox);
@ -38,19 +39,22 @@ VisualDatabaseDisplaySubTypeFilterWidget::VisualDatabaseDisplaySubTypeFilterWidg
flowWidget->setMaximumHeight(300);
layout->addWidget(flowWidget);
// Create the toggle button for Exact Match/Includes mode
// Toggle button setup (Exact Match / Includes mode)
toggleButton = new QPushButton(this);
toggleButton->setCheckable(true);
layout->addWidget(toggleButton);
connect(toggleButton, &QPushButton::toggled, this, &VisualDatabaseDisplaySubTypeFilterWidget::updateFilterMode);
connect(filterModel, &FilterTreeModel::layoutChanged, this, [this]() {
QTimer::singleShot(100, this, &VisualDatabaseDisplaySubTypeFilterWidget::syncWithFilterModel);
});
createSubTypeButtons(); // Populate buttons initially
updateFilterMode(false);
createSubTypeButtons(); // Populate buttons initially
updateFilterMode(false); // Initialize the toggle button text
}
void VisualDatabaseDisplaySubTypeFilterWidget::createSubTypeButtons()
{
// Iterate through main types and create buttons
// Iterate through sub types and create buttons
for (auto it = allSubCardTypesWithCount.begin(); it != allSubCardTypesWithCount.end(); ++it) {
auto *button = new QPushButton(it.key(), flowWidget);
button->setCheckable(true);
@ -60,9 +64,9 @@ void VisualDatabaseDisplaySubTypeFilterWidget::createSubTypeButtons()
flowWidget->addWidget(button);
typeButtons[it.key()] = button;
// Connect toggle signal
// Connect toggle signal for each button
connect(button, &QPushButton::toggled, this,
[this, mainType = it.key()](bool checked) { handleSubTypeToggled(mainType, checked); });
[this, subType = it.key()](bool checked) { handleSubTypeToggled(subType, checked); });
}
updateSubTypeButtonsVisibility(); // Ensure visibility is updated initially
}
@ -72,6 +76,7 @@ void VisualDatabaseDisplaySubTypeFilterWidget::updateSubTypeButtonsVisibility()
int threshold = spinBox->value();
QString filterText = searchBox->text().trimmed().toLower();
// Iterate through buttons and hide/disable those below the threshold
for (auto it = typeButtons.begin(); it != typeButtons.end(); ++it) {
QString subType = it.key().toLower();
bool isActive = activeSubTypes.value(it.key(), false);
@ -92,12 +97,12 @@ int VisualDatabaseDisplaySubTypeFilterWidget::getMaxSubTypeCount() const
return maxCount;
}
void VisualDatabaseDisplaySubTypeFilterWidget::handleSubTypeToggled(const QString &mainType, bool active)
void VisualDatabaseDisplaySubTypeFilterWidget::handleSubTypeToggled(const QString &subType, bool active)
{
activeSubTypes[mainType] = active;
activeSubTypes[subType] = active;
if (typeButtons.contains(mainType)) {
typeButtons[mainType]->setChecked(active);
if (typeButtons.contains(subType)) {
typeButtons[subType]->setChecked(active);
}
updateSubTypeFilter();
@ -105,11 +110,11 @@ void VisualDatabaseDisplaySubTypeFilterWidget::handleSubTypeToggled(const QStrin
void VisualDatabaseDisplaySubTypeFilterWidget::updateSubTypeFilter()
{
// Clear existing filters related to main type
filterModel->clearFiltersOfType(CardFilter::Attr::AttrType);
// Clear existing filters related to sub types
filterModel->clearFiltersOfType(CardFilter::Attr::AttrSubType);
if (exactMatchMode) {
// Exact Match: Only selected main types are allowed
// Exact Match: Only selected sub types are allowed
QSet<QString> selectedTypes;
for (const auto &type : activeSubTypes.keys()) {
if (activeSubTypes[type]) {
@ -118,11 +123,11 @@ void VisualDatabaseDisplaySubTypeFilterWidget::updateSubTypeFilter()
}
if (!selectedTypes.isEmpty()) {
// Require all selected types (TypeAnd)
// Require all selected subtypes (TypeAnd)
for (const auto &type : selectedTypes) {
QString typeString = type;
filterModel->addFilter(
new CardFilter(typeString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrType));
new CardFilter(typeString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrSubType));
}
// Exclude any other types (TypeAndNot)
@ -130,17 +135,17 @@ void VisualDatabaseDisplaySubTypeFilterWidget::updateSubTypeFilter()
if (!selectedTypes.contains(type)) {
QString typeString = type;
filterModel->addFilter(
new CardFilter(typeString, CardFilter::Type::TypeAndNot, CardFilter::Attr::AttrType));
new CardFilter(typeString, CardFilter::Type::TypeAndNot, CardFilter::Attr::AttrSubType));
}
}
}
} else {
// Default Includes Mode (TypeOr) - match any selected main types
// Default Includes Mode (TypeOr) - match any selected subtypes
for (const auto &type : activeSubTypes.keys()) {
if (activeSubTypes[type]) {
QString typeString = type;
filterModel->addFilter(
new CardFilter(typeString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrType));
new CardFilter(typeString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrSubType));
}
}
}
@ -152,3 +157,40 @@ void VisualDatabaseDisplaySubTypeFilterWidget::updateFilterMode(bool checked)
toggleButton->setText(exactMatchMode ? tr("Mode: Exact Match") : tr("Mode: Includes"));
updateSubTypeFilter();
}
void VisualDatabaseDisplaySubTypeFilterWidget::syncWithFilterModel()
{
// Temporarily block signals for each button to prevent toggling while updating button states
for (auto it = typeButtons.begin(); it != typeButtons.end(); ++it) {
it.value()->blockSignals(true);
}
// Uncheck all buttons
for (auto it = typeButtons.begin(); it != typeButtons.end(); ++it) {
it.value()->setChecked(false);
}
// Get active filters for sub types
QSet<QString> activeTypes;
for (const auto &filter : filterModel->getFiltersOfType(CardFilter::AttrSubType)) {
if (filter->type() == CardFilter::Type::TypeAnd) {
activeTypes.insert(filter->term());
}
}
// Check the buttons for active types
for (const auto &type : activeTypes) {
activeSubTypes[type] = true;
if (typeButtons.contains(type)) {
typeButtons[type]->setChecked(true);
}
}
// Re-enable signal emissions for each button
for (auto it = typeButtons.begin(); it != typeButtons.end(); ++it) {
it.value()->blockSignals(false);
}
// Update the visibility of buttons
updateSubTypeButtonsVisibility();
}

View file

@ -23,6 +23,7 @@ public:
void handleSubTypeToggled(const QString &mainType, bool active);
void updateSubTypeFilter();
void updateFilterMode(bool checked);
void syncWithFilterModel();
private:
FilterTreeModel *filterModel;

View file

@ -46,7 +46,7 @@ private:
enum Attr a;
public:
CardFilter(QString &term, Type type, Attr attr) : trm(term), t(type), a(attr){};
CardFilter(QString &term, Type type, Attr attr) : trm(term), t(type), a(attr) {};
Type type() const
{