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 }