xref: /haiku/src/apps/haikudepot/packagemodel/PackageFilter.cpp (revision 2ec05ec7ed44e169ad9007a3e6daf645129912b8)
1 /*
2  * Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>.
3  * Copyright 2014, Axel Dörfler <axeld@pinc-software.de>.
4  * Copyright 2016-2024, Andrew Lindesay <apl@lindesay.co.nz>.
5  * All rights reserved. Distributed under the terms of the MIT License.
6  *
7  * Note that this file included code earlier from `Model.cpp` and
8  * copyrights have been latterly been carried across in 2024.
9  */
10 
11 
12 #include "PackageFilter.h"
13 #include "PackageUtils.h"
14 
15 
~PackageFilter()16 PackageFilter::~PackageFilter()
17 {
18 }
19 
20 
21 void
AddFilter(PackageFilterRef filter)22 AndFilter::AddFilter(PackageFilterRef filter)
23 {
24 	fFilters.push_back(filter);
25 }
26 
27 
NotFilter(PackageFilterRef filter)28 NotFilter::NotFilter(PackageFilterRef filter)
29 	:
30 	fFilter(filter)
31 {
32 }
33 
34 
35 bool
AcceptsPackage(const PackageInfoRef & package) const36 NotFilter::AcceptsPackage(const PackageInfoRef& package) const
37 {
38 	return !(fFilter.IsSet() && fFilter->AcceptsPackage(package));
39 }
40 
41 
42 bool
AcceptsPackage(const PackageInfoRef & package) const43 AndFilter::AcceptsPackage(const PackageInfoRef& package) const
44 {
45 	std::vector<PackageFilterRef>::const_iterator it;
46 	for (it = fFilters.begin(); it != fFilters.end(); it++) {
47 		PackageFilterRef aFilter = *it;
48 		if (!aFilter.IsSet() || !aFilter->AcceptsPackage(package))
49 			return false;
50 	}
51 	return true;
52 }
53 
54 
55 class StateFilter : public PackageFilter
56 {
57 public:
StateFilter(PackageState state)58 	StateFilter(PackageState state)
59 		:
60 		fState(state)
61 	{
62 	}
63 
AcceptsPackage(const PackageInfoRef & package) const64 	virtual bool AcceptsPackage(const PackageInfoRef& package) const
65 	{
66 		return PackageUtils::State(package) == fState;
67 	}
68 
69 private:
70 	PackageState	fState;
71 };
72 
73 
74 class CategoryFilter : public PackageFilter {
75 public:
CategoryFilter(const BString & categoryCode)76 	CategoryFilter(const BString& categoryCode)
77 		:
78 		fCategoryCode(categoryCode)
79 	{
80 	}
81 
AcceptsPackage(const PackageInfoRef & package) const82 	virtual bool AcceptsPackage(const PackageInfoRef& package) const
83 	{
84 		if (!package.IsSet())
85 			return false;
86 
87 		PackageClassificationInfoRef classificationInfo = package->PackageClassificationInfo();
88 
89 		if (!classificationInfo.IsSet())
90 			return false;
91 
92 		return classificationInfo->HasCategoryByCode(CategoryCode());
93 	}
94 
CategoryCode() const95 	const BString& CategoryCode() const
96 	{
97 		return fCategoryCode;
98 	}
99 
100 private:
101 	BString		fCategoryCode;
102 };
103 
104 
105 class DepotFilter : public PackageFilter {
106 public:
DepotFilter(const BString & name)107 	DepotFilter(const BString& name)
108 		:
109 		fName(name)
110 	{
111 	}
112 
AcceptsPackage(const PackageInfoRef & package) const113 	virtual bool AcceptsPackage(const PackageInfoRef& package) const
114 	{
115 		if (!package.IsSet())
116 			return false;
117 		return package->DepotName() == fName;
118 	}
119 
Name() const120 	const BString& Name() const
121 	{
122 		return fName;
123 	}
124 
125 private:
126 	BString		fName;
127 };
128 
129 
130 class SourceFilter : public PackageFilter {
131 public:
AcceptsPackage(const PackageInfoRef & package) const132 	virtual bool AcceptsPackage(const PackageInfoRef& package) const
133 	{
134 		if (!package.IsSet())
135 			return false;
136 		const BString& packageName = package->Name();
137 		return packageName.EndsWith("_source");
138 	}
139 };
140 
141 
142 class DevelopmentFilter : public PackageFilter
143 {
144 public:
AcceptsPackage(const PackageInfoRef & package) const145 	virtual bool AcceptsPackage(const PackageInfoRef& package) const
146 	{
147 		if (!package.IsSet())
148 			return false;
149 		const BString& packageName = package->Name();
150 		return packageName.EndsWith("_devel")
151 			|| packageName.EndsWith("_debuginfo");
152 	}
153 };
154 
155 
156 class SearchTermsFilter : public PackageFilter {
157 public:
SearchTermsFilter(const BString & searchTerms)158 	SearchTermsFilter(const BString& searchTerms)
159 	{
160 		// Separate the string into terms at spaces
161 		int32 index = 0;
162 		while (index < searchTerms.Length()) {
163 			int32 nextSpace = searchTerms.FindFirst(" ", index);
164 			if (nextSpace < 0)
165 				nextSpace = searchTerms.Length();
166 			if (nextSpace > index) {
167 				BString term;
168 				searchTerms.CopyInto(term, index, nextSpace - index);
169 				term.ToLower();
170 				fSearchTerms.Add(term);
171 			}
172 			index = nextSpace + 1;
173 		}
174 	}
175 
AcceptsPackage(const PackageInfoRef & package) const176 	virtual bool AcceptsPackage(const PackageInfoRef& package) const
177 	{
178 		if (!package.IsSet())
179 			return false;
180 		// Every search term must be found in one of the package texts
181 		for (int32 i = fSearchTerms.CountStrings() - 1; i >= 0; i--) {
182 			const BString& term = fSearchTerms.StringAt(i);
183 			if (!_TextContains(package->Name(), term)
184 				&& !_TextContains(package->Publisher().Name(), term)
185 				&& !_AcceptsPackageFromLocalizedText(package, term)) {
186 				return false;
187 			}
188 		}
189 		return true;
190 	}
191 
SearchTerms() const192 	BString SearchTerms() const
193 	{
194 		BString searchTerms;
195 		for (int32 i = 0; i < fSearchTerms.CountStrings(); i++) {
196 			const BString& term = fSearchTerms.StringAt(i);
197 			if (term.IsEmpty())
198 				continue;
199 			if (!searchTerms.IsEmpty())
200 				searchTerms.Append(" ");
201 			searchTerms.Append(term);
202 		}
203  		return searchTerms;
204 	}
205 
206 private:
_TextContains(BString text,const BString & string) const207  	bool _TextContains(BString text, const BString& string) const
208  	{
209  		text.ToLower();
210  		int32 index = text.FindFirst(string);
211  		return index >= 0;
212  	}
213 
_AcceptsPackageFromLocalizedText(const PackageInfoRef & package,const BString & searchTerm) const214 	bool _AcceptsPackageFromLocalizedText(const PackageInfoRef& package,
215 		const BString& searchTerm) const
216 	{
217 		if (!package.IsSet())
218 			return false;
219 
220 		PackageLocalizedTextRef localizedText = package->LocalizedText();
221 
222 		if (!localizedText.IsSet())
223 			return false;
224 
225 		return _TextContains(localizedText->Title(), searchTerm)
226         	|| _TextContains(localizedText->Summary(), searchTerm)
227         	|| _TextContains(localizedText->Description(), searchTerm);
228 	}
229 
230 private:
231  	BStringList fSearchTerms;
232 };
233 
234 
235 // #pragma mark - factory
236 
237 
238 /*static*/ PackageFilterRef
CreateCategoryFilter(const BString & category)239 PackageFilterFactory::CreateCategoryFilter(const BString& category)
240 {
241 	return PackageFilterRef(new CategoryFilter(category), true);
242 }
243 
244 
245 /*static*/ PackageFilterRef
CreateSearchTermsFilter(const BString & searchTerms)246 PackageFilterFactory::CreateSearchTermsFilter(const BString& searchTerms)
247 {
248 	return PackageFilterRef(new SearchTermsFilter(searchTerms), true);
249 }
250 
251 
252 /*static*/ PackageFilterRef
CreateDepotFilter(const BString & depotName)253 PackageFilterFactory::CreateDepotFilter(const BString& depotName)
254 {
255 	return PackageFilterRef(new DepotFilter(depotName), true);
256 }
257 
258 
259 /*static*/ PackageFilterRef
CreateStateFilter(PackageState state)260 PackageFilterFactory::CreateStateFilter(PackageState state)
261 {
262 	return PackageFilterRef(new StateFilter(state), true);
263 }
264 
265 
266 /*static*/ PackageFilterRef
CreateSourceFilter()267 PackageFilterFactory::CreateSourceFilter()
268 {
269 	return PackageFilterRef(new SourceFilter(), true);
270 }
271 
272 
273 /*static*/ PackageFilterRef
CreateDevelopmentFilter()274 PackageFilterFactory::CreateDevelopmentFilter()
275 {
276 	return PackageFilterRef(new DevelopmentFilter(), true);
277 }
278