1 /*
2 SPDX-FileCopyrightText: 2013-2021 Laurent Montel <montel@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include "textrulerwidgethandler.h"
8
9 #include "search/searchpattern.h"
10 #include <KLineEdit>
11 #include <KLocalizedString>
12 #include <QComboBox>
13 #include <QStackedWidget>
14
15 using namespace MailCommon;
16
17 #include <QLabel>
18
19 // also see SearchRule::matches() and SearchRule::Function
20 // if you change the following strings!
21 static const struct {
22 SearchRule::Function id;
23 const char *displayName;
24 } TextFunctions[] = {{SearchRule::FuncContains, I18N_NOOP("contains")},
25 {SearchRule::FuncContainsNot, I18N_NOOP("does not contain")},
26 {SearchRule::FuncEquals, I18N_NOOP("equals")},
27 {SearchRule::FuncNotEqual, I18N_NOOP("does not equal")},
28 {SearchRule::FuncStartWith, I18N_NOOP("starts with")},
29 {SearchRule::FuncNotStartWith, I18N_NOOP("does not start with")},
30 {SearchRule::FuncEndWith, I18N_NOOP("ends with")},
31 {SearchRule::FuncNotEndWith, I18N_NOOP("does not end with")},
32
33 {SearchRule::FuncRegExp, I18N_NOOP("matches regular expr.")},
34 {SearchRule::FuncNotRegExp, I18N_NOOP("does not match reg. expr.")}};
35 static const int TextFunctionCount = sizeof(TextFunctions) / sizeof(*TextFunctions);
36
37 //---------------------------------------------------------------------------
38
createFunctionWidget(int number,QStackedWidget * functionStack,const QObject * receiver,bool) const39 QWidget *TextRuleWidgetHandler::createFunctionWidget(int number, QStackedWidget *functionStack, const QObject *receiver, bool /*isBalooSearch*/) const
40 {
41 if (number != 0) {
42 return nullptr;
43 }
44
45 auto funcCombo = new QComboBox(functionStack);
46 funcCombo->setMinimumWidth(50);
47 funcCombo->setObjectName(QStringLiteral("textRuleFuncCombo"));
48 for (int i = 0; i < TextFunctionCount; ++i) {
49 funcCombo->addItem(i18n(TextFunctions[i].displayName));
50 }
51 funcCombo->adjustSize();
52 QObject::connect(funcCombo, SIGNAL(activated(int)), receiver, SLOT(slotFunctionChanged()));
53 return funcCombo;
54 }
55
56 //---------------------------------------------------------------------------
57
createValueWidget(int number,QStackedWidget * valueStack,const QObject * receiver) const58 QWidget *TextRuleWidgetHandler::createValueWidget(int number, QStackedWidget *valueStack, const QObject *receiver) const
59 {
60 if (number == 0) {
61 auto lineEdit = new KLineEdit(valueStack);
62 lineEdit->setClearButtonEnabled(true);
63 lineEdit->setTrapReturnKey(true);
64 lineEdit->setObjectName(QStringLiteral("regExpLineEdit"));
65 QObject::connect(lineEdit, SIGNAL(textChanged(QString)), receiver, SLOT(slotValueChanged()));
66 QObject::connect(lineEdit, SIGNAL(returnPressed()), receiver, SLOT(slotReturnPressed()));
67 return lineEdit;
68 }
69
70 // blank QLabel to hide value widget for in-address-book rule
71 if (number == 1) {
72 auto label = new QLabel(valueStack);
73 label->setObjectName(QStringLiteral("textRuleValueHider"));
74 label->setBuddy(valueStack);
75 return label;
76 }
77 return nullptr;
78 }
79
80 //---------------------------------------------------------------------------
81
currentFunction(const QStackedWidget * functionStack) const82 SearchRule::Function TextRuleWidgetHandler::currentFunction(const QStackedWidget *functionStack) const
83 {
84 const auto funcCombo = functionStack->findChild<QComboBox *>(QStringLiteral("textRuleFuncCombo"));
85
86 if (funcCombo && funcCombo->currentIndex() >= 0) {
87 return TextFunctions[funcCombo->currentIndex()].id;
88 }
89
90 return SearchRule::FuncNone;
91 }
92
93 //---------------------------------------------------------------------------
94
function(const QByteArray &,const QStackedWidget * functionStack) const95 SearchRule::Function TextRuleWidgetHandler::function(const QByteArray &, const QStackedWidget *functionStack) const
96 {
97 return currentFunction(functionStack);
98 }
99
100 //---------------------------------------------------------------------------
101
currentValue(const QStackedWidget * valueStack,SearchRule::Function) const102 QString TextRuleWidgetHandler::currentValue(const QStackedWidget *valueStack, SearchRule::Function) const
103 {
104 // in other cases of func it is a lineedit
105 const KLineEdit *lineEdit = valueStack->findChild<KLineEdit *>(QStringLiteral("regExpLineEdit"));
106
107 if (lineEdit) {
108 return lineEdit->text();
109 }
110
111 // or anything else, like addressbook
112 return QString();
113 }
114
115 //---------------------------------------------------------------------------
116
value(const QByteArray &,const QStackedWidget * functionStack,const QStackedWidget * valueStack) const117 QString TextRuleWidgetHandler::value(const QByteArray &, const QStackedWidget *functionStack, const QStackedWidget *valueStack) const
118 {
119 SearchRule::Function func = currentFunction(functionStack);
120 return currentValue(valueStack, func);
121 }
122
123 //---------------------------------------------------------------------------
124
prettyValue(const QByteArray &,const QStackedWidget * functionStack,const QStackedWidget * valueStack) const125 QString TextRuleWidgetHandler::prettyValue(const QByteArray &, const QStackedWidget *functionStack, const QStackedWidget *valueStack) const
126 {
127 SearchRule::Function func = currentFunction(functionStack);
128 return currentValue(valueStack, func);
129 }
130
131 //---------------------------------------------------------------------------
132
handlesField(const QByteArray &) const133 bool TextRuleWidgetHandler::handlesField(const QByteArray &) const
134 {
135 return true; // we handle all fields (as fallback)
136 }
137
138 //---------------------------------------------------------------------------
139
reset(QStackedWidget * functionStack,QStackedWidget * valueStack) const140 void TextRuleWidgetHandler::reset(QStackedWidget *functionStack, QStackedWidget *valueStack) const
141 {
142 // reset the function combo box
143 const auto funcCombo = functionStack->findChild<QComboBox *>(QStringLiteral("textRuleFuncCombo"));
144
145 if (funcCombo) {
146 funcCombo->blockSignals(true);
147 funcCombo->setCurrentIndex(0);
148 funcCombo->blockSignals(false);
149 }
150
151 // reset the value widget
152 auto *lineEdit = valueStack->findChild<KLineEdit *>(QStringLiteral("regExpLineEdit"));
153 if (lineEdit) {
154 lineEdit->blockSignals(true);
155 lineEdit->clear();
156 lineEdit->blockSignals(false);
157 lineEdit->setClearButtonEnabled(false);
158 lineEdit->setClearButtonEnabled(true);
159 valueStack->setCurrentWidget(lineEdit);
160 }
161 }
162
163 //---------------------------------------------------------------------------
164
setRule(QStackedWidget * functionStack,QStackedWidget * valueStack,const SearchRule::Ptr rule,bool) const165 bool TextRuleWidgetHandler::setRule(QStackedWidget *functionStack, QStackedWidget *valueStack, const SearchRule::Ptr rule, bool /*isBalooSearch*/) const
166 {
167 if (!rule) {
168 reset(functionStack, valueStack);
169 return false;
170 }
171
172 const SearchRule::Function func = rule->function();
173 int i = 0;
174 for (; i < TextFunctionCount; ++i) {
175 if (func == TextFunctions[i].id) {
176 break;
177 }
178 }
179
180 const auto funcCombo = functionStack->findChild<QComboBox *>(QStringLiteral("textRuleFuncCombo"));
181
182 if (funcCombo) {
183 funcCombo->blockSignals(true);
184 if (i < TextFunctionCount) {
185 funcCombo->setCurrentIndex(i);
186 } else {
187 funcCombo->setCurrentIndex(0);
188 }
189 funcCombo->blockSignals(false);
190 functionStack->setCurrentWidget(funcCombo);
191 }
192 auto *lineEdit = valueStack->findChild<KLineEdit *>(QStringLiteral("regExpLineEdit"));
193
194 if (lineEdit) {
195 lineEdit->blockSignals(true);
196 lineEdit->setText(rule->contents());
197 lineEdit->blockSignals(false);
198 lineEdit->setClearButtonEnabled(false);
199 lineEdit->setClearButtonEnabled(true);
200 valueStack->setCurrentWidget(lineEdit);
201 }
202 return true;
203 }
204
205 //---------------------------------------------------------------------------
206
update(const QByteArray &,QStackedWidget * functionStack,QStackedWidget * valueStack) const207 bool TextRuleWidgetHandler::update(const QByteArray &, QStackedWidget *functionStack, QStackedWidget *valueStack) const
208 {
209 // raise the correct function widget
210 functionStack->setCurrentWidget(functionStack->findChild<QWidget *>(QStringLiteral("textRuleFuncCombo")));
211
212 // raise the correct value widget
213 SearchRule::Function func = currentFunction(functionStack);
214 if (func == SearchRule::FuncIsInAddressbook || func == SearchRule::FuncIsNotInAddressbook) {
215 valueStack->setCurrentWidget(valueStack->findChild<QWidget *>(QStringLiteral("textRuleValueHider")));
216 } else {
217 auto *lineEdit = valueStack->findChild<KLineEdit *>(QStringLiteral("regExpLineEdit"));
218
219 if (lineEdit) {
220 valueStack->setCurrentWidget(lineEdit);
221 }
222 }
223 return true;
224 }
225