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