[kdepim] upstream filter-rework patch

Rex Dieter rdieter at fedoraproject.org
Fri Jul 6 00:48:33 UTC 2012


commit af15e326da81c06916e5d1f8d1220afb4268e0f4
Author: Rex Dieter <rdieter at fedoraproject.org>
Date:   Thu Jul 5 19:51:45 2012 -0500

    upstream filter-rework patch

 kdepim-4.8.95-filtering.patch | 2017 +++++++++++++++++++++++++++++++++++++++++
 kdepim.spec                   |   10 +-
 2 files changed, 2025 insertions(+), 2 deletions(-)
---
diff --git a/kdepim-4.8.95-filtering.patch b/kdepim-4.8.95-filtering.patch
new file mode 100644
index 0000000..02d60bc
--- /dev/null
+++ b/kdepim-4.8.95-filtering.patch
@@ -0,0 +1,2017 @@
+commit d64d61b470c56b92294f6adee6d74305a217628d
+Author: Andras Mantia <amantia at kde.org>
+Date:   Wed Jul 4 18:35:46 2012 +0300
+
+    A biggish refactoring of the filter functionality:
+    
+    1) Do not take the items from the cache only, as they might be incomplete (especially in online imap case, but not only).
+    This should fix the body loss bug on spam filtering.(Bug 287752 and similar ones + countless of reports on user list)
+    Might fix 293768.
+    
+    2) Download only what is really needed for the filter and add safety checks that
+    the mail is not modified if the requested part is missing. So far the distinction
+    was only betwee the body and rest. This should speed up filtering.
+    Also related to 287752, but should fix also 292283, 288109.
+    
+    3) Rename qDebug->kDebug + fix some includes
+    
+    4) The code should also fix the duplicate mails appearing after filtering (some of the duplicates
+    with empty content), eg. 275233
+    
+    All bug reporters: in case you still see the bug, reopen the corresponding one.
+    For the reports that were CC'd, but not closed, please try to reproduce and tell
+    the result.
+    
+    So far the bug is fixed on master, but might be backported later to 4.9.
+    
+    BUG: 287752
+    BUG: 292283
+    BUG: 288109
+    BUG: 286043
+    BUG: 295484
+    BUG: 302337
+    BUG: 295000
+    BUG: 295684
+    CCBUG: 293768
+    CCBUG: 275233
+    CCBUG: 293918
+    CCBUG: 284310
+    CCBUG: 286364
+    CCBUG: 283682
+
+diff --git a/kmail/kmcommands.cpp b/kmail/kmcommands.cpp
+index b6edc27..2c8cc68 100644
+--- a/kmail/kmcommands.cpp
++++ b/kmail/kmcommands.cpp
+@@ -1228,8 +1228,9 @@ KMCommand::Result KMFilterCommand::execute()
+ 
+ KMFilterActionCommand::KMFilterActionCommand( QWidget *parent,
+                                               const QVector<qlonglong> &msgListId,
+-                                              const QString &filterId, bool requireBody )
+-    : KMCommand( parent ), mMsgListId(msgListId), mFilterId( filterId  ), mRequireBody(requireBody)
++                                              const QString &filterId,
++                                              MailCommon::SearchRule::RequiredPart requiredPart )
++    : KMCommand( parent ), mMsgListId(msgListId), mFilterId( filterId  ), mRequiredPart(requiredPart)
+ {
+ }
+ 
+@@ -1239,11 +1240,6 @@ KMCommand::Result KMFilterActionCommand::execute()
+   MessageViewer::KCursorSaver busy( MessageViewer::KBusyPtr::busy() );
+ #endif
+   int msgCount = 0;
+-  MailCommon::FilterManager::FilterRequires filterrequires = MailCommon::FilterManager::Unknown;
+-  if( mRequireBody )
+-      filterrequires = MailCommon::FilterManager::FullMessage;
+-  else
+-      filterrequires = MailCommon::FilterManager::HeaderMessage;
+   const int msgCountToFilter = mMsgListId.count();
+   ProgressItem* progressItem =
+      ProgressManager::createProgressItem (
+@@ -1262,7 +1258,7 @@ KMCommand::Result KMFilterActionCommand::execute()
+     }
+ 
+ 
+-    MailCommon::FilterManager::instance()->filter( id, mFilterId,filterrequires );
++    MailCommon::FilterManager::instance()->filter( id, mFilterId, mRequiredPart );
+     progressItem->incCompletedItems();
+   }
+ 
+@@ -1272,17 +1268,17 @@ KMCommand::Result KMFilterActionCommand::execute()
+ }
+ 
+ 
+-KMMetaFilterActionCommand::KMMetaFilterActionCommand( const QString &filterId, bool requireBody,
++KMMetaFilterActionCommand::KMMetaFilterActionCommand( const QString &filterId, SearchRule::RequiredPart requiredPart,
+                                                       KMMainWidget *main )
+     : QObject( main ),
+-      mFilterId( filterId ), mRequireBody(requireBody), mMainWidget( main )
++      mFilterId( filterId ), mRequiredPart(requiredPart), mMainWidget( main )
+ {
+ }
+ 
+ void KMMetaFilterActionCommand::start()
+ {
+   KMCommand *filterCommand = new KMFilterActionCommand(
+-      mMainWidget, mMainWidget->messageListPane()->selectionAsMessageItemListId() , mFilterId, mRequireBody );
++      mMainWidget, mMainWidget->messageListPane()->selectionAsMessageItemListId() , mFilterId, mRequiredPart );
+   filterCommand->start();
+ }
+ 
+diff --git a/kmail/kmcommands.h b/kmail/kmcommands.h
+index 6dbc2a6..13d1149 100644
+--- a/kmail/kmcommands.h
++++ b/kmail/kmcommands.h
+@@ -4,13 +4,13 @@
+ #define KMCommands_h
+ 
+ #include "kmail_export.h"
+-#include <kmime/kmime_message.h>
+ #include "messagecomposer/messagefactory.h"
++#include "messagelist/core/view.h"
++#include "searchpattern.h"
+ 
+ #include <akonadi/kmime/messagestatus.h>
+-#include <messagelist/core/view.h>
+-using Akonadi::MessageStatus;
+ #include <kio/job.h>
++#include <kmime/kmime_message.h>
+ 
+ #include <QPointer>
+ #include <QList>
+@@ -18,6 +18,8 @@ using Akonadi::MessageStatus;
+ #include <akonadi/itemfetchscope.h>
+ #include <akonadi/collection.h>
+ 
++using Akonadi::MessageStatus;
++
+ class KProgressDialog;
+ class KMMainWidget;
+ 
+@@ -463,13 +465,14 @@ class KMAIL_EXPORT KMFilterActionCommand : public KMCommand
+ 
+ public:
+   KMFilterActionCommand(QWidget *parent,
+-                         const QVector<qlonglong> &msgListId, const QString &filterId , bool requireBody);
++                         const QVector<qlonglong> &msgListId, const QString &filterId,
++                        MailCommon::SearchRule::RequiredPart requiredPart);
+ 
+ private:
+   virtual Result execute();
+   QVector<qlonglong> mMsgListId;
+   QString mFilterId;
+-  bool mRequireBody;
++  MailCommon::SearchRule::RequiredPart mRequiredPart;
+ };
+ 
+ 
+@@ -478,14 +481,14 @@ class KMAIL_EXPORT KMMetaFilterActionCommand : public QObject
+   Q_OBJECT
+ 
+ public:
+-  KMMetaFilterActionCommand( const QString &filterId, bool requireBody, KMMainWidget *main );
++  KMMetaFilterActionCommand( const QString &filterId, MailCommon::SearchRule::RequiredPart requiredPart, KMMainWidget *main );
+ 
+ public slots:
+   void start();
+ 
+ private:
+   QString mFilterId;
+-  bool mRequireBody;
++  MailCommon::SearchRule::RequiredPart mRequiredPart;
+   KMMainWidget *mMainWidget;
+ };
+ 
+diff --git a/kmail/kmmainwidget.cpp b/kmail/kmmainwidget.cpp
+index 3688e55..1cab55a 100644
+--- a/kmail/kmmainwidget.cpp
++++ b/kmail/kmmainwidget.cpp
+@@ -4264,7 +4264,7 @@ void KMMainWidget::initializeFilterActions()
+       if ( action( normalizedName.toUtf8() ) ) {
+         continue;
+       }
+-      KMMetaFilterActionCommand *filterCommand = new KMMetaFilterActionCommand( filter->identifier(), filter->requiresBody(), this );
++      KMMetaFilterActionCommand *filterCommand = new KMMetaFilterActionCommand( filter->identifier(), filter->requiredPart(), this );
+       mFilterCommands.append( filterCommand );
+       QString displayText = i18n( "Filter %1", filter->name() );
+       QString icon = filter->icon();
+diff --git a/mailcommon/filter/filteraction.cpp b/mailcommon/filter/filteraction.cpp
+index b4a348a..dbd8798 100644
+--- a/mailcommon/filter/filteraction.cpp
++++ b/mailcommon/filter/filteraction.cpp
+@@ -1,5 +1,6 @@
+ /*
+  * Copyright (c) 1996-1998 Stefan Taferner <taferner at kde.org>
++ * Copyright (C) 2012 Andras Mantia <amantia at kde.org>
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+@@ -50,11 +51,6 @@ QString FilterAction::name() const
+   return mName;
+ }
+ 
+-bool FilterAction::requiresBody() const
+-{
+-  return true;
+-}
+-
+ bool FilterAction::isEmpty() const
+ {
+   return false;
+diff --git a/mailcommon/filter/filteraction.h b/mailcommon/filter/filteraction.h
+index cd6e18c..8480932 100644
+--- a/mailcommon/filter/filteraction.h
++++ b/mailcommon/filter/filteraction.h
+@@ -21,6 +21,7 @@
+ #define MAILCOMMON_FILTERACTION_H
+ 
+ #include "../mailcommon_export.h"
++#include "../searchpattern.h"
+ 
+ #include "itemcontext.h"
+ 
+@@ -66,7 +67,8 @@ class MAILCOMMON_EXPORT FilterAction : public QObject
+                                ///  (e.g. "disk full").
+     };
+ 
+-    /**
++
++  /**
+      * Creates a new filter action.
+      *
+      * The action is initialized with an identifier @p name and
+@@ -103,10 +105,9 @@ class MAILCOMMON_EXPORT FilterAction : public QObject
+     virtual ReturnCode process( ItemContext &context ) const = 0;
+ 
+     /**
+-     * Determines if the action depends on the body of the message
+-     */
+-    virtual bool requiresBody() const;
+-
++     * Returns the required part from the item that is needed for the action to
++     * operate. See @ref SearchRule::RequiredPart */
++    virtual SearchRule::RequiredPart requiredPart() const = 0;
+     /**
+      * Determines whether this action is valid. But this is just a
+      * quick test. Eg., actions that have a mail address as parameter
+diff --git a/mailcommon/filter/filteractionaddheader.cpp b/mailcommon/filter/filteractionaddheader.cpp
+index 53f4c2c..282ed30 100644
+--- a/mailcommon/filter/filteractionaddheader.cpp
++++ b/mailcommon/filter/filteractionaddheader.cpp
+@@ -142,6 +142,12 @@ void FilterActionAddHeader::clearParamWidget( QWidget *paramWidget ) const
+   lineEdit->clear();
+ }
+ 
++SearchRule::RequiredPart FilterActionAddHeader::requiredPart() const
++{
++    return SearchRule::CompleteMessage;
++}
++
++
+ QString FilterActionAddHeader::argsAsString() const
+ {
+   QString result = mParameter;
+diff --git a/mailcommon/filter/filteractionaddheader.h b/mailcommon/filter/filteractionaddheader.h
+index 4690ca3..76dd342 100644
+--- a/mailcommon/filter/filteractionaddheader.h
++++ b/mailcommon/filter/filteractionaddheader.h
+@@ -38,6 +38,8 @@ class FilterActionAddHeader: public FilterActionWithStringList
+     virtual void applyParamWidgetValue( QWidget *paramWidget );
+     virtual void clearParamWidget( QWidget *paramWidget ) const;
+ 
++    virtual SearchRule::RequiredPart requiredPart() const;
++
+     virtual QString argsAsString() const;
+     virtual void argsFromString( const QString &argsStr );
+ 
+diff --git a/mailcommon/filter/filteractionaddtag.cpp b/mailcommon/filter/filteractionaddtag.cpp
+index 55114c9..51cb9b9 100644
+--- a/mailcommon/filter/filteractionaddtag.cpp
++++ b/mailcommon/filter/filteractionaddtag.cpp
+@@ -90,9 +90,9 @@ FilterAction::ReturnCode FilterActionAddTag::process( ItemContext &context ) con
+   return GoOn;
+ }
+ 
+-bool FilterActionAddTag::requiresBody() const
++SearchRule::RequiredPart FilterActionAddTag::requiredPart() const
+ {
+-  return false;
++  return SearchRule::Envelope;
+ }
+ 
+ void FilterActionAddTag::argsFromString( const QString &argsStr )
+diff --git a/mailcommon/filter/filteractionaddtag.h b/mailcommon/filter/filteractionaddtag.h
+index 7b75a8f..48a6c26 100644
+--- a/mailcommon/filter/filteractionaddtag.h
++++ b/mailcommon/filter/filteractionaddtag.h
+@@ -33,7 +33,7 @@ class FilterActionAddTag: public FilterActionWithStringList
+   public:
+     FilterActionAddTag( QObject *parent = 0 );
+     virtual ReturnCode process( ItemContext &context ) const;
+-    virtual bool requiresBody() const;
++    SearchRule::RequiredPart requiredPart() const;
+ 
+     static FilterAction* newAction();
+ 
+diff --git a/mailcommon/filter/filteractionaddtoaddressbook.cpp b/mailcommon/filter/filteractionaddtoaddressbook.cpp
+index f2d56f6..c3eb8f7 100644
+--- a/mailcommon/filter/filteractionaddtoaddressbook.cpp
++++ b/mailcommon/filter/filteractionaddtoaddressbook.cpp
+@@ -19,9 +19,9 @@
+ 
+ #include "filteractionaddtoaddressbook.h"
+ 
+-#include <messageviewer/minimumcombobox.h>
++#include "messageviewer/minimumcombobox.h"
+ 
+-#include <libkdepim/addcontactjob.h>
++#include "libkdepim/addcontactjob.h"
+ 
+ #include <KDE/Akonadi/CollectionComboBox>
+ #include <KDE/KABC/Addressee>
+@@ -81,12 +81,18 @@ FilterAction::ReturnCode FilterActionAddToAddressBook::process( ItemContext &con
+       contact.insertCategory( mCategory );
+ 
+     KPIM::AddContactJob *job = new KPIM::AddContactJob( contact, Akonadi::Collection( mCollectionId ) );
+-    job->start();
++    job->start();    
+   }
+ 
+   return GoOn;
+ }
+ 
++SearchRule::RequiredPart FilterActionAddToAddressBook::requiredPart() const
++{
++  return SearchRule::Envelope;
++}
++
++
+ QWidget* FilterActionAddToAddressBook::createParamWidget( QWidget *parent ) const
+ {
+   QWidget *widget = new QWidget( parent );
+diff --git a/mailcommon/filter/filteractionaddtoaddressbook.h b/mailcommon/filter/filteractionaddtoaddressbook.h
+index 61f793f..5647441 100644
+--- a/mailcommon/filter/filteractionaddtoaddressbook.h
++++ b/mailcommon/filter/filteractionaddtoaddressbook.h
+@@ -35,6 +35,8 @@ class FilterActionAddToAddressBook: public FilterActionWithStringList
+     virtual ReturnCode process( ItemContext &context ) const;
+     static FilterAction* newAction();
+ 
++    virtual SearchRule::RequiredPart requiredPart() const;
++
+     virtual bool isEmpty() const;
+ 
+     virtual QWidget* createParamWidget( QWidget *parent ) const;
+diff --git a/mailcommon/filter/filteractionbeep.cpp b/mailcommon/filter/filteractionbeep.cpp
+index 0c76ac2..9deb0f7 100644
+--- a/mailcommon/filter/filteractionbeep.cpp
++++ b/mailcommon/filter/filteractionbeep.cpp
+@@ -35,6 +35,13 @@ FilterAction::ReturnCode FilterActionBeep::process( ItemContext &/*context*/ ) c
+   return GoOn;
+ }
+ 
++
++SearchRule::RequiredPart FilterActionBeep::requiredPart() const
++{
++  return SearchRule::Envelope;
++}
++
++
+ FilterAction* FilterActionBeep::newAction()
+ {
+   return new FilterActionBeep;
+diff --git a/mailcommon/filter/filteractionbeep.h b/mailcommon/filter/filteractionbeep.h
+index 5dcf5cc..4e9ef42 100644
+--- a/mailcommon/filter/filteractionbeep.h
++++ b/mailcommon/filter/filteractionbeep.h
+@@ -30,6 +30,7 @@ class FilterActionBeep : public FilterActionWithNone
+     FilterActionBeep( QObject *parent = 0 );
+     virtual ReturnCode process( ItemContext &context ) const;
+     static FilterAction* newAction();
++    virtual SearchRule::RequiredPart requiredPart() const;
+ };
+ 
+ }
+diff --git a/mailcommon/filter/filteractioncopy.cpp b/mailcommon/filter/filteractioncopy.cpp
+index 699b9ce..50ab146 100644
+--- a/mailcommon/filter/filteractioncopy.cpp
++++ b/mailcommon/filter/filteractioncopy.cpp
+@@ -21,6 +21,7 @@
+ 
+ #include <KDE/Akonadi/ItemCopyJob>
+ #include <KDE/KLocale>
++// #include <KDE/KMessageBox>
+ 
+ using namespace MailCommon;
+ 
+@@ -32,16 +33,32 @@ FilterActionCopy::FilterActionCopy( QObject *parent )
+ FilterAction::ReturnCode FilterActionCopy::process( ItemContext &context ) const
+ {
+   // copy the message 1:1
+-  new Akonadi::ItemCopyJob( context.item(), mFolder, 0 ); // TODO handle error
++  Akonadi::ItemCopyJob *job = new Akonadi::ItemCopyJob( context.item(), mFolder, 0 );
++  connect(job, SIGNAL(result(KJob*)), this, SLOT(jobFinished(KJob*)));
+ 
+   return GoOn;
+ }
+ 
++void FilterActionCopy::jobFinished(KJob* job)
++{
++  if (job->error()) {
++    kError() << "Error while moving mail: " << job->errorString();
++//     KMessageBox::error(0, i18n("<qt>Error while copying the mail.<br/>The error was: <b>%1</b>.</qt>").arg(job->errorString()),
++//                           i18n("Filter error"));
++  }
++}
++
++
+ bool FilterActionCopy::requiresBody() const
+ {
+   return false;
+ }
+ 
++SearchRule::RequiredPart FilterActionCopy::requiredPart() const
++{
++    return SearchRule::Envelope;
++}
++
+ FilterAction* FilterActionCopy::newAction()
+ {
+   return new FilterActionCopy;
+diff --git a/mailcommon/filter/filteractioncopy.h b/mailcommon/filter/filteractioncopy.h
+index 4291a97..21cf84e 100644
+--- a/mailcommon/filter/filteractioncopy.h
++++ b/mailcommon/filter/filteractioncopy.h
+@@ -22,6 +22,8 @@
+ 
+ #include "filteractionwithfolder.h"
+ 
++class KJob;
++
+ namespace MailCommon {
+ 
+ //=============================================================================
+@@ -30,11 +32,16 @@ namespace MailCommon {
+ //=============================================================================
+ class FilterActionCopy: public FilterActionWithFolder
+ {
++  Q_OBJECT
+   public:
+     FilterActionCopy( QObject *parent = 0 );
+     virtual ReturnCode process( ItemContext &context ) const;
+     virtual bool requiresBody() const;
++    virtual SearchRule::RequiredPart requiredPart() const;
+     static FilterAction* newAction();
++
++  protected Q_SLOTS:
++    void jobFinished(KJob* job);
+ };
+ 
+ }
+diff --git a/mailcommon/filter/filteractiondelete.cpp b/mailcommon/filter/filteractiondelete.cpp
+index e11978e..da0bbb2 100644
+--- a/mailcommon/filter/filteractiondelete.cpp
++++ b/mailcommon/filter/filteractiondelete.cpp
+@@ -37,6 +37,12 @@ FilterAction::ReturnCode FilterActionDelete::process( ItemContext &context ) con
+   return GoOn;
+ }
+ 
++SearchRule::RequiredPart FilterActionDelete::requiredPart() const
++{
++  return SearchRule::Envelope;
++}
++
++
+ QWidget* FilterActionDelete::createParamWidget( QWidget *parent ) const
+ {
+     QLabel *lab = new QLabel(parent);
+diff --git a/mailcommon/filter/filteractiondelete.h b/mailcommon/filter/filteractiondelete.h
+index 76881cf..7c83892 100644
+--- a/mailcommon/filter/filteractiondelete.h
++++ b/mailcommon/filter/filteractiondelete.h
+@@ -32,6 +32,7 @@ class FilterActionDelete : public FilterActionWithNone
+   public:
+     FilterActionDelete( QObject *parent = 0 );
+     virtual ReturnCode process( ItemContext &context ) const;
++    virtual SearchRule::RequiredPart requiredPart() const;
+     static FilterAction* newAction();
+     QWidget* createParamWidget( QWidget *parent ) const;
+ };
+diff --git a/mailcommon/filter/filteractionexec.cpp b/mailcommon/filter/filteractionexec.cpp
+index d3d9653..66ee897 100644
+--- a/mailcommon/filter/filteractionexec.cpp
++++ b/mailcommon/filter/filteractionexec.cpp
+@@ -33,6 +33,11 @@ FilterAction::ReturnCode FilterActionExec::process( ItemContext &context ) const
+   return FilterActionWithCommand::genericProcess( context, false ); // ignore output
+ }
+ 
++SearchRule::RequiredPart FilterActionExec::requiredPart() const
++{
++  return SearchRule::CompleteMessage;
++}
++
+ FilterAction* FilterActionExec::newAction()
+ {
+   return new FilterActionExec();
+diff --git a/mailcommon/filter/filteractionexec.h b/mailcommon/filter/filteractionexec.h
+index 5436fb0..94b50e8 100644
+--- a/mailcommon/filter/filteractionexec.h
++++ b/mailcommon/filter/filteractionexec.h
+@@ -33,6 +33,7 @@ class FilterActionExec : public FilterActionWithCommand
+   public:
+     FilterActionExec( QObject *parent = 0 );
+     virtual ReturnCode process( ItemContext &context ) const;
++    virtual SearchRule::RequiredPart requiredPart() const;
+     static FilterAction* newAction();
+ };
+ 
+diff --git a/mailcommon/filter/filteractionforward.cpp b/mailcommon/filter/filteractionforward.cpp
+index 4da32ff..25288c2 100644
+--- a/mailcommon/filter/filteractionforward.cpp
++++ b/mailcommon/filter/filteractionforward.cpp
+@@ -79,6 +79,11 @@ FilterAction::ReturnCode FilterActionForward::process( ItemContext &context ) co
+   return GoOn;
+ }
+ 
++SearchRule::RequiredPart FilterActionForward::requiredPart() const
++{
++  return SearchRule::CompleteMessage;
++}
++
+ QWidget* FilterActionForward::createParamWidget( QWidget *parent ) const
+ {
+   QWidget *addressAndTemplate = new QWidget( parent );
+diff --git a/mailcommon/filter/filteractionforward.h b/mailcommon/filter/filteractionforward.h
+index 0051a68..d5b6682 100644
+--- a/mailcommon/filter/filteractionforward.h
++++ b/mailcommon/filter/filteractionforward.h
+@@ -34,6 +34,7 @@ class FilterActionForward: public FilterActionWithAddress
+     FilterActionForward( QObject *parent = 0 );
+     static FilterAction* newAction();
+     virtual ReturnCode process( ItemContext &context ) const;
++    virtual SearchRule::RequiredPart requiredPart() const;
+     virtual QWidget* createParamWidget( QWidget *parent ) const;
+     virtual void applyParamWidgetValue( QWidget *paramWidget );
+     virtual void setParamWidgetValue( QWidget *paramWidget ) const;
+diff --git a/mailcommon/filter/filteractionmove.cpp b/mailcommon/filter/filteractionmove.cpp
+index 3f7d715..165010d 100644
+--- a/mailcommon/filter/filteractionmove.cpp
++++ b/mailcommon/filter/filteractionmove.cpp
+@@ -53,3 +53,9 @@ bool FilterActionMove::requiresBody() const
+ {
+   return false;
+ }
++
++SearchRule::RequiredPart FilterActionMove::requiredPart() const
++{
++    return SearchRule::Envelope;
++}
++
+diff --git a/mailcommon/filter/filteractionmove.h b/mailcommon/filter/filteractionmove.h
+index 22f4541..aa9ab16 100644
+--- a/mailcommon/filter/filteractionmove.h
++++ b/mailcommon/filter/filteractionmove.h
+@@ -30,10 +30,12 @@ namespace MailCommon {
+ //=============================================================================
+ class FilterActionMove: public FilterActionWithFolder
+ {
++  Q_OBJECT
+   public:
+     FilterActionMove( QObject *parent = 0 );
+     virtual ReturnCode process( ItemContext &context ) const;
+     virtual bool requiresBody() const;
++    virtual SearchRule::RequiredPart requiredPart() const;
+     static FilterAction* newAction();
+ };
+ 
+diff --git a/mailcommon/filter/filteractionpipethrough.cpp b/mailcommon/filter/filteractionpipethrough.cpp
+index 0313a20..20a7c1b 100644
+--- a/mailcommon/filter/filteractionpipethrough.cpp
++++ b/mailcommon/filter/filteractionpipethrough.cpp
+@@ -37,3 +37,9 @@ FilterAction::ReturnCode FilterActionPipeThrough::process( ItemContext &context
+ {
+   return FilterActionWithCommand::genericProcess( context, true ); // use output
+ }
++
++SearchRule::RequiredPart FilterActionPipeThrough::requiredPart() const
++{
++  return SearchRule::CompleteMessage;
++}
++
+diff --git a/mailcommon/filter/filteractionpipethrough.h b/mailcommon/filter/filteractionpipethrough.h
+index 5135fa9..382d107 100644
+--- a/mailcommon/filter/filteractionpipethrough.h
++++ b/mailcommon/filter/filteractionpipethrough.h
+@@ -34,6 +34,7 @@ class FilterActionPipeThrough: public FilterActionWithCommand
+   public:
+     FilterActionPipeThrough( QObject *parent = 0 );
+     virtual ReturnCode process( ItemContext &context ) const;
++    virtual SearchRule::RequiredPart requiredPart() const;
+     static FilterAction* newAction();
+ };
+ 
+diff --git a/mailcommon/filter/filteractionplaysound.cpp b/mailcommon/filter/filteractionplaysound.cpp
+index f3ad74c..faa7113 100644
+--- a/mailcommon/filter/filteractionplaysound.cpp
++++ b/mailcommon/filter/filteractionplaysound.cpp
+@@ -72,6 +72,12 @@ bool FilterActionPlaySound::requiresBody() const
+   return false;
+ }
+ 
++SearchRule::RequiredPart FilterActionPlaySound::requiredPart() const
++{
++    return SearchRule::Envelope;
++}
++
++
+ bool FilterActionPlaySound::argsFromStringInteractive( const QString &argsStr, const QString &filterName )
+ {
+   bool needUpdate = false;
+diff --git a/mailcommon/filter/filteractionplaysound.h b/mailcommon/filter/filteractionplaysound.h
+index 6e12a83..456b3a2 100644
+--- a/mailcommon/filter/filteractionplaysound.h
++++ b/mailcommon/filter/filteractionplaysound.h
+@@ -36,11 +36,13 @@ namespace MailCommon {
+ //=============================================================================
+ class FilterActionPlaySound : public FilterActionWithTest
+ {
++  Q_OBJECT
+   public:
+     FilterActionPlaySound(  );
+     ~FilterActionPlaySound();
+     virtual ReturnCode process( ItemContext &context ) const;
+     virtual bool requiresBody() const;
++    virtual SearchRule::RequiredPart requiredPart() const;
+     static FilterAction* newAction();
+     virtual bool argsFromStringInteractive( const QString &argsStr, const QString &filterName );
+ 
+diff --git a/mailcommon/filter/filteractionredirect.cpp b/mailcommon/filter/filteractionredirect.cpp
+index 5f6f586..7498b3a 100644
+--- a/mailcommon/filter/filteractionredirect.cpp
++++ b/mailcommon/filter/filteractionredirect.cpp
+@@ -64,3 +64,8 @@ FilterAction::ReturnCode FilterActionRedirect::process( ItemContext &context ) c
+ 
+   return GoOn;
+ }
++
++SearchRule::RequiredPart FilterActionRedirect::requiredPart() const
++{
++  return SearchRule::CompleteMessage;
++}
+diff --git a/mailcommon/filter/filteractionredirect.h b/mailcommon/filter/filteractionredirect.h
+index 48a823c..c21c27e 100644
+--- a/mailcommon/filter/filteractionredirect.h
++++ b/mailcommon/filter/filteractionredirect.h
+@@ -33,6 +33,7 @@ class FilterActionRedirect: public FilterActionWithAddress
+   public:
+     FilterActionRedirect( QObject *parent = 0 );
+     virtual ReturnCode process( ItemContext &context ) const;
++    virtual SearchRule::RequiredPart requiredPart() const;
+     static FilterAction* newAction();
+ };
+ 
+diff --git a/mailcommon/filter/filteractionremoveheader.cpp b/mailcommon/filter/filteractionremoveheader.cpp
+index 90315ba..2490f6b 100644
+--- a/mailcommon/filter/filteractionremoveheader.cpp
++++ b/mailcommon/filter/filteractionremoveheader.cpp
+@@ -19,8 +19,8 @@
+ 
+ #include "filteractionremoveheader.h"
+ 
++#include "messageviewer/minimumcombobox.h"
+ 
+-#include <messageviewer/minimumcombobox.h>
+ #include <KDE/KLocale>
+ 
+ using namespace MailCommon;
+@@ -73,6 +73,11 @@ FilterAction::ReturnCode FilterActionRemoveHeader::process( ItemContext &context
+   return GoOn;
+ }
+ 
++SearchRule::RequiredPart FilterActionRemoveHeader::requiredPart() const
++{
++  return SearchRule::CompleteMessage;
++}
++
+ void FilterActionRemoveHeader::setParamWidgetValue( QWidget *paramWidget ) const
+ {
+   MessageViewer::MinimumComboBox *comboBox = dynamic_cast<MessageViewer::MinimumComboBox*>(paramWidget );
+diff --git a/mailcommon/filter/filteractionremoveheader.h b/mailcommon/filter/filteractionremoveheader.h
+index 77365fc..a1031c3 100644
+--- a/mailcommon/filter/filteractionremoveheader.h
++++ b/mailcommon/filter/filteractionremoveheader.h
+@@ -33,6 +33,7 @@ class FilterActionRemoveHeader: public FilterActionWithStringList
+   public:
+     FilterActionRemoveHeader( QObject *parent = 0 );
+     virtual ReturnCode process( ItemContext &context ) const;
++    virtual SearchRule::RequiredPart requiredPart() const;
+     virtual QWidget* createParamWidget( QWidget *parent ) const;
+     virtual void setParamWidgetValue( QWidget *paramWidget ) const;
+ 
+diff --git a/mailcommon/filter/filteractionreplyto.cpp b/mailcommon/filter/filteractionreplyto.cpp
+index 97502bd..073f689 100644
+--- a/mailcommon/filter/filteractionreplyto.cpp
++++ b/mailcommon/filter/filteractionreplyto.cpp
+@@ -51,3 +51,9 @@ FilterAction::ReturnCode FilterActionReplyTo::process( ItemContext &context ) co
+ 
+   return GoOn;
+ }
++
++SearchRule::RequiredPart FilterActionReplyTo::requiredPart() const
++{
++  return SearchRule::CompleteMessage;
++}
++
+diff --git a/mailcommon/filter/filteractionreplyto.h b/mailcommon/filter/filteractionreplyto.h
+index f8655d9..2bf53c6 100644
+--- a/mailcommon/filter/filteractionreplyto.h
++++ b/mailcommon/filter/filteractionreplyto.h
+@@ -33,6 +33,7 @@ class FilterActionReplyTo: public FilterActionWithAddress
+   public:
+     FilterActionReplyTo( QObject *parent = 0 );
+     virtual ReturnCode process( ItemContext &context ) const;
++    virtual SearchRule::RequiredPart requiredPart() const;
+     static FilterAction* newAction();
+ };
+ 
+diff --git a/mailcommon/filter/filteractionrewriteheader.cpp b/mailcommon/filter/filteractionrewriteheader.cpp
+index 6d7c3e4..eea7865 100644
+--- a/mailcommon/filter/filteractionrewriteheader.cpp
++++ b/mailcommon/filter/filteractionrewriteheader.cpp
+@@ -83,6 +83,12 @@ FilterAction::ReturnCode FilterActionRewriteHeader::process( ItemContext &contex
+   return GoOn;
+ }
+ 
++SearchRule::RequiredPart FilterActionRewriteHeader::requiredPart() const
++{
++  return SearchRule::CompleteMessage;
++}
++
++
+ QWidget* FilterActionRewriteHeader::createParamWidget( QWidget *parent ) const
+ {
+   QWidget *widget = new QWidget( parent );
+diff --git a/mailcommon/filter/filteractionrewriteheader.h b/mailcommon/filter/filteractionrewriteheader.h
+index 825e82d..30a00f4 100644
+--- a/mailcommon/filter/filteractionrewriteheader.h
++++ b/mailcommon/filter/filteractionrewriteheader.h
+@@ -35,6 +35,7 @@ class FilterActionRewriteHeader: public FilterActionWithStringList
+   public:
+     FilterActionRewriteHeader( QObject *parent = 0 );
+     virtual ReturnCode process( ItemContext &context ) const;
++    virtual SearchRule::RequiredPart requiredPart() const;
+     virtual QWidget* createParamWidget( QWidget *parent ) const;
+     virtual void setParamWidgetValue( QWidget *paramWidget ) const;
+     virtual void applyParamWidgetValue( QWidget *paramWidget );
+diff --git a/mailcommon/filter/filteractionsendfakedisposition.cpp b/mailcommon/filter/filteractionsendfakedisposition.cpp
+index 4225f57..f614898 100644
+--- a/mailcommon/filter/filteractionsendfakedisposition.cpp
++++ b/mailcommon/filter/filteractionsendfakedisposition.cpp
+@@ -85,6 +85,12 @@ FilterAction::ReturnCode FilterActionSendFakeDisposition::process( ItemContext &
+   return GoOn;
+ }
+ 
++SearchRule::RequiredPart FilterActionSendFakeDisposition::requiredPart() const
++{
++  return SearchRule::CompleteMessage;
++}
++
++
+ void FilterActionSendFakeDisposition::argsFromString( const QString &argsStr )
+ {
+   if ( argsStr.length() == 1 ) {
+diff --git a/mailcommon/filter/filteractionsendfakedisposition.h b/mailcommon/filter/filteractionsendfakedisposition.h
+index be25071..0d27ba1 100644
+--- a/mailcommon/filter/filteractionsendfakedisposition.h
++++ b/mailcommon/filter/filteractionsendfakedisposition.h
+@@ -33,6 +33,7 @@ class FilterActionSendFakeDisposition: public FilterActionWithStringList
+   public:
+     FilterActionSendFakeDisposition( QObject *parent = 0 );
+     virtual ReturnCode process( ItemContext &context ) const;
++    virtual SearchRule::RequiredPart requiredPart() const;
+ 
+     static FilterAction* newAction();
+ 
+diff --git a/mailcommon/filter/filteractionsendreceipt.cpp b/mailcommon/filter/filteractionsendreceipt.cpp
+index 3728555..13b3408 100644
+--- a/mailcommon/filter/filteractionsendreceipt.cpp
++++ b/mailcommon/filter/filteractionsendreceipt.cpp
+@@ -22,8 +22,8 @@
+ #include "../mailkernel.h"
+ #include "../mailutil.h"
+ 
+-#include <messagecomposer/messagefactory.h>
+-#include <messagecomposer/messagesender.h>
++#include "messagecomposer/messagefactory.h"
++#include "messagecomposer/messagesender.h"
+ 
+ #include <KDE/KLocale>
+ 
+@@ -53,6 +53,12 @@ FilterAction::ReturnCode FilterActionSendReceipt::process( ItemContext &context
+   return GoOn;
+ }
+ 
++SearchRule::RequiredPart FilterActionSendReceipt::requiredPart() const
++{
++  return SearchRule::CompleteMessage;
++}
++
++
+ FilterAction* FilterActionSendReceipt::newAction()
+ {
+   return new FilterActionSendReceipt;
+diff --git a/mailcommon/filter/filteractionsendreceipt.h b/mailcommon/filter/filteractionsendreceipt.h
+index bab1294..2d554fd 100644
+--- a/mailcommon/filter/filteractionsendreceipt.h
++++ b/mailcommon/filter/filteractionsendreceipt.h
+@@ -33,6 +33,7 @@ class FilterActionSendReceipt : public FilterActionWithNone
+   public:
+     FilterActionSendReceipt( QObject *parent = 0 );
+     virtual ReturnCode process( ItemContext &context ) const;
++    virtual SearchRule::RequiredPart requiredPart() const;
+     static FilterAction* newAction();
+ };
+ 
+diff --git a/mailcommon/filter/filteractionsetidentity.cpp b/mailcommon/filter/filteractionsetidentity.cpp
+index 8405964..5b5e9e6 100644
+--- a/mailcommon/filter/filteractionsetidentity.cpp
++++ b/mailcommon/filter/filteractionsetidentity.cpp
+@@ -74,6 +74,12 @@ FilterAction::ReturnCode FilterActionSetIdentity::process( ItemContext &context
+   return GoOn;
+ }
+ 
++SearchRule::RequiredPart FilterActionSetIdentity::requiredPart() const
++{
++  return SearchRule::CompleteMessage;
++}
++
++
+ QWidget* FilterActionSetIdentity::createParamWidget( QWidget *parent ) const
+ {
+   KPIMIdentities::IdentityCombo *comboBox = new KPIMIdentities::IdentityCombo( KernelIf->identityManager(), parent );
+diff --git a/mailcommon/filter/filteractionsetidentity.h b/mailcommon/filter/filteractionsetidentity.h
+index c054a1e..654675f 100644
+--- a/mailcommon/filter/filteractionsetidentity.h
++++ b/mailcommon/filter/filteractionsetidentity.h
+@@ -33,6 +33,7 @@ class FilterActionSetIdentity: public FilterActionWithUOID
+   public:
+     FilterActionSetIdentity( QObject *parent = 0 );
+     virtual ReturnCode process( ItemContext &context ) const;
++    virtual SearchRule::RequiredPart requiredPart() const;
+     virtual bool argsFromStringInteractive( const QString &argsStr, const QString &filterName );
+     static FilterAction* newAction();
+ 
+diff --git a/mailcommon/filter/filteractionsetstatus.cpp b/mailcommon/filter/filteractionsetstatus.cpp
+index 3da6102..b257499 100644
+--- a/mailcommon/filter/filteractionsetstatus.cpp
++++ b/mailcommon/filter/filteractionsetstatus.cpp
+@@ -60,3 +60,9 @@ FilterAction::ReturnCode FilterActionSetStatus::process( ItemContext &context )
+ }
+ 
+ 
++SearchRule::RequiredPart FilterActionSetStatus::requiredPart() const
++{
++    return SearchRule::Envelope;
++}
++
++
+diff --git a/mailcommon/filter/filteractionsetstatus.h b/mailcommon/filter/filteractionsetstatus.h
+index 53f64ba..a283950 100644
+--- a/mailcommon/filter/filteractionsetstatus.h
++++ b/mailcommon/filter/filteractionsetstatus.h
+@@ -32,6 +32,7 @@ class FilterActionSetStatus: public FilterActionStatus
+   public:
+     FilterActionSetStatus( QObject *parent = 0 );
+     virtual ReturnCode process( ItemContext &context ) const;
++    virtual SearchRule::RequiredPart requiredPart() const;
+ 
+     static FilterAction* newAction();
+ 
+diff --git a/mailcommon/filter/filteractionsettransport.cpp b/mailcommon/filter/filteractionsettransport.cpp
+index 601db46..d37db8c 100644
+--- a/mailcommon/filter/filteractionsettransport.cpp
++++ b/mailcommon/filter/filteractionsettransport.cpp
+@@ -90,6 +90,12 @@ FilterAction::ReturnCode FilterActionSetTransport::process( ItemContext &context
+   return GoOn;
+ }
+ 
++SearchRule::RequiredPart FilterActionSetTransport::requiredPart() const
++{
++  return SearchRule::CompleteMessage;
++}
++
++
+ void FilterActionSetTransport::applyParamWidgetValue( QWidget *paramWidget )
+ {
+   const MailTransport::TransportComboBox *comboBox = dynamic_cast<MailTransport::TransportComboBox*>( paramWidget );
+diff --git a/mailcommon/filter/filteractionsettransport.h b/mailcommon/filter/filteractionsettransport.h
+index 5c8b063..7cad943 100644
+--- a/mailcommon/filter/filteractionsettransport.h
++++ b/mailcommon/filter/filteractionsettransport.h
+@@ -33,6 +33,7 @@ class FilterActionSetTransport: public FilterAction
+   public:
+     FilterActionSetTransport( QObject *parent = 0 );
+     virtual ReturnCode process( ItemContext &context ) const;
++    virtual SearchRule::RequiredPart requiredPart() const;
+     static FilterAction *newAction();
+     virtual QWidget *createParamWidget( QWidget *parent ) const;
+     /**
+diff --git a/mailcommon/filter/filteractionstatus.cpp b/mailcommon/filter/filteractionstatus.cpp
+index f99b28a..5787485 100644
+--- a/mailcommon/filter/filteractionstatus.cpp
++++ b/mailcommon/filter/filteractionstatus.cpp
+@@ -63,6 +63,11 @@ bool FilterActionStatus::requiresBody() const
+   return false;
+ }
+ 
++SearchRule::RequiredPart FilterActionStatus::requiredPart() const
++{
++    return SearchRule::Envelope;
++}
++
+ bool FilterActionStatus::isEmpty() const
+ {
+   return false;
+diff --git a/mailcommon/filter/filteractionstatus.h b/mailcommon/filter/filteractionstatus.h
+index 7867235..1172062 100644
+--- a/mailcommon/filter/filteractionstatus.h
++++ b/mailcommon/filter/filteractionstatus.h
+@@ -25,9 +25,11 @@ namespace MailCommon {
+ 
+ class FilterActionStatus : public FilterActionWithStringList
+ {
++  Q_OBJECT
+ public:
+     FilterActionStatus(const char *name, const QString &label, QObject *parent = 0);
+     virtual bool requiresBody() const;
++    virtual SearchRule::RequiredPart requiredPart() const;
+     virtual bool isEmpty() const;
+     virtual void argsFromString( const QString &argsStr );
+     virtual QString argsAsString() const;
+diff --git a/mailcommon/filter/filteractionunsetstatus.cpp b/mailcommon/filter/filteractionunsetstatus.cpp
+index 7413aa0..cb0d7d5 100644
+--- a/mailcommon/filter/filteractionunsetstatus.cpp
++++ b/mailcommon/filter/filteractionunsetstatus.cpp
+@@ -17,6 +17,7 @@
+ */
+ 
+ #include "filteractionunsetstatus.h"
++
+ #include <KDE/KLocale>
+ using namespace MailCommon;
+ 
+@@ -30,8 +31,6 @@ FilterActionUnsetStatus::FilterActionUnsetStatus( QObject *parent )
+ {
+ }
+ 
+-
+-
+ FilterAction::ReturnCode FilterActionUnsetStatus::process( ItemContext &context ) const
+ {
+   const int index = mParameterList.indexOf( mParameter );
+@@ -48,3 +47,7 @@ FilterAction::ReturnCode FilterActionUnsetStatus::process( ItemContext &context
+   return GoOn;
+ }
+ 
++SearchRule::RequiredPart FilterActionUnsetStatus::requiredPart() const
++{
++    return SearchRule::Envelope;
++}
+diff --git a/mailcommon/filter/filteractionunsetstatus.h b/mailcommon/filter/filteractionunsetstatus.h
+index df5651d..53c8095 100644
+--- a/mailcommon/filter/filteractionunsetstatus.h
++++ b/mailcommon/filter/filteractionunsetstatus.h
+@@ -27,7 +27,8 @@ class FilterActionUnsetStatus: public FilterActionStatus
+   public:
+     FilterActionUnsetStatus( QObject *parent = 0 );
+     virtual ReturnCode process( ItemContext &context ) const;
+-
++    virtual SearchRule::RequiredPart requiredPart() const;
++    
+     static FilterAction* newAction();
+ };
+ }
+diff --git a/mailcommon/filter/filterimporter/filterimporterevolution.cpp b/mailcommon/filter/filterimporter/filterimporterevolution.cpp
+index ca996ab..edeb69f 100644
+--- a/mailcommon/filter/filterimporter/filterimporterevolution.cpp
++++ b/mailcommon/filter/filterimporter/filterimporterevolution.cpp
+@@ -128,7 +128,7 @@ void FilterImporterEvolution::parsePartAction( const QDomElement &ruleFilter,
+             kDebug() << " parttype part : name : not implemented :" << name;
+           }
+           if(fieldName.isEmpty()) {
+-            qDebug()<<" parttype part : name : not implemented :" << name;
++            kDebug()<<" parttype part : name : not implemented :" << name;
+             continue;
+           }
+           QString contents;
+@@ -146,7 +146,7 @@ void FilterImporterEvolution::parsePartAction( const QDomElement &ruleFilter,
+                 if(name==QLatin1String("flag")) {
+ 
+                   const QString flag = valueFilter.attribute( "value" );
+-                  qDebug()<<" flag :"<<flag;
++                  kDebug()<<" flag :"<<flag;
+                   if(flag==QLatin1String("Seen")) {
+                     contents = QLatin1String("Read");
+                   } else if(flag==QLatin1String("Answered")) {
+@@ -158,7 +158,7 @@ void FilterImporterEvolution::parsePartAction( const QDomElement &ruleFilter,
+                   } else if(flag==QLatin1String("Junk")) {
+                     contents = QLatin1String("Spam");
+                   } else {
+-                    qDebug()<<" unknown status flags "<<flag;
++                    kDebug()<<" unknown status flags "<<flag;
+                   }
+                 }
+                 kDebug() << " value filter name :" << name;
+@@ -195,7 +195,7 @@ void FilterImporterEvolution::parsePartAction( const QDomElement &ruleFilter,
+               }
+               if ( valueFilter.hasAttribute( "value" ) ) {
+                 const QString value = valueFilter.attribute( "value" );
+-                qDebug() << " value filter value :" << name;
++                kDebug() << " value filter value :" << name;
+                 if ( value == QLatin1String( "contains" ) ) {
+                   functionName = SearchRule::FuncContains;
+                 } else if ( value == QLatin1String( "not contains" ) ) {
+diff --git a/mailcommon/filter/filterimporter/filterimporterprocmail.cpp b/mailcommon/filter/filterimporter/filterimporterprocmail.cpp
+index 67055b0..ea23216 100644
+--- a/mailcommon/filter/filterimporter/filterimporterprocmail.cpp
++++ b/mailcommon/filter/filterimporter/filterimporterprocmail.cpp
+@@ -87,7 +87,7 @@ MailCommon::MailFilter *FilterImporterProcmail::parseLine( QTextStream &stream,
+       line.remove( QLatin1String( "^(To|Cc):" ) );
+       fieldName = "<recipients>";
+     } else {
+-      qDebug()<<" line condition not parsed :"<<line;
++      kDebug()<<" line condition not parsed :"<<line;
+     }
+     SearchRule::Ptr rule = SearchRule::createInstance( fieldName, functionName, line );
+     filter->pattern()->append( rule );
+diff --git a/mailcommon/filter/filterimporter/filterimportersylpheed.cpp b/mailcommon/filter/filterimporter/filterimportersylpheed.cpp
+index d23e14f..0e1eb41 100644
+--- a/mailcommon/filter/filterimporter/filterimportersylpheed.cpp
++++ b/mailcommon/filter/filterimporter/filterimportersylpheed.cpp
+@@ -136,7 +136,7 @@ void FilterImporterSylpheed::parseConditions( const QDomElement &e, MailCommon::
+       kDebug() << " tag not recognize " << nexttag;
+     }
+     if(fieldName.isEmpty()) {
+-      qDebug()<<" field not implemented "<<nexttag;
++      kDebug()<<" field not implemented "<<nexttag;
+     }
+ 
+     if ( ruleFilter.hasAttribute( "type" ) ) {
+diff --git a/mailcommon/filter/filtermanager.cpp b/mailcommon/filter/filtermanager.cpp
+index 0f4101b..34ab576 100644
+--- a/mailcommon/filter/filtermanager.cpp
++++ b/mailcommon/filter/filtermanager.cpp
+@@ -142,7 +142,7 @@ void FilterManager::filter( const Akonadi::Item &item, const QString &identifier
+   d->mMailFilterAgentInterface->filter( item.id(), identifier, 0 /*FilterManager::FilterRequires::Unknown*/ );
+ }
+ 
+-void FilterManager::filter(const qlonglong &id, const QString &identifier , FilterRequires requires) const
++void FilterManager::filter(const qlonglong& id, const QString& identifier, SearchRule::RequiredPart requires) const
+ {
+   d->mMailFilterAgentInterface->filter( id, identifier, static_cast<int>(requires) );
+ }
+@@ -163,7 +163,7 @@ void FilterManager::filter( const Akonadi::Item::List &messages, FilterSet set )
+ }
+ 
+ 
+-void FilterManager::filter(const Akonadi::Item::List &messages, FilterRequires requires, const QStringList& listFilters) const
++void FilterManager::filter(const Akonadi::Item::List& messages, SearchRule::RequiredPart requires, const QStringList& listFilters) const
+ {
+     QVector<qlonglong> itemIds;
+ 
+diff --git a/mailcommon/filter/filtermanager.h b/mailcommon/filter/filtermanager.h
+index 4f069dd..9c75e36 100644
+--- a/mailcommon/filter/filtermanager.h
++++ b/mailcommon/filter/filtermanager.h
+@@ -54,12 +54,6 @@ class MAILCOMMON_EXPORT FilterManager : public QObject
+       All = Inbound|BeforeOutbound|Outbound|Explicit
+     };
+ 
+-    enum FilterRequires {
+-      Unknown = 0,
+-      HeaderMessage = 1,
+-      FullMessage = 2
+-    };
+-
+     /**
+      * Returns the global filter manager object.
+      */
+@@ -97,7 +91,7 @@ class MAILCOMMON_EXPORT FilterManager : public QObject
+     void filter( const Akonadi::Item &item, const QString &identifier ) const;
+ 
+     void filter( const qlonglong &id, const QString &identifier,
+-                 FilterRequires requires = Unknown ) const;
++                 SearchRule::RequiredPart requires ) const;
+ 
+     /**
+      * Process given message item by applying the filter rules one by
+@@ -124,7 +118,7 @@ class MAILCOMMON_EXPORT FilterManager : public QObject
+ 
+     void filter( const QVector<qlonglong> &itemIds, FilterSet set = Explicit ) const;
+ 
+-    void filter( const Akonadi::Item::List &messages, FilterRequires requires,
++    void filter( const Akonadi::Item::List &messages, SearchRule::RequiredPart requires,
+                  const QStringList &listFilters ) const;
+ 
+     /// Manage filters interface
+diff --git a/mailcommon/filter/itemcontext.cpp b/mailcommon/filter/itemcontext.cpp
+index 43df66a..2ef50c5 100644
+--- a/mailcommon/filter/itemcontext.cpp
++++ b/mailcommon/filter/itemcontext.cpp
+@@ -21,8 +21,9 @@
+ 
+ using namespace MailCommon;
+ 
+-ItemContext::ItemContext( const Akonadi::Item &item )
+-    : mItem( item ), mNeedsPayloadStore( false ), mNeedsFlagStore( false ), mDeleteItem( false )
++ItemContext::ItemContext( const Akonadi::Item& item, SearchRule::RequiredPart requestedPart )
++    : mItem( item ), mNeedsPayloadStore( false ), mNeedsFlagStore( false ), mDeleteItem( false ),
++    mRequestedPart( requestedPart )
+ {
+ }
+ 
+@@ -71,3 +72,8 @@ bool ItemContext::deleteItem() const
+   return mDeleteItem;
+ }
+ 
++
++bool ItemContext::needsFullPayload() const
++{
++  return mRequestedPart != SearchRule::Envelope;
++}
+diff --git a/mailcommon/filter/itemcontext.h b/mailcommon/filter/itemcontext.h
+index bb4f7cc..89659ba 100644
+--- a/mailcommon/filter/itemcontext.h
++++ b/mailcommon/filter/itemcontext.h
+@@ -21,6 +21,7 @@
+ #define MAILCOMMON_ITEMCONTEXT_H
+ 
+ #include "../mailcommon_export.h"
++#include "../searchpattern.h"
+ 
+ #include <Akonadi/Collection>
+ #include <Akonadi/Item>
+@@ -40,8 +41,9 @@ class MAILCOMMON_EXPORT ItemContext
+   public:
+     /**
+      * Creates an item context for the given @p item.
++     * @p requestedPart the part requested for the item (Envelope, Header or CompleteMessage)
+      */
+-    ItemContext( const Akonadi::Item &item );
++    ItemContext( const Akonadi::Item &item, SearchRule::RequiredPart requestedPart );
+ 
+     /**
+      * Returns the item of the context.
+@@ -79,6 +81,10 @@ class MAILCOMMON_EXPORT ItemContext
+      */
+     bool needsFlagStore() const;
+ 
++    /** Returns true if the full payload was requested for the item or not.
++     * Full payload is needed to change the headers or the body */
++    bool needsFullPayload() const;
++
+     void setDeleteItem();
+     bool deleteItem() const;
+ 
+@@ -88,6 +94,7 @@ class MAILCOMMON_EXPORT ItemContext
+     bool mNeedsPayloadStore;
+     bool mNeedsFlagStore;
+     bool mDeleteItem;
++    SearchRule::RequiredPart mRequestedPart;
+ };
+ 
+ }
+diff --git a/mailcommon/filter/kmfilterdialog.cpp b/mailcommon/filter/kmfilterdialog.cpp
+index 20b8d91..227f427 100644
+--- a/mailcommon/filter/kmfilterdialog.cpp
++++ b/mailcommon/filter/kmfilterdialog.cpp
+@@ -641,8 +641,8 @@ void KMFilterDialog::slotRunFilters()
+         i18n( "Filters changed." ) );
+       return;
+   }
+-  bool requiresBody = false;
+-  const QStringList selectedFiltersId = mFilterList->selectedFilterId(requiresBody);
++  SearchRule::RequiredPart requiredPart = SearchRule::Envelope;
++  const QStringList selectedFiltersId = mFilterList->selectedFilterId( requiredPart );
+   if ( selectedFiltersId.isEmpty() ) {
+     KMessageBox::information(
+       this,
+@@ -652,7 +652,7 @@ void KMFilterDialog::slotRunFilters()
+     return;
+   }
+   Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob( mFolderRequester->collection(), this );
+-  job->setProperty( "requiresBody", QVariant::fromValue( requiresBody ) );
++  job->setProperty( "requiredPart", QVariant::fromValue( requiredPart ) );
+   job->setProperty( "listFilters", QVariant::fromValue( selectedFiltersId ) );
+ 
+   connect( job, SIGNAL(result(KJob*)),
+@@ -671,14 +671,9 @@ void KMFilterDialog::slotFetchItemsForFolderDone( KJob *job )
+     filtersId = fjob->property( "listFilters" ).toStringList();
+   }
+ 
+-  MailCommon::FilterManager::FilterRequires requires = MailCommon::FilterManager::Unknown;
+-  if ( fjob->property( "requiresBody" ).isValid() ) {
+-    bool requiresBody = fjob->property( "requiresBody" ).toBool();
+-    if ( requiresBody ) {
+-      requires = MailCommon::FilterManager::FullMessage;
+-    } else {
+-      requires = MailCommon::FilterManager::HeaderMessage;
+-    }
++  SearchRule::RequiredPart requires = SearchRule::Envelope;
++  if ( fjob->property( "requiredPart" ).isValid() ) {
++    requires = fjob->property( "requiredPart" ).value<SearchRule::RequiredPart>();
+   }
+   Akonadi::Item::List items = fjob->items();
+   mRunNow->setEnabled( true );
+@@ -1352,20 +1347,18 @@ QList<QListWidgetItem*> KMFilterListBox::selectedFilter()
+   return listWidgetItem;
+ }
+ 
+-QStringList KMFilterListBox::selectedFilterId( bool &requiresBody ) const
++QStringList KMFilterListBox::selectedFilterId( SearchRule::RequiredPart& requiredPart ) const
+ {
+   QStringList listFilterId;
+-  requiresBody = false;
++  requiredPart = SearchRule::Envelope;
+   const int numberOfFilters = mListWidget->count();
+   for ( int i = 0; i <numberOfFilters; ++i ) {
+     if ( mListWidget->item(i)->isSelected() && !mListWidget->item(i)->isHidden() ) {
+       const QString id =
+         static_cast<QListWidgetFilterItem*>( mListWidget->item( i ) )->filter()->identifier();
+       listFilterId << id;
+-      if ( !requiresBody ) {
+-        requiresBody =
+-          static_cast<QListWidgetFilterItem*>( mListWidget->item( i ) )->filter()->requiresBody();
+-      }
++      requiredPart = qMax(requiredPart,
++          static_cast<QListWidgetFilterItem*>( mListWidget->item( i ) )->filter()->requiredPart());
+     }
+   }
+   return listFilterId;
+diff --git a/mailcommon/filter/kmfilterdialog.h b/mailcommon/filter/kmfilterdialog.h
+index 3247cb4..1b6964e 100644
+--- a/mailcommon/filter/kmfilterdialog.h
++++ b/mailcommon/filter/kmfilterdialog.h
+@@ -27,6 +27,7 @@
+ #include "filteraction.h"
+ #include "filterimporterexporter.h"
+ #include "mailfilter.h"
++#include "searchpattern.h"
+ 
+ #include <KDialog>
+ 
+@@ -137,7 +138,7 @@ class MAILCOMMON_EXPORT KMFilterListBox : public QGroupBox
+      */
+     QList<MailCommon::MailFilter *> filtersForSaving( bool closeAfterSaving ) const;
+ 
+-    QStringList selectedFilterId( bool &requiresBody ) const;
++    QStringList selectedFilterId( SearchRule::RequiredPart &requiredPart ) const;
+ 
+   signals:
+     /**
+diff --git a/mailcommon/filter/mailfilter.cpp b/mailcommon/filter/mailfilter.cpp
+index 594c38b..1cd2b6d 100644
+--- a/mailcommon/filter/mailfilter.cpp
++++ b/mailcommon/filter/mailfilter.cpp
+@@ -1,6 +1,7 @@
+ /* -*- mode: C++; c-file-style: "gnu" -*-
+  * kmail: KDE mail client
+  * Copyright (c) 1996-1998 Stefan Taferner <taferner at kde.org>
++ * Copyright (C) 2012 Andras Mantia <amantia at kde.org>
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+@@ -41,6 +42,10 @@ using MailCommon::FilterLog;
+ #include <kconfiggroup.h>
+ #include <krandom.h>
+ 
++#include <algorithm>
++#include <boost/bind.hpp>
++
++
+ using namespace MailCommon;
+ 
+ MailFilter::MailFilter()
+@@ -233,15 +238,27 @@ MailFilter::AccountType MailFilter::applicability() const
+   return mApplicability;
+ }
+ 
+-bool MailFilter::requiresBody()
++SearchRule::RequiredPart MailFilter::requiredPart() const
+ {
+-  if (pattern() && pattern()->requiresBody())
+-    return true; // no pattern means always matches?
+-  QListIterator<FilterAction*> it( *actions() );
+-  while ( it.hasNext() )
+-    if ( it.next()->requiresBody() )
+-      return true;
+-  return false;
++  //find the required message part needed for the filter
++  //this can be either only the Envelope, all Header or the CompleteMessage
++  //Makes the assumption that  Envelope < Header < CompleteMessage
++  int requiredPart = SearchRule::Envelope;
++
++  if (pattern())
++    requiredPart = qMax( requiredPart, (int)pattern()->requiredPart() ) ; // no pattern means always matches?
++
++  int requiredPartByActions = SearchRule::Envelope;
++
++  QList<FilterAction*> actionList = *actions();
++  if (!actionList.isEmpty()) {
++    requiredPartByActions = (*std::max_element(actionList.constBegin(), actionList.constEnd(),
++                                             boost::bind(&MailCommon::FilterAction::requiredPart, _1) <
++                                             boost::bind(&MailCommon::FilterAction::requiredPart, _2) ))->requiredPart();
++  }
++  requiredPart = qMax( requiredPart, requiredPartByActions);
++  
++  return (SearchRule::RequiredPart) requiredPart;  
+ }
+ 
+ bool MailFilter::folderRemoved( const Akonadi::Collection & aFolder, const Akonadi::Collection& aNewFolder )
+diff --git a/mailcommon/filter/mailfilter.h b/mailcommon/filter/mailfilter.h
+index 1444393..c594333 100644
+--- a/mailcommon/filter/mailfilter.h
++++ b/mailcommon/filter/mailfilter.h
+@@ -104,9 +104,10 @@ public:
+   */
+   ReturnCode execActions( ItemContext &context, bool& stopIt ) const ;
+ 
+-  /** Determines if the filter depends on the body of the message
+-  */
+-  bool requiresBody();
++  /**
++    * Returns the required part from the item that is needed for the filter to
++    * operate. See @ref SearchRule::RequiredPart */
++  SearchRule::RequiredPart requiredPart() const;
+ 
+   /** Write contents to given config group. */
+   void writeConfig( KConfigGroup& config, bool exportFilter ) const;
+diff --git a/mailcommon/searchpattern.cpp b/mailcommon/searchpattern.cpp
+index e50f253..d600b35 100644
+--- a/mailcommon/searchpattern.cpp
++++ b/mailcommon/searchpattern.cpp
+@@ -1,6 +1,7 @@
+ /* -*- mode: C++; c-file-style: "gnu" -*-
+ 
+   Author: Marc Mutz <mutz at kde.org>
++  Copyright (C) 2012 Andras Mantia <amantia at kde.org>
+ 
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+@@ -57,6 +58,10 @@ using MailCommon::FilterLog;
+ #include <QRegExp>
+ #include <QXmlStreamWriter>
+ 
++#include <algorithm>
++#include <boost/bind.hpp>
++
++
+ using namespace MailCommon;
+ 
+ static const char *funcConfigNames[] =
+@@ -274,11 +279,6 @@ const QString SearchRule::asString() const
+   return result;
+ }
+ 
+-bool SearchRule::requiresBody() const
+-{
+-  return true;
+-}
+-
+ #ifndef KDEPIM_NO_NEPOMUK
+ 
+ Nepomuk::Query::ComparisonTerm::Comparator SearchRule::nepomukComparator() const
+@@ -436,15 +436,24 @@ bool SearchRuleString::isEmpty() const
+   return field().trimmed().isEmpty() || contents().isEmpty();
+ }
+ 
+-bool SearchRuleString::requiresBody() const
++SearchRule::RequiredPart SearchRuleString::requiredPart() const
+ {
+-  if ( !field().startsWith( '<' ) || field() == "<recipients>" ) {
+-    return false;
+-  }
++  const QByteArray f = field();
++  SearchRule::RequiredPart part = Header;
++  if ( kasciistricmp( f, "<recipients>" ) == 0 ||
++       kasciistricmp( f, "<status>" ) == 0 ||
++       kasciistricmp( f, "<tag>" ) == 0 ||
++       kasciistricmp( f, "Subject" ) == 0 ||
++       kasciistricmp( f, "From" ) == 0 )
++      part = Envelope;
++  if ( kasciistricmp( f, "<message>" ) == 0 ||
++       kasciistricmp( f, "<body>" ) == 0 )
++      part = CompleteMessage;
+ 
+-  return true;
++  return part; 
+ }
+ 
++
+ bool SearchRuleString::matches( const Akonadi::Item &item ) const
+ {
+   const KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>();
+@@ -943,6 +952,12 @@ bool SearchRuleNumerical::matches( const Akonadi::Item &item ) const
+   return rc;
+ }
+ 
++SearchRule::RequiredPart SearchRuleNumerical::requiredPart() const
++{
++  return SearchRule::Envelope;
++}
++
++
+ bool SearchRuleNumerical::matchesInternal( long numericalValue,
+     long numericalMsgContents, const QString & msgContents ) const
+ {
+@@ -1088,6 +1103,12 @@ bool SearchRuleDate::matchesInternal( const QDate& dateValue,
+   return false;
+ }
+ 
++SearchRule::RequiredPart SearchRuleDate::requiredPart() const
++{
++  return SearchRule::Envelope;
++}
++
++
+ #ifndef KDEPIM_NO_NEPOMUK
+ 
+ void SearchRuleDate::addQueryTerms( Nepomuk::Query::GroupTerm &groupTerm ) const
+@@ -1185,6 +1206,12 @@ bool SearchRuleStatus::matches( const Akonadi::Item &item ) const
+   return rc;
+ }
+ 
++SearchRule::RequiredPart SearchRuleStatus::requiredPart() const
++{
++  return SearchRule::Envelope;
++}
++
++
+ #ifndef KDEPIM_NO_NEPOMUK
+ void SearchRuleStatus::addTagTerm( Nepomuk::Query::GroupTerm &groupTerm,
+                                    const QString &tagId ) const
+@@ -1273,7 +1300,7 @@ bool SearchPattern::matches( const Akonadi::Item &item, bool ignoreBody ) const
+   switch ( mOperator ) {
+   case OpAnd: // all rules must match
+     for ( it = constBegin(); it != end; ++it ) {
+-      if ( !( (*it)->requiresBody() && ignoreBody ) ) {
++      if ( !( (*it)->requiredPart() == SearchRule::CompleteMessage && ignoreBody ) ) {
+         if ( !(*it)->matches( item ) ) {
+           return false;
+         }
+@@ -1283,7 +1310,7 @@ bool SearchPattern::matches( const Akonadi::Item &item, bool ignoreBody ) const
+ 
+   case OpOr:  // at least one rule must match
+     for ( it = constBegin(); it != end; ++it ) {
+-      if ( !( (*it)->requiresBody() && ignoreBody ) ) {
++      if ( !( (*it)->requiredPart() == MailCommon::SearchRule::CompleteMessage && ignoreBody ) ) {
+         if ( (*it)->matches( item ) ) {
+           return true;
+         }
+@@ -1299,18 +1326,19 @@ bool SearchPattern::matches( const Akonadi::Item &item, bool ignoreBody ) const
+   }
+ }
+ 
+-bool SearchPattern::requiresBody() const
++SearchRule::RequiredPart SearchPattern::requiredPart() const
+ {
+-  QList<SearchRule::Ptr>::const_iterator it;
+-  QList<SearchRule::Ptr>::const_iterator end( constEnd() );
+-  for ( it = constBegin(); it != end; ++it ) {
+-    if ( (*it)->requiresBody() ) {
+-      return true;
+-    }
++  SearchRule::RequiredPart reqPart = SearchRule::Envelope;
++
++  if (!isEmpty()) {
++    reqPart = (*std::max_element(constBegin(), constEnd(),
++                                 boost::bind(&MailCommon::SearchRule::requiredPart, _1) <
++                                 boost::bind(&MailCommon::SearchRule::requiredPart, _2) ))->requiredPart();
+   }
+-  return false;
++  return reqPart;
+ }
+ 
++
+ void SearchPattern::purify()
+ {
+   QList<SearchRule::Ptr>::iterator it = end();
+diff --git a/mailcommon/searchpattern.h b/mailcommon/searchpattern.h
+index dcda954..f80d3fb 100644
+--- a/mailcommon/searchpattern.h
++++ b/mailcommon/searchpattern.h
+@@ -104,6 +104,12 @@ class MAILCOMMON_EXPORT SearchRule
+       FuncNotEndWith
+     };
+ 
++    enum RequiredPart {
++      Envelope = 0,
++      Header,
++      CompleteMessage
++    };
++
+     /**
+      * Creates new new search rule.
+      *
+@@ -195,10 +201,9 @@ class MAILCOMMON_EXPORT SearchRule
+     virtual bool isEmpty() const = 0;
+ 
+     /**
+-     * Returns true if the rule depends on a complete message,
+-     * otherwise returns false.
+-     */
+-    virtual bool requiresBody() const;
++     * Returns the required part from the item that is needed for the search to
++     * operate. See @ref RequiredPart */
++    virtual SearchRule::RequiredPart requiredPart() const = 0;
+ 
+     /**
+      * Saves the object into a given config @p group.
+@@ -356,10 +361,10 @@ class SearchRuleString : public SearchRule
+     virtual bool isEmpty() const ;
+ 
+     /**
+-     * @copydoc SearchRule::requiresBody()
++     * @copydoc SearchRule::requiredPart()
+      */
+-    virtual bool requiresBody() const;
+-
++    virtual RequiredPart requiredPart() const;
++    
+     /**
+      * @copydoc SearchRule::matches()
+      */
+@@ -424,6 +429,11 @@ class SearchRuleNumerical : public SearchRule
+      */
+     virtual bool matches( const Akonadi::Item &item ) const;
+ 
++    /**
++     * @copydoc SearchRule::requiredPart()
++     */
++    virtual RequiredPart requiredPart() const;
++
+     // Optimized matching not implemented, will use the unoptimized matching
+     // from SearchRule
+     using SearchRule::matches;
+@@ -473,6 +483,11 @@ class SearchRuleDate : public SearchRule
+      */
+     virtual bool matches( const Akonadi::Item &item ) const;
+ 
++    /**
++     * @copydoc SearchRule::requiredPart()
++     */
++    virtual RequiredPart requiredPart() const;
++
+     // Optimized matching not implemented, will use the unoptimized matching
+     // from SearchRule
+     using SearchRule::matches;
+@@ -571,6 +586,11 @@ class MAILCOMMON_EXPORT SearchRuleStatus : public SearchRule
+     virtual bool isEmpty() const ;
+     virtual bool matches( const Akonadi::Item &item ) const;
+ 
++     /**
++     * @copydoc SearchRule::requiredPart()
++     */
++   virtual RequiredPart requiredPart() const;
++
+ #ifndef KDEPIM_NO_NEPOMUK
+     virtual void addQueryTerms( Nepomuk::Query::GroupTerm &groupTerm ) const;
+ #endif
+@@ -660,10 +680,10 @@ class MAILCOMMON_EXPORT SearchPattern : public QList<SearchRule::Ptr>
+     bool matches( const Akonadi::Item &item, bool ignoreBody = false ) const;
+ 
+     /**
+-     * Returns true if the pattern only depends the DwString that backs a message.
+-     */
+-    bool requiresBody() const;
+-
++     * Returns the required part from the item that is needed for the search to
++     * operate. See @ref RequiredPart */
++    SearchRule::RequiredPart requiredPart() const;
++    
+     /**
+      * Removes all empty rules from the list. You should call this
+      * method whenever the user had had control of the rules outside of
+@@ -781,4 +801,7 @@ class MAILCOMMON_EXPORT SearchPattern : public QList<SearchRule::Ptr>
+ };
+ 
+ }
++
++Q_DECLARE_METATYPE(MailCommon::SearchRule::RequiredPart)
++
+ #endif /* MAILCOMMON_SEARCHPATTERN_H_ */
+diff --git a/mailcommon/tests/searchpatterntest.cpp b/mailcommon/tests/searchpatterntest.cpp
+index 703a572..e5e5462 100644
+--- a/mailcommon/tests/searchpatterntest.cpp
++++ b/mailcommon/tests/searchpatterntest.cpp
+@@ -69,7 +69,7 @@ class SearchPatternTest : public QObject
+       KConfigGroup cfgGroup( &config, "Filter #0" );
+ 
+       SearchPattern pattern( cfgGroup );
+-      qDebug() << pattern.asString();
++      kDebug() << pattern.asString();
+ 
+       QFile file( sparqlFile );
+       QVERIFY( file.open( QIODevice::ReadOnly ) );
+diff --git a/mailfilteragent/filtermanager.cpp b/mailfilteragent/filtermanager.cpp
+index 142d978..b985925 100644
+--- a/mailfilteragent/filtermanager.cpp
++++ b/mailfilteragent/filtermanager.cpp
+@@ -1,6 +1,22 @@
+ // -*- mode: C++; c-file-style: "gnu" -*-
+-// kmfiltermgr.cpp
+-
++/* Copyright: before 2012: missing, see KMail copyrights
++ * Copyright (C) 2012 Andras Mantia <amantia at kde.org> *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ */
+ #include "filtermanager.h"
+ 
+ #include <akonadi/agentmanager.h>
+@@ -43,7 +59,7 @@ class FilterManager::Private
+   public:
+     Private( FilterManager *qq )
+       : q( qq ),
+-        mRequiresBody( false ), mInboundFiltersExist( false )
++        mRequiredPart( SearchRule::Envelope ), mInboundFiltersExist( false )
+     {
+     }
+ 
+@@ -64,7 +80,7 @@ class FilterManager::Private
+ */
+     FilterManager *q;
+     QList<MailCommon::MailFilter *> mFilters;
+-    bool mRequiresBody;
++    SearchRule::RequiredPart mRequiredPart;
+     bool mInboundFiltersExist;
+ };
+ 
+@@ -99,6 +115,8 @@ void FilterManager::Private::slotItemsFetchedForFilter( const Akonadi::Item::Lis
+   if(listMailFilters.isEmpty())
+       listMailFilters = mFilters;
+ 
++  SearchRule::RequiredPart requestedPart = q->sender()->property( "requiredPart" ).value<SearchRule::RequiredPart>();
++  
+   foreach ( const Akonadi::Item &item, items ) {
+     if ( progressItem ) {
+       progressItem->incCompletedItems();
+@@ -115,7 +133,7 @@ void FilterManager::Private::slotItemsFetchedForFilter( const Akonadi::Item::Lis
+       }
+     }
+ 
+-    const int filterResult = q->process( listMailFilters, item, filterSet );
++    const int filterResult = q->process( listMailFilters, item, requestedPart, filterSet );
+     if ( filterResult == 2 ) {
+       // something went horribly wrong (out of space?)
+       //CommonKernel->emergencyExit( i18n( "Unable to process messages: " ) + QString::fromLocal8Bit( strerror( errno ) ) );
+@@ -149,6 +167,8 @@ void FilterManager::Private::itemFetchJobForFilterDone( KJob *job )
+     return;
+   }
+ 
++  SearchRule::RequiredPart requestedPart = fetchJob->property( "requiredPart" ).value<SearchRule::RequiredPart>();
++
+   if ( job->property( "filterId" ).isValid() ) {
+     const QString filterId = job->property( "filterId" ).toString();
+ 
+@@ -166,12 +186,12 @@ void FilterManager::Private::itemFetchJobForFilterDone( KJob *job )
+       return;
+     }
+ 
+-    q->process( items.first(), wantedFilter );
++    q->process( items.first(), requestedPart, wantedFilter );
+   } else {
+     const FilterManager::FilterSet set = static_cast<FilterManager::FilterSet>( job->property( "filterSet" ).toInt() );
+     const QString accountId = job->property( "accountId" ).toString();
+ 
+-    q->process( items.first(), set, !accountId.isEmpty(), accountId );
++    q->process( items.first(), requestedPart, set, !accountId.isEmpty(), accountId );
+   }
+ }
+ 
+@@ -317,9 +337,13 @@ void FilterManager::readConfig()
+   QStringList emptyFilters;
+   d->mFilters = FilterImporterExporter::readFiltersFromConfig( config, emptyFilters );
+ 
+-  // check if at least one filter requires the message body
+-  d->mRequiresBody = std::find_if( d->mFilters.constBegin(), d->mFilters.constEnd(),
+-                                   boost::bind( &MailCommon::MailFilter::requiresBody, _1 ) ) != d->mFilters.constEnd();
++  d->mRequiredPart = SearchRule::Envelope;
++  if (!d->mFilters.isEmpty()){
++    QList<MailFilter*>::const_iterator it = std::max_element(d->mFilters.constBegin(), d->mFilters.constEnd(),
++                                                             boost::bind(&MailCommon::MailFilter::requiredPart, _1) < boost::bind(&MailCommon::MailFilter::requiredPart, _2));
++    d->mRequiredPart = (*it)->requiredPart();
++  }
++  qDebug() << "REQUIRED PART: " << d->mRequiredPart;
+   // check if at least one filter is to be applied on inbound mail
+   d->mInboundFiltersExist = std::find_if( d->mFilters.constBegin(), d->mFilters.constEnd(),
+                                           boost::bind( &MailCommon::MailFilter::applyOnInbound, _1 ) ) != d->mFilters.constEnd();
+@@ -345,36 +369,35 @@ void FilterManager::filter( qlonglong itemId, FilterSet set, const QString &acco
+   Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob( Akonadi::Item( itemId ), this );
+   job->setProperty( "filterSet", static_cast<int>(set) );
+   job->setProperty( "accountId", accountId );
+-  if ( d->mRequiresBody )
++  if ( d->mRequiredPart == SearchRule::CompleteMessage )
+     job->fetchScope().fetchFullPayload( true );
+-  else
++  else if ( d->mRequiredPart == SearchRule::Header )    
+     job->fetchScope().fetchPayloadPart( Akonadi::MessagePart::Header, true );
++  else
++    job->fetchScope().fetchPayloadPart( Akonadi::MessagePart::Envelope, true );
+   job->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );
+ 
+   connect( job, SIGNAL(result(KJob*)), SLOT(itemFetchJobForFilterDone(KJob*)) );
+ }
+ 
+-void FilterManager::filter(qlonglong itemId, const QString &filterId , FilterRequires requires)
++void FilterManager::filter(qlonglong itemId, const QString& filterId, SearchRule::RequiredPart requires)
+ {
+   Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob( Akonadi::Item( itemId ), this );
+   job->setProperty( "filterId", filterId );
+-  if( requires == Unknown) {
+-      if ( d->mRequiresBody )
+-          job->fetchScope().fetchFullPayload( true );
+-      else
+-          job->fetchScope().fetchPayloadPart( Akonadi::MessagePart::Header, true );
+-  } else if( requires == FullMessage ) {
+-      job->fetchScope().fetchFullPayload( true );
+-  } else if( requires == HeaderMessage ) {
+-      job->fetchScope().fetchPayloadPart( Akonadi::MessagePart::Header, true );
+-  }
++
++  if ( requires == SearchRule::CompleteMessage )
++    job->fetchScope().fetchFullPayload( true );
++  else if ( requires == SearchRule::Header )
++    job->fetchScope().fetchPayloadPart( Akonadi::MessagePart::Header, true );
++  else
++    job->fetchScope().fetchPayloadPart( Akonadi::MessagePart::Envelope, true );
+ 
+   job->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );
+ 
+   connect( job, SIGNAL(result(KJob*)), SLOT(itemFetchJobForFilterDone(KJob*)) );
+ }
+ 
+-int FilterManager::process( const Akonadi::Item &item, const MailCommon::MailFilter *filter )
++int FilterManager::process( const Akonadi::Item& item, SearchRule::RequiredPart requestedPart, const MailFilter* filter )
+ {
+   if ( !filter->isEnabled() ) {
+     return 1;
+@@ -393,7 +416,7 @@ int FilterManager::process( const Akonadi::Item &item, const MailCommon::MailFil
+       return 1;
+     }
+ 
+-    ItemContext context( item );
++    ItemContext context( item, requestedPart );
+ 
+     if ( filter->execActions( context, stopIt ) == MailCommon::MailFilter::CriticalError ) {
+       return 2;
+@@ -427,12 +450,18 @@ bool FilterManager::processContextItem( ItemContext context, bool emitSignal, in
+       }
+     } else if ( context.needsPayloadStore() ) {
+         Akonadi::ItemModifyJob *modifyJob = new Akonadi::ItemModifyJob( context.item(), this );
++        //The below is a safety check to ignore modifying payloads if it was not requested,
++        //as in that case we might change the payload to an invalid one
++        modifyJob->setIgnorePayload( !context.needsFullPayload() );
+         if(itemCanDelete) {
+           modifyJob->setProperty( "moveTargetCollection", QVariant::fromValue( context.moveTargetCollection() ) );
+         }
+         connect( modifyJob, SIGNAL(result(KJob*)), SLOT(modifyJobResult(KJob*)));
+     } else if ( context.needsFlagStore() ) {
+         Akonadi::ItemModifyJob *modifyJob = new Akonadi::ItemModifyJob( context.item(), this );
++        //The below is a safety check to ignore modifying payloads if it was not requested,
++        //as in that case we might change the payload to an invalid one
++        modifyJob->setIgnorePayload( !context.needsFullPayload() );
+         if(itemCanDelete) {
+           modifyJob->setProperty( "moveTargetCollection", QVariant::fromValue( context.moveTargetCollection() ) );
+           modifyJob->setIgnorePayload( true );
+@@ -457,13 +486,18 @@ bool FilterManager::processContextItem( ItemContext context, bool emitSignal, in
+ }
+ 
+ 
+-int FilterManager::process( const QList<MailFilter*>& mailFilters, const Akonadi::Item &item, FilterSet set, bool account, const QString &accountId )
++int FilterManager::process(const QList<MailCommon::MailFilter*>& mailFilters, const Akonadi::Item& item, SearchRule::RequiredPart requestedPart, FilterManager::FilterSet set, bool account, const QString& accountId )
+ {
+     if ( set == NoSet ) {
+       kDebug() << "FilterManager: process() called with not filter set selected";
+       emit itemNotMoved( item );
+       return 1;
+     }
++    
++    if ( !item.hasPayload<KMime::Message::Ptr>() ) {
++      kError() << "Filter is null or item doesn't have correct payload.";
++      return 1;
++    }
+ 
+     bool stopIt = false;
+ 
+@@ -472,7 +506,7 @@ int FilterManager::process( const QList<MailFilter*>& mailFilters, const Akonadi
+       return 1;
+     }
+ 
+-    ItemContext context( item );
++    ItemContext context( item, requestedPart );
+     QList<MailCommon::MailFilter*>::const_iterator end( mailFilters.constEnd() );
+     for ( QList<MailCommon::MailFilter*>::const_iterator it = mailFilters.constBegin();
+           !stopIt && it != end ; ++it ) {
+@@ -511,15 +545,10 @@ int FilterManager::process( const QList<MailFilter*>& mailFilters, const Akonadi
+ }
+ 
+ 
+-int FilterManager::process( const Akonadi::Item &item, FilterSet set,
+-                            bool account, const QString &accountId )
++int FilterManager::process( const Akonadi::Item &item,  SearchRule::RequiredPart requestedPart,
++                            FilterSet set, bool account, const QString &accountId )
+ {
+-  return process( d->mFilters, item, set, account, accountId );
+-}
+-
+-int FilterManager::process( const Akonadi::Item &item, const QList<MailFilter*>& mailFilters )
+-{
+-  return process( mailFilters, item );
++  return process( d->mFilters, item, requestedPart, set, account, accountId );
+ }
+ 
+ QString FilterManager::createUniqueName( const QString &name ) const
+@@ -546,9 +575,9 @@ QString FilterManager::createUniqueName( const QString &name ) const
+   return uniqueName;
+ }
+ 
+-bool FilterManager::requiresFullMailBody() const
++MailCommon::SearchRule::RequiredPart FilterManager::requiredPart() const
+ {
+-  return d->mRequiresBody;
++  return d->mRequiredPart;
+ }
+ 
+ #ifndef NDEBUG
+@@ -560,7 +589,7 @@ void FilterManager::dump() const
+ }
+ #endif
+ 
+-void FilterManager::applySpecificFilters(const QList<Akonadi::Item> &selectedMessages, FilterManager::FilterRequires requires, const QStringList& listFilters )
++void FilterManager::applySpecificFilters(const QList<Akonadi::Item> &selectedMessages, SearchRule::RequiredPart requires, const QStringList& listFilters )
+ {
+     const int msgCountToFilter = selectedMessages.size();
+ 
+@@ -572,20 +601,18 @@ void FilterManager::applySpecificFilters(const QList<Akonadi::Item> &selectedMes
+     progressItem->setTotalItems( msgCountToFilter );
+ 
+     Akonadi::ItemFetchJob *itemFetchJob = new Akonadi::ItemFetchJob( selectedMessages, this );
+-    if( requires == Unknown) {
+-        if ( d->mRequiresBody )
+-            itemFetchJob->fetchScope().fetchFullPayload( true );
+-        else
+-            itemFetchJob->fetchScope().fetchPayloadPart( Akonadi::MessagePart::Header, true );
+-    } else if( requires == FullMessage ) {
++    if( requires == SearchRule::CompleteMessage ) {
+         itemFetchJob->fetchScope().fetchFullPayload( true );
+-    } else if( requires == HeaderMessage ) {
++    } else if( requires == SearchRule::Header ) {
+         itemFetchJob->fetchScope().fetchPayloadPart( Akonadi::MessagePart::Header, true );
++    } else {
++        itemFetchJob->fetchScope().fetchPayloadPart( Akonadi::MessagePart::Envelope, true );
+     }
+ 
+     itemFetchJob->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );
+     itemFetchJob->setProperty( "progressItem", QVariant::fromValue( static_cast<QObject*>( progressItem ) ) );
+     itemFetchJob->setProperty( "listFilters", QVariant::fromValue( listFilters ) );
++    itemFetchJob->setProperty( "requestedPart", QVariant::fromValue(requires) );
+ 
+     connect( itemFetchJob, SIGNAL(itemsReceived(Akonadi::Item::List)),
+              this, SLOT(slotItemsFetchedForFilter(Akonadi::Item::List)) );
+@@ -605,13 +632,17 @@ void FilterManager::applyFilters( const QList<Akonadi::Item> &selectedMessages,
+   progressItem->setTotalItems( msgCountToFilter );
+ 
+   Akonadi::ItemFetchJob *itemFetchJob = new Akonadi::ItemFetchJob( selectedMessages, this );
+-  if ( d->mRequiresBody )
++  if ( d->mRequiredPart == SearchRule::CompleteMessage )
+     itemFetchJob->fetchScope().fetchFullPayload( true );
+-  else
++  else if ( d->mRequiredPart == SearchRule::Header )
+     itemFetchJob->fetchScope().fetchPayloadPart( Akonadi::MessagePart::Header, true );
++  else
++    itemFetchJob->fetchScope().fetchPayloadPart( Akonadi::MessagePart::Envelope, true );
++  
+   itemFetchJob->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );
+   itemFetchJob->setProperty( "progressItem", QVariant::fromValue( static_cast<QObject*>( progressItem ) ) );
+   itemFetchJob->setProperty( "filterSet", QVariant::fromValue( static_cast<int>( filterSet ) ) );
++  itemFetchJob->setProperty( "requestedPart", QVariant::fromValue(d->mRequiredPart) );
+ 
+   connect( itemFetchJob, SIGNAL(itemsReceived(Akonadi::Item::List)),
+            this, SLOT(slotItemsFetchedForFilter(Akonadi::Item::List)) );
+diff --git a/mailfilteragent/filtermanager.h b/mailfilteragent/filtermanager.h
+index 4b65af0..ad418e3 100644
+--- a/mailfilteragent/filtermanager.h
++++ b/mailfilteragent/filtermanager.h
+@@ -23,6 +23,8 @@
+ #include <akonadi/collection.h>
+ #include <akonadi/item.h>
+ 
++#include "mailcommon/searchpattern.h"
++
+ namespace MailCommon {
+ class MailFilter;
+ class ItemContext;
+@@ -96,12 +98,12 @@ class FilterManager: public QObject
+      *          0 otherwise. If the caller does not any longer own the message
+      *                       he *must* not delete the message or do similar stupid things. ;-)
+      */
+-    int process( const Akonadi::Item &item, FilterSet set = Inbound,
++    int process( const Akonadi::Item &item, MailCommon::SearchRule::RequiredPart requestedPart,
++                 FilterSet set = Inbound,
+                  bool account = false, const QString &accountId = QString() );
+ 
+-    int process( const Akonadi::Item &item, const QList<MailCommon::MailFilter*>& mailFilters );
+-
+-    int process( const QList<MailCommon::MailFilter*>& mailFilters, const Akonadi::Item &item, FilterSet set = Inbound,
++    int process( const QList<MailCommon::MailFilter*>& mailFilters, const Akonadi::Item &item,
++                 MailCommon::SearchRule::RequiredPart requestedPart, FilterSet set = Inbound,
+                  bool account = false, const QString &accountId = QString() );
+ 
+     /**
+@@ -110,12 +112,12 @@ class FilterManager: public QObject
+      * Applies @p filter to message @p item.
+      * Return codes are as with the above method.
+      */
+-    int process( const Akonadi::Item &item, const MailCommon::MailFilter *filter );
++    int process( const Akonadi::Item &item, MailCommon::SearchRule::RequiredPart requestedPart, const MailCommon::MailFilter *filter );
+ 
+     void filter( qlonglong itemId, FilterSet set, const QString &accountId );
+-    void filter( qlonglong itemId, const QString &filterId, FilterRequires requires );
++    void filter( qlonglong itemId, const QString &filterId, MailCommon::SearchRule::RequiredPart requires );
+ 
+-    void applySpecificFilters(const QList<Akonadi::Item> &selectedMessages, FilterManager::FilterRequires requires, const QStringList& listFilters );
++    void applySpecificFilters(const QList<Akonadi::Item> &selectedMessages, MailCommon::SearchRule::RequiredPart requires, const QStringList& listFilters );
+ 
+     /**
+      * Applies the filters on the given @p messages.
+@@ -125,7 +127,7 @@ class FilterManager: public QObject
+     /**
+      * Returns whether the configured filters need the full mail content.
+      */
+-    bool requiresFullMailBody() const;
++    MailCommon::SearchRule::RequiredPart requiredPart() const;
+ 
+ 
+     void mailCollectionRemoved( const Akonadi::Collection& collection );
+diff --git a/mailfilteragent/mailfilteragent.cpp b/mailfilteragent/mailfilteragent.cpp
+index 13bd323..7220d90 100644
+--- a/mailfilteragent/mailfilteragent.cpp
++++ b/mailfilteragent/mailfilteragent.cpp
+@@ -117,11 +117,13 @@ void MailFilterAgent::initialCollectionFetchingDone( KJob *job )
+   Akonadi::CollectionFetchJob *fetchJob = qobject_cast<Akonadi::CollectionFetchJob*>( job );
+ 
+   changeRecorder()->itemFetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );
+-  changeRecorder()->itemFetchScope().setCacheOnly( true );
+-  if (m_filterManager->requiresFullMailBody()) {
++  mRequestedPart = m_filterManager->requiredPart();
++  if (mRequestedPart == MailCommon::SearchRule::CompleteMessage) {
+     changeRecorder()->itemFetchScope().fetchFullPayload();
+-  } else {
++  } else if (mRequestedPart == MailCommon::SearchRule::Header) {
+     changeRecorder()->itemFetchScope().fetchPayloadPart( Akonadi::MessagePart::Header, true );
++  } else {
++    changeRecorder()->itemFetchScope().fetchPayloadPart( Akonadi::MessagePart::Envelope, true );
+   }
+   changeRecorder()->fetchCollection( true );
+   changeRecorder()->setChangeRecordingEnabled( false );
+@@ -151,7 +153,7 @@ void MailFilterAgent::itemAdded( const Akonadi::Item &item, const Akonadi::Colle
+   if ( status.isRead() || status.isSpam() || status.isIgnored() )
+     return;
+ 
+-  m_filterManager->process( item, FilterManager::Inbound, true, collection.resource() );
++  m_filterManager->process( item, mRequestedPart, FilterManager::Inbound, true, collection.resource() );
+ }
+ 
+ void MailFilterAgent::mailCollectionAdded( const Akonadi::Collection &collection, const Akonadi::Collection& )
+@@ -193,7 +195,7 @@ void MailFilterAgent::applySpecificFilters( const QVector<qlonglong> &itemIds, i
+     items << Akonadi::Item( id );
+   }
+ 
+-  m_filterManager->applySpecificFilters( items, static_cast<FilterManager::FilterRequires>(requires),listFilters );
++  m_filterManager->applySpecificFilters( items, static_cast<MailCommon::SearchRule::RequiredPart>(requires),listFilters );
+ }
+ 
+ 
+@@ -204,7 +206,7 @@ void MailFilterAgent::filterItem( qlonglong item, int filterSet, const QString &
+ 
+ void MailFilterAgent::filter(qlonglong item, const QString &filterIdentifier , int requires)
+ {
+-  m_filterManager->filter( item, filterIdentifier, static_cast<FilterManager::FilterRequires>(requires) );
++  m_filterManager->filter( item, filterIdentifier, static_cast<MailCommon::SearchRule::RequiredPart>(requires) );
+ }
+ 
+ void MailFilterAgent::reload()
+diff --git a/mailfilteragent/mailfilteragent.h b/mailfilteragent/mailfilteragent.h
+index d44f068..165b4a1 100644
+--- a/mailfilteragent/mailfilteragent.h
++++ b/mailfilteragent/mailfilteragent.h
+@@ -22,6 +22,8 @@
+ 
+ #include <akonadi/agentbase.h>
+ 
++#include "mailcommon/searchpattern.h"
++
+ namespace Akonadi {
+ class Monitor;
+ }
+@@ -62,6 +64,7 @@ class MailFilterAgent : public Akonadi::AgentBase, public Akonadi::AgentBase::Ob
+     FilterManager *m_filterManager;
+ 
+     FilterLogDialog *m_filterLogDialog;
++    MailCommon::SearchRule::RequiredPart mRequestedPart;
+ };
+ 
+ #endif
diff --git a/kdepim.spec b/kdepim.spec
index bd30032..1d33082 100644
--- a/kdepim.spec
+++ b/kdepim.spec
@@ -2,7 +2,7 @@ Name:    kdepim
 Summary: KDE PIM (Personal Information Manager) applications
 Epoch:   7
 Version: 4.8.95
-Release: 1%{?dist}
+Release: 2%{?dist}
 
 License: GPLv2
 Group:   Applications/Productivity
@@ -21,7 +21,9 @@ Patch0:  kdepim-4.5.85-install-headers.patch
 # fix KMail migration (kde#283563)
 Patch2: kdepim-4.7.2-kmail-migration.patch
 
-# upstream patches
+## upstream patches
+# https://projects.kde.org/projects/kde/kdepim/repository/revisions/d64d61b470c56b92294f6adee6d74305a217628d
+Patch100: kdepim-4.8.95-filtering.patch
 
 Provides: kdepim4 = %{version}-%{release}
 
@@ -94,6 +96,7 @@ Requires: %{name} = %{?epoch:%{epoch}:}%{version}-%{release}
 
 %patch0 -p1 -b .install-headers
 %patch2 -p1 -b .kmail-migration
+%patch100 -p1 -b .filtering
 
 
 %build
@@ -223,6 +226,9 @@ rm -rf %{buildroot}
 
 
 %changelog
+* Thu Jul 05 2012 Rex Dieter <rdieter at fedoraproject.org> 7:4.8.95-2
+- upstream filter-rework patch
+
 * Wed Jun 27 2012 Jaroslav Reznik <jreznik at redhat.com> - 7:4.8.95-1
 - 4.8.95
 


More information about the scm-commits mailing list