summaryrefslogtreecommitdiffstats
path: root/kmail/kmsearchpattern.h
diff options
context:
space:
mode:
Diffstat (limited to 'kmail/kmsearchpattern.h')
-rw-r--r--kmail/kmsearchpattern.h407
1 files changed, 407 insertions, 0 deletions
diff --git a/kmail/kmsearchpattern.h b/kmail/kmsearchpattern.h
new file mode 100644
index 000000000..bb9a9600d
--- /dev/null
+++ b/kmail/kmsearchpattern.h
@@ -0,0 +1,407 @@
+// -*- mode: C++; c-file-style: "gnu" -*-
+// kmsearchpattern.h
+// Author: Marc Mutz <Marc@Mutz.com>
+// This code is under GPL!
+
+#ifndef _kmsearchpattern_h_
+#define _kmsearchpattern_h_
+
+#include <klocale.h>
+#include <qptrlist.h>
+#include <qstring.h>
+#include <qcstring.h>
+#include "kmmsgbase.h" // for KMMsgStatus
+
+class KMMessage;
+class KConfig;
+class DwBoyerMoore;
+class DwString;
+
+
+// maximum number of filter rules per filter
+const int FILTER_MAX_RULES=8;
+
+/** Incoming mail is sent through the list of mail filter
+ rules before it is placed in the associated mail folder (usually "inbox").
+ This class represents one mail filter rule. It is also used to represent
+ a search rule as used by the search dialog and folders.
+
+ @short This class represents one search pattern rule.
+*/
+class KMSearchRule
+{
+public:
+ /** Operators for comparison of field and contents.
+ If you change the order or contents of the enum: do not forget
+ to change funcConfigNames[], sFilterFuncList and matches()
+ in KMSearchRule, too.
+ Also, it is assumed that these functions come in pairs of logical
+ opposites (ie. "=" <-> "!=", ">" <-> "<=", etc.).
+ */
+ enum Function { FuncNone = -1,
+ FuncContains=0, FuncContainsNot,
+ FuncEquals, FuncNotEqual,
+ FuncRegExp, FuncNotRegExp,
+ FuncIsGreater, FuncIsLessOrEqual,
+ FuncIsLess, FuncIsGreaterOrEqual,
+ FuncIsInAddressbook, FuncIsNotInAddressbook,
+ FuncIsInCategory, FuncIsNotInCategory,
+ FuncHasAttachment, FuncHasNoAttachment};
+ KMSearchRule ( const QCString & field=0, Function=FuncContains,
+ const QString &contents=QString::null );
+ KMSearchRule ( const KMSearchRule &other );
+
+ const KMSearchRule & operator=( const KMSearchRule & other );
+
+ /** Create a search rule of a certain type by instantiating the appro-
+ priate subclass depending on the @p field. */
+ static KMSearchRule* createInstance( const QCString & field=0,
+ Function function=FuncContains,
+ const QString & contents=QString::null );
+
+ static KMSearchRule* createInstance( const QCString & field,
+ const char * function,
+ const QString & contents );
+
+ static KMSearchRule * createInstance( const KMSearchRule & other );
+
+ /** Initialize the object from a given config file. The group must
+ be preset. @p aIdx is an identifier that is used to distinguish
+ rules within a single config group. This function does no
+ validation of the data obtained from the config file. You should
+ call isEmpty yourself if you need valid rules. */
+ static KMSearchRule* createInstanceFromConfig( const KConfig * config, int aIdx );
+
+ virtual ~KMSearchRule() {};
+
+ /** Tries to match the rule against the given KMMessage.
+ @return TRUE if the rule matched, FALSE otherwise. Must be
+ implemented by subclasses.
+ */
+ virtual bool matches( const KMMessage * msg ) const = 0;
+
+ /** Optimized version tries to match the rule against the given
+ @see DwString.
+ @return TRUE if the rule matched, FALSE otherwise.
+ */
+ virtual bool matches( const DwString & str, KMMessage & msg,
+ const DwBoyerMoore * headerField=0,
+ int headerLen=-1 ) const;
+
+ /** Determine whether the rule is worth considering. It isn't if
+ either the field is not set or the contents is empty.
+ KFilter should make sure that it's rule list contains
+ only non-empty rules, as matches doesn't check this. */
+ virtual bool isEmpty() const = 0;
+
+ /** Returns true if the rule depends on a complete message,
+ otherwise returns false. */
+ virtual bool requiresBody() const { return true; }
+
+
+ /** Save the object into a given config file. The group must be
+ preset. @p aIdx is an identifier that is used to distinguish
+ rules within a single config group. This function will happily
+ write itself even when it's not valid, assuming higher layers to
+ Do The Right Thing(TM). */
+ void writeConfig( KConfig * config, int aIdx ) const;
+
+ /** Return filter function. This can be any of the operators
+ defined in Function. */
+ Function function() const { return mFunction; }
+
+ /** Set filter function. */
+ void setFunction( Function aFunction ) { mFunction = aFunction; }
+
+ /** Return message header field name (without the trailing ':').
+ There are also six pseudo-headers:
+ @li \<message\>: Try to match against the whole message.
+ @li \<body\>: Try to match against the body of the message.
+ @li \<any header\>: Try to match against any header field.
+ @li \<recipients\>: Try to match against both To: and Cc: header fields.
+ @li \<size\>: Try to match against size of message (numerical).
+ @li \<age in days\>: Try to match against age of message (numerical).
+ @li \<status\>: Try to match against status of message (status).
+ */
+ QCString field() const { return mField; }
+
+ /** Set message header field name (make sure there's no trailing
+ colon ':') */
+ void setField( const QCString & field ) { mField = field; }
+
+ /** Return the value. This can be either a substring to search for in
+ or a regexp pattern to match against the header. */
+ QString contents() const { return mContents; }
+ /** Set the value. */
+ void setContents( const QString & aContents ) { mContents = aContents; }
+
+ /** Returns the rule as string. For debugging.*/
+ const QString asString() const;
+
+private:
+ static Function configValueToFunc( const char * str );
+ static QString functionToString( Function function );
+
+ QCString mField;
+ Function mFunction;
+ QString mContents;
+};
+
+
+// subclasses representing the different kinds of searches
+
+/** This class represents a search to be performed against a string.
+ * The string can be either a message header, or a pseudo header, such
+ * as \<body\>
+ @short This class represents a search pattern rule operating on a string.
+*/
+
+class KMSearchRuleString : public KMSearchRule
+{
+public:
+ KMSearchRuleString( const QCString & field=0, Function function=FuncContains,
+ const QString & contents=QString::null );
+ KMSearchRuleString( const KMSearchRuleString & other );
+ const KMSearchRuleString & operator=( const KMSearchRuleString & other );
+
+ virtual ~KMSearchRuleString();
+ virtual bool isEmpty() const ;
+ virtual bool requiresBody() const;
+
+ virtual bool matches( const KMMessage * msg ) const;
+
+ /** Optimized version tries to match the rule against the given DwString.
+ @return TRUE if the rule matched, FALSE otherwise.
+ */
+ virtual bool matches( const DwString & str, KMMessage & msg,
+ const DwBoyerMoore * headerField=0,
+ int headerLen=-1 ) const;
+
+ /** Helper for the main matches() method. Does the actual comparing. */
+ bool matchesInternal( const QString & msgContents ) const;
+
+private:
+ const DwBoyerMoore *mBmHeaderField;
+};
+
+
+/** This class represents a search to be performed against a numerical value,
+ * such as the age of the message in days or its size.
+ @short This class represents a search pattern rule operating on numerical
+ values.
+*/
+
+class KMSearchRuleNumerical : public KMSearchRule
+{
+public:
+ KMSearchRuleNumerical( const QCString & field=0, Function function=FuncContains,
+ const QString & contents=QString::null );
+ virtual bool isEmpty() const ;
+
+ virtual bool matches( const KMMessage * msg ) const;
+
+ /** Helper for the main matches() method. Does the actual comparing. */
+ bool matchesInternal( long numericalValue, long numericalMsgContents,
+ const QString & msgContents ) const;
+};
+
+
+namespace KMail {
+// The below are used in several places and here so they are accessible.
+ struct MessageStatus {
+ const char * const text;
+ const char * const icon;
+ };
+
+ // If you change the ordering here; also do it in the enum below
+ static const MessageStatus StatusValues[] = {
+ { I18N_NOOP( "Important" ), "kmmsgflag" },
+ { I18N_NOOP( "New" ), "kmmsgnew" },
+ { I18N_NOOP( "Unread" ), "kmmsgunseen" },
+ { I18N_NOOP( "Read" ), "kmmsgread" },
+ { I18N_NOOP( "Old" ), 0 },
+ { I18N_NOOP( "Deleted" ), "kmmsgdel" },
+ { I18N_NOOP( "Replied" ), "kmmsgreplied" },
+ { I18N_NOOP( "Forwarded" ), "kmmsgforwarded" },
+ { I18N_NOOP( "Queued" ), "kmmsgqueued" },
+ { I18N_NOOP( "Sent" ), "kmmsgsent" },
+ { I18N_NOOP( "Watched" ), "kmmsgwatched" },
+ { I18N_NOOP( "Ignored" ), "kmmsgignored" },
+ { I18N_NOOP( "Spam" ), "kmmsgspam" },
+ { I18N_NOOP( "Ham" ), "kmmsgham" },
+ { I18N_NOOP( "To Do" ), "kmmsgtodo" },
+ { I18N_NOOP( "Has Attachment"), "kmmsgattachment" }
+ };
+ // If you change the ordering here; also do it in the array above
+ enum StatusValueTypes {
+ StatusImportant = 0,
+ StatusNew = 1,
+ StatusUnread = 2,
+ StatusRead = 3,
+ StatusOld = 4,
+ StatusDeleted = 5,
+ StatusReplied = 6,
+ StatusForwarded = 7,
+ StatusQueued = 8,
+ StatusSent = 9,
+ StatusWatched = 10,
+ StatusIgnored = 11,
+ StatusSpam = 12,
+ StatusHam = 13,
+ StatusToDo = 14,
+ StatusHasAttachment = 15
+ };
+
+ static const int StatusValueCount =
+ sizeof( StatusValues ) / sizeof( MessageStatus );
+ // we want to show all status entries in the quick search bar, but only the
+ // ones up to attachment in the search/filter dialog, because there the
+ // attachment case is handled separately.
+ static const int StatusValueCountWithoutHidden = StatusValueCount - 1;
+}
+
+/** This class represents a search to be performed against the status of a
+ * messsage. The status is represented by a bitfield.
+ @short This class represents a search pattern rule operating on message
+ status.
+*/
+class KMSearchRuleStatus : public KMSearchRule
+{
+public:
+ KMSearchRuleStatus( const QCString & field=0, Function function=FuncContains,
+ const QString & contents=QString::null );
+ KMSearchRuleStatus( int status, Function function=FuncContains );
+
+ virtual bool isEmpty() const ;
+ virtual bool matches( const KMMessage * msg ) const;
+ //Not possible to implement this form for status searching
+ virtual bool matches( const DwString &, KMMessage &,
+ const DwBoyerMoore *,
+ int ) const;
+ static KMMsgStatus statusFromEnglishName(const QString&);
+ private:
+ KMMsgStatus mStatus;
+};
+
+// ------------------------------------------------------------------------
+
+/** This class is an abstraction of a search over messages. It is
+ intended to be used inside a KFilter (which adds KFilterAction's),
+ as well as in KMSearch. It can read and write itself into a
+ KConfig group and there is a constructor, mainly used by KMFilter
+ to initialize from a preset KConfig-Group.
+
+ From a class hierarchy point of view, it is a QPtrList of
+ KMSearchRule's that adds the boolean operators (see Operator)
+ 'and' and 'or' that connect the rules logically, and has a name
+ under which it could be stored in the config file.
+
+ As a QPtrList with autoDelete enabled, it assumes that it is the
+ central repository for the rules it contains. So if you want to
+ reuse a rule in another pattern, make a deep copy of that rule.
+
+ @short An abstraction of a search over messages.
+ @author Marc Mutz <Marc@Mutz.com>
+*/
+class KMSearchPattern : public QPtrList<KMSearchRule>
+{
+
+public:
+ /** Boolean operators that connect the return values of the
+ individual rules. A pattern with @p OpAnd will match iff all
+ it's rules match, whereas a pattern with @p OpOr will match iff
+ any of it's rules matches.
+ */
+ enum Operator { OpAnd, OpOr };
+ /** Constructor that initializes from a given KConfig group, if
+ given. This feature is mainly (solely?) used in KMFilter,
+ as we don't allow to store search patterns in the config (yet).
+ If config is 0, provides a pattern with minimal, but
+ sufficient initialization. Unmodified, such a pattern will fail
+ to match any KMMessage. You can query for such an empty
+ rule by using isEmpty, which is inherited from QPtrList.
+ */
+ KMSearchPattern( const KConfig * config=0 );
+
+ /** Destructor. Deletes all stored rules! */
+ ~KMSearchPattern();
+
+ /** The central function of this class. Tries to match the set of
+ rules against a KMMessage. It's virtual to allow derived
+ classes with added rules to reimplement it, yet reimplemented
+ methods should and (&&) the result of this function with their
+ own result or else most functionality is lacking, or has to be
+ reimplemented, since the rules are private to this class.
+
+ @return TRUE if the match was successful, FALSE otherwise.
+ */
+ bool matches( const KMMessage * msg, bool ignoreBody = false ) const;
+ bool matches( const DwString & str, bool ignoreBody = false ) const;
+ bool matches( Q_UINT32 sernum, bool ignoreBody = false ) const;
+
+ /** Returns true if the pattern only depends the DwString that backs
+ a message */
+ bool requiresBody() const;
+
+ /** Removes all empty rules from the list. You should call this
+ method whenever the user had had control of the rules outside of
+ this class. (e.g. after editing it with KMSearchPatternEdit).
+ */
+ void purify();
+
+ /** Reads a search pattern from a KConfig. The group has to be
+ preset. If it does not find a valid saerch pattern in the preset
+ group, initializes the pattern as if it were constructed using
+ the default constructor.
+
+ For backwards compatibility with previous versions of KMail, it
+ checks for old-style filter rules (e.g. using @p OpIgnore)
+ in @p config und converts them to the new format on writeConfig.
+
+ Derived classes reimplementing readConfig() should also call this
+ method, or else the rules will not be loaded.
+ */
+ void readConfig( const KConfig * config );
+ /** Writes itself into @p config. The group has to be preset. Tries
+ to delete old-style keys by overwriting them with QString::null.
+
+ Derived classes reimplementing writeConfig() should also call this
+ method, or else the rules will not be stored.
+ */
+ void writeConfig( KConfig * config ) const;
+
+ /** Get the name of the search pattern. */
+ QString name() const { return mName; }
+ /** Set the name of the search pattern. KMFilter uses this to
+ store it's own name, too. */
+ void setName( const QString & newName ) { mName = newName ; }
+
+ /** Get the filter operator */
+ KMSearchPattern::Operator op() const { return mOperator; }
+ /** Set the filter operator */
+ void setOp( KMSearchPattern::Operator aOp ) { mOperator = aOp; }
+
+ /** Returns the pattern as string. For debugging.*/
+ QString asString() const;
+
+ /** Overloaded assignment operator. Makes a deep copy. */
+ const KMSearchPattern & operator=( const KMSearchPattern & aPattern );
+
+private:
+ /** Tries to import a legacy search pattern, ie. one that still has
+ e.g. the @p unless or @p ignore operator which were useful as
+ long as the number of rules was restricted to two. This method
+ is called from readConfig, which detects legacy configurations
+ and also makes sure that this method is called from an initialized
+ object.
+ */
+ void importLegacyConfig( const KConfig * config );
+ /** Initializes the object. Clears the list of rules, sets the name
+ to "<i18n("unnamed")>", and the boolean operator to @p OpAnd. */
+ void init();
+
+ QString mName;
+ Operator mOperator;
+};
+
+#endif /* _kmsearchpattern_h_ */