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 "statusrulewidgethandler.h"
0008 
0009 #include <KLazyLocalizedString>
0010 #include <QComboBox>
0011 #include <QIcon>
0012 #include <QStackedWidget>
0013 using namespace MailCommon;
0014 
0015 static const struct {
0016     SearchRule::Function id;
0017     const KLazyLocalizedString displayName;
0018 } StatusFunctions[] = {{SearchRule::FuncContains, kli18n("is")}, {SearchRule::FuncContainsNot, kli18n("is not")}};
0019 static const int StatusFunctionCount = sizeof(StatusFunctions) / sizeof(*StatusFunctions);
0020 
0021 struct MessageStatusInfo {
0022     const KLazyLocalizedString text;
0023     const char *icon;
0024 };
0025 
0026 // If you change the ordering here; also do it in the enum below
0027 static const MessageStatusInfo StatusValues[] = {
0028     {kli18nc("message status", "Important"), "emblem-important"},
0029     {kli18nc("message status", "Action Item"), "mail-task"},
0030     {kli18nc("message status", "Unread"), "mail-unread"},
0031     {kli18nc("message status", "Read"), "mail-read"},
0032     {kli18nc("message status", "Deleted"), "mail-deleted"},
0033     {kli18nc("message status", "Replied"), "mail-replied"},
0034     {kli18nc("message status", "Forwarded"), "mail-forwarded"},
0035     {kli18nc("message status", "Queued"), "mail-queued"},
0036     {kli18nc("message status", "Sent"), "mail-sent"},
0037     {kli18nc("message status", "Watched"), "mail-thread-watch"},
0038     {kli18nc("message status", "Ignored"), "mail-thread-ignored"},
0039     {kli18nc("message status", "Spam"), "mail-mark-junk"},
0040     {kli18nc("message status", "Ham"), "mail-mark-notjunk"},
0041     {kli18nc("message status", "Has Attachment"), "mail-attachment"} // must be last
0042 };
0043 
0044 static const int StatusValueCount = sizeof(StatusValues) / sizeof(MessageStatusInfo);
0045 // we want to show all status entries in the quick search bar, but only the
0046 // ones up to attachment in the search/filter dialog, because there the
0047 // attachment case is handled separately.
0048 static const int StatusValueCountWithoutHidden = StatusValueCount - 1;
0049 
0050 //---------------------------------------------------------------------------
0051 
0052 QWidget *StatusRuleWidgetHandler::createFunctionWidget(int number, QStackedWidget *functionStack, const QObject *receiver, bool /*isBalooSearch*/) const
0053 {
0054     if (number != 0) {
0055         return nullptr;
0056     }
0057 
0058     auto funcCombo = new QComboBox(functionStack);
0059     funcCombo->setMinimumWidth(50);
0060     funcCombo->setObjectName(QLatin1StringView("statusRuleFuncCombo"));
0061     for (int i = 0; i < StatusFunctionCount; ++i) {
0062         funcCombo->addItem(StatusFunctions[i].displayName.toString());
0063     }
0064     funcCombo->adjustSize();
0065     QObject::connect(funcCombo, SIGNAL(activated(int)), receiver, SLOT(slotFunctionChanged()));
0066     return funcCombo;
0067 }
0068 
0069 //---------------------------------------------------------------------------
0070 
0071 QWidget *StatusRuleWidgetHandler::createValueWidget(int number, QStackedWidget *valueStack, const QObject *receiver) const
0072 {
0073     if (number != 0) {
0074         return nullptr;
0075     }
0076 
0077     auto statusCombo = new QComboBox(valueStack);
0078     statusCombo->setMinimumWidth(50);
0079     statusCombo->setObjectName(QLatin1StringView("statusRuleValueCombo"));
0080     for (int i = 0; i < StatusValueCountWithoutHidden; ++i) {
0081         if (StatusValues[i].icon != nullptr) {
0082             statusCombo->addItem(QIcon::fromTheme(QLatin1StringView(StatusValues[i].icon)), StatusValues[i].text.toString());
0083         } else {
0084             statusCombo->addItem(StatusValues[i].text.toString());
0085         }
0086     }
0087     statusCombo->adjustSize();
0088     QObject::connect(statusCombo, SIGNAL(activated(int)), receiver, SLOT(slotValueChanged()));
0089     return statusCombo;
0090 }
0091 
0092 //---------------------------------------------------------------------------
0093 
0094 SearchRule::Function StatusRuleWidgetHandler::currentFunction(const QStackedWidget *functionStack) const
0095 {
0096     const auto funcCombo = functionStack->findChild<QComboBox *>(QStringLiteral("statusRuleFuncCombo"));
0097 
0098     if (funcCombo && funcCombo->currentIndex() >= 0) {
0099         return StatusFunctions[funcCombo->currentIndex()].id;
0100     }
0101 
0102     return SearchRule::FuncNone;
0103 }
0104 
0105 //---------------------------------------------------------------------------
0106 
0107 SearchRule::Function StatusRuleWidgetHandler::function(const QByteArray &field, const QStackedWidget *functionStack) const
0108 {
0109     if (!handlesField(field)) {
0110         return SearchRule::FuncNone;
0111     }
0112 
0113     return currentFunction(functionStack);
0114 }
0115 
0116 //---------------------------------------------------------------------------
0117 
0118 int StatusRuleWidgetHandler::currentStatusValue(const QStackedWidget *valueStack) const
0119 {
0120     const auto statusCombo = valueStack->findChild<QComboBox *>(QStringLiteral("statusRuleValueCombo"));
0121 
0122     if (statusCombo) {
0123         return statusCombo->currentIndex();
0124     }
0125 
0126     return -1;
0127 }
0128 
0129 //---------------------------------------------------------------------------
0130 
0131 QString StatusRuleWidgetHandler::value(const QByteArray &field, const QStackedWidget *, const QStackedWidget *valueStack) const
0132 {
0133     if (!handlesField(field)) {
0134         return {};
0135     }
0136 
0137     const int status = currentStatusValue(valueStack);
0138     if (status != -1) {
0139         return StatusValues[status].text.untranslatedText();
0140     } else {
0141         return {};
0142     }
0143 }
0144 
0145 //---------------------------------------------------------------------------
0146 
0147 QString StatusRuleWidgetHandler::prettyValue(const QByteArray &field, const QStackedWidget *, const QStackedWidget *valueStack) const
0148 {
0149     if (!handlesField(field)) {
0150         return {};
0151     }
0152 
0153     const int status = currentStatusValue(valueStack);
0154     if (status != -1) {
0155         return StatusValues[status].text.toString();
0156     } else {
0157         return {};
0158     }
0159 }
0160 
0161 //---------------------------------------------------------------------------
0162 
0163 bool StatusRuleWidgetHandler::handlesField(const QByteArray &field) const
0164 {
0165     return field == "<status>";
0166 }
0167 
0168 //---------------------------------------------------------------------------
0169 
0170 void StatusRuleWidgetHandler::reset(QStackedWidget *functionStack, QStackedWidget *valueStack) const
0171 {
0172     // reset the function combo box
0173     auto funcCombo = functionStack->findChild<QComboBox *>(QStringLiteral("statusRuleFuncCombo"));
0174 
0175     if (funcCombo) {
0176         funcCombo->blockSignals(true);
0177         funcCombo->setCurrentIndex(0);
0178         funcCombo->blockSignals(false);
0179     }
0180 
0181     // reset the status value combo box
0182     auto statusCombo = valueStack->findChild<QComboBox *>(QStringLiteral("statusRuleValueCombo"));
0183 
0184     if (statusCombo) {
0185         statusCombo->blockSignals(true);
0186         statusCombo->setCurrentIndex(0);
0187         statusCombo->blockSignals(false);
0188     }
0189 }
0190 
0191 //---------------------------------------------------------------------------
0192 
0193 bool StatusRuleWidgetHandler::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     // set the function
0201     const SearchRule::Function func = rule->function();
0202     int funcIndex = 0;
0203     for (; funcIndex < StatusFunctionCount; ++funcIndex) {
0204         if (func == StatusFunctions[funcIndex].id) {
0205             break;
0206         }
0207     }
0208 
0209     const auto funcCombo = functionStack->findChild<QComboBox *>(QStringLiteral("statusRuleFuncCombo"));
0210 
0211     if (funcCombo) {
0212         funcCombo->blockSignals(true);
0213         if (funcIndex < StatusFunctionCount) {
0214             funcCombo->setCurrentIndex(funcIndex);
0215         } else {
0216             funcCombo->setCurrentIndex(0);
0217         }
0218         funcCombo->blockSignals(false);
0219         functionStack->setCurrentWidget(funcCombo);
0220     }
0221 
0222     // set the value
0223     const QString value = rule->contents();
0224     int valueIndex = 0;
0225     for (; valueIndex < StatusValueCountWithoutHidden; ++valueIndex) {
0226         if (value == StatusValues[valueIndex].text.untranslatedText()) {
0227             break;
0228         }
0229     }
0230 
0231     const auto statusCombo = valueStack->findChild<QComboBox *>(QStringLiteral("statusRuleValueCombo"));
0232 
0233     if (statusCombo) {
0234         statusCombo->blockSignals(true);
0235         if (valueIndex < StatusValueCountWithoutHidden) {
0236             statusCombo->setCurrentIndex(valueIndex);
0237         } else {
0238             statusCombo->setCurrentIndex(0);
0239         }
0240         statusCombo->blockSignals(false);
0241         valueStack->setCurrentWidget(statusCombo);
0242     }
0243     return true;
0244 }
0245 
0246 //---------------------------------------------------------------------------
0247 
0248 bool StatusRuleWidgetHandler::update(const QByteArray &field, QStackedWidget *functionStack, QStackedWidget *valueStack) const
0249 {
0250     if (!handlesField(field)) {
0251         return false;
0252     }
0253 
0254     // raise the correct function widget
0255     functionStack->setCurrentWidget(functionStack->findChild<QWidget *>(QStringLiteral("statusRuleFuncCombo")));
0256 
0257     // raise the correct value widget
0258     valueStack->setCurrentWidget(valueStack->findChild<QWidget *>(QStringLiteral("statusRuleValueCombo")));
0259 
0260     return true;
0261 }