Messagelib

searchlinecommand.cpp
1/*
2 SPDX-FileCopyrightText: 2024 Laurent Montel <montel@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "searchlinecommand.h"
8#include <KLocalizedString>
9using namespace Qt::Literals::StringLiterals;
10using namespace MessageList::Core;
11QMap<QString, SearchLineCommand::SearchLineType> SearchLineCommand::mKeyList = {
12 {"subject"_L1, SearchLineCommand::SearchLineType::Subject},
13 {"to"_L1, SearchLineCommand::SearchLineType::To},
14 {"cc"_L1, SearchLineCommand::SearchLineType::Cc},
15 {"bcc"_L1, SearchLineCommand::SearchLineType::Bcc},
16 {"from"_L1, SearchLineCommand::SearchLineType::From},
17 {"has:attachment"_L1, SearchLineCommand::SearchLineType::HasAttachment},
18 {"has:hasinvitation"_L1, SearchLineCommand::SearchLineType::HasInvitation},
19 {"is:unread"_L1, SearchLineCommand::SearchLineType::IsUnRead},
20 {"is:read"_L1, SearchLineCommand::SearchLineType::IsRead},
21 {"is:important"_L1, SearchLineCommand::SearchLineType::IsImportant},
22 {"is:ignored"_L1, SearchLineCommand::SearchLineType::IsIgnored},
23 {"is:ham"_L1, SearchLineCommand::SearchLineType::IsHam},
24 {"is:spam"_L1, SearchLineCommand::SearchLineType::IsSpam},
25 {"is:watched"_L1, SearchLineCommand::SearchLineType::IsWatched},
26 {"is:replied"_L1, SearchLineCommand::SearchLineType::IsReplied},
27 {"is:forwarded"_L1, SearchLineCommand::SearchLineType::IsForwarded},
28};
29SearchLineCommand::SearchLineCommand() = default;
30
31SearchLineCommand::~SearchLineCommand() = default;
32
33bool SearchLineCommand::hasSubType(const QString &v)
34{
35 return v == QLatin1StringView("is") || v == QLatin1StringView("has");
36}
37
38QString SearchLineCommand::convertSearchLinetypeToTranslatedString(SearchLineCommand::SearchLineType type) const
39{
40 switch (type) {
41 case Unknown:
42 case HasStateOrAttachment:
43 case Literal:
44 case Date:
45 case Size:
46 return {};
47 case To:
48 return i18n("To contains");
49 case Bcc:
50 return i18n("BCC contains");
51 case Cc:
52 return i18n("CC contains");
53 case From:
54 return i18n("From contains");
55 case Subject:
56 return i18n("Subject contains");
57 case HasAttachment:
58 return i18n("Mail has attachment");
59 case HasInvitation:
60 return i18n("Mail has invitation");
61 case IsImportant:
62 return i18n("Mail is important");
63 case IsRead:
64 return i18n("Mail is read");
65 case IsUnRead:
66 return i18n("Mail is Unread");
67 case IsIgnored:
68 return i18n("Mail is Ignored");
69 case IsHam:
70 return i18n("Mail is Ham");
71 case IsSpam:
72 return i18n("Mail is Spam");
73 case IsWatched:
74 return i18n("Mail is watched");
75 case IsReplied:
76 return i18n("Mail is replied");
77 case IsForwarded:
78 return i18n("Mail is forwarded");
79 }
80 return {};
81}
82
83QString SearchLineCommand::generateCommadLineStr() const
84{
85 QString result;
86 for (const auto &info : mSearchLineInfo) {
87 if (!result.isEmpty()) {
88 result += QLatin1Char(' ') + i18n("AND") + QLatin1Char(' ');
89 }
90 const QString translatedType = convertSearchLinetypeToTranslatedString(info.type);
91 if (!translatedType.isEmpty()) {
92 result += translatedType;
93 }
94 if (!info.argument.isEmpty()) {
95 if (!translatedType.isEmpty()) {
96 result += QLatin1Char(' ');
97 }
98 result += info.argument;
99 }
100 }
101 return result;
102}
103
104void SearchLineCommand::parseSearchLineCommand(const QString &str)
105{
106 mSearchLineInfo.clear();
107 if (str.isEmpty()) {
108 return;
109 }
110 SearchLineInfo searchLineInfo;
111 QString tmp;
112 int parentheses = 0;
113 for (int i = 0, total = str.length(); i < total; ++i) {
114 const QChar ch = str.at(i);
115 if (ch == QLatin1Char(':')) {
116 // qDebug() << " tmp ! " << tmp;
117 if (mKeyList.contains(tmp.trimmed())) {
118 // qDebug() << " contains " << tmp;
119 searchLineInfo.type = mKeyList.value(tmp.trimmed());
120 tmp.clear();
121 } else if (hasSubType(tmp)) {
122 searchLineInfo.type = HasStateOrAttachment;
123 tmp += ch;
124 // continue
125 }
126 } else if (ch.isSpace()) {
127 // We can use is:... or has:...
128 if (mKeyList.contains(tmp)) {
129 searchLineInfo.type = mKeyList.value(tmp);
130 tmp.clear();
131 }
132
133 // qDebug() << " is space " << "pare" << parentheses << " tmp " << tmp;
134 if (searchLineInfo.type != Unknown && parentheses == 0) {
135 searchLineInfo.argument = tmp;
136 tmp.clear();
137 } else { // Literal
138 tmp += ch;
139 }
140 if (searchLineInfo.isValid() && parentheses == 0) {
141 mSearchLineInfo.append(std::move(searchLineInfo));
142 searchLineInfo.clear();
143 tmp.clear();
144 }
145 } else if (ch == QLatin1Char('(')) {
146 parentheses++;
147 if (parentheses > 1) {
148 tmp += ch;
149 }
150 // qDebug() << " parenthese ( equal " << parentheses;
151 } else if (ch == QLatin1Char(')')) {
152 parentheses--;
153 if (parentheses > 0) {
154 tmp += ch;
155 }
156 // qDebug() << " parenthese ) equal " << parentheses;
157 if (parentheses == 0) {
158 searchLineInfo.argument = tmp;
159 tmp.clear();
160 // qDebug() << " new values " << searchLineInfo;
161 mSearchLineInfo.append(std::move(searchLineInfo));
162 searchLineInfo.clear();
163 }
164 } else {
165 tmp += ch;
166 // qDebug() << " tmp " << tmp << " ch " << ch << "end";
167 }
168 }
169 if (searchLineInfo.type != Unknown) {
170 if (searchLineInfo.type == HasStateOrAttachment) {
171 if (mKeyList.contains(tmp)) {
172 searchLineInfo.type = mKeyList.value(tmp);
173 mSearchLineInfo.append(std::move(searchLineInfo));
174 }
175 } else {
176 if (!tmp.isEmpty()) {
177 searchLineInfo.argument = tmp;
178 mSearchLineInfo.append(std::move(searchLineInfo));
179 }
180 }
181 } else {
182 if (!tmp.isEmpty()) {
183 searchLineInfo.type = Literal;
184 searchLineInfo.argument = tmp;
185 mSearchLineInfo.append(std::move(searchLineInfo));
186 }
187 }
188 // qDebug() << " END " << mSearchLineInfo;
189 // TODO add date ?
190 // TODO add size: ?
191 // TODO add support for double quote
192 // TODO add more email state (spam/starred etc .)
193 // We need to extend emailquery or creating query by hand
194}
195
196QList<SearchLineCommand::SearchLineInfo> SearchLineCommand::searchLineInfo() const
197{
198 return mSearchLineInfo;
199}
200
201void SearchLineCommand::setSearchLineInfo(const QList<SearchLineInfo> &newSearchLineInfo)
202{
203 mSearchLineInfo = newSearchLineInfo;
204}
205
206void SearchLineCommand::SearchLineInfo::clear()
207{
208 type = SearchLineCommand::SearchLineType::Unknown;
209 argument.clear();
210}
211
212bool SearchLineCommand::SearchLineInfo::isValid() const
213{
214 if (type == SearchLineType::Unknown) {
215 return false;
216 }
217 return true;
218}
219
220bool SearchLineCommand::SearchLineInfo::operator==(const SearchLineInfo &other) const
221{
222 return type == other.type && argument == other.argument;
223}
224
225QDebug operator<<(QDebug d, const MessageList::Core::SearchLineCommand::SearchLineInfo &info)
226{
227 d << " type " << info.type;
228 d << " argument " << info.argument;
229 return d;
230}
231
232#include "moc_searchlinecommand.cpp"
QString i18n(const char *text, const TYPE &arg...)
KTEXTEDITOR_EXPORT QDebug operator<<(QDebug s, const MovingCursor &cursor)
The implementation independent part of the MessageList library.
Definition aggregation.h:22
bool isSpace(char32_t ucs4)
bool contains(const Key &key) const const
T value(const Key &key, const T &defaultValue) const const
QString & append(QChar ch)
const QChar at(qsizetype position) const const
void clear()
bool isEmpty() const const
qsizetype length() const const
QString trimmed() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Oct 11 2024 12:08:46 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.