mirror of
				https://github.com/subsurface/subsurface.git
				synced 2025-02-19 22:16:15 +00:00 
			
		
		
		
	Filter: make tags, people and location filter logically-and
If the user provides multiple tags, they probably want to search for dive with *all* of these tags. Replace the convoluted loops by std::all_of(). This makes it trivial to change logically-and to logically-or: Replace std::all_of() by std::any_of(). Reported-by: Jan Mulder <jlmulder@xs4all.nl> Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
		
							parent
							
								
									f67f07223f
								
							
						
					
					
						commit
						8fa156eb0d
					
				
					 1 changed files with 34 additions and 43 deletions
				
			
		|  | @ -16,57 +16,48 @@ | ||||||
| #include <algorithm> | #include <algorithm> | ||||||
| 
 | 
 | ||||||
| namespace { | namespace { | ||||||
| 	bool hasTag(const QStringList tags, const struct dive *d) | 	// Check if a string-list contains at least one string containing the second argument.
 | ||||||
|  | 	// Comparison is non case sensitive and removes white space.
 | ||||||
|  | 	bool listContainsSuperstring(const QStringList &list, const QString &s) | ||||||
| 	{ | 	{ | ||||||
| 		if (!tags.isEmpty()) { | 		return std::any_of(list.begin(), list.end(), [&s](const QString &s2) | ||||||
| 			auto dive_tags = get_taglist_string(d->tag_list).split(","); | 				   { return s2.trimmed().contains(s.trimmed(), Qt::CaseInsensitive); }); | ||||||
| 			bool found_tag = false; |  | ||||||
| 			for (const auto& filter_tag : tags) |  | ||||||
| 				for (const auto& dive_tag : dive_tags) |  | ||||||
| 					if (dive_tag.trimmed().toUpper().contains(filter_tag.trimmed().toUpper())) |  | ||||||
| 						found_tag = true; |  | ||||||
| 
 |  | ||||||
| 			return found_tag; |  | ||||||
| 		} |  | ||||||
| 		return true; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	bool hasPerson(const QStringList people, const struct dive *d) | 	bool hasTags(const QStringList &tags, const struct dive *d) | ||||||
| 	{ | 	{ | ||||||
| 		if (!people.isEmpty()) { | 		if (tags.isEmpty()) | ||||||
| 			QStringList dive_people = QString(d->buddy).split(",", QString::SkipEmptyParts) | 			return true; | ||||||
| 				+ QString(d->divemaster).split(",", QString::SkipEmptyParts); | 		QStringList dive_tags = get_taglist_string(d->tag_list).split(","); | ||||||
| 
 | 
 | ||||||
| 			bool found_person = false; | 		return std::all_of(tags.begin(), tags.end(), [&dive_tags](const QString &tag) | ||||||
| 			for(const auto& filter_person : people) | 				   { return listContainsSuperstring(dive_tags, tag); }); | ||||||
| 				for(const auto& dive_person : dive_people) |  | ||||||
| 					if (dive_person.trimmed().toUpper().contains(filter_person.trimmed().toUpper())) |  | ||||||
| 						found_person = true; |  | ||||||
| 
 |  | ||||||
| 			return found_person; |  | ||||||
| 		} |  | ||||||
| 		return true; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	bool hasLocation(const QStringList locations, const struct dive *d) | 	bool hasPersons(const QStringList &people, const struct dive *d) | ||||||
| 	{ | 	{ | ||||||
| 		if (!locations.isEmpty()) { | 		if (people.isEmpty()) | ||||||
| 			QStringList diveLocations; | 			return true; | ||||||
| 			if (d->divetrip) | 		QStringList dive_people = QString(d->buddy).split(",", QString::SkipEmptyParts) | ||||||
| 				diveLocations.push_back(QString(d->divetrip->location)); | 			+ QString(d->divemaster).split(",", QString::SkipEmptyParts); | ||||||
| 
 | 
 | ||||||
| 			if (d->dive_site) | 		return std::all_of(people.begin(), people.end(), [&dive_people](const QString &person) | ||||||
| 				diveLocations.push_back(QString(d->dive_site->name)); | 				   { return listContainsSuperstring(dive_people, person); }); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 			bool found_location = false; | 	bool hasLocations(const QStringList &locations, const struct dive *d) | ||||||
| 			for (const auto& filter_location : locations) | 	{ | ||||||
| 				for (const auto& dive_location : diveLocations) | 		if (locations.isEmpty()) | ||||||
| 					if (dive_location.trimmed().toUpper().contains(filter_location.trimmed().toUpper())) | 			return true; | ||||||
| 						found_location = true; | 		QStringList diveLocations; | ||||||
|  | 		if (d->divetrip) | ||||||
|  | 			diveLocations.push_back(QString(d->divetrip->location)); | ||||||
| 
 | 
 | ||||||
| 			return found_location; | 		if (d->dive_site) | ||||||
| 		} | 			diveLocations.push_back(QString(d->dive_site->name)); | ||||||
| 		return true; | 
 | ||||||
|  | 		return std::all_of(locations.begin(), locations.end(), [&diveLocations](const QString &location) | ||||||
|  | 				   { return listContainsSuperstring(diveLocations, location); }); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// TODO: Finish this iimplementation.
 | 	// TODO: Finish this iimplementation.
 | ||||||
|  | @ -130,15 +121,15 @@ bool MultiFilterSortModel::showDive(const struct dive *d) const | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
| 	// tags.
 | 	// tags.
 | ||||||
| 	if (!hasTag(filterData.tags, d)) | 	if (!hasTags(filterData.tags, d)) | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
| 	// people
 | 	// people
 | ||||||
| 	if (!hasPerson(filterData.people, d)) | 	if (!hasPersons(filterData.people, d)) | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
| 	// Location
 | 	// Location
 | ||||||
| 	if (!hasLocation(filterData.location, d)) | 	if (!hasLocations(filterData.location, d)) | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
| 	if (!hasEquipment(filterData.equipment, d)) | 	if (!hasEquipment(filterData.equipment, d)) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue