File indexing completed on 2024-11-17 04:51:14
0001 /* 0002 SPDX-FileCopyrightText: 2015-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "searchrulestatus.h" 0008 #include "filter/filterlog.h" 0009 using MailCommon::FilterLog; 0010 0011 using namespace MailCommon; 0012 0013 struct _statusNames { 0014 const char *name; 0015 Akonadi::MessageStatus status; 0016 }; 0017 0018 static struct _statusNames statusNames[] = {{"Important", Akonadi::MessageStatus::statusImportant()}, 0019 {"Unread", Akonadi::MessageStatus::statusUnread()}, 0020 {"Read", Akonadi::MessageStatus::statusRead()}, 0021 {"Deleted", Akonadi::MessageStatus::statusDeleted()}, 0022 {"Replied", Akonadi::MessageStatus::statusReplied()}, 0023 {"Forwarded", Akonadi::MessageStatus::statusForwarded()}, 0024 {"Queued", Akonadi::MessageStatus::statusQueued()}, 0025 {"Sent", Akonadi::MessageStatus::statusSent()}, 0026 {"Watched", Akonadi::MessageStatus::statusWatched()}, 0027 {"Ignored", Akonadi::MessageStatus::statusIgnored()}, 0028 {"Action Item", Akonadi::MessageStatus::statusToAct()}, 0029 {"Spam", Akonadi::MessageStatus::statusSpam()}, 0030 {"Ham", Akonadi::MessageStatus::statusHam()}, 0031 {"Has Attachment", Akonadi::MessageStatus::statusHasAttachment()}}; 0032 0033 QString englishNameForStatus(Akonadi::MessageStatus status) 0034 { 0035 for (const _statusNames &statusName : statusNames) { 0036 if (statusName.status == status) { 0037 return QString::fromLatin1(statusName.name); 0038 } 0039 } 0040 return {}; 0041 } 0042 0043 SearchRuleStatus::SearchRuleStatus(const QByteArray &field, Function func, const QString &aContents) 0044 : SearchRule(field, func, aContents) 0045 { 0046 // the values are always in english, both from the conf file as well as 0047 // the patternedit gui 0048 mStatus = statusFromEnglishName(aContents); 0049 } 0050 0051 SearchRuleStatus::SearchRuleStatus(Akonadi::MessageStatus status, Function func) 0052 : SearchRule("<status>", func, englishNameForStatus(status)) 0053 { 0054 mStatus = status; 0055 } 0056 0057 Akonadi::MessageStatus SearchRuleStatus::statusFromEnglishName(const QString &aStatusString) 0058 { 0059 for (const _statusNames &statusName : statusNames) { 0060 if (!aStatusString.compare(QString::fromLatin1(statusName.name))) { 0061 return statusName.status; 0062 } 0063 } 0064 Akonadi::MessageStatus unknown; 0065 return unknown; 0066 } 0067 0068 QString SearchRuleStatus::informationAboutNotValidRules() const 0069 { 0070 // TODO 0071 return {}; 0072 } 0073 0074 bool SearchRuleStatus::isEmpty() const 0075 { 0076 return field().trimmed().isEmpty() || contents().isEmpty(); 0077 } 0078 0079 bool SearchRuleStatus::matches(const Akonadi::Item &item) const 0080 { 0081 Akonadi::MessageStatus status; 0082 status.setStatusFromFlags(item.flags()); 0083 bool rc = false; 0084 switch (function()) { 0085 case FuncEquals: // fallthrough. So that "<status> 'is' 'read'" works 0086 case FuncContains: 0087 if (status & mStatus) { 0088 rc = true; 0089 } 0090 break; 0091 case FuncNotEqual: // fallthrough. So that "<status> 'is not' 'read'" works 0092 case FuncContainsNot: 0093 if (!(status & mStatus)) { 0094 rc = true; 0095 } 0096 break; 0097 // FIXME what about the remaining funcs, how can they make sense for 0098 // statuses? 0099 default: 0100 break; 0101 } 0102 if (FilterLog::instance()->isLogging()) { 0103 QString msg = (rc ? QStringLiteral("<font color=#00FF00>1 = </font>") : QStringLiteral("<font color=#FF0000>0 = </font>")); 0104 msg += FilterLog::recode(asString()); 0105 FilterLog::instance()->add(msg, FilterLog::RuleResult); 0106 } 0107 return rc; 0108 } 0109 0110 SearchRule::RequiredPart SearchRuleStatus::requiredPart() const 0111 { 0112 return SearchRule::Envelope; 0113 } 0114 0115 void SearchRuleStatus::addQueryTerms(Akonadi::SearchTerm &groupTerm, bool &emptyIsNotAnError) const 0116 { 0117 using namespace Akonadi; 0118 emptyIsNotAnError = true; 0119 // TODO double check that isRead also works 0120 if (!mStatus.statusFlags().isEmpty()) { 0121 EmailSearchTerm term(EmailSearchTerm::MessageStatus, mStatus.statusFlags().values().first(), akonadiComparator()); 0122 term.setIsNegated(isNegated()); 0123 groupTerm.addSubTerm(term); 0124 } else { 0125 // Special case Unread 0126 Akonadi::MessageStatus status; 0127 status.setRead(true); 0128 EmailSearchTerm term(EmailSearchTerm::MessageStatus, status.statusFlags().values().first(), akonadiComparator()); 0129 term.setIsNegated(!isNegated()); 0130 groupTerm.addSubTerm(term); 0131 } 0132 }