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 <QRegularExpression>
11#include <QList>
12#include <QSet>
13#include <kis_debug.h>
14
16{
17public:
19 : searchTokenizer("\\s*,+\\s*")
20 {}
21
22 QRegularExpression searchTokenizer;
23
24 QChar excludeBegin {'!'};
25 QChar tagBegin {'#'};
26 QChar exactMatchBeginEnd {'"'};
27
32
37
38 QString filter;
39};
40
41
46
51
52bool checkDelimitersAndCut(const QChar& begin, const QChar& end, QString& token) {
53 if (token.startsWith(begin) && token.endsWith(end)) {
54 token.remove(0, 1);
55 token = token.left(token.length() - 1);
56 return true;
57 } else {
58 return false;
59 }
60}
61
62bool checkDelimitersAndCut(const QChar& beginEnd, QString& token) {
63 return checkDelimitersAndCut(beginEnd, beginEnd, token);
64}
65
66bool checkPrefixAndCut(QChar& prefix, QString& token) {
67 if (token.startsWith(prefix)) {
68 token.remove(0, 1);
69 return true;
70 } else {
71 return false;
72 }
73}
74
75void KisResourceSearchBoxFilter::setFilter(const QString& filter)
76{
77 m_d->filter = QString(filter);
79}
80
81
82bool KisResourceSearchBoxFilter::matchesResource(const QString &_resourceName, const QStringList &tagList) const
83{
84 // exact matches
85 QString resourceName = _resourceName.toLower();
86
87 if (m_d->resourceExactMatchesIncluded.count() > 0
88 && !m_d->resourceExactMatchesIncluded.contains(resourceName)) {
89 return false;
90 }
91 if (m_d->resourceExactMatchesExcluded.contains(resourceName)) {
92 return false;
93 }
94
95 // partial name matches
96 if (m_d->resourceNamesPartialIncluded.count() > 0) {
97 Q_FOREACH(const QString& partialName, m_d->resourceNamesPartialIncluded) {
98 if (!resourceName.contains(partialName) && tagList.filter(partialName, Qt::CaseInsensitive).isEmpty()) {
99 return false;
100 }
101 }
102 }
103
104 Q_FOREACH(const QString& partialName, m_d->resourceNamesPartialExcluded) {
105 if (resourceName.contains(partialName) || tagList.filter(partialName, Qt::CaseInsensitive).size() > 0) {
106 return false;
107 }
108 }
109
110 // Tag partial matches
111 if (m_d->tagsPartialIncluded.count() > 0 ) {
112 Q_FOREACH(const QString& partialTag, m_d->tagsPartialIncluded) {
113 if (tagList.filter(partialTag, Qt::CaseInsensitive).isEmpty()) {
114 return false;
115 }
116 }
117 }
118
119 if (m_d->tagsPartialExcluded.count() > 0) {
120 Q_FOREACH(const QString& partialTag, m_d->tagsPartialExcluded) {
121 if (tagList.filter(partialTag, Qt::CaseInsensitive).size() > 0) {
122 return false;
123 }
124 }
125 }
126
127 // Tag exact matches
128 if (m_d->tagExactMatchesIncluded.count() > 0) {
129 Q_FOREACH(const QString& tagName, m_d->tagExactMatchesIncluded) {
130 if (!tagList.contains(tagName, Qt::CaseInsensitive)) {
131 return false;
132 }
133 }
134 }
135
136 if (m_d->tagExactMatchesExcluded.count() > 0) {
137 Q_FOREACH(const QString excludedTag, m_d->tagExactMatchesExcluded) {
138 if (tagList.contains(excludedTag, Qt::CaseInsensitive)) {
139 return false;
140 }
141 }
142 }
143
144 return true;
145}
146
148{
149 return m_d->filter.isEmpty();
150}
151
153{
154 m_d->resourceExactMatchesIncluded.clear();
155 m_d->resourceExactMatchesExcluded.clear();
156 m_d->tagExactMatchesIncluded.clear();
157 m_d->tagExactMatchesExcluded.clear();
158
159 m_d->resourceNamesPartialIncluded.clear();
160 m_d->resourceNamesPartialExcluded.clear();
161 m_d->tagsPartialIncluded.clear();
162 m_d->tagsPartialExcluded.clear();
163}
164
166{
168
169 QString tempFilter(m_d->filter);
170
171 QStringList tokens = tempFilter.split(m_d->searchTokenizer, Qt::SkipEmptyParts);
172
173 Q_FOREACH(const QString& token, tokens) {
174 QString workingToken(token.toLower());
175 const bool included = !checkPrefixAndCut(m_d->excludeBegin, workingToken);
176
177 if (checkPrefixAndCut(m_d->tagBegin, workingToken)) {
178 if (checkDelimitersAndCut(m_d->exactMatchBeginEnd, workingToken)) {
179 if (included) {
180
181 m_d->tagExactMatchesIncluded.insert(workingToken);
182 } else {
183
184 m_d->tagExactMatchesExcluded.insert(workingToken);
185 }
186 } else {
187 if (included) {
188
189 m_d->tagsPartialIncluded.append(workingToken);
190 } else {
191
192 m_d->tagsPartialExcluded.append(workingToken);
193 }
194 }
195 } else if (checkDelimitersAndCut(m_d->exactMatchBeginEnd, workingToken)) {
196 if (included) {
197
198 m_d->resourceExactMatchesIncluded.insert(workingToken);
199 } else {
200
201 m_d->resourceExactMatchesExcluded.insert(workingToken);
202 }
203
204 } else {
205 if (included) {
206
207 m_d->resourceNamesPartialIncluded.append(workingToken);
208 } else {
209
210 m_d->resourceNamesPartialExcluded.append(workingToken);
211 }
212 }
213 }
214}
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