mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
Filter: implement any-of mode
Add an additional mode to the tags, people and location filters: any_of. Replace the original invert-bool by an enum. Move the common code into a distinct function. Reported-by: Willem Ferguson <willemferguson@zoology.up.ac.za> Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
ce669adc53
commit
e550a788f0
4 changed files with 66 additions and 31 deletions
|
@ -140,10 +140,10 @@ void FilterWidget2::clearFilter()
|
||||||
ui.fromTime->setTime(filterData.fromTime);
|
ui.fromTime->setTime(filterData.fromTime);
|
||||||
ui.toDate->setDate(filterData.toDate.date());
|
ui.toDate->setDate(filterData.toDate.date());
|
||||||
ui.toTime->setTime(filterData.toTime);
|
ui.toTime->setTime(filterData.toTime);
|
||||||
ui.tagsMode->setCurrentIndex(filterData.tagsNegate ? 1 : 0);
|
ui.tagsMode->setCurrentIndex((int)filterData.tagsMode);
|
||||||
ui.peopleMode->setCurrentIndex(filterData.peopleNegate ? 1 : 0);
|
ui.peopleMode->setCurrentIndex((int)filterData.peopleMode);
|
||||||
ui.locationMode->setCurrentIndex(filterData.locationNegate ? 1 : 0);
|
ui.locationMode->setCurrentIndex((int)filterData.locationMode);
|
||||||
ui.equipmentMode->setCurrentIndex(filterData.equipmentNegate ? 1 : 0);
|
ui.equipmentMode->setCurrentIndex((int)filterData.equipmentMode);
|
||||||
|
|
||||||
ignoreSignal = false;
|
ignoreSignal = false;
|
||||||
|
|
||||||
|
@ -186,10 +186,10 @@ void FilterWidget2::updateFilter()
|
||||||
filterData.people = ui.people->text().split(",", QString::SkipEmptyParts);
|
filterData.people = ui.people->text().split(",", QString::SkipEmptyParts);
|
||||||
filterData.location = ui.location->text().split(",", QString::SkipEmptyParts);
|
filterData.location = ui.location->text().split(",", QString::SkipEmptyParts);
|
||||||
filterData.equipment = ui.equipment->text().split(",", QString::SkipEmptyParts);
|
filterData.equipment = ui.equipment->text().split(",", QString::SkipEmptyParts);
|
||||||
filterData.tagsNegate = ui.tagsMode->currentIndex() == 1;
|
filterData.tagsMode = (FilterData::Mode)ui.tagsMode->currentIndex();
|
||||||
filterData.peopleNegate = ui.peopleMode->currentIndex() == 1;
|
filterData.peopleMode = (FilterData::Mode)ui.peopleMode->currentIndex();
|
||||||
filterData.locationNegate = ui.locationMode->currentIndex() == 1;
|
filterData.locationMode = (FilterData::Mode)ui.locationMode->currentIndex();
|
||||||
filterData.equipmentNegate = ui.equipmentMode->currentIndex() == 1;
|
filterData.equipmentMode = (FilterData::Mode)ui.equipmentMode->currentIndex();
|
||||||
filterData.logged = ui.logged->isChecked();
|
filterData.logged = ui.logged->isChecked();
|
||||||
filterData.planned = ui.planned->isChecked();
|
filterData.planned = ui.planned->isChecked();
|
||||||
|
|
||||||
|
|
|
@ -298,6 +298,11 @@
|
||||||
<string>All of</string>
|
<string>All of</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Any of</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>None of</string>
|
<string>None of</string>
|
||||||
|
@ -312,6 +317,11 @@
|
||||||
<string>All of</string>
|
<string>All of</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Any of</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>None of</string>
|
<string>None of</string>
|
||||||
|
@ -323,12 +333,17 @@
|
||||||
<widget class="QComboBox" name="locationMode">
|
<widget class="QComboBox" name="locationMode">
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Matches</string>
|
<string>All of</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Doesn't match</string>
|
<string>Any of</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>None of</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -340,6 +355,11 @@
|
||||||
<string>All of</string>
|
<string>All of</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Any of</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>None of</string>
|
<string>None of</string>
|
||||||
|
|
|
@ -24,28 +24,37 @@ namespace {
|
||||||
{ return s2.trimmed().contains(s.trimmed(), Qt::CaseInsensitive); } );
|
{ return s2.trimmed().contains(s.trimmed(), Qt::CaseInsensitive); } );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasTags(const QStringList &tags, const struct dive *d, bool negate)
|
// Check whether either all, any or none of the items of the first list is
|
||||||
|
// in the second list as a super string.
|
||||||
|
// The mode is controlled by the second argument
|
||||||
|
bool check(const QStringList &items, const QStringList &list, FilterData::Mode mode)
|
||||||
|
{
|
||||||
|
bool negate = mode == FilterData::Mode::NONE_OF;
|
||||||
|
bool any_of = mode == FilterData::Mode::ANY_OF;
|
||||||
|
auto fun = [&list, negate](const QString &item)
|
||||||
|
{ return listContainsSuperstring(list, item) != negate; };
|
||||||
|
return any_of ? std::any_of(items.begin(), items.end(), fun)
|
||||||
|
: std::all_of(items.begin(), items.end(), fun);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasTags(const QStringList &tags, const struct dive *d, FilterData::Mode mode)
|
||||||
{
|
{
|
||||||
if (tags.isEmpty())
|
if (tags.isEmpty())
|
||||||
return true;
|
return true;
|
||||||
QStringList dive_tags = get_taglist_string(d->tag_list).split(",");
|
QStringList dive_tags = get_taglist_string(d->tag_list).split(",");
|
||||||
|
return check(tags, dive_tags, mode);
|
||||||
return std::all_of(tags.begin(), tags.end(), [&dive_tags, negate](const QString &tag)
|
|
||||||
{ return listContainsSuperstring(dive_tags, tag) != negate; } );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasPersons(const QStringList &people, const struct dive *d, bool negate)
|
bool hasPersons(const QStringList &people, const struct dive *d, FilterData::Mode mode)
|
||||||
{
|
{
|
||||||
if (people.isEmpty())
|
if (people.isEmpty())
|
||||||
return true;
|
return true;
|
||||||
QStringList dive_people = QString(d->buddy).split(",", QString::SkipEmptyParts)
|
QStringList dive_people = QString(d->buddy).split(",", QString::SkipEmptyParts)
|
||||||
+ QString(d->divemaster).split(",", QString::SkipEmptyParts);
|
+ QString(d->divemaster).split(",", QString::SkipEmptyParts);
|
||||||
|
return check(people, dive_people, mode);
|
||||||
return std::all_of(people.begin(), people.end(), [&dive_people, negate](const QString &person)
|
|
||||||
{ return listContainsSuperstring(dive_people, person) != negate; } );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasLocations(const QStringList &locations, const struct dive *d, bool negate)
|
bool hasLocations(const QStringList &locations, const struct dive *d, FilterData::Mode mode)
|
||||||
{
|
{
|
||||||
if (locations.isEmpty())
|
if (locations.isEmpty())
|
||||||
return true;
|
return true;
|
||||||
|
@ -56,12 +65,11 @@ namespace {
|
||||||
if (d->dive_site)
|
if (d->dive_site)
|
||||||
diveLocations.push_back(QString(d->dive_site->name));
|
diveLocations.push_back(QString(d->dive_site->name));
|
||||||
|
|
||||||
return std::all_of(locations.begin(), locations.end(), [&diveLocations, negate](const QString &location)
|
return check(locations, diveLocations, mode);
|
||||||
{ return listContainsSuperstring(diveLocations, location) != negate; } );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Finish this iimplementation.
|
// TODO: Finish this implementation.
|
||||||
bool hasEquipment(const QStringList &, const struct dive *, bool)
|
bool hasEquipment(const QStringList &, const struct dive *, FilterData::Mode)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -129,18 +137,18 @@ bool MultiFilterSortModel::showDive(const struct dive *d) const
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// tags.
|
// tags.
|
||||||
if (!hasTags(filterData.tags, d, filterData.tagsNegate))
|
if (!hasTags(filterData.tags, d, filterData.tagsMode))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// people
|
// people
|
||||||
if (!hasPersons(filterData.people, d, filterData.peopleNegate))
|
if (!hasPersons(filterData.people, d, filterData.peopleMode))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Location
|
// Location
|
||||||
if (!hasLocations(filterData.location, d, filterData.locationNegate))
|
if (!hasLocations(filterData.location, d, filterData.locationMode))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!hasEquipment(filterData.equipment, d, filterData.equipmentNegate))
|
if (!hasEquipment(filterData.equipment, d, filterData.equipmentMode))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Planned/Logged
|
// Planned/Logged
|
||||||
|
|
|
@ -15,6 +15,13 @@ struct dive;
|
||||||
struct dive_trip;
|
struct dive_trip;
|
||||||
|
|
||||||
struct FilterData {
|
struct FilterData {
|
||||||
|
// The mode ids are chosen such that they can be directly converted from / to combobox indices.
|
||||||
|
enum class Mode {
|
||||||
|
ALL_OF = 0,
|
||||||
|
ANY_OF = 1,
|
||||||
|
NONE_OF = 2
|
||||||
|
};
|
||||||
|
|
||||||
bool validFilter = false;
|
bool validFilter = false;
|
||||||
int minVisibility = 0;
|
int minVisibility = 0;
|
||||||
int maxVisibility = 5;
|
int maxVisibility = 5;
|
||||||
|
@ -35,10 +42,10 @@ struct FilterData {
|
||||||
QStringList people;
|
QStringList people;
|
||||||
QStringList location;
|
QStringList location;
|
||||||
QStringList equipment;
|
QStringList equipment;
|
||||||
bool tagsNegate = false;
|
Mode tagsMode = Mode::ALL_OF;
|
||||||
bool peopleNegate = false;
|
Mode peopleMode = Mode::ALL_OF;
|
||||||
bool locationNegate = false;
|
Mode locationMode = Mode::ALL_OF;
|
||||||
bool equipmentNegate = false;
|
Mode equipmentMode = Mode::ALL_OF;
|
||||||
bool logged = true;
|
bool logged = true;
|
||||||
bool planned = true;
|
bool planned = true;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue