mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-13 05:20:00 -08:00
Use shared multi-select Essence dropdown in Visual Database filters
This commit is contained in:
parent
39eb983fe9
commit
abe4dc2b8f
1 changed files with 59 additions and 143 deletions
|
|
@ -1,27 +1,17 @@
|
||||||
#include "visual_database_display_color_filter_widget.h"
|
#include "visual_database_display_color_filter_widget.h"
|
||||||
|
|
||||||
#include "../cards/additional_info/mana_symbol_widget.h"
|
#include "../cards/additional_info/essence_filter_picker.h"
|
||||||
#include "filter_tree_model.h"
|
#include "filter_tree_model.h"
|
||||||
#include "libcockatrice/filters/filter_card.h"
|
#include "libcockatrice/filters/filter_card.h"
|
||||||
#include <libcockatrice/card/essence_types.h>
|
|
||||||
|
|
||||||
#include <QAbstractItemModel>
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QDebug>
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QPersistentModelIndex>
|
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QtGlobal>
|
#include <libcockatrice/card/essence_types.h>
|
||||||
#include <libcockatrice/filters/filter_tree.h>
|
#include <libcockatrice/filters/filter_tree.h>
|
||||||
|
|
||||||
/**
|
|
||||||
* This widget provides a graphical control element for the CardFilter::Attr::AttrColor filters applied to the filter
|
|
||||||
* model.
|
|
||||||
* @param parent The Qt Widget that this widget will parent to
|
|
||||||
* @param _filterModel The filter model that this widget will manipulate
|
|
||||||
*/
|
|
||||||
VisualDatabaseDisplayColorFilterWidget::VisualDatabaseDisplayColorFilterWidget(QWidget *parent,
|
VisualDatabaseDisplayColorFilterWidget::VisualDatabaseDisplayColorFilterWidget(QWidget *parent,
|
||||||
FilterTreeModel *_filterModel)
|
FilterTreeModel *_filterModel)
|
||||||
: QWidget(parent), filterModel(_filterModel), layout(new QHBoxLayout(this))
|
: QWidget(parent), filterModel(_filterModel), layout(new QHBoxLayout(this))
|
||||||
|
|
@ -30,20 +20,13 @@ VisualDatabaseDisplayColorFilterWidget::VisualDatabaseDisplayColorFilterWidget(Q
|
||||||
layout->setSpacing(3);
|
layout->setSpacing(3);
|
||||||
layout->setContentsMargins(0, 0, 0, 0);
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
// All fifteen Continuum Universes Essence types are filterable.
|
// Share the same compact Essence selection UI as Visual Deck Storage.
|
||||||
// Never fall back to MTG's five-color WUBRG control. N is colorless.
|
// A 15-icon horizontal row cannot fit the database filter toolbar.
|
||||||
for (const QChar essence : Essence::symbols()) {
|
essencePicker = new EssenceFilterPicker(this);
|
||||||
auto *manaSymbol = new ManaSymbolWidget(this, QString(essence), false, true);
|
layout->addWidget(essencePicker);
|
||||||
manaSymbol->setFixedSize(22, 22);
|
|
||||||
manaSymbol->setToolTip(essence == QChar('N') ? tr("N — Colorless Essence")
|
|
||||||
: tr("Essence %1").arg(essence));
|
|
||||||
|
|
||||||
layout->addWidget(manaSymbol);
|
connect(essencePicker, &EssenceFilterPicker::essenceToggled, this,
|
||||||
|
&VisualDatabaseDisplayColorFilterWidget::handleColorToggled);
|
||||||
// Connect the color toggled signal
|
|
||||||
connect(manaSymbol, &ManaSymbolWidget::colorToggled, this,
|
|
||||||
&VisualDatabaseDisplayColorFilterWidget::handleColorToggled);
|
|
||||||
}
|
|
||||||
|
|
||||||
modeComboBox = new QComboBox(this);
|
modeComboBox = new QComboBox(this);
|
||||||
layout->addWidget(modeComboBox);
|
layout->addWidget(modeComboBox);
|
||||||
|
|
@ -54,108 +37,77 @@ VisualDatabaseDisplayColorFilterWidget::VisualDatabaseDisplayColorFilterWidget(Q
|
||||||
connect(filterModel, &FilterTreeModel::layoutChanged, this,
|
connect(filterModel, &FilterTreeModel::layoutChanged, this,
|
||||||
[this]() { syncDebouncer.call([this] { syncWithFilterModel(); }); });
|
[this]() { syncDebouncer.call([this] { syncWithFilterModel(); }); });
|
||||||
|
|
||||||
// Call retranslateUi to set the initial text
|
|
||||||
retranslateUi();
|
retranslateUi();
|
||||||
|
syncWithFilterModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisualDatabaseDisplayColorFilterWidget::retranslateUi()
|
void VisualDatabaseDisplayColorFilterWidget::retranslateUi()
|
||||||
{
|
{
|
||||||
|
essencePicker->retranslateUi();
|
||||||
|
|
||||||
modeComboBox->blockSignals(true);
|
modeComboBox->blockSignals(true);
|
||||||
modeComboBox->clear();
|
modeComboBox->clear();
|
||||||
|
|
||||||
modeComboBox->addItem(tr("Exact match"), QVariant::fromValue(FilterMode::ExactMatch));
|
modeComboBox->addItem(tr("Exact match"), QVariant::fromValue(FilterMode::ExactMatch));
|
||||||
modeComboBox->addItem(tr("Includes"), QVariant::fromValue(FilterMode::Includes));
|
modeComboBox->addItem(tr("Includes"), QVariant::fromValue(FilterMode::Includes));
|
||||||
modeComboBox->addItem(tr("Include / Exclude"), QVariant::fromValue(FilterMode::IncludeExclude));
|
modeComboBox->addItem(tr("Include / Exclude"), QVariant::fromValue(FilterMode::IncludeExclude));
|
||||||
|
|
||||||
modeComboBox->setToolTip(tr("How selected and unselected Essence types are combined in the filter"));
|
modeComboBox->setToolTip(tr("How selected and unselected Essence types are combined in the filter"));
|
||||||
|
|
||||||
// Restore current mode
|
|
||||||
const int index = modeComboBox->findData(QVariant::fromValue(currentMode));
|
const int index = modeComboBox->findData(QVariant::fromValue(currentMode));
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
modeComboBox->setCurrentIndex(index);
|
modeComboBox->setCurrentIndex(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
modeComboBox->blockSignals(false);
|
modeComboBox->blockSignals(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisualDatabaseDisplayColorFilterWidget::handleColorToggled(QChar color, bool active)
|
void VisualDatabaseDisplayColorFilterWidget::handleColorToggled(QChar essence, bool active)
|
||||||
{
|
{
|
||||||
if (active) {
|
if (active) {
|
||||||
addFilter(color);
|
addFilter(essence);
|
||||||
} else {
|
} else {
|
||||||
removeFilter(color);
|
removeFilter(essence);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisualDatabaseDisplayColorFilterWidget::addFilter(QChar color)
|
void VisualDatabaseDisplayColorFilterWidget::addFilter(QChar essence)
|
||||||
{
|
{
|
||||||
QString colorString = color;
|
const QString essenceString(essence);
|
||||||
QString typeStr;
|
const QList<const CardFilter *> filters = filterModel->getFiltersOfType(CardFilter::Attr::AttrColor);
|
||||||
|
for (const CardFilter *filter : filters) {
|
||||||
// Remove previous filters
|
if (filter->term() == essenceString) {
|
||||||
|
filterModel->removeFilter(filter);
|
||||||
QList<const CardFilter *> allColorFilters = filterModel->getFiltersOfType(CardFilter::Attr::AttrColor);
|
|
||||||
QList<const CardFilter *> matchingFilters;
|
|
||||||
|
|
||||||
for (const CardFilter *filter : allColorFilters) {
|
|
||||||
if (filter->term() == color) {
|
|
||||||
matchingFilters.append(filter);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const CardFilter *filter : matchingFilters) {
|
|
||||||
filterModel->removeFilter(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add actual filter
|
|
||||||
|
|
||||||
switch (currentMode) {
|
switch (currentMode) {
|
||||||
case FilterMode::ExactMatch:
|
case FilterMode::ExactMatch:
|
||||||
filterModel->addFilter(new CardFilter(colorString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrColor));
|
filterModel->addFilter(
|
||||||
|
new CardFilter(essenceString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrColor));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FilterMode::Includes:
|
case FilterMode::Includes:
|
||||||
filterModel->addFilter(new CardFilter(colorString, CardFilter::Type::TypeOr, CardFilter::Attr::AttrColor));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FilterMode::IncludeExclude:
|
case FilterMode::IncludeExclude:
|
||||||
filterModel->addFilter(new CardFilter(colorString, CardFilter::Type::TypeOr, CardFilter::Attr::AttrColor));
|
filterModel->addFilter(
|
||||||
|
new CardFilter(essenceString, CardFilter::Type::TypeOr, CardFilter::Attr::AttrColor));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisualDatabaseDisplayColorFilterWidget::removeFilter(QChar color)
|
void VisualDatabaseDisplayColorFilterWidget::removeFilter(QChar essence)
|
||||||
{
|
{
|
||||||
QString colorString = color;
|
const QString essenceString(essence);
|
||||||
|
const QList<const CardFilter *> filters = filterModel->getFiltersOfType(CardFilter::Attr::AttrColor);
|
||||||
// Remove inclusion filters
|
for (const CardFilter *filter : filters) {
|
||||||
QList<const CardFilter *> allColorFilters = filterModel->getFiltersOfType(CardFilter::Attr::AttrColor);
|
if (filter->term() == essenceString) {
|
||||||
QList<const CardFilter *> matchingFilters;
|
filterModel->removeFilter(filter);
|
||||||
|
|
||||||
for (const CardFilter *filter : allColorFilters) {
|
|
||||||
if (filter->term() == color) {
|
|
||||||
matchingFilters.append(filter);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const CardFilter *filter : matchingFilters) {
|
|
||||||
filterModel->removeFilter(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add exclusion filters if the mode demands it
|
|
||||||
switch (currentMode) {
|
switch (currentMode) {
|
||||||
case FilterMode::ExactMatch:
|
case FilterMode::ExactMatch:
|
||||||
filterModel->addFilter(
|
|
||||||
new CardFilter(colorString, CardFilter::Type::TypeAndNot, CardFilter::Attr::AttrColor));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FilterMode::IncludeExclude:
|
case FilterMode::IncludeExclude:
|
||||||
filterModel->addFilter(
|
filterModel->addFilter(
|
||||||
new CardFilter(colorString, CardFilter::Type::TypeAndNot, CardFilter::Attr::AttrColor));
|
new CardFilter(essenceString, CardFilter::Type::TypeAndNot, CardFilter::Attr::AttrColor));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FilterMode::Includes:
|
case FilterMode::Includes:
|
||||||
// No exclusion in Includes mode
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -174,10 +126,9 @@ void VisualDatabaseDisplayColorFilterWidget::updateFilterMode()
|
||||||
|
|
||||||
filterModel->clearFiltersOfType(CardFilter::Attr::AttrColor);
|
filterModel->clearFiltersOfType(CardFilter::Attr::AttrColor);
|
||||||
|
|
||||||
const QList<ManaSymbolWidget *> manaSymbolWidgets = findChildren<ManaSymbolWidget *>();
|
const QSet<QChar> selected = essencePicker->activeEssences();
|
||||||
|
for (const QChar essence : Essence::symbols()) {
|
||||||
for (ManaSymbolWidget *manaSymbolWidget : manaSymbolWidgets) {
|
handleColorToggled(essence, selected.contains(essence));
|
||||||
handleColorToggled(manaSymbolWidget->getSymbolChar(), manaSymbolWidget->isColorActive());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
filterModel->blockSignals(false);
|
filterModel->blockSignals(false);
|
||||||
|
|
@ -188,79 +139,44 @@ void VisualDatabaseDisplayColorFilterWidget::updateFilterMode()
|
||||||
emit filterModeChanged(currentMode);
|
emit filterModeChanged(currentMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisualDatabaseDisplayColorFilterWidget::setManaSymbolActive(QChar color, bool active)
|
void VisualDatabaseDisplayColorFilterWidget::setEssenceActive(QChar essence, bool active)
|
||||||
{
|
{
|
||||||
QList<ManaSymbolWidget *> manaSymbolWidgets = findChildren<ManaSymbolWidget *>();
|
essencePicker->setEssenceActive(essence, active);
|
||||||
|
|
||||||
for (ManaSymbolWidget *manaSymbolWidget : manaSymbolWidgets) {
|
|
||||||
if (manaSymbolWidget->getSymbolChar() == color) {
|
|
||||||
manaSymbolWidget->setColorActive(active);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QChar> VisualDatabaseDisplayColorFilterWidget::getActiveColors()
|
QList<QChar> VisualDatabaseDisplayColorFilterWidget::getActiveColors()
|
||||||
{
|
{
|
||||||
QList<QChar> activeColors;
|
QList<QChar> result;
|
||||||
QList<ManaSymbolWidget *> manaSymbolWidgets = findChildren<ManaSymbolWidget *>();
|
const QSet<QChar> selected = essencePicker->activeEssences();
|
||||||
|
for (const QChar essence : Essence::symbols()) {
|
||||||
for (ManaSymbolWidget *manaSymbolWidget : manaSymbolWidgets) {
|
if (selected.contains(essence)) {
|
||||||
if (manaSymbolWidget->isColorActive()) {
|
result.append(essence);
|
||||||
activeColors.append(manaSymbolWidget->getSymbolChar());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
return activeColors;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisualDatabaseDisplayColorFilterWidget::syncWithFilterModel()
|
void VisualDatabaseDisplayColorFilterWidget::syncWithFilterModel()
|
||||||
{
|
{
|
||||||
QList<const CardFilter *> allColorFilters = filterModel->getFiltersOfType(CardFilter::Attr::AttrColor);
|
const QList<const CardFilter *> filters = filterModel->getFiltersOfType(CardFilter::Attr::AttrColor);
|
||||||
|
|
||||||
QList<ManaSymbolWidget *> manaSymbolWidgets = findChildren<ManaSymbolWidget *>();
|
for (const QChar essence : Essence::symbols()) {
|
||||||
|
bool selected = false;
|
||||||
for (ManaSymbolWidget *manaSymbolWidget : manaSymbolWidgets) {
|
for (const CardFilter *filter : filters) {
|
||||||
bool found = false;
|
if (filter->term() != QString(essence)) {
|
||||||
for (const CardFilter *filter : allColorFilters) {
|
continue;
|
||||||
if (manaSymbolWidget->getSymbolChar() == filter->term()) {
|
}
|
||||||
switch (currentMode) {
|
if (currentMode == FilterMode::ExactMatch) {
|
||||||
case FilterMode::ExactMatch:
|
selected = filter->type() == CardFilter::Type::TypeAnd;
|
||||||
switch (filter->type()) {
|
} else {
|
||||||
case CardFilter::Type::TypeAnd:
|
selected = filter->type() == CardFilter::Type::TypeOr;
|
||||||
setManaSymbolActive(filter->term().at(0), true);
|
}
|
||||||
break;
|
if (selected) {
|
||||||
default:
|
break;
|
||||||
setManaSymbolActive(filter->term().at(0), false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case FilterMode::Includes:
|
|
||||||
switch (filter->type()) {
|
|
||||||
case CardFilter::Type::TypeOr:
|
|
||||||
setManaSymbolActive(filter->term().at(0), true);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
setManaSymbolActive(filter->term().at(0), false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case FilterMode::IncludeExclude:
|
|
||||||
switch (filter->type()) {
|
|
||||||
case CardFilter::Type::TypeOr:
|
|
||||||
setManaSymbolActive(filter->term().at(0), true);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
setManaSymbolActive(filter->term().at(0), false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
found = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Signals are blocked inside the picker; loading saved filters must
|
||||||
if (!found) {
|
// not mutate the FilterTreeModel again.
|
||||||
setManaSymbolActive(manaSymbolWidget->getSymbolChar(), false);
|
setEssenceActive(essence, selected);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue