Krita Source Code Documentation
Loading...
Searching...
No Matches
KisResourceSearchBoxFilter.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2019 Agata Cacko <cacko.azh@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9
10#include <QRegExp>
11#include <QRegularExpression>
12#include <QList>
13#include <QSet>
14#include <kis_debug.h>
15
17{
18public:
20 : searchTokenizer("\\s*,+\\s*")
21 {}
22
23 QRegularExpression searchTokenizer;
24
25 QChar excludeBegin {'!'};
26 QChar tagBegin {'#'};
27 QChar exactMatchBeginEnd {'"'};
28
33
38
39 QString filter;
40};
41
42
47
52
53bool checkDelimitersAndCut(const QChar& begin, const QChar& end, QString& token) {
54 if (token.startsWith(begin) && token.endsWith(end)) {
55 token.remove(0, 1);
56 token = token.left(token.length() - 1);
57 return true;
58 } else {
59 return false;
60 }
61}
62
63bool checkDelimitersAndCut(const QChar& beginEnd, QString& token) {
64 return checkDelimitersAndCut(beginEnd, beginEnd, token);
65}
66
67bool checkPrefixAndCut(QChar& prefix, QString& token) {
68 if (token.startsWith(prefix)) {
69 token.remove(0, 1);
70 return true;
71 } else {
72 return false;
73 }
74}
75
76void KisResourceSearchBoxFilter::setFilter(const QString& filter)
77{
78 m_d->filter = QString(filter);
80}
81
82
83bool KisResourceSearchBoxFilter::matchesResource(const QString &_resourceName, const QStringList &tagList) const
84{
85 // exact matches
86 QString resourceName = _resourceName.toLower();
87
88 if (m_d->resourceExactMatchesIncluded.count() > 0
89 && !m_d->resourceExactMatchesIncluded.contains(resourceName)) {
90 return false;
91 }
92 if (m_d->resourceExactMatchesExcluded.contains(resourceName)) {
93 return false;
94 }
95
96 // partial name matches
97 if (m_d->resourceNamesPartialIncluded.count() > 0) {
98 Q_FOREACH(const QString& partialName, m_d->resourceNamesPartialIncluded) {
99 if (!resourceName.contains(partialName) && tagList.filter(partialName, Qt::CaseInsensitive).isEmpty()) {
100 return false;
101 }
102 }
103 }
104
105 Q_FOREACH(const QString& partialName, m_d->resourceNamesPartialExcluded) {
106 if (resourceName.contains(partialName) || tagList.filter(partialName, Qt::CaseInsensitive).size() > 0) {
107 return false;
108 }
109 }
110
111 // Tag partial matches
112 if (m_d->tagsPartialIncluded.count() > 0 ) {
113 Q_FOREACH(const QString& partialTag, m_d->tagsPartialIncluded) {
114 if (tagList.filter(partialTag, Qt::CaseInsensitive).isEmpty()) {
115 return false;
116 }
117 }
118 }
119
120 if (m_d->tagsPartialExcluded.count() > 0) {
121 Q_FOREACH(const QString& partialTag, m_d->tagsPartialExcluded) {
122 if (tagList.filter(partialTag, Qt::CaseInsensitive).size() > 0) {
123 return false;
124 }
125 }
126 }
127
128 // Tag exact matches
129 if (m_d->tagExactMatchesIncluded.count() > 0) {
130 Q_FOREACH(const QString& tagName, m_d->tagExactMatchesIncluded) {
131 if (!tagList.contains(tagName, Qt::CaseInsensitive)) {
132 return false;
133 }
134 }
135 }
136
137 if (m_d->tagExactMatchesExcluded.count() > 0) {
138 Q_FOREACH(const QString excludedTag, m_d->tagExactMatchesExcluded) {
139 if (tagList.contains(excludedTag, Qt::CaseInsensitive)) {
140 return false;
141 }
142 }
143 }
144
145 return true;
146}
147
149{
150 return m_d->filter.isEmpty();
151}
152
154{
155 m_d->resourceExactMatchesIncluded.clear();
156 m_d->resourceExactMatchesExcluded.clear();
157 m_d->tagExactMatchesIncluded.clear();
158 m_d->tagExactMatchesExcluded.clear();
159
160 m_d->resourceNamesPartialIncluded.clear();
161 m_d->resourceNamesPartialExcluded.clear();
162 m_d->tagsPartialIncluded.clear();
163 m_d->tagsPartialExcluded.clear();
164}
165
167{
169
170 QString tempFilter(m_d->filter);
171
172 QStringList tokens = tempFilter.split(m_d->searchTokenizer, Qt::SkipEmptyParts);
173
174 Q_FOREACH(const QString& token, tokens) {
175 QString workingToken(token.toLower());
176 const bool included = !checkPrefixAndCut(m_d->excludeBegin, workingToken);
177
178 if (checkPrefixAndCut(m_d->tagBegin, workingToken)) {
179 if (checkDelimitersAndCut(m_d->exactMatchBeginEnd, workingToken)) {
180 if (included) {
181
182 m_d->tagExactMatchesIncluded.insert(workingToken);
183 } else {
184
185 m_d->tagExactMatchesExcluded.insert(workingToken);
186 }
187 } else {
188 if (included) {
189
190 m_d->tagsPartialIncluded.append(workingToken);
191 } else {
192
193 m_d->tagsPartialExcluded.append(workingToken);
194 }
195 }
196 } else if (checkDelimitersAndCut(m_d->exactMatchBeginEnd, workingToken)) {
197 if (included) {
198
199 m_d->resourceExactMatchesIncluded.insert(workingToken);
200 } else {
201
202 m_d->resourceExactMatchesExcluded.insert(workingToken);
203 }
204
205 } else {
206 if (included) {
207
208 m_d->resourceNamesPartialIncluded.append(workingToken);
209 } else {
210
211 m_d->resourceNamesPartialExcluded.append(workingToken);
212 }
213 }
214 }
215}
bool checkPrefixAndCut(QChar &prefix, QString &token)
bool checkDelimitersAndCut(const QChar &begin, const QChar &end, QString &token)
void setFilter(const QString &filter)
bool matchesResource(const QString &resourceName, const QStringList &tagList) const