File indexing completed on 2024-06-09 05:18:13
0001 /* 0002 0003 SPDX-FileCopyrightText: Marc Mutz <mutz@kde.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #pragma once 0009 0010 #include "mailcommon/searchrule.h" 0011 #include "mailcommon_export.h" 0012 #include <KLocalizedString> 0013 0014 #include <QList> 0015 #include <QString> 0016 0017 #include <Akonadi/SearchQuery> 0018 0019 namespace Akonadi 0020 { 0021 class Item; 0022 } 0023 0024 namespace KMime 0025 { 0026 class Message; 0027 } 0028 0029 class KConfigGroup; 0030 0031 namespace MailCommon 0032 { 0033 // ------------------------------------------------------------------------ 0034 0035 /** This class is an abstraction of a search over messages. It is 0036 intended to be used inside a KFilter (which adds KFilterAction's), 0037 as well as in KMSearch. It can read and write itself into a 0038 KConfig group and there is a constructor, mainly used by KMFilter 0039 to initialize from a preset KConfig-Group. 0040 0041 From a class hierarchy point of view, it is a QPtrList of 0042 SearchRule's that adds the boolean operators (see Operator) 0043 'and' and 'or' that connect the rules logically, and has a name 0044 under which it could be stored in the config file. 0045 0046 As a QPtrList with autoDelete enabled, it assumes that it is the 0047 central repository for the rules it contains. So if you want to 0048 reuse a rule in another pattern, make a deep copy of that rule. 0049 0050 @short An abstraction of a search over messages. 0051 @author Marc Mutz <mutz@kde.org> 0052 */ 0053 class MAILCOMMON_EXPORT SearchPattern : public QList<SearchRule::Ptr> 0054 { 0055 public: 0056 /** 0057 * Boolean operators that connect the return values of the 0058 * individual rules. A pattern with @p OpAnd will match iff all 0059 * it's rules match, whereas a pattern with @p OpOr will match if 0060 * any of it's rules matches. 0061 */ 0062 enum Operator { 0063 OpAnd, 0064 OpOr, 0065 OpAll, 0066 }; 0067 0068 enum SparqlQueryError { 0069 NoError = 0, 0070 MissingCheck, 0071 FolderEmptyOrNotIndexed, 0072 EmptyResult, 0073 NotEnoughCharacters, 0074 }; 0075 0076 /** 0077 * Constructor which provides a pattern with minimal, but 0078 * sufficient initialization. Unmodified, such a pattern will fail 0079 * to match any KMime::Message. You can query for such an empty 0080 * rule by using isEmpty, which is inherited from QPtrList. 0081 */ 0082 SearchPattern(); 0083 0084 /** 0085 * Constructor that initializes from a given KConfig group, if 0086 * given. This feature is mainly (solely?) used in KMFilter, 0087 * as we don't allow to store search patterns in the config (yet). 0088 */ 0089 explicit SearchPattern(const KConfigGroup &config); 0090 0091 /** Destructor. Deletes all stored rules! */ 0092 ~SearchPattern(); 0093 0094 /** 0095 * The central function of this class. Tries to match the set of 0096 * rules against a KMime::Message. It's virtual to allow derived 0097 * classes with added rules to reimplement it, yet reimplemented 0098 * methods should and (&&) the result of this function with their 0099 * own result or else most functionality is lacking, or has to be 0100 * reimplemented, since the rules are private to this class. 0101 * 0102 * @return true if the match was successful, false otherwise. 0103 */ 0104 bool matches(const Akonadi::Item &item, bool ignoreBody = false) const; 0105 0106 /** 0107 * Returns the required part from the item that is needed for the search to 0108 * operate. See @ref SearchRule::RequiredPart */ 0109 SearchRule::RequiredPart requiredPart() const; 0110 0111 /** 0112 * Removes all empty rules from the list. You should call this 0113 * method whenever the user had had control of the rules outside of 0114 * this class. (e.g. after editing it with SearchPatternEdit). 0115 */ 0116 QString purify(bool removeAction = true); 0117 0118 /** 0119 * Reads a search pattern from a KConfigGroup. If it does not find 0120 * a valid saerch pattern in the preset group, initializes the pattern 0121 * as if it were constructed using the default constructor. 0122 * 0123 * For backwards compatibility with previous versions of KMail, it 0124 * checks for old-style filter rules (e.g. using @p OpIgnore) 0125 * in @p config und converts them to the new format on writeConfig. 0126 * 0127 * Derived classes reimplementing readConfig() should also call this 0128 * method, or else the rules will not be loaded. 0129 */ 0130 void readConfig(const KConfigGroup &config); 0131 0132 /** 0133 * Writes itself into @p config. Tries to delete old-style keys by 0134 * overwriting them with QString(). 0135 * 0136 * Derived classes reimplementing writeConfig() should also call this 0137 * method, or else the rules will not be stored. 0138 */ 0139 void writeConfig(KConfigGroup &config) const; 0140 0141 /** 0142 * Returns the name of the search pattern. 0143 */ 0144 QString name() const 0145 { 0146 return mName; 0147 } 0148 0149 /** 0150 * Sets the name of the search pattern. KMFilter uses this to 0151 * store it's own name, too. 0152 */ 0153 void setName(const QString &newName) 0154 { 0155 mName = newName; 0156 } 0157 0158 /** 0159 * Returns the filter operator. 0160 */ 0161 SearchPattern::Operator op() const 0162 { 0163 return mOperator; 0164 } 0165 0166 /** 0167 * Sets the filter operator. 0168 */ 0169 void setOp(SearchPattern::Operator aOp) 0170 { 0171 mOperator = aOp; 0172 } 0173 0174 static int filterRulesMaximumSize(); 0175 /** 0176 * Returns the pattern as string. For debugging. 0177 */ 0178 QString asString() const; 0179 0180 /** 0181 * Returns the pattern as akonadi query 0182 */ 0183 SparqlQueryError asAkonadiQuery(Akonadi::SearchQuery &) const; 0184 0185 /** 0186 * Overloaded assignment operator. Makes a deep copy. 0187 */ 0188 const SearchPattern &operator=(const SearchPattern &aPattern); 0189 0190 /** 0191 * Writes the pattern into a byte array for persistence purposes. 0192 */ 0193 QByteArray serialize() const; 0194 0195 /** 0196 * Constructs the pattern from a byte array serialization. 0197 */ 0198 void deserialize(const QByteArray &); 0199 0200 QDataStream &operator>>(QDataStream &s) const; 0201 QDataStream &operator<<(QDataStream &s); 0202 0203 void generateSieveScript(QStringList &requiresModules, QString &code); 0204 0205 private: 0206 /** 0207 * Tries to import a legacy search pattern, ie. one that still has 0208 * e.g. the @p unless or @p ignore operator which were useful as long as 0209 * the number of rules was restricted to two. This method is called from 0210 * readConfig, which detects legacy configurations and also makes sure 0211 * that this method is called from an initialized object. 0212 */ 0213 MAILCOMMON_NO_EXPORT void importLegacyConfig(const KConfigGroup &config); 0214 0215 /** 0216 * Initializes the object. Clears the list of rules, sets the name 0217 * to "<i18n("unnamed")>", and the boolean operator to @p OpAnd. 0218 */ 0219 void init(); 0220 QString mName; 0221 Operator mOperator; 0222 }; 0223 } 0224 0225 Q_DECLARE_METATYPE(MailCommon::SearchRule::RequiredPart)