File indexing completed on 2024-11-17 04:51:15
0001 /* 0002 SPDX-FileCopyrightText: 2013-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "headersrulerwidgethandler.h" 0008 0009 #include "search/searchpattern.h" 0010 0011 #include <KLineEdit> 0012 #include <KLocalizedString> 0013 0014 #include <KLazyLocalizedString> 0015 #include <QComboBox> 0016 #include <QLabel> 0017 #include <QStackedWidget> 0018 using namespace MailCommon; 0019 0020 // also see SearchRule::matches() and SearchRule::Function 0021 // if you change the following strings! 0022 static const struct { 0023 SearchRule::Function id; 0024 const KLazyLocalizedString displayName; 0025 } HeaderFunctions[] = {{SearchRule::FuncContains, kli18n("contains")}, 0026 {SearchRule::FuncContainsNot, kli18n("does not contain")}, 0027 {SearchRule::FuncEquals, kli18n("equals")}, 0028 {SearchRule::FuncNotEqual, kli18n("does not equal")}, 0029 {SearchRule::FuncStartWith, kli18n("starts with")}, 0030 {SearchRule::FuncNotStartWith, kli18n("does not start with")}, 0031 {SearchRule::FuncEndWith, kli18n("ends with")}, 0032 {SearchRule::FuncNotEndWith, kli18n("does not end with")}, 0033 0034 {SearchRule::FuncRegExp, kli18n("matches regular expr.")}, 0035 {SearchRule::FuncNotRegExp, kli18n("does not match reg. expr.")}, 0036 {SearchRule::FuncIsInAddressbook, kli18n("is in address book")}, 0037 {SearchRule::FuncIsNotInAddressbook, kli18n("is not in address book")}}; 0038 static const int HeadersFunctionCount = sizeof(HeaderFunctions) / sizeof(*HeaderFunctions); 0039 0040 //--------------------------------------------------------------------------- 0041 0042 QWidget *HeadersRuleWidgetHandler::createFunctionWidget(int number, QStackedWidget *functionStack, const QObject *receiver, bool isBalooSearch) const 0043 { 0044 if (number != 0) { 0045 return nullptr; 0046 } 0047 0048 auto funcCombo = new QComboBox(functionStack); 0049 funcCombo->setMinimumWidth(50); 0050 funcCombo->setObjectName(QLatin1StringView("headerRuleFuncCombo")); 0051 for (int i = 0; i < HeadersFunctionCount; ++i) { 0052 if (!(isBalooSearch && (HeaderFunctions[i].id == SearchRule::FuncIsInAddressbook || HeaderFunctions[i].id == SearchRule::FuncIsNotInAddressbook))) { 0053 funcCombo->addItem(HeaderFunctions[i].displayName.toString()); 0054 } 0055 } 0056 funcCombo->adjustSize(); 0057 QObject::connect(funcCombo, SIGNAL(activated(int)), receiver, SLOT(slotFunctionChanged())); 0058 return funcCombo; 0059 } 0060 0061 //--------------------------------------------------------------------------- 0062 0063 QWidget *HeadersRuleWidgetHandler::createValueWidget(int number, QStackedWidget *valueStack, const QObject *receiver) const 0064 { 0065 if (number == 0) { 0066 auto lineEdit = new KLineEdit(valueStack); 0067 lineEdit->setClearButtonEnabled(true); 0068 lineEdit->setTrapReturnKey(true); 0069 lineEdit->setObjectName(QLatin1StringView("regExpLineEdit")); 0070 QObject::connect(lineEdit, SIGNAL(textChanged(QString)), receiver, SLOT(slotValueChanged())); 0071 QObject::connect(lineEdit, SIGNAL(returnPressed()), receiver, SLOT(slotReturnPressed())); 0072 return lineEdit; 0073 } 0074 0075 // blank QLabel to hide value widget for in-address-book rule 0076 if (number == 1) { 0077 auto label = new QLabel(valueStack); 0078 label->setObjectName(QLatin1StringView("headerRuleValueHider")); 0079 label->setBuddy(valueStack); 0080 return label; 0081 } 0082 return nullptr; 0083 } 0084 0085 //--------------------------------------------------------------------------- 0086 0087 SearchRule::Function HeadersRuleWidgetHandler::currentFunction(const QStackedWidget *functionStack) const 0088 { 0089 const auto funcCombo = functionStack->findChild<QComboBox *>(QStringLiteral("headerRuleFuncCombo")); 0090 0091 if (funcCombo && funcCombo->currentIndex() >= 0) { 0092 return HeaderFunctions[funcCombo->currentIndex()].id; 0093 } 0094 0095 return SearchRule::FuncNone; 0096 } 0097 0098 //--------------------------------------------------------------------------- 0099 0100 SearchRule::Function HeadersRuleWidgetHandler::function(const QByteArray &field, const QStackedWidget *functionStack) const 0101 { 0102 if (!handlesField(field)) { 0103 return SearchRule::FuncNone; 0104 } 0105 return currentFunction(functionStack); 0106 } 0107 0108 //--------------------------------------------------------------------------- 0109 QString HeadersRuleWidgetHandler::currentValue(const QStackedWidget *valueStack, SearchRule::Function func) const 0110 { 0111 Q_UNUSED(func) 0112 0113 const KLineEdit *lineEdit = valueStack->findChild<KLineEdit *>(QStringLiteral("regExpLineEdit")); 0114 0115 if (lineEdit) { 0116 return lineEdit->text(); 0117 } 0118 0119 // or anything else, like addressbook 0120 return {}; 0121 } 0122 0123 //--------------------------------------------------------------------------- 0124 0125 QString HeadersRuleWidgetHandler::value(const QByteArray &field, const QStackedWidget *functionStack, const QStackedWidget *valueStack) const 0126 { 0127 if (!handlesField(field)) { 0128 return {}; 0129 } 0130 SearchRule::Function func = currentFunction(functionStack); 0131 if (func == SearchRule::FuncIsInAddressbook) { 0132 return QStringLiteral("is in address book"); // just a non-empty dummy value 0133 } else if (func == SearchRule::FuncIsNotInAddressbook) { 0134 return QStringLiteral("is not in address book"); // just a non-empty dummy value 0135 } else { 0136 return currentValue(valueStack, func); 0137 } 0138 } 0139 0140 //--------------------------------------------------------------------------- 0141 0142 QString HeadersRuleWidgetHandler::prettyValue(const QByteArray &field, const QStackedWidget *functionStack, const QStackedWidget *valueStack) const 0143 { 0144 if (!handlesField(field)) { 0145 return {}; 0146 } 0147 0148 SearchRule::Function func = currentFunction(functionStack); 0149 0150 if (func == SearchRule::FuncIsInAddressbook) { 0151 return i18n("is in address book"); 0152 } else if (func == SearchRule::FuncIsNotInAddressbook) { 0153 return i18n("is not in address book"); 0154 } else { 0155 return currentValue(valueStack, func); 0156 } 0157 } 0158 0159 //--------------------------------------------------------------------------- 0160 0161 bool HeadersRuleWidgetHandler::handlesField(const QByteArray &field) const 0162 { 0163 return field == "To" || field == "From" || field == "CC" || field == "<recipients>"; 0164 } 0165 0166 //--------------------------------------------------------------------------- 0167 0168 void HeadersRuleWidgetHandler::reset(QStackedWidget *functionStack, QStackedWidget *valueStack) const 0169 { 0170 // reset the function combo box 0171 const auto funcCombo = functionStack->findChild<QComboBox *>(QStringLiteral("headerRuleFuncCombo")); 0172 0173 if (funcCombo) { 0174 funcCombo->blockSignals(true); 0175 funcCombo->setCurrentIndex(0); 0176 funcCombo->blockSignals(false); 0177 } 0178 0179 // reset the value widget 0180 auto lineEdit = valueStack->findChild<KLineEdit *>(QStringLiteral("regExpLineEdit")); 0181 if (lineEdit) { 0182 lineEdit->blockSignals(true); 0183 lineEdit->clear(); 0184 lineEdit->blockSignals(false); 0185 lineEdit->setClearButtonEnabled(false); 0186 lineEdit->setClearButtonEnabled(true); 0187 valueStack->setCurrentWidget(lineEdit); 0188 } 0189 } 0190 0191 //--------------------------------------------------------------------------- 0192 0193 bool HeadersRuleWidgetHandler::setRule(QStackedWidget *functionStack, QStackedWidget *valueStack, const SearchRule::Ptr rule, bool isBalooSearch) const 0194 { 0195 if (!rule || !handlesField(rule->field())) { 0196 reset(functionStack, valueStack); 0197 return false; 0198 } 0199 0200 const SearchRule::Function func = rule->function(); 0201 if ((isBalooSearch && (func == SearchRule::FuncIsInAddressbook || func == SearchRule::FuncIsNotInAddressbook))) { 0202 reset(functionStack, valueStack); 0203 return false; 0204 } 0205 0206 int i = 0; 0207 for (; i < HeadersFunctionCount; ++i) { 0208 if (func == HeaderFunctions[i].id) { 0209 break; 0210 } 0211 } 0212 0213 const auto funcCombo = functionStack->findChild<QComboBox *>(QStringLiteral("headerRuleFuncCombo")); 0214 0215 if (funcCombo) { 0216 funcCombo->blockSignals(true); 0217 if (i < HeadersFunctionCount) { 0218 funcCombo->setCurrentIndex(i); 0219 } else { 0220 funcCombo->setCurrentIndex(0); 0221 } 0222 funcCombo->blockSignals(false); 0223 functionStack->setCurrentWidget(funcCombo); 0224 } 0225 0226 if (func == SearchRule::FuncIsInAddressbook || func == SearchRule::FuncIsNotInAddressbook) { 0227 auto w = valueStack->findChild<QWidget *>(QStringLiteral("headerRuleValueHider")); 0228 valueStack->setCurrentWidget(w); 0229 } else { 0230 auto lineEdit = valueStack->findChild<KLineEdit *>(QStringLiteral("regExpLineEdit")); 0231 0232 if (lineEdit) { 0233 lineEdit->blockSignals(true); 0234 lineEdit->setText(rule->contents()); 0235 lineEdit->blockSignals(false); 0236 lineEdit->setClearButtonEnabled(false); 0237 lineEdit->setClearButtonEnabled(true); 0238 valueStack->setCurrentWidget(lineEdit); 0239 } 0240 } 0241 return true; 0242 } 0243 0244 //--------------------------------------------------------------------------- 0245 0246 bool HeadersRuleWidgetHandler::update(const QByteArray &field, QStackedWidget *functionStack, QStackedWidget *valueStack) const 0247 { 0248 if (!handlesField(field)) { 0249 return false; 0250 } 0251 0252 // raise the correct function widget 0253 functionStack->setCurrentWidget(functionStack->findChild<QWidget *>(QStringLiteral("headerRuleFuncCombo"))); 0254 0255 // raise the correct value widget 0256 SearchRule::Function func = currentFunction(functionStack); 0257 if (func == SearchRule::FuncIsInAddressbook || func == SearchRule::FuncIsNotInAddressbook) { 0258 valueStack->setCurrentWidget(valueStack->findChild<QWidget *>(QStringLiteral("headerRuleValueHider"))); 0259 } else { 0260 auto lineEdit = valueStack->findChild<KLineEdit *>(QStringLiteral("regExpLineEdit")); 0261 0262 if (lineEdit) { 0263 valueStack->setCurrentWidget(lineEdit); 0264 } 0265 } 0266 return true; 0267 }